RouteForge v0.5.4-beta
Modernes read-only Operator-Tool für Preflight Checks von ASN, Prefix, RPKI und Registry/IRR.
From 4a49a822a93eac5a10f7a6b68ef7cca5efa74a1a Mon Sep 17 00:00:00 2001
From: DeepZone
- Modernes read-only Operator-Tool für Preflight Checks von ASN, Prefix, RPKI und Registry/IRR. Modernes read-only Operator-Tool für Preflight Checks von ASN, Prefix, RPKI und Registry/IRR. {systemStatusError} RouteForge liefert nachvollziehbare Routing-Preflightchecks für technische Operator-Workflows. Version: v0.5.4-beta RouteForge liefert nachvollziehbare Routing-Preflightchecks für technische Operator-Workflows. Version: v0.5.5-beta
+
@@ -43,7 +43,7 @@ Routing changes often require fast but traceable checks across multiple external
## Current Alpha Status
-RouteForge is a **functional beta** release with production-like workflows for read-only validation and demo usage. Current release target: **v0.5.4-beta**.
+RouteForge is a **functional beta** release with production-like workflows for read-only validation and demo usage. Current release target: **v0.5.5-beta**.
## Quickstart with Docker Compose
@@ -215,9 +215,13 @@ In the standard setup, RouteForge does **not** require a hardcoded host IP in th
- SQLite/dev mode keeps lightweight startup initialization (`create_all`) for local/demo compatibility.
- Run migrations manually before production upgrades (`alembic upgrade head`).
+### SQLite permission note
+- For SQLite selfhosting setups, the backend entrypoint ensures `/app/data` is writable by the non-root runtime user `routeforge` at container startup.
+
### Operations docs
- Backup/Restore: `docs/operations/backup-restore.md`
- Reverse Proxy: `docs/operations/reverse-proxy.md`
+- Troubleshooting: `docs/operations/troubleshooting.md`
- Logging: `docs/operations/logging.md`
- Upgrades: `docs/operations/upgrades.md`
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7321812..aba5164 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,5 +1,19 @@
# Release Notes
+## v0.5.5-beta
+
+**SQLite Volume Permission Hotfix**
+
+### Highlights
+
+- Fixes SQLite readonly database errors after non-root container hardening.
+- Backend entrypoint now prepares `/app/data` permissions for the `routeforge` runtime user.
+- Runtime remains non-root.
+- Troubleshooting documentation added.
+
+---
+
+
## v0.5.4-beta
**Production Polish & Security Baseline**
diff --git a/backend/app/api/routes_health.py b/backend/app/api/routes_health.py
index 66fbd54..5d9281b 100644
--- a/backend/app/api/routes_health.py
+++ b/backend/app/api/routes_health.py
@@ -8,4 +8,4 @@
@router.get('/health')
def health() -> dict:
- return {"status": "ok", "version": "v0.5.4-beta", "database": get_database_status(engine).get("status", "unknown")}
+ return {"status": "ok", "version": "v0.5.5-beta", "database": get_database_status(engine).get("status", "unknown")}
diff --git a/backend/app/api/routes_system.py b/backend/app/api/routes_system.py
index de8514d..940de25 100644
--- a/backend/app/api/routes_system.py
+++ b/backend/app/api/routes_system.py
@@ -11,7 +11,7 @@
def system_info():
return {
'name': 'RouteForge',
- 'version': 'v0.5.4-beta',
+ 'version': 'v0.5.5-beta',
'demo_mode': settings.demo_mode,
'read_only': True,
'data_sources': ['RIPEstat', 'RIPEstat Whois/Registry'],
diff --git a/backend/app/core/system_status.py b/backend/app/core/system_status.py
index 38e3460..9abf794 100644
--- a/backend/app/core/system_status.py
+++ b/backend/app/core/system_status.py
@@ -113,7 +113,7 @@ def build_system_status(engine: Engine | None) -> dict:
return {
"status": "ok",
"name": settings.app_name,
- "version": "v0.5.4-beta",
+ "version": "v0.5.5-beta",
"read_only": True,
"mode": "demo" if settings.demo_mode else "live",
"demo_mode": settings.demo_mode,
diff --git a/backend/app/main.py b/backend/app/main.py
index 46c4e77..22177ff 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -15,7 +15,7 @@
logging.basicConfig(level=getattr(logging, settings.log_level.upper(), logging.INFO))
logger = logging.getLogger("routeforge")
-app = FastAPI(title="RouteForge", version="0.5.4")
+app = FastAPI(title="RouteForge", version="0.5.5")
app.add_middleware(
CORSMiddleware,
diff --git a/backend/pyproject.toml b/backend/pyproject.toml
index b6d164b..38206f7 100644
--- a/backend/pyproject.toml
+++ b/backend/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "routeforge-backend"
-version = "0.5.4"
+version = "0.5.5"
description = "RouteForge backend"
license = "AGPL-3.0-or-later"
requires-python = ">=3.12"
diff --git a/backend/tests/test_api_smoke.py b/backend/tests/test_api_smoke.py
index 11c623b..eeb28ad 100644
--- a/backend/tests/test_api_smoke.py
+++ b/backend/tests/test_api_smoke.py
@@ -157,7 +157,7 @@ def test_system_status_endpoint() -> None:
response = client.get('/api/system/status')
assert response.status_code == 200
payload = response.json()
- assert payload.get('version') == 'v0.5.4-beta'
+ assert payload.get('version') == 'v0.5.5-beta'
assert payload.get('read_only') is True
assert payload.get('database', {}).get('status')
assert payload.get('ripestat', {}).get('cache_ttl_seconds') is not None
diff --git a/docs/operations/troubleshooting.md b/docs/operations/troubleshooting.md
new file mode 100644
index 0000000..4530d7c
--- /dev/null
+++ b/docs/operations/troubleshooting.md
@@ -0,0 +1,20 @@
+# Troubleshooting
+
+## sqlite3.OperationalError: attempt to write a readonly database
+
+### Ursache
+
+Bei SQLite-Deployments liegt die Datenbank häufig unter `/app/data/routeforge.db`.
+Wenn das Docker-Volume auf `/app/data` root-owned ist, kann der non-root Runtime-User `routeforge` nicht in die SQLite-Datei schreiben. Dadurch schlagen Check-Speicherungen mit `sqlite3.OperationalError: attempt to write a readonly database` fehl.
+
+### Fix ab v0.5.5-beta
+
+Ab `v0.5.5-beta` setzt der Backend-Entrypoint beim Containerstart die Ownership für `/app/data` auf `routeforge:routeforge` und startet danach den Prozess weiterhin als non-root User `routeforge`.
+
+### Workaround für ältere Versionen
+
+```bash
+docker compose down
+docker compose run --rm --user root backend sh -c "mkdir -p /app/data && chown -R routeforge:routeforge /app/data && chmod -R u+rwX /app/data"
+docker compose up -d --build
+```
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 8080088..4036f3b 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "routeforge-frontend",
- "version": "0.5.4",
+ "version": "0.5.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "routeforge-frontend",
- "version": "0.5.4",
+ "version": "0.5.5",
"license": "AGPL-3.0-or-later",
"dependencies": {
"react": "^18.3.1",
diff --git a/frontend/package.json b/frontend/package.json
index 7a4c616..592c2e8 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "routeforge-frontend",
- "version": "0.5.4",
+ "version": "0.5.5",
"private": true,
"license": "AGPL-3.0-or-later",
"type": "module",
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 5375fff..6a21d62 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -22,14 +22,14 @@ export default function App() {
getSystemStatus().then((payload) => { setSystemStatus(payload); setSystemStatusError('') }).catch(() => setSystemStatusError('System status could not be loaded.'))
}, [])
- const systemLine = useMemo(() => system ? `${system.name} ${system.version} · mode=${system.demo_mode ? 'DEMO' : 'LIVE'} · read_only=${String(system.read_only)}` : 'RouteForge v0.5.4-beta · read-only preflight checks', [system])
+ const systemLine = useMemo(() => system ? `${system.name} ${system.version} · mode=${system.demo_mode ? 'DEMO' : 'LIVE'} · read_only=${String(system.read_only)}` : 'RouteForge v0.5.5-beta · read-only preflight checks', [system])
const title = { dashboard: 'Dashboard', asn: 'ASN Check', prefix: 'Prefix Check', preflight: 'Preflight Check', reports: 'Reports', system: 'System Status', about: 'About RouteForge' }[active]
const proxyStatus = systemStatusError ? 'ERROR' : 'OK'
const migrationStatus = systemStatus?.database?.migration_status || 'unknown'
return
RouteForge v0.5.4-beta
RouteForge v0.5.5-beta
System Health
{systemStatusError ? Features
{JSON.stringify(systemStatus.features, null, 2)}