Scaffold and implement a backend dynamic plugin for Red Hat Developer Hub (RHDH).
- New backend API plugins
- Backend modules for existing plugins (e.g.,
catalog-backend-module-*) - Scaffolder actions and templates
- Catalog processors and providers
- Authentication modules
- Any server-side functionality for RHDH
Not for frontend plugins — use the frontend command instead.
- Determine RHDH version
- Scaffold app and plugin
- Implement plugin logic
- Export and package (see
exportcommand) - Configure for RHDH
Consult ../../rhdh/references/versions.md for the compatibility matrix. Ask the user which RHDH version they target if not specified.
Run the scaffold script from the directory where the app should be created:
python scripts/scaffold.py \
--type backend \
--rhdh-version 1.9 \
--plugin-id my-pluginRun python scripts/scaffold.py --help for all options.
Note: The Backstage app exists only to provide the correct CLI version for plugin generation. All development and testing happens in the plugin directory.
The generated plugin structure:
plugins/<plugin-id>-backend/
├── src/
│ ├── index.ts # Main entry point
│ ├── plugin.ts # Plugin definition (new backend system)
│ └── service/
│ └── router.ts # Express router
├── package.json
└── README.md
Backend plugins must use the new backend system for dynamic plugin compatibility. Export a default using createBackendPlugin() or createBackendModule().
import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import { createRouter } from './service/router';
export const myPlugin = createBackendPlugin({
pluginId: 'my-plugin',
register(env) {
env.registerInit({
deps: {
httpRouter: coreServices.httpRouter,
logger: coreServices.logger,
config: coreServices.rootConfig,
},
async init({ httpRouter, logger, config }) {
httpRouter.use(
await createRouter({
logger,
config,
}),
);
httpRouter.addAuthPolicy({
path: '/health',
allow: 'unauthenticated',
});
},
});
},
});
export default myPlugin;export { default } from './plugin';Build and verify:
cd plugins/<plugin-id>-backend
yarn buildUse the export command for the full pipeline. Quick version:
cd plugins/<plugin-id>-backend
npx @red-hat-developer-hub/cli@latest plugin export
npx @red-hat-developer-hub/cli@latest plugin package \
--tag quay.io/<namespace>/<plugin-name>:v0.1.0
podman push quay.io/<namespace>/<plugin-name>:v0.1.0For advanced options (dependency handling, multi-plugin bundles, tgz/npm), use the export command reference.
Add to dynamic-plugins.yaml:
plugins:
- package: oci://quay.io/<namespace>/<plugin-name>:v0.1.0!<plugin-id>-backend-dynamic
disabled: false
pluginConfig:
myPlugin:
someOption: valueFor local testing, copy dist-dynamic to RHDH's dynamic-plugins-root:
cp -r dist-dynamic /path/to/rhdh/dynamic-plugins-root/<plugin-id>-backend-dynamicWindows: Use
xcopy /E /Iorrobocopy /Einstead ofcp -r.
See examples/dynamic-plugins.yaml for complete configuration examples.
- Verify plugin uses new backend system (
createBackendPlugin) - Check plugin is exported as default export
- Ensure version compatibility with target RHDH
- Use
--shared-packageto exclude problematic shared deps - Use
--embed-packageto bundle required deps
- Run
yarn tscto check TypeScript errors before export - Ensure all
@backstage/*versions match target RHDH