feedc0de 01185ad0bc
Validate and deploy Anubis / Validate manifests (push) Successful in 12s
Validate and deploy Anubis / Deploy to Kubernetes (push) Successful in 35s
Add existing anubis deployment and add CI/CD
2026-09-04 10:43:09 +02:00
2026-09-04 10:36:18 +02:00

Gitea Anubis protection

This repository deploys Anubis 1.27.0 in front of selected public Gitea paths on code.brunner.ninja. It uses a pinned container image, a Traefik ForwardAuth middleware, restricted Gitea Actions deployment credentials, and an out-of-repository signing key.

Protected routes

Anubis is used for:

  • repository and API paths belonging to the current third-party mirror owners;
  • the complete EFeru owner subtree, including the owner page itself;
  • comparison pages under every owner, including feedc0de.

The existing catch-all Gitea route remains unprotected, so login, about, explore, owner pages other than EFeru, and every feedc0de/* repository remain unchanged outside their comparison pages.

Proof-of-work difficulty is 6 and authorization cookies expire after one hour. Each additional difficulty level multiplies expected work by 16. Solve time is random and depends on the client's CPU and browser.

Repository contents

  • anubis.yaml: policy ConfigMap, Deployment, Service, Middleware, and IngressRoute.
  • install.sh: signing-key creation, server-side dry-run, apply, and rollout.
  • robots.txt: the matching Gitea crawler policy installed on arschrock.
  • test.sh: local shell and Kubernetes schema validation.
  • ci-deployer.yaml: restricted Gitea Actions identity and revocable token.
  • create-ci-kubeconfig.sh: one-time CI credential bootstrap.
  • .gitea/workflows/deploy.yml: validation for pushes and pull requests, plus deployment after successful validation of main.

Install manually

With an administrator kubeconfig active, run:

./install.sh

The installer creates default/gitea-anubis-key only if it is missing. That Secret contains Anubis's Ed25519 signing key and is deliberately neither stored in Git nor accessible to the CI identity. The script then validates and applies anubis.yaml, restarts Anubis so policy-only changes take effect, and waits up to five minutes for the rollout.

Validate locally

./test.sh

This checks both shell scripts and validates the Kubernetes resources with kubeconform. Traefik resources are skipped by schema validation because the standard catalog does not contain the cluster-specific CRDs; the Kubernetes API validates them during the deployment's server-side dry-run.

Automatic deployment with Gitea Actions

The workflow validates every push and pull request. A successful push to main applies anubis.yaml and waits up to five minutes for Anubis to become ready. CI substitutes the Git commit SHA into the pod-template annotation, so a ConfigMap-only policy edit starts a new pod instead of leaving the old policy in memory.

The workflow requires one Gitea Actions repository secret:

  • KUBE_CONFIG_BASE64: a base64-encoded, restricted Anubis deployment kubeconfig.

One-time CI setup

  1. Run ./install.sh with an administrator identity so all application resources already exist.

  2. Run:

    ./create-ci-kubeconfig.sh
    

    If kubectl is available only through arschrock, use remote mode:

    KUBECTL_SSH_HOST=arschrock ./create-ci-kubeconfig.sh
    
  3. Copy only the final base64 line into the Gitea repository Actions secret named KUBE_CONFIG_BASE64.

  4. Protect main, require successful validation before merging, and review manifest and workflow changes.

  5. Push a harmless README change and confirm that the deployment job succeeds.

The workflow matches the existing brunner.ninja runner: Kubernetes API https://host.containers.internal:6443, with TLS server name 192.168.0.2.

CI can get, patch, and update only these existing named objects in default:

  • ConfigMap gitea-anubis-policy;
  • Deployment and Service gitea-anubis;
  • Middleware gitea-anubis;
  • IngressRoute code-brunner-ninja-anubis.

It cannot create or delete resources, cannot access the Kubernetes Secrets API, and has no permission over legacy-gitea-service. Revoke CI access by deleting default/gitea-anubis-deployer-token and the Gitea repository secret. Rerun create-ci-kubeconfig.sh to issue a replacement token.

Kubernetes RBAC cannot constrain individual fields inside an allowed Deployment patch. A malicious change merged into main could alter the pod specification, so branch protection and review remain part of the security boundary.

Gitea robots.txt

Install robots.txt as /var/lib/gitea/custom/public/robots.txt on arschrock, owned by gitea:gitea, then restart Gitea. Gitea requires a restart to load new custom public files. This host-level file is documented in the repository but is not changed by CI.

Scope maintenance

The mirror-owner list was generated from Gitea's public repository API on 2026-08-31. Add newly created third-party mirror owners to both robots.txt and the two owner expressions in anubis.yaml. Comparison pages are matched generically and need no owner-list maintenance.

S
Description
Anubis is used in my cluster to protect cpu-intensive webpages like git compares on gitea, to keep out nasty AI and crawler bots
Readme GPL-3.0
58 KiB
Languages
Shell 100%