# gallery.fukun.net 基于 [Photoview](https://github.com/photoview/photoview) 定制的个人相册,部署在腾讯云 `62.234.90.54`。 --- ## 访问 | 地址 | 说明 | |------|------| | `https://gallery.fukun.net` | 管理后台(需登录) | | `https://cdn.fukun.net/gallery/photos/...` | CDN 公开原图 | --- ## 定制项(与上游 Photoview 的差异) - **品牌** — 左上角 FK 书法 logo,页面标题 `Gallery.FuKun.Net` - **外观** — 纯黑背景 (`#000`),菜单图标改为极简线条,顶栏 64px 高与主站一致 - **字体** — iA Writer Quattro S + Noto Sans SC(与主站 fukun.net 一致) - **交互** — 点击图片打开侧边栏详情(去掉全屏预览),手机端点遮罩层关闭 - **无 Docker** — Go 二进制 + systemd,SQLite 单文件数据库 - **人脸识别** — 已关闭(`PHOTOVIEW_DISABLE_FACE_RECOGNITION=1`) - **CDN** — 仅公开原图走 `cdn.fukun.net`;管理界面图片直连(需鉴权 cookie,无法跨域走 CDN) --- ## 服务器 | 项目 | 详情 | |------|------| | 服务器 | 腾讯云轻量 · 北京七区 | | 公网 IP | `62.234.90.54` | | 系统 | Ubuntu 24.04 LTS · 4核4G · SSD 40G + 20G | | Go | 1.22.2(系统自带)→ 编译时自动下载 toolchain 1.26.0 | | Node | v22.22.2 | | Nginx | `/etc/nginx/` · 80/443 | | SSL | 腾讯云证书 · `/etc/nginx/ssl/` | ### 架构 ``` Internet │ ┌────────────────┼────────────────┐ │ │ │ fukun.net gallery.fukun.net pwd.fukun.net (Hugo 博客) (Photoview) (Vaultwarden) 直接访问 直接访问 直接访问 │ │ ┌────┴────┐ ┌────┴────┐ │ │ │ │ HTML 静态资源 页面/API /photos/* 不缓存 加了缓存头 proxy serve 文件 │ │ │ │ │ │ ┌──────┴──────────┴─────────┴──────┐ │ cdn.fukun.net │ ← 腾讯云 CDN │ /blog/* → fukun.net │ 只代理静态资源 │ /gallery/* → gallery...net │ 主站不经过 CDN └─────────────────────────────────┘ ``` `gallery.fukun.net` 由 Nginx 统一接入,按路径分流: | 路径 | 行为 | |------|------| | `/photos/*` | 直接 serve 原图(CDN 回源口,加 CORS + 缓存头) | | `/assets/*` | 缓存 30 天(JS/CSS/字体,文件名带 hash) | | `/*` | 反向代理到 `127.0.0.1:8000`(Photoview) | --- ## 目录结构 ### 服务器(`/home/gallery/`) ``` /home/gallery/ ├── photoview-src/ # 源码 + 编译产物(git 管理) │ ├── api/ │ │ ├── .env # 运行时环境变量 │ │ └── photoview # Go 二进制(38MB) │ └── ui/ │ └── dist/ # 前端构建产物 ├── photos/ # 相片库根目录 ├── data/ │ ├── photoview.db # SQLite 数据库 │ └── media-cache/ # 缩略图缓存 └── go/ # Go 模块缓存(449MB,运行时不需要) ``` ### 各目录职责 | 目录 | 谁创建 | 生命周期 | 备份? | |------|--------|----------|--------| | `photoview-src/` | 手动上传 | 持久,更新时重传/`git pull` | 不需要(git 管理) | | `photos/` | 手动上传 | 持久 | ✅ **核心数据,必须备份** | | `data/photoview.db` | Photoview 首次启动 | 持久 | ✅ 备份(单文件直接 cp) | | `data/media-cache/` | Photoview 扫描时 | 可重建 | 可选(丢了能重新生成) | | `go/` | `go mod download` | 可重建 | 不需要 | --- ## 本地开发 > 后端依赖 Linux C 库(dlib/libheif/ImageMagick),无法在 Windows 本地运行。 > 只能改前端代码,API 指向生产环境。 ```bash git clone ssh://git@fukun.net/data/git-repos/gallery.git cd ui cat > .env << EOF REACT_APP_API_ENDPOINT=https://gallery.fukun.net/api/ REACT_APP_BUILD_VERSION=dev REACT_APP_BUILD_DATE=$(date -u +%Y-%m-%d) REACT_APP_BUILD_COMMIT_SHA=local EOF npm ci npm run dev # localhost:1234,API 连生产服务器 ``` 改完前端后,构建 + 部署到服务器(见下文「部署」)。 --- ## 运行时配置 ### systemd — `/etc/systemd/system/photoview.service` | 环境变量 | 值 | |----------|-----| | `PHOTOVIEW_DATABASE_DRIVER` | `sqlite` | | `PHOTOVIEW_SQLITE_PATH` | `/home/gallery/data/photoview.db` | | `PHOTOVIEW_LISTEN_IP` | `127.0.0.1` | | `PHOTOVIEW_LISTEN_PORT` | `8000` | | `PHOTOVIEW_SERVE_UI` | `1` | | `PHOTOVIEW_UI_PATH` | `/home/gallery/photoview-src/ui/dist` | | `PHOTOVIEW_MEDIA_CACHE` | `/home/gallery/data/media-cache` | | `PHOTOVIEW_DISABLE_FACE_RECOGNITION` | `1` | | `LD_LIBRARY_PATH` | `/usr/local/im7/lib` | ### Nginx — `/etc/nginx/sites-enabled/gallery.fukun.net` ```nginx server { listen 80; server_name gallery.fukun.net cdn.fukun.net; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name gallery.fukun.net cdn.fukun.net; ssl_certificate /etc/nginx/ssl/gallery.fukun.net_bundle.crt; ssl_certificate_key /etc/nginx/ssl/gallery.fukun.net.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; client_max_body_size 4G; # 相片直出(CDN 回源) location /photos/ { alias /home/gallery/photos/; add_header Access-Control-Allow-Origin "*" always; } # 静态资源 location /assets/ { proxy_pass http://127.0.0.1:8000; proxy_http_version 1.1; proxy_set_header Host $host; expires 30d; add_header Cache-Control "public, immutable"; } # Photoview location / { add_header Access-Control-Allow-Origin "https://gallery.fukun.net" always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Credentials "true" always; proxy_pass http://127.0.0.1:8000; 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; proxy_send_timeout 86400s; } } ``` ### SSL 证书 腾讯云证书,`/etc/nginx/ssl/gallery.fukun.net_bundle.crt` + `gallery.fukun.net.key`。 --- ## 部署(从零或重装) ### 1. 系统依赖 ```bash sudo apt update sudo apt install -y \ g++ libheif-dev libdlib-dev libjpeg-dev \ libblas-dev liblapack-dev libmagic-dev \ ffmpeg git wget curl # exiftool(EXIF 解析,启动必须) sudo apt install -y exiftool ``` ### 2. ImageMagick 7(关键) > Ubuntu 24.04 只有 IM6,Photoview 的 Go 绑定 `imagick.v3` 依赖 IM7,必须源码编译。 ```bash tar xzf ImageMagick-7.1.1-47.tar.gz cd ImageMagick-7.1.1-47 ./configure --prefix=/usr/local/im7 --with-quantum-depth=16 --disable-docs --disable-static make -j4 sudo make install ``` ### 3. libcblas 兼容 > Ubuntu 24.04 把 CBLAS 合并进了 BLAS,但 dlib 的 linker 显式查找 `-lcblas`。 ```bash sudo ln -sf /usr/lib/x86_64-linux-gnu/libblas.so /usr/lib/x86_64-linux-gnu/libcblas.so ``` ### 4. 上传源码 & 构建 ```bash # 本地打包上传 tar --exclude='.git' -czf pv-src.tar.gz . scp pv-src.tar.gz ubuntu@62.234.90.54:/tmp/ # 服务器解压 sudo mkdir -p /home/gallery/photoview-src sudo tar -xzf /tmp/pv-src.tar.gz -C /home/gallery/photoview-src sudo chown -R gallery:gallery /home/gallery/photoview-src ``` **构建前端:** ```bash sudo -u gallery bash -c " cd /home/gallery/photoview-src/ui # REACT_APP_API_ENDPOINT 必须用完整 URL,否则 new URL() 报 Invalid URL cat > .env << ENDENV REACT_APP_API_ENDPOINT=https://gallery.fukun.net/api/ REACT_APP_BUILD_VERSION=2.0.0-manual REACT_APP_BUILD_DATE=$(date -u +%Y-%m-%d) REACT_APP_BUILD_COMMIT_SHA=fukun-gallery ENDENV npm ci npm run build " ``` **构建后端:** ```bash sudo -u gallery bash -c " export PKG_CONFIG_PATH=/usr/local/im7/lib/pkgconfig export CGO_ENABLED=1 cd /home/gallery/photoview-src/api go mod download # 修复 go-face(删 -lcblas 避免重复链接) FACE=\$(find \$(go env GOMODCACHE) -path '*go-face*' -name face.go) sudo chmod u+w \"\$FACE\" sed -i 's/-lcblas//g' \"\$FACE\" go build -v -o photoview . " ``` ### 5. systemd 服务 ```bash sudo mkdir -p /home/gallery/{photos,data/media-cache} sudo chown -R gallery:gallery /home/gallery/data sudo tee /etc/systemd/system/photoview.service << 'EOF' [Unit] Description=Photoview Gallery Server After=network.target [Service] Type=simple User=gallery Group=gallery WorkingDirectory=/home/gallery/photoview-src/api ExecStart=/home/gallery/photoview-src/api/photoview Restart=on-failure RestartSec=5 NoNewPrivileges=yes PrivateTmp=yes Environment=PHOTOVIEW_DATABASE_DRIVER=sqlite Environment=PHOTOVIEW_SQLITE_PATH=/home/gallery/data/photoview.db Environment=PHOTOVIEW_LISTEN_IP=127.0.0.1 Environment=PHOTOVIEW_LISTEN_PORT=8000 Environment=PHOTOVIEW_SERVE_UI=1 Environment=PHOTOVIEW_UI_PATH=/home/gallery/photoview-src/ui/dist Environment=PHOTOVIEW_MEDIA_CACHE=/home/gallery/data/media-cache Environment=PHOTOVIEW_DISABLE_FACE_RECOGNITION=1 Environment=LD_LIBRARY_PATH=/usr/local/im7/lib [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now photoview ``` 验证: ```bash curl -s http://127.0.0.1:8000/api/graphql \ -X POST -H 'Content-Type: application/json' \ -d '{"query":"{ siteInfo { initialSetup } }"}' # {"data":{"siteInfo":{"initialSetup":true}}} ``` ### 6. SSL 证书 & Nginx 上传证书(`gallery.fukun.net.key` + `gallery.fukun.net_bundle.crt`)到 `/etc/nginx/ssl/`,然后创建上文 Nginx 配置并 reload: ```bash sudo nginx -t && sudo nginx -s reload ``` --- ## Ubuntu 24.04 特有问题 | 问题 | 原因 | 解决 | |------|------|------| | `MagickWand.h: No such file` | 24.04 只有 IM6,Photoview 依赖 IM7 | 源码编译 IM7 到 `/usr/local/im7` | | `cannot find -lcblas` | 24.04 把 CBLAS 合并进 BLAS | `ln -sf libblas.so libcblas.so` | | `exiftool not found` → panic | 启动必须有 exiftool | `apt install exiftool` | | go-face `-lcblas` 重复链接 | go-face 内部也声明了 | `sed -i 's/-lcblas//g'` | | go module cache 只读 | `go mod download` 文件只读 | `sudo chmod u+w` 后再改 | | `new URL('/api/graphql')` 报 Invalid URL | 相对路径无法构造 URL | `REACT_APP_API_ENDPOINT` 用完整 URL | --- ## CDN 配置 统一加速域名 `cdn.fukun.net`,按路径回源: ``` cdn.fukun.net ├── /blog/* → 回源 fukun.net(博客静态资源) └── /gallery/* → 回源 gallery.fukun.net/photos/(相册原图) ``` | 配置项 | 值 | |--------|-----| | 加速域名 | `cdn.fukun.net` | | 回源协议 | HTTPS | | 回源 HOST | 留空(自动用源站域名) | **注意:** CDN 只加速公开的静态文件。管理界面里的图片需要鉴权 cookie,不能走 CDN,仍直连 `gallery.fukun.net`。Hugo 博客嵌入原图时用 `https://cdn.fukun.net/gallery/photos/xxx.jpg`。 --- ## 维护 ### 状态 ```bash sudo systemctl status photoview sudo journalctl -u photoview -f ``` ### 更新前端 ```bash scp -r ui/src ui/public ubuntu@62.234.90.54:/tmp/pv-ui/ ssh ubuntu@62.234.90.54 ' sudo cp -r /tmp/pv-ui/* /home/gallery/photoview-src/ui/ sudo chown -R gallery:gallery /home/gallery/photoview-src/ui sudo -u gallery bash -c "cd /home/gallery/photoview-src/ui && npm ci && npm run build" sudo systemctl restart photoview ' ``` ### 更新后端 ```bash ssh ubuntu@62.234.90.54 ' cd /home/gallery/photoview-src/api export PKG_CONFIG_PATH=/usr/local/im7/lib/pkgconfig CGO_ENABLED=1 sudo -u gallery go build -o photoview . sudo systemctl restart photoview ' ``` ### 备份 ```bash # 数据库 sudo cp /home/gallery/data/photoview.db /opt/backup/photoview_$(date +%Y%m%d).db # 上传照片 scp *.jpg ubuntu@62.234.90.54:/tmp/pv-photos/ ssh ubuntu@62.234.90.54 'sudo mv /tmp/pv-photos/* /home/gallery/photos/ && sudo chown -R gallery:gallery /home/gallery/photos/' ``` --- ## 端口汇总 | 端口 | 用途 | 公网 | |------|------|------| | 22 | SSH | ✅ | | 80/443 | Nginx 全站 | ✅ | | 8000 | Photoview | ❌ 127.0.0.1 | | 8080 | Vaultwarden | ❌ 127.0.0.1 | | 17581 | OpenClaw | ❌ | --- ## 初始化 1. 浏览器访问 `https://gallery.fukun.net` 2. 创建管理员账号 3. **Photo Path** 填 `/home/gallery/photos` 4. 上传相片后,Settings → Scan All --- ## 仓库 ``` ssh://git@fukun.net/data/git-repos/gallery.git ``` 服务器 `/data/git-repos/gallery.git`(bare),推送到 `master`。