This guide walks through deploying a fully automated remote development server from scratch.
-
A cloud provider account — Hetzner is recommended (affordable, EU-based, great API). Any provider supporting cloud-init works (AWS, GCP, Azure, DigitalOcean, etc.).
-
A domain name — with DNS managed by Cloudflare.
-
A Cloudflare API token — with
Zone → DNS → Editpermission for your domain's zone. -
Server requirements:
- Ubuntu 24.04 LTS
- Minimum: 2 vCPUs, 4 GB RAM, 40 GB SSD (Hetzner CPX21 or larger)
- Recommended: 4 vCPUs, 8 GB RAM, 80 GB SSD (Hetzner CPX31)
-
Copy the example file:
cp cloud-init.example.yaml cloud-init.yaml
-
Fill in all placeholders:
Placeholder Example Value Description <YOUR_DOMAIN>example.comYour root domain <YOUR_SUBDOMAIN>devSubdomain for the dev server <YOUR_EMAIL>admin@example.comEmail for Let's Encrypt & alerts <YOUR_CLOUDFLARE_API_TOKEN>cf_abc123...Scoped Cloudflare API token <YOUR_CLOUDFLARE_ZONE_ID>zone_xyz789...Cloudflare zone ID for your domain <YOUR_ADMIN_PASSWORD>MySecurePass1Coder admin password (≥8 chars, no spaces). Omit to auto-generate. -
Optionally enable AI agents:
ENABLE_AGENT_COPILOT=true ENABLE_AGENT_CLAUDE=true ENABLE_AGENT_CODEX=true ENABLE_AGENT_OPENCODE=true GITHUB_TOKEN=ghp_xxxx ANTHROPIC_API_KEY=sk-ant-xxxx OPENAI_API_KEY=sk-xxxx OPENCODE_PROVIDER=opencode-zen
⚠️ NEVER commitcloud-init.yaml(the filled-in version) to Git.
# Install hcloud CLI
brew install hcloud # macOS
# or: apt install hcloud-cli # Ubuntu
# Create the server
hcloud server create \
--name dev-server \
--type cpx31 \
--image ubuntu-24.04 \
--location nbg1 \
--ssh-key your-ssh-key-name \
--user-data-from-file cloud-init.yaml- Go to https://console.hetzner.cloud
- Create new server → Ubuntu 24.04
- Choose CPX31 (or larger)
- Under Cloud config, paste the contents of your
cloud-init.yaml - Add your SSH key
- Create server
- AWS: Use the
UserDatafield in EC2 launch configuration - GCP: Use
metadata.user-datawithcloud-initcompatible images - DigitalOcean: Paste into the "User data" field when creating a droplet
If your server does not support cloud-init (e.g. a dedicated/bare-metal machine), use the one-liner installer instead:
-
Run the configurator and let it generate
RVSconfig.yml(offered aftercloud-init.yaml). -
SSH into the server and run:
curl -fsSL https://raw.githubusercontent.com/PhilippWu/RemoteVibeServer/main/install.sh | sudo bash -
Paste the contents of
RVSconfig.ymlwhen prompted, then press Ctrl-D.
The script parses the YAML into /etc/dev-server/env, installs Docker, UFW,
fail2ban, and downloads the provisioning scripts — then runs setup.sh
automatically.
Provisioning takes approximately 3–8 minutes depending on server specs and network speed.
# SSH into the server
ssh root@<SERVER_IP>
# Watch the provisioning log
tail -f /var/log/dev-server-provision.logcloud-init status --wait# On the server:
cat /etc/dev-server/statusExpected output:
provisioned_at=2024-01-15T10:30:00Z
fqdn=dev.example.com
public_ip=1.2.3.4
coder_url=https://dev.example.com
coder_status=active
caddy_status=active
| Check | Command / Action |
|---|---|
| DNS resolves correctly | dig dev.example.com → should show your server's IP |
| HTTPS works | curl -I https://dev.example.com → 200 or 307 |
| Valid TLS certificate | openssl s_client -connect dev.example.com:443 |
| Coder is running | systemctl status coder |
| Caddy is running | systemctl status caddy |
| Firewall is active | ufw status |
- Open
https://dev.example.comin your browser - Log in with the admin credentials — username is the email you configured, password is
CODER_ADMIN_PASSWORD(or check/etc/dev-server/envon the server if it was auto-generated) - Create a workspace using the pre-installed Docker template
- Click "VS Code Web" in the workspace card to open VS Code directly in the browser
# Install Coder CLI locally
curl -fsSL https://coder.com/install.sh | sh
# Login
coder login https://dev.example.com
# List workspaces
coder ls
# Connect via SSH
coder ssh my-workspace
# Or: configure SSH for VS Code Remote
coder config-ssh
# Then open VS Code → Remote-SSH → select "coder.my-workspace"Coder configures SSH automatically. After coder config-ssh, your ~/.ssh/config will have entries like:
Host coder.my-workspace
HostName coder.my-workspace
ProxyCommand coder ssh --stdio my-workspace
...
Open VS Code → Remote-SSH → connect to coder.my-workspace.
If you enabled AI agents during provisioning, verify they are available:
# In a Coder workspace terminal:
which github-copilot-cli # if ENABLE_AGENT_COPILOT=true
which claude # if ENABLE_AGENT_CLAUDE=true
which codex # if ENABLE_AGENT_CODEX=true
which opencode # if ENABLE_AGENT_OPENCODE=true# Check the full log
cat /var/log/dev-server-provision.log
# Check cloud-init logs
cat /var/log/cloud-init-output.log
journalctl -u cloud-init# Check the Cloudflare record was created
dig dev.example.com @1.1.1.1
# If not, re-run DNS setup
source /etc/dev-server/env
bash /opt/dev-server-provision/infra/dns.sh# Check Caddy logs
journalctl -u caddy --no-pager -n 50
# Caddy needs port 80 open for ACME challenge
ufw status | grep 80systemctl status coder
journalctl -u coder --no-pager -n 50
# Ensure Docker is running
systemctl status dockerAll scripts are idempotent. To re-provision:
FORCE_DOWNLOAD=true /etc/dev-server/bootstrap.sh 2>&1 | tee /var/log/dev-server-provision.logcurl -fsSL https://coder.com/install.sh | sh -s -- --method=standalone
systemctl restart coderapt-get update && apt-get install --only-upgrade caddy
systemctl restart caddyFORCE_DOWNLOAD=true /etc/dev-server/bootstrap.sh