Skip to content

Coder

The Coder extension adds the Coder server, a self-hosted development workspaces server, to a Frostyard bootc image. Use it to run Coder on this machine. Every image carries the extension’s definition, switched off. The extension itself is not in the image: Updex turns it on and downloads it.

You need:

  • A Frostyard bootc image. Every image built on Base has systemd-sysext and frostyard-updex.
  • Root access to enable, update, and remove the extension.
  • Network access to https://repository.frostyard.org/ext/coder/.
  • Free space in /var for the image.

Coder has no published test results on Frostyard images yet. Try it on a machine you can spare first.

See what Updex found, then enable the feature and download it now:

Terminal window
updex features list --component=coder
sudo updex features enable coder --now

coder appears as a component, with its feature disabled. The enable command downloads the image, checks its checksum and signature, links it, and refreshes the merge.

Check the merge and the command that the extension adds:

Terminal window
systemd-sysext status
command -v coder
systemctl status coder-sysext-setup.service

systemd-sysext status lists coder, command -v coder prints /usr/bin/coder, and coder-sysext-setup.service is active (exited).

coder.service does not start yet. It waits until you set CODER_ACCESS_URL, as the next section shows.

If enable --now exits with a refresh error (refresh_error in JSON), the download worked, but the activation did not. If the output says activation did not finish, the extension is merged, but users and groups can be missing: reboot. Otherwise the merge state is unknown: reboot. A sudo systemd-sysext refresh by hand does not create users and groups. Then run the checks above again.

Coder reads its settings from /etc/coder.d/coder.env. The merge copies that file from /usr/share/factory/etc/coder.d/, and never overwrites your edits. coder.service is skipped until the file is ready. A skip is not a failure, and the service does not retry.

Edit the file:

Terminal window
sudoedit /etc/coder.d/coder.env

Set CODER_ACCESS_URL to the URL that users and workspaces use to reach Coder:

Terminal window
CODER_ACCESS_URL=https://coder.example.com

It must be reachable from outside the machine. If the file sets a key more than once, the last line counts.

Check CODER_HTTP_ADDRESS. It is the address that Coder listens on:

  • CODER_HTTP_ADDRESS=127.0.0.1:3000 means this host only. Keep it if a reverse proxy on this host serves CODER_ACCESS_URL. To listen on every interface, change it to CODER_HTTP_ADDRESS=0.0.0.0:3000.
  • CODER_HTTP_ADDRESS= with no value stops Coder from starting. Hosts that installed the extension before revision 3 have this line. An empty value does not mean the default. Set a value, for example CODER_HTTP_ADDRESS=0.0.0.0:3000, or delete the line to use the default 127.0.0.1:3000.
  • If you set CODER_TLS_ENABLE=true, Coder listens on CODER_TLS_ADDRESS instead. Its default is 127.0.0.1:3443.

The other keys can stay empty. An empty CODER_PG_CONNECTION_URL uses the built-in PostgreSQL, and an empty CODER_TLS_ENABLE leaves TLS off. You can make the file mode 0600: the check runs as root.

Start the server:

Terminal window
sudo systemctl restart coder.service
systemctl status coder.service

coder.service is active. From now on it starts at boot.

While the file is not ready, systemd skips coder.service. Read the reason:

Terminal window
journalctl -u coder.service -n 20

A line that starts with coder-configured: names the setting to fix. For example: coder-configured: CODER_ACCESS_URL is not set in /etc/coder.d/coder.env; set it, then run: systemctl restart coder.service. Fix the setting, then run sudo systemctl restart coder.service.

If Coder starts and then stops, for example on a bad certificate or database URL, systemd stops trying after 3 starts in 60 seconds. Fix /etc/coder.d/coder.env, then run:

Terminal window
sudo systemctl reset-failed coder.service
sudo systemctl restart coder.service

The extension adds a coder system user with home /home/coder, and puts it in the docker and incus-admin groups. The groups let Coder templates create containers and Incus instances when the Docker or Incus extension is merged. On a host without that extension, the group is still created.

coder-workspace-proxy.service is also in the extension. It stays off. It is a separate role that needs its own environment file and a running Coder server to register with. Enable it only if you need it.

Check for an update, then install it:

Terminal window
updex features check --component=coder
sudo updex features update --component=coder

Updex downloads and verifies the new image, switches the link, deletes older versions, and refreshes the merge. See Manage system extensions for --no-vacuum, --dry-run, and the update timer. The refresh swaps /usr under the running system.

Roll back with sudo updex features rollback coder. It takes effect at the next boot. See Roll back.

Remove Coder:

Terminal window
sudo updex features disable coder --now --force

Updex unmerges all extensions on the host, deletes the image, and merges the rest again. The coder command and its units go. Your /etc/coder.d/ files stay. Reboot when the command finishes. Without --force, Updex refuses while the image is merged.

Item What you get
Package The coder package from the upstream release, installed into the image with dpkg. The build checks the download against a pinned checksum
Command /usr/bin/coder
Settings file /etc/coder.d/coder.env, from /usr/share/factory/etc/coder.d/. The factory file sets CODER_HTTP_ADDRESS=127.0.0.1:3000 and leaves the other keys empty
User coder, home /home/coder, groups docker and incus-admin
Version The image file name carries the coder package version, plus a +rN snosi revision when one is set
Image file coder_<version>_<os>_<arch>.raw.zst; .raw.xz, .raw.gz, and .raw also work
Download From https://repository.frostyard.org/ext/coder/, signature required (Verify=true), into /var/lib/extensions.d/
Services coder.service (started at boot through coder-sysext-setup.service, skipped until the settings let Coder start); coder-workspace-proxy.service (off)
Start check /usr/lib/coder-sysext/coder-configured, run by the coder.service.d/10-snosi-configured.conf drop-in. The drop-in also stops restarts after 3 starts in 60 seconds

Each build checks /usr/bin/coder, both service units, the factory coder.env, the start check and its drop-in, and the user, tmpfiles, preset, and activation files. A build that is missing one fails. A build also fails if the factory coder.env passes the start check as shipped, or fails it once CODER_ACCESS_URL is set.

The image is a revised build: it carries SYSEXT_REVISION=3, so its file name has a +r3 suffix until the Coder version changes. Revision 1 tried to start coder.service with the empty factory settings. The server exited at once and restarted every 5 seconds. Revision 2 skipped the service until CODER_ACCESS_URL had a value, but the empty CODER_HTTP_ADDRESS still made it restart every 5 seconds. Revision 3 also checks the listen address, sets CODER_HTTP_ADDRESS=127.0.0.1:3000 in the factory file, and limits restarts.

Reviewed 2026-10-27; Updex facts reviewed 2026-10-30. snosi commit b2858ca0222814c395cf8248db98f3e096d57dc9; Updex v2.1.3 commit 2661e987faac986f2594d1d9bbbadf1bf3053f5b.