Files
coder/docs/admin/setup/index.md
T
Nick Vigilante d40e24cf7d docs: nest the CLI reference by subcommand (#29956)
## Summary

Nests the CLI reference by subcommand so the Command Line sidebar
collapses from 156 flat entries to 49 top-level verbs.
Each page's URL follows the invocation, its page title is the full
command as inline code, and its sidebar label is only its own verb as
inline code.

| | Before | After |
| --- | --- | --- |
| File | `docs/reference/cli/oauth2-provider_dcr_disable.md` |
`docs/reference/cli/oauth2-provider/dcr/disable.md` |
| URL | `/reference/cli/oauth2-provider_dcr_disable` |
`/reference/cli/oauth2-provider/dcr/disable` |
| Page title (front matter) | `oauth2-provider dcr disable` | `` `coder
oauth2-provider dcr disable` `` |
| Sidebar label (manifest) | `oauth2-provider dcr disable` | ``
`disable` `` |

Resolves DOCS-140 (coder/coder half). Also fixes the Makefile part of
DOCS-1073 / DOCS-912, which this change depends on.

## Changes

- `scripts/clidocgen`: pages nest by command path. A command with
visible subcommands becomes its directory's `index.md`, so
`oauth2-provider/index.md` and `oauth2-provider/dcr/index.md` sit above
`oauth2-provider/dcr/disable.md`. Subcommand table links are relative to
the parent page.
- `scripts/clidocgen`: the manifest "Command Line" section is built from
the command tree (nested, sorted by name, hidden commands skipped)
instead of a flat list. The redundant `coder` child that pointed back at
`reference/cli/index.md` is gone.
- `Makefile`: the CLI rule now replaces `docs/reference/cli/` wholesale,
so stale pages get removed. The manifest rule now runs `clidocgen
-manifest-only` on top of the API staging manifest, so the CLI nav is
generated instead of edited by hand. As a result, the nine pages that
had no nav entry (`ai-gateway*`, `secret enable/disable`, `server
fix-oidc-links`) now have one.
- `scripts/configdocgen` and 48 prose pages: links point at the new
paths (for example `reference/cli/server.md` is now
`reference/cli/server/index.md`).

## How to review/QA this PR

- `docs/reference/cli/**/*` (approximately 190 pages): Each of these
pages are generated automatically. Some pages appear deleted, and some
pages appear new. Every deleted page corresponds to a new page somewhere
else, so no information is being deleted. The docs in this section
should adhere to the following, so a test in the build preview for each
of these items should be satisfactory:
- [ ] Each subcommand of a command gets nested as a child instead of
being displayed as a flat list.
  - [ ] Each parent command is stored in an `index.md` file.
- [ ] The title of each page inside the page should now feature the full
`coder XYZ` command.
- [ ] The title of each page inside the page should now be formatted as
inline code.
- [ ] The title of each page in the sidebar should be the most granular
subcommand of the whole command string (if the page's title is `coder
ai-gateway keys create`, the sidebar label is `create`).
- [ ] The title of each page in the sidebar should now be formatted as
inline code.
  - [ ] The page slug for each page is now the most granular subcommand.
  - [ ] All links now point to the correct page.
- `docs/manifest.json`: The changes here reflect the updated structure
of the `docs/reference/cli` section.
- `docs/**/*.md` outside of `docs/reference/cli/**/*` (approximately 50
pages): The extent of the changes in these pages are just updating the
paths to point to the new page locations.
- [ ] The links on the page all point to the correct new path in
`docs/reference/cli`.
- `scripts/clidocgen` (4 files): This is the Go code responsible for
generating everything inside of `docs/reference/cli/**/*`. A typical
code review here should be satisfactory.
- `scripts/configdocgen` (2 files): these two files just have updates to
the raw `.md` path used by `docs/admin/setup/configuration-reference.md`
and updates the tests to reflect that.
- `Makefile`: This updates the `make` targets for generating the CLI
docs to fit the new structure.

## Merge ordering

Without the renderer PRs deployed, both docs sites show literal
backticks in titles and sidebar labels. Without the redirects, the old
flat URLs return 404.

1. Deploy before merging this PR: coder/docs-engine#176 (beta-docs
renders these titles as inline code) and coder/coder.com#1111 (classic
docs renders them as inline code). Both are safe to ship first, because
titles without backticks render as before.
2. Merge this PR.
3. Merge coder/coder.com#1112 (redirects from the old flat URLs) only
once this content reaches the mainline release branch that serves
unversioned `/docs`.

## Testing

- `go test ./scripts/clidocgen/ ./scripts/configdocgen/
./scripts/docshtmlcheck/`: pass. New tests cover page paths, subcommand
links, the nested manifest, and front matter quoting.
- `make docs/reference/cli/index.md docs/manifest.json
docs/admin/setup/configuration-reference.md`, then a forced rerun: the
second run produced no diff.
- Checked the manifest: all 164 CLI entries resolve to a file, no page
is missing a nav entry, and everything outside "Command Line" is
byte-identical.
- Relative `.md` links across `docs/`: 0 broken, same as `main`.
- `make pre-commit` and `make pre-push`: pass. On earlier pre-push
attempts, different unrelated vitest files timed out under host load.
Those files pass when run alone, and the final push passed with
`PARALLEL_JOBS=1`.

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

**Goal (from DOCS-140 and the requester):** URLs follow the command
hierarchy. Pages are titled with the full command, and sidebar entries
with the last verb only. Both are formatted as inline code.

**Contract with the renderers:** a title wrapped entirely in one pair of
backticks (``^`[^`]+`$``) renders as inline code. Plain-text consumers
(`<title>`, meta, search, llms corpus) strip the backticks. Page title
comes from front matter `title`, and the sidebar label from the manifest
node `title`.

**Decisions**

- A parent command is `dir/index.md` rather than a sibling `dir.md`. The
root CLI page is already `index.md`, and both docs-engine and the legacy
coder.com renderer map `x/index.md` to `/x`.
- The manifest is built from the command tree, not from the written
files, so ordering is deterministic and the nesting matches the pages
exactly.
- The manifest discard bug (DOCS-1073 item 1) is fixed here, because
without that fix the generated nested manifest would never reach the
tree. DOCS-1073 items 2 through 4 (a prose fix and a hidden-command
policy) are out of scope.
- `-manifest-only` keeps the existing parallel `make gen` layout: the
API rule still owns `_gen/manifest-staging.json`, and CLI regeneration
doesn't retrigger swag.
- The renderer and redirect work lives in the companion PRs in
coder/docs-engine and coder/coder.com. It is linked above and not
duplicated here.

</details>

---

> [!NOTE]
> Generated by Coder Agents on behalf of @nickvigilante.
2026-09-28 15:44:10 -04:00

6.4 KiB

title
title
Configure control plane access

The control plane's primary configuration is done via environment variables. For a full list of the options, run coder server --help or see our CLI documentation.

Tip

Need to look up an exact environment variable, CLI flag, or YAML key for a setting? See the configuration reference for a searchable list of every option.

Access URL

CODER_ACCESS_URL is required if you are not using the tunnel. Set this to the external URL that users and workspaces use to connect to Coder (e.g. https://coder.example.com). This should not be localhost.

Access URL should be an external IP address or domain with DNS records pointing to Coder.

Tunnel

If an access URL is not specified, Coder will create a publicly accessible URL to reverse proxy your deployment for simple setup.

Address

You can change which port(s) Coder listens on.

# Listen on port 80
export CODER_HTTP_ADDRESS=0.0.0.0:80

# Enable TLS and listen on port 443)
export CODER_TLS_ENABLE=true
export CODER_TLS_ADDRESS=0.0.0.0:443

## Redirect from HTTP to HTTPS
export CODER_REDIRECT_TO_ACCESS_URL=true

# Start the control plane
coder server

Wildcard access URL

Tip

Learn more about the importance and benefits of wildcard access URLs

CODER_WILDCARD_ACCESS_URL is necessary for port forwarding via the dashboard or running coder_apps on an absolute path. Set it to a wildcard hostname that resolves to Coder, such as *.coder.example.com or *-coder.example.com. The suffix form creates application hostnames such as 8080--main--myworkspace--john-coder.example.com. It requires a DNS record and TLS certificate for *.example.com.

Note

We do not recommend using a top-level-domain for Coder wildcard access (for example *.workspaces), even on private networks with split-DNS. Some browsers consider these "public" domains and will refuse Coder's cookies, which are vital to the proper operation of this feature.

If you are providing TLS certificates directly to the control plane, either

  1. Use a single certificate and key for both the root and wildcard domains.
  2. Configure multiple certificates and keys via coder.tls.secretNames in the Helm Chart, or --tls-cert-file and --tls-key-file command line options (these both take a comma separated list of files; list certificates and their respective keys in the same order).

After you enable the wildcard access URL, you should disable path-based apps for security.

TLS & Reverse Proxy

The control plane can directly use TLS certificates with CODER_TLS_ENABLE and accompanying configuration flags. However, Coder can also run behind a reverse-proxy to terminate TLS certificates from LetsEncrypt.

Kubernetes TLS configuration

Below are the steps to configure Coder to terminate TLS when running on Kubernetes. You must have the certificate .key and .crt files in your working directory prior to step 1.

  1. Create the TLS secret in your Kubernetes cluster

    kubectl create secret tls coder-tls -n <coder-namespace> --key="tls.key" --cert="tls.crt"
    

    You can use a single certificate for the both the access URL and wildcard access URL. The certificate CN must match the wildcard domain, such as *.example.coder.com.

  2. Reference the TLS secret in your Coder Helm chart values

    coder:
      tls:
        secretNames:
          - coder-tls
    
      # Alternatively, if you use an Ingress controller to terminate TLS,
      # set the following values:
      ingress:
        enable: true
        tls:
          enable: true
          secretName: coder-tls
          wildcardSecretName: coder-tls
    

PostgreSQL Database

Coder uses a PostgreSQL database to store users, workspace metadata, and other deployment information. Use CODER_PG_CONNECTION_URL to set the database that Coder connects to. If unset, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root.

Note

Postgres 13 is the minimum supported version.

If you are using the built-in PostgreSQL deployment and need to use psql (aka the PostgreSQL interactive terminal), output the connection URL with the following command:

$ coder server postgres-builtin-url
psql "postgres://coder@localhost:49627/coder?sslmode=disable&password=feU...yI1"

Migrate from the built-in database to an external database

To migrate from the built-in database to an external database, follow these steps:

  1. Stop your Coder deployment.
  2. Run coder server postgres-builtin-serve in a background terminal.
  3. Run coder server postgres-builtin-url and copy its output command.
  4. Run pg_dump <built-in-connection-string> > coder.sql to dump the internal database to a file.
  5. Restore that content to an external database with psql <external-connection-string> < coder.sql.
  6. Start your Coder deployment with CODER_PG_CONNECTION_URL=<external-connection-string>.

Configure Coder behind a proxy

To configure Coder behind a corporate proxy, set the environment variables HTTP_PROXY and HTTPS_PROXY. Be sure to restart the control plane. Lowercase values (e.g. http_proxy) are also respected in this case.

Continue your setup with external authentication

Coder supports external authentication via OAuth2.0. This allows enabling integrations with Git providers, such as GitHub, GitLab, and Bitbucket.

External authentication can also be used to integrate with external services like JFrog Artifactory and others.

Please refer to the external authentication section for more information.

Up Next