I needed a dev server: VM with SSH access and dev tools installed. I described what I wanted to Claude Code and let it handle the setup.
The Prompt
I asked for a Vultr VM with 8 cores and 32GB of RAM, accessible only through Tailscale, with persistent sessions that survive network drops.
What Claude Code Built
1. Provisioned the VM via Vultr API
It created an 8-core/32GB Ubuntu instance, waited for the IP, then SSH’d in as root.
2. Hardened SSH
Port 49152 # Random high port
PermitRootLogin no
PasswordAuthentication no
ListenAddress 100.x.x.x # Tailscale interface only
Key-based auth only, listening only on the Tailscale interface.
3. Set up three layers of firewall
- UFW: Deny all incoming except Tailscale subnet
- …
I needed a dev server: VM with SSH access and dev tools installed. I described what I wanted to Claude Code and let it handle the setup.
The Prompt
I asked for a Vultr VM with 8 cores and 32GB of RAM, accessible only through Tailscale, with persistent sessions that survive network drops.
What Claude Code Built
1. Provisioned the VM via Vultr API
It created an 8-core/32GB Ubuntu instance, waited for the IP, then SSH’d in as root.
2. Hardened SSH
Port 49152 # Random high port
PermitRootLogin no
PasswordAuthentication no
ListenAddress 100.x.x.x # Tailscale interface only
Key-based auth only, listening only on the Tailscale interface.
3. Set up three layers of firewall
- UFW: Deny all incoming except Tailscale subnet
- fail2ban: Auto-ban IPs after failed login attempts
- Vultr firewall: Block everything at the hypervisor level
4. Installed Tailscale with SSH enabled
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --ssh --authkey=$TAILSCALE_KEY
This creates a second SSH path via Tailscale’s built-in SSH server, independent of OpenSSH.
5. Installed the dev stack
Node.js (via nvm), Python (via pyenv), Docker, and common tools. Configured Docker to run without sudo.
6. Set up persistent sessions with tmux
A startup script that automatically reattaches to an existing session, so network drops don’t kill running processes.
7. Created local management scripts
dev-start and dev-stop scripts on my laptop that spin the VM up and down via the Vultr API.
The Lockout
After finishing, Claude Code verified that root login was disabled by attempting to SSH in as root. The login failed. fail2ban noticed the failed attempts and banned us.
Claude Code had set up Tailscale SSH as a secondary path. It used tailscale ssh to get back in and ran:
fail2ban-client set sshd unbanip 100.x.x.x
Setup
You’ll need:
- Claude Code (or similar AI with tool use)
- A cloud provider account (Vultr, DigitalOcean, AWS, etc.)
- A Tailscale account
Store API keys as environment variables and reference them by name (e.g., $VULTR_API_KEY) so secrets don’t appear in the conversation.
Example prompt:
Create an 8-core VM on Vultr, lock it down so it’s only accessible via Tailscale, set up Node/Python/Docker, and give me scripts to start and stop it.