stack_secrets reads KV v2 on the target host and writes the stack's .env at 0600, failing loudly on a sealed vault, a bad token, a missing field or an unsafe value. Adds an example OpenBao stack on app and moves webapp onto it; metrics keeps a hand-placed .env. Co-Authored-By: Claude Opus 5.5 <[email protected]>
60 lines
2.1 KiB
YAML
60 lines
2.1 KiB
YAML
# A database-backed application: the stack that needs more than "sync and up".
|
|
#
|
|
# Every credential comes from .env, with no defaults. `${VAR:?message}` makes
|
|
# Compose refuse to start and say which variable is missing, which is strictly
|
|
# better than booting with an empty password. .env is never synced from this
|
|
# repository: the compose_stack role renders it on the host from OpenBao, from
|
|
# the stack_secrets in ansible/playbooks/webapp.yml.
|
|
services:
|
|
db:
|
|
container_name: webapp-db
|
|
image: postgres:17-alpine
|
|
restart: unless-stopped
|
|
# ./pgdata is deliberately NOT pre-created by the playbook: Postgres refuses
|
|
# to start unless its data directory is 0700 or 0750, and the image gets that
|
|
# right on first start. See "Common mistakes" in skills/adding-a-stack.
|
|
volumes:
|
|
- ./pgdata:/var/lib/postgresql/data
|
|
environment:
|
|
POSTGRES_DB: webapp
|
|
POSTGRES_USER: webapp
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?missing from .env; see stack_secrets in webapp.yml}
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U webapp"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- backend
|
|
|
|
web:
|
|
container_name: webapp
|
|
# Built from the payload rather than pulled. stack_build in the playbook
|
|
# decides when a rebuild happens: on an update run, not on every deploy.
|
|
build:
|
|
context: ./app
|
|
image: example/webapp:local
|
|
restart: unless-stopped
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
environment:
|
|
DATABASE_URL: postgres://webapp:${POSTGRES_PASSWORD:?missing from .env; see stack_secrets in webapp.yml}@db:5432/webapp
|
|
SECRET_KEY: ${SECRET_KEY:?missing from .env; see stack_secrets in webapp.yml}
|
|
# Set by the role to stack_dest, so a path handed to a sibling container is
|
|
# the path on the host and not wherever the SSH session happened to land.
|
|
UPLOAD_HOST_DIR: ${PWD}/uploads
|
|
VIRTUAL_HOST: app.example.com
|
|
VIRTUAL_PORT: "8080"
|
|
LETSENCRYPT_HOST: app.example.com
|
|
volumes:
|
|
- ./uploads:/var/lib/webapp/uploads
|
|
networks:
|
|
- backend
|
|
- proxy-net
|
|
|
|
networks:
|
|
backend:
|
|
proxy-net:
|
|
external: true
|