neenv

neenv's mark: a stepped stone foundation under the ground line, two walls rising from it, open above

neenv

Neenv (नींव) is a foundation: the ground prepared before any wall goes up. A door, a file store or a mail service cannot stand on raw ground. Each needs the same things to be true first: machines that answer, names that resolve, certificates that every machine trusts, a place to keep secrets, someone watching.

This repository is not software. Neenv is not a product to install. It is the list of what must already be true on a platform before the applications on it can stand, and what each layer carries for them. Every layer is a commodity part; what is written here is which parts, and why each one is needed.

What stands on it

Project What it is What it needs from neenv
dvar's mark dvar the front door several applications share: one sign-in every layer below; it is the first structure on the ground
chowkidar's mark chowkidar the guard inside dvar's sign-in server what dvar needs
bhandara's mark bhandara a file store that every application keeps its files in PostgreSQL, an S3-style store, certificates, names
dakiya's mark dakiya one mail-sending service for every application PostgreSQL, certificates, names, a secret store

Anything built later stands on the same ground. Nothing in this table can exist without it.

The layers

Each layer is a commodity part. The right-hand column is what we run for it; any part that does the same job will do.

Layer What it carries What we run
Machines and power Servers that stay up, and a UPS under each one that shuts it down cleanly when the battery runs low. Debian on bare metal, no virtual machines; NUT watches each UPS
The network A private network joining every site and every device, so a phone away from home reaches a service as if it were at home. WireGuard, a full mesh between the sites; Tailscale as a second road where no port can be opened inward
DNS A name for every service. A name is how a person finds a service, and how the door knows where to send them back. Bind9 on several servers for private names; Cloudflare for public ones; OctoDNS writes both from files in git
A catalogue One list of every machine, service, name and address, which the other layers read instead of keeping their own copies. NetBox, loaded from files in git; Ansible reads its machines from it
A certificate authority One root that every machine trusts. A browser trusts the door, the door trusts a service's back channel, and the proxy trusts a service's certificate, all because of that root. step-ca, with ACME for servers and SCEP for phones; the root is limited to our own names (pattern below)
A reverse proxy Holds TLS for every name. It verifies a calling service's certificate and tells the service behind it who is calling. nginx
PostgreSQL Holds the state of the door and of the services that serve other services. PostgreSQL; MariaDB for the older applications
An object store Files kept as objects, encrypted with a key the store never sees. Garage (S3-compatible), with customer-supplied keys
A public domain The door's address: the one place a stranger is sent to sign in. Keycloak behind the door's public name
A scheduler Every recurring job (backups, checks, renewals) runs in one place, where its last run can be seen. Windmill; its jobs live in git
Backups Every store copied each night to a second place and a third, off site, and a restore proved on a schedule rather than assumed. restic to a REST server at home and an append-only twin abroad; a nightly job restores and checks
Monitoring Every layer and every service is checked, and a failure reaches a person. Prometheus, Alertmanager and Grafana, with the blackbox and node exporters; alerts land in Mattermost and by email
Mail Mail in for a named list of addresses, kept where a machine reads it; mail out signed so it is not taken for spam. Postfix at the edge accepting only the listed addresses, with OpenDKIM; Dovecot stores what arrives (LMTP into Maildir, read by machines, no IMAP served); outgoing mail through Google Workspace
Chat Where people and agents write to each other, and where alerts and job results are posted. Mattermost, signed in through the door
A secret store Passwords and keys live in one store, never in a file beside the service that uses them. OpenBao for machines (each reads with its own certificate); Vaultwarden for people
Configuration and code Every machine is built from text, so a lost one is rebuilt rather than repaired. Ansible from Gitea; Gitea Actions runs the checks and the deploys

Before building on it

Check that each of these is true first:

For a trial, dvar's demo prepares a small neenv for you: a throwaway certificate authority, nginx, PostgreSQL, an S3 store and a mail sink, in one compose file you can read in one sitting.

Patterns

How one layer is built well, with drills you can run yourself:

What a drill's exit code means

Every drill answers the same way, so a script can run them all:

Exit Run without ARM Run with ARM=<name> (one fix removed on purpose)
0 every check passed exactly the checks that arm should break failed, and no others
1 a check failed the arm did not break what it should, or broke something else: the drill cannot tell
2 it could not run: a missing tool, an unknown arm, a setup step that failed the same

An arm run that exits 0 is the proof that each check can fail. A check that never fails proves nothing. Some drills carry their arms inside one command instead: drill-environments.sh selftest, the practice's drill-done.sh selftest, the rules mode of the patching, central-logs and time drills, drill-capacity.sh, and drill-untrusted-input.sh gate, drill-ca-standby.sh and drill-tenant-restore.sh run one passing case and several broken ones, and exit 0 only when each comes out as it must.

Licence

Apache-2.0. Copyright 2026 Ploutos Services LLC.