Best Practices for Configuring code-server Behind a Reverse Proxy

Running code-server behind a reverse proxy is the recommended method for secure internet exposure, requiring proper TLS termination, Host header forwarding, and WebSocket support while leveraging code-server's built-in proxy module for port routing.

Deploying code-server from the coder/code-server repository behind a reverse proxy such as NGINX, Caddy, or Traefik provides enterprise-grade security and flexible routing. This architecture places the proxy at the network edge to handle encryption and authentication, while the internal code-server process serves the VS Code web interface on a local port. Understanding the interaction between these components ensures reliable WebSocket connections and correct URL generation for proxied services.

Architectural Overview

When running code-server behind a reverse proxy, three primary components handle the request flow:

  • code-server (listening on 127.0.0.1:8080 by default): Serves the VS Code web UI and provides built-in proxying for other local services via /proxy/<port>/ or /absproxy/<port>/ endpoints. It validates the Origin header on WebSocket upgrades.
  • Reverse proxy (NGINX, Caddy, Traefik): Terminates TLS, sets correct Host and X-Forwarded-Proto headers, rewrites request paths when serving from sub-paths, forwards WebSocket upgrades, and optionally enforces additional authentication.
  • Client browser: Connects to https://<your-domain>, receives a valid certificate from the proxy, and communicates with the local code-server instance through the proxy tunnel.

Core Proxy Settings in code-server

The proxy implementation resides in src/node/proxy.ts, which creates an HTTP proxy server, rewrites absolute redirects when a base path is set, and provides custom error handling. The test suite in test/unit/node/proxy.test.ts validates critical behaviors including disabled proxy responses, base-path handling, and WebSocket origin checks.

Configure code-server using these flags and environment variables:

  • --proxy-domain <domain>: Enables sub-domain proxying. When a request arrives for 8080.<domain>, code-server rewrites internal redirects to include the host header. This logic processes responses via proxy.on("proxyRes") in the source file.
  • VSCODE_PROXY_URI: Overrides the default /proxy/<port>/ behavior. Setting this to https://{{port}}.example.dev causes the Ports panel to generate external URLs instead of local paths.
  • --disable-proxy: Disables the built-in /proxy endpoint entirely, returning 403 Forbidden for all proxy requests (validated in the unit test "should return 403 Forbidden if proxy is disabled").
  • --auth=none: Disables code-server's built-in authentication. Use this only when your reverse proxy already handles identity verification.

Essential Reverse Proxy Configuration

Follow these steps to ensure reliable operation:

  1. Terminate TLS at the proxy: Use certificates from Let's Encrypt or a corporate CA. Avoid self-signed certificates in production environments as they break certain mobile browsers.
  2. Forward the original Host header: Set proxy_set_header Host $http_host; in NGINX or equivalent so code-server can generate correct absolute URLs and validate WebSocket origins.
  3. Enable WebSocket support: Forward Upgrade and Connection headers unchanged. code-server rejects connections that fail origin validation against the Host header (see test/unit/node/proxy.test.ts lines 72-88).
  4. Handle sub-path routing: When serving from a sub-path like /code/, configure the proxy to strip the prefix before forwarding (e.g., uri strip_prefix /code in Caddy).
  5. Configure proxy-domain for sub-domains: Use code-server --proxy-domain example.com when routing 8080.example.com to local ports so redirects preserve the host header.
  6. Set VSCODE_PROXY_URI for external proxies: Export this variable before launching code-server if you want the Ports panel to reference an external proxy infrastructure.

Implementation Examples

Caddy Configuration (Sub-path)

For serving code-server under a sub-path, strip the prefix before proxying (as documented in docs/guide.md lines 41-56):

mydomain.com {
  reverse_proxy 127.0.0.1:8080
}

# Serve under /code/ (strip prefix)

mydomain.com/code/* {
  uri strip_prefix /code
  reverse_proxy 127.0.0.1:8080
}

NGINX Configuration (HTTPS)

Standard HTTPS configuration with WebSocket support (see docs/guide.md lines 90-101):

server {
    listen 80;
    server_name mydomain.com;

    location / {
        proxy_pass http://localhost:8080/;
        proxy_set_header Host $http_host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection upgrade;
        proxy_set_header Accept-Encoding gzip;
    }
}

Sub-domain Proxying with code-server

Launch code-server with the proxy domain flag to handle sub-domain routing:

code-server --proxy-domain example.com

With this configuration, requests to 8080.example.com proxy to the local service on port 8080, and redirects sent by the target are rewritten to preserve the host header (handled in src/node/proxy.ts lines 21-27).

Custom External Proxy URI

To override the default port proxying behavior:

export VSCODE_PROXY_URI="https://{{port}}.mycompany.dev"
code-server

The Ports panel will now generate URLs like https://3000.mycompany.dev instead of the default /proxy/3000/ path.

Security Considerations

  • Origin validation: code-server validates that WebSocket Origin headers match the request Host header. Ensure your proxy forwards the original Host header to prevent connection failures.
  • Disable unused features: If you do not require the built-in port proxying, start code-server with --disable-proxy to prevent accidental exposure of internal services.
  • Certificate trust: While self-signed certificates work for local testing (documented in the self-signed certificate section of the guide), production deployments require certificates trusted by all client browsers.

Summary

  • Reverse proxy placement: Always position NGINX, Caddy, or Traefik in front of code-server for TLS termination and security hardening.
  • Header forwarding: Preserve the original Host header and WebSocket upgrade headers to ensure code-server functions correctly behind the proxy.
  • Path handling: Strip sub-path prefixes at the proxy layer when serving code-server from non-root paths.
  • Sub-domain support: Use --proxy-domain and VSCODE_PROXY_URI to customize how code-server generates URLs for proxied ports.
  • Security hardening: Disable the built-in proxy with --disable-proxy when not needed, and rely on the reverse proxy for authentication via --auth=none only in trusted environments.

Frequently Asked Questions

Do I need to configure WebSocket support separately when running code-server behind a reverse proxy?

Yes. You must explicitly forward the Upgrade and Connection headers through your proxy configuration. According to test/unit/node/proxy.test.ts, code-server validates WebSocket upgrade requests against the Origin header, which requires the original Host header to be preserved for the check to pass.

How do I serve code-server from a sub-path like /code/?

Configure your reverse proxy to strip the path prefix before forwarding requests. In Caddy, use uri strip_prefix /code inside the site block. In NGINX, use a location block with proxy_pass and ensure the X-Forwarded-Prefix header is set if your application logic depends on it.

What is the difference between --proxy-domain and VSCODE_PROXY_URI?

The --proxy-domain flag enables code-server to rewrite redirects for sub-domain proxying (e.g., 8080.example.com) by processing the host header in src/node/proxy.ts. VSCODE_PROXY_URI is an environment variable that changes the URL format displayed in the Ports panel, allowing you to route traffic through an entirely separate external proxy infrastructure.

Can I disable code-server's built-in authentication when using a reverse proxy?

Yes. Set --auth=none when your reverse proxy handles authentication via OAuth, mutual TLS, or other identity providers. This configuration is common in enterprise deployments where the edge proxy manages all authentication concerns.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →