Install on a server
Run on your own server or any VPS
The provider-agnostic install. If you have a server already, or you're spinning one up at a host like Hetzner, Linode, Vultr, AWS, Google Cloud, or running your own hardware, this is the path. It's the same everywhere: an Ubuntu machine, a wildcard DNS record, Docker, then Astrodock.
Pick a place to run it
Any Linux machine you can SSH into and run Docker on works. Popular choices:
| Provider | Notes |
|---|---|
| Hetzner Cloud | Cheapest solid option; create a CX/CPX server. |
| DigitalOcean | Very beginner-friendly — see the dedicated DigitalOcean guide. |
| Linode (Akamai), Vultr, OVH | Standard VPS providers; create an Ubuntu instance. |
| AWS Lightsail | The simplest AWS option — a fixed-price VM. Easier than EC2 for this. |
| AWS EC2 / Google Compute Engine / Azure VM | Work fine; you'll set any firewall rules in the provider's console. |
| Your own hardware / homelab | Works too. If it isn't publicly reachable, use ASTRODOCK_TLS_MODE=internal (Astrodock's own certificates) instead of auto. |
Recommended specs: Ubuntu 22.04 or 24.04 LTS, at least 2 GB RAM (the first build can exhaust 1 GB), 1+ vCPU, and ~20 GB disk to start.
-
Create the server
Spin up an Ubuntu LTS instance at your provider (or use your own box). Add your SSH key during setup. Note its public IP address.
-
Point your domain at it
Apps live under one domain — we'll use
apps.example.com, so apps become<name>.apps.example.comand the dashboard isadmin.apps.example.com. At your DNS provider (registrar or cloud DNS), add a single wildcard record:Type: A Name: *.apps Value: <your server's IP>That one record covers the dashboard and every app. More detail and edge cases (apex domains, internal/LAN setups) in Custom domains & DNS.
-
Connect to the server
ssh root@<your server's IP> # (or: ssh your-user@<ip> — then prefix the commands below with sudo) -
Install Docker
On Ubuntu/Debian, the official convenience script installs Docker Engine and the Compose plugin in one go:
curl -fsSL https://get.docker.com | shVerify:
docker compose versionRunning as a non-root user?
Add yourself to the
dockergroup so you don't needsudofor every command:sudo usermod -aG docker $USER, then log out and back in. -
Install Astrodock
curl -fsSL https://get.astrodock.ai | shDownloads the compose file, generates every secret, pulls the prebuilt images, and starts the stack in
/opt/astrodock. Nothing is cloned and nothing is built on the server.Check on it with
cd /opt/astrodock && docker compose ps.Prefer to build from source?
Clone the repository, run
./scripts/setup.sh, thendocker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build. Slower on a small box, but nothing prebuilt is trusted. -
Finish setup in your browser
Open http://<your server IP>. Astrodock boots unconfigured and serves a setup wizard there:
- Create your administrator account, using the one-time token from the log
(
docker compose logs api | grep -A2 'first-run setup'). The token is what stops anyone else claiming your server first. - Enter your domain. The wizard shows the DNS record to create, prefilled with your server's IP, and checks whether it's live before you commit.
- Turn on HTTPS with a contact email, and it hands you the link to your
real dashboard at
https://admin.apps.example.com.
Running on a LAN / homelab without a public domain?
In the wizard, pick Self-signed for HTTPS and use an internal name like
home.lan— Astrodock issues its own certificates and your browser warns once. From the shell that's./scripts/setup.sh --domain home.lan --tls internal. See Custom domains & DNS.Prefer to configure from the shell?
./scripts/setup.sh --domain apps.example.com --email you@example.com --admin-email you@example.com --admin-password '…'sets everything up front and skips the wizard entirely. Orcp .env.example .envand edit by hand — see the Configuration reference. Never commit.env. - Create your administrator account, using the one-time token from the log
(
Optional: add a firewall
Astrodock publishes only 80 and 443 — its database, object store, control plane and runner all sit on an internal Docker network, unreachable from outside the machine. So make sure 80, 443 and 22 are open at your provider, but a firewall that allows exactly those adds little on day one.
It earns its keep against a future mistake: something installed later that publishes a port you didn't intend. Add inbound rules for 22, 80 and 443 in your provider's console — AWS Security Groups, Google Cloud firewall rules, Azure Network Security Groups, DigitalOcean/Vultr Cloud Firewalls — and leave outbound on allow-all, since builds fetch packages and certificates need Let's Encrypt.
Prefer the provider firewall to ufw
Docker writes its own routing rules ahead of ufw's chains, so a
ufw deny on a published port does not actually block it. Astrodock therefore
reports on exposure rather than managing it — Settings → Readiness warns if
anything beyond 80/443 becomes reachable.