Under the hood

Specs, stack & features.

The short version of everything adamance does. It's a lot for a one-person project, but I don't like leaving gaps where the important stuff goes.

Where this stands. Every feature on this page is designed, and most of it is built and running. The rest is being built, and all of it is in v1. The exceptions are the last two sections, what comes next and multi-forest federation: those land after v1 by design, and each one says so. The first public release lands before the end of 2026, and probably sooner. Everything gets hand-verified before launch, so if it comes to it, the date moves before the bar does. The security side of it is set out in full in the threat model, including what adamance deliberately does not defend against.

Feature list

Everything adamance does, in one list.

The homepage covers the headlines. This is the rest of it, and where to read more on any of it. The first eight are the summary sheet. Everything after them is a section in its own right, ordered by how much it matters rather than how it was built.

The spec sheet

Identity & access

  • Single sign-on over OIDC, with MFA and step-up on sensitive actions
  • One directory for people and groups (FreeIPA / Kerberos)
  • Short-lived SSH certificates, no standing keys in files
  • Per-person grants, scoped to the machines someone actually needs
  • Just-in-time elevation: admin can be requested for a window and expires on its own, rather than held permanently
  • One-line host enrollment with approve-to-join
  • Guest accounts, temporary access with ephemeral certs that expire on their own
  • Hand over a slice rather than the keys: scope an operator to part of the estate, give an auditor read-only with no SSH and no secrets, or delegate a subset of what you hold
  • Agent accounts (designed, not built yet): a scoped account type for an AI agent, cert-only with no password and no console sign-in, always recorded, and holding a ceiling no policy can lift

Policy & enforcement

  • Policy as code in Rego, evaluated by OPA
  • Signed policy bundles pushed to every host
  • Governs SSH, sudo, and the firewall, with nftables rules the agent checks before applying
  • Deny-by-default and fail-closed, with manual admin approval when you want it
  • Enforced locally on each host, so it keeps working offline
  • Dry-run any decision in the console: ask what the live policy would allow, and see the reasons

Network & transport

  • mTLS between every agent and the control plane, and between the control-plane services, verified in both directions
  • Post-quantum key exchange (X25519 + ML-KEM-768) on agent-to-server mTLS, so today's traffic can't be harvested now and decrypted later
  • Runs over what you already have: existing VLANs, a VPN, or a private mesh

Audit & compliance

  • Append-only, hash-chained audit log with tamper detection
  • Optional off-box anchoring on a timer, to offsite storage you control or to write-once WORM hardware, so history survives even a full breach
  • Session recording, and on the groups of machines where you require it, privileged access is gated on the recorder being live
  • Compliance reports mapped to SOC 2, ISO 27001, NIST 800-53, FedRAMP Moderate, HIPAA, and PCI DSS, with CIS benchmarks scored per host
  • Hosts report their own posture, and a machine that has drifted is a different state from one the console could not read, rather than the same tidy green

Secrets & supply chain

  • Sealed vault for secrets (OpenBao)
  • Encrypted at rest, plus encrypted backups; sensitive tokens hashed
  • Key custody anchored to real hardware. If the server has a TPM, setup detects it and seals the vault's unseal keys to that chip instead of leaving them readable on disk, and the server still comes back on its own after a reboot. Three postures to pick from: convenient, TPM-sealed, or keys held entirely off the box with a manual unseal
  • Ed25519-signed policy bundles and agent binaries, verified on every host
  • Signed container images with an SBOM (cosign)

Run & operate

  • Self-hosted in Docker: web console, control-plane server, headless host agent
  • One-command install with a browser setup wizard
  • One-command upgrade and rollback, with auto-rollback on failure
  • Command-line tool plus a self-service user portal
  • High availability, with Grafana / Prometheus dashboards
  • Backup and restore, plus a self-healing watchdog that restarts what has wedged. The checks that actually matter are never auto-cleared, they are escalated to you
  • Encrypted external-storage backups for airgapped setups
  • Break-glass recovery: you own the box, so you are never truly stuck. Root-gated, restrictable to specific networks, and it leaves a permanent mark

Foundations

  • Go, control plane, host agent, CLI
  • TypeScript + React, web console and portals
  • Rego, the policy engine
  • SQL, schema and migrations
  • Shell, installers and packaging
  • GNU AGPL-3.0 (commercial licenses available)
  • Public on GitHub at v1

Tested hard

  • Red-teamed with experimental AI-agent pentesting frameworks
  • Reviewed by a panel of frontier models (US and China)
  • Every finding that held up got fixed and re-tested
  • Eight threat models, one per subsystem, summarised here, published in full on GitHub, and shipping with the source
In detail

The long version of what the front page summarises.

Each of these is a sentence the homepage now states briefly. Nothing was dropped on the way here. It was moved, so the front page could stay short and this page could stay complete.

Those hosts can be anything: desktops, laptops, VMs, 64-bit Pis and SBCs, and the servers quietly humming away wherever you keep them. It starts as small as two machines, the server and a single host, and scales up from there.

