## Problem
`coder config-ssh --ssh-host-prefix=""` (or the matching env var,
`CODER_CONFIGSSH_SSH_HOST_PREFIX=`) was silently ignored, and the
deprecated `Host coder.*` block was written to the SSH config anyway.
The
merge logic that decides whether to fall back to the server's default
prefix checked `user.userHostPrefix == ""`, which is true both when the
flag was never passed and when it was explicitly set to empty, so there
was no way to distinguish the two. The same issue applied to
`--hostname-suffix`.
## How this affects users
Anyone who wants to opt out of the legacy prefix-based SSH aliases
(`ssh coder.myworkspace`) in favor of the newer suffix-based ones
(`ssh myworkspace.coder`) had no way to do so, the `Host coder.*`
wildcard
block kept reappearing on every `config-ssh` run regardless of the flag.
Because that wildcard matches any hostname starting with `coder.`, not
just Coder workspaces, it can silently intercept SSH connections to
unrelated hosts that happen to share that prefix.
It got worse on top of that: even after passing `--ssh-host-prefix=""`,
running `config-ssh --use-previous-options` in a later session, a normal
way to refresh local config without retyping every flag, would silently
bring the block back, because the empty choice was never persisted to
the
file in the first place.
## Solution
Track whether each option (`--ssh-host-prefix`, `--hostname-suffix`) was
explicitly set by the user, as opposed to left at its zero value, and
only
fall back to the server default (or skip persisting the option) when it
was genuinely never set.
## How it works
Two new fields on `sshConfigOptions`, `userHostPrefixExplicit` and
`hostnameSuffixExplicit`, carry this information:
- **Live invocation**: they're set from `userSetOption(inv, ...)`, which
inspects serpent's `Option.ValueSource` for the flag, right after
`header`/`headerCommand` are set in the `Handler`, before any
`--use-previous-options`/prompt logic can replace the struct wholesale
from a prior run's saved options.
- **Persistence**: `sshConfigWriteSectionHeader` now writes the
`# :ssh-host-prefix=` comment line even when the value is empty, as long
as it was explicit, and `sshConfigParseLastOptions` sets the field back
to `true` whenever it parses that line on a later run, regardless of
value.
`mergeSSHOptions`'s fallback condition changed from
`user.userHostPrefix == ""` to
`user.userHostPrefix == "" && !user.userHostPrefixExplicit` (and the
mirror for suffix). `equal()` and `asList()` were extended to include
the
two new fields so the `--dry-run` diff and "options differ, use new
ones?"
prompt stay accurate.
## Why implemented this way
- Reuses `userSetOption` (`cli/util.go`), an existing helper already
used
for this exact "distinguish zero value from unset" problem elsewhere in
the CLI (`cli/templateedit.go`), instead of inventing new machinery.
- Storing the "explicit" bit as a plain field on `sshConfigOptions`,
rather
than as extra parameters to `mergeSSHOptions`, keeps that function
dependency-free (still plain data in, plain data out, no
`serpent.Invocation` coupling), while letting the same bit flow
naturally
through the SSH config's persisted-options comment, solving the
live-flag
case and the `--use-previous-options` persistence case with one
mechanism instead of two.
- A sentinel-value approach was considered and rejected: a self-tracking
custom `serpent.Value` doesn't work because serpent applies a flag's
default through the same `Value.Set()` call used for real input, so it
can't tell the two apart; a plain sentinel string would work but leak
into several other code paths (equality checks, diff/prompt text, the
persisted comment) that would all need to filter it out.
Closes https://github.com/coder/internal/issues/1208
## Manual verification
Every step below was run against a local dev server
(`./scripts/develop.sh`
+ `./scripts/coder-dev.sh`), pointed at a throwaway `--ssh-config-file`,
never a real `~/.ssh/config`.
### 1. Baseline: unchanged behavior with no flags
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG"
cat "$TEST_SSH_CONFIG"
```
Both `Host coder.*` and `Host *.coder` are written, unchanged from
before this fix (both server defaults are non-empty out of the box).
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.coder
# ------------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".
#
Host coder.*
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand .../coder-slim ... ssh --stdio --ssh-host-prefix coder. %h
Host *.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.coder !exec ".../coder-slim connect exists %h"
ProxyCommand .../coder-slim ... ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
### 2. Explicit empty `--ssh-host-prefix` omits the legacy block (the
core fix)
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --ssh-host-prefix ""
cat "$TEST_SSH_CONFIG"
```
`Host coder.*` is gone, only `Host *.coder` remains. The choice is now
also persisted (`# :ssh-host-prefix=`).
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.coder
# ------------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:
# :ssh-host-prefix=
#
Host *.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.coder !exec ".../coder-slim connect exists %h"
ProxyCommand .../coder-slim ... ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
### 3. Same, via the environment variable instead of the flag
```sh
CODER_CONFIGSSH_SSH_HOST_PREFIX="" ./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG"
grep -c "Host coder" "$TEST_SSH_CONFIG"
```
Confirms the fix isn't flag-only, `userSetOption` checks `ValueSource`,
set the same way for `ValueSourceFlag` and `ValueSourceEnv`.
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.coder
0
```
</details>
### 4. Explicit empty prefix combined with an explicit suffix
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --ssh-host-prefix "" --hostname-suffix mytest
cat "$TEST_SSH_CONFIG"
```
Only `Host *.mytest` is written. Both options are correctly recorded in
the persisted comment.
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.mytest
# ------------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:
# :ssh-host-prefix=
# :hostname-suffix=mytest
#
Host *.mytest
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.mytest !exec ".../coder-slim connect exists %h"
ProxyCommand .../coder-slim ... ssh --stdio --hostname-suffix mytest %h
# ------------END-CODER------------
```
</details>
### 5. The explicitly-empty choice survives `--use-previous-options`
with no flag repeated
This is the persistence half of the fix: confirms the "omit this block"
choice, once persisted, doesn't get lost on a later run that reuses
previous options without repeating `--ssh-host-prefix`. Before this fix,
this exact sequence would bring `Host coder.*` back.
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --ssh-host-prefix ""
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --use-previous-options
cat "$TEST_SSH_CONFIG"
```
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.coder
No changes to make.
# ------------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:
# :ssh-host-prefix=
#
Host *.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.coder !exec ".../coder-slim connect exists %h"
ProxyCommand .../coder-slim ... ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
The second command printed `No changes to make.`, and critically, `Host
coder.*` did **not** reappear even though that run passed no
`--ssh-host-prefix` flag at all, only `--use-previous-options`.
### 6. `--use-previous-options` still wins over this run's explicit
empty flag (unaffected by this fix)
Confirms this fix didn't change the pre-existing, intentional precedence
of `--use-previous-options`: a previously-saved *non-empty* value still
wins over an explicit empty flag passed on a later run.
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --ssh-host-prefix "custom-test."
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --use-previous-options --ssh-host-prefix ""
cat "$TEST_SSH_CONFIG"
```
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.coder
No changes to make.
# ------------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:
# :ssh-host-prefix=custom-test.
#
Host custom-test.*
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand .../coder-slim ... ssh --stdio --ssh-host-prefix custom-test. %h
Host *.coder
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
Match host *.coder !exec ".../coder-slim connect exists %h"
ProxyCommand .../coder-slim ... ssh --stdio --hostname-suffix coder %h
# ------------END-CODER------------
```
</details>
`Host custom-test.*` is preserved verbatim, `--use-previous-options`
correctly overrides the explicit empty flag when the saved value is
non-empty, the mirror image of step 5's explicit-empty saved value.
### 7. End-to-end sanity check with a real workspace
```sh
./scripts/coder-dev.sh config-ssh --yes --ssh-config-file "$TEST_SSH_CONFIG" --ssh-host-prefix "" --hostname-suffix mytest
ssh -F "$TEST_SSH_CONFIG" -o ConnectTimeout=15 myworkspace.mytest echo ok
```
<details>
<summary>Output</summary>
```text
Updated "/tmp/tmp.9Y7VIeuQoY"
You should now be able to ssh into your workspace.
For example, try running:
$ ssh myworkspace.mytest
ok
```
</details>
`ok` came back from a real, running workspace, confirming the
ProxyCommand and Match/exec wiring generated by the suffix-only config
actually establishes a working SSH session end-to-end, not just a
text-generation check.
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)
- Adds server-side and client-side validation for
CODER_CONFIGSSH_HOSTNAME_SUFFIX and CODER_SSH_CONFIG_OPTIONS.
- **Server-side breaking change:** invalid values for either of these will cause `coderd` to exit with an error.
- Client-side: `coder config-ssh` will exit with an error if it detects invalid config.
- Adds tests for the above
Local smoke-testing: ran `develop.sh --env-file <path to an env file
containing badness>`. Validated that server startup failed as expected.
> 🤖 Generated by Coder Agents with supervision from a human.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Cleans the last few instances of ExpectMatch that didn't use the new `(ctx, ...)` variant, then deletes the deprecated method and renames `ExpectMatchContext` to drop the `Context` suffix.
relates to #16828
Changes SSH config so that suffixes only match if Coder Connect is not running / available. This means that we will use the existing Coder Connect tunnel if it is available, rather than creating a new tunnel via `coder ssh --stdio`.
Wires up `config-ssh` command to use a hostname suffix if configured.
part of: #16828
e.g. `coder config-ssh --hostname-suffix spiketest` gives:
```
# ------------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=spiketest
#
Host coder.* *.spiketest
ConnectTimeout=0
StrictHostKeyChecking=no
UserKnownHostsFile=/dev/null
LogLevel ERROR
ProxyCommand /home/coder/repos/coder/build/coder_config_ssh --global-config /home/coder/.config/coderv2 ssh --stdio --ssh-host-prefix coder. --hostname-suffix spiketest %h
# ------------END-CODER------------
```
Adds `hostname-suffix` as a Config SSH option that we get from Coderd, and also accept via a CLI flag.
It doesn't actually do anything with this value --- that's for PRs up the stack, since we need the `coder ssh` command to be updated to understand the suffix first.
Rather than create a separate `Host` entry for every workspace,
configure a wildcard such as `coder.*` which can accomodate all of a
user's workspaces.
Depends on #16088.
Joins in fields like `username`, `avatar_url`, `organization_name`,
`template_name` to `workspaces` via a **view**.
The view must be maintained moving forward, but this prevents needing to
add RBAC permissions to fetch related workspace fields.
Currently, importing `codersdk` just to interact with the API requires
importing tailscale, which causes builds to fail unless manually using
our fork.
Drop "New" and "Builder" from the function names, in favor of the top-level resource created. This shortens tests and gives a nice syntax. Since everything is a builder, the prefix and suffix don't add much value and just make things harder to read.
I've also chosen to leave `Do()` as the function to insert into the database. Even though it's a builder pattern, I fear `.Build()` might be confusing with Workspace Builds. One other idea is `Insert()` but if we later add dbfake functions that update, this might be inconsistent.
I'd like to convert dbfake into a builder pattern to prevent a proliferation of XXXWithYYY methods. This is one step of the way by removing the Non-builder function.
* Detects the following pattern where the CLI is initialized with a client authenticated as the "first user":
client := coderdtest.New(t, ...)
[...]
user := coderdtest.CreateFirstUser(t, client)
[...]
clitest.SetupConfig(t, client, root)
* Updates documentation regarding role permissions on workspaces.
* Adds agenttest.New() helper function
* Makes sure agent gets closed on test cleanup
* Makes sure you don't forget to set session token
* Sets the agent and client logger automatically
* chore: add /v2 to import module path
go mod requires semantic versioning with versions greater than 1.x
This was a mechanical update by running:
```
go install github.com/marwan-at-work/mod/cmd/mod@latest
mod upgrade
```
Migrate generated files to import /v2
* Fix gen
Adds a flag --disable-password-auth that prevents the password login
endpoint from working unless the user has the "owner" (aka. site admin)
role.
Adds a subcommand `coder server create-admin-user` which creates a user
directly in the database with the "owner" role, the "admin" role in
every organization, and password auth. This is to avoid lock-out
situations where all accounts have the login type set to an identity
provider and nobody can login.
* chore: rename `AgentConn` to `WorkspaceAgentConn`
The codersdk was becoming bloated with consts for the workspace
agent that made no sense to a reader. `Tailnet*` is an example
of these consts.
* chore: remove `Get` prefix from *Client functions
* chore: remove `BypassRatelimits` option in `codersdk.Client`
It feels wrong to have this as a direct option because it's so infrequently
needed by API callers. It's better to directly modify headers in the two
places that we actually use it.
* Merge `appearance.go` and `buildinfo.go` into `deployment.go`
* Merge `experiments.go` and `features.go` into `deployment.go`
* Fix `make gen` referencing old type names
* Merge `error.go` into `client.go`
`codersdk.Response` lived in `error.go`, which is wrong.
* chore: refactor workspace agent functions into agentsdk
It was odd conflating the codersdk that clients should use
with functions that only the agent should use. This separates
them into two SDKs that are closely coupled, but separate.
* Merge `insights.go` into `deployment.go`
* Merge `organizationmember.go` into `organizations.go`
* Merge `quota.go` into `workspaces.go`
* Rename `sse.go` to `serversentevents.go`
* Rename `codersdk.WorkspaceAppHostResponse` to `codersdk.AppHostResponse`
* Format `.vscode/settings.json`
* Fix outdated naming in `api.ts`
* Fix app host response
* Fix unsupported type
* Fix imported type
This feature is used by the coder agent to exchange a new token. By
protecting the SessionToken via mutex we ensure there are no data races
when accessing it.
* fix: Refactor agent to consume API client
This simplifies a lot of code by creating an interface for
the codersdk client into the agent. It also moves agent
authentication code so instance identity will work between
restarts.
Fixes#3485 and #4082.
* Fix client reconnections
* feat: HA tailnet coordinator
* fixup! feat: HA tailnet coordinator
* fixup! feat: HA tailnet coordinator
* remove printlns
* close all connections on coordinator
* impelement high availability feature
* fixup! impelement high availability feature
* fixup! impelement high availability feature
* fixup! impelement high availability feature
* fixup! impelement high availability feature
* Add replicas
* Add DERP meshing to arbitrary addresses
* Move packages to highavailability folder
* Move coordinator to high availability package
* Add flags for HA
* Rename to replicasync
* Denest packages for replicas
* Add test for multiple replicas
* Fix coordination test
* Add HA to the helm chart
* Rename function pointer
* Add warnings for HA
* Add the ability to block endpoints
* Add flag to disable P2P connections
* Wow, I made the tests pass
* Add replicas endpoint
* Ensure close kills replica
* Update sql
* Add database latency to high availability
* Pipe TLS to DERP mesh
* Fix DERP mesh with TLS
* Add tests for TLS
* Fix replica sync TLS
* Fix RootCA for replica meshing
* Remove ID from replicasync
* Fix getting certificates for meshing
* Remove excessive locking
* Fix linting
* Store mesh key in the database
* Fix replica key for tests
* Fix types gen
* Fix unlocking unlocked
* Fix race in tests
* Update enterprise/derpmesh/derpmesh.go
Co-authored-by: Colin Adler <colin1adler@gmail.com>
* Rename to syncReplicas
* Reuse http client
* Delete old replicas on a CRON
* Fix race condition in connection tests
* Fix linting
* Fix nil type
* Move pubsub to in-memory for twenty test
* Add comment for configuration tweaking
* Fix leak with transport
* Fix close leak in derpmesh
* Fix race when creating server
* Remove handler update
* Skip test on Windows
* Fix DERP mesh test
* Wrap HTTP handler replacement in mutex
* Fix error message for relay
* Fix API handler for normal tests
* Fix speedtest
* Fix replica resend
* Fix derpmesh send
* Ping async
* Increase wait time of template version jobd
* Fix race when closing replica sync
* Add name to client
* Log the derpmap being used
* Don't connect if DERP is empty
* Improve agent coordinator logging
* Fix lock in coordinator
* Fix relay addr
* Fix race when updating durations
* Fix client publish race
* Run pubsub loop in a queue
* Store agent nodes in order
* Fix coordinator locking
* Check for closed pipe
Co-authored-by: Colin Adler <colin1adler@gmail.com>
* fix: Add coder user to docker group on installation
This makes for a simpler setup, and reduces the likelihood
a user runs into a strange issue.
* Add wgnet
* Add ping
* Add listening
* Finish refactor to make this work
* Add interface for swapping
* Fix conncache with interface
* chore: update gvisor
* fix tailscale types
* linting
* more linting
* Add coordinator
* Add coordinator tests
* Fix coordination
* It compiles!
* Move all connection negotiation in-memory
* Migrate coordinator to use net.conn
* Add closed func
* Fix close listener func
* Make reconnecting PTY work
* Fix reconnecting PTY
* Update CI to Go 1.19
* Add CLI flags for DERP mapping
* Fix Tailnet test
* Rename ConnCoordinator to TailnetCoordinator
* Remove print statement from workspace agent test
* Refactor wsconncache to use tailnet
* Remove STUN from unit tests
* Add migrate back to dump
* chore: Upgrade to Go 1.19
This is required as part of #3505.
* Fix reconnecting PTY tests
* fix: update wireguard-go to fix devtunnel
* fix migration numbers
* linting
* Return early for status if endpoints are empty
* Update cli/server.go
Co-authored-by: Colin Adler <colin1adler@gmail.com>
* Update cli/server.go
Co-authored-by: Colin Adler <colin1adler@gmail.com>
* Fix frontend entites
* Fix agent bicopy
* Fix race condition for the last node
* Fix down migration
* Fix connection RBAC
* Fix migration numbers
* Fix forwarding TCP to a local port
* Implement ping for tailnet
* Rename to ForceHTTP
* Add external derpmapping
* Expose DERP region names to the API
* Add global option to enable Tailscale networking for web
* Mark DERP flags hidden while testing
* Update DERP map on reconnect
* Add close func to workspace agents
* Fix race condition in upstream dependency
* Fix feature columns race condition
Co-authored-by: Colin Adler <colin1adler@gmail.com>
* fix: Change uses of t.Cleanup -> defer in test bodies
Mixing t.Cleanup and defer can lead to unexpected order of execution.
* fix: Ensure t.Cleanup is not aborted by require
* chore: Add helper annotations