diff --git a/services/auth.yaml b/services/auth.yaml new file mode 100644 index 0000000..6358b59 --- /dev/null +++ b/services/auth.yaml @@ -0,0 +1,59 @@ +version: "3.8" + +secrets: + MASTER_KEY: + file: ../secrets/auth/zitadel/MASTER_KEY + +services: + backup: + volumes: + - ../data/auth:/mnt/backup/src/auth:ro + + zitadel: + restart: 'unless-stopped' + image: 'ghcr.io/zitadel/zitadel:latest' + environment: + ZITADEL_DATABASE_COCKROACH_HOST: crdb + ZITADEL_EXTERNALSECURE: true + ZITADEL_EXTERNALDOMAIN: auth.${DOMAIN} + ZITADEL_EXTERNALPORT: 8321 + ZITADEL_WEBAUTHN_NAME: ${DOMAIN} + secrets: + - MASTER_KEY + command: "start-from-init --masterkeyFile /run/secrets/MASTER_KEY --tlsMode disabled" + depends_on: + secrets: + condition: 'service_completed_successfully' + caddy: + condition: 'service_healthy' + crdb: + condition: 'service_healthy' + ports: + - '8321:8080' + + generate-secrets: + volumes: + - ../secrets/auth/zitadel/MASTER_KEY:/secrets/auth/zitadel/MASTER_KEY + + crdb: + restart: unless-stopped + image: 'cockroachdb/cockroach:latest-v22.2' + depends_on: + secrets: + condition: 'service_completed_successfully' + command: "start-single-node --insecure" + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8080/health?ready=1"] + interval: '10s' + timeout: '30s' + retries: 5 + start_period: '20s' + ports: + - '9090:8080' + - '26257:26257' + volumes: + - ../data/auth/crdb/data:/cockroach/cockroach-data:rw + + caddy: + volumes: + - ./auth/Proxyfile:/etc/caddy.d/zitadel:ro diff --git a/services/auth/Proxyfile b/services/auth/Proxyfile new file mode 100644 index 0000000..9a45724 --- /dev/null +++ b/services/auth/Proxyfile @@ -0,0 +1,3 @@ +auth.{$DOMAIN} { + reverse_proxy zitadel:8321 +} diff --git a/services/authelia.yaml b/services/authelia.yaml deleted file mode 100644 index 9e08940..0000000 --- a/services/authelia.yaml +++ /dev/null @@ -1,99 +0,0 @@ -version: "3.8" - -secrets: - JWT_SECRET: - file: ../secrets/authelia/JWT_SECRET - SESSION_SECRET: - file: ../secrets/authelia/SESSION_SECRET - STORAGE_PASSWORD: - file: ../secrets/authelia/STORAGE_PASSWORD - STORAGE_ENCRYPTION_KEY: - file: ../secrets/authelia/STORAGE_ENCRYPTION_KEY - SMTP_PASSWORD: - file: ../secrets/smtp/SMTP_PASSWORD - -services: - authelia: - container_name: authelia - image: docker.io/authelia/authelia:4.37 - userns_mode: keep-id - depends_on: - - postgres - - secrets - - caddy - #- smtp - restart: unless-stopped - expose: - - 9091 - secrets: [JWT_SECRET, SESSION_SECRET, STORAGE_PASSWORD, STORAGE_ENCRYPTION_KEY, SMTP_PASSWORD] - environment: - AUTHELIA_JWT_SECRET_FILE: /run/secrets/JWT_SECRET - AUTHELIA_SESSION_DOMAIN: ${DOMAIN} - AUTHELIA_SESSION_SECRET_FILE: /run/secrets/SESSION_SECRET - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /run/secrets/STORAGE_ENCRYPTION_KEY - - AUTHELIA_STORAGE_POSTGRES_DATABASE: authelia - AUTHELIA_STORAGE_POSTGRES_HOST: postgres - AUTHELIA_STORAGE_POSTGRES_USERNAME: authelia - AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE: /run/secrets/STORAGE_PASSWORD - - AUTHELIA_DEFAULT_REDIRECTION_URL: https://${DOMAIN} - AUTHELIA_TOTP_ISSUER: ${DOMAIN} - AUTHELIA_WEBAUTHN_DISPLAY_NAME: ${DOMAIN} - - AUTHELIA_ACCESS_CONTROL_DEFAULT_POLICY: two_factor - - AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE: /run/secrets/SMTP_PASSWORD - AUTHELIA_NOTIFIER_SMTP_HOST: ${SMTP_HOST} - AUTHELIA_NOTIFIER_SMTP_PORT: ${SMTP_PORT} - AUTHELIA_NOTIFIER_SMTP_USERNAME: ${SMTP_USERNAME} - AUTHELIA_NOTIFIER_SMTP_SENDER: "Woodbine <${SMTP_USERNAME}@${DOMAIN}>" - - volumes: - - ../data/authelia/config:/config - - postgres: - image: postgres:16.0-alpine - depends_on: - - secrets - - caddy - secrets: [STORAGE_PASSWORD] - restart: unless-stopped - environment: - POSTGRES_PASSWORD_FILE: /run/secrets/STORAGE_PASSWORD - POSTGRES_DB: authelia - POSTGRES_USER: authelia - volumes: - - postgres-data:/var/lib/postgresql/data - - # setup a reverse proxy for caddy - caddy: - volumes: - - ./authelia/Proxyfile:/etc/caddy.d/authelia:ro - - # backup the authelia config - backup: - volumes: - - ../data/authelia/config:/mnt/backup/src/authelia/config:ro - - # backup the postgres database - #backup-postgres: - # volumes: - # - ../secrets/authelia/STORAGE_PASSWORD:/run/secrets/AUTHELIA_PGPASSWORD - # environment: - # - AUTHELIA_PGHOST: authelia - # - AUTHELIA_PGUSER: authelia - # - AUTHELIA_DBS_TO_INCLUDE: authelia - # - AUTHELIA_PGPASSWORD_FILE: /run/secrets/AUTHELIA_PGPASSWORD - - # generate all these secrets if they are empty on start - secrets: - volumes: - - ../secrets/authelia/JWT_SECRET:/secrets/authelia/JWT_SECRET - - ../secrets/authelia/SESSION_SECRET:/secrets/authelia/SESSION_SECRET - - ../secrets/authelia/STORAGE_PASSWORD:/secrets/authelia/STORAGE_PASSWORD - - ../secrets/authelia/STORAGE_ENCRYPTION_KEY:/secrets/authelia/STORAGE_ENCRYPTION_KEY - -volumes: - postgres-data: - authelia-config: diff --git a/services/backup.yaml b/services/backup.yaml index bfa951c..d1e11b8 100644 --- a/services/backup.yaml +++ b/services/backup.yaml @@ -2,17 +2,21 @@ version: "3.8" secrets: B2_APPLICATION_KEY: - file: ../secrets/backup/B2_APPLICATION_KEY + file: ../secrets/backup/duplicity/B2_APPLICATION_KEY B2_APPLICATION_KEY_ID: - file: ../secrets/backup/B2_APPLICATION_KEY_ID + file: ../secrets/backup/duplicity/B2_APPLICATION_KEY_ID BUCKET_NAME: - file: ../secrets/backup/BUCKET_NAME + file: ../secrets/backup/duplicity/BUCKET_NAME PASSPHRASE: - file: ../secrets/backup/PASSPHRASE + file: ../secrets/backup/duplicity/PASSPHRASE services: - backup: - container_name: backup + generate-secrets: + volumes: + - ../secrets/backup/duplicity/BUCKET_NAME:/secrets/backup/duplicity/BUCKET_NAME + - ../secrets/backup/duplicity/PASSPHRASE:/secrets/backup/duplicity/PASSPHRASE + + duplicity: image: tecnativa/docker-duplicity:latest restart: unless-stopped depends_on: [secrets] @@ -24,8 +28,7 @@ services: - ./backup/backup-files:/backup-files:ro entrypoint: ["/bin/sh", "/backup-files"] -# backup-postgres: -# container_name: backup-postgres +# duplicity-postgres: # image: tecnativa/docker-duplicity-postgres:latest # restart: unless-stopped # depends_on: [secrets] @@ -33,11 +36,6 @@ services: # environment: # HOSTNAME: ${DOMAIN} # TZ: America/New_York -# entrypoint: ["/backup-databases"] # volumes: # - ./backup/backup-databases:/backup-databases:ro - - secrets: - volumes: - - ../secrets/backup/BUCKET_NAME:/secrets/backup/BUCKET_NAME - - ../secrets/backup/PASSPHRASE:/secrets/backup/PASSPHRASE +# entrypoint: ["/bin/sh", "/backup-databases"] diff --git a/services/caddy.yaml b/services/caddy.yaml deleted file mode 100644 index eef1b15..0000000 --- a/services/caddy.yaml +++ /dev/null @@ -1,24 +0,0 @@ -version: "3.8" - -services: - caddy: - image: caddy - restart: unless-stopped - ports: - - "80:80" - - "443:443" - - "443:443/udp" - volumes: - - ./caddy/Caddyfile:/etc/caddy/Caddyfile - - ../data/caddy/site:/site - - ../data/caddy/data:/data - - caddy_config:/config - environment: - - DOMAIN - - backup: - volumes: - - ../data/caddy:/mnt/backup/src/caddy:ro - -volumes: - caddy_config: diff --git a/services/mail.yaml b/services/mail.yaml new file mode 100644 index 0000000..29357b6 --- /dev/null +++ b/services/mail.yaml @@ -0,0 +1,59 @@ +version: "3.8" + +secrets: + SMTP_PASSWORD: + file: ../secrets/mail/SMTP_PASSWORD + +services: + generate-secrets: + volumes: + - ../secrets/mail/maddy/MASTER_KEY:/secrets/mail/maddy/MASTER_KEY + + backup: + volumes: + - ../data/mail:/mnt/backup/src/mail:ro + + caddy: + volumes: + - ./mail/Proxyfile:/etc/caddy.d/mail:ro + + maddy: + image: foxcpp/maddy:latest + secrets: [SMTP_PASSWORD] + restart: unless-stopped + depends_on: ["smtp-setup"] + environment: + - MADDY_HOSTNAME=mx.mail.${DOMAIN} + - MADDY_DOMAIN=mail.${DOMAIN} + volumes: + - ../data/mail/maddy:/data + # TODO: get from caddy? + #- ../secrets/tls/fullchain.pem:/data/tls/fullchain.pem:ro + #- ../secrets/tls/privkey.pem:/data/tls/privkey.pem:ro + ports: + - 25:25 + - 143:143 + - 587:587 + - 993:993 + + roundcube: + image: roundcube/roundcubemail:1.6.x-apache + environment: + ROUNDCUBEMAIL_DEFAULT_HOST: ssl://mx.mail.${DOMAIN} + ROUNDCUBEMAIL_DEFAULT_PORT: 993 + ROUNDCUBEMAIL_SMTP_SERVER: tls://mx.mail.${DOMAIN} + ROUNDCUBEMAIL_SMTP_PORT: 587 + ROUNDCUBEMAIL_DB_TYPE: sqlite + volumes: + - ../data/mail/roundcube/db:/var/roundcube/db + ports: + - 9002:80 + + smtp-setup: + container_name: smtp-setup + image: alpine + restart: no + secrets: [SMTP_PASSWORD] + volumes: + - ./secrets/check-secrets:/check-secrets:ro + entrypoint: ["/check-secrets"] diff --git a/services/mail/Proxyfile b/services/mail/Proxyfile new file mode 100644 index 0000000..81e8469 --- /dev/null +++ b/services/mail/Proxyfile @@ -0,0 +1,4 @@ +mail.{$DOMAIN} { + reverse_proxy roundcube:9002 +} + diff --git a/services/proxy.yaml b/services/proxy.yaml new file mode 100644 index 0000000..62ae6e5 --- /dev/null +++ b/services/proxy.yaml @@ -0,0 +1,27 @@ +version: "3.8" + +services: + caddy: + image: caddy + restart: unless-stopped + ports: + - "80:80" + - "443:443" + - "443:443/udp" + volumes: + - ./proxy/Caddyfile:/etc/caddy/Caddyfile + - ../data/proxy/caddy/site:/site + - ../data/proxy/caddy/data:/data + - ../data/proxy/caddy/config:/config + environment: + - DOMAIN + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost"] + interval: '10s' + timeout: '30s' + retries: 5 + start_period: '20s' + + backup: + volumes: + - ../data/proxy:/mnt/backup/src/proxy:ro diff --git a/services/caddy/Caddyfile b/services/proxy/Caddyfile similarity index 100% rename from services/caddy/Caddyfile rename to services/proxy/Caddyfile diff --git a/services/caddy/readme b/services/proxy/readme similarity index 100% rename from services/caddy/readme rename to services/proxy/readme diff --git a/services/secrets.yaml b/services/secrets.yaml index 9870fb4..aeeed63 100644 --- a/services/secrets.yaml +++ b/services/secrets.yaml @@ -1,7 +1,7 @@ version: "3.8" services: - secrets: + generate-secrets: image: alpine/openssl restart: no volumes: diff --git a/services/smtp.yaml b/services/smtp.yaml deleted file mode 100644 index 2e4b545..0000000 --- a/services/smtp.yaml +++ /dev/null @@ -1,35 +0,0 @@ -version: "3.8" - -secrets: - SMTP_PASSWORD: - file: ../secrets/smtp/SMTP_PASSWORD - -services: - smtp: - image: foxcpp/maddy:0.6 - secrets: [SMTP_PASSWORD] - restart: unless-stopped - depends_on: ["smtp-setup"] - environment: - - MADDY_HOSTNAME=mx.${DOMAIN} - - MADDY_DOMAIN=${DOMAIN} - volumes: - - ../data/smtp/data:/data - # TODO: get from caddy? - - ../secrets/tls/fullchain.pem:/data/tls/fullchain.pem:ro - - ../secrets/tls/privkey.pem:/data/tls/privkey.pem:ro - ports: - - 25:25 - - 143:143 - - 587:587 - - 993:993 - - smtp-setup: - container_name: smtp-setup - image: alpine - restart: no - secrets: [SMTP_PASSWORD] - volumes: - - ./secrets/check-secrets:/check-secrets:ro - entrypoint: ["/check-secrets"] - diff --git a/services/authelia/Proxyfile b/services/testing/authelia/Proxyfile similarity index 63% rename from services/authelia/Proxyfile rename to services/testing/authelia/Proxyfile index 4432146..66d0fb2 100644 --- a/services/authelia/Proxyfile +++ b/services/testing/authelia/Proxyfile @@ -1,3 +1,3 @@ -login.{$DOMAIN} { +auth.{$DOMAIN} { reverse_proxy authelia:9091 } diff --git a/services/testing/authelia/config.yml b/services/testing/authelia/config.yml new file mode 100644 index 0000000..b53229c --- /dev/null +++ b/services/testing/authelia/config.yml @@ -0,0 +1,2 @@ +notifier: + smtp: diff --git a/services/authelia/readme b/services/testing/authelia/readme similarity index 100% rename from services/authelia/readme rename to services/testing/authelia/readme diff --git a/services/testing/authentik.yaml b/services/testing/authentik.yaml new file mode 100644 index 0000000..f9b77e7 --- /dev/null +++ b/services/testing/authentik.yaml @@ -0,0 +1,89 @@ +version: "3.8" + +services: + postgresql: + image: docker.io/library/postgres:12-alpine + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 5s + volumes: + - database:/var/lib/postgresql/data + environment: + POSTGRES_PASSWORD: ${PG_PASS:?database password required} + POSTGRES_USER: ${PG_USER:-authentik} + POSTGRES_DB: ${PG_DB:-authentik} + redis: + image: docker.io/library/redis:alpine + command: --save 60 1 --loglevel warning + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "redis-cli ping | grep PONG"] + start_period: 20s + interval: 30s + retries: 5 + timeout: 3s + volumes: + - redis:/data + authentik: + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2} + restart: unless-stopped + command: server + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgresql + AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} + AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} + AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} + volumes: + - ../data/authentik/media:/media + - ../data/authentik/custom-templates:/templates + ports: + - "${COMPOSE_PORT_HTTP:-9000}:9000" + - "${COMPOSE_PORT_HTTPS:-9443}:9443" + depends_on: + - postgresql + - redis + worker: + image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.2} + restart: unless-stopped + command: worker + environment: + AUTHENTIK_REDIS__HOST: redis + AUTHENTIK_POSTGRESQL__HOST: postgresql + AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik} + AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik} + AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS} + # `user: root` and the docker socket volume are optional. + # See more for the docker socket integration here: + # https://goauthentik.io/docs/outposts/integrations/docker + # Removing `user: root` also prevents the worker from fixing the permissions + # on the mounted folders, so when removing this make sure the folders have the correct UID/GID + # (1000:1000 by default) + user: root + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ../data/authentik/media:/media + - ../data/authentik/custom-templates:/templates + - ../secrets/authentik/certs:/certs + depends_on: + - postgresql + - redis + # setup a reverse proxy for caddy + caddy: + volumes: + - ./authentik/Proxyfile:/etc/caddy.d/authentik:ro + + # backup the zitadel folder + backup: + volumes: + - ../data/authentik:/mnt/backup/src/authentik:ro + +volumes: + database: + driver: local + redis: + driver: local diff --git a/services/testing/authentik/Proxyfile b/services/testing/authentik/Proxyfile new file mode 100644 index 0000000..22bd03d --- /dev/null +++ b/services/testing/authentik/Proxyfile @@ -0,0 +1,3 @@ +auth.{$DOMAIN} { + reverse_proxy authentik:9000 +} diff --git a/services/web.yaml b/services/web.yaml index 9ebe231..c4aeff5 100644 --- a/services/web.yaml +++ b/services/web.yaml @@ -16,7 +16,7 @@ services: - ./web/Caddyfile:/etc/caddy/Caddyfile - ../data/web/site:/site - ../data/web/data:/data - - caddy_config:/config + - ../data/web/config:/config caddy: volumes: @@ -25,6 +25,3 @@ services: backup: volumes: - ../data/web:/mnt/backup/src/web:ro - -volumes: - caddy_config: diff --git a/services/web/Proxyfile b/services/web/Proxyfile index e28dee0..e69c404 100644 --- a/services/web/Proxyfile +++ b/services/web/Proxyfile @@ -1,8 +1,8 @@ web.{$DOMAIN} { - forward_auth authelia:9091 { - uri /api/verify?rd=https://login.{$DOMAIN}/ - copy_headers Remote-User Remote-Groups Remote-Name Remote-Email - } +# forward_auth authelia:9091 { +# uri /api/verify?rd=https://auth.{$DOMAIN}/ +# copy_headers Remote-User Remote-Groups Remote-Name Remote-Email +# } reverse_proxy web:4431 }