All tutorials
14 min read

How to Run Claude Code on an Ubuntu 24.04 VPS with tmux

Run Claude Code on an Ubuntu 24.04 VPS in 9 steps: native install as a non-root user, headless login, a tmux session, and Remote Control from your phone.

TL;DR:

  • Install Claude Code 2.1.291 as an unprivileged coder user with curl -fsSL https://claude.ai/install.sh | bash. It updates itself in the background.
  • Anthropic lists Ubuntu 20.04 or newer, 4 GB of RAM or more, an x64 or ARM64 processor and a location in a supported country as the requirements.
  • On a server without a browser, claude auth login prints a sign-in link to open on your computer. Remote Control needs this claude.ai login on a Pro, Max, Team or Enterprise plan, not an API key.
  • Run Claude Code in a named tmux session so it survives SSH disconnects, then type /remote-control to steer it from the Claude app on iOS or Android.
  • A Claude Code VPS needs only SSH (22/tcp) open: Remote Control makes outbound HTTPS requests and opens no inbound port.

Applies to: Ubuntu 24.04 LTS · Claude Code 2.1.291 · tmux 3.4 · checked October 2026

Claude Code is Anthropic's agentic coding tool: a terminal program that reads a codebase, edits files and runs commands, and sends model requests to the Anthropic API. This tutorial runs Claude Code on an Ubuntu 24.04 VPS under a non-root user, signs in without a browser, adds a deploy key for one repository, keeps the session in tmux, and connects it to your phone with Remote Control. A server keeps the session working while your laptop is closed.

Prerequisites

  • A VPS running Ubuntu 24.04 LTS with root or sudo SSH access and at least 4 GB RAM, the requirement in Anthropic's Claude Code setup guide. On Arct Cloud, Linux images give root SSH access, the Cost Optimized cvm.micro and General Purpose vm.micro plans (2 vCPU, 4 GB RAM, 40 GB NVMe each) meet that figure, and sustained full-CPU load is not permitted, so start long builds and test suites on demand. See Linux VPS plans.
  • A non-root user with sudo privileges and SSH key login. How to Generate an SSH Key covers creating the key and giving a sudo user access.
  • A Claude Pro, Max, Team or Enterprise plan, or a Claude Console account, used from one of Anthropic's supported countries.
  • A GitHub repository for Claude Code to work on, and the Claude app on your phone.

Steps 1 and 2 run as your sudo user, and Steps 3 to 9 run as coder. Replace values written in capitals, such as YOUR_SERVER_IP (for example 203.0.113.10), with your own.

Step 1: Update the server and keep only SSH open

Update the packages and install Git and tmux:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git tmux curl

The server will hold your Claude sign-in and a repository key, so confirm SSH accepts keys only:

sudo sshd -T | grep -i '^passwordauthentication'

The output should read passwordauthentication no. If it reads yes, turn off password login as Step 7 of How to Generate an SSH Key shows, before you continue.

Allow SSH before you enable the Uncomplicated Firewall (UFW), or the current session drops:

sudo ufw allow OpenSSH
sudo ufw enable

Type y to confirm. Claude Code needs no inbound port: Remote Control makes outbound HTTPS requests only. If your provider runs a network firewall in front of the server, open the same SSH port there.

Step 2: Create an unprivileged user for Claude Code

Commands that Claude Code runs on the server run as the Linux user who started it. A user without sudo limits what an approved command can reach, and Anthropic's installer installs into that user's home directory and refuses sudo. If the coder user already exists from How to Install OpenCode on Ubuntu 24.04 or the Codex CLI tutorial, skip to the login command below. Otherwise, create a coder user and copy your SSH key to it:

sudo useradd --create-home --shell /bin/bash coder
sudo install -d -m 700 -o coder -g coder /home/coder/.ssh
sudo install -m 600 -o coder -g coder ~/.ssh/authorized_keys /home/coder/.ssh/authorized_keys

Log in as coder from a new terminal on your computer:

