Deploy the Developer Portal
The API7 Developer Portal is made up of two official container images that work together:
| Image | Role | Port | Source repo |
|---|---|---|---|
api7/api7-ee-developer-portal | Portal API (backend) — the Go service that stores portal definitions, API products, developers, applications, subscriptions, and credentials. Shares the main api7ee PostgreSQL database with the rest of the control plane. | 4321 (HTTPS) | api7ee-3-control-plane |
api7/api7-ee-developer-portal-fe | Developer Portal frontend — the customer-facing Next.js web app that developers sign in to. Uses its own PostgreSQL for user sessions and developer accounts (via Better Auth + Drizzle), and talks to the Portal API using a per-portal token. | 3001 | api7ee-developer-portal |
One backend serves your entire organization; you can deploy multiple frontend instances — one per portal — if you want separate branding or audiences.
This guide shows how to deploy the full stack from scratch. In most production deployments on Kubernetes the backend is already installed as part of the main api7/api7ee3 Helm chart; in that case you only need to deploy the frontend and point it at the existing Portal API.
Prerequisites
- API7 Enterprise installed and activated with a portal-enabled license (trial licenses include portal support by default).
- Network connectivity from the frontend host to the Portal API endpoint (
4321/tcp). - Docker and Docker Compose, or a Kubernetes cluster with Helm, depending on which deployment method you choose.
Step 1: Create a portal and token in the Provider Portal
Before deploying the Developer Portal frontend, create a portal instance and generate a connection token from the API7 Dashboard.
- Log in to the API7 Dashboard.
- Navigate to Provider Portal > Add Portal.
- Provide a Name and the Public URL where the Developer Portal will be accessible (for example,
https://portal.example.com). - After creating the portal, open its Settings > Tokens tab.
- Click Generate New Token and save the token (format:
a7prt-xxxxxxxxxxxx). You will paste this into the frontend configuration in Step 2.
Each portal has a unique public URL. A single portal can back one frontend instance or multiple frontend replicas that share the same token and user-session database.
Step 2: Write the configuration files
The backend and frontend read their configuration from separate YAML files. Create a working directory and add both files.
mkdir api7-developer-portal && cd api7-developer-portal
mkdir -p backend_conf frontend_conf
Backend config — backend_conf/conf.yaml
The backend connects to the main api7ee database of your control plane. The DSN below matches the default credentials from the api7/api7ee3 Helm chart; adjust as needed.
server:
listen:
host: "0.0.0.0"
port: 4321
tls:
enabled: true
key_file: "" # Optional: /app/certs/tls.key for TLS termination
cert_file: "" # Optional: /app/certs/tls.crt for TLS termination
status:
disable: false
host: "127.0.0.1"
port: 4322
log:
level: warn
output: stderr
access_log: stdout
database:
dsn: "postgres://api7ee:YOUR_DB_PASSWORD@api7-postgresql:5432/api7ee"
max_open_conns: 30
max_idle_time: 30s
timeout: 5s
Frontend config — frontend_conf/config.yaml
The frontend points at the backend using the portal token you generated in Step 1 and keeps its own small PostgreSQL for user sessions.
portal:
# Portal API endpoint (the backend). Use the public or internal address as appropriate.
url: https://api7-developer-portal-backend:4321
# The token generated from Provider Portal in Step 1.
token: a7prt-xxxxxxxxxxxx
db:
# PostgreSQL connection string for the frontend's user-session database.
url: "postgres://portal:YOUR_PORTAL_DB_PASSWORD@portal-postgres:5432/portal"
auth:
# Generate a secure value: openssl rand -base64 32
secret: "REPLACE_WITH_SECURE_RANDOM_STRING"
app:
# The public URL where developers will access this portal.
baseURL: "https://portal.example.com"
trustedOrigins:
- "https://portal.example.com"
Replace auth.secret with a securely generated random value before running in any shared environment. Do not use the example value in production.
Step 3: Deploy
Choose the deployment method that matches your environment.
- Docker Compose
- Kubernetes
Docker Compose is the quickest way to run a self-contained Developer Portal stack for development or testing. The Compose file below brings up both images (backend and frontend) plus a dedicated PostgreSQL for the frontend's user sessions.
Create docker-compose.yaml in the same directory:
services:
api7-postgresql:
image: postgres:16
hostname: api7-postgresql
environment:
POSTGRES_USER: api7ee
POSTGRES_PASSWORD: YOUR_DB_PASSWORD
POSTGRES_DB: api7ee
healthcheck:
test: ["CMD", "pg_isready", "-U", "api7ee"]
interval: 5s
timeout: 5s
retries: 5
networks:
- portal
portal-postgres:
image: postgres:16
hostname: portal-postgres
environment:
POSTGRES_USER: portal
POSTGRES_PASSWORD: YOUR_PORTAL_DB_PASSWORD
POSTGRES_DB: portal
volumes:
- portal_postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "portal", "-d", "portal"]
interval: 5s
timeout: 5s
retries: 5
networks:
- portal
api7-developer-portal-backend:
image: api7/api7-ee-developer-portal:${API7_VERSION}
hostname: api7-developer-portal-backend
restart: always
volumes:
- ./backend_conf/conf.yaml:/usr/local/api7/conf/conf.yaml:ro
command:
- /usr/local/api7/api7-ee-developer-portal
- -c
- /usr/local/api7/conf/conf.yaml
ports:
- "4321:4321"
depends_on:
api7-postgresql:
condition: service_healthy
networks:
- portal
api7-developer-portal-frontend:
image: api7/api7-ee-developer-portal-fe:${API7_VERSION}
hostname: api7-developer-portal-frontend
restart: always
volumes:
- ./frontend_conf/config.yaml:/app/apps/site/config.yaml:ro
environment:
# Defaults to "1" (strict TLS verification).
# Only set to "0" in development if the backend uses a self-signed certificate.
NODE_TLS_REJECT_UNAUTHORIZED: "1"
ports:
- "3001:3001"
depends_on:
portal-postgres:
condition: service_healthy
api7-developer-portal-backend:
condition: service_started
networks:
- portal
networks:
portal:
driver: bridge
volumes:
portal_postgres_data:
Set the image version and start the stack:
export API7_VERSION=3.9.1 # pin to a specific release; see Supported Versions
docker compose up -d
Check that all four containers reach the healthy / Up state:
docker compose ps
This Compose file deploys its own PostgreSQL alongside the backend for self-containment. In a real deployment, the backend typically shares the main api7ee PostgreSQL that the rest of your control plane uses — point backend_conf/conf.yaml at that existing database and remove the api7-postgresql service from the Compose file.
On Kubernetes, the Portal API backend is deployed as part of the main api7/api7ee3 control plane chart when developer_portal.enable: true (the default). You normally only need to deploy the frontend separately. This tab shows both — enabling the backend in the CP chart, then deploying the frontend as its own workload.
Enable the backend in the control plane chart
In your control plane values file (for example, cp-values.yaml), ensure the Developer Portal backend is enabled and configured:
developer_portal:
replicaCount: 1
image:
repository: api7/api7-ee-developer-portal
tag: "3.9.1" # pin to your API7 Enterprise release
developer_portal_service:
type: ClusterIP
port: 4321
developer_portal_configuration:
enable: true
server:
listen:
host: "0.0.0.0"
port: 4321
tls:
enabled: true
status:
host: "127.0.0.1"
port: 4322
log:
level: warn
database:
dsn: "postgres://api7ee:YOUR_DB_PASSWORD@api7-postgresql:5432/api7ee"
Install or upgrade the control plane chart with these values:
helm upgrade --install api7ee3 api7/api7ee3 \
-f cp-values.yaml \
-n api7
The backend is now reachable inside the cluster at https://api7ee3-developer-portal:4321.
Deploy the frontend
The frontend does not ship with a dedicated Helm chart, so deploy it as a standard Kubernetes workload. The manifest below uses a ConfigMap to mount the config.yaml you wrote in Step 2, and a small StatefulSet-backed PostgreSQL for the frontend's own user-session database.
apiVersion: v1
kind: ConfigMap
metadata:
name: developer-portal-frontend-config
namespace: api7
data:
config.yaml: |
portal:
url: https://api7ee3-developer-portal:4321
token: a7prt-xxxxxxxxxxxx
db:
url: "postgres://portal:YOUR_PORTAL_DB_PASSWORD@portal-postgres:5432/portal"
auth:
secret: "REPLACE_WITH_SECURE_RANDOM_STRING"
app:
baseURL: "https://portal.example.com"
trustedOrigins:
- "https://portal.example.com"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: developer-portal-frontend
namespace: api7
spec:
replicas: 2
selector:
matchLabels:
app: developer-portal-frontend
template:
metadata:
labels:
app: developer-portal-frontend
spec:
containers:
- name: frontend
image: api7/api7-ee-developer-portal-fe:3.9.1 # pin to your release
ports:
- containerPort: 3001
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "1"
volumeMounts:
- name: config
mountPath: /app/apps/site/config.yaml
subPath: config.yaml
readOnly: true
volumes:
- name: config
configMap:
name: developer-portal-frontend-config
---
apiVersion: v1
kind: Service
metadata:
name: developer-portal-frontend
namespace: api7
spec:
selector:
app: developer-portal-frontend
ports:
- port: 80
targetPort: 3001
type: ClusterIP
Apply the manifest:
kubectl apply -f developer-portal-frontend.yaml
You will also need to create the frontend's PostgreSQL database (portal) and expose the frontend Service through an Ingress or LoadBalancer so that external developers can reach it at the public URL you set as app.baseURL.
Store the real auth.secret and PostgreSQL password in a Secret rather than embedding them in the ConfigMap. The manifest above inlines the values for brevity — adapt it to your secret-management practice before running in production.
Step 4: Verify the deployment
- Open the public URL you configured (
app.baseURL) in a browser, for example,https://portal.example.com. - Verify that the home page loads and the Sign Up button is visible.
- Create a test developer account to confirm authentication is functional.
- Navigate to API Hub to confirm the frontend can reach the Portal API. If API products have been published to this portal, they will appear here.
Deploy multiple portal instances
You can deploy multiple Developer Portal frontends against the same backend — each serving a different audience (for example, public developers, internal teams, or partners):
- In the Provider Portal, create an additional portal with a unique name and public URL.
- Generate a new token for that portal.
- Deploy another frontend instance (a new
Deploymenton Kubernetes or a separate Compose stack) using the new token and public URL in itsconfig.yaml.
API products are published to specific portals. An API product published to one portal is not visible on another unless you explicitly publish it there as well.
Next steps
- Configure the Developer Portal — set up authentication, public access, and other runtime settings.
- Customize the Developer Portal — apply your branding and extend the frontend.
- Manage API Products — publish APIs for developer consumption.