Provisioning over SSH
Enter a host, a key and a domain. The app checks that the server is ready, generates the secrets, brings up Umami, Postgres and Caddy in an isolated Docker network, and issues a certificate. If the first install fails, it rolls the server back to how it was.
A dry run that leaves nothing behind
Before anything is installed, the app collects facts about the server: free space, busy ports, whether sudo needs a password, whether Docker is alive. Not one file is written — the script is piped to standard input, not saved to /tmp.
Analytics that stays put
Umami runs on the client's server and listens on loopback only. The app reaches its panel through an SSH tunnel; the local port is not published either. Visitor data never leaves the client's machine.
An agent that speaks up while you sleep
It lives on the client's server and watches disk, memory, CPU, domain expiry and certificate expiry. Email and Telegram alerts are sent from that server — so they arrive even when the app is closed.
Updates that can be undone
A stack update takes a database dump and a copy of the configs before touching anything. If a migration goes wrong, both come back. Backups are one button; so is removal, in two clearly separated flavours.
Everything in one window
Sites grouped by server, a dashboard per site, an overview across all of them, server health, domain and certificate deadlines, open ports. Ten to thirty clients without ten to thirty browser tabs.
Checks that ask the right question
An external check asks what the agent asks: is the page there, is the string on it, does the JSON field have a value, does the redirect happen. A fifth kind asks where the name points — that one is only visible from outside. And Job Guard watches the checks that never answer at all: a backup or cron job reports to its own secret URL, and we write to you when the report does not come.
A window into the client's database
Add a read-only SQL query on a site's own tab and it becomes a card: a number, a line of text or a small table, sized and arranged by hand. It runs from the app through the same tunnel as analytics — no phpMyAdmin, no SSH console — and the answer stays on this screen: it is never saved or sent anywhere, not even to us.
Mail for the domain, through the client's own Cloudflare
Turn on mail for a site's domain and add addresses like support@ that forward to an inbox that already exists. The app reads the domain's DNS, prepares the one line it needs if the domain already sends mail, and calls Cloudflare's API with a key that stays on this machine. Mail never touches our infrastructure — it goes straight from Cloudflare to the inbox you chose.