Your laptop dies two days before a deadline, or you're stuck on a work machine that won't let you install anything, or you just want to fix a typo in a config file from your phone without SSHing in and fighting with vim. Whatever the reason, there's a real itch for "I want my actual coding setup, but I don't want it tied to one physical machine." code-server scratches that itch. It runs VS Code on a server you control and streams the whole editor into any browser, extensions and all.
This guide walks through running it in a Proxmox VE LXC container, which is about as light a footprint as you can get for something that behaves like a full desktop editor. No Docker, no reverse-engineering someone's docker-compose file — just a container, one install script, and a config file with four lines in it.
Budget around 20 minutes for the whole thing on a fresh Proxmox VE 9.2 host, most of which is Proxmox downloading a Debian template the first time.
What You Will Learn
- What code-server actually is, and why it's easy to confuse with a similarly-named Microsoft feature
- Why an LXC container is a sensible home for it, and where it isn't the right tool
- How to size and create the container from the Proxmox VE web interface
- The exact install, enable, and configuration commands, explained line by line
- How to open the editor up to your home network safely
- What to check when the page won't load, the password gets rejected, or an extension is missing
What Is This Feature?
code-server is an open-source project maintained by Coder that packages up Code - OSS — the open-source build that Microsoft's VS Code is itself built on — and runs it headless on a server. Instead of opening a native app, you point a browser at a URL and get the full editor: file tree, integrated terminal, Git panel, extensions, the works. Under the hood it's talking to your browser over a WebSocket connection, which is why a flaky network or a proxy that blocks WebSockets will make it feel sluggish or just stop working entirely — worth remembering later when something behaves oddly through a reverse proxy.
It's easy to mix this up with Microsoft's own "VS Code Server," the background process that powers Remote-SSH and Remote Tunnels from a desktop copy of VS Code. That's a different project with a different purpose. code-server is the one you install and run yourself, on your own hardware, with your own password — nothing phones home to Microsoft's tunnel service.
An LXC container is Proxmox's lightweight alternative to a full virtual machine. Rather than emulating hardware and booting an entire separate kernel, it shares the host's Linux kernel and just isolates the processes and filesystem inside. That's why a container boots in a couple of seconds and can comfortably run in 512 MB of RAM where a VM running the same OS would want two or three times that just to idle. code-server is a single process plus a web server, so it's a good match for that model.
Once installed, code-server registers itself as a systemd service — the same init system Debian and most modern Linux distributions use to start, stop, and restart background processes automatically. That means it comes back up on its own if the container reboots, without you having to remember to relaunch it by hand.
Why Would You Use It?
The obvious case is working from more than one device without carrying your setup between them. Install your extensions once, and they're there whether you open the editor from a work laptop, a personal desktop, or an iPad with a Bluetooth keyboard. There's no dotfiles-syncing step, no "wait, which machine has the latest version of this script."
It's also genuinely handy inside a homelab even if you never touch it from outside your house. Editing a docker-compose file or a shell script over SSH with nano is fine, but a real editor with syntax highlighting and a file tree beats it for anything more than a quick one-line fix. Running code-server next to the rest of your self-hosted stack means you can edit configs for services on the same network without hopping between a terminal and a separate editor window.
Where I'd steer you away from it: don't expect to compile a large C++ project or run a resource-hungry build pipeline inside a 2 GB LXC container. code-server itself is light, but the actual work you do inside it — npm installs, Rust builds, whatever — still has to run somewhere, and that somewhere is this container's CPU and RAM. For scripts, configs, small-to-medium repos, and general homelab tinkering it's more than enough. For a full development workstation, give it real resources or use it on a proper VM instead.
Prerequisites
- A Proxmox VE 8.x or 9.x host with a storage location for container templates and container disks (local-lvm or local-zfs both work fine)
- The Debian 13 LXC template — you'll download it in Step 1 if it isn't already cached
- At least 2 vCPU cores and 2 GB of RAM free on the host (bump this to 4 GB if you plan on running larger repos or several extensions with language servers active)
- Comfort typing a handful of commands into a terminal — there's no scripting knowledge required, just copy-paste
- A network bridge your other VMs and containers already use, so you can reach the new container's IP address from your browser
Step-by-Step Tutorial
Step 1: Download the Debian 13 Template
In the Proxmox VE web interface, click your node in the left-hand tree, then local storage (or whichever storage holds your templates), then CT Templates. Click Templates, search for "debian-13," and download the standard image. If you'd rather do it from the shell, this does the same thing:
pveam update
pveam available --section system | grep debian-13
pveam download local debian-13-standard_13.1-2_amd64.tar.zst
The exact filename changes as Proxmox updates the template catalog, so check the output of the available command if the download line above errors out with a "not found" message — just swap in whatever version string it lists.
Step 2: Create the LXC Container
Click Create CT in the top-right corner. Here's what to set on each tab:
- General: give it a hostname like
codeserver, set a root password (or paste in an SSH public key), and leave Unprivileged container checked — there's no reason code-server needs root-level access to the host - Template: pick the debian-13-standard image you just downloaded
- Disks: 8 GB is comfortable for the OS plus code-server plus a handful of small-to-medium repos; go bigger if you're cloning large projects
- CPU: 2 cores
- Memory: 2048 MB, with 512 MB of swap
- Network: attach it to vmbr0 (or your usual bridge) and either take a DHCP address or set a static one now — a static IP will save you a step later since the address won't change on reboot
Confirm on the last tab and let it finish, then select the new container and click Start.
Step 3: Log In and Update the Container
Click Console on the container, log in as root with the password you set, and run:
apt update && apt full-upgrade -y
apt install -y curl sudo
The minimal Debian template doesn't ship sudo by default, which is why the second command is there — you'll want it in a minute for running code-server as a less-privileged user instead of root.
Step 4: Install code-server
Coder publishes an install script that detects your distribution and grabs the right package automatically. On Debian it downloads the current .deb and installs it with dpkg:
curl -fsSL https://code-server.dev/install.sh | sh
This takes under a minute on most connections and prints a short summary when it's done, including the command to start the service. If you'd rather see exactly what it's going to do before running it, add -s -- --dry-run to the end of the curl command first.
Step 5: Enable code-server as a Service
The install sets up a systemd unit but doesn't start it automatically. Enable and start it for the root user with:
systemctl enable --now code-server@root
That @root matters — code-server runs per-user, so the service name always includes the account it's running under. If you later create a dedicated non-root user (worth doing, see Best Practices below), you'd enable code-server@thatuser instead, and each user gets their own separate config and password.
Step 6: Open Up Access
By default code-server only listens on 127.0.0.1:8080 inside the container, which means it's unreachable from anywhere but the container itself. Edit the config file to change that:
nano ~/.config/code-server/config.yaml
You'll see something like this:
bind-addr: 127.0.0.1:8080
auth: password
password: 7d9f3a2e1c4b8091a5f6d2e3b7c1a894
cert: false
Change the bind-addr line to 0.0.0.0:8080 so it listens on all interfaces, save the file, and copy that password somewhere safe — you'll need it in a second. Restart the service to pick up the change:
systemctl restart code-server@root
Step 7: Open It in Your Browser
Find the container's IP address — it's shown on the container's Summary page in Proxmox, or run ip a inside the console. Head to http://<container-ip>:8080 from any device on the same network. You'll be prompted for the password from the config file, and after that you're looking at a full VS Code window running entirely on your homelab.
Commands Explained
| Command | What It Does |
|---|---|
pveam download local debian-13-standard... | Downloads a container OS template into Proxmox's local storage, so Create CT can use it |
apt full-upgrade -y | Updates every installed package to its latest version, including ones that need to remove or replace an older package to upgrade |
curl -fsSL https://code-server.dev/install.sh | sh | Downloads and runs Coder's install script, which detects Debian and installs the correct .deb package for you |
systemctl enable --now code-server@root | Registers the systemd service so it starts on boot, and starts it immediately in the same command |
systemctl restart code-server@root | Restarts the service so it re-reads the config file after you edit it |
journalctl -u code-server@root -e | Jumps to the end of the service's logs — the first place to look when something's not starting |
Common Errors
"This site can't be reached" in the browser. Almost always means bind-addr is still set to 127.0.0.1:8080, so the service is only listening inside the container. Double-check Step 6 and confirm you restarted the service after editing the file.
Password rejected even though you copied it correctly. Config file changes don't apply until code-server restarts. If you edited the file and forgot to run systemctl restart code-server@root, you're still looking at the old (or a stale cached) password prompt.
-bash: sudo: command not found. The minimal Debian template doesn't include sudo out of the box. Run apt install -y sudo as root first, which is why Step 3 has it in the same line as the update command.
An extension you rely on isn't in the marketplace search. This one trips people up constantly. code-server uses the Open VSX Registry instead of Microsoft's official Visual Studio Marketplace, because Microsoft's marketplace terms don't allow other editors to use it. Most popular extensions are on Open VSX, but a few — GitHub's official Copilot extension is the best-known example — are Microsoft-marketplace-only and won't show up no matter how you search.
Container feels sluggish over a slow connection. Since the editor streams over a WebSocket, high latency or a flaky Wi-Fi connection shows up as laggy typing and slow file loads rather than a clean error message. It's a bandwidth-and-latency thing, not something broken in the install.
Troubleshooting
Start with the service itself:
systemctl status code-server@root
If it shows "active (running)" but the page still won't load, the problem is almost certainly networking rather than code-server. From inside the container, confirm it's actually listening where you expect:
ss -tlnp | grep 8080
You should see 0.0.0.0:8080 in the output, not 127.0.0.1:8080. If it still shows the loopback address, the config edit didn't save, or you restarted before saving — go back and check the file again.
If the service won't start at all, check the logs for the actual error rather than guessing:
journalctl -u code-server@root -e
A common one here is a corrupted or half-written config.yaml from an interrupted edit — deleting the file and restarting the service regenerates a fresh one with a new random password.
Last thing to rule out: Proxmox's own firewall, if you've got it enabled at the datacenter or container level. It's off by default, but if you turned it on for other containers on this network, you'll need a rule allowing inbound TCP on port 8080 to this container specifically.
Best Practices
Take a snapshot of the container right after the initial setup finishes, before you start installing extensions and cloning repos into it. If you break the config later, rolling back is a few clicks instead of a rebuild.
Running code-server as root works, but it's not something I'd leave in place long-term. Create a normal user, add it to sudo, and enable code-server@thatuser instead — that way, anything you do inside the editor's terminal runs with normal permissions rather than root by default.
Don't set auth: none in the config just to skip the password prompt, especially once bind-addr is listening on 0.0.0.0. That password is the only thing standing between anyone on your network and a terminal on this machine.
If you ever want to reach this from outside your home network, don't just port-forward 8080 straight to the container. Put it behind a reverse proxy with a real TLS certificate — Nginx Proxy Manager or Traefik both work well for this — or better yet, reach it over a private mesh network like Tailscale so it's never exposed to the open internet at all.
Keep an eye on the container's disk usage if you're a heavy cloner of repositories. An 8 GB disk fills up faster than you'd think once node_modules folders start piling up.
Frequently Asked Questions
Is code-server the same thing as GitHub Codespaces?
No. Codespaces is GitHub's hosted, pay-per-use service. code-server is self-hosted software you run on your own hardware, with no per-hour billing and no dependency on GitHub's infrastructure.
Do I need Docker for this?
No. The install.sh script installs a native Debian package directly, which is actually simpler to manage inside an LXC container than running Docker-in-LXC.
Can I run more than one instance in the same container?
Yes, by creating a separate system user for each and enabling code-server@username per user — each gets an independent config, password, and default port you can change in their config file.
How do I update it later?
Re-run the same install command from Step 4. It detects the existing installation and installs the newer package over it.
Will this survive a Proxmox host reboot?
Yes, as long as the container itself is set to start on boot (check the Options tab on the container) and the systemd service is enabled, which it is once you've run the enable --now command.
Conclusion
What you've got now is a full VS Code environment that lives on your own hardware, survives reboots on its own, and costs you 2 GB of RAM on a Proxmox host that's probably already running a dozen other things. That's a pretty good trade for never again losing your extension setup to a laptop reformat.
From here, the next reasonable step is putting a reverse proxy in front of it if you want to reach it away from home, or bumping the container's resources if you find yourself running heavier projects than you expected. Either way, the container you just built is a normal Debian system underneath — anything you already know about managing one applies here too.