Title: Run Codemany on your own Linux server
URL: https://codemany.com/docs/machines/linux-server
Description: Set up Codemany on a mini PC at home or in the office, or on a Google Cloud VM: hardware, Ubuntu Server, install, setup over SSH, the fleet, costs and troubleshooting.
All pages as Markdown: https://codemany.com/llms.txt

---

[Machines](https://codemany.com/docs#machines)

# Run Codemany on your own Linux server.

Codemany runs your GitHub Actions jobs on a machine you own. Set one up on a small box on your network, or on a cloud VM.

## What you need

- A 64-bit Linux machine (x86-64 or ARM64) with systemd and glibc. **Supported:** Ubuntu 22.04 and 24.04 LTS, and Debian 12 or newer, with the apt repository. Fedora and other glibc distros work with the install script. This guide uses **Ubuntu Server 24.04 LTS**.
- A GitHub account that can add self-hosted runners to your repos (repo admin, or org owner for an organization).
- Another computer with a browser, to finish setup.

## How big a machine

Codemany sizes the runner count to the machine. Each runner gets **4 GB of memory, 2 CPU threads and 15 GB of disk**, and **4 GB of memory and 20 GB of disk** stay free for the system. One runner runs one job at a time.

| Machine | Runners at once |
| --- | --- |
| 4 threads, 16 GB, 256 GB disk | 2 |
| 8 threads, 32 GB, 512 GB disk | 4 |
| 16 threads, 32 GB, 1 TB disk | 6 |
| 16 threads, 64 GB, 1 TB disk | 8 |

A "16 GB" machine shows a little less to Linux, so it fits 2 runners, not 3. After installing, `codemany capacity` prints the real number and what limits it.

**A fresh VM per job** (the `vm` isolation mode) needs hardware virtualization: Intel VT-x or AMD-V, turned on in the BIOS. Check with `ls /dev/kvm` after installing Linux. This mode is experimental. The default mode does not need it.

## 1. A small box at home or in the office

### Buy a mini PC

Any small x86-64 PC works. We bought this one: [on Amazon](https://www.amazon.com/dp/B0DRVSK2T9). For about 6 runners, pick 8 cores (16 threads), 32 GB of memory and a 1 TB NVMe disk. For 2 runners, 4 cores and 16 GB are enough. Wired Ethernet is better than Wi-Fi.

### Install Ubuntu Server 24.04 LTS

1. Download Ubuntu Server 24.04 LTS from [ubuntu.com/download/server](https://ubuntu.com/download/server).
2. Write it to a USB stick (balenaEtcher, or Raspberry Pi Imager, both free).
3. Boot the mini PC from the stick (usually F7, F11 or F12 at power-on) and follow the installer.
4. On the **SSH Setup** screen, tick **Install OpenSSH server**.
5. Pick a username. Jobs run as this user.

While you are in the BIOS: turn on **VT-x / AMD-V** (for VM-per-job), and set **Restore on AC power loss** to **Power on**, so the box comes back after a power cut.

### Reach it over SSH

You can unplug the screen and keyboard now. Everything else happens over SSH from your Mac or PC. On the mini PC, `hostname -I` prints its address. Then, from your computer:

```
ssh you@192.168.1.50          # your username and the box's address
```

The apt package brings Avahi along, so your network finds the box by name (`ssh you@<hostname>.local`, `http://codemany.local:8825`). With the one-line installer, install it yourself: `sudo apt install -y avahi-daemon avahi-utils`.

### Install Codemany

**With apt** (recommended: `apt upgrade` keeps it updated). The key is installed only if its fingerprint is `92EA E8F4 E140 E71F E883 C291 DBC1 D871 7AE5 E521`:

```
curl --proto '=https' --tlsv1.2 -fsSLo codemany.gpg \
  https://codemany.com/download/linux/apt/codemany-archive-keyring.gpg
gpg --show-keys --with-colons codemany.gpg | grep -qx 'fpr:::::::::92EAE8F4E140E71FE883C291DBC1D8717AE5E521:' \
  && sudo install -m 644 codemany.gpg /usr/share/keyrings/codemany-archive-keyring.gpg \
  || echo "codemany.gpg is not Codemany's key: stop" >&2
echo "deb [signed-by=/usr/share/keyrings/codemany-archive-keyring.gpg] https://codemany.com/download/linux/apt stable main" \
  | sudo tee /etc/apt/sources.list.d/codemany.list
sudo apt update && sudo apt install -y codemany
```

Installing starts Codemany as your service and prints the setup link.

**Or with one line** (any glibc distro; it checks the download's signed SHA-256 and starts the service for you):

```
curl --proto '=https' --tlsv1.2 -fsSL https://codemany.com/install.sh | sh
```

On a server (no desktop), installing also turns on lingering, so Codemany keeps running after you close SSH and starts at boot.

### Finish setup in a browser

On a server, Codemany serves its setup page on your network until it is set up. Print its link again any time:

```
codemany setup-link
```

It prints `http://192.168.1.50:8825/#code=…` (and a `127.0.0.1` one). Open it from any computer on your network; `http://codemany.local:8825/#code=…` works too. The code makes it yours: without it, nobody can do anything on that page.

Not on the same network? Tunnel over SSH, then print the link for your end of the tunnel:

```
ssh -L 18825:127.0.0.1:8825 you@192.168.1.50
codemany setup-link --port 18825    # on the box: http://127.0.0.1:18825/#code=…
```

(Port 18825 on your side, because a Mac running Codemany already uses 8825.)

In the setup page:

1. **Connect GitHub:** enter a code on github.com, or paste a token.
2. **Pick repos**, or an organization.
3. **Start runners.** The 14-day trial starts here, no card.

To keep setup on the box itself (tunnel only), install the service with `codemany install-service --setup-listen 127.0.0.1:8825`. On a cloud VM (Google Cloud, AWS, Azure, DigitalOcean, Hetzner and others) that is the default: setup stays on the box, and you reach it through the tunnel.

### Use it in workflows

```
jobs:
  test:
    runs-on: [self-hosted, Linux, codemany]
```

Keep `Linux` in `runs-on`: without it, a job can land on your Mac too.

### Open the dashboard

Once set up, the dashboard is on your network at `http://codemany.local:8825`. If your Mac runs Codemany too, it already has that name, and the box is `http://codemany-2.local:8825`. `http://<hostname>.local:8825` always works.

Without the admin token, the dashboard is read-only, also on the box and through an SSH tunnel; its footer says so. To use its buttons, run `codemany admin-token` on the box and paste the token into the dashboard's **Admin token** button.

### Add it to your Mac's fleet

1. On your Mac, open **Machines**. The box shows under **Nearby**.
2. Choose **Add to the fleet…**. The Mac asks the box for a code.
3. On the box, print the code: `codemany pair`.
4. Type it on the Mac. Both now show **All machines**, and either one opens the other.

If the box isn't under Nearby, choose **Add a machine…** and type its address (`192.168.1.50:8825`). If `ufw` is on, allow your network: `sudo ufw allow from 192.168.0.0/16 to any port 8825`.

### Keep it updated and awake

Ubuntu Server installs security updates by itself (`unattended-upgrades`). To let it update Codemany too:

```
echo 'Unattended-Upgrade::Origins-Pattern { "origin=Codemany,suite=stable"; };' \
  | sudo tee /etc/apt/apt.conf.d/52codemany-unattended
```

Or update by hand: `sudo apt update && sudo apt upgrade`.

Nothing else to do: Codemany notices the new version, lets running jobs finish, and restarts into it. To restart by hand without cutting a job short:

```
codemany drain --wait && systemctl --user restart codemany && codemany resume
```

Ubuntu Server does not sleep. If you installed a desktop edition, stop it from sleeping:

```
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
```

## 2. A cloud VM (Google Cloud)

Codemany can create and manage a cloud machine for you on Google Cloud, Hetzner or DigitalOcean: SSH key, install, setup, fleet, idle stop and removal included. See [Cloud machines](https://codemany.com/docs/machines/cloud). The steps below set one up by hand.

A cloud VM costs money every hour it runs, and it is not on your network. Read [Reaching it safely](https://codemany.com/docs/machines/linux-server#safely) before you start.

### Set up Google Cloud

1. Create an account at [cloud.google.com](https://cloud.google.com) and open the console.
2. **Billing:** add a billing account (Billing › Manage billing accounts).
3. **Project:** create one (the project picker at the top › New project), for example `codemany-ci`, and link it to the billing account.
4. **Compute Engine:** open Compute Engine › VM instances and choose **Enable** for the Compute Engine API.

To use commands instead, install the [gcloud CLI](https://cloud.google.com/sdk/docs/install), then:

```
gcloud auth login
gcloud projects create codemany-ci-$RANDOM --name="Codemany CI"   # note the id it prints
gcloud config set project PROJECT_ID
gcloud billing accounts list
gcloud billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID
gcloud services enable compute.googleapis.com
```

### Create the VM

Recommended: **e2-standard-4** (4 vCPUs, 16 GB: 2 runners), **Ubuntu 24.04 LTS**, a **100 GB balanced disk**, in a region near you (here `us-central1`).

```
gcloud compute instances create codemany-1 \
  --zone=us-central1-a \
  --machine-type=e2-standard-4 \
  --image-family=ubuntu-2404-lts-amd64 --image-project=ubuntu-os-cloud \
  --boot-disk-size=100GB --boot-disk-type=pd-balanced
```

In the console: Compute Engine › VM instances › **Create instance**. Name `codemany-1`, region `us-central1`, machine type `e2-standard-4`. Under **OS and storage**, choose **Change**: Ubuntu, Ubuntu 24.04 LTS (x86/64), balanced persistent disk, 100 GB. Leave the firewall boxes (HTTP, HTTPS) unticked. **Create**.

**A fresh VM per job** needs nested virtualization. E2 doesn't offer it; use an Intel N2 machine instead:

```
gcloud compute instances create codemany-1 \
  --zone=us-central1-a \
  --machine-type=n2-standard-4 \
  --enable-nested-virtualization \
  --image-family=ubuntu-2404-lts-amd64 --image-project=ubuntu-os-cloud \
  --boot-disk-size=100GB --boot-disk-type=pd-balanced
```

In the console, choose the N2 series and turn on nested virtualization in the machine configuration's advanced settings. If you can't find it, use the command above. On the VM, `ls /dev/kvm` should then show the device.

### Install Codemany

SSH in (or use the **SSH** button in the console):

```
gcloud compute ssh codemany-1 --zone=us-central1-a
```

On the VM, install with apt or the one-liner exactly as in [Install Codemany](https://codemany.com/docs/machines/linux-server#install) above.

### Reaching it safely

**Never open port 8825 to the internet.** Don't add a firewall rule for it. Google Cloud's default firewall already blocks it; keep it that way.

Reach the setup page and the dashboard through an SSH tunnel instead. Codemany knows it's on a cloud VM and keeps setup off the VM's network, so the tunnel is the only way in. From your computer:

```
gcloud compute ssh codemany-1 --zone=us-central1-a -- -L 18825:localhost:8825
```

While that runs, `http://127.0.0.1:18825` on your computer is the VM's dashboard. For setup, open the link `codemany setup-link --port 18825` prints on the VM, then connect GitHub and pick repos as in [Finish setup in a browser](https://codemany.com/docs/machines/linux-server#setup).

To close port 22 to the internet too, use IAP: allow SSH from Google's IAP range only (`35.235.240.0/20`), and add `--tunnel-through-iap` to the `gcloud compute ssh` commands.

**`codemany.local` doesn't reach a cloud machine.** Names like that only work on your local network. The cloud VM is managed on its own, through the tunnel, and doesn't show in your Mac's fleet. If you join it to the same private network as your other machines (a VPN such as Tailscale or WireGuard), add it on your Mac with **Machines › Add a machine…**, its VPN address (`100.x.y.z:8825`) and the code from `codemany pair`.

### What it costs

An estimate, at on-demand prices in `us-central1`: **e2-standard-4 with a 100 GB balanced disk is about $110 a month**. An n2-standard-4 (for VM-per-job) is about $125 to $155 a month, depending on sustained-use discounts. Prices change and vary by region: check the [Google Cloud pricing calculator](https://cloud.google.com/products/calculator). This is Google's bill, separate from Codemany's.

### Stop or delete it

A stopped VM costs nothing for its CPU and memory, but its disk is still billed:

```
gcloud compute instances stop codemany-1 --zone=us-central1-a
gcloud compute instances start codemany-1 --zone=us-central1-a
```

Delete it to stop all charges. First free its machine slot: in its dashboard, **Settings › License › Deactivate this machine…** (or remove it from another machine's Settings › License later):

```
gcloud compute instances delete codemany-1 --zone=us-central1-a
```

### AWS and others

Any provider with Ubuntu 24.04 works the same way: create the VM, keep 8825 closed, install Codemany, and tunnel with `ssh -L 18825:127.0.0.1:8825`. On AWS, a `t3.xlarge` or `m7i.xlarge` with 100 GB of gp3 is similar to the machine above, and the security group should allow only SSH. VM-per-job needs nested virtualization or a bare-metal instance: check your provider offers `/dev/kvm` before choosing that mode.

## Pricing

One subscription per GitHub account or organization that owns the repos. **$20/month includes 2 machines** (Mac or Linux), and **each extra machine is $10/month**. A Mac and a mini PC fit in the $20. 14 days free, no card. See [Pricing](https://codemany.com/pricing).

## Troubleshooting

**Is it healthy?** `codemany doctor` checks the service, the dashboard, the licence, GitHub, the runners, KVM, Avahi and lingering, one PASS, WARN or FAIL line each, and exits non-zero on a FAIL. `codemany status` shows the runners.

**What can jobs use?** `codemany doctor` also lists the tools runner jobs get on this machine (git, Docker, compilers and so on) and the labels they add. `codemany capacity` says how many runners fit, and why.

**Logs.** `journalctl --user -u codemany -f` shows Codemany's log. The full log, with the runners' own output, is in files: `tail -f ~/.codemany/logs/codemany.err.log ~/.codemany/logs/codemany.out.log`.

**It stops when I log out.** Lingering is off (`codemany doctor` says so). Turn it on: `sudo loginctl enable-linger "$USER"`.

**`codemany setup-link` says "no daemon is waiting for setup".** The service isn't running: start it with `codemany install-service`. If it says "already set up", open the dashboard instead.

**Port 8825 is taken.** If another user's Codemany on the same machine holds 8825, Codemany takes the next free port from 8826 to 8835, and `codemany status` and `codemany setup-link` find it. Tunnel to that port instead (`codemany setup-link --port 18825` prints the link for your end). Any other program on 8825 must move: `sudo ss -ltnp 'sport = :8825'` shows which.

**Jobs wait in `queued`.** The workflow's `runs-on` labels must all be on the runner: `self-hosted`, `Linux` and `codemany` (or your own pool label).

**VM-per-job won't start.** `codemany isolation vm-image` says why (no `/dev/kvm`, not in the `kvm` group, no nested virtualization).

[Previous The fleet](https://codemany.com/docs/machines)[Next Cloud machines](https://codemany.com/docs/machines/cloud)