Any Linux distro will do, as long as it uses systemd and has an ordinary writable root. Here's exactly what's supported. All of it lives on your own hardware, and once it's set up it can run fully airgapped, no internet required, for the most locked-down environments.

Also in v1: Active Directory integration so you keep the directory you already run, RADIUS and VPN sign-in so the other boxes on your network authenticate against adamance too, a network-wide DNS sinkhole with content filtering and locked-down Kids accounts, and an optional Samba module that lets adamance be the domain itself.

A server that's rebooting, wedged, or part-way through an upgrade doesn't change what your hosts allow. No failing open while nobody's watching, and no locking everyone out at 3am. What that costs you.

The actions that carry real risk ask for a second factor at the moment you take them, with a security key or an authenticator app. Admin can be requested for a window and left to expire, rather than held forever.

Most of the report is measured from your machines, live. Where a control can only be attested, an organisational policy or a certification, the report says so on its face, so an answer somebody typed can never dress up as evidence. And a host that has drifted reads differently from one the console couldn't reach, instead of both showing the same tidy green.

Certificates that expire in minutes instead of a key sitting in a config file. Recording as a condition of the account rather than a setting somebody forgot. It can ask for more than it has, and a person decides. Under all of it sits a ceiling no rule can raise, so a mistake in a policy cannot quietly hand it the keys.

Session recording is set per group of machines, and where you require it, it has to be live before anyone gets privileged access. Everything fails closed, so when something breaks, it breaks safe. Here is the standard it is held to.

Building each piece, I kept asking the same three questions: how could I break this, how could an attacker use it against you, and how do I close that door before it ships? Asking that at every layer, over and over, is the only way I know to end up with something that holds up when someone hostile is looking at it.

Every finding that held up got fixed and re-tested. None of it is me reinventing cryptography; it's careful wiring of tools that already earned their reputations, then attacking that wiring hard and patching it harder.

Keep them apart however your network already works, per-host firewall rules, separate VLANs, a VPN, or a Tailscale mesh. This is how enterprise Active Directory scales across a company, and it's the piece Linux never got.

No analytics, no crash pings, no "anonymous usage stats." There's nothing on my end for it to reach. This website is not adamance: it sits on Cloudflare, which counts page views, and the mailing list runs on Buttondown. The product ships with neither.

Hardened by design, not by luck.

Read the threat model for what that covers and what it deliberately does not, or go straight to the documents themselves. I won't call it unbreakable, nothing honest ever is, but it's built in layers, so getting through means beating every one of them at once.

Encrypted at rest, not just in transit.

Sensitive fields are encrypted by adamance itself, in the database and in every backup, never plaintext columns. Full-disk encryption is your volume's job, and every managed host reports whether its own disk is actually encrypted rather than adamance taking your word for it. Secrets and signing keys live in a sealed vault, and the signing keys stay offline. Backups are encrypted too, and sensitive tokens are stored only as one-way hashes.

Anchored to the hardware, if you have it.

If your server has a TPM chip, setup finds it and seals the vault's keys to that specific machine, so they're never sitting readable on the disk. Pull the drive and you get ciphertext and no way to open it. It still starts back up on its own after a reboot. No TPM is fine too, and if you'd rather hold the keys off the box completely and unseal by hand, that's a setting.

Tamper-evident audit, not just logs.

Every action lands in an append-only, hash-chained trail (HMAC-SHA256). Alter or reorder a single entry and every hash after it stops matching, even when the change comes from someone with database access. Cutting the tail off is the quiet one: what is left still verifies on its own, and catching it takes the off-box anchor, which holds a head number higher than the chain that survived. Verification runs continuously. Anchoring is a setup step rather than a default, and it is the step that turns a hash chain into something that can catch a deletion at all.

Evidence out of reach.

Set it up, and adamance backs up the audit log off-box on a timer, to email, a git repo, or external storage. Everything that already landed there is beyond the reach of anyone who later takes the server, and on write-once storage it cannot be rewritten even by you. What an attacker cannot do is keep the copies flowing while they own the machine, so the thing to watch for is copies that stop arriving. Getting to what already left means breaking into a second system as well. On airgapped setups it lands on storage with no network at all, so the only way in is physical.

Git is a Merkle tree, so a commit hash covers every byte of the repository underneath it: if your hash matches the published one, every file you just downloaded is the file I published, and there is no per-file manifest for anyone to check. One comparison does the whole tree. A release tarball and its SHA-256 sit beside it for anyone who would rather not clone.

Once it is up, the proof harness is what checks the claims: it breaks a real dependency on your running deployment, confirms the operation that should now be refused is refused, restores it, and writes down what it proved. That part runs after the install rather than before it, because it needs a live system to break.

This install script comes straight off the control plane you just stood up, built from the source you verified two steps ago and running on your own network over TLS. The thing handing you the script is the thing you already checked, which is a different proposition from piping in a script from a server you have never seen. The gateway signature-checks the agent before it will serve it and answers a refusal rather than hand over something unverified, and the console shows you a SHA-256 you can paste in to pin the download yourself instead of trusting the same server for both the bytes and the hash. Match the short code in the console, click Approve, and repeat for every box you want managed.

