pentacent / keila

Open Source Newsletter Tool.
https://keila.io
GNU Affero General Public License v3.0
1.43k stars 79 forks source link

Compose production example #302

Open almereyda opened 5 months ago

almereyda commented 5 months ago

The current Docker Compose example explicitly states that it is not production ready.

https://github.com/pentacent/keila/blob/90e3e5da2c89afc5984c630a900040d662d53f10/ops/docker-compose.yml

To increase the user base of Keila, it could be beneficial to add a working production example.

We are using the following combination of files to configure a production-ready Keila instance behind a Traefik reverse proxy on the external web network:

.env.example:

URL_HOST=keila.example.com
URL_SCHEMA=https

POSTGRES_DB=com-example-keila
POSTGRES_USER=com-example-keila
POSTGRES_PASSWORD=

SECRET_KEY_BASE=

DB_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres/${POSTGRES_DB}

MAILER_SMTP_FROM_EMAIL=
MAILER_SMTP_HOST=
MAILER_SMTP_USER=
MAILER_SMTP_PASSWORD=
MAILER_SMTP_PORT=465
MAILER_ENABLE_SSL=true
MAILER_ENABLE_STARTTLS=false
#KEILA_USER=
#KEILA_PASSWORD=

USER_CONTENT_DIR=/uploads
USER_CONTENT_BASE_URL=https://uploads.example.com
UPLOADS_HOST=uploads.example.com

CAPTCHA_PROVIDER=hcaptcha
CAPTCHA_SITE_KEY=
CAPTCHA_SECRET_KEY=
CAPTCHA_URL=https://hcaptcha.com/siteverify

compose.yml:

networks:
  internal:
  web:
    external: true

services:
  uploads:
    image: caddy
    networks:
      - web
    volumes:
      - ./.state/uploads:/usr/share/caddy
    labels:
      traefik.enable: true
      traefik.http.routers.com-example-uploads.rule: "Host(`${UPLOADS_HOST}`)"
      traefik.http.routers.com-example-uploads.tls: true
      traefik.http.routers.com-example-uploads.tls.certresolver: letsencrypt

  keila:
    image: pentacent/keila:latest
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      - SECRET_KEY_BASE 
      - DB_URL
      - URL_HOST
      - URL_SCHEMA
      - MAILER_SMTP_HOST
      - MAILER_SMTP_USER
      - MAILER_SMTP_PASSWORD
      - MAILER_SMTP_FROM_EMAIL
      - MAILER_SMTP_PORT
      - MAILER_ENABLE_SSL
      - MAILER_ENABLE_STARTTLS
      - USER_CONTENT_DIR
      - USER_CONTENT_BASE_URL
      - CAPTCHA_PROVIDER
      - CAPTCHA_SITE_KEY
      - CAPTCHA_SECRET_KEY
      - CAPTCHA_URL
    volumes:
      - ./.state/uploads:/uploads
    networks:
      - web
      - internal
    labels:
      traefik.enable: true
      traefik.http.routers.com-example-keila.rule: "Host(`${URL_HOST}`)"
      traefik.http.routers.com-example-keila.tls: true
      traefik.http.routers.com-example-keila.tls.certresolver: letsencrypt

  postgres:
    image: postgres:15-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:
      - ./.state/postgres:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB
      - POSTGRES_USER
      - POSTGRES_PASSWORD
    networks:
      - internal

Where would be the good places to add those examples to the repository and to the documentation?

VincentSC commented 1 month ago

Got a small variation, adding nginx-proxy en my personally preferred style. I think the Traefik-labels and nginx-environment can be mixed, serving both.

Also small fix for the healthcheck - no double $.

Caddy I have not figured out, as the data-dir is documented differently like everywhere.

compose.yml:

