• 26.21-alpha cdc0c3c6fd

    26.21-alpha
    All checks were successful
    Deploy site / deploy (push) Successful in 5s
    CI / lint (push) Successful in 30s
    CI / test (push) Successful in 2m55s
    CI / validate-json (push) Successful in 33s
    CI / markdown-links (push) Successful in 21s
    Build ISO / build-iso (push) Successful in 22m11s
    Release / release (push) Successful in 16m23s
    Pre-release

    daniel released this 2026-10-23 16:57:05 +02:00 | 2 commits to main since this release

    Added

    • New logo: Mark M (a lowercase f cut out of an arched gate), winner of
      the furtka.org vote (29 of 42 votes). It is now in the website header,
      favicon and share card, the installer header and tab icon, the on-box UI
      (every page and the login), the console welcome screens of the live ISO
      and the installed box, and the BIOS boot-menu splash. Brand files in
      docs/brand/, generated by website/tools/brand-assets.py.
    • furtka.org/download/ (and /de/download/): ISO download with size,
      date and checksum, requirements and step-by-step install guide. Releases
      now publish furtka-<ver>.iso.sha256 and refresh the site.

    Security

    • App names are validated everywhere. POST /api/apps/remove with
      {"name": ".."} or "/" sent shutil.rmtree at /var/lib/furtka or the
      root filesystem (and wiping users.json reopened first-run admin setup to
      the LAN). Names from URLs, JSON bodies and manifests must now match
      ^[a-z][a-z0-9_-]*$; installer.remove/update_env check it too.
    • Settings can't inject into .env. Line breaks are refused; values
      with $ are single-quoted so compose doesn't expand them (pa$word used
      to become pa). Validation runs before the write, so a rejected /etc
      path is no longer saved anyway.
    • Damaged users.json fails closed. An empty/corrupt file used to read
      as "no admin yet" and turned /login into an open create-admin form.
      /login now answers 503 with SSH recovery steps; save_users fsyncs.
    • API server hardening: threaded (state changes still serialised), 1 MiB
      body cap, 30 s socket timeout, cross-site POSTs refused via
      Sec-Fetch-Site, JSON 500 instead of dropped connections.

    Fixed

    • Installer disk picker: SATA SSDs were labelled "HDD" and lost the
      recommendation to bigger spinning disks; type now comes from lsblk
      TRAN/ROTA. zram, eMMC boot/RPMB areas, read-only and 0-byte disks are
      hidden; disks under 16 GB are greyed out; USB disks rank last; >2 TB disks
      on BIOS machines get an MBR warning; the boot stick is also found via the
      archiso kernel args when bootmnt is gone. Step 2 only accepts a listed disk.

    • Installer runs one install at a time (double-click / second browser
      started a second archinstall on the same disk), and a crashed archinstall
      (OOM kill, signal) now shows as an error instead of a progress bar stuck
      forever. Disk-probe exceptions land in the log instead of a bare 500.

    • Failed installs can be retried from the error page without re-entering
      everything.

    • No 2-minute boot stall on boards with a second NIC: the target gets a
      systemd-networkd-wait-online --any drop-in.

    • Self-update: symlink flip is atomic; any error after the flip rolls
      back (and restores the previous Caddyfile); health check survives read
      timeouts; every failure ends in an error stage the settings page shows.

    • Interrupted app installs no longer block all later installs — a stale
      state with no live runner is marked failed after 60 s.

    • Catalog sync / update checks no longer strand on socket resets or disk
      full.

    • Apps page after an API restart redirects to /login instead of
      showing an empty app list.

    • 32-bit UEFI machines (Atom Bay Trail / Cherry Trail) get Limine
      instead of systemd-boot: Arch has no ia32 systemd-boot and archinstall's
      GRUB path hardcodes x86_64-efi, so these boxes installed but didn't boot.

    • Force-HTTPS redirect only covers <hostname>.local / <hostname> and
      is a 302. The old 301 for every host sent devices that use the IP to a
      TLS handshake that can't succeed, and stayed cached after HTTPS was
      turned off. Self-update migrates the old snippet.

    • Self-update starts newly added timers immediately and links units
      through current.
      _link_new_units() enabled a timer a release
      introduced but never started it, so after the 26.19 → 26.20 update the
      bench sat with furtka-welcome.timer inactive (dead) — and the console
      banner without its IP line — until the next reboot. It also linked the
      unit from /opt/furtka/versions/<ver>/… instead of /opt/furtka/current/…,
      so the link would have stopped following later updates and rollbacks
      (installer-created links use current). Now: link via current, enable,
      start.

    Changed

    • Wizard wording: "Server name" with a live http://<name>.local preview,
      "Pick a disk" with an explicit erase warning, readable confirm table,
      password hint explains it's also the SSH/console password, names are
      lowercased instead of rejected, system account names are refused.
    • Live console banner says a network cable with internet is required.
    • ISO builds pin archinstall (4.4-1, sha256-checked from the Arch archive)
      instead of taking whatever the repos ship that day; the build fails
      clearly when Arch's Python moves on. Bump steps in iso/README.md.
    • On-box UI polish: sticky top nav, bordered cards and status tiles, app
      tile hover lift, brand-red section markers; animations respect
      prefers-reduced-motion.
    Downloads