Self-Hosting code-server with Docker Compose

What Is code-server?

code-server runs VS Code in a browser, giving you a full development environment accessible from any device. It replaces cloud IDEs like GitHub Codespaces and Gitpod while keeping your code on your own hardware. If you already know VS Code, you know code-server — same editor, same extensions, same keybindings, just served over HTTP.

Why Self-Host It?

FactorCloud IDESelf-Hosted code-server
Monthly cost$20-40/user$0 (your hardware)
Code privacyOn vendor serversOn your server
Compute powerFixed tiersWhatever your server has
Extension supportLimited marketplaceFull VS Code marketplace
Offline accessNoYes (LAN)
LatencyDepends on regionDepends on your connection

The cost savings compound fast if you have multiple developers or run heavy workloads. A $200 mini PC outperforms most cloud IDE tiers within two months.

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free RAM (2 GB+ recommended for larger projects)
  • 10 GB of free disk space (more for project files and dependencies)
  • A domain name (optional, for HTTPS remote access)

Docker Compose Configuration

We’ll use the LinuxServer.io image — it’s easier to configure via environment variables and follows a standardized pattern.

Create a docker-compose.yml:

services:
  code-server:
    image: lscr.io/linuxserver/code-server:4.109.2
    container_name: code-server
    environment:
      - PUID=1000          # Your user ID (run `id -u` to find yours)
      - PGID=1000          # Your group ID (run `id -g` to find yours)
      - TZ=America/New_York # Your timezone
      - PASSWORD=changeme   # CHANGE THIS — web UI login password
      - SUDO_PASSWORD=changeme # CHANGE THIS — password for sudo in terminal
      - DEFAULT_WORKSPACE=/config/workspace
    volumes:
      - code-server-config:/config       # Settings, extensions, workspace
      - ./projects:/config/workspace     # Your project files
    ports:
      - "8443:8443"        # Web UI (HTTP, not HTTPS despite the port number)
    restart: unless-stopped

volumes:
  code-server-config:

Important: Change both PASSWORD and SUDO_PASSWORD before starting. For stronger security, use hashed passwords instead:

# Generate a hashed password
echo -n 'your-password' | npx argon2-cli -e

Then replace PASSWORD with HASHED_PASSWORD in your compose file, using the hash output as the value.

Start the stack:

docker compose up -d

Access code-server at http://your-server-ip:8443. Enter the password you set in PASSWORD.

Initial Setup

  1. Open http://your-server-ip:8443 in your browser
  2. Enter your password
  3. You’ll see the VS Code interface with the workspace directory open
  4. Install extensions from the sidebar — the full Open VSX marketplace is available (not Microsoft’s marketplace, but most popular extensions are mirrored)

Install Common Extensions

Open the integrated terminal (Ctrl+`) and install extensions via CLI:

code-server --install-extension ms-python.python
code-server --install-extension dbaeumer.vscode-eslint
code-server --install-extension esbenp.prettier-vscode

Or install from the Extensions sidebar (Ctrl+Shift+X) using the GUI.

Configuration

Git Integration

SSH keys persist across container restarts when stored in the config volume:

# Inside the code-server terminal
ssh-keygen -t ed25519 -C "[email protected]"
cat ~/.ssh/id_ed25519.pub
# Add this key to your GitHub/GitLab account

Configure Git:

git config --global user.name "Your Name"
git config --global user.email "[email protected]"

Settings Sync

code-server settings live in /config/.local/share/code-server/User/settings.json. Since this is inside the mounted volume, your settings persist across container updates.

Custom Extensions from VSIX

If an extension isn’t on Open VSX, install it manually:

# Download the .vsix file to your workspace
code-server --install-extension /config/workspace/extension.vsix

Using the Official Image Instead

If you prefer the upstream codercom/code-server image:

services:
  code-server:
    image: codercom/code-server:4.109.2
    container_name: code-server
    user: "1000:1000"
    environment:
      - DOCKER_USER=coder
    volumes:
      - code-server-local:/home/coder/.local      # Extensions, cached data
      - code-server-config:/home/coder/.config     # Config (includes password)
      - ./projects:/home/coder/project             # Your project files
    ports:
      - "8080:8080"   # Web UI
    restart: unless-stopped

volumes:
  code-server-local:
  code-server-config:

With the official image, authentication is configured in ~/.config/code-server/config.yaml (auto-generated on first run). The password is printed to logs on first startup:

docker logs code-server 2>&1 | grep password

Reverse Proxy

For HTTPS access, put code-server behind a reverse proxy. Here’s a Caddy example:

code.example.com {
    reverse_proxy localhost:8443
}

WebSocket support is required for the terminal and live features. Most reverse proxies handle this automatically. See our Reverse Proxy Guide for Nginx Proxy Manager and Traefik configurations.

Backup

Back up the config volume to preserve settings, extensions, and workspace data:

# Stop the container first for a clean backup
docker compose stop code-server

# Back up the config volume
docker run --rm -v code-server-config:/data -v $(pwd):/backup \
  alpine tar czf /backup/code-server-backup-$(date +%Y%m%d).tar.gz /data

docker compose start code-server

Your project files in ./projects should be version-controlled with Git independently.

See our Backup Strategy Guide for automated backup approaches.

Troubleshooting

Extensions Not Installing

Symptom: “Unable to install extension” errors in the marketplace.

Fix: code-server uses the Open VSX registry, not Microsoft’s marketplace. Some extensions (like GitHub Copilot) are only available on Microsoft’s marketplace. Check open-vsx.org for availability. For missing extensions, download the .vsix from GitHub releases and install manually.

Permission Denied on Project Files

Symptom: Cannot create or edit files in the workspace directory.

Fix: The PUID and PGID values must match the owner of your host ./projects directory:

# Check ownership
ls -la ./projects

# Fix if needed
sudo chown -R 1000:1000 ./projects

Terminal Not Opening

Symptom: Integrated terminal shows a blank screen or fails to connect.

Fix: This is usually a WebSocket issue with reverse proxies. Ensure your proxy forwards WebSocket connections. In Nginx, add:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

High Memory Usage

Symptom: code-server consumes excessive RAM with large projects.

Fix: VS Code’s TypeScript language server and extensions like ESLint can be memory-hungry. Disable unused extensions. Add to settings.json:

{
  "typescript.tsserver.maxTsServerMemory": 2048,
  "files.watcherExclude": {
    "**/node_modules/**": true,
    "**/.git/**": true
  }
}

Resource Requirements

MetricValue
RAM (idle)~300 MB
RAM (active development)512 MB - 2 GB (depends on project size and extensions)
CPULow-Medium (spikes during language server operations)
Disk~500 MB for code-server + project files
NetworkMinimal (browser streams UI updates)

Verdict

code-server is the best way to get VS Code in a browser. The LinuxServer.io image makes setup trivial — it’s a single container with no dependencies. Use it if you want to code from a tablet, Chromebook, or any machine without local dev tools installed. The experience is nearly identical to desktop VS Code, with the only notable gap being that some Microsoft-exclusive extensions (Copilot, Remote SSH) aren’t available.

For teams wanting managed workspaces with multiple users, look at Coder (the commercial product from the same team) or Gitpod instead.