簡介
在撰寫技術文章或開發紀錄時,圖片的管理與嵌入往往會中斷寫作心流。本指南旨在建立一套完全私有化、高效且自動化的圖床工作流:在 Ubuntu 伺服器的 Docker 環境中部署 Zipline,搭配 Nginx Proxy Manager 做反向代理,再透過 Cloudflare 提供邊緣快取。
完成後,只需在 VS Code 中貼上圖片,PicList 便會自動完成上傳、分類、設定過期時間,並回傳支援跨域直連的 HTTPS 網址,全程無需離開編輯器。
本架構特別適合需要精確控制檔案生命週期(例如 30 天後自動刪除)、且重視資料隱私的開發者或內容創作者。
先決條件
開始本指南之前,請確認已具備下列環境:
- 一台執行 Ubuntu 的伺服器,並已安裝 Docker 與 Portainer。
- 一個已正常運行於
proxy_network(內網網段192.168.32.0/20)的 Nginx Proxy Manager(NPM)容器。 - 一個由 Cloudflare 代管的專屬網域(本指南以
your_domain作為佔位符)。 - 客戶端已安裝 VS Code(含 PicList 擴充套件或桌面版主程式)以及 ShareX。
全量參數提取表
以下為本架構中最終確認有效的所有核心參數設定值,供快速查閱與除錯對照:
| 組件 | 參數名稱 | 設定值 | 說明 |
|---|---|---|---|
| Docker 網路 | 子網段 | 192.168.32.0/20 | NPM 與 Zipline 所在的內部網路 |
| UFW 防火牆 | 允許規則 | allow from 192.168.32.0/20 to any port 3006 | 若需透過主機 IP 存取時使用 |
| Zipline 核心 | CORE_SECRET | 需大於 32 字元的隨機英數 | 系統安全金鑰 |
| Zipline 核心 | CORE_RETURN_HTTPS | true | 強制 API 回傳 HTTPS 網址 |
| NPM 代理 | Forward Port | 3000 | 走 Docker 內網直連容器預設埠口 |
| NPM 進階 | client_max_body_size | 512M | 解除 Nginx 預設 1MB 上傳限制 |
| PicList/ShareX | API 地址 | https://your_domain/api/upload | 標準上傳端點 |
| PicList/ShareX | POST 參數名 | file | 接收檔案的變數名稱 |
| PicList/ShareX | JSON 路徑 | files[0].url | 解析回傳網址的精確路徑 |
| API 標頭 | x-zipline-folder | (依實際建立的資料夾 ID) | 指定上傳目標資料夾 |
| API 標頭 | x-zipline-deletes-at | 30d 或 90d | 設定伺服器端自動刪除時間 |
| Cloudflare | 快取規則 URI Path | 包含 /u/ | 針對圖片目錄強制邊緣快取 |

