What Coder does
Coder separates two things that are often confused: the editor and the environment. The editor stays the one you like — VS Code in the browser, VS Code on your machine, a JetBrains IDE or a plain terminal. The environment lives on the server: a container that holds the code, the languages, the test databases and the project's tools.
This environment is described in a template written in Terraform. The administrator publishes it once; each developer then creates their workspace from that template, starts it when they work and stops it when they are done. An agent installed in the workspace connects to the Coder server and carries the terminal, ports and editor sessions.
What Coder brings
- Identical workspaces — everyone works in the same environment, described in a versioned template.
- Docker template included — one container per workspace on the VPS, with a persistent
/homevolume. - Every editor — code-server in the browser, VS Code Remote-SSH, JetBrains Gateway,
coder ssh. - Port forwarding —
coder port-forwardopens the application you are building on your machine. - Automatic stop — idle workspaces stop according to the template schedule.
- Accounts and single sign-on — local accounts, GitHub or OpenID Connect.
Coder compared with other options
Scroll the table
| Coder on a VPS | code-server alone | GitHub Codespaces | |
|---|---|---|---|
| Users | A team, with accounts and roles | One person | GitHub accounts |
| Environment | Versioned Terraform template | The server itself | devcontainer file |
| Editors | Browser, VS Code, JetBrains, SSH | Browser | Browser, VS Code, JetBrains |
| Where the code lives | On your server | On your server | At GitHub |
| Cost | The VPS price | The VPS price | Per compute hour and storage |
Prerequisites
An Ubuntu 24.04 VPS with 2 GB of RAM and 20 GB of disk for one or two developers — plan 4 to 8 GB of RAM for a small team —, Docker and the Compose plugin installed, and a subdomain pointing to the VPS, for example coder.example.com. HTTPS is essential: workspace agents call the server back on that address, and editor sessions go over WebSocket.
Install Coder with Docker Compose
Prepare the directory and the secrets
The
.envfile holds the database password, the host's Docker group ID — it lets the server use the Docker socket without running as root — and the domain.mkdir -p /opt/coder && cd /opt/coder { echo "DB_PASSWORD=$(openssl rand -hex 16)" echo "DOCKER_GID=$(stat -c %g /var/run/docker.sock)" echo "DOMAIN=coder.example.com" } > .env chmod 600 .envWrite the docker-compose.yml file
Two services: the Coder server, which ships with Terraform, and PostgreSQL. The port is only published on the loopback interface; nginx will handle HTTPS.
services: coder: image: ghcr.io/coder/coder:v2.39.0 restart: unless-stopped group_add: - "${DOCKER_GID}" depends_on: database: condition: service_healthy ports: - "127.0.0.1:7080:7080" environment: CODER_HTTP_ADDRESS: "0.0.0.0:7080" CODER_ACCESS_URL: "https://${DOMAIN}" CODER_PG_CONNECTION_URL: "postgresql://coder:${DB_PASSWORD}@database:5432/coder?sslmode=disable" CODER_TELEMETRY_ENABLE: "false" volumes: - /var/run/docker.sock:/var/run/docker.sock database: image: postgres:17.11-alpine restart: unless-stopped environment: POSTGRES_USER: coder POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: coder volumes: - coder-db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U coder -d coder"] interval: 5s retries: 12 volumes: coder-db: {}Start and check
The first start creates the database schema in a few seconds.
docker compose up -d docker compose logs -f coder # attendre « View the Web UI » curl -fsS http://127.0.0.1:7080/healthz
The Docker socket hands over the server keys
Coder creates workspaces through the Docker socket, and anyone who can edit a template can start any container on the VPS — and therefore act as root on the host. Keep the owner and template administrator roles for trusted people, and never publish port 7080 on the public address.
Put Coder behind nginx over HTTPS
Get a certificate with certbot certonly --nginx -d coder.example.com, then declare the site. The Upgrade and Connection headers are essential: without them, the web terminal and agent connections fail.
server {
listen 443 ssl;
http2 on;
server_name coder.example.com;
ssl_certificate /etc/letsencrypt/live/coder.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/coder.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:7080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1h;
}
}Reload nginx with nginx -t && systemctl reload nginx, then open https://coder.example.com. Create the first account right away: the first visitor of the welcome screen becomes the owner of the installation.
Create the first template and the first workspace
In Templates, click Create Template and choose the Docker Containers starter template. Coder downloads the required Terraform providers and publishes the template. Then create a workspace from it: a container starts on the VPS, its agent connects, and the page shows the Running state with a button to open code-server.
The template is a plain main.tf file. To adapt it to your project, change the base image, add tools to the agent startup script, then publish a new version: existing workspaces offer it at their next restart.
Connect from VS Code, JetBrains or SSH
The browser is enough to start, but most developers prefer their usual editor. Install the CLI on your machine and connect it to the server:
curl -L https://coder.com/install.sh | sh
coder login https://coder.example.com
coder list
coder ssh mon-espace
coder port-forward mon-espace --tcp 3000:3000
coder config-ssh # ajoute les hôtes coder.<espace> à ~/.ssh/configAfter coder config-ssh, VS Code Remote-SSH and JetBrains Gateway see each workspace as an ordinary SSH host. The connection goes through the server's HTTPS address: no extra SSH port is opened on the VPS.
Automatic stop and VPS resources
At rest, the Coder server and its database use about 550 MB of RAM, and an idle workspace based on the Docker template image about 200 MB — much more during a build or a test suite. In the template settings, under Schedule, set an automatic stop delay: a workspace forgotten in the evening no longer consumes anything overnight. The /home volume is kept when stopped; only the container is recreated at restart.
Backup and updates
Accounts, templates and settings live in PostgreSQL; developers' work lives in the workspaces' /home volumes.
cd /opt/coder
docker compose exec -T database pg_dump -U coder coder | gzip > coder-$(date +%F).sql.gz
docker volume ls --filter name=coder- # volumes /home des espaces de travailTo update, change the image tag in docker-compose.yml according to the [releases page](https://github.com/coder/coder/releases), then run docker compose pull && docker compose up -d: the server migrates its database at startup. Take a backup before every major upgrade.
One-click install on ServOrbit
On a ServOrbit VPS, Coder installs from the Marketplace. The script deploys the server and its PostgreSQL database, generates the administrator password and creates the owner account before anything is exposed — so the first-administrator sign-up screen is never reachable from the Internet. It also configures the nginx reverse proxy over HTTPS with WebSocket, on a subdomain of your domain or on the VPS's free subdomain. Sign in with the address [email protected] and the password shown in your client area, then change it in the account settings.