# Best Practices for Configuring code-server Behind a Reverse Proxy

> Securely expose code-server with a reverse proxy. Learn best practices for TLS, Host headers, WebSockets, and port routing with code-server's proxy module for optimal internet access.

- Repository: [Coder/code-server](https://github.com/coder/code-server)
- Tags: best-practices
- Published: 2026-03-01

---

**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](https://github.com/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`](https://github.com/coder/code-server/blob/main/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`](https://github.com/coder/code-server/blob/main/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`](https://github.com/coder/code-server/blob/main/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`](https://github.com/coder/code-server/blob/main/docs/guide.md) lines 41-56):

```text
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`](https://github.com/coder/code-server/blob/main/docs/guide.md) lines 90-101):

```nginx
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:

```bash
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`](https://github.com/coder/code-server/blob/main/src/node/proxy.ts) lines 21-27).

### Custom External Proxy URI

To override the default port proxying behavior:

```bash
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`](https://github.com/coder/code-server/blob/main/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`](https://github.com/coder/code-server/blob/main/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.