Configuring a workstation
Go beyond the defaults: declarative Workstation and WorkstationConfig manifests, a browser IDE, devtools, ports, and more.
A bare Workstation gets you a clean machine. Real environments are described
declaratively, in YAML, and applied with rl apply. This page shows the
two-resource model and builds up a fully configured browser-IDE workstation.
For exhaustive field tables, see the Reference Guide.
Two resources: config layer + instance
Ringleader splits what to install from which machine:
- A WorkstationConfig is a reusable configuration layer: image, packages, devtools, ports, identity, and so on.
- A Workstation is an instance. It can carry config inline, but usually it just matches a config.
A config attaches to a workstation in one of two ways:
- By selector: the config’s
spec.selector.matchLabelsmatch the workstation’smetadata.labels. No reference needed. - By explicit reference: the workstation lists it in
spec.configs.
# By selector — any Workstation labeled tier: dev picks this up automatically,
# including ones created later. This is the default to reach for.
spec:
selector:
matchLabels:
tier: dev# By explicit reference — the Workstation names the config directly. Reach
# for this when a config belongs to exactly one workstation, not a group.
spec:
configs:
- name: ide
namespace: devSelector matching is the one to default to: label a workstation once and it inherits every config that targets that label, including configs added later. Use explicit reference for a config meant for one specific workstation, such as a one-off you do not want any other workstation to pick up. The browser-IDE example further down this page uses selector matching.
All matching configs plus the workstation’s own spec are merged into one
effective configuration (lower priority applies first), which
rl workstation get-resolved-configuration <name>
prints on demand.
Where manifests live
Ringleader does not care where your manifest file sits on disk. apply reads
the local path you give it (rl apply -f path/to/workstation.yaml), and the
workstation and its configs are what get stored, not the file itself. In
practice, keep the manifest in your project’s repository, typically alongside
the code it supports (a deploy/ or .ringleader/ folder both work fine),
and commit it like any other config. That is what makes an environment
reproducible and reviewable: anyone on the team can rl apply -f the same
file and get the same workstation, and a change to the environment shows up as a diff
in a pull request instead of living only on your machine.
A browser-IDE workstation
The manifest below (a YAML file you write and apply) boots a Debian workstation with
Node.js, the Claude Code and Codex CLIs, and VS Code Web
(code-server) auto-started on port 8080, and forwards that port back to your Mac
so the IDE is reachable at http://127.0.0.1:8080.
apiVersion: core.ringleader.dev/v1
kind: Namespace
metadata:
name: dev
---
apiVersion: workstations.ringleader.dev/v1
kind: WorkstationConfig
metadata:
name: ide
namespace: dev
spec:
# Attach to every Workstation in this namespace whose labels match.
selector:
matchLabels:
tier: dev
priority: 100
image:
os: linux
distribution: debian
version: "13"
# The agent owns user creation; default the login shell.
identity:
shell: /bin/bash
# OS packages. Each entry is a bare name or {name, version, updatePolicy}.
packages:
- git
- name: curl
updatePolicy: latest
# Curated install recipes, installed by the in-VM devtool registry.
devtools:
- name: nodejs # prerequisite for the npm-installed CLIs
- name: claude-code
- name: codex
- name: vscode-web
# Per-tool configuration pushed to already-installed tools. Here: serve
# code-server on :8080 with no auth (the loopback-only forward fronts it).
toolconfigs:
- id: vscode-web
name: vscode-web
config:
port: 8080
auth: none
# Declared listening ports.
ports:
- 8080
# Unattended security upgrades (Debian: unattended-upgrades).
securityUpdates: true
# Forwarding is not implicit. This template makes the daemon seed a
# device-local LocalBinding once, when the workstation first reaches Running, that
# forwards every listening port (incl. :8080) back to the host 1:1.
defaultLocalBinding:
enabled: true
autoForward:
forwardAll: true
---
apiVersion: workstations.ringleader.dev/v1
kind: Workstation
metadata:
name: ide-box
namespace: dev
labels:
tier: dev # matches the `ide` config's selector
spec:
# VM sizing for local providers (qemu -m / -smp). NOTE: providerConfig is
# read from the Workstation spec only — it is NOT merged from config layers —
# so it must live here, not on the WorkstationConfig. A browser IDE plus an
# AI agent needs real headroom.
providerConfig:
memory: 6 # GiB
cpus: 2Apply it and wait for it to finish setting up:
rl apply -f ide-box.yaml
rl workstation wait ide-box -n dev --for Ready --timeout 15mThe devtool installs are real npm/code-server network installs (a few minutes
on a fresh VM); the workstation reports Configured once it has applied
them. Then open http://127.0.0.1:8080 in your browser.
providerConfig is not overlaid
providerConfig is resolved from the
Workstation spec only. Put VM sizing (memory, cpus) and cloud
providerConfig.gcp settings directly on the Workstation, not on a shared
WorkstationConfig.More configuration
The same config fields can be set on either a WorkstationConfig or a
Workstation. A few common ones:
Environment variables and dotfiles
spec:
environment:
EDITOR: vim
GOPATH: /home/dev/go
dotfiles:
.bashrc: |
alias ll='ls -alF'Pin a provider or image
By default Ringleader chooses a provider for you (automatic placement). Pin one explicitly when you need to:
spec:
provider: gcp # shorthand for requirements: [provider:gcp]
image:
distribution: debian
version: "13"Stop and restart declaratively
spec:
stopped: true # halt the machine; it rests in the Stopped phaseSet stopped: false (or remove it) to start it again. To force a restart of a
running workstation, change spec.restartNonce to any new value.
Where to go next
- Tutorials: want the hands-on, step-by-step version of what you just built? Start there and work up to running an AI coding agent inside the workstation.
- CLI Reference: every command for driving these resources.
- Reference Guide: the full field tables for each kind.