Files
coder/docs/admin/networking/troubleshooting.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

5.5 KiB

title
title
Troubleshooting

coder ping <workspace> will ping the workspace agent and print diagnostics on the state of the connection. These diagnostics are created by inspecting both the client and agent network configurations, and provide insights into why a direct connection may be impeded, or why the quality of one might be degraded.

The -v/--verbose flag can be appended to the command to print client debug logs.

$ coder ping dev
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 42ms
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 41ms
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 39ms
✔ preferred DERP region: 999 (Council Bluffs, Iowa)
✔ sent local data to Coder networking coordinator
✔ received remote agent data from Coder networking coordinator
    preferred DERP region: 999 (Council Bluffs, Iowa)
    endpoints: x.x.x.x:46433, x.x.x.x:46433, x.x.x.x:46433
✔ Wireguard handshake 11s ago

❗ You are connected via a DERP relay, not directly (p2p)
Possible client-side issues with direct connection:
 - Network interface utun0 has MTU 1280, (less than 1378), which may degrade the quality of direct connections

Possible agent-side issues with direct connection:
 - Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers
 - Agent IP address is within an AWS range (AWS uses hard NAT)

Common Problems with Direct Connections

Disabled Deployment-wide

Direct connections can be disabled at the deployment level by setting the CODER_BLOCK_DIRECT environment variable or the --block-direct-connections flag on the control plane. When set, this will be reflected in the output of coder ping.

UDP Blocked

Some corporate firewalls block UDP traffic. Direct connections require UDP traffic to be allowed between the client and agent, as well as between the client/agent and STUN servers in most cases. coder ping will indicate if either the Coder agent or client had issues sending or receiving UDP packets to STUN servers.

If this is the case, you may need to add exceptions to the firewall to allow UDP for Coder workspaces, clients, and STUN servers.

Endpoint-Dependent NAT (Hard NAT)

Hard NATs prevent public endpoints gathered from STUN servers from being used by the peer to establish a direct connection. Typically, if only one side of the connection is behind a hard NAT, direct connections can still be established easily. However, if both sides are behind hard NATs, direct connections may take longer to establish or may not be possible at all.

coder ping will indicate if it's possible the client or agent is behind a hard NAT.

Learn more about STUN and NAT.

No STUN Servers

If there are no STUN servers available within a deployment's DERP MAP, direct connections may not be possible. Notable exceptions are if the client and agent are on the same network, or if either is able to use UPnP instead of STUN to resolve the public IP of the other. coder ping will indicate if no STUN servers were found.

Endpoint Firewalls

Direct connections may also be impeded if one side is behind a hard NAT and the other is running a firewall that blocks ingress traffic from unknown 5-tuples (Protocol, Source IP, Source Port, Destination IP, Destination Port).

If this is suspected, you may need to add an exception for Coder to the firewall, or reconfigure the hard NAT.

VPNs

If a VPN is the default route for all IP traffic, it may interfere with the ability for clients and agents to form direct connections. This happens if the NAT does not permit traffic to be 'hairpinned' from the public IP address of the NAT (determined via STUN) to the internal IP address of the agent.

If this is the case, you may need to add exceptions to the VPN for Coder, modify the NAT configuration, or deploy an internal STUN server.

Low MTU

If a network interface on the side of either the client or agent has an MTU smaller than 1378, any direct connections form may have degraded quality or might hang entirely.

Use coder ping to check for MTU issues, as it inspects network interfaces on both the client and the workspace agent:

$ coder ping my-workspace
...
Possible client-side issues with direct connection:

 - Network interface utun0 has MTU 1280 (less than 1378), which may degrade the quality of direct connections or render them unusable.

If another interface cannot be used, and the MTU cannot be changed, you should disable direct connections and relay all traffic via DERP instead, which will not be affected by the low MTU.

To disable direct connections, set the --block-direct-connections flag or CODER_BLOCK_DIRECT environment variable on the control plane.

Throughput

The coder speedtest <workspace> command measures the throughput between the client and the workspace agent.

$ coder speedtest workspace
29ms via coder
Starting a 5s download test...
INTERVAL       TRANSFER         BANDWIDTH
0.00-1.00 sec  630.7840 MBits   630.7404 Mbits/sec
1.00-2.00 sec  913.9200 MBits   913.8106 Mbits/sec
2.00-3.00 sec  943.1040 MBits   943.0399 Mbits/sec
3.00-4.00 sec  933.3760 MBits   933.2143 Mbits/sec
4.00-5.00 sec  848.8960 MBits   848.7019 Mbits/sec
5.00-5.02 sec  13.5680 MBits    828.8189 Mbits/sec
----------------------------------------------------
0.00-5.02 sec  4283.6480 MBits  853.8217 Mbits/sec