Docs
AISIX AI GatewayAISIX EnterpriseSelf-Hosted DeploymentOn-Premises Installation

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 methodTargetRequirements
Docker ComposeInternet-connected hostDocker with Docker Compose V2, cURL, tar, OpenSSL, and access to Docker Hub
HelmInternet-connected Kubernetes clusterA working cluster, Helm, kubectl, OpenSSL, and access to Docker Hub
Offline packageAir-gapped hostDocker 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:

ServiceRole
cp-apiManages organizations, environments, resources, and billing
dp-managerIssues mTLS certificates and delivers configuration to data planes
dashboardBrowser interface
PostgreSQL databaseShared 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.

ComponentCPUMemoryHost storageStarting instancesSizing guidance
AISIX gateway4 cores8–16 GB≥100 GB3 minimum; 4 recommended per gateway deploymentScale horizontally with traffic. Start with 16 GB for high concurrency or guardrail workloads. Increase host storage for longer local log retention.
cp-api2 cores4 GB≥32 GB2Stateless; place instances in separate failure domains.
dp-manager2–4 cores4–8 GB≥32 GB2Delivers configuration and processes gateway heartbeats and usage telemetry. Place instances in separate failure domains.
dashboard1–2 cores2 GB≥20 GB2Stateless; place instances in separate failure domains.
PostgreSQL4–8 cores16 GB≥500 GB NVMe SSD3Critical 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 cores8–16 GB≥200 GB1–2Stores 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:

ComponentCPU per replicaMemory per replicaStarting replicasSizing guidance
AISIX gateway4 cores8–16 GB3 minimum; 4 recommended per gateway deploymentScale horizontally with traffic. Start with 16 GB for high concurrency or guardrail workloads.
cp-api2 cores4 GB2Stateless; place replicas in separate failure domains.
dp-manager2–4 cores4–8 GB2Place replicas in separate failure domains.
dashboard1–2 cores2 GB2Stateless; place replicas in separate failure domains.
PostgreSQL4–8 cores16 GB3 for production HAUse an external HA deployment rather than the bundled single-instance database.
Prometheus (optional)4 cores8–16 GB1–2Reuse 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" | bash

The 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:8080

Open 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-cp

The 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: RuntimeDefault

restricted-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=false

The 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=101

Verify 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-v2

Where 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 -u

The 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=7944

Then 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 architectureDownload 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.gz

The 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.sh

Each 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 .env file 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 settingHelm valuePurpose
AISIX_CLOUD_PUBLIC_BASE_URLapi.publicBaseURLBrowser-facing origin, such as https://<aisix-host>. Login validates the session issuer against this value.
AISIX_CLOUD_DPMGR_BASE_URLapi.dpmgrBaseURLdp-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 settingHelm valuePurpose
AISIX_TRUSTED_ORIGINSui.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.