Public Access
Initial implementation: aptly container image, Compose stacks, Helm chart, and Gitea Actions pipelines
Provides a self-contained, containerized aptly (Debian repo manager) stack with independently releasable image and Helm chart versions. - images/: aptly-server (aptly built from source, cross-compiled) and aptly-deb-builder (nfpm + dpkg-buildpackage) container images - rootfs/: shared aptly-init/aptly-reconcile/aptly-push/aptly-pack scripts consumed identically by Compose and the Helm chart, driven by one declarative state.yaml contract - compose/: test (ephemeral, open) and production docker-compose stacks with an nginx read/auth sidecar - charts/aptly/: aptly-native Helm chart covering every security posture from fully open to authenticated read+write, Ingress and Gateway API support (usable in parallel for migration scenarios), metrics, and declarative repo/mirror/publish reconciliation via a Helm hook - .gitea/workflows/: CI (lint, template, kubeconform, E2E smoke test) plus separately tagged image (image/v*) and chart (chart/v*) releases, weekly rebuilds, and a preflight workflow validating the runner's Docker/Helm-OCI capabilities - pubkeys/: RSA chart-signing key for Helm --sign / Artifact Hub's signKey annotation (Helm can't verify Ed25519 keys) - docs/, README.md, charts/aptly/README.md: usage, security, and versioning documentation
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
# Production stack: security.preset "publicRead" equivalent — reads are
|
||||
# open (apt clients need no credentials), the mutating API is behind Basic
|
||||
# Auth. aptly itself is never published to the host; only nginx is. See
|
||||
# docs/security.md for how to move to the other three presets (fully open,
|
||||
# fully authenticated, or read-only), and .env.example for every variable
|
||||
# used below.
|
||||
#
|
||||
# First run:
|
||||
# cp .env.example .env && edit it
|
||||
# cp config/users.example config/users && edit it (at least change the password)
|
||||
# docker compose up -d
|
||||
# docker compose logs -f aptly-init # check for GPG warnings
|
||||
services:
|
||||
aptly-init:
|
||||
image: git.morlana.online/f.weber/aptly:${APTLY_IMAGE_TAG:-latest}
|
||||
entrypoint: ["/usr/local/bin/aptly-init"]
|
||||
environment:
|
||||
APTLY_GPG_ENABLED: "${APTLY_GPG_ENABLED:-true}"
|
||||
# Fixed in-container paths — put your key material at the host paths
|
||||
# below (an empty/missing directory is fine: aptly-init then warns and
|
||||
# publishes unsigned instead of failing to start).
|
||||
APTLY_GPG_PRIVATE_KEY_FILE: "/etc/aptly-secrets/gpg/private.asc"
|
||||
APTLY_GPG_PASSPHRASE_FILE: "/etc/aptly-secrets/gpg/passphrase"
|
||||
APTLY_USERS_FILE: "/etc/aptly-secrets/users"
|
||||
APTLY_INTERNAL_USER: "aptly-internal"
|
||||
APTLY_INTERNAL_PASSWORD: "${APTLY_INTERNAL_PASSWORD:?set APTLY_INTERNAL_PASSWORD in .env}"
|
||||
volumes:
|
||||
- ./config/aptly.yaml:/etc/aptly-src/aptly.yaml:ro
|
||||
- ./config/users:/etc/aptly-secrets/users:ro
|
||||
- ${APTLY_GPG_DIR:-./config/gpg}:/etc/aptly-secrets/gpg:ro
|
||||
- aptly_run:/run/aptly
|
||||
restart: "no"
|
||||
|
||||
aptly:
|
||||
image: git.morlana.online/f.weber/aptly:${APTLY_IMAGE_TAG:-latest}
|
||||
depends_on:
|
||||
aptly-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
APTLY_API_LISTEN: "0.0.0.0:8080"
|
||||
volumes:
|
||||
- aptly_data:/var/lib/aptly
|
||||
- aptly_run:/run/aptly
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/api/healthy"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
start_period: 10s
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 1g
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
nginx:
|
||||
image: nginxinc/nginx-unprivileged:1-alpine
|
||||
depends_on:
|
||||
aptly:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- aptly_data:/var/lib/aptly:ro
|
||||
- aptly_run:/run/aptly:ro
|
||||
- ./config/nginx.prod.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
ports:
|
||||
- "${APTLY_PUBLISH_PORT:-8080}:8080"
|
||||
read_only: true
|
||||
tmpfs:
|
||||
- /tmp
|
||||
- /var/cache/nginx
|
||||
- /run
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/healthz"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256m
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
# --- TLS via an external reverse proxy (recommended) ---
|
||||
# Put Traefik/Caddy/whatever you already run in front of this service
|
||||
# instead of terminating TLS here. Traefik label example:
|
||||
# labels:
|
||||
# - "traefik.enable=true"
|
||||
# - "traefik.http.routers.aptly.rule=Host(`apt.example.com`)"
|
||||
# - "traefik.http.routers.aptly.tls.certresolver=letsencrypt"
|
||||
|
||||
reconcile:
|
||||
image: git.morlana.online/f.weber/aptly:${APTLY_IMAGE_TAG:-latest}
|
||||
depends_on:
|
||||
aptly:
|
||||
condition: service_healthy
|
||||
entrypoint: ["/usr/local/bin/aptly-reconcile"]
|
||||
environment:
|
||||
APTLY_URL: "http://aptly:8080"
|
||||
APTLY_STATE_FILE: "/state.yaml"
|
||||
APTLY_FAIL_ON_ERROR: "${APTLY_RECONCILE_FAIL_ON_ERROR:-false}"
|
||||
volumes:
|
||||
- ./config/state.yaml:/state.yaml:ro
|
||||
restart: "no"
|
||||
|
||||
# Run on demand: docker compose --profile backup run --rm backup
|
||||
backup:
|
||||
image: git.morlana.online/f.weber/aptly:${APTLY_IMAGE_TAG:-latest}
|
||||
profiles: ["backup"]
|
||||
entrypoint: ["/bin/sh", "-c"]
|
||||
command:
|
||||
- >
|
||||
set -eu;
|
||||
ts=$$(date -u +%Y%m%dT%H%M%SZ);
|
||||
tar -C /var/lib/aptly --exclude=.gnupg -c . | zstd -q -o "/backup/aptly-$${ts}.tar.zst";
|
||||
echo "wrote /backup/aptly-$${ts}.tar.zst"
|
||||
volumes:
|
||||
- aptly_data:/var/lib/aptly:ro
|
||||
- ${APTLY_BACKUP_DIR:-./backup}:/backup
|
||||
|
||||
volumes:
|
||||
aptly_data:
|
||||
aptly_run:
|
||||
Reference in New Issue
Block a user