diff --git a/.env.example b/.env.example index 1bcbd60..73325f1 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,11 @@ # --- Portainer / Compose --- APP_PORT="3000" -POSTGRES_DB="formbuilder" -POSTGRES_USER="formbuilder" -POSTGRES_PASSWORD="change-this" +DATABASE_URL="postgresql://user:password@postgres-host:5432/formbuilder" + +# Only needed if using docker-compose.postgres.yml instead of an existing DB. +# POSTGRES_DB="formbuilder" +# POSTGRES_USER="formbuilder" +# POSTGRES_PASSWORD="change-this" # --- Auth.js --- # Generate with: openssl rand -base64 32 diff --git a/README.md b/README.md index 89906f4..cde45e6 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,7 @@ The app container runs `prisma migrate deploy` before starting the Next.js stand ```bash APP_PORT=3000 -POSTGRES_DB=formbuilder -POSTGRES_USER=formbuilder -POSTGRES_PASSWORD=replace-with-a-strong-password +DATABASE_URL=postgresql://user:password@postgres-host:5432/formbuilder AUTH_SECRET=replace-with-openssl-rand-base64-32 AUTH_URL=https://forms.example.com @@ -34,6 +32,12 @@ AUTH_BOOTSTRAP_ADMINS=you@example.com Optional values are documented in `.env.example` for Redis rate limiting, email, file storage, hCaptcha, and webhook worker auth. +If you do not already have Postgres, deploy with both Compose files and set `POSTGRES_PASSWORD`: + +```bash +docker compose -f docker-compose.yml -f docker-compose.postgres.yml up --build +``` + ## Authentik Setup Create an OAuth2/OpenID provider in Authentik: @@ -50,11 +54,12 @@ The first successful signer becomes an admin. Any emails listed in `AUTH_BOOTSTR ## Persistent Data -The compose stack creates two named volumes: +The default compose stack creates one named volume: -- `postgres_data`: Postgres database - `uploads`: local uploaded files mounted at `/app/uploads` +When using `docker-compose.postgres.yml`, it also creates `postgres_data` for the bundled database. + For multi-instance deployments, set `RATE_LIMIT_DRIVER=redis` and provide `REDIS_URL`. For durable object storage outside the app container, configure the S3 values in `.env.example`. ## Useful Commands diff --git a/docker-compose.postgres.yml b/docker-compose.postgres.yml new file mode 100644 index 0000000..1b688ee --- /dev/null +++ b/docker-compose.postgres.yml @@ -0,0 +1,25 @@ +services: + app: + depends_on: + postgres: + condition: service_healthy + environment: + DATABASE_URL: postgresql://${POSTGRES_USER:-formbuilder}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-formbuilder} + + postgres: + image: postgres:16-alpine + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB:-formbuilder} + POSTGRES_USER: ${POSTGRES_USER:-formbuilder} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-formbuilder} -d ${POSTGRES_DB:-formbuilder}"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: diff --git a/docker-compose.yml b/docker-compose.yml index d5bf78e..ac0fd11 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,13 +4,10 @@ services: context: . dockerfile: Dockerfile restart: unless-stopped - depends_on: - postgres: - condition: service_healthy environment: NODE_ENV: production PORT: 3000 - DATABASE_URL: postgresql://${POSTGRES_USER:-formbuilder}:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-formbuilder} + DATABASE_URL: ${DATABASE_URL:?set DATABASE_URL} AUTH_SECRET: ${AUTH_SECRET:?set AUTH_SECRET} AUTH_URL: ${AUTH_URL:?set AUTH_URL} PUBLIC_BASE_URL: ${AUTH_URL} @@ -40,21 +37,5 @@ services: volumes: - uploads:/app/uploads - postgres: - image: postgres:16-alpine - restart: unless-stopped - environment: - POSTGRES_DB: ${POSTGRES_DB:-formbuilder} - POSTGRES_USER: ${POSTGRES_USER:-formbuilder} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} - volumes: - - postgres_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-formbuilder} -d ${POSTGRES_DB:-formbuilder}"] - interval: 10s - timeout: 5s - retries: 5 - volumes: - postgres_data: uploads: