version: '3.8' networks: traefik-public: external: true homelab-backend: driver: overlay volumes: paperless_data: paperless_media: paperless_db: paperless_redis: openwebui_data: stirling_pdf_data: searxng_data: n8n_data: secrets: paperless_db_password: external: true paperless_secret_key: external: true services: n8n: image: n8nio/n8n:latest volumes: - n8n_data:/home/node/.n8n - /var/run/docker.sock:/var/run/docker.sock networks: - traefik-public environment: - N8N_HOST=n8n.sj98.duckdns.org - N8N_PROTOCOL=https - NODE_ENV=production - WEBHOOK_URL=https://n8n.sj98.duckdns.org/ healthcheck: test: ["CMD-SHELL", "wget -q --spider http://localhost:5678/healthz || exit 1"] interval: 30s timeout: 10s retries: 3 deploy: placement: constraints: - node.role == manager resources: limits: memory: 1G cpus: '0.5' reservations: memory: 256M cpus: '0.1' restart_policy: condition: on-failure delay: 5s max_attempts: 3 labels: - "traefik.enable=true" - "traefik.http.routers.n8n.rule=Host(`n8n.sj98.duckdns.org`)" - "traefik.http.routers.n8n.entrypoints=websecure" - "traefik.http.routers.n8n.tls.certresolver=leresolver" - "traefik.http.services.n8n.loadbalancer.server.port=5678" - "traefik.docker.network=traefik-public" logging: driver: "json-file" options: max-size: "10m" max-file: "3" openwebui: image: ghcr.io/open-webui/open-webui:0.3.32 volumes: - openwebui_data:/app/backend/data networks: - traefik-public healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s deploy: placement: constraints: - node.labels.heavy == true resources: limits: memory: 4G cpus: '4.0' reservations: memory: 2G cpus: '1.0' restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback labels: - "traefik.enable=true" - "traefik.http.routers.openwebui.rule=Host(`ai.sj98.duckdns.org`)" - "traefik.http.routers.openwebui.entrypoints=websecure" - "traefik.http.routers.openwebui.tls.certresolver=leresolver" - "traefik.http.services.openwebui.loadbalancer.server.port=8080" - "traefik.docker.network=traefik-public" - "tsdproxy.enable=true" - "tsdproxy.name=openwebui" logging: driver: "json-file" options: max-size: "10m" max-file: "3" paperless-redis: image: redis:7-alpine volumes: - paperless_redis:/data networks: - homelab-backend healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 3s retries: 3 deploy: placement: constraints: - node.labels.leader == true resources: limits: memory: 256M cpus: '0.5' reservations: memory: 64M cpus: '0.1' restart_policy: condition: on-failure delay: 5s max_attempts: 3 logging: driver: "json-file" options: max-size: "10m" max-file: "3" paperless-db: image: postgres:15-alpine volumes: - paperless_db:/var/lib/postgresql/data networks: - homelab-backend environment: - POSTGRES_DB=paperless - POSTGRES_USER=paperless - POSTGRES_PASSWORD_FILE=/run/secrets/paperless_db_password secrets: - paperless_db_password healthcheck: test: ["CMD-SHELL", "pg_isready -U paperless"] interval: 30s timeout: 5s retries: 3 deploy: placement: constraints: - node.labels.leader == true resources: limits: memory: 512M cpus: '1.0' reservations: memory: 256M cpus: '0.25' restart_policy: condition: on-failure delay: 5s max_attempts: 3 logging: driver: "json-file" options: max-size: "10m" max-file: "3" paperless: image: ghcr.io/paperless-ngx/paperless-ngx:2.19.3 volumes: - paperless_data:/usr/src/paperless/data - paperless_media:/usr/src/paperless/media environment: - PAPERLESS_REDIS=redis://paperless-redis:6379 - PAPERLESS_DBHOST=paperless-db - PAPERLESS_DBNAME=paperless - PAPERLESS_DBUSER=paperless - PAPERLESS_DBPASS_FILE=/run/secrets/paperless_db_password - PAPERLESS_URL=https://paperless.sj98.duckdns.org - PAPERLESS_SECRET_KEY_FILE=/run/secrets/paperless_secret_key - TZ=America/Chicago secrets: - paperless_db_password - paperless_secret_key depends_on: - paperless-redis - paperless-db networks: - traefik-public - homelab-backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/"] interval: 30s timeout: 10s retries: 3 start_period: 90s deploy: placement: constraints: - node.labels.leader == true resources: limits: memory: 1536M cpus: '2.0' reservations: memory: 768M cpus: '0.5' restart_policy: condition: on-failure delay: 10s max_attempts: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback labels: - "traefik.enable=true" - "traefik.http.routers.paperless.rule=Host(`paperless.sj98.duckdns.org`)" - "traefik.http.routers.paperless.entrypoints=websecure" - "traefik.http.routers.paperless.tls.certresolver=leresolver" - "traefik.http.services.paperless.loadbalancer.server.port=8000" - "traefik.docker.network=traefik-public" - "tsdproxy.enable=true" - "tsdproxy.name=paperless" logging: driver: "json-file" options: max-size: "10m" max-file: "3" stirling-pdf: image: frooodle/s-pdf:0.18.1 volumes: - stirling_pdf_data:/configs environment: - DOCKER_ENABLE_SECURITY=false - INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false - LANGS=en_US networks: - traefik-public healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/"] interval: 30s timeout: 10s retries: 3 start_period: 30s deploy: placement: constraints: - node.labels.leader == true resources: limits: memory: 1536M cpus: '2.0' reservations: memory: 768M cpus: '0.5' restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback labels: - "traefik.enable=true" - "traefik.http.routers.pdf.rule=Host(`pdf.sj98.duckdns.org`)" - "traefik.http.routers.pdf.entrypoints=websecure" - "traefik.http.routers.pdf.tls.certresolver=leresolver" - "traefik.http.services.pdf.loadbalancer.server.port=8080" - "traefik.docker.network=traefik-public" - "tsdproxy.enable=true" - "tsdproxy.name=pdf" logging: driver: "json-file" options: max-size: "10m" max-file: "3" searxng: image: searxng/searxng:2024.11.20-e9f6095cc volumes: - searxng_data:/etc/searxng environment: - SEARXNG_BASE_URL=https://search.sj98.duckdns.org/ networks: - traefik-public healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 30s deploy: placement: constraints: - node.labels.leader == true resources: limits: memory: 1536M cpus: '2.0' reservations: memory: 512M cpus: '0.5' restart_policy: condition: on-failure delay: 5s max_attempts: 3 update_config: parallelism: 1 delay: 10s failure_action: rollback labels: - "traefik.enable=true" - "traefik.http.routers.searxng.rule=Host(`search.sj98.duckdns.org`)" - "traefik.http.routers.searxng.entrypoints=websecure" - "traefik.http.routers.searxng.tls.certresolver=leresolver" - "traefik.http.services.searxng.loadbalancer.server.port=8080" - "traefik.docker.network=traefik-public" - "tsdproxy.enable=true" - "tsdproxy.name=search" logging: driver: "json-file" options: max-size: "10m" max-file: "3" watchtower: image: containrrr/watchtower:1.7.1 volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - DOCKER_API_VERSION=1.44 command: --cleanup --interval 86400 deploy: placement: constraints: - node.role == manager resources: limits: memory: 256M cpus: '0.25' reservations: memory: 64M cpus: '0.05' restart_policy: condition: on-failure delay: 5s max_attempts: 3 logging: driver: "json-file" options: max-size: "10m" max-file: "3" tsdproxy: image: almeidapaulopt/tsdproxy:v0.5.1 networks: - traefik-public volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /srv/tsdproxy/config/tsdproxy.yaml:/config/tsdproxy.yaml:ro - /srv/tsdproxy/data:/data deploy: resources: limits: memory: 256M cpus: '0.25' reservations: memory: 64M cpus: '0.05' restart_policy: condition: on-failure delay: 5s max_attempts: 3 labels: - "traefik.enable=true" - "traefik.http.routers.tsdproxy.rule=Host(`tsdproxy.sj98.duckdns.org`)" - "traefik.http.routers.tsdproxy.entrypoints=websecure" - "traefik.http.routers.tsdproxy.tls.certresolver=leresolver" - "traefik.http.services.tsdproxy.loadbalancer.server.port=8080" - "traefik.docker.network=traefik-public" - "tsdproxy.enable=true" - "tsdproxy.name=tsdproxy" logging: driver: "json-file" options: max-size: "10m" max-file: "3"