Built on

The open-source foundation.

This is the industry-standard, battle-hardened open source that's quietly run serious infrastructure for years, each project brilliant at its one job. adamance doesn't reinvent any of it. It wires those projects together behind a single console, and gets out of the way.

FreeIPA

Identity, groups, and Kerberos, the directory every host checks against

Keycloak

Single sign-on, OIDC, and step-up MFA

OPA

The policy engine, access rules written in Rego

step-ca

The certificate authority, short-lived SSH and TLS certs

OpenBao

The sealed secrets vault

PostgreSQL

The data store, over TLS

Grafana + Prometheus

Metrics and dashboards

Docker

How the whole thing ships and runs

Go, TypeScript, Rego

What adamance itself is written in: Go for the control plane and agent, TypeScript for the console, Rego for the rules

Compatibility

It runs on the machines you already own.

Nearly any 64-bit x86 or ARM machine running Linux, whatever distro you prefer. There are only two things the operating system can't do without: systemd, and a writable root filesystem.

The machines you manage

64-bit x86 or 64-bit ARM. Laptops, desktops, servers, VMs, and every Pi from the 3 onward on a 64-bit image. The agent is a static binary and its policy engine — about 85 MB on disk and under 100 MB of RAM, with no runtime to install. No 32-bit or RISC-V build.

The host

systemd and a writable root. The agent's entire job is governing systemd, PAM, SSSD, and sshd, so a distro that inits some other way gives it nothing to drive. Host packages install to /usr the ordinary way, which rules out immutable and atomic-rootfs images.

The server

Docker on a 64-bit host, x86 or ARM, with 16 GB of RAM. One machine runs the whole control plane: the directory, the identity provider, the database, the secret store, the policy engine, the gateway, the console and the session-recording store. It does not need to match the distro of the machines it manages. If you also manage the server as one of your hosts, it needs what any other host needs.

The server on ARM is designed, not built yet. The agent has shipped as an ARM build from the start. The server's container images are published for 64-bit x86 only today, and the session-recording store needs an ARM build its upstream does not publish. Both are build work, not a redesign.

How it is meant to run. One server, reached over a private network or a VPN rather than exposed to the open internet. Scale ceilings are still being measured, and they will go here once they are measured rather than estimated.

The login system

One login for every machine you own.

Every account lives in one directory, and only adamance is allowed to write to it.

Three components own three jobs, and none of them own each other's. FreeIPA is the directory: Kerberos and LDAP, the single record of who exists and which groups they belong to. Keycloak is the broker, running the browser sign-in and issuing the tokens the console and API check, federated to that directory in read-only mode. It cannot write to it. adamance itself owns the credential lifecycle, so a password change takes one audited path instead of two systems racing to be authoritative.

That read-only setting is a decision rather than a default nobody touched. A broker allowed to write to the directory gives you two places a password can change and no answer for which one is correct when they differ. Keeping writes on a single path is what makes the audit record of a password change worth reading at all.

Sessions key on the account's immutable directory ID, resolved once at login, rather than on a username or an email address. Both of those can change, and a freed-up username can be handed to somebody new. Key a grant on one of them and you have built a fault that quietly gives a new starter the last holder's access, months later, with nothing in the log that looks wrong. Renaming a person here moves nothing.

Two-factor lives inside the login flow rather than beside it: the broker prompts for a second factor as soon as an account has one enrolled, so switching it on for somebody is a directory change instead of a separate rollout. Certificates issued for SSH carry a hard ceiling of 24 hours, and revoking one publishes a real OpenSSH revocation list that hosts collect and apply to a running sshd.

What it still depends on. Signing in needs the control plane reachable, because that is where the directory and the broker live. What does not need it is everything your hosts are already enforcing, which is further down this page.

AI agents — designed, not built yet

An account for an AI agent, not a human's borrowed one.

Treat an agent like a coworker. Tell it what it needs to know, give it what it needs to touch, and nothing else.

This one is designed, not built yet. The subject type an agent account would use is defined, and the gateway already refuses to admit it — the fence is in place before the thing it fences. What does not exist yet is the other half: nothing can issue an agent identity, and no agent can hold a session. Everything below describes the design that is ruled and specified, not behaviour you can exercise today. It ships with the after-v1 work.

Most of what goes wrong with AI agents would have been caught by one question, asked before anyone handed anything over: which of your coworkers has the run of everything? None of them, and not because they are new or unproven. Access follows the job, so the engineer nine years in still cannot touch payroll, and nobody at all gets a copy of the admin's password. Yet that is roughly what an agent gets when it is handed a human's credentials and pointed at a fleet: more reach than anyone it works alongside, and no line of its own in the log.

