180 lines
5.5 KiB
Markdown
180 lines
5.5 KiB
Markdown
# MikroTik Backup System
|
|
|
|
Version **0.0.1** is the initial Rust rewrite of the previous Python/TypeScript application. It is a single self-hosted service with an embedded web UI, SQLite storage, RouterOS/SwOS backup workflows, scheduling, retention, notifications, and local OpenAPI documentation.
|
|
|
|
## Quick start
|
|
|
|
### Docker Compose
|
|
|
|
```bash
|
|
docker compose build app
|
|
docker compose up -d
|
|
```
|
|
|
|
The default published address is `127.0.0.1:5581`. Persistent application data is stored in the `data` volume.
|
|
|
|
The image uses `rust:1.99.1-alpine3.24` for the build stage and `alpine:3.24` for runtime. The service runs as UID/GID `10001` with a read-only root filesystem.
|
|
|
|
### Native build
|
|
|
|
Requires Rust 1.99.1 or compatible toolchain and the native dependencies needed by the crates in `Cargo.lock`.
|
|
|
|
```bash
|
|
cargo build --release --locked
|
|
./target/release/mikrotik-backup serve
|
|
```
|
|
|
|
Or use the launcher:
|
|
|
|
```bash
|
|
./start.sh
|
|
```
|
|
|
|
## First account
|
|
|
|
Registration is disabled by default. Set `DEFAULT_ADMIN_PASSWORD` before first startup, or let the application create the initial administrator password file under `DATA_DIR/secrets/initial-admin-password`.
|
|
|
|
New installations and new accounts default to **English**. Imported accounts preserve their saved language preference. The UI also supports Polish, Spanish, and Norwegian.
|
|
|
|
## Main configuration
|
|
|
|
| Variable | Default | Purpose |
|
|
| --- | --- | --- |
|
|
| `DATA_DIR` | `./storage` | Database, backups, secrets, SSH known hosts |
|
|
| `DATABASE_PATH` | `<DATA_DIR>/routeros_backup_next.db` | SQLite database path |
|
|
| `LISTEN_ADDR` | `127.0.0.1:5581` | HTTP listener |
|
|
| `API_PREFIX` | `/api` | API base path |
|
|
| `TIMEZONE` | `Europe/Warsaw` | Scheduler timezone |
|
|
| `SECRET_KEY` | generated/persisted when absent | JWT signing secret |
|
|
| `ALLOW_REGISTRATION` | `false` | Allow account registration |
|
|
| `DEFAULT_ADMIN_USERNAME` | `admin` | Initial administrator name |
|
|
| `DEFAULT_ADMIN_PASSWORD` | empty | Initial administrator password |
|
|
| `SSH_HOST_KEY_POLICY` | `accept-new` | `accept-new` or `strict` |
|
|
| `SSH_TIMEOUT_SECONDS` | `30` | Device SSH timeout |
|
|
| `MAX_PARALLEL_BACKUPS` | `4` | Concurrent backup limit |
|
|
| `CORS_ORIGINS` | `[]` | Explicit allowed HTTP(S) origins |
|
|
|
|
Run configuration validation without starting the server:
|
|
|
|
```bash
|
|
./target/release/mikrotik-backup check-config
|
|
```
|
|
|
|
## Data layout
|
|
|
|
```text
|
|
DATA_DIR/
|
|
├── routeros_backup_next.db
|
|
├── backups/
|
|
│ ├── exports/<device-id>/
|
|
│ └── binary/<device-id>/
|
|
├── secrets/
|
|
└── ssh/
|
|
```
|
|
|
|
RouterOS text exports are stored under `backups/exports`; binary RouterOS backups and SwOS `.swb` files are stored under `backups/binary`.
|
|
|
|
## Legacy Python/TypeScript import
|
|
|
|
The importer is explicit and never runs during normal startup. Stop the old application first and import into a **new** Rust destination.
|
|
|
|
```bash
|
|
./import-python.sh /srv/mikrotik-backup-old
|
|
```
|
|
|
|
Docker Compose example:
|
|
|
|
```bash
|
|
docker compose run --rm \
|
|
-v /srv/mikrotik-backup-old:/legacy:ro \
|
|
app import-python --source /legacy
|
|
```
|
|
|
|
The importer copies accounts, devices, settings, logs, backup metadata, and every referenced backup file. It validates existing backup checksums when present and refuses to publish an incomplete destination. See [docs/migration.md](docs/migration.md).
|
|
|
|
## RouterOS and SwOS
|
|
|
|
RouterOS uses SSH-based export/backup operations. SwOS uses its web interface and downloads `/backup.swb`, with Digest authentication first and Basic as fallback. Connection testing distinguishes general web reachability from backup-endpoint availability.
|
|
|
|
SwOS details and troubleshooting are in [docs/switchos.md](docs/switchos.md).
|
|
|
|
## Configuration comparison
|
|
|
|
`.rsc` files support:
|
|
|
|
- side-by-side and unified diff;
|
|
- changed-lines-only mode and search;
|
|
- paged browser rendering to limit DOM size;
|
|
- semantic RouterOS analysis that groups changes by configuration section and identifies added, removed, and modified commands/fields;
|
|
- masking of sensitive values in semantic summaries.
|
|
|
|
Binary backups are not diffed.
|
|
|
|
## Embedded web assets and caching
|
|
|
|
`build.rs` combines the UI sources listed in `web/assets.list`. Each compiled CSS/JavaScript bundle receives a content hash in its filename, for example:
|
|
|
|
```text
|
|
/assets/app.<hash>.js
|
|
/assets/app.<hash>.css
|
|
/assets/docs.<hash>.js
|
|
/assets/docs.<hash>.css
|
|
```
|
|
|
|
The HTML shell is generated with those exact filenames. Hashed assets use:
|
|
|
|
```text
|
|
Cache-Control: public, max-age=31536000, immutable
|
|
```
|
|
|
|
HTML and API responses remain non-cacheable by default. `/favicon.ico` intentionally returns `204 No Content`.
|
|
|
|
## API documentation
|
|
|
|
Interactive local documentation:
|
|
|
|
```text
|
|
/docs
|
|
```
|
|
|
|
OpenAPI JSON:
|
|
|
|
```text
|
|
/openapi.json
|
|
```
|
|
|
|
Swagger UI is embedded locally and does not require a CDN.
|
|
|
|
## Validation
|
|
|
|
Frontend unit tests:
|
|
|
|
```bash
|
|
node web/tests/core.test.cjs
|
|
```
|
|
|
|
JavaScript syntax:
|
|
|
|
```bash
|
|
node --check web/js/i18n.js
|
|
node --check web/js/core.js
|
|
node --check web/js/views.js
|
|
node --check web/js/app.js
|
|
```
|
|
|
|
Rust checks when a toolchain is available:
|
|
|
|
```bash
|
|
cargo fmt --check
|
|
cargo test --locked
|
|
cargo clippy --locked --all-targets -- -D warnings
|
|
```
|
|
|
|
The browser smoke tests under `web/tests/` require Playwright.
|
|
|
|
## Security and dependencies
|
|
|
|
The service uses request size/time limits, JWT validation, password hashing, SSH host-key verification, secret redaction, restricted filesystem permissions, and a non-root container runtime. Dependency audit notes and the local `libssh2-sys` patch provenance are summarized in [docs/security.md](docs/security.md).
|
|
|
|
Third-party license notices are in `docs/THIRD_PARTY_NOTICES.txt`.
|