Security modes
aptly itself has no authentication — upstream explicitly warns against putting
the REST API directly on the internet. This repo solves that with an nginx sidecar
(Compose: its own container; Helm: a second container in the same pod, aptly only
listens on 127.0.0.1).
The four presets
security.preset |
Read (apt clients) | Read auth | Write (/api/) |
Write auth |
|---|---|---|---|---|
open |
on | no | on | no |
publicRead (default) |
on | no | on | yes |
authenticated |
on | yes | on | yes |
readOnly |
on | no | off (404) | — |
open is the "completely unsecured" option you asked for — one line, no
confirmation gate:
security:
preset: open
Health probes (/api/ready, /api/healthy) are reachable without credentials in
every mode — otherwise Kubernetes/Compose could never recognize the instance as
healthy.
Every cell individually reachable
security.read.* and security.write.* explicitly override the preset:
security:
preset: authenticated
read:
requireAuth: false # = publicRead, just spelled out explicitly
The Ingress split (Helm) — what it actually does
ingress:
mode: split
api:
enabled: true
host: aptly-api.example.com
This creates two Ingress objects (different host, different
annotations/TLS/ingressClass possible) — but both point at the same Service.
nginx itself does not check which host a request arrived on; /api/ is reachable
through both hosts, as long as security.write.enabled allows it. The split is
therefore a pure Ingress/DNS feature (e.g. a separate certificate or a WAF only on
the API host), not a hard network separation. For real isolation:
security.write.inClusterOnly: true (then renders no API Ingress at all — an honest
implementation, not an nginx trick) or a networkPolicy.
The CIDR pitfall
security:
write:
allowCIDRs: ["10.42.0.0/16"]
Behind an Ingress controller, $remote_addr in nginx is the controller's pod IP,
not the real client — allowCIDRs without trustedProxies then matches practically
everyone. Set security.trustedProxies to your Ingress controller's CIDR (enables
X-Forwarded-For evaluation), or use a networkPolicy for real L3 restriction. If
trustedProxies is missing while allowCIDRs is set, the chart renders a
# WARNING line directly into the nginx config.
Unsigned
aptly:
gpg:
enabled: false
Sets gpg_disable_sign: true in the aptly config and Signing.Skip: true in
every publish call the reconcile job makes — both are needed; aptly's publish API
takes its own signing parameter per call and ignores the global config flag
(empirically verified). The client then needs [trusted=yes] instead of
signed-by=.