agentsclimarketplace

Nginx to traefik

Skill qwedsazxc78/devops-ai-skill/skills/nginx-to-traefik

Class-swap migration that ports services from NGINX Ingress to Traefik Ingress (`ingressClassName: traefik`) while keeping both controllers running in parallel. DNS A-records are the only cutover lever. Designed for eye-of-horus-gitops conventions: nginx files move to archive/ (never deleted), Traefik Ingresses live in kustomization.resources (never patches), backend Service names and secretName are written verbatim (Kustomize namePrefix does not touch them). Operator-declared LB IPs only — never auto-derived from cluster state. State stored in docs/reports/nginx-to-traefik/<slug>/.From its SKILL.md

Install
npx -y skills add qwedsazxc78/devops-ai-skill --skill nginx-to-traefik

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 10 stars10 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.6 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it

nginx-to-traefik Skill

Invoked by Zeus pipeline *nginx-to-traefik.

This skill is the first half of the chained migration NGINX → Traefik Ingress → Gateway API. Used standalone it ports a batch of services to Traefik while leaving the NGINX controller serving everyone else. Used under skill nginx-to-gateway (the orchestrator), its state.yaml output is consumed as the input to skill gateway-api-migration with --source-class traefik.

Canonical references

FileWhen to read
references/nginx-to-traefik-env-config.mdStep 0b — env-config schema and operator prompts
references/annotation-translation.mdStep 3 — annotation mapping
references/dns-cutover-runbook.mdStep 10 — printed/linked at end of run

Bundled scripts

ScriptUsed byPurpose
scripts/inventory_nginx_ingresses.pyStep 1Per-overlay nginx Ingress inventory
scripts/generate_traefik_ingress.pyStep 3Emit <service>-traefik-ingress.yaml
scripts/update_kustomization.pyStep 5, 6Idempotent edits to kustomization.yaml + app.ingress.yaml
scripts/validate_cross_consistency.shStep 7b4-way DNS↔verify↔ingress↔cert cross-check

Activation

Triggered explicitly by *nginx-to-traefik from Zeus. Not auto-triggered.

Invocation forms

*nginx-to-traefik                              # interactive: inventory + propose batches
*nginx-to-traefik <env>                        # process all services in one env
*nginx-to-traefik <env> <batch>                # named batch (b1 | b2)
*nginx-to-traefik <env> <service>              # single service
*nginx-to-traefik --resume                     # continue from state.yaml

Step Flow

StepActionScript
0Tool check (kustomize, yq, git)inline command -v
0bLoad references/nginx-to-traefik-env-config.md; prompt operator for Traefik + nginx LB IPs if missing, write to config, then continueinline
1Inventory active nginx ingresses per envinventory_nginx_ingresses.py
2Propose batch plan, wait for y/N confirmationinline
3Generate <service>-traefik-ingress.yaml per servicegenerate_traefik_ingress.py
4git mv nginx file to archive/inline
5Edit kustomization.yaml: add Traefik file to resources:, drop nginx from patches:update_kustomization.py
6Update common.traefik/overlays/<env>/app.ingress.yaml managed-cert host listupdate_kustomization.py
7kustomize build both modules for the envinline
7b4-way consistency checkvalidate_cross_consistency.sh
8Update scripts/dns-create-traefik.sh batch listinline
9Update scripts/verify-traefik-<env>.sh URL listinline
10Print commit message + file list (never auto-commit)inline

Step 0 — Tool check

Run command -v kustomize yq git. HALT on any missing.

Step 0b — Env-config

Read references/nginx-to-traefik-env-config.md. If state.yaml.envConfig is missing entries for the target env, issue the 5 prompts listed in the reference and write the captured values back. Never derive LB IPs from any cluster resource — this is invariant §5.3 from the spec.

Step 1 — Inventory

Invoke inventory_nginx_ingresses.py --overlay-dir <common.service/overlays/<env>>. Filter to ingressClass == "nginx". Write to state.yaml.inventory[]. HALT if zero nginx ingresses found.

Step 2 — Batch plan

Group inventory entries by host TLD + service criticality. Default batches: b1 = read-mostly services, b2 = write-heavy services. Print the proposed batch plan and ask y/N. HALT on decline.

Step 3 — Generate Traefik Ingress per service

For each service in the active batch, invoke generate_traefik_ingress.py --input <service>-nginx-ingress.yaml --output <service>-traefik-ingress.yaml. Capture stderr WARN lines into state.yaml.warnings[]. Compute SHA256 of each output for state.yaml.outputs.traefikIngresses[].sha256.

