Skip to content

Instantly share code, notes, and snippets.

@regenrek
Last active September 8, 2025 07:37
Show Gist options
  • Save regenrek/2c44005f0ea4dcd8fe70014744d7213a to your computer and use it in GitHub Desktop.
Save regenrek/2c44005f0ea4dcd8fe70014744d7213a to your computer and use it in GitHub Desktop.
Coolify - Plausible SMTP Mailer
# Example docker-compose service for self-hosted Plausible in Coolify
# with working SMTP (Resend over SMTPS/465)
# We use Bamboo.Mua instead of Bamboo.SMTPAdapter because it handles
# TLS verification correctly in Alpine-based images (no cacerts: undefined error).
services:
plausible:
image: "ghcr.io/plausible/community-edition:v3"
command: >
sh -c "sleep 10 &&
/entrypoint.sh db createdb &&
/entrypoint.sh db migrate &&
/entrypoint.sh run"
environment:
- SERVICE_FQDN_PLAUSIBLE
- DATABASE_URL=postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@plausible-db:5432/${POSTGRES_DB:-plausible-db}
- CLICKHOUSE_DATABASE_URL=http://plausible-events-db:8123/plausible_events_db
- BASE_URL=${SERVICE_FQDN_PLAUSIBLE}
- SECRET_KEY_BASE=${SERVICE_BASE64_64_PLAUSIBLE}
- TOTP_VAULT_KEY=${SERVICE_REALBASE64_32_TOTP}
# Optional: Google login
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET}
# Email setup (Resend via SMTPS 465 with Bamboo.Mua)
- MAILER_ADAPTER=Bamboo.Mua
- MAILER_EMAIL=${MAILER_EMAIL} # e.g. [email protected]
- MAILER_NAME=${MAILER_NAME}
- SMTP_HOST_ADDR=smtp.resend.com
- SMTP_HOST_PORT=465
- SMTP_HOST_SSL_ENABLED=true
- SMTP_USER_NAME=resend
- SMTP_USER_PWD=${SMTP_USER_PWD} # your Resend API key
- EXTRA_CONFIG_PATH=/app/smtp_tls.exs
volumes:
- type: bind
source: ./smtp_tls.exs
target: /app/smtp_tls.exs
read_only: true
content: |
import Config
config :plausible, Plausible.Mailer,
ssl: [
verify: :verify_peer,
cacertfile: "/etc/ssl/cert.pem",
middlebox_comp_mode: false
],
retries: 2
depends_on:
plausible-db:
condition: service_healthy
plausible-events-db:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8000/api/health"]
interval: 10s
timeout: 5s
retries: 5
start_period: 45s
plausible-db:
image: "postgres:16-alpine"
volumes:
- plausible-postgres-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=${POSTGRES_DB:-plausible-db}
- POSTGRES_USER=${SERVICE_USER_POSTGRES}
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 20s
retries: 10
plausible-events-db:
image: "clickhouse/clickhouse-server:24.12-alpine"
environment:
- CLICKHOUSE_SKIP_USER_SETUP=1
volumes:
- plausible-events-data:/var/lib/clickhouse
- type: bind
source: ./clickhouse/clickhouse-config.xml
target: /etc/clickhouse-server/config.d/logging.xml
read_only: true
content: |
<clickhouse>
<profiles>
<default>
<log_queries>0</log_queries>
<log_query_threads>0</log_query_threads>
</default>
</profiles>
</clickhouse>
- type: bind
source: ./clickhouse/clickhouse-user-config.xml
target: /etc/clickhouse-server/users.d/logging.xml
read_only: true
content: |
<clickhouse>
<logger>
<level>warning</level>
<console>true</console>
</logger>
<query_thread_log remove="remove"/>
<query_log remove="remove"/>
<text_log remove="remove"/>
<trace_log remove="remove"/>
<metric_log remove="remove"/>
<asynchronous_metric_log remove="remove"/>
<session_log remove="remove"/>
<part_log remove="remove"/>
</clickhouse>
ulimits:
nofile:
soft: 262144
hard: 262144
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1"]
start_period: 30s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment