chore: update prod-compose to use file-envs for secrets
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Simon 2025-12-03 12:38:24 +01:00
parent ee094eec2f
commit d8384098b4
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
5 changed files with 66 additions and 18 deletions

3
.gitignore vendored
View file

@ -41,3 +41,6 @@ npm-debug.log
.env .env
.elixir_ls/ .elixir_ls/
# Docker secrets directory (generated by `just init-secrets`)
/secrets/

View file

@ -85,3 +85,26 @@ clean:
mix clean mix clean
rm -rf .elixir_ls rm -rf .elixir_ls
rm -rf _build rm -rf _build
# Production environment commands
# ================================
# Initialize secrets directory with generated secrets (only if not exists)
init-secrets:
#!/usr/bin/env bash
set -euo pipefail
if [ -d "secrets" ]; then
echo "Secrets directory already exists. Skipping generation."
exit 0
fi
echo "Creating secrets directory and generating secrets..."
mkdir -p secrets
mix phx.gen.secret > secrets/secret_key_base.txt
mix phx.gen.secret > secrets/token_signing_secret.txt
openssl rand -base64 32 | tr -d '\n' > secrets/db_password.txt
touch secrets/oidc_client_secret.txt
echo "Secrets generated in ./secrets/"
# Start production environment with Docker Compose
start-prod: init-secrets
docker compose -f docker-compose.prod.yml up -d

View file

@ -250,7 +250,7 @@ For actual production deployment:
- Set `OIDC_BASE_URL` to your production OIDC provider - Set `OIDC_BASE_URL` to your production OIDC provider
- Configure proper Docker networks - Configure proper Docker networks
3. **Set up SSL/TLS** (e.g., via reverse proxy like Nginx/Traefik) 3. **Set up SSL/TLS** (e.g., via reverse proxy like Nginx/Traefik)
4. **Use secure secrets management** (environment variables, Docker secrets, vault) 4. **Use secure secrets management** — All sensitive environment variables support a `_FILE` suffix for Docker secrets (e.g., `SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base`). See `docker-compose.prod.yml` for an example setup with Docker secrets.
5. **Configure database backups** 5. **Configure database backups**

View file

@ -140,11 +140,10 @@ if config_env() == :prod do
config :mv, MvWeb.Endpoint, config :mv, MvWeb.Endpoint,
url: [host: host, port: 443, scheme: "https"], url: [host: host, port: 443, scheme: "https"],
http: [ http: [
# Enable IPv6 and bind on all interfaces. # Bind on all IPv4 interfaces.
# Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access. # Use {0, 0, 0, 0, 0, 0, 0, 0} for IPv6, or {127, 0, 0, 1} for localhost only.
# See the documentation on https://hexdocs.pm/bandit/Bandit.html#t:options/0 # See the documentation on https://hexdocs.pm/bandit/Bandit.html#t:options/0
# for details about using IPv6 vs IPv4 and loopback vs public addresses. ip: {0, 0, 0, 0},
ip: {0, 0, 0, 0, 0, 0, 0, 0},
port: port port: port
], ],
secret_key_base: secret_key_base, secret_key_base: secret_key_base,

View file

@ -1,22 +1,33 @@
services: services:
app: app:
image: git.local-it.org/local-it/mitgliederverwaltung:latest image: mitgliederverwaltung:latest
container_name: mv-prod-app container_name: mv-prod-app
# Use host network for local testing to access localhost:8080 (Rauthy) ports:
# In real production, remove this and use external OIDC provider - "4001:4001"
network_mode: host
environment: environment:
DATABASE_URL: "ecto://postgres:postgres@localhost:5001/mv_prod" # Database configuration using separate variables
SECRET_KEY_BASE: "${SECRET_KEY_BASE}" # Use Docker service name for internal networking
TOKEN_SIGNING_SECRET: "${TOKEN_SIGNING_SECRET}" DATABASE_HOST: "db-prod"
PHX_HOST: "${PHX_HOST}" DATABASE_PORT: "5432"
DATABASE_USER: "postgres"
DATABASE_NAME: "mv_prod"
DATABASE_PASSWORD_FILE: "/run/secrets/db_password"
# Phoenix secrets via Docker secrets
SECRET_KEY_BASE_FILE: "/run/secrets/secret_key_base"
TOKEN_SIGNING_SECRET_FILE: "/run/secrets/token_signing_secret"
PHX_HOST: "${PHX_HOST:-localhost}"
PORT: "4001" PORT: "4001"
PHX_SERVER: "true" PHX_SERVER: "true"
# Rauthy OIDC config - uses localhost because of host network mode # Rauthy OIDC config - use host.docker.internal to reach host services
OIDC_CLIENT_ID: "mv" OIDC_CLIENT_ID: "mv"
OIDC_BASE_URL: "http://localhost:8080/auth/v1" OIDC_BASE_URL: "http://host.docker.internal:8080/auth/v1"
OIDC_CLIENT_SECRET: "${OIDC_CLIENT_SECRET:-}" OIDC_CLIENT_SECRET_FILE: "/run/secrets/oidc_client_secret"
OIDC_REDIRECT_URI: "http://localhost:4001/auth/user/rauthy/callback" OIDC_REDIRECT_URI: "http://localhost:4001/auth/user/rauthy/callback"
secrets:
- db_password
- secret_key_base
- token_signing_secret
- oidc_client_secret
depends_on: depends_on:
- db-prod - db-prod
restart: unless-stopped restart: unless-stopped
@ -26,13 +37,25 @@ services:
container_name: mv-prod-db container_name: mv-prod-db
environment: environment:
POSTGRES_USER: postgres POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres POSTGRES_PASSWORD_FILE: /run/secrets/db_password
POSTGRES_DB: mv_prod POSTGRES_DB: mv_prod
secrets:
- db_password
volumes: volumes:
- postgres_data_prod:/var/lib/postgresql/data - postgres_data_prod:/var/lib/postgresql/data
ports: ports:
- "5001:5432" - "5001:5432"
restart: unless-stopped restart: unless-stopped
secrets:
db_password:
file: ./secrets/db_password.txt
secret_key_base:
file: ./secrets/secret_key_base.txt
token_signing_secret:
file: ./secrets/token_signing_secret.txt
oidc_client_secret:
file: ./secrets/oidc_client_secret.txt
volumes: volumes:
postgres_data_prod: postgres_data_prod: