diff --git a/deploy.env b/deploy.env index 6bdfb86ee..a9e321c32 100644 --- a/deploy.env +++ b/deploy.env @@ -3,16 +3,7 @@ # ============================================================================= # This file is a template for docker compose deployment # Copy this file to .env and change the values as needed - - -# Fully qualified domain name for the deployment. Replace localhost with your domain, -# such as mydomain.com. -FQDN=localhost - -# Change this to https if you wish to enable TLS. -SCHEME=http - -APPFLOWY_BASE_URL=${SCHEME}://${FQDN} +APPFLOWY_BASE_URL=http://localhost # ============================================================================= # 🗄️ DATABASE & CACHE: Core data infrastructure @@ -24,13 +15,23 @@ POSTGRES_USER=postgres POSTGRES_PASSWORD=password POSTGRES_PORT=5432 POSTGRES_DB=postgres +POSTGRES_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} # Redis Settings REDIS_HOST=redis REDIS_PORT=6379 # ============================================================================= -# 🏗️ INFRASTRUCTURE SERVICES: Object storage and networking +# 📤️ EMAIL configuration +# ============================================================================= +SMTP_HOST=your-smtp-host.com +SMTP_USER=user@domain.com +SMTP_PASSWORD=password +SMTP_PORT=587 +SMTP_MAIL_FROM=appflowy@domain.com + +# ============================================================================= +# 🏗️ INFRASTRUCTURE SERVICES: Object storage # ============================================================================= # MinIO Configuration: S3-compatible object storage for file uploads and attachments @@ -59,7 +60,7 @@ APPFLOWY_GOTRUE_BASE_URL=http://gotrue:9999 # URL that connects to the postgres docker container. If your password contains special characters, # instead of using ${POSTGRES_PASSWORD}, you will need to convert them into url encoded format. # For example, `p@ssword` will become `p%40ssword`. -APPFLOWY_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} +APPFLOWY_DATABASE_URL=${POSTGRES_URL} # AppFlowy Service Configuration # Access Control System: Enables/disables permission-based access control @@ -82,10 +83,7 @@ APPFLOWY_DATABASE_MAX_CONNECTIONS=40 # URL that connects to the redis docker container APPFLOWY_REDIS_URI=redis://${REDIS_HOST}:${REDIS_PORT} -# GoTrue database connection. If your password contains special characters, -# instead of using ${POSTGRES_PASSWORD}, use the url encoded version. -# For example, `p@ssword` will become `p%40ssword` -GOTRUE_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=auth +GOTRUE_DATABASE_URL=${POSTGRES_URL}?search_path=auth # ============================================================================= # 🔐 GOTRUE: Authentication service configuration @@ -117,9 +115,6 @@ GOTRUE_MAILER_AUTOCONFIRM=true # Set this to true if users can only join by invite GOTRUE_DISABLE_SIGNUP=false -# Number of emails that can be sent per minute -GOTRUE_RATE_LIMIT_EMAIL_SENT=100 - # Email Templates # Optional. You can provide a public http link (eg. github) to customize your magic link template. # Refer to https://github.com/supabase/auth?tab=readme-ov-file#configuration for details on how to create a custom email template. @@ -143,29 +138,6 @@ ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=http://appflowy_cloud:8000 # or set it to empty string. ADMIN_FRONTEND_PATH_PREFIX=/console -# ============================================================================= -# 📧 EMAIL CONFIGURATION: SMTP settings (optional but recommended for production) -# ============================================================================= - -# If you intend to use mail confirmation, you need to set the SMTP configuration below -# You would then need to set GOTRUE_MAILER_AUTOCONFIRM=false -# Check for logs in gotrue service if there are any issues with email confirmation -# Note that smtps will be used for port 465, otherwise plain smtp with optional STARTTLS -GOTRUE_SMTP_HOST=smtp.gmail.com -GOTRUE_SMTP_PORT=465 -GOTRUE_SMTP_USER=email_sender@some_company.com -GOTRUE_SMTP_PASS=email_sender_password -GOTRUE_SMTP_ADMIN_EMAIL=comp_admin@some_company.com - -# AppFlowy Cloud Mailer -# Note that smtps (TLS) is always required, even for ports other than 465 -APPFLOWY_MAILER_SMTP_HOST=smtp.gmail.com -APPFLOWY_MAILER_SMTP_PORT=465 -APPFLOWY_MAILER_SMTP_USERNAME=email_sender@some_company.com -APPFLOWY_MAILER_SMTP_EMAIL=email_sender@some_company.com -APPFLOWY_MAILER_SMTP_PASSWORD=email_sender_password -APPFLOWY_MAILER_SMTP_TLS_KIND=wrapper # "none" "wrapper" "required" "opportunistic" - # ============================================================================= # 🔑 OAUTH PROVIDERS: Third-party authentication (optional) # ============================================================================= @@ -283,7 +255,7 @@ APPFLOWY_EMBEDDING_CHUNK_OVERLAP=200 # AppFlowy Indexer (for search functionality) APPFLOWY_INDEXER_ENABLED=true -APPFLOWY_INDEXER_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} +APPFLOWY_INDEXER_DATABASE_URL=${POSTGRES_URL} APPFLOWY_INDEXER_REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} APPFLOWY_INDEXER_EMBEDDING_BUFFER_SIZE=5000 @@ -299,7 +271,7 @@ APPFLOWY_COLLABORATE_REMOVE_BATCH_SIZE=100 # AppFlowy Worker Service APPFLOWY_WORKER_REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT} -APPFLOWY_WORKER_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB} +APPFLOWY_WORKER_DATABASE_URL=${POSTGRES_URL} APPFLOWY_WORKER_DATABASE_NAME=${POSTGRES_DB} # ============================================================================= @@ -308,21 +280,9 @@ APPFLOWY_WORKER_DATABASE_NAME=${POSTGRES_DB} # AppFlowy Web # If your AppFlowy Web is hosted on a different domain, update this variable to the correct domain +# If you are running AppFlowy Web locally for development purpose, use http://localhost:3000 APPFLOWY_WEB_URL=${APPFLOWY_BASE_URL} -# If you are running AppFlowy Web locally for development purpose, use the following value instead -# APPFLOWY_WEB_URL=http://localhost:3000 - -# ============================================================================= -# 🗄️ PGADMIN: Database Management Web Interface -# ============================================================================= - -# PgAdmin credentials for database management web UI -# You can access pgadmin at http://your-host/pgadmin -# Use the APPFLOWY_DATABASE_URL values when connecting to the database -PGADMIN_DEFAULT_EMAIL=admin@example.com -PGADMIN_DEFAULT_PASSWORD=password - # ============================================================================= # 🌐 NGINX: Reverse proxy and web server configuration # ============================================================================= diff --git a/docker-compose.yml b/docker-compose.yml index 53f70baf1..b6591778c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,14 +3,11 @@ services: nginx: restart: on-failure - image: nginx + image: appflowyinc/nginx + build: docker/nginx ports: - - ${NGINX_PORT:-80}:80 # Disable this if you are using TLS + - ${NGINX_PORT:-80}:80 - ${NGINX_TLS_PORT:-443}:443 - volumes: - - ./nginx/nginx.conf:/etc/nginx/nginx.conf - - ./nginx/ssl/certificate.crt:/etc/nginx/ssl/certificate.crt - - ./nginx/ssl/private_key.key:/etc/nginx/ssl/private_key.key # You do not need this if you have configured to use your own s3 file storage minio: @@ -28,10 +25,9 @@ services: restart: on-failure image: pgvector/pgvector:pg16 environment: - - POSTGRES_USER=${POSTGRES_USER:-postgres} - - POSTGRES_DB=${POSTGRES_DB:-postgres} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password} - - POSTGRES_HOST=${POSTGRES_HOST:-postgres} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} healthcheck: test: [ "CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}" ] interval: 5s @@ -78,10 +74,10 @@ services: - API_EXTERNAL_URL=${API_EXTERNAL_URL} - DATABASE_URL=${GOTRUE_DATABASE_URL} - PORT=9999 - - GOTRUE_SMTP_HOST=${GOTRUE_SMTP_HOST} # e.g. smtp.gmail.com - - GOTRUE_SMTP_PORT=${GOTRUE_SMTP_PORT} # e.g. 465 - - GOTRUE_SMTP_USER=${GOTRUE_SMTP_USER} # email sender, e.g. noreply@appflowy.io - - GOTRUE_SMTP_PASS=${GOTRUE_SMTP_PASS} # email password + - GOTRUE_SMTP_HOST=${SMTP_HOST} + - GOTRUE_SMTP_PORT=${SMTP_PORT} + - GOTRUE_SMTP_USER=${SMTP_USER} + - GOTRUE_SMTP_PASS=${SMTP_PASSWORD} - GOTRUE_MAILER_URLPATHS_CONFIRMATION=/gotrue/verify - GOTRUE_MAILER_URLPATHS_INVITE=/gotrue/verify - GOTRUE_MAILER_URLPATHS_RECOVERY=/gotrue/verify @@ -128,12 +124,11 @@ services: - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET} - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION} - APPFLOWY_S3_PRESIGNED_URL_ENDPOINT=${APPFLOWY_S3_PRESIGNED_URL_ENDPOINT} - - APPFLOWY_MAILER_SMTP_HOST=${APPFLOWY_MAILER_SMTP_HOST} - - APPFLOWY_MAILER_SMTP_PORT=${APPFLOWY_MAILER_SMTP_PORT} - - APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME} - - APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL} - - APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD} - - APPFLOWY_MAILER_SMTP_TLS_KIND=${APPFLOWY_MAILER_SMTP_TLS_KIND} + - APPFLOWY_MAILER_SMTP_HOST=${SMTP_HOST} + - APPFLOWY_MAILER_SMTP_PORT=${SMTP_PORT} + - APPFLOWY_MAILER_SMTP_USERNAME=${SMTP_USER} + - APPFLOWY_MAILER_SMTP_EMAIL=${EMAIL_FROM} + - APPFLOWY_MAILER_SMTP_PASSWORD=${SMTP_PASSWORD} - APPFLOWY_ACCESS_CONTROL=${APPFLOWY_ACCESS_CONTROL} - APPFLOWY_DATABASE_MAX_CONNECTIONS=${APPFLOWY_DATABASE_MAX_CONNECTIONS} - AI_SERVER_HOST=${AI_SERVER_HOST} @@ -200,12 +195,11 @@ services: - APPFLOWY_S3_SECRET_KEY=${APPFLOWY_S3_SECRET_KEY} - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET} - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION} - - APPFLOWY_MAILER_SMTP_HOST=${APPFLOWY_MAILER_SMTP_HOST} - - APPFLOWY_MAILER_SMTP_PORT=${APPFLOWY_MAILER_SMTP_PORT} - - APPFLOWY_MAILER_SMTP_USERNAME=${APPFLOWY_MAILER_SMTP_USERNAME} - - APPFLOWY_MAILER_SMTP_EMAIL=${APPFLOWY_MAILER_SMTP_EMAIL} - - APPFLOWY_MAILER_SMTP_PASSWORD=${APPFLOWY_MAILER_SMTP_PASSWORD} - - APPFLOWY_MAILER_SMTP_TLS_KIND=${APPFLOWY_MAILER_SMTP_TLS_KIND} + - APPFLOWY_MAILER_SMTP_HOST=${SMTP_HOST} + - APPFLOWY_MAILER_SMTP_PORT=${SMTP_PORT} + - APPFLOWY_MAILER_SMTP_USERNAME=${SMTP_USER} + - APPFLOWY_MAILER_SMTP_EMAIL=${EMAIL_FROM} + - APPFLOWY_MAILER_SMTP_PASSWORD=${SMTP_PASSWORD} depends_on: postgres: condition: service_healthy diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 000000000..6237ae294 --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,4 @@ +FROM nginxinc/nginx-unprivileged:stable-alpine + +COPY --chown=nginx nginx.conf /etc/nginx/conf.d/default.conf +COPY ssl/ /etc/nginx/ssl/ diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 000000000..443557779 --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,226 @@ +# Appflowy minimal nginx configuration +# If you use use a reverse proxy, look the `external_proxy_config/nginx`. + +# Use Docker internal resolver +resolver 127.0.0.11 valid=10s; + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +map $http_origin $cors_origin { + # AppFlowy Web origin + "~^http://localhost:3000$" $http_origin; + default "null"; +} + +server { + listen 8080; + + # https://github.com/nginxinc/nginx-prometheus-exporter + location = /stub_status { + stub_status; + } +} + + +server { + ssl_certificate /etc/nginx/ssl/certificate.crt; + ssl_certificate_key /etc/nginx/ssl/private_key.key; + + listen 80; + listen 443 ssl; + client_max_body_size 10M; + + underscores_in_headers on; + set $appflowy_cloud_backend "http://appflowy_cloud:8000"; + set $gotrue_backend "http://gotrue:9999"; + set $admin_frontend_backend "http://admin_frontend:3000"; + set $appflowy_web_backend "http://appflowy_web:80"; + set $minio_backend "http://minio:9001"; + set $minio_api_backend "http://minio:9000"; + # Host name for minio, used internally within docker compose + set $minio_internal_host "minio:9000"; + set $pgadmin_backend "http://pgadmin:80"; + + proxy_set_header Host $host; + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # GoTrue + location /gotrue/ { + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Credentials' 'true' always; + add_header 'Access-Control-Allow-Headers' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Max-Age' 3600 always; + add_header 'Content-Type' 'text/plain charset=UTF-8' always; + add_header 'Content-Length' 0 always; + return 204; + } + + proxy_pass $gotrue_backend; + + rewrite ^/gotrue(/.*)$ $1 break; + + # Allow headers like redirect_to to be handed over to the gotrue + # for correct redirecting + proxy_pass_request_headers on; + } + + # WebSocket + location /ws { + proxy_pass $appflowy_cloud_backend; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_read_timeout 86400s; + } + + location /api { + proxy_pass $appflowy_cloud_backend; + proxy_set_header X-Request-Id $request_id; + + # Set CORS headers for other requests + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; + add_header 'Access-Control-Max-Age' 3600 always; + return 204; + } + + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; + add_header 'Access-Control-Max-Age' 3600 always; + + location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ { + proxy_pass $appflowy_cloud_backend; + proxy_request_buffering off; + client_max_body_size 256M; + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; + add_header 'Access-Control-Max-Age' 3600 always; + return 204; + } + + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; + add_header 'Access-Control-Max-Age' 3600 always; + } + + # AppFlowy-Cloud + location /api/chat { + proxy_pass $appflowy_cloud_backend; + + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding on; + proxy_buffering off; + proxy_cache off; + + proxy_read_timeout 600s; + proxy_connect_timeout 600s; + proxy_send_timeout 600s; + } + + location /api/import { + proxy_pass $appflowy_cloud_backend; + + # Set headers + proxy_set_header X-Request-Id $request_id; + + # Handle CORS + add_header 'Access-Control-Allow-Origin' $cors_origin always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Device-Id' always; + add_header 'Access-Control-Max-Age' 3600 always; + + # Timeouts + proxy_read_timeout 600s; + proxy_connect_timeout 600s; + proxy_send_timeout 600s; + + # Disable buffering for large file uploads + proxy_request_buffering off; + proxy_buffering off; + proxy_cache off; + client_max_body_size 2G; + } + } + + # Minio Web UI + # Derive from: https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html + # Optional Module, comment this section if you did not deploy minio in docker-compose.yml + # This endpoint is meant to be used for the MinIO Web UI, accessible via the admin portal + location /minio/ { + proxy_pass $minio_backend; + + rewrite ^/minio/(.*) /$1 break; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-NginX-Proxy true; + + ## This is necessary to pass the correct IP to be hashed + real_ip_header X-Real-IP; + + proxy_connect_timeout 300s; + + ## To support websockets in MinIO versions released after January 2023 + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress) + # Uncomment the following line to set the Origin request to an empty string + # proxy_set_header Origin ''; + + chunked_transfer_encoding off; + } + + # Optional Module, comment this section if you did not deploy minio in docker-compose.yml + # This is used for presigned url, which is needs to be exposed to the AppFlowy client application. + location /minio-api/ { + proxy_pass $minio_api_backend; + + # Set the host to internal host because the presigned url was signed against the internal host + proxy_set_header Host $minio_internal_host; + rewrite ^/minio-api/(.*) /$1 break; + + proxy_connect_timeout 300s; + # Default is HTTP/1, keepalive is only enabled in HTTP/1.1 + proxy_http_version 1.1; + proxy_set_header Connection ""; + chunked_transfer_encoding off; + } + + # PgAdmin + # Optional Module, comment this section if you did not deploy pgadmin in docker-compose.yml + location /pgadmin/ { + set $pgadmin pgadmin; + proxy_pass $pgadmin_backend; + + proxy_set_header X-Script-Name /pgadmin; + proxy_redirect off; + } + + # Admin Frontend + # Optional Module, comment this section if you did not deploy admin_frontend in docker-compose.yml + location /console { + proxy_pass $admin_frontend_backend; + } + + # AppFlowy Web + location / { + proxy_pass $appflowy_web_backend; + } +} \ No newline at end of file diff --git a/nginx/ssl/certificate.crt b/docker/nginx/ssl/certificate.crt similarity index 100% rename from nginx/ssl/certificate.crt rename to docker/nginx/ssl/certificate.crt diff --git a/nginx/ssl/private_key.key b/docker/nginx/ssl/private_key.key similarity index 100% rename from nginx/ssl/private_key.key rename to docker/nginx/ssl/private_key.key diff --git a/nginx/nginx.conf b/nginx/nginx.conf deleted file mode 100644 index 09b45e67f..000000000 --- a/nginx/nginx.conf +++ /dev/null @@ -1,246 +0,0 @@ -# Minimal nginx configuration for AppFlowy-Cloud -# Self Hosted AppFlowy Cloud user should alter this file to suit their needs, -# or use the appflowy.site.conf in external_proxy_config/nginx if they are using -# an external proxy. - -events { - worker_connections 1024; -} - -http { - # docker dns resolver - resolver 127.0.0.11 valid=10s; - #error_log /var/log/nginx/error.log debug; - - map $http_upgrade $connection_upgrade { - default upgrade; - '' close; - } - - map $http_origin $cors_origin { - # AppFlowy Web origin - "~^http://localhost:3000$" $http_origin; - default "null"; - } - - server { - listen 8080; - - # https://github.com/nginxinc/nginx-prometheus-exporter - location = /stub_status { - stub_status; - } - } - - - server { - ssl_certificate /etc/nginx/ssl/certificate.crt; - ssl_certificate_key /etc/nginx/ssl/private_key.key; - - listen 80; - listen 443 ssl; - client_max_body_size 10M; - - underscores_in_headers on; - set $appflowy_cloud_backend "http://appflowy_cloud:8000"; - set $gotrue_backend "http://gotrue:9999"; - set $admin_frontend_backend "http://admin_frontend:3000"; - set $appflowy_web_backend "http://appflowy_web:80"; - set $minio_backend "http://minio:9001"; - set $minio_api_backend "http://minio:9000"; - # Host name for minio, used internally within docker compose - set $minio_internal_host "minio:9000"; - set $pgadmin_backend "http://pgadmin:80"; - - # GoTrue - location /gotrue/ { - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Credentials' 'true' always; - add_header 'Access-Control-Allow-Headers' '*' always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Max-Age' 3600 always; - add_header 'Content-Type' 'text/plain charset=UTF-8' always; - add_header 'Content-Length' 0 always; - return 204; - } - - proxy_pass $gotrue_backend; - - rewrite ^/gotrue(/.*)$ $1 break; - - # Allow headers like redirect_to to be handed over to the gotrue - # for correct redirecting - proxy_set_header Host $http_host; - proxy_pass_request_headers on; - } - - # WebSocket - location /ws { - proxy_pass $appflowy_cloud_backend; - - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "Upgrade"; - proxy_set_header Host $host; - proxy_read_timeout 86400s; - } - - location /api { - proxy_pass $appflowy_cloud_backend; - proxy_set_header X-Request-Id $request_id; - proxy_set_header Host $http_host; - - # Set CORS headers for other requests - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; - add_header 'Access-Control-Max-Age' 3600 always; - return 204; - } - - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; - add_header 'Access-Control-Max-Age' 3600 always; - - location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ { - proxy_pass $appflowy_cloud_backend; - proxy_request_buffering off; - client_max_body_size 256M; - if ($request_method = 'OPTIONS') { - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; - add_header 'Access-Control-Max-Age' 3600 always; - return 204; - } - - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Client-Version, Device-Id' always; - add_header 'Access-Control-Max-Age' 3600 always; - } - - # AppFlowy-Cloud - location /api/chat { - proxy_pass $appflowy_cloud_backend; - - proxy_http_version 1.1; - proxy_set_header Connection ""; - chunked_transfer_encoding on; - proxy_buffering off; - proxy_cache off; - - proxy_read_timeout 600s; - proxy_connect_timeout 600s; - proxy_send_timeout 600s; - } - - location /api/import { - proxy_pass $appflowy_cloud_backend; - - # Set headers - proxy_set_header X-Request-Id $request_id; - proxy_set_header Host $http_host; - - # Handle CORS - add_header 'Access-Control-Allow-Origin' $cors_origin always; - add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS' always; - add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, Device-Id' always; - add_header 'Access-Control-Max-Age' 3600 always; - - # Timeouts - proxy_read_timeout 600s; - proxy_connect_timeout 600s; - proxy_send_timeout 600s; - - # Disable buffering for large file uploads - proxy_request_buffering off; - proxy_buffering off; - proxy_cache off; - client_max_body_size 2G; - } - } - - # Minio Web UI - # Derive from: https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html - # Optional Module, comment this section if you did not deploy minio in docker-compose.yml - # This endpoint is meant to be used for the MinIO Web UI, accessible via the admin portal - location /minio/ { - proxy_pass $minio_backend; - - rewrite ^/minio/(.*) /$1 break; - proxy_set_header Host $http_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-NginX-Proxy true; - - ## This is necessary to pass the correct IP to be hashed - real_ip_header X-Real-IP; - - proxy_connect_timeout 300s; - - ## To support websockets in MinIO versions released after January 2023 - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - # Some environments may encounter CORS errors (Kubernetes + Nginx Ingress) - # Uncomment the following line to set the Origin request to an empty string - # proxy_set_header Origin ''; - - chunked_transfer_encoding off; - } - - # Optional Module, comment this section if you did not deploy minio in docker-compose.yml - # This is used for presigned url, which is needs to be exposed to the AppFlowy client application. - location /minio-api/ { - proxy_pass $minio_api_backend; - - # Set the host to internal host because the presigned url was signed against the internal host - proxy_set_header Host $minio_internal_host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - - rewrite ^/minio-api/(.*) /$1 break; - - proxy_connect_timeout 300s; - # Default is HTTP/1, keepalive is only enabled in HTTP/1.1 - proxy_http_version 1.1; - proxy_set_header Connection ""; - chunked_transfer_encoding off; - } - - # PgAdmin - # Optional Module, comment this section if you did not deploy pgadmin in docker-compose.yml - location /pgadmin/ { - set $pgadmin pgadmin; - proxy_pass $pgadmin_backend; - - proxy_set_header X-Script-Name /pgadmin; - proxy_set_header X-Scheme $scheme; - proxy_set_header Host $host; - proxy_redirect off; - } - - # Admin Frontend - # Optional Module, comment this section if you did not deploy admin_frontend in docker-compose.yml - location /console { - proxy_pass $admin_frontend_backend; - - proxy_set_header X-Scheme $scheme; - proxy_set_header Host $host; - } - - # AppFlowy Web - location / { - proxy_pass $appflowy_web_backend; - proxy_set_header X-Scheme $scheme; - proxy_set_header Host $host; - } - } - -} diff --git a/services/appflowy-worker/src/application.rs b/services/appflowy-worker/src/application.rs index 1b3667460..10f49997a 100644 --- a/services/appflowy-worker/src/application.rs +++ b/services/appflowy-worker/src/application.rs @@ -167,13 +167,20 @@ pub struct AppState { } async fn get_worker_mailer(config: &Config) -> Result { + let mut smtp_tls_kind = "none" + if config.mailer.smtp_port == 465 { + smtp_tls_kind = "wrapper" + } else if config.mailer.smtp_port == 587 { + smtp_tls_kind = "opportunistic" + } + let mailer = Mailer::new( config.mailer.smtp_username.clone(), config.mailer.smtp_email.clone(), config.mailer.smtp_password.clone(), &config.mailer.smtp_host, config.mailer.smtp_port, - config.mailer.smtp_tls_kind.as_str(), + smtp_tls_kind, ) .await?;