Deployment guide

Coder on a VPS: Self-Hosted Cloud Development Environments

Deploy on a VPS Cloud →

Tutorial

Coder on a VPS: Self-Hosted Cloud Development Environments

Self-hosting7 min read3 steps

Installing PHP, Node.js, the right PostgreSQL version and a dozen extensions on every new developer's laptop takes time, and setups always drift apart. Cloud development environments such as GitHub Codespaces or Gitpod solve this, but they bill by the hour and keep your code on their side. Coder is an open-source platform (AGPL-3.0 licence) that does the same job on your own server: every developer gets an identical workspace in one click, described by a Terraform template. This guide installs it on a VPS with Docker Compose, puts it behind nginx over HTTPS, creates a first Docker workspace and shows how to connect from VS Code, JetBrains or SSH.

Contents· What Coder does1/12
  1. 01What Coder does
  2. 02What Coder brings
  3. 03Coder compared with other options
  4. 04Prerequisites
  5. 05Install Coder with Docker Compose
  6. 06The Docker socket hands over the server keys
  7. 07Put Coder behind nginx over HTTPS
  8. 08Create the first template and the first workspace
  9. 09Connect from VS Code, JetBrains or SSH
  10. 10Automatic stop and VPS resources
  11. 11Backup and updates
  12. 12One-click install on ServOrbit

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 /home volume.
  • Every editor — code-server in the browser, VS Code Remote-SSH, JetBrains Gateway, coder ssh.
  • Port forwarding — coder port-forward opens 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 VPScode-server aloneGitHub Codespaces
UsersA team, with accounts and rolesOne personGitHub accounts
EnvironmentVersioned Terraform templateThe server itselfdevcontainer file
EditorsBrowser, VS Code, JetBrains, SSHBrowserBrowser, VS Code, JetBrains
Where the code livesOn your serverOn your serverAt GitHub
CostThe VPS priceThe VPS pricePer 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

  1. Prepare the directory and the secrets

    The .env file 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 .env
  2. Write 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: {}
  3. 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/config

After 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 travail

To 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.

Your development environments on your VPS

A ServOrbit Ubuntu 24.04 VPS with 2 GB of RAM is enough to start Coder; plan 4 GB or more for a team. One-click install from the Marketplace, HTTPS on your domain or on the VPS's free subdomain, owner account and password created for you.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab