Humanitec Platform Orchestrator is the backend of an Internal Developer Platform. It standardizes how apps get config and infrastructure across environments. It keeps a live view of resources and exposes APIs so your portal tooling can show the right context. It is not a portal or a CI system. It complements tools like Backstage by handling orchestration behind the scenes.
This plugin brings Humanitec data into your Backstage catalog. On each service page you can see environments, workloads, and resources tied to a Humanitec app. A small backend in your Backstage instance proxies requests to the Humanitec API. There is a scaffolder module that adds actions to create Humanitec apps or validate inputs during templates. The goal is simple. Give engineers the status and context they need without leaving Backstage.Common use cases include showing what runs where across dev, staging, and production. Surfacing linked resources such as databases or ingress. Starting new services from templates that are wired to your standards in Humanitec. This setup pairs a familiar portal with a consistent platform backend. It reduces context switching and helps teams follow your golden paths at scale.
Installation Instructions
These instructions apply to self-hosted Backstage only. To use this plugin on Roadie, visit the docs.
Install the frontend package
yarn workspace app add @humanitec/backstage-plugin
Add the card to the entity page
Edit packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { Grid } from '@material-ui/core';
import { EntitySwitch } from '@backstage/plugin-catalog';
import { HumanitecCardComponent } from '@humanitec/backstage-plugin';
export const EntityPage = () => {
return (
<Grid container>
<Grid item md={6}>
<HumanitecCardComponent />
</Grid>
</Grid>
);
};
Only show the card when the entity has Humanitec annotations
Edit packages/app/src/components/catalog/EntityPage.tsx
import React from 'react';
import { Grid } from '@material-ui/core';
import { EntitySwitch } from '@backstage/plugin-catalog';
import { HumanitecCardComponent, hasHumanitecAnnotations } from '@humanitec/backstage-plugin';
export const EntityPage = () => {
return (
<Grid container>
<EntitySwitch>
<EntitySwitch.Case if={hasHumanitecAnnotations}>
<Grid item md={6}>
<HumanitecCardComponent />
</Grid>
</EntitySwitch.Case>
</EntitySwitch>
</Grid>
);
};
Add the scaffolder field extension to the frontend
This validates a Humanitec app id in templates.
Edit packages/app/src/App.tsx
import React from 'react';
import { FlatRoutes } from '@backstage/core-app-api';
import { Route } from 'react-router';
import { ScaffolderPage, ScaffolderFieldExtensions } from '@backstage/plugin-scaffolder';
import { ValidateHumanitecAppIDFieldExtension } from '@humanitec/backstage-plugin';
export const AppRoutes = () => (
<FlatRoutes>
<Route
path="/create"
element={
<ScaffolderPage>
<ScaffolderFieldExtensions>
<ValidateHumanitecAppIDFieldExtension />
</ScaffolderFieldExtensions>
</ScaffolderPage>
}
/>
</FlatRoutes>
);
Configure the app
Edit app-config.yaml
humanitec:
orgId: my-humanitec-organization
token: ${HUMANITEC_TOKEN}
Provide HUMANITEC_TOKEN without the word Bearer.
Example runtime
HUMANITEC_TOKEN=your_token_value yarn dev
Add entity annotations so the card can load data
Create a catalog file or update an existing one
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: name-of-application-workload
description: Humanitec Workload Environments
annotations:
humanitec.com/orgId: my-humanitec-organization
humanitec.com/appId: my-humanitec-application
spec:
type: service
owner: [email protected]
lifecycle: experimental
Install the backend package new backend system
yarn workspace backend add @humanitec/backstage-plugin-backend
Edit packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// Humanitec backend plugin
backend.add(import('@humanitec/backstage-plugin-backend'));
backend.start();
Install the scaffolder backend module new backend system
yarn workspace backend add @humanitec/backstage-plugin-scaffolder-backend-module
Edit packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// Humanitec backend plugin
backend.add(import('@humanitec/backstage-plugin-backend'));
// Humanitec scaffolder actions
backend.add(import('@humanitec/backstage-plugin-scaffolder-backend-module'));
backend.start();
Use the scaffolder actions in a template
Add steps to a template yaml
steps:
- name: Create Humanitec App
id: humanitec-create-app
action: humanitec:create-app
input:
setupFile: humanitec-apps.yaml
appId: ${{ parameters.componentName }}
- name: Fetch configured humanitec.orgId
id: humanitec-environment
action: humanitec:get-environment
The setupFile can be omitted to use the default humanitec-app.yaml. The file describes the initial app, environments, modules, and automations.
Example humanitec app file
---
id: ${{values.componentName | dump}}
name: ${{values.componentName | dump}}
environments:
development:
metadata:
env_id: development
name: Initial deployment
modules:
${{values.componentName | dump}}:
externals:
http:
type: dns
profile: humanitec/default-module
spec:
containers:
${{values.componentName | dump}}:
id: ${{values.componentName}}
image: ${{values.registryUrl}}/${{values.componentName}}:dummy
resources:
limits:
cpu: 0.25
memory: 256Mi
requests:
cpu: 0.025
memory: 64Mi
variables: {}
volume_mounts: {}
files: {}
ingress:
rules:
externals.http:
http:
"/":
port: 9898
type: prefix
automations:
development:
- active: true
exclude_images_filter: false
images_filter: []
type: update
update_to: branch
Install the backend package legacy backend system
If your backend uses the legacy system, add the package
yarn workspace backend add @humanitec/backstage-plugin-backend
Create packages/backend/src/plugins/humanitec.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@humanitec/backstage-plugin-backend';
export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
});
}
Wire it in packages/backend/src/index.ts
import { createServiceBuilder } from '@backstage/backend-common';
import { loadBackendConfig } from '@backstage/backend-common';
import { createEnv, useHotMemoize } from './createEnv';
import humanitec from './plugins/humanitec';
async function main() {
const config = await loadBackendConfig();
const env = createEnv('humanitec', config);
const apiRouter = await humanitec(env);
const service = createServiceBuilder(module)
.setPort(7007)
.addRouter('/api/humanitec', apiRouter);
await service.start();
}
main().catch(err => {
process.exit(1);
});
Install the scaffolder backend module legacy backend system
Add the package
yarn workspace backend add @humanitec/backstage-plugin-scaffolder-backend-module
Create packages/backend/src/plugins/humanitecScaffolder.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@humanitec/backstage-plugin-scaffolder-backend-module';
export default async function createPlugin(env: PluginEnvironment): Promise<Router> {
return await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
tokenManager: env.tokenManager,
});
}
Wire it in packages/backend/src/index.ts
import humanitecScaffolder from './plugins/humanitecScaffolder';
async function main() {
// previous setup
const scaffolderRouter = await humanitecScaffolder(env);
const service = createServiceBuilder(module)
.setPort(7007)
.addRouter('/api/humanitec-scaffolder', scaffolderRouter);
await service.start();
}
Keep HUMANITEC_TOKEN set when you run the app. Configure humanitec orgId and token in app-config.yaml. Add humanitec.com annotations to the entities you want to show.
Things to Know
If the installation instructions were followed correctly, you should see the following changes:
- Entity page now renders HumanitecCardComponent
- Scaffolder page now has ValidateHumanitecAppIDFieldExtension
- Backend exposes Humanitec routes for the frontend
- Scaffolder backend module adds humanitec actions you can call from templates
Useful Links
Changelog
This changelog is produced from commits made to the Humanitec Platform Orchestratorr plugin since 10 months ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.
Breaking changes
- No breaking changes noted
Features
- Upgrade to Backstage 1.34.0 #75 merged 10 months ago
Security
- Update tar fs to 2.1.4 to address a security alert #107 merged 4 days ago
- Pull in fixes for several security alerts #104 merged 2 months ago
- Update multer and tar fs to resolve security alerts #99 merged 3 months ago
- Fix remaining security alerts #90 merged 6 months ago
- Upgrade tar fs to address a security alert #87 merged 6 months ago
- Bump xml crypto to 6.0.1 to address critical CVEs #86 merged 7 months ago
- Bump Babel runtime corejs3 to 7.26.10 with a security fix for regex replacement #84 merged 7 months ago
- Bump Babel runtime to 7.26.10 with the same security fix #85 merged 7 months ago
- Bump jsonpath plus to 10.3.0 to fix an RCE risk #83 merged 7 months ago
- Fix elliptic and koa versions to remove vulnerabilities #80 merged 7 months ago
- Bump jsonpath plus to 10.2.0 with safer eval #76 merged 8 months ago
Dependencies
- Refresh yarn lock including tmp #105 merged 2 months ago
- Bump Backstage permission backend plugin to 0.6.0 #92 merged 5 months ago
- Bump dompurify and esbuild #89 merged 6 months ago
- Bump axios to 1.8.3 #82 merged 7 months ago
CI
- Fix yarn release calls in the publish workflow #100 merged 3 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.