docs(docs): document RPM install on RHEL-family Linux (#29295)

## Summary

Coder ships `.rpm` assets with every release and `install.sh` routes the
RHEL family to `install_rpm()`, but no public page said so. The only
page that named RHEL was the uninstall page. This adds an RPM install
page for the control plane.

New page `docs/install/server/rpm.md`:

- Supported distribution matrix for RHEL 8/9/10, Rocky, AlmaLinux,
CentOS Stream, Amazon Linux, Fedora, and openSUSE, with the
`ID`/`ID_LIKE` detection that makes derivatives work.
- Install tabs for the install script, `dnf install`, and `rpm -U`.
- What the package lays down: `/usr/bin/coder`,
`/etc/coder.d/coder.env`, `coder.service`,
`coder-workspace-proxy.service`, and the unprivileged `coder` user.
- Configure-then-start ordering, because `coder.service` carries
`ConditionFileNotEmpty=/etc/coder.d/coder.env` and won't start against
an empty config.
- SELinux caveat for Docker/Podman inside workspaces on RHEL nodes,
linking the existing guidance instead of duplicating it.
- Iron Bank UBI9-minimal pointer for hardened environments, scoped
correctly as a container image rather than an RPM path.

Supporting edits: manifest entry under "3. Install the control plane"
between OpenShift and Cloud Providers, a row in the platform table on
`install/server/index.md`, and a pointer from `install/cli.md`.

## Placement

The page sits at `docs/install/server/rpm.md`, as a sibling of Docker,
Kubernetes, Rancher, and OpenShift, rather than under community install
methods: RPMs are officially built and shipped, not an unofficial
method. It is a control-plane deployment page, not CLI download content,
so it is out of scope for the CLI-retirement work.

## Verification

Claims on the page were checked against real RHEL-family images, not
just the install script:

| Check | Method | Result |
|-------|--------|--------|
| `ID` and `ID_LIKE` per distribution | `docker run <image> sh -c '.
/etc/os-release; ...'` across UBI 8/9/10, Rocky 9, Alma 9/10, CentOS
Stream 9/10, Amazon Linux 2/2023, Fedora, openSUSE Leap and Tumbleweed |
Every RHEL-family image lists `fedora` in `ID_LIKE`; both openSUSE
variants list `opensuse`. Matches the `distro()` branch in `install.sh`
|
| `dnf install ./coder_*.rpm` | Rocky Linux 9 container | Installs
cleanly |
| Package contents | `rpm -ql coder` | `/usr/bin/coder`,
`/etc/coder.d/coder.env`, `coder.service`,
`coder-workspace-proxy.service` |
| Service account and start condition | Installed unit file | Runs as
`coder:coder`; `ConditionFileNotEmpty=/etc/coder.d/coder.env` |
| Architectures | `.github/workflows/release.yaml` | `amd64`, `armv7`,
`arm64` |

Not verified: `systemctl enable --now coder` against a live database,
since the containers used for verification have no init system. The
`systemctl is-active` output on the page is standard systemd output,
flagged here for the reviewer.

Lint: `make lint/markdown`, `make lint/emdash`, and `make lint/prose`
all clean on the changed files; `pnpm run format-docs` applied.

<details>
<summary>Implementation plan and decision log</summary>

### Style guide application

The first revision of this page was drafted from sibling install pages
rather than from the style guide, and was rewritten against
[`docs/.style/content-guidelines.md`](https://github.com/coder/coder/blob/main/docs/.style/content-guidelines.md)
and the prose style guide. What changed: one sentence per source line,
declared audience and outcome in the opening paragraph, numbered
procedures with one instruction per step and conditions stated first,
`refer to` instead of `see`, `sh` fences instead of `shell`, H3 tab
headings, non-breaking space between number and unit, and `Learn more`
instead of `Next steps`.

### Decisions

- **No version numbers or FIPS certification claims for Iron Bank.** The
tags in `scripts/ironbank/hardening_manifest.yaml` are stale (`0.15.3`);
documenting them would re-create the drift. The page links the registry
and names the UBI9-minimal base only.
- **Iron Bank framed as a container path.** It is a container image, so
the page routes readers to Kubernetes/OpenShift rather than implying it
is an alternative to the RPM.
- **Dropped an unverified SELinux claim.** An earlier draft asserted
that the control plane runs under enforcing mode with no policy changes.
That was not tested, so it is gone. The section now covers only the
workspace container-runtime case, which links to existing verified
guidance.
- **`ID_LIKE` values kept out of the table.** They vary by version (RHEL
8/9 report `fedora`, RHEL 10 reports `centos fedora`), so the table
lists `ID` and the prose states the invariant the install script
actually matches on.
- **Minimal edit to `install/cli.md`.** That file is slated for deletion
in the Install restructure, so it gets a pointer and nothing more.

### Rebase onto the install spine restructure

The install spine restructure landed on `main` while this PR was open
and removed the install-method tabs on `install/index.md` that the first
revision pointed from. The branch was rebased and squashed onto it: the
page moved from `docs/install/rpm.md` to `docs/install/server/rpm.md`,
every relative link was repointed at the new locations
(`../plan/sizing/index.md`, `../prepare/airgap.md`,
`../operate/upgrade.md`, `../operate/uninstall.md`,
`./kubernetes/index.md`), the install script snippet picked up the
standardized `curl -fsSL` flags, and discovery moved from the removed
`install/index.md` tabs to the platform table on
`install/server/index.md`. The prose is otherwise unchanged.

### Follow-ups tracked elsewhere

The install spine has no other bare-host or Linux-package option under
platforms; every other entry is a container platform or a cloud VM. Open
question recorded on the IA proposal: whether this generalizes to a
single "Linux host (system packages)" page covering `.deb` and `.apk`
too.

</details>

---

Linear:
[DOCS-886](https://linear.app/codercom/issue/DOCS-886/document-support-for-running-coder-on-red-hat-linux)

🤖 Generated with Coder Agents on behalf of @nickvigilante.
This commit is contained in:
Nick Vigilante
2026-09-25 11:47:34 -04:00
committed by GitHub
parent 702b13112d
commit 9afdea4808
4 changed files with 149 additions and 0 deletions
+2
View File
@@ -22,6 +22,8 @@ curl -fsSL https://coder.com/install.sh | sh
Refer to [GitHub releases](https://github.com/coder/coder/releases) for
alternate installation methods (e.g. standalone binaries, system packages).
To run the Coder control plane on a Red Hat Enterprise Linux host or another RHEL-family distribution, refer to [Install Coder on RHEL-family Linux](./server/rpm.md).
## Windows
If you plan to use the built-in PostgreSQL database, ensure that the
+1
View File
@@ -11,6 +11,7 @@ Choose the one that matches the platform your team already operates, or intends
| [Rancher](./rancher.md) | Kubernetes clusters your team already manages through Rancher |
| [OpenShift](./openshift.md) | Red Hat OpenShift clusters, which need specific security context settings |
| [Docker](./docker.md) | A single machine, such as a proof of concept or a small team deployment |
| [RPM (RHEL family)](./rpm.md) | A single Red Hat Enterprise Linux host, or another RHEL-family distribution |
| [Cloud providers](./cloud/index.md) | A virtual machine on AWS, Google Cloud, or Azure, or a marketplace listing |
| [Community install methods](./community.md) | Platforms Coder doesn't package, where a community-contributed method exists |
+140
View File
@@ -0,0 +1,140 @@
---
title: Install Coder on RHEL-family Linux
---
This guide is for a Coder deployment administrator who runs the Coder control plane on a single Red Hat Enterprise Linux host or another RHEL-family distribution.
Coder publishes an RPM with every release, and `systemd` manages the server like any other service.
For a multi-replica deployment, refer to [Kubernetes](./kubernetes/index.md) or [OpenShift](./openshift.md) instead.
To install the CLI on a client machine that connects to an existing deployment, refer to [Install the Coder CLI](../cli.md).
## Supported distributions
Coder builds one RPM per release and architecture.
The install script reads `/etc/os-release` and selects the RPM when `ID` or `ID_LIKE` names a Fedora-family or openSUSE-family distribution.
| Distribution | Versions | `ID` |
|--------------------------|------------------|----------------------------------------|
| Red Hat Enterprise Linux | 8, 9, 10 | `rhel` |
| Rocky Linux | 8, 9, 10 | `rocky` |
| AlmaLinux | 8, 9, 10 | `almalinux` |
| CentOS Stream | 9, 10 | `centos` |
| Amazon Linux | 2, 2023 | `amzn` |
| Fedora | Current releases | `fedora` |
| openSUSE | Leap, Tumbleweed | `opensuse-leap`, `opensuse-tumbleweed` |
Every RHEL-family distribution in the table lists `fedora` in `ID_LIKE`, and both openSUSE variants list `opensuse`.
A derivative that isn't listed here takes the same path when its `ID_LIKE` includes `fedora`.
Each release publishes RPMs for `amd64`, `arm64`, and `armv7`.
## Requirements
- A host running one of the distributions above.
- 2 CPU cores and 4&nbsp;GB of memory to evaluate Coder.
For production sizing, refer to the [Coder Validated Architecture](../plan/sizing/index.md).
- `root` or `sudo` access.
- An external PostgreSQL database for anything beyond a proof of concept.
Refer to [Using an external database](../../tutorials/external-database.md).
## Install the package
The install script detects the distribution and installs the matching RPM.
Install the package directly with `dnf` or `rpm` when the host can't run a piped shell script, or when you stage packages yourself.
<div class="tabs">
### Install script
```sh
curl -fsSL https://coder.com/install.sh | sh
```
The script installs the latest mainline release.
Pass `--stable` for the latest stable release, or `--version X.Y.Z` for a specific version.
Pass `--dry-run` to print the commands without running them.
### dnf
1. Download the RPM for your version and architecture from [GitHub releases](https://github.com/coder/coder/releases).
2. Install the package.
```sh
sudo dnf install ./coder_<version>_linux_amd64.rpm
```
On hosts that use `yum`, run `sudo yum install` instead.
### rpm
Install or upgrade the package in place.
This is the command the install script runs.
```sh
sudo rpm -U coder_<version>_linux_amd64.rpm
```
</div>
The package installs the `coder` binary to `/usr/bin/coder`, the configuration file to `/etc/coder.d/coder.env`, and two `systemd` units: `coder.service` for the control plane and `coder-workspace-proxy.service` for an optional [workspace proxy](../../admin/networking/workspace-proxies.md).
It also creates the unprivileged `coder` user that the service runs as.
To stage the RPM on a host with no internet access, refer to [Air-gapped deployments](../prepare/airgap.md).
## Configure the server
`coder.service` doesn't start while `/etc/coder.d/coder.env` is empty.
Set your configuration before you start the service.
1. Open the configuration file.
```sh
sudo vi /etc/coder.d/coder.env
```
2. Set `CODER_ACCESS_URL` to the external URL that users and workspaces connect to.
3. Set `CODER_PG_CONNECTION_URL` to your PostgreSQL connection string.
4. Save the file.
The file ships with the TLS and HTTP address variables commented in place.
For every server option, refer to the [configuration reference](../../admin/setup/configuration-reference.md).
## Start the service
1. Start Coder now and on every boot.
```sh
sudo systemctl enable --now coder
```
2. Confirm that the service is running.
```console
$ systemctl is-active coder
active
```
3. Read the startup logs.
```sh
journalctl -u coder.service -b
```
To test a configuration change without the service manager, run `coder server` in the foreground.
## SELinux and container runtimes in workspaces
SELinux affects workspaces that run their own container runtime.
If your templates run Docker or Podman inside a workspace on a RHEL-family node, refer to [Docker in workspaces](../../admin/templates/extending-templates/docker-in-workspaces.md) for the runtime requirements.
## Hardened base images
Coder publishes a container image built on Red Hat's UBI9-minimal base through [Iron Bank](https://ironbank.dso.mil/), the Department of Defense hardened container registry.
Choose that image when your compliance program requires an accredited base image.
The Iron Bank image is a container image, so deploy it with [Kubernetes](./kubernetes/index.md) or [OpenShift](./openshift.md) rather than through the RPM.
## Learn more
- [Validate your deployment](../validate/index.md)
- [Set up your control plane](../../admin/setup/index.md)
- [Create your first template](../../tutorials/template-from-scratch.md)
- [Upgrade Coder](../operate/upgrade.md)
- [Uninstall Coder](../operate/uninstall.md)
+6
View File
@@ -170,6 +170,12 @@
"path": "./install/server/openshift.md",
"icon_path": "./images/icons/openshift.svg"
},
{
"title": "RPM (RHEL family)",
"description": "Install the Coder control plane from an RPM package on Red Hat Enterprise Linux and other RHEL-family distributions.",
"path": "./install/server/rpm.md",
"icon_path": "./images/icons/system.svg"
},
{
"title": "Cloud Providers",
"description": "Install guides and example templates for deploying Coder on AWS, Google Cloud, and Azure.",