From 0595dbfd86ba4776dca72c70b303c619617bf24b Mon Sep 17 00:00:00 2001 From: openclaw Date: Sun, 26 Jul 2026 21:25:57 +0800 Subject: [PATCH 1/2] ops: keep production imports local and backups non-root --- .env.example | 3 +++ .gitignore | 2 ++ README.md | 6 ++++-- compose.pro.yaml | 3 ++- deploy/postgres-backup.sh | 6 ++++-- package.json | 1 + services/api/package.json | 1 + 7 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 930cf6a..1fc39c9 100644 --- a/.env.example +++ b/.env.example @@ -19,5 +19,8 @@ TEST_MODE=false POSTGRES_DB=cents POSTGRES_USER=cents POSTGRES_PASSWORD=change-me +# Host uid/gid used by the backup container when writing ./backups/db. +BACKUP_UID=1001 +BACKUP_GID=1001 APP_TIME_ZONE=Asia/Shanghai EXCHANGE_RATE_API_URL=https://api.frankfurter.dev diff --git a/.gitignore b/.gitignore index 555a684..6bcd580 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +backup/ +services/api/src/import-excel.ts legacy-cent-app/ node_modules/ dist/ diff --git a/README.md b/README.md index efdd96d..a7bbb5f 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,9 @@ docker compose --env-file .env -f compose.pro.yaml exec api \ ## 生产数据库备份 -`backup` 容器每天北京时间 `03:00` 将 PostgreSQL 备份到生产 clone 目录下的 `./backups`。备份采用 PostgreSQL custom format,并在写入后校验;超过 30 天的备份会自动删除。 +`backup` 容器每天北京时间 `03:00` 将 PostgreSQL 备份到生产 clone 目录下的 `./backups/db`。备份容器使用宿主机普通用户运行,不会以 root 保存备份文件。备份采用 PostgreSQL custom format,并在写入后校验;超过 30 天的备份会自动删除。 + +`BACKUP_UID` 和 `BACKUP_GID` 应设置为生产宿主机运行 Cents 的普通用户 UID/GID;默认值为 `1001`。 查看调度和备份日志: @@ -103,5 +105,5 @@ docker compose --env-file .env -f compose.pro.yaml exec backup \ 备份文件位于宿主机: ```text -./backups/cents-YYYYMMDD-HHMMSS.dump +./backups/db/cents-YYYYMMDD-HHMMSS.dump ``` diff --git a/compose.pro.yaml b/compose.pro.yaml index afed19d..2bf3cd4 100644 --- a/compose.pro.yaml +++ b/compose.pro.yaml @@ -37,6 +37,7 @@ services: backup: image: postgres:17-alpine restart: unless-stopped + user: "${BACKUP_UID:-1001}:${BACKUP_GID:-1001}" environment: TZ: Asia/Shanghai PGHOST: db @@ -45,7 +46,7 @@ services: PGPASSWORD: ${POSTGRES_PASSWORD} entrypoint: ["/usr/local/bin/cents-backup"] volumes: - - ./backups:/backups + - ./backups/db:/backups - ./deploy/postgres-backup.sh:/usr/local/bin/cents-backup:ro depends_on: db: diff --git a/deploy/postgres-backup.sh b/deploy/postgres-backup.sh index ace5b92..f83f832 100755 --- a/deploy/postgres-backup.sh +++ b/deploy/postgres-backup.sh @@ -27,11 +27,13 @@ case "${1:-cron}" in run_backup ;; cron) + cron_dir=/tmp/cents-crontabs + mkdir -p "$cron_dir" printf '%s\n' \ '0 3 * * * /usr/local/bin/cents-backup run >> /proc/1/fd/1 2>> /proc/1/fd/2' \ - > /etc/crontabs/root + > "$cron_dir/$(id -u)" printf 'Backup scheduler started: daily at 03:00 %s, retaining 30 days\n' "${TZ:-local time}" - exec crond -f -l 2 + exec crond -f -l 2 -c "$cron_dir" ;; *) printf 'Unknown command: %s\n' "$1" >&2 diff --git a/package.json b/package.json index 960dab9..f75b034 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dev:web:tunnel": "npm run dev --workspace @cents/web -- --port 6064", "dev:api": "npm run dev --workspace @cents/api", "user:add": "npm run user:add --workspace @cents/api --", + "data:import": "npm run data:import --workspace @cents/api --", "build": "npm run build --workspaces --if-present", "typecheck": "npm run typecheck --workspaces --if-present", "lint": "npm run lint --workspaces --if-present" diff --git a/services/api/package.json b/services/api/package.json index e6b38d8..45f7c0d 100644 --- a/services/api/package.json +++ b/services/api/package.json @@ -8,6 +8,7 @@ "start": "tsx src/server.ts", "bootstrap": "tsx src/bootstrap.ts", "user:add": "tsx src/add-user.ts", + "data:import": "tsx src/import-excel.ts", "password:reset": "tsx src/reset-password.ts", "build": "tsc --noEmit", "typecheck": "tsc --noEmit" From b2199b8902fa610e1087bed3760ffd4454d1c441 Mon Sep 17 00:00:00 2001 From: openclaw Date: Mon, 27 Jul 2026 07:24:42 +0800 Subject: [PATCH 2/2] chore: remove one-time data import command --- .gitignore | 1 - package.json | 1 - services/api/package.json | 1 - 3 files changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6bcd580..7d68e31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ backup/ -services/api/src/import-excel.ts legacy-cent-app/ node_modules/ dist/ diff --git a/package.json b/package.json index f75b034..960dab9 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,6 @@ "dev:web:tunnel": "npm run dev --workspace @cents/web -- --port 6064", "dev:api": "npm run dev --workspace @cents/api", "user:add": "npm run user:add --workspace @cents/api --", - "data:import": "npm run data:import --workspace @cents/api --", "build": "npm run build --workspaces --if-present", "typecheck": "npm run typecheck --workspaces --if-present", "lint": "npm run lint --workspaces --if-present" diff --git a/services/api/package.json b/services/api/package.json index 45f7c0d..e6b38d8 100644 --- a/services/api/package.json +++ b/services/api/package.json @@ -8,7 +8,6 @@ "start": "tsx src/server.ts", "bootstrap": "tsx src/bootstrap.ts", "user:add": "tsx src/add-user.ts", - "data:import": "tsx src/import-excel.ts", "password:reset": "tsx src/reset-password.ts", "build": "tsc --noEmit", "typecheck": "tsc --noEmit"