The fix is not a smarter agent. It is the same arrangement you already use for people, applied to something that is not one. An agent gets its own account, its own scope, and its own line in the record. Then you can stop worrying about what it might decide to do, because the answer is the same as it is for anyone else here: whatever you granted, and nothing beyond it.

The shape of it. An agent account will be a principal type of its own in the directory, alongside people, groups, and hosts. It will authenticate with short-lived certificates like everything else, be governed by the same deny-by-default Rego, and land in the same append-only audit chain. Nothing about it is a separate system running beside the real one. It is the same machinery, with a subject that is understood not to be a person, and a set of doors that stay shut for exactly that reason.

It is also not an AI product. adamance ships no model, calls no API, and runs no inference. It issues the account and holds the boundary. Which agent you run on the other side of that boundary is entirely your business.

Its own identity, never a loaner

Not a human account with a script attached, and not a shared service account three teams use. Each agent account is to have a named human sponsor who stays accountable for it, so the log will record the agent, the sponsor, and the task it was running. "The agent did it" is never the end of the sentence.

Scoped to the job

It starts with nothing at all. Access is added per host, per command, per path, and per time window, in the same policy language that governs your people. An agent hired to restart one service on two web servers can restart that service on those two web servers, and the rest of the estate does not exist as far as it is concerned.

A ceiling policy cannot lift

Some things stay closed to an agent principal whatever a rule says: editing policy, creating or altering accounts, enrolling hosts, opening the vault, touching the audit chain, and approving anything at all, including its own request. The refusal does not live in the rules, so a mistake in the rules cannot hand an agent the keys.

Credentials measured in minutes

No password, no console sign-in, and no long-lived API token sitting in a config file waiting to be copied. The agent gets short-lived certificates like every other principal, only shorter, issued against the identity of the enrolled machine it runs on. A credential someone steals is worth minutes, on one host, for one scope.

It cannot pass a step-up check

An agent has no security key and no phone, on purpose. The operations marked in policy as needing a fresh second factor are therefore closed to it outright: it cannot satisfy the check, so it cannot clear it. The only way one of those actions happens is a human standing behind it with their own factor.

Asking is allowed, deciding is not

An agent can request something outside its scope. The request is to land in the console stating the host, the action, and the reason, with a person granting it for a window that expires on its own. Where dual-control is on, agent requests obey it the way people's do, and the approver is never the requester.

What it can see is a grant too

Read access is scoped like everything else, because what you tell an agent matters as much as what you let it run. It cannot enumerate your directory, list hosts outside its scope, or read anyone else's audit entries. Need to know is enforced here rather than requested in a prompt.

Recorded, and not optionally

Session recording will not be a per-group setting for agent accounts, it will be the condition of having one. The session is to be captured, signed, and replayable in the console, into the same hash-chained log as human activity. If the recorder is not live, the agent does not work.

Rate limits and a kill switch

Caps on actions per window and hosts touched at once, so a loop that has gone wrong trips a limit and suspends itself instead of doing the same destructive thing four thousand times. Suspending by hand is one click: certificates revoked, live sessions cut, account frozen while you work out what happened.

Why it is enforced rather than asked. An agent reads things. Tickets, log lines, config files, web pages, whatever you point it at, and some of that was written by somebody else. Sooner or later one of those somebodies will try to talk your agent into doing something you never asked for, and an agent that has been talked into it will ask politely and mean it.

So none of these boundaries are instructions in a prompt. They are the same checks on the same hosts that decide whether a person may run sudo, evaluated before anything happens and enforced locally whether or not the server is reachable. Nothing an agent reads can widen what it is allowed to do. The worst case for a hijacked agent is that it does, badly, the small set of things it was already permitted to do, on the handful of machines it was already scoped to, with the session on record.

Bring your own agent. Whatever you are running is fine: a coding agent on your laptop, a scheduled job that patches servers overnight, an in-house script with a model behind it, or whichever framework is fashionable that month. It will authenticate the way everything else does, and be governed the way everything else is. Nothing about adamance assumes a particular vendor, and nothing needs to reach the internet for any of it to work.

And here is the limit. This governs what an agent can reach and what it can do once it gets there. It does not make an agent competent. Give it a broad grant and it can do broad damage inside that grant, quickly, and the audit trail will show you exactly how. Scope is a tool for making mistakes small, not for making them impossible, and it repays being mean with it.

Where it stands. This one is in v1. It is designed in full and being built now, which makes it the newest thing on this page and the most likely to move the release date. It moves the date rather than the bar: it goes out having had the same treatment as everything else here, attacked on purpose by me and by the model panel with the agent itself assumed hostile, before anyone is asked to hand one the keys to a machine. The threat model is written on the assumption that an agent can be talked into anything, and bounds what happens when it is.

Tamper-evident audit

A record that breaks loudly instead of quietly.

Every entry is HMAC-chained to the one before it, and a signed copy can leave the box on a timer.

