The 09-01 package referenced a nonexistent Cloudron etcd addon and an unpinned base image. Rewritten: digest-pinned apisix 3.18.0 with an embedded single-node etcd, loopback-only Admin API, and read-only rootfs support. Deployed live at apigw.knownelement.com (healthz 200). Umbrella: https://projects.knownelement.com/issues/632
75 lines
3.0 KiB
Markdown
75 lines
3.0 KiB
Markdown
# APISIX Cloudron Package
|
|
|
|
**DEPLOYED**: `https://apigw.knownelement.com` (production Cloudron, 2026-09-07)
|
|
|
|
## Description
|
|
|
|
Apache APISIX is a dynamic, real-time, high-performance API Gateway. It
|
|
provides rich traffic management features such as load balancing, dynamic
|
|
upstream, canary release, circuit breaking, authentication, observability
|
|
and more.
|
|
|
|
## Package design
|
|
|
|
- **Base image**: `apache/apisix:3.18.0-debian` (pinned by tag AND digest).
|
|
- **Embedded etcd**: Cloudron has no etcd addon, so a single-node etcd
|
|
(copied from `quay.io/coreos/etcd` v3.5.33, digest-pinned) runs inside
|
|
the container, state under `/app/data/etcd`. This keeps the Admin API
|
|
and dynamic routes available with zero platform dependencies.
|
|
- **Read-only rootfs ready**: Cloudron 8 mounts app root filesystems
|
|
read-only. `start.sh` relocates the APISIX runtime tree (CLI, deps,
|
|
generated `config.yaml`, `nginx.conf`, logs, sockets) to
|
|
`/app/data/apisix` via `APISIX_PREFIX` and a path-patched CLI copy.
|
|
- **Ports**: only the proxy port (9080) is served; Cloudron terminates
|
|
TLS and proxies `https://apigw.knownelement.com` to it. In-container
|
|
TLS is disabled.
|
|
|
|
## Authentication / admin access
|
|
|
|
The **Admin API listens on 127.0.0.1:9180 only** - it is never published.
|
|
It is protected by a random 64-hex-char key persisted at
|
|
`/app/data/.admin_key` (rotating it invalidates automation clients).
|
|
|
|
Operate the gateway from the host (or any admin shell):
|
|
|
|
```bash
|
|
# read the admin key
|
|
cloudron exec -a apigw.knownelement.com cat /app/data/.admin_key
|
|
|
|
# example: list routes (from inside the app container)
|
|
cloudron exec -a apigw.knownelement.com curl \
|
|
-H "X-API-Key: $KEY" http://127.0.0.1:9180/apisix/admin/routes
|
|
```
|
|
|
|
Data-plane auth (key-auth, jwt-auth, OIDC relay, IP restriction, ...) is
|
|
per-route and configured by the operator through the Admin API - the
|
|
gateway itself has no user concept.
|
|
|
|
## Operator notes
|
|
|
|
- **Routes persist** in the embedded etcd across restarts and Cloudron
|
|
backups (state is under `/app/data`).
|
|
- **Health**: Cloudron's healthcheck hits `/` (a 404 counts as alive);
|
|
`/healthz` returns 200 for external monitoring.
|
|
- **Real client IPs** are restored from the Cloudron proxy's
|
|
`X-Forwarded-For` (RFC1918 trusted).
|
|
- **etcd tuning**: auto-compaction every hour keeps the embedded store
|
|
small; single-node by design (gateway config is reproducible from
|
|
infrastructure-as-code, not a durability concern).
|
|
|
|
## Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `Dockerfile` | Pinned base image + etcd/etcdctl binaries + start.sh |
|
|
| `start.sh` | etcd lifecycle, config generation, health route seed |
|
|
| `CloudronManifest.json` | Package manifest (localstorage only) |
|
|
| `sbom.cyclonedx.json` | SBOM [#834] (syft, pinned container) |
|
|
|
|
## History
|
|
|
|
The original package (2026-09-01) used a nonexistent Cloudron "etcd
|
|
addon" and an unpinned `apache/apisix:latest` - it could never have
|
|
installed. Rewritten 2026-09-07 (embedded etcd, digest pins, read-only
|
|
rootfs support) and deployed to production; see JOURNAL.md §20.
|