zuplo 7.5.5 → 7.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ ---
2
+ title: Install
3
+ sidebar_label: Install
4
+ ---
5
+
6
+ Use this guide to install Zuplo Self-Hosted in a single cluster with automatic
7
+ certificates from cert-manager. Before you begin, complete the
8
+ [requirements](./requirements.md).
9
+
10
+ ## Set environment variables
11
+
12
+ Set these variables in the shell that you use for the installation:
13
+
14
+ ```bash
15
+ # From the Zuplo portal. See Requirements for instructions.
16
+ export ZUPLO_ACCOUNT_NAME='acme-corp'
17
+
18
+ # Provided by Zuplo during onboarding.
19
+ export ZUPLO_CHART_VERSION='<chart version from onboarding>'
20
+ export ZUPLO_REGISTRY_KEY='<base64 credential from onboarding>'
21
+
22
+ # Yours.
23
+ export ZUPLO_SUBDOMAIN='api.example.com'
24
+ export ZUPLO_MANAGEMENT_HOSTNAME='zuplo-admin.example.com'
25
+ export ZUPLO_BUILD_REGISTRY='us-docker.pkg.dev/acme-corp/zuplo-gateways'
26
+ export ACME_EMAIL='platform@example.com'
27
+ ```
28
+
29
+ ## Authenticate to the Zuplo registry
30
+
31
+ The chart is an OCI artifact in Zuplo's registry. The same credential pulls the
32
+ chart and the component images.
33
+
34
+ ```bash
35
+ printf '%s' "$ZUPLO_REGISTRY_KEY" |
36
+ helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
37
+ ```
38
+
39
+ ```
40
+ Login Succeeded
41
+ ```
42
+
43
+ ## Create the values file
44
+
45
+ Create `zuplo-values.yaml` and commit it to your infrastructure repository. Pass
46
+ this file to Helm during every upgrade.
47
+
48
+ ```yaml title="zuplo-values.yaml"
49
+ account:
50
+ # Your Zuplo account name.
51
+ name: acme-corp
52
+
53
+ deployments:
54
+ # Parent domain for your APIs. Needs wildcard DNS:
55
+ # *.api.example.com -> your ingress address
56
+ subdomain: api.example.com
57
+
58
+ managementApi:
59
+ # Where deployments are pushed IN. Must be reachable by Zuplo and your CI/CD.
60
+ hostname: zuplo-admin.example.com
61
+ dedicatedIngress:
62
+ enabled: false
63
+
64
+ builder:
65
+ # Where the in-cluster builder pushes built gateway images.
66
+ provider: docker
67
+ registry: us-docker.pkg.dev/acme-corp/zuplo-gateways
68
+ secretName: builder-secret
69
+
70
+ cert-manager:
71
+ # Issues and renews one certificate per deployment hostname. Leaving this on
72
+ # is what keeps a wildcard certificate out of the picture.
73
+ enabled: true
74
+ acme:
75
+ # Required when cert-manager.enabled is true. The certificate authority
76
+ # sends expiration warnings to this address.
77
+ email: platform@example.com
78
+ ```
79
+
80
+ ## Create the credentials file
81
+
82
+ The chart creates Kubernetes Secrets from Helm values. Put credentials in a
83
+ separate values file so that you don't commit them with the rest of the
84
+ configuration.
85
+
86
+ ```bash
87
+ cat > zuplo-secrets.yaml <<EOF
88
+ zuploImageRegistry:
89
+ registry: us-docker.pkg.dev
90
+ username: _json_key_base64
91
+ password: ${ZUPLO_REGISTRY_KEY}
92
+
93
+ builder:
94
+ username: _json_key_base64
95
+ password: ${ZUPLO_REGISTRY_KEY}
96
+ EOF
97
+ ```
98
+
99
+ :::danger{title="Treat this file as a secret"}
100
+
101
+ The chart doesn't support `existingSecret`. It stores these values in Kubernetes
102
+ Secrets and in the Helm release history. Don't commit this file as plaintext.
103
+ Encrypt it with SOPS or Sealed Secrets, or generate it in CI from a secret
104
+ store. Add it to `.gitignore` with your kubeconfig.
105
+
106
+ :::
107
+
108
+ ## Install the chart
109
+
110
+ Install the pinned chart version:
111
+
112
+ ```bash
113
+ helm install zuplo \
114
+ oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
115
+ --version "$ZUPLO_CHART_VERSION" \
116
+ --namespace zuplo --create-namespace \
117
+ -f zuplo-values.yaml \
118
+ -f zuplo-secrets.yaml
119
+ ```
120
+
121
+ ```
122
+ Pulled: us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo:<version>
123
+ NAME: zuplo
124
+ LAST DEPLOYED: ...
125
+ NAMESPACE: zuplo
126
+ STATUS: deployed
127
+ REVISION: 1
128
+ ```
129
+
130
+ The installation takes one to two minutes and creates resources in two
131
+ namespaces:
132
+
133
+ - `zuplo` is the release namespace created by `--create-namespace`. It contains
134
+ gateway deployments and the subcharts.
135
+ - `zuplo-system` is created by the chart and contains the Zuplo management
136
+ plane.
137
+
138
+ :::tip{title="Always pass `--version`"}
139
+
140
+ Without `--version`, Helm selects the most recent chart available at
141
+ installation time. Record the pinned version with `zuplo-values.yaml` so that
142
+ you can review and reproduce upgrades.
143
+
144
+ :::
145
+
146
+ ## Point DNS to the load balancer
147
+
148
+ Get the address of the `LoadBalancer` Service created by the chart:
149
+
150
+ ```bash
151
+ kubectl get svc zuplo-haproxy-ingress -n zuplo
152
+ ```
153
+
154
+ ```
155
+ NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
156
+ zuplo-haproxy-ingress LoadBalancer 10.128.82.11 203.0.113.24 80:31670/TCP,443:31011/TCP 50s
157
+ ```
158
+
159
+ Create two DNS A records pointing at `EXTERNAL-IP`, both resolving publicly and
160
+ neither behind a TLS-terminating proxy:
161
+
162
+ | Type | Name | Value |
163
+ | ---- | ------------------------- | -------------- |
164
+ | `A` | `*.api.example.com` | `203.0.113.24` |
165
+ | `A` | `zuplo-admin.example.com` | `203.0.113.24` |
166
+
167
+ Certificates can't be issued until these records resolve. cert-manager checks
168
+ the challenge URL from inside the cluster before it contacts the certificate
169
+ authority.
170
+
171
+ Next, [verify your installation](./verify.md).
@@ -3,40 +3,64 @@ title: Zuplo Self-Hosted
3
3
  sidebar_label: Overview
