Compare commits

..

No commits in common. '660f5a39eedf8c85e988765600dae39e2c7f0f9b' and 'ea3c4d90164f3aa0bb10847ca7103f2b4c43df4f' have entirely different histories.

6
.gitignore vendored

@ -1,3 +1,5 @@
/secrets/
/data/
secrets/
data/
.redo
*.tmp
env.production

@ -21,13 +21,16 @@ Fill out env.template and make sure to pass it in the next command
## running
We have two scripts in the `scripts/` directory - up and down
./scripts/up
To stop all the containers, you can ctrl+c, or
./scripts/down
To enable additional services, add their compose file to the following command
podman compose --env-file env.production \
--file services/secrets.yaml \
--file services/backup.yaml \
--file services/smtp.yaml \
--file services/caddy.yaml \
--file services/authelia.yaml \
--file services/web.yaml \
up --build --abort-on-container-exit
## port forwarding

@ -1,7 +0,0 @@
podman compose --env-file env.production \
--file services/secrets.yaml \
--file services/backup.yaml \
--file services/proxy.yaml \
--file services/auth.yaml \
--file services/web.yaml \
down --volumes

@ -1,7 +0,0 @@
podman compose --env-file env.production \
--file services/secrets.yaml \
--file services/backup.yaml \
--file services/proxy.yaml \
--file services/auth.yaml \
--file services/web.yaml \
up --build

@ -1,59 +0,0 @@
version: "3.8"
secrets:
MASTER_KEY:
file: ../secrets/auth/zitadel/MASTER_KEY
services:
backup:
volumes:
- ../data/auth:/mnt/backup/src/auth:ro
generate-secrets:
volumes:
- ../secrets/auth/zitadel/MASTER_KEY:/secrets/auth/zitadel/MASTER_KEY
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:
generate-secrets:
condition: 'service_completed_successfully'
caddy:
condition: 'service_healthy'
crdb:
condition: 'service_healthy'
ports:
- '8321:8080'
crdb:
restart: unless-stopped
image: 'cockroachdb/cockroach:latest-v23.1'
depends_on:
generate-secrets:
condition: 'service_completed_successfully'
command: "start-single-node --insecure --store=path=/cockroach/cockroach-data,size=20%"
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

@ -1,3 +0,0 @@
auth.{$DOMAIN} {
reverse_proxy zitadel:8321
}

@ -0,0 +1,99 @@
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:

@ -1,3 +1,3 @@
auth.{$DOMAIN} {
login.{$DOMAIN} {
reverse_proxy authelia:9091
}

@ -2,21 +2,20 @@ version: "3.8"
secrets:
B2_APPLICATION_KEY:
file: ../secrets/backup/duplicity/B2_APPLICATION_KEY
file: ../secrets/backup/B2_APPLICATION_KEY
B2_APPLICATION_KEY_ID:
file: ../secrets/backup/duplicity/B2_APPLICATION_KEY_ID
file: ../secrets/backup/B2_APPLICATION_KEY_ID
BUCKET_NAME:
file: ../secrets/backup/duplicity/BUCKET_NAME
file: ../secrets/backup/BUCKET_NAME
PASSPHRASE:
file: ../secrets/backup/duplicity/PASSPHRASE
file: ../secrets/backup/PASSPHRASE
services:
backup:
container_name: backup
image: tecnativa/docker-duplicity:latest
restart: unless-stopped
depends_on:
generate-secrets:
condition: 'service_completed_successfully'
depends_on: [secrets]
secrets: [B2_APPLICATION_KEY, B2_APPLICATION_KEY_ID, BUCKET_NAME, PASSPHRASE]
environment:
HOSTNAME: ${DOMAIN}
@ -25,13 +24,8 @@ services:
- ./backup/backup-files:/backup-files:ro
entrypoint: ["/bin/sh", "/backup-files"]
generate-secrets:
volumes:
- ../secrets/backup/duplicity/BUCKET_NAME:/secrets/backup/duplicity/BUCKET_NAME
- ../secrets/backup/duplicity/PASSPHRASE:/secrets/backup/duplicity/PASSPHRASE
# duplicity-postgres:
# backup-postgres:
# container_name: backup-postgres
# image: tecnativa/docker-duplicity-postgres:latest
# restart: unless-stopped
# depends_on: [secrets]
@ -39,6 +33,11 @@ services:
# environment:
# HOSTNAME: ${DOMAIN}
# TZ: America/New_York
# entrypoint: ["/backup-databases"]
# volumes:
# - ./backup/backup-databases:/backup-databases:ro
# entrypoint: ["/bin/sh", "/backup-databases"]
secrets:
volumes:
- ../secrets/backup/BUCKET_NAME:/secrets/backup/BUCKET_NAME
- ../secrets/backup/PASSPHRASE:/secrets/backup/PASSPHRASE

@ -0,0 +1,24 @@
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:

@ -1,57 +0,0 @@
version: "3.8"
secrets:
SMTP_PASSWORD:
file: ../secrets/mail/SMTP_PASSWORD
services:
generate-secrets:
volumes:
- ../secrets/mail/maddy/SMTP_PASSWORD:/secrets/mail/maddy/SMTP_PASSWORD
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:
generate-secrets:
condition: 'service_completed_successfully'
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
check-secrets:
secrets:
- SMTP_PASSWORD

@ -1,4 +0,0 @@
mail.{$DOMAIN} {
reverse_proxy roundcube:9002
}

@ -1,27 +0,0 @@
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

@ -1,16 +1,9 @@
version: "3.8"
services:
generate-secrets:
secrets:
image: alpine/openssl
restart: no
volumes:
- ./secrets/generate-secrets:/generate-secrets:ro
entrypoint: ["/generate-secrets"]
check-secrets:
image: alpine
restart: no
volumes:
- ./secrets/check-secrets:/check-secrets:ro
entrypoint: ["/check-secrets"]

@ -1,14 +0,0 @@
#!/usr/bin/env sh
# this throws an error if any secrets are empty
set -o errexit
set -o nounset
set -o pipefail
for secret in /run/secrets/* ; do
if [ -s "$secret" ]; then
>&2 echo "ERROR: empty secret: $(basename $secret)"
exit 1
fi
done

@ -1,13 +0,0 @@
#!/usr/bin/env sh
# this generates a random 64 char hex string for all empty secret files in /secrets/*/*/*
set -o errexit
set -o nounset
set -o pipefail
for secret in /secrets/*/*/* ; do
test -d "$secret" && rmdir "$secret"
test -s "$secret" && continue
openssl rand -hex 64 > $secret
done

@ -0,0 +1,35 @@
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"]

@ -1,89 +0,0 @@
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

@ -1,3 +0,0 @@
auth.{$DOMAIN} {
reverse_proxy authentik:9000
}

@ -16,7 +16,7 @@ services:
- ./web/Caddyfile:/etc/caddy/Caddyfile
- ../data/web/site:/site
- ../data/web/data:/data
- ../data/web/config:/config
- caddy_config:/config
caddy:
volumes:
@ -25,3 +25,6 @@ services:
backup:
volumes:
- ../data/web:/mnt/backup/src/web:ro
volumes:
caddy_config:

@ -1,8 +1,8 @@
web.{$DOMAIN} {
# forward_auth authelia:9091 {
# uri /api/verify?rd=https://auth.{$DOMAIN}/
# copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
# }
forward_auth authelia:9091 {
uri /api/verify?rd=https://login.{$DOMAIN}/
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy web:4431
}

Loading…
Cancel
Save