Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/roles/fleet/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true

- name: Restart Fleet
ansible.builtin.systemd:
name: "{{ fleet_service_name }}"
state: restarted
79 changes: 79 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/roles/fleet/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
- name: Ensure supporting packages are installed
ansible.builtin.package:
name:
- tar
- gzip
state: present

- name: Ensure Fleet service user exists
ansible.builtin.user:
name: "{{ fleet_service_user }}"
system: true
shell: /sbin/nologin
create_home: false

- name: Create Fleet directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ fleet_service_user }}"
group: "{{ fleet_service_user }}"
mode: "0755"
loop:
- /opt/fleet
- /etc/fleet

- name: Download Fleet release archive
ansible.builtin.get_url:
url: "{{ fleet_download_url }}"
dest: "{{ fleet_archive_path }}"
mode: "0644"
force: true
register: fleet_archive

- name: Extract Fleet binaries
ansible.builtin.unarchive:
src: "{{ fleet_archive_path }}"
dest: "{{ fleet_extract_dir }}"
remote_src: true
owner: "{{ fleet_service_user }}"
group: "{{ fleet_service_user }}"
mode: "0755"
extra_opts:
- --strip-components=1
when: fleet_archive is changed

- name: Ensure Fleet binary is executable
ansible.builtin.file:
path: "{{ fleet_binary_path }}"
owner: "{{ fleet_service_user }}"
group: "{{ fleet_service_user }}"
mode: "0755"

- name: Render Fleet environment file
ansible.builtin.template:
src: fleet_env.j2
dest: "{{ fleet_env_file }}"
owner: "root"
group: "root"
mode: "0600"
notify:
- Restart Fleet

- name: Install Fleet systemd unit
ansible.builtin.template:
src: fleet.service.j2
dest: "/etc/systemd/system/{{ fleet_service_name }}.service"
owner: "root"
group: "root"
mode: "0644"
notify:
- Reload systemd
- Restart Fleet

- name: Enable and start Fleet
ansible.builtin.systemd:
name: "{{ fleet_service_name }}"
enabled: true
state: started
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[Unit]
Description=Fleet device management server
After=network.target

[Service]
Type=simple
User={{ fleet_service_user }}
Group={{ fleet_service_user }}
EnvironmentFile={{ fleet_env_file }}
ExecStart={{ fleet_binary_path }} serve
Restart=on-failure
RestartSec=5
LimitNOFILE=999999

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% for item in fleet_env_map | dictsort %}
{{ item.0 }}={{ item.1 | tojson }}
{% endfor %}
5 changes: 5 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/roles/nginx/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
46 changes: 46 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/roles/nginx/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
- name: Enable EPEL repository
ansible.builtin.package:
name: epel-release
state: present

- name: Install nginx and certbot packages
ansible.builtin.package:
name:
- nginx
- certbot
- python3-certbot-nginx
state: present

- name: Ensure nginx configuration directory exists
ansible.builtin.file:
path: /etc/nginx/conf.d
state: directory
owner: root
group: root
mode: "0755"

- name: Deploy Fleet reverse proxy configuration
ansible.builtin.template:
src: fleet.conf.j2
dest: /etc/nginx/conf.d/fleet.conf
owner: root
group: root
mode: "0644"
notify:
- Reload nginx

- name: Ensure nginx enabled and running
ansible.builtin.service:
name: nginx
state: started
enabled: true

- name: Request TLS certificates with certbot
ansible.builtin.command: >
certbot --nginx --non-interactive --agree-tos --redirect
--email {{ tls_email }}
{% for domain in tls_domains %}-d {{ domain }} {% endfor %}
args:
creates: "/etc/letsencrypt/live/{{ tls_domains[0] }}/fullchain.pem"
when: tls_domains | length > 0
22 changes: 22 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/roles/nginx/templates/fleet.conf.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
upstream fleet_app {
server 127.0.0.1:8080;
}

server {
listen 80;
server_name {{ tls_domains | join(" ") }};

location / {
proxy_pass http://fleet_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
}

location /.well-known/acme-challenge/ {
root /usr/share/nginx/html;
}
}
9 changes: 9 additions & 0 deletions ec2/byo-vpc/byo-db/ansible/site.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
- name: Configure Fleet host
hosts: localhost
become: true
connection: local
gather_facts: false
roles:
- fleet
- nginx
140 changes: 140 additions & 0 deletions ec2/byo-vpc/byo-db/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
data "aws_ami" "rhel" {
most_recent = true
owners = ["309956199498"] # Red Hat, Inc.

filter {
name = "name"
values = ["RHEL-9.*_HVM-*-x86_64-*"]
}

filter {
name = "virtualization-type"
values = ["hvm"]
}

filter {
name = "root-device-type"
values = ["ebs"]
}
}

