• v0.2.0-rc.1 d961cb8792

    Jarl v0.2.0-rc.1 Pre-release

    adam released this 2026-10-09 16:29:01 +01:00 | 112 commits to main since this release

    Added

    • DNSSEC signing per zone (docs/dnssec.md): jarl zone dnssec enable|status|check-ds|disable|wipe and the zone page's DNSSEC tab, or
      the zone's new dnssec_policy field in the API. named signs the zone
      with BIND's default policy (one ECDSA P-256 key that is never replaced)
      or a custom one, using inline signing, with keys in a per-view directory
      under /var/lib/bind/jarl/dnssec-keys. Jarl shows the keys and the DS
      record to give the registrar, says when it's safe to publish it, and
      checks the parent's DS records (check-ds, which also tells named with
      rndc dnssec -checkds). It refuses steps that would break a signed
      domain: switching straight to unsigned (it goes through BIND's
      insecure policy instead, and finishes only once named is done),
      deleting a signed zone or moving it to another view, and TTLs above the
      policy's max-zone-ttl. wipe starts over with a clean slate once the
      parent has no DS. Each step in the web UI opens a dialog that says what it
      needs first. jarl zone delegation now also compares the parent's DS
      records with the zone's keys.
    • Porkbun support (optional, docs/dnssec.md#porkbun): with an API key in
      the new porkbun: section of jarl.yaml (and nowhere else), jarl zone registrar status|sync-glue|set-ns|publish-ds|remove-ds and the zone
      page's Registrar tab show and change the domain's name servers, glue
      records (one per name server inside the domain, with all its IPv4 and
      IPv6 addresses) and DS records at Porkbun. Every change first checks that
      it won't take the domain offline (the name servers answer for the zone,
      glue matches, a DS goes out only once the domain is delegated to servers
      that serve the signed zone, DS records match the zone's keys before the
      name servers change); --dry-run shows the checks and --force skips
      them. Administrators only.
    • Backups include the DNSSEC keys (private keys too), stored inside the
      backup file, and jarld restore puts them back for named
      (bind.named_user, default bind). jarl-backup.service has
      CAP_DAC_READ_SEARCH to read them; --without-keys skips them.
    • Jarl raises a zone's serial above the one named has loaded whenever it
      writes a zone file whose serial isn't higher (after restoring an older
      database, say), so named loads it (it refuses otherwise for a signed
      zone) and secondaries pick it up.
    • Two-factor login to the web UI with an authenticator app (TOTP: SHA-1,
      6 digits, 30 s, as every app supports). Users turn it on under Account
      (password, QR code, a code to confirm) and get 10 one-time recovery
      codes. Logging in then asks for a code (or a recovery code) after the
      password; each code works once. In a session with two-factor login,
      creating or rotating API tokens, changing users and resetting someone's
      two-factor login need a code from the last 5 minutes: the web UI asks
      for one, API clients send X-Jarl-TOTP. API tokens and the local socket
      are not affected.
    • totp.require in jarl.yaml (none, admins, all) makes two-factor
      login compulsory; such a user who hasn't set it up can only set it up
      after logging in. totp.issuer names the server in authenticator apps
      (default Jarl <hostname>).
    • Resetting a user's two-factor login (lost phone): Users → Reset 2FA,
      jarl user totp reset NAME, or on the server
      jarld user totp reset NAME (also with jarld stopped).
    • The dashboard and jarl status list users who must use two-factor login
      but haven't set it up, and suggest disabling the first admin account
      when it is still active next to personal administrator accounts.
      jarl user list/show and the Users page show who uses it.
    • API: POST /auth/login/totp, /me/totp (setup, enable, disable,
      recovery-codes), DELETE /users/{id}/totp; database migration 4.
    • scripts/testenv.sh: turns a fresh Debian/Ubuntu machine into a test bed.
      It installs BIND and the build tools (Go from go.dev), writes a hand-made
      style configuration with internal and external views, a split-horizon
      zone (example.com or JARL_TEST_ZONE) and a reverse zone, starts named
      and prints the steps to install Jarl and adopt the configuration
      (docs/development.md).
    • View colours. Give a view a colour (Views → Edit, jarl view color, or
      PUT /views/{id}/color) and the zone list, the zone page and the views
      list show its name in that colour. The colours are muted, and pastel in
      dark mode. The default is the link colour. A colour isn't configuration,
      so setting one needs no changeset or deploy.
    • A "← Zones" link above a zone, back to the zone list, and "← History"
      above a changeset. The zone list keeps its filter, view and type in the
      address, so going back to it (with that link or the browser's back
      button) restores them. A view opened from a zone or the zone list has a
      "← example.com (external)" or "← Zones" link back.

    Changed

    • The version moved from the header to a footer: "Powered by Jarl v0.1.0",
      linking to the release on Gitea. A build that isn't of a release tag
      shows its commit instead, linked to the commit and marked -modified
      with uncommitted changes. Before, every build of a commit after a
      release still showed the release's version. GET /status and
      /auth/whoami report the build as build (docs/development.md).
    • jarld version, jarl --version, jarl status and jarl whoami give
      a version number only for release builds. Other builds say they are
      development builds and how far past the last tag they are: dev ca0f148b78b6 (3 commits after v0.2.0-rc.1). Before, they printed the
      version and the commit (0.2.0-rc.1 (ca0f148b78b6)), which read like a
      release.
    • make deb gives development builds their own package version after
      the last tag (0.2.0~rc.1+git3.gca0f148, plus the build time with
      uncommitted changes). Installing one over the RC or an older build is
      an upgrade: no more apt install --reinstall. It also removes older
      packages from dist/ (docs/development.md).
    • The view in the zone list, and on the zone page, links to that view,
      and the views page highlights it. It used to be plain text, and the zone
      page linked to the views page as a whole.
    • Switching a zone's tabs (Records, Settings, …) no longer blanks the page
      while the tab loads: the page changes once the tab is ready, and
      "Loading…" appears only if a page takes a while.
    • jarl zone serials compares the serial named serves, which for a signed
      zone is the signed zone's (ahead of Jarl's).
    • jarld import turns dnssec-policy in an existing configuration into
      the zones' DNSSEC setting, and warns that their keys must be moved into
      Jarl's key directory before adopting.
    • dnssec-policy is no longer accepted as a zone, view or server option
      (zones have a DNSSEC setting instead), nor key-directory as a zone
      option.
    • Deleting a zone also removes the journal and signed files named kept
      next to it.
    • Release candidates (tags like v0.2.0-rc.1) publish their .debs to a
      separate testing distribution of the package registry instead of
      stable. Servers that follow stable can't pick up an RC with
      apt upgrade. An RC may also take its release notes from the
      ## [0.2.0] or ## [Unreleased] section of the CHANGELOG instead of
      needing its own (docs/development.md, "Release candidates").

    Fixed

    • Publishing a release candidate failed: scripts/gitea-release.sh
      rejected its .debs, whose names carry the Debian version
      (0.2.0~rc.1) instead of 0.2.0-rc.1.
    • jarld init -u and the install guide recommend naming the first
      administrator after yourself (one account per person).
    • jarld import no longer warns that a zone with allow-update { none; }
      uses dynamic updates (validation already allowed it).
    • docs/cli.md gives the CLI configuration file's location on macOS
      (~/Library/Application Support/jarl/config.yaml) and Windows
      (%AppData%\jarl\config.yaml). It was documented only as
      ~/.config/jarl/config.yaml.
    Downloads