Each event carries a sequence number, the hash of the entry before it, and an HMAC-SHA256 computed over that sequence number, that previous hash, and the canonical form of the event itself. Alter one field in one row and its hash stops matching, and so does every entry that follows it. Delete a row instead and you leave a gap in a sequence that is unique and monotonic, so the absence is exactly as visible as the edit would have been.

Append-only is not a convention anyone has to honour here. The database enforces it: a trigger rejects UPDATE, DELETE and TRUNCATE outright, sitting behind a runtime role that was never granted them in the first place. Two independent things have to fail before the application can rewrite a row, and anyone reaching past both is someone with administrator rights on the database itself, which the chain and the off-box copy are there to catch. That trigger is exercised in CI against a real Postgres on every run, rather than a mock that agrees with whatever it is told.

Sending copies off the box is optional, and off until you point it at a destination. Turn it on and they leave on a timer, to somewhere the box does not control: external storage you own, write-once WORM hardware, a git repository, an email account, or over SSH or SCP to any machine you can reach, a NAS or a spare box on your own network included. It is not only the audit chain that can travel, either. Full system logs and firewall logs go the same way, on the same timer, signed the same way, so the forensic picture of an incident survives the machine as completely as the audit trail does.

Someone who takes the entire machine has not taken the audit chain and logs that already left it. To reach those they would need your infrastructure and your git host, or your mailbox, or the box in your cupboard, which is not one breach but two unrelated ones. A copy stays verifiable wherever it lands, so a destination has to be reachable rather than trusted. Verification runs continuously against the anchored head, so a break surfaces instead of sitting unnoticed, and there is a runbook for the morning it does.

This detects tampering. It does not prevent it. Someone with the box can still destroy what is on the box. That limit is stated in the threat model rather than left for you to find. The design accepts that and puts the evidence somewhere else instead of pretending the local copy is unbreakable.

Fail-closed

You cannot ship an unprotected endpoint by accident.

Before it accepts any traffic, the server checks that every route needing a permission rule has one, and stops if a route is missing its rule.

The failure this removes is the silent one. Somebody adds an endpoint, wires up the handler, and does not add the policy that decides who may call it. Nothing errors. The route works perfectly. It works for everybody. That mistake does not surface in a test run or a code review, because every line anyone wrote is correct, and it is the missing line that is wrong.

So the server does not rely on anyone remembering. At startup it walks every route that is meant to be gated, confirms a real policy decision sits behind each one, and aborts the boot if any route is unbacked, naming the route it could not find a policy for. An endpoint with no authorization cannot reach production by accident, because the server carrying it does not come up.

Behind that check sit more than two thousand tests over the policy code that makes the decisions, run on every change. Beside them are contract tests whose entire purpose is catching two layers that have quietly stopped agreeing about the same rule, which is the other way a gate stops meaning what you assume it means.

Where the check stops. It proves a route is wired to a policy. It does not prove the policy is the one you intended. A rule that decides the wrong thing will pass every test that agrees with it. What this removes is an entire class of accident, not the work of deciding what the rule ought to say.

Offline enforcement

Turn the server off and your hosts carry on enforcing.

Every host holds a signed copy of the policy and decides locally.

Most tools that centralise access control have a bad day when the central part is unreachable. They fail open, and for a while everybody can do anything, or they fail shut, and nobody can get in to fix whatever broke. Neither is a good position at 3am, and the usual way to find out which one you bought is during the incident.

Here every host runs its own policy engine and holds its own copy of the rules, so the decision is made on the machine, by the machine. The control plane hands out policy and collects the record, but it does not sit in the path of the decision. A server that is down, rebooting, or part-way through an upgrade does not change what your hosts permit.

That copy is not trusted merely because it arrived. Bundles are signed, the agent verifies the signature itself before loading one, and it refuses any bundle older than the one it is already running, so a stale set of rules cannot be replayed at a host to widen access. When the policy engine cannot answer, the SSH path denies instead of waving the connection through.

What happens to a certificate that expires mid-outage. One you already hold keeps working right up to its expiry, because the host checks it against a public key it was given at enrollment and never calls anywhere to do it. Getting a new one does need the server. So an outage shorter than your certificate lifetime is invisible, and a longer one stops new sessions rather than letting them through. Break-glass is the way in while it lasts, which is why it does not depend on the policy engine being up.

What that costs you. A host enforces the policy it last received. Grant or remove somebody's access while a machine is cut off and that change lands when the machine is reachable again, not instantly. Short certificate lifetimes are what bound the gap, and a revocation list a host has already collected keeps working with no server present.

One console

One console, and no walls around the rest.

Most of it is right here. What is not is still yours, in the tool that owns it.

Running six good tools usually means learning six admin panels and remembering which one owns what. That is the tax adamance exists to remove. Most settings you will touch are in the adamance console, in one place, and changing one there is a single action rather than a trip through somebody else's interface.

Underneath, the console talks to one API, and that API does the talking to FreeIPA, Keycloak, OPA, step-ca, OpenBao and the rest. You are not holding six sets of credentials or keeping six mental maps.

