Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: manage Caddyfile with a docker config #50

Merged
merged 14 commits into from
Feb 20, 2025
4 changes: 4 additions & 0 deletions .github/workflows/ansible.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

# Trigger on main to clear the lock
push:
branches: [ "main" ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:

Expand Down
12 changes: 6 additions & 6 deletions ansible/roles/docker-swarm-app-caddy/assets/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
dynamic_dns {
provider digitalocean {env.DIGITALOCEAN_API_TOKEN}
domains {
{{domain}} @ www
{$DOMAIN} @ www
}
dynamic_domains
}
Expand All @@ -20,7 +20,7 @@
authentication portal myportal {
crypto default token lifetime 3600
crypto key sign-verify {env.JWT_SHARED_KEY}
cookie domain {{domain}}
cookie domain {$DOMAIN}
enable identity provider github
ui {
links {
Expand All @@ -36,7 +36,7 @@
}

authorization policy admins_policy {
set auth url https://auth.{{domain}}/oauth2/github
set auth url https://auth.{$DOMAIN}/oauth2/github
crypto key verify {env.JWT_SHARED_KEY}
allow roles authp/admin authp/user
validate bearer header
Expand All @@ -58,15 +58,15 @@
}

# Snippet enable automatic DNS configuration
(external-dns) {
(dns-challenge) {
tls {
dns digitalocean {env.DIGITALOCEAN_API_TOKEN}
}
}

# Auth endpoint for caddy security
auth.{{domain}} {
import external-dns
auth.{$DOMAIN} {
import dns-challenge
authenticate with myportal
}

Expand Down
9 changes: 8 additions & 1 deletion ansible/roles/docker-swarm-app-caddy/assets/caddy-stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ services:
- caddy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- "{{ caddy_dir }}/Caddyfile:/etc/caddy/Caddyfile"
- caddy_data:/data
- caddy_config:/config
configs:
- source: caddy_global_caddyfile
target: "/etc/caddy/Caddyfile"
secrets:
- caddy_github_client_id
- caddy_github_client_secret
- caddy_jwt_shared_key
- caddy_digitalocean_api_token
environment:
DOMAIN: "{{ domain }}"
GITHUB_CLIENT_ID_FILE: /run/secrets/caddy_github_client_id
GITHUB_CLIENT_SECRET_FILE: /run/secrets/caddy_github_client_secret
JWT_SHARED_KEY_FILE: /run/secrets/caddy_jwt_shared_key
Expand Down Expand Up @@ -58,6 +61,10 @@ volumes:
caddy_data:
caddy_config:

configs:
caddy_global_caddyfile:
external: true

networks:
caddy:
attachable: true
Expand Down
18 changes: 15 additions & 3 deletions ansible/roles/docker-swarm-app-caddy/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,31 @@
state: directory
mode: '0644'

- name: Define asssets folder
set_fact:
assets_path: "{{ role_path }}/assets"

- name: Copy Compose file to remote server
template:
src: "{{ item }}"
dest: "{{ caddy_dir }}"
mode: '0644'
with_fileglob:
- "{{ role_path }}/assets/*-stack.yml"
- "{{ role_path }}/assets/Caddyfile"
- "{{ role_path }}/assets/Dockerfile"
- "{{ assets_path }}/*-stack.yml"
- "{{ assets_path }}/Caddyfile"
- "{{ assets_path }}/Dockerfile"

###
# Create Caddy Pre-requisits
###
- name: Manager Caddy Configs
include_role:
name: utils-rotate-docker-configs
vars:
docker_compose_path: "{{ caddy_dir }}/caddy-stack.yml"
configs:
- {name: 'caddy_global_caddyfile', file_path: "{{ caddy_dir }}/Caddyfile"}

- name: Manager Caddy Secrets
include_role:
name: utils-rotate-docker-secrets
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docker_compose_path: "{{ undef(hint='You must specify docker-compose file to update') }}"
18 changes: 18 additions & 0 deletions ansible/roles/utils-rotate-docker-configs/handlers/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- name: List all Docker configs managed by this role
command: docker config ls --filter label=managed_by=rotate_docker_configs --format "{{ '{{ .Name }}' }}"
register: existing_configs
changed_when: false

- name: Identify configs to keep
set_fact:
configs_to_keep: "{{ configs_to_keep | default([]) + [item.name + '_' + config_checksums[item.name]] }}"
loop: "{{ configs }}"

- name: Remove dangling configs
docker_config:
name: "{{ item }}"
state: absent
when: item not in configs_to_keep
loop: "{{ existing_configs.stdout_lines }}"
ignore_errors: true
register: ignore_errors_register
3 changes: 3 additions & 0 deletions ansible/roles/utils-rotate-docker-configs/meta/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies: []
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
# if you add dependencies to this list.
30 changes: 30 additions & 0 deletions ansible/roles/utils-rotate-docker-configs/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
- name: Gather file stats and checksums
stat:
path: "{{ item.file_path }}"
checksum: md5
loop: "{{ configs }}"
register: file_stats

- name: Create dictionary of checksums
set_fact:
config_checksums: "{{ config_checksums | default({}) | combine({ item.name: file_stats.results[idx].stat.checksum }) }}"

Check warning on line 10 in ansible/roles/utils-rotate-docker-configs/tasks/main.yaml

View workflow job for this annotation

GitHub Actions / validate

jinja[spacing]

Jinja2 spacing could be improved: {{ config_checksums | default({}) | combine({ item.name: file_stats.results[idx].stat.checksum }) }} -> {{ config_checksums | default({}) | combine({item.name: file_stats.results[idx].stat.checksum}) }}

Check warning on line 10 in ansible/roles/utils-rotate-docker-configs/tasks/main.yaml

View workflow job for this annotation

GitHub Actions / validate

jinja[spacing]

Jinja2 spacing could be improved: {{ config_checksums | default({}) | combine({ item.name: file_stats.results[idx].stat.checksum }) }} -> {{ config_checksums | default({}) | combine({item.name: file_stats.results[idx].stat.checksum}) }}

Check warning on line 10 in ansible/roles/utils-rotate-docker-configs/tasks/main.yaml

View workflow job for this annotation

GitHub Actions / validate

jinja[spacing]

Jinja2 spacing could be improved: {{ config_checksums | default({}) | combine({ item.name: file_stats.results[idx].stat.checksum }) }} -> {{ config_checksums | default({}) | combine({item.name: file_stats.results[idx].stat.checksum}) }}
loop: "{{ configs }}"
loop_control:
index_var: idx

- name: Create new configs if value has changed
docker_config:
name: "{{ item.name }}_{{ config_checksums[item.name] }}"
data_src: "{{ item.file_path }}"
state: present
labels:
managed_by: "rotate_docker_configs"
name: "{{ item.name }}"
loop: "{{ configs }}"

- name: Replace config names in Docker Compose file
replace:
path: "{{ docker_compose_path }}"
regexp: "{{ item.name }}(_[a-f0-9]{32})?"
replace: "{{ item.name }}_{{ config_checksums[item.name] }}"
loop: "{{ configs }}"
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
checksum_directory: /var/data/ansible
docker_compose_path: "{{ undef(hint='You must specify docker-compose file to update') }}"
36 changes: 0 additions & 36 deletions ansible/roles/utils-rotate-docker-secrets/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
- name: Ensure checksum directory exists
file:
path: "{{ checksum_directory }}"
mode: '0644'
state: directory

- name: Calculate checksums for secrets
set_fact:
secret_checksums: "{{ secret_checksums
Expand All @@ -13,27 +7,6 @@
| cut -d\" \" -f1')}) }}"
loop: "{{ secrets }}"

- name: Check if previous checksums file exists
stat:
path: "{{ checksum_directory }}/secrets.ini"
register: previous_checksums_file

- name: Load previous checksums if file exists
set_fact:
previous_checksums: "{{ previous_checksums
| default({})
| combine({
item.name: lookup(
'ansible.builtin.ini',
'checksum',
section=item.name,
file=checksum_directory + '/secrets.ini'
)
})
}}"
loop: "{{ secrets }}"
when: previous_checksums_file.stat.exists

- name: Create new secrets if value has changed
docker_secret:
name: "{{ item.name }}_{{ secret_checksums[item.name] }}"
Expand All @@ -45,15 +18,6 @@
when: (previous_checksums[item.name] is not defined) or (previous_checksums[item.name] != secret_checksums[item.name])
loop: "{{ secrets }}"

- name: Update checksums file
ini_file:
path: ./secrets.ini
section: "{{ item.name }}"
option: checksum
value: "{{ secret_checksums[item.name] }}"
mode: '0644'
loop: "{{ secrets }}"

- name: Replace secret names in Docker Compose file
replace:
path: "{{ docker_compose_path }}"
Expand Down
Loading