VPS Setup and Hardening
Choose a VPS provider, create a non-root user, configure SSH key authentication, set up a firewall, install Node.js and Claude Code, and complete first-time OAuth authentication.
What You'll Learn
- Choose the right VPS provider and plan for remote Claude Code workloads based on memory, disk, and pricing
- Create a non-root Linux user with correct sudoers restrictions for running Claude Code safely
- Harden SSH access with key-only authentication and disable password login
- Configure a firewall (ufw or iptables) to allow only required ports from required sources
- Install Node.js 22, Claude Code CLI, and complete first-time OAuth authentication on the VPS
VPS Provider Comparison and Sizing
Claude Code itself is lightweight at runtime. What you actually need is a VPS with enough memory to run Node.js comfortably plus any co-located services you intend to add later.
Minimum specs for solo Claude Code:
- 2 GB RAM (1 GB works, but is tight once you add any other service)
- 1 vCPU
- 40 GB disk (most of this is for logs and workspace files, not Claude Code itself)
- Linux (Ubuntu 22.04 or 24.04 LTS recommended)
Realistic specs if you plan to add other services (n8n, Traefik, Postgres, monitoring):
- 4-8 GB RAM
- 2-4 vCPU
- 100-400 GB disk
Provider comparison (2026 pricing):
| Provider | Entry plan | Price intro | Renewal | Notes |
|---|---|---|---|---|
| Hostinger KVM 1 | 1 vCPU, 4 GB, 50 GB | $4.99/mo | ~$11/mo | 24-month term, aggressive intro |
| Hostinger KVM 2 | 2 vCPU, 8 GB, 100 GB | $6.99/mo | ~$15/mo | Sweet spot for multi-service |
| Hetzner CX22 | 2 vCPU, 4 GB, 40 GB | $4.59/mo | $4.59/mo | Monthly, no contract, German data center |
| DigitalOcean Basic | 1 vCPU, 2 GB, 50 GB | $12/mo | $12/mo | Easiest UI, most docs |
| Vultr Cloud Compute | 1 vCPU, 2 GB, 55 GB | $10/mo | $10/mo | Many regions |
| Contabo VPS S | 4 vCPU, 8 GB, 200 GB | $6.99/mo | $6.99/mo | Best specs-per-dollar, slower support |
Our pick for this Pro Track: Hostinger KVM 2 at $7/mo intro. 8 GB RAM gives room to add n8n, a web service, and a knowledge graph later without a resize. The intro pricing lowers the barrier to experimentation.
Deal-breakers to avoid: providers with CPU-stealing neighbors (shared-hypervisor OpenVZ providers, ultra-low-end VPS marketplaces), providers with unclear data residency policies, and anything without KVM virtualization.
Initial Ubuntu Setup and Non-Root User
Never run Claude Code as root. Anthropic explicitly recommends against it, and the VS Code extension refuses to start as root for security reasons. Create a dedicated user on first login.
Step 1: SSH in as root the first time (via the password your VPS provider emailed):
ssh root@your.vps.ip.address
Step 2: Update the system and install basic tooling:
apt update && apt upgrade -y
apt install -y curl wget git tmux ufw fail2ban htop
Step 3: Create a non-root user for Claude Code:
We will call this user claude-user throughout this Pro Track, but you can pick any name.
adduser claude-user
# Set a strong password when prompted. You will mostly use SSH keys,
# but having a password is still useful for sudo.
# Grant sudo access (you can lock this down further in Module 6):
usermod -aG sudo claude-user
# Switch to the new user to verify:
su - claude-user
whoami # should print: claude-user
exit # return to root
Step 4: Copy SSH keys to the new user so you can log in directly:
mkdir -p /home/claude-user/.ssh
cp /root/.ssh/authorized_keys /home/claude-user/.ssh/
chown -R claude-user:claude-user /home/claude-user/.ssh
chmod 700 /home/claude-user/.ssh
chmod 600 /home/claude-user/.ssh/authorized_keys
From a separate terminal on your laptop, test the new user login:
ssh claude-user@your.vps.ip.address
If that works, you are ready to disable root SSH access in the next section.
Do Not Skip the SSH Key Test
Before you disable root SSH or password auth in the next section, confirm that the new user can log in via SSH key from at least two of your devices. If you lock yourself out, you will need to use your VPS provider's web console (Hostinger calls this "Browser Terminal") to recover. Better to verify access before touching sshd configuration.
Harden SSH: Keys Only, No Root Login
Password authentication and root SSH access are the two biggest attack vectors for a public-facing VPS. Both should be disabled within the first hour of setting up the server.
Edit the SSH daemon config:
sudo nano /etc/ssh/sshd_config
Find and set (or add) these three lines:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Save (Ctrl+O, Enter, Ctrl+X) and reload sshd:
sudo systemctl reload ssh
Test from a separate terminal before closing the current session:
# Should succeed:
ssh claude-user@your.vps.ip.address
# Should FAIL (password auth disabled):
ssh some-password-only-user@your.vps.ip.address
# Should FAIL (root login disabled):
ssh root@your.vps.ip.address
If your test session in a new window still works with keys, you are hardened. Close your original root SSH session.
Bonus: install fail2ban for brute-force protection:
sudo systemctl enable --now fail2ban
Fail2ban watches auth logs and auto-bans IPs that fail SSH auth too many times. This matters even with password auth disabled, because aggressive scanning still consumes CPU and fills logs.
Firewall: Only Open What You Need
A fresh VPS has all ports open by default. Lock it down with ufw (Uncomplicated Firewall), a friendlier wrapper around iptables.
Baseline firewall rules for a Claude Code VPS:
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (otherwise you lock yourself out)
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS (if you plan to add web services like n8n)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable the firewall
sudo ufw enable
# Verify:
sudo ufw status verbose
What this gives you:
- Only SSH, HTTP, and HTTPS are reachable from the internet
- All outbound traffic allowed (Claude needs to reach the Anthropic API, Telegram servers, GitHub, npm registry, etc.)
- Anything else is blocked by default
Gotchas to know:
-
If you plan to add Docker later (for n8n, Traefik, etc.), Docker bypasses ufw by default via its own iptables rules. This is a well-documented Docker quirk. Use the DOCKER-USER chain to block Docker-exposed ports from the public internet.
-
If you change your SSH port away from 22 (a common hardening step), update the ufw rule BEFORE reloading sshd, or you lock yourself out.
-
Cloud provider firewalls (Hostinger, DigitalOcean, Hetzner) exist independently of ufw. A port blocked at the provider level but open in ufw is still blocked. Check both layers when troubleshooting.
Keep a Backup Access Path
Always have at least one way to get back into the VPS if SSH breaks. Every reputable provider offers a web console ("Browser Terminal", "Recovery Console", "KVM Console") that works over HTTP independent of SSH. Bookmark it. Test it once before you need it.
Install Node.js 22 and Claude Code
Claude Code requires Node.js 18+, but we recommend Node.js 22 LTS for long-term stability. Use NodeSource, not the default Ubuntu apt repos, because Ubuntu LTS ships an older Node.js.
Install Node.js 22 from NodeSource:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --version # should print v22.x.x
npm --version
Install Claude Code globally:
sudo npm install -g @anthropic-ai/claude-code@latest
claude --version
First-time authentication:
su - claude-user # switch to your non-root user if not already
cd ~
claude
Claude Code will prompt you to authenticate. Two paths:
Path A: Claude Pro subscription (Anthropic account login)
- Opens a browser-based auth flow.
- The CLI prints a URL. Open it on any device (your laptop, your phone). Log in with your Anthropic account. Claude stores the OAuth token in
~/.claude/auth.json. - OAuth tokens currently expire after roughly 18 months. Plan to rotate them annually.
Path B: API key (pay-as-you-go)
- Generate an API key at console.anthropic.com.
- Paste it when prompted.
- API keys do not expire unless you rotate them manually.
Verify Claude Code works:
> Hello, tell me what directory I am in
Claude should respond and, if you approve the tool call, run pwd and report back. If you see the conversation working, you have a functional Claude Code installation on your VPS.
Next: Module 3 wraps this installation in a systemd service so it persists across reboots and disconnects.
Core Insights
- Hostinger KVM 2 at $7/mo intro hits the sweet spot for a Claude Code VPS with room for co-located services
- Never run Claude Code as root; create a dedicated non-root user with sudo for administrative tasks only
- Harden SSH with keys-only auth and no root login within the first hour of setup; test before disabling
- Use ufw for a simple firewall baseline (SSH + HTTP + HTTPS only) and be aware Docker bypasses ufw via DOCKER-USER chain
- Install Node.js 22 LTS from NodeSource rather than Ubuntu default repos; OAuth tokens expire annually and need rotation