-
Notifications
You must be signed in to change notification settings - Fork 154
Description
Problem
When running 9router in Docker with DATA_DIR=/app/data and a persistent volume mounted at /app/data, all usage data, request logs, and request detail recordings are lost whenever the Docker container is restarted (e.g. VPS crash, Docker daemon restart, redeployment).
This happens because usageDb.js and requestDetailsDb.js use os.homedir() (resolving to ~/.9router/) to store their data files, while localDb.js correctly respects the DATA_DIR environment variable.
Affected Files and Storage Paths
| Module | File | Storage Path | Respects DATA_DIR? |
|---|---|---|---|
src/lib/localDb.js |
db.json |
${DATA_DIR}/db.json |
Yes |
src/lib/usageDb.js |
usage.json |
~/.9router/usage.json |
No |
src/lib/usageDb.js |
log.txt |
~/.9router/log.txt |
No |
src/lib/requestDetailsDb.js |
request-details.sqlite |
~/.9router/request-details.sqlite |
No |
This is already noted in docs/ARCHITECTURE.md:
"usageDb currently stores under ~/.9router and does not follow DATA_DIR."
Steps to Reproduce
- Deploy 9router with Docker, set
DATA_DIR=/app/data, mount a persistent volume at/app/data - Use the proxy, accumulate usage data and request logs
- Restart the Docker container (e.g.
docker restart) - All usage stats, cost tracking, request logs, and request detail recordings are gone
- Config/settings in
db.jsonare preserved (becauselocalDb.jscorrectly usesDATA_DIR)
Current Workaround
Mount an additional volume at /root/.9router to persist the usage data directory. This works but requires users to know about this undocumented second data location.
Suggested Fixes
Option A: Make usageDb and requestDetailsDb respect DATA_DIR (Recommended)
In both src/lib/usageDb.js and src/lib/requestDetailsDb.js, change the DATA_DIR resolution to check for the DATA_DIR env variable first, falling back to the current getUserDataDir() logic:
// Before (current):
const DATA_DIR = getUserDataDir();
// After (proposed):
const DATA_DIR = process.env.DATA_DIR || getUserDataDir();This is a one-line change in each file and would make all data files land in the same directory (/app/data/) when DATA_DIR is set, requiring only a single volume mount for full persistence.
Option B: Document the second volume mount requirement
If changing the storage behavior is not desired, the Dockerfile and README should document that Docker deployments need two volume mounts:
/app/datafor config/state (db.json)/root/.9routerfor usage data (usage.json,log.txt,request-details.sqlite)
Option C: Update the Dockerfile
Add a VOLUME instruction for both paths in the Dockerfile:
VOLUME ["/app/data", "/root/.9router"]Environment
- 9router version: latest (master)
- Deployment: Docker via Dokploy
- OS: Linux (node:20-alpine)