2492 字
12 分钟
使用 Docker + traefik 部署 ente 全家桶

更新日志

创建文章

2026-03-18
  • 撰写初版文章

前言#

其实早在之前我就因为寻找 2FA 的软件找到了 Ente Auth,并且知道了服务端是支持自部署的。但是由于 Ente 是一个全家桶服务,但是我也只需要 2FA 的功能,再之当时我部署了 Immich 不需要 Ente Photos 的功能,服务器的配置也不足以支持全家桶,我就没有部署了。

现在为什么又需要了呢,因为我的 Immich 的存储位置是通过挂载S3的方式进行的,效率奇差,我也确实需要 2FA 自动备份的功能,当时我使用的是 Aegis,只能自动备份到本地,还是不太方便。得益于 Ente Photos 支持 S3 存储,Ente Auth 自动备份云端,且 Ente 全家桶优美的UI布局和我购置了一台 4C16G 的轻量服务器,已经有条件有需求部署 Ente 全家桶,遂进行。

环境#

  • 可以访问外网的 Linux 服务器
  • Docker
  • Docker Compose
  • 域名

如下是我的配置:

Terminal window
root@10-23-233-143:~# echo "🔹 系统版本: $(lsb_release -d | cut -f2-)"; echo "🔹 CPU 核心数: $(nproc) 核"; echo "🔹 内存大小: $(free -h | awk '/^Mem:/ {print $2}')"; echo "🔹 磁盘空间 (根目录): $(df -h / | awk 'NR==2 {print "总计 " $2 " | 已用 " $3 " | 可用 " $4 " | 使用率 " $5}')"
🔹 系统版本: Ubuntu 24.04.4 LTS
🔹 CPU 核心数: 4
🔹 内存大小: 15Gi
🔹 磁盘空间 (根目录): 总计 96G | 已用 14G | 可用 83G | 使用率 14%

部署#

TIP

此处默认已经安装 Docker、Docker Compose 和 traefik,如未安装,可参考如下安装教程:

创建目录 /opt/docker/ente 作为容器运行目录。

Terminal window
mkdir -p /opt/docker/ente

cd 进入该目录,创建必要的一些文件,并且使用你熟悉的编辑器进行编辑,在此处我使用 vim

Terminal window
cd /opt/docker/ente
touch docker-compose.yml .env museum.yaml

docker-compose.yml 键入以下内容:

