mirror of
https://github.com/Awuqing/BackupX.git
synced 2026-09-04 23:16:41 +08:00
docs(cluster): document bastion and recovery operations
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: Bare-metal Deployment
|
||||
description: systemd + Nginx deployment from the prebuilt release tarball or source.
|
||||
description: Hardened systemd deployment from the prebuilt release tarball or source, with opt-in Nginx.
|
||||
---
|
||||
|
||||
# Bare-metal Deployment
|
||||
@@ -11,6 +11,8 @@ description: systemd + Nginx deployment from the prebuilt release tarball or sou
|
||||
```bash
|
||||
# Download the matching tarball
|
||||
curl -LO https://github.com/Awuqing/BackupX/releases/latest/download/backupx-linux-amd64.tar.gz
|
||||
curl -LO https://github.com/Awuqing/BackupX/releases/latest/download/backupx-linux-amd64.tar.gz.sha256
|
||||
sha256sum -c backupx-linux-amd64.tar.gz.sha256
|
||||
|
||||
# Extract and install
|
||||
tar xzf backupx-linux-amd64.tar.gz && cd backupx-*-linux-amd64
|
||||
@@ -23,9 +25,17 @@ The installer performs these steps automatically:
|
||||
2. Copies the binary to `/opt/backupx/bin/backupx` and the web console to `/opt/backupx/web`
|
||||
3. Installs the default configuration at `/etc/backupx/config.yaml`
|
||||
4. Installs `backupx.service` (systemd), enabled at boot
|
||||
5. (Optional) installs an Nginx site file — see [Nginx Reverse Proxy](./nginx)
|
||||
5. Leaves Nginx unchanged unless `INSTALL_NGINX=1` is explicitly requested
|
||||
6. Verifies the first-setup API before reporting success
|
||||
|
||||
The executable and web assets are owned by root; only `/opt/backupx/data` is writable by the `backupx` service account. `/etc/backupx/config.yaml` is installed as `root:backupx` with mode `0640`.
|
||||
|
||||
The bundled Nginx template is a starting point and may conflict with an existing default server. Review its hostname and TLS policy first, then opt in:
|
||||
|
||||
```bash
|
||||
sudo INSTALL_NGINX=1 ./install.sh
|
||||
```
|
||||
|
||||
For multi-node clusters, edit `/etc/backupx/config.yaml` after installation and set the Master URL that remote Agents can reach:
|
||||
|
||||
```yaml
|
||||
@@ -70,6 +80,7 @@ ExecStart=/opt/backupx/bin/backupx -config /etc/backupx/config.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
NoNewPrivileges=true
|
||||
UMask=0027
|
||||
LimitNOFILE=65535
|
||||
|
||||
[Install]
|
||||
@@ -87,6 +98,8 @@ curl -fsS http://127.0.0.1:8340/api/auth/setup/status
|
||||
|
||||
Open `http://your-server:8340`, switch to English if desired, and create the first administrator on the **System setup** screen. For a custom listen port, run the installer with a matching `HEALTH_URL`.
|
||||
|
||||
For production, expose BackupX through HTTPS or restrict port `8340` at the firewall. The installer does not make firewall changes.
|
||||
|
||||
## Password reset
|
||||
|
||||
If the admin password is lost:
|
||||
|
||||
@@ -15,7 +15,11 @@ server:
|
||||
host: "0.0.0.0" # BACKUPX_SERVER_HOST
|
||||
port: 8340 # BACKUPX_SERVER_PORT
|
||||
mode: "release" # release | debug
|
||||
external_url: "" # BACKUPX_SERVER_EXTERNAL_URL — public Master URL for Agent install scripts
|
||||
external_url: "" # BACKUPX_SERVER_EXTERNAL_URL — stable public Master URL
|
||||
trusted_proxies: # BACKUPX_SERVER_TRUSTED_PROXIES — exact proxy IPs/CIDRs
|
||||
- "127.0.0.1"
|
||||
- "::1"
|
||||
web_root: "" # BACKUPX_SERVER_WEB_ROOT — built frontend directory
|
||||
|
||||
database:
|
||||
path: "./data/backupx.db" # BACKUPX_DATABASE_PATH — embedded SQLite
|
||||
@@ -48,6 +52,7 @@ The environment wins when both file and env are set. All dot-paths become unders
|
||||
|------------|--------------|
|
||||
| `server.port` | `BACKUPX_SERVER_PORT` |
|
||||
| `server.external_url` | `BACKUPX_SERVER_EXTERNAL_URL` |
|
||||
| `server.trusted_proxies` | `BACKUPX_SERVER_TRUSTED_PROXIES` (comma-separated for env) |
|
||||
| `security.jwt_expire` | `BACKUPX_SECURITY_JWT_EXPIRE` |
|
||||
| `log.level` | `BACKUPX_LOG_LEVEL` |
|
||||
| `backup.max_concurrent` | `BACKUPX_BACKUP_MAX_CONCURRENT` |
|
||||
@@ -64,3 +69,18 @@ server:
|
||||
```
|
||||
|
||||
This value is used when BackupX renders one-click Agent install scripts and docker-compose snippets. It must be reachable from every Agent host. Leave it empty only when `X-Forwarded-Proto` / `X-Forwarded-Host` are reliable and point to the same URL that Agents can access.
|
||||
|
||||
The install wizard can set an Agent-specific runtime URL for a proxy or SSH-bastion node. The public install link continues to use `server.external_url`, while the generated Agent config uses that override.
|
||||
|
||||
## Trusted reverse proxies
|
||||
|
||||
BackupX trusts forwarded client-address headers only from `server.trusted_proxies`. The default permits loopback Nginx only. If a reverse proxy runs in another container or host, add its exact IP or subnet:
|
||||
|
||||
```yaml
|
||||
server:
|
||||
trusted_proxies:
|
||||
- "127.0.0.1"
|
||||
- "172.18.0.0/16"
|
||||
```
|
||||
|
||||
Do not configure `0.0.0.0/0`: client addresses feed authentication throttling, install-token throttling, and audit records. Set an empty list when BackupX is exposed directly and should trust no forwarded headers.
|
||||
|
||||
@@ -1,81 +1,96 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: Docker Deployment
|
||||
description: Production-style Docker deployment with docker compose, mounted source directories, and environment overrides.
|
||||
description: Hardened single-process Docker deployment with health checks and persistent data.
|
||||
---
|
||||
|
||||
# Docker Deployment
|
||||
|
||||
BackupX's official Docker image [`awuqing/backupx`](https://hub.docker.com/r/awuqing/backupx) supports multi-architecture (linux/amd64 + linux/arm64).
|
||||
The official [`awuqing/backupx`](https://hub.docker.com/r/awuqing/backupx) image supports `linux/amd64` and `linux/arm64`.
|
||||
|
||||
## Compose file
|
||||
|
||||
```yaml title="docker-compose.yml"
|
||||
services:
|
||||
backupx:
|
||||
image: awuqing/backupx:latest
|
||||
image: ${BACKUPX_IMAGE:-awuqing/backupx:latest}
|
||||
container_name: backupx
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
stop_grace_period: 30s
|
||||
ports:
|
||||
- "8340:8340"
|
||||
- "${BACKUPX_BIND_ADDRESS:-0.0.0.0}:${BACKUPX_PORT:-8340}:8340"
|
||||
volumes:
|
||||
- backupx-data:/app/data
|
||||
# Mount host directories you want to back up:
|
||||
- /var/www:/mnt/www:ro
|
||||
- /etc/nginx:/mnt/nginx-conf:ro
|
||||
# - /var/www:/mnt/www:ro
|
||||
# - /etc/nginx:/mnt/nginx-conf:ro
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
cap_drop:
|
||||
- ALL
|
||||
cap_add:
|
||||
- CHOWN
|
||||
- DAC_OVERRIDE
|
||||
- SETGID
|
||||
- SETUID
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
# Required when remote Agents must connect through a public or routed URL:
|
||||
# - BACKUPX_SERVER_EXTERNAL_URL=https://backup.example.com
|
||||
- BACKUPX_LOG_LEVEL=info
|
||||
- BACKUPX_BACKUP_MAX_CONCURRENT=2
|
||||
TZ: Asia/Shanghai
|
||||
# BACKUPX_SERVER_EXTERNAL_URL: https://backup.example.com
|
||||
BACKUPX_LOG_LEVEL: info
|
||||
BACKUPX_BACKUP_MAX_CONCURRENT: "2"
|
||||
healthcheck:
|
||||
test: ["CMD", "su-exec", "backupx:backupx", "wget", "-q", "-T", "3", "-O", "/dev/null", "http://127.0.0.1:8340/ready"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
backupx-data:
|
||||
```
|
||||
|
||||
Start with:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
## Host-directory backup
|
||||
The entrypoint uses root only to migrate ownership of data written by older images, then starts one unprivileged `backupx` process. Compose retains only the ownership and UID/GID transition capabilities needed for that initialization. The backend serves both the API and built web assets; the image neither mounts the Docker socket nor bundles a Docker CLI. Pin `BACKUPX_IMAGE` to a release tag in production.
|
||||
|
||||
To back up files from the host, mount them into the container. When creating a file-type task in the web UI, point the source path at the mount location (e.g. `/mnt/www`). Make sure the directory is visible inside the container.
|
||||
## Host-directory backups
|
||||
|
||||
## Multi-node clusters
|
||||
Mount each source directory and use its container path in the task. The container's `backupx` user must be able to read it; restore destinations need a separate, narrowly scoped writable mount. Prefer a remote Agent for privileged host paths. If a Master-side task truly requires root, make that exception explicit with `user: "0:0"` and review every mount.
|
||||
|
||||
When deploying Agents on other machines, set `BACKUPX_SERVER_EXTERNAL_URL` on the Master container to the URL that those Agents can reach:
|
||||
## Multi-node cluster
|
||||
|
||||
Set the stable URL that Agents can reach:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- BACKUPX_SERVER_EXTERNAL_URL=https://backup.example.com
|
||||
BACKUPX_SERVER_EXTERNAL_URL: https://backup.example.com
|
||||
```
|
||||
|
||||
Use an HTTPS URL if Agents cross untrusted networks. The generated one-click install scripts and docker-compose snippets use this value as `BACKUPX_AGENT_MASTER`.
|
||||
Use HTTPS across untrusted networks. Proxy, private-CA, and SSH-bastion deployments are covered in [Multi-Node Cluster](../features/multi-node).
|
||||
|
||||
## Environment variables
|
||||
If an external reverse proxy is in another container, add only its bridge subnet to `BACKUPX_SERVER_TRUSTED_PROXIES`, for example `172.18.0.0/16`. Do not trust every address.
|
||||
|
||||
All configuration keys can be overridden with the `BACKUPX_` prefix:
|
||||
## Environment overrides
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
- BACKUPX_SERVER_PORT=8340
|
||||
- BACKUPX_LOG_LEVEL=debug
|
||||
- BACKUPX_BACKUP_MAX_CONCURRENT=4
|
||||
- BACKUPX_BACKUP_TEMP_DIR=/tmp/backupx
|
||||
TZ: Asia/Shanghai
|
||||
BACKUPX_LOG_LEVEL: debug
|
||||
BACKUPX_BACKUP_MAX_CONCURRENT: "4"
|
||||
BACKUPX_BACKUP_TEMP_DIR: /tmp/backupx
|
||||
```
|
||||
|
||||
See the [Configuration](./configuration) page for the full list.
|
||||
The image's internal port is fixed at `8340`; change only the published host port with `BACKUPX_PORT`.
|
||||
|
||||
## Upgrades
|
||||
|
||||
Check **System Settings → Check Updates** in the UI to see if a new version is available, then on the host:
|
||||
## Upgrade and rollback preparation
|
||||
|
||||
```bash
|
||||
docker compose pull && docker compose up -d
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
No migrations needed — BackupX auto-migrates the SQLite schema on startup.
|
||||
Wait for `healthy` before switching traffic or removing an old deployment. Before upgrades, stop the Master for a file-level copy or take an atomic snapshot of the entire `backupx-data` volume. Keep exactly one active Master for a data volume; SQLite does not support multiple Master containers sharing `/app/data`.
|
||||
|
||||
@@ -23,13 +23,16 @@ server {
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8340;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $http_host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
|
||||
# Large uploads (restore flow)
|
||||
client_max_body_size 0;
|
||||
proxy_request_buffering off;
|
||||
|
||||
# Live log stream uses SSE — buffering must be off
|
||||
proxy_buffering off;
|
||||
@@ -39,6 +42,10 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
`proxy_request_buffering off` is required for Master-relay cluster backups. Without it, Nginx writes the complete Agent upload to its temporary storage before BackupX receives it, defeating streaming and potentially filling the proxy disk.
|
||||
|
||||
If Nginx runs on another host or in another container, add only that proxy IP or subnet to `server.trusted_proxies`. Do not use `0.0.0.0/0`; BackupX uses the trusted client address for login throttling, install-token throttling, and audit records.
|
||||
|
||||
## HTTPS with certbot
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,155 +1,229 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: Multi-Node Cluster
|
||||
description: Master-Agent mode — route backups to remote servers via HTTP long-polling.
|
||||
description: Deploy BackupX Agents through direct HTTPS, forward proxies, or SSH bastions.
|
||||
---
|
||||
|
||||
# Multi-Node Cluster
|
||||
|
||||
BackupX supports Master-Agent mode: backup tasks can be routed to specific nodes. The Agent runs the backup locally and uploads straight to storage. All connections are initiated by the Agent, so remote networks only need outbound HTTP access.
|
||||
BackupX uses a single active Master as the control plane and an Agent on each source server. Agents initiate every connection, report a heartbeat every 15 seconds, and poll for commands every 5 seconds. No inbound Agent port is required.
|
||||
|
||||
## Architecture
|
||||
## Architecture and boundaries
|
||||
|
||||
```
|
||||
[Web Console] ─── JWT ──→ [Master (backupx)]
|
||||
↑ ↓
|
||||
│ │ HTTP long-poll (token auth)
|
||||
│ ↓
|
||||
[Agent (backupx agent)] ← runs on remote host
|
||||
↓
|
||||
[70+ Storage Backends]
|
||||
```text
|
||||
[Web console] ────────> [Active Master + SQLite]
|
||||
^
|
||||
| outbound HTTP(S) polling
|
||||
+---------+---------+
|
||||
| | |
|
||||
[Agent B] [Agent C] [Agent D]
|
||||
| | |
|
||||
+----> storage targets
|
||||
```
|
||||
|
||||
- **Protocol** — HTTP long-polling; the Agent initiates every connection
|
||||
- **Heartbeat** — Agent reports every 15s; Master marks nodes offline after 45s of silence
|
||||
- **Dispatch** — Master persists `run_task` commands to a queue; Agent polls and claims them
|
||||
- **Execution** — Agent reuses the same BackupRunner (file / mysql / postgresql / sqlite / saphana) and uploads directly to storage
|
||||
- **Security** — Each node has its own token; the Agent never holds the Master's JWT secret or AES-256 key
|
||||
- Each node has an independent Agent Token. The Agent never receives the Master's JWT or encryption key.
|
||||
- A node is marked offline after 45 seconds without a heartbeat.
|
||||
- The Master persists commands; an Agent claims and executes them locally.
|
||||
- Network storage is normally written directly by the Agent. A Master-local target can opt into authenticated streaming relay.
|
||||
|
||||
## Centralize backups from servers B/C/D into storage M
|
||||
:::warning Single-active Master
|
||||
The embedded SQLite database is not a shared multi-writer database. Run exactly one active Master against a data directory. For control-plane recovery, use an active/passive host, persistent-volume snapshots, and a stable DNS name or virtual IP. Never scale multiple Master replicas over the same `/app/data` or `backupx.db`.
|
||||
:::
|
||||
|
||||
Use the Master as the control plane and register every source server as an Agent. A task's **Source server** determines where paths and database tools are resolved; its **Storage targets** determine where the resulting artifact is retained.
|
||||
BackupX applies a five-second SQLite busy timeout and command-queue indexes to reduce contention from concurrent Agent polls and task updates. Keep the database on a local or block-backed filesystem. For a file-level control-plane backup, stop the Master before copying the whole data directory; do not copy only `backupx.db` while it is running.
|
||||
|
||||
BackupX chooses the data path per target:
|
||||
## Choose a network path
|
||||
|
||||
| Destination | Data path |
|
||||
| --- | --- |
|
||||
| S3, WebDAV, FTP, cloud drive, or another network backend | Agent streams directly to the destination |
|
||||
| `local_disk` with **Relay remote backups through Master** enabled (for example storage server M mounted through NFS) | Agent streams through the authenticated Master API; Master writes to its configured local path |
|
||||
| Scenario | Agent Master URL | Agent proxy URL | Notes |
|
||||
| --- | --- | --- | --- |
|
||||
| Routed network or public service | `https://backup.example.com` | empty | Recommended; allow only outbound TCP 443 |
|
||||
| Corporate forward proxy | `https://backup.example.com` | `http://proxy.internal:3128` | HTTP(S) and SOCKS5(H) are supported |
|
||||
| SSH dynamic tunnel through a bastion | `https://backup.internal` | `socks5h://127.0.0.1:1080` | Preserves TLS hostname and resolves internal DNS through the tunnel |
|
||||
| SSH fixed local forward | `http://127.0.0.1:18340` | empty | The HTTP hop is protected by SSH; bind the forward to loopback only |
|
||||
|
||||
The relay is streaming: the Master does not create a second temporary copy of the entire artifact. The reverse path is used when restoring a Master-local artifact back to its source Agent. Use HTTPS whenever Agent traffic crosses an untrusted network.
|
||||
For private PKI, provide the absolute path of a pre-provisioned PEM CA certificate. Do not use `--insecure-tls` in production.
|
||||
|
||||
To configure the common `A → {B,C,D} → M` topology:
|
||||
When no explicit proxy is configured, Agent-to-Master HTTP traffic follows `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`. A system service does not normally inherit an interactive shell's environment, so set the proxy in the install wizard or Agent YAML for systemd deployments.
|
||||
|
||||
1. Run BackupX Master on A and mount M on A if M is exposed as NFS or another filesystem.
|
||||
2. Create a `local_disk` target for that mount and keep **Relay remote backups through Master** enabled, or create an S3/WebDAV target exposed by M. Existing local-disk targets keep their prior Agent-local behavior until this switch is enabled.
|
||||
3. Install one Agent on B, C, and D from **Node Management**.
|
||||
4. Create a backup task for each source, choose B/C/D under **Source server**, browse that server's paths, and select M as the storage target. A source-server pool label can route identical tasks dynamically.
|
||||
5. Verify the per-target result in the backup record. For a Master-local target, the record reports transfer mode `master_relay`; network backends remain `direct`.
|
||||
## Prepare the Master
|
||||
|
||||
## Walkthrough
|
||||
Set a stable URL before generating commands:
|
||||
|
||||
### 0. Set the Master URL for production clusters
|
||||
|
||||
Before generating Agent install commands, make sure the Master URL shown to Agents is stable and reachable from every target host.
|
||||
|
||||
If BackupX runs behind Docker, Nginx, a load balancer, or an outer reverse proxy, configure `server.external_url` or `BACKUPX_SERVER_EXTERNAL_URL` on the Master:
|
||||
|
||||
```yaml title="config.yaml"
|
||||
```yaml title="/etc/backupx/config.yaml"
|
||||
server:
|
||||
external_url: "https://backup.example.com"
|
||||
trusted_proxies:
|
||||
- "127.0.0.1"
|
||||
- "::1"
|
||||
# Add the exact reverse-proxy IP or subnet when it is not local.
|
||||
# - "172.18.0.0/16"
|
||||
```
|
||||
|
||||
This URL is baked into systemd units, foreground commands, and docker-compose snippets. If it is wrong, Agents will install successfully but stay offline because they keep polling an internal or browser-only address.
|
||||
`external_url` is the default install and Agent runtime address. A restricted node can override both generated target-side URLs with its tunnel or internal address while the browser continues to use the public address.
|
||||
|
||||
### 1. Open the install wizard
|
||||
Use HTTPS across untrusted networks. For Master-relay uploads, configure the reverse proxy with unlimited request body size and request buffering disabled; see [Nginx Reverse Proxy](../deployment/nginx).
|
||||
|
||||
In the Web Console → **Node Management** → **Add Node**. You'll see a three-step wizard.
|
||||
Configure the Agent with the final API URL, not an HTTP-to-HTTPS redirect. The Agent deliberately does not follow redirects so its authentication Token cannot be forwarded to an unintended host.
|
||||
|
||||
- **Step 1 — Node info.** Give the node a name, or switch to batch mode and paste multiple names (one per line, max 50).
|
||||
- **Step 2 — Deploy options.** Pick install mode (`systemd` recommended, `docker`, or `foreground` for debugging), architecture (auto-detect by default), agent version (defaults to the master's version), TTL for the install link (5 min / 15 min / 1 h / 24 h), and download source (`github` direct, or the `ghproxy` mirror for mainland China).
|
||||
- **Step 3 — Copy the command.** A one-line install command is shown with a live countdown. Click copy, paste into the target machine, and run with root privileges. The default command embeds the rendered installer, so the target host does not need to fetch `/api/install/:token` through your reverse proxy. The public install URL is still available as a fallback.
|
||||
## Deploy an Agent
|
||||
|
||||
### 2. One-line install on the target host
|
||||
Open **Node Management → Add Node**:
|
||||
|
||||
Use the command generated by the Web Console. It writes the installer to a temporary file, validates the `BACKUPX_AGENT_INSTALL_V1` marker, then runs it with root privileges.
|
||||
1. Enter one node name, or up to 50 names in batch mode.
|
||||
2. Select systemd, Docker, or foreground mode; architecture; Agent release; command TTL; and download source.
|
||||
3. Select **Direct** or **Proxy or bastion**. For the restricted path, set an Agent-specific Master URL, proxy URL, or private CA path.
|
||||
4. Copy the generated command to the target host and run it with root privileges.
|
||||
|
||||
The script runs automatically and:
|
||||
Systemd is recommended for host-file backup and restore because the Agent needs access to arbitrary local paths. A Docker Agent sees only explicitly mounted paths; recreate it with read-only backup-source mounts and separately scoped writable restore destinations before assigning file tasks.
|
||||
|
||||
1. Detects OS and architecture (`uname -m`)
|
||||
2. Downloads the matching `backupx` binary from GitHub Release (or the ghproxy mirror)
|
||||
3. Installs to `/opt/backupx-agent` and creates a `backupx` system user
|
||||
4. Writes `/etc/systemd/system/backupx-agent.service` with the token baked into environment variables
|
||||
5. Runs `systemctl enable --now backupx-agent`
|
||||
6. Polls `/api/v1/agent/self` until the master confirms `status: online` (up to 30 s)
|
||||
The URL-based command downloads a one-time installer and verifies its marker before execution. The wizard binds the selected Agent URL, explicit proxy, and private CA to that download command as well as to the installed Agent configuration. If the install endpoint is still unreachable, use the separately displayed embedded command. The embedded command contains the long-lived node Token and must be handled as a secret.
|
||||
|
||||
Docker mode uses the same `BACKUPX_AGENT_MASTER`, `BACKUPX_AGENT_TOKEN`, and `BACKUPX_AGENT_TEMP_DIR=/var/lib/backupx-agent/tmp` environment contract. After starting the container, the installer also probes `/api/v1/agent/self`; if the node does not come online, it prints `docker ps` and `docker logs --tail=100 backupx-agent` diagnostics before exiting non-zero.
|
||||
The installer:
|
||||
|
||||
If you choose the URL-based fallback command and `curl` prints HTML or the shell reports `Syntax error: newline unexpected`, the install URL is being served by the web console instead of the backend. Ensure either `/api/install/` or `/install/` is forwarded to the BackupX backend, or use the embedded command generated by the console.
|
||||
1. Detects `linux/amd64` or `linux/arm64`.
|
||||
2. Downloads the selected Release archive through the explicit proxy when configured, otherwise using the host's normal direct/environment-proxy route, and verifies its SHA-256 sidecar when the release provides one.
|
||||
3. Writes `/etc/backupx-agent/config.yaml` and `/etc/backupx-agent/agent.token` with mode `0600`.
|
||||
4. Keeps the Token out of the systemd unit and Docker environment metadata.
|
||||
5. Starts the Agent and checks `/api/v1/agent/self` for up to 30 seconds.
|
||||
6. Returns non-zero with systemd or Docker diagnostics when the node does not become online.
|
||||
|
||||
Reruns are idempotent — to upgrade or re-provision, simply generate a new install command and run it again. The one-time install link expires after its TTL or after first consumption, whichever is sooner.
|
||||
Older releases without checksum sidecars remain installable with a warning. New releases should always publish and verify the sidecar.
|
||||
|
||||
### 3. Rotate agent tokens at any time
|
||||
|
||||
Go to the node's action menu (︙) → **Rotate Token**. The new token is shown once and the old token remains valid for 24 h, allowing rolling restarts without downtime. After 24 h, the old token is rejected.
|
||||
|
||||
### 4. Batch deployment
|
||||
|
||||
In Step 1 choose "Batch" and paste node names (one per line, max 50). Step 3 shows a table with one command per node plus a **Download .sh** button that bundles all commands into a shell script, convenient for SSH loops or Ansible tasks.
|
||||
|
||||
### 5. Route a task to the node
|
||||
|
||||
In the **Backup Tasks** page, pick the source server when creating the task. When the task runs:
|
||||
|
||||
- Local (`nodeId=0`) → Master executes in-process
|
||||
- Remote node → Master enqueues the command → Agent claims → Agent runs locally → uploads → reports back
|
||||
|
||||
The node table shows the Agent health and command queue state: pending/dispatched depth, running long commands, timeouts, oldest active command age, and the latest Agent-side error. The same queue depth, running-command, and timeout snapshots are exported as Prometheus metrics:
|
||||
|
||||
- `backupx_agent_command_queue_depth`
|
||||
- `backupx_agent_command_running`
|
||||
- `backupx_agent_command_timeout_total`
|
||||
|
||||
## Known limitations
|
||||
|
||||
- **Encrypted backups are Master-only** — the Agent doesn't hold Master's AES-256 key. Creating or updating a task with `encrypt: true` and a remote node or node pool is rejected up front
|
||||
- **Directory browser timeout** — remote dir listing is a synchronous RPC through the queue (15s default)
|
||||
- **Dispatched command timeout** — claimed-but-unfinished commands are marked `timeout` after 10 minutes
|
||||
|
||||
## CLI reference
|
||||
### Installed systemd configuration
|
||||
|
||||
```yaml title="/etc/backupx-agent/config.yaml"
|
||||
master: "https://backup.example.com"
|
||||
tokenFile: "/etc/backupx-agent/agent.token"
|
||||
heartbeatInterval: "15s"
|
||||
pollInterval: "5s"
|
||||
tempDir: "/var/lib/backupx-agent/tmp"
|
||||
proxyUrl: ""
|
||||
caCertFile: ""
|
||||
```
|
||||
backupx agent --help
|
||||
-master string Master URL
|
||||
-token string Agent auth token
|
||||
-config string YAML config path (takes precedence over env)
|
||||
-temp-dir string Local temp directory (default /tmp/backupx-agent)
|
||||
-insecure-tls Skip TLS verification (testing only)
|
||||
```
|
||||
|
||||
## systemd unit
|
||||
|
||||
```ini title="/etc/systemd/system/backupx-agent.service"
|
||||
[Unit]
|
||||
Description=BackupX Agent
|
||||
After=network.target
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
StartLimitIntervalSec=300
|
||||
StartLimitBurst=10
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=backupx
|
||||
Environment="BACKUPX_AGENT_MASTER=https://master.example.com"
|
||||
Environment="BACKUPX_AGENT_TOKEN=your-token"
|
||||
ExecStart=/opt/backupx/backupx agent
|
||||
ExecStart=/opt/backupx-agent/backupx agent --config /etc/backupx-agent/config.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=10s
|
||||
TimeoutStopSec=30s
|
||||
UMask=0077
|
||||
LimitNOFILE=65535
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
The Agent runs as root because file backup and restore paths may belong to arbitrary system users. Restrict who can create tasks and who can modify the root-owned Agent configuration.
|
||||
|
||||
## SSH bastion example
|
||||
|
||||
Prefer a SOCKS tunnel when the internal Master uses HTTPS: its hostname and certificate validation remain unchanged.
|
||||
|
||||
Create a dedicated SSH account and pre-provision its private key plus a verified `known_hosts` file. Then create:
|
||||
|
||||
```sshconfig title="/etc/backupx-agent/ssh_config"
|
||||
Host backupx-bastion
|
||||
HostName bastion.example.com
|
||||
User backupx-tunnel
|
||||
IdentityFile /etc/backupx-agent/tunnel_ed25519
|
||||
IdentitiesOnly yes
|
||||
BatchMode yes
|
||||
UserKnownHostsFile /etc/backupx-agent/known_hosts
|
||||
StrictHostKeyChecking yes
|
||||
DynamicForward 127.0.0.1:1080
|
||||
ExitOnForwardFailure yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
```
|
||||
|
||||
```ini title="/etc/systemd/system/backupx-agent-tunnel.service"
|
||||
[Unit]
|
||||
Description=BackupX Agent SSH tunnel
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
Before=backupx-agent.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/ssh -NT -F /etc/backupx-agent/ssh_config backupx-bastion
|
||||
Restart=always
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Add a drop-in so the Agent fails closed when the tunnel is unavailable:
|
||||
|
||||
```ini title="/etc/systemd/system/backupx-agent.service.d/tunnel.conf"
|
||||
[Unit]
|
||||
Requires=backupx-agent-tunnel.service
|
||||
After=backupx-agent-tunnel.service
|
||||
```
|
||||
|
||||
Reload and start both units:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --now backupx-agent
|
||||
sudo journalctl -u backupx-agent -f
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now backupx-agent-tunnel backupx-agent
|
||||
```
|
||||
|
||||
In the wizard, keep the internal HTTPS Master URL and set the proxy to `socks5h://127.0.0.1:1080`. Verify the bastion host key out-of-band before enabling the service.
|
||||
|
||||
## Central storage data paths
|
||||
|
||||
| Destination | Data path |
|
||||
| --- | --- |
|
||||
| S3, WebDAV, FTP, cloud drive, or another network backend | Agent streams directly to the destination |
|
||||
| `local_disk` with **Relay remote backups through Master** enabled | Agent streams through the authenticated Master API; Master writes to its local mount |
|
||||
|
||||
The relay does not create a second complete temporary copy on the Master. Restore uses the reverse streaming path. Nginx request buffering must be disabled for this behavior to remain streaming.
|
||||
|
||||
## Operations
|
||||
|
||||
```bash
|
||||
sudo systemctl status backupx-agent
|
||||
sudo journalctl -u backupx-agent -n 100 --no-pager
|
||||
sudo /opt/backupx-agent/backupx agent --config /etc/backupx-agent/config.yaml
|
||||
```
|
||||
|
||||
Rotate a node Token from its action menu. Update `/etc/backupx-agent/agent.token` on the node and restart the service during the 24-hour overlap window.
|
||||
|
||||
Monitor these Prometheus metrics:
|
||||
|
||||
- `backupx_agent_command_queue_depth`
|
||||
- `backupx_agent_command_running`
|
||||
- `backupx_agent_command_timeout_total`
|
||||
- `backupx_node_online`
|
||||
|
||||
## CLI reference
|
||||
|
||||
```text
|
||||
backupx agent --help
|
||||
-master string Master URL
|
||||
-token string Agent authentication token
|
||||
-token-file string Read the Agent Token from a file
|
||||
-config string YAML configuration path
|
||||
-temp-dir string Local temporary directory
|
||||
-proxy-url string HTTP(S) or SOCKS5(H) proxy
|
||||
-ca-cert string PEM CA certificate used to verify the Master
|
||||
-insecure-tls Skip TLS verification (testing only)
|
||||
```
|
||||
|
||||
Environment variables: `BACKUPX_AGENT_MASTER`, `BACKUPX_AGENT_TOKEN`, `BACKUPX_AGENT_TOKEN_FILE`, `BACKUPX_AGENT_HEARTBEAT`, `BACKUPX_AGENT_POLL`, `BACKUPX_AGENT_TEMP_DIR`, `BACKUPX_AGENT_PROXY_URL`, `BACKUPX_AGENT_CA_CERT_FILE`, and `BACKUPX_AGENT_INSECURE_TLS`.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- The Master is single-active because it uses embedded SQLite.
|
||||
- Encrypted backups are Master-only because Agents do not hold the Master encryption key.
|
||||
- Remote directory browsing is a synchronous queue RPC with a 15-second timeout.
|
||||
- Claimed commands that stop reporting progress are timed out according to the Master command monitor.
|
||||
|
||||
@@ -48,8 +48,9 @@ Images: [`awuqing/backupx`](https://hub.docker.com/r/awuqing/backupx) — suppor
|
||||
Download from the [Releases page](https://github.com/Awuqing/BackupX/releases) and run the installer:
|
||||
|
||||
```bash
|
||||
sha256sum -c backupx-v*-linux-amd64.tar.gz.sha256
|
||||
tar xzf backupx-v*-linux-amd64.tar.gz && cd backupx-*
|
||||
sudo ./install.sh # creates system user, installs to /opt/backupx, sets up systemd + nginx
|
||||
sudo ./install.sh # creates system user, installs to /opt/backupx, sets up systemd
|
||||
```
|
||||
|
||||
The installer:
|
||||
@@ -58,7 +59,7 @@ The installer:
|
||||
2. Installs the binary to `/opt/backupx/bin/backupx` and the web console to `/opt/backupx/web`
|
||||
3. Creates `/etc/backupx/config.yaml` with safe defaults
|
||||
4. Installs and enables the `backupx.service` systemd unit
|
||||
5. (Optional) Configures an Nginx reverse proxy
|
||||
5. Leaves Nginx unchanged unless `INSTALL_NGINX=1` is explicitly requested
|
||||
6. Waits for `/api/auth/setup/status`; if startup fails, prints systemd diagnostics and exits non-zero
|
||||
|
||||
## From source
|
||||
@@ -74,6 +75,8 @@ sudo ./deploy/install.sh
|
||||
After `make build`, the binary is at `server/bin/backupx` and the built web UI is at `web/dist/`.
|
||||
The installer consumes those exact paths, so no Docker runtime is required. If an existing configuration uses a non-default port, set `HEALTH_URL` for the readiness check, for example `sudo HEALTH_URL=http://127.0.0.1:9000/api/auth/setup/status ./deploy/install.sh`.
|
||||
|
||||
The Nginx template is opt-in because automatically installing a catch-all virtual host can intercept existing sites. Review `deploy/nginx.conf`, then use `sudo INSTALL_NGINX=1 ./deploy/install.sh` only when it matches the host.
|
||||
|
||||
## Verify the install
|
||||
|
||||
```bash
|
||||
|
||||
@@ -21,7 +21,7 @@ description: Overview of BackupX — a self-hosted server backup management plat
|
||||
```
|
||||
[Web Console] ─── JWT ──→ [Master (backupx)]
|
||||
│
|
||||
│ HTTP long-poll (token auth)
|
||||
│ outbound HTTP polling (token auth)
|
||||
▼
|
||||
[Agent (backupx agent)]
|
||||
│
|
||||
|
||||
@@ -32,11 +32,14 @@ backupx agent --master http://master:8340 --token <token>
|
||||
|------|-------------|
|
||||
| `--master <url>` | Master URL |
|
||||
| `--token <token>` | Agent auth token |
|
||||
| `--token-file <path>` | Read the Agent Token from a file; preferred for services and containers |
|
||||
| `--config <path>` | YAML config (takes precedence over env) |
|
||||
| `--temp-dir <path>` | Local temp directory (default `/tmp/backupx-agent`) |
|
||||
| `--proxy-url <url>` | Explicit HTTP(S) or SOCKS5(H) proxy |
|
||||
| `--ca-cert <path>` | PEM CA certificate used to verify the Master |
|
||||
| `--insecure-tls` | Skip TLS verification (testing only) |
|
||||
|
||||
Environment variables: `BACKUPX_AGENT_MASTER`, `BACKUPX_AGENT_TOKEN`, `BACKUPX_AGENT_HEARTBEAT`, `BACKUPX_AGENT_POLL`, `BACKUPX_AGENT_TEMP_DIR`, `BACKUPX_AGENT_INSECURE_TLS`.
|
||||
Environment variables: `BACKUPX_AGENT_MASTER`, `BACKUPX_AGENT_TOKEN`, `BACKUPX_AGENT_TOKEN_FILE`, `BACKUPX_AGENT_HEARTBEAT`, `BACKUPX_AGENT_POLL`, `BACKUPX_AGENT_TEMP_DIR`, `BACKUPX_AGENT_PROXY_URL`, `BACKUPX_AGENT_CA_CERT_FILE`, `BACKUPX_AGENT_INSECURE_TLS`. When no explicit proxy URL is set, the Agent also honors `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY`.
|
||||
|
||||
## `backupx backint`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user