4
4
  ---
5
5
 
6
- Zuplo Self-Hosted (also known as on-prem) is a deployment model where you run
7
- the Zuplo Gateway on your own infrastructure — any cloud or private data center.
8
- Zuplo Self-Hosted runs exclusively on Kubernetes and is installed with a single
9
- Helm chart into your cluster.
6
+ Zuplo Self-Hosted (also known as on-prem) lets you run the Zuplo API Gateway on
7
+ your own cloud or private data center. It runs on Kubernetes and installs into
8
+ your cluster with a single Helm chart.
10
9
 
11
- Self-hosted deployment might be the right choice for you if you need:
10
+ Consider a self-hosted deployment when you need to:
12
11
 
13
- - Complete control over your infrastructure and deployment environment
14
- - To run Zuplo in a private data center or on-premises environment
15
- - To meet data sovereignty or regulatory requirements that require API traffic
16
- and data to remain within your infrastructure
17
- - To integrate with existing on-premises systems and networks
12
+ - Control the infrastructure and deployment environment.
13
+ - Run Zuplo in a private data center or on-premises environment.
14
+ - Keep API traffic and data on your infrastructure for regulatory or data
15
+ sovereignty requirements.
16
+ - Integrate with on-premises systems and networks.
18
17
 
19
- ## How It Works
18
+ ## How it works
20
19
 
21
20
  Your cluster runs two groups of workloads: a small Zuplo management plane that
22
- receives deployments, builds gateway images inside your cluster, and manages
23
- certificates and routing, and the gateway deployments themselves, which serve
24
- your API traffic. Developers deploy to your instance directly with the Zuplo CLI
25
- — the same Zuplo project format and deployment workflow used on every other
26
- Zuplo deployment model. Gateway images are built in-cluster and stored in your
27
- own container registry, and API traffic is served entirely from your
21
+ receives deployments, builds gateway images, and manages certificates and
22
+ routing, and the gateway deployments themselves, which serve your API traffic.
23
+ You use the same Zuplo project format and deployment workflow as every other
24
+ Zuplo deployment model.
25
+
26
+ A deployment runs partly in Zuplo and partly on your infrastructure:
27
+
28
+ | Step | Runs on |
29
+ | --------------------------------------------- | ----------------- |
30
+ | Compiling your project into a gateway bundle | Zuplo |
31
+ | Building the container image from that bundle | **Your cluster** |
32
+ | Storing the image | **Your registry** |
33
+ | Running the gateway and serving API traffic | **Your cluster** |
34
+
35
+ Zuplo hosts the portal and compiles the project. Your infrastructure builds,
36
+ stores, and runs the container image. API requests also stay on your
28
37
  infrastructure.
29
38
 
30
- ## Deployment Models
39
+ ## Quick start
31
40
 
32
- ### Hybrid Deployment
41
+ The installation guide uses the following configuration:
42
+
43
+ - A single cluster in one region. The cluster runs the management plane and the
44
+ gateways.
45
+ - Automatic certificates from the bundled cert-manager. It issues a certificate
46
+ for each deployment over HTTP-01, so the ingress must be publicly reachable on
47
+ port 80. You don't need a wildcard certificate or manual renewal.
48
+ - A container registry that you provide. The in-cluster builder uses a username
49
+ and password to push gateway images to the registry.
50
+
51
+ Start with this configuration to establish a working installation before you
52
+ introduce infrastructure-specific changes.
53
+
54
+ ## Deployment models
55
+
56
+ ### Hybrid deployment
33
57
 
34
58
  You run the gateway and management plane on your infrastructure, while a small
35
59
  set of Zuplo cloud services provides supporting features such as deployment
36
60
  configuration and API key management. All API traffic to your gateways stays on
37
61
  your infrastructure. This is the standard deployment model.
38
62
 
39
- ### Restricted-Egress Environments
63
+ ### Restricted-egress environments
40
64
 
41
65
  For environments with strict egress restrictions or stronger isolation
