在群晖上安装appflowy,一个带ai的自托管的云笔记应用,支持多端同步,分享链接

166 阅读6分钟

情况说明

  • 群晖923+
  • docker部署
  • 安装为最新的0.10.3版本,github地址:github.com/AppFlowy-IO…
  • 事先安装了postgresql、minio、redis,所以下面docker-compose并没有这两个镜像,而是使用外部库。
  • 理论上需要安装postgres、minio、redis、gotrue、ai(我没用起来,可以不部署)、appflowy-worker、appflowy-web(web端用的,如果只用移动端可以不部署)、appflowy-cloud、appflowy-admin_frontend( 我没用起来,可能是配置问题,可以不部署)、nginx(不嫌麻烦的话可以用群晖自带的反向代理,我这里用了)
  • 因为我的console没用起来,所以是直接在配置中先打开了注册,注册完账号后就可以关闭了。
  • 当前应用没有账号密码注册,只有邮箱验证码,所以必须要有一个可以提供邮件发送的smtp配置。
  • 群晖某目录下(无所谓哪个目录)结构为:

首先贴配置

docker-compose

这个没什么,原样贴进去就行,但是当前的端口9999需要根据你自己环境替换,只需改nginx的ports里面的别改多了,后续我继续以9999端口示例。关键的是后面的.env,设计到较多的敏感信息,我会进行过滤,注意进行替换

# Essential services for AppFlowy Cloud

