一句話結論: 這份程式碼已經可以直接上線;本機一條 npm start 即可跑起正式模式,雲端則用附帶的 Dockerfile 打包,掛上持久化磁碟與環境變數就能對外服務。上線前把第 7 節的檢查清單逐項打勾,並先跑一次 npm run preflight 自動檢查(0 項「擋上線」才算過)。
/)與管理後台(/admin),單一網址,無需安裝。/api/health 做健康探測。/api/*、/admin/api/* 與 /docs/*。data/mapsync.db,掛載持久化磁碟;scripts/backup.js 產出可離線保存的快照。| 變數 | 必填 | 預設 | 說明 |
|---|---|---|---|
PORT | 否 | 8848 | 服務監聽埠 |
HOST | 否 | 0.0.0.0 | 監聽位址 |
NODE_ENV | 建議 | — | 正式環境設 production |
MAPSYNC_DATA_DIR | 正式環境建議 | ./data | 資料庫目錄,雲端請指向掛載的持久化磁碟(如 /data) |
MAPSYNC_BACKUP_DIR | 否 | ./backups | 備份輸出目錄 |
MAPSYNC_ADMIN_TOKEN | 正式環境必填 | 自動產生 | 後台權杖。未設定時系統會產生並寫入 data/admin-token.txt |
MAPSYNC_LLM_KEY | 否 | — | 設定後解析引擎自動升級為 LLM |
MAPSYNC_LLM_ENDPOINT | 否 | OpenAI 相容端點 | 自帶相容 API 的服務位址 |
MAPSYNC_LLM_MODEL | 否 | gpt-4o-mini | 模型名稱 |
MAPSYNC_PLACES_KEY | 否 | — | 設定後解析結果自動補上 place_id/經緯度/地址/營業時間 |
MAPSYNC_PLACES_ENDPOINT | 否 | Google Places v1 | 可覆寫(測試用) |
MAPSYNC_PLACES_TIMEOUT_MS | 否 | 6000 | Places 查詢逾時,逾時只略過補點 |
MAPSYNC_PUBLIC_URL | 否 | — | 對外網址;設定後可供 preflight 檢查外部可達性 |
MAPSYNC_DRIVE_TOKEN | 否 | — | 遠端備份用;Google Drive 上傳的 OAuth 存取權杖 |
MAPSYNC_DRIVE_FOLDER_ID | 否 | — | 遠端備份目錄(Drive 資料夾 id,不給則放根目錄) |
MAPSYNC_RCLONE_REMOTE | 否 | — | 改用 rclone 模式時的目標,例如 <code>gdrive:mapsync-backups</code> |
兩組金鑰都是可選的加速項而非必需品:不設時解析與打點照常運作(規則引擎+內建地標辭典),只是覆蓋率較低。
範本見 <code>.env.example</code>。切勿把真實權杖提交進版本庫(<code>.gitignore</code> 已排除 <code>.env</code> 與 <code>data/</code>)。
npm start
# App http://127.0.0.1:8848/
# Admin http://127.0.0.1:8848/admin
# Health http://127.0.0.1:8848/api/health
# Ready http://127.0.0.1:8848/api/ready
Windows 可直接雙擊專案根目錄的 start.bat(會自動帶入 NODE_ENV=production 並印出網址)。
首次啟動會自動建立資料庫並寫入示範資料。要清空重來:<code>npm run seed</code>。
# 1. 準備環境變數
cp .env.example .env
# 編輯 .env,至少設定:
# MAPSYNC_ADMIN_TOKEN=<一串長隨機字串>
# DOMAIN=mapsync.example.com
# 2. 啟動(首次會 build 映像)
cd deploy && docker compose --env-file ../.env up -d --build
# 3. 驗證
curl -fsS https://$DOMAIN/api/health
X-Frame-Options、X-Content-Type-Options、Referrer-Policy 等安全標頭。mapsync-data volume 保存資料庫;升級映像不會動到資料。HEALTHCHECK,平台可據此自動重啟不健康的實例。以 Fly.io 為例:
fly launch --no-deploy # 產生 fly.toml,選一個離使用者近的 region
fly volumes create mapsync_data --size 1 # 1GB 持久化磁碟
fly secrets set MAPSYNC_ADMIN_TOKEN=<長隨機字串>
# 在 fly.toml 加入:
# [mounts]
# source = "mapsync_data"
# destination = "/data"
# [env]
# MAPSYNC_DATA_DIR = "/data"
fly deploy
其他平台同理:把 <code>deploy/Dockerfile</code> 當建置來源、<code>MAPSYNC_DATA_DIR</code> 指向持久化磁碟、設定 <code>MAPSYNC_ADMIN_TOKEN</code>,並把健康檢查路徑設為 <code>/api/health</code>。
start.bat;視窗關閉即停止。要開機自動執行,用工作排程器呼叫 start.bat。deploy/mapsync.service 到 /etc/systemd/system/,設定 /etc/mapsync/mapsync.env 後 systemctl enable --now mapsync。內含 Restart=always、NoNewPrivileges、ProtectSystem=strict 等硬化設定。deploy/Dockerfile 已內建 HEALTHCHECK,平台依 /api/health 判斷實例健康並自動重啟。PWA 與分享面板的上線注意事項
/api/ 與 /admin 一律走網路,不會把資料或權杖寫進快取。/sw.js(建議 Cache-Control: no-cache),避免使用者卡在舊版 App 殼。服務本身也已內建上線防護(不依賴反向代理):<code>nosniff</code>、<code>X-Frame-Options: DENY</code>、<code>Referrer-Policy</code>、<code>Permissions-Policy</code>、CSP;寫入類 API 每來源每分鐘 120 次上限;請求大小上限 512 KB;啟動時埠被占用會直接以明確錯誤碼退出而不是默默失敗。
npm test 全數通過(30/30;另建議同時跑 npm run test:ai、npm run test:prod)MAPSYNC_SEED_DEMO;必要時 npm run wipe)MAPSYNC_ADMIN_TOKEN 為長隨機字串(非預設值)NODE_ENV=production、MAPSYNC_DATA_DIR 指向持久化磁碟npm run backup)npm run preflight 無任何「擋上線」項目(環境、金鑰、HTTPS、PWA 資源逐項驗)GET /api/health 回 200 且 db:"up"GET /api/version 版本與部署版本一致/admin 用權杖登入,看得到 pins 資料表/api/health),告警送至指定管道npm run backup),並確認備份檔可還原npm run backup:remote,Drive API 或 rclone),並實測一次data/ 同步到雲端硬碟;只同步 backups/(避免同步到執行中的 SQLite)app_logs 的 error 級別筆數,異常即排查標示[x]者代表本機正式環境已完成驗證;[ ]者屬於外部環境設定,需在實際主機上完成。
/api/health 回 200/503,含 uptimeSec、db 狀態;/api/ready 另檢查 schema 是否完整。容器平台與外部 uptime 皆可探測。app_logs/events,後台可即時查看;level=error 筆數即為告警指標。/api/version 回報版本、Node 版本與環境;每次部署在下方紀錄表留下版本與時間。npm run backup 產出快照;node scripts/backup.js --restore <檔名> 還原(會先自動備份現況)。回滾流程(3 步)
git checkout v0.9.0(版本錨點)或上一個穩定版後重新部署(Docker:docker compose up -d --build)。node scripts/backup.js --restore mapsync-<時間>.db → 重啟服務。腳本會先自動備份現況再覆蓋。curl -fsS /api/health + npm run smoke(16 項)+ 後台確認資料表筆數回到預期。實地演練紀錄(2026-09-21)
| 步驟 | 動作 | 結果 |
|---|---|---|
| 1 | 演練前基準 | 圖釘 9 筆 |
| 2 | npm run backup | 產出 mapsync-2026-09-21T04-45-01-819Z.db(112 KB) |
| 3 | 新增標記圖釘 | 圖釘 10 筆(含 p_682ee97d5ab0) |
| 4 | 停服務 → --restore | 還原成功,且自動先備份現況(另存 04-45-11 快照) |
| 5 | 重啟服務後查詢 | 圖釘回到 9 筆、標記圖釘消失、/api/health 200 |
程式碼回滾不動資料庫;資料回滾會覆蓋現有資料,因此腳本會先自動備份現況。上述流程已實際走過一次,非紙上推演。
| 時間 | 版本 | 環境 | 方式 | 結果 |
|---|---|---|---|---|
| 2026-09-21 04:35 | v0.9.0 | 本機正式模式(127.0.0.1:8848) | npm start | <span class="rich-badge ok">成功</span> 健康檢查 200、核心流程以瀏覽器實機驗證 |
| 2026-09-21 04:43 | v0.9.0 | 本機正式模式(生產強化版) | npm start | <span class="rich-badge ok">成功</span> 冒煙 16/16、可用率監控 100%、告警路徑驗證通過 |
| 2026-09-21 04:45 | v0.9.0 | 本機正式模式 | 停機 → 備份還原 → 重啟 | <span class="rich-badge ok">成功</span> 回滾演練:10 筆 → 還原 → 9 筆,標記消失 |
| 2026-09-21 04:46 | v0.9.0 | 版控錨點 | git tag v0.9.0 | <span class="rich-badge ok">成功</span> 標籤 v0.9.0、38 檔入版控、修正 Linux 檔名大小寫 |
| 2026-09-21 04:57 | v0.10.0 | 本機正式模式 | 重啟載入新模組 | <span class="rich-badge ok">成功</span> 驗收 30/30、冒煙 16/16、AI 鏈路 21/21、資料庫欄位遷移完成 |
| 2026-09-21 04:59 | v0.10.0 | 本機正式模式 | 瀏覽器開 /share 實測 | <span class="rich-badge ok">成功</span> 分享內容預填、解析完成並留痕 |
| 2026-09-21 05:10 | v0.10.0 | 上線前檢查 | npm run preflight | <span class="rich-badge ok">成功</span> 0 項擋上線、6 項待補(皆為環境設定與金鑰) |
| (待填) | v0.10.0 | 雲端 + 網域 | Docker + Caddy | <span class="rich-badge warn">待執行</span> 需先決定平台與網域(HTTPS 為分享面板前提) |
每次部署後請補一列,這是「留下部署紀錄」的可查驗形式。