hostit
hostit is a tiny self-hosted platform for small web apps, built to be driven by AI agents (or humans) over SSH and a REST API. Each app runs in its own container with its own subdomain and an automatic HTTPS certificate. The whole thing is a handful of small Go binaries, and it runs my (and my kids’) little apps – including this website.
hostit is free to run, but not currently open source: the binaries below are free to download and use; the source is not public right now. See the changelog for what’s changed recently.
What it is
hostit runs as three small services, and the same setup covers every size:
- hostit-control – the registry, REST API and web dashboard. It decides; it never runs your apps.
- hostit-node – the per-machine runtime: it builds and runs the containers, manages their users, btrfs subvolumes and firewall rules. One per machine.
- hostit-proxy – the front door: TLS on :443 and per-subdomain routing.
On a single box all three run together. To grow, add machines that run only hostit-node and dial back to control over mTLS – apps move between nodes without downtime, and a control restart never stops apps serving.
Download
Latest release: v0.48.1 (Linux, amd64). Older versions and checksums are in the archive.
- hostit-control (14.4 MB) – registry, REST API, web UI. Start here.
- hostit-node (19.1 MB) – the app runtime. Needs a container runtime (podman) on the box.
- hostit-proxy (5.3 MB) – TLS termination and routing.
- Ansible example (15 KB) – a self-contained example role + playbook that installs and configures all three. The recommended way to deploy.
Verify downloads against SHA256SUMS.
Install with Ansible (recommended)
The example role installs the packages, writes each component’s config under /etc/hostit/, hardens sshd for app logins, puts app homes on btrfs, and starts the services. Upgrading is just re-running it with a newer hostit_version.
curl -LO https://heckel.io/hostit/archive/v0.48.1/hostit-ansible-example-0.48.1.tar.gz
tar xzf hostit-ansible-example-0.48.1.tar.gz && cd hostit-ansible
# Point it at your host(s) and fill in your settings + secrets:
cp inventory/single-box.example.yml inventory/hosts.yml # or split.example.yml for multi-node
cp group_vars/hostit.example.yml group_vars/hostit.yml # domain, admin emails, OAuth, TLS
cp group_vars/hostit_vault.example.yml group_vars/hostit_vault.yml # secrets (encrypt with ansible-vault)
ansible-playbook -i inventory/hosts.yml playbook.yml
You need a wildcard DNS record (*.apps.example.com and apps.example.com) pointing at the box. For instant TLS on new apps, give it Route 53 credentials (DNS-01); otherwise apps get a certificate on first request. The README.md in the tarball covers single-box vs split (multi-node) topologies and the cluster certificates a split setup needs.
Install manually
If you’d rather not use Ansible, install the packages directly. The node package needs a container runtime first:
sudo apt-get install -y podman
sudo dpkg -i hostit-node_0.48.1_linux_amd64.deb
sudo dpkg -i hostit-control_0.48.1_linux_amd64.deb hostit-proxy_0.48.1_linux_amd64.deb
Each package installs a systemd service (hostit-control, hostit-node, hostit-proxy) and drops an /etc/hostit/<component>/<component>.yml.example. Copy each to <component>.yml, set your domain (and OAuth/TLS/AI keys if you want them), put app homes on a btrfs filesystem, then systemctl enable --now the three services.
Create your first app
Once it’s up, everything is a REST call, a CLI command, or an MCP tool with an API token – which is the point, since an AI agent can drive it:
hostit control app add myapp # subdomain + SSH login, ready to deploy
# ... upload files, write hostit.yml ...
hostit deploy # apply hostit.yml and (re)start it
An app is either mode: static (hostit serves public/) or mode: app (your command, supervised). SSH straight into the container (ssh myapp@apps.example.com) to install packages or debug.
What you get
- One app, one container, one subdomain, one certificate – no per-app plumbing.
- Apps are btrfs subvolumes cloned from a shared base image, so a new app is nearly free and snapshots are cheap. Snapshots and one-click rollback are built in.
- A built-in assistant: describe an app in plain language and it writes, deploys, and iterates on it in place.
- Conversations (new in v0.41.0): standalone chats with the assistant that cost almost nothing when idle, and convert into a real hosted app the moment they outgrow a chat.
- Connections: grant an app an OAuth account, a pasted credential, or an MCP tool server – it reads them from its own socket instead of holding a secret. Mark one “include by default” and every new chat and app gets it; a first-run tour offers the ones the operator suggests.
- hostit as an MCP server (new in v0.44.0): point an MCP client on your own machine (Claude Code, Claude Desktop) at hostit and it gets typed tools to create, deploy, inspect and manage your apps – you log in once in the browser, with no token to paste. As of v0.46.0 those tools also list and change which of your connections an app may use.
- Apps move between nodes (new in v0.43.0) with their files, snapshots and identity intact, over the cluster link, no SSH; a moved app lands as a clone of the shared base image, not a full copy.
- IPv6 (new in v0.45.0): where the host has a public IPv6 address, apps answer over IPv6 and make outbound IPv6 connections, with the same per-app egress isolation applied to v6 as to v4.
- A container per app with per-app uid mapping and nftables egress rules, so apps cannot see or reach each other.