Files
coder/cli/testdata/coder_config-ssh_--help.golden
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

67 lines
2.5 KiB
Plaintext

coder v0.0.0-devel
USAGE:
coder config-ssh [flags]
Add an SSH Host entry for your workspaces "ssh workspace.coder"
- 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:
--coder-binary-path string, $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.
--disable-autostart bool, $CODER_CONFIGSSH_DISABLE_AUTOSTART (default: false)
Disable starting the workspace automatically when connecting via SSH.
-n, --dry-run bool, $CODER_SSH_DRY_RUN
Perform a trial run with no changes made, showing a diff at the end.
--force-unix-filepaths bool, $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 '/').
--hostname-suffix string, $CODER_CONFIGSSH_HOSTNAME_SUFFIX
Override the default hostname suffix.
--no-wildcard bool, $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.
--ssh-config-file string, $CODER_SSH_CONFIG_FILE (default: ~/.ssh/config)
Specifies the path to an SSH config.
--ssh-host-prefix string, $CODER_CONFIGSSH_SSH_HOST_PREFIX
Override the default host prefix.
-o, --ssh-option string-array, $CODER_SSH_CONFIG_OPTS
Specifies additional SSH options to embed in each host stanza.
--use-previous-options bool, $CODER_SSH_USE_PREVIOUS_OPTIONS
Specifies whether or not to keep options from previous run of
config-ssh.
--wait yes|no|auto, $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.
-y, --yes bool
Bypass confirmation prompts.
———
Run `coder --help` for a list of global options.