And past what the console covers, nothing is walled off. Every setting FreeIPA has is still FreeIPA's, and still yours. Same for the others. They are running on your hardware, configured the way their own documentation describes, and adamance does not take that away or wrap it in something you have to go through.

So you are never waiting on us to expose a switch. You go to the tool and set it there, the way you would if you were running it yourself, because you are. A wrapper that quietly narrows what the thing underneath can do eventually stands between you and fixing your own system.

And you can find any of it without knowing where it lives.

Hit Ctrl K anywhere in the console and search the guides and the settings together. Enter takes you to the page that owns the one you picked.

It answers rather than just matching: a setting you have not configured says so, one you are not allowed to see says that instead of looking like it does not exist, and a secret tells you it is set without ever showing you the value.

Active Directory

Active Directory integration.

adamance works alongside the Active Directory you already run, rather than replacing it.

Most companies that run Linux also run Active Directory, and nobody wants a second directory to keep up to date. Already have Active Directory? Keep it: adamance is being built to sit alongside the one you have rather than replace it.

It takes real setup, once. Joining the two directories takes a bit of deliberate work up front, by someone with domain admin rights, and it does mean a change on the AD side rather than a setting inside adamance. You do it once, and after that everything below happens automatically. What it involves is at the bottom of this section.

Nothing gets copied. adamance won't mirror your users, import your directory, or keep a second copy of anyone's password. There is no nightly job to drift out of date. Active Directory stays the one source of truth, and adamance asks it a question at the moment someone tries to do something.

It arrives in two steps. First signing in, where AD accounts log into the adamance console directly. Then the full trust, where an AD user resolves as a real identity on every managed Linux host without ever being given a separate Linux account.

Who does what

Active Directory keeps doing the thing it's good at: who works here, who left, who's in which team. adamance does the part AD was never built for: which Linux machines they can reach, for how long, what they can run when they get there, and a record of what happened.

Signing in to the console

Someone types their normal work password. adamance hands it straight to a domain controller and ask "is this right?" If the answer is yes they're in, with whatever access their AD groups earn them. adamance never sees the password again and never stores it.

Signing in to a Linux machine

This is where a trust comes in. Once your AD domain and adamance trust each other, a person's existing AD login works on the Linux boxes too: no second account, no separate password, nothing created on the machine itself. Their Linux identity is derived from their AD account, the same way on every host, automatically.

Writing the rules

You point at the AD groups you already have. "The people in Linux-Admins can use sudo on the production servers." adamance reads your group list, it doesn't ask you to rebuild it.

When someone leaves

You disable them in AD as you always have, and there is nothing left to let them in. A certificate already issued can be revoked on demand, and hosts stop honouring it when they pick up the new revocation list, hourly by default. A session already open stays open until it ends, which is why certificates are short-lived.

What it takes to set up

DNS that can find your domain controllers, clocks that agree, and a few firewall ports. Nothing exotic, but it is a real change to your directory rather than a checkbox. After that the trust stays up on its own, with no sync to monitor.

One scope note: adamance has its own policy engine and does not read or translate Group Policy, so your GPOs do not come across.

Samba module

Windows machines can join adamance directly.

With the optional Samba module, adamance can be your Active Directory server.

Active Directory integration, above, is about keeping the directory you already run. This is the other direction. Turn the Samba module on and adamance becomes the domain itself, so a small office can stop paying for Windows Server and still have the thing it was paying for.

Keep the AD you have, or be the AD. Same console either way, and the same record of who did what.

There is a reason this is a separate module rather than a setting. FreeIPA cannot act as a domain controller for Windows clients, and Samba 4 is the only free implementation of the protocol stack Windows expects from one. Being the domain means running that stack, so it ships as something you switch on deliberately rather than something quietly always there.

What that means

  • Windows machines join it natively, the same way they join Active Directory, because Samba implements the domain protocols Windows expects: a PAC-bearing Kerberos KDC, the AD schema, and SYSVOL and NETLOGON over SMB
  • It ships as a separate module and stays off until you switch it on. FreeIPA remains the core adamance is built on for Linux identity, policy and certificates, so this adds a capability rather than swapping the engine underneath
  • Samba is free software, so the domain runs on your hardware with no Windows Server licence anywhere in it
  • adamance still has its own policy engine and does not read or translate Group Policy, so this is domain join and directory, not a GPO console
Policy sandbox

A sandbox for your access rules.

Try a rule against a made-up situation and see what it would decide, before it can affect anybody.

Access rules are only reassuring if you can check them, so adamance lets you ask a straight question and get a straight answer: if this person, on that machine, tried to do this thing, what happens?

You fill in three things: the person, the machine, and the action. Alice from the operators group, say, on the web server, restarting a service with sudo. The verdict comes back allowed or refused, with the reason your rules produced it.

Two obvious uses. Check what your rules really say before you hand somebody access, rather than finding out afterwards. And when a person swears they should have been let in, ask the same question they asked and read the reason back.

