Simple Voice Chat was advertising a blank voice_host, causing clients to
try connecting to the pod's internal IP over UDP. Explicitly set
voice_host=mudcraft.nook.family:24454 via ConfigMap + initContainer.
LuckPerms reads config.yml as a literal string — ${LP_PASSWORD} was
never being substituted, causing auth failures against PostgreSQL.
initContainer now has the secret injected as an env var and uses sed
to write the real password into the config before LuckPerms reads it.
Also adds faultexception to WHITELIST so they can connect.
Existing /data/plugins/LuckPerms/ dir on PVC was created by root, so
UID 1000 couldn't create subdirs (libs/, etc.). fsGroup:1000 tells k8s
to chown all volume mounts to group 1000 at pod startup, fixing access.
LuckPerms was failing with AccessDeniedException on /data/plugins/LuckPerms/libs
because the initContainer was creating directories as root. Main container runs
as UID 1000 and couldn't write inside them. Running initContainer as matching
UID 1000 fixes ownership.
SubPath mounts into plugin directories were causing k8s to create those
directories owned by root before the server process could write to them.
LuckPerms was failing with "Unable to create libs directory" as a result.
Move config injection to the initContainer: it now cleans stale JARs
(rm *.jar), copies fresh JARs from the plugins image, and pre-creates
the LuckPerms and PurpurExtras directories with configs copied from
ConfigMaps. Main container no longer mounts configs via subPath.
Also fixes stale JAR accumulation — initContainer now clears old JARs
before copying, preventing broken old versions from loading.
- LuckPerms stores all permissions/groups in Postgres (not ephemeral ops.json)
- Mount luckperms config.yml from ConfigMap with DB connection details
- LP_PASSWORD injected from same secret as DB_PASSWORD
- OPS env var kept as bootstrap until LuckPerms admin group is configured
- Expose UDP 24454 on mudcraft pod and Service (Simple Voice Chat)
- Add Traefik voicechat UDP entrypoint on port 24454
- Add IngressRouteUDP to route external UDP 24454 → mudcraft service
Comprehensive runner image with Python, Node.js 20, Ruby, Go 1.22,
Docker CLI, kubectl, Helm, yq, gh, make, jq, rsync, zstd, and all
standard tools. Mirrors GitHub ubuntu-24.04 hosted runner so workflows
are swappable between Gitea and GitHub with no friction.
Add Node.js 20 LTS (required for all Forgejo JS actions), Python 3.12,
Ruby, Go 1.22, Docker CLI, kubectl, Helm, yq, gh, zstd, and common
build/system tools. Mirrors GitHub ubuntu-24.04 hosted runner capability
so jobs work without needing container: overrides for standard tasks.
Replace Alpine-based legion-runner with a minimal Ubuntu 24.04 image.
The act_runner binary is copied from the official image via multi-stage
build. Job-specific tooling (Ruby, Node, Python, etc.) belongs in
per-job container images specified via container: in workflows, not
in the base runner image.
Rename: legion-runner → ci-base
The Buffering middleware was causing 413 on large Docker layer pushes
by spooling entire request bodies to disk before forwarding. Docker's
chunked blob upload protocol (PATCH/PUT with Content-Range) requires
streaming, not buffering.
Replace with IngressRoute CRDs + Certificate resources for direct
streaming passthrough. responseForwarding.flushInterval=100ms ensures
prompt chunk delivery to the registry backend.
code.forgejo.org maintains up-to-date mirrors of common GitHub Actions
(checkout, upload-artifact, etc.) and is the recommended source for
Gitea Actions runners.
- external-secrets.yaml: GITEA_INSTANCE_URL changed from cluster-internal
URL to https://git.neuralplatform.ai so runner can register externally
- gitea.yaml: add GITEA__actions__DEFAULT_ACTIONS_URL=gitea so all
actions/* references resolve from gitea.com, not github.com
- Dockerfile: track runner image (Python 3.12 + build deps) in repo