backuplint 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backuplint-1.0.0/Dockerfile.controller +64 -0
- backuplint-1.0.0/LICENSE +21 -0
- backuplint-1.0.0/MANIFEST.in +13 -0
- backuplint-1.0.0/PKG-INFO +318 -0
- backuplint-1.0.0/README.md +275 -0
- backuplint-1.0.0/SECURITY.md +28 -0
- backuplint-1.0.0/docker/agent-entrypoint.sh +66 -0
- backuplint-1.0.0/docker/agent-preflight.py +70 -0
- backuplint-1.0.0/docker/controller-entrypoint.sh +42 -0
- backuplint-1.0.0/docker/controller-healthcheck.py +60 -0
- backuplint-1.0.0/docker/controller-preflight.py +75 -0
- backuplint-1.0.0/pyproject.toml +78 -0
- backuplint-1.0.0/setup.cfg +4 -0
- backuplint-1.0.0/src/backuplint/__init__.py +3 -0
- backuplint-1.0.0/src/backuplint/__main__.py +6 -0
- backuplint-1.0.0/src/backuplint/audit.py +293 -0
- backuplint-1.0.0/src/backuplint/classify.py +109 -0
- backuplint-1.0.0/src/backuplint/cli.py +1444 -0
- backuplint-1.0.0/src/backuplint/compose.py +215 -0
- backuplint-1.0.0/src/backuplint/config.py +531 -0
- backuplint-1.0.0/src/backuplint/coverage.py +386 -0
- backuplint-1.0.0/src/backuplint/database.py +39 -0
- backuplint-1.0.0/src/backuplint/engine/__init__.py +22 -0
- backuplint-1.0.0/src/backuplint/engine/base.py +43 -0
- backuplint-1.0.0/src/backuplint/engine/factory.py +56 -0
- backuplint-1.0.0/src/backuplint/engine/restic_engine.py +139 -0
- backuplint-1.0.0/src/backuplint/engine/types.py +43 -0
- backuplint-1.0.0/src/backuplint/errors.py +11 -0
- backuplint-1.0.0/src/backuplint/events.py +253 -0
- backuplint-1.0.0/src/backuplint/fleet/__init__.py +19 -0
- backuplint-1.0.0/src/backuplint/fleet/agent.py +515 -0
- backuplint-1.0.0/src/backuplint/fleet/capabilities.py +266 -0
- backuplint-1.0.0/src/backuplint/fleet/certs.py +346 -0
- backuplint-1.0.0/src/backuplint/fleet/compat.py +104 -0
- backuplint-1.0.0/src/backuplint/fleet/controller.py +784 -0
- backuplint-1.0.0/src/backuplint/fleet/controller_store.py +1476 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/__init__.py +14 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/assurance.py +478 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/auth.py +215 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/config.py +31 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/format.py +173 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/http.py +562 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/query.py +1288 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/static/logo-mark-64.png +0 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/static/logo-mark-white-64.png +0 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/static/logo-mark.svg +4 -0
- backuplint-1.0.0/src/backuplint/fleet/dashboard/ui.py +1583 -0
- backuplint-1.0.0/src/backuplint/fleet/delivery.py +260 -0
- backuplint-1.0.0/src/backuplint/fleet/policy_apply.py +346 -0
- backuplint-1.0.0/src/backuplint/fleet/policy_store.py +1199 -0
- backuplint-1.0.0/src/backuplint/fleet/presence.py +44 -0
- backuplint-1.0.0/src/backuplint/fleet/protocol.py +178 -0
- backuplint-1.0.0/src/backuplint/fleet/provisioning.py +114 -0
- backuplint-1.0.0/src/backuplint/fleet/queue_policy.py +319 -0
- backuplint-1.0.0/src/backuplint/fleet/telemetry.py +264 -0
- backuplint-1.0.0/src/backuplint/fleet_config.py +44 -0
- backuplint-1.0.0/src/backuplint/install/__init__.py +50 -0
- backuplint-1.0.0/src/backuplint/install/deployment.py +29 -0
- backuplint-1.0.0/src/backuplint/install/detect.py +162 -0
- backuplint-1.0.0/src/backuplint/install/diagnostics.py +132 -0
- backuplint-1.0.0/src/backuplint/install/distro.py +85 -0
- backuplint-1.0.0/src/backuplint/install/executor.py +580 -0
- backuplint-1.0.0/src/backuplint/install/features.py +231 -0
- backuplint-1.0.0/src/backuplint/install/layout.py +296 -0
- backuplint-1.0.0/src/backuplint/install/manifest.py +137 -0
- backuplint-1.0.0/src/backuplint/install/packages.py +165 -0
- backuplint-1.0.0/src/backuplint/install/plan.py +226 -0
- backuplint-1.0.0/src/backuplint/install/profile.py +275 -0
- backuplint-1.0.0/src/backuplint/install/roles.py +99 -0
- backuplint-1.0.0/src/backuplint/install/support.py +86 -0
- backuplint-1.0.0/src/backuplint/install/systemd_units.py +148 -0
- backuplint-1.0.0/src/backuplint/install/wizard.py +143 -0
- backuplint-1.0.0/src/backuplint/integrity_state.py +206 -0
- backuplint-1.0.0/src/backuplint/models.py +45 -0
- backuplint-1.0.0/src/backuplint/paths.py +74 -0
- backuplint-1.0.0/src/backuplint/policy/__init__.py +27 -0
- backuplint-1.0.0/src/backuplint/policy/cli.py +400 -0
- backuplint-1.0.0/src/backuplint/policy/errors.py +7 -0
- backuplint-1.0.0/src/backuplint/policy/gitops.py +89 -0
- backuplint-1.0.0/src/backuplint/policy/resolve.py +79 -0
- backuplint-1.0.0/src/backuplint/policy/rollout.py +87 -0
- backuplint-1.0.0/src/backuplint/policy/schema.py +213 -0
- backuplint-1.0.0/src/backuplint/policy/settings.py +220 -0
- backuplint-1.0.0/src/backuplint/process.py +44 -0
- backuplint-1.0.0/src/backuplint/reporting.py +387 -0
- backuplint-1.0.0/src/backuplint/restic.py +494 -0
- backuplint-1.0.0/src/backuplint/restic_errors.py +175 -0
- backuplint-1.0.0/src/backuplint/restore_dest.py +256 -0
- backuplint-1.0.0/src/backuplint/restore_verify.py +416 -0
- backuplint-1.0.0/src/backuplint/schedule_config.py +181 -0
- backuplint-1.0.0/src/backuplint/schedule_lock.py +96 -0
- backuplint-1.0.0/src/backuplint/schedule_store.py +416 -0
- backuplint-1.0.0/src/backuplint/scheduler.py +591 -0
- backuplint-1.0.0/src/backuplint/secrets/__init__.py +65 -0
- backuplint-1.0.0/src/backuplint/secrets/errors.py +35 -0
- backuplint-1.0.0/src/backuplint/secrets/file_checks.py +193 -0
- backuplint-1.0.0/src/backuplint/secrets/ref.py +190 -0
- backuplint-1.0.0/src/backuplint/secrets/resolve.py +146 -0
- backuplint-1.0.0/src/backuplint/secrets/value.py +53 -0
- backuplint-1.0.0/src/backuplint/siem/__init__.py +35 -0
- backuplint-1.0.0/src/backuplint/siem/config.py +375 -0
- backuplint-1.0.0/src/backuplint/siem/event.py +571 -0
- backuplint-1.0.0/src/backuplint/siem/exporter.py +224 -0
- backuplint-1.0.0/src/backuplint/siem/queue.py +602 -0
- backuplint-1.0.0/src/backuplint/siem/runtime.py +241 -0
- backuplint-1.0.0/src/backuplint/siem/telemetry.py +129 -0
- backuplint-1.0.0/src/backuplint/siem/transport/__init__.py +6 -0
- backuplint-1.0.0/src/backuplint/siem/transport/base.py +78 -0
- backuplint-1.0.0/src/backuplint/siem/transport/https_json.py +186 -0
- backuplint-1.0.0/src/backuplint/sqlite_backup.py +530 -0
- backuplint-1.0.0/src/backuplint/sqlite_util.py +51 -0
- backuplint-1.0.0/src/backuplint/timeutil.py +100 -0
- backuplint-1.0.0/src/backuplint/volumes.py +43 -0
- backuplint-1.0.0/src/backuplint.egg-info/PKG-INFO +318 -0
- backuplint-1.0.0/src/backuplint.egg-info/SOURCES.txt +117 -0
- backuplint-1.0.0/src/backuplint.egg-info/dependency_links.txt +1 -0
- backuplint-1.0.0/src/backuplint.egg-info/entry_points.txt +2 -0
- backuplint-1.0.0/src/backuplint.egg-info/requires.txt +13 -0
- backuplint-1.0.0/src/backuplint.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# BackupLint fleet controller image (no Docker socket, no Restic, no Compose tooling).
|
|
2
|
+
# Build from the repository root:
|
|
3
|
+
# docker build -f Dockerfile.controller -t backuplint-controller:local .
|
|
4
|
+
#
|
|
5
|
+
# Durable CA/TLS/SQLite state must be mounted at /state (see docs/controller-container.md).
|
|
6
|
+
|
|
7
|
+
# Pin the Debian bookworm slim digest so release images are auditable.
|
|
8
|
+
# python:3.12-slim-bookworm @ 2026-09-19 (includes libpcre2 10.42-1+deb12u1).
|
|
9
|
+
FROM python:3.12-slim-bookworm@sha256:392307d22300de8b5986851a12d9176dfc0fc073e65bf6523ebd7dcbeb23564e
|
|
10
|
+
|
|
11
|
+
ARG BACKUPLINT_UID=10001
|
|
12
|
+
ARG BACKUPLINT_GID=10001
|
|
13
|
+
ARG BACKUPLINT_VERSION=1.0.0
|
|
14
|
+
ARG BACKUPLINT_REVISION=unknown
|
|
15
|
+
|
|
16
|
+
LABEL org.opencontainers.image.title="BackupLint Controller" \
|
|
17
|
+
org.opencontainers.image.description="HTTPS fleet controller (no Docker socket, no Restic)" \
|
|
18
|
+
org.opencontainers.image.source="https://github.com/Netryon/BackupLint" \
|
|
19
|
+
org.opencontainers.image.licenses="MIT" \
|
|
20
|
+
org.opencontainers.image.version="${BACKUPLINT_VERSION}" \
|
|
21
|
+
org.opencontainers.image.revision="${BACKUPLINT_REVISION}" \
|
|
22
|
+
org.opencontainers.image.vendor="BackupLint"
|
|
23
|
+
|
|
24
|
+
RUN apt-get update \
|
|
25
|
+
&& apt-get install -y --no-install-recommends openssl ca-certificates \
|
|
26
|
+
&& rm -rf /var/lib/apt/lists/* \
|
|
27
|
+
&& groupadd --system --gid "${BACKUPLINT_GID}" backuplint \
|
|
28
|
+
&& useradd --system --uid "${BACKUPLINT_UID}" --gid backuplint \
|
|
29
|
+
--home-dir /state --shell /usr/sbin/nologin backuplint
|
|
30
|
+
|
|
31
|
+
WORKDIR /app
|
|
32
|
+
|
|
33
|
+
# Copy metadata first for better layer caching, then application sources.
|
|
34
|
+
COPY pyproject.toml README.md LICENSE ./
|
|
35
|
+
COPY src ./src
|
|
36
|
+
COPY docker/controller-entrypoint.sh \
|
|
37
|
+
docker/controller-healthcheck.py \
|
|
38
|
+
docker/controller-preflight.py \
|
|
39
|
+
./docker/
|
|
40
|
+
|
|
41
|
+
RUN pip install --no-cache-dir --upgrade pip \
|
|
42
|
+
&& pip install --no-cache-dir . \
|
|
43
|
+
&& chmod 755 \
|
|
44
|
+
/app/docker/controller-entrypoint.sh \
|
|
45
|
+
/app/docker/controller-healthcheck.py \
|
|
46
|
+
/app/docker/controller-preflight.py \
|
|
47
|
+
&& mkdir -p /state \
|
|
48
|
+
&& chown backuplint:backuplint /state \
|
|
49
|
+
&& backuplint --version
|
|
50
|
+
|
|
51
|
+
ENV BACKUPLINT_CONTROLLER_DATA_DIR=/state \
|
|
52
|
+
BACKUPLINT_CONTROLLER_LISTEN=0.0.0.0:8443 \
|
|
53
|
+
BACKUPLINT_CONTROLLER_HOSTNAME=localhost \
|
|
54
|
+
HOME=/state \
|
|
55
|
+
TMPDIR=/tmp \
|
|
56
|
+
PYTHONUNBUFFERED=1
|
|
57
|
+
|
|
58
|
+
USER backuplint:backuplint
|
|
59
|
+
EXPOSE 8443
|
|
60
|
+
|
|
61
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
62
|
+
CMD ["python", "/app/docker/controller-healthcheck.py"]
|
|
63
|
+
|
|
64
|
+
ENTRYPOINT ["/app/docker/controller-entrypoint.sh"]
|
backuplint-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 BackupLint contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Explicit sdist membership for release hygiene.
|
|
2
|
+
include LICENSE README.md pyproject.toml SECURITY.md
|
|
3
|
+
graft src
|
|
4
|
+
graft docker
|
|
5
|
+
include Dockerfile.controller
|
|
6
|
+
global-exclude *.py[cod] __pycache__ .DS_Store
|
|
7
|
+
prune docs
|
|
8
|
+
prune tests
|
|
9
|
+
prune test-lab
|
|
10
|
+
prune scripts
|
|
11
|
+
prune deploy
|
|
12
|
+
prune .github
|
|
13
|
+
exclude AGENT_*.md
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: backuplint
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Check whether Docker Compose persistent data is covered by backup configuration
|
|
5
|
+
Author: BackupLint contributors
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 BackupLint contributors
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Requires-Python: >=3.11
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: typer>=0.12
|
|
32
|
+
Requires-Dist: PyYAML>=6.0
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
35
|
+
Requires-Dist: hypothesis>=6.100; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
37
|
+
Requires-Dist: bandit>=1.7; extra == "dev"
|
|
38
|
+
Requires-Dist: pip-audit>=2.7; extra == "dev"
|
|
39
|
+
Provides-Extra: browser
|
|
40
|
+
Requires-Dist: playwright>=1.40; extra == "browser"
|
|
41
|
+
Requires-Dist: pytest-playwright>=0.5; extra == "browser"
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
<p align="center">
|
|
45
|
+
<img src="docs/images/logo-mark-blue.svg" width="72" height="72" alt="BackupLint logo">
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<h1 align="center">BackupLint</h1>
|
|
49
|
+
|
|
50
|
+
<p align="center"><strong>Find Docker data your backups missed before you discover it during a restore.</strong></p>
|
|
51
|
+
|
|
52
|
+
<p align="center"><em>Don’t just assume your backups work. Prove they work.</em></p>
|
|
53
|
+
|
|
54
|
+
BackupLint is an independent **backup-assurance** layer for Docker Compose stacks. It compares Compose mounts with your backup configuration and reports **PASS**, **WARN**, **FAIL**, or operational **ERROR**.
|
|
55
|
+
|
|
56
|
+
It is **not** a backup engine. It does not replace Restic, Borg, Kopia, or your backup jobs. For v1, **Restic is the only supported engine** when engine-backed checks are enabled. It does not SSH into hosts, delete data, or restore over live application files.
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
coverage ≠ integrity ≠ restore verification ≠ disaster recovery
|
|
60
|
+
presence (online / stale / offline) ≠ audit health
|
|
61
|
+
coverage FAIL ≠ repository-unavailable ERROR
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Choose your deployment
|
|
65
|
+
|
|
66
|
+
BackupLint is **one package**. Pick a role:
|
|
67
|
+
|
|
68
|
+
| Role | Use it when | What it does |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| **Standalone** | One machine, local backup assurance only | Audits this machine. No fleet controller/dashboard and does not receive other agents. |
|
|
71
|
+
| **Agent** | This machine reports to an existing BackupLint controller | Audits locally and reports over mTLS. No controller/dashboard on this machine. |
|
|
72
|
+
| **Controller** | Dedicated central management node | Receives agent reports, hosts the optional dashboard, central policy, fleet state, and optional SIEM export. |
|
|
73
|
+
| **All-in-one** | The main server should audit itself **and** manage other agents | Runs local checks **and** the fleet controller/dashboard on the same machine. |
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
One server only → Standalone
|
|
77
|
+
Dedicated management server → Controller
|
|
78
|
+
Additional monitored servers → Agent
|
|
79
|
+
Main server + fleet management on one machine → All-in-one
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Standalone vs all-in-one:** standalone never runs a controller. All-in-one does: it is a controller that also audits the host it runs on. Use standalone unless you need a fleet.
|
|
83
|
+
|
|
84
|
+
Details: [docs/installation.md](docs/installation.md), [docs/installation-profiles.md](docs/installation-profiles.md).
|
|
85
|
+
|
|
86
|
+
## 60-second local check (standalone)
|
|
87
|
+
|
|
88
|
+
1. Install the release wheel (see [Native install](#native--bare-metal-install)).
|
|
89
|
+
2. Create `backuplint.yml` next to your Compose file:
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
backup_paths:
|
|
93
|
+
- /srv/docker
|
|
94
|
+
- /srv/app-config
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
3. Scan:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
backuplint scan compose.yml
|
|
101
|
+
backuplint scan compose.yml --config backuplint.yml --json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
BackupLint Audit
|
|
106
|
+
|
|
107
|
+
✓ sonarr /srv/docker/sonarr protected
|
|
108
|
+
✓ radarr /srv/docker/radarr protected
|
|
109
|
+
✗ vaultwarden /srv/vaultwarden not protected
|
|
110
|
+
|
|
111
|
+
Result: FAIL
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Want fleet management?
|
|
115
|
+
|
|
116
|
+
Use **controller** on a management node (or **all-in-one** on the main server), then **agent** on every other host. See [Choose your deployment](#choose-your-deployment), [docs/fleet.md](docs/fleet.md), and [docs/dashboard.md](docs/dashboard.md).
|
|
117
|
+
|
|
118
|
+
## What BackupLint needs from you
|
|
119
|
+
|
|
120
|
+
BackupLint does **not** require one broad privileged “admin account”. You supply only what each role needs.
|
|
121
|
+
|
|
122
|
+
### Local audit (standalone, agent, or all-in-one)
|
|
123
|
+
|
|
124
|
+
- Compose file path
|
|
125
|
+
- BackupLint config (`backuplint.yml`)
|
|
126
|
+
- Expected backup paths
|
|
127
|
+
- Docker Engine + Compose plugin access when Compose discovery is used
|
|
128
|
+
- Restic repository location for Restic-backed checks
|
|
129
|
+
- Restic password via `password_file`, `RESTIC_PASSWORD`, or `RESTIC_PASSWORD_FILE` (`password_file` always wins). Passwords are never printed.
|
|
130
|
+
|
|
131
|
+
### Controller
|
|
132
|
+
|
|
133
|
+
- Hostname/DNS name agents will use (certificate SAN)
|
|
134
|
+
- Listener address/port (typically `8443`)
|
|
135
|
+
- Controller state directory
|
|
136
|
+
- Dashboard operator password if the dashboard is enabled
|
|
137
|
+
- Optional SIEM endpoint/config
|
|
138
|
+
|
|
139
|
+
### Agent
|
|
140
|
+
|
|
141
|
+
- Controller URL
|
|
142
|
+
- Unique agent ID from `enroll-token`
|
|
143
|
+
- One-time enrollment token
|
|
144
|
+
- Controller CA certificate
|
|
145
|
+
- Local Compose/config/Restic access required for the checks that agent will run
|
|
146
|
+
|
|
147
|
+
Enrollment:
|
|
148
|
+
|
|
149
|
+
- the **agent generates its private key locally**
|
|
150
|
+
- the controller signs a **CSR**
|
|
151
|
+
- the **agent private key is not copied to the controller**
|
|
152
|
+
- the enrollment token is **one-use**
|
|
153
|
+
- after enrollment, traffic is **mTLS**
|
|
154
|
+
|
|
155
|
+
Revoke with `backuplint controller revoke <agent_id>`.
|
|
156
|
+
|
|
157
|
+
## Native / bare-metal install
|
|
158
|
+
|
|
159
|
+
Python **3.11+** (`venv`). Rocky/Alma 9: use `python3.11`. Docker Engine + Compose plugin for `scan`. Restic on `PATH` only if you enable engine-backed checks.
|
|
160
|
+
|
|
161
|
+
Download `backuplint-1.0.0-py3-none-any.whl` from the [v1.0.0 GitHub Release](https://github.com/Netryon/BackupLint/releases/tag/v1.0.0), then:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
python3 -m venv .venv
|
|
165
|
+
source .venv/bin/activate
|
|
166
|
+
pip install backuplint-1.0.0-py3-none-any.whl
|
|
167
|
+
backuplint --version
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Interactive native installer (directories, optional packages, systemd):
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
sudo backuplint install --interactive --yes
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Unattended profile:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
sudo backuplint install --profile profile.yaml --non-interactive --yes
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Roles, layout, CSR enrollment, upgrades, uninstall: [docs/installation.md](docs/installation.md), [docs/native-installer.md](docs/native-installer.md).
|
|
183
|
+
|
|
184
|
+
## Docker install
|
|
185
|
+
|
|
186
|
+
Official GHCR images are published for **linux/amd64**. Raspberry Pi 4 remains a native-install current-candidate platform.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
docker pull ghcr.io/netryon/backuplint-controller:1.0.0
|
|
190
|
+
docker pull ghcr.io/netryon/backuplint-agent:1.0.0
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The same images are also tagged `v1.0.0` and `latest` (stable 1.0.0 convenience tag). Prefer digest pinning in production; immutable digests are listed on the [v1.0.0 GitHub Release](https://github.com/Netryon/BackupLint/releases/tag/v1.0.0).
|
|
194
|
+
|
|
195
|
+
Controller and agent images run as **uid 10001**. Privileged mode is not required. A Docker socket is **not** required for heartbeat, enrollment, or policy. Compose discovery **inside** an agent container needs intentional host/Docker access (not the default).
|
|
196
|
+
|
|
197
|
+
Local source builds remain available as an advanced option:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
docker build -f Dockerfile.controller --build-arg BACKUPLINT_VERSION=1.0.0 -t backuplint-controller:1.0.0 .
|
|
201
|
+
docker build -f Dockerfile.agent --build-arg BACKUPLINT_VERSION=1.0.0 -t backuplint-agent:1.0.0 .
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
[docs/docker.md](docs/docker.md)
|
|
205
|
+
|
|
206
|
+
## Dashboard
|
|
207
|
+
|
|
208
|
+
Optional **read-only** UI on the controller (`https://…:8443/dashboard/`). Presence and audit health stay separate. The dashboard does not write policy.
|
|
209
|
+
|
|
210
|
+
v1 authentication: a **shared operator password**, stored as a **scrypt** hash. There is **no multi-user RBAC** and **no SSO** in v1.
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
backuplint controller dashboard-password --data-dir ./bl-controller
|
|
214
|
+
backuplint controller run --data-dir ./bl-controller --listen 127.0.0.1:8443 --dashboard
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
[docs/dashboard.md](docs/dashboard.md)
|
|
218
|
+
|
|
219
|
+
## Screenshots
|
|
220
|
+
|
|
221
|
+
Public-safe demo fleet (synthetic labels).
|
|
222
|
+
|
|
223
|
+

|
|
224
|
+
|
|
225
|
+

|
|
226
|
+
|
|
227
|
+

|
|
228
|
+
|
|
229
|
+

|
|
230
|
+
|
|
231
|
+

|
|
232
|
+
|
|
233
|
+

|
|
234
|
+
|
|
235
|
+

|
|
236
|
+
|
|
237
|
+

|
|
238
|
+
|
|
239
|
+
## Supported platforms (v1.0.0)
|
|
240
|
+
|
|
241
|
+
| Platform | Arch | Current-candidate |
|
|
242
|
+
| --- | --- | --- |
|
|
243
|
+
| Ubuntu | x86_64 | tested |
|
|
244
|
+
| Debian | x86_64 | tested |
|
|
245
|
+
| Rocky Linux 9 | x86_64 | tested |
|
|
246
|
+
| Fedora 43 | x86_64 | tested |
|
|
247
|
+
| Raspberry Pi 4 / Raspberry Pi OS | ARM64 | tested |
|
|
248
|
+
| Native controller + agent | — | tested |
|
|
249
|
+
| Container controller + agent, including mixed topologies | — | tested |
|
|
250
|
+
|
|
251
|
+
Raspberry Pi **3** is not a current-candidate proof. WSL2 is **unsupported**.
|
|
252
|
+
|
|
253
|
+
Controller sizing is evidence-backed **through 500 agents** (about **6–8 MB/agent/day** management-plane traffic at the tested 30s cadence). That **excludes Restic backup payload**. **Do not treat >500 agents as certified capacity.**
|
|
254
|
+
|
|
255
|
+
[docs/support-matrix.md](docs/support-matrix.md) · [docs/validation.md](docs/validation.md) · [docs/architecture.md](docs/architecture.md)
|
|
256
|
+
|
|
257
|
+
## Security
|
|
258
|
+
|
|
259
|
+
Read-only diagnostics. No deletion of user data, no modification of backups, no secret printing from Compose, `.env`, or backup tools.
|
|
260
|
+
|
|
261
|
+
Container images: digest-pinned `python:3.12-slim-bookworm`, Trivy-reviewed, residual CVEs remain. **Not a “zero CVE” claim.** Agent: non-root uid 10001, unprivileged, no baked secrets.
|
|
262
|
+
|
|
263
|
+
[docs/security.md](docs/security.md) · [SECURITY.md](SECURITY.md)
|
|
264
|
+
|
|
265
|
+
## Known limitations
|
|
266
|
+
|
|
267
|
+
- Named volume coverage depends on local `docker volume inspect`; missing volumes are **WARN**, not FAIL
|
|
268
|
+
- Cache/temporary mounts are skipped by path heuristics
|
|
269
|
+
- Restic coverage uses snapshot path roots, not file-level contents
|
|
270
|
+
- Database image warnings are advisory; filesystem coverage is not a consistent DB backup
|
|
271
|
+
- Isolated restore verification is not a disaster-recovery drill
|
|
272
|
+
- Unit tests alone are not production readiness
|
|
273
|
+
|
|
274
|
+
## Documentation
|
|
275
|
+
|
|
276
|
+
| Topic | Doc |
|
|
277
|
+
| --- | --- |
|
|
278
|
+
| Native install | [docs/installation.md](docs/installation.md) |
|
|
279
|
+
| Native installer / systemd | [docs/native-installer.md](docs/native-installer.md) |
|
|
280
|
+
| Docker | [docs/docker.md](docs/docker.md) |
|
|
281
|
+
| Fleet / enrollment | [docs/fleet.md](docs/fleet.md) |
|
|
282
|
+
| Dashboard | [docs/dashboard.md](docs/dashboard.md) |
|
|
283
|
+
| Troubleshooting | [docs/troubleshooting.md](docs/troubleshooting.md) |
|
|
284
|
+
| Validation evidence | [docs/validation.md](docs/validation.md) |
|
|
285
|
+
| Release notes | [docs/release-notes-v1.0.0.md](docs/release-notes-v1.0.0.md) |
|
|
286
|
+
|
|
287
|
+
## Feedback, bugs, and questions
|
|
288
|
+
|
|
289
|
+
Feedback is welcome. Please use the channel that matches what you need:
|
|
290
|
+
|
|
291
|
+
- **Bug report:** [open a bug report](https://github.com/Netryon/BackupLint/issues/new?template=bug_report.yml)
|
|
292
|
+
- **Feature request / improvement idea:** [request a feature](https://github.com/Netryon/BackupLint/issues/new?template=feature_request.yml)
|
|
293
|
+
- **Setup / usage question:** [ask a question](https://github.com/Netryon/BackupLint/issues/new?template=question.yml)
|
|
294
|
+
- **Security vulnerability:** use a [private GitHub Security Advisory](https://github.com/Netryon/BackupLint/security/advisories/new) — do **not** post secrets or vulnerability details in a public issue.
|
|
295
|
+
|
|
296
|
+
Before posting logs or configuration, remove passwords, tokens, private keys, internal hostnames/IPs, repository credentials, and personal data.
|
|
297
|
+
|
|
298
|
+
## Development install
|
|
299
|
+
|
|
300
|
+
For contributors only (editable tree + test extras):
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
git clone https://github.com/Netryon/BackupLint.git
|
|
304
|
+
cd BackupLint
|
|
305
|
+
python3 -m venv .venv
|
|
306
|
+
source .venv/bin/activate
|
|
307
|
+
pip install -e ".[dev]"
|
|
308
|
+
ruff check src tests
|
|
309
|
+
pytest -q tests/unit
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
313
|
+
|
|
314
|
+
## License
|
|
315
|
+
|
|
316
|
+
[MIT](LICENSE) © 2026 BackupLint contributors.
|
|
317
|
+
|
|
318
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) · [SECURITY.md](SECURITY.md)
|