diff --git a/CHANGELOG.md b/CHANGELOG.md index 00650cd..60b3b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, r ## [Unreleased] +## [26.5-alpha] - 2026-04-20 + +### Fixed + +- **HTTPS handshake regression on the installed box (#10).** Phase 1 shipped two linked bugs: the `:443 { tls internal }` site block had no hostname, so Caddy never issued a leaf cert and every SNI handshake died with `SSL_ERROR_INTERNAL_ERROR_ALERT`; and both `furtka.https` and the Caddyfile's `/rootCA.crt` handler referenced `/var/lib/caddy/.local/share/caddy/pki/…`, a path that doesn't exist because our systemd unit sets `XDG_DATA_HOME=/var/lib`. Force-HTTPS toggle made the brokenness user-visible by redirecting working HTTP to dead HTTPS. Fixed: the Caddyfile now ships a `__FURTKA_HOSTNAME__.local, __FURTKA_HOSTNAME__ { tls internal }` block with the placeholder substituted at install time (`webinstaller/app.py`) and on every self-update (`furtka.updater._refresh_caddyfile` reads `/etc/hostname`). `auto_https disable_redirects` keeps Caddy's built-in redirect out of the way of the `/settings` toggle. PKI paths corrected in both `furtka/https.py` and `assets/Caddyfile`. Verified end-to-end on the 192.168.178.110 test VM: TLS 1.3 handshake completes, leaf cert issued, `/rootCA.crt` returns 200. + +### Changed + +- **Wizard footer version is now dynamic.** `webinstaller/app.py` resolves the Furtka version at startup via a Flask context processor — reads `/opt/furtka/VERSION` on the live ISO (written by `iso/build.sh` from `pyproject.toml` at build time), falls back to `pyproject.toml` in dev runs, then to literal `"dev"`. The 26.4 footer was hand-pinned and drifted within hours of release; that follow-up item is now closed. +- **Docs realigned with 26.4-alpha reality.** `apps/README.md` added (manifest schema, volume namespacing, `.env.example` guardrails, SVG sanitiser limits, install/test flow). Root `README.md` roadmap updated with Phase 1 HTTPS + smoke-VM pipeline as shipped items and 26.4-alpha in the release list. `iso/README.md` corrected: mDNS is wired (not "later milestone"), post-install default URL is `http://furtka.local` (not `proksi.local`), HTTPS is available via `tls internal` since 26.4. `website/README.md` now documents the auto-deploy on push-to-main as the default path, manual `deploy.sh` as the SSH-hop fallback. + ## [26.4-alpha] - 2026-04-18 ### Added @@ -86,7 +97,8 @@ First tagged snapshot. Pre-alpha — the installer does not yet boot, but the de - **Containers:** Docker + Compose - **License:** AGPL-3.0 -[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.4-alpha...HEAD +[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.5-alpha...HEAD +[26.5-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.5-alpha [26.4-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.4-alpha [26.3-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.3-alpha [26.2-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.2-alpha diff --git a/iso/build.sh b/iso/build.sh index 1317a87..e87a5c2 100755 --- a/iso/build.sh +++ b/iso/build.sh @@ -78,6 +78,11 @@ cp -a "$REPO_ROOT/webinstaller/." "$PROFILE_WORK/airootfs/opt/furtka/" # next to webinstaller/app.py so _resolve_assets_dir() finds it at runtime. cp -a "$REPO_ROOT/assets" "$PROFILE_WORK/airootfs/opt/furtka/assets" rm -rf "$PROFILE_WORK/airootfs/opt/furtka/__pycache__" +# VERSION next to the webinstaller so the wizard footer can render the +# release string at runtime instead of carrying a hardcoded one. Matches +# what the resource-manager payload ships in its own VERSION file below. +ISO_VERSION=$(grep -E '^version = ' "$REPO_ROOT/pyproject.toml" | head -1 | sed 's/.*= "\(.*\)"/\1/') +echo "$ISO_VERSION" > "$PROFILE_WORK/airootfs/opt/furtka/VERSION" # Pack the resource manager (furtka/ Python package + bundled apps/) as a # tarball that webinstaller hands to archinstall via custom_commands. Lives at @@ -94,9 +99,9 @@ cp -a "$REPO_ROOT/apps" "$PAYLOAD_STAGE/" cp -a "$REPO_ROOT/assets" "$PAYLOAD_STAGE/" find "$PAYLOAD_STAGE" -type d -name __pycache__ -exec rm -rf {} + # VERSION at tarball root: the installer reads it to choose the versions// -# directory name and /opt/furtka/current/VERSION reports it at runtime. -grep -E '^version = ' "$REPO_ROOT/pyproject.toml" | head -1 \ - | sed 's/.*= "\(.*\)"/\1/' > "$PAYLOAD_STAGE/VERSION" +# directory name and /opt/furtka/current/VERSION reports it at runtime. Same +# value we wrote into /opt/furtka/VERSION for the live wizard footer above. +echo "$ISO_VERSION" > "$PAYLOAD_STAGE/VERSION" tar -czf "$PROFILE_WORK/airootfs/opt/furtka-resource-manager.tar.gz" \ -C "$PAYLOAD_STAGE" . rm -rf "$PAYLOAD_STAGE" diff --git a/pyproject.toml b/pyproject.toml index a021315..ba8406b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "furtka" -version = "26.4-alpha" +version = "26.5-alpha" description = "Open-source home server OS — simple enough for everyone." requires-python = ">=3.11" readme = "README.md" diff --git a/webinstaller/app.py b/webinstaller/app.py index 31847be..be4cafe 100644 --- a/webinstaller/app.py +++ b/webinstaller/app.py @@ -15,6 +15,40 @@ from flask import Flask, jsonify, redirect, render_template, request, url_for app = Flask(__name__) + +def _resolve_version() -> str: + """Resolve the Furtka version to display in the wizard footer. + + On the live ISO `iso/build.sh` writes `/opt/furtka/VERSION` at build time + from `pyproject.toml`; that's the authoritative source at runtime. For + local dev runs (pytest, `flask run` outside the ISO) fall back to + reading `pyproject.toml` directly, then to the literal "dev" so the + footer never 500s if both files are missing. + """ + iso_path = Path(__file__).resolve().parent / "VERSION" + for candidate in (iso_path, Path(__file__).resolve().parent.parent / "pyproject.toml"): + try: + text = candidate.read_text(encoding="utf-8") + except (FileNotFoundError, PermissionError, OSError): + continue + if candidate.name == "VERSION": + value = text.strip() + if value: + return value + else: + match = re.search(r'^version\s*=\s*"([^"]+)"', text, re.MULTILINE) + if match: + return match.group(1) + return "dev" + + +FURTKA_VERSION = _resolve_version() + + +@app.context_processor +def _inject_version(): + return {"furtka_version": FURTKA_VERSION} + LANGUAGES = { "en": {"locale": "en_US.UTF-8", "label": "English", "keyboard": "us"}, "de": {"locale": "de_DE.UTF-8", "label": "Deutsch", "keyboard": "de"}, diff --git a/webinstaller/templates/base.html b/webinstaller/templates/base.html index a272fd0..e90efb5 100644 --- a/webinstaller/templates/base.html +++ b/webinstaller/templates/base.html @@ -30,7 +30,7 @@ diff --git a/website/content/_index.de.md b/website/content/_index.de.md index a2885a4..6875f24 100644 --- a/website/content/_index.de.md +++ b/website/content/_index.de.md @@ -1,7 +1,7 @@ --- title: "Furtka" description: "Offenes Heimserver-Betriebssystem — einfach genug für alle." -status: "26.4-alpha — in Arbeit" +status: "26.5-alpha — in Arbeit" --- **Furtka** ist ein offenes Heimserver-Betriebssystem. diff --git a/website/content/_index.md b/website/content/_index.md index 516777e..ecd56e6 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -1,7 +1,7 @@ --- title: "Furtka" description: "Open-source home server OS — simple enough for everyone." -status: "26.4-alpha — work in progress" +status: "26.5-alpha — work in progress" --- **Furtka** is an open-source home server OS. diff --git a/website/hugo.toml b/website/hugo.toml index 4ce514c..18f561f 100644 --- a/website/hugo.toml +++ b/website/hugo.toml @@ -6,7 +6,7 @@ enableRobotsTXT = true [params] description = "Open-source home server OS — simple enough for everyone." - version = "26.4-alpha" + version = "26.5-alpha" contactEmail = "hallo@furtka.org" [markup.goldmark.renderer]