Docs
How Girder works, how to install it on your own server, and how to run it day to day, by hand or through an agent.
Overview
Girder is a self-hosted PaaS: one static Go binary that turns a Linux server into a platform you deploy to with git push. Everything runs on your hardware. There is no hosted control plane and no per-app metering.
What happens when you push
- You push to Girder's built-in git server over SSH. Girder is the git origin; GitHub is never in the loop.
- A pre-receive hook builds your app from its Dockerfile and streams the build log back to your terminal. A failed build rejects the push, so broken code never reaches production.
- The new container rolls out behind Traefik with a health check and zero downtime. If the health check fails, Girder rolls back to the previous image on its own.
- Postgres, Redis, S3, domains, TLS, cron jobs, and backups are platform primitives, one command each.
Multi-node works the same way: provision more servers from the CLI or dashboard and assign apps to them. Same code path as single-node.
Requirements
- A Linux server with a public IPv4. Any provider works; a Hetzner cx23 or bigger is the reference setup.
- A domain whose DNS is managed by Cloudflare (free plan is fine), plus a Cloudflare API token with
Zone:DNS:Editon that domain. This is how Girder does automatic DNS and Let's Encrypt certificates. - A Tailscale account (free) and an auth key from the admin console. Tailscale is not optional: it is how you reach git, the dashboard, and every admin surface. Only ports 80 and 443 are ever public.
- Optional: a Hetzner API token. It enables the cloud firewall (80 and 443 only) and lets you provision extra nodes straight from the CLI.
Install
Download the release linked in your purchase email and copy it to your server (or build from source). Then run the installer as root:
# on the server, as root $ ./girder init \ --domain apps.example.com \ --email [email protected] \ --cf-token <cloudflare-token> \ --cf-zone <zone-id> \ --tailscale-key <tskey-...> \ --hcloud-token <optional>
Missing flags are prompted for. The installer:
- installs Docker and Tailscale and joins your tailnet,
- locks the firewall to 80 and 443 only (ufw, plus the Hetzner cloud firewall with a token),
- installs and starts the Girder daemon as a systemd service,
- writes the config and points the wildcard
*.apps.example.comat the server.
Later updates are one command on the server: girder update downloads the latest release, verifies it against the published checksums, swaps the binary, and restarts.
License
Release builds check for a license at daemon start. Install the file attached to your purchase email:
$ girder license install /root/license.json
$ girder license status # customer + update window
Your license is perpetual. When the included update year lapses, the software keeps running exactly as it is; only new updates stop until you renew.
Everyday use
Your first app
$ girder apps create myapp
$ cd myapp
$ git remote add girder ssh://git@your-server:2222/myapp.git
$ git push girder main
# → https://myapp.apps.example.com (real certificate, zero downtime)
The daily commands
- Services:
girder services add myapp postgres(orredis,s3) provisions the service and injects credentials as env vars on the next deploy. Multi-process apps share one database with--from. - Domains:
girder domains add myapp app.example.commaps a custom host with automatic DNS and TLS. Adownloadkind serves the app's bucket publicly. - Env vars: set per app, encrypted at rest. You can list names, never values.
- Rollback:
girder apps rollback myapp <sha>returns to a previous image. - Cron:
girder jobs add myapp nightly --schedule "*/15 * * * *" --cmd "..."runs inside the app's container. - Backups: nightly by default,
girder backup nowon demand. Prove restores withgirder backup verify; a restore always lands in a scratch database first, never over live data. - More nodes:
girder nodes create node-2provisions a server,girder apps assign myapp node-2moves the app, DNS included. - Dashboard:
http://your-server:8080on the tailnet. Get the token withgirder api-token. - Sanity check:
girder doctorverifies the whole installation.
Security model
Only TCP 80 and 443 face the internet. Port 443 serves your apps; port 80 stays open to redirect to HTTPS and to keep plain-HTTP fetches like robots.txt and external health checks working. Everything else lives on your tailnet:
- Git over SSH (port 2222): public-key only, with per-key app ACLs.
- Dashboard and API (port 8080): tailnet-only and token-authenticated.
- Postgres, Redis, S3: reachable only from app containers and the tailnet.
Your laptop joins the same tailnet, which is how you push code and open the dashboard without exposing a single admin port. Install Tailscale on any machine that should deploy or administer the platform.
On top of that: per-app Docker networks, an encrypted secret store, a read-only Docker API for the ingress layer, security headers (HSTS, nosniff, referrer policy) on every app by default, and a tamper-evident audit log of every mutating call.
MCP and agents
Girder ships an MCP server, girder-mcp, that exposes the entire control plane as tools. An agent connected to it can create apps, set env vars, provision databases, map domains, read logs, roll back deploys, run backups, and manage nodes.
Connect your agent
Add the server to your MCP client (Claude Desktop, Cursor, or any other):
{
"mcpServers": {
"girder": {
"command": "girder-mcp",
"env": {
"PLATFORM_API_URL": "http://100.x.y.z:8080",
"PLATFORM_API_TOKEN": "<output of: girder api-token>"
}
}
}
}
The URL is the control node's tailnet address, so the machine running the agent must be on the tailnet. The token never leaves your machines.
What the agent can do
- Apps and deploys: list, create, logs, rollback, restart, env vars
- Services: provision and share postgres, redis, s3
- Domains and DNS: map hosts, toggle proxying, upsert raw records
- Backups: run now, verify, restore to scratch, promote
- Nodes: create, scale, patch, power, reclaim disk
- Observability: health probes, uptime, the audit log
Agent skills
Two ready-made agent skills ship with Girder. One teaches an agent to install a new instance from a bare server, the other teaches it to deploy and operate apps. Install them into your agent and the whole lifecycle, from bare metal to rollback, becomes something you can delegate.
myapp with a postgres database" or "the last build failed, tell me why" are both one prompt once the MCP server is connected.