When Do You Need code-server?
I started using code-server when I had to debug a staging server from an iPad at a coffee shop — VS Code couldn’t be installed directly, and the codebase lived on a VPS. After trying a few remote IDE solutions, code-server became my go-to because it’s straightforward: it is VS Code, loading directly in the browser, with full extensions, an integrated terminal, and nothing extra to install on the client side.
code-server is a good fit when you:
- Code from multiple devices (laptop, iPad, work computer)
- Want to leverage a more powerful VPS for building and compiling instead of your local machine
- Need a dev environment that mirrors production as closely as possible — same OS, same dependencies
- Have teammates who need to review code directly on the server without passing files back and forth
Installing code-server
System Requirements
Ubuntu 20.04 or 22.04 (LTS). Minimum 1GB RAM — though in practice, the TypeScript language server alone can consume 300–500MB, so if you’re running multiple extensions simultaneously, 2GB is where things get comfortable. You’ll need at least 2GB of free disk space; with extensions and workspaces added, 5GB is a safer target. Bandwidth requirements are low — 1 Mbps is plenty for normal use.
Quick Install via Script
curl -fsSL https://code-server.dev/install.sh | sh
The script auto-detects your distro, adds the appropriate package repo, and installs the binary. On Ubuntu it uses apt; on Fedora it uses dnf — no manual intervention needed. Once done, verify the version:
code-server --version
Manual Install via .deb (When You Need Version Control)
VERSION="4.95.3"
wget https://github.com/coder/code-server/releases/download/v${VERSION}/code-server_${VERSION}_amd64.deb
sudo dpkg -i code-server_${VERSION}_amd64.deb
Detailed Configuration
Default Config File
Run it once to generate the config file:
code-server --config ~/.config/code-server/config.yaml
The default content will look like this:
bind-addr: 127.0.0.1:8080
auth: password
password: your-password-here
cert: false
Important: Keep bind-addr: 127.0.0.1 — this restricts connections to localhost only. Nginx will handle exposing it externally with HTTPS. Don’t bind directly to 0.0.0.0 without SSL in place.
Generate a stronger random password:
PASSWORD=$(openssl rand -base64 16)
echo "Your password: $PASSWORD"
sed -i "s/password: .*/password: $PASSWORD/" ~/.config/code-server/config.yaml
Running code-server as a systemd Service
sudo systemctl enable --now code-server@$USER
sudo systemctl status code-server@$USER
Configuring Nginx as a Reverse Proxy
This is where most people run into issues. code-server uses WebSockets to sync the editor in real time, so Nginx needs the Upgrade header — without it, the editor will load but the terminal and live sync won’t work.
Create the Nginx config file:
sudo nano /etc/nginx/sites-available/code-server
server {
listen 80;
server_name code.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name code.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/code.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/code.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
proxy_http_version 1.1;
}
}
Enable the site, test the config, then reload:
sudo ln -s /etc/nginx/sites-available/code-server /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Hardening Security
code-server has password authentication by default, but this editor gives you a terminal directly on the server — if it gets compromised, you lose the whole machine. I usually add a few extra layers to be safe:
Restrict access by IP (if you’re connecting from a fixed IP):
location / {
allow 203.0.113.10; # Your IP
deny all;
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_http_version 1.1;
}
Add HTTP Basic Auth (defense in depth — two layers of authentication):
sudo apt install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd your_username
Add to the location block in Nginx:
auth_basic "Code Server";
auth_basic_user_file /etc/nginx/.htpasswd;
My final setup on staging: IP whitelist + basic auth + code-server password. Three layers might seem like overkill, but when it’s a terminal with root access on a server, I’m not willing to take chances.
Testing and Monitoring
Testing the Connection and WebSockets
Visit https://code.yourdomain.com — enter your password and VS Code loads right in the browser. If the editor loads but the terminal doesn’t respond, WebSockets are likely being blocked. Check the Nginx logs:
# HTTP 101 = WebSocket handshake successful
sudo tail -f /var/log/nginx/access.log | grep " 101 "
Viewing code-server Logs
# Follow service logs in real time
sudo journalctl -u code-server@$USER -f
# Enable verbose logging for debugging
code-server --log-level debug
Monitoring Resource Usage
TypeScript, ESLint, and Pylance can be surprisingly memory-hungry — the TypeScript language server alone can take up 300–500MB on large projects. Monitor usage with:
ps aux | grep code-server | awk '{print $2, $4, $6, $11}'
Only have 1GB of RAM? Limit the Node.js process memory:
sudo systemctl edit code-server@$USER
Paste in:
[Service]
Environment="NODE_OPTIONS=--max-old-space-size=512"
Restart=on-failure
RestartSec=5s
Apply the changes:
sudo systemctl daemon-reload
sudo systemctl restart code-server@$USER
Daily Usage Tips
- Sync settings via GitHub: Enable Settings Sync in VS Code and sign in with GitHub — extensions and settings automatically sync between your local machine and code-server, no need to reinstall from scratch
- Built-in port forwarding: When developing a web app on the server and need to preview it locally, use the Ports tab in the bottom panel of the editor — forward ports without needing a manual SSH tunnel
- Use a dedicated subdomain: Host code-server at
code.domain.comrather than a path likedomain.com/code— this avoids issues with extensions that rely on Service Workers - Regular backups: The
~/.local/share/code-server/directory contains your installed extensions and workspace state — backing this up is enough for a quick restore when needed

