From 394a973d6ccadde7ccba3e0c28346245340a7725 Mon Sep 17 00:00:00 2001 From: Maddox Date: Tue, 27 Jan 2026 23:47:40 +0000 Subject: [PATCH] Add healthchecks to download-stack, deploy playbook, and mealie resource limits nzbget and rutorrent share gluetun's network namespace via network_mode: service:gluetun. When autoheal restarts gluetun, the dependent containers lose their network and fail silently. Added healthchecks so autoheal detects and restarts them too: - nzbget: curl localhost:6789 - rutorrent: curl localhost:80 - depends_on changed to condition: service_healthy New deploy-download-stack.yml playbook stages startup (gluetun first, wait for healthy, then dependents) since the LXC host lacks Python requests for community.docker modules. Also added resource limits to mealie (512M memory, 1 CPU). Co-Authored-By: Claude Opus 4.5 --- .../databases/mealie/docker-compose.yml | 5 ++ .../download-stack/docker-compose.yml | 18 ++++- playbooks/deploy-download-stack.yml | 71 +++++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 playbooks/deploy-download-stack.yml diff --git a/compose-files/databases/mealie/docker-compose.yml b/compose-files/databases/mealie/docker-compose.yml index 426bfd8..7aceb71 100644 --- a/compose-files/databases/mealie/docker-compose.yml +++ b/compose-files/databases/mealie/docker-compose.yml @@ -52,6 +52,11 @@ services: labels: - "com.centurylinklabs.watchtower.enable=true" - "autoheal=true" + deploy: + resources: + limits: + memory: 512M + cpus: '1.0' networks: proxy: diff --git a/compose-files/download-stack/download-stack/docker-compose.yml b/compose-files/download-stack/download-stack/docker-compose.yml index c61262e..0c6c911 100644 --- a/compose-files/download-stack/download-stack/docker-compose.yml +++ b/compose-files/download-stack/download-stack/docker-compose.yml @@ -64,6 +64,12 @@ services: - /mnt/nas/downloads/nzbget:/downloads - /mnt/nas/media:/media network_mode: service:gluetun + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:6789 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s deploy: resources: limits: @@ -72,7 +78,8 @@ services: reservations: memory: 256M depends_on: - - gluetun + gluetun: + condition: service_healthy restart: unless-stopped labels: - "autoheal=true" @@ -96,8 +103,15 @@ services: - /mnt/nas/downloads/rutorrent:/downloads - /mnt/nas/media:/media network_mode: service:gluetun + healthcheck: + test: ["CMD-SHELL", "curl -sf http://localhost:80 || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s depends_on: - - gluetun + gluetun: + condition: service_healthy restart: unless-stopped deploy: resources: diff --git a/playbooks/deploy-download-stack.yml b/playbooks/deploy-download-stack.yml new file mode 100644 index 0000000..c566a9b --- /dev/null +++ b/playbooks/deploy-download-stack.yml @@ -0,0 +1,71 @@ +--- +- name: Deploy Download Stack (gluetun + nzbget + rutorrent) + hosts: download-stack + become: true + vars: + service_dir: /home/docker/appdata/download-stack + compose_src: "{{ playbook_dir }}/../compose-files/download-stack/download-stack" + + tasks: + - name: Create download-stack directory + file: + path: "{{ service_dir }}" + state: directory + mode: '0755' + + - name: Ensure download network exists + shell: docker network inspect download >/dev/null 2>&1 || docker network create download + changed_when: false + + - name: Copy docker-compose.yml + copy: + src: "{{ compose_src }}/docker-compose.yml" + dest: "{{ service_dir }}/docker-compose.yml" + mode: '0644' + backup: yes + + - name: Check if local .env exists + delegate_to: localhost + become: no + stat: + path: "{{ compose_src }}/.env" + register: local_env + + - name: Copy .env file (if local copy exists) + copy: + src: "{{ compose_src }}/.env" + dest: "{{ service_dir }}/.env" + mode: '0600' + when: local_env.stat.exists + + - name: Pull images + shell: docker compose pull + args: + chdir: "{{ service_dir }}" + + - name: Start gluetun first + shell: docker compose up -d --force-recreate gluetun + args: + chdir: "{{ service_dir }}" + + - name: Wait for gluetun to become healthy + shell: docker inspect --format '{{ '{{' }}.State.Health.Status{{ '}}' }}' gluetun + register: gluetun_health + until: gluetun_health.stdout == "healthy" + retries: 30 + delay: 5 + changed_when: false + + - name: Start nzbget and rutorrent + shell: docker compose up -d --force-recreate nzbget rutorrent + args: + chdir: "{{ service_dir }}" + + - name: Check container status + shell: docker ps --filter name=gluetun --filter name=nzbget --filter name=rutorrent --format "table {{ '{{' }}.Names{{ '}}' }}\t{{ '{{' }}.Status{{ '}}' }}" | head -10 + register: container_status + changed_when: false + + - name: Show status + debug: + msg: "{{ container_status.stdout_lines }}"