ssh coder@YOUR_SERVER_IP

Step 3: Install Claude Code with the native installer

Run Anthropic's native installer as coder, without sudo:

curl -fsSL https://claude.ai/install.sh | bash

The script downloads the release for your processor from downloads.claude.ai, checks its SHA-256 checksum against the release manifest, and installs the launcher at ~/.local/bin/claude. It ends with Installation complete!. Check the version:

claude --version

The output looks similar to this:

2.1.291 (Claude Code)

Your output may show a newer version. If the shell reports claude: command not found, add ~/.local/bin to your PATH, as Anthropic's troubleshooting page shows:

echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

To follow the stable channel, which runs about a week behind and skips releases with major regressions, run the installer with bash -s stable in place of bash.

Step 4: Sign in without a browser

The default login opens a browser on the same machine, and the VPS has none. Remote Control in Step 8 works only with Option A.

Option A: claude.ai login for Pro, Max, Team or Enterprise

claude auth login

Choose the claude.ai option if asked, open the printed URL in the browser on your own computer, and sign in with your claude.ai account. The browser cannot reach Claude Code's callback server on the VPS, so it shows a login code instead of redirecting. Paste the code into the SSH terminal and press Enter.

Option B: Claude Console account with API billing

claude auth login --console

Sign in as in Option A; usage is billed to the Console organization instead of a subscription. To use an existing Console API key instead, set ANTHROPIC_API_KEY before you start claude; Claude Code asks once to approve it.

Check the result:

claude auth status

The JSON authMethod field reads claude.ai after Option A. Claude Code stores the login in ~/.claude/.credentials.json with file mode 0600; treat that file like a password. Skip claude setup-token here: its one-year token can only make model requests and cannot start Remote Control.

Step 5: Add a deploy key for one repository

A GitHub deploy key grants SSH access to a single repository, read-only unless you allow write access, so a leaked key reaches that repository only. Create one, replacing YOUR_REPO with the repository name:

ssh-keygen -t ed25519 -N "" -C "coder deploy key YOUR_REPO" -f ~/.ssh/YOUR_REPO_deploy_key
cat ~/.ssh/YOUR_REPO_deploy_key.pub

On GitHub, open the repository, then Settings > Deploy keys > Add deploy key. Enter a Title, such as coder on YOUR_SERVER_IP, paste the public key into Key, leave Allow write access cleared unless Claude Code should push, and click Add key.

Add the host alias GitHub documents for deploy keys, so Git uses this key for this repository. Replace YOUR_REPO in both places first:

tee -a ~/.ssh/config > /dev/null <<'EOF'
Host github.com-YOUR_REPO
  HostName github.com
  User git
  IdentityFile ~/.ssh/YOUR_REPO_deploy_key
  IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config

Clone through the alias, with YOUR_GITHUB_USER set to the repository owner:

mkdir -p ~/projects
git clone [email protected]_REPO:YOUR_GITHUB_USER/YOUR_REPO.git ~/projects/YOUR_REPO

Compare the host key with GitHub's SSH key fingerprints before you type yes. A second repository needs its own key and alias.

Step 6: Set Manual mode and deny rules

Claude Code 2.1.283 and later start interactive sessions in auto mode, where a classifier model reviews actions instead of you. On a server that holds your sign-in and a deploy key, start in Manual mode and change modes per task. Check for an existing settings file first:

cat ~/.claude/settings.json

If the file exists, open it with nano ~/.claude/settings.json and add the permissions block below inside its outer braces, after a comma, instead of replacing the file. An install with bash -s stable in Step 3 saves "autoUpdatesChannel": "stable" there. If cat reports No such file or directory, create the file:

