Compare commits

..
3 Commits
Author SHA1 Message Date
Julian Boldt 4379a17b15 Release v1.23.9
Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
- Update-Karte: Der Hinweis für Installationen ohne Release-Images nennt jetzt die tatsächliche Ursache („OPNEXUS_IMAGE_REPO ist nicht gesetzt“)
  statt „baut aus dem Quellcode“.
- `cosign.pub`: öffentlicher Schlüssel für die Signaturen der Release-Images (das Release-Skript kann Images jetzt signieren).
2026-10-20 15:16:51 +02:00
Julian Boldt 983e05a816 Release v1.23.8
Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
- **Einstellungen › OPNexus aktualisieren:** Auf einer Installation, die aus dem Quellcode gebaut wird (kein `OPNEXUS_IMAGE_REPO`), erscheint nicht mehr
  die Anleitung zum Aktivieren des Updaters – Updates per Klick gibt es dort ohnehin nicht –, sondern nur der Hinweis auf `git pull` und
  `docker compose up -d --build`. Das Backend erkennt den Modus jetzt selbst (neue Umgebungsvariable im Compose-File).
2026-10-20 14:52:10 +02:00
Julian Boldt dd6a64d953 Release v1.23.7
Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
- Hinweistext der Versionsprüfung verweist auf den Schalter „oben“ statt „unten“.
2026-10-20 14:43:39 +02:00
14 changed files with 67 additions and 11 deletions

No files matched your search

+16
View File
@@ -31,6 +31,22 @@ den Einstellungen.
Nächste Codenamen (der Reihe nach, wenn die jeweils nächste MINOR-Version
ansteht): Merlin …
## [1.23.9] "Harrier" — 2026-10-20
- Update-Karte: Der Hinweis für Installationen ohne Release-Images nennt jetzt die tatsächliche Ursache („OPNEXUS_IMAGE_REPO ist nicht gesetzt“)
statt „baut aus dem Quellcode“.
- `cosign.pub`: öffentlicher Schlüssel für die Signaturen der Release-Images (das Release-Skript kann Images jetzt signieren).
## [1.23.8] "Harrier" — 2026-10-20
- **Einstellungen › OPNexus aktualisieren:** Auf einer Installation, die aus dem Quellcode gebaut wird (kein `OPNEXUS_IMAGE_REPO`), erscheint nicht mehr
die Anleitung zum Aktivieren des Updaters – Updates per Klick gibt es dort ohnehin nicht –, sondern nur der Hinweis auf `git pull` und
`docker compose up -d --build`. Das Backend erkennt den Modus jetzt selbst (neue Umgebungsvariable im Compose-File).
## [1.23.7] "Harrier" — 2026-10-20
- Hinweistext der Versionsprüfung verweist auf den Schalter „oben“ statt „unten“.
## [1.23.6] "Harrier" — 2026-10-20
- **Versionsprüfung im Webinterface:** Unter Einstellungen › OPNexus aktualisieren lässt sich die Prüfung auf neue Versionen jetzt per Schalter
+2 -2
View File
@@ -7,7 +7,7 @@ Zentrale Verwaltung mehrerer [OPNsense](https://opnsense.org)-Firewalls: Regeln,
![Zentrale Firewall-Regeln](docs/screenshots/readme-rules-de.webp)
> **Stand:** `1.23.6` ist die aktuelle stabile Version. Entwickelt und getestet wurde gegen echte OPNsense-Instanzen; eine frische Installation aus dem Release-Bundle sowie Updates und Rollbacks sind durchgängig geprüft. Ecken und Kanten bitte melden.
> **Stand:** `1.23.9` ist die aktuelle stabile Version. Entwickelt und getestet wurde gegen echte OPNsense-Instanzen; eine frische Installation aus dem Release-Bundle sowie Updates und Rollbacks sind durchgängig geprüft. Ecken und Kanten bitte melden.
## Funktionen
@@ -62,7 +62,7 @@ Für den Zugriff von anderen Rechnern und den Produktivbetrieb mit TLS (mitgelie
```bash
OPNEXUS_IMAGE_REPO=git.opnexus.dev/opnexus
OPNEXUS_VERSION=1.23.6
OPNEXUS_VERSION=1.23.9
```
```bash
+2 -2
View File
@@ -7,7 +7,7 @@ Central management for multiple [OPNsense](https://opnsense.org) firewalls: rule
![Central firewall rules](docs/screenshots/readme-rules-en.webp)
> **Status:** `1.23.6` is the current stable release. It has been developed and tested against real OPNsense instances; a clean install from the release bundle, updates and rollbacks have been verified end to end. Please report rough edges.
> **Status:** `1.23.9` is the current stable release. It has been developed and tested against real OPNsense instances; a clean install from the release bundle, updates and rollbacks have been verified end to end. Please report rough edges.
## What it does
@@ -64,7 +64,7 @@ For access from other machines and for production use with TLS (bundled Caddy pr
```bash
OPNEXUS_IMAGE_REPO=git.opnexus.dev/opnexus
OPNEXUS_VERSION=1.23.6
OPNEXUS_VERSION=1.23.9
```
```bash
+3
View File
@@ -27,6 +27,9 @@ class Settings(BaseSettings):
# keine Instanz- oder Nutzerdaten.
update_check_url: str = ""
update_check_interval_hours: int = 12
# Registry der Release-Images (OPNEXUS_IMAGE_REPO). Leer = OPNexus wird lokal aus dem
# Quellcode gebaut; dann gibt es keine Updates per Klick (nur der Hinweis in den Einstellungen).
opnexus_image_repo: str = ""
# ── Updates aus dem Webinterface (app/services/updater_client.py) ─────
# Optionaler Updater-Container (Compose-Profil "updater"). Das Backend hat
+3
View File
@@ -104,6 +104,9 @@ async def updater_status(db: AsyncSession = Depends(get_db), user: AdminUser = D
updater = await updater_client.status()
except updater_client.UpdaterUnavailable as exc:
result["reason"] = str(exc)
# Without the updater the install mode is still known from the image registry setting; the UI uses it
# to not offer enabling the updater on an install that builds from source (it could not update anyway).
result["mode"] = "release" if settings.opnexus_image_repo.strip() else "local"
return result
except updater_client.UpdaterRejected:
result["reason"] = "unreachable"
+1 -1
View File
@@ -6,5 +6,5 @@ convention — but both are bumped together whenever a release ships).
Versioning scheme: see CHANGELOG.md ("Versionierung").
"""
APP_VERSION = "1.23.6"
APP_VERSION = "1.23.9"
APP_CODENAME = "Harrier"
+11
View File
@@ -58,6 +58,17 @@ async def test_status_without_token_is_unavailable_not_an_error(client, respx_mo
assert body["update_available"] is True # der Hinweis bleibt trotzdem
@pytest.mark.asyncio
@pytest.mark.parametrize("repo,mode", [("", "local"), ("git.example.test/opnexus", "release")])
async def test_install_mode_is_known_without_the_updater(client, respx_mock, monkeypatch, tmp_path, repo, mode):
# The panel must not tell a source-built install to enable an updater that could not update it anyway.
monkeypatch.setattr(settings, "updater_token_file", str(tmp_path / "missing"))
monkeypatch.setattr(settings, "opnexus_image_repo", repo)
_feed(respx_mock, _bump(minor=1))
body = (await client.get("/api/system/updater")).json()
assert body["available"] is False and body["reason"] == "not_enabled" and body["mode"] == mode
@pytest.mark.asyncio
async def test_status_unreachable_updater(client, respx_mock):
_feed(respx_mock, _bump(minor=1))
+4
View File
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEA4pZWkNMkAtCGc54M2wuWy7CXwkT
3PCysv1/1IbkyJRPdM8+DFf26fBxWG9P9PLKfwavhqVYtHILxxzxKmtjeQ==
-----END PUBLIC KEY-----
+1
View File
@@ -116,6 +116,7 @@ services:
COOKIE_SECURE: ${COOKIE_SECURE:-false}
TRUST_PROXY_HEADERS: ${TRUST_PROXY_HEADERS:-false}
UPDATE_CHECK_URL: ${UPDATE_CHECK_URL:-}
OPNEXUS_IMAGE_REPO: ${OPNEXUS_IMAGE_REPO:-}
ALLOW_INSECURE_FIREWALL_URLS: ${ALLOW_INSECURE_FIREWALL_URLS:-false}
ALLOW_INSECURE_SMTP_AUTH: ${ALLOW_INSECURE_SMTP_AUTH:-false}
SMTP_CA_FILE: ${SMTP_CA_FILE:-}
+3 -1
View File
@@ -208,7 +208,9 @@ export function OpnexusUpdateSection() {
{!status.available && (
<div className="space-y-2 rounded-lg border border-slate-200 bg-slate-50 p-3 text-sm text-slate-700">
{status.reason === "not_enabled" || status.reason === "unauthorized" ? (
{(status.reason === "not_enabled" || status.reason === "unauthorized") && status.mode === "local" ? (
<p>{t("settings.update.localMode")}</p>
) : status.reason === "not_enabled" || status.reason === "unauthorized" ? (
<>
<p className="font-medium">{t("settings.update.notEnabledTitle")}</p>
<p>{t("settings.update.notEnabledBody")}</p>
+2 -2
View File
@@ -122,7 +122,7 @@
"upToDate": "OPNexus ist auf dem neuesten Stand.",
"notes": "Release-Notes",
"checked": "Zuletzt geprüft: {time}",
"feedOff": "Die Versionsprüfung ist aus. Unten einschalten, damit OPNexus neue Versionen erkennt.",
"feedOff": "Die Versionsprüfung ist aus. Schalte sie oben ein, damit OPNexus neue Versionen erkennt.",
"feedTitle": "Auf neue Versionen prüfen",
"feedHint": "Fragt regelmäßig den Release-Feed ab, ob eine neuere Version erschienen ist. Gesendet wird nur eine einfache Anfrage (GET) mit der eigenen Versionsnummer, nichts sonst. Standardmäßig aus.",
"feedToggle": "Versionsprüfung aktivieren",
@@ -138,7 +138,7 @@
"notEnabledImages": "Das geht nur mit Release-Images (Release-Bundle oder OPNEXUS_IMAGE_REPO in der .env). Wer OPNexus selbst aus dem Quellcode baut, aktualisiert mit „git pull“ und „docker compose up -d --build“.",
"notEnabledCli": "Bis dahin geht das Update auf dem Server mit „opnexus update“.",
"unreachable": "Der Updater antwortet nicht. Auf dem Server prüfen: docker compose ps updater",
"localMode": "Diese Installation baut OPNexus lokal aus dem Quellcode (kein Release-Image). Aktualisieren auf dem Server mit git pull und docker compose up -d --build.",
"localMode": "Diese Installation nutzt keine Release-Images (OPNEXUS_IMAGE_REPO ist in der .env nicht gesetzt). Aktualisieren auf dem Server mit „git pull“ und „docker compose up -d --build“.",
"majorChange": "Version {latest} ist ein Hauptversions-Sprung. Bitte erst die Release-Notes lesen und dann auf dem Server mit „opnexus update {latest}“ aktualisieren.",
"button": "Auf {latest} aktualisieren",
"confirmTitle": "Auf {latest} aktualisieren?",
+2 -2
View File
@@ -122,7 +122,7 @@
"upToDate": "OPNexus is up to date.",
"notes": "Release notes",
"checked": "Last checked: {time}",
"feedOff": "The version check is off. Switch it on below so OPNexus can detect new versions.",
"feedOff": "The version check is off. Switch it on above so OPNexus can detect new versions.",
"feedTitle": "Check for new versions",
"feedHint": "Regularly asks the release feed whether a newer version has been published. Only a plain request (GET) carrying your own version number is sent, nothing else. Off by default.",
"feedToggle": "Enable version check",
@@ -138,7 +138,7 @@
"notEnabledImages": "This only works with release images (release bundle, or OPNEXUS_IMAGE_REPO in the .env). If you build OPNexus from source, update with “git pull” and “docker compose up -d --build”.",
"notEnabledCli": "Until then, update on the server with “opnexus update”.",
"unreachable": "The updater does not respond. Check on the server: docker compose ps updater",
"localMode": "This installation builds OPNexus locally from source (no release image). Update on the server with git pull and docker compose up -d --build.",
"localMode": "This installation does not use release images (OPNEXUS_IMAGE_REPO is not set in the .env). Update on the server with “git pull” and “docker compose up -d --build”.",
"majorChange": "Version {latest} is a major version jump. Please read the release notes first, then update on the server with “opnexus update {latest}”.",
"button": "Update to {latest}",
"confirmTitle": "Update to {latest}?",
+1 -1
View File
@@ -1,6 +1,6 @@
// Manually bumped whenever a notable change ships — mirrors the dated
// entries already kept in the project README/CHANGELOG.md, no build
// tooling involved. Versioning scheme: see CHANGELOG.md ("Versionierung").
export const APP_VERSION = "1.23.6";
export const APP_VERSION = "1.23.9";
export const APP_CODENAME = "Harrier";
export const APP_MAINTAINER = "Julian Boldt";
+16
View File
@@ -9,6 +9,8 @@
# scripts/build_release_images.sh v1.10.0 --push # bauen und pushen
# scripts/build_release_images.sh v1.10.0 --push --multiarch # amd64+arm64 (braucht QEMU/buildx)
#
# Signieren (cosign): OPNEXUS_SIGN=1 COSIGN_KEY=/pfad/cosign.key [COSIGN_PASSWORD=…] — der öffentliche
# Schlüssel liegt als cosign.pub im Repo; die Registry muss ihren Token-Realm per https melden.
# REPO: Umgebungsvariable OPNEXUS_IMAGE_REPO (Standard git.opnexus.dev/opnexus).
# Hinweis: Hinter dem Cloudflare-Proxy (Free) scheitern Pushes mit Layern > 100 MB —
# dann die Registry-Domain auf "DNS only" stellen oder aus dem LAN pushen.
@@ -45,5 +47,19 @@ for svc in backend frontend proxy updater; do
docker build "${targs[@]}" "$src/$svc"
if [ "$push" = 1 ]; then for t in "${tags[@]}"; do docker push "$image:$t"; done; fi
fi
if [ "$push" = 1 ] && [ "${OPNEXUS_SIGN:-0}" = 1 ]; then
# Signiert wird der Digest (nicht der veränderliche Tag). Ein Schlüssel: COSIGN_KEY (+ COSIGN_PASSWORD).
[ -n "${COSIGN_KEY:-}" ] || { echo "OPNEXUS_SIGN=1, aber COSIGN_KEY ist nicht gesetzt" >&2; exit 1; }
if [ "$multi" = 1 ]; then
digest="$(docker buildx imagetools inspect "$image:$version" --format '{{json .Manifest.Digest}}' | tr -d '"')"
else
digest="$(docker image inspect "$image:$version" --format '{{json .RepoDigests}}' | tr ',' '\n' | grep -F "$image@" | tr -d '[]"')"; digest="${digest##*@}"
fi
[ -n "$digest" ] || { echo "Digest von $image:$version nicht gefunden (Push fehlgeschlagen?)" >&2; exit 1; }
# Ohne öffentliches Transparenzlog (Rekor): Prüfen soll auch in abgeschotteten Netzen gehen.
cosign sign --yes --use-signing-config=false --tlog-upload=false --key "$COSIGN_KEY" "$image@$digest"
cosign verify --key cosign.pub --insecure-ignore-tlog=true "$image@$digest" >/dev/null
echo " signiert: $image@$digest"
fi
done
[ "$push" = 1 ] && echo "Fertig und gepusht: $repo (${tags[*]})" || echo "Fertig (lokal gebaut, nicht gepusht)."