逐步教學
步驟一:透過 Portainer 部署伺服器端環境
我們將使用 Portainer 的 Stack 功能部署 Zipline 與 PostgreSQL 資料庫。為避免容器名稱冗長,Compose 檔中已強制指定 container_name。
- 登入 Portainer,進入 Stacks,點選 Add stack。
- 命名為
zipline,並在 Web editor 中貼上以下docker-compose.yml內容:
services:
zipline_db:
container_name: zipline_db
image: postgres:16
restart: unless-stopped
networks:
- proxy_network
environment:
POSTGRES_USER: ${POSTGRESQL_USER:-zipline}
POSTGRES_PASSWORD: ${POSTGRESQL_PASSWORD}
POSTGRES_DB: ${POSTGRESQL_DB:-zipline}
TZ: ${TZ:-Asia/Taipei}
volumes:
- ${ZIPLINE_DB_DIR:-zipline_pgdata}:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
zipline:
container_name: zipline
image: ghcr.io/diced/zipline
restart: unless-stopped
networks:
- proxy_network
ports:
- '${ZIPLINE_PORT:-3000}:3000'
environment:
CORE_SECRET: ${CORE_SECRET}
DATABASE_URL: postgres://${POSTGRESQL_USER:-zipline}:${POSTGRESQL_PASSWORD}@zipline_db:5432/${POSTGRESQL_DB:-zipline}
TZ: ${TZ:-Asia/Taipei}
CORE_RETURN_HTTPS: "true"
depends_on:
zipline_db:
condition: service_healthy
volumes:
- '${ZIPLINE_UPLOADS_DIR:-./uploads}:/zipline/uploads'
- '${ZIPLINE_PUBLIC_DIR:-./public}:/zipline/public'
- '${ZIPLINE_THEMES_DIR:-./themes}:/zipline/themes'
healthcheck:
test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3000/api/healthcheck']
interval: 15s
timeout: 2s
retries: 2
networks:
proxy_network:
external: true
volumes:
zipline_pgdata:
- 往下捲動至 Environment variables(進階模式),填入以下環境變數(請務必替換密碼與金鑰):
TZ=Asia/Taipei
ZIPLINE_PORT=3006
CORE_SECRET=請替換為至少32字元的極度複雜隨機英數密碼
ZIPLINE_UPLOADS_DIR=/您的自訂路徑/zipline/uploads
ZIPLINE_PUBLIC_DIR=/您的自訂路徑/zipline/public
ZIPLINE_THEMES_DIR=/您的自訂路徑/zipline/themes
ZIPLINE_DB_DIR=zipline_pgdata
POSTGRESQL_USER=zipline_admin
POSTGRESQL_PASSWORD=請替換為高強度資料庫密碼
POSTGRESQL_DB=zipline_db
- 點選 Deploy the stack 完成部署。
步驟二:Ubuntu 防火牆設定(UFW)
為了讓同屬 proxy_network 的容器(或透過主機轉發的流量)能正確存取 Zipline,需開放主機的 3006 埠口給特定 Docker 網段。透過 SSH 登入 Ubuntu 後執行:
sudo ufw allow from 192.168.32.0/20 to any port 3006
sudo ufw reload
sudo ufw status
步驟三:設定 Nginx Proxy Manager 反向代理
- 進入 NPM 後台,新增 Proxy Host。
- Details 分頁:
- Domain Names:
your_domain - Scheme:
http - Forward Hostname / IP:
zipline(與 NPM 同屬proxy_network,可直接填容器名稱) - Forward Port:
3000(容器內部埠口)
- Advanced 分頁(解決大檔案上傳限制):填入以下設定:
client_max_body_size 512M;
proxy_read_timeout 600s;
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
- SSL 分頁:申請或套用憑證,勾選 Force SSL 後儲存。
步驟四:Zipline 基礎設定與取得 Token
- 前往
https://your_domain登入 Zipline。 - 建立管理員帳號後,進入 Settings,關閉 Enable Embeds(或 Format URL with Viewer)功能,確保圖片網址為純直連,不會跳轉至預覽頁面。
- 進入 Manage Account,在 Tokens 區塊點選 Create Token,複製並妥善保存。
- (選用)在首頁建立資料夾,並從網址列記錄該資料夾的 ID,後續設定上傳目標時會用到。
步驟五:設定客戶端 PicList(供 VS Code 使用)
- 開啟 PicList 主程式,進入「圖床設定」→「自定義 Web 圖床」。
- 新增設定,依序填入:
- API 地址:
https://your_domain/api/upload - POST 參數名:
file - JSON 路徑:
files[0].url - 自定義 Header:必須為合法 JSON 格式,可在此指定目標資料夾與過期時間(下方範例設為 30 天後刪除)。
{
"authorization": "您在步驟四取得的 Token",
"x-zipline-folder": "您的資料夾 ID",
"x-zipline-deletes-at": "30d"
}
- 自定義 Body:留空。
- 儲存並設為預設圖床。完成後,在 VS Code 中直接貼上圖片,即可自動取得 Markdown 格式的圖片連結。

