# 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.
