Skip to content
Search

Coder

lastmod 2026-09-14created 2026-05-3110 edits

Secure environments for developers and their agents

Tutorials

Install

Docker

## 1. 공식 compose 예제 다운로드 / Download the official compose example
curl -fLo compose.yaml https://raw.githubusercontent.com/coder/coder/main/compose.yaml

## 2. docker 그룹 GID 확인 (아래 group_add 값에 사용) / Get docker group GID
getent group docker | cut -d: -f3

## 3. Coder 기동 / Start Coder
docker compose up -d

## 4. 로그 확인 (access URL 확인용) / Check logs for the access URL
docker compose logs -f coder

An externally reachable IP or domain must be set in the CODER_ACCESS_URL environment variable.

Client login

## 클라이언트 설치
curl -fsSL https://coder.com/install.sh | sh

## `coder` 커맨드 사용 가능
coder login https://coder.run   # 브라우저가 열리고 세션 토큰 발급 / opens browser for session token

How to connect via SSH

After creating a workspace:

coder config-ssh

## 워크스페이스.coder 이름으로 접속하자. 예를 들어 이름이 `demo-workspace` 라면:
ssh demo-workspace.coder

Attaching a GPU to a Docker template

Just modify the template:

Since kreuzwerker/docker is in use, the gpus argument is available as-is on docker_container. It is converted into DeviceRequests, the same as docker run --gpus all.

resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = docker_image.main.image_id
  name  = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"

  gpus = "all"   # == docker run --gpus all

  # ...
}

Increasing shared memory in a Docker template

Just modify the template:

The docker_container of kreuzwerker/docker has a shm_size argument. The unit is MB, and it behaves the same as docker run --shm-size=10g.

resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "coder-dgx-spark:cuda13"
  name  = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"

  gpus     = "all"
  shm_size = 10240   # == docker run --shm-size=10g (MB 단위)

  # ...
}

Changing shm_size causes the container to be recreated, so the workspace must be restarted. The home directory is in home_volume, so data is preserved.

After applying, check inside the container:

df -h /dev/shm

If Size shows 10G, it is working. /dev/shm is tmpfs, so it only occupies as much RAM as is actually used.

=== Note: ipc_mode = "host" === If you want to remove the limit entirely, you can use ipc_mode = "host" instead of shm_size. However, it shares the host IPC namespace, which weakens isolation. shm_size, which explicitly limits the size, is recommended.

Troubleshooting

HTTP 400: System message must be at the beginning

After running vLLM, connecting AI as "OpenAI compatible" fails with HTTP 400 and prints the following error:

System message must be at the beginning

The Jinja chat template is the problem.

Many templates contain defensive code like this:

{%- if messages[0]['role'] != 'system' and ns.system_seen %}
    {{- raise_exception('System message must be at the beginning') }}
{%- endif %}

That is, role: "system" appeared in the messages array at a position other than the first. Either the gateway inserted an extra system message while passing the prompt through, or the client sent a system message again in the middle of the conversation.

Common causes:

  • Anthropic-format client (Claude Code, etc.) → OpenAI-format conversion. In Anthropic, system is a separate top-level field, so its position can get misaligned during conversion.
  • The agent harness inserts a system reminder in the middle of the conversation (Claude Code and Cline often do this)
  • Two or more system messages (the first is fine, but the second is in the middle)
  • Mapping role: "developer" to system shifts the position

See also

Favorite site

author Zer0 sitemap