Deploy with the Offline RPM Bundle
This guide covers deploying API7 Enterprise on RedHat-family operating systems
(RHEL / Rocky / AlmaLinux / CentOS, 8 and 9) from the offline RPM bundle. It
needs only tar, systemctl, a text editor, and a browser — no internet access
required.
The bundle is delivered as api7-ee-rpm-<version>-<dist>.<arch>.tar.gz (e.g.
api7-ee-rpm-3.9.13-el8.x86_64.tar.gz). Below, <bundle> denotes the extracted
directory.
Architecture
API7 Enterprise has two layers: the Control Plane (CP) and the Data Plane (DP):
Browser / API client
│ HTTPS 7443
┌───────────▼─────────────┐
│ Control Plane (CP) │
│ dashboard ── console │ manage, configure, observe, sign certs
│ │ │
│ dp-manager ──── PostgreSQL (persistence: config/audit/users…)
└──────│──────────────────┘
│ etcd-over-mTLS 7943 (push config / heartbeat)
┌──────▼──────────────────┐
North-south traffic │ Data Plane (DP) │ actually serves API traffic
───── 9080/9443 │ api7-gateway │
└─────────────────────────┘
| Layer | Role | Notes |
|---|---|---|
| Control plane | Management & control | Configures gateways, signs data-plane certs, pushes config, aggregates observability; persists to PostgreSQL |
| Data plane | Traffic processing | Runs APISIX/OpenResty, executes routes and plugins; stateless, config synced from the control plane |
The control plane and data plane may share one host (evaluation) or run on separate hosts (production). Below, "CP host" and "DP host" distinguish them; on a single host they are the same machine.
What a Fully Working Dashboard Needs
The dashboard (the management UI/API) is not self-contained — a fully functional control plane needs the following. The first three are systemd services from the RPM bundle; the rest are prerequisites you provide.
| Component | Provided by | Required | Purpose |
|---|---|---|---|
api7ee-dashboard | api7ee-dashboard RPM (bundles Node.js) | Yes | Control-plane backend; serves the UI/API on 7443 |
api7ee-console | same RPM (runs on the bundled Node.js) | Yes | The Web console UI, reverse-proxied by the dashboard (3000 → 7443) |
api7ee-dp-manager | api7ee-dp-manager RPM | Yes | Pushes config to gateways, issues data-plane mTLS certs, handles heartbeat (7943) |
| PostgreSQL | external — Quick Start installs a local one; provide your own for production | Yes | Persistence: configuration, users, audit logs, etc. |
| Prometheus | external (not in the bundle) | For metrics | Stores gateway metrics via dp-manager remote-write; powers dashboard analytics (see Install Prometheus) |
| Jaeger | external (not in the bundle) | For tracing | Stores request traces for the dashboard's online-debug / tracing views (dp-manager → OTLP collector 4318; dashboard → query UI 16686) |
api7-gateway | api7-gateway RPM | Data plane | Serves API traffic; not required to run the dashboard, but needed for it to manage anything (see Onboard the data-plane gateway) |
Bundle Contents
After extraction (tar -xzf <bundle>.tar.gz) the directory contains:
| File | Category | Contents |
|---|---|---|
api7ee-dp-manager-*.rpm | Control plane | Data-plane management / config push / cert-signing service |
api7ee-dashboard-*.rpm | Control plane | Control-plane backend + Web console (TLS 7443); bundled Node.js. One package provides two systemd services: api7ee-dashboard and api7ee-console |
api7-gateway-*.rpm | Data plane | Gateway (APISIX, bundled OpenResty runtime) |
which-*.rpm, libxslt-*.rpm, etc. | OS dependencies | The few system libraries the gateway needs, bundled in |
install.sh | Installer | One-shot offline install of all the RPMs above |
quickstart.sh | Evaluation helper | Single-host evaluation one-shot (see Method A) |
Each package ships its own runtime (Node.js / OpenResty); the host's nodejs /
openresty are not required, so installation is fully offline and does not affect
software already on the host.
Not included (prepare separately):
- PostgreSQL — the control plane's only external dependency (see System Requirements / Prepare PostgreSQL).
- License — upload it in the console after installation.
- Data-plane certificate — issued automatically per gateway group by the console (see Onboard the data-plane gateway).
Paths Quick Reference
File layout after installation:
/usr/local/api7/ # control plane
├── dp-manager/{bin,conf}
└── dashboard/{bin,conf,console,node} # node = bundled Node.js
/usr/local/apisix/ # data plane (gateway)
├── conf/ # config.yaml + certs/params written by the onboarding script
└── logs/ # gateway logs
/usr/local/openresty/ # gateway's bundled OpenResty
/usr/bin/apisix # gateway CLI
/usr/lib/systemd/system/ # systemd units for each service
/var/log/api7/ /var/lib/api7/ # control-plane logs and runtime data
| Purpose | Path |
|---|---|
| dp-manager config | /usr/local/api7/dp-manager/conf/dp-manager.yaml |
| dashboard config | /usr/local/api7/dashboard/conf/dashboard.yaml |
| console config | /usr/local/api7/dashboard/conf/console.env |
| gateway config | /usr/local/apisix/conf/config.yaml |
| control-plane logs | /var/log/api7/*.log |
| gateway logs | /usr/local/apisix/logs/error.log |
Config files are installed as %config(noreplace): upgrades do not overwrite your
changes (the new defaults are saved as *.rpmnew). Services run under dedicated
accounts (control plane api7, data plane apisix), created automatically at
install time.
System Requirements
| Item | Requirement |
|---|---|
| OS | RHEL / Rocky / AlmaLinux / CentOS 8 or 9, x86_64 |
| Init system | systemd (all components run as systemd services). Container-based evaluation must run systemd as PID 1 (see Method A) |
| Privileges | root (or sudo) |
| PostgreSQL | 13+ (15 recommended); the control plane's only external dependency — local, on a separate host, or cloud-managed |
| Ports (control plane) | 7443 (console/API, external), 7943 (data-plane mTLS onboarding, open to DP hosts), 7900/7901/7080/7081 (local/internal) |
| Ports (data plane) | 9080/9443 (business traffic ingress) |
| Network | Fully offline; for split deployment the DP host must reach the CP host's 7943, and the control plane must reach PostgreSQL's 5432 |
Deployment Overview
Prepare PostgreSQL → install packages → configure CP → start CP
→ browser bootstrap (change password + License) → console issues the data-plane cert/params
→ configure the gateway on the DP host → console confirms the instance is Healthy
Two paths, pick one per scenario:
| Path | Use case | Characteristics |
|---|---|---|
| Method A: Quick Start | Single-host evaluation / PoC | One command; installs and initializes a local PostgreSQL automatically; ready in minutes |
| Method B: Standard Deployment | Production | Manual step-by-step; supports external/HA DB, split CP/DP, security hardening |
Method A: Quick Start (Single-Host Evaluation)
For a single-host evaluation or PoC, the bundled quickstart.sh brings the control
plane up in minutes (it installs the RPMs, installs and initializes a local
PostgreSQL, configures and starts the control plane, and prints the access URL).
➡️ See the dedicated guide: Quick Start: Single-Host RPM Evaluation (including container-based evaluation).
For production, use Method B below.
Method B: Standard Deployment (Production)
Prepare PostgreSQL
The control plane needs a PostgreSQL (13+, 15 recommended). The schema is migrated automatically when the control plane starts — no manual table creation. If you already have an instance, skip to Create database and role.
Install
Online host:
sudo dnf -y module enable postgresql:15 # required on RHEL/Rocky 8; optional on 9
sudo dnf -y install postgresql-server
Offline host: download the RPMs on a same-version online machine, then copy them over and install:
# online machine
sudo dnf -y module enable postgresql:15 # required on RHEL/Rocky 8, else you get the default PG 10 (< 13)
sudo dnf install -y --downloadonly --downloaddir=./pg-rpms postgresql-server
# target machine (after copying in pg-rpms/)
sudo dnf -y localinstall ./pg-rpms/*.rpm --disablerepo='*'
Initialize and Start
sudo /usr/bin/postgresql-setup --initdb
sudo systemctl enable --now postgresql
Create Database and Role
sudo -u postgres psql <<'SQL'
CREATE USER api7ee WITH PASSWORD 'YourStrongPassword';
CREATE DATABASE api7ee OWNER api7ee;
SQL
Enable Password Authentication (Important)
The control plane connects with "username + password + TCP," but the stock
PostgreSQL on RHEL defaults local TCP to ident, which makes the connection fail. Edit
/var/lib/pgsql/data/pg_hba.conf and add, before the generic rules:
host api7ee api7ee 127.0.0.1/32 scram-sha-256
host api7ee api7ee ::1/128 scram-sha-256
If the DB and the control plane are on separate hosts, also: set
listen_addresses = '*' in postgresql.conf; add the control-plane subnet to
pg_hba.conf (e.g. host api7ee api7ee 10.0.0.0/24 scram-sha-256); open port 5432
in the firewall.
Reload after editing: sudo systemctl reload postgresql.
Verify and Record the Connection String
PGPASSWORD='YourStrongPassword' psql -h 127.0.0.1 -U api7ee -d api7ee -c '\conninfo'
Connection string (used next): postgres://api7ee:YourStrongPassword@<PG_HOST>:5432/api7ee.
If the password contains special characters such as @ : / ?, URL-encode them (e.g. @ → %40).
Install Packages
Run once on the CP host and once on the DP host:
tar -xzf api7-ee-rpm-<version>-<dist>.<arch>.tar.gz
cd api7-ee-rpm-<version>-<dist>.<arch>/
sudo ./install.sh # equivalent to dnf -y localinstall ./*.rpm --disablerepo='*'
For split deployment: the CP host needs only the two control-plane packages
(api7ee-dp-manager, api7ee-dashboard); the DP host needs only api7-gateway.
Installing the whole bundle is fine too — just do not start the services you do not need.
Configure the Control Plane (CP Host)
Put the database connection string into two configs (both pointing at the same database); leave everything else at the defaults.
In /usr/local/api7/dp-manager/conf/dp-manager.yaml and /usr/local/api7/dashboard/conf/dashboard.yaml:
database:
dsn: "postgres://api7ee:YourStrongPassword@<PG_HOST>:5432/api7ee"
- The console uses
7443(TLS) by default; to use your own certificate, setserver.tls.cert_file/server.tls.key_fileindashboard.yaml(leave empty to use the built-in self-signed cert). console.envusually needs no changes; do not change itsPORT=3000(the dashboard reverse-proxies to127.0.0.1:3000; changing it causes a 502).
Start the Control Plane (CP Host)
sudo systemctl enable --now api7ee-dp-manager
sudo systemctl enable --now api7ee-dashboard # also brings up api7ee-console
systemctl is-active api7ee-dp-manager api7ee-dashboard api7ee-console # expect all three active
Open 7443 for browser access, and 7943 (DP→CP) for split deployment:
sudo firewall-cmd --add-port=7443/tcp --add-port=7943/tcp --permanent && sudo firewall-cmd --reload.
If SELinux is Enforcing and a service misbehaves, check sudo ausearch -m avc -ts recent;
you may temporarily sudo setenforce 0 to confirm, then configure a proper policy —
do not disable it globally without reason.
Bootstrap (Change Password + License)
- Open
https://<CP_HOST>:7443in a browser (accept the self-signed cert). - Log in for the first time with
admin / adminand change the password as prompted. - Go to Settings → License, upload the License (contains a
BEGIN CERTIFICATEsegment + aBEGIN LICENSEsegment), and confirm the status is normal.
Onboard the Data-Plane Gateway
The data plane's connection parameters and mTLS certificate are issued centrally by the console (a single source of truth) — do not copy them by hand.
- Console → Gateway Groups → select/create a group → Add Instance.
- The console generates a deployment script with the group's certificate and the control-plane address embedded.
The console's Add Instance currently generates Docker / Docker Compose / Helm
scripts; it does not yet emit a native RPM script. For an RPM-installed gateway,
follow Deploy an RPM Data Plane Using the Dashboard's Docker Script
to apply those same connection parameters to /usr/local/apisix/conf/config.yaml,
then systemctl restart api7-gateway. The DP host must be able to reach the CP host's 7943.
Acceptance
# DP host
systemctl is-active api7-gateway # active
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9080/ # 404 = serving (no route yet)
In the console, open the gateway group → Instances: when the instance status is Healthy (heartbeat + config sync both succeeded), the deployment is complete. After that, publish routes/services in the console and the data plane syncs them automatically.
Install Prometheus (Required for Metrics)
The dashboard's metrics and analytics are not stored in the dp-manager: the gateway pushes metric blocks to the dp-manager, which remote-writes them to a Prometheus instance. Prometheus is a required external service and is not included in the RPM bundle — you must install and run it yourself, then point the dp-manager at it.
-
Install Prometheus on the CP host (or a reachable host) and start it with the remote-write receiver enabled:
prometheus --web.enable-remote-write-receiver # Prometheus v2.54+
# older builds: --enable-feature=remote-write-receiver -
Point
prometheus.addrindp-manager.yamlat it (the default assumes a local Prometheus on9090), keepremote_write_path: /api/v1/write, then restart the dp-manager:prometheus:
addr: "http://127.0.0.1:9090" # your Prometheus address
remote_write_path: "/api/v1/write"systemctl restart api7ee-dp-manager
Until Prometheus is installed and configured, the dashboard shows no traffic metrics
and the gateway logs agent.lua:544: upload metrics block failed, status: 500 — this
is expected when Prometheus is absent; proxying and instance health are unaffected.
Operations Reference
Services and Ports
| Layer | Service (systemd) | Default ports | Main config |
|---|---|---|---|
| Control plane | api7ee-dp-manager | 7900 / 7943 (mTLS) / 7901 | /usr/local/api7/dp-manager/conf/dp-manager.yaml |
| Control plane | api7ee-dashboard | 7443 (UI/API) / 7080 / 7081 | /usr/local/api7/dashboard/conf/dashboard.yaml |
| Control plane | api7ee-console | 3000 internal (reverse-proxied by dashboard) | /usr/local/api7/dashboard/conf/console.env |
| Data plane | api7-gateway | 9080 / 9443 (traffic ingress) | /usr/local/apisix/conf/config.yaml |
api7-gateway has the compatibility alias apisix.service (systemctl ... apisix also works).
Common Commands
systemctl status api7ee-dashboard # check status
systemctl restart api7ee-dp-manager # restart
journalctl -u api7-gateway -n 100 --no-pager # view recent logs
Upgrade
dnf upgrade installs the new RPMs; %config(noreplace) keeps your config intact
(new defaults are saved as *.rpmnew). Restart the affected services after upgrading.
Troubleshooting
| Symptom | Where to look |
|---|---|
| Console UI 502 | console.env's PORT must be 3000; fix it and systemctl restart api7ee-console |
| Control plane fails to start | Usually the DB is unreachable: check the DSN, PostgreSQL reachability, that the api7ee database/role exist, and that pg_hba.conf has password auth enabled |
Data-plane instance OutOfSync | Usually DP→CP 7943 is unreachable, or the cert does not match the control-plane environment; re-run the console-generated onboarding script |
| DP cannot reach CP | The CP 7943 port is not open, or the cert/DSN come from different environments and mismatch |
Offline install reports nothing provides which/libxslt | You have a slim package without the dependencies; use the official full bundle instead |
System has not been booted with systemd as init system | The host/container is not running systemd as PID 1; API7 EE runs as systemd services (see System requirements / Method A) |
Uninstall
sudo systemctl disable --now api7-gateway api7ee-console api7ee-dashboard api7ee-dp-manager
# console is installed by the dashboard package and has no standalone RPM, so it is not listed below
sudo dnf -y remove api7-gateway api7ee-dashboard api7ee-dp-manager
# config and data remain under /usr/local/api7, /usr/local/apisix, /var/log/api7, /var/lib/api7 — clean up manually as needed
Glossary
| Term | Meaning |
|---|---|
| Control plane / CP | The management and control layer: dp-manager + dashboard + console |
| Data plane / DP | The traffic-processing layer: api7-gateway |
| Gateway Group | A logical grouping of data-plane gateways in the control plane; certs and config are pushed per group |
| mTLS | Mutual TLS; the data plane joins via 7943 after both sides authenticate with certificates |
| DSN | Database connection string, of the form postgres://user:pass@host:5432/db |