services:
  nginx:
    restart: on-failure
    image: nginx:1.27
    ports:
      - 9999:80   # Disable this if you are using TLS
      #- ${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
    networks:
      - shared_network
      #- ./nginx_logs:/var/log/nginx

  gotrue:
    restart: on-failure
    image: appflowyinc/gotrue:${GOTRUE_VERSION:-latest}
    healthcheck:
      test: "curl --fail http://127.0.0.1:9999/health || exit 1"
      interval: 5s
      timeout: 5s
      retries: 12
    environment:
      # There are a lot of options to configure GoTrue. You can reference the example config:
      # https://github.com/supabase/auth/blob/master/example.env
      - GOTRUE_ADMIN_EMAIL=${GOTRUE_ADMIN_EMAIL}
      - GOTRUE_ADMIN_PASSWORD=${GOTRUE_ADMIN_PASSWORD}
      - GOTRUE_DISABLE_SIGNUP=${GOTRUE_DISABLE_SIGNUP:-false}
      - GOTRUE_SITE_URL=appflowy-flutter://                           # redirected to AppFlowy application
      - GOTRUE_URI_ALLOW_LIST=**                                      # adjust restrict if necessary
      - GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}                        # authentication secret
      - GOTRUE_JWT_EXP=${GOTRUE_JWT_EXP}
      # Without this environment variable, the createuser command will create an admin
      # with the `admin` role as opposed to `supabase_admin`
      - GOTRUE_JWT_ADMIN_GROUP_NAME=supabase_admin
      - GOTRUE_DB_DRIVER=postgres
      - 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_MAILER_URLPATHS_CONFIRMATION=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_INVITE=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_RECOVERY=/gotrue/verify
      - GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE=/gotrue/verify
      - GOTRUE_SMTP_ADMIN_EMAIL=${GOTRUE_SMTP_ADMIN_EMAIL}                # email with admin privileges e.g. internal@appflowy.io
      - GOTRUE_SMTP_MAX_FREQUENCY=${GOTRUE_SMTP_MAX_FREQUENCY:-1ns}       # set to 1ns for running tests
      - GOTRUE_RATE_LIMIT_EMAIL_SENT=${GOTRUE_RATE_LIMIT_EMAIL_SENT:-100} # number of email sendable per minute
      - GOTRUE_MAILER_AUTOCONFIRM=${GOTRUE_MAILER_AUTOCONFIRM:-false}     # change this to true to skip email confirmation
      # Google OAuth config
      - GOTRUE_EXTERNAL_GOOGLE_ENABLED=${GOTRUE_EXTERNAL_GOOGLE_ENABLED}
      - GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=${GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID}
      - GOTRUE_EXTERNAL_GOOGLE_SECRET=${GOTRUE_EXTERNAL_GOOGLE_SECRET}
      - GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI=${GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI}
      # GITHUB OAuth config
      - GOTRUE_EXTERNAL_GITHUB_ENABLED=${GOTRUE_EXTERNAL_GITHUB_ENABLED}
      - GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=${GOTRUE_EXTERNAL_GITHUB_CLIENT_ID}
      - GOTRUE_EXTERNAL_GITHUB_SECRET=${GOTRUE_EXTERNAL_GITHUB_SECRET}
      - GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI=${GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI}
      # Discord OAuth config
      - GOTRUE_EXTERNAL_DISCORD_ENABLED=${GOTRUE_EXTERNAL_DISCORD_ENABLED}
      - GOTRUE_EXTERNAL_DISCORD_CLIENT_ID=${GOTRUE_EXTERNAL_DISCORD_CLIENT_ID}
      - GOTRUE_EXTERNAL_DISCORD_SECRET=${GOTRUE_EXTERNAL_DISCORD_SECRET}
      - GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI=${GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI}
    networks:
      - shared_network

  appflowy_cloud:
    restart: on-failure
    ports:
      - 18000:8000
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - APPFLOWY_ENVIRONMENT=production
      - APPFLOWY_DATABASE_URL=${APPFLOWY_DATABASE_URL}
      - APPFLOWY_REDIS_URI=${APPFLOWY_REDIS_URI}
      - APPFLOWY_GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}
      - APPFLOWY_GOTRUE_BASE_URL=${APPFLOWY_GOTRUE_BASE_URL}
      - APPFLOWY_S3_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - APPFLOWY_S3_MINIO_URL=${APPFLOWY_S3_MINIO_URL}
      - APPFLOWY_S3_ACCESS_KEY=${APPFLOWY_S3_ACCESS_KEY}
      - APPFLOWY_S3_SECRET_KEY=${APPFLOWY_S3_SECRET_KEY}
      - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET}
      - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION}
      - APPFLOWY_ACCESS_CONTROL=${APPFLOWY_ACCESS_CONTROL}
      # For the CI testing, we set the database connection to 20. The default value is 40.
      - APPFLOWY_DATABASE_MAX_CONNECTIONS=20
      - AI_SERVER_HOST=${AI_SERVER_HOST}
      - AI_SERVER_PORT=${AI_SERVER_PORT}
      - APPFLOWY_WEB_URL=${APPFLOWY_WEB_URL}
      - 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}
      - AI_OPENAI_API_KEY=${AI_OPENAI_API_KEY}
    build:
      context: .
      dockerfile: Dockerfile
      args:
        FEATURES: ""
        PROFILE: ci
    networks:
      - shared_network
    image: appflowyinc/appflowy_cloud:${APPFLOWY_CLOUD_VERSION:-latest}
    depends_on:
      gotrue:
        condition: service_healthy

  admin_frontend:
    restart: on-failure
    build:
      context: .
      dockerfile: ./admin_frontend/Dockerfile
    image: appflowyinc/admin_frontend:${APPFLOWY_ADMIN_FRONTEND_VERSION:-latest}
    ports:
      - 13000:3000
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - ADMIN_FRONTEND_REDIS_URL=${ADMIN_FRONTEND_REDIS_URL:-redis://redis:6379}
      - ADMIN_FRONTEND_GOTRUE_URL=${ADMIN_FRONTEND_GOTRUE_URL:-http://gotrue:9999}
      - ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=${ADMIN_FRONTEND_APPFLOWY_CLOUD_URL:-http://appflowy_cloud:8000}
      - ADMIN_FRONTEND_PATH_PREFIX=${ADMIN_FRONTEND_PATH_PREFIX:-}
    networks:
      - shared_network
    depends_on:
      gotrue:
        condition: service_healthy
      appflowy_cloud:
        condition: service_started

  ai:
    restart: on-failure
    image: appflowyinc/appflowy_ai:${APPFLOWY_AI_VERSION:-latest}
    environment:
      - AI_SERVER_PORT=${AI_SERVER_PORT}
      - OPENAI_API_KEY=${AI_OPENAI_API_KEY}
      - DEFAULT_AI_MODEL=openai/gpt-oss-20b:free # Make sure the model is available in your OpenAI account
      - DEFAULT_AI_COMPLETION_MODEL=openai/gpt-oss-20b:free # Make sure the model is available in your OpenAI account
      - AZURE_OPENAI_API_KEY=${AI_AZURE_OPENAI_API_KEY}
      - AZURE_OPENAI_ENDPOINT=${AI_AZURE_OPENAI_API_BASE}
      - AZURE_OPENAI_API_VERSION=${AI_AZURE_OPENAI_API_VERSION}
      - APPFLOWY_S3_ACCESS_KEY=${APPFLOWY_S3_ACCESS_KEY}
      - APPFLOWY_S3_SECRET_KEY=${APPFLOWY_S3_SECRET_KEY}
      - APPFLOWY_S3_BUCKET=${APPFLOWY_S3_BUCKET}
      - APPFLOWY_S3_REGION=${APPFLOWY_S3_REGION}
      - AI_DATABASE_URL=${APPFLOWY_DATABASE_URL}
      - AI_REDIS_URL=${APPFLOWY_REDIS_URI}
      - AI_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - AI_MINIO_URL=${APPFLOWY_S3_MINIO_URL}
      - AI_APPFLOWY_HOST=${APPFLOWY_BASE_URL}
      - APPFLOWY_GOTRUE_JWT_SECRET=${GOTRUE_JWT_SECRET}

  appflowy_worker:
    restart: on-failure
    image: appflowyinc/appflowy_worker:${APPFLOWY_WORKER_VERSION:-latest}
    build:
      context: .
      dockerfile: ./services/appflowy-worker/Dockerfile
    ports:
      - "14001:4001"
    environment:
      - RUST_LOG=${RUST_LOG:-info}
      - APPFLOWY_WORKER_REDIS_URL=${APPFLOWY_WORKER_REDIS_URL:-redis://redis:6379}
      - APPFLOWY_WORKER_ENVIRONMENT=production
      - APPFLOWY_WORKER_DATABASE_URL=${APPFLOWY_WORKER_DATABASE_URL}
      - APPFLOWY_WORKER_DATABASE_NAME=${APPFLOWY_WORKER_DATABASE_NAME}
      - APPFLOWY_S3_USE_MINIO=${APPFLOWY_S3_USE_MINIO}
      - APPFLOWY_S3_MINIO_URL=${APPFLOWY_S3_MINIO_URL}
      - APPFLOWY_S3_ACCESS_KEY=${APPFLOWY_S3_ACCESS_KEY}
      - 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}
    networks:
      - shared_network
      
  appflowy_web:
    image: appflowyinc/appflowy_web:latest
    environment:
      - APPFLOWY_BASE_URL=${APPFLOWY_BASE_URL}
      - APPFLOWY_GOTRUE_BASE_URL=${APPFLOWY_BASE_URL}/gotrue
      - APPFLOWY_WS_BASE_URL=${APPFLOWY_WEBSOCKET_BASE_URL}
    networks:
      - shared_network

volumes:
  postgres_data:
  minio_data:

networks:
  shared_network:
    name: appflowy_network
    driver: bridge

nginx.conf

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 {
         default $http_origin;
      }

    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 $appflowy_web_backend "http://appflowy_web:80";

        # GoTrue
        location /gotrue/ {
            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 {
            # Existing proxy configuration
            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_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_read_timeout 86400s;
        }

        location /api {
            proxy_pass $appflowy_cloud_backend;
            proxy_set_header X-Request-Id $request_id;
            proxy_set_header Host $http_host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header X-Forwarded-Proto $scheme;


            location ~* ^/api/workspace/([a-zA-Z0-9_-]+)/publish$ {
                proxy_pass $appflowy_cloud_backend;
                proxy_request_buffering off;
                client_max_body_size 256M;
            }

            # 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;

                # 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;
            }
        }

        # AppFlowy Web
        location / {
            proxy_pass $appflowy_web_backend;
            proxy_set_header X-Scheme $scheme;
            proxy_set_header Host $host;
        }
    }

}

env

涉及较多的敏感信息需要自行替换。下图的emoji数字即为需要替换的内容,端口如果不是9999环境变量中记得替换。

  • 1️⃣你的域名,ddns到家庭内网的域名
  • 2️⃣postges的内网ip,上面说了库为单独部署,所以需要ip,否则docker可以使用镜像名称识别,redis、minio也是一样,下面不再赘述
  • 3️⃣postgres的用户名
  • 4️⃣postgres的密码
  • 5️⃣postgres的短裤
  • 6️⃣redis的内网ip
  • 7️⃣redis的端口
  • 8️⃣redis的密码
  • 9️⃣minio的内网ip
  • 1️⃣0️⃣minio的上传端口和控制台的端口不一样,一般为9000
  • 1️⃣1️⃣用于控制台的超管邮箱,实际我没用起来
  • 1️⃣2️⃣用于控制台的超管密码,实际我也没用起来
  • 1️⃣3️⃣可以在控制台执行openssl rand -base64 32生成
  • 1️⃣4️⃣你的可用于发送邮件的smtp账号,如果不是谷歌的,需要替换smtp.gmail.com这个内容
  • 1️⃣5️⃣你的可用于发送邮件的smtp账号密码
  • 1️⃣6️⃣你的这个发送邮件的smtp账号的邮箱
  • 1️⃣7️⃣调用大模型的密钥
  • 1️⃣8️⃣调用的大模型
FQDN=1️⃣:9999

SCHEME=https
WS_SCHEME=wss

APPFLOWY_BASE_URL=${SCHEME}://${FQDN}
APPFLOWY_WEBSOCKET_BASE_URL=${WS_SCHEME}://${FQDN}/ws/v2

POSTGRES_HOST=2️⃣
POSTGRES_USER=3️⃣
POSTGRES_PASSWORD=4️⃣
POSTGRES_PORT=5️⃣
POSTGRES_DB=appflowy

# Redis Settings
REDIS_HOST=6️⃣
REDIS_PORT=7️⃣
REDIS_PASSWORD=8️⃣

MINIO_HOST=9️⃣
MINIO_PORT=1️⃣0️⃣
APPFLOWY_GOTRUE_BASE_URL=http://gotrue:9999

APPFLOWY_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}