services:
museum:
image: ghcr.io/ente-io/server:latest
container_name: ente-museum
depends_on:
postgres:
condition: service_healthy
env_file:
- .env
volumes:
- ./museum.yaml:/museum.yaml:ro
- ./data/museum:/data:ro
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.museum.rule=Host(`api.ente.peean.net`)" # 服务器端点,自行修改
- "traefik.http.routers.museum.entrypoints=websecure"
- "traefik.http.routers.museum.tls.certresolver=edgeone" # 我使用的腾讯云边缘加速 EdgeOne,根据自己 traefik 配置自行修改
- "traefik.http.routers.museum.service=museum"
- "traefik.http.services.museum.loadbalancer.server.port=8080"
postgres:
image: postgres:15
container_name: ente-postgresql
env_file:
- .env
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
networks:
- proxy
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 40s
start_interval: 1s
volumes:
- ./data/postgresql:/var/lib/postgresql/data
web:
image: ghcr.io/ente-io/web
container_name: ente-web
env_file:
- .env
environment:
- ENTE_API_ORIGIN=${ENTE_API_ORIGIN}
- ENTE_ALBUMS_ORIGIN=${ENTE_ALBUMS_ORIGIN}
- ENTE_PHOTOS_ORIGIN=${ENTE_PHOTOS_ORIGIN}
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.web.rule=Host(`photos.ente.peean.net`)" # Photos
- "traefik.http.routers.web.entrypoints=websecure"
- "traefik.http.routers.web.tls.certresolver=edgeone"
- "traefik.http.routers.web.service=web"
- "traefik.http.services.web.loadbalancer.server.port=3000"
- "traefik.http.routers.accounts.rule=Host(`accounts.ente.peean.net`)" # Accounts
- "traefik.http.routers.accounts.entrypoints=websecure"
- "traefik.http.routers.accounts.tls.certresolver=edgeone"
- "traefik.http.routers.accounts.service=accounts"
- "traefik.http.services.accounts.loadbalancer.server.port=3001"
- "traefik.http.routers.albums.rule=Host(`albums.ente.peean.net`)" # Albums
- "traefik.http.routers.albums.entrypoints=websecure"
- "traefik.http.routers.albums.tls.certresolver=edgeone"
- "traefik.http.routers.albums.service=albums"
- "traefik.http.services.albums.loadbalancer.server.port=3002"
- "traefik.http.routers.auth.rule=Host(`auth.ente.peean.net`)" # Auth
- "traefik.http.routers.auth.entrypoints=websecure"
- "traefik.http.routers.auth.tls.certresolver=edgeone"
- "traefik.http.routers.auth.service=auth"
- "traefik.http.services.auth.loadbalancer.server.port=3003"
- "traefik.http.routers.cast.rule=Host(`cast.ente.peean.net`)" # Cast
- "traefik.http.routers.cast.entrypoints=websecure"
- "traefik.http.routers.cast.tls.certresolver=edgeone"
- "traefik.http.routers.cast.service=cast"
- "traefik.http.services.cast.loadbalancer.server.port=3004"
- "traefik.http.routers.share.rule=Host(`share.ente.peean.net`)" # Locker
- "traefik.http.routers.share.entrypoints=websecure"
- "traefik.http.routers.share.tls.certresolver=edgeone"
- "traefik.http.routers.share.service=share"
- "traefik.http.services.share.loadbalancer.server.port=3005"
- "traefik.http.routers.embed.rule=Host(`embed.ente.peean.net`)" # Embed
- "traefik.http.routers.embed.entrypoints=websecure"
- "traefik.http.routers.embed.tls.certresolver=edgeone"
- "traefik.http.routers.embed.service=embed"
- "traefik.http.services.embed.loadbalancer.server.port=3006"
- "traefik.http.routers.paste.rule=Host(`paste.ente.peean.net`)" # Paste
- "traefik.http.routers.paste.entrypoints=websecure"
- "traefik.http.routers.paste.tls.certresolver=edgeone"
- "traefik.http.routers.paste.service=paste"
- "traefik.http.services.paste.loadbalancer.server.port=3008"
networks:
proxy:
external: true

traefik 相关配置请根据自己的实际情况配置。

.env 键入以下内容:

# Copy this file to .env in the same directory in which this file is present
# This file contains the environment variables needed for Ente's cluster to run properly.
# This file is split based on services declared in Docker Compose file
#
# Service: Postgres
# This is used for storing data in database pertaining to collections, files, users, subscriptions, etc.
# These credentials are needed for accessing the database via Museum.
# Please set a strong password for accessing the database.
# Enter these values in museum.yaml file under `db`.
# This need not be defined if using external DB (i. e. no Compose service for PostgreSQL is used)
POSTGRES_USER=ente
POSTGRES_PASSWORD=<STRONG_STRONG_POSTGRES_PASSWORD>
POSTGRES_DB=ente
# Service: Web
# This is used for configuring public albums, API endpoints, etc.
# Replace the below endpoints to the correct subdomains of your choice.
ENTE_API_ORIGIN=https://api.ente.peean.net
ENTE_ALBUMS_ORIGIN=https://albums.ente.peean.net
ENTE_PHOTOS_ORIGIN=https://photos.ente.peean.net

其中,各项配置根据实际情况调整,POSTGRES_PASSWORD 请一定要替换为强密码。更多配置请参照官方文档对于 Environment Variables 的描述。

museum.yaml 键入以下内容:

