Files
coder/docs/reference/cli/config-ssh.md
T
Bobby Ho dcb120d6ab feat: add --no-wildcard flag to coder config-ssh (#26753)
Add `--no-wildcard` (`CODER_CONFIGSSH_NO_WILDCARD`) to `coder
config-ssh` that generates an individual `Host` entry per workspace
instead of a single wildcard block (`Host *.coder`).

The wildcard approach cannot be enumerated by third-party SSH clients,
the VS Code Remote-SSH sidebar, or scripts that parse `~/.ssh/config` to
discover hosts. With `--no-wildcard`, each workspace gets its own entry
so those tools work without Coder-specific extensions.

The flag is persisted in the config section header so re-running without
it prompts the user about the option change. Workspaces are fetched with
pagination before writing so the diff shows actual hostnames.

## Manual testing

**Unit tests (no server needed):**

```sh
go test ./cli/ -run TestSSHConfigOptions_writeToBuffer -v
go test ./cli/ -run TestConfigSSH_NoWildcard -v
```

**End-to-end with a dev server:**

1. Build: `go build -o ./coder .`
2. Start dev server in a separate terminal: `./scripts/develop.sh`
3. Log in: `./coder login http://localhost:3000`
4. Create two workspaces
5. Run both variants into temp files:
```sh
./coder config-ssh --no-wildcard --hostname-suffix coder --ssh-config-file /tmp/test-ssh-config --yes
./coder config-ssh --hostname-suffix coder --ssh-config-file /tmp/test-ssh-config-wildcard --yes
diff /tmp/test-ssh-config-wildcard /tmp/test-ssh-config
```

<details>
<summary>Output: <code>--no-wildcard</code></summary>

```
# ------------START-CODER-----------
# This section is managed by coder. DO NOT EDIT.
#
# You should not hand-edit this section unless you are removing it, all
# changes will be lost when running "coder config-ssh".
#
# Last config-ssh options:
# :hostname-suffix=coder
# :no-wildcard=true
#
Host coder.myworkspace
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR
    ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h

Host coder.myworkspace2
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR
    ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h

Host myworkspace.coder
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR

Match host myworkspace.coder !exec "<coder> connect exists %h"
    ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h

Host myworkspace2.coder
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR

Match host myworkspace2.coder !exec "<coder> connect exists %h"
    ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```

</details>

<details>
<summary>Output: wildcard (default)</summary>

```
# ------------START-CODER-----------
# This section is managed by coder. DO NOT EDIT.
#
# You should not hand-edit this section unless you are removing it, all
# changes will be lost when running "coder config-ssh".
#
# Last config-ssh options:
# :hostname-suffix=coder
#
Host coder.*
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR
    ProxyCommand <coder> --global-config <config> ssh --stdio --ssh-host-prefix coder. %h

Host *.coder
    ConnectTimeout=0
    StrictHostKeyChecking=no
    UserKnownHostsFile=/dev/null
    LogLevel ERROR

Match host *.coder !exec "<coder> connect exists %h"
    ProxyCommand <coder> --global-config <config> ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```

</details>

<details>
<summary>diff wildcard → --no-wildcard</summary>

```diff
8a9
> # :no-wildcard=true
10c11
< Host coder.*
---
> Host coder.myworkspace
17c18
< Host *.coder
---
> Host coder.myworkspace2
21a23
>     ProxyCommand <coder> ssh --stdio --ssh-host-prefix coder. %h
23c25,31
< Match host *.coder !exec "<coder> connect exists %h"
---
> Host myworkspace.coder
>     ConnectTimeout=0
>     StrictHostKeyChecking=no
>     UserKnownHostsFile=/dev/null
>     LogLevel ERROR
>
> Match host myworkspace.coder !exec "<coder> connect exists %h"
```

</details>

Closes https://github.com/coder/coder/issues/17153 (Phase 1: CLI flag)
2026-06-30 13:02:15 -07:00

4.7 KiB
Generated

config-ssh

Add an SSH Host entry for your workspaces "ssh workspace.coder"

Usage

coder config-ssh [flags]

Description

  - You can use -o (or --ssh-option) so set SSH options to be used for all your
workspaces:

     $ coder config-ssh -o ForwardAgent=yes

  - You can use --dry-run (or -n) to see the changes that would be made:

     $ coder config-ssh --dry-run

Options

--ssh-config-file

Type string
Environment $CODER_SSH_CONFIG_FILE
Default ~/.ssh/config

Specifies the path to an SSH config.

--coder-binary-path

Type string
Environment $CODER_SSH_CONFIG_BINARY_PATH

Optionally specify the absolute path to the coder binary used in ProxyCommand. By default, the binary invoking this command ('config ssh') is used.

-o, --ssh-option

Type string-array
Environment $CODER_SSH_CONFIG_OPTS

Specifies additional SSH options to embed in each host stanza.

-n, --dry-run

Type bool
Environment $CODER_SSH_DRY_RUN

Perform a trial run with no changes made, showing a diff at the end.

--use-previous-options

Type bool
Environment $CODER_SSH_USE_PREVIOUS_OPTIONS

Specifies whether or not to keep options from previous run of config-ssh.

--ssh-host-prefix

Type string
Environment $CODER_CONFIGSSH_SSH_HOST_PREFIX

Override the default host prefix.

--hostname-suffix

Type string
Environment $CODER_CONFIGSSH_HOSTNAME_SUFFIX

Override the default hostname suffix.

--wait

Type yes|no|auto
Environment $CODER_CONFIGSSH_WAIT
Default auto

Specifies whether or not to wait for the startup script to finish executing. Auto means that the agent startup script behavior configured in the workspace template is used.

--disable-autostart

Type bool
Environment $CODER_CONFIGSSH_DISABLE_AUTOSTART
Default false

Disable starting the workspace automatically when connecting via SSH.

--no-wildcard

Type bool
Environment $CODER_CONFIGSSH_NO_WILDCARD
Default false

Generate an individual host entry for each workspace instead of a wildcard host block. This allows third-party tools and SSH clients to discover workspaces by reading the config file.

--force-unix-filepaths

Type bool
Environment $CODER_CONFIGSSH_UNIX_FILEPATHS

By default, 'config-ssh' uses the os path separator when writing the ssh config. This might be an issue in Windows machine that use a unix-like shell. This flag forces the use of unix file paths (the forward slash '/').

-y, --yes

Type bool

Bypass confirmation prompts.