On-Premises Installation
Plan production resources and install the AISIX Enterprise control plane in your infrastructure with Docker Compose, Helm, or an offline package.
Applies to:AISIX AI Gateway 1.4.0
Deployments:DockerKubernetesRoles:Platform engineerSecurity engineerTime:45 minutesImpact:No restart, no traffic change
Install the AISIX Enterprise control plane in infrastructure you operate using Docker Compose, Helm, or an offline package. This guide helps you choose an installation method, configure the control-plane endpoints, and verify a persistent environment.
The installation provides the same AISIX Enterprise control-plane workflows as Hybrid Cloud, including resource management, gateway certificate issuance, usage reporting, and budget enforcement. The control-plane services and data remain in your infrastructure, including in a fully air-gapped environment.
For a local evaluation that continues through creating gateway resources and sending a first AI request, use the AISIX Enterprise Quickstart instead.
This installs the control plane, not the gateway
This page installs the AISIX Enterprise control plane — cp-api, dp-manager, the dashboard, and a database — through the api7/aisix-cp Helm chart or the Compose and offline equivalents. It does not install the AISIX gateway that serves AI traffic (the data plane), which is a separate chart, api7/aisix. Once the control plane is up, install the gateway by following Deploy AISIX Gateways on Kubernetes or Connect an AISIX Gateway.
Licensing
Before deploying the AISIX Enterprise control plane in production, contact API7 or email support@api7.ai.
Plan the Installation
Choose an installation method based on the target infrastructure and its network access:
| Installation method | Target | Requirements |
|---|---|---|
| Docker Compose | Internet-connected host | Docker with Docker Compose V2, cURL, tar, OpenSSL, and access to Docker Hub |
| Helm | Internet-connected Kubernetes cluster | A working cluster, Helm, kubectl, OpenSSL, and access to Docker Hub |
| Offline package | Air-gapped host | Docker with Docker Compose V2, tar, OpenSSL, and a separate machine with cURL that can download the package |
The control-plane images are multi-architecture manifests carrying both linux/amd64 and linux/arm64, so the chart's pods schedule on arm64 nodes — AWS Graviton, for example — as well as amd64 ones. The offline package is the exception: it is built per architecture and must match the target host. See Install in an Air-Gapped Environment.
Before installing with Helm, decide whether to use the bundled PostgreSQL database or an external database. Docker Compose and offline package installations use the bundled database. Also choose the public dashboard origin and the data-plane manager endpoint that gateways will reach. You can start with local endpoints, but configure externally reachable endpoints before exposing the dashboard or attaching gateways on other hosts.
Docker Compose installations use host ports 5432, 8080, and 7944 by default. Make sure they are available or configure different host bindings. See the Port Reference for each component, traffic direction, and recommended exposure. If you rebind the 8080 host port to something other than the default, also update AISIX_CLOUD_PUBLIC_BASE_URL/api.publicBaseURL in Configure External Access before signing in — login validates the session issuer against that value, and a mismatch fails with 403 INVALID_ORIGIN.
Control Plane Components
Every installation method uses these components:
| Service | Role |
|---|---|
cp-api | Manages organizations, environments, resources, and billing |
dp-manager | Issues mTLS certificates and delivers configuration to data planes |
dashboard | Browser interface |
| PostgreSQL database | Shared datastore. Docker Compose packages include it; Helm can deploy it or connect to an external database. |
The online and offline Docker Compose packages require the bundled PostgreSQL 16 service. The Helm chart can deploy a bundled PostgreSQL instance or connect to an external database.
AISIX gateways run separately as data planes. They connect outbound to dp-manager over mTLS, so the control plane does not need inbound network access to gateway hosts. See Deploy AISIX Gateways on Kubernetes to install the api7/aisix gateway chart against this control plane.
Production Resource Baseline
The following specifications are deployment-planning starting points, not Helm chart defaults, benchmark-derived capacity guarantees, or fixed minimums for every workload. Benchmark and adjust them for your request rate, request size, enabled traffic controls, number of gateways, and data retention periods.
Docker Compose or Offline Package on Hosts
The online and offline Docker Compose packages provide a single-host topology with one instance of each control-plane service and a bundled PostgreSQL database. They do not support an external database or expose the multi-host service configuration required for control-plane high availability.
For an HA production topology, use Helm and the instance counts below. For a package-based evaluation or non-HA deployment, use the CPU, memory, and storage columns to assess host capacity.
CPU, memory, and host storage are per component instance. Host storage is a capacity allowance for the operating system, container images, platform-managed logs, and local component state; it is not equivalent to an application persistent-volume requirement in Kubernetes.
| Component | CPU | Memory | Host storage | Starting instances | Sizing guidance |
|---|---|---|---|---|---|
| AISIX gateway | 4 cores | 8–16 GB | ≥100 GB | 3 minimum; 4 recommended per gateway deployment | Scale horizontally with traffic. Start with 16 GB for high concurrency or guardrail workloads. Increase host storage for longer local log retention. |
cp-api | 2 cores | 4 GB | ≥32 GB | 2 | Stateless; place instances in separate failure domains. |
dp-manager | 2–4 cores | 4–8 GB | ≥32 GB | 2 | Delivers configuration and processes gateway heartbeats and usage telemetry. Place instances in separate failure domains. |
dashboard | 1–2 cores | 2 GB | ≥20 GB | 2 | Stateless; place instances in separate failure domains. |
| PostgreSQL | 4–8 cores | 16 GB | ≥500 GB NVMe SSD | 3 | Critical stateful component. For production HA, use Helm with an external PostgreSQL deployment, such as a primary, synchronous standby, and asynchronous standby. Adjust storage for the usage-event retention period. |
| Prometheus (optional) | 4 cores | 8–16 GB | ≥200 GB | 1–2 | Stores monitoring metrics. Reuse an existing Prometheus deployment when available, and size storage for metric cardinality and retention. |
For smaller deployments, cp-api, dp-manager, dashboard, and Prometheus can share hosts if you reserve CPU and memory for each component and provide enough shared host capacity for container images and logs. Keep redundant instances in separate failure domains.
Helm on Kubernetes
For Kubernetes, plan compute per replica and scale the AISIX gateway independently using Performance and Sizing. The following values are planning recommendations rather than chart defaults:
| Component | CPU per replica | Memory per replica | Starting replicas | Sizing guidance |
|---|---|---|---|---|
| AISIX gateway | 4 cores | 8–16 GB | 3 minimum; 4 recommended per gateway deployment | Scale horizontally with traffic. Start with 16 GB for high concurrency or guardrail workloads. |
cp-api | 2 cores | 4 GB | 2 | Stateless; place replicas in separate failure domains. |
dp-manager | 2–4 cores | 4–8 GB | 2 | Place replicas in separate failure domains. |
dashboard | 1–2 cores | 2 GB | 2 | Stateless; place replicas in separate failure domains. |
| PostgreSQL | 4–8 cores | 16 GB | 3 for production HA | Use an external HA deployment rather than the bundled single-instance database. |
| Prometheus (optional) | 4 cores | 8–16 GB | 1–2 | Reuse an existing Prometheus deployment when available. |
The default control-plane Helm chart does not assign application persistent volumes to cp-api, dp-manager, or dashboard. Account for container images and platform-managed logs as Kubernetes node capacity instead of per-pod storage. If you operate PostgreSQL or Prometheus in the cluster, provision persistent storage separately and size it for usage-event or metric retention. As starting points, allocate at least 500 GB of NVMe SSD storage per PostgreSQL instance and 200 GB per Prometheus instance.
Do not place PostgreSQL replicas in the same failure domain or on shared storage. The bundled PostgreSQL chart does not provide a replicated database by default; see High Availability and External Database.
These specifications cover AISIX components only, not the compute resources required by upstream model inference. AISIX itself does not require a GPU.
Install Online
Use an online installation when the host or Kubernetes cluster can pull container images from Docker Hub.
Docker Compose on a Host
Use Docker Compose for an internet-connected host with Docker and Docker Compose. The installation URL resolves to the current release.
curl -sL "https://run.api7.ai/aisix-self-hosted/quickstart" | bashThe script downloads the package into ./aisix-self-hosted, generates a .env file with fresh secrets, pulls images from Docker Hub, and starts the stack.
The package uses its bundled PostgreSQL service and does not support an external database. Use the Helm installation when an external PostgreSQL database is required.
When startup finishes, the script prints the dashboard URL. The default URL is http://localhost:8080. Open the dashboard and create the first admin account.
Manage the stack from ./aisix-self-hosted:
./aisix-self-hosted/run.sh logs # tail logs
./aisix-self-hosted/run.sh stop # stop containers
./aisix-self-hosted/run.sh down # remove containers (keeps the data volume)Helm on Kubernetes
For Kubernetes, install the chart from the API7 Helm repository:
helm repo add api7 https://charts.api7.ai
helm repo update
export AISIX_CP_RELEASE=aisix-cp
export AISIX_NAMESPACE=aisix-cp
helm install "${AISIX_CP_RELEASE}" api7/aisix-cp \
-n "${AISIX_NAMESPACE}" --create-namespace \
--set secrets.masterKey="$(openssl rand -base64 32)" \
--set secrets.betterAuthSecret="$(openssl rand -base64 48)" \
--set postgresql.auth.password="$(openssl rand -hex 24)" \
--set postgresql.auth.postgresPassword="$(openssl rand -hex 24)"Without -n, Helm installs into whatever namespace your current kubectl context defaults to — usually default — rather than a namespace dedicated to the control plane. --create-namespace creates ${AISIX_NAMESPACE} if it does not already exist. The rest of this guide, External Database, and Upgrade AISIX all assume the same AISIX_CP_RELEASE/AISIX_NAMESPACE values, so keep them set in your shell (or substitute your own throughout).
The chart deploys the core API, data-plane manager, dashboard, and a bundled PostgreSQL instance by default.
To reach the dashboard before configuring external access, forward the cp-api service:
kubectl -n "${AISIX_NAMESPACE}" port-forward svc/aisix-cp-api 8080:8080Open http://localhost:8080 while the port-forward is running.
To use an existing database, first provision the external database and role. Then disable the bundled PostgreSQL chart with postgresql.builtin=false and configure the top-level externalDatabase.* values.
To inspect the default chart values locally, run:
helm show values api7/aisix-cpThe chart source and values are published in the api7/api7-helm-chart repository.
Use URL-safe database passwords, such as values generated with openssl rand -hex 24. The database password is embedded in a postgres:// connection URL, so characters such as +, /, and = from openssl rand -base64 can break the URL.
Install on OpenShift
The control-plane chart installs on OpenShift under the default restricted-v2 security context constraint. No custom SCC, no anyuid, and no service-account changes are needed.
The chart pins no UID. The default pod security context for cp-api, dp-manager, and the dashboard — the api, dpm, and ui values keys — is exactly:
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefaultrestricted-v2 supplies the runAsUser and fsGroup from the namespace's allocated range, and the pods accept whatever it assigns. The container images declare numeric users — 10001 for cp-api and dp-manager, 1001 for the dashboard — and every file each process reads is world-readable, so an arbitrary UID with GID 0 works. The only paths written at runtime are emptyDir volumes.
The container security context is unchanged and already satisfies restricted-v2: all capabilities dropped, a read-only root filesystem, and no privilege escalation.
Install the Chart
The bundled PostgreSQL chart is a dependency of the control-plane chart, and it still pins its own UID. A dependency chart cannot have its values made conditional from the parent chart. Turn its two security contexts off at install time so restricted-v2 assigns the UID. That is the only OpenShift-specific change to the Helm installation above — the complete command is:
helm repo add api7 https://charts.api7.ai
helm repo update
export AISIX_CP_RELEASE=aisix-cp
export AISIX_NAMESPACE=aisix-cp
helm install "${AISIX_CP_RELEASE}" api7/aisix-cp \
-n "${AISIX_NAMESPACE}" --create-namespace \
--set secrets.masterKey="$(openssl rand -base64 32)" \
--set secrets.betterAuthSecret="$(openssl rand -base64 48)" \
--set postgresql.auth.password="$(openssl rand -hex 24)" \
--set postgresql.auth.postgresPassword="$(openssl rand -hex 24)" \
--set postgresql.primary.podSecurityContext.enabled=false \
--set postgresql.primary.containerSecurityContext.enabled=falseThe last two values are the OpenShift-specific ones. The four above them are the same secrets every Helm installation sets.
The secrets are not optional
The chart ships literal placeholder defaults for secrets.masterKey and secrets.betterAuthSecret — CHANGE_ME_GENERATE_WITH_openssl_rand_-base64_32 and its 48-byte twin. The chart validates secrets.masterKey at render time and refuses to install rather than silently accepting it: leaving it unset, empty, or on the placeholder value fails both helm template and helm install with Error: execution error at (aisix-cp/templates/secret.yaml:7:6): secrets.masterKey must be set to a real base64-encoded 32-byte key (generate with: openssl rand -base64 32). Set all four values regardless — a rejected secrets.masterKey is the fast, visible failure; do not rely on the same validation catching the other three.
Nothing else needs disabling. In particular, do not turn off postgresql.shmVolume — PostgreSQL then falls back to the 64 MB /dev/shm the container runtime provides, and parallel queries fail with could not resize shared memory segment.
Using an external database avoids the PostgreSQL security-context question entirely, and is the recommended production choice regardless of platform.
To pin a fixed UID instead — on a cluster that does not assign one, or to match existing volume ownership — add the values back to the command above:
--set api.podSecurityContext.runAsUser=10001 \
--set api.podSecurityContext.runAsGroup=101 \
--set api.podSecurityContext.fsGroup=101Verify the Security Context Constraint
Confirm that restricted-v2 admitted the pods and assigned a UID from the namespace's range:
oc get pods -n "${AISIX_NAMESPACE}" \
-o custom-columns='POD:.metadata.name,SCC:.metadata.annotations.openshift\.io/scc'POD SCC
aisix-cp-api-f9b94c475-lhfn2 restricted-v2
aisix-cp-dpm-6c7cb848c5-cpw68 restricted-v2
aisix-cp-postgresql-0 restricted-v2
aisix-cp-ui-64b6cc9887-nlxzd restricted-v2Where the assigned UID appears
restricted-v2 injects runAsUser into each container's security context, not the pod's. oc get pod -o jsonpath='{.spec.securityContext.runAsUser}' stays empty on a correctly admitted pod, which reads like a failure and is not one. Read the container instead, or ask the process:
oc exec -n "${AISIX_NAMESPACE}" deploy/aisix-cp-api -- id -uThe answer is an arbitrary UID from the namespace's openshift.io/sa.scc.uid-range, such as 1000730000 — not the image's 10001.
Expose the Control Plane with Routes
The chart creates ClusterIP services only and no Route. On OpenShift, publish the dashboard with an edge Route and dp-manager with a passthrough Route — dp-manager speaks mTLS, which a TLS-terminating edge Route would break.
oc -n "${AISIX_NAMESPACE}" create route edge aisix-cp \
--service=aisix-cp-api --port=8080
oc -n "${AISIX_NAMESPACE}" create route passthrough aisix-cp-dpm \
--service=aisix-cp-dpm --port=7944Then point the two public values at those hostnames and upgrade the release:
AISIX_CP_HOST=$(oc -n "${AISIX_NAMESPACE}" get route aisix-cp -o jsonpath='{.spec.host}')
AISIX_DPM_HOST=$(oc -n "${AISIX_NAMESPACE}" get route aisix-cp-dpm -o jsonpath='{.spec.host}')
helm upgrade "${AISIX_CP_RELEASE}" api7/aisix-cp -n "${AISIX_NAMESPACE}" --reuse-values \
--set api.publicBaseURL="https://${AISIX_CP_HOST}" \
--set api.dpmgrBaseURL="https://${AISIX_DPM_HOST}:443"Set both before issuing a gateway certificate. Until api.dpmgrBaseURL holds a real endpoint, the dashboard's generated install command keeps its https://<your-dp-manager>:7944 placeholder and cannot be run as given. See Configure External Access for what each value controls.
dp-manager issues its TLS server certificate for the host a client dials, so the passthrough Route's hostname is covered on the first handshake — no extra configuration. A gateway that dials an IP literal instead offers no name, and is covered only by naming that address in api.dpmgrBaseURL.
Install in an Air-Gapped Environment
For a host with no registry access, use the offline package. It includes every required container image.
The offline package is published per CPU architecture, and the latest URL of each resolves to the current release. Pick the one matching the air-gapped host:
| Host architecture | Download URL |
|---|---|
linux/amd64 (x86-64) | https://run.api7.ai/aisix-self-hosted/aisix-self-hosted-offline-latest-linux-amd64.tar.gz |
linux/arm64 (AArch64) | https://run.api7.ai/aisix-self-hosted/aisix-self-hosted-offline-latest-linux-arm64.tar.gz |
Version-pinned URLs of the form aisix-self-hosted-offline-<version>-linux-<arch>.tar.gz are published in the same directory.
On a machine with internet access, download the package for the target host's architecture:
curl -fSL "https://run.api7.ai/aisix-self-hosted/aisix-self-hosted-offline-latest-linux-amd64.tar.gz" \
-o aisix-self-hosted-offline-latest-linux-amd64.tar.gzThe URLs without an architecture suffix — aisix-self-hosted-offline-latest.tar.gz and aisix-self-hosted-offline-<version>.tar.gz — keep working and are the linux/amd64 package, so existing automation does not need to change. The linux/arm64 package is published only under its own suffix.
Transfer the package to the air-gapped host, then start the stack:
tar -xzf aisix-self-hosted-offline-latest-linux-amd64.tar.gz
cd aisix-self-hosted
./run.shEach package bundles images for one architecture only. If the package does not match the host, run.sh stops before loading anything and prints the URL of the right one — rather than letting docker load succeed and every container fail later with exec format error.
The startup script:
- loads the bundled container images
- generates a
.envfile with fresh secrets - starts the stack without internet access
- prints the dashboard URL when startup finishes
The default dashboard URL is http://localhost:8080.
The cp-api image included in the package contains a model-pricing snapshot so usage and budget calculations can initialize without reaching models.dev. At startup, the control plane loads the model-pricing catalog from that snapshot. To use online pricing instead, set AISIX_CLOUD_PRICESYNC_SNAPSHOT_PATH= in .env and recreate the api service. See On-Premises Configuration for the pricing catalog settings.
Configure External Access
Before exposing the control plane outside the local host or cluster, configure the public dashboard origin and the data-plane manager endpoint.
For Docker Compose, edit .env. For Kubernetes, update your Helm values:
| Docker Compose setting | Helm value | Purpose |
|---|---|---|
AISIX_CLOUD_PUBLIC_BASE_URL | api.publicBaseURL | Browser-facing origin, such as https://<aisix-host>. Login validates the session issuer against this value. |
AISIX_CLOUD_DPMGR_BASE_URL | api.dpmgrBaseURL | dp-manager mTLS endpoint that data-plane hosts connect to. An https:// URL such as https://dpm.example.com:7944, whose host may be a DNS name or an IP address. A scheme-less host:port is normalized to https:// at load; a value that is neither shape fails startup naming the variable. |
The Helm chart exposes the cp-api, dp-manager, and dashboard services as ClusterIP by default. Expose the cp-api and dp-manager services through network endpoints appropriate for your cluster, then set the two public values above to those endpoints.
dp-manager receives the data-plane manager endpoint too, and issues its TLS server certificate for that host. Data planes verify the certificate against the address they dial, so the value must match the endpoint in the generated gateway install command — whether that is a DNS name or an IP address.
After updating these settings, recreate the affected services with docker compose up -d or apply the changes with helm upgrade.
Trusted Sign-In Origins
Sign-in accepts requests only from trusted browser origins. The public base URL origin is trusted automatically, along with its loopback twin. The twin is the same origin with the hostname swapped between localhost and 127.0.0.1, keeping the same scheme and port as the base URL. For example, a base URL of http://localhost:8080 also trusts http://127.0.0.1:8080 — but not a different port or scheme — so a local install works from either address. You do not need to list the base URL again anywhere.
Set additional origins only when the dashboard is reached through more than one hostname, such as a second domain or a reverse proxy. Provide them as a comma-separated list:
| Docker Compose setting | Helm value | Purpose |
|---|---|---|
AISIX_TRUSTED_ORIGINS | ui.extraEnvVars (add AISIX_TRUSTED_ORIGINS) | Extra sign-in origins, comma-separated, such as https://<console-host>,https://<admin-host>. |
A sign-in attempt from an untrusted origin fails with a message stating that the address is not allowed. Add the origin here to resolve it.
For more Docker Compose environment variables and Helm values, see On-Premises Configuration.
Verify the Installation
Open the dashboard at its configured public base URL. For a new installation, create the first admin account, then sign in. The version of the running control plane appears at the bottom of the dashboard's left navigation, in one of two forms:
v1.0.0— a released version. Quote this number when you check the release notes or report an issue.dev · 2f9c1ab— a build from a development commit rather than a release, identified by the abbreviated commit it was built from.
The same identity is available without signing in, which is useful in scripts and support bundles. Replace the base URL below with your own public base URL if the control plane is not reached at the default local address:
AISIX_CP_URL="http://localhost:8080"
curl -sS "${AISIX_CP_URL}/api/config/public" | jq '{cp_version, cp_commit}'{
"cp_version": "1.0.0",
"cp_commit": "a22f131"
}The API reports the released version without the v prefix the dashboard displays. cp_version is empty on a build that was not cut from a release; cp_commit identifies the commit in either case.
Gateway versions are reported separately, per instance, in the environment's Data planes view — the control plane and your gateways are upgraded independently.
Next Steps
Create or select the target organization and environment, then connect an AISIX gateway to issue a gateway certificate and attach the runtime that will serve traffic. On Kubernetes, install the gateway with the api7/aisix chart by following Deploy AISIX Gateways on Kubernetes — a separate chart from the api7/aisix-cp control plane installed above.
Use the On-Premises Configuration Reference to review Docker Compose environment variables and Helm values.