Make proxmox_storage a global setting instead of a per-job snapshot
Backup jobs stored their own proxmox_storage column, copied from settings at creation time and never resynced. process_backup preferred that frozen job value, so changing Settings > Proxmox storage had no effect on existing jobs. Drop the per-job column and always use the current global setting when starting a backup. Also copies AGENTS.md to CLAUDE.md.
This commit is contained in:
@@ -0,0 +1,226 @@
|
||||
# Agent notes for PVE Cloud Backup
|
||||
|
||||
This project is a directly installed Proxmox backup web app. It runs from:
|
||||
|
||||
```text
|
||||
/opt/pve-cloud-backup/
|
||||
backend/ FastAPI app, worker, SQLite migrations, tests
|
||||
frontend/ Vue 3 + TypeScript + Tailwind source
|
||||
static/ generated frontend build; ignored by git
|
||||
data/ runtime SQLite database; ignored by git
|
||||
logs/ runtime logs; ignored by git
|
||||
scripts/ install/update/uninstall/manual integration scripts
|
||||
systemd/ source copies of service units
|
||||
```
|
||||
|
||||
The live services are:
|
||||
|
||||
- `pve-cloud-backup-web.service`
|
||||
- `pve-cloud-backup-worker.service`
|
||||
|
||||
The web app listens on `0.0.0.0:8080`.
|
||||
|
||||
## Core rules
|
||||
|
||||
- Keep runtime configuration in SQLite only. Do not add `.env`, YAML, JSON, TOML, or other runtime config files.
|
||||
- Do not commit `/opt/pve-cloud-backup/data/`, `/logs/`, `/static/`, `.venv`, `node_modules`, caches, or generated artifacts.
|
||||
- Do not use Docker or add distributed-worker infrastructure.
|
||||
- Do not call `vzdump` directly. Use `pvesh` for backup operations.
|
||||
- Do not require a crypt remote. Plain OneDrive remotes and crypt remotes are both allowed.
|
||||
- Do not use `rclone sync`.
|
||||
- Use exact-object rclone operations:
|
||||
- upload with `copyto`;
|
||||
- verify with `lsjson`;
|
||||
- delete files with `deletefile`;
|
||||
- remove empty per-backup folders with `rmdir`.
|
||||
- Never delete a local archive unless upload completed and the remote object was verified.
|
||||
- Mock `pvesh` and `rclone` in automated tests. Manual integration testing is limited to `scripts/integration-test.sh` and must only run when the user explicitly asks for a real backup test.
|
||||
|
||||
## Runtime data
|
||||
|
||||
SQLite database:
|
||||
|
||||
```text
|
||||
/opt/pve-cloud-backup/data/app.db
|
||||
```
|
||||
|
||||
Important runtime settings live in SQLite, not files:
|
||||
|
||||
- Proxmox node
|
||||
- Proxmox backup storage
|
||||
- local dump directory
|
||||
- rclone executable path
|
||||
- rclone remote name
|
||||
- remote path inside that rclone remote
|
||||
- timezone
|
||||
- retention defaults
|
||||
- Discord webhook URL
|
||||
- CORS origins
|
||||
|
||||
Treat all node names, storage names, guest names, VMIDs, rclone remotes, and filesystem paths as operator-specific runtime data. Do not hardcode deployment-specific values in application code or publish-facing docs.
|
||||
|
||||
## Backend map
|
||||
|
||||
- `backend/app/main.py`
|
||||
- FastAPI app, API routes, setup/settings validation, static frontend serving.
|
||||
- `backend/app/backup_service.py`
|
||||
- Backup state machine, upload/delete/retention/recovery logic.
|
||||
- `backend/app/commands.py`
|
||||
- Shell wrappers for `pvesh` and `rclone`.
|
||||
- `backend/app/jobs.py`
|
||||
- Cron validation, timezone-aware next-run calculation, job CRUD helpers.
|
||||
- `backend/app/migrations.py`
|
||||
- SQLite schema and default settings.
|
||||
- `backend/app/settings_store.py`
|
||||
- SQLite settings serialization/parsing.
|
||||
- `backend/app/worker.py`
|
||||
- Scheduler/worker entrypoint.
|
||||
- `backend/tests/`
|
||||
- Unit tests. Keep external command usage mocked.
|
||||
|
||||
## Frontend map
|
||||
|
||||
- `frontend/src/App.vue`
|
||||
- Single-file UI for setup, dashboard, guests, jobs, history, backup details, and settings.
|
||||
- `frontend/src/main.ts`
|
||||
- Vue mount entrypoint.
|
||||
- `frontend/src/style.css`
|
||||
- Tailwind/global styling.
|
||||
|
||||
The built frontend goes to `/opt/pve-cloud-backup/static/` via `npm run build`; do not commit that directory.
|
||||
|
||||
## Backup workflow
|
||||
|
||||
Expected states:
|
||||
|
||||
- `queued`
|
||||
- `pve_running`
|
||||
- `local_ready`
|
||||
- `uploading`
|
||||
- `remote_ready`
|
||||
- `local_deleting`
|
||||
- `completed`
|
||||
- `failed`
|
||||
- `deleting`
|
||||
- `deleted`
|
||||
|
||||
Important behavior:
|
||||
|
||||
- The worker atomically claims queued backups before starting Proxmox work.
|
||||
- `pve_running` must have a real Proxmox UPID before polling task status.
|
||||
- Local archive discovery must ignore `.log` and `.notes`; only real archive suffixes count.
|
||||
- Remote path shape is:
|
||||
|
||||
```text
|
||||
<rclone_remote>:<rclone_remote_path>/<backup_id>/<archive_name>
|
||||
```
|
||||
|
||||
- Deleting a backup removes the exact remote file and then attempts to remove the empty `<backup_id>` folder.
|
||||
- Deleting a backup already in `deleted` state purges the SQLite metadata row.
|
||||
- Deleting a job deletes all known non-active backups for that job first, then removes the job.
|
||||
- Retention runs after backup completion and hourly from the worker.
|
||||
|
||||
## Applying updates after pulling changes
|
||||
|
||||
After a `git pull`, apply the new code with:
|
||||
|
||||
```bash
|
||||
cd /opt/pve-cloud-backup
|
||||
./scripts/apply-update.sh
|
||||
```
|
||||
|
||||
The script:
|
||||
|
||||
1. backs up `data/app.db` to `data/update-backups/`;
|
||||
2. stops web/worker services;
|
||||
3. creates/updates `backend/.venv`;
|
||||
4. installs backend requirements;
|
||||
5. optionally runs backend tests if `RUN_TESTS=1`;
|
||||
6. runs `npm ci` or `npm install`;
|
||||
7. builds frontend assets into `static/`;
|
||||
8. runs SQLite migrations;
|
||||
9. installs systemd units from `systemd/`;
|
||||
10. reloads systemd;
|
||||
11. restarts and health-checks services.
|
||||
|
||||
Use this stricter variant when practical:
|
||||
|
||||
```bash
|
||||
cd /opt/pve-cloud-backup
|
||||
git pull --ff-only
|
||||
RUN_TESTS=1 ./scripts/apply-update.sh
|
||||
```
|
||||
|
||||
If the health check fails, inspect:
|
||||
|
||||
```bash
|
||||
journalctl -u pve-cloud-backup-web.service -u pve-cloud-backup-worker.service --no-pager -n 100
|
||||
```
|
||||
|
||||
## Validation commands
|
||||
|
||||
CI workflow:
|
||||
|
||||
```text
|
||||
.gitea/workflows/ci.yml
|
||||
```
|
||||
|
||||
The workflow is for Gitea Actions and runs backend tests, frontend build, and shell script syntax checks. It uses setup-action package caching for pip and npm, keyed from `backend/requirements.txt` and `frontend/package-lock.json`.
|
||||
|
||||
Backend tests:
|
||||
|
||||
```bash
|
||||
cd /opt/pve-cloud-backup/backend
|
||||
./.venv/bin/pytest
|
||||
```
|
||||
|
||||
Frontend typecheck/build:
|
||||
|
||||
```bash
|
||||
cd /opt/pve-cloud-backup/frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
Service status:
|
||||
|
||||
```bash
|
||||
systemctl is-active pve-cloud-backup-web.service pve-cloud-backup-worker.service
|
||||
```
|
||||
|
||||
API smoke checks:
|
||||
|
||||
```bash
|
||||
curl -fsS http://127.0.0.1:8080/api/setup/status
|
||||
curl -fsS http://127.0.0.1:8080/api/jobs | python3 -m json.tool
|
||||
curl -fsS http://127.0.0.1:8080/api/backups | python3 -m json.tool
|
||||
```
|
||||
|
||||
Manual integration test:
|
||||
|
||||
```bash
|
||||
INTEGRATION_VMID=<vmid> API_URL=http://127.0.0.1:8080 /opt/pve-cloud-backup/scripts/integration-test.sh
|
||||
```
|
||||
|
||||
Only run the manual integration test when the user explicitly wants a real Proxmox/rclone backup test.
|
||||
|
||||
## Git workflow
|
||||
|
||||
Default branch:
|
||||
|
||||
```text
|
||||
main
|
||||
```
|
||||
|
||||
Do not document private deployment remotes, hostnames, or organization names in committed files. Local git remotes belong in `.git/config`, not project documentation.
|
||||
|
||||
Before committing, check:
|
||||
|
||||
```bash
|
||||
git status --short --ignored
|
||||
```
|
||||
|
||||
Confirm ignored runtime files stay ignored:
|
||||
|
||||
```bash
|
||||
git check-ignore -v data/app.db logs/worker.log static/index.html frontend/node_modules/.package-lock.json backend/.venv/pyvenv.cfg
|
||||
```
|
||||
Reference in New Issue
Block a user