locals {
instance_configuration = merge({
type = "t3a.large"
key_name = null
iam_instance_profile = null
volume_size = 50
volume_type = "gp3"
volume_iops = null
volume_throughput = null
delete_on_termination = true
}, var.instance_configuration)

extra_environment = {
for pair in var.fleet_config.extra_environment_variables :
pair.key => pair.value
}

fleet_env_map = merge(
{
FLEET_SERVER_PRIVATE_KEY = random_password.fleet_server_private_key.result
},
local.extra_environment,
)

fleet_download_url = "https://github.com/fleetdm/fleet/releases/download/fleet-${var.fleet_config.fleet_version}/fleet_${var.fleet_config.fleet_version}_linux.tar.gz"

ansible_extra_vars = jsonencode({
fleet_download_url = local.fleet_download_url
fleet_archive_path = "/tmp/fleet.tar.gz"
fleet_extract_dir = "/opt/fleet"
fleet_binary_path = "/opt/fleet/fleet"
fleet_env_file = "/etc/fleet/fleet_env"
fleet_env_map = local.fleet_env_map
fleet_service_user = var.fleet_config.service_user
fleet_service_name = var.name
tls_domains = var.fleet_config.tls.domains
tls_email = var.fleet_config.tls.email
})

ansible_repo_url = var.ansible_source.repo_url
ansible_repo_ref = var.ansible_source.ref
ansible_repo_path = "/opt/fleet-terraform"
ansible_sparse_path = "ec2/byo-vpc/byo-db/ansible"
ansible_playbook = "ec2/byo-vpc/byo-db/ansible/site.yml"

cloud_init = templatefile("${path.module}/templates/cloud-init.yaml.tftpl", {
ansible_extra_vars = local.ansible_extra_vars
ansible_repo_url = local.ansible_repo_url
ansible_repo_ref = local.ansible_repo_ref
ansible_repo_path = local.ansible_repo_path
ansible_sparse_path = local.ansible_sparse_path
ansible_playbook = local.ansible_playbook
})

security_group_ids = length(var.security_group_ids) == 0 ? [aws_security_group.fleet[0].id] : var.security_group_ids
}

resource "random_password" "fleet_server_private_key" {
length = 32
special = true
override_special = "!@#$%^&*()-_=+[]{}"
}

resource "aws_security_group" "fleet" {
count = length(var.security_group_ids) == 0 ? 1 : 0
name_prefix = "${var.name}-fleet-"
description = "Security group for Fleet EC2 instance"
vpc_id = var.vpc_id

egress {
description = "Allow all egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}

dynamic "ingress" {
for_each = var.ingress_rules
content {
description = lookup(ingress.value, "description", null)
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = lookup(ingress.value, "cidr_blocks", [])
ipv6_cidr_blocks = lookup(ingress.value, "ipv6_cidr_blocks", [])
security_groups = lookup(ingress.value, "security_groups", [])
prefix_list_ids = lookup(ingress.value, "prefix_list_ids", [])
}
}
}

resource "aws_instance" "fleet" {
ami = data.aws_ami.rhel.id
instance_type = local.instance_configuration.type
subnet_id = var.subnet_id
vpc_security_group_ids = local.security_group_ids
associate_public_ip_address = var.associate_public_ip_address
iam_instance_profile = local.instance_configuration.iam_instance_profile
key_name = local.instance_configuration.key_name
user_data = local.cloud_init
user_data_replace_on_change = true

root_block_device {
volume_size = local.instance_configuration.volume_size
volume_type = local.instance_configuration.volume_type
iops = local.instance_configuration.volume_iops
throughput = local.instance_configuration.volume_throughput
delete_on_termination = local.instance_configuration.delete_on_termination
encrypted = true
}

tags = merge(
{
Name = "${var.name}-fleet"
},
var.tags,
)
}
20 changes: 20 additions & 0 deletions ec2/byo-vpc/byo-db/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
output "instance_id" {
description = "Identifier of the Fleet EC2 instance."
value = aws_instance.fleet.id
}

output "instance_public_ip" {
description = "Public IPv4 address assigned to the Fleet EC2 instance."
value = aws_instance.fleet.public_ip
}

output "security_group_ids" {
description = "Security groups attached to the Fleet EC2 instance."
value = local.security_group_ids
}

output "fleet_server_private_key" {
description = "Generated Fleet server private key."
value = random_password.fleet_server_private_key.result
sensitive = true
}
21 changes: 21 additions & 0 deletions ec2/byo-vpc/byo-db/templates/cloud-init.yaml.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#cloud-config
package_update: true
package_upgrade: true
packages:
- python3
- python3-pip
- git
- ansible-core

runcmd:
- |
#!/bin/bash
set -euo pipefail
export HOME=/root
repo_dir="${ansible_repo_path}"
git clone --depth 1 --filter=blob:none --sparse --branch "${ansible_repo_ref}" "${ansible_repo_url}" "${ansible_repo_path}"
git -C "${repo_dir}" sparse-checkout set "${ansible_sparse_path}"
cat >/tmp/fleet-extra-vars.json <<'JSON'
${ansible_extra_vars}
JSON
ansible-playbook "${repo_dir}/${ansible_playbook}" --inventory localhost, --extra-vars @/tmp/fleet-extra-vars.json
Loading
Loading