mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.*
262 lines
8.7 KiB
Markdown
262 lines
8.7 KiB
Markdown
# Persistent Shared Workspaces with Service Accounts
|
|
|
|
> [!NOTE]
|
|
> This guide requires a
|
|
> [Premium license](https://coder.com/pricing#compare-plans) because service
|
|
> accounts are a Premium feature. For more details,
|
|
> [contact your account team](https://coder.com/contact).
|
|
|
|
This guide walks through setting up a long-lived workspace that is owned by a
|
|
service account and shared with a rotating set of users. Because no single
|
|
person owns the workspace, it persists across team changes and every user
|
|
authenticates as themselves.
|
|
|
|
This pattern is useful for any scenario where a workspace outlives the people
|
|
who use it:
|
|
|
|
- **On-call rotations** — Engineers share a workspace pre-loaded with runbooks,
|
|
dashboards, and monitoring tools. Access rotates with the shift schedule.
|
|
- **Shared staging or QA** — A team workspace hosts a persistent staging
|
|
environment. Testers and reviewers are added and removed as sprints change.
|
|
- **Pair programming** — A service-account-owned workspace gives two or more
|
|
developers a shared environment without either one owning (and accidentally
|
|
deleting) it.
|
|
- **Contractor onboarding** — An external team gets scoped access to a workspace
|
|
for the duration of an engagement, then access is revoked.
|
|
|
|
The steps below use an **on-call SRE workspace** as a running example, but the
|
|
same commands apply to any of the scenarios above. Substitute the usernames,
|
|
group names, and template to match your use case.
|
|
|
|
## Prerequisites
|
|
|
|
- A running Coder deployment (v2.32+) with workspace sharing enabled. Sharing
|
|
is on by default for OSS; Premium deployments may require
|
|
[admin configuration](../user-guides/shared-workspaces.md#policies).
|
|
- The [Coder CLI](../install/index.md) installed and authenticated.
|
|
- An account with the `Owner` or `User Admin` role.
|
|
- [OIDC authentication](../admin/users/oidc-auth/index.md) configured so
|
|
shared users log in with their corporate SSO identity. Configure
|
|
[refresh tokens](../admin/users/oidc-auth/refresh-tokens.md) to prevent
|
|
session timeouts during long work sessions.
|
|
- A [wildcard access URL](../admin/networking/wildcard-access-url.md) configured
|
|
(e.g. `*.coder.example.com`) so that shared users can access workspace apps
|
|
without a 404.
|
|
- (Recommended) [IdP Group Sync](../admin/users/idp-sync.md#group-sync)
|
|
configured if your identity provider manages group membership for the teams
|
|
that will share the workspace.
|
|
|
|
## 1. Create a service account
|
|
|
|
Create a dedicated service account that will own the shared workspace. Service
|
|
accounts are non-human accounts intended for automation and shared ownership.
|
|
Because no individual user owns the workspace, there are no personal
|
|
credentials to expose and the shared environment is not affected when any user
|
|
leaves the team or the organization.
|
|
|
|
```sh
|
|
# On-call example — substitute a name that fits your use case
|
|
coder users create \
|
|
--username oncall-sre \
|
|
--service-account
|
|
```
|
|
|
|
## 2. Generate an API token for the service account
|
|
|
|
Generate a long-lived API token so you can create and manage workspaces on
|
|
behalf of the service account:
|
|
|
|
```sh
|
|
coder tokens create \
|
|
--user oncall-sre \
|
|
--name oncall-automation \
|
|
--lifetime 8760h
|
|
```
|
|
|
|
Store this token securely (e.g. in a secrets manager like Vault or AWS Secrets
|
|
Manager).
|
|
|
|
> [!IMPORTANT]
|
|
> Never distribute this token to end users. The token is for workspace
|
|
> administration only. Shared users authenticate as themselves and reach the
|
|
> workspace through sharing.
|
|
|
|
## 3. Create the workspace
|
|
|
|
Authenticate as the service account and create the workspace:
|
|
|
|
```sh
|
|
export CODER_SESSION_TOKEN="<token-from-step-2>"
|
|
|
|
coder create oncall-sre/oncall-workspace \
|
|
--template your-oncall-template \
|
|
--use-parameter-defaults \
|
|
--yes
|
|
```
|
|
|
|
> [!TIP]
|
|
> Design a dedicated template for the workspace with the tools your team
|
|
> needs pre-installed (e.g. monitoring dashboards for on-call, test runners
|
|
> for QA). Set `subdomain = true` on workspace apps so that shared users can
|
|
> access web-based tools without a 404. See
|
|
> [Accessing workspace apps in shared workspaces](../user-guides/shared-workspaces.md#accessing-workspace-apps-in-shared-workspaces).
|
|
|
|
## 4. Share the workspace
|
|
|
|
Use `coder sharing share` to grant access to users who need the workspace:
|
|
|
|
```sh
|
|
coder sharing share oncall-sre/oncall-workspace --user alice
|
|
```
|
|
|
|
This gives `alice` the default `use` role, which allows connection via SSH and
|
|
workspace apps, starting and stopping the workspace, and viewing logs and stats.
|
|
|
|
To grant `admin` permissions (which includes all `use` permissions as well as renaming, updating, and inviting
|
|
others to join with the `use` role):
|
|
|
|
```sh
|
|
coder sharing share oncall-sre/oncall-workspace --user alice:admin
|
|
```
|
|
|
|
To share with multiple users at once:
|
|
|
|
```sh
|
|
coder sharing share oncall-sre/oncall-workspace --user alice:admin,bob
|
|
```
|
|
|
|
To share with an entire Coder group:
|
|
|
|
```sh
|
|
coder sharing share oncall-sre/oncall-workspace --group sre-oncall
|
|
```
|
|
|
|
> [!NOTE]
|
|
> Groups can be synced from your identity provider using
|
|
> [IdP Sync](../admin/users/idp-sync.md#group-sync). If your IdP already
|
|
> manages team membership, sharing with a group is the simplest approach.
|
|
|
|
## 5. Rotate access
|
|
|
|
When team membership changes, remove outgoing users and add incoming ones:
|
|
|
|
```sh
|
|
# Remove outgoing user
|
|
coder sharing remove oncall-sre/oncall-workspace --user alice
|
|
|
|
# Add incoming user
|
|
coder sharing share oncall-sre/oncall-workspace --user carol
|
|
```
|
|
|
|
> [!IMPORTANT]
|
|
> The workspace must be restarted for user removal to take effect.
|
|
|
|
Verify current sharing status at any time:
|
|
|
|
```sh
|
|
coder sharing status oncall-sre/oncall-workspace
|
|
```
|
|
|
|
## 6. Automate access changes (optional)
|
|
|
|
For use cases with frequent rotation (such as on-call shifts), you can integrate
|
|
the share/remove commands into external tooling like PagerDuty, Opsgenie, or a
|
|
cron job.
|
|
|
|
### Rotation script
|
|
|
|
```sh
|
|
#!/bin/bash
|
|
# rotate-access.sh
|
|
# Usage: ./rotate-access.sh <outgoing-user> <incoming-user>
|
|
|
|
WORKSPACE="oncall-sre/oncall-workspace"
|
|
OUTGOING="$1"
|
|
INCOMING="$2"
|
|
|
|
if [ -n "$OUTGOING" ]; then
|
|
echo "Removing access for $OUTGOING..."
|
|
coder sharing remove "$WORKSPACE" --user "$OUTGOING"
|
|
fi
|
|
|
|
echo "Granting access to $INCOMING..."
|
|
coder sharing share "$WORKSPACE" --user "$INCOMING"
|
|
|
|
echo "Restarting workspace to apply changes..."
|
|
coder restart "$WORKSPACE" --yes
|
|
|
|
echo "Current sharing status:"
|
|
coder sharing status "$WORKSPACE"
|
|
```
|
|
|
|
### Group-based rotation with IdP Sync
|
|
|
|
If your identity provider manages group membership (e.g. an `sre-oncall` group
|
|
in Okta or Azure AD), you can skip manual share/remove commands entirely:
|
|
|
|
1. Configure [Group Sync](../admin/users/idp-sync.md#group-sync) to
|
|
synchronize the group from your IdP to Coder.
|
|
|
|
1. Share the workspace with the group once:
|
|
|
|
```sh
|
|
coder sharing share oncall-sre/oncall-workspace --group sre-oncall
|
|
```
|
|
|
|
1. When your IdP rotates group membership, Coder group membership updates on
|
|
next login. All current members have access; removed members lose access
|
|
after a workspace restart.
|
|
|
|
## Finding shared workspaces
|
|
|
|
Shared users can find workspaces shared with them:
|
|
|
|
```sh
|
|
# List all shared workspaces you can access, including your own
|
|
coder list --search shared:true
|
|
|
|
# List workspaces shared with you
|
|
coder list --search shared_with_user:me
|
|
|
|
# List workspaces shared with a specific user
|
|
coder list --search shared_with_user:alice
|
|
|
|
# List workspaces shared with a specific group
|
|
coder list --search shared_with_group:sre-oncall
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Shared user sees 404 on workspace apps
|
|
|
|
Workspace apps using path-based routing block non-owners by default. Configure a
|
|
[wildcard access URL](../admin/networking/wildcard-access-url.md) and set
|
|
`subdomain = true` on the workspace app in your template.
|
|
|
|
### Removed user still has access
|
|
|
|
Access removal requires a workspace restart. Run
|
|
`coder restart <workspace>` after removing a user or group.
|
|
|
|
### Group sync not updating membership
|
|
|
|
Group membership changes in your IdP are not reflected until the user logs out
|
|
and back in. Group sync runs at login time, not on a polling schedule. Check the
|
|
Coder server logs with
|
|
`CODER_LOG_FILTER=".*userauth.*|.*groups returned.*"` for details. See
|
|
[Troubleshooting group sync](../admin/users/idp-sync.md#troubleshooting-grouproleorganization-sync)
|
|
for more information.
|
|
|
|
## Next steps
|
|
|
|
- [Shared Workspaces](../user-guides/shared-workspaces.md) — full reference
|
|
for workspace sharing features and UI
|
|
- [IdP Sync](../admin/users/idp-sync.md) — group, role, and organization
|
|
sync configuration
|
|
- [Configuring Okta](./configuring-okta.md) — Okta-specific OIDC setup with
|
|
custom claims and scopes
|
|
- [Security Best Practices](./best-practices/security-best-practices.md) —
|
|
deployment-wide security hardening
|
|
- [Sessions and Tokens](../admin/users/sessions-tokens.md) — API token
|
|
management and scoping
|