Self-hosted installation
This guide installs AIP on your own Kubernetes cluster. It is separate from the trial SDK install, which only installs the Python client against Resaro's hosted trial platform — this guide installs the whole platform (API, web UI, database, object storage, and the analysis op runtime) into your infrastructure.
Resaro supplies AIP as one installer file. It downloads nothing at install time, so the same file installs on any cluster, with or without internet access.
Prerequisites
Your cluster needs:
- Kubernetes 1.35 — the version Resaro runs and tests AIP on.
- Nodes matching the package architecture (amd64 or arm64).
- A default StorageClass that can provision volumes.
- An ingress controller AIP can attach to.
- A method to issue HTTPS certificates, such as cert-manager.
You need:
- A kubeconfig for the cluster, from an account that can install cluster-wide
software.
./install.sh --dry-runnames every action the account can't do. - A Linux or macOS workstation to run the commands.
- A domain name for AIP, and the rights to create DNS records under it.
Unpack the installer
The installer filename is aip-installer-<client-name>-<arch>-<version>.tar.gz
— it holds your organization name, your cluster's architecture, and the
version:
tar xzf aip-installer-*.tar.gz
cd aip-installer-*/
Run every command in this guide from that unpacked directory — it holds
install.sh, zarf-config.yaml, and bin/, and every path in this guide is
relative to it.
Set ZARF for your workstation (the computer running these commands —
not your cluster). bin/ holds one Zarf program per workstation type, named
zarf-<os>-<arch>; list them with ls bin/. Zarf sends the images across the
network and your cluster runs them, so a macOS workstation program installs
correctly to a Linux cluster:
# macOS on Apple silicon
export ZARF=./bin/zarf-darwin-arm64
# Linux on x86
export ZARF=./bin/zarf-linux-amd64
Set the namespace variables. AIP installs into three namespaces:
export AIP_NS=aip-v2 # API, web interface, PostgreSQL, and MinIO
export NUCLIO_NS=nuclio # function controller and op pods
export OBS_NS=monitoring # monitoring dashboards, only if installed
The Secret names aip-v2-ui-tls, aip-v2-api-tls, and aip-v2-minio-tls
start with the same letters as $AIP_NS — they are Secret names, not
namespaces.
Point your kubeconfig at the target cluster. Every command in this guide uses the current context:
$ZARF tools kubectl config current-context
Set four values in zarf-config.yaml (everything else has a working
default):
BASE_DOMAIN— your domain for AIP, e.g.aip.example.org. The web interface uses this name; other services add a prefix (api.,minio.,grafana.). Lowercase letters, numbers, hyphens, and dots only — an underscore breaks ingress. Selecting the final domain now matters: a later change needs a new ingress install.INIT_ADMIN_PASSWORD— the password for theadminlogin.INGRESS_CLASS— your cluster's ingress class ($ZARF tools kubectl get ingressclassto find it).CLUSTER_ISSUER— the certificate issuer, depending on which of the four certificate methods below Resaro built your package for.
Some analysis ops call an external model endpoint and need OPENAI_API_KEY,
JUDGE_API_KEY, or HF_TOKEN in this file — Resaro tells you which keys
your package needs.
Choose the certificate method
Resaro builds your package for one of four methods; Resaro tells you which.
Your own cert-manager issuer — set CLUSTER_ISSUER to that issuer's
name. Prepare nothing. Do not use --install-infra.
You supply the certificates — set CLUSTER_ISSUER to "". Before
install, create three TLS Secrets in $AIP_NS: aip-v2-ui-tls (for
<base-domain>), aip-v2-api-tls (for api.<base-domain>), and
aip-v2-minio-tls (for minio.<base-domain>) — one certificate naming all
three hosts (or <base-domain> + *.<base-domain>) can fill all three:
$ZARF tools kubectl create namespace $AIP_NS
for name in aip-v2-ui-tls aip-v2-api-tls aip-v2-minio-tls; do
$ZARF tools kubectl -n $AIP_NS \
create secret tls "$name" --cert=<path-to-your-cert> --key=<path-to-your-key>
done
If you also install the monitoring dashboards, Grafana needs a fourth Secret,
obs-grafana-tls in $OBS_NS, covering grafana.<base-domain>.
You supply the certificate authority — keep CLUSTER_ISSUER: aip-ca, add
--install-infra (the aip-ca issuer comes from the package). Create one
Secret; AIP issues the three certificates itself, signed by your authority:
$ZARF tools kubectl create namespace cert-manager
$ZARF tools kubectl -n cert-manager create secret tls aip-ca \
--cert=<path-to-your-ca-cert> --key=<path-to-your-ca-key>
AIP creates its own authority — keep CLUSTER_ISSUER: aip-ca, add
--install-infra, prepare nothing. After install, distribute the authority's
certificate to your users (see Trust the certificate below).
What AIP installs
install.sh reads zarf-config.yaml, checks what the cluster already has,
and — only with --install-infra — supplies what's absent:
| AIP looks for | Named by | With --install-infra, if absent |
|---|---|---|
| the IngressClass | INGRESS_CLASS | installs Traefik, only if INGRESS_CLASS is traefik |
| cert-manager | — | installs cert-manager |
| the ClusterIssuer | CLUSTER_ISSUER | creates the aip-ca authority, only if CLUSTER_ISSUER is aip-ca |
Without --install-infra, an absent item stops the install and names the
remedy. If your cluster has no ingress controller and no cert-manager, keep
the defaults traefik / aip-ca and add --install-infra.
Set INGRESS_CLASS to the class of your own controller if you have one —
--install-infra doesn't change this. Keep traefik only if your cluster
has no ingress controller at all; a second controller gets its own load
balancer that your DNS records won't point at, and the installer stops if it
finds that combination.
Install
Two flags to decide before you start:
--install-infra— required ifCLUSTER_ISSUERisaip-ca, or if your cluster has no ingress controller or cert-manager.--components observability— installs the monitoring dashboards (Grafana, Loki, Tempo, Mimir) in the same run, showing service health, the logs/traces of a failed analysis run, and cluster load. Resaro strongly recommends these for every deployment; they use AIP's existing object storage, so nothing extra needs configuring.
Dry run first (changes nothing, checks the same options you'll actually pass):
./install.sh --dry-run # add --install-infra, --components observability, or both
It reports the target cluster, your account's access, the ingress class, the
certificate issuer, the default StorageClass, and the components to deploy.
The deploying line names everything AIP adds to the cluster — on a cluster
that already has an ingress controller and cert-manager, it reads AIP only — no cluster infrastructure will be installed.
Then install, with the same options:
./install.sh # add --install-infra, --components observability, or both
A second run is safe — it continues an interrupted install, upgrades the
platform in place (pods may restart), never resets a password, and never
deletes data. Run it again with --components observability to add the
dashboards later. Protect zarf-config.yaml: it holds the admin password
and later runs need the file again.
Complete the setup
Create the DNS records
Find your ingress address:
$ZARF tools kubectl get svc -A --field-selector spec.type=LoadBalancer
Point these names at that address — they must resolve from your users' browsers, not only inside the cluster:
aip.example.org → <that address> the web interface
api.aip.example.org → <that address> the API, used by the Python SDK
minio.aip.example.org → <that address> object storage
grafana.aip.example.org → <that address> dashboards, only with --components observability
Do not omit the minio.aip.example.org record — dataset previews and
downloads fail without it, since AIP signs its links against that exact name
and a browser cannot change them. Publish grafana.<base-domain> only to the
networks your operators use — Grafana has one shared admin login and no
single sign-on yet, and it can read the AIP database.
Trust the certificate
Applies only if you kept CLUSTER_ISSUER: aip-ca. If you supplied your own
authority, open https://<your base domain> first — if the browser shows no
warning, your machines already trust it. Otherwise, distribute the
authority's certificate:
$ZARF tools kubectl -n cert-manager get secret aip-ca \
-o jsonpath='{.data.tls\.crt}' | base64 -d > aip-ca.crt
Send aip-ca.crt to your users' trust stores using the same method you use
for other internal certificates.
Sign in
Open https://<your base domain> — username admin, password the
INIT_ADMIN_PASSWORD you set. If you deployed the monitoring dashboards,
open https://grafana.<your base domain> and sign in as admin with the
password AIP generated on your cluster (not the AIP password):
$ZARF tools kubectl -n $OBS_NS get secret grafana-admin-secret \
-o jsonpath='{.data.admin-password}' | base64 -d
Troubleshooting
| Symptom | Cause / fix |
|---|---|
bundle signature verification FAILED | The transfer damaged the file, or it was altered. Do not install it — ask Resaro for a new copy. |
| Auth error part-way through install | A cluster credential expired mid-run. Re-authenticate, then run ./install.sh again — it continues from where it stopped. |
A pod stays Pending | Kubernetes cannot schedule the pod — check node resources and taints. |
| Browser shows a certificate warning | With aip-ca, that machine doesn't have aip-ca.crt yet (see Trust the certificate). With your own issuer, run $ZARF tools kubectl -n $AIP_NS get certificate to check readiness. |
| Web interface opens but a dataset won't preview/download | The minio.<domain> DNS record is missing — see Create the DNS records. |
To see the state of all components:
$ZARF tools kubectl get pods -n $AIP_NS
$ZARF tools kubectl get pods -n $NUCLIO_NS
Reference
Where the components run
| Namespace | Contents |
|---|---|
$AIP_NS | API, web interface, PostgreSQL, object storage |
$NUCLIO_NS | Function controller and the analysis ops |
zarf | In-cluster image registry |
traefik | Ingress. Present only if you used --install-infra |
cert-manager | Certificate issuance. Present only if you used --install-infra |
$OBS_NS | Grafana, Loki, Tempo, Mimir. Present only if you used --components observability |
Installer options (run ./install.sh --help to see them all)
| Option | Effect |
|---|---|
--dry-run | Examine the cluster and show the plan. Changes nothing |
--components <list> | Also install optional components, such as observability |
--install-infra | Permit AIP to install what the cluster lacks: ingress controller, cert-manager, the aip-ca authority. Off by default |
--airgap | Verify the cluster has no internet access. Fails if egress works |
--skip-init | Omit cluster initialization. The installer already omits it when the cluster holds a zarf namespace |
--skip-smoke | Omit the post-install check |