v0.35.1: performance, AGPL licensing and documentation overhaul

- Web Server reads static files inline; proxy middleware chain flattened
- About window with license summary and project links; AGPL-3.0-or-later
- Rewritten documentation: feature list, screenshots, performance guide
- Fix false spikes in per-Vhost request-rate charts
This commit is contained in:
gru committed 2026-11-05 18:29:56 +01:00
1 parent d3b492874b
commit eba9f89283
135 files changed
+1425 -1064

No files matched your search

+4 -10
View File
@@ -211,9 +211,7 @@ def admin_health_endpoint(record: dict) -> tuple[str, bool, str]:
if isinstance(values, list):
allowed_hosts = [str(value).strip() for value in values if str(value).strip()]
except (OSError, sqlite3.Error, ValueError, TypeError, json.JSONDecodeError):
# Old releases and damaged/uninitialized databases used the startup HTTP
# listener. The real startup diagnostics remain authoritative if this
# compatibility read cannot resolve persisted settings.
# Fall back to the startup listener for old or uninitialized databases.
pass
host, port = (raw[1:].split(']:') if raw.startswith('[') else raw.rsplit(':', 1))
@@ -234,9 +232,7 @@ def healthy(record: dict, version: str, attempts: int = 30) -> bool:
host, port = (raw[1:].split(']:') if raw.startswith('[') else raw.rsplit(':', 1))
for _ in range(attempts):
if tls:
# Local deployment health is process identity/liveness, not PKI validation.
# The configured admin certificate may intentionally be self-signed or for
# a DNS name while we connect to the local socket.
# Local liveness probe only; the admin certificate may be self-signed.
conn = http.client.HTTPSConnection(host, int(port), timeout=2, context=ssl._create_unverified_context())
else:
conn = http.client.HTTPConnection(host, int(port), timeout=2)
@@ -362,14 +358,12 @@ def update(record: dict, binary: Path, sha: str, start: bool, refresh_geoip: boo
# Repair missing or stale installer-owned shell setup on upgrades.
install_shell_path(prefix)
check_shell_path(prefix)
# Repair stale root:root/0700 metadata before staging/network work and before
# stopping the currently healthy service.
# Repair stale ownership before stopping the running service.
ensure_service_data_access(data, account)
release, version = stage(binary, prefix, record['user'], sha)
geoip_names: list[str] = []
if refresh_geoip:
# Keep the same lock for checksum/download staging and publication. The
# runtime worker uses this file too, so manual upgrades cannot race it.
# Shared lock with the runtime worker prevents concurrent upgrades.
geoip_lock_fd = acquire_geoip_update_lock(data, account.pw_uid, account.pw_gid)
geoip_stage, geoip_names = prepare_geoip_update(data, prefix)
active = subprocess.run(['systemctl', 'is-active', '--quiet', SERVICE], check=False, stdout=subprocess.DEVNULL).returncode == 0
+2 -7
View File
@@ -13,7 +13,7 @@ from scripts.version import project_version
MANAGED = ["build.rs", "langs", "deploy", "debian", "grafana", "make_zip.py", "src", "tests", "scripts", "tools", "integrations", "nagios", "docker-agent", "migrations", "examples", "docs", ".github", ".cargo",
"Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "dev.sh", "upgrade.sh", "install.sh", "update.sh",
"README.md", "ROADMAP.md", "CHANGELOG.md", "AGENTS.md", "SHA256SUMS",
"README.md", "LICENSE", "CHANGELOG.md", "AGENTS.md", "SHA256SUMS",
".env.example", ".gitignore"]
@@ -72,12 +72,7 @@ def upgrade(source: Path, target: Path, *, stopped: bool, data_dir: Path | None
elif new.is_file():
installed.append(name)
shutil.copy2(new, old)
# Old renewal observations were diagnostic scheduler state only;
# certificates, accounts and renewal profiles live elsewhere. 0.19.1
# has no runtime JSON importer. Validate the obsolete sidecar now,
# write the completed source-upgrade manifest, then remove the file
# as the final fallible operation. SQLite observations are rebuilt by
# the normal renewal scheduler. No second legacy copy is retained.
# Obsolete renewal sidecar: validate, record the manifest, then remove it last.
runtime_data = (data_dir or (target / "data")).resolve()
certs_dir = runtime_data / "certs"
if certs_dir.is_symlink():