What code-server needs from the machine
The requirements page asks for little: a Linux machine, 1 GB of RAM and 2 CPU cores at the minimum, and WebSockets end to end, since the browser and the server talk over them. The release packages add a C library floor.
| Item | What the code-server docs state |
|---|---|
| Memory and CPU | 1 GB RAM and 2 cores, recommended as the minimum |
| Operating system | Any Linux distribution; no Windows releases are published |
| Architecture | Releases for amd64 and arm64; other CPUs install through npm |
| C library | glibc 2.28 and glibcxx 3.4.21 or newer for the standalone release, from which the .deb and .rpm are built |
| Network | WebSockets enabled between browser and server |
| Listening | 127.0.0.1:8080 with a generated password, no TLS |
That floor covers the editor process only. The real load is everything you run from its terminal: compilers, language servers, test suites, containers. Size for the toolchain, not for code-server.
Sizing the box
The rows below are our reading of the workload, not figures from Coder. Memory first, because language servers and parallel builds eat it, then cores, then NVMe for checkouts and dependency caches.
| How you use it | What sets the load | Class on the dedicated range |
|---|---|---|
| One developer: editing, git, scripts | The editor and a language server or two | Moonshot cartridge such as the 4-core Xeon E3-1585L v5 with NVMe |
| Large compiles, local containers | Compiler threads and container memory | Moonshot Xeon D-1587, 16 cores, memory to 128 GB, 1.92 TB NVMe |
| A team, one VM per developer | Several isolated environments | Dual-socket Xeon host, memory sized per VM |
Each line, its memory range, port and cities are on the dedicated server range, priced live from the catalogue. For the team row, the docs' advice on multi-tenancy is one virtual machine per user; a Proxmox dedicated server arrives with the hypervisor installed.
Why a whole machine
A remote dev box is a build machine you also type into. On a dedicated server the cores, memory and disks serve your builds alone, with root, and no hypervisor unless you install one. The port is unmetered, so pulling images, packages and repositories carries no transfer bill.
Firewall work is where remote boxes get lost. Every racked single-, dual- and quad-socket server has an out-of-band console (HPE iLO, Dell iDRAC or a Supermicro BMC); among cartridges only the m510 and m710x have one, the rest have power control. A bad ufw rule is then fixed from the console, and the OS can be reinstalled from the control panel as often as needed. Racked machines are handed over in about 30 minutes once payment is approved, on our own network, AS19624.
Installing it: the .deb, or the script read first
The docs' quick start pipes install.sh straight into sh. Download it instead, read it, and run it with --dry-run, which echoes every command without running it. On Debian and Ubuntu the script fetches the .deb from GitHub and installs it with dpkg, so fetching that .deb yourself is the same result. Servers are handed over with a root login, so first make an ordinary account: adduser dev, then usermod -aG sudo dev, then reconnect over SSH as dev and run everything below from that session.
# Option A: the install script, downloaded and read, never piped into a shell
curl -fsSL https://code-server.dev/install.sh -o install.sh
less install.sh
sh install.sh --dry-run
sh install.sh
# Option B: the .deb from the GitHub releases page
VERSION=4.141.1 # newest release in October 2026; check the releases page
curl -fOL https://github.com/coder/code-server/releases/download/v$VERSION/code-server_${VERSION}_amd64.deb
sudo dpkg -i code-server_${VERSION}_amd64.deb
# Either way: a systemd service for your own user, started on boot
sudo systemctl enable --now code-server@$USER
The packaged unit runs code-server as the user after the @, and the editor's terminal is a shell as that user. Use your own unprivileged login, never root. The first start writes ~/.config/code-server/config.yaml with a random password.
config.yaml: bind address and a hashed password
The default file holds four keys: bind-addr: 127.0.0.1:8080, auth: password, a plaintext password, and cert: false. Each key maps to a command-line flag, and flags win over the file. Passwords are the exception: code-server refuses them as flags and reads them only from this file or the PASSWORD and HASHED_PASSWORD variables.
Replace the plaintext with hashed-password, which takes precedence over password. The docs hash with echo -n into npx argon2-cli -e, which leaves the password in shell history and needs Node. The variant below is ours: it reads the password without echo and hashes it with Ubuntu's argon2 package, producing the same argon2i format as the docs' example. code-server writes the file with your default permissions, so set mode 600 yourself.
sudo apt install -y argon2
read -rs -p 'code-server password: ' PW; echo
HASH=$(printf '%s' "$PW" | argon2 "$(openssl rand -hex 16)" -e); unset PW
umask 077
cat > ~/.config/code-server/config.yaml <<EOF
bind-addr: 127.0.0.1:8080
auth: password
hashed-password: "$HASH"
cert: false
EOF
chmod 600 ~/.config/code-server/config.yaml
sudo systemctl restart code-server@$USER
The hash stays in double quotes, as the docs insist. Login attempts are rate limited to two per minute plus twelve per hour; that slows guessing but is no substitute for keeping the port private.
Reaching it: SSH tunnel or TLS proxy
The guide is blunt: never expose code-server to the internet without authentication and encryption, since anyone who gets in can take over the machine through the terminal. Its first recommendation is SSH port forwarding, which needs nothing beyond the SSH server you already run. Its tunnel recipe also switches auth to none; we would keep the password unless you are the only account on the box, because any local user can reach 127.0.0.1:8080.
Where a device has no SSH client, such as an iPad, the guide's alternative is Let's Encrypt in front of code-server, with Caddy or NGINX. Caddy is a host process, so without a ufw rule for 80 and 443 it is blocked on IPv4 and IPv6 alike. Set IPV6=yes before adding rules, or the rules get no IPv6 copies. Point an A record (and AAAA, if the server has IPv6) at the machine first.
sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp # proxy route only; omit it if you tunnel
sudo ufw --force enable
# Tunnel route, run on your own computer, then open http://127.0.0.1:8080
# ssh -N -L 8080:127.0.0.1:8080 you@your-server
# Proxy route: Caddy's apt repository, as in the code-server guide
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install -y caddy
sudo tee /etc/caddy/Caddyfile >/dev/null <<'EOF'
code.example.com {
reverse_proxy 127.0.0.1:8080
}
EOF
sudo systemctl reload caddy
For single sign-on instead of one shared password, the guide points to a reverse proxy that handles it: oauth2-proxy, Pomerium or Cloudflare Access. A self-signed certificate is its last resort.
Extensions: Open VSX and the Microsoft terms
code-server installs extensions from the Open VSX gallery. The FAQ explains why: VS Code's core is open source, the marketplace and many Microsoft extensions are not, and "Microsoft prohibits the use of any non-Microsoft VS Code from accessing their marketplace". The Terms of Use it cites tie Marketplace Offerings to Microsoft's own Visual Studio products.
- Unavailable, per the FAQ: Live Share and the Remote extensions (SSH, Containers, WSL).
- Missing from Open VSX: download the VSIX and run
code-server --install-extensionwith its path, or use Extensions: Install from VSIX. EXTENSIONS_GALLERYpoints code-server at another gallery; the docs strongly discourage aiming it at Microsoft's, as against its Terms of Use.- Extensions live in
~/.local/share/code-server/extensions.
Upgrades, backups and housekeeping
- Upgrade by installing the new version over the old one: rerun the script, or
dpkg -ithe newer .deb. User data in~/.local/share/code-serversurvives. Restart the service afterwards so the new build is the one running. - Back up
~/.config/code-serverand~/.local/share/code-server(settings, keybindings, extensions), and copy them off the machine yourself. Push the code to a git remote; a self-hosted Gitea server or Forgejo works. - Telemetry:
--disable-telemetry, ordisable-telemetry: truein config.yaml, since keys map to flags. /healthzreports alive or expired without authentication; useful for a monitor.- A dev server on port 3000 is reachable at
/proxy/3000/behind code-server's own login.
Where it fits, and where it does not
code-server is one editor behind one password. The docs call it a tool for individuals and send teams to Coder, their workspace product, or to one VM per user. It is not a pipeline either: builds that run on every push belong on a Jenkins server or a GitHub Actions self-hosted runner. And if an extension exists only on Microsoft's marketplace, the FAQ says VS Code web (code serve-web) can be the better choice.
Questions
Is code-server the same as Microsoft's VS Code in a browser?
No. It takes the open-source core of VS Code and patches it for self-hosting: password login, a built-in port proxy, sub-path hosting, settings stored on disk. The docs say it is not entirely equivalent to Microsoft's VS Code, chiefly because it cannot use Microsoft's extension marketplace.
Where do I find or change the code-server password?
In ~/.config/code-server/config.yaml, written on first start. Edit the field and restart the service with sudo systemctl restart code-server@$USER. A hashed-password entry takes precedence over password, so store the argon2 hash and delete the plaintext line.
Can I run the Docker image instead of the .deb?
Yes; the docs publish codercom/code-server for amd64 and arm64. Their run command maps the port as 127.0.0.1:8080:8080, which keeps it on loopback, and that is local-only on Docker Engine 28 and later. A mapping without an address publishes the port on every host address, 0.0.0.0 and [::], and on IPv4 that traffic bypasses ufw's rules.
Can several developers share one instance?
Not well. There is a single password and every login gets the same user's terminal. For several people the FAQ recommends virtual machines, one per user, which a dual-socket host running a hypervisor handles.
What licence is code-server under?
MIT, copyright Coder Technologies Inc., so self-hosting it carries no licence fee. Extensions carry their own licences, and Microsoft's marketplace terms are a separate matter covered above.