APPFLOWY_ACCESS_CONTROL=true

APPFLOWY_WEBSOCKET_MAILBOX_SIZE=6000

APPFLOWY_DATABASE_MAX_CONNECTIONS=40

APPFLOWY_REDIS_URI=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}

GOTRUE_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=auth

GOTRUE_ADMIN_EMAIL=1️⃣1️⃣
GOTRUE_ADMIN_PASSWORD=1️⃣2️⃣

GOTRUE_JWT_SECRET=1️⃣3️⃣

# Expiration time in seconds for the JWT token
GOTRUE_JWT_EXP=604800

# External URL where the GoTrue service is exposed
API_EXTERNAL_URL=${APPFLOWY_BASE_URL}/gotrue

GOTRUE_MAILER_AUTOCONFIRM=false

# Set this to true if users can only join by invite
GOTRUE_DISABLE_SIGNUP=true

# Number of emails that can be sent per minute
GOTRUE_RATE_LIMIT_EMAIL_SENT=100

GOTRUE_MAILER_TEMPLATES_MAGIC_LINK=

ADMIN_FRONTEND_REDIS_URL=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}

# URL that connects to gotrue docker container
ADMIN_FRONTEND_GOTRUE_URL=http://gotrue:9999

# URL that connects to the cloud docker container
ADMIN_FRONTEND_APPFLOWY_CLOUD_URL=http://appflowy_cloud:8000

