Skip to content

Run with Docker

Prefer containers? The server ships as a single image:

bash
podman pull ghcr.io/yinyue123/16code:latest    # docker works the same

The container needs two things from the host, both persistent:

Host pathMounted atWhy
/etc/code.yaml/etc/code.yamlThe config file — see Configuration File
/var/lib/code/var/lib/code/dataAll data including the HTTPS certificate cache. Not persisting this triggers Let's Encrypt rate limits on every recreate.

The server inside the container runs as a non-root user (uid 10001), so both paths must be owned by it.

Setup

bash
# 1. config — start from the example and edit (at minimum: tlsDomains, cookieSecure)
sudo curl -fsSL -o /etc/code.yaml \
  https://raw.githubusercontent.com/yinyue123/16code/main/deploy/server.example.yaml
sudo $EDITOR /etc/code.yaml

# 2. data dir + ownership for the container user
sudo mkdir -p /var/lib/code
sudo chown 10001:10001 /etc/code.yaml /var/lib/code

Run

bash
podman run -d --name code-server --network host \
  --cap-add NET_BIND_SERVICE \
  -v /etc/code.yaml:/etc/code.yaml \
  -v /var/lib/code:/var/lib/code/data \
  --restart always \
  ghcr.io/yinyue123/16code:latest
  • --network host — the server binds 80/443 directly; simplest for the ACME challenge and WebSockets.
  • --cap-add NET_BIND_SERVICE — lets the non-root process bind ports below 1024. Not needed if you configure high ports.
  • Config file mounted read-write (no :ro) so you can edit it live from inside:
bash
podman exec -it code-server code-server-setup

Saving with Ctrl+S reloads the server in place — no container restart.

As a systemd service (Podman quadlet)

Put this in /etc/containers/systemd/code-server.container, then systemctl daemon-reload && systemctl start code-server:

ini
[Unit]
Description=code cloud server

[Container]
Image=ghcr.io/yinyue123/16code:latest
ContainerName=code-server
Network=host
Volume=/etc/code.yaml:/etc/code.yaml
Volume=/var/lib/code:/var/lib/code/data
AddCapability=CAP_NET_BIND_SERVICE

[Service]
Restart=always

[Install]
WantedBy=multi-user.target

Behind an existing reverse proxy

If nginx/Caddy/a tunnel already terminates TLS on this host, keep auto-HTTPS off and put the server on a loopback port instead: in /etc/code.yaml set tlsDomains: [] and listen: "127.0.0.1:5080", drop AddCapability, and point the proxy at 127.0.0.1:5080 (WebSocket pass-through required).

Upgrade

bash
podman pull ghcr.io/yinyue123/16code:latest
podman restart code-server        # quadlet: systemctl restart code-server

Config, data, history, and certificates all live on the host volumes — an image upgrade touches none of them.