Rolls the apps-catalog split, the /settings CSS wrap fix, and the version bump to 26.6-alpha across pyproject + website copy. Core release tarball still carries apps/fileshare as the offline first-boot seed; the new daniel/furtka-apps catalog (tagged 26.6-alpha today) is the authoritative source on boxes that have synced at least once. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
17 KiB
Changelog
All notable changes to Furtka will be documented in this file.
The format is based on Keep a Changelog.
This project uses calendar versioning: YY.N-stage (e.g. 26.0-alpha = 2026, release 0, alpha stage).
Unreleased
26.6-alpha - 2026-04-20
Added
- Apps catalog synced independently of core. A new
daniel/furtka-appsForgejo repo carries the bundled app catalog; running boxes pull the latest release viafurtka-catalog-sync.timer(10 min post-boot + daily, ±6 h jitter) and extract atomically into/var/lib/furtka/catalog/. The resolver now prefers catalog apps over the seed/opt/furtka/current/apps/tree that ships inside the core release tarball, so apps can update without cutting a Furtka core release. Manual trigger: "Sync apps catalog" button on/apps, orsudo furtka catalog syncat the console. Fresh boxes with no network fall back to the seed, so offline first-boot still shows installable apps. Installed apps are never auto-swapped — users click Reinstall in/appsto move an existing install onto a newer catalog version (settings merge-preserved via the existinginstaller.install_frompath). - Catalog CLI:
furtka catalog sync [--check] [--json]+furtka catalog status [--json]. Same shape as the corefurtka updatecommands. - Catalog API endpoints:
POST /api/catalog/sync/check,POST /api/catalog/sync/apply(detached viasystemd-runfor symmetry with/api/furtka/update/apply),GET /api/catalog/status. The existing/api/bundledendpoint keeps working as a backwards-compat alias for/api/apps/available, which now returns the union of catalog + seed apps with a new"source"field on each entry ("catalog"|"bundled").
Changed
furtka._release_commonextracted fromfurtka.updater. Bothupdaterand the newcatalogmodule now share one implementation of the Forgejo-releases-API call, SHA256 verification, path-traversal-guarded tarball extraction, and CalVer comparison. Public updater surface unchanged._link_new_unitsnow auto-enables newly-linked.timerunits. On self-update, a fresh timer file (e.g.furtka-catalog-sync.timeradded in this release) needssystemctl enableto actually start firing — linking alone isn't enough. Fresh installs get their enable via the webinstaller's_FURTKA_UNITSlist as before.
Fixed
- SHA-256 CA fingerprint no longer overflows the
/settingsLocal HTTPS card on narrow viewports..kv ddgrid items now setmin-width: 0+overflow-wrap: anywhereso the colon-separated hex string breaks within the card's right edge instead of pushing past it.
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 withSSL_ERROR_INTERNAL_ERROR_ALERT; and bothfurtka.httpsand the Caddyfile's/rootCA.crthandler referenced/var/lib/caddy/.local/share/caddy/pki/…, a path that doesn't exist because our systemd unit setsXDG_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_caddyfilereads/etc/hostname).auto_https disable_redirectskeeps Caddy's built-in redirect out of the way of the/settingstoggle. PKI paths corrected in bothfurtka/https.pyandassets/Caddyfile. Verified end-to-end on the 192.168.178.110 test VM: TLS 1.3 handshake completes, leaf cert issued,/rootCA.crtreturns 200.
Changed
- Wizard footer version is now dynamic.
webinstaller/app.pyresolves the Furtka version at startup via a Flask context processor — reads/opt/furtka/VERSIONon the live ISO (written byiso/build.shfrompyproject.tomlat build time), falls back topyproject.tomlin 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.mdadded (manifest schema, volume namespacing,.env.exampleguardrails, SVG sanitiser limits, install/test flow). RootREADME.mdroadmap updated with Phase 1 HTTPS + smoke-VM pipeline as shipped items and 26.4-alpha in the release list.iso/README.mdcorrected: mDNS is wired (not "later milestone"), post-install default URL ishttp://furtka.local(notproksi.local), HTTPS is available viatls internalsince 26.4.website/README.mdnow documents the auto-deploy on push-to-main as the default path, manualdeploy.shas the SSH-hop fallback.
26.4-alpha - 2026-04-18
Added
- Local HTTPS via Caddy
tls internalon port 443. Caddy generates a per-box local root CA on first start; the Caddyfile now serves both:80and:443from the same routes. HTTP stays on by default — no regression for users who haven't trusted the CA yet. New "Local HTTPS" section in/settingsshows the CA's SHA-256 fingerprint, offers a one-click download ofrootCA.crt, links to the per-OS install guide at/https-install/, and exposes an opt-in "force HTTPS" toggle that only unhides itself once the current browser has already trusted the cert (so enabling it can't lock the user out of the settings page). Backend:GET /api/furtka/https/statusandPOST /api/furtka/https/forceinfurtka.https. The force toggle drops a Caddy import snippet into/etc/caddy/furtka.d/redirect.caddyfileand reloads Caddy; reload failure automatically rolls the snippet state back so a bad config can't wedge the next service start. - Impressum + Datenschutzerklärung on furtka.org (both DE and EN) covering §5 DDG and Art. 13 GDPR. Linked from the site footer on every page; bilingual with DE as the legally binding version.
- Auto-deploy of furtka.org on push-to-main. New
.forgejo/workflows/deploy-site.ymlruns on the self-hosted runner (which is forge-runner-01 — the webserver host), so the deploy is just a local rsync +hugo --minifyinto/var/www/furtka.org/. No SSH, no secrets. Manualwebsite/deploy.shremains for out-of-band deploys. - Post-build smoke VM on Proxmox test host 192.168.178.165. Every
build-isorun boots the freshly built ISO in a throwaway VM on pollux (8 GiB RAM / 2 vCPU — the 4 GB default OOM-ed the host during mkinitcpio), then curls:5000to confirm the webinstaller is alive. VMs in VMID range 9000–9099 tagged with the commit SHA; last 5 kept for post-mortem debugging. Optionalworkflow_dispatch"Smoke latest ISO" re-tests the cached ISO in ~2 min without rebuilding. Step-levelcontinue-on-errormeans a VM-side flake doesn't mark the ISO build red.
Fixed
- Settings page "Installed" field now refreshes after a self-update. The
/api/furtka/update/checkresponse already carriescurrent— the settings JS now drivesupd-currentfrom it the same way it drivesupd-latest, so clicking "Check for updates" after a successful update reflects the new installed version without a force-reload. - Auto-reload on update completion is now reliable. Clicking "Update now" arms a 45 s fallback
setTimeout(location.reload)in addition to the existing/update-state.jsonpolling loop. If the mid-apply API restart drops the poll connection beforestage: doneis ever observed (as seen on the 2026-04-16 VM test), the fallback still brings the page up on the new version. The fallback is cleared ondone(5 s reload wins) orrolled_back(user needs the error visible). - Version string in the webinstaller footer was pinned at
26.0-alphaand didn't track releases. Bumped to26.4-alphafor this release; follow-up will make it render frompyproject.tomldynamically.
26.3-alpha - 2026-04-16
Fixed
- Release workflow no longer depends on
jq. The previousapt-get install -y jqstep hung on a slow mirror for 15+ minutes and stalled the 26.2-alpha publish.publish-release.shnow assembles the release-create payload via a tinypython3 -cblock — Python is always available on the Forgejo Actions runner.apt-getpath removed entirely.
26.2-alpha - 2026-04-16
Fixed
- Updater "Check for updates" no longer 404s when every release is a pre-release.
check_update()queried Forgejo's/releases/latest, which silently excludes pre-releases (anything tagged-alpha/-beta/-rc) and returns 404 when there is no stable release. Switched to/releases?limit=1, which Forgejo sorts newest-first across all release kinds. During the alpha stage where every tag is a pre-release this is the only thing that works; once we tag a stable release, the same query still picks it up.
26.1-alpha - 2026-04-16
Added
-
Furtka self-update (Phase 2). Tagging a release on main fires
.forgejo/workflows/release.yml, which packagesfurtka/+apps/+ a root-levelVERSIONfile asfurtka-<tag>.tar.gz, uploads it plus a.sha256+release.jsonto the Forgejo releases page, and makes the release available to running boxes. New CLI:furtka update [--check]+furtka rollback. New endpoints:POST /api/furtka/update/check+/apply+GET /api/furtka/update/status. UI: "Furtka updates" card on/settingsshows installed vs latest, Update button runs the apply flow detached viasystemd-run, progress polls/update-state.jsonserved by Caddy so the mid-update API restart doesn't interrupt reporting. Atomic/opt/furtka/currentsymlink flip, auto-rollback on health-check failure post-restart, SHA256-verified downloads. -
Per-app container image updates (Phase 1).
POST /api/apps/<name>/updaterunsdocker compose pull, compares the running container's image digest to the just-pulled local image digest per service, and only restarts containers whose image actually changed. Update button on each installed-app row in/apps. Keepsimage: :latestpins simple — no compose-file mutations. -
Per-version install layout on
/opt/furtka/. Install now extracts the resource-manager payload to/opt/furtka/versions/<VERSION>/and creates/opt/furtka/currentas an atomic symlink; updates flip the symlink in place andsystemctl linkevery unit from the shippedassets/systemd/tree. Runtime JSON (status.json,furtka.json,update-state.json) moved to/var/lib/furtka/so self-updates never clobber it. -
On-box UI uplevel across three pages sharing one design system (
/style.cssserved by Caddy). Redesigned landing page with a "Your apps" tile grid driven by/api/apps, afileshareapp tile that deep-links tosmb://<host>.local/files, status tiles, and subtle "Coming next" links tofurtka.org./appspage renders real app icons inlined from each manifest'sicon.svg(defensive SVG sanitiser — strips script/on*/javascript: content, 16 KB cap). New/settingspage with About-this-box, Appearance, Furtka-updates, and Coming-next sections. Persistent top nav (Jakob's Law) on every page. Light-mode support viaprefers-color-scheme. -
Webinstaller step 2 (boot drive) now shows size / type / health chips plus a "Recommended" badge on the auto-selected drive instead of a raw numeric score.
-
Forgejo branch protection on
main— no direct pushes except owner-whitelisted, required status checks (CI / lint*,CI / test*,CI / validate-json*), applied via the idempotentops/forgejo/apply-branch-protection.shscript. -
In-browser app settings, so users no longer need SSH +
vimto configure an app before first install. Manifest gains optionalsettings(name/label/description/type/required/default) anddescription_longfields. Installing a bundled app opens a form rendered from the manifest; installed apps grow a "Settings" button that edits merged values (password fields blank = keep current). API:POST /api/apps/installnow accepts asettingsobject in the JSON body; newGET/POST /api/apps/<name>/settingsfor inspecting and updating an installed app. Password values never leave the server. -
nanoadded to the installer package list so users have a beginner-friendly editor at the console/SSH (wasvim-only, whichcommand not found'd under Arch 4.x because it was actually missing from the package set too). -
opensshadded explicitly to the installer package list andsshdadded to enabled services.archinstall: truein archinstall 4.x did not actually install openssh-server, so the documented recovery path (SSH → edit.env) silently failed. -
Forgejo Actions runner live on Proxmox VM (
forge-runner-01, Ubuntu 24.04) with DinD sidecar — CI green end-to-end. Setup scripts inops/forgejo-runner/. -
Walking-skeleton live ISO (
iso/build.sh). Overlays an Archrelengprofile with Flask + the webinstaller, bakes a systemd unit that auto-starts the wizard on boot, produces a hybrid BIOS/UEFI ISO viamkarchisoin a privilegedarchlinux:latestcontainer. Tested booting under OVMF in Proxmox — wizard screens 1–3 respond athttp://<vm-ip>:5000. -
Public website at furtka.org (
website/). Hugo static site, English + German, served from/var/www/furtka.orgonforge-runner-01via nginx. Upstream openresty proxy handles TLS. Intentionally minimal single-page copy while the project is pre-alpha. Deploy is./website/deploy.sh(rsync + remote Hugo build); one-time VM setup inops/nginx/setup-vm.sh.
Changed
- Every on-box asset (landing page, settings page, style.css, status/welcome scripts, systemd units, Caddyfile) moved from inline Python string constants in
webinstaller/app.pyinto real files underfurtka/assets/. The installer reads them from disk at install time; the self-updater ships them in the release tarball. - Settings-button label went from "Einstellungen" (prototyping leftover) to "Settings" — rest of the UI chrome is English.
- Keyboard layout at the TTY now follows the chosen installer language (
de→de,pl→pl,en→us) instead of hardcodingus. Previously German users couldn't type/,-, or=at the recovery console. fileshareapp:description_long+settings(SMB_USER, SMB_PASSWORD) for the new settings form. Docker-level healthcheck fromdperson/sambais disabled in the compose override — it timed out under normal operation and marked a working share "unhealthy" indocker ps.- Project name finalized: Furtka. Working title "Homebase" retired. Domain
furtka.orgregistered via Strato 2026-04-13. - Managed gateway NS hostnames updated from
ns1.homebase.cloud/ns2.homebase.cloudtons1.furtka.org/ns2.furtka.org. - Python package renamed from
homebase→furtkainpyproject.toml.
26.0-alpha - 2026-04-13
First tagged snapshot. Pre-alpha — the installer does not yet boot, but the design is locked and the prototype components are shaped.
Added
- Installer webapp prototype (
webinstaller/) — Flask app with 3-step wizard (hostname → drive → overview), serves drive list viadrives.py::list_scored_devices(). - Drive scoring module (
webinstaller/drives.py) — scores attached disks by type (NVMe/SSD/HDD), SMART health (smartctl -H), and size. Consumed by the installer and usable as a CLI. - Base archinstall configuration (
archinstall/user_configuration.json) — systemd-boot, ext4, Docker + Compose preinstalled, server profile, SSH. Credentials template atarchinstall/user_credentials.example.json(real credentials gitignored). - Installer wireframes (
docs/installer-wireframes.md) — Robert's hand-drawn 4-screen UX sketches. - Competitor analysis (
docs/competitors.md) — CasaOS, Umbrel, YunoHost reviewed across install flow, hardware detection, app store UX, reverse proxy/SSL, user complaints. Key finding: device-aware wizard + managed gateway are uncontested differentiators. - Wizard flow spec (
docs/wizard-flow.md) — 8-screen first-boot flow extending Robert's wireframe with YunoHost-style domain/SSL/diagnostic/confirm screens. Locked tech picks with rejected alternatives. - Project README — vision, principles, architecture, key decisions, landscape, roadmap.
Decisions locked
- Reverse proxy: Caddy (auto Let's Encrypt, simplest config)
- Identity provider: Authentik (bundled SSO, every app auto-wired at install)
- Managed gateway DNS: NS delegation to
ns1.furtka.org/ns2.furtka.org(wildcard cert via Let's Encrypt DNS-01) - Local HTTPS: Local CA installed by user once (no browser warnings on
*.proksi.local) - Base OS: Arch (rolling, Debian remains fallback)
- Containers: Docker + Compose
- License: AGPL-3.0