42
66
  requirements, [book a meeting](https://zuplo.com/meeting) to review your
@@ -44,9 +68,8 @@ requirements with the Zuplo team.
44
68
 
45
69
  ## Responsibilities
46
70
 
47
- Self-hosting keeps you in control of your infrastructure while Zuplo supplies
48
- everything Zuplo-specific — the chart, the images, and the support to run them
49
- well:
71
+ You manage the infrastructure and apply updates. Zuplo supplies the Helm chart,
72
+ component images, and product support:
50
73
 
51
74
  | Phase | Your team | Zuplo |
52
75
  | ------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
@@ -67,54 +90,54 @@ operated by Zuplo.
67
90
  ## Requirements
68
91
 
69
92
  This section lists what your team needs to prepare before installing Zuplo
70
- Self-Hosted. Use it to plan your platform and security review. Your Zuplo
71
- solutions architect walks through each item during onboarding.
93
+ Self-Hosted. Use it to plan your platform and security review. The
94
+ [Requirements](./requirements.md) page includes a checklist and preflight
95
+ commands. Your Zuplo solutions architect also reviews these items during
96
+ onboarding.
72
97
 
73
- ### Kubernetes Cluster
98
+ ### Kubernetes cluster
74
99
 
75
- - A cluster dedicated to Zuplo. If you want to run Zuplo in a multi-tenant
76
- cluster, consult your Zuplo point of contact first.
77
- - A conformant Kubernetes cluster — managed offerings such as EKS, AKS, and GKE,
78
- or your own distribution.
100
+ - A cluster dedicated to Zuplo. To run Zuplo in a multi-tenant cluster, consult
101
+ your Zuplo point of contact first.
102
+ - A conformant Kubernetes cluster, such as EKS, AKS, GKE, or a self-managed
103
+ distribution.
79
104
  - Support for Services of type `LoadBalancer` to expose the ingress.
80
105
  - Cluster administrator access for the initial install (the chart installs CRDs
81
106
  and cluster-scoped RBAC).
82
107
  - Zuplo builds gateway images inside your cluster. The build process runs
83
108
  privileged pods, so clusters that enforce a restricted Pod Security Standard
84
- cluster-wide need accommodations discuss this with your Zuplo solutions
109
+ cluster-wide need accommodations. Discuss this with your Zuplo solutions
85
110
  architect during onboarding.
86
111
  - Helm 3 on the machine performing the install; supported versions are confirmed
87
112
  during onboarding.
88
113
 
89
114
  ### DNS and TLS
90
115
 
91
- You control DNS for two names, both pointing at the cluster's ingress load
92
- balancer:
93
-
94
- - A wildcard subdomain for your gateway environments, for example
95
- `*.api.example.com` — each deployed gateway environment receives a hostname
96
- under it.
97
- - A hostname for the management API, for example `zuplo-admin.example.com` —
98
- used by the Zuplo CLI and your CI/CD pipelines to deploy.
116
+ You control DNS for two names, both pointing at the address of the cluster's
117
+ ingress load balancer:
99
118
 
100
- For TLS you can either:
119
+ - A **wildcard** subdomain for your gateway environments, for example
120
+ `*.api.example.com`. Every deployed environment receives its own hostname
121
+ under it. Because the names aren't known before deployment, the wildcard
122
+ record routes all of them to the ingress.
123
+ - A hostname for the management API, such as `zuplo-admin.example.com`. The
124
+ Zuplo CLI and your CI/CD pipelines use this hostname to deploy.
101
125
 
102
- - Use the bundled cert-manager to issue certificates automatically from an ACME
103
- certificate authority (for example Let's Encrypt), which requires the
104
- hostnames to be reachable for HTTP-01 challenges, or
105
- - Bring your own wildcard certificate as a Kubernetes TLS secret — common in
106
- private-network deployments.
126
+ For TLS, use the bundled cert-manager. It issues certificates from an ACME
127
+ certificate authority such as Let's Encrypt. It creates one certificate for each
128
+ hostname and renews the certificates automatically.
107
129
 
108
- ### Container Registry
130
+ ### Container registry
109
131
 
110
132
  Gateway images are built inside your cluster and pushed to a container registry
111
133
  that you provide. You need:
112
134
 
113
135
  - A registry your cluster can push to and pull from (for example ACR, Google
114
136
  Artifact Registry, GitHub Container Registry, or a private Harbor).
115
- - Write credentials for that registry, supplied at install time.
137
+ - Credentials with push and pull rights for that registry, supplied at install
138
+ time.
116
139
 
117
- ### Network Egress
140
+ ### Network egress
118
141
 
119
142
  In the hybrid deployment model, the cluster needs outbound HTTPS access to:
120
143
 
@@ -129,13 +152,15 @@ If your environment can't allow this egress,
129
152
  [book a meeting](https://zuplo.com/meeting) to review options with the Zuplo
130
153
  team.
131
154
 
132
- ### Provided by Zuplo During Onboarding
155
+ ### Information from Zuplo
133
156
 
134
157
  - Credentials to pull Zuplo component images from Zuplo's private registry.
135
- - Your account configuration and an API key for the management API.
136
158
  - The Helm chart, an installation guide, and a starter configuration reviewed
137
159
  with your team.
138
160
 
161
+ You find your account name in the [Zuplo portal](https://portal.zuplo.com). For
162
+ instructions, see [Requirements](./requirements.md).
163
+
139
164
  ### Observability
140
165
 
141
166
  The chart bundles a Prometheus-based metrics stack that Zuplo components use for
@@ -143,7 +168,27 @@ autoscaling gateway deployments. You can integrate your own logging and
143
168
  monitoring stack alongside it; gateway and component logs are written to
144
169
  standard output for collection by your log shipper.
145
170
 
146
- ## Getting Started
171
+ ## Components installed in your cluster
172
+
173
+ A single Helm chart installs everything, across two namespaces.
174
+
175
+ | Namespace | What runs there |
176
+ | -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
177
+ | `zuplo-system` | The Zuplo management plane: `control-plane`, `deployer`, `gateway`, `storage`, and `acme-forwarder`. Build Jobs run here. |
178
+ | `zuplo` | Your gateway deployments and the bundled HAProxy ingress controller, cert-manager, Prometheus stack, and prometheus-adapter subcharts. |
179
+
180
+ You supply the cluster, DNS for two hostnames, and a container registry for the
181
+ gateway images your cluster builds. Zuplo supplies the chart, the component
182
+ images, and the credentials to pull them.
183
+
184
+ ## Get started
185
+
186
+ 1. Review the [requirements](./requirements.md) and run the preflight checks.
187
+ 2. [Install](./install.md) the Helm chart.
188
+ 3. [Verify the installation](./verify.md), including a complete deployment.
189
+ 4. [Upgrade](./upgrade.md) to later chart versions when needed.
190
+ 5. Use [troubleshooting](./troubleshooting.md) to resolve installation and
191
+ deployment errors.
147
192
 
148
- To learn more about self-hosting Zuplo or to discuss your specific requirements,
193
+ To discuss your specific requirements,
149
194
  [book a meeting](https://zuplo.com/meeting) with the Zuplo team.
@@ -0,0 +1,195 @@
1
+ ---
2
+ title: Requirements
3
+ sidebar_label: Requirements
4
+ ---
5
+
6
+ Confirm every item on this page before you install Zuplo Self-Hosted. The
7
+ installation uses a single non-interactive `helm install` command.
8
+
9
+ This page assumes you already have a working Kubernetes cluster. Creating one is
10
+ out of scope.
11
+
12
+ ## Cluster
13
+
14
+ | Requirement | Detail |
15
+ | ----------------------- | -------------------------------------------------------------------------------------------------------- |
16
+ | Kubernetes | A conformant cluster. Managed offerings (EKS, AKS, GKE, LKE) and self-managed distributions both work. |
17
+ | Dedicated cluster | Recommended. To run Zuplo in a multi-tenant cluster, consult your Zuplo point of contact first. |
18
+ | Cluster administrator | The chart installs CRDs and cluster-scoped RBAC. |
19
+ | `LoadBalancer` Services | The chart creates exactly one, for the HAProxy ingress controller. |
20
+ | Privileged pods | Gateway images are built in-cluster by a Job that runs a privileged container. |
21
+ | Helm | Helm 3.8 or later. The chart is distributed as an OCI artifact. |
22
+ | `kubectl` | Within one minor version of the cluster. |
23
+ | Nodes | Three or more. The chart requests three HAProxy replicas and a Prometheus stack, and builds run as Jobs. |
24
+
25
+ A default `StorageClass` is not required. The bundled Prometheus runs without
26
+ persistent volumes, so the install creates no `PersistentVolumeClaim`.
27
+
28
+ :::caution{title="Privileged builds"}
29
+
30
+ The builder Job sets `privileged: true` because it builds container images
31
+ inside the cluster. A cluster that enforces the `restricted` Pod Security
32
+ Standard on the `zuplo-system` namespace blocks builds. Label the namespace for
33
+ the `privileged` policy, or discuss alternatives with your Zuplo solutions
34
+ architect.
35
+
36
+ :::
37
+
38
+ ## Container registry
39
+
40
+ Gateway images are built in your cluster and pushed to a registry you provide.
41
+ The chart does not create it.
42
+
43
+ - A registry your cluster can push to and pull from, such as Google Artifact
44
+ Registry, Amazon ECR, Azure Container Registry, GitHub Container Registry, or
45
+ a private Harbor.
46
+ - Credentials with both push and pull rights, supplied at install time. The
47
+ builder Job and gateway pods use the same Secret. With read-only credentials,
48
+ the build can finish, but the gateway rollout fails.
49
+ - Enough quota for a new image tag with every deployment. The chart doesn't
50
+ remove old tags, so configure a retention policy in the registry.
51
+
52
+ ## DNS names
53
+
54
+ Choose two hostnames. After you install the chart, point both to the external IP
55
+ of the `LoadBalancer` Service:
56
+
57
+ | Name | Example | Used by |
58
+ | --------------------------------- | ------------------------- | ------------------------------------ |
59
+ | Wildcard under a parent subdomain | `*.api.example.com` | Your API consumers |
60
+ | A management API hostname | `zuplo-admin.example.com` | The Zuplo CLI, your CI/CD, and Zuplo |
61
+
62
+ Each gateway environment gets a hostname under the parent subdomain when you
63
+ deploy it. Because these hostnames aren't known in advance, the wildcard record
64
+ routes them to your ingress.
65
+
66
+ Leave `cert-manager.enabled` at its default of `true`. cert-manager requests a
67
+ certificate for each hostname when you deploy it. The first request to a
68
+ deployment can fail while cert-manager issues its certificate.
69
+
70
+ :::tip{title="Send your management API hostname to Zuplo early"}
71
+
72
+ Zuplo registers your management API endpoint so that deployments from the Zuplo
73
+ portal reach your cluster. This registration requires only the hostname. Send it
74
+ to your Zuplo solutions architect after you choose it. Zuplo CLI deployments
75
+ don't require registration because you pass the endpoint to the CLI.
76
+
77
+ :::
78
+
79
+ :::caution{title="Forward HTTP-01 challenge requests"}
80
+
81
+ If a proxy or external load balancer sits in front of the ingress, keep port 80
82
+ publicly reachable. Forward requests to `/.well-known/acme-challenge/*` without
83
+ authentication, caching, or response modification. Both cert-manager's
84
+ self-check and the certificate authority must receive the response from the
85
+ temporary solver Ingress.
86
+
87
+ :::
88
+
89
+ ## Network access
90
+
91
+ Allow the following connections:
92
+
93
+ | Path | Port | Reached by | Fails silently? |
94
+ | ------------------------------------ | ---- | -------------------------------- | --------------- |
95
+ | `*.{parent subdomain}` | 443 | Your API consumers | No |
96
+ | The management API hostname | 443 | The Zuplo CLI and your CI/CD | No |
97
+ | Cluster DNS resolution of both names | 53 | cert-manager, inside the cluster | **Yes** |
98
+
99
+ cert-manager checks the challenge URL from inside the cluster before asking the
100
+ certificate authority to validate it. If cluster DNS can't resolve both names,
101
+ challenges remain `pending`. To inspect a pending challenge, see
102
+ [Troubleshooting](./troubleshooting.md).
103
+
104
+ For HTTP-01 validation, the certificate authority must also reach the ingress on
105
+ port 80. If your cluster can't expose port 80 to the public internet, discuss an
106
+ alternative certificate configuration with your Zuplo solutions architect.
107
+
108
+ ## Access to Zuplo services
109
+
110
+ The cluster needs outbound HTTPS to Zuplo services, both container registries,
111
+ and your certificate authority. The management API hostname is the only inbound
112
+ path.
113
+
114
+ :::note
115
+
116
+ Your Zuplo solutions architect provides the exact hostnames and ports for your
117
+ firewall rules during onboarding.
118
+
119
+ :::
120
+
121
+ ## Observability
122
+
123
+ Zuplo components use the bundled Prometheus stack to autoscale gateway
124
+ deployments based on ingress request rate. It isn't intended as a general
125
+ observability service. Because it has no persistent storage, its history doesn't
126
+ survive a pod restart.
127
+
128
+ Plan to run your own logging and monitoring alongside it. Every component, and
129
+ every gateway, logs to standard output for collection by your log shipper.
130
+
131
+ ## Check for conflicts
132
+
133
+ The chart bundles cert-manager, kube-prometheus-stack, and prometheus-adapter as
134
+ subcharts. On a cluster that already runs any of them, the install fails on CRD
135
+ ownership.
136
+
137
+ ```bash
138
+ # Anything returned here is a conflict to resolve before installing.
139
+ kubectl get crd | grep -E 'cert-manager\.io|monitoring\.coreos\.com'
140
+ kubectl get ingressclass
141
+ kubectl get svc -A --field-selector spec.type=LoadBalancer
142
+ ```
143
+
144
+ The quick start requires a cluster without an existing cert-manager or
145
+ Prometheus Operator installation. If either is present, use a dedicated cluster
146
+ or discuss an alternative configuration with your Zuplo solutions architect.
147
+
148
+ ## Run the preflight checks
149
+
150
+ Run the following commands and compare their output with the comments:
151
+
152
+ ```bash
153
+ # 1. The cluster is reachable and the version is what you expect.
154
+ kubectl version
155
+
156
+ # 2. Helm is 3.8 or later (OCI support).
157
+ helm version --short
158
+
159
+ # 3. Nodes are Ready.
160
+ kubectl get nodes
161
+
162
+ # 4. A LoadBalancer implementation exists. On a managed cloud this is the
163
+ # cloud controller manager; on bare metal it is MetalLB or equivalent.
164
+ kubectl get pods -A | grep -Ei 'cloud-controller|metallb|cloud-provider'
165
+
166
+ # 5. No conflicting CRDs (see above). Empty output is success.
167
+ kubectl get crd | grep -E 'cert-manager\.io|monitoring\.coreos\.com'
168
+ ```
169
+
170
+ ## Gather installation values
171
+
172
+ Gather the following values before you install. You don't need a running cluster
173
+ to collect them.
174
+
175
+ ### From the Zuplo portal
176
+
177
+ Create your account at [portal.zuplo.com](https://portal.zuplo.com), then
178
+ collect:
179
+
180
+ - Open **Account Settings → General**
181
+ ([portal](https://portal.zuplo.com/+/account/settings/general)). This is the
182
+ `account.name` value, so copy it exactly.
183
+
184
+ ### From Zuplo
185
+
186
+ - Credentials for Zuplo's private registry. The same credential pulls the Helm
187
+ chart and the component images.
188
+ - The chart version to pin.
189
+
190
+ ### To Zuplo
191
+
192
+ - The management API hostname you chose, so Zuplo can register it as your
193
+ account's deployment target.
194
+
195
+ Next, [install Zuplo Self-Hosted](./install.md).
@@ -0,0 +1,318 @@
1
+ ---
2
+ title: Troubleshooting
3
+ sidebar_label: Troubleshooting
4
+ description:
5
+ Find the cause of common self-hosted installation and deployment errors, and
6
+ apply the corresponding fix.
7
+ ---
8
+
9
+ Search this page for the error text from your command output.
10
+
11
+ ## Existing cert-manager or Prometheus installation
12
+
13
+ ```text
14
+ Error: INSTALLATION FAILED: Unable to continue with install: CustomResourceDefinition "certificates.cert-manager.io" exists and cannot be imported into the current release
15
+ ```
16
+
17
+ Your cluster already runs cert-manager, and the chart bundles its own. The quick
18
+ start requires a cluster without an existing cert-manager installation. Use a
19
+ dedicated cluster or discuss an alternative configuration with your Zuplo
20
+ solutions architect.
21
+
22
+ The same error with `monitoring.coreos.com` CRDs means that the cluster has an
23
+ existing Prometheus Operator installation.
24
+
25
+ ## Missing image registry password
26
+
27
+ ```text
28
+ Error: execution error at (zuplo/templates/zuplo-secrets.yaml:2:31): .Values.zuploImageRegistry.password is required.
29
+ ```
30
+
31
+ Your credentials file was not passed to Helm, or was passed before the values
32
+ file and overwritten.
33
+
34
+ Pass both files, credentials last:
35
+
36
+ ```bash
37
+ helm install zuplo ... -f zuplo-values.yaml -f zuplo-secrets.yaml
38
+ ```
39
+
40
+ ## Missing certificate email address
41
+
42
+ ```text
43
+ Error: execution error at (zuplo/templates/cert-issuer.yaml:...): cert-manager.acme.email field is required if using cert-manager
44
+ ```
45
+
46
+ `cert-manager.enabled` is `true` but `cert-manager.acme.email` is empty. Set an
47
+ address that you monitor. The certificate authority sends expiration warnings
48
+ there.
49
+
50
+ ## Missing account name
51
+
52
+ ```text
53
+ Error: execution error at (zuplo/templates/configuration.yaml:1:15): .Values.account.name is required.
54
+ ```
55
+
56
+ `account.name` is missing from `zuplo-values.yaml`. Copy it exactly from
57
+ **Account Settings → General**
58
+ ([portal](https://portal.zuplo.com/+/account/settings/general)). The management
59
+ API rejects API keys whose account does not match this string.
60
+
61
+ ## HTTP-01 DNS lookup failure
62
+
63
+ The full string looks like this:
64
+
65
+ ```
66
+ Waiting for HTTP-01 challenge propagation: failed to perform self check GET
67
+ request 'http://zuplo-admin.example.com/.well-known/acme-challenge/<token>':
68
+ Get "http://zuplo-admin.example.com/.well-known/acme-challenge/<token>":
69
+ dial tcp: lookup zuplo-admin.example.com on 10.128.0.10:53: no such host
70
+ ```
71
+
72
+ Your DNS record does not exist yet, or cluster DNS cannot resolve it.
73
+ cert-manager checks the challenge URL from inside the cluster before asking the
74
+ certificate authority to validate it. A failed self-check doesn't consume the
75
+ certificate authority's rate limit.
76
+
77
+ Check it:
78
+
79
+ ```bash
80
+ kubectl get challenge -A
81
+ dig +short A zuplo-admin.example.com
82
+ ```
83
+
84
+ Create the missing record, pointing at the `EXTERNAL-IP` of
85
+ `zuplo-haproxy-ingress`. cert-manager retries on its own; no restart needed.
86
+
87
+ ## Certificate not ready after DNS resolves
88
+
89
+ ```text
90
+ READY: False
91
+ ```
92
+
93
+ Check what the challenge says:
94
+
95
+ ```bash
96
+ kubectl get challenge -A -o jsonpath='{range .items[*]}{.metadata.name}{"\n "}{.status.reason}{"\n"}{end}'
97
+ ```
98
+
99
+ If DNS resolves correctly, check the following possible causes:
100
+
101
+ - The certificate authority can't reach port 80. HTTP-01 validation uses plain
102
+ HTTP on port 80. Confirm that the ingress responds from outside your network:
103
+
104
+ ```bash
105
+ curl -i "http://zuplo-admin.example.com/.well-known/acme-challenge/probe"
106
+ ```
107
+
108
+ A `404` or `302` means HAProxy is answering. A timeout means it is not.
109
+
110
+ - A proxy or external load balancer changes the HTTP-01 request or response.
111
+ Configure it to forward `/.well-known/acme-challenge/*` without
112
+ authentication, caching, or response modification.
113
+
114
+ If neither cause applies, share the challenge status with your Zuplo solutions
115
+ architect.
116
+
117
+ ## Management API authorization failure
118
+
119
+ ```json
120
+ { "detail": "Authorization Failed" }
121
+ ```
122
+
123
+ The request carried an API key, but the management API rejected it. The gateway
124
+ validates the key and then checks that its account matches `account.name` in
125
+ your values file. A valid key from another Zuplo account fails this check.
126
+
127
+ Compare what the cluster was installed with against **Account Settings →
128
+ General** ([portal](https://portal.zuplo.com/+/account/settings/general)):
129
+
130
+ ```bash
131
+ kubectl get configuration default -n zuplo-system \
132
+ -o jsonpath='{.spec.account.name}{"\n"}'
133
+ ```
134
+
135
+ If they differ, correct `account.name` in `zuplo-values.yaml` and run
136
+ `helm upgrade`. If they match, the key itself may belong to a different account.
137
+ Create one under **Account Settings → API Keys**
138
+ ([portal](https://portal.zuplo.com/+/account/settings/api-keys)) while the right
139
+ account is active.
140
+
141
+ `"detail": "No Authorization Header"` means no key was sent at all. Set
142
+ `ZUPLO_API_KEY` in the environment the Zuplo CLI runs in.
143
+
144
+ ## Environment variables unavailable
145
+
146
+ ```
147
+ We are unable to fetch the environment variables from Zuplo for this project.
148
+ To fix this, check that the project, <name> exists and this api-key has access to it.
149
+ If you want to force deployment without the environment variables, set
150
+ ZUPLO_ALLOW_DEPLOY_WITH_EMPTY_VARS to true.
151
+ ```
152
+
153
+ `zuplo deploy` stops before uploading the project. At this point, the CLI is
154
+ communicating with Zuplo rather than your management API, so this error doesn't
155
+ indicate a problem with your installation.
156
+
157
+ The project name comes from the `project` field in your `zuplo.jsonc`. Confirm a
158
+ project by that name exists in your account, and that the API key you are using
159
+ belongs to that same account.
160
+
161
+ Setting `ZUPLO_ALLOW_DEPLOY_WITH_EMPTY_VARS=true` forces the deploy through. The
162
+ gateway builds and serves traffic without environment variables, so any route
163
+ that reads one fails at runtime. Use this setting only to test the cluster.
164
+
165
+ ## Fallback ingress certificate
166
+
167
+ ```text
168
+ CN=kubernetes-ingress-ca
169
+ ```
170
+
171
+ HAProxy serves its fallback certificate when the requested hostname doesn't have
172
+ an issued certificate.
173
+
174
+ ```bash
175
+ kubectl get certificate -A
176
+ ```
177
+
178
+ If the certificate isn't `READY: True`, follow the DNS troubleshooting steps on
179
+ this page.
180
+
181
+ ## Hostname missing from certificate
182
+
183
+ ```text
184
+ SSL: no alternative certificate subject name matches target host name
185
+ ```
186
+
187
+ cert-manager issues a certificate for each deployment hostname. A deployment can
188
+ report `Ready` before its certificate is available. Retry the request for up to
189
+ a minute.
190
+
191
+ If the error persists, run `kubectl get certificate -n zuplo` and follow the DNS
192
+ troubleshooting steps on this page.
193
+
194
+ ## ACME challenge probe redirects
195
+
196
+ ```text
197
+ HTTP/1.1 302 Found
198
+ ```
199
+
200
+ You probed a hostname that already has an Ingress. Those hosts redirect port 80
201
+ to HTTPS.
202
+
203
+ This redirect doesn't affect certificate issuance. cert-manager creates a
204
+ separate challenge Ingress that continues to serve on port 80. To test the
205
+ ingress, use a hostname with no Ingress, as described in
206
+ [Verify your install](./verify.md).
207
+
208
+ ## Failed to deploy the environment but the cluster shows the build succeeding
209
+
210
+ ```text
211
+ Failed to deploy the environment
212
+ ```
213
+
214
+ The status polled by the Zuplo CLI might not reflect the build result inside a
215
+ self-hosted cluster. The CLI can report a failure even when the build and
216
+ gateway rollout succeed.
217
+
218
+ Confirm the result in the cluster:
219
+
220
+ ```bash
221
+ kubectl get jobs -n zuplo-system # build-<name> Complete 1/1
222
+ kubectl get deploy -n zuplo # the gateway Deployment exists
223
+ curl https://<deployment hostname>/<a route>
224
+ ```
225
+
226
+ If these checks pass, the deployment succeeded. If the build Job failed or no
227
+ Deployment appears, search this page for the reported error.
228
+
229
+ ## Builder Job fails after dependency installation
230
+
231
+ ```
232
+ {"severity":"INFO","message":"Using zuplo CLI for compilation"}
233
+ {"severity":"EMERGENCY","message":"Failed to run NPM commands","error":"exit status 1"}
234
+ ```
235
+
236
+ The upload is missing its `.zuplo/` directory. The Zuplo CLI generates
237
+ `.zuplo/worker.ts` and `.zuplo/build.json`, which the in-cluster compile step
238
+ needs. The archive extracts and `npm install` completes before this error, so
239
+ the final log line can look like a dependency failure.
240
+
241
+ The usual cause is a `.zupignore` that excludes `.zuplo/`. When a project has a
242
+ `.zupignore`, the CLI uses it without modification. The CLI removes `.zuplo/`
243
+ from `.gitignore` rules automatically, but it doesn't modify `.zupignore`.
244
+ Remove `.zuplo/` from `.zupignore`, and then deploy again.
245
+
246
+ Read the complete Job log. The compiler error appears before the `EMERGENCY`
247
+ line:
248
+
249
+ ```bash
250
+ kubectl logs -n zuplo-system -l job-name=<build-job-name> --tail=-1
251
+ ```
252
+
253
+ ## Builder Job pods are pending or rejected
254
+
255
+ The builder Job runs a privileged container because it builds container images.
256
+ A `restricted` Pod Security Standard on `zuplo-system` blocks it:
257
+
258
+ ```
259
+ pods "build-..." is forbidden: violates PodSecurity "restricted:latest":
260
+ privileged (container "builder" must not set securityContext.privileged=true)
261
+ ```
262
+
263
+ Label the namespace for the `privileged` policy, or talk to your Zuplo solutions
264
+ architect about alternatives.
265
+
266
+ ## Deployments not found after Helm installation
267
+
268
+ ```text
269
+ Error from server (NotFound): deployments.apps not found
270
+ ```
271
+
272
+ Look in the right namespace. The management plane runs in `zuplo-system`;
273
+ gateway deployments and every subchart run in `zuplo`.
274
+
275
+ ```bash
276
+ kubectl get pods -n zuplo-system
277
+ kubectl get pods -n zuplo
278
+ ```
279
+
280
+ ## Container registry authorization failure
281
+
282
+ ```text
283
+ Error: failed to authorize: failed to fetch anonymous token: unexpected status from GET request ... 403 Forbidden
284
+ ```
285
+
286
+ `helm registry login` has not run, or the credential expired.
287
+
288
+ ```bash
289
+ printf '%s' "$ZUPLO_REGISTRY_KEY" |
290
+ helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
291
+ ```
292
+
293
+ The same credential pulls the chart and the component images. If pods remain in
294
+ `ImagePullBackOff`, check that `zuploImageRegistry.password` is set.
295
+
296
+ ## Gateway image pull failure
297
+
298
+ ```text
299
+ ImagePullBackOff
300
+ ```
301
+
302
+ The built image pushed successfully but the cluster cannot pull it back.
303
+ `builder.registry` credentials need **both** push and pull rights, and the
304
+ `builder-secret` is used for both.
305
+
306
+ ```bash
307
+ kubectl describe pod -n zuplo <pod> | tail -20
308
+ ```
309
+
310
+ ## Kubernetes client version skew warning
311
+
312
+ ```
313
+ WARNING: version difference between client (1.32) and server (1.36) exceeds the
314
+ supported minor version skew of +/-1
315
+ ```
316
+
317
+ Upgrade `kubectl` before continuing. A client outside the supported version skew
318
+ can omit fields added by the server.
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: Upgrade
3
+ sidebar_label: Upgrade
4
+ ---
5
+
6
+ If you installed with a values file, you can upgrade with one command. If you
7
+ used `--set` flags, first create a values file with the same settings. Helm
8
+ renders every resource again during an upgrade, and omitted settings revert to
9
+ their defaults.
10
+
11
+ ## Upgrade the chart
12
+
13
+ ```bash
14
+ printf '%s' "$ZUPLO_REGISTRY_KEY" |
15
+ helm registry login us-docker.pkg.dev -u _json_key_base64 --password-stdin
16
+
17
+ helm upgrade zuplo \
18
+ oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
19
+ --version "$NEW_CHART_VERSION" \
20
+ --namespace zuplo \
21
+ -f zuplo-values.yaml \
22
+ -f zuplo-secrets.yaml
23
+ ```
24
+
25
+ Pass both files, unchanged, with every upgrade. The chart creates its Kubernetes
26
+ Secrets from values, so omitting the credentials file on an upgrade empties the
27
+ registry Secrets and every subsequent image pull fails.
28
+
29
+ Check what changed before applying it:
30
+
31
+ ```bash
32
+ helm diff upgrade zuplo \
33
+ oci://us-docker.pkg.dev/zuplo-customers/self-hosted/helm-charts/zuplo \
34
+ --version "$NEW_CHART_VERSION" \
35
+ --namespace zuplo \
36
+ -f zuplo-values.yaml -f zuplo-secrets.yaml
37
+ ```
38
+
39
+ `helm diff` is the [helm-diff plugin](https://github.com/databus23/helm-diff),
40
+ installed with `helm plugin install https://github.com/databus23/helm-diff`.
41
+
42
+ ## Verify the upgrade
43
+
44
+ Work through [Verify your install](./verify.md) again. The gateway deployments
45
+ already in the cluster keep serving through the upgrade; they are rebuilt only
46
+ when you deploy them.
47
+
48
+ ```bash
49
+ kubectl wait --for=condition=Available deployment --all \
50
+ -n zuplo-system --timeout=5m
51
+ helm history zuplo -n zuplo
52
+ ```
53
+
54
+ ## Roll back an upgrade
55
+
56
+ ```bash
57
+ helm rollback zuplo <revision> -n zuplo
58
+ ```
59
+
60
+ Rollback restores the workloads and configuration from the selected revision.
@@ -0,0 +1,279 @@
1
+ ---
2
+ title: Verify Your Install
3
+ sidebar_label: Verify your install
4
+ ---
5
+
6
+ Run the six checks in order. Each check depends on the previous one, which helps
7
+ you identify the source of a failure. Checks one through five require only the
8
+ installation. Check six also requires a Zuplo API key and project.
9
+
10
+ ## Check the deployments
11
+
12
+ Gate on readiness before testing anything over the network.
13
+
14
+ ```bash
15
+ kubectl wait --for=condition=Available deployment --all \
16
+ -n zuplo-system --timeout=5m
17
+ kubectl wait --for=condition=Available deployment --all \
18
+ -n zuplo --timeout=5m
19
+ ```
20
+
21
+ ```
22
+ deployment.apps/control-plane condition met
23
+ deployment.apps/deployer condition met
24
+ deployment.apps/gateway condition met
25
+ deployment.apps/storage condition met
26
+ deployment.apps/acme-forwarder condition met
27
+ deployment.apps/custom-error-pages condition met
28
+ deployment.apps/zuplo-cert-manager condition met
29
+ deployment.apps/zuplo-cert-manager-cainjector condition met
30
+ deployment.apps/zuplo-cert-manager-webhook condition met
31
+ deployment.apps/zuplo-haproxy-ingress condition met
32
+ deployment.apps/zuplo-kube-prometheus-stac-operator condition met
33
+ deployment.apps/zuplo-kube-state-metrics condition met
34
+ deployment.apps/zuplo-prometheus-adapter condition met
35
+ ```
36
+
37
+ The `control-plane`, `deployer`, `gateway`, `storage`, and `acme-forwarder`
38
+ deployments are part of the Zuplo management plane. The other deployments come
39
+ from subcharts.
40
+
41
+ ## Check the ingress
42
+
43
+ Send a request for a hostname that has no Ingress. This checks that the load
44
+ balancer can reach HAProxy.
45
+
46
+ ```bash
47
+ LB=$(kubectl get svc zuplo-haproxy-ingress -n zuplo \
48
+ -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
49
+
50
+ curl -i "http://$LB/" -H 'Host: no-such-deployment.example.com'
51
+ ```
52
+
53
+ ```
54
+ HTTP/1.1 404 Not Found
55
+ content-type: text/html
56
+
57
+ {
58
+ "type": "https://httpproblems.com/http-status/404",
59
+ "title": "Not Found",
60
+ "status": 404,
61
+ "detail": "This Zuplo project does not exist"
62
+ }
63
+ ```
64
+
65
+ The expected result is `404 Not Found` from HAProxy's default backend. A timeout
66
+ or refused connection means that traffic isn't reaching the ingress controller.
67
+
68
+ Use a hostname without an Ingress for this check. Hosts with an Ingress redirect
69
+ port 80 to HTTPS and return a `302` instead.
70
+
71
+ :::note
72
+
73
+ Requests for hosts with an Ingress are redirected from port 80 to 443. The
74
+ separate challenge Ingress created by cert-manager continues to serve ACME
75
+ challenge paths on port 80.
76
+
77
+ :::
78
+
79
+ ## Check the control plane
80
+
81
+ The control plane turns your values into a `Configuration` resource, then
82
+ creates the management API's Ingress from it.
83
+
84
+ ```bash
85
+ kubectl get configuration default -n zuplo-system -o yaml
86
+ ```
87
+
88
+ ```yaml
89
+ spec:
90
+ account:
91
+ name: acme-corp
92
+ builder:
93
+ registry: us-docker.pkg.dev/acme-corp/zuplo-gateways
94
+ secretName: builder-secret
95
+ deployments:
96
+ subdomain: api.example.com
97
+ certificates:
98
+ certManager:
99
+ issuer: zuplo-cluster-issuer
100
+ managementApi:
101
+ hostname: zuplo-admin.example.com
102
+ ingressControllers:
103
+ - haproxy
104
+ ```
105
+
106
+ Confirm every value matches what you put in `zuplo-values.yaml`. A
107
+ single-cluster installation has no `workers` or `authorization` entry. Those
108
+ settings are for installations that distribute deployments across clusters.
109
+
110
+ Then confirm the reconciler acted on the rest:
111
+
112
+ ```bash
113
+ kubectl get ingress -n zuplo-system
114
+ kubectl get clusterissuer
115
+ ```
116
+
117
+ ```
118
+ NAME CLASS HOSTS ADDRESS PORTS AGE
119
+ gateway-haproxy haproxy zuplo-admin.example.com 203.0.113.24 80, 443 62s
120
+
121
+ NAME READY STATUS AGE
122
+ zuplo-cluster-issuer True The ACME account was registered with the ACME server 116s
123
+ ```
124
+
125
+ `READY: True` for `zuplo-cluster-issuer` means that the chart registered an
126
+ account with the certificate authority. It doesn't indicate whether a
127
+ certificate has been issued.
128
+
129
+ :::note
130
+
131
+ `Configuration` doesn't report a status. Check the Ingress and ClusterIssuer
132
+ resources that it produces instead.
133
+
134
+ :::
135
+
136
+ ## Check certificate issuance
137
+
138
+ Check that the certificate authority issued a certificate for the management API
139
+ hostname:
140
+
141
+ ```bash
142
+ kubectl get certificate -A
143
+ ```
144
+
145
+ ```
146
+ NAMESPACE NAME READY SECRET AGE
147
+ zuplo-system gateway-cert-manager True gateway-cert-manager 4m
148
+ ```
149
+
150
+ `READY: True` means that the certificate authority validated your hostname and
151
+ issued a certificate. If it remains `False` for more than a few minutes, see
152
+ [Troubleshooting](./troubleshooting.md).
153
+
154
+ cert-manager retries automatically after you fix DNS. You don't need to restart
155
+ it.
156
+
157
+ ## Check the management API
158
+
159
+ Send an unauthenticated request to check DNS, the load balancer, HAProxy, the
160
+ certificate, and authentication:
161
+
162
+ ```bash
163
+ curl -i https://zuplo-admin.example.com/v1/deployments
164
+ ```
165
+
166
+ ```
167
+ HTTP/2 401
168
+
169
+ {
170
+ "type": "https://httpproblems.com/http-status/401",
171
+ "title": "Unauthorized",
172
+ "status": 401,
173
+ "detail": "No Authorization Header",
174
+ ...
175
+ }
176
+ ```
177
+
178
+ The expected result is `401 Unauthorized`. It confirms that `curl` completed a
179
+ TLS handshake with a trusted certificate and that the gateway requires an API
180
+ key. A TLS error indicates a certificate problem. A timeout indicates a DNS or
181
+ load balancer problem.
182
+
183
+ Confirm the certificate is the real one rather than HAProxy's self-signed
184
+ fallback:
185
+
186
+ ```bash
187
+ echo | openssl s_client -connect zuplo-admin.example.com:443 \
188
+ -servername zuplo-admin.example.com 2>/dev/null |
189
+ openssl x509 -noout -subject -issuer
190
+ ```
191
+
192
+ ```
193
+ subject=CN=zuplo-admin.example.com
194
+ issuer=C=US, O=Let's Encrypt, CN=YR2
195
+ ```
196
+
197
+ An issuer of `CN=kubernetes-ingress-ca` means HAProxy is serving its built-in
198
+ fallback certificate because no issued certificate is available. Repeat the
199
+ certificate issuance check.
200
+
201
+ ## Deploy and call a project
202
+
203
+ The final check builds a gateway image in your cluster, stores it in your
204
+ registry, and serves it from your infrastructure.
205
+
206
+ Deploy your project with the Zuplo CLI. The `project` field in `zuplo.jsonc`
207
+ selects the project, and Zuplo routes the deployment to your cluster:
208
+
209
+ ```bash
210
+ export ZUPLO_API_KEY='<your Zuplo API key>'
211
+
212
+ npx zuplo deploy
213
+ ```
214
+
215
+ Zuplo compiles the project, then hands the compiled bundle to your cluster's
216
+ management API, which builds the container image and rolls it out.
217
+
218
+ While the command runs, watch the build Job in your cluster:
219
+
220
+ ```bash
221
+ kubectl get jobs -n zuplo-system -w
222
+ ```
223
+
224
+ ```
225
+ NAME STATUS COMPLETIONS DURATION AGE
226
+ build-basic-main-ca9748b-ztcwzdd Running 0/1 32s 32s
227
+ build-basic-main-ca9748b-ztcwzdd Complete 1/1 58s 63s
228
+ ```
229
+
230
+ Confirm that the deployment uses an image from your registry:
231
+
232
+ ```bash
233
+ kubectl get deploy -n zuplo -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.template.spec.containers[0].image}{"\n"}{end}'
234
+ ```
235
+
236
+ ```
237
+ basic-main-ca9748b us-docker.pkg.dev/acme-corp/zuplo-gateways/basic-main-ca9748b:20260806-172436
238
+ ```
239
+
240
+ Ask the management API what it is serving:
241
+
242
+ ```bash
243
+ curl -H "Authorization: Bearer $ZUPLO_API_KEY" \
244
+ https://zuplo-admin.example.com/v1/deployments
245
+ ```
246
+
247
+ ```json
248
+ {
249
+ "data": [
250
+ {
251
+ "projectName": "basic",
252
+ "deploymentName": "basic-main-ca9748b-haproxy",
253
+ "deploymentUrl": "https://basic-main-ca9748b.api.example.com"
254
+ }
255
+ ]
256
+ }
257
+ ```
258
+
259
+ Call the deployed API:
260
+
261
+ ```bash
262
+ curl https://basic-main-ca9748b.api.example.com/hello
263
+ ```
264
+
265
+ The first request to a deployment can fail while cert-manager issues its
266
+ certificate. Retry the request for up to a minute.
267
+
268
+ :::note
269
+
270
+ The CLI can misreport the status of deployments to self-hosted clusters. See
271
+ [Troubleshooting](./troubleshooting.md#failed-to-deploy-the-environment-but-the-cluster-shows-the-build-succeeding).
272
+ Use the in-cluster checks to confirm the result.
273
+
274
+ :::
275
+
276
+ ## Resolve a failed check
277
+
278
+ [Troubleshooting](./troubleshooting.md) lists errors from these checks and their
279
+ causes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zuplo",
3
- "version": "7.5.5",
3
+ "version": "7.5.7",
4
4
  "type": "module",
5
5
  "description": "The programmable API Gateway",
6
6
  "author": "Zuplo, Inc.",
@@ -19,9 +19,9 @@
19
19
  "zuplo": "zuplo.js"
20
20
  },
21
21
  "dependencies": {
22
- "@zuplo/cli": "7.5.5",
23
- "@zuplo/core": "7.5.5",
24
- "@zuplo/runtime": "7.5.5",
25
- "@zuplo/test": "7.5.5"
22
+ "@zuplo/cli": "7.5.7",
23
+ "@zuplo/core": "7.5.7",
24
+ "@zuplo/runtime": "7.5.7",
25
+ "@zuplo/test": "7.5.7"
26
26
  }
27
27
  }