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.
Before you start
Section titled “Before you start”You need:
- A Frostyard bootc image. Every image built on Base has
systemd-sysextandfrostyard-updex. - Root access to enable, update, and remove the extension.
- Network access to
https://repository.frostyard.org/ext/coder/. - Free space in
/varfor the image.
Coder has no published test results on Frostyard images yet. Try it on a machine you can spare first.
Enable Coder
Section titled “Enable Coder”See what Updex found, then enable the feature and download it now:
updex features list --component=codersudo updex features enable coder --nowcoder 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:
systemd-sysext statuscommand -v codersystemctl status coder-sysext-setup.servicesystemd-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.
Configure and start Coder
Section titled “Configure and start Coder”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:
sudoedit /etc/coder.d/coder.envSet CODER_ACCESS_URL to the URL that users and workspaces use to reach Coder:
CODER_ACCESS_URL=https://coder.example.comIt 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:3000means this host only. Keep it if a reverse proxy on this host servesCODER_ACCESS_URL. To listen on every interface, change it toCODER_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 exampleCODER_HTTP_ADDRESS=0.0.0.0:3000, or delete the line to use the default127.0.0.1:3000.- If you set
CODER_TLS_ENABLE=true, Coder listens onCODER_TLS_ADDRESSinstead. Its default is127.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:
sudo systemctl restart coder.servicesystemctl status coder.servicecoder.service is active. From now on it starts at boot.
If Coder does not start
Section titled “If Coder does not start”While the file is not ready, systemd skips coder.service. Read the reason:
journalctl -u coder.service -n 20A 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:
sudo systemctl reset-failed coder.servicesudo systemctl restart coder.serviceThe 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.
Update, roll back, and remove
Section titled “Update, roll back, and remove”Check for an update, then install it:
updex features check --component=codersudo updex features update --component=coderUpdex 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:
sudo updex features disable coder --now --forceUpdex 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.
What ships
Section titled “What ships”| 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.
See also
Section titled “See also”Sources
Section titled “Sources”Reviewed 2026-10-27; Updex facts reviewed 2026-10-30. snosi commit
b2858ca0222814c395cf8248db98f3e096d57dc9;
Updex v2.1.3 commit
2661e987faac986f2594d1d9bbbadf1bf3053f5b.
-
mkosi.images/coder/mkosi.extra/usr/lib/systemd/system-preset/40-coder.preset -
mkosi.images/coder/mkosi.extra/usr/lib/systemd/system/coder-sysext-setup.service -
mkosi.images/coder/mkosi.extra/usr/lib/systemd/system/multi-user.target.d/10-coder.conf -
mkosi.images/coder/mkosi.extra/usr/lib/systemd/system/coder.service.d/10-snosi-configured.conf -
mkosi.images/coder/mkosi.extra/usr/lib/coder-sysext/coder-configured -
mkosi.images/coder/mkosi.extra/usr/lib/sysusers.d/coder.conf -
mkosi.images/coder/mkosi.extra/usr/lib/tmpfiles.d/coder.conf -
mkosi.images/base/mkosi.extra/usr/lib/sysupdate.coder.d/coder.feature -
mkosi.images/base/mkosi.extra/usr/lib/sysupdate.coder.d/coder.transfer -
snosi#1119: skip
coder.serviceuntilCODER_ACCESS_URLis set -
snosi#1120: the empty
CODER_HTTP_ADDRESSmakescoder.servicefail and restart -
snosi#1121: require a bind address and stop restart loops (r3)
-
Updex
docs/adr/0019-apply-merged-sysusers-and-tmpfiles-on-a-live-refresh.md(a live refresh runssystemd-sysusersandsystemd-tmpfiles --create; when the last refresh fails, the merge state is unknown; a refresh by hand does not runsystemd-sysusers)