步驟六:設定客戶端 ShareX(供桌面截圖使用)
若要讓桌面截圖也能自動上傳至指定分類,請複製以下 JSON,並在 ShareX 中透過「目標 → 自訂上傳工具設定 → 匯入 → 從剪貼簿」匯入。匯入後,將 authorization 欄位替換為您的實際 Token。
{
"Version": "17.0.0",
"Name": "Zipline - ShareX 專用",
"DestinationType": "ImageUploader, TextUploader, FileUploader",
"RequestMethod": "POST",
"RequestURL": "https://your_domain/api/upload",
"Headers": {
"authorization": "YOUR_API_TOKEN",
"x-zipline-folder": "YOUR_FOLDER_ID",
"x-zipline-deletes-at": "90d"
},
"URL": "{json:files[0].url}",
"Body": "MultipartFormData",
"FileFormName": "file"
}

進階優化:Cloudflare 強制邊緣快取
為避免高流量文章消耗家用伺服器的出口頻寬,可透過 Cloudflare 快取圖片的讀取流量。
- 確認 Cloudflare DNS 中的網域已處於「橘雲(Proxied)」狀態。
- 進入 快取(Caching)→ Cache Rules,建立新規則。
- 觸發條件:
URI Pathstarts with/u/。 - 快取行為:
- 選擇 Eligible for cache。
- Edge TTL:選擇 Override origin,設為 1 個月(建議不超過伺服器端的自動刪除時間)。
- Browser TTL:選擇 Override origin,設為 1 天。
- 部署後,用瀏覽器無痕模式開啟任一圖片並按 F12,檢查 Response Headers 中的
cf-cache-status,顯示HIT即表示設定成功。

