本文记录一次在 Linux 服务器上部署 Immich 的过程:使用 Docker Compose 运行 Immich,把照片与数据库数据持久化到 /storage/photo_backup,再通过 Cloudflare DNS、Nginx 反向代理和 Let’s Encrypt 证书对外提供 HTTPS 访问。
安全说明:本文已移除所有敏感信息,例如 Cloudflare API Key、数据库密码、Token、服务器后台令牌等。示例里的域名、路径和端口可按需替换。
目标架构
- 应用:Immich
- 运行方式:Docker Compose
- 对外域名:
photo.example.com
- 本机监听:
127.0.0.1:2283
- 反向代理:Nginx / Tengine
- HTTPS:Let’s Encrypt + Certbot
- 数据目录:
/storage/photo_backup
目录规划:
1 2 3 4
| /storage/photo_backup/ ├── library # Immich 上传与媒体文件 ├── postgres # PostgreSQL 数据 └── model-cache # 机器学习模型缓存
|
1. 创建数据目录
1 2 3
| mkdir -p /storage/photo_backup/library \ /storage/photo_backup/postgres \ /storage/photo_backup/model-cache
|
2. 准备 Docker Compose
创建项目目录:
1 2
| mkdir -p /opt/immich cd /opt/immich
|
创建 .env:
1 2 3 4 5 6 7
| UPLOAD_LOCATION=/storage/photo_backup/library DB_DATA_LOCATION=/storage/photo_backup/postgres IMMICH_VERSION=release DB_PASSWORD=请替换为强随机密码 DB_USERNAME=postgres DB_DATABASE_NAME=immich TZ=Etc/UTC
|
创建 docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| name: immich
services: immich-server: container_name: immich_server image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release} volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload - /etc/localtime:/etc/localtime:ro env_file: - .env ports: - "127.0.0.1:2283:2283" depends_on: - redis - database restart: always healthcheck: disable: false
immich-machine-learning: container_name: immich_machine_learning image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} volumes: - ${UPLOAD_LOCATION}:/usr/src/app/upload - ${DB_DATA_LOCATION}/../model-cache:/cache env_file: - .env restart: always healthcheck: disable: false
redis: container_name: immich_redis image: docker.io/valkey/valkey:8-bookworm healthcheck: test: redis-cli ping || exit 1 restart: always
database: container_name: immich_postgres image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 environment: POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_USER: ${DB_USERNAME} POSTGRES_DB: ${DB_DATABASE_NAME} POSTGRES_INIT_ARGS: "--data-checksums" volumes: - ${DB_DATA_LOCATION}:/var/lib/postgresql/data restart: always
|
说明:Immich 官方示例有时会固定镜像 digest。如果遇到 digest 拉取失败,可以临时改用同版本 tag,但生产环境建议定期确认官方最新推荐 compose 文件。
校验配置:
1
| docker compose config --quiet
|
3. 配置 DNS
在 Cloudflare DNS 中添加 A 记录:
1 2 3 4 5
| 类型:A 名称:photo 内容:服务器公网 IPv4 代理状态:DNS only TTL:Auto 或 120
|
如果要使用 HTTP-01 方式申请 Let’s Encrypt 证书,建议先关闭 Cloudflare 代理,确认公网能直连服务器的 80 端口。
4. Nginx HTTP 临时配置
先配置 HTTP,用于 Let’s Encrypt 的验证路径:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| server { listen 80; server_name photo.example.com;
location ^~ /.well-known/acme-challenge/ { root /www/wwwroot/photo.example.com; default_type text/plain; }
location / { proxy_pass http://127.0.0.1:2283; proxy_http_version 1.1; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 600s; proxy_send_timeout 600s; client_max_body_size 0; } }
|
加载前检查:
1 2
| nginx -t nginx -s reload
|
5. 申请 SSL 证书
安装 Certbot 后使用 webroot 模式:
1 2 3 4 5 6 7 8
| certbot certonly \ --webroot \ -w /www/wwwroot/photo.example.com \ -d photo.example.com \ --email admin@example.com \ --agree-tos \ --no-eff-email \ --non-interactive
|
证书签发后路径通常为:
1 2
| /etc/letsencrypt/live/photo.example.com/fullchain.pem /etc/letsencrypt/live/photo.example.com/privkey.pem
|
6. 启用 HTTPS 反向代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| server { listen 80; server_name photo.example.com;
location ^~ /.well-known/acme-challenge/ { root /www/wwwroot/photo.example.com; default_type text/plain; }
location / { return 301 https://$host$request_uri; } }
server { listen 443 ssl http2; server_name photo.example.com;
ssl_certificate /etc/letsencrypt/live/photo.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/photo.example.com/privkey.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off;
client_max_body_size 0;
location / { proxy_pass http://127.0.0.1:2283; proxy_http_version 1.1; 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 https; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 600s; proxy_send_timeout 600s; proxy_buffering off; } }
|
重新加载:
1 2
| nginx -t nginx -s reload
|
7. 启动 Immich
1 2 3
| cd /opt/immich docker compose pull docker compose up -d
|
查看状态:
1 2
| docker compose ps docker compose logs -f immich-server
|
当 immich_server、immich_postgres、immich_redis 变为 healthy,且日志显示 Immich Server 正常监听后,即可访问:
1
| https://photo.example.com/
|
8. 证书续期后自动重载 Nginx
Certbot 会创建自动续期任务。为了让证书更新后 Nginx 自动加载新证书,可以添加 deploy hook:
1 2 3 4 5 6
| mkdir -p /etc/letsencrypt/renewal-hooks/deploy cat > /etc/letsencrypt/renewal-hooks/deploy/nginx-reload.sh <<'SCRIPT'
nginx -t && nginx -s reload SCRIPT chmod 755 /etc/letsencrypt/renewal-hooks/deploy/nginx-reload.sh
|
常用维护命令
1 2 3 4 5 6 7 8 9 10 11
| cd /opt/immich
docker compose ps
docker compose logs -f immich-server
docker compose pull docker compose up -d
|
总结
这套部署方式的重点是:
- Immich 只绑定到本机地址,减少暴露面;
- 所有公网访问统一走 Nginx HTTPS;
- 数据目录明确放在
/storage/photo_backup,便于备份;
- DNS、证书、反代、容器状态分别验证,减少排错成本。
部署完成后,首次访问 Web UI 创建管理员账号即可开始使用。