Running Claude Code Remote Control on a Free Oracle Cloud Server: PAYG, Ampere A1 and an Always-On systemd Setup
Run Claude Code Remote Control on an Oracle Cloud Always Free Ampere A1 VM: PAYG, ARM64 setup, GitHub access and systemd to survive SSH disconnects, with fixes.
On this page
- 1.Overall architecture: Oracle provides the server, the Claude subscription is separate
- 2.Oracleās free allowance: two official documents give different numbers
- 3.Step 1: Sign up for Oracle, upgrade to PAYG, and set a budget first
- 4.Step 2: Create the Ampere A1 VM
- 5.Step 3: Connect over SSH, update the system and create dedicated users
- 6.Step 4: Install Claude Code and sign in
- 7.Step 5: GitHub access: the SSH key handles code, gh handles Issues
- 8.Step 6: Start Remote Control manually to test it
- 9.Step 7: Turn it into an always-on systemd service
- 9.1How to confirm it really is always-on
- 10.Multiple projects, multiple Remote Controls
- 11.Common errors at a glance
- 12.Security, backups and cost
- FAQ
I hand off website and product work to Claude Code from my phone. Claude Code runs on an Oracle Cloud ARM server, and Remote Control lets me connect to it from my phone or a browser. Each project has its own systemd service, set up to keep running after SSH disconnects and to start automatically when the server reboots. This post is the full set of steps from a real setup in October 2026, including the errors I ran into and how I fixed them.
The short version: the server can be an Oracle Always Free Ampere A1, but Claude Code needs its own Pro, Max, Team or Enterprise subscription. Upgrading to Pay As You Go (PAYG) lets the account use more kinds of resources, but it does not guarantee you will get a server, and it can incur charges. āAlways-onā comes from a systemd user service plus linger, not from any service promising it will never disconnect.
This is my own setup log, not an official tutorial. Oracleās free allowances and Claude Codeās commands and supported plans can change. I checked the official documentation on 12 October 2026; before you follow along, go by the latest official guidance and your own bill. Usernames and URLs in the commands are examples; replace them with your own.
Overall architecture: Oracle provides the server, the Claude subscription is separate
iPhone / Mac / browser
ā Claude Code Remote Control (connected via Anthropic's service)
ā¼
Oracle Cloud VM: Ubuntu 24.04 / ARM64 (Ampere A1)
āā Linux user: project-a ā Git repo A ā claude-project-a.service
āā Linux user: project-b ā Git repo B ā claude-project-b.service
āā Linux user: content ā separate worktree ā claude-content.service
| Component | What it does | Cost |
|---|---|---|
| Oracle Cloud VM | Provides an always-on Linux server | Free within the Always Free limits; charged above them |
| Claude Code | Writes code, edits files and runs commands on the server | Needs a Claude subscription (Remote Control supports Pro, Max, Team, Enterprise) |
| GitHub | Code lives in the repo; Claude Code pushes and pulls with an SSH key | Depends on your GitHub plan |
| systemd user service | Keeps running after SSH disconnects, starts at boot, restarts on failure | Built into Ubuntu |
Oracle only provides the server and does not cover Claudeās model costs. āFreeā in this post refers only to the server, not to the whole AI development setup.
Oracleās free allowance: two official documents give different numbers
| Official document (checked 12 October 2026) | Ampere A1 free allowance |
|---|---|
| Always Free Resources | First 1,500 OCPU hours and 9,000 GB hours per month, roughly 2 OCPUs and 12 GB of memory for Always Free accounts |
| Arm-based Compute | First 3,000 OCPU hours and 18,000 GB hours per month (including paid and trial accounts) |
Since the two disagree, I plan around the conservative 2 OCPU / 12 GB, estimating about 750 hours a month:
| Configuration | OCPU hours | GB hours | Against the conservative allowance |
|---|---|---|---|
| 1 VM with 2 OCPU / 12 GB | 1,500 | 9,000 | Within the allowance |
| 2 VMs with 1 OCPU / 6 GB each | 1,500 | 9,000 | Within the allowance |
| 1 VM with 4 OCPU / 24 GB | 3,000 | 18,000 | May exceed it; check your own account first |
A few more official rules worth knowing:
- It must be in your Home Region: Always Free servers have to be created in the tenancyās home region, and disks outside the home region are charged at regular prices.
- Total disk: boot volumes and block volumes share 200 GB in total, plus 5 volume backups. The same document gives the minimum boot volume as both 47 GB and 50 GB; go by what the Console shows.
- Idle servers may be reclaimed: if, over 7 consecutive days, the 95th percentile of CPU utilization, network utilization and memory utilization (A1 only) are all below 20%, Oracle may reclaim the server. Donāt generate fake load just to avoid reclamation.
Step 1: Sign up for Oracle, upgrade to PAYG, and set a budget first
- Sign up for an OCI account on the Oracle Cloud website and complete identity and payment method verification.
- Think before you pick a Home Region: Always Free servers can only be created there, so donāt treat it as something you can change at any time later. Decide based on where you are, latency and A1 availability.
- If you want to upgrade, find Upgrade at the top of the Console, choose Pay As You Go and follow the official steps. According to Oracleās documentation, resources that meet the Always Free conditions stay free after the upgrade.
- Set a budget right after upgrading: Billing & Cost Management ā Budgets ā Create Budget. Set a low monthly budget with email alerts. Budgets only send alerts and do not block charges automatically, so you still need to check Cost Analysis regularly.
Whether PAYG makes it easier to create an A1 depends on the region, timing and actual capacity, so I wonāt claim that āupgrading gets you one.ā
Step 2: Create the Ampere A1 VM
- Compute ā Instances ā Create Instance. Check the Compartment, Home Region and Availability Domain.
- For Image, choose Ubuntu 24.04 and make sure it is the ARM64 (aarch64) build.
- For Shape, choose VM.Standard.A1.Flex and start with 1 OCPU / 6 GB or 2 OCPU / 12 GB.
- For Capacity type, choose On-demand. Donāt choose Preemptible for an always-on server.
- Let Oracle choose the Fault Domain automatically.
- Use a sensible minimum boot volume, and first check that you have free disk allowance left.
- Networking: open TCP 22 (SSH) only to the sources that need it. Remote Control normally doesnāt need any extra inbound ports opened.
- For the SSH key, paste the public key (the
.pubfile). Never paste the private key into the Console or any chat.
Generate an SSH key on a Mac:
ssh-keygen -t ed25519 -f ~/.ssh/oci_claude -C 'oci-claude'
cat ~/.ssh/oci_claude.pub
If you see Out of host capacity when creating the instance, there is temporarily no host capacity for the options you chose. It is not a problem with your SSH key, image or credit card. I cover the troubleshooting order and what PAYG actually does in What to Do About Oracleās Out of host capacity.
Step 3: Connect over SSH, update the system and create dedicated users
chmod 600 ~/.ssh/oci_claude
ssh -i ~/.ssh/oci_claude ubuntu@<YOUR_VM_PUBLIC_IP>
You can set up a short name in ~/.ssh/config on the Mac, so afterwards you only need ssh my-claude-vm:
Host my-claude-vm
HostName <YOUR_VM_PUBLIC_IP>
User ubuntu
IdentityFile ~/.ssh/oci_claude
IdentitiesOnly yes
On the VM, update the system, install the tools and confirm it is ARM64:
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl ca-certificates jq unzip gh
uname -m # should be aarch64
free -h
Donāt run every project under ubuntu or root. Create a Linux user for each project that needs separate permissions, and enable linger so its systemd services keep running when nobody is logged in:
sudo adduser --disabled-password --gecos '' project-a
sudo loginctl enable-linger project-a
loginctl show-user project-a -p Linger # should be Linger=yes
If memory runs short, you can add swap (swap is not RAM and adds disk reads and writes). Before running this, check with df -h that you have enough disk space, and donāt append to /etc/fstab more than once:
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
printf '/swapfile none swap sw 0 0\n' | sudo tee -a /etc/fstab
Step 4: Install Claude Code and sign in
Switch to the project user to install it. Donāt use sudo to install it into rootās home directory:
sudo -iu project-a
curl -fsSL https://claude.ai/install.sh | bash
~/.local/bin/claude --version
~/.local/bin/claude # first run: follow the on-screen steps to sign in
Once you have signed in, you can exit the interactive Claude session. For installation, follow the official setup guide. Two things to watch:
- Remote Control only supports claude.ai subscription sign-in: if
ANTHROPIC_API_KEYis set in the environment, the official documentation says you will see āRemote Control requires claude.ai subscription auth.ā - Donāt copy
~/.claude/to other users: each Linux user signs in on their own.
Step 5: GitHub access: the SSH key handles code, gh handles Issues
As the project user, generate an SSH key just for GitHub and add the public key to GitHub (as a personal SSH key, or as a Deploy key for a single repo, which has narrower permissions):
mkdir -p ~/.ssh && chmod 700 ~/.ssh
ssh-keygen -t ed25519 -f ~/.ssh/github -C 'project-a-github'
cat ~/.ssh/github.pub
cat >> ~/.ssh/config <<'EOF'
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github
IdentitiesOnly yes
EOF
chmod 600 ~/.ssh/config
ssh -T git@github.com
mkdir -p ~/projects && cd ~/projects
git clone git@github.com:<OWNER>/<REPO>.git
Something I ran into: Git could push, but Claude Code said it couldnāt read GitHub Issues. The reason is that the SSH key only covers Git transfers; reading Issues and PRs requires a separate sign-in with the GitHub CLI. The steps and the permission risks are in Claude Code Canāt Read GitHub Issues.
Step 6: Start Remote Control manually to test it
Run this inside the projectās repo directory:
sudo -iu project-a
cd ~/projects/<REPO>
~/.local/bin/claude remote-control --name 'My Project - Development' --spawn=worktree
The first time, it asks Enable Remote Control? (y/n); answer y. Once it succeeds, the screen shows the connection status. Check in the Claude app on your phone or at claude.ai/code that you can see this environment, then press Ctrl+C to stop the manual test.
According to the official documentation, claude remote-control is server mode. Common flags:
| Flag | What it does |
|---|---|
--name "name" |
The name shown in the claude.ai/code list |
--spawn worktree |
Each new session gets its own git worktree (requires a git repo); the default, same-dir, has everyone share the current directory |
--capacity <N> |
Maximum concurrent sessions, 32 by default |
-c, --continue |
Resume the session the server last opened in this directory |
--debug-file <path> |
Writes debug logs to a file, useful when troubleshooting startup failures |
--spawn=worktree only separates working directories. It is not permission isolation at the operating system level.
Step 7: Turn it into an always-on systemd service
As the project user, create a user service (replace project-a, my-repo and the name with your own):
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/claude-my-repo.service <<'SERVICE_UNIT'
[Unit]
Description=Claude Code Remote Control - My Repo
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
WorkingDirectory=/home/project-a/projects/my-repo
ExecStart=/home/project-a/.local/bin/claude remote-control --name "My Project - Development" --spawn=worktree
Restart=on-failure
RestartSec=15
Environment=HOME=/home/project-a
Environment=PATH=/home/project-a/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MemoryHigh=2500M
MemoryMax=3500M
NoNewPrivileges=true
UMask=0077
[Install]
WantedBy=default.target
SERVICE_UNIT
After writing it, check that the file is complete. I have had a heredoc that never ended and a missing [Install] section:
tail -n 12 ~/.config/systemd/user/claude-my-repo.service
Then go back to the admin account ubuntu to start the service. Running systemctl --user directly in a sudo -iu shell gave me Failed to connect to bus: No medium found, so you need to specify the userās runtime directory and D-Bus explicitly (the reason is in systemctl āuser No medium found):
exit # back to ubuntu
uid=$(id -u project-a)
sudo loginctl enable-linger project-a
sudo -u project-a XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user daemon-reload
sudo -u project-a XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user enable --now claude-my-repo.service
MemoryHigh and MemoryMax are per-service limits. When running several services, adjust them to the serverās actual memory.
How to confirm it really is always-on
sudo -u project-a XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user status claude-my-repo.service --no-pager -l
- It shows
Active: active (running).enabledis not the same asrunning: I once had a service that showedenabledbut was actuallyinactive (dead). - The log has a successful connection message and the name you set. My successful log showed
Capacity: 1/32 Ā· New sessions will be created in an isolated worktree, which matches the official default limit of 32. - You can see this environment on your phone or in the browser, and you can start new work in it.
- Close SSH completely and reconnect; the service is still running.
- At a time when nothing important is running, reboot to test whether it comes back automatically.
To read the logs or restart a single service:
sudo -u project-a XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
journalctl --user -u claude-my-repo.service -n 80 --no-pager
sudo -u project-a XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user restart claude-my-repo.service
Restart only the one that has a problem, so you donāt interrupt the other Remote Control sessions that are running.
Multiple projects, multiple Remote Controls
I run several environments on the same server: different products use different Linux users, while ādevelopmentā and āwriting articlesā for the same repo are split into two working directories and two services with git worktree. When to use separate users, how to create the worktrees, and what to watch with branches and PRs are covered in Running Multiple Claude Code Remote Controls on One Server.
Common errors at a glance
| Symptom | Check first | What to do |
|---|---|---|
Out of host capacity |
Availability Domain, Fault Domain, shape | Automatic Fault Domain, another AD, a smaller shape, try again later |
| SSH timeout | IP, Security List, SSH key | Fix the network and keys first; donāt open ports to everyone |
claude: command not found |
PATH | Use the full path ~/.local/bin/claude |
systemctl --user shows No medium found |
linger, user bus, XDG_RUNTIME_DIR | Run it from ubuntu, specifying the UID and D-Bus |
enabled but inactive (dead) |
Whether it was stopped manually, the logs | Read the journal, then start it |
Repeated status=1/FAILURE |
Logs, sign-in, working directory | Stop the restart loop first, then run it manually as the same user to see the real error |
| Remote Control disappears when SSH closes | Whether it was only run manually | Create a systemd user service and enable linger |
| Git can push but Issues canāt be read | Git over SSH is not the GitHub API | Authorize separately with gh auth login |
exec format error |
Whether the downloaded program is the ARM64 build | Switch to the Linux ARM64 build; changing permissions wonāt fix it |
| Charges appear on the bill | Resources over the limit, disks, backups, network | Check Cost Analysis and adjust resources |
For startup failures such as status=1/FAILURE, I first stop that service, read journalctl --user -u <service> -n 100, then switch to the same user and directory and run claude remote-control manually. I deal with the real error message once I have it, rather than guessing whether it is sign-in, the network or the number of concurrent connections. The official documentation also notes that in server mode the process exits on its own after a network outage of roughly 10 minutes, so the service needs automatic restart configured.
Security, backups and cost
- Keep keys private: never put SSH private keys, GitHub tokens,
~/.claude/or~/.config/gh/in a repo, a systemd unit file or a screenshot. - Least privilege: projects that touch production or databases get their own Linux user;
NoNewPrivileges=trueis not a complete sandbox. - GitHub only protects what has been pushed: uncommitted changes, worktrees and Claudeās local settings are not backed up automatically, so commit and push important changes.
- Check the bill every week: OCPU hours, GB hours, disks, backups and network traffic. If you want to claim it costs nothing per month, you need that monthās bill to back it up.
- A daily health check:
PROJECT_USER=project-a
uid=$(id -u "$PROJECT_USER")
loginctl show-user "$PROJECT_USER" -p Linger
sudo -u "$PROJECT_USER" XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user --no-pager --failed
free -h
df -h /
uptime
--failed only lists failed services, so you still need to confirm that important services are active (running). Restart=on-failure also canāt fix an expired sign-in or an outage at an external service.
This setup is where Jason Finance runs every day. For how the site itself was built, see Jason Finance from Zero to One. More posts are on the AI startup topic page.
FAQ
Is Oracle Cloud Always Free really free?
Resources that meet the Always Free conditions and limits are free, and they stay free after upgrading to Pay As You Go; resources beyond the limits are charged. For the Ampere A1 free allowance, two official Oracle documents give different figures (1,500 OCPU hours / 9,000 GB hours per month, versus 3,000 / 18,000). This post uses the conservative 2 OCPU and 12 GB; your account's Always Free labels and your bill are what count.
Does upgrading to Pay As You Go guarantee I can create an Ampere A1 instance?
No. PAYG lets the account use more kinds of resources, but it does not add physical host capacity in a region, so you can still hit Out of host capacity. A PAYG account can also incur real charges, and Budgets only send alerts; they do not block charges automatically.
Which plans does Claude Code Remote Control need?
According to the Claude Code documentation, Remote Control supports the Pro, Max, Team and Enterprise plans and does not support API keys. It is off by default on Team and Enterprise, and an Owner has to turn it on in the Claude Code admin settings.
Does Claude Code keep running after I close SSH?
If you run it directly in the SSH window, the process usually ends when the connection closes. With a systemd user service plus loginctl enable-linger, the process keeps running after SSH disconnects and also starts automatically after the server reboots.
Does Permanent Remote Control mean it never disconnects?
No. In this post, always-on means it starts automatically, restarts automatically on failure and keeps running after SSH disconnects. It is not an availability guarantee from Oracle or Anthropic. The official documentation also says that in server mode the claude remote-control process exits after a network outage of roughly 10 minutes.
Can Oracle's ARM64 servers run Claude Code?
Yes. My environment is Ubuntu 24.04 aarch64 (Ampere A1). I installed Claude Code with the official install script and started Remote Control successfully. When downloading other tools, check that a Linux ARM64 build exists.
Related articles
- Building a Website Without Reading Code: How I Built Jason Finance Cheaply with Claude Code + GitHub + Cloudflare, and What It CostsI can't read code. Jason Finance runs on Claude Code, GitHub, Cloudflare Workers and Supabase free plans. The setup, costs, AI permissions and limits.
- Git Can Push, but Claude Code Can't Read GitHub Issues: SSH vs GitHub API PermissionsClaude Code can't read GitHub Issues but git push works? SSH keys only cover Git. Sign in with gh CLI, check scope, protect the token, go from Issue to PR.
- Running Multiple Claude Code Remote Controls on One Server: Linux Users, systemd and git worktreeMultiple Claude Code Remote Controls on one server: Linux users by trust, one systemd service each, git worktree for dev vs writing, --spawn=worktree limits.

Jason
Account Manager in Google Large Customer Sales and Columbia MBA admit, sharing the money tools and experience he actually uses.
Comments
Sign in with Google to comment. Your comment will not show your Google profile picture or name; it appears under a randomly generated nickname to protect your privacy.
By signing in you agree to this site's privacy policy.