# Backup Script Manager A single-administrator web application that runs ordered, typed backup steps on home-lab hosts over SSH and retrieves artifacts over SFTP. Supported operations: - Combine up to 50 Docker commands, remote host commands, database dumps, and directory archives in one job. - Execute commands with zero or more declared outputs, allowing preparation and cleanup steps. - Create compressed PostgreSQL or MySQL dumps using tools installed on the remote host. - Archive a remote directory as `tar.gz`. - Export restore-ready Backup Manager configuration with encrypted credential envelopes. - Run jobs manually or with timezone-aware cron schedules. - Retain a configured number of successful runs and notify by webhook or SMTP. - Browse retained executions by job and download their artifacts with recorded SHA-256 checksums. ## Run With Docker Compose Create the deployment configuration and a permanent encryption key: ```bash cp .env.example .env openssl rand -base64 32 ``` Set the generated value as `MASTER_KEY` and choose a strong `ADMIN_PASSWORD` in `.env`, then start the application: ```bash docker compose up --build -d ``` Open `http://localhost:3000`. The default binds only to loopback. For network access, put the application behind an HTTPS reverse proxy, set `BIND_ADDRESS` as needed, and set `SECURE_COOKIE=true`; do not expose the HTTP login directly to the LAN. Compose uses managed volumes by default. To use bind mounts, set `DATA_PATH` and `BACKUP_PATH` in `.env`; the process runs as UID/GID `10001`, so those host directories must already exist and be writable by that identity. Keep `MASTER_KEY` in a password manager: losing or changing it makes stored SSH and database credentials unreadable. ## Remote Host Requirements - SSH must allow password or private-key authentication and the same account must support SFTP. - Verify a probed SSH fingerprint against the host itself, for example with `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256`, before saving it. - The account needs write access to `/tmp` and read access to backup sources. - Docker jobs require `docker`, `tar`, and `gzip`; the SSH account must be permitted to run Docker without an interactive prompt. - Directory jobs require `tar` and `gzip`. - PostgreSQL jobs require `pg_dump` and `gzip` on the SSH host. MySQL jobs require `mysqldump` and `gzip`. Docker jobs execute in an existing container. Each configured output is a path inside that container. The manager copies it to a permission-restricted remote staging directory, downloads it, and deletes only that staging directory; it does not delete the original container output. ## Job Steps Every job targets one SSH host and runs its steps sequentially over one pinned connection. Use the step arrows in the job builder to control order. Available steps are: - **Docker command:** runs an executable with explicit arguments inside an existing container. Declared container outputs are copied with `docker cp`. - **Remote command:** runs an executable with explicit arguments on the SSH host. It can collect generated host files or archives. - **PostgreSQL/MySQL dump:** creates a compressed dump using an encrypted password associated with that step. - **Directory archive:** archives an absolute host path. - **Backup Manager configuration:** creates a local, integrity-protected JSON artifact containing hosts, jobs, schedules, and notification settings. Credential values remain encrypted and restoration requires the original `MASTER_KEY`; the key itself is never exported. Command arguments are entered one per line and are passed as distinct shell-quoted values; shell pipelines and redirection are not interpreted. Add an explicit script on the remote system when more complex command logic is required. By default, a failed step stops the job and no artifacts are published. Enable **Continue if this step fails** only for non-critical steps. The run then continues, skips outputs from the failed step, and finishes as `succeeded_with_warnings` if all required steps complete. Artifact names must be unique across the job, and every job must contain at least one artifact-producing step. Schedules use five-field cron syntax. Jobs do not overlap: a scheduled occurrence is skipped if that job is already queued or running. Runs from different jobs are processed serially in this initial single-instance release. ## Local Development Node.js 22 or later is required. ```bash npm install export ADMIN_PASSWORD=development-only export MASTER_KEY="$(openssl rand -base64 32)" npm run dev ``` Vite serves the UI on `http://localhost:5173` and proxies API requests to port `3000`. Verification commands: ```bash npm run lint npm run typecheck npm test npm run build ``` Run all checks in that order with `npm run check`. ## Storage - `data/app.db` contains hosts, encrypted secrets, job definitions, schedules, and run history. - `backups///` contains completed artifacts. - `backups/.staging/` contains in-progress downloads and is cleaned when a run fails. Configuration exports omit run history, artifact metadata, artifact files, the administrator password, runtime paths, and `MASTER_KEY`. Store the exported JSON and the key separately. For a complete storage-level backup, back up both the data and artifact volumes together. Restore a configuration export from **Settings > Restore configuration**. Restores require the original `MASTER_KEY`, reject modified exports, update records with matching stable identities, add missing records, and leave unrelated local configuration and run history untouched. Numeric IDs and host references are remapped when necessary. A backup from another manager can initialize an empty installation but cannot merge into a populated installation. Restore is blocked while any job is queued or running, and conflicting names owned by unrelated local records must be resolved first.