Step 4 — Archive nginx file

git mv <service>-nginx-ingress.yaml archive/. HALT if the file is already under archive/. Backup the pre-edit path in state.yaml.backups[].

Step 5 — Kustomization resource edit

update_kustomization.py --overlay-dir <overlay> \
  --replace <service>-nginx-ingress.yaml=<service>-traefik-ingress.yaml \
  --drop-patch <service>-nginx-ingress.yaml

The script is idempotent: re-running step 5 on a complete state is a no-op.

Step 6 — Managed-cert host list

For each new Traefik Ingress, ensure its primary host is present in common.traefik/overlays/<env>/app.ingress.yaml.spec.tls[].hosts and spec.rules[].host. Use update_kustomization.py --app-ingress <path> --add-host <host>.

Step 7 — kustomize build

kustomize build common.service/overlays/<env> > /tmp/svc-build.yaml
kustomize build common.traefik/overlays/<env> > /tmp/traefik-build.yaml

HALT on non-zero exit. Roll back step 4–6 via git restore of backed-up files.

Step 7b — Cross-consistency check

Invoke validate_cross_consistency.sh with the four host sources. HALT on non-zero exit. The stderr stale-host list goes into the report.

Step 8 — DNS script update

Locate scripts/dns-create-traefik.sh. Find or create the array HOSTS_<ENV_UPPER>_<BATCH_UPPER>=(...). Insert each new host (idempotent via grep -q before append). Record the diff in state.yaml.steps["8"].

Step 9 — Verify script update

Same pattern as Step 8 but URLS_<ENV>_<BATCH> in scripts/verify-traefik-<env>.sh. URL format: https://<host>/.

Step 10 — Print commit message and file list

Never auto-commit. Print:

  1. The full set of files touched (Step 3 outputs + Step 4 moves + Step 5/6 edits + Step 8/9 edits).
  2. A suggested commit message in Conventional Commits zh-TW style.
  3. A pointer to references/dns-cutover-runbook.md for the operator to follow after the commit lands.

State file (state.yaml)

The state file lives at docs/reports/nginx-to-traefik/<slug>/state.yaml where <slug> is <env>-<batch>-<isodate>. Schema:

schemaVersion: 1
skillVersion: "1.0.0"
env: dev
batch: b1
createdAt: 2026-05-14T10:00:00Z
envConfig:
  capturedAt: <iso>
  envs:
    dev: { nginxLbIp: ..., traefikLbIp: ..., certIssuer: ..., managedCertNamespace: ..., managedCertResourceName: ... }
inventory:
  - { file: argocd-nginx-ingress.yaml, name: argocd-server, namespace: argocd, hosts: [argocd.dev.example.com] }
batchPlan:
  b1: [argocd-server, grafana]
outputs:
  traefikIngresses:
    - { file: argocd-traefik-ingress.yaml, host: argocd.dev.example.com, namespace: argocd, backend: argocd-server, port: 80, sha256: <hex> }
backups:
  - { path: argocd-nginx-ingress.yaml, restorePath: archive/argocd-nginx-ingress.yaml }
steps:
  "0":  { status: pass }
  "0b": { status: pass, prompts: 0 }
  "1":  { status: pass, count: 2 }
  "2":  { status: pass, confirmed: true }
  "3":  { status: pass, generated: 2, warnings: 0 }
  "4":  { status: pass, moved: 2 }
  "5":  { status: pass, edits: 2 }
  "6":  { status: pass, hostsAdded: 2 }
  "7":  { status: pass }
  "7b": { status: pass, staleHosts: [] }
  "8":  { status: pass, hostsAdded: 2 }
  "9":  { status: pass, urlsAdded: 2 }
  "10": { status: pass }
warnings: []
verdict: COMPLETE

The outputs.traefikIngresses[] list is the hand-off contract for skill C (nginx-to-gateway): when chained, skill C reads this list and passes --source-class traefik --source-state <statePath> to skill B.

Halt conditions

StepHalt cause
0Required tool missing
0bOperator declines to supply env-config values
1Zero nginx Ingresses found
2Operator declines batch plan
3generate_traefik_ingress.py exit code != 0
4File already under archive/
5kustomization.yaml schema mismatch
7kustomize build non-zero
7bCross-consistency check non-zero

After halt, the skill writes state.yaml.verdict: HALTED with the failing step. --resume re-runs from the failed step.

What ships with it: 7 files

23.3 KB alongside SKILL.md, 4 of them executable

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.