[INFRA-77] feat: add email service and SMTP configuration to docker-compose (#3098)

* feat: add email service and SMTP configuration to docker-compose

- Introduced a new email service in docker-compose with environment variables for SMTP configuration.
- Updated Caddyfile to route SMTP traffic for email service.
- Added necessary SMTP ports and health checks for the email service.
- Updated variables.env to include email-related configurations and replicas.

* refactor: clean up Caddyfile SMTP routing configuration

- Simplified the indentation and formatting of the SMTP routing sections in the Caddyfile.
- Ensured consistent structure for the proxy routes for email services on specified ports.

* fix: update SMTP domain binding in Caddyfile

- Changed the SMTP domain binding in the Caddyfile to use '0.0.0.0' for specified ports (10025, 10465, 10587) to allow connections from all network interfaces.
- This adjustment enhances the accessibility of the email service routing configuration.

* fix: update mail server testing instructions in README

- Changed placeholder from `<mail-domain>` to `<host-domain>` for clarity in SMTP connection testing instructions.
- This update improves the accuracy of the documentation for users testing their mail server setup.

* feat: enhance email service configuration in docker-compose and Caddyfile

- Added SMTP environment variables to coolify-compose.yml for better email service configuration.
- Updated docker-compose-caddy.yml to remove redundant SMTP_DOMAIN variable.
- Modified Caddyfile to simplify SMTP domain binding for email service routes.
- Ensured proper permissions for TLS directory in email Dockerfile.

* refactor: remove email service environment variables in coolify-compose.yml

---------

Co-authored-by: akshat5302 <akshatjain9782@gmail.com>
This commit is contained in:
Manish Gupta
2025-05-21 13:29:28 +05:30
committed by GitHub
parent 5fd38e15bb
commit ee6e7596bb
6 changed files with 138 additions and 67 deletions

View File

@@ -323,4 +323,4 @@ services:
- api
- space
- admin
- live
- live

View File

@@ -15,6 +15,12 @@ x-monitor-env: &monitor-env
SERVICE_TCP_POSTGRES: plane-db:5432
TRUSTED_PROXIES: ${TRUSTED_PROXIES:-0.0.0.0/0}
x-email-env: &email-env
SMTP_DOMAIN: ${SMTP_DOMAIN:-0.0.0.0}
EMAIL_SAVE_ENDPOINT: http://api:8000/intake/email
TLS_CERT_PATH: ${TLS_CERT_PATH:-}
TLS_PRIV_KEY_PATH: ${TLS_PRIV_KEY_PATH:-}
x-proxy-env: &proxy-env
SITE_ADDRESS: ${SITE_ADDRESS:-localhost:80}
CERT_EMAIL: ${CERT_EMAIL:-admin@example.com}
@@ -24,6 +30,10 @@ x-proxy-env: &proxy-env
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
LISTEN_SMTP_PORT_25: ${LISTEN_SMTP_PORT_25:-25}
LISTEN_SMTP_PORT_465: ${LISTEN_SMTP_PORT_465:-465}
LISTEN_SMTP_PORT_587: ${LISTEN_SMTP_PORT_587:-587}
x-pg-env: &pg-env
POSTGRES_USER: ${POSTGRES_USER:-plane}
@@ -127,10 +137,9 @@ services:
admin:
image: artifacts.plane.so/makeplane/admin-commercial:${APP_RELEASE_VERSION}
command: node admin/server.js admin
restart: unless-stopped
deploy:
replicas: ${ADMIN_REPLICAS:-1}
restart_policy:
condition: on-failure
depends_on:
- api
- web
@@ -138,10 +147,9 @@ services:
web:
image: artifacts.plane.so/makeplane/web-commercial:${APP_RELEASE_VERSION}
command: node web/server.js web
restart: unless-stopped
deploy:
replicas: ${WEB_REPLICAS:-1}
restart_policy:
condition: on-failure
depends_on:
- api
- worker
@@ -149,10 +157,9 @@ services:
space:
image: artifacts.plane.so/makeplane/space-commercial:${APP_RELEASE_VERSION}
command: node space/server.js space
restart: unless-stopped
deploy:
replicas: ${SPACE_REPLICAS:-1}
restart_policy:
condition: on-failure
depends_on:
- api
- web
@@ -162,10 +169,9 @@ services:
command: node live/dist/start.js live
environment:
<<: [*live-env, *redis-env]
restart: unless-stopped
deploy:
replicas: ${LIVE_REPLICAS:-1}
restart_policy:
condition: on-failure
depends_on:
- api
- web
@@ -176,20 +182,18 @@ services:
- ${INSTALL_DIR:-./plane}/data/monitor:/app
environment:
<<: [*plane, *monitor-env]
restart: unless-stopped
deploy:
replicas: 1
restart_policy:
condition: on-failure
api:
image: artifacts.plane.so/makeplane/backend-commercial:${APP_RELEASE_VERSION}
command: ./bin/docker-entrypoint-api-ee.sh
environment:
<<: [*plane, *app-env, *pg-env, *redis-env, *rabbitmq-env, *docstore-env]
restart: unless-stopped
deploy:
replicas: ${API_REPLICAS:-1}
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/logs/api:/code/plane/logs
depends_on:
@@ -201,10 +205,9 @@ services:
command: ./bin/docker-entrypoint-worker.sh
environment:
<<: [*plane, *app-env, *pg-env, *redis-env, *rabbitmq-env, *docstore-env]
restart: unless-stopped
deploy:
replicas: ${WORKER_REPLICAS:-1}
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/logs/worker:/code/plane/logs
depends_on:
@@ -217,10 +220,9 @@ services:
command: ./bin/docker-entrypoint-beat.sh
environment:
<<: [*plane, *app-env, *pg-env, *redis-env, *rabbitmq-env, *docstore-env]
restart: unless-stopped
deploy:
replicas: ${BEAT_WORKER_REPLICAS:-1}
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/logs/beat-worker:/code/plane/logs
depends_on:
@@ -233,10 +235,9 @@ services:
command: ./bin/docker-entrypoint-migrator.sh
environment:
<<: [*plane, *app-env, *pg-env, *redis-env, *rabbitmq-env, *docstore-env]
restart: "no"
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/logs/migrator:/code/plane/logs
depends_on:
@@ -248,10 +249,9 @@ services:
command: postgres -c 'max_connections=1000'
environment:
<<: [*pg-env]
restart: unless-stopped
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/data/db:/var/lib/postgresql/data
@@ -259,10 +259,9 @@ services:
image: valkey/valkey:7.2.5-alpine
environment:
<<: [*redis-env]
restart: unless-stopped
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/data/redis:/data
@@ -270,10 +269,9 @@ services:
image: rabbitmq:3.13.6-management-alpine
environment:
<<: [*rabbitmq-env]
restart: unless-stopped
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/data/mq:/var/lib/rabbitmq
@@ -282,10 +280,9 @@ services:
command: server /export --console-address ":9090"
environment:
<<: [*docstore-env]
restart: unless-stopped
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
- ${INSTALL_DIR:-./plane}/data/minio/uploads:/export
- ${INSTALL_DIR:-./plane}/data/minio/data:/data
@@ -302,6 +299,21 @@ services:
- plane-redis
- plane-mq
email:
image: artifacts.plane.so/makeplane/email-commercial:${APP_RELEASE_VERSION}
volumes:
- ${INSTALL_DIR:-./plane}/data/email/tls:/opt/email/tls
environment:
<<: [*email-env]
healthcheck:
test: ["CMD", "nc", "-zv", "localhost", "10025"]
interval: 1m30s
timeout: 30s
retries: 5
start_period: 30s
restart: unless-stopped
deploy:
replicas: ${EMAIL_REPLICAS:-1}
# Comment this if you already have a reverse proxy running
proxy:
image: artifacts.plane.so/makeplane/proxy-commercial:${APP_RELEASE_VERSION}
@@ -317,6 +329,18 @@ services:
published: ${LISTEN_HTTPS_PORT:-443}
protocol: tcp
mode: host
- target: 10025
published: ${LISTEN_SMTP_PORT_25:-25}
protocol: tcp
mode: host
- target: 10465
published: ${LISTEN_SMTP_PORT_465:-465}
protocol: tcp
mode: host
- target: 10587
published: ${LISTEN_SMTP_PORT_587:-587}
protocol: tcp
mode: host
volumes:
- ${INSTALL_DIR:-./plane}/caddy/config:/config
- ${INSTALL_DIR:-./plane}/caddy/data:/data
@@ -326,3 +350,4 @@ services:
- space
- admin
- live
- email

View File

@@ -9,6 +9,8 @@ API_REPLICAS=1
WORKER_REPLICAS=1
BEAT_WORKER_REPLICAS=1
LIVE_REPLICAS=1
SILO_REPLICAS=1
EMAIL_REPLICAS=1
LISTEN_HTTP_PORT=80
LISTEN_HTTPS_PORT=443
@@ -112,4 +114,17 @@ MINIO_ENDPOINT_SSL=0
API_KEY_RATE_LIMIT=60/minute
# Live Server Secret Key
LIVE_SERVER_SECRET_KEY=htbqvBJAgpm9bzvf3r4urJer0ENReatceh
LIVE_SERVER_SECRET_KEY=htbqvBJAgpm9bzvf3r4urJer0ENReatceh
# Email Configuration
LISTEN_SMTP_PORT_25=25
LISTEN_SMTP_PORT_465=465
LISTEN_SMTP_PORT_587=587
# If using SMTP DOMAIN as FQDN e.g mail.example.com,
# Generate a valid SSL certificate of SMTP Domain
# Save the TLS Certificate pem files `cert.pem` and `key.pem` in `/opt/plane/data/email/tls` folder
# Set the below path to `tls/cert.pem` and `tls/key.pem`
SMTP_DOMAIN=0.0.0.0
TLS_CERT_PATH=
TLS_PRIV_KEY_PATH=

View File

@@ -43,11 +43,13 @@ EXPOSE 10025 10465 10587
# create a user and group - app-user
RUN addgroup -S app-group && adduser -S app-user -G app-group
RUN chown -R app-user:app-group /opt/email && \
RUN mkdir -p /opt/email/tls && \
chown -R app-user:app-group /opt/email && \
chmod 755 /opt/email/emails && \
chmod 777 /opt/email/keys
chmod 777 /opt/email/keys && \
chmod 777 /opt/email/tls
VOLUME [ "/opt/email/keys" ]
VOLUME [ "/opt/email/tls" ]
USER app-user

View File

@@ -1,54 +1,62 @@
# Required DNS Records for Receiving Mail Server
## 1. MX Record (Essential)
```
Type: MX
Host: yourdomain.com
Value: mail.yourdomain.com
Priority: 10
TTL: 3600
```
## 2. A Record (Essential)
## 1. A Record
> `HOST-DOMAIN` points to the server running the email service (e.g `plane.example.com`).
This can also be replaced with CNAME record of cloud load balancer.
```
Type: A
Host: mail.yourdomain.com
Value: YOUR_SERVER_IP
TTL: 3600
Host: <host-domain>
Value: <public-ip-address>
TTL: Auto | 3600
```
## 3. rDNS/PTR Record (Important)
## 2. MX Record
> `MAIL-DOMAIN` refers to incoming email domain e.g. `intake.example.com`
```
# Set this through your hosting provider/server provider
YOUR_SERVER_IP.in-addr.arpa. IN PTR mail.yourdomain.com.
Type: MX
Host: <mail-domain>
Value: <host-domain>
Priority: 10
TTL: Auto | 3600
```
## 4. SPF Record (Recommended)
## 3. SPF Record
```
Type: TXT
Host: yourdomain.com
Value: v=spf1 ip4:YOUR_SERVER_IP -all
TTL: 3600
Host: <mail-domain>
Value: "v=spf1 ip4:<A-record-ip-host-domain> -all"
TTL: Auto | 3600
```
## 4. DMARC Record
```
Type: TXT
Host: _dmarc.<mail-domain>
Value: "v=DMARC1; p=reject; rua=mailto:<valid-email-addr>"
TTL: Auto | 3600
```
## Verification Commands
```bash
# Verify MX record
dig MX yourdomain.com
# Verify A record
dig A mail.yourdomain.com
dig A <mail-domain>
# Verify PTR record
dig -x YOUR_SERVER_IP
# Verify MX record
dig MX <mail-domain>
# Verify SPF record
dig TXT yourdomain.com
dig TXT <mail-domain>
# Verify DMARC record
dig TXT _dmarc.<mail-domain>
```
You can also visit `https://mxtoolbox.com/` to know the issues with your DNS records configuration.
## Common Issues and Solutions
1. MX Record Issues:
@@ -60,16 +68,13 @@ dig TXT yourdomain.com
- Verify IP address is correct
- Ensure mail subdomain matches MX record
3. PTR Record Issues:
- Must match your mail server hostname
- Set through hosting provider
- Essential for preventing spam classification
4. Testing Mail Server Setup:
## Testing Mail Server Setup:
```bash
# Test SMTP connection
telnet mail.yourdomain.com 25
telnet <host-domain> 25
telnet <host-domain> 465
telnet <host-domain> 587
# Test with real email
swaks --to test@yourdomain.com --server mail.yourdomain.com
```

View File

@@ -19,6 +19,30 @@
email {$CERT_EMAIL:admin@example.com}
acme_ca {$CERT_ACME_CA}
{$CERT_ACME_DNS}
layer4 {
:10025 {
route {
proxy {
upstream email:10025
}
}
}
:10465 {
route {
tls
proxy {
upstream email:10465
}
}
}
:10587 {
route {
proxy {
upstream email:10587
}
}
}
}
servers {
timeouts {
read_body 600s