GOTRUE_SMTP_HOST=smtp.gmail.com
GOTRUE_SMTP_PORT=465
GOTRUE_SMTP_USER=1️⃣4️⃣
GOTRUE_SMTP_PASS=1️⃣5️⃣
GOTRUE_SMTP_ADMIN_EMAIL=1️⃣6️⃣

# 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=1️⃣4️⃣
APPFLOWY_MAILER_SMTP_EMAIL=1️⃣6️⃣
APPFLOWY_MAILER_SMTP_PASSWORD=1️⃣5️⃣
APPFLOWY_MAILER_SMTP_TLS_KIND=wrapper # "none" "wrapper" "required" "opportunistic"
GOTRUE_EXTERNAL_GOOGLE_ENABLED=false
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID=
GOTRUE_EXTERNAL_GOOGLE_SECRET=
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI=${API_EXTERNAL_URL}/callback

# GitHub OAuth2
GOTRUE_EXTERNAL_GITHUB_ENABLED=false
GOTRUE_EXTERNAL_GITHUB_CLIENT_ID=
GOTRUE_EXTERNAL_GITHUB_SECRET=
GOTRUE_EXTERNAL_GITHUB_REDIRECT_URI=${API_EXTERNAL_URL}/callback

# Discord OAuth2
GOTRUE_EXTERNAL_DISCORD_ENABLED=false
GOTRUE_EXTERNAL_DISCORD_CLIENT_ID=
GOTRUE_EXTERNAL_DISCORD_SECRET=
GOTRUE_EXTERNAL_DISCORD_REDIRECT_URI=${API_EXTERNAL_URL}/callback

