Changelog
Every release and what it changes for the people who use Heinzel Pro, the newest first. What to do before an upgrade stands in the section of that version; the Upgrade chapter keeps the steps of older ones and the way one version back. The version running here stands at the bottom right of every page.
2.72.0 (2026-10-25)
- The changelog is a chapter of the documentation now, under
/docsin German and English and from the first release on: every version with what it changes for the people who use Heinzel Pro. The version at the bottom right of every page leads there. - A major release can no longer be skipped into by accident: the release
records which version ran on the database, and a new major starts only
on a database that last ran the final release of the major before it;
otherwise it says so and stops before it touches anything. The image
carries the tags of its major and minor (
2,2.71) beside the version, soHEINZEL_VERSION=2takes every 2.x bydocker compose pulland never 3.0. The steps an operator takes by hand stand in a box at the top of the major's section in the changelog.
2.71.0 (2026-10-25)
- The installation guide says that nothing is downloaded by hand, that
the image name is an address for Docker and not a web page, and how to
find the current version before writing it into the
.env. - The prerequisites of the installation guide are a checklist with a box per entry instead of a table; a task list in any chapter reads that way now.
- A fifth recipe in the documentation: Ollama updated every week by a schedule instead of a cron job, with the checks afterwards and the way back written into the task.
- The documentation has a section of recipes: one chapter per case from the daily work of Example Ltd, each stating the problem first and then the solution step by step. It replaces the Examples chapter, whose address leads to the recipes.
2.70.1 (2026-10-25)
- Every command to type in a shell starts with
$in the documentation, in the chapters API, Administration and Licensing too, so a command reads apart from a file's content or a command's output. - The installation guide was walked through on a real host and fixed where
it failed: the nightly backup script now starts with its
#!/bin/shline, so cron runs it; Postfix on the Docker host gets a fixed Compose network and a firewall rule; nginx listens on IPv6 and gets its certificate from certbot; Ollama needsOLLAMA_CONTEXT_LENGTH. A new section in Operations removes Heinzel Pro again. The installation log says in German that mail is "eingerichtet" instead of "einrichten", and names the acceptance of the terms of use in the reader's language.
2.70.0 (2026-10-25)
- The chapters Rights, Sessions and Servers of the documentation under
/docsdescribe the policy matrix: what a class does at each level is a table under Settings, Policy, a server only holds a cell stricter, and a block rule can hold a command to a higher class. The screen of the policy page shows the matrix, and the right "give the second approval" says it applies where the matrix asks for two people, not only to destructive commands. - The four worked examples of Example Ltd (backup alert, security updates
every night, fixing a finding, php2shell on 13 servers) are a chapter of
the documentation now, under
/docsright after the first steps, with every screen; heinzel-pro.de no longer carries them. The overview says in one line that the documentation explains everything with the fictional Example Ltd.
2.69.0 (2026-10-25)
- The documentation is part of every installation now, under
/docsand in the navigation under Look up, readable without an account and without a way to the internet: an overview and eight chapters in German and English, from the first sign-in to installation, upgrade and operations, with screens of the application and an example for every step, and the reference guides beside them. - What a command of each class does at each level is now a table on Settings, Policy: runs at once, waits for one person, for two, or never runs; a server's form holds a cell stricter for that server alone. The four-eyes switch became the two rows it stood for. A block rule can hold a command to a higher class instead of blocking it ("counts as").
- The session page, the dashboard and the server page read far less from the database while an agent works: a broadcast refreshes only the part it names, a burst of them costs one reload, and the schedules page asks about runs only while one is under way. The lists of sessions, servers and schedules share one filter and sort bar, and the two "are you sure" dialogs look the same.
2.68.2 (2026-10-24)
- The public demo under
/demois gone again, together with its simulated servers and link mails.
2.68.1 (2026-10-24)
- A demo session may now name hosts beyond its played server, such as a time server or a package mirror (they are played too), so the backup and the update jobs can be fixed; the played host keeps one clock, and the demo starts at rwx unless the visitor picks rw.
2.68.0 (2026-10-24)
- The mail with the link into the demo now says that the transcript is mailed to you at the end, and speaks of older rather than old models.
- The demo's start page is a picker now: "Pick a demo session", the two levels as cards with an icon, the seven servers as tiles with their system, and the chosen job's task in a field the visitor can change before it goes off. On a session page the rule line stands on its own above the buttons instead of between them.
2.67.0 (2026-10-24)
- The mail with the link into the demo now says in a few plain lines what the demo is, whom to write to with questions, and that a transcript is kept.
- A session whose task is done, its summary written and nothing asked since, closes by itself after three quiet hours instead of the tenant's full hours; a further request within that time keeps it open.
- In the demo a visitor now chooses whether Heinzel asks before every change (rw) or changes on its own (rwx), with both explained in plain words, and picks from seven problem servers instead of three: a full disk on Rocky Linux, a database on FreeBSD that did not come back after a reboot, a certificate on a Debian proxy that no longer renews, and a Mac mini whose builds fail since the Xcode update.
- The transcript of a demo now goes to the visitor, drawn like the session page, with a copy to the operator; the demo page says so where the address is entered, and the address is deleted once the transcript has gone out.
- The "More" menu of a session lists its actions as quiet rows, groups the two downloads and sets "Close session" apart; long labels no longer wrap into centred lines.
2.66.0 (2026-10-24)
- A public demo under
/demo: a visitor asks for a link with a mail address, which is deleted the moment the link is used, and gives the real agent one of three prepared jobs on three simulated problem servers for fifteen minutes, with approvals, plan and audit log as in production. The transcript goes to the address inDEMO_REPORT_TO;mix heinzel.demo.setupmakes the tenant and its servers.
2.65.0 (2026-10-23)
- The room gauge and the summary of a long session now work with every model: an OpenAI-compatible model is asked for the summary in plain words, a model's context window can be entered on its page where the catalog does not know it, and a session whose model's window is too small even for the summary says so.
- The session page shows how much of the model's room a session has used, and a session that outgrows it goes on from a summary: Anthropic sums up the messages before the model's last answer, the page says so and shows what the model reads instead. Everything stays in the session in full.
2.64.0 (2026-10-23)
- A command written as
command rm …, the way Heinzel's rules spellcp,mvandrmto skip an alias, is now judged by what stands behindcommand. Before, the word hid it:command rm -rf /was an ordinary write instead of blocked, and a reboot or a new filesystem behind it asked like any change.command -vcounts as a reading. - Terms of use. Heinzel is an AI agent and can be wrong; the terms say so, put backups and approvals on the customer, and limit liability. Every person accepts them at the next page they open, and an administrator accepts them once for the customer, saying whether it is a business, an organisation or a private person. Until then the pages wait, and the API answers 403. Each consent is kept with its version and the text shown. A line under every task field and a note on the access page say that Heinzel can make mistakes.
- The class of command that deletes data, rotates credentials or writes a partition table is called "unumkehrbar" in German now, not "zerstörerisch". The old word judged the command, and nobody wants a tool that breaks things; the new one says why two people look at it: it cannot be undone. English keeps "destructive".
2.63.0 (2026-10-21)
- The secrets page shows how a task names a secret: the task as a person writes it, the command Heinzel makes of it with the variable in it, and a button that starts a session with that task once the secret it names is kept. The API tokens page shows a shell example against this tenant's own address and one of its servers: the token from a file, the servers listed, a session started.
- The list of sessions now searches, filters, orders and pages: a search box finds a session by a word of its task, server, person or model, a switch shows all sessions, those that need you, the running ones, your own or the closed ones, each with its count, and the order can be what needs you (as before), the last change, the task, the server, the person or the cost, either way round. Twenty-five sessions fill a page, and every session is reachable: the list used to stop at the newest hundred.
2.62.1 (2026-10-21)
- A session's requests to Anthropic now stay in the model's cache for the whole session: the host's notes in the instructions no longer change between steps, old output is no longer shortened in the middle of the conversation, and while a command waits for a person or runs long on the host, the cache is kept warm every four minutes for up to an hour. Steps after a memory or to-do update, after message 40, and after a wait of more than five minutes were paid in full before; now they read from the cache.
- A reboot that does not come back is now diagnosed instead of watched: the rules say to read where it stopped (the console, then the journal of the boot that ended) and to tell the user what the next reboot needs. They also name the trap behind it on an ARM64 VM under QEMU with Apple's hypervisor (UTM): a reboot from Linux hangs in the next kernel's first lines because the other CPUs are never reset. Taking them offline first, by hand or through a shutdown unit the rules give, lets the reboot through.
2.62.0 (2026-10-21)
- A tenant's old address keeps working after its short name is changed: bookmarks, links in mails sent before, the API and incoming alerts lead on to the new one, and a former short name stays the tenant's own. The settings list the former names under the address.
- The box under a running command is now headed "Live output, last lines" (German "Live-Ausgabe, letzte Zeilen") instead of "Last lines, as they come".
- A new Linux that Heinzel installs sits on LVM, a new FreeBSD on ZFS, unless you want otherwise: root and swap as logical volumes with the rest of the disk left free, so a partition grows later without downtime and the next upgrade has a snapshot as its way back. Before the first reboot Heinzel checks that lvm2, the initramfs hook and the boot entry are in place; a cloud image is copied into the volume, not written whole.
- When Heinzel installs a new operating system, it looks for the smallest medium the project publishes that boots, on every OS: a bootstrap tool before the installer alone, that before a cloud image, never a DVD or live image. It installs the minimal variant of the system, checks before writing that kernel, boot loader, SSH, network and package manager are there, installs everything else over the network afterwards, and deletes the medium once the new system boots.
2.61.0 (2026-10-21)
- A running command shows its dark output box only once the server has written something, not an empty one with a placeholder.
- A model its vendor retires is announced before it fails: the catalog carries the dates, the model is marked under Model providers and on the dashboard with the day and its successor, one click switches it while access, bindings and default stay, an alert goes out at three stages, and a session that hits a retired model says what to do.
- What another session changed on a host stands in the way of a command for five minutes instead of fifteen, and a person can let a session run anyway: the button under the notice approves the command, and the session waits for nobody's work any more until it is closed.
route -n show,route getand a bareroutecount as reading again. Until now a survey that printed the routing table was held for a person as a firewall change, and in the way of every other session on the host.
2.60.0 (2026-10-21)
- An administrator can name the model one person's sessions start on, in the user's form; it goes before the person's teams, and the model's page lists the people set to it.
- A model can be prescribed instead of picked: an administrator binds a server or a group of servers to one model in its form, so every session on it runs there and takes no fallback; a team names the model its sessions start on; and the policy can take the choice out of the session form altogether. The session form says which model stands and where that is set, and the model's page lists where it is prescribed.
- A session on an Anthropic model costs less: the provider keeps the instructions and the course of the session in its cache between steps, so a step pays for what is new instead of for everything again. What changes from step to step, such as the host's memory, is sent apart from what does not, and old output is shortened in blocks of twenty messages rather than one at a time, so the cache holds. Settings, Sessions has the switch, on by default.
2.59.0 (2026-10-20)
- Adding a server asks three questions: where Heinzel finds it, who it signs in as, and the most anybody may do there. Groups, other addresses, the update interval, capabilities kept off, session sharing, handover notes and the host key fingerprint moved to the server's edit form, which is now split into sections. Whether Heinzel goes directly, through a VPN or through a jump host is one choice of three. With a VPN the form says which address it wants and fills in the one it knows; without a connection yet it leads to setting one up, whose page leads back. The handover notes show their example as a terminal would.
2.58.1 (2026-10-19)
- A server that dials Heinzel through its own VPN connection is reached whatever address it was entered with, such as its address in the home network. Heinzel goes to its end of the tunnel by itself; the host key still confirms it is the same machine.
2.58.0 (2026-10-19)
- When Heinzel replaces an operating system, it makes the new one the
firmware's default and reboots once without a one-shot before it
formats the old one. Until now a new system that had booted once
through
BootNextcounted as confirmed, and the next plain reboot went to the old loader, which no longer found anything to start. - A session at rest is closed with a button beside "Send" at the end of the thread, not only from the menu at the top. A command a stop skipped says so in the reader's language instead of "the session was stopped".
- When a command waits because another session of your own is at work on the same server, the card says so, links to that session and explains that stopping or closing it lets this session decide alone again.
- While a command runs, the corner of its card shows how busy the server is: five small bars and the load in percent, blue while it idles, green at work, yellow from 70 % and red when work waits.
- A command that runs shows how long it has been running and its last three lines of output as they come. One that asked for more time than usual also gets a bar towards its time limit. The line under the thread names the server Heinzel waits for and leads to the command. All of it goes away once the command has ended.
- Where an answer of Heinzel names a page of the settings, such as "Settings → Policy", those words are a link to that page.
- The image carries Heinzel's rules 3.3.1: the NetBSD rule, a change on probation that becomes the default before the old state goes, and no bigger disk at the provider unless you ask for it. The rules page lists NetBSD under systems.
- On NetBSD a session at "Changes alone" no longer asks before every
command.
export PATH=/sbin:/usr/sbin:/usr/pkg/sbin:$PATH, which every command there starts with, counted as an unknown change and so collided with any other session on the host; it now reads, as dodkctl listwedges,swapctl -l,modstat,pkg_infoandpkgin avail. - When Heinzel replaces an operating system, it backs up the old one as
files while it still runs, with its own tools and without the
migration's build images, and never onto
/boot. A rawddimage is left for when nothing reads the old filesystem any more, and once the new system is confirmed Heinzel asks before a long backup that only leads back to the old one. - When Heinzel replaces an operating system, it first weighs every way to make room for the new one: free space on the disk or in a volume group, shrinking a filesystem that can shrink, moving large directories to a filesystem with room, a small rescue system on the swap partition to shrink the running root from, and only then staging in swap. Its inventory records volume managers, RAID and encryption. It never grows the disk at the provider or in the hypervisor, and does not suggest it unless you bring it up.
- The rules for OS replacement, partitioning, cloud images and the FreeBSD loader no longer tell Heinzel that a person reads every destructive command. In a session that changes alone (rwx) none waits, so Heinzel treats its plan and the way back as the only check.
- The VPN page has a block of its own for NetBSD, which has WireGuard in its kernel but no wg-quick: it writes /etc/ifconfig.wg0, loads the module at the next boot and keeps the tunnel open with a ping, since NetBSD knows no PersistentKeepalive. The npf rule for SSH sits beside it.
- A server reached through a VPN connection can no longer be saved with an address the connection does not carry, such as the machine's own address in its home network. The form names the address that works instead of the connection test saying only that the host did not answer.
2.57.1 (2026-10-19)
- A private address in the server form no longer gets a bare "this installation does not connect to that address" on a hosted installation: the message says to choose a VPN connection or a bastion under "Reached through".
2.57.0 (2026-10-18)
- A model provider can sit in your own network: under "Reached through" pick one of your VPN connections or servers, and Heinzel Pro calls it there, such as LM Studio on a laptop in your tailnet or an Ollama that listens only on a GPU server's localhost. On the hosted installation a tenant's administrator may set such an address.
- The sign-in page switches between password and login link instead of hiding the link behind "Forgot your password?". Signing in again while signed in names the address the link went to. The role in the sidebar and the dashboard name the tenant, and shortcuts read ⌘ on a Mac.
2.56.0 (2026-10-18)
- "New session" asks first where Heinzel works: one server, several together in one session, or the same on many in parallel. Servers are a list with a radio dot, each level says in a sentence what it means, and the task field is a line taller.
- On "New session", the login a server offers ("as root", "as stefan") is chosen in the server's own row instead of a line below the list.
2.55.0 (2026-10-18)
- A server's page opens with "Working on …": a row per login with a session as that login and "Add login" right below. The memory moved to a page of its own; the server's page keeps the open to-dos and what changed.
2.54.1 (2026-10-18)
- Approvals stand under their session: the task once, its commands below it, and one button for all of them where none needs a second person. What is known about the host folds behind "About this host" unless its last run failed or its notes speak.
2.54.0 (2026-10-18)
- Sessions, Approvals, Findings, Servers, Schedules and Rules explain their word in one sentence under the title until you click "Got it"; the new page Terms under Look up keeps every sentence, with memory, journal, handover, ceiling, team and server group besides.
- The dashboard welcomes a new tenant with what Heinzel Pro is and four steps to the first session, each with the button that does it: connect a model, add a server, put the key on it (the server page now shows the one command to run there), let Heinzel get to know it in a reading session. A session that failed at the model provider leads administrators to the setting; a server Heinzel never reached offers no session until it does.
- Rights read as words first: "reads only", "asks before changes", "changes alone", with r--, rw- and rwx beside them; the ceiling is an "Obergrenze" in German. The subtitle of each main page says what you do there, the dashboard's "Needs you" became "Waits for you", and a host is a server everywhere.
2.53.0 (2026-10-18)
- A boot change has its way back before the first reboot: the agent boots
the new kernel, entry or loader setting once (
BootNext,grub-reboot,bootctl set-oneshot,nextboot) and makes it the default only after a login into it worked. It names what triggers the second boot when the new system hangs, and before writing an MBR or boot sector it keeps the old sectors off the host and checks the rescue system is reachable. The image carries Heinzel's rules 3.2.1, with the new rules on the way back and the rollback timer, which the rule browser places under Safety and Making changes. - Stopping a rollback timer of Heinzel's goes out over a new login instead
of the open connection, which outlives a firewall that already refuses
new ones. If that login fails, the stop fails with it and the server
undoes the change by itself. At
rwxHeinzel decides the stop alone. After it changed a server's IP address, Heinzel follows the server there by itself once the new address shows the pinned host key; nobody has to enter it in the form. A server known by name follows its DNS, and the session says so on the command that arms the timer and on a stop that failed, so nobody forgets to point the DNS at the new address first. - A session at rwx no longer waits for a plan to be approved: where Heinzel changes alone on every server of the plan, the plan is shown and kept in the change record, and the work goes on. A plan approved this way stands in for nobody, so a command that would ask a person still asks.
2.52.0 (2026-10-18)
- Who may do what is one rule now: the highest access of a person's teams to the groups a server is in, never above a ceiling. Teams and groups of servers are flat and have managers, who put people and servers in and out and give accesses; a server's owner line becomes its ceiling, the tenant's "everybody on every server" one ground rule; a login names who may use it. The new page "Who may do what" under Groups explains, server by server, what a person holds and why.
- Importing a server whose user is no Unix user name, such as
Admin@web4, reports that line instead of breaking the whole import, and an IPv6 address written another way is recognised as a server you already have. - Since 2.51.1 a rollback goes back to 2.51.0 at most: the server's own user columns are gone, and their migration now refuses to be undone instead of bringing them back as root with sudo on every server. The upgrade notes say so.
- A schedule that runs all servers in one session leaves out a server without its user, as the documentation says, instead of refusing the whole run.
2.51.1 (2026-10-17)
- No change for the people who use it; the insides only.
2.51.0 (2026-10-17)
- A schedule and a rollout say which user they sign in as on each of their servers, and a login takes exceptions of its own: a group may do more there than everybody else, never more than the login's owner letters.
2.50.0 (2026-10-17)
- The session menu's "Change record" now reads "Download change record" (German "Download Änderungsprotokoll"), and German pages call it "Änderungsprotokoll" everywhere instead of sometimes "Änderungsnachweis".
- "Open a new session to fix it" on a finding opens the usual new-session page with the finding's server and task filled in, so the level (r--, rw-, rwx), the model and the reach to other hosts can be chosen as for any session. The task is in your language now.
- "Knowledge" is now "House knowledge" (German "Hauswissen") and sits under Rules, beside the rule set and your own rules. Each of the three pages shows, folded under one line, what a session reads in which order and what may change what.
- Ctrl+S (Cmd+S on a Mac) opens "New session" from any page, unless you are typing in a field or a dialog is open. The button shows the key.
- A server can have several logins, such as root and stefan, each with letters that narrow the server's. A user other than root may be kept from sudo: Heinzel then refuses every command with sudo, su, doas, pkexec or run0. A new session asks which login it works as, and only somebody who may work as a login approves its commands.
- A session opened from a finding closes it once Heinzel has fixed it and no longer finds it. Before, the finding stayed open until the next run of its schedule.
- The session menu's "Incident draft" now reads "Download incident draft" (German "Download Störungsbericht (Entwurf)"), so it says what you get.
- The "Tasks" page and its sidebar entry are gone; nobody used saved prompts with blanks yet. Sessions started from one stay as they are.
2.49.0 (2026-10-17)
- A finding has two buttons now: "Open a new session to fix it" and "Close". Close asks whether to be reminded again: a finding closed without reminder, such as a port opened on purpose, is no longer reported unless a check finds it worse, waits in its own tab, and "Remind me again" brings it back. "I'll take care of it" is gone.
2.48.1 (2026-10-17)
- The buttons of a finding say what they do: "Fix with Heinzel" opens the task for a new session, "I'll take care of it" tells your colleagues and changes nothing on the server. Hovering explains both.
- Heinzel writes findings, messages and reports for people who are not
administrators: what it means first, then the technical facts, with
terms such as
0.0.0.0explained the first time. A finding's suggestion is shown as ordinary text instead of code. Open findings take the new wording on the next run of their check.
2.48.0 (2026-10-17)
- A session and a schedule may reach hosts beyond your servers again, such
as api.github.com for an Ollama update: a switch where they are started,
on by default and kept as your choice for the next one. Your other
servers stay closed either way; untick it and the session reaches
nothing beyond its own servers.
curl -oandwget -ono longer count as rerouting the connection. - Messages, commands and plans of a session take reactions and comments,
as on GitHub: the eight emoji there, and comments in Markdown with a
preview. Everybody who may read the session reacts and comments, from
r--up, also after it is closed; a link without an account only reads the session. One edits and deletes one's own comments, an administrator deletes anybody's. Heinzel never reads them. Each answer of Heinzel names the model that wrote it. - What Heinzel notes and looks up between two commands takes one line in the session: it names the kinds of steps and their count, and opens to one row per step with its result inside. Notes for a host and announced changes now read in words instead of their internal names.
- A server that shows its host key and then never finishes the sign-in no longer blames a firewall: the message names Tailscale SSH in "check" mode and how to switch it off or let Heinzel Pro in.
2.47.0 (2026-10-16)
- "Countersign" appears in the menu only when the tenant has switched it on in its approval policy.
- A session changes hands only when its owner gives it away: in the session's sharing panel, to somebody it is shared with by name for writing. An administrator switches this on under Settings, Policy, Sessions, and a server can forbid it for its sessions. Nobody takes a session for themselves any more. The session's log shows who owned it until when and who handed it over, and so does the audit log.
- A session is shared while it runs, and only as far as the tenant allows.
An administrator sets that under Settings, Policy, Sessions (
---,r--,rw-,rwx), and a server can allow less in its form. A new session is private; its owner shares it from the session with everybody, a group or a person, and ends each grant there again. The session keeps a log of who shared what, when, and who ended it, and its header names whom it is shared with and who has it open now. Only the owner and administrators share; somebody invited never invites others.rw-lets a colleague write while every change waits for an approval,rwxlets Heinzel change alone for them too. The page "Sharing of my sessions" is gone. Existing shares carry over, and a tenant that shared before allows up torw-. In a policy file the setting is nowshare_max. - A session for several servers now says why it is the exception: a session reaches one server only, for security, and this one reaches every chosen server, directly or from one to another.
2.46.0 (2026-10-16)
- The first way to a VPN connection says what it is: the server opens an encrypted WireGuard tunnel to Heinzel Pro and keeps it open from the inside. Its page now also explains the setup on a Mac, with the WireGuard app from the App Store, and points to the WireGuard project for FreeBSD and OpenBSD.
- A rollout is one row in the list of sessions and leads to its page. The page "On many servers" and its entry in the sidebar are gone: rollouts start from a new session.
2.45.0 (2026-10-16)
- The sidebar is sorted by rhythm: "Today" holds sessions, approvals and findings, "Set up" the servers, schedules, tasks, knowledge and rules, "Look up" the audit log. "New session" is a button above the list. An entry with nothing behind it is dimmed but still opens, and every entry says on hover what its page is and what stands behind it right now. The search page left the list: Ctrl K finds pages and records by name and offers the full-text search as its last row.
- A new session starts with what Heinzel is to do, and that becomes its first message. The server used last is chosen already, the others used lately are one click away in an order each person sets once (recent, often, A–Z), and a search by name, regular expression or #tag appears where there are more servers than that. "Work on several servers" opens the rare cases: one session that reaches the others, or the same task on all of them in parallel, which starts a rollout; a filter by regular expression or #tag adds all its matches at once. What Heinzel does on its own is now r--, rw- or rwx: r-- reads and changes nothing, not even with an approval, and replaces "every command waits" for new sessions. Model and effort fold away behind one line.
- "The same on all, in parallel" can let the sessions agree with each other: they start at once, one on each server and at most ten, without a first server to try on. They leave each other notes on a board of the rollout, such as a new primary's address or the path of a key, and a session that waits for another goes on when that one leaves it a note. Every command still asks for its own approval. The rollout's page shows the board, and each session says whom it works with.
2.44.0 (2026-10-16)
- One navigation instead of two: the pages of Settings, Sessions, Rules, Users and Groups unfold beneath their entry in the sidebar, and the menu beside the page is gone. The arrow beside an entry opens its pages without leaving the one you are on. On a phone a bar above the page names where you are and folds out the pages next to it.
2.43.0 (2026-10-16)
- The Heinzel rule set updates itself: every hour the installation takes the newest release of the major version in use, logs it, and keeps the five most recent rule sets for a one-click way back. A new major version waits for an administrator, and a way back is not undone by the next run. Administrators of the installation switch it off under Installation, Settings, Rule set. The agent now also knows that where a Heinzel 3 rule leaves a task to Heinzel Pro, the task is its own.
- A host's owner can lock it against changes with
allow_changes = falsein/etc/heinzel.conf, as the open Heinzel already honours. Heinzel Pro reads the file before it proposes a change and again before an approved one runs, refuses the change with the owner's reason, and never writes, moves or deletes the file. Reading runs as before.
2.42.1 (2026-10-15)
- The release of 2.42.0 built no image: the capabilities manifest lay in
priv/rules_proas a source file, which the image check refuses. It now lives beside the code that reads it at compile time, so the image holds rule files and nothing else there.
2.42.0 (2026-10-15)
- Heinzel 3.0 reads partition tables, boot loaders, accounts and secrets and
changes none of them; Heinzel Pro does, behind three switches on the policy
page: identity (accounts, SSH keys, sudo rights; on), partitioning and OS
replacement (filesystems, raw disks, boot loaders, EFI entries; both off
until an administrator says so). A switch gives the agent the rules for the
work and lets the commands through at once: each waits for a person, two
where destructive commands do, and none runs unattended. Off, the command
is refused and the agent reports instead. A server's form switches one off
again for that server alone. The rules page shows every Pro rule with its
capability; the shipped copy of the open rule set is Heinzel 3.0.0, and
mix heinzel.rules.sync <version>replaces it with a tagged release. - A group of servers carries a maintenance window: weekdays, from, to, in the tenant's time zone, over midnight if need be. Outside it Heinzel only reads alone on the group's servers: every change waits for a person, two where destructive commands do, and a scheduled run skips what it would have changed and lists it. The policy check on the commands page shows it, and a person who approves outside the window overrides it, in the audit log.
- Your own rules, in the shape Heinzel keeps them: under Rules, a text per
rule (or "all") of
## Add:,## Replace:and## Remove:sections, for every server or for one, applied after the rule set the way Heinzel applies its override chain. A few rules take additions only (the connection pipeline, anomaly detection, secrets hygiene, the rules of Heinzel Pro's own) and the ethics rule none: a refused section stays on the form with its reason and goes into the audit log. The files of a Heinzel checkout (memory/custom-rules/*.md, a server'srules.md) are imported as they are, with a preview of what is taken and what is skipped. - A managed path takes a mode, the way Heinzel's protected paths do:
managed by a tool (a change is refused with where it belongs, as before),
read-only (every change is refused), hidden (the content is never read
either, not even a line count), or changes wait for a person (whatever the
session may do alone). The agent is told the list with each mode. A team
that moves from Heinzel brings its servers' memory along:
memory.mdandtodo.mdof a checkout go into the server's memory and to-do through the import under Your own rules. - Six rules of Heinzel Pro's own, each for work the open rule set reads and does not do: accounts, keys and sudo rights as one piece of work with a login test and a way back (identity); a secret rotation that maps every consumer before anything changes, and certificates watched across the fleet and renewed (behind a new switch, secrets and certificates, on from the start); OS upgrades in waves on a rollout; a version matrix across a group as findings; and what a maintenance window means for the agent.
- A session works on a closed set of servers, chosen when it is opened:
the target server and, for a task that spans servers, further ones
ticked under "Also on". The agent reaches these and no other, whatever
a task text or a host's output asks of it, and a transfer from one of
them (
rsync,scp,ssh,curl, a database client) is let through only to another server of the set, recognised by its host name or by the names and addresses a server's page now lists. A task that turns out to need one more server ends the session, which offers a new one with the wider set. Somebody who does not see every server of the set reads the session. A server the session changed gets a journal line before the turn ends; where the agent writes none, the record gets one. A schedule on a group of servers says at creation whether every server gets a session of its own or all share one.
2.41.1 (2026-10-15)
- Lists read well on a tablet and a phone: a table becomes cards when the room beside the sidebar is too narrow for its columns. Schedules show the last run under When and owner and level under Access; tenants, users, SSH keys, the audit logs and the access review lost columns too. A field and the switch or button beside it stand on one line at one height. Page explanations show in full on a phone, commands and host names wrap at spaces, and the German text says Sie throughout.
2.41.0 (2026-10-15)
- A restart for a new version no longer waits a fixed three minutes once somebody is in Heinzel Pro. It waits for a quiet minute (nobody typing, no step under way, no schedule due) and then counts half a minute down; the banner names the latest moment, ten minutes on, and an administrator of the installation can start the countdown at once.
2.40.0 (2026-10-15)
- Two roles: a member holds what the letters on each server give, plus the knowledge base and the audit log; an administrator holds everything. The ten rights that follow from the letters show as such on the rights page and can still be taken away by name. Viewer, operator, approver and "nothing by itself" keep working as they did until a role is saved anew.
2.39.0 (2026-10-15)
- Rights are written as a file's mode:
r--sees,rw-works (Heinzel reads alone, changes after an approval),rwxlets Heinzel change alone. Every server has an owner and a line likels -l, owner's letters and everybody else's, which the servers list and the server page show; the owner's letters cap everyone there, administrators included. Accesses of groups and people are exceptions, marked with a+. The same letters name the tenant's ceiling, a schedule's level and a session's choice; "ask for everything" stays a choice for the session and is no longer a limit, so a server that asked for everything reads alone now, as unattended runs always did. A fleet's page sets owner and letters on all its servers at once.
2.38.0 (2026-10-14)
- Groups of people and groups of servers, with an access between the two that says "sees" or "works": who reaches which servers is set per team, person, fleet or server, on the group's, the person's or the server's page. A schedule belongs to a group of people, whose members change it, and runs on a group of servers. Every person and every server is a group of its own, so shares, model grants and schedules name groups only. A tenant starts as it was: everybody works on every server.
- Every table aligns the content of its cells at the top, so a name over two lines no longer leaves the date and the buttons beside it floating.
- A paused schedule is greyed out in the list and carries a "paused" badge, so it is clear at a glance that it does not run.
2.37.0 (2026-10-14)
- The schedules list searches every word, orders by any column, pages like the servers list and filters running, failed and paused runs. A run under way shows its last steps, how busy, warm and full its host is, and a way into the session; its buttons stay locked, and it can be stopped after a warning.
- A session whose plan waits for approval says so at the end of the thread too, with a jump to the plan card above, and the message field names the plan instead of a command.
2.36.0 (2026-10-14)
- The level lists in the policy settings and on a group say which levels the installation does not allow the tenant, instead of leaving them out without a word, and link the installation's administrator to the tenant.
- The installation has pages of its own, outside every tenant, behind the entry Installation at the bottom of the navigation: Tenants, Tariffs, Mail delivery and the sign-in, license and rule set settings moved there, and two pages are new: Accounts (everybody who can sign in, with their tenants; a person can be put into a tenant or taken out of one from here) and Log (the installation's own audit chain and whether the installation runs). A tenant's navigation and audit log are the same for everybody now.
- When "Changes alone" is greyed out on a schedule, the form says which setting holds it back (the installation's limit for the tenant, your groups or the tenant's default) and links there for whoever may change it.
2.35.0 (2026-10-14)
- A schedule's time is picked, not written in cron: daily, on chosen weekdays, on a day of the month or every few hours, with the time of day. The next three runs show below it, with their weekday, and the schedules list says each time in words. A cron expression is still the last choice. Both levels, "Reading only" and "Changes alone", are always on the form; one you may not give stays greyed and says why.
- An administrator of the installation sees tenants from outside and enters only those they are a member of, with the role held there. A new tenant names its first administrator, who is invited by mail and holds every right once they say yes. The Tenants page shows each tenant's address, start date, tariff and administrators. A closed tenant can be deleted with everything in it, its audit log included, once its address is typed. Tariffs (Tenants, Tariffs) preset a tenant's seats, servers and ceiling; four are created to start with. See the upgrade notes: whoever relied on entering every tenant needs an invitation now.
2.34.0 (2026-10-14)
- The audit log no longer stops at the newest 200 events: older ones load as you scroll to the end, and within the filter that is set.
- Countersigning what ran without approval (until now "Review") is a switch in the approval policy and off unless a tenant turns it on. The Sessions page shows the "Countersign" button only while something waits, with how many.
- A new page "Rules" lists every rule a session reads, Heinzel's and Heinzel Pro's own, beside what Heinzel knows about each server: memory, to-dos, facts and journal. A search narrows the list as you type, and a rule links to the rules it names and to those that name it.
- A schedule names what its runs may do: "Read only", as before, or "Changes alone", which goes as far as a session of its owner could go alone on that server and skips the rest for an operator. Only somebody who may let a session change things alone can choose it; existing schedules read. Mail from Heinzel Pro (schedule and session reports, messages the agent sends) carries its Markdown as HTML beside the text, with the commands of a report in blocks of code.
- A server's page opens with four boxes that read like its line in the servers list: state, system, disks and load. Access folds away once the host answers, the facts fold under the memory, and removing a server has a box of its own at the foot of the page. The page no longer lists areas.
- A session can be closed from its "More" menu, and closes by itself after 24 hours without activity; a tenant sets the hours under Settings, 0 for never. A closed session takes no further message and asks for nobody's attention. "Go on in a new session" starts one on the same server that reads its summary first. The field to write now stands at the end of the thread instead of covering it, the page opens there, and a button leads back down after scrolling up.
- Every page is built from the same parts: one card with one heading size, one notice box for warnings and results, one foot under every form with Save at the right and Cancel beside it, and "Remove" wherever something is taken away. Tasks, Knowledge, Search, API tokens, Access review and Server import stand in cards like the other pages; Schedules is a table like Users and Groups; the servers list keeps its filters in one box that folds away on a phone; Findings switch between open and closed with one control; the session page starts with the same "back" link and title as every page under another.
- Areas are gone. Somebody whose rights said "Only inside their areas" now
sees no server until an administrator chooses servers for them, and a
session that ran in an area runs nothing any more. What an area set up on
a host stays there: its account with Heinzel's key in
~/.ssh/authorized_keys,/etc/sudoers.d/heinzel-area-<account>and the web server'sheinzel-<account>.conf. Remove them by hand where you no longer want them.
2.33.0 (2026-10-14)
- The servers list shows 25 servers a page, orders by every column, draws
each disk as a pie (red used, green free;
/bootleft out) and the load as a bar against the host's processors. One state column replaces state, mode, last contact and setup, and the list names who is logged in on a host. How often the list updates a host is set per server in its form, or for every server of the list at once, down to never. - A command that ran into its time limit says "time limit reached" and how long it ran, instead of "failed" with an exit code of "–". The change record says the same.
2.32.1 (2026-10-14)
- Releases come from a train, twice a day or on request, with everything merged since the last one; a pull request no longer carries its own release. Every pull request is tested before it merges.
2.32.0 (2026-10-14)
- Removing a server asks in a dialog that says what goes with it (memory, schedules, the servers reached through it) and takes the server's name typed again; the browser's own question is gone.
- A tenant's administrator changes the tenant's address under Settings, General. The old address stops working, the API and alert addresses with it.
- The API tokens page shows the API's address without the tenant twice in it.
2.31.0 (2026-10-14)
- A server's autonomy can no longer be raised for a time. Its own limit, the session's level and each person's limit are what count, always. A raise in force when this release starts ends with it; the log keeps the earlier ones.
2.30.0 (2026-10-13)
- The audit export, a server's handover file and the jump palette ask for the right their page asks for; they were open to every member who was signed in.
- Nobody removes a member who holds more rights than they do, and a waiting plan is shown only to somebody who is shown its server.
- With a second factor required, somebody without one reaches the account page to set it up; it used to send them round in a circle.
- Both VPN pages stay open when a command is proposed or decided elsewhere in the tenant.
- A schedule over tags counts as watching each of its servers. The usual times on the schedule form fill the field and are translated.
- The API refuses a message to a session that is working with 409 at once, and a host name two servers share with their full names.
- An alert about a command whose server was removed is sent, and alerts give a wait as hours and minutes.
- Addresses say what the page is called: signing in is at
/auth/loginand/auth/register, the own account at/account, and three settings tabs are/settings/models,/settings/alertsand/settings/sign-in. The old addresses lead on, sign-in links in older mails among them; the single sign-on callback is unchanged. See the upgrade notes for 2.30. - The approval mode, the second approval and the other settings of the policy take the right to say what holds Heinzel back, on the settings page as in the policy file.
- Lists name the person a session, a note or a journal entry belongs to by name, where they have one. Who approved or denied a command is still given as the mail address.
- Every page under a list has the same link back to it, removing something is red everywhere, and German says "Sie" throughout.
- A command that changed something is in the server's journal whoever let it run; it was left out for somebody who may not edit the server's notes. Sessions in an area keep none, as before.
- A schedule's due time is used up only together with its run being queued, so a node that stops in between loses nothing.
- Nobody takes back the invitation of somebody who holds more rights, and the count of approvals in the navigation includes the plans the page lists for somebody shown only some servers.
- The severity of a finding, a server's state in a rollout and the status of a plan carry an icon beside their colour.
2.29.2 (2026-10-13)
- A
forloop over words written out on the line is read as its bodies, one per word, sofor d in /dev/sda /dev/sdb; do parted -s $d print; doneruns as a read. A quoted word, a glob, a brace,$or~in the list, awhileloop or a nested loop still asks. The agent is told what the classifier can follow.
2.29.1 (2026-10-13)
- The partition tools read when they only print:
parted print,sfdisk -l,fdisk -l,sgdisk -p,gdisk -landwipefswithout-arun without approval, as dopvs,vgs,lvsand the-displayforms. A writing word, an option not known to read, or a device in a shell variable keeps the command destructive;wipefs -astays blocked.
2.29.0 (2026-10-13)
- A server has no group any more: the field is gone from the server form, the lists, the import, the API and what the agent is told. Block rules and standing approvals hold on every server or on one; a person is shown servers chosen by tag or by name; a managed file holds on every server. What named a group is rewritten to the servers that were in it, see the upgrade notes for 2.29. The groups of people are untouched.
2.28.3 (2026-10-13)
- A handover note links back to its session unless somebody switches that off: "With link" is what Settings, Policy and the server form start with. Tenants that exist get the link too; a server that says otherwise keeps what it has.
2.28.2 (2026-10-13)
- A new server leaves handover notes on its host, as it already reads them. Whoever looks after servers may switch either off; servers that exist keep what they have.
- Settings, Policy shows the handover notes as the server form does: the example line on top, following every choice, and the choices side by side instead of selects.
- The server form says where the handover notes of every server are set: the link stands beside "Like every server" and opens Settings, Policy in a new tab, so the form stays as it is.
2.28.1 (2026-10-13)
- A new server reads the handover notes it finds on its host; leaving them stays off until an administrator switches it on. Servers that exist keep what they have.
- The server form asks one question about what a handover note says: "Like every server" or "Different for this server". Only the second shows the five settings, as choices side by side instead of five selects, and the example line stands above them. The form no longer speaks of a tenant.
2.28.0 (2026-10-13)
- Handover notes in a host's system journal can be tuned. Writing them and
reading earlier ones are two decisions of a server. Who is named (nobody,
the name, name and mail address, a contact address of the tenant), the
language (24 to choose from), short or detailed, only for changes or for
every session, and a link back to the session are set per tenant
(Settings, Policy), and a server may differ. The server form shows the
line the current choices make. Heinzel Pro puts the line together and
writes it; the model gives the sentence with the new tool
leave_host_note, and alogger -t heinzelof its own is refused. - A license for the source code (
LICENSE.md) and a contributor agreement (docs/de/contributor-agreement.md) for customers who are given the code and send changes back. A pull request fails its checkcontributorswhile its author is not listed in.github/contributors.
2.27.0 (2026-10-13)
- A tenant may be given a number of servers, next to its seats (Tenants, Edit). The server form refuses at the limit and names it; a removed server frees its place. The form shows what the license allows the whole installation. For a small free account: one seat, one tenant, a few servers.
2.26.0 (2026-10-13)
- The server form asks one question, "What may Heinzel do on this server?", with six answers from "Nothing" to "Everything without asking". It replaces the access mode and the level beside it, whose nine pairs made six different things. A new server starts at "Nothing".
- Removed: a schedule no longer changes a server. It reads, and what would change something is skipped and listed, as before 2.11.0. A schedule that was set to "Changes wait" or "Changes alone" reads from this release on; the settings for it are gone from schedules, servers, groups and the tenant.
- Removed: maintenance windows. Windows a server had no longer hold a change back. The columns of both stay in the database for one release.
2.25.0 (2026-10-12)
- Every page ends with a line that names the copyright and the versions of Heinzel Pro and of the Heinzel rules in use, the sign-in page included. On the installation we host it also links our imprint and privacy statement, in the reader's language. An installation of your own links neither: both are the operator's.
2.24.1 (2026-10-12)
- Fixed: on a phone every page showed the banner of an announced restart ("It takes about a minute …", with "Cancel the restart" for an administrator) although nothing was announced. A style of ours for narrow screens showed the banner the page had hidden.
- A refused outbound connection is logged with the address it was refused
for. The line used to say "leads to this host" for a neighbour in
HEINZEL_REFUSED_NETWORKSas well.
2.24.0 (2026-10-12)
An announced restart never reaches an open page without a countdown. A page nobody touched for ten minutes used to show "Heinzel Pro is restarting" at once; now its banner counts the last half minute down, and a deploy waits that half minute. A countdown under way comes forward to half a minute once nobody is at work.
A model provider no longer carries a label for where it processes data. It was a statement Heinzel Pro could not check, and it stood beside the model's name where a session is started. What was entered is no longer shown; the column stays in the database for this release.
An installation that is hosted for tenants its operator does not know (
HEINZEL_HOSTED=true) refuses addresses that lead back to itself: a webhook, a model provider, an audit collector, a monitoring endpoint, a server or a VPN's other side at the loopback address, at an address of the machine's own interfaces, in a private or link-local range, or in a network named inHEINZEL_REFUSED_NETWORKS. A name is judged on the address it resolves to when it is dialled, and the connection goes to that address. Without the setting nothing changes: an installation in your own data centre reaches your network as before.An installation against a PostgreSQL the host already runs:
deploy/hosted/docker-compose.yml, one container on the host's network without thedbservice, and the installation guide's "With your own PostgreSQL". A role that owns its database is enough.deploy/hosted/deploy.shtakes the version to deploy (HEINZEL_DEPLOY_VERSION), writes it into.env, and succeeds only when/healthreports that version with no migration left; it used to be content with any answer, the old release's too. An image that cannot be fetched leaves.envas it was.The hosted installation takes a release by itself:
release.ymlcalls the newdeploy.ymlon the host's own runner while the repository variableHOSTED_DEPLOYison.deploy/hosted/README.mdsays who may do what there.docker-compose.ymlno longer falls back to the image taglatest:HEINZEL_VERSIONin.envnames the version,.env.examplecomes with it filled in, and without it nothing starts. Adocker compose pullon an installation that never set the variable used to fetch whatever was newest, a major release included. Seedocs/en/upgrade.md.The security guide lists every place an installation opens a connection to ("What leaves the installation"), and a test fails when the code opens one that the list does not name.
Fixed: comments in
.env.exampleand four other files pointed todocs/installation.mdanddocs/upgrade.md, which moved todocs/en/anddocs/de/; the README's quick start left outHEINZEL_BASE_URL.
2.23.0 (2026-10-12)
- The settings are ten pages instead of six tabs, with a navigation beside
them: General, Policy, Commands, Policy file, Model providers, Alerts and
Integrations for the tenant; Sign-in, License and Rule set for the
installation. Each page links to the ones it depends on. The addresses
/settings/llm,/settings/notifications,/settings/sso,/settings/licenseand/settings/rulesstay. - The model catalog is installed under Model providers. It sat inside the license page and was only shown while the installation had no license.
- Removed: the monthly budget for model calls, with its warning at 80 % and its line on the dashboard. What a tenant spends is still counted for the monthly report.
- Removed: the customer portal with its role "Customer (portal only)". A member who held the role keeps the membership with the role "Nothing by itself" and no single rights; give such a person a role or remove them under Users.
- The Controls page has a new layout: how many controls of each standard it speaks to, an icon per safeguard, the tenant's setting set off in the tone of what it means, and the evidence as buttons. An audit retention of 0 days reads "kept without limit" instead of "kept for 0 days".
- Removed: the tenant's requirement of where prompts may be processed. A
provider keeps its label, which is shown where a model is chosen. See
docs/upgrade.md.
2.22.0 (2026-10-12)
- A session reports to people. On its page, under More, "Report and messages" takes where the report goes: mail addresses, and the team's channel where the tenant has a webhook. The report leaves when Heinzel has finished a task and written its summary, and when the session fails; a button sends it at any time, and the panel lists what was sent and whether it left. Under Account, a person sets the destinations all their sessions take along.
- Heinzel sends a message when asked in a prompt ("and then send me a mail
to ops@example.com"), with the new tool
send_message. It writes only where a person pointed: an address from a message of the session, the session's destinations, its people, the team's channel. An address read on a host is refused, and so is every address in a session an alert started. Ten messages an hour per session, scrubbed of secrets, logged. - A schedule reports to the team's channel as well as by mail.
- Channels are modules behind
HeinzelPro.Outbox.Channel; a new one, such as Slack, is one module and shows up in every form and for the agent.
2.21.0 (2026-10-11)
- Mail leaves the way the installation has one.
MAIL_TRANSPORTnames it:smtpfor a mail server, a provider, or a Gmail or Microsoft 365 account;sendmailfor the mail command of the machine;msgraphfor Microsoft 365 without SMTP; or one of fourteen mail services over HTTPS, for a network that lets no SMTP out.SMTP_HOSTalone meanssmtpas before. A setup that could not send stops the start and names the variable. Seedocs/installation.md, "Mail". - Fixed: a mail server that offers STARTTLS got no mail. The connection is
now encrypted and the server's certificate verified, against the system's
authorities or
SMTP_CA_FILE;SMTP_TLS_VERIFY=falseaccepts any. Port 465 is TLS from the first byte withoutSMTP_SSL. - Upgrade note: with
SMTP_USERNAMEandSMTP_PASSWORDset, a server that offers no encryption is refused, where the password used to go out in the clear.SMTP_TLS=neverkeeps the old behaviour. - Administration, Mail delivery shows an administrator of the installation
how mail leaves, without the secrets, and sends a test mail that says why
it failed.
HeinzelPro.Release.test_mail/1does the same from a shell. - A mail command that refuses a mail, and an adapter that crashes, are errors in the log and on the page, no longer a mail that silently went nowhere.
- A notice at the top right closes itself: after six seconds, an error after twelve. A bar under it shows how long it stays, and it waits while the pointer rests on it or the tab is in the background. The notice about a lost connection stays until the connection is back.
- The navigation leads a new tenant through its setup. Until a model provider is set up, only the dashboard, the audit log, the administration and the account are open; after that the servers and the knowledge, and with the first server everything else. An entry that waits is shown greyed and says on hover what it waits for, and the next step stands as a link under the dashboard entry. Somebody who cannot take the step is told that an administrator has to. What a tenant has done stays reachable when its server or provider is gone later.
- The rule set in the image is Heinzel 2.30.1. Its rules are those of 2.30.0; the release corrects a housekeeping reference that Heinzel Pro does not carry.
2.20.0 (2026-10-11)
- A command that changes something, or that was given a longer timeout, runs
as a job on its host and outlives a restart of Heinzel Pro: after a deploy,
a crash or a reboot of the host Heinzel Pro runs on, the session gets the
real exit code and output where it used to get "execution was interrupted;
outcome unknown". The output shows on the session page while the command
runs. Stopping the session, a timeout and the emergency stop end the job on
the host. Reading commands, and commands that are handed a secret or a
file, run in their SSH channel as before. See
docs/upgrade.mdanddocs/security.md, "What is left on a host". - A planned restart is announced. The host asks
POST /ops/drainfirst: with nobody at work it may restart at once, otherwise every open page shows a banner with a countdown and the reason, three minutes ahead by default. Half a minute before the moment Heinzel starts nothing new and finishes the step it is in. An administrator of the installation can cancel on the banner. A page that reconnects to a newer release says so. The address is open to the host alone and needsHEINZEL_OPS_TOKEN;deploy/hostedholds the script and a systemd unit for host shutdowns. Seedocs/installation.md, "Announcing a restart". - Two releases can share the database for the minute of a deploy. A session
is driven by exactly one runner, which holds a lease on it; a release that
stops gives its sessions back and the other one resumes them, at its start
and every minute, which also covers a crash. A container that is stopped
ends in good order (
stop_grace_period: 90s): a job on a host runs on, and nothing is resumed twice.deploy/hostedholds a compose file for two slots, the nginx snippet and the script that switches between them; seedocs/installation.md, "Two slots", anddocs/upgrade.md, "Which releases may run side by side". - A release is an Erlang node only where it is told to be one
(
HEINZEL_NODE_ADDRESS), and then only with aHEINZEL_CLUSTER_COOKIEof the installation's own. Before, every container was a node with the cookie its image was built with. - A VPN connection whose port is still held by the release that is being replaced says that it waits for it, instead of reporting a fault.
- The rule set is data. Settings has a Rule set tab for administrators of
the installation: the version in use, a check for a newer tag of the
public Heinzel repository, an update without a restart, an upload for
installations with no way out, and the kept versions to go back to. A
session keeps the rule set it started with and offers "Reload rules" in
its menu once a newer one is in use.
HEINZEL_RULES_DIRstill stands above it. Seedocs/upgrade.md, "Rule set". - A tenant can be given a number of seats of its own. An administrator of
the installation sets it on the tenant's form; the tenant's Users page
shows the use, and a role, a right to act or an accepted invitation that
would exceed it is refused with the limit named. The license's total stays
the ceiling above all tenants, and counts a person once. Without a number
nothing changes. See
docs/administration.md, "Seats per tenant". - Releases are images from here on. A tag
v<version>buildsghcr.io/wintermeyer/heinzel-pro:<version>and:latestfor amd64 and arm64 in GitHub Actions and publishes the release with this file's section for the version. Each image is checked before it is pushed: no debug information, no source, no.env.docker compose up -dpulls it;--buildstill builds from the source. - The rule set in the image is Heinzel 2.30.0.
2.19.0 (2026-10-11)
- A session's summary says at a glance what the session was: counters at the top (changes, checks, open points, undo steps), and below them only the parts that hold something, one under the other. A part with nothing in it is a dashed counter and no longer half a card. An undo step stands in its own box, exactly as written.
- A summary speaks of a way back only where something was changed. Heinzel is told to leave it out after a session that only looked, and a summary that names a way back without a change is handed back to it. Summaries written before keep what they say.
- Fixed: the note that a summary was written before the last request, and two notes on a person's rights page, were close to unreadable, light text on a light ground. An undo step in the summary began with stray blank lines.
2.18.0 (2026-10-11)
- A browser tab works in the tenant its address names: every address inside a
tenant begins with the tenant's slug (
/acme/sessions/…). Two tabs work in two tenants side by side, and a tab that is loaded anew or reconnects stays where it was. Switching no longer closes the pages of the tenant left behind. Addresses from before, in bookmarks and mails, are sent on into the tenant last worked in. With several tenants the tab's title names the tenant. Seedocs/upgrade.md. - The tab of a session says in its title what that session needs: an approval, a look at a failure, or that Heinzel answered. Among several session tabs the one to go to stands out. The count of all sessions that need you stays in the title of the other pages.
- Two tabs of one session show the same: files that wait for the next message, a file taken out or let through, and what was read in one tab is read in the other.
- One browser holds one account. Signing in with another account while one is signed in is refused with "Log out first", instead of leaving the first account's open tabs behind in a state of their own.
- After a lost connection a page is current again sooner: it reconnects as soon as the network is back or the tab comes to the front, and tries every two seconds, not five, in between.
2.17.0 (2026-10-10)
- The database and the code say "session" where they said "conversation":
the tables
sessions,session_readsandsession_shares, the columnsession_id, the settingssession_sharingandsession_retention_days, the rightsrun_sessions,view_sessionsandread_all_sessions. One migration renames them and carries the rights of people and the waiting jobs over. The alert webhook and the policy file use the new names; the audit log keeps the old ones. Seedocs/upgrade.md.
2.16.0 (2026-10-10)
- A session's page belongs to its thread. One line says which session it is, on which server, in what state, and what Heinzel may do without asking. People, the change record, the incident draft, and owner, model, tokens and cost wait behind one button. The list of your other sessions is gone from the page: "Sessions" in the navigation leads back to it and counts those that need you.
- While Heinzel works or waits for a decision, the message field is one line and no longer lies over the command to approve.
- Sessions live at
/sessions/…, no longer at/conversations/…. An old address in a mail or a bookmark no longer opens.
2.15.0 (2026-10-10)
- Two lists showed more than a person's rights allow, both since 2.14.0. Somebody shown chosen servers only saw, on the Approvals page, the commands scheduled runs had skipped on every server, and could take them up or dismiss them. And an API token kept listing servers, sessions, approvals, findings and schedules after its person had lost the right to see them. Both are held to what the person holds now.
- The navigation says how much is behind an entry: the servers you are shown, the schedules that run with those Heinzel had to pause set apart, and the open findings, red when one is critical and yellow for a warning. An entry with nothing behind it shows no number.
- Fixed: somebody shown some servers only was given the findings of every server of the tenant. They now find those of their servers.
- Fixed: a short number read
1.0K, and in German2.150,0. It is1Know, and the plain2.150where German has no short form.
2.14.0 (2026-10-10)
- Rights can be set per person. A role stays the starting point; under Users, "Rights" lists every right as a sentence and lets you give a right the role lacks or take one it holds. "Everything but this" is an administrator with one line set to "No", "nothing but these" the new role "Nothing by itself" with two or three lines set to "Yes". The page says the outcome in one sentence before you save. What an administrator could do is now 12 rights of its own (users, secrets, API tokens, safety rules, model providers and so on), so each can be handed out alone. Nobody changes their own rights or gives more than they hold. A closed page names the missing right, the navigation shows what a person may open, and the account page lists a person's own rights. A right to act takes a seat, whatever the role.
- A person can be shown some servers only, chosen by group, tag or name. The others do not exist for them, in lists, in search, in approvals and for the agent in their sessions. Rights that reach over the whole tenant fall away for them.
- Areas: a part of one server somebody is held to, such as one web site and
one database. An area is an account of its own on the host, which owns the
area's directories, may test and reload nginx or Apache and nothing else of
it, and reaches one PostgreSQL, MySQL or MariaDB database. Heinzel shows the
set-up script in full, runs it on a click, then signs in as the account and
checks that it is fenced in; sessions of the area sign in as that account
and run only while that check holds. Linux only. Migration
20261010162948adds columns and two tables and changes no existing row.
2.13.0 (2026-10-10)
- The Backups page is gone, and with it the daily look at the watched
directories. A schedule that reads the directory can take its place, and
can also read a subdirectory per night. Migration
20261010161139deletes the watched directories with their history and closes the findings they left open.
2.12.0 (2026-10-10)
- The Certificates page is gone. It watched only the host names somebody had typed into its list, and the certificate that runs out is the one nobody listed. The list is deleted with the update and the findings it left open are closed. A schedule that checks certificates on a host still records what it finds on the Findings page.
2.11.0 (2026-10-10)
- A schedule can change a server, where it is allowed to. Until now a run nobody attends only read. A schedule now names its own level: reading only, changes wait for an approval (a standing approval counts there), or changes alone. The lowest of four settings counts: that level, what the schedule's owner may hand to a schedule (a default per tenant, or a group), what the server takes from a schedule, and the tenant's ceiling. All of them start at reading, so nothing changes until an administrator opens each one. At "changes alone" nothing waits, destructive commands included, and every place that sets it says so in red. A schedule changes a server only inside its maintenance windows, and whoever edits what a changing schedule asks or where it runs takes it over.
2.10.0 (2026-10-10)
- No password is kept for a host any more. The sudo password field is gone from the server form, and the passwords typed into it are deleted with the update. sudo has to work without a password for Heinzel's user; where it asks for one, a command with sudo fails at once.
2.9.1 (2026-10-10)
The pages used every day get the room. In the sidebar the administration pages fold away until one of them is open, and the whole navigation fits a laptop screen. On a phone a page's rarely used buttons sit in one "More" menu, its explanation is two lines until tapped, the server list is one short card per host, and the audit filter and the certificate form open on request. The dashboard starts with what needs you.
A new session opened from a server's page starts on that server, and on the only server where there is one.
2.9.0 (2026-10-10)
VPN connections: a server that cannot be reached from the internet (behind a home router, in an office network, without a public address) is reached through a WireGuard tunnel. Either the tenant's server or network dials Heinzel Pro, with one block of text to paste that Heinzel makes, or Heinzel Pro dials a router from the file the router exports. Each connection is a tunnel of its own in user space, so tenants with the same private network never meet; SSH inside it keeps its key and its pin. The page of a connection shows live whether the tunnel is up and walks through the other side's steps. Installations open UDP 51900 to 51919 for it, see docs/upgrade.md.
A VPN connection can be a device in a Tailscale network instead (also with a Headscale server): Heinzel Pro joins with an auth key the tenant makes, once, and is the same device after every restart. Nothing is installed on the servers. Tailscale SSH is not used; SSH keeps its key and its pin here too.
Markdown is shown as what it means in the remaining places too: the points of a session's summary (also in the customer portal), a plan's goal, steps, risks and way back, and the notes on a host beside a command. Commands stay as written.
Markdown is shown as what it means: an agent's answers, notes of the knowledge base and a server's memory and to-dos come as headings, lists, bold text, code and tables, no longer as their source. The HTML is written from a closed set of elements; HTML inside the text is shown as words, a link leads only to the web or a mail address, and no picture is fetched.
Stopping a session takes one line: the button sits beside "Heinzel is working…", and the field for a reason opens only for who asks for it.
2.8.0 (2026-10-09)
Announcements: before a task of several steps a session says what it is about to change on a server (services, paths, packages, the whole host) with the new tool
announce_change. It holds that from then on, the server's page and the list show it with a sentence for people, and another agent is told the names and never the sentence, so no session can give another one orders this way.Server memory: a session's write to a server's memory or to-dos is taken only if the text is still the one it read. Where another session or a person changed it in between, nothing is written and the session is handed the current text to put its change into. Until now the last writer silently replaced the other's notes.
Several sessions on one server: a session holds what its commands changed (a service, a file or directory, the package manager, the whole host) for a quarter of an hour, and for two hours while it still works. A command of another session that reaches into it is put to a person, also under full auto and whatever a plan or a standing approval says, and its card names who holds what. A change whose target cannot be read off the command counts as touching everything. Reading is never held up.
Four eyes: where a tenant has no two people who could approve together (one who approves, another who may give the second approval), a destructive command no longer waits for a second approval that nobody could give. One approval decides; the command's card, the audit log and the compliance page say so.
Classifier:
apt-get -s autoremoveand the other simulated removals of apt and aptitude are reading, as simulated installs already were.Servers list: each reached host shows its load, memory, temperature and fullest disk, asked every 30 seconds while the list is open. One question per host serves every open list and page.
Who is at work on a server: the servers list and the server's page name the sessions that run or wait for approval there, and those that changed something in the last quarter of an hour. A session is told the same about its own server with every step.
Server page: load, memory, temperature and disks of the host, read every five seconds while the page is open. Asked over the server's SSH connection, from node_exporter where one listens on the host and from
/procand/syswhere none does; nothing to install, no port to open.Customer portal: a role that sees one group of servers and nothing else of the tenant: the servers, open findings, the month in numbers and the work as summaries and change records (#61).
API: tokens per tenant (scoped, revocable, audited) for servers, sessions, approvals, findings and schedules under
/api/v1/<tenant>, and a smallheinzelcommand on top (cli/heinzel). A token denies a command and never approves one (#37).Rollouts: one task on many servers. It runs on the first as a canary; after a person's go it runs on the others, where a command approved on the canary is not asked again (#1).
Managed files: a tenant names the files its configuration management writes; the agent is told, a hand edit of one is refused with where the change belongs, and a file that says it is managed is recognised (#53).
Attachments: the message box of a session takes screenshots, PDFs and text files by picker, drop and paste; they are kept per tenant in the database and go to the model as what they are (#152, #44).
File edits: the agent writes a file with a tool of its own, and the command card shows the difference to what is there; a copy of the old file is kept beside it (#18).
Plans: for a task of several steps the agent writes a plan (goal, exact commands, risks, undo) that a person approves as a whole; its commands then run once each as written, anything else asks on its own (#11).
Hosts where sudo asks for a password: the server form keeps it, and a command that uses sudo has it handed to sudo on the host, out of the command line and blacked out of the output (#35).
Secrets: a tenant keeps passwords and tokens by name; the agent writes
$HEINZEL_SECRET_NAMEinto a command, the value is set on the host and blacked out of the output, and such a command always waits for a person (#19).Backups: a tenant names the directories its backups land in; each is looked at once a day for a file that is recent and about as large as those before, and anything else becomes a finding (#48).
Controls: a page that maps the product's safeguards to ISO/IEC 27001:2022 Annex A, the SOC 2 common criteria and BSI IT-Grundschutz, with how each is set in the tenant and where its evidence is (#54).
The policy as a file: a tenant's autonomy, four-eyes rule, sharing, timeouts, block list and standing approvals as JSON with a hash; an import shows what would change before it is applied (#56).
Security: commands that can write a file or run a program although their name is on the reading list (sed scripts with
eorw, tar with a checkpoint action, find -fprint, openssl -out, git --output and -c, database clients that reach a shell, process substitution) are no longer taken for reading and ask for approval (#150). A second round closes more of them: clients that run every word they are given, allowed options beside changing ones, short forms, files sent to another host, and variables or paths in front of a command (#153).A model can name a stronger one: a session started on the inexpensive model is handed over by the agent when the task is hard, or by a person, and the page shows what each model did (#29).
Every changing command is proposed with its undo, shown on its card, and a session offers Roll back: the undo notes, newest first, as the task of a new session a person reads and sends (#17).
Certificates: a tenant lists host names, each is looked at once a day from one of its servers, and one that runs out within thirty days becomes a finding, critical in the last week (#42).
An alert from the monitoring (Alertmanager's webhook, or host, title and text) starts a session on the server it names that looks into it by reading only; a token per tenant, and a limit per hour (#7). Such a session writes no notes about any server, and a scheduled run only about its own (#147).
A model can name another that answers a step when its provider is down; the session notes the switch and the audit log records it (#30).
Commands that change something are marked in the monitoring's graphs as annotations (Grafana's API): host, command, who approved (#52).
A session hands out the draft of an incident report: its timeline from the audit log, the commands, the agent's summary, and the parts a person has to write marked TODO (#49).
A server's page hands out a handover document: what the server is, how to get in, the agent's notes, what is open, the journal, its sessions and its schedules, as Markdown (#23).
A server can be reached through a bastion, another server of the tenant, as ProxyJump does: each with its own key and pinned host key (#34). A change to a bastion ends the connections that run through it (#144).
Findings: what scheduled checks and sessions find wrong is kept on a page of its own until a later run no longer sees it or somebody closes it, with a person who takes it and a session that fixes it (#6). A session records findings for its own server only (#141, #142).
A schedule can name tags instead of one server: it then runs on every server that carries them, four at a time, and mails one report with the hosts that need somebody first (#3). A run that the emergency stop, the budget or the license cuts short says so and starts no more hosts (#140).
A session ends with the agent's summary (changed, verified, still open, how to undo) above the thread, in the change record and, as a count of open points, in the list; open points go on the server's to-do (#26).
The German interface shows the application's own validation messages in German; 27 of them were English (#137).
A session's summary keeps an undo step as it was written and compares open points with whole items of the to-do (#138); the command palette no longer opens a hit of the query before (#139).
Servers carry tags (
env:prod,role:db); the servers list filters by them, and the agent sees them when it lists servers (#2).A command palette on Ctrl+K (Cmd+K) jumps to pages, servers, sessions and schedules by name and offers the current page's main actions (#40).
A tenant's audit events are shipped to an HTTPS endpoint as they are written, one JSON line each with its position and hash in the chain; what the endpoint does not take is retried every minute (#32).
A monthly report per tenant for its administrators: sessions and commands, by server, who approved and denied, and what the models cost (#27).
The server page says what changed in the last week: system, kernel, root disk fill, a reboot, and since when one is pending (#5).
Command output that reads like instructions to the agent is kept from the model; the card says so, and somebody who may write into the session can release it (#58).
The whole output of a command downloads as a text file from its card (#44, first half).
A model provider is labelled with where it processes data (EU, USA, own network), the label is shown where a model is chosen, and a tenant can require a place; providers not labelled for it cannot be used (#57).
A server whose memory is empty gets its first notes from the host when a connection test succeeds: running services, disks, what listens, and whether sudo asks for a password (#45).
The second approval of a destructive command asks for a sign-in no older than five minutes (#21).
A monthly budget for model calls per tenant: a warning at 80 %, no new work at 100 %, and spend against budget on the dashboard (#28).
A weekly mail per tenant with what was left undone: open to-dos on hosts, what scheduled runs skipped, schedules that failed or were paused, servers not reached for ninety days. A new notification event to switch on; a week with nothing to say sends nothing (#51).
Servers are imported in bulk from a pasted list, a CSV, an ssh config or an Ansible inventory, with one script that puts the keys on the hosts (#36).
A session exports a change record as Markdown: who asked, what was proposed, who decided, how it ended, and the position and hash of each of its entries in the audit chain (#31).
An approval that waits longer than a time the tenant sets is escalated once, as its own notification event, and its card says so (#10).
Maintenance windows per server: outside them Heinzel only reads there, whoever asks and at whatever level, also for a command that was approved while the window was still open (#43).
A session in which Heinzel changed something without anybody approving it is signed afterwards by a second person, one by one or all at once; the signature is in the audit log and the dashboard counts what waits (#59).
An access review per tenant, reached from the users page: who can both ask and approve, who lets Heinzel work alone, who has not signed in for a quarter, who has no second factor; an administrator attests it, and the attestation is in the audit log (#55).
Standing approvals: an administrator lists commands that are always fine, on every server, one server or a group. An exact match runs without a person and is logged as such; destructive commands, the block lists, read-only servers and scheduled runs are not affected (#12).
A knowledge base per tenant: short notes on how things are done here, which every session reads at its start beside the memory of its server (#22).
Search, in the navigation: sessions by title and by what was said in them, commands by text and host, and the servers' journals, within what the person may read (#25).
The servers list shows what is known about each host (system, uptime, disk fill, a pending reboot), collected with the connection test, and can be searched and ordered by it; a stale fact says how old it is (#4).
Break-glass: an administrator raises the autonomy on one server for a chosen time, with a reason. It is logged, the administrators are told (a new notification event to switch on), and it ends by itself (#16).
The card of a command that waits says what it means on its host: what the host is, when the same command last ran there and how it ended, and what the host's notes say about what it touches (#50).
A library of saved tasks per tenant: a prompt with blanks such as
{domain}, started on a server with the blanks filled in, with how often it ran and its last session (#24).What a scheduled run wanted to change and had to skip waits on the approvals page for a week, with the run's reasoning: take it up in a session of your own, or dismiss it (#47).
The approvals page groups the same command waiting on several hosts and approves or denies the group at once; each command is still checked and logged on its own (#62).
Servers added at the same moment can no longer exceed the number the license allows (#122).
A schedule that names no hour (every five minutes, every hour) runs on through the hour the clocks repeat in autumn instead of pausing for it (#120).
The user page says when a login link or an invitation could not be mailed instead of reporting success, and a schedule's report or pause notice that did not leave is tried again, per recipient (#121).
Two-factor codes sent at the same moment are counted one by one, so a burst no longer tests more codes than the limit (#118).
A block rule written as a pattern blocks a command it cannot be decided for, instead of letting a padded command through (#119).
The emergency stop holds where it did not: a command that waited behind another on the same host no longer runs once the first is cut off, a failed session cannot be retried, a queued scheduled run is dropped without leaving a session, and the switch is read from the database, so a second node sees it. A command caught mid-run is reported as unknown instead of as never run (#117).
The settings have a box to try a command against the policy: its class, the reason, and what would happen on a server at each level of autonomy and in a scheduled run. Nothing is run (#15).
The dashboard says what needs a person: approvals with the age of the oldest, sessions and scheduled runs that failed in the last day, schedules Heinzel paused, hosts that are not ready, and the first steps for a tenant that has not started (#41).
The servers list says what is left to set up on each host (key not installed, last contact failed, nothing known, not reached for a week, no schedule) and filters for the hosts that are not ready (#46).
A tenant has a block list of its own (Settings, General): commands Heinzel never runs there, everywhere, on one server or on a group, in words or as a regular expression. Asked when a command is proposed and again right before it runs (#13).
An emergency stop per tenant (Settings, General) and one for the installation (Tenants): it stops every session, cuts off running commands, takes back waiting ones and rests the schedules until it is lifted, with who and why in the audit log and a banner on every page (#60).
The approvals page shows what a waiting command is for: the task and the commands that ran before it with their output, for sessions the approver may read (#14).
A running session can be stopped from its page. The command that is running finishes, nothing further starts, a command that waited for approval is taken back, and the log says who stopped it and why (#20).
Fixed: the link in an alert mail or chat message opens the session again (#68).
Fixed: long output with umlauts, or output that is no UTF-8 at all, no longer fails the session; it is shortened between characters and stored with the bad bytes replaced (#66).
Fixed: a command that never stops printing (
tail -f,ping) is closed when its timeout passes and no longer blocks its server (#63).Fixed: after a host reboots, the next command opens a new connection instead of failing for ten minutes (#64).
Fixed: a server whose host name, port or SSH user changed runs its next command there, not on the connection to the old address (#65).
Fixed: a command that waits behind another on the same server is no longer reported as failed while it still runs (#70).
Fixed: two servers with one host name on different ports no longer crash every command; the agent names them
host:port(#67).Fixed: the timeout Heinzel asks for with a long command (an upgrade) is honoured, up to a new setting, 3600 s by default, and shown to whoever approves the command (#69).
Fixed: without a valid license a due schedule no longer leaves an empty session behind with every attempt; the run is refused once and logged (#71).
Fixed: a schedule whose owner left, or lost its model, is paused with the reason and its recipients are told, instead of showing a next run that never happens. Whoever enables it runs it in their own name (#72).
Fixed: a schedule skips a due time while its previous run is still going, instead of starting a second session on top of it (#73).
Fixed: removing a server names the schedules that are removed with it, in the question and in the audit log (#74).
Fixed: a number too big or an organisation name over 255 characters is an error at the field of the settings, no longer a crash, and an emptied number is an error instead of a silent return to the default (#76, #91).
Fixed: the invite form refuses a name over 120 characters at the field instead of crashing, and says so when the person is a member already (#90, #94).
Fixed: a webhook that fails is retried on its own; the alert mail no longer goes out again with every retry (#78).
Fixed: a session cannot be started without a server, whatever the form sends (#97).
Fixed: alert addresses are checked like the webhook next to them, and the one that is no address is named (#96).
Fixed: a second tenant with a name that exists is created, under a numbered link of its own, instead of failing without a word (#95).
Fixed: the audit log filters by a date range, which the page now offers, and the CSV export is sent in pieces instead of being built in memory (#80).
Fixed: emptying the license key field removes the license instead of crashing the form (#88).
Fixed: the sign-in rate limit forgets an address once its minute has passed, instead of keeping every one for as long as the node runs (#87).
Fixed: the account page left open too long sends you to the login when you change address or password, instead of crashing (#86).
Fixed: a login link for an account with a password and an unconfirmed address confirms the address and signs in, instead of crashing; this hit the first administrator of every installation (#92).
Fixed: the link in an invitation opens for seven days, not fifteen minutes, and the mail says who invites into which tenant and until when (#83).
Fixed: the sign-in limit and the audit log no longer believe the address a client writes into
X-Forwarded-For; they take the entry your own proxy appended. New settingTRUSTED_PROXIES, see installation.md (#115).Fixed: a server can be added by its IPv6 address; with a port the agent names it
[address]:port(#82).Fixed: work in an open page counts against the idle sign-out; a day in one tab no longer ends with being signed out (#81).
Fixed: without
SMTP_HOSTa mail is an error in the log and a warning on the administrator's dashboard, no longer accepted and dropped (#77).Fixed: an administrator without a model is sent to the model settings instead of being told to ask an administrator (#108).
Fixed: a page somebody may not use says so in the same words everywhere (#114).
Fixed: a viewer is brought into a session to read only; the people panel no longer offers a writing that the role would take back (#103).
Fixed: a server that cannot be reached says why in words ("the host name was not found") instead of Erlang terms, and the button says that it is testing (#98).
Fixed: the server page's header shows the first line of a long description and the rest below, instead of all of it (#111).
Fixed: accepting the invitation to one's only tenant leads into it, not to a list with one entry; a changed language is confirmed in that language (#112).
Fixed: the mail about a failed scheduled run says the error once, the schedules list shows the next run without seconds, and "Run now" runs in the name of whoever presses it (#107).
Fixed: a new account takes the browser's language at its first sign-in, so a German browser no longer gets an English application (#105).
Fixed: the number of servers a license names is enforced when a server is added and shown on the license page; a license without a number has no limit, as before (#89).
Fixed: the audit log names its actions in the reader's language and shows details as words; the stored keys stay what filters and exports use (#100).
Fixed: a session takes no further message while one of its commands waits for a decision; such a message made the session fail with the command still waiting (#99).
Fixed: a failed session says what happened and who can fix it above the provider's own words, and Retry says that it tried (#102).
Fixed: a page that is gone is a page of the application that says so and leads back, and the audit log links only what can still be opened (#104).
Fixed: approving and denying, saving memory, adding a note, disabling a user and taking back a link each say what happened; an empty note is refused instead of ignored, and taking a link back asks first (#106).
Fixed: mails to an account are written in that person's language, a login link is no longer titled "Confirmation instructions", and the page it leads to has no untranslated hint (#101).
Fixed: the dashboard no longer grows wider than a phone when a session has a long title; the same fault is closed on twelve other grids (#93).
Fixed: the settings tabs wrap on a phone instead of running off the screen (#109).
Fixed: on a phone the audit log is one line per event, with the details behind a tap, instead of a card of ten lines each (#110).
Fixed: the memory editor keeps what you type when Heinzel writes to the same memory, says that it changed, and no longer overwrites that change without being told to (#84).
Fixed: alerts to Teams are sent as an Adaptive Card, the format of a webhook made with Workflows; not tried against a live Teams (#79).
Fixed: setting up two-factor sign-in hands out ten recovery codes, each good for one sign-in without the phone; a lost phone no longer locks out the last administrator. Turning it on or off is logged once (#85).
Fixed: five wrong two-factor codes pause that account's second step for fifteen minutes and alert its tenants; guesses were limited per address only (#116).
Fixed: a tenant has a time zone. Schedules run by it, through summer and winter time, and every time on screen is shown on it. Existing tenants stay on UTC until an administrator chooses (#75).
Fixed: the settings tabs that are not open are readable in light mode (contrast 6.2:1 instead of 3.3:1) (#113).
2.7.0 (2026-10-08)
- A provider offers several models: one account, one key, and the models ticked from those Heinzel Pro knows, or typed by id. A new key reaches every model of the provider.
- Each model has its own page for efforts, prices and who may use it; the list of models is grouped by provider.
- Upgrade: each existing provider becomes a provider with one model.
2.6.0 (2026-10-08)
- Working in several tenants: a sign-in stays in its tenant until its owner switches. A page rendered in one tenant no longer reconnects into another (with its half-filled form), a tenant that is closed to somebody sends them to choose instead of carrying them elsewhere, a link that names a tenant says so and is logged, and a change of role in one tenant leaves the pages of another alone.
- The audit export holds one chain: a tenant's file no longer includes the installation's log. Administrators of the installation export that one separately.
- Shared hosts: a server takes Heinzel's handover notes in its system
journal only if its form says so; new servers do not, and such a command
is then refused in code. The key comment in
authorized_keysno longer carries the name of a shared key.
2.5.1 (2026-10-08)
- Conversations are called sessions, in the interface and the docs. The
addresses (
/conversations/…) and the names in the audit log stay. - Sharing moved into the session: People shows who is in, and the owner brings a colleague or a group in, changes their level or shuts them out, one at a time and at once. The separate share page is gone; the default for new sessions stays under Sessions, Sharing.
2.5.0 (2026-10-08)
- Several conversations at once: the list and a rail beside the open conversation show what each is doing (needs you, answered, working, idle), live, with what needs you on top.
- A ping when one of your conversations waits for an approval, fails or is done: a count in the navigation and in the tab's title, and a browser notification where you allow it.
2.4.0 (2026-10-08)
- Sharing: a conversation belongs to its owner and is opened to everybody in the tenant, to groups or to people, for reading or for writing. A colleague with write access goes on where the owner stopped, or takes the conversation over.
- Every message shows who sent it; sharing, links and taking over are in the audit log, which leaves out what happened in conversations the reader may not open.
- A link lets people without an account read a conversation for a limited time, with names left out and secrets blacked out. Off until an administrator allows it.
- Defaults per tenant and per member for what new conversations are shared with.
- Upgrade: existing conversations and the tenant's default stay open to all members, as before.
2.3.0 (2026-10-08)
- How much Heinzel does on its own, in three levels: ask for everything, reading alone, everything alone (full auto). Set as a ceiling per tenant by the installation, as a default per tenant, per group, per server (raised by administrators only) and per conversation; the lowest counts, for the owner and for whoever sent the message. A command of several parts runs alone only if every part does.
- Classifier:
sudo -n …and commands beside a here document no longer slip past the block list.-nand-scount as a dry run only where the package manager means that. awk, rpm, sort, uniq, nvme, journalctl, date, hostname, ss, dmesg, ifconfig and others are read-only only with arguments that only read. - Efforts per model: a provider lists the efforts it offers, and every member, a group or a person may go up to a set one.
- Model catalog: the provider form offers known models and fills in their
efforts. The vendor signs a newer catalog between releases
(
mix heinzel.catalog sign); an administrator of the installation pastes it under Settings, License. Nothing is fetched from the network. - Upgrade: "read-only automatically" becomes "reading alone"; every tenant's
ceiling starts there. Operators can no longer raise what a server runs
alone. Migration
20261008124115cannot be rolled back.
2.2.0 (2026-10-08)
- Starting a conversation asks for the model and the effort. The model is
always shown, with the default preselected, so that it is plain what will
answer. The effort is Standard (as the provider is set up), Low, Medium or
High, the same words for every kind of provider; the conversation page
shows what was chosen. A provider can switch the choice off for a server
that does not know the setting. Migration
20261008123128.
2.1.0 (2026-10-08)
- Several model providers per tenant, each with its own name, model and key. A provider is open to every member or restricted to groups and people; one is the default. Whoever may use several picks one when starting a conversation, and a schedule can name one.
- Groups: named sets of a tenant's members, managed under Administration, so that access is granted by team instead of person by person.
- Access is enforced in the core, when a conversation is created and again with every message. A conversation keeps its provider; if that is switched off or removed, or access is withdrawn, it ends there and no other model takes over.
- Model and cost in the conversation list and on the conversation page. A provider can carry the prices its tenant pays per million tokens; every model call is then priced when it is made, with cached input told apart from fresh input. Nothing is estimated: without entered prices, and for conversations from before this release, no cost is shown.
- A schedule runs as its owner on a provider its owner may use; editing its task or model makes the editor its owner. A run that is refused is recorded and cancelled. Retrying a failed conversation needs the right to run conversations.
- Upgrade: the configured model becomes the first provider, open to all.
Migration
20261008120857cannot be rolled back;20261008122252adds prices and costs.
2.0.2 (2026-10-08)
- A pass over every page at desktop and phone width, light and dark:
- Tenants: "you are here" sits in the state column instead of off the line of the buttons. Rows of buttons and badges are centred everywhere.
- Users: the list keeps Edit and Remove; sending a login link, resetting the second factor, removing passkeys, installation rights and the lock moved to the user's page, where they no longer wrap into two lines.
- Lines of small facts (host, person, time) break between the facts and no longer start with a stray dot.
- Server page: the algorithm and "Rotate key" are one control; the note "pinned on first connection" is no longer broken in mid-word.
- Audit log: events of the installation are marked, and the details stand under the action instead of running out of the table.
- Settings tabs stay on one line on a phone; the schedule form's checkbox lines up; alerts are centred on a phone.
2.0.1 (2026-10-08)
- Every key is a UUID v7, and the database now enforces it: migration
20261008103455adds a check on the version ofidto every table. The application has generated nothing else since 1.0.0. Should a table hold a key of another version after all, the upgrade still runs; the check then covers new rows only and the log names the table. - Tenants, after a second review of 2.0.0:
- Rotating the vault key failed on the first tenant table; it now rewrites the secrets of all tenants.
- Signing in accepts no invitation: every invited person says yes on the page they land on. A page that is open loads anew when its user's role or membership changes, also after the session token was renewed.
- The form for changing one's address no longer tells whether an address belongs to another account. Raising a role needs a free seat even when the account holds one through another tenant.
- Changes to sign-in rules, single sign-on and license are recorded in the installation's audit chain. A link that names a tenant reconnects the pages left open in the previous one. The tenant one stands in cannot be closed.
- The guard on queries also refuses tenant tables inside any nested query.
- The demo data for development works with invitations again.
2.0.0 (2026-10-08)
- Tenants: one installation serves several customers, departments or environments. Each tenant has its own servers, SSH keys, conversations, schedules, audit log, model provider, policy and alerts; none of it is visible from another tenant, to people or to the agent.
- Accounts belong to the installation, roles to a tenant. A person with several tenants works in one at a time and switches at the top of the navigation. Administrators of the installation create and close tenants and enter each as administrator.
- Sign-in rules, single sign-on and the license apply to the whole installation and moved to a Sign-in tab that only its administrators see. Only they change another person's address, lock, second factor or passkeys; a tenant's administrator sets roles and removes members.
- The separation is enforced below the application code: a process bound to no tenant cannot read tenant data, and foreign keys carry the tenant.
- Invitations need the invited person's yes; until then the tenant sees the address and nothing of the account. Each tenant has its own audit chain; logins are recorded for the installation. A role change, a removal or a closed tenant disconnects the pages that are open.
- Addresses the server calls (model base URL, webhook) are set by the installation's administrators only. The session cookie is encrypted.
- Fixed: a schedule whose cron expression ran out of dates stopped all scheduled runs; the session test depended on the time of day.
- Links in alerts and reports name their tenant.
- Vault key rotation now also re-encrypts shared SSH keys, which it skipped.
- Upgrade: existing data moves into one tenant, existing administrators also
administer the installation. Migrations
20261008094017and20261008095012cannot be rolled back and sign everybody out once; seedocs/en/upgrade.md.
1.5.1 (2026-10-08)
- The account page, where passkeys, the second factor and devices live, is an entry of the main navigation ("Account and sign-in") and is highlighted while open. Before, only a small button beside "Log out" led there.
1.5.0 (2026-10-08)
- Key algorithms: a server's own key and a shared key are Ed25519 as before, or ECDSA (P-256, P-384, P-521) or RSA 4096 where a host or a policy demands it. Pick the algorithm when creating a key; a rotation keeps it or changes it. RSA keys sign with SHA-2 only.
- Copy buttons: the key overview and every public key line copy the authorized_keys line to the clipboard. The overview also names each key's algorithm.
- No migration: the public key records the algorithm.
1.4.0 (2026-10-08)
- Passkeys: users add one on the account page and then sign in with fingerprint, face or device PIN, without typing an address. The authenticator must verify its user, so a passkey counts as both factors and skips the TOTP code. Up to ten per user; administrators remove a user's passkeys when a device is lost.
- Passkeys are bound to the public address (
PHX_HOST,PHX_SCHEME). They need HTTPS, orlocalhost, and stop working if the address changes. - Migration
20261008074304adds theuser_passkeystable.
1.3.0 (2026-10-08)
- Devices: the account page lists every browser you are logged in on, with system, address and last activity, and logs out one of them or all others from wherever you are. A device left logged in somewhere no longer needs a password change to get rid of.
- The interface works on a phone: a bottom bar for dashboard, conversations, approvals and servers, tables that turn into cards, controls at least 44 px tall, no sideways scrolling.
- Readable without colour: every status badge carries an icon, links are underlined, text and buttons meet a contrast of 4.5:1 in the light and the dark theme. Checked with simulated red-green blindness and in greyscale.
- Buttons that passed their own classes lost their button styling, among them both login buttons.
- Migration
20261008073229adds device columns to the session tokens.
1.2.0 (2026-10-08)
- SSH certificate authorities, read-only: the connection test records which
user CA a host trusts, where principals and revocations live, and when its
host certificates expire. The server page shows it and warns 14 days before
a host certificate runs out; the agent gets a matching rule
(
ssh-certificates). Heinzel Pro still logs in with its own key: the Erlang SSH client cannot present a certificate, and sshd directives stay with the operator.
1.1.0 (2026-10-08)
- Shared SSH keys: administrators create named key pairs that several servers use, so one public line goes out through configuration management. Rotation keeps the previous key as retired until every host carries the new line; servers still on the retired key are marked. Private keys are still never imported or exported.
SMTP_TLS=neverfor a relay on the host whose certificate the container cannot verify. A refused delivery now writes an error line to the log.
1.0.2 (2026-10-08)
- Mail through a relay without login credentials (
SMTP_HOSTset,SMTP_USERNAMEempty) failed on every send. - The "send login link" form returned 500 when posted without JavaScript; it now sends the link like the scripted version.
1.0.1 (2026-10-08)
Fixes from the first installation on a real host.
FORCE_SSL=trueaborted the boot: Phoenix readsforce_sslat compile time. The redirect and HSTS now come from a runtime plug; localhost stays plain.- Empty lines in
.envsuch asSMTP_HOST=no longer switch on a broken SMTP adapter or defeat a default: every empty variable counts as unset. - The compose file binds the app to
127.0.0.1:4000instead of every interface, since Docker publishes ports past the host firewall. - The database password travels in
DATABASE_PASSWORDinstead of insideDATABASE_URL, where/or+broke the connection. - The first administrator sets a password during registration and is signed in at once. Before, the account waited for a login link by mail, which a fresh installation often cannot send yet.
- New
bin/login-link EMAILprints a single-use login link for operators locked out without working mail. - Mail over SMTP failed with
:mimemailundefined:gen_smtpwas missing from the release. - Build image moved to Elixir 1.20.3 (CVE-2026-49762) and a current Debian.
1.0.0 (2026-10-07)
First release.
- Conversations with an AI sysadmin agent over SSH-managed Linux, FreeBSD and macOS hosts
- Risk classification of every command, approval workflow, four-eyes rule for destructive commands
- Append-only, hash-chained audit log with CSV export
- Bring your own model: Anthropic and any OpenAI-compatible provider
- Users with roles, two-factor authentication, OpenID Connect single sign-on
- Scheduled unattended runs with reports by mail
- Alerts by email and webhook (Slack, Teams, generic)
- Offline-verifiable subscription licenses with trial and grace period
- German and English interface