Nothing you ask here changes anything. Nobody is granted access, no machine is told about it, and the question is not filed away as though someone really tried it. It is a what-if, and it stays one.

The same goes for a rule you are still writing. Try it against a made-up situation and see what it would do, in a sandbox that is kept well away from the rules your machines are actually enforcing. A mistake gets caught while it is still a draft, instead of after it has reached your fleet.

What it does, and what it does not

  • It asks the rules you are actually running, so the answer is the answer rather than an approximation of one
  • Nothing is written down. No access is granted, nothing is recorded as a real decision, and no machine is touched
  • It covers the decisions adamance makes: who may use sudo, who may reach a machine over SSH, and what the firewall lets through. The console starts you off with worked examples rather than a blank box
  • Two ways to use it: ask about the rules running right now, or try a draft rule in a sandbox kept apart from them, so an experiment can never change a real decision
Step-up MFA

Sensitive actions ask again.

Signing in once is not a licence to do anything for the rest of the day.

The actions that carry real risk ask for a second factor at the moment you take them, whether or not you are already signed in. A stolen session is worth a lot less when the thing worth stealing needs proof again on the way out.

Which actions count is not a judgement the console makes on the day. Every operation that carries real risk is marked in the policy itself as needing a fresh factor, so the list is the same for everybody and changing it is a policy change you can read.

Admin also does not have to be permanent. You can request it for a window and let it expire on its own rather than remembering to take it back, which is the arrangement to pick if more than one person has the keys. It is deliberately not forced: one person testing on their own machine should not have to build an approval chain to use their own server.

Two people, where it matters. Dual-control is a policy setting rather than a module you install. Mark an action as needing a second approver and the grant waits until somebody other than the requester signs it off.

Transport

Recording this traffic now will not help anyone later.

Every connection between an agent and the server uses a post-quantum key exchange.

The attack does not need a quantum computer today. It needs patience. Traffic gets captured now, stored, and opened years later when the maths gets cheaper, which is why the industry calls it harvest now, decrypt later. Anything with a long secret life is worth recording on the off-chance, and the traffic between a control plane and the machines it governs is about as long-lived a secret as you can get.

So every connection between an agent and the server negotiates X25519 with ML-KEM-768, a hybrid: the classical exchange and the post-quantum one, together. Hybrid matters. If the post-quantum half turns out to have a flaw, you still have the exchange the internet has trusted for a decade. If the classical half falls to a quantum computer, the other half is still standing. Breaking it means breaking both.

Plenty of products say "quantum-safe" and mean they have a slide about it. This one is in the TLS configuration the agent and the server share, on every handshake, today, for anyone who installs it.

And here is the limit. The key exchange is hybrid. The signatures are not. Certificates and identities still use Ed25519, which is classical, and moving those to post-quantum signatures is a later transition rather than something shipping now. Today's recording is still protected, because the exchange is what a recorder needs to break. A signature is only worth forging while the certificate is still valid, which is a matter of hours here rather than years.

Optional

Flip on what you need.

Off by default, enabled per deployment. adamance runs great without any of them. You may not need these, but you probably want them, and each one is a switch in the console rather than an afternoon of work. None of them sit in the path that decides access: that machinery is adamance itself, and it works the same with every one of these switched off.

Wazuh

SIEM, file-integrity monitoring, and threat detection

Tailscale

Reach your fleet over a private mesh instead of the open internet

Samba AD DC

adamance becomes the domain itself, and Windows machines join it natively

RADIUS and VPN sign-in

The other boxes on your network authenticate against the same directory as your hosts

DNS sinkhole and web filtering

Network-wide ad, tracker and malware-domain blocking, with category filtering and Kids accounts

Network services

VPN sign-in, RADIUS and DNS filtering.

Two ways for the rest of your network to authenticate against the same directory that governs your hosts. Both are optional, and adamance runs fine without either. Network-wide DNS filtering lives here too. Optional, and off until you turn it on.

VPN sign-in

  • Authenticates the VPN you already run rather than replacing it. OpenVPN and IPsec/strongSwan both talking to adamance directly
  • Two ways in: x509 client certificates from the built-in certificate authority, or a direct LDAP or Kerberos lookup if you would rather the VPN ask the directory itself. Certificates are revoked through the same pipeline that governs SSH, so cutting someone off covers both
  • Profiles and certificates pushed by the agent to managed hosts, so nobody is hand-installing config files or emailing a profile around
  • The machine has to qualify too, not just the person. A host that has drifted out of compliance does not get a tunnel just because someone typed the right password
  • Or skip the VPN server entirely. Tailscale's private mesh is integrated today, for teams who would rather have machines reach each other directly than run a box in the middle
  • Entirely optional. If you have no VPN, or would rather keep the one you have separate from identity, everything else works the same