常見問題與故障排除
1. Portainer 中 Zipline 容器顯示 Unhealthy(橘燈)
- 現象:資料庫與應用程式的啟動日誌皆正常,但容器被標記為不健康。
- 根本原因:健康檢查指令(
wget)與容器內部網路解析存在時序問題,屬於假警報,完全不影響服務正常運作。 - 解法:若要消除警告,可在 Compose 檔中移除
healthcheck區塊,或將測試網址改為127.0.0.1。
2. 上傳時出現 413 Request Entity Too Large
- 現象:上傳稍大的檔案時直接報錯失敗。
- 根本原因:Nginx 預設將請求 Body 限制在 1MB。
- 解法:在 NPM 的 Advanced 設定中加入
client_max_body_size 512M;解除限制。
3. PicList 日誌顯示 SUCCESS,但介面仍提示上傳失敗
- 現象:後台日誌出現 200 OK,介面卻找不到回傳的圖片網址。
- 根本原因:Zipline 回傳的 JSON 結構與 PicList 預期的路徑不符。曾嘗試修改「自定義 Body」格式,反而破壞了上傳的資料結構。
- 解法:「自定義 Body」欄位必須完全留空,並將「JSON 路徑」精準設定為
files[0].url。
4. 取得的直連網址自動跳轉至 /view/ 頁面
- 現象:在瀏覽器中開啟
/u/開頭的網址,會自動跳轉為帶有黑色背景介面的/view/頁面。 - 根本原因:這是 Zipline 針對瀏覽器 HTML 請求的預覽保護機制。透過 Markdown
![]()嵌入時不會觸發跳轉,正常使用不受影響。 - 解法:若需徹底停用跳轉,進入 Zipline 後台 Settings,關閉 Enable Embeds 選項。
5. API 回傳的網址為 http 而非 https
- 現象:上傳後取得的網址顯示為
http://your_domain/...。 - 根本原因:NPM 以 HTTP 轉發流量至 Docker 內網,導致 Zipline 誤判連線協議為 HTTP。
- 解法:在 Portainer 的環境變數中加入
CORE_RETURN_HTTPS=true強制覆蓋即可。
Android 設定
Android 端雖有多款第三方 Zipline 客戶端,但考量到最新 Android 版本(如 Pixel 9)的相容性與功能完整度,建議採用以下兩種方案。
方案一:原生 App(由 cssnr 開發)
這是目前社群中維護最積極、對 Zipline v4 API 支援最穩定的版本,能完整支援 Android「分享選單」,可直接從相簿將照片上傳至伺服器。
- 專案位址:GitHub - cssnr/zipline-android
- 安裝方式:前往 GitHub Releases 下載最新版 APK 安裝。
- 核心設定步驟:
- Server URL:填入
https://your_domain(結尾不要加斜線/)。 - Token:填入步驟四取得的 API Token。
- Name Format:必填。若留空,部分版本會觸發邏輯錯誤,誤報「容量超限」或上傳卡死。建議填入
{filename}或{random:8}。 - 測試分享:在手機相簿選取照片,點選「分享」並選擇 Zipline App,確認進度條正常跑完。
技術筆記:若使用其他 App(如 Stef-00012 版本)遇到「1.89MB 超過 500MB」的矛盾報錯,通常是
Name Format欄位驗證失敗所致,並非真正的容量限制,手動填入檔名格式即可解決。
方案二:PWA 輕量化方案(無需安裝)
若不想安裝額外的 APK,Zipline 內建的 Web UI 已針對行動裝置優化,體驗近似原生 App。
- 使用 Vivaldi 或 Firefox 瀏覽器開啟您的 Zipline 網址。
- 點選瀏覽器選單中的「新增至主螢幕」。
- 桌面圖示建立後,即可完整支援您在伺服器端設定的所有「上傳範本」與「自動刪除」規則,且不存在第三方 App 的解析相容性問題。
iOS 設定
透過 iOS 捷徑(Shortcuts)功能,可將手機照片快速上傳至 Zipline 伺服器並自動取得分享連結。
1. 建立捷徑與設定輸入
- 新增一個捷徑。
- 在捷徑設定中開啟「在分享工作表中顯示」。
- 設定捷徑接收「影像」與「檔案」類型的輸入。
2. 設定網路請求(取得 URL 的內容)
這是捷徑的核心動作,依下列設定配置:
- URL:
https://your_domain/api/upload(必須包含/api/upload路徑,否則傳輸會失敗)。 - 方法:POST。
- 標頭(Headers):
authorization:建議使用捷徑內建的變數存放 Token,避免明文暴露。x-zipline-folder:填入目標資料夾 ID(選填)。x-zipline-deletes-at:90d,設定 90 天後自動刪除(不需自動刪除可省略)。x-zipline-image-compression-percent:85,壓縮品質 85%(不需壓縮可省略)。x-zipline-image-compression-type:webp,強制轉換為 WebP 格式(選填)。
- 要求主體:選擇「表單」。
- 表單欄位:新增一個欄位,鍵(Key)填入
file,值(Value)選擇「捷徑輸入」的檔案。
3. 解析回傳資料並複製連結
上傳成功後,Zipline 會回傳 JSON 格式的結果,依以下步驟解析取得網址:
- 取得字典值:從「URL 的內容」中取出
files的值。 - 從列表取得項目:取上述結果的「第一個項目」。
- 取得字典值:從該項目中取出
url的值。 - 拷貝至剪貼簿:將
url複製到剪貼簿,方便後續貼上使用。

4. 常見問題排除
錯誤訊息:無法從「RTF」轉換到「辭典」: 通常代表伺服器回傳的是 HTML 錯誤頁面,而非預期的 JSON。請確認 API URL 是否正確(例如有無遺漏
/api/upload),以及 Authorization Token 是否仍有效。關於標籤(Tags)設定: 目前 Zipline 的上傳 API(
/api/upload)不支援在標頭中直接指定標籤。若有分類需求,請改用x-zipline-folder標頭指定資料夾來管理。
結論
透過本文的架構,我們將底層伺服器、反向代理、前端寫作工具與邊緣快取網路整合為一套完整的工作流。它不僅消除了 Markdown 寫作時圖片散落各處的痛點,「過期自動刪除」與「資料夾分類指派」功能更能有效管理伺服器硬碟空間,降低長期維運成本。無論是從桌面、手機或 VS Code,都能以一致的體驗完成圖片上傳,是一套穩固且具備高度擴充性的個人化數位資產發布流程。
