Files
homelab/ansible/roles/nginx-proxy/templates/docker-compose.yml.j2
T
rblundon 881e2e24a8 Add shared nginx-proxy role; deploy Hermes in Docker; rename Paperclip
nginx-proxy (new role):
- Shared nginx + certbot under /opt/nginx, replacing the copies that
  lived inside the Paperclip compose project
- Apps publish via tasks_from: add_vhost (cert marker -> issue cert ->
  write vhost -> nginx -t -> reload); a vhost that fails nginx -t is
  rolled back
- Certs issued one per domain via Cloudflare DNS challenge; domains
  registered as marker files in cert-domains/; optional LE staging
- Stock nginx.conf plus conf.d (directory mounts, not single-file
  mounts); catch-all server drops unknown Host/SNI
- Containers renamed to nginx and certbot

hermes_docker (new role):
- Official Hermes image, host networking, gateway and dashboard bound
  to loopback and published through nginx-proxy
- Dashboard login via basic-auth provider, secrets from the vault
- Main model set from hermes_model (fantasmic endpoint, key from vault);
  config.yaml overrides are merged from a 0600 staged file that is
  removed afterwards, so the key never appears in a command line
- Data dir owner-only (HERMES_HOME_MODE=0700)

paperclip-docker:
- Remove nginx, certbot and docker-compose download tasks; deploy with
  community.docker.docker_compose_v2 (idempotent, remove_orphans)
- Stop passing the Cloudflare token and certbot email to the Paperclip
  container via env_file
- Bind Postgres to 127.0.0.1 (host networking exposed it on all
  interfaces); stop chowning pgdata, which the postgres image owns
- Handler recreates the paperclip service so .env changes apply
- Domain m-v.wdw-labs.cloud -> cranium-command.wdw-labs.cloud

Playbooks:
- Add day1_deploy_nginx_proxy.yml and day1_deploy_hermes_docker.yml
- deploy_paperclip_stack.yml: run nginx-proxy before paperclip-docker,
  CLI-based container checks (no Docker SDK dependency)
- Remove deploy-hermes.yml

Host vars: add nginx_proxy_certbot_email and nginx_proxy_certbot_staging
(staging stays on until the switch to real certs).
2026-09-30 23:12:40 -05:00

47 lines
1.5 KiB
Django/Jinja

# Managed by Ansible (nginx-proxy role)
services:
certbot:
image: {{ nginx_proxy_certbot_image }}
container_name: {{ nginx_proxy_certbot_container }}
volumes:
- {{ nginx_proxy_certs_dir }}:/etc/letsencrypt
- {{ nginx_proxy_scripts_dir }}:/scripts:ro
- {{ nginx_proxy_domains_dir }}:/etc/cert-domains.d:ro
environment:
CLOUDFLARE_API_TOKEN: ${CLOUDFLARE_API_TOKEN}
CERTBOT_EMAIL: ${CERTBOT_EMAIL}
CERTBOT_STAGING: "{{ '1' if nginx_proxy_certbot_staging | bool else '0' }}"
entrypoint: /bin/sh
command:
- -c
- |
while true; do
/scripts/certbot-init.sh || echo "issuance failed; will retry next cycle"
certbot renew --quiet
sleep 12h
done
restart: unless-stopped
nginx:
image: {{ nginx_proxy_nginx_image }}
container_name: {{ nginx_proxy_nginx_container }}
network_mode: host
volumes:
# Directory mounts (not single files) so Ansible's atomic file
# replacement is visible inside the container.
- {{ nginx_proxy_conf_dir }}:/etc/nginx/conf.d:ro
- {{ nginx_proxy_certs_dir }}:/etc/nginx/certs:ro
command:
- /bin/sh
- -c
- |
( while :; do sleep {{ nginx_proxy_reload_interval }}; nginx -s reload; done ) &
exec nginx -g 'daemon off;'
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/nginx-health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s