Create and manage Coder workspaces from Backstage.
- Users link their Coder accounts with Backstage via tokens
- Associate Coder workspaces with catalog items in Backstage
- Workspace list component for viewing and managing workspaces
This assumes you already have a Coder deployment running.
Replace https://coder.example.com with your Coder deployment access URL. This also assumes
you have a template that has a parameter for a git repository URL (e.g. git_repo_url) that auto-clones
the repository or uses envbuilder to build
the Dev Container.
-
If you have a standalone Backstage app (you didn't clone this repo), then do
yarn --cwd packages/app add @coder/backstage-plugin-coder
-
Add the proxy key to your
app-config.yaml:proxy: endpoints: '/coder': # Replace with your Coder deployment access URL (add a trailing slash) target: 'https://coder.example.com/' changeOrigin: true # Add methods based on what API calls you need allowedMethods: ['GET', 'POST'] allowedHeaders: ['Authorization', 'Coder-Session-Token'] headers: X-Custom-Source: backstage
-
Add the
CoderProviderto the application:// packages/app/src/App.tsx import { type CoderAppConfig, CoderProvider, } from '@coder/backstage-plugin-coder'; const appConfig: CoderAppConfig = { deployment: { accessUrl: 'https://coder.example.com', }, // Set the default template (and parameters) for // catalog items. Individual properties can be overridden // by a repo's catalog-info.yaml file workspaces: { defaultTemplateName: 'devcontainers', defaultMode: 'manual', // This property defines which parameters in your Coder // workspace templates are used to store repository links repoUrlParamKeys: ['custom_repo', 'repo_url'], params: { repo: 'custom', region: 'eu-helsinki', }, }, }; // ... export default app.createRoot( <CoderProvider appConfig={appConfig}> <AlertDisplay /> <OAuthRequestDialog /> <AppRouter> <Root>{routes}</Root> </AppRouter> </CoderProvider>, );
Note: You can also wrap a single page or component with
CoderProviderif you only need Coder in a specific part of your app. See our API reference (particularly the section on theCoderProvidercomponent) for more details. -
Add the
CoderWorkspacesCardcard to the entity page in your app:// packages/app/src/components/catalog/EntityPage.tsx import { CoderWorkspacesCard } from '@coder/backstage-plugin-coder'; // We recommend placing the component inside of overviewContent const overviewContent = ( <Grid container spacing={3} alignItems="stretch"> {entityWarningContent} <Grid item md={6}> <EntityAboutCard variant="gridItem" /> </Grid> {/* Coder component should go inside Grid to help it work with MUI layouts */} <Grid item md={6} xs={12}> <CoderWorkspacesCard readEntityData /> </Grid> {/* Other elements for overviewContent go here */} </Grid> );
The Coder plugin uses Backstage's native OAuth2 system for secure authentication. This requires both backend and frontend configuration.
[!NOTE] > New Backend System Required: This setup uses Backstage's New Backend System and the
@coder/plugin-auth-backend-module-coder-providermodule.
Coder is registered as an auth provider. You can use it for:
Resource Access (Default) - Users authenticate to Coder via button in workspace card for API access.
Sign-In Provider (Optional) - Users can sign in to Backstage with Coder for seamless workspace access.
Tip
Resource Access = backend + frontend setup below. Sign-In Provider = Resource Access + signIn configuration (see Optional section).
-
Install the auth backend module:
yarn workspace backend add @coder/plugin-auth-backend-module-coder-provider
-
Register the module in
packages/backend/src/index.ts:backend.add(import('@coder/plugin-auth-backend-module-coder-provider'));
-
Create an OAuth2 application in Coder:
- Navigate to Deployment Settings → OAuth2 Applications in your Coder deployment
- Create a new application
- Set the callback URL to:
https://your-backstage-instance.com/api/auth/coder/handler/frame - For local development:
http://localhost:7007/api/auth/coder/handler/frame - Save the client ID and client secret
-
Configure OAuth credentials in
app-config.yaml(use environment variables):auth: providers: coder: development: clientId: ${CODER_OAUTH_CLIENT_ID} clientSecret: ${CODER_OAUTH_CLIENT_SECRET} deploymentUrl: ${CODER_DEPLOYMENT_URL}
For complete backend setup details, see @coder/plugin-auth-backend-module-coder-provider README.
Register the Coder auth API in packages/app/src/apis.ts:
import { OAuth2 } from '@backstage/core-app-api';
import { coderAuthApiRef } from '@coder/backstage-plugin-coder';
import {
discoveryApiRef,
oauthRequestApiRef,
configApiRef,
createApiFactory,
} from '@backstage/core-plugin-api';
export const apis: AnyApiFactory[] = [
// ... other APIs
createApiFactory({
api: coderAuthApiRef,
deps: {
discoveryApi: discoveryApiRef,
oauthRequestApi: oauthRequestApiRef,
configApi: configApiRef,
},
factory: ({ discoveryApi, oauthRequestApi, configApi }) =>
OAuth2.create({
discoveryApi,
oauthRequestApi,
provider: {
id: 'coder',
title: 'Coder',
icon: () => null,
},
environment: configApi.getOptionalString('auth.environment'),
defaultScopes: [],
}),
}),
];To enable Coder as a Backstage sign-in provider (users can sign in to Backstage with Coder):
-
Add sign-in resolver to your existing
auth.providers.coderconfiguration inapp-config.yaml:auth: providers: coder: development: # ... OAuth credentials above signIn: resolvers: - resolver: usernameMatchingUserEntityName
-
Configure SignInPage in
packages/app/src/App.tsx:import { coderAuthApiRef } from '@coder/backstage-plugin-coder'; import { SignInPage } from '@backstage/core-components'; const app = createApp({ components: { SignInPage: props => ( <SignInPage {...props} providers={[ { id: 'coder-auth-provider', title: 'Coder', message: 'Sign in using Coder', apiRef: coderAuthApiRef, }, // ... other providers ]} /> ), }, });
-
Add to User Settings (shows connected providers):
import { CoderProviderSettings } from '@coder/backstage-plugin-coder'; import { UserSettingsPage } from '@backstage/plugin-user-settings'; <Route path="/settings" element={<UserSettingsPage providerSettings={<CoderProviderSettings />} />} />;
- Resource Access: Click "Sign in with Coder OAuth" in workspace card → OAuth popup → token stored
- Sign-In Provider: Sign in via Backstage login page → token automatically available
Both support managing connections in Settings → Authentication Providers. Token persistence and refresh handled by Backstage's OAuth2 helper.
In addition to the above, you can define additional properties on your specific repo's catalog-info.yaml file.
Example:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: python-project
spec:
type: other
lifecycle: unknown
owner: pms
# Properties for the Coder plugin are placed here
coder:
templateName: 'devcontainers'
mode: 'auto'
params:
repo: 'custom'
region: 'us-pittsburgh'You can find more information about what properties are available (and how they're applied) in our catalog-info.yaml file documentation.
This plugin is in active development. The following features are planned:
- OAuth2 support (vs. token auth) for linking Coder accounts
- Example component using the Coder API to make authenticated requests on behalf of the user
- Add support for only rendering component if
catalog-info.yamlindicates the item is compatible with Coder - OAuth support (vs. token auth) for linking Coder accounts
- "Open in Coder" button/card component for catalog items
- Example creating workspaces with Backstage Scaffolder
- Example dedicated "Coder" page in Backstage
This plugin is part of the Backstage community. We welcome contributions!

