• Jarl v0.6.0-rc.2
    release / release (push) Successful in 2m13s
    Pre-Release

    adam released this 2026-10-13 18:21:48 +00:00 | 28 commits to main since this release

    Added

    • Reverse zones made easy (docs/reverse.md):

      • Missing reverse zones: the Zones page and jarl zone suggest-reverse list the reverse zones the private views lack for
        their A and AAAA records' addresses: the /24 of a private IPv4 network,
        a /32 for a public address (the rest of its /24 belongs to others),
        the /48 of IPv6 addresses. Create one, or all (--create), filled.
      • Fill: jarl zone create 10.0.10.0/24 --fill (ticked in the New
        zone dialog) adds a PTR record for each address the view's records use
        there; jarl zone fill-ptr and the reverse zone's page add the ones
        missing later. An address with several names gets its mail or name
        server's name, else a host's.
      • The right view: a reverse zone created without a view goes to the
        private view whose records use its addresses.
      • PTR records kept in step per zone (jarl zone update ZONE --auto-ptr, zone settings → Reverse DNS): adding, changing,
        disabling or deleting an A or AAAA record does the same to its PTR
        record, as the Update PTR box does for one change.
      • Suggestions come in two groups: yours (private networks, a ULA or
        an IPv6 /48 this server has an address in), which Create all
        creates, and public addresses, each a /32 or /128 to create only
        if it is yours (not a web host's) or Dismiss. A view can turn
        suggestions off (jarl view update vps --reverse-suggestions=false),
        e.g. one only a VPS uses.
    • A zone created inside another in the same view (a /24 inside a /8,
      lab.adbraun.lol inside adbraun.lol) takes the parent's records
      under it, which named would no longer serve from the parent; a
      delegation and its glue stay.

    • Zone commands take a network for a reverse zone: jarl zone show 10.0.10.0/24.

    • New reverse zone (Zones page) lists the networks your records use
      without a reverse zone, in every view, also where nothing is suggested
      (suggestions off, dismissed, public views); pick one, change its size
      (/48, /56, /64, /128 for IPv6, around the records' address) and create
      it filled. With a view chosen, it also lists the addresses only other
      views' records use, and fill names them from there (a VPS's AAAA in
      external, its PTR in internal). jarl zone suggest-reverse --all [--view V]. Both lists have a search, so hundreds of addresses stay
      manageable: the public addresses fold away, show 25 at a time, and
      Dismiss these N dismisses everything a search found in one change
      (--dismiss takes several networks).

    • Encrypted DNS: several host names (one certificate for all; the
      health check says when the served certificate misses one), and each
      listen address gets its own views
      for the host names' records
      (--address 10.0.10.5=internal, a view checkbox per address in the
      form), local to the view, with a warning when a public view would get
      a private address. A view no longer ticked loses the address. The form
      starts from where the records are now. The Certificates page and jarl cert show say what named uses a certificate for (DNS over TLS or HTTPS,
      on which addresses and ports).

    • docs/encrypted-dns.md: forwarding to Quad9 or Cloudflare over TLS, how to
      check it works, and why not over HTTPS.

    • Comparing one name across views: jarl zone diff adbraun.lol nas [A],
      and a Compare button on each record.

    • Exploring the statistics: jarld keeps every answer for a while
      (stats.retention.queries, default 7 days), and every client, name,
      view, record type, result and blocklist on the Statistics page leads to
      an explore page for it: answers over time, the top clients, names,
      views, types, results and blocklists among them (each a link that
      narrows it further), and the latest answers. "NXDOMAIN in external" →
      the clients asking → everything one of them asks. A filter bar types
      filters in, several values each (any of them), !value to leave one
      out and *.example.com for a domain and below; hide on a list entry
      leaves it out. Explore the answers opens the page from the
      Statistics page. GET /stats/explore.

    • Storage on the dashboard: the size of Jarl's databases (and how many
      answers the query log holds), and per disk Jarl uses a bar of how full it
      is and how much of it the databases take. The Statistics page shows the
      statistics database's size too, and its disk tiles get the same bar.

    Changed

    • jarl option set tls NAME … (and key, remote-servers, http,
      dnssec-policy, server …) replaces only the statement with that name:
      setting tls cloudflare used to replace tls quad9. jarl option unset tls cloudflare removes one by its name.
    • Compare views and jarl zone diff are rebuilt around the view
      you're on (docs/views.md#comparing-views): a summary per view, then
      what is answered differently (a view's own records in linked zones,
      drift otherwise) with Use this everywhere, the names only some
      views have, grouped, with Add to VIEW, and how many are the same.
      One line per record: the CLI cuts long TXT records to the terminal
      (--wide shows them whole). --with picks the views to compare with.
      GET /zones/{zone}/compare returns these sections instead of rows.

    Fixed

    • Server options → Added by Jarl: long statements didn't wrap, and the
      browser console reported a Content Security Policy violation (an inline
      style the page's policy blocks).

    Upgrading from 0.5

    • Tested: 0.5.2 packages with views, a linked zone, a reverse zone,
      blocking, a tls statement and statistics, upgraded in place in Debian
      13 (BIND 9.20.29): everything kept and answered as before, the new
      features worked on the upgraded data, and a 0.5.2 backup restored.
    • The database gets two new versions (12 and 13), applied when jarld
      starts; a 0.5 jarld can't open it afterwards, so take a backup first (sudo jarld backup). Nothing changes until you turn auto_ptr on for a
      zone.
    • The statistics database gets a new version too (the query log); 0.5
      can't open it afterwards either. It starts empty and fills from then on.
    Downloads
  • Jarl v0.6.0-rc.1
    release / release (push) Successful in 2m13s
    Pre-Release

    adam released this 2026-10-13 17:49:25 +00:00 | 32 commits to main since this release

    Added

    • Reverse zones made easy (docs/reverse.md):

      • Missing reverse zones: the Zones page and jarl zone suggest-reverse list the reverse zones the private views lack for
        their A and AAAA records' addresses: the /24 of a private IPv4 network,
        a /32 for a public address (the rest of its /24 belongs to others),
        the /48 of IPv6 addresses. Create one, or all (--create), filled.
      • Fill: jarl zone create 10.0.10.0/24 --fill (ticked in the New
        zone dialog) adds a PTR record for each address the view's records use
        there; jarl zone fill-ptr and the reverse zone's page add the ones
        missing later. An address with several names gets its mail or name
        server's name, else a host's.
      • The right view: a reverse zone created without a view goes to the
        private view whose records use its addresses.
      • PTR records kept in step per zone (jarl zone update ZONE --auto-ptr, zone settings → Reverse DNS): adding, changing,
        disabling or deleting an A or AAAA record does the same to its PTR
        record, as the Update PTR box does for one change.
      • Suggestions come in two groups: yours (private networks, a ULA or
        an IPv6 /48 this server has an address in), which Create all
        creates, and public addresses, each a /32 or /128 to create only
        if it is yours (not a web host's) or Dismiss. A view can turn
        suggestions off (jarl view update vps --reverse-suggestions=false),
        e.g. one only a VPS uses.
    • A zone created inside another in the same view (a /24 inside a /8,
      lab.adbraun.lol inside adbraun.lol) takes the parent's records
      under it, which named would no longer serve from the parent; a
      delegation and its glue stay.

    • Zone commands take a network for a reverse zone: jarl zone show 10.0.10.0/24.

    • New reverse zone (Zones page) lists the networks your records use
      without a reverse zone, in every view, also where nothing is suggested
      (suggestions off, dismissed, public views); pick one, change its size
      (/48, /56, /64, /128 for IPv6, around the records' address) and create
      it filled. With a view chosen, it also lists the addresses only other
      views' records use, and fill names them from there (a VPS's AAAA in
      external, its PTR in internal). jarl zone suggest-reverse --all [--view V]. Both lists have a search, so hundreds of addresses stay
      manageable: the public addresses fold away, show 25 at a time, and
      Dismiss these N dismisses everything a search found in one change
      (--dismiss takes several networks).

    • Encrypted DNS: several host names (one certificate for all; the
      health check says when the served certificate misses one), and each
      listen address gets its own views
      for the host names' records
      (--address 10.0.10.5=internal, a view checkbox per address in the
      form), local to the view, with a warning when a public view would get
      a private address. A view no longer ticked loses the address. The form
      starts from where the records are now. The Certificates page and jarl cert show say what named uses a certificate for (DNS over TLS or HTTPS,
      on which addresses and ports).

    • docs/encrypted-dns.md: forwarding to Quad9 or Cloudflare over TLS, how to
      check it works, and why not over HTTPS.

    • Comparing one name across views: jarl zone diff adbraun.lol nas [A],
      and a Compare button on each record.

    • Exploring the statistics: jarld keeps every answer for a while
      (stats.retention.queries, default 7 days), and every client, name,
      view, record type, result and blocklist on the Statistics page leads to
      an explore page for it: answers over time, the top clients, names,
      views, types, results and blocklists among them (each a link that
      narrows it further), and the latest answers. "NXDOMAIN in external" →
      the clients asking → everything one of them asks. GET /stats/explore.

    • Storage on the dashboard: the size of Jarl's databases (and how many
      answers the query log holds), and per disk Jarl uses a bar of how full it
      is and how much of it the databases take. The Statistics page shows the
      statistics database's size too, and its disk tiles get the same bar.

    Changed

    • jarl option set tls NAME … (and key, remote-servers, http,
      dnssec-policy, server …) replaces only the statement with that name:
      setting tls cloudflare used to replace tls quad9. jarl option unset tls cloudflare removes one by its name.
    • Compare views and jarl zone diff are rebuilt around the view
      you're on (docs/views.md#comparing-views): a summary per view, then
      what is answered differently (a view's own records in linked zones,
      drift otherwise) with Use this everywhere, the names only some
      views have, grouped, with Add to VIEW, and how many are the same.
      One line per record: the CLI cuts long TXT records to the terminal
      (--wide shows them whole). --with picks the views to compare with.
      GET /zones/{zone}/compare returns these sections instead of rows.

    Fixed

    • Server options → Added by Jarl: long statements didn't wrap, and the
      browser console reported a Content Security Policy violation (an inline
      style the page's policy blocks).

    Upgrading from 0.5

    • Tested: 0.5.2 packages with views, a linked zone, a reverse zone,
      blocking, a tls statement and statistics, upgraded in place in Debian
      13 (BIND 9.20.29): everything kept and answered as before, the new
      features worked on the upgraded data, and a 0.5.2 backup restored.
    • The database gets two new versions (12 and 13), applied when jarld
      starts; a 0.5 jarld can't open it afterwards, so take a backup first (sudo jarld backup). Nothing changes until you turn auto_ptr on for a
      zone.
    • The statistics database gets a new version too (the query log); 0.5
      can't open it afterwards either. It starts empty and fills from then on.
    Downloads
  • v0.5.2 a3b054cc86

    Jarl v0.5.2
    release / release (push) Successful in 2m5s
    Stable

    adam released this 2026-10-12 20:12:04 +00:00 | 44 commits to main since this release

    Added

    • Mail reverse DNS check: the addresses of the public zones' MX hosts and
      SPF records are looked up as the internet sees them, every 6 hours: a
      PTR record whose name resolves back to the address, which Gmail and
      Outlook require. It says who runs the reverse zone (your provider) and
      what to set there, and notes when Jarl has its own reverse zone for the
      address, which only your clients see. The Exposure page (Check now),
      jarl exposure mail and Prometheus jarl_mail_reverse_dns_ok.
    • Added by Jarl: the Server options page, jarl option generated and
      GET /options/generated list what Jarl writes into named.conf by
      itself (keys.conf, the statistics channel and logging, blocking's
      response-policy, the view keys), why, and what controls each.
    • stats.rate_limit_log (default true): false stops Jarl adding named's
      query-errors category to its log channel when rate limiting is set.

    Changed

    • Option values with a list of three or more elements (allow-query,
      forwarders, listen-on, ...) are shown one element per line.
    Downloads
  • v0.5.1 d33f573782

    Jarl v0.5.1
    release / release (push) Successful in 2m6s
    Stable

    adam released this 2026-10-12 20:09:59 +00:00 | 46 commits to main since this release

    Added

    • Encrypted DNS health: jarld checks the DoT and DoH listeners every 10
      minutes as a client would (the certificate is for the host name,
      current and the one Jarl last wrote; a question gets an answer) and
      says what is wrong: nothing listening, a firewall, the wrong or an
      older certificate. On the Encrypted DNS page (Check now), the
      dashboard, jarl encrypted-dns health and Prometheus
      jarl_encrypted_dns_up.
    • Comparing a zone's views: the Compare views tab and jarl zone diff
      show the names and types that differ between the views that have a
      zone, linked or not, with "Use this version" to share one view's
      version. GET /zones/{zone}/compare.

    Changed

    • --local (and "local": true) works on zones that aren't linked too:
      their records are local anyway. --shared there is still refused.
    • When certificates.dir changes, jarld points the tls statements
      encrypted DNS wrote at the new place when it starts; named kept the old
      copies before, which renewals no longer updated.

    Fixed

    • Sharing a view's version of a name that was shared already (Use this
      version on the shared side) didn't replace another view's override; it
      said there was nothing to do.
    Downloads
  • v0.5.0 67ae0091b3

    Jarl v0.5.0
    release / release (push) Successful in 2m5s
    Stable

    adam released this 2026-10-12 19:30:17 +00:00 | 48 commits to main since this release

    Upgrading from 0.4

    • The database gets three new versions (internet exposure, certificates,
      linked zones), applied when jarld starts; a 0.4 jarld can't open it
      afterwards, so take a backup first (sudo jarld backup). Backups made
      by 0.4 restore into this version. Tested: 0.4.0 packages with views,
      zones, records, blocking and statistics, upgraded in place and
      restored from a 0.4.0 backup.

    • Statistics per view start with this version: earlier figures are for
      all views together.

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Changed

    • The web UI's top bar had grown too long, and the user name, Users and
      Log out ended up on a second line on the left. The server's
      configuration and security pages (Server options, ACLs, TSIG keys,
      Exposure, Certificates, Encrypted DNS, Audit log) are now in a
      Server menu, and Account, Users and Log out in a menu under your
      name. On narrow screens the search box and your name stay together on
      the right.

    Fixed

    • "update PTR" when editing a record (jarl record update ID --ptr) did
      nothing unless the name or address changed too, and the web UI didn't
      even send it alone: a reverse zone created after the record never got
      its PTR. Alone, it now adds the PTR record if it is missing (or enables
      it). For records of linked zones, the reverse zones of every linked view
      count, not only the record's own view.

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).

    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.

    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • Statistics per view (docs/stats.md): the
      Statistics page has a toggle per view, with All and None, remembered in
      the browser, to see some views only or several together (linked views,
      say). Answers, result codes, record types, zones, blocking, rate
      limiting and the top lists follow it; named's own counters stay for the
      whole server, and the page says so. jarl stats --view, API
      ?views=. Per-view figures start with this version.
    • DNS over TLS and HTTPS (docs/encrypted-dns.md):
      jarl encrypted-dns setup --hostname NAME --address ADDR (and the
      Encrypted DNS page) obtains a certificate for the host name if needed,
      checks that nothing else listens on port 853 and the DoH port (443 by
      default) at those addresses, offering a free port, and stages named's
      tls statement and listeners as one change, keeping port 53 where it
      was, plus the host name's records in your private views (local to the
      view in a linked zone). The page and jarl encrypted-dns say what to
      give Android, Linux, Firefox, Chrome and Windows. A tls statement whose
      files are missing is refused (tls_file_missing), and a certificate
      named uses can't be deleted.
    • Linked zones (docs/views.md): zones of the
      same name in different views can be linked, and Jarl keeps their shared
      records in step: a change in one view reaches the others in the same
      changeset (diff, permissions, history and undo cover every view). Each
      view can still have records of its own (--local, "Only here"), which
      override the shared records of that name and type there, and keeps its
      own zone options. Linking existing zones changes no answer: what is the
      same everywhere becomes shared, the rest stays local, and a view's
      version can be shared later (--shared, "Share"). jarl zone link and
      unlink, zone create --link-with VIEW, record add|set|update --local|--shared, a LINK column in record list, "Keep them linked"
      when copying a zone in the web UI, POST /zones/{zone}/link and
      /unlink. ACME challenges are written once per link, and --view all
      changes a link once.
    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads
  • Jarl v0.5.0-rc.1
    release / release (push) Successful in 2m4s
    Pre-Release

    adam released this 2026-10-12 19:25:12 +00:00 | 49 commits to main since this release

    Upgrading from 0.4

    • The database gets three new versions (internet exposure, certificates,
      linked zones), applied when jarld starts; a 0.4 jarld can't open it
      afterwards, so take a backup first (sudo jarld backup). Backups made
      by 0.4 restore into this version. Tested: 0.4.0 packages with views,
      zones, records, blocking and statistics, upgraded in place and
      restored from a 0.4.0 backup.

    • Statistics per view start with this version: earlier figures are for
      all views together.

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Changed

    • The web UI's top bar had grown too long, and the user name, Users and
      Log out ended up on a second line on the left. The server's
      configuration and security pages (Server options, ACLs, TSIG keys,
      Exposure, Certificates, Encrypted DNS, Audit log) are now in a
      Server menu, and Account, Users and Log out in a menu under your
      name. On narrow screens the search box and your name stay together on
      the right.

    Fixed

    • "update PTR" when editing a record (jarl record update ID --ptr) did
      nothing unless the name or address changed too, and the web UI didn't
      even send it alone: a reverse zone created after the record never got
      its PTR. Alone, it now adds the PTR record if it is missing (or enables
      it). For records of linked zones, the reverse zones of every linked view
      count, not only the record's own view.

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).

    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.

    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • Statistics per view (docs/stats.md): the
      Statistics page has a toggle per view, with All and None, remembered in
      the browser, to see some views only or several together (linked views,
      say). Answers, result codes, record types, zones, blocking, rate
      limiting and the top lists follow it; named's own counters stay for the
      whole server, and the page says so. jarl stats --view, API
      ?views=. Per-view figures start with this version.
    • DNS over TLS and HTTPS (docs/encrypted-dns.md):
      jarl encrypted-dns setup --hostname NAME --address ADDR (and the
      Encrypted DNS page) obtains a certificate for the host name if needed,
      checks that nothing else listens on port 853 and the DoH port (443 by
      default) at those addresses, offering a free port, and stages named's
      tls statement and listeners as one change, keeping port 53 where it
      was, plus the host name's records in your private views (local to the
      view in a linked zone). The page and jarl encrypted-dns say what to
      give Android, Linux, Firefox, Chrome and Windows. A tls statement whose
      files are missing is refused (tls_file_missing), and a certificate
      named uses can't be deleted.
    • Linked zones (docs/views.md): zones of the
      same name in different views can be linked, and Jarl keeps their shared
      records in step: a change in one view reaches the others in the same
      changeset (diff, permissions, history and undo cover every view). Each
      view can still have records of its own (--local, "Only here"), which
      override the shared records of that name and type there, and keeps its
      own zone options. Linking existing zones changes no answer: what is the
      same everywhere becomes shared, the rest stays local, and a view's
      version can be shared later (--shared, "Share"). jarl zone link and
      unlink, zone create --link-with VIEW, record add|set|update --local|--shared, a LINK column in record list, "Keep them linked"
      when copying a zone in the web UI, POST /zones/{zone}/link and
      /unlink. ACME challenges are written once per link, and --view all
      changes a link once.
    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads
  • Jarl v0.4.1-rc.5
    release / release (push) Successful in 2m3s
    Pre-Release

    adam released this 2026-10-12 18:34:01 +00:00 | 53 commits to main since this release

    Upgrading from 0.4

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Fixed

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).
    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.
    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • Statistics per view (docs/stats.md): the
      Statistics page has a toggle per view, with All and None, remembered in
      the browser, to see some views only or several together (linked views,
      say). Answers, result codes, record types, zones, blocking, rate
      limiting and the top lists follow it; named's own counters stay for the
      whole server, and the page says so. jarl stats --view, API
      ?views=. Per-view figures start with this version.
    • DNS over TLS and HTTPS (docs/encrypted-dns.md):
      jarl encrypted-dns setup --hostname NAME --address ADDR (and the
      Encrypted DNS page) obtains a certificate for the host name if needed,
      checks that nothing else listens on port 853 and the DoH port (443 by
      default) at those addresses, offering a free port, and stages named's
      tls statement and listeners as one change, keeping port 53 where it
      was, plus the host name's records in your private views (local to the
      view in a linked zone). The page and jarl encrypted-dns say what to
      give Android, Linux, Firefox, Chrome and Windows. A tls statement whose
      files are missing is refused (tls_file_missing), and a certificate
      named uses can't be deleted.
    • Linked zones (docs/views.md): zones of the
      same name in different views can be linked, and Jarl keeps their shared
      records in step: a change in one view reaches the others in the same
      changeset (diff, permissions, history and undo cover every view). Each
      view can still have records of its own (--local, "Only here"), which
      override the shared records of that name and type there, and keeps its
      own zone options. Linking existing zones changes no answer: what is the
      same everywhere becomes shared, the rest stays local, and a view's
      version can be shared later (--shared, "Share"). jarl zone link and
      unlink, zone create --link-with VIEW, record add|set|update --local|--shared, a LINK column in record list, "Keep them linked"
      when copying a zone in the web UI, POST /zones/{zone}/link and
      /unlink. ACME challenges are written once per link, and --view all
      changes a link once.
    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads
  • Jarl v0.4.1-rc.4
    release / release (push) Successful in 2m1s
    Pre-Release

    adam released this 2026-10-12 16:12:26 +00:00 | 55 commits to main since this release

    Upgrading from 0.4

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Fixed

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).
    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.
    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • DNS over TLS and HTTPS (docs/encrypted-dns.md):
      jarl encrypted-dns setup --hostname NAME --address ADDR (and the
      Encrypted DNS page) obtains a certificate for the host name if needed,
      checks that nothing else listens on port 853 and the DoH port (443 by
      default) at those addresses, offering a free port, and stages named's
      tls statement and listeners as one change, keeping port 53 where it
      was, plus the host name's records in your private views (local to the
      view in a linked zone). The page and jarl encrypted-dns say what to
      give Android, Linux, Firefox, Chrome and Windows. A tls statement whose
      files are missing is refused (tls_file_missing), and a certificate
      named uses can't be deleted.
    • Linked zones (docs/views.md): zones of the
      same name in different views can be linked, and Jarl keeps their shared
      records in step: a change in one view reaches the others in the same
      changeset (diff, permissions, history and undo cover every view). Each
      view can still have records of its own (--local, "Only here"), which
      override the shared records of that name and type there, and keeps its
      own zone options. Linking existing zones changes no answer: what is the
      same everywhere becomes shared, the rest stays local, and a view's
      version can be shared later (--shared, "Share"). jarl zone link and
      unlink, zone create --link-with VIEW, record add|set|update --local|--shared, a LINK column in record list, "Keep them linked"
      when copying a zone in the web UI, POST /zones/{zone}/link and
      /unlink. ACME challenges are written once per link, and --view all
      changes a link once.
    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads
  • Jarl v0.4.1-rc.3
    release / release (push) Successful in 2m2s
    Pre-Release

    adam released this 2026-10-12 15:32:48 +00:00 | 57 commits to main since this release

    Upgrading from 0.4

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Fixed

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).
    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.
    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • Linked zones (docs/views.md): zones of the
      same name in different views can be linked, and Jarl keeps their shared
      records in step: a change in one view reaches the others in the same
      changeset (diff, permissions, history and undo cover every view). Each
      view can still have records of its own (--local, "Only here"), which
      override the shared records of that name and type there, and keeps its
      own zone options. Linking existing zones changes no answer: what is the
      same everywhere becomes shared, the rest stays local, and a view's
      version can be shared later (--shared, "Share"). jarl zone link and
      unlink, zone create --link-with VIEW, record add|set|update --local|--shared, a LINK column in record list, "Keep them linked"
      when copying a zone in the web UI, POST /zones/{zone}/link and
      /unlink. ACME challenges are written once per link, and --view all
      changes a link once.
    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads
  • Jarl v0.4.1-rc.2
    release / release (push) Successful in 7m35s
    Pre-Release

    adam released this 2026-10-12 13:44:10 +00:00 | 60 commits to main since this release

    Upgrading from 0.4

    • New exposure warnings (docs/exposure.md) appear for views reachable from
      the internet, e.g. "no rate-limit" or "version visible" on an external
      view: fix them from the Exposure page, or acknowledge them. A change
      that newly opens a public view up (an open resolver, say) now needs
      --accept-risk, or the checkbox on the Changes page.

    • Once you use address ranges, the database can't go back to 0.4: its
      parser doesn't know them. Remove the ranges first if you need to
      downgrade.

    Fixed

    • Option values in the web UI looked different from the editor: a long
      line wrapped back to the left edge, losing its indentation, and the
      column changed width when Edit opened. Values now keep their layout
      (a long line scrolls), with the same width and padding as the editor.
      The "{ } around the list are optional" hint only shows for options that
      end in a list (not rate-limit, which only has one inside).
    • Query statistics skipped every query signed with a TSIG key (named
      writes "/key NAME" after the client's port), such as queries with a
      view's key: they are counted now.
    • A changeset with a staged record delete could not be applied after that
      record was deleted elsewhere (e.g. with the CLI), and it was hard to see
      which operation to remove: the error only said "record 832 does not
      exist". A staged delete of a record that is already gone now counts as
      done (with a warning), and the other operations that no longer apply
      (an edit or disable of a deleted record, a change to an object changed
      since) are named with their number and summary. The Changes page marks
      that operation and offers to remove it right in the error.

    Added

    • TLS certificates (docs/certificates.md): Jarl
      obtains certificates from Let's Encrypt or any ACME CA (account set up
      in jarl.yaml under acme.account) and renews them itself, from the CA's
      renewal information (ARI) or two thirds into their lifetime, with
      back-off after failures. It answers the DNS-01 challenges in a zone it
      serves, or through Porkbun's DNS API while Porkbun serves the domain;
      auto decides from the domain's public name servers at every renewal,
      so moving the domain to your own name servers needs no change. A CNAME
      on _acme-challenge into a zone Jarl serves is followed, for domains
      hosted elsewhere. A certificate is used for jarld's HTTPS ("web") and/or
      written for named (<bind.config_dir>/tls/NAME/, "dns"; named rereads
      it on renewal), and certificates you renew yourself can be used too
      (reread when their files change). Certificates page and dashboard card
      in the web UI, jarl cert (check, create, issue, update, delete,
      account), /api/v1/certificates, Prometheus
      jarl_certificate_expiry_timestamp_seconds, jarl_certificate_failing.
    • jarld serves HTTPS and plain HTTP on the same ports once it has a
      certificate (tls.cert_file, or one with the web use, which takes
      effect without a restart): plain HTTP from the server itself and from
      trusted proxies is served as before, browsers elsewhere are redirected
      to HTTPS and API requests get https_required. Before, with
      tls.cert_file, plain HTTP got an error even from localhost.
    • Internet exposure (docs/exposure.md): Jarl works out
      which views are reachable from the internet (match-clients ending in a
      catch-all; for a server without views, open allow-query and a
      non-private listen address), with a per-view override, and checks them:
      response rate limiting, open resolvers, ANY answers (minimal-any), cache
      snooping, open NOTIFY and zone transfers, BIND version and host name,
      management interfaces. Fixes are staged like any change, including
      response rate limiting from ISC's example in log-only mode, with your
      secondaries exempt, and a later "start enforcing". With statistics on,
      Jarl reads named's rate limiting log lines and shows what was (or would
      have been) limited: counts, client networks and names (Exposure page,
      jarl stats breakdown rrl, top lists ratelimited, Prometheus
      jarl_ratelimit_logged_total). A change that newly opens a public view
      up must be confirmed (checkbox on the Changes page, --accept-risk, API
      accept_risk; 409 confirm_risk otherwise). Findings can be
      acknowledged with a reason: they stay visible as info, with who, when
      and why. Exposure page and dashboard card in the web UI, jarl exposure (fix, ack, unack), GET /exposure.
    • jarl changeset show, diff, apply, discard and remove take the
      changeset from -C or JARL_CHANGESET when no ID is given
      (jarl changeset apply). A changeset from JARL_CHANGESET is now
      checked before it is used, for staging too: it must exist, be open and
      be yours, so a stale export (an applied changeset, or an ID that later
      turned into someone else's web UI draft) can't silently take your
      changes; the error says what to do. Commands say on stderr which
      changeset from JARL_CHANGESET they use, and apply/discard remind
      you to unset JARL_CHANGESET. -C and ID arguments are used as given.
    • Address ranges such as 10.0.10.101-10.0.10.199 or
      2001:db8::100-2001:db8::1ff (also ! negated, and with spaces around
      the dash) wherever an address match list is used: ACLs, views'
      match-clients and match-destinations, options such as allow-query, and
      blocking's client groups (docs/concepts.md). Jarl
      keeps the range as written and writes the fewest prefixes that cover
      exactly that range to named.conf, with the range as a comment. The web
      UI shows what a range becomes while you type it (GET /catalog/ranges). Mistakes are refused when entered: an end that isn't
      a full address, the start after the end, IPv4 mixed with IPv6, a range
      in an option that takes no address match list (forwarders). A range
      covered by an earlier element is reported as never matching, a range of
      every address counts as "any" for the open resolver and open transfer
      checks, and an IPv6 range in the IPv4-mapped space gets a warning. ACL
      names can no longer look like a range.
    • Prometheus metrics at /metrics (docs/metrics.md),
      set up in the new metrics: section of jarl.yaml (off by default).
      metrics.allow lists the addresses that may scrape (loopback by
      default), metrics.token lets anyone who sends it as a bearer token
      scrape, and metrics.listen adds addresses that serve only /metrics
      (for a Prometheus server elsewhere). Root and jarld's own user can also
      scrape on the local socket.
      • Health, always: named up, recursive and TCP clients against their
        limits, adopted, open changesets, last apply, validation problems by
        severity, drifted files, object counts, the last backup (and failure,
        and whether it is stale), blocking paused, each blocklist's entries,
        last check and change and whether it fails, the DNSSEC phase of every
        signed zone, and when API tokens expire.
      • With query statistics on: named's counters (queries, result codes,
        record types, UDP/TCP, authoritative/recursive, rate limiting, upstream
        round-trip times, DNSSEC validation, cache hits) and Jarl's (logged
        responses per view and zone, blocked queries per blocklist), as
        counters since jarld started, plus named's memory, CPU, threads, cache
        and sockets, and the collector's health.
      • Example queries and alert rules, checked with promtool.
    Downloads