# Apple OAuth2
GOTRUE_EXTERNAL_APPLE_ENABLED=false
GOTRUE_EXTERNAL_APPLE_CLIENT_ID=
GOTRUE_EXTERNAL_APPLE_SECRET=
GOTRUE_EXTERNAL_APPLE_REDIRECT_URI=${API_EXTERNAL_URL}/callback

# SAML 2.0. Refer to https://github.com/AppFlowy-IO/AppFlowy-Cloud/blob/main/doc/OKTA_SAML.md for example using Okta.
GOTRUE_SAML_ENABLED=false
GOTRUE_SAML_PRIVATE_KEY=

APPFLOWY_S3_USE_MINIO=true

APPFLOWY_S3_CREATE_BUCKET=true

APPFLOWY_S3_MINIO_URL=http://${MINIO_HOST}:${MINIO_PORT}

APPFLOWY_S3_ACCESS_KEY=${AWS_ACCESS_KEY}
APPFLOWY_S3_SECRET_KEY=${AWS_SECRET}

APPFLOWY_S3_BUCKET=appflowy

APPFLOWY_S3_REGION=us-east-1

AI_OPENAI_API_KEY=1️⃣7️⃣

# If no summary model is provided, there will be no search summary when using AI search.
AI_OPENAI_API_SUMMARY_MODEL=1️⃣9️⃣

AI_AZURE_OPENAI_API_KEY=1️⃣7️⃣
AI_AZURE_OPENAI_API_BASE=1️⃣8️⃣
AI_AZURE_OPENAI_API_VERSION=1️⃣9️⃣

# AI Service Configuration (Docker container defaults)
AI_SERVER_PORT=5001
AI_SERVER_HOST=ai
AI_DATABASE_URL=postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
AI_REDIS_URL=redis://${REDIS_HOST}:${REDIS_PORT}
AI_APPFLOWY_BUCKET_NAME=${APPFLOWY_S3_BUCKET}
AI_APPFLOWY_HOST=${APPFLOWY_BASE_URL}
AI_MINIO_URL=http://${MINIO_HOST}:${MINIO_PORT}

# Embedding Configuration
APPFLOWY_EMBEDDING_CHUNK_SIZE=2000
APPFLOWY_EMBEDDING_CHUNK_OVERLAP=200

# =============================================================================
# ⚙️ WORKER SERVICES: Background processing (good defaults for production)
# =============================================================================

# 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_REDIS_URL=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}
APPFLOWY_INDEXER_EMBEDDING_BUFFER_SIZE=5000

APPFLOWY_COLLABORATE_MULTI_THREAD=false

APPFLOWY_COLLABORATE_REMOVE_BATCH_SIZE=100

# AppFlowy Worker Service
APPFLOWY_WORKER_REDIS_URL=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}
APPFLOWY_WORKER_DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
APPFLOWY_WORKER_DATABASE_NAME=${POSTGRES_DB}

# =============================================================================
# 🌐 WEB FRONTEND: AppFlowy Web interface
# =============================================================================

# AppFlowy Web
# If your AppFlowy Web is hosted on a different domain, update this variable to the correct domain
APPFLOWY_WEB_URL=${APPFLOWY_BASE_URL}

# If you are running AppFlowy Web locally for development purpose, use the following value instead
APPFLOWY_WEB_URL=https://1️⃣:9999

NGINX_PORT=9999
NGINX_TLS_PORT=18443

RUST_LOG=info

CLOUDFLARE_TUNNEL_TOKEN=

AI_TEST_ENABLED=true
ADMIN_FRONTEND_PATH_PREFIX=/console

导入docker-compose并构建启动

群晖的反向代理

以防万一配置一些自定义标题,这些是我在尝试过程中解决问题添加的,没去试最后成功后这些是否还有作用。

最后是路由器的端口映射

成果

这篇文章就是使用的自部署的appflowy写的,移动端如果是苹果的话需要用外网账号下载,修改配置需要重启软件,还会卡很久。PS:我是第一次见一个手机app可以卡这么久的(绝对比你想象的要久),说明**进步空间**巨大。