mkdir -p ~/.claude
tee ~/.claude/settings.json > /dev/null <<'EOF'
{
  "permissions": {
    "defaultMode": "default",
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(~/.ssh/**)"
    ],
    "ask": [
      "Bash(git push *)"
    ]
  }
}
EOF
  • "defaultMode": "default" is Manual mode: Claude Code runs reads without asking and asks before most file edits, shell commands and network requests.
  • The deny rules stop Claude's file tools and recognized file commands, such as cat, from reading .env files and ~/.ssh. They do not cover a command that reads files without naming them, such as grep -r, so keep secrets out of the repository.
  • The ask rule forces a prompt before git push in every mode, auto mode included.

Shift+Tab cycles from Manual to Accept edits (file edits without asking), Plan (proposes changes without editing) and Auto. Leave --dangerously-skip-permissions off this server: Anthropic reserves that mode for isolated containers and VMs without internet access.

Step 7: Start Claude Code in a tmux session

Open a named tmux session in the repository:

tmux new -s claude -c ~/projects/YOUR_REPO

Start Claude Code inside tmux:

claude

On the first start in a folder, Claude Code shows the workspace trust dialog. Trusting a folder lets its .claude/settings.json pre-approve tools, so accept it only for repositories you control. Start in a project folder, not your home directory, where trust is never saved.

If Claude Code asks whether to change your default permission mode to auto mode, decline so the Step 6 setting stays in place. The status bar shows manual mode on. Describe a task, such as Explain the structure of this repository, and commit before large tasks so git diff shows what Claude Code changed.

Detach with Ctrl+B, then D. Claude Code keeps running after SSH closes. Reattach on your next login as coder:

tmux attach -t claude

A reboot ends the tmux session: open a new one in the repository and run claude --continue to load the most recent conversation. How to Install Codex CLI on a Linux Server uses the same pattern, so both agents can run in separate tmux sessions. Agent tasks run builds and tests on the server's vCPU, so start them when you need a result, not in a continuous loop.

Step 8: Use Claude Code Remote Control from your phone

Remote Control connects the Claude app on iOS or Android, or claude.ai/code in a browser, to the session on the VPS, while files and commands stay on the server. In the Claude Code session inside tmux, run:

/remote-control YOUR_REPO

The first time, select Enable Remote Control to confirm. YOUR_REPO becomes the session title, and the status bar shows /rc active while connected. Run /remote-control again for a status panel with the session URL and a QR code.

On your phone, sign in to the Claude app with the same account and tap Code, or scan the QR code. An online session shows a computer icon with a green dot. Permission prompts appear in the app, where you can switch between Manual, Accept edits and Plan; Auto is not available there. For a push notification when Claude Code waits for approval, run /config and turn on Push when actions required.

Claude Code makes outbound HTTPS requests to the Anthropic API, which relays messages between the app and the server, and opens no inbound port. While Remote Control is connected, Anthropic stores the session transcript on its servers to keep devices in sync.

To start later sessions with Remote Control on, run claude --remote-control "YOUR_REPO" in tmux, or set Enable Remote Control for all sessions to true in /config. Server mode, claude remote-control, serves several sessions but exits after about 10 minutes without network, while an interactive session keeps retrying.

Step 9: Verify Claude Code and Remote Control

In a second SSH session as coder, run:

claude --version
claude auth status
claude doctor

claude doctor reports installation health, settings errors and Remote Control eligibility. Then test the whole path:

  1. Detach from tmux with Ctrl+B, then D, and close every SSH connection.
  2. In the Claude app, open the session and ask Claude to create a file named remote-test.txt.
  3. In Manual mode, the edit waits for approval and the prompt appears in the app. Reject it.

A prompt on your phone after SSH closed confirms that tmux, Remote Control and Manual mode all work.

Update Claude Code

Native installs update in the background, and a new version applies at the next start. To update now:

claude update

Then type /exit in tmux and run claude --continue; Remote Control reconnects to the resumed conversation. To stay on the stable channel, add "autoUpdatesChannel": "stable" to ~/.claude/settings.json.

When Claude Code starts within three days of the claude.ai login expiring, it shows Your login expires in 3 days · run /login to renew. A session that stays open in tmux shows this warning only when it starts, and Remote Control stops once the login expires. If the transcript shows Remote Control disconnected with an expired login, run /login, then /remote-control.

Troubleshoot common Claude Code errors

SymptomCauseFix
bash: claude: command not found~/.local/bin is not on PATHAdd the Step 3 export PATH line to ~/.bashrc
Installation was killed before it could finish (exit code 137)Out of memory; the install needs roughly 512 MB freeAdd a swap file or free memory
Failed to get a valid version from downloads.claude.aiThe download service is unreachable or not offered in the server's regionCheck outbound HTTPS and the supported countries list
Remote Control requires claude.ai subscription auth.An API key, apiKeyHelper or token overrides the loginRemove it, then run claude auth login
Remote Control requires a full-scope login tokenA claude setup-token token is in CLAUDE_CODE_OAUTH_TOKENUnset it and run claude auth login
Remote Control is only available when using Claude via api.anthropic.comANTHROPIC_BASE_URL points at a gatewayUnset it and restart the session
Remote Control requires feature-flag evaluationCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC or DISABLE_GROWTHBOOK is setUnset the variable the message names
Remote Control isn't enabled for this accountStale account data after a plan changeRun claude auth logout, then claude auth login
Remote Control is disabled by your organization's policyA Team or Enterprise Owner has it off, or the login still belongs to an earlier Team or Enterprise organizationAsk an Owner to turn on the Remote Control toggle; on a Pro or Max plan, run claude auth logout, then claude auth login
Your organization has disabled Claude subscription access for Claude CodeThe organization blocks subscription loginUse Step 4, Option B, or ask your admin
Remote Control disconnected with an expired loginThe claude.ai login expiredRun /login, then /remote-control
Session offline in the app after SSH closedClaude Code ran outside tmuxStart it in tmux and run claude --continue

For other problems, run claude doctor.

FAQ

Can I run Claude Code on my server?

Yes. Claude Code runs on Ubuntu 20.04 or newer with 4 GB of RAM or more and an x64 or ARM64 processor, and Anthropic lists a supported country as a requirement. Install it as an unprivileged user with the native installer, sign in with claude auth login, and run it in tmux.

How much RAM does Claude Code need?

Anthropic lists 4 GB of RAM or more. The installer needs about 512 MB of free memory and stops with exit code 137 when the server runs out. The model runs on Anthropic's servers, so the VPS memory goes to Claude Code and the builds and tests it starts.

Is Claude Code free?

No. Claude Code needs a Claude Pro, Max, Team or Enterprise plan, or a Claude Console account billed for API usage. The free claude.ai plan does not include Claude Code access.

Can I use Claude Code Remote Control without a subscription?

No. Remote Control needs a claude.ai login on a Pro, Max, Team or Enterprise plan; API keys, setup-token tokens, LLM gateways and providers such as Amazon Bedrock are not supported. On Team and Enterprise plans, an Owner must turn it on first.

Why is Claude Code Remote Control not available?

Remote Control is unavailable when an API key or token takes precedence over your claude.ai login, ANTHROPIC_BASE_URL points at a gateway, your organization has it off, or your account data is stale. Run claude doctor to see which eligibility check failed.

Why does Claude Code Remote Control keep disconnecting?

The claude process has to keep running, so start it inside tmux, where closing SSH does not end it. An expired claude.ai login also stops Remote Control: run /login, then /remote-control. In server mode, the process exits after about 10 minutes without network.

How does Claude Code Remote Control work?

Claude Code keeps running on your server and makes outbound HTTPS requests to the Anthropic API, which relays messages from claude.ai or the Claude app. It opens no inbound port. Anthropic stores the session transcript while Remote Control is connected.

Next steps

Arct Cloud General Purpose plans run on AMD EPYC Milan 7003 Series processors up to 3.7 GHz with NVMe storage. Compare plans.

This work is licensed under CC BY-NC-SA 4.0.