RADIUS

  • A different mechanism to the VPN sign-in above, not another one of them: it makes adamance the authentication backend for anything that speaks the protocol. The two do overlap, and for a single VPN server either route would work. The difference is scope, one tunnel against every box on the network that asks
  • Two fields, one on each side. Add the device in adamance with a shared secret, then put adamance's address and that same secret into the device. Nothing per user, because your people are already in the directory
  • The boxes people already own: OpenVPN, strongSwan, Fortinet, Palo Alto, Cisco, pfSense, MikroTik, and plenty that are never tested by name, because the protocol is the contract rather than the vendor
  • The role Network Policy Server plays in a Windows domain, filled here by the same directory that already governs your hosts
  • Sign-ins land where the rest do. Admission becomes a decision about the machine and the person rather than a bare password check, and it goes into the same append-only log as an SSH session, under the same rules
  • Entirely optional. If certificates already cover your VPN, there is no RADIUS server to stand up or maintain

DNS sinkhole and web filtering

  • Network-wide ad, tracker and malware-domain blocking for every machine at once, instead of per-device blockers you keep reinstalling and that only cover one browser
  • Category-based content filtering on top, applied per account on a managed host rather than per browser
  • Kids accounts, a hardened, locked-down account type for family and shared machines
  • Filtering follows the account rather than living in a browser add-on they can uninstall. An application carrying its own encrypted resolver is a real limit, and the enforcement path gets written down here before any of this ships
Coming after v1

What comes after v1.

Designed and scoped, not built yet. These ship together with multi-forest federation below, as one release rather than trickling out one piece at a time.

Prebuilt cloud images

  • Terraform modules for AWS, Azure and GCP already exist. Next: a prebuilt image, so a cloud server is running in one step instead of several
  • Ordinary Linux underneath, so you keep the root shell

Sign in with a personal account

  • Sign in with a Google or Proton account, for homelabs and community setups, brokered through Keycloak rather than trusting the provider directly
  • It links to an adamance account instead of replacing one, so it is a way to log in and never the identity your Linux machines run on
  • Super-admin and break-glass stay local accounts, and compliance modes switch it off entirely
  • Sensitive actions still ask for a second factor or your password again
Coming after v1

Multi-forest federation.

The other half of the after-v1 work, and a separate thing from Active Directory interop above: that one is about talking to a Microsoft AD you already run, this one is about tying many adamance instances into one organization. A whole tree of realms under a single governance model, the way enterprise Active Directory has worked for decades. Designed in full, not built yet.

The shape of it. A realm is one adamance installation with its own directory and its own certificate authority, usually one site or one business unit. A forest is a group of realms sharing a namespace: one root realm, child realms beneath it, two-way trust between them from the moment a child is created. A trust is the declared relationship that lets people in one realm authenticate to machines in another. In Active Directory terms a forest is a forest and a realm is a domain, so if you've run AD, you already know the shape.

Trust types

Two-way and transitive inside a forest, created automatically with each child realm. Between separate forests: two-way, one-way, or external to a Windows AD. New inter-forest trusts default to non-transitive, and turning transitivity on is a deliberate super-admin decision.

Authentication and authorization

Standard MIT Kerberos cross-realm, nothing homemade. The receiving realm always decides, and policy sees a visitor tagged foreign-trusted rather than local, so outsiders can be treated differently on purpose. Foreign access carries extra audit detail in both forests.

No replication, queries on demand

Realms never copy each other's directories. Lookups are pull-on-demand with a short cache and an instant invalidate, so revoking someone does not wait on a timer. Queries work only across trusts you already have, the way AD's global catalog does, and there is no browse-anyone's-directory mode.

Delegation

Forest super-admin, realm super-admin, and a dedicated trust admin who can create and dissolve trusts while holding no other super-admin power.

Segmentation

A trust is an identity relationship, not a flat network. Realms stay separated by whatever you already run: per-host nftables rules pushed with policy, VLANs, a VPN, or a Tailscale mesh that reaches only what it should.

Emergency

If a partner forest is compromised, suspending the trust cuts foreign access in seconds instead of waiting for a cache to expire. Establishing and dissolving a trust are both recorded on both sides, along with the operators who approved them.

What it unlocks. Sites in three cities under one root. A subsidiary that keeps its own admins and shares a handful of systems. Contractors from a vendor's forest reaching exactly two machines and nothing else, through a one-way trust that never gives them an account on your side. An acquisition that keeps running its own directory while both sides get on with the work. A lab that shares people with production but stays a separate blast radius. One organization, many realms, one honest answer to who can touch what.

Why it isn't in v1. A trust is a door between two organizations, and a bad one isn't a bug in one install, it's a way into both. Forged cross-realm tickets, transitivity chaining somewhere nobody intended, a foreign admin quietly adding people to a group you granted access to: those are the real failure modes, and each one deserves to be got right slowly. So v1 ships as a single-realm forest, which is the same model with exactly one realm in it. The realm, origin, and forest-root fields are already in the data model, populated and indexed from day one, so switching federation on later is a feature, not a migration.

Where it stands. Designed, written down, and reviewed. Not built. When it does land it will have been through the same treatment as everything else here, attacked on purpose by me and by the model panel, before anyone is asked to trust it with a second organization.