|
|
@@ -0,0 +1,326 @@
|
|
|
+services:
|
|
|
+ {{ service_name }}:
|
|
|
+ image: ghcr.io/goauthentik/server:2025.10.1
|
|
|
+ {#
|
|
|
+ If not in swarm mode, check whether container_name is set and apply restart policy,
|
|
|
+ else swarm mode handles restarts via deploy.restart_policy
|
|
|
+ #}
|
|
|
+ {% if not swarm_enabled %}
|
|
|
+ restart: {{ restart_policy }}
|
|
|
+ container_name: {{ container_name }}
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ Set container hostname for identification
|
|
|
+ #}
|
|
|
+ hostname: {{ container_hostname }}
|
|
|
+ command: server
|
|
|
+ {#
|
|
|
+ Environment variables for Authentik server configuration:
|
|
|
+ - Secret key, error reporting, Redis/PostgreSQL connection settings
|
|
|
+ - Optional email configuration for notifications
|
|
|
+ #}
|
|
|
+ environment:
|
|
|
+ - TZ={{ container_timezone }}
|
|
|
+ - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
|
|
|
+ - AUTHENTIK_ERROR_REPORTING__ENABLED={{ authentik_error_reporting }}
|
|
|
+ - AUTHENTIK_REDIS__HOST={{ service_name }}-redis
|
|
|
+ - AUTHENTIK_POSTGRESQL__HOST={{ service_name }}-postgres
|
|
|
+ - AUTHENTIK_POSTGRESQL__USER={{ database_user }}
|
|
|
+ - AUTHENTIK_POSTGRESQL__NAME={{ database_name }}
|
|
|
+ - AUTHENTIK_POSTGRESQL__PASSWORD=${DATABASE_PASSWORD}
|
|
|
+ {% if email_enabled %}
|
|
|
+ - AUTHENTIK_EMAIL__HOST={{ email_host }}
|
|
|
+ - AUTHENTIK_EMAIL__PORT={{ email_port }}
|
|
|
+ - AUTHENTIK_EMAIL__USERNAME={{ email_username }}
|
|
|
+ - AUTHENTIK_EMAIL__PASSWORD=${EMAIL_PASSWORD}
|
|
|
+ - AUTHENTIK_EMAIL__USE_TLS={{ email_use_tls }}
|
|
|
+ - AUTHENTIK_EMAIL__USE_SSL={{ email_use_ssl }}
|
|
|
+ - AUTHENTIK_EMAIL__FROM={{ email_from }}
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ When traefik is enabled, add traefik network for reverse proxy access
|
|
|
+ #}
|
|
|
+ {% if traefik_enabled %}
|
|
|
+ networks:
|
|
|
+ {{ traefik_network }}:
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ Port mappings for HTTP/HTTPS (only when Traefik is disabled)
|
|
|
+ Note: Swarm mode uses 'host' mode for port publishing to avoid port conflicts
|
|
|
+ #}
|
|
|
+ {% if not traefik_enabled %}
|
|
|
+ ports:
|
|
|
+ {% if swarm_enabled %}
|
|
|
+ - target: 9000
|
|
|
+ published: {{ ports_http }}
|
|
|
+ protocol: tcp
|
|
|
+ mode: host
|
|
|
+ - target: 9443
|
|
|
+ published: {{ ports_https }}
|
|
|
+ protocol: tcp
|
|
|
+ mode: host
|
|
|
+ {% else %}
|
|
|
+ - "{{ ports_http }}:9000"
|
|
|
+ - "{{ ports_https }}:9443"
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ Volume configuration for persistent data:
|
|
|
+ - media: User-uploaded media files
|
|
|
+ - templates: Custom template files
|
|
|
+ #}
|
|
|
+ volumes:
|
|
|
+ {% if volume_mode == 'mount' %}
|
|
|
+ - {{ volume_mount_path }}/media:/media
|
|
|
+ - {{ volume_mount_path }}/templates:/templates
|
|
|
+ {% elif volume_mode in ['local', 'nfs'] %}
|
|
|
+ - {{ service_name }}-media:/media
|
|
|
+ - {{ service_name }}-templates:/templates
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ When traefik_enabled is set, and not running in swarm mode, add traefik labels
|
|
|
+ (optionally enable TLS if traefik_tls_enabled is set)
|
|
|
+ #}
|
|
|
+ {% if traefik_enabled and not swarm_enabled %}
|
|
|
+ labels:
|
|
|
+ - traefik.enable=true
|
|
|
+ - traefik.docker.network={{ traefik_network }}
|
|
|
+ - traefik.http.services.{{ service_name }}-web.loadBalancer.server.port=9000
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.service={{ service_name }}-web
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
|
|
|
+ {% if traefik_tls_enabled %}
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.service={{ service_name }}-web
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.entrypoints={{ traefik_tls_entrypoint }}
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.tls=true
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.tls.certresolver={{ traefik_tls_certresolver }}
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+ depends_on:
|
|
|
+ - {{ service_name }}-postgres
|
|
|
+ - {{ service_name }}-redis
|
|
|
+ {#
|
|
|
+ Deploy configuration for Swarm mode and/or resource limits:
|
|
|
+ - Swarm: Configure replicas, placement constraints, and restart policy
|
|
|
+ - Resources: Set CPU/memory limits (and reservations in Swarm mode)
|
|
|
+ - Traefik: Labels for reverse proxy integration (Swarm mode)
|
|
|
+ #}
|
|
|
+ {% if swarm_enabled or resources_enabled %}
|
|
|
+ deploy:
|
|
|
+ {% if swarm_enabled %}
|
|
|
+ mode: {{ swarm_placement_mode }}
|
|
|
+ {% if swarm_placement_mode == 'replicated' %}
|
|
|
+ replicas: {{ swarm_replicas }}
|
|
|
+ {% endif %}
|
|
|
+ {% if swarm_placement_host %}
|
|
|
+ placement:
|
|
|
+ constraints:
|
|
|
+ - node.hostname == {{ swarm_placement_host }}
|
|
|
+ {% endif %}
|
|
|
+ restart_policy:
|
|
|
+ condition: on-failure
|
|
|
+ {% endif %}
|
|
|
+ {% if resources_enabled %}
|
|
|
+ resources:
|
|
|
+ limits:
|
|
|
+ cpus: '{{ resources_cpu_limit }}'
|
|
|
+ memory: {{ resources_memory_limit }}
|
|
|
+ {% if swarm_enabled %}
|
|
|
+ reservations:
|
|
|
+ cpus: '{{ resources_cpu_reservation }}'
|
|
|
+ memory: {{ resources_memory_reservation }}
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ When traefik_enabled is set in swarm mode, add traefik labels
|
|
|
+ (optionally enable TLS if traefik_tls_enabled is set)
|
|
|
+ #}
|
|
|
+ {% if swarm_enabled and traefik_enabled %}
|
|
|
+ labels:
|
|
|
+ - traefik.enable=true
|
|
|
+ - traefik.docker.network={{ traefik_network }}
|
|
|
+ - traefik.http.services.{{ service_name }}-web.loadBalancer.server.port=9000
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.service={{ service_name }}-web
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
|
|
|
+ - traefik.http.routers.{{ service_name }}-http.entrypoints={{ traefik_entrypoint }}
|
|
|
+ {% if traefik_tls_enabled %}
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.service={{ service_name }}-web
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.rule=Host(`{{ traefik_host }}.{{ traefik_domain }}`)
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.entrypoints={{ traefik_tls_entrypoint }}
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.tls=true
|
|
|
+ - traefik.http.routers.{{ service_name }}-https.tls.certresolver={{ traefik_tls_certresolver }}
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+
|
|
|
+ {#
|
|
|
+ Authentik Worker: Background task processor
|
|
|
+ Handles long-running tasks like email sending, cleanup jobs, and scheduled tasks
|
|
|
+ #}
|
|
|
+ {{ service_name }}-worker:
|
|
|
+ image: ghcr.io/goauthentik/server:2025.10.1
|
|
|
+ {#
|
|
|
+ If not in swarm mode, apply restart policy and container name
|
|
|
+ #}
|
|
|
+ {% if not swarm_enabled %}
|
|
|
+ restart: {{ restart_policy }}
|
|
|
+ container_name: {{ service_name }}-worker
|
|
|
+ {% endif %}
|
|
|
+ command: worker
|
|
|
+ {#
|
|
|
+ Environment variables (same as server for consistency)
|
|
|
+ #}
|
|
|
+ environment:
|
|
|
+ - TZ={{ container_timezone }}
|
|
|
+ - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY}
|
|
|
+ - AUTHENTIK_ERROR_REPORTING__ENABLED={{ authentik_error_reporting }}
|
|
|
+ - AUTHENTIK_REDIS__HOST={{ service_name }}-redis
|
|
|
+ - AUTHENTIK_POSTGRESQL__HOST={{ service_name }}-postgres
|
|
|
+ - AUTHENTIK_POSTGRESQL__USER={{ database_user }}
|
|
|
+ - AUTHENTIK_POSTGRESQL__NAME={{ database_name }}
|
|
|
+ - AUTHENTIK_POSTGRESQL__PASSWORD=${DATABASE_PASSWORD}
|
|
|
+ {% if email_enabled %}
|
|
|
+ - AUTHENTIK_EMAIL__HOST={{ email_host }}
|
|
|
+ - AUTHENTIK_EMAIL__PORT={{ email_port }}
|
|
|
+ - AUTHENTIK_EMAIL__USERNAME={{ email_username }}
|
|
|
+ - AUTHENTIK_EMAIL__PASSWORD=${EMAIL_PASSWORD}
|
|
|
+ - AUTHENTIK_EMAIL__USE_TLS={{ email_use_tls }}
|
|
|
+ - AUTHENTIK_EMAIL__USE_SSL={{ email_use_ssl }}
|
|
|
+ - AUTHENTIK_EMAIL__FROM={{ email_from }}
|
|
|
+ {% endif %}
|
|
|
+ user: root
|
|
|
+ {#
|
|
|
+ Volume configuration:
|
|
|
+ - Docker socket: Required for worker to manage containers
|
|
|
+ - media/certs/templates: Shared with server container
|
|
|
+ #}
|
|
|
+ volumes:
|
|
|
+ - /run/docker.sock:/run/docker.sock
|
|
|
+ {% if volume_mode == 'mount' %}
|
|
|
+ - {{ volume_mount_path }}/media:/media
|
|
|
+ - {{ volume_mount_path }}/certs:/certs
|
|
|
+ - {{ volume_mount_path }}/templates:/templates
|
|
|
+ {% elif volume_mode in ['local', 'nfs'] %}
|
|
|
+ - {{ service_name }}-media:/media
|
|
|
+ - {{ service_name }}-certs:/certs
|
|
|
+ - {{ service_name }}-templates:/templates
|
|
|
+ {% endif %}
|
|
|
+ depends_on:
|
|
|
+ - {{ service_name }}-postgres
|
|
|
+ - {{ service_name }}-redis
|
|
|
+
|
|
|
+ {#
|
|
|
+ Redis: Cache and message broker for Authentik
|
|
|
+ Stores sessions, caching data, and task queue messages
|
|
|
+ #}
|
|
|
+ {{ service_name }}-redis:
|
|
|
+ image: docker.io/library/redis:8.2.3
|
|
|
+ {#
|
|
|
+ If not in swarm mode, apply restart policy and container name
|
|
|
+ #}
|
|
|
+ {% if not swarm_enabled %}
|
|
|
+ restart: {{ restart_policy }}
|
|
|
+ container_name: {{ service_name }}-redis
|
|
|
+ {% endif %}
|
|
|
+ command: --save 60 1 --loglevel warning
|
|
|
+ {#
|
|
|
+ Health check: Verify Redis is responding to ping commands
|
|
|
+ #}
|
|
|
+ healthcheck:
|
|
|
+ test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
|
|
+ start_period: 20s
|
|
|
+ interval: 30s
|
|
|
+ retries: 5
|
|
|
+ timeout: 3s
|
|
|
+ {#
|
|
|
+ Volume configuration for Redis data persistence
|
|
|
+ #}
|
|
|
+ volumes:
|
|
|
+ {% if volume_mode == 'mount' %}
|
|
|
+ - {{ volume_mount_path }}/redis:/data
|
|
|
+ {% elif volume_mode in ['local', 'nfs'] %}
|
|
|
+ - {{ service_name }}-redis:/data
|
|
|
+ {% endif %}
|
|
|
+
|
|
|
+ {#
|
|
|
+ PostgreSQL: Main database for Authentik (only if not using external database)
|
|
|
+ Stores all user data, configurations, and authentication flows
|
|
|
+ #}
|
|
|
+ {% if not database_external %}
|
|
|
+ {{ service_name }}-postgres:
|
|
|
+ image: docker.io/library/postgres:17.6
|
|
|
+ {#
|
|
|
+ If not in swarm mode, apply restart policy and container name
|
|
|
+ #}
|
|
|
+ {% if not swarm_enabled %}
|
|
|
+ restart: {{ restart_policy }}
|
|
|
+ container_name: {{ service_name }}-db
|
|
|
+ {% endif %}
|
|
|
+ {#
|
|
|
+ Environment variables for PostgreSQL configuration
|
|
|
+ #}
|
|
|
+ environment:
|
|
|
+ - TZ={{ container_timezone }}
|
|
|
+ - POSTGRES_USER={{ database_user }}
|
|
|
+ - POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
|
|
+ - POSTGRES_DB={{ database_name }}
|
|
|
+ {#
|
|
|
+ Health check: Verify PostgreSQL is ready to accept connections
|
|
|
+ #}
|
|
|
+ healthcheck:
|
|
|
+ test: ["CMD-SHELL", "pg_isready -U {{ database_user }}"]
|
|
|
+ start_period: 30s
|
|
|
+ interval: 10s
|
|
|
+ timeout: 10s
|
|
|
+ retries: 5
|
|
|
+ {#
|
|
|
+ Volume configuration for PostgreSQL data persistence
|
|
|
+ #}
|
|
|
+ volumes:
|
|
|
+ {% if volume_mode == 'mount' %}
|
|
|
+ - {{ volume_mount_path }}/postgres:/var/lib/postgresql/data
|
|
|
+ {% elif volume_mode in ['local', 'nfs'] %}
|
|
|
+ - {{ service_name }}-postgres:/var/lib/postgresql/data
|
|
|
+ {% endif %}
|
|
|
+ {% endif %}
|
|
|
+
|
|
|
+{#
|
|
|
+ Volume definitions:
|
|
|
+ - When volume_mode is 'local' (default): use docker-managed local volumes
|
|
|
+ - When volume_mode is 'nfs': configure NFS-backed volumes
|
|
|
+ - When volume_mode is 'mount': no volume definition needed (bind mounts used directly)
|
|
|
+#}
|
|
|
+{% if volume_mode == 'local' %}
|
|
|
+volumes:
|
|
|
+ {% if not database_external %}
|
|
|
+ {{ service_name }}-postgres:
|
|
|
+ driver: local
|
|
|
+ {% endif %}
|
|
|
+ {{ service_name }}-redis:
|
|
|
+ driver: local
|
|
|
+{% elif volume_mode == 'nfs' %}
|
|
|
+volumes:
|
|
|
+ {{ service_name }}-postgres:
|
|
|
+ driver: local
|
|
|
+ driver_opts:
|
|
|
+ type: nfs
|
|
|
+ o: addr={{ volume_nfs_server }},{{ volume_nfs_options }}
|
|
|
+ device: ":{{ volume_nfs_path }}/postgres"
|
|
|
+ {{ service_name }}-redis:
|
|
|
+ driver: local
|
|
|
+ driver_opts:
|
|
|
+ type: nfs
|
|
|
+ o: addr={{ volume_nfs_server }},{{ volume_nfs_options }}
|
|
|
+ device: ":{{ volume_nfs_path }}/redis"
|
|
|
+{% endif %}
|
|
|
+
|
|
|
+{#
|
|
|
+ Network definitions (only when Traefik is enabled):
|
|
|
+ - Traefik network: always external (managed by Traefik)
|
|
|
+#}
|
|
|
+{% if traefik_enabled %}
|
|
|
+networks:
|
|
|
+ {{ traefik_network }}:
|
|
|
+ external: true
|
|
|
+{% endif %}
|