Claude Code on VPS: systemd Setup That Survives Reboots
Yes, Claude Code runs well on a VPS. Install it with Anthropic's native Linux installer, sign in once over SSH, and run your jobs headless with claude -p from a systemd timer. Your agent keeps working with the laptop closed and comes back by itself after a reboot. The parts that usually break are persistence (keeping it alive after reboots), auth tokens stored on the server, and security (SSH and firewall), so most of this guide covers those three.
Which option is right for you?
The right setup depends on how comfortable you are with Linux and whether the work needs files that live on your server.
| Your situation | What to pick first | First page to open |
|---|---|---|
| Beginner, never managed a Linux server | Hostinger's "Ubuntu 24.04 with Claude Code" template on a 4 GB+ plan, because Claude Code comes preinstalled | Hostinger: How to use the Claude Code VPS template |
| You already have an Ubuntu or Debian VPS | Native installer plus a systemd timer, because it auto-updates and survives reboots | Claude Code advanced setup |
| Daily recurring work on GitHub repos, no server wanted | Anthropic's cloud scheduled tasks, because no server is needed | Automate work with scheduled tasks |
| Tight budget | Smallest 4 GB KVM plan plus Claude Pro, because 4 GB is the documented minimum | Claude pricing |
| Interactive coding from your phone | tmux on the VPS plus Remote Control, because the session stays open between visits | Remote Control docs |
| You're building a product others will use | A Claude Console API key, because Anthropic's terms require it for that use | Legal and compliance |
Can Claude Code run on a VPS?
Yes. Claude Code is a terminal program, so it runs on any supported Linux VPS over SSH, and claude -p runs it with no interactive terminal.
Anthropic lists the system requirements as Ubuntu 20.04+, Debian 10+ or Alpine Linux 3.19+, "4 GB+ RAM", an x64 or ARM64 processor, and an internet connection (as of October 2026). The model runs on Anthropic's servers, so the VPS only needs room for the Claude Code process, your repository and your test tooling. It doesn't need a GPU or a desktop environment.
Headless mode is what makes unattended work possible. According to the headless docs, adding -p (or --print) to any claude command runs it non-interactively. Claude Code exits with code 0 on success and a non-zero code on failure, so systemd and cron can tell whether a run worked. For example:
claude -p "Run the test suite and summarize failures" --allowedTools "Bash,Read"
Before you put a subscription on a server, read the usage rules. Anthropic's legal and compliance page says "Advertised usage limits for Pro and Max plans assume ordinary, individual usage of Claude Code and the Agent SDK." Your own agent working on your own repos fits that description. Running a service for other users on your Pro or Max login does not. Those users need their own credentials, and Anthropic says products should use Console API keys. The flag reference is in Claude Code Headless Mode: Flags, Auth and Cost (2026).
How do you install Claude Code on a VPS?
Run Anthropic's native installer as a non-root user, then confirm with claude --version.
The command is curl -fsSL https://claude.ai/install.sh | bash, the recommended method in the official setup page. One thing changed from older guides: you no longer need Node.js. Most articles from 2025 tell you to install Node 18 and use npm. According to the setup page, the npm package now requires Node.js 22 or later, and even then it just downloads the same native binary.
- SSH into the server:
ssh you@203.0.113.10(example IP). - Create a dedicated user for the agent so it doesn't run as root:
sudo adduser --disabled-password --gecos "" agent. - Switch to that user:
sudo -iu agent. - Install:
curl -fsSL https://claude.ai/install.sh | bash. - Open a new shell (or run
exec bash), then check the install:claude --version. A working install prints something like2.1.211 (Claude Code). - Run
claude doctor. It checks the install and your settings without starting a session. - Sign in (see the auth section below).
The native installer puts a launcher at ~/.local/bin/claude and updates itself in the background. On a server you won't watch, consider the stable channel, which runs about a week behind and skips releases with major regressions. Install it with curl -fsSL https://claude.ai/install.sh | bash -s stable, or put "autoUpdatesChannel": "stable" in ~/.claude/settings.json.
Common mistakes:
claude: command not found:~/.local/binisn't on your PATH. Hostinger's install guide fixes this withecho 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.profile.- Installed as root, running as another user: each user has their own
~/.local/binand~/.claude. Install as the user that will run the jobs. - Free plan: the setup docs say Claude Code needs a Pro, Max, Team, Enterprise or Console account. The free claude.ai plan doesn't include it.
How do you install Claude Code on an Ubuntu VPS?
On Ubuntu 20.04 or newer, use the native installer. If you'd rather update through apt, use Anthropic's signed apt repository instead. Use npm only if your tooling needs it.
| Method | Command | Auto-updates | Pick it if | |
|---|---|---|---|---|
| Native installer | `curl -fsSL https://claude.ai/install.sh \ | bash` | Yes, in the background | You want the simplest setup that stays current |
| apt repository | sudo apt install claude-code (after adding the repo) | No, you update with apt upgrade | You want version changes only when you run apt | |
| npm | npm install -g @anthropic-ai/claude-code | Only if the npm global folder is writable | Your existing tooling already manages Node |
All three are documented on the Claude Code setup page (as of October 2026).
apt route, step by step (from the official page):
sudo apt install curl gnupgsudo install -d -m 0755 /etc/apt/keyringssudo curl -fsSL https://downloads.claude.ai/keys/claude-code.asc -o /etc/apt/keyrings/claude-code.asc- Check the key:
gpg --show-keys /etc/apt/keyrings/claude-code.asc. The fingerprint should be31DDDE24DDFAB679F42D7BD2BAA929FF1A7ECACE. - Add the stable repo:
echo "deb [signed-by=/etc/apt/keyrings/claude-code.asc] https://downloads.claude.ai/claude-code/apt/stable stable main" | sudo tee /etc/apt/sources.list.d/claude-code.list sudo apt update && sudo apt install claude-code
Ubuntu pitfalls and fixes:
sudo npm install -g: the setup docs warn against this because it "can lead to permission issues and security risks." If you use npm, install Node 22+ for your own user (nvm works) and install without sudo.EBADENGINEwarning on old Node: according to the setup docs, on Node versions below 22 npm prints a warning, but the install still completes andclauderuns. Upgrading Node makes the warning go away.NO_PUBKEY BAA929FF1A7ECACEfromapt update: the key download failed. Check that the server can reachdownloads.claude.ai, then run step 3 again.- Works over SSH, fails from systemd: systemd doesn't read
~/.bashrcor~/.profile. SetPATHin the unit file (shown later). - Out-of-memory kills on a 1–2 GB VPS: the documented minimum is 4 GB. A cheap plan below that can fail during
npm installor test runs, even if Claude Code itself starts.
How do you install Claude Code on a Hostinger VPS?
On Hostinger, the easiest route is to pick the "Ubuntu 24.04 with Claude Code" template, which comes with Claude Code installed. Then sign in over SSH or with the browser terminal.
Hostinger's template guide says you can reach the server with ssh root@[your-vps-ip] or from the Web Console in the Hostinger dashboard, then sign in with claude /login. If you'd rather start from plain Ubuntu, follow the Ubuntu steps above. Nothing about Hostinger changes them.
Plans (from Hostinger's Claude Code hosting page, as of October 2026; check the official page for current prices):
| Plan | vCPU / RAM | Intro price | Renews at |
|---|---|---|---|
| KVM 1 | 1 / 4 GB | $6.49/mo (24-month term) | $11.99/mo |
| KVM 2 | 2 / 8 GB | $8.79/mo (24-month term) | $14.99/mo |
| KVM 4 | 4 / 16 GB | $12.99/mo (24-month term) | $28.99/mo |
Hostinger's hosting page notes that "All plans are paid upfront", so the monthly figure is the total price divided across the term. KVM 1 meets Anthropic's 4 GB minimum exactly. KVM 2 leaves room for builds and test runners. Hostinger suits beginners who want a preinstalled template and a browser terminal. If you need month-to-month billing at the advertised price, or a data center close to a particular region, compare other providers first.
Steps after the server is ready:
- Connect with SSH or the dashboard's Web Console.
- The template logs you in as root. Create the
agentuser (adduser --disabled-password --gecos "" agent) and copy your SSH key into/home/agent/.ssh/authorized_keys. - Run
sudo -iu agent, thenclaude --version. If the command isn't found for this user, run the native installer asagent. The template's copy may only be on root's PATH. - Sign in as
agent, not as root.
Hostinger firewall pitfall: the managed firewall lives under Security → Firewall. Click Add Firewall, name it, click Create, then the ⋯ button → Edit, and add rules with Add rule. Hostinger's firewall article warns that "An empty ruleset will block all traffic when applied to a server." Add an accept rule for SSH before you activate the group, or you'll lock yourself out. Hostinger says changes take effect in two minutes or less.
How do you set up Claude Code to run unattended on a VPS?
Use a systemd timer that triggers a service running claude -p.
Keep the auth token in a root-only environment file. This setup survives SSH disconnects (systemd owns the process, not your shell) and reboots (the timer is enabled at boot, and Persistent=true catches up on missed runs). tmux is good for interactive sessions you check on later, but a tmux session doesn't come back after a reboot.
Step 1: Create a long-lived token
On any machine with a browser (your laptop is easiest), run:
claude setup-token
The authentication docs describe this as the method "For CI pipelines, scripts, or other environments where interactive browser login isn't available." The token lasts one year. It prints to the terminal once and isn't saved anywhere, so copy it right away. It requires Pro, Max, Team or Enterprise, and it can only make model requests. It can't start Remote Control sessions.
Alternatives: a Console ANTHROPIC_API_KEY (billed per token through the API). Or run claude interactively on the VPS. Over SSH, the browser can't reach the local callback, so paste the code at the Paste code here if prompted prompt. That login is saved to ~/.claude/.credentials.json with file mode 0600.
Step 2: Store it in a root-only environment file
sudo install -m 600 -o root -g root /dev/null /etc/claude-agent.env
sudo nano /etc/claude-agent.env
Contents (example):
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-REPLACE_ME
systemd reads EnvironmentFile= before it switches to the agent user. So the agent's processes get the token, but the file stays unreadable to that user's shell and to anything Claude runs as a file read.
Two documented traps:
--bareignores this token. The authentication docs say bare mode "does not readCLAUDE_CODE_OAUTH_TOKEN". If you add--bare, useANTHROPIC_API_KEYinstead.- A stray
ANTHROPIC_API_KEYwins. In-pmode, the precedence rules say an API key "is always used when present." It ranks above the OAuth token, so a leftover key in the environment silently switches you to per-token API billing.
Step 3: Write the job script
/home/agent/jobs/nightly.sh (example; adjust the paths, prompt and tools):
#!/usr/bin/env bash
set -euo pipefail
cd /home/agent/repos/myapp
git pull --ff-only
claude -p "$(cat /home/agent/jobs/nightly-prompt.md)" \
--permission-mode acceptEdits \
--allowedTools "Read,Edit,Bash(npm test *),Bash(git diff *)" \
--permission-prompts none \
--max-budget-usd 3 \
--output-format json > "/home/agent/logs/nightly-$(date +%F).json"
Make it executable with chmod +x. According to the CLI reference, --permission-prompts none needs v2.1.259 or later. It denies anything that would otherwise wait for a person, so the run never hangs on a prompt. The JSON output includes total_cost_usd, which the headless docs describe as a client-side estimate. For safe allow-lists, see Claude Code Permissions Best Practices: Headless Template.
Step 4: Create the service and timer
/etc/systemd/system/claude-nightly.service:
[Unit]
Description=Nightly Claude Code job
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
User=agent
WorkingDirectory=/home/agent/repos/myapp
EnvironmentFile=/etc/claude-agent.env
Environment=PATH=/home/agent/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/agent/jobs/nightly.sh
TimeoutStartSec=45min
/etc/systemd/system/claude-nightly.timer:
[Unit]
Description=Run Claude nightly job at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=5min
[Install]
WantedBy=timers.target
Then:
sudo systemctl daemon-reloadsudo systemctl start claude-nightly.service(one test run right now)journalctl -u claude-nightly.service -n 50(read the result)sudo systemctl enable --now claude-nightly.timersystemctl list-timers | grep claude(confirm the next run time)
With Persistent=true, systemd records the last run time on disk. If the server was down when the job was due, the job runs right after boot.
When to use Restart=always instead
Use Restart=always only for a process that should never exit, such as your own chat-bot wrapper that calls Claude Code. systemd restarts it however it exits, and RestartSec defaults to 100ms. If a long-running agent hits a rate limit or an auth error, that default can create a tight restart loop that burns through your usage. Set RestartSec=60 or more. For retry logic around limits, see Claude Code Rate Limit Reached: Retry Setup for Cron Jobs.
Stopping a run: systemctl stop sends SIGTERM, and the headless docs say Claude Code then exits with code 143 and leaves the current turn unfinished. That's fine for a nightly job, but don't read code 143 in your logs as a crash.
How do you connect Claude Code to a VPS?
You connect to the VPS over SSH with a key, then run Claude Code in that remote shell. Claude Code doesn't attach to a server by itself.
- On your laptop, create a key if you don't have one:
ssh-keygen -t ed25519. - Copy it to the server:
ssh-copy-id agent@203.0.113.10(or paste the.pubfile into the provider's SSH key field). - Add a shortcut to
~/.ssh/config(example):
``text Host agentbox HostName 203.0.113.10 User agent IdentityFile ~/.ssh/id_ed25519 ``
- Connect with
ssh agentbox.
Pick how you work once you're connected:
| Way of working | How | Good for | Limitation |
|---|---|---|---|
| tmux session | tmux new -s agent, run claude, detach with Ctrl-b then d, come back with tmux attach -t agent | Long interactive sessions you check later | Lost on reboot |
| VS Code Remote-SSH | Connect to agentbox and use the integrated terminal | Editing files next to the agent | Needs a laptop session open |
| Remote Control | Start from a session signed in with your claude.ai account | Checking in from your phone | Doesn't work with a setup-token token |
| systemd timer | The setup in the previous section | Recurring jobs with no one watching | Not interactive |
Remote Control keeps running on the machine you started it from and reconnects when that machine is back online. On a VPS that machine never sleeps, which is why people pair it with tmux. To read the output of timer runs, journalctl -u claude-nightly.service and the JSON files in ~/logs cover most needs.
How do you secure a VPS running Claude Code?
Use key-only SSH, a firewall that opens only SSH, and a non-sudo agent user.
Also block root login. An always-on box that can push to your repos and holds a one-year token is a better target than your laptop. Claude Code connects out to Anthropic, so it needs no open inbound port of its own.
SSH hardening
OpenSSH's defaults are PasswordAuthentication yes and PermitRootLogin prohibit-password, so password logins are allowed unless you turn them off.
- Make sure your key login works for your sudo user first.
- Create
/etc/ssh/sshd_config.d/99-hardening.conf:
``text PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin no ``
- Check the config:
sudo sshd -t. Then reload:sudo systemctl reload ssh. - Keep your current session open, and log in from a second terminal before you close it.
Moving SSH to a non-default port cuts down log noise, but it doesn't replace key-only login. On Hostinger, any port change also needs a matching firewall rule.
Firewall
Ubuntu's firewall guide says "ufw by default is initially disabled." Turn it on in this order:
sudo ufw allow OpenSSHsudo ufw enablesudo ufw status verbose
If you also use a provider firewall (Hostinger's, for example), both have to allow SSH. If either blocks it, you're locked out.
Agent-level hardening
- No sudo for
agent. If a prompt goes wrong, the damage stays inside/home/agent. - Scoped Git access. Use a deploy key or a fine-grained GitHub token limited to the repos the agent works on, and protect
mainwith branch rules. - Token hygiene.
/etc/claude-agent.envstays600 root:root. Set a reminder to rotate it before the one-year expiry. If a token leaks, revoke it and runclaude setup-tokenagain. - Untrusted folders. Without
--bare, a-prun loads hooks and.mcp.jsonservers from the project folder without a trust prompt, according to the headless docs. Only point jobs at repos you control.
Copy-paste rule sets are in AI Agent Guardrails Example: Copy-Paste Claude Code Rules.
How do you use Claude Code on a VPS for recurring tasks?
Give each recurring task its own prompt file, script and systemd timer. Then read the JSON output to check whether it worked.
Good jobs for a VPS (examples, not results):
- Nightly test-and-fix: pull, run tests, fix what's obviously broken on a
claude/nightly-fixbranch, and open a draft PR. - Morning summary: read yesterday's
git logand issue tracker export, then writereports/YYYY-MM-DD.md. - Weekly dependency check: list outdated packages, update the low-risk ones on a branch, run tests, and note what failed.
Each prompt should say what "done" looks like and what the agent must not touch. Name the branch it may push to and say which files are off-limits. One timer per job keeps logs separate and lets you pause a job with systemctl disable --now name.timer.
Which scheduler fits?
| Scheduler | Survives reboot | Catches missed runs | Local files on VPS | Note |
|---|---|---|---|---|
| systemd timer | Yes | Yes, with Persistent=true | Yes | Most robust on a VPS |
| cron | Yes | No | Yes | Simpler syntax. See Claude Code Cron Job Setup |
| Anthropic cloud scheduled tasks | Not your server | n/a | No, it clones GitHub repos | Research preview, runs no more than hourly |
Anthropic's scheduled tasks (formerly routines) run on Anthropic's cloud and are available on Pro, Max, Team and Enterprise. They reject cron expressions that run more often than once per hour and cap scheduled runs at 100 per hour per account (as of October 2026). Pick them when the work is only about GitHub repos. Pick the VPS when the work needs a database, local files or tools that only live on your server.
Catch silent failures. An exit code of 0 only means the process finished. Parse the JSON result field and fail the job if the expected output file is missing. Watch for the login-expiry warning, which the auth docs show three days before an interactive login expires. A monitoring setup is in AI Agent Monitoring in Claude Code: Catch Silent Failures.
Usage. Every run draws from the same plan limits as your interactive sessions. Claude Pro is $20/month billed monthly ($17/month on annual billing), and Max starts at $100/month, according to Claude's pricing page (as of October 2026; check the official page). If nightly jobs keep reaching the limit, cut the prompt's scope before you upgrade.
Next steps
Three things you can do today:
- Install Claude Code as a non-root
agentuser on your VPS, then runclaude --versionandclaude doctor. - Generate a token with
claude setup-token, put it in/etc/claude-agent.envwith mode600, and turn on key-only SSH plusufw. - Write one small job (a read-only daily summary is a safe first choice). Wire it to a systemd timer, run it once with
systemctl start, and read the journal.
If you'd rather not run a server: Anthropic's cloud scheduled tasks come with Pro ($20/month) and Max (from $100/month) as of October 2026 (check the pricing page). You create them at claude.ai/code/routines or with /schedule. They suit GitHub-centered work like PR reviews, issue triage and docs updates. They don't suit work that needs files or services that live only on your VPS, runs more often than hourly, or an API-key-only login. The feature is also still in research preview, so its limits may change. If you want a VPS but not the setup work, Hostinger's Claude Code template removes the install step. Hardening and scheduling are still up to you.
Related guides on this site:
- Claude Code Headless Mode: Flags, Auth and Cost (2026)
- Claude Code Cron Job Setup: Run Automations Overnight
- Claude Code Permissions Best Practices: Headless Template
- Claude Code Rate Limit Reached: Retry Setup for Cron Jobs
- AI Agent Monitoring in Claude Code: Catch Silent Failures
FAQ
Can I install Claude Code on my own VPS without a dedicated dev machine?
Yes. You can do the whole setup from the VPS terminal or a provider's browser console. The one step that needs a browser is signing in. Over SSH, Claude Code shows a URL you open on any device (your phone works), and you paste the code back at the Paste code here if prompted prompt.
Does Claude Code on a VPS require a GUI or desktop environment?
No. The CLI needs a supported Linux (for example Ubuntu 20.04+ or Debian 10+), 4 GB+ RAM and an internet connection. Headless -p runs don't need an interactive terminal at all. A desktop app exists, but a server doesn't need it.
What do Reddit users say about running Claude Code on a VPS long-term?
Forum threads are individual reports, so this guide doesn't repeat them as fact. The long-term issues that are documented are logins that expire (setup tokens last one year), usage limits shared with your interactive sessions, background auto-updates, and processes that don't come back after a reboot. If you plan for those four, the most common long-term failures are covered.
Is a VPS or a local machine better for running Claude Code 24/7?
For around-the-clock jobs, a VPS is the better choice. It doesn't sleep, it has a fixed IP for SSH, and systemd brings jobs back after a reboot. A local machine is better for interactive work on private files you don't want on a server. If your recurring work is all on GitHub, Anthropic's cloud scheduled tasks let you skip owning a machine.
Sources
- Claude Code: Advanced setup (requirements, installers, updates)
- Claude Code: Authentication
- Claude Code: Run Claude Code programmatically (headless)
- Claude Code: CLI reference
- Claude Code: Legal and compliance
- Claude Code: Automate work with scheduled tasks
- Claude Code: Remote Control
- Claude pricing
- Hostinger: Installing Claude Code on a VPS
- Hostinger: How to use the Claude Code VPS template
- Hostinger: Claude Code VPS hosting plans
- Hostinger: How to use a managed VPS firewall
- systemd.service manual
- systemd.timer manual
- OpenSSH sshd_config manual
- Ubuntu Server: Firewalls (ufw)
Spotted something out of date or wrong? Tell us at shigoto.ai.note@gmail.com. Guides are re-checked against official sources on a rolling schedule.