Files
Codex f5997b47d9
CI / Frontend build (push) Successful in 13s
CI / Script syntax (push) Successful in 3s
CI / Backend tests (push) Failing after 17s
Add Gitea CI workflow
2026-07-15 01:10:59 +02:00

186 lines
4.8 KiB
Markdown

# PVE Cloud Backup
Self-hosted Proxmox VE backup manager for uploads to an existing rclone remote such as OneDrive.
The application is intentionally small:
- FastAPI backend and worker
- Vue 3 + TypeScript + Tailwind frontend, compiled once into `static/`
- SQLite for all runtime configuration and state
- `pvesh` for Proxmox API access
- `rclone copyto`, `rclone lsjson`, `rclone deletefile`, and `rclone rmdir` for exact remote objects and empty per-backup folders
- systemd services, no Docker
## Layout
All application files live under:
```text
/opt/pve-cloud-backup/
backend/
frontend/
static/
data/
app.db
logs/
scripts/
```
The install script copies the two systemd service files to `/etc/systemd/system/`.
## Prerequisites
Install these on the Proxmox host:
- Python 3 with `venv`
- Node.js and npm for the one-time frontend build
- `rclone`
- a preconfigured rclone remote, for example OneDrive or a crypt remote backed by OneDrive
- working `pvesh` access as the service user
The app does not configure rclone. If no remote exists, setup fails until you configure rclone yourself.
## Install
From the installation directory:
```bash
cd /opt/pve-cloud-backup
./scripts/install.sh
```
The installer:
1. creates required subdirectories,
2. creates a Python virtual environment,
3. installs Python dependencies,
4. builds the Vue frontend into `/opt/pve-cloud-backup/static`,
5. initializes SQLite migrations,
6. installs and starts systemd services.
Open:
```text
http://<proxmox-host>:8080
```
## Setup
On first launch, complete the setup wizard:
- Proxmox node
- Proxmox backup storage
- local backup directory
- rclone executable path
- rclone remote name
- remote backup path/folder within that remote
- Discord webhook URL
- allowed CORS origins
- default compression
- default backup mode
- default retention policy
- max concurrent backups
All settings are stored in SQLite at `/opt/pve-cloud-backup/data/app.db`.
## Recovery behavior
On worker startup, unfinished records in these states are reconciled:
- `pve_running`
- `local_ready`
- `uploading`
- `remote_ready`
- `local_deleting`
- `deleting`
The worker does not delete unknown local files or remote objects. Local archives are deleted only after upload finishes and the remote object is verified.
## Retention cleanup
Retention cleanup runs in two places:
- immediately after a backup completes for that job;
- periodically from the worker service, once per hour, so changed rules and day-based expiry are enforced even if no new backup runs.
Remote deletion uses exact-object `rclone deletefile` calls for backup records already known in SQLite, then best-effort `rclone rmdir` cleanup for the empty per-backup folder.
## Testing
Run backend tests:
```bash
cd /opt/pve-cloud-backup/backend
./.venv/bin/pytest
```
Run frontend type check and build:
```bash
cd /opt/pve-cloud-backup/frontend
npm run build
```
Manual integration test against a real Proxmox guest:
```bash
INTEGRATION_VMID=<vmid> API_URL=http://127.0.0.1:8080 /opt/pve-cloud-backup/scripts/integration-test.sh
```
Optional environment variables:
- `INTEGRATION_GUEST_NAME` to assert the discovered guest name before queueing.
- `INTEGRATION_STORAGE` to override the configured Proxmox backup storage.
- `INTEGRATION_LOCAL_BACKUP_DIR` to assert the configured local dump directory.
- `INTEGRATION_CRON` to choose the created job schedule. Default: `0 3 * * *`.
- `INTEGRATION_RUN_NOW=0` to create the job without immediately queueing it.
The script creates a disabled backup job and, by default, queues it once. Only run it when you intentionally want a real Proxmox backup and rclone upload.
## CI
Gitea Actions workflow:
```text
.gitea/workflows/ci.yml
```
It runs on pushes and pull requests to `main` and can also be started manually. The workflow checks:
- backend dependency install and pytest;
- frontend dependency install and production build;
- shell script syntax.
Package caches are enabled through the Gitea Actions cache-compatible setup actions:
- Python/pip cache keyed by `backend/requirements.txt`;
- npm cache keyed by `frontend/package-lock.json`.
The Gitea runner must have action cache support configured for cache restore/save to work.
## Updates
After pulling new code, apply it with:
```bash
cd /opt/pve-cloud-backup
git pull --ff-only
./scripts/apply-update.sh
```
For a stricter update that runs backend tests before restarting services:
```bash
RUN_TESTS=1 ./scripts/apply-update.sh
```
The update script backs up `data/app.db`, rebuilds dependencies/assets, runs migrations, installs service units, restarts services, and checks API health.
## Uninstall
```bash
/opt/pve-cloud-backup/scripts/uninstall.sh
```
The uninstall script removes and disables systemd services. It leaves `/opt/pve-cloud-backup` intact so `app.db`, logs, and any remaining data are not destroyed accidentally.