fix(api-gateway): rewrite APISIX package and deploy to production

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
This commit is contained in:
2026-09-07 10:02:09 -05:00
parent d8bc507741
commit 17a3e8e9c0
7 changed files with 260 additions and 359 deletions
+54 -168
View File
@@ -1,188 +1,74 @@
# 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.
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.
## Features
## Package design
### Core Capabilities
- **Dynamic Configuration**: Hot updates and hot plugins without restarts
- **Multi-Protocol Support**: HTTP/HTTPS, TCP/UDP, Dubbo, MQTT, gRPC, WebSocket
- **Load Balancing**: Multiple load balancing strategies
- **Security**: IP restrictions, JWT authentication, API Key authentication
- **Traffic Management**: Rate limiting, circuit breaking, canary releases
- **Observability**: Prometheus metrics, distributed tracing
- **AI Gateway**: Support for LLM proxying and AI workloads
- **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.
### Gateway Features
- Proxy Rewrite (host, URI, schema, method, headers)
- Upstream Health Checks
- Request/Response Transformation
- CORS Support
- Web Application Firewall (WAF) via plugins
- OpenID Connect integration
## Authentication / admin access
## Configuration
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).
### Etcd Connection
APISIX requires an etcd instance for configuration storage. The Cloudron package automatically configures this connection using Cloudron's etcd addon.
### Environment Variables
- `CLOUDRON_ETCD_HOST`: Etcd host (automatically set by Cloudron)
- `CLOUDRON_ETCD_PORT`: Etcd port (automatically set by Cloudron)
- `ADMIN_KEY`: Admin API key (default: admin-key-secret-change-me, **change this in production**)
### Ports
- **9180**: Admin API port (for configuration via REST API)
- **9080**: HTTP proxy port (client requests)
- **9443**: HTTPS proxy port (client requests with SSL)
## Usage
### 1. Configure Routes via Admin API
APISIX provides a RESTful Admin API for configuration:
Operate the gateway from the host (or any admin shell):
```bash
# List all routes
curl http://localhost:9180/apisix/admin/routes/ \
-H 'X-API-KEY: admin-key-secret-change-me'
# read the admin key
cloudron exec -a apigw.knownelement.com cat /app/data/.admin_key
# Create a new route
curl http://localhost:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: admin-key-secret-change-me' \
-X PUT -d '{
"uri": "/hello",
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
# 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
```
### 2. Test the Gateway
```bash
# Test via HTTP
curl http://localhost:9080/hello
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.
# Test via HTTPS (after configuring SSL)
curl -k https://localhost:9443/hello
```
## Operator notes
### 3. Add SSL Certificates
```bash
curl http://localhost:9180/apisix/admin/ssls/1 \
-H 'X-API-KEY: admin-key-secret-change-me' \
-X PUT -d '{
"cert": "...",
"key": "...",
"snis": ["example.com"]
}'
```
- **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).
### 4. Configure Plugins
APISIX supports 100+ plugins for various capabilities:
## Files
```bash
# Enable rate limiting
curl http://localhost:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: admin-key-secret-change-me' \
-X PATCH -d '{
"plugins": {
"limit-count": {
"count": 10,
"time_window": 60,
"rejected_code": 429
}
}
}'
```
| 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) |
## Security
## History
### Change Default Admin Key
The default admin key is `admin-key-secret-change-me`. **Change this immediately after installation**:
```bash
# Get current admin key from Cloudron environment
# Update in /usr/local/apisix/conf/config.yaml
# Restart APISIX
```
### Use HTTPS in Production
Always use HTTPS (port 9443) for production deployments. Configure SSL certificates via the Admin API.
### IP Restrictions
Configure IP restrictions to limit who can access the Admin API:
```bash
curl http://localhost:9180/apisix/admin/routes/1 \
-H 'X-API-KEY: admin-key-secret-change-me' \
-X PATCH -d '{
"plugins": {
"ip-restriction": {
"whitelist": ["192.168.1.0/24"]
}
}
}'
```
## Architecture
```
┌─────────────┐
│ Client │
└──────┬──────┘
┌──────────────┐
│ APISIX │
│ (Gateway) │
└──────┬──────┘
┌──────────────┐
│ Upstream │
│ Services │
└──────────────┘
┌──────────────┐
│ Etcd │
│ (Config DB) │
└──────────────┘
```
## Documentation
For more information on configuring APISIX:
- [Official Documentation](https://apisix.apache.org/docs/)
- [Admin API Reference](https://apisix.apache.org/docs/apisix/admin-api/)
- [Plugin Configuration](https://apisix.apache.org/docs/apisix/plugins/)
- [Best Practices](https://apisix.apache.org/docs/general/faq)
- [AI Gateway Guide](https://apisix.apache.org/ai-gateway/)
## Troubleshooting
### APISIX won't start
1. Check etcd connectivity: `curl http://localhost:2379/health`
2. Review logs in `/usr/local/apisix/logs/error.log`
3. Verify configuration syntax in `/usr/local/apisix/conf/config.yaml`
### Routes not working
1. Check Admin API key is correct
2. Verify upstream servers are accessible
3. Check firewall rules allow traffic to ports 9080/9443
4. Review route configuration via Admin API
### Performance issues
1. Increase worker processes in nginx_config
2. Enable HTTP/2 for better performance
3. Consider horizontal scaling (multiple APISIX instances)
## Upstream
[GitHub Repository](https://github.com/apache/apisix)
[Apache Project Page](https://apisix.apache.org/)
[Official Docker Images](https://hub.docker.com/r/apache/apisix)
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.