VeeCode Kong Service Manager is a Backstage plugin that connects your catalog to Kong Gateway. It lets you view a service, see its routes, and manage plugins from one place. You can point it at more than one Kong instance and switch between them inside Backstage.
Inside an entity page you can inspect the service that the component references. You can list every route tied to it. You can create, edit, or delete routes when you need to change traffic. You can install, update, or disable plugins on the service or on a single route. The plugin keeps the work in Backstage so you do not jump between tools.
It can also surface an OpenAPI spec linked to the component. You see which plugins are associated with that service. You can enable or remove them from the spec with a pull request to your repo. This helps you review changes before they land in Kong.
Common use cases include rolling out auth across services, setting rate limits during a launch, tuning logging or analytics, and auditing what is installed today. Teams use the permissions in the plugin to control who can read, change, or delete routes and plugins. If you already run Kong and Backstage, this gives you a simple control plane inside your portal.
Installation Instructions
These instructions apply to self-hosted Backstage only.
Install the frontend package
If you use Yarn 3
yarn workspace app add @veecode-platform/plugin-kong-service-manager
If you use another Yarn version
yarn add --cwd packages/app @veecode-platform/plugin-kong-service-manager
Wire the frontend into your Backstage app
Edit packages app src components catalog EntityPage.tsx
import React from 'react';
import { EntityLayout } from '@backstage/plugin-catalog';
import { EntitySwitch, isKind } from '@backstage/plugin-catalog';
import { EntityAboutCard } from '@backstage/plugin-catalog';
import { Content } from '@backstage/core-components';
// Import the Kong Service Manager components
import {
KongServiceManagerContent,
isKongServiceManagerAvailable,
} from '@veecode-platform/plugin-kong-service-manager';
const overviewContent = (
<Content>
<EntityAboutCard variant="gridItem" />
</Content>
);
const serviceEntityPage = (
<EntityLayout>
<EntityLayout.Route path="/" title="Overview">
{overviewContent}
</EntityLayout.Route>
<EntityLayout.Route path="/ci-cd" title="CI/CD">
{/* your CI CD content here */}
</EntityLayout.Route>
{/* Add the Kong route */}
<EntityLayout.Route
if={isKongServiceManagerAvailable}
path="/kong-service-manager"
title="Kong"
>
<KongServiceManagerContent />
</EntityLayout.Route>
</EntityLayout>
);
export const EntityPage = () => (
<EntitySwitch>
<EntitySwitch.Case if={isKind('component')} children={serviceEntityPage} />
{/* other cases */}
</EntitySwitch>
);
You can add the route to any entity page that makes sense for your portal. The example above adds it to the Service entity page
Configure Kong instances in app config
Add your Kong instances to app-config.yaml
Example for Kong Enterprise with admin token
kong:
instances:
- id: kong-instance01
apiBaseUrl: ${KONG_HOST}
workspace: ${KONG_WORKSPACE}
auth:
kongAdmin: ${KONG_ADMIN_TOKEN}
Example for Kong Community with a custom header
kong:
instances:
- id: kong-instance01
apiBaseUrl: ${KONG_HOST}
auth:
custom:
header: ${KONG_HEADER}
value: ${KONG_AUTH}
You can set these variables in your environment or in app-config.local.yaml as needed
Add catalog annotations to your component
Add the annotations to the entity that represents the service you want to manage. Only one service per entity
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: component-a
description: Example service
annotations:
kong-manager/service-name: nameservice_test_A01
kong-manager/instance: kongInstance1,kongInstance2
kong-manager/spec: openapi-swagger.yaml
spec:
type: service
owner: team-a
lifecycle: production
kong manager instance accepts a comma separated list without spaces. Every instance listed here must exist in app config
Install the backend plugin old backend system
Add the backend package
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-backend
Create a router module at packages backend src plugins kongServiceManager.ts
import { Router } from 'express';
import { PluginEnvironment } from '../types';
import { createRouter } from '@veecode-platform/plugin-kong-service-manager-backend';
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
// Many plugins accept more options. Start minimal and pass what you have
const router = await createRouter({
logger: env.logger,
config: env.config,
discovery: env.discovery,
permissions: env.permissions,
httpAuth: env.httpAuth,
});
return router;
}
Wire the router in packages backend src index.ts
import { createEnv } from './createEnv';
import kongServiceManager from './plugins/kongServiceManager';
async function main() {
const env = await createEnv('backend');
const apiRouter = Router();
// other plugin routers
apiRouter.use(
'/kong-service-manager',
await kongServiceManager(env),
);
env.serve(apiRouter);
}
main().catch(err => {
console.error(err);
process.exit(1);
});
If your backend uses a different env helper pattern adapt the import of env fields logger config discovery permissions httpAuth to your setup
Install the backend plugin new backend system
Add the backend package
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-backend
Register the backend module in packages backend src index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// Register other modules
backend.add(import('@backstage/plugin-app-backend'));
backend.add(import('@backstage/plugin-catalog-backend'));
// Register Kong Service Manager backend module
backend.add(import('@veecode-platform/plugin-kong-service-manager-backend'));
backend.start();
This uses the new backend module registration style. The module mounts its routes under the default path it provides
Set up permissions
Grant the plugin permissions in your backend. Start permissive then tighten later
Install the common package to access the permission constants if needed
yarn add --cwd packages/backend @veecode-platform/plugin-kong-service-manager-common
Old backend system example using a static policy
packages backend src plugins permission.ts
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { createStaticPermissionPolicy } from '@backstage/plugin-permission-node';
import {
kongServiceReadPermission,
kongReadAvailablePluginsPermission,
kongRoutesReadPermission,
kongApplyPluginToServicePermission,
kongUpdateServicePluginPermission,
kongDisableServicePluginPermission,
kongRouteCreatePermission,
kongUpdateRoutePermission,
kongRouteDeletePermission,
kongApplyPluginToRoutePermission,
kongUpdateRoutePluginPermission,
kongDisableRoutePluginPermission,
kongReadSpecsPermission,
kongUpdateSpecPermission,
kongAIPluginsPermission,
kongAuthPluginsPermission,
kongSecurityPluginsPermission,
kongTrafficPluginsPermission,
kongServerlessPluginsPermission,
kongTransformPluginsPermission,
kongLoggingPluginsPermission,
kongAnalyticsPluginsPermission,
} from '@veecode-platform/plugin-kong-service-manager-common';
export const permissionPolicy = createStaticPermissionPolicy({
decisions: [
{ permission: kongServiceReadPermission, result: AuthorizeResult.ALLOW },
{ permission: kongReadAvailablePluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongRoutesReadPermission, result: AuthorizeResult.ALLOW },
{ permission: kongApplyPluginToServicePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateServicePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongDisableServicePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongRouteCreatePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateRoutePermission, result: AuthorizeResult.ALLOW },
{ permission: kongRouteDeletePermission, result: AuthorizeResult.ALLOW },
{ permission: kongApplyPluginToRoutePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateRoutePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongDisableRoutePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongReadSpecsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateSpecPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAIPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAuthPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongSecurityPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongTrafficPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongServerlessPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongTransformPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongLoggingPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAnalyticsPluginsPermission, result: AuthorizeResult.ALLOW },
],
});
Wire the policy into your permission backend as you usually do
New backend system example
Create a module file packages backend src modules permissionPolicy.ts
import { coreServices, createBackendModule } from '@backstage/backend-plugin-api';
import { AuthorizeResult } from '@backstage/plugin-permission-common';
import { createStaticPermissionPolicy } from '@backstage/plugin-permission-node';
import {
kongServiceReadPermission,
kongReadAvailablePluginsPermission,
kongRoutesReadPermission,
kongApplyPluginToServicePermission,
kongUpdateServicePluginPermission,
kongDisableServicePluginPermission,
kongRouteCreatePermission,
kongUpdateRoutePermission,
kongRouteDeletePermission,
kongApplyPluginToRoutePermission,
kongUpdateRoutePluginPermission,
kongDisableRoutePluginPermission,
kongReadSpecsPermission,
kongUpdateSpecPermission,
kongAIPluginsPermission,
kongAuthPluginsPermission,
kongSecurityPluginsPermission,
kongTrafficPluginsPermission,
kongServerlessPluginsPermission,
kongTransformPluginsPermission,
kongLoggingPluginsPermission,
kongAnalyticsPluginsPermission,
} from '@veecode-platform/plugin-kong-service-manager-common';
export default createBackendModule({
pluginId: 'permission',
moduleId: 'kong-service-manager-policy',
register(env) {
env.registerInit({
deps: { permissions: coreServices.permissions },
async init({ permissions }) {
const policy = createStaticPermissionPolicy({
decisions: [
{ permission: kongServiceReadPermission, result: AuthorizeResult.ALLOW },
{ permission: kongReadAvailablePluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongRoutesReadPermission, result: AuthorizeResult.ALLOW },
{ permission: kongApplyPluginToServicePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateServicePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongDisableServicePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongRouteCreatePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateRoutePermission, result: AuthorizeResult.ALLOW },
{ permission: kongRouteDeletePermission, result: AuthorizeResult.ALLOW },
{ permission: kongApplyPluginToRoutePermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateRoutePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongDisableRoutePluginPermission, result: AuthorizeResult.ALLOW },
{ permission: kongReadSpecsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongUpdateSpecPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAIPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAuthPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongSecurityPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongTrafficPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongServerlessPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongTransformPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongLoggingPluginsPermission, result: AuthorizeResult.ALLOW },
{ permission: kongAnalyticsPluginsPermission, result: AuthorizeResult.ALLOW },
],
});
await permissions.setPolicy(policy);
},
});
},
});
Register the module in packages backend src index.ts
import { createBackend } from '@backstage/backend-defaults';
const backend = createBackend();
// other modules
backend.add(import('@backstage/plugin-permission-backend'));
// register the policy module
backend.add(import('./modules/permissionPolicy'));
backend.start();
Adjust the policy later to match your access model
Configure git provider for Specs feature
Add an integration for your git provider. Below are minimal examples
GitHub example
integrations:
github:
- host: github.com
token: ${GITHUB_TOKEN}
auth:
environment: development
providers:
github:
development:
clientId: ${GITHUB_CLIENT_ID}
clientSecret: ${GITHUB_CLIENT_SECRET}
GitLab example
integrations:
gitlab:
- host: gitlab.com
token: ${GITLAB_TOKEN}
auth:
environment: development
providers:
gitlab:
development:
clientId: ${GITLAB_CLIENT_ID}
clientSecret: ${GITLAB_CLIENT_SECRET}
Environment variables reference
Set these to match your Kong setup
export KONG_HOST="https://kong.example.com"
export KONG_WORKSPACE="default"
export KONG_ADMIN_TOKEN="your_admin_token"
# For community with custom header
export KONG_HEADER="Authorization"
export KONG_AUTH="Basic your_token_or_key"
Quick recap
- Install the frontend package
- Add the route and content to EntityPage
- Add kong instances in app config
- Add the catalog annotations on the service entity
- Install and wire the backend plugin for your backend style
- Add a permission policy that allows the plugin actions
- Add git provider integration if you want to use the Specs features
Changelog
This changelog is produced from commits made to the VeeCode Kong Service Manager plugin since 8 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
None
Features
- Add Tenant Explorer plugin with overview and table components merged 3 months ago
- Add alpha exports to Kong Service Manager merged 3 months ago
Improvements
- Refactor and enhance plugin management components merged 3 months ago
- Improve re render behavior in a component merged 8 months ago
Bug fixes
- Fix validate issue merged 8 months ago
- Fix bug merged 8 months ago
Documentation
- Update README merged 8 months ago
Maintenance
- Reorder dependencies in package.json files and update yarn.lock merged 3 months ago
- Refactor code structure for readability and maintainability merged 3 months ago
- Refactor components for readability and maintainability merged 3 months ago
- Style updates merged 8 months ago
- Style updates merged 8 months ago
- Release chores merged 3 months ago
- Release chores merged 3 months ago
- Release chores merged 8 months ago
- Release chores merged 8 months ago
- Release chores merged 8 months ago
- Release chores merged 8 months ago
- Release chores merged 8 months ago
- Release chores merged 8 months ago
Set up Backstage in minutes with Roadie
Focus on using Backstage, rather than building and maintaining it.