services:
  app:
    image: pentacent/keila:latest
    depends_on:
      - db
    volumes:
      - ./volumes/uploads:/uploads
    environment:
      VIRTUAL_PORT: 4000
      VIRTUAL_HOST: "${DOMAIN}"
      LETSENCRYPT_HOST: "${DOMAIN}"
      SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
      DB_URL: "postgres://${DB_USERNAME}:${DB_PASSWORD}@db/${DB_DATABASE}"
      URL_HOST: "${DOMAIN}"
      URL_SCHEMA: "https"
      PORT: 4000
      MAILER_SMTP_HOST: "${MAILER_SMTP_HOST}"
      MAILER_SMTP_USER: "${MAILER_SMTP_USER}"
      MAILER_SMTP_PASSWORD: "${MAILER_SMTP_PASSWORD}"
      MAILER_SMTP_FROM_EMAIL: "${MAILER_SMTP_FROM_EMAIL}"
      MAILER_SMTP_PORT: "${MAILER_SMTP_PORT}"
      MAILER_ENABLE_SSL: "${MAILER_ENABLE_SSL}"
      MAILER_ENABLE_STARTTLS: "${MAILER_ENABLE_STARTTLS}"
      USER_CONTENT_DIR: "${USER_CONTENT_DIR}"
      USER_CONTENT_BASE_URL: "https://${UPLOADS_DOMAIN}"
      KEILA_USER: "${KEILA_USER}"
      KEILA_PASSWORD: "${KEILA_PASSWORD}"
    labels:
      traefik.enable: true
      traefik.http.routers.com-example-keila.rule: "Host(`${URL_HOST}`)"
      traefik.http.routers.com-example-keila.tls: true
      traefik.http.routers.com-example-keila.tls.certresolver: letsencrypt
    restart: unless-stopped
    networks:
      - default
      - nginx-proxy

  uploads:
    image: caddy
    volumes:
      - ./volumes/uploads:/usr/share/caddy
#      - ./volumes/uploads:/data/caddy
    environment:
      VIRTUAL_HOST: "${UPLOADS_DOMAIN}"
      LETSENCRYPT_HOST: "${UPLOADS_DOMAIN}"
    labels:
      traefik.enable: true
      traefik.http.routers.com-example-uploads.rule: "Host(`${UPLOADS_DOMAIN}`)"
      traefik.http.routers.com-example-uploads.tls: true
      traefik.http.routers.com-example-uploads.tls.certresolver: letsencrypt
    networks:
      - default
      - nginx-proxy

  db:
    image: postgres:15
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d ${DB_DATABASE} -U ${DB_USERNAME}"]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 5s
    volumes:
      - ./volumes/postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${DB_DATABASE}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    networks:
      - default

networks:
  default:
    driver: "bridge"
  nginx-proxy:
    external: true
    name: nginx-proxy

.env:

COMPOSE_PROJECT_NAME=keila
DOMAIN=newsletter.example.com
URL_SCHEMA=https

DB_DATABASE=keila
DB_USERNAME=keila
DB_PASSWORD=

# head -c 48 /dev/urandom | base64
SECRET_KEY_BASE= 

KEILA_USER=user@domain.com
KEILA_PASSWORD=

MAILER_SMTP_FROM_EMAIL=from@example.com
MAILER_SMTP_HOST=
MAILER_SMTP_USER=
MAILER_SMTP_PASSWORD=
MAILER_SMTP_PORT=465
MAILER_ENABLE_SSL=false
MAILER_ENABLE_STARTTLS=true

KEILA_USER=user@example.com
KEILA_PASSWORD=

USER_CONTENT_DIR=/uploads
UPLOADS_DOMAIN=newsletteruploads.example.com

CAPTCHA_PROVIDER=hcaptcha
CAPTCHA_SITE_KEY=
CAPTCHA_SECRET_KEY=
CAPTCHA_URL=https://hcaptcha.com/siteverify

The compose.yml can be checked with docker compose config

The moment we discuss the personal style and not correctness, security, etc, then it's finished :)