Files
FileHost/docs-site/en/guide/migration.md
T
O96u ff20f97522 release: v1.2.1 — login captcha, docs site, and bug fixes
Add slider captcha for web login, VitePress documentation on GitHub Pages,
and fixes for gallery delete refresh, pagination jump, and copy-format persistence.
2026-08-29 11:42:18 +08:00

4.4 KiB

v1.2.0 local disk migration guide

From v1.2.0, all local image files live under data/images/; SQLite keys also start with images/. Legacy top-level folders next to images (e.g. data/blog/, data/twikoo/) are no longer used.

Migration is two steps: run the CLI to move files on disk, then let startup sync align the SQLite index.


Migrating from other image hosts (EasyImage, Lsky, Chevereto, …)

There is no dedicated “pull from URLs” or “import via vendor API” tool. Moving from legacy PicHost or another self-hosted install uses the same local file workflow:

  1. Locate the image files on the old server (copy the tree, not just the database).
  2. Place them under PicHost data/ as a top-level folder next to images (any name — it becomes images/{name}/...).
  3. Run migrate / migrate --apply, then restart PicHost.
Source Typical path on old server After copy into PicHost
PicHost v1.1.x data/blog/, data/twikoo/ Already under data/ → run migrate
EasyImage(s) i/ or upload/ e.g. data/easyimage/ → migrate
Lsky public/uploads/ etc. e.g. data/lsky/ → migrate
Chevereto etc. images/ or content/ e.g. data/chevereto/ → migrate
Custom your folder name data/your-folder/ → migrate

The CLI scans every top-level directory under data/ except images, not only blog / twikoo.

Limits: files only — accounts, tokens, and old public URLs are not imported. mapping.json maps old storage keys, not full old-site URLs. For S3/R2-only legacy hosts, sync blobs to data/… or attach the bucket in PicHost Storage settings.


Layout before and after

Before (typical v1.1.x)

/data
├── pichost.db
├── blog/
│   └── 2026/08/TeKJ2fD6cB6j.webp
├── twikoo/
└── images/

Index keys might look like blog/2026/08/TeKJ2fD6cB6j.webp.

After (v1.2.0)

/data
├── pichost.db
├── mapping.json
└── images/
    ├── blog/
    │   └── 2026/08/TeKJ2fD6cB6j.webp
    └── twikoo/

Index key: images/blog/2026/08/TeKJ2fD6cB6j.webp.


Step 1: CLI file migration

Run before or after upgrading the image; backup data/ first.

docker exec pichost migrate          # preview + mapping.json
docker exec pichost migrate --apply  # move files

Local: npm run migrate / npm run migrate -- --apply.

Item Behavior
Scan Every top-level directory under data/ except images
Target data/images/{original-top-dir}/{relative-path}
Extensions jpg, jpeg, png, webp, gif, svg, ico
Sidecar .meta.json next to an image is moved if present
Other files Not moved; parent directory kept if anything remains
Mapping data/mapping.json — old key → new key

Script: server/cli/migrate-to-single-images.mjs.


Step 2: Startup index sync (automatic)

Runs on every start (npm run dev, Docker). No manual command.

[INFO] 开始同步图片索引:扫描本地磁盘 ...
[INFO] 磁盘扫描完成:...
[INFO] 开始归一化遗留图片路径 ...
[INFO] 开始校验索引与磁盘一致性,清理无文件的孤儿记录
[INFO] 图片索引同步结束
Step Purpose
Scan data/images/ Insert missing index rows for files on disk
Normalize legacy keys blog/... → images/blog/... when files are in place
Purge orphans Remove index rows with no file on disk
Repair Content-Type Fix application/octet-stream entries

The CLI only moves files. Index alignment runs at startup — restart after migrate --apply.


  1. Backup data/.
  2. docker exec pichost migrate — review output and mapping.json.
  3. docker exec pichost migrate --apply.
  4. Deploy v1.2.0 and restart.
  5. Check logs for successful index sync.
  6. Use mapping.json to update external URLs if needed.

Skip step 1 if you only use object storage or everything is already under data/images/.


URLs

| Old key | blog/TeKJ2fD6cB6j.webp | | New key | images/blog/TeKJ2fD6cB6j.webp |

With “hide folder” mode, short URLs like /TeKJ2fD6cB6j.webp may still resolve by filename. Use mapping.json for bulk replacements.

Chinese version: v1.2 迁移指南