# Database
db:
host: postgres
port: 5432
name: ente
user: ente
password: <STRONG_STRONG_POSTGRES_PASSWORD>
# Object Storage
s3:
# Change this to false if enabling SSL
are_local_buckets: false
# Only path-style URL works if disabling are_local_buckets with MinIO
use_path_style_urls: false
# Primary hot storage bucket configuration
b2-eu-cen:
# Uncomment the below configuration to override the top-level configuration
key: <ACCESS_KEY_ID>
secret: <SECRET_ACCESS_KEY>
endpoint: <ENDPOINT_ADDRESS>
region: <REGION_AREA>
bucket: <BUCKET_NAME>
# Secondary hot storage configuration
wasabi-eu-central-2-v3:
key: <ACCESS_KEY_ID>
secret: <SECRET_ACCESS_KEY>
endpoint: <ENDPOINT_ADDRESS>
region: <REGION_AREA>
bucket: <BUCKET_NAME>
compliance: false
# Cold storage bucket configuration
scw-eu-fr-v3:
key: <ACCESS_KEY_ID>
secret: <SECRET_ACCESS_KEY>
endpoint: <ENDPOINT_ADDRESS>
region: <REGION_AREA>
bucket: <BUCKET_NAME>
# App Endpoints
apps:
# If you're running a self hosted instance and wish to serve public links,
# set this to the URL where your albums web app is running.
public-albums: https://albums.ente.peean.net
public-locker: https://share.ente.peean.net
public-paste: https://paste.ente.peean.net
cast: https://cast.ente.peean.net
# Embed app base endpoint for embedded sharing
embed-albums: https://embed.ente.peean.net
# Set this to the URL where your accounts web app is running, primarily used for
# passkey based 2FA.
accounts: https://accounts.ente.peean.net
# Encryption Keys
key:
# Key for encrypting user emails
encryption: <ENCRYPTION_kEY>
# Hash key
hash: <HASH_KEY>
# JWT
jwt:
# Secret for signing JWTs
secret: <JWT_SECRET>
# Email
smtp:
host: smtp.feishu.cn
port: 465
# Optional username and password if using local relay server
username: <SMTP_USERNAME>
password: <SMTP_PASSWORD>
# Email address used for sending emails (this mail's credentials have to be provided)
email: <SMTP_EMAIL>
# Optional name for sender
sender-name: <SMTP_SENDER_NAME>
# Optional encryption, encryption method (tls, ssl)
encryption: ssl
# WebAuthn Passkey Support
webauthn:
rpid: ente.peean.net
rporigins:
- https://albums.ente.peean.net
- https://share.ente.peean.net
- https://paste.ente.peean.net
- https://cast.ente.peean.net
- https://embed.ente.peean.net
- https://accounts.ente.peean.net
# Replication
# By default, replication of objects (photos, thumbnails, videos) is disabled and only one bucket is used.
# To enable replication, set replication.enabled to true. For this to work, 3 buckets have to be configured in total.
replication:
# Enable replication across buckets
enabled: true
# Number of goroutines for replication
worker-count: 6
# Temp directory for replication
tmp-storage: tmp/replication

其中,以下几点注意修改:

  • db.password 必须与 .env 中的 POSTGRES_PASSWORD 一致。
  • s3 的配置根据需求修改,具体可参照官方文档的 Object Storage 部分,这里我启用了冷热备份,故需要三个存储桶。
  • apps 部分使用自己的域名进行替换。
  • keyjwt 部分可以 clone 官方 git 仓库生成,如果不想可使用如下命令生成:
    Terminal window
    echo "key.encryption: $(openssl rand -base64 32)"; echo "key.hash: $(openssl rand -base64 64 | tr -d '\n')"; echo "jwt.secret: $(openssl rand -base64 32 | tr '/+' '_-' | tr -d '=')"
  • smtp 部分使用你将使用的邮件提供商的配置,我这选择的是飞书的免费域名邮箱。由于配置了 SMTP,首次进入系统注册时将会通过 SMTP 向注册邮箱发送验证码,所以这块配置必须正确,否则将会因为无法发送验证码而报错,这边 encryption 必须配置,虽然写着可选,但是由于我未配置出现问题了,找半天问题才找到。如果不配置SMTP,验证码将会通过容器日志的方式进行打印,具体还请参考官方文档 Step 1: Creating first user
  • webauthn 关系到是否可以使用 Passkey,rpid 使用主域名,比如:
    webauthn:
    rpid: example.com
    rporigins:
    - https://auth.example.com
    - https://photos.example.com
  • replication 决定了是否启用存储桶复制,如果不需要,就不用配置三个存储桶了。

接下来就可以愉快的启动容器了!

Terminal window
docker compose pull && docker compose up -d

启动成功后即可通过 photos.ente.peean.net 访问 Ente Photos 了,注册第一个账户。

服务端配置#

此时,你应该发现并且发问:为什么存储只有 10G?

是的,默认空间就是 10G,由于 Ente Photos 没有可视化控制界面,所以扩容需要通过官方的 CLI 工具进行修改。

这边选择直接下载 CLI 工具的二进制包的方式。

ente-cli#

其实这一块官方文档亦有详细描述,可参照 Ente CLI for self-hosted instance

release 请查看:ente-cli

Terminal window
mkdir -p /opt/ente-cli/export && cd /opt/ente-cli
wget https://github.com/ente-io/ente/releases/download/cli-v0.2.3/ente-cli-v0.2.3-linux-amd64.tar.gz
tar -zxvf ente-cli-v0.2.3-linux-amd64.tar.gz && rm ente-cli-v0.2.3-linux-amd64.tar.gz

先导入环境变量,否则会报错。(无需先行创建 secrets.txt)

Terminal window
export ENTE_CLI_SECRETS_PATH=./secrets.txt

接下来在该目录下创建配置文件 config.yml,并且键入以下内容(域名替换为自己的):

# Set the API endpoint to your domain where Museum is being served.
endpoint:
api: https://api.ente.peean.net

然后添加账户 ./ente account add,根据交互性提示操作即可:

Terminal window
root@10-23-233-143:/opt/ente-cli# ./ente account add
Enter app type (default: photos): photos
Enter export directory: export
Enter email address: <EMAIL_ADDR>
Enter password:
Please wait authenticating...
Enter TOTP: 981304
Account added successfully
run `ente export` to initiate export of your account data
TIP

此处键入密码是不显示的,不是没有输进去,接着操作即可。

输入账号密码,如果启用了双因素认证,还需要输入 TOTP,然后一切照常就能 successfully 了。

查看账户 ./ente account list

Terminal window
root@10-23-233-143:/opt/ente-cli# ./ente account list
Configured accounts: 1
====================================
Email: <EMAIL_ADDR>
ID: 1580559962386438
App: photos
ExportDir: export
====================================

如果仅自用,可以禁用注册。

Terminal window
cd /opt/docker/ente
vim museum.yaml

编辑 museum.yaml 文件,新增以下内容:

# Internal
internal:
# List of admin user IDs
admins:
- 1580559962386438
# Disable user registration
disable-registration: true
  • internal.admins 配置管理员列表,这里只添加了刚刚注册的用户,用户 ID 在上述步骤 ./ente account list 可以查看到。
  • internal.disable-registration 代表禁用注册。

然后重启服务:

Terminal window
docker compose down
docker compose up -d

回到 cli 目录,进行扩容操作:

Terminal window
./ente admin update-subscription -u <EMAIL_ADDR>

回到网页端再次查看,可以看到空间变成 100T 了,便完成了扩容操作。

客户端配置#

此处以 Ente Photos 为例,Ente Auth 和 Ente Locker 配置差不多,自行探究。

软件下载地址:Installing Ente Photos | Ente Help,根据使用平台自行选择下载渠道。

打开软件进入初始化界面,默认链接的是官方服务器端点,直接注册登录将链接到 https://api.ente.io,但是我们这需要链接到我们自部署的服务器端点。

软件初始化界面

快速点击 7 次界面上的 ducky(就是界面上的鸭鸭啦!),将会弹出开发者设置弹窗,点击

开发者设置

现在,可以修改服务器端点,比如我这是 https://api.ente.peean.net

修改服务器端点

修改完后再进行登录,登录后会要求文件管理权限,因为要备份照片嘛。授予权限后将会快速扫描设备,要求你选择需要备份的文件夹,此处先选择 稍后再说

备份选择

先进入设置,配置好备份设置。路径 备份 → 备份设置,开启 仅备份新照片,然后再选择需要备份的文件夹开始备份吧!如果不开启 仅备份新照片,退出登录重新登录,又会全部扫描一遍再显示上传,虽然并不会重复上传,但还是避免这种情况为好。

备份设置

参考#

  1. Docker Compose - Self-hosting | Ente Help
  2. Ente全家桶部署:Ente Photos、Ente Auth | 荒岛
  3. Story behind Ente’s mascot | Ente Blog
使用 Docker + traefik 部署 ente 全家桶
https://blog.peean.net/posts/1a8a95d01c97c2cd/
作者
Peean
发布于
2026-03-18
许可协议
CC BY-NC-SA 4.0