diff --git a/deploy/cli-install/coolify-compose.yml b/deploy/cli-install/coolify-compose.yml index 0c7836135d..8c8cd6c715 100644 --- a/deploy/cli-install/coolify-compose.yml +++ b/deploy/cli-install/coolify-compose.yml @@ -323,4 +323,4 @@ services: - api - space - admin - - live + - live \ No newline at end of file diff --git a/deploy/cli-install/docker-compose-caddy.yml b/deploy/cli-install/docker-compose-caddy.yml index bd7be95a7f..334e325611 100644 --- a/deploy/cli-install/docker-compose-caddy.yml +++ b/deploy/cli-install/docker-compose-caddy.yml @@ -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 \ No newline at end of file diff --git a/deploy/cli-install/variables.env b/deploy/cli-install/variables.env index c32e50ac19..1a537bfa24 100644 --- a/deploy/cli-install/variables.env +++ b/deploy/cli-install/variables.env @@ -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 \ No newline at end of file +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= \ No newline at end of file diff --git a/email/Dockerfile b/email/Dockerfile index d23668d4e3..26dff855a1 100644 --- a/email/Dockerfile +++ b/email/Dockerfile @@ -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 diff --git a/email/README.md b/email/README.md index 3b50d1895d..966d4bba88 100644 --- a/email/README.md +++ b/email/README.md @@ -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: +Value: +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: +Value: +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: +Value: "v=spf1 ip4: -all" +TTL: Auto | 3600 ``` +## 4. DMARC Record +``` +Type: TXT +Host: _dmarc. +Value: "v=DMARC1; p=reject; rua=mailto:" +TTL: Auto | 3600 +``` + + + ## Verification Commands ```bash -# Verify MX record -dig MX yourdomain.com - # Verify A record -dig A mail.yourdomain.com +dig A -# Verify PTR record -dig -x YOUR_SERVER_IP +# Verify MX record +dig MX # Verify SPF record -dig TXT yourdomain.com +dig TXT + +# Verify DMARC record +dig TXT _dmarc. ``` +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 25 +telnet 465 +telnet 587 + -# Test with real email -swaks --to test@yourdomain.com --server mail.yourdomain.com ``` diff --git a/proxy/Caddyfile.ee b/proxy/Caddyfile.ee index 10cd4e7013..900cc9dde0 100644 --- a/proxy/Caddyfile.ee +++ b/proxy/Caddyfile.ee @@ -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