Compare commits

..

64 Commits

Author SHA1 Message Date
unkin-agent 461e3c6530 Add public main.unkin.net and edge.unkin.net zones to bind-external
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
2026-10-19 22:08:48 +11:00
unkin-agent e8b1a41af1 bump artifactapi to v3.19.0 (#563)
v3.19.0 adds local and virtual goproxy repositories.

- pin api, ui and image-keeper to v3.19.0

Reviewed-on: #563
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-19 22:07:09 +11:00
unkin-agent 1379e0bf79 bump artifactapi to v3.18.0 (#562)
v3.18.0 adds the ansible Galaxy remote plus local and virtual ansible repositories.

- pin api, ui and image-keeper to v3.18.0

Reviewed-on: #562
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-18 19:03:40 +11:00
unkin-agent d3df1c03cd bump artifactapi to v3.17.1 (#561)
v3.17.1 adds local and virtual gems repositories with yank tombstones, owner-checked Redis locks, and fails GitHub scans on asset errors.

- pin api, ui and image-keeper to v3.17.1

Reviewed-on: #561
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-18 02:49:49 +11:00
unkin-agent d0932a6946 bump artifactapi to v3.16.0 (#560)
v3.16.0 adds local and virtual npm, the gems remote, HEAD on remotes, and fixes mutable refresh and per-request host handling.

- pin api, ui and image-keeper to v3.16.0

Reviewed-on: #560
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-17 22:00:21 +11:00
unkin-agent 7aee011da1 bump artifactapi to v3.15.0 (#559)
v3.15.0 adds local helm and puppet repos, the nuget remote and a shared virtual merge cache.

- pin api, ui and image-keeper to v3.15.0

Reviewed-on: #559
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-17 16:16:43 +11:00
unkin-agent 9aea107185 bind-operator: v0.4.0 (#558)
bind-operator v0.4.0 applies config changes with `rndc reconfig` instead of restarting pods, which records the result in a new `status.appliedConfig` field and a `ConfigApplied` condition. It also renders `forwarders { };` for forward zones with no forwarders.

- bump the bind-operator image to v0.4.0
- bump the CRD install URL to the v0.4.0 tag

Reviewed-on: #558
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-17 15:33:16 +11:00
unkin-agent 3057392c35 mail: use real edge MTA public IPs (#556)
The edge gateways now exist, so the smarthost and rspamd trust their real public IPs instead of the TEST-NET placeholders.

- set mta1 (66.226.148.207) and mta2 (66.226.149.50) in smarthost gateways.cidr
- allow both in the smarthost NetworkPolicy
- trust both in the rspamd external_relay ip_map

Reviewed-on: #556
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-17 12:51:26 +11:00
unkin-agent 331d96278d bind-internal: add mail edge A records (#557)
The lab resolver is authoritative for unkin.net and main.unkin.net, so names that exist only in public DNS return NXDOMAIN internally. The edge MTAs and the smarthost resolve these names through it.

- add mail-in.main.unkin.net A 103.216.191.185 (home WAN)
- add mta1.edge.unkin.net A 66.226.148.207
- add mta2.edge.unkin.net A 66.226.149.50
- records mirror public DNS

Reviewed-on: #557
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-17 12:50:56 +11:00
unkin-agent 2493e729f4 bind-resolvers: forward to public resolvers, RBLs direct (#555)
Recursing public names in-cluster SERVFAILs a few percent of cold lookups and loses the cache on every restart, which breaks CI. DNSBLs refuse or poison queries relayed via public resolvers, so rspamd's RBL lookups must keep resolving directly.

- add global forwarders 1.1.1.1 and 8.8.8.8 (forward first) to bind-resolvers
- add empty-forwarder zones to the openforwarder view for the RBL domains rspamd queries, so they resolve iteratively

Reviewed-on: #555
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-16 23:29:33 +11:00
unkin-agent 8ea58cb6c1 Allow the bne dmz vpc in the resolver dmz acl (#554)
The second mail edge site moves to BinaryLane Brisbane (VPC 172.18.32.0/24), whose hosts resolve through the internal resolvers over the vpn.

- add 172.18.32.0/24 to acl-dmz

Reviewed-on: #554
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-16 23:09:20 +11:00
unkin-agent 9188ef9ac3 bind-resolvers: stop querying IPv6 nameservers (#553)
The in-cluster BIND resolvers have no IPv6 route but still try every AAAA nameserver. Each attempt fails with "network unreachable" yet counts toward the per-query recursion budget, so cold lookups of names with many dual-stack NS (registry.opentofu.org, cloudfront, crates.io, gcr.io) hit `quota reached` and SERVFAIL, surfacing as transient DNS errors in CI.

- mark all IPv6 servers bogus in the openforwarder view so recursion is IPv4-only

Reviewed-on: #553
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-16 22:34:48 +11:00
unkin-agent 8a1d544393 Enable Vault OIDC auth on artifactapi config writes (#552)
artifactapi v3.14.0 can require a Vault-issued bearer JWT for writes to /api/v2/remotes and /api/v2/virtuals, so config changes stop being open to anything in-cluster.

- bump artifactapi and artifactapi-ui images to v3.14.0
- set ARTIFACTAPI_OIDC_ISSUER to the Vault identity OIDC issuer and ARTIFACTAPI_OIDC_AUDIENCE to artifactapi

Requires terraform-artifactapi #64 merged first.

Reviewed-on: #552
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-16 22:23:54 +11:00
unkin-agent 9a38cacf54 Move resolver DMZ ACL to the RFC 1918 mail VPC ranges (#551)
BinaryLane only accepts RFC 1918 VPC ranges, so the syd and mel mail DMZ VPCs move from 198.18.30.0/24 and 198.18.31.0/24 to 172.18.30.0/24 and 172.18.31.0/24.

- replace the 198.18.30-31.0/24 entries in acl-dmz with 172.18.30.0/24 and 172.18.31.0/24

Reviewed-on: #551
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-16 21:52:33 +11:00
unkin-agent 52cfabb38f Verify smarthost edge relays against the internal CA (#548)
The edge MTAs present certificates from the internal Vault PKI, so the smarthost cannot verify mta1/mta2.edge.unkin.net against the system CA bundle.

- pin both edge relay TLS policies to the internal CA via `tafile=`
- mount `vault-ca-cert` into the smarthost pods and reload on change

---------

Co-authored-by: BenVincent <benvin@main.unkin.net>
Reviewed-on: #548
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-14 22:06:30 +11:00
unkin-agent 49a98aa428 Add main.unkin.net as a second mail domain (#550)
main.unkin.net is the test mail domain: it receives into the existing unkin.net mailboxes, and its outbound mail is DKIM-signed as d=unkin.net, which aligns under relaxed DMARC.

- relay main.unkin.net on the smarthost and route it to Stalwart over LMTP
- add main.unkin.net as a domain alias of unkin.net in Stalwart

Reviewed-on: #550
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 21:43:43 +11:00
unkin-agent bb45b20f8a Route rspamd-tagged mail to Junk through Stalwart's spam filter (#544)
Stalwart only files mail into Junk natively when its own spam filter marks it, so rspamd-tagged mail reached Junk only for accounts with a Sieve script, and first boot loads upstream DNSBLs, HTTP lists and URL lookups.

- enable the spam filter with one header rule scoring `X-Spam: Yes` above the spam threshold, covering every account including newly provisioned ones
- remove the upstream spam rules, tags, DNSBL servers, HTTP lists and lookup keys
- disable the classifier model and Pyzor

Reviewed-on: #544
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 21:43:13 +11:00
unkin-agent 822d50b07d Allow BinaryLane DMZ VPCs in resolver ACL (#545)
The mail edge VMs in the BinaryLane DMZ VPCs query the internal resolvers over the VPN, but the resolver match-clients ACLs do not include their ranges.

- add 198.18.30.0/24 (syd) and 198.18.31.0/24 (mel) to `acl-dmz`

Reviewed-on: #545
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 21:32:11 +11:00
unkin-agent 283f9e8ac4 Give stalwart-apply a writable HOME (#549)
The stalwart-apply PostSync Job fails with "Read-only file system": stalwart-cli caches the server schema under $HOME/.cache, which sits on the read-only root. The plan never applies, so Stalwart runs without its certificate, listeners or stdout tracer.

- mount a /tmp emptyDir in both Job containers
- set HOME=/tmp for the cli and kubectl (discovery cache)

Reviewed-on: #549
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 21:26:50 +11:00
unkin-agent 02ded6c26b Terminate haproxy edge TLS at Traefik (#547)
Browsers coalesce HTTP/2 connections across *.unkin.net hosts sharing the traefik-external IP. A request for a haproxy-fronted host (e.g. git.unkin.net) on a grafana connection skips SNI passthrough and hits Traefik with no HTTP router, returning 404.

- replace the TLS passthrough listener with an HTTPS listener terminating the three LE wildcards
- replace the haproxy TLSRoute with an HTTPRoute for the same hosts
- add a BackendTLSPolicy re-encrypting to haproxy:443

Reviewed-on: #547
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 21:12:40 +11:00
unkin-agent 82b86072ee Deploy Stalwart into the mail namespace (#539)
Stalwart is the mailbox server for the mail migration and runs multi-node from the start, so it needs a coordinator and a shared in-memory store.

- run Stalwart as a 3-replica StatefulSet with a headless Service, topology spread and a PDB
- add the `mail-valkey` ValkeyCluster as in-memory store and coordinator
- keep data in CNPG Postgres and blobs in cephrgw S3
- converge settings from plan.ndjson in a PostSync Job, then roll the StatefulSet
- add a global `spam-to-junk` Sieve script filing rspamd-tagged mail into Junk and stopping
- exempt LMTP from the inbound throttles, as all inbound mail comes from the smarthost
- label pods as smarthost clients and move the client LoadBalancer to 198.18.200.18

Reviewed-on: #539
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 20:58:08 +11:00
unkin-agent 716ff7c807 Recurse from root hints on bind-resolvers (#546)
DNSBLs such as Spamhaus refuse queries that arrive via public resolvers, and forwarding everything to 8.8.8.8/1.1.1.1 leaves the estate dependent on them. The lab resolvers now do full recursion themselves (DNSSEC-validated via the operator default `dnssec-validation auto` and BIND built-in root hints).

- drop the global forwarders from the bind-resolvers BindCluster
- keep the per-zone forwarders for unkin.net, consul, k8s and reverse zones unchanged

Reviewed-on: #546
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-13 20:53:37 +11:00
unkin-agent 0ee11a065b Add rspamd, ClamAV and sentinel Valkey to the mail namespace (#542)
The smarthost routes all mail through one rspamd: inbound that survived the edge gets the AI (LiteLLM Haiku) pass and is tagged for Stalwart's Junk filing; outbound from the lab and pods is DKIM-signed.

- add rspamd (milter via ClusterIP only), ClamAV and a 3-node sentinel Valkey
- tag inbound (`X-Spam`, `X-Spam-Status`, `X-Spamd-Result`), reject only viruses, tempfail when ClamAV fails
- score inbound against the hop before the edge relays (`external_relay`)
- DKIM-sign and skip GPT only for the smarthost's mynetworks sources
- elect the highest-offset Valkey on full restart; RDB, 384mb `volatile-ttl`
- read a hashed controller password (`password_hash`)

Requires `password_hash` in kv `mail/default/rspamd-controller`.

Reviewed-on: #542
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 22:36:55 +11:00
unkin-agent 70dd1bd775 Add postfix smarthost to the mail namespace (#541)
Mail needs one routing hub between the edge gateways, Stalwart and the lab: inbound to Stalwart over LMTP, outbound to the gateways, all of it through rspamd.

- add a 2-replica postfix StatefulSet `mail-in.main.unkin.net` (50Gi spool per pod, node spread, PDB)
- serve port 25 with the LE `*.main.unkin.net` wildcard, reflected into `mail`
- gateways (TLS, XFORWARD) relay to relay_domains with LMTP recipient verification; lab and pods relay anywhere
- pass all mail through the rspamd milter, tempfailing when it is down
- limit port 25 via NetworkPolicy to gateways, lab and `mail.unkin.net/smarthost-client=true` pods
- relay outbound via mta1/mta2.edge.unkin.net with verified TLS; add ClusterIP + LB 198.18.200.16

Requires #539 merged.

Reviewed-on: #541
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 22:30:47 +11:00
unkin-agent 07584e5179 bind-internal: point mail.unkin.net at 198.18.200.18 (#543)
The internal A record for mail.unkin.net used 198.18.200.11, which Consul (#531) claims; Stalwart's LoadBalancer moved to 198.18.200.18 in #539.

- point mail.unkin.net A record at 198.18.200.18

Merge with or after #539.

Reviewed-on: #543
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 22:16:56 +11:00
unkin-agent 47fe9e085a Add internal mail.unkin.net A record (#540)
Mail clients on the lab network reach Stalwart at mail.unkin.net, served by the stalwart-lb PureLB VIP.

- add an internal unkin.net A record for mail pointing at 198.18.200.11

Requires argocd-apps #539 for the VIP to answer.

Reviewed-on: #540
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 21:26:06 +11:00
unkin-agent 1d9b7ec924 Add mail namespace with Stalwart backing stores (#538)
Stalwart needs a Postgres metadata store and an S3 blob store before it can be deployed into the new `mail` namespace.

- add CNPG Cluster `stalwart-db` (db/owner `stalwart`, CNPG-minted `stalwart-db-app` creds) with barman backups to a dedicated `cnpg-mail` bucket and a nightly ScheduledBackup
- add cephrgw Bucket `stalwart-blobs` with an owner user writing RW keys to `stalwart-blobs-s3`
- add the au-syd1 overlay, platform ApplicationSet path and project destination

Reviewed-on: #538
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 00:25:41 +11:00
unkin-agent fc7d69644c Add terraform-binarylane woodpecker service account (#537)
The new terraform-binarylane repo needs a Woodpecker ServiceAccount for its CI pipelines to authenticate to Vault.

- add serviceaccount_terraform_binarylane.yaml in the woodpecker namespace
- add it to the woodpecker base kustomization

Reviewed-on: #537
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-12 00:22:04 +11:00
unkin-agent 045c7ff009 Bump pdbmux to v0.5.0 (#536)
v0.5.0 answers AST name queries for pdbmux_source and reports the backend host as its value.

- bump pdbmux image to v0.5.0

Reviewed-on: #536
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-10 14:39:01 +11:00
unkin-agent 69f2a2a6ec add artifactapi image-keeper daemonset (#535)
artifactapi pulls its own images from itself, so a cold boot with every api pod down cannot pull them. Kubelet GC never removes images referenced by pods on the node, so a pod on every node holding the pinned tags keeps them local.

- add image-keeper DaemonSet referencing the api and ui images as no-op init containers
- run a static busybox as `true` inside the distroless api image
- tolerate all taints, run at low priority with tiny non-root resources

Reviewed-on: #535
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-10 01:06:10 +11:00
unkin-agent f89927b1f4 bump artifactapi to v3.13.1 (#534)
v3.13.1 adds rpm virtual repos, the cargo remote type and GitHub scan retry; its images now publish to docker-internal instead of the Gitea registry.

- pin api and ui to docker-internal/artifactapi{,-ui}:v3.13.1

Reviewed-on: #534
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 23:25:52 +11:00
unkin-agent 7960ee03f9 pin artifactapi back to v3.12.0 (#532)
The v3.13.0 images were never published (registry push failed), so the current pin cannot be pulled.

- pin api and ui images back to v3.12.0

Reviewed-on: #532
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 22:52:29 +11:00
unkin-agent 393100430b Bump artifactapi to v3.13.0 (#529)
Bump artifactapi API and UI images from v3.12.0 to v3.13.0.

- Update git.unkin.net/unkin/artifactapi to v3.13.0
- Update git.unkin.net/unkin/artifactapi-ui to v3.13.0

Reviewed-on: #529
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 22:48:05 +11:00
unkin-agent 5024945c74 consul: remove standalone k8s consul (#530)
The standalone k8s Consul runs its own raft under DC `au-syd1`, the same DC name as the VM cluster that k8s servers are about to join. Its leftover state risks a split brain, so it goes before the replacement lands.

- remove `apps/overlays/au-syd1/consul`, dropping `platform-consul` from the platform ApplicationSet and cascading deletion of the `consul` namespace and PVCs
- keep `apps/base/consul` for reuse by the replacement

Reviewed-on: #530
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 22:46:40 +11:00
unkin-agent 87880ac8ef kea: bump to v0.1.7 from docker-internal (#527)
v0.1.7 stops the operator reconcile hot-loop, which was hot-reloading Kea about 9 times a second and flooding the dhcp-system logs. Images now publish to docker-internal.

- bump kea-operator, kea and kea-api to v0.1.7
- pull all three from artifactapi docker-internal

Reviewed-on: #527
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 21:49:33 +11:00
unkin-agent 7ac84461ce consul: pull chart via artifactapi helm mirror (#528)
The consul overlay fetches its chart directly from helm.releases.hashicorp.com, while the other 15 helm overlays on the estate mirror use the artifactapi virtual helm repo, which already proxies hashicorp-helm.

- point consul helmCharts repo at the artifactapi virtual helm repo

Reviewed-on: #528
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-09 21:49:13 +11:00
unkin-agent 9b857bef64 logging: expose vlselect on internal traefik (#525)
Querying the VLCluster from outside the cluster (CLI tools, puppet VMs) needs a resolvable TLS endpoint for vlselect, mirroring the existing logs-ingest endpoint for vlinsert.

- add `vlselect` Gateway on `traefik-internal` with vault-issuer TLS and external-dns for `vlselect.k8s.syd1.au.unkin.net`
- add HTTP->HTTPS redirect route and HTTPS route to `vlselect-logs:9471`, unauthenticated

Reviewed-on: #525
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-05 14:08:33 +11:00
unkin-agent d1825bb655 authentik: raise server cpu request to 500m (#526)
authentik-server requests only 50m CPU, so on busy nodes it is starved, `/-/health/live/` exceeds the 3s liveness timeout and kubelet restarts it (~100 restarts per pod).

- raise `server.resources.requests.cpu` from 50m to 500m

Reviewed-on: #526
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-05 14:07:45 +11:00
unkin-agent 206fe90f80 Raise puppetserver compiler requests to match real usage (#524)
Compiler pods average ~2Gi memory but request 1Gi, so the scheduler overpacks nodes and the HPA's utilisation target is skewed.

- raise compiler requests to 1 cpu / 2Gi and limits to 4 cpu / 4Gi
- scale up faster (30s window, 75%) and down slower (600s window)

Reviewed-on: #524
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-05 12:34:19 +11:00
unkin-agent 6d842c7d66 feat(bind-internal): publish haproxy edge sites from k8s DNS (#523)
The VM haproxies are being decommissioned; the sites they published via puppet CNAMEs are already served by the k8s haproxy edge, so k8s DNS publishes them instead.

- add main.unkin.net A records for sonarr, radarr, lidarr, readarr, prowlarr, nzbget, jellyfin -> 198.18.199.0
- add unkin.net A records for fafflix and git (git-edge.yaml) -> 198.18.199.0, auth -> 198.18.200.4
- point the commented git.yaml cutover at replacing git-edge.yaml

Merge alongside puppet-prod halb DNS removal; A records only take effect once the puppet CNAMEs are gone.

Reviewed-on: #523
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-05 01:31:06 +11:00
unkin-agent d9cc24dbdb Serve grafana.unkin.net from traefik-external (#522)
grafana.unkin.net still routes through the puppet haproxy edge to the old grafana VMs; the k8s grafana should serve it directly like identity and vlogs.

- add grafana-external Gateway (traefik-external, *.unkin.net wildcard) with redirect + main HTTPRoutes
- reflect wildcard-unkin-net-tls into grafana
- set grafana root_url to https://grafana.unkin.net
- add grafana A record -> 198.18.199.0 in the bind-operator unkin.net zone
- drop grafana.unkin.net from the k8s haproxy routes and config

Requires terraform-authentik grafana redirect URI PR applied first, and the puppet halb vrrp_cnames grafana.unkin.net CNAME removed.

Reviewed-on: #522
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-05 00:38:21 +11:00
unkin-agent 115cdd492f Bump artifactapi to v3.12.0 (#521)
artifactapi v3.12.0 makes DELETE eviction clear every cache layer, so stale mutable indexes (e.g. epel repomd) no longer survive eviction. It also adds `?prefix=` filtering to object listings.

- bump artifactapi and artifactapi-ui images to v3.12.0

Reviewed-on: #521
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-04 23:41:15 +11:00
unkin-agent 9375052d6c Set traefik resource requests so HPAs can scale (#520)
Both traefik HPAs report `ScalingActive False: missing request for cpu` because the chart values set no container resources, so the CPU-utilisation metric can't be computed and neither Deployment ever scales.

- traefik-external requests 200m CPU / 128Mi, memory limit 512Mi
- traefik-internal requests 500m CPU / 256Mi, memory limit 1Gi
- No CPU limits, to avoid throttling the proxy
- The chart derives GOMEMLIMIT (90% of the memory limit) from the new limits

Reviewed-on: #520
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-04 15:27:49 +11:00
unkin-agent af61ac5e92 Set traefik-external externalTrafficPolicy to Local (#519)
With the default Cluster external policy, kube-proxy SNATs inbound traffic to the traefik-external LoadBalancer, hiding real client IPs from traefik and adding a cross-node hop. Local preserves source IPs. Internal policy stays Cluster so in-cluster callers on nodes without a traefik-external pod still reach it.

- Set `externalTrafficPolicy: Local` on the traefik-external Service
- Set `internalTrafficPolicy: Cluster` explicitly

Reviewed-on: #519
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-04 15:26:23 +11:00
unkin-agent 2bcce4894f Drop git.unkin.net from k8s gitea gateway and routes (#518)
git.unkin.net is served by the VM haproxy during the forge migration. Claiming it on the k8s gitea Gateway/HTTPRoutes competes with that path, so the k8s gitea serves only its admin name until cutover.

- remove git.unkin.net from the gitea HTTPRoute and redirect route hostnames
- remove the http-primary/https-primary listeners and their parentRefs
- set the gateway cert common-name to git.k8s.syd1.au.unkin.net

Reviewed-on: #518
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-04 15:07:08 +11:00
unkin-agent b0bfa4605f vmagent: raise kubernetes-apiservers max_scrape_size to 64MiB (#517)
The kubernetes-apiservers job reports up=0 on every target because the apiserver /metrics response exceeds vmagent's default 16MiB scrape size limit.

- set max_scrape_size: 64MiB on the kubernetes-apiservers job only

Reviewed-on: #517
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-04 14:01:14 +11:00
unkin-agent cc0dd24991 vmagent: fix consul target address relabel (#516)
The consul job joins node and port with ":" but then sets `replacement: "${1}:${2}"` with the default `(.*)` regex, so `__address__` becomes `node:port:`. vmagent rejects every consul target as an invalid port, including node_exporter.

- drop the replacement so the default `$1` yields `node:port`

Reviewed-on: #516
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-03 22:51:46 +10:00
unkin-agent 27dd7e7f3d vmagent: cap consul SD wait time under nginx timeout (#515)
nginx in front of Consul closes requests at 90s. vmagent's consul SD sends blocking queries with a 525s wait, so every watch fails with a 504 and the consul job finds no targets. That leaves no puppet-host metrics (node_exporter etc.) in VictoriaMetrics.

- set `promscrape.consul.waitTime: 50s` on the main VMAgent

Reviewed-on: #515
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-03 22:15:16 +10:00
unkin-agent 96624a69c4 Rename the terraform-infra CI ServiceAccount to terraform-netbox (#514)
terraform-infra is replaced by terraform-netbox, whose Vault kubernetes auth role binds the terraform-netbox service account in the woodpecker namespace.

- rename serviceaccount_terraform_infra to serviceaccount_terraform_netbox

Pairs with terraform-vault #161 (the auth role) and terraform-git #105 (the repo).

Reviewed-on: #514
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-03 09:34:19 +10:00
unkin-agent 73cb3903c2 Add k8up Grafana dashboard (#513)
With k8up operator metrics now scraped into VictoriaMetrics, backup job and schedule state still has no dashboard to view it.

- add the k8up dashboard from M0NsTeRRR/grafana-dashboards as a gzipped GrafanaDashboard CR
- resolve its datasource to the in-cluster VictoriaMetrics uid
- register it in the grafana kustomization

Reviewed-on: #513
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 23:29:40 +10:00
unkin-agent 575bd5d361 Scrape k8up operator metrics (#512)
The k8up operator already serves Prometheus metrics (backup/check/prune job counts, controller-runtime) on its k8up-metrics Service, but nothing scrapes them, so backup health is invisible in VictoriaMetrics.

- add a VMServiceScrape for the k8up-metrics Service (port http, /metrics)

Reviewed-on: #512
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 23:28:59 +10:00
unkin-agent 79e8ccb3d8 feat(grafana): sync kubernetes dashboards from victoria-metrics-k8s-stack (#511)
Grafana lacks Kubernetes cluster/workload dashboards; the victoria-metrics-k8s-stack sync-job ships a maintained set as GrafanaDashboard CRs.

- render victoria-metrics-k8s-stack 0.95.0 in the grafana overlay with only the dashboard sync-job enabled
- sync dotdc kubernetes-views/api-server and kube-prometheus dashboards via the artifactapi github_user remote
- skip dashboards already in apps/base/grafana and those without scraped metrics
- trust vault-ca-cert for artifactapi TLS

Requires terraform-artifactapi #49 applied first.

Reviewed-on: #511
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 23:04:57 +10:00
unkin-agent 5a8559e97c grafana: drop alerting Service and POD_IP env owned by grafana-operator (#510)
grafana-operator already creates the headless `grafana-alerting` Service (port 9094) and injects `POD_IP` into the grafana container, so the copies added in #509 make Argo CD and the operator fight over the same objects.

- remove `service-alerting.yaml` from the grafana base
- remove the `POD_IP` env entry from the Grafana CR
- keep the `unified_alerting` `ha_*` config, which targets the operator's Service

Reviewed-on: #510
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 22:44:54 +10:00
unkin-agent ec60a8c9d7 grafana: enable unified alerting HA gossip (#509)
Grafana runs 3 replicas with no alerting HA config, so every replica sends every notification.

- add headless `grafana-alerting` Service exposing gossip on 9094 TCP/UDP
- inject `POD_IP` from `status.podIP` into the grafana container
- set `unified_alerting` `ha_peers`, `ha_listen_address` and `ha_advertise_address` so replicas form one Alertmanager cluster

Reviewed-on: #509
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 22:37:19 +10:00
unkin-agent ee2476fe5d grafana: scale to 3 replicas, raise limits (#508)
A single Grafana pod with a 1 cpu/1Gi limit is a single point of failure and gets throttled under dashboard load. State lives in Postgres, so extra replicas are safe; spreading them keeps a node loss from taking out Grafana.

- set `replicas: 3` on the grafana deployment
- raise grafana container limits to 2 cpu / 4Gi
- spread grafana pods across nodes with a soft hostname topology constraint

Reviewed-on: #508
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-10-02 22:15:25 +10:00
unkin-agent e6e882abfc Give vlogs its own namespace (#507)
The Vault KV layout is kubernetes/namespace/<ns>/<sa>/<secret>, so vlogs and logviewer both running as SA default in the shared logging namespace would collide on one oauth-credentials entry. Splitting vlogs out resolves it without widening any Vault policy.

- Move apps/base/logging/vlogs to apps/base/vlogs, namespace vlogs
- Add namespace.yaml and a vlogs-scoped VaultAuth (role default)
- Point the VaultStaticSecret at kubernetes/namespace/vlogs/default/oauth-credentials
- Add the au-syd1 overlay, platform ApplicationSet path and project destination
- Move the wildcard-unkin-net-tls reflection from logging to vlogs; vlogs was its only consumer there

Secret is already seeded at the new Vault path.

Reviewed-on: #507
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-28 22:55:28 +10:00
unkin-agent c979579c50 Collect pod logs with VLAgent, retire the NATS/ClickHouse chain (#506)
The vector -> JetStream -> ClickHouse chain duplicated storage the in-cluster VictoriaLogs already provides, and its NATS StatefulSet keeps the logging Application from syncing.

- collect pod logs with a VLAgent DaemonSet remote-writing to vlinsert-logs
- delete vector, NATS, ClickHouse, logarchiver and logviewer
- drop clickhouse-system from the logging ApplicationSet

---------

Co-authored-by: BenVincent <benvin@main.unkin.net>
Reviewed-on: #506
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 20:23:58 +10:00
unkin-agent 9f6019b0e4 Drop obsolete vector-test CI pipeline (#505)
Vector is being removed from the logging stack in favour of a VictoriaLogs VLAgent, so every path this pipeline tests is going away and the pipeline becomes dead weight.

- Delete `.woodpecker/vector-test.yaml`.

Companion PR removes the vector manifests under `apps/base/logging/vector/`.

Reviewed-on: #505
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 20:12:45 +10:00
unkinben a5a5cc44e9 Promote bind-operator to v0.3.1 (#503)
bind-operator v0.3.1 fixes the apex NS bug two ways: the operator no longer glues apex NS records to pod IPs, and a new CEL rule on `DNSRecordSpec` rejects apex NS DNSRecords at admission. The CRDs are pinned by tag URL, so bumping only the image would leave the admission half inert.

- Bump the bind-operator image to `v0.3.1`
- Bump the CRD install URL to the matching `v0.3.1` tag

---------

Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Reviewed-on: #503
Co-authored-by: Ben Vincent <ben@unkin.net>
Co-committed-by: Ben Vincent <ben@unkin.net>
2026-09-27 18:11:38 +10:00
unkin-agent be2c751175 Redirect vlogs root to the VictoriaLogs UI (#504)
Visiting https://vlogs.unkin.net/ currently lands on the bare VictoriaLogs index page with relative links, not the query UI.

- Add an Exact `/` rule to the `vlogs` HTTPRoute that 302s to `/select/vmui/`
- Keep the PathPrefix `/` catch-all pointed at `vlogs-oauth2:80`, so auth is unchanged

Reviewed-on: #504
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 18:10:35 +10:00
unkin-agent 216b1d72ac Split bind-internal DNSRecords into one file per record (#501)
records.yaml had grown to ten DNSRecord documents across two zones, so finding or reviewing a single record meant scanning the whole file and every change touched it.

- move each record to authoritative/<zone>/<type>/<record>.yaml
- add a kustomization.yaml per zone and per type directory
- keep the git.unkin.net cutover record commented out, alongside a commented kustomization entry
- move the DNSRecord-namespace rationale onto the authoritative kustomization
- delete records.yaml

Rendered output is unchanged.

Reviewed-on: #501
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 17:43:16 +10:00
unkin-agent 7581578df1 Split bind-external DNSRecords into one file per record (#500)
A single records.yaml holding every DNSRecord means any record change touches a shared file, and deleting one record is a hunk edit rather than a file removal. One file per record under <zone>/<type>/<record>.yaml makes each record independently editable and removable.

- move acme-apex-ns to acme-unkin-net/ns/apex.yaml and acme-ns1-a to acme-unkin-net/a/ns1.yaml
- add kustomization.yaml per zone and type directory, referencing directories from the parent
- carry the delegation rationale onto the zone kustomization
- drop records.yaml and reference the zone directory from the app kustomization

Rendered output is unchanged.

Reviewed-on: #500
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 17:28:37 +10:00
unkin-agent 6515e7f637 Expose VictoriaLogs UI at vlogs.unkin.net behind oauth2-proxy (#498)
The vlselect query UI is only reachable in-cluster, so every log search needs a port-forward. Publish it at vlogs.unkin.net behind oauth2-proxy on the external (DMZ) Traefik.

- Add `apps/base/logging/vlogs`: external Gateway, http->https redirect and main HTTPRoute
- Terminate TLS with the reflected Let's Encrypt `*.unkin.net` wildcard; reflect it into `logging`
- Publish the `vlogs` A record at the DMZ gateway VIP from the bind-operator `unkin.net` zone
- Route all traffic through the `vlogs-oauth2` Service, upstreaming to `vlselect-logs:9471`
- Gate on the Authentik `vlogs` application, group `akP-vlogs-admin`
- Read OIDC credentials from `kv/kubernetes/namespace/logging/default/vlogs-oauth-credentials`

Depends on unkin/terraform-authentik#40.

Reviewed-on: #498
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 17:21:40 +10:00
unkin-agent 90d512fadf Drop the gocache serve Deployment and nginx sidecar (#499)
`connect` mode gives the client no local cache, so every cache operation is a network round trip -- about 2.7x slower than pointing the plugin straight at S3. Developers and CI run the plugin in direct mode instead.

- Remove the `go-cache-plugin serve` Deployment and its nginx stream-proxy ConfigMap
- Remove the PureLB Service, freeing `198.18.200.11`
- Keep the `gocache` bucket and `gocache-s3` Secret for direct-mode clients

Reviewed-on: #499
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
2026-09-27 11:20:59 +10:00
213 changed files with 3532 additions and 3760 deletions
-29
View File
@@ -1,29 +0,0 @@
when:
- event: pull_request
steps:
- name: vector-test
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/timberio/vector:0.57.0-debian
commands:
# Dummy creds + writable dirs so the full topologies build; the unit tests
# only exercise the transforms (sources are not started).
- export CLICKHOUSE_USER=ci CLICKHOUSE_PASSWORD=ci
- export NATS_PRODUCER_PASSWORD=ci NATS_CONSUMER_PASSWORD=ci
- mkdir -p /vector-data-dir /etc/vault-ca
- cp /etc/ssl/certs/ca-certificates.crt /etc/vault-ca/ca.crt
# Transform tier + VM ingest: unit-tested transforms.
- vector test apps/base/logging/vector/aggregator.yaml apps/base/logging/vector/aggregator-tests.yaml
- vector test apps/base/logging/vector/vm-ingest.yaml apps/base/logging/vector/vm-ingest-tests.yaml
# Agent has no transforms to unit-test; validate it builds. (The archiver
# leg is now the logarchiver service, not a Vector pipeline.)
- vector validate --no-environment apps/base/logging/vector/agent.yaml
backend_options:
kubernetes:
serviceAccountName: default
resources:
requests:
memory: 256Mi
cpu: 250m
limits:
memory: 1Gi
cpu: 1
+1 -1
View File
@@ -36,7 +36,7 @@ spec:
mountPath: /combined-certs
containers:
- name: api
image: git.unkin.net/unkin/artifactapi:v3.11.2
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/artifactapi:v3.19.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
+2
View File
@@ -5,6 +5,8 @@ metadata:
name: api-env
namespace: artifactapi
data:
ARTIFACTAPI_OIDC_AUDIENCE: artifactapi
ARTIFACTAPI_OIDC_ISSUER: https://vault.service.consul:8200/v1/identity/oidc
DBHOST: postgres-pooler
DBNAME: artifacts
DBPORT: "5432"
+105
View File
@@ -0,0 +1,105 @@
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: image-keeper
namespace: artifactapi
spec:
selector:
matchLabels:
app: image-keeper
updateStrategy:
rollingUpdate:
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: image-keeper
spec:
automountServiceAccountToken: false
priorityClassName: low
tolerations:
- operator: Exists
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
initContainers:
# artifactapi is distroless with no exit-0 flag, so run a static busybox as `true`
- name: copy-true
image: busybox:1.37.0-musl
imagePullPolicy: IfNotPresent
command: ["cp", "/bin/busybox", "/keeper/true"]
volumeMounts:
- name: keeper
mountPath: /keeper
resources:
limits:
cpu: 10m
memory: 16Mi
requests:
cpu: 1m
memory: 4Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
- name: api
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/artifactapi:v3.19.0
imagePullPolicy: IfNotPresent
command: ["/keeper/true"]
volumeMounts:
- name: keeper
mountPath: /keeper
readOnly: true
resources:
limits:
cpu: 10m
memory: 16Mi
requests:
cpu: 1m
memory: 4Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
- name: ui
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/artifactapi-ui:v3.19.0
imagePullPolicy: IfNotPresent
command: ["true"]
resources:
limits:
cpu: 10m
memory: 16Mi
requests:
cpu: 1m
memory: 4Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
containers:
- name: pause
image: rancher/mirrored-pause:3.6
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 10m
memory: 16Mi
requests:
cpu: 1m
memory: 4Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumes:
- name: keeper
emptyDir: {}
+1
View File
@@ -11,6 +11,7 @@ resources:
- cnpg_pooler.yaml
- gateway.yaml
- httproute.yaml
- image-keeper.yaml
- namespace.yaml
- oauth2-proxy-configmap.yaml
- oauth2-proxy-deployment.yaml
+1 -1
View File
@@ -22,7 +22,7 @@ spec:
automountServiceAccountToken: true
containers:
- name: ui
image: git.unkin.net/unkin/artifactapi-ui:v3.11.2
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/artifactapi-ui:v3.19.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
@@ -3,4 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- ns1.yaml
@@ -0,0 +1,16 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: acme-ns1-a
namespace: bind-external
spec:
zoneRef: acme-unkin-net
name: ns1
type: A
ttl: 3600
values:
# Public address of this cluster's external BIND, same target as
# acme-ns1.unkin.net. Resolvers that cached the seeded ns1.acme.unkin.net
# NS name must still reach the zone.
- 103.216.191.185
@@ -0,0 +1,11 @@
---
# Authoritative delegation records for acme.unkin.net. Without these the zone
# only holds the operator's seed apex (NS ns1.acme.unkin.net glued to the
# primary pod IP), which is unroutable off-cluster and goes stale on
# reschedule. DNSRecords must live in the same namespace as their BindZone.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ns
- a
@@ -0,0 +1,16 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: acme-apex-ns
namespace: bind-external
spec:
zoneRef: acme-unkin-net
# "@" is the zone apex.
name: "@"
type: NS
ttl: 3600
values:
# Matches the parent delegation in Google Cloud DNS. Out of zone, so the
# child needs no glue of its own.
- acme-ns1.unkin.net.
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- apex.yaml
@@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- mta1.yaml
- mta2.yaml
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: edge-mta1-a
namespace: bind-external
spec:
zoneRef: edge-unkin-net
name: "mta1"
type: A
ttl: 3600
values:
- 66.226.148.207
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: edge-mta2-a
namespace: bind-external
spec:
zoneRef: edge-unkin-net
name: "mta2"
type: A
ttl: 3600
values:
- 66.226.149.50
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- a
+3 -1
View File
@@ -7,5 +7,7 @@ resources:
- cluster.yaml
- tsigkey.yaml
- zones.yaml
- records.yaml
- acme-unkin-net
- main-unkin-net
- edge-unkin-net
- agent-dns-rolebinding.yaml
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- mail-in.yaml
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-mail-in-a
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "mail-in"
type: A
ttl: 3600
values:
- 103.216.191.185
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-acme-challenge-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "_acme-challenge"
type: CNAME
ttl: 3600
values:
- _acme-challenge.main.acme.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-au-syd1-pve-api-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "au-syd1-pve-api"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-au-syd1-pve-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "au-syd1-pve"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-grafana-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "grafana"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,15 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- acme-challenge.yaml
- au-syd1-pve.yaml
- au-syd1-pve-api.yaml
- grafana.yaml
- lidarr.yaml
- nzbget.yaml
- prowlarr.yaml
- radarr.yaml
- readarr.yaml
- sonarr.yaml
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-lidarr-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "lidarr"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-nzbget-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "nzbget"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-prowlarr-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "prowlarr"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-radarr-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "radarr"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-readarr-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "readarr"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-sonarr-cname
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "sonarr"
type: CNAME
ttl: 3600
values:
- lb1.unkin.net.
@@ -0,0 +1,9 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- a
- mx
- txt
- cname
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-apex-mx
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "@"
type: MX
ttl: 3600
values:
- "10 mta1.edge.unkin.net."
- "20 mta2.edge.unkin.net."
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- apex.yaml
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-apex-txt
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "@"
type: TXT
ttl: 3600
values:
- '"v=spf1 ip4:66.226.148.207 ip4:66.226.149.50 -all"'
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: main-dmarc-txt
namespace: bind-external
spec:
zoneRef: main-unkin-net
name: "_dmarc"
type: TXT
ttl: 3600
values:
- '"v=DMARC1; p=none; rua=mailto:dmarc@unkin.net; adkim=r; aspf=r"'
@@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- apex.yaml
- dmarc.yaml
-36
View File
@@ -1,36 +0,0 @@
# Authoritative delegation records for acme.unkin.net. Without these the zone
# only holds the operator's seed apex (NS ns1.acme.unkin.net glued to the
# primary pod IP), which is unroutable off-cluster and goes stale on
# reschedule. DNSRecords must live in the same namespace as their BindZone.
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: acme-apex-ns
namespace: bind-external
spec:
zoneRef: acme-unkin-net
# "@" is the zone apex.
name: "@"
type: NS
ttl: 3600
values:
# Matches the parent delegation in Google Cloud DNS. Out of zone, so the
# child needs no glue of its own.
- acme-ns1.unkin.net.
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: acme-ns1-a
namespace: bind-external
spec:
zoneRef: acme-unkin-net
name: ns1
type: A
ttl: 3600
values:
# Public address of this cluster's external BIND, same target as
# acme-ns1.unkin.net. Resolvers that cached the seeded ns1.acme.unkin.net
# NS name must still reach the zone.
- 103.216.191.185
+36
View File
@@ -28,3 +28,39 @@ spec:
type: A
ttl: 3600
values: ["103.216.191.185"]
---
# Public mail zones, delegated from Google Cloud DNS to acme-ns1.unkin.net like
# acme.unkin.net. DNSRecords are applied with the zone's update key.
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: main-unkin-net
namespace: bind-external
spec:
clusterRef: bind-external
zoneName: main.unkin.net
type: primary
defaultTTL: 3600
dynamicUpdate: true
updateKeyRef: certmanager
allowTransfer:
- key certmanager
nameservers:
- acme-ns1.unkin.net.
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindZone
metadata:
name: edge-unkin-net
namespace: bind-external
spec:
clusterRef: bind-external
zoneName: edge.unkin.net
type: primary
defaultTTL: 3600
dynamicUpdate: true
updateKeyRef: certmanager
allowTransfer:
- key certmanager
nameservers:
- acme-ns1.unkin.net.
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: dashboard-ceph-cname
namespace: bind-internal
spec:
zoneRef: ceph-unkin-net
name: dashboard
type: CNAME
ttl: 600
values:
# Ceph mgr dashboard, reached via lb1. Lets in-cluster clients (the
# cephrgw-operator) resolve dashboard.ceph.unkin.net.
- lb1.unkin.net.
@@ -0,0 +1,7 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- dashboard.yaml
- s3.yaml
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: s3-ceph-cname
namespace: bind-internal
spec:
zoneRef: ceph-unkin-net
name: s3
type: CNAME
ttl: 600
values:
# radosgw S3 endpoint. Points at the Consul service for now; the real
# target will be changed later.
- radosgw.service.consul.
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- cname
@@ -2,9 +2,15 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Individually-managed authoritative records live under <zone>/<type>/<record>.yaml.
# DNSRecords must live in the same namespace as their BindZone (the operator
# resolves zoneRef/clusterRef/updateKeyRef within the record's namespace), so
# these sit alongside the zone in bind-internal, not in the app namespace.
resources:
- cluster.yaml
- tsigkey.yaml
- zones.yaml
- records.yaml
- unkin-net
- main-unkin-net
- ceph-unkin-net
- acls.yaml
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: jellyfin-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: jellyfin
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,13 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- jellyfin.yaml
- mail-in.yaml
- lidarr.yaml
- nzbget.yaml
- prowlarr.yaml
- radarr.yaml
- readarr.yaml
- sonarr.yaml
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: lidarr-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: lidarr
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: mail-in-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: mail-in
type: A
ttl: 600
values:
# home WAN (public path for edge to smarthost relay), mirrors public DNS.
- 103.216.191.185
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: nzbget-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: nzbget
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: prowlarr-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: prowlarr
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: radarr-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: radarr
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: readarr-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: readarr
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: sonarr-dns-internal
namespace: bind-internal
spec:
zoneRef: main-unkin-net
name: sonarr
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- a
@@ -1,164 +0,0 @@
# Individually-managed authoritative records for the unkin.net zone.
# DNSRecords must live in the same namespace as their BindZone (the operator
# resolves zoneRef/clusterRef/updateKeyRef within the record's namespace), so
# these sit alongside the zone in bind-internal, not in the app namespace.
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
# "internal" in the name distinguishes this from the external DNS that
# Authentik will manage its own records from later.
name: identity-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: identity
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the authentik Gateway serves the
# identity.unkin.net hostname there.
- 198.18.199.0
---
# PRODUCTION CUTOVER RECORD — intentionally commented out.
# git.unkin.net currently resolves to the LIVE VM forge (HAProxy VRRP VIP
# 198.18.19.17), which holds every repo the estate depends on. Uncommenting this
# repoints the whole org's git.unkin.net at the new k8s Gitea gateway VIP, so it
# is the FINAL step of the forge migration — gated on the data migration (gitea
# dump/restore + SECRET_KEY copy) in argocd-apps docs/gitea-migration.md.
# NOTE: the live git.unkin.net answer is served by the puppet DNS master today
# (profiles::dns::master, records from PuppetDB); this k8s apex zone holds only
# SOA+NS + a few DNSRecords so far. Confirm the k8s bind cluster is the live
# authority for unkin.net (or update the puppet record instead) before relying
# on this CR at cutover.
# ---
# apiVersion: bind.unkin.net/v1alpha1
# kind: DNSRecord
# metadata:
# name: git-dns-internal
# namespace: bind-internal
# spec:
# zoneRef: unkin-net
# name: git
# type: A
# ttl: 600
# values:
# # traefik-internal gateway VIP; the gitea Gateway serves git.unkin.net there.
# - 198.18.200.4
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: s3-ceph-cname
namespace: bind-internal
spec:
zoneRef: ceph-unkin-net
name: s3
type: CNAME
ttl: 600
values:
# radosgw S3 endpoint. Points at the Consul service for now; the real
# target will be changed later.
- radosgw.service.consul.
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: dashboard-ceph-cname
namespace: bind-internal
spec:
zoneRef: ceph-unkin-net
name: dashboard
type: CNAME
ttl: 600
values:
# Ceph mgr dashboard, reached via lb1. Lets in-cluster clients (the
# cephrgw-operator) resolve dashboard.ceph.unkin.net.
- lb1.unkin.net.
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: lb1-unkin-net
namespace: bind-internal
spec:
zoneRef: unkin-net
name: lb1
type: A
ttl: 600
values:
- 103.216.191.185
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: ghp-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: ghp
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the ghp Gateway serves ghp.unkin.net there.
- 198.18.200.4
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: arrstack-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: arrstack
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the arrproxy Gateway serves the
# arrstack.unkin.net front door (oauth2-proxy) there.
- 198.18.199.0
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: logviewer-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: logviewer
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the logviewer Gateway serves
# logviewer.unkin.net there.
- 198.18.200.4
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: cheeztv-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: cheeztv
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the cheeztv Gateway serves cheeztv.unkin.net
# there.
- 198.18.200.4
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: watchstate-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: watchstate
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the watchstate-external Gateway serves
# the watchstate.unkin.net front door (oauth2-proxy) there.
- 198.18.199.0
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: arrstack-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: arrstack
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the arrproxy Gateway serves the
# arrstack.unkin.net front door (oauth2-proxy) there.
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: auth-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: auth
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the kanidm Gateway serves auth.unkin.net there.
- 198.18.200.4
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: cheeztv-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: cheeztv
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the cheeztv Gateway serves cheeztv.unkin.net
# there.
- 198.18.200.4
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: fafflix-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: fafflix
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: ghp-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: ghp
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the ghp Gateway serves ghp.unkin.net there.
- 198.18.200.4
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: git-edge-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: git
type: A
ttl: 600
values:
# traefik-external haproxy edge Gateway VIP (TLS passthrough).
- 198.18.199.0
@@ -0,0 +1,23 @@
---
# PRODUCTION CUTOVER RECORD — intentionally commented out.
# git.unkin.net currently resolves to the haproxy edge (git-edge.yaml), which
# forwards to the LIVE VM forge holding every repo. Uncommenting this
# repoints the whole org's git.unkin.net at the new k8s Gitea gateway VIP, so it
# is the FINAL step of the forge migration — gated on the data migration (gitea
# dump/restore + SECRET_KEY copy) in argocd-apps docs/gitea-migration.md.
# Uncomment this record AND its entry in kustomization.yaml (removing
# git-edge.yaml there) to activate it.
# ---
# apiVersion: bind.unkin.net/v1alpha1
# kind: DNSRecord
# metadata:
# name: git-dns-internal
# namespace: bind-internal
# spec:
# zoneRef: unkin-net
# name: git
# type: A
# ttl: 600
# values:
# # traefik-internal gateway VIP; the gitea Gateway serves git.unkin.net there.
# - 198.18.200.4
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: grafana-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: grafana
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the grafana-external Gateway serves
# grafana.unkin.net there.
- 198.18.199.0
@@ -0,0 +1,17 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
# "internal" in the name distinguishes this from the external DNS that
# Authentik will manage its own records from later.
name: identity-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: identity
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the authentik Gateway serves the
# identity.unkin.net hostname there.
- 198.18.199.0
@@ -0,0 +1,23 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- arrstack.yaml
- auth.yaml
- cheeztv.yaml
- fafflix.yaml
# PRODUCTION CUTOVER RECORD — see git.yaml. Uncomment together with the
# record itself, and remove git-edge.yaml.
# - git.yaml
- ghp.yaml
- git-edge.yaml
- grafana.yaml
- identity.yaml
- lb1.yaml
- logviewer.yaml
- mail.yaml
- mta1-edge.yaml
- mta2-edge.yaml
- vlogs.yaml
- watchstate.yaml
@@ -0,0 +1,13 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: lb1-unkin-net
namespace: bind-internal
spec:
zoneRef: unkin-net
name: lb1
type: A
ttl: 600
values:
- 103.216.191.185
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: logviewer-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: logviewer
type: A
ttl: 600
values:
# traefik-internal gateway VIP; the logviewer Gateway serves
# logviewer.unkin.net there.
- 198.18.200.4
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: mail-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: mail
type: A
ttl: 600
values:
# stalwart-lb PureLB VIP (IMAPS, submission, HTTPS).
- 198.18.200.18
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: mta1-edge-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: mta1.edge
type: A
ttl: 600
values:
# edge MTA 1 public IP, mirrors public DNS.
- 66.226.148.207
@@ -0,0 +1,14 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: mta2-edge-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: mta2.edge
type: A
ttl: 600
values:
# edge MTA 2 public IP, mirrors public DNS.
- 66.226.149.50
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: vlogs-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: vlogs
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the vlogs-external Gateway serves the
# vlogs.unkin.net front door (oauth2-proxy) there.
- 198.18.199.0
@@ -0,0 +1,15 @@
---
apiVersion: bind.unkin.net/v1alpha1
kind: DNSRecord
metadata:
name: watchstate-dns-internal
namespace: bind-internal
spec:
zoneRef: unkin-net
name: watchstate
type: A
ttl: 600
values:
# traefik-EXTERNAL (DMZ) gateway VIP; the watchstate-external Gateway serves
# the watchstate.unkin.net front door (oauth2-proxy) there.
- 198.18.199.0
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- a
@@ -38,6 +38,9 @@ spec:
clusterRef: bind-resolvers
entries:
- 198.18.24.0/24
- 172.18.30.0/24 # BinaryLane DMZ VPC syd (mail edge, via VPN)
- 172.18.31.0/24 # BinaryLane DMZ VPC mel (mail edge, via VPN)
- 172.18.32.0/24 # BinaryLane DMZ VPC bne (mail edge, via VPN)
---
apiVersion: bind.unkin.net/v1alpha1
kind: BindACL
@@ -18,9 +18,10 @@ spec:
purelb.io/service-group: common
purelb.io/addresses: 198.18.200.7
external-dns.alpha.kubernetes.io/hostname: bind-resolvers.k8s.syd1.au.unkin.net
# Public names go via global forwarders; RBL zones bypass them (view.yaml).
forwarders:
- 8.8.8.8
- 1.1.1.1
- 8.8.8.8
# The internal split-horizon zones are served UNSIGNED by the in-cluster
# authoritative, but their public parents publish DS records (e.g. unkin.net
# is DNSSEC-signed on the Internet). With dnssec-validation on, the validator
@@ -21,3 +21,16 @@ spec:
extraOptions:
- "allow-recursion { any; }"
- "allow-query-cache { any; }"
# pods have no IPv6 route; v6 NS attempts burn the recursion-query budget
- "server ::/0 { bogus yes; }"
# RBL zones resolve directly: DNSBLs refuse queries relayed via public resolvers.
- 'zone "spamhaus.org" { type forward; forwarders { }; }'
- 'zone "mailspike.net" { type forward; forwarders { }; }'
- 'zone "spameatingmonkey.net" { type forward; forwarders { }; }'
- 'zone "dnswl.org" { type forward; forwarders { }; }'
- 'zone "virusfree.cz" { type forward; forwarders { }; }'
- 'zone "blocklist.de" { type forward; forwarders { }; }'
- 'zone "msbl.org" { type forward; forwarders { }; }'
- 'zone "surbl.org" { type forward; forwarders { }; }'
- 'zone "uribl.com" { type forward; forwarders { }; }'
- 'zone "rspamd.com" { type forward; forwarders { }; }'
+1 -1
View File
@@ -21,7 +21,7 @@ spec:
runAsNonRoot: true
containers:
- name: operator
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/bind-operator:v0.3.0
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/bind-operator:v0.4.0
args:
- --metrics-bind-address=:8080
- --health-probe-bind-address=:8081
+1 -1
View File
@@ -6,7 +6,7 @@ resources:
- namespace.yaml
# CRDs are pulled from the bind-operator repo at the matching tag rather than
# vendored here, so they never drift from the operator.
- https://git.unkin.net/unkin/bind-operator/raw/tag/v0.3.0/config/crd/install.yaml
- https://git.unkin.net/unkin/bind-operator/raw/tag/v0.4.0/config/crd/install.yaml
- rbac.yaml
- agent-dns-rbac.yaml
- deployment.yaml
@@ -1,6 +1,6 @@
---
# Let's Encrypt *.main.unkin.net wildcard for the haproxy edge (pve, arr stack,
# jellyfin, stalwart webadmin/autoconfig). DNS-01 needs the delegated
# jellyfin, stalwart webadmin/autoconfig) and the mail smarthost. DNS-01 needs the delegated
# _acme-challenge.main.unkin.net CNAME in the public unkin.net zone.
# _acme-challenge.main.unkin.net. CNAME _acme-challenge.main.acme.unkin.net.
apiVersion: cert-manager.io/v1
@@ -13,9 +13,9 @@ spec:
secretTemplate:
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "haproxy"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "haproxy,mail"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "haproxy"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "haproxy,mail"
privateKey:
size: 4096
dnsNames:
@@ -14,9 +14,9 @@ spec:
secretTemplate:
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "cheeztv,arrstack,authentik,gitea,watchstate,mediamark,repospawner,haproxy"
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "cheeztv,arrstack,authentik,gitea,watchstate,mediamark,repospawner,haproxy,vlogs,grafana,mail"
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "cheeztv,arrstack,authentik,gitea,watchstate,mediamark,repospawner,haproxy"
reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "cheeztv,arrstack,authentik,gitea,watchstate,mediamark,repospawner,haproxy,vlogs,grafana,mail"
privateKey:
size: 4096
dnsNames:
@@ -1,7 +0,0 @@
---
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/name: clickhouse-system
name: clickhouse-system
+1 -1
View File
@@ -11,7 +11,7 @@ metadata:
argocd.argoproj.io/sync-wave: "1"
spec:
replicas: 1
image: git.unkin.net/unkin/kea-api:v0.1.3
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/kea-api:v0.1.7
tokenSecretName: kea-api-token
service:
type: ClusterIP
+1 -1
View File
@@ -11,7 +11,7 @@ metadata:
argocd.argoproj.io/sync-wave: "1"
spec:
replicas: 2
image: git.unkin.net/unkin/kea:v0.1.3
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/kea:v0.1.7
domainName: main.unkin.net
defaultLeaseTime: 1200
maxLeaseTime: 86400
+1 -1
View File
@@ -21,7 +21,7 @@ spec:
runAsNonRoot: true
containers:
- name: operator
image: git.unkin.net/unkin/kea-operator:v0.1.5
image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/kea-operator:v0.1.7
args:
- --metrics-bind-address=:8080
- --health-probe-bind-address=:8081
+3 -31
View File
@@ -1,11 +1,6 @@
---
# HTTPS front for the k8s Gitea, served on two names:
# git.unkin.net — canonical/production (apex, bind-operator zone;
# DNS flip is the gated cutover step, see the doc)
# git.k8s.syd1.au.unkin.net — admin/backup route (external-dns k8s.syd1 zone),
# same dual-name pattern as identity.unkin.net.
# The cert-manager Certificate (vault-issuer) takes CN git.unkin.net and gets a
# DNS SAN for each TLS listener hostname automatically.
# HTTPS front for the k8s Gitea on git.k8s.syd1.au.unkin.net (external-dns
# k8s.syd1 zone). git.unkin.net stays on the VM haproxy until cutover.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
@@ -17,36 +12,13 @@ metadata:
traefik.io/instance: internal
annotations:
cert-manager.io/cluster-issuer: vault-issuer
cert-manager.io/common-name: git.unkin.net
cert-manager.io/common-name: git.k8s.syd1.au.unkin.net
cert-manager.io/private-key-size: "4096"
# Only the k8s admin route is published by external-dns (it owns just the
# k8s.syd1.au.unkin.net zone). git.unkin.net lives in the apex zone and is
# flipped at cutover — NOT managed here.
external-dns.alpha.kubernetes.io/hostname: git.k8s.syd1.au.unkin.net
external-dns.alpha.kubernetes.io/target: 198.18.200.4
spec:
gatewayClassName: traefik-internal
listeners:
- name: http-primary
port: 80
protocol: HTTP
hostname: git.unkin.net
allowedRoutes:
namespaces:
from: Same
- name: https-primary
port: 443
protocol: HTTPS
hostname: git.unkin.net
allowedRoutes:
namespaces:
from: Same
tls:
mode: Terminate
certificateRefs:
- group: ""
kind: Secret
name: gitea-tls
- name: http-admin
port: 80
protocol: HTTP
-10
View File
@@ -9,13 +9,8 @@ metadata:
app.kubernetes.io/instance: gitea
spec:
hostnames:
- git.unkin.net
- git.k8s.syd1.au.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: gitea
sectionName: http-primary
- group: gateway.networking.k8s.io
kind: Gateway
name: gitea
@@ -41,13 +36,8 @@ metadata:
app.kubernetes.io/instance: gitea
spec:
hostnames:
- git.unkin.net
- git.k8s.syd1.au.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: gitea
sectionName: https-primary
- group: gateway.networking.k8s.io
kind: Gateway
name: gitea
+15
View File
@@ -0,0 +1,15 @@
---
# k8up dashboard (M0NsTeRRR/grafana-dashboards), datasource resolved to the
# in-cluster VictoriaMetrics. Backed by the k8up VMServiceScrape.
apiVersion: grafana.integreatly.org/v1beta1
kind: GrafanaDashboard
metadata:
name: k8up
namespace: grafana
spec:
instanceSelector:
matchLabels:
dashboards: "grafana"
resyncPeriod: 5m
allowCrossNamespaceImport: false
gzipJson: H4sIAAAAAAACA+2ce3PbNhLAvwqHc3eTzlixqIdfSTvjptc2M7Hjq9Pc3NUeDUhCEiIIYAHQsqLRffZbAHzAop0qaSRHKf4SCZLAcrH7wwJYcREixrhCinAmw5NgEVIiFRz8tgjjnFD1ksFJtBeEKVJI8lwk2Nym5pk+CEcCDRFDIdyRk1SXtFrBT7YwaLXCJVzADMVU361EjuF8TFLnjCScveCUC/2wGMXoSXsv6ETQZqff3wuib3TdDE1Nc6e1tME/glOKhZL6eilOiuQ45kik4fJaN51imQiS6Qf05clRngXVPcFYqUye7O/r4qeE64pwStRdaYdEJoj+ByNxqZBQZ5ypMVwFIcMRw+qlfulOOzo42DPayMZvOKeKZMU9RikspxSOKWETreXfrs3JDT7nMzgdIip1SxlimEqr/IRTijKJU+f6SJD0gttuGhfdop/v9ODgtmhvrn+XZcPdO9XqZhVR5u3C1xkWSIHaHfUJkAeeXTzU25ngU6zGOJdOh6dYdeb9foqS3rtJYnr8QUlXBI0qQSOtPp7Vdpjw1LZNERvlaGTbp4gwhW+Vbl6O+ewVYfg8n8ZYSEdR+soZYeQMZWWpbggMTWGmrTvUz09tC+EUiUnKZ8xIntF8RNhbqK8wmaj9tPO0G7qaOwdjlBkC3TiqM1JtQ3edhu46R7uju8tkjNOcYhm847F8FAX2GgrstndHgW+AfxSqJRSn29dht9DhQUOHx7ujwu9RMoFxQMJAkj+O+o6b/NshE3wxxsnkMdUXNRmo44Vd0d+pSMYw+D+qBvtNDXZ2R4O/YAmRy+Nq8Kipwe7uaPBC5OxR9deJmvrr7V4cs00V9h6Ioju1Bg+3qsHnZqoEKphT/O1VOCOpGp9E7fbfnwVjTEZjZU9iLlIsTtrZbSA5JWkQUxiBn12F312JKxYEz1Va1aHFaiFKRuwkSKAZLJ7dwCSPwBSsLJ6SNKX4A7U+z6rqhiBsa2ZlCWJOU339b6wM4J/vZ6UM+yo1h3CgX+o71zrGakr/yDIEzjAyWsG3GRcKpwPmzhPs9R+IwEk5G73ZiNUMCabpC86GZGSeT/EQ5VSV9mAn2ovq3dRYYOhpmkrz9BRlGWGjerpYX3afQjHoPFfmzaTCWT1rtfP4mObm2g3SB3YCbGfkOSNGS4wzbFrk0L9g6Ng2uY7ddxp232lGnyDIWSGsFaKcnpelRgAofJdLRYbzshjlyiwEcEHA/FDZV2WxAK9P8Gu3KUQTIzv4mFTnXJ3Du4bXZU/IEjVGCul6ku7yhozgRPgVmvNcFUsQa9ndPXaFxAirol/+pEnpRZFanXpdCDzPrJbc4inQRDjUAOs3FiDz6RO9rjKQ5YxvMEL5CC+a7vHt/67C2ievwqVZ8iEM0Go4U1ZN8Qiz9EcuptbRBoOqV4BuzpKNwEOzLBOehstrx8c0q79AH2P8beEmYTv8dJ8bCYxZw+n2HIm09bo3RJ/NJXsNl+xG3iW35pJmmP+wPxpf1OsFA2VWEFrBfd7513K8Bxwtw0KHHmj0oKulEC62Vpyp6W0Nh4Ro6K7HFS2Z049zvNWFGGcsXPG7KVgpef+ziYGg4FDP/GzZv3W8VhZtwbl0QPmmVPkrFNtVaTfcrK6egYJtNFpYliTvoecqydYOxtaLwbbgmNWoGMTz4ElzEPwmeFK7qMyTBEs5zOkg4bmOgtcYNvf0cuAbEBfi3tgscemhNNgP1mzUcOGT29kQOSyVPDo2gI7jBjoOPTo8OhK9urt5clTNfOXgME+fEXaGbp3X+wpxEjWn5UeeJ54nyO52bJ4oTkM+GNk5evQb9Oh5enh6CLvTt3l6OA15euwcPY4a9Djw9PD0yPQu9+bZUTXjybFr5KjSEGpy9D05PDnKfZHNw8NtafP8+FN55Qd1okn/4cTyi1yOg5+QwjM030Ry+UcyLEMUK4VbCXibJLaKJIdgb2puQ7dEfm9SSS7Hd7Lx9YUXJgMFp//Fgq9ecrczy2QafcH4ZenDuuCCQp9Pi5SZsudiJE51OktRrjWcCjS71Hkr+j5K7FbokFD6GoyGqHn5pwOBUk2a1U1T/a+KH0XxVtZkHJFV9aeEsuSGvHfZAmaHhUGRyxQtxkutg4zTCm26EJn9f31UQlBbTcYJU5fkPS4wqv85gX8gUgkS58XjdYcX9ZRku9APS1dJ4C1sVSJwjmRiSbYAXfA8swbvpOtU+9j1+FTqtTYLPhyGy8+Y8XL/7vv1cr1h6ahwuWg1t+uw3tdbzRCu+tgZUvQLpERmFFW75+YPPYb2jhnGXGkHKPO/yprKze3aWmoFSFASta8PdKv1vNwq/w1r7a7TQE/ZSDJAN4hQnbM1kAzQNuZKLixE70ktWY+wi6qC5XIdzlaZvaUoQSVKADFKUNZ2J+GLgFQYggbpqeip+Fen4gKiGjmHKqa/4KHJuYQrl8Y9TPcZkRSEStaMrRvEc/NXrHA1YC+Ew7cJzS0+DAJMzD3B84RyNAlawX553Mq4VCCqbKX5NDOheAY+Tm6NEikNoCacqRMbAqP0NaPzkpYmkBY800mq5atY6aw7Pa0s0NHCR5iibeR6ud6wUW3COONG5MeNe8eNZKypng5SM53R0zc5SHMB4hY3fs5RBMxtschuko8bT15YEQNHxMCKGFgR/ejiRxc/unzmmDvq1/Dsenh+EJ7gKx+HzWGFR42oQcGoLfPUSO1J6knqSboRktZ/0HVQ2vMo/bwo9cT0xPTE/Lpiz063BmbfA/NeYDI8+5In7ed45ifsHpoemtsLM11qHnhqemp6anpqemp+ONTsOl8QPPTQvBeaOQMRCWDhi94m+rWS0iPUI9QjdHuBp8vQjmfoHzH0i1zidOj5qauc17Z+bZolW3Ra7xTVydXdY9MPjiWbT7Wo0lnq724nuRDWDBbLhz+8vW53AX8JIxUcNP4GNrN8NW95757k5rD+XLf5mDUzGTWnlNZ6pSVR73wWeQrMJ/VN5fe772ST185iFPJ7jsXcvOPvYv7GvmbklH+S8FWvX1T6eosE0Tl6/9L1/tNYc+tOmdFb3Z2RORvh26prJyT7VdDLOUtc9FmvazsmYiW3qTvaXMzLDe0oAN45ax2af0AoXpyH5Y0ZSSY206ksea99uWi/slytA6f34yg6Oj6O41a/E0et3rCNWqjX7bXifq/TTnv9XoRiw8DKKPVceYbxxHzZ3FS//D9scYEQEl4AAA==
+33
View File
@@ -37,3 +37,36 @@ spec:
- group: ""
kind: Secret
name: grafana-tls
---
# Public grafana.unkin.net via the external Traefik; TLS uses the reflected
# Let's Encrypt *.unkin.net wildcard, DNS lives in the bind-operator zone.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
labels:
traefik.io/instance: external
name: grafana-external
namespace: grafana
spec:
gatewayClassName: traefik-external
listeners:
- allowedRoutes:
namespaces:
from: Same
hostname: grafana.unkin.net
name: http
port: 80
protocol: HTTP
- allowedRoutes:
namespaces:
from: Same
hostname: grafana.unkin.net
name: https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- group: ""
kind: Secret
name: wildcard-unkin-net-tls
mode: Terminate
+16 -3
View File
@@ -9,8 +9,16 @@ metadata:
spec:
deployment:
spec:
replicas: 3
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: grafana
containers:
- name: grafana
env:
@@ -31,11 +39,11 @@ spec:
cpu: 100m
memory: 256Mi
limits:
cpu: "1"
memory: 1Gi
cpu: "2"
memory: 4Gi
config:
server:
root_url: "https://grafana.k8s.syd1.au.unkin.net"
root_url: "https://grafana.unkin.net"
database:
type: "postgres"
host: "postgres-pooler-rw.grafana.svc.cluster.local:5432"
@@ -61,3 +69,8 @@ spec:
# to akR-global-admin members (and direct members) via terraform-authentik.
role_attribute_path: "contains(ak_groups[*], 'akP-grafana-admin') && 'Admin' || 'Viewer'"
role_attribute_strict: "false"
# Gossip between replicas so each alert notification is sent once.
unified_alerting:
ha_peers: "grafana-alerting.grafana.svc.cluster.local:9094"
ha_listen_address: "${POD_IP}:9094"
ha_advertise_address: "${POD_IP}:9094"
+55
View File
@@ -53,3 +53,58 @@ spec:
- path:
type: PathPrefix
value: /
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: grafana-external-http-redirect
namespace: grafana
labels:
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
spec:
hostnames:
- grafana.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: grafana-external
sectionName: http
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301
matches:
- path:
type: PathPrefix
value: /
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: grafana-external
namespace: grafana
labels:
app.kubernetes.io/name: grafana
app.kubernetes.io/instance: grafana
spec:
hostnames:
- grafana.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: grafana-external
sectionName: https
rules:
- backendRefs:
- group: ""
kind: Service
name: grafana-service
port: 3000
weight: 1
matches:
- path:
type: PathPrefix
value: /
+1
View File
@@ -18,6 +18,7 @@ resources:
- dashboards/frr-ospf-route-metrics.yaml
- dashboards/gitea.yaml
- dashboards/haproxy.yaml
- dashboards/k8up.yaml
- dashboards/media-dashboard.yaml
- dashboards/node-exporter-full.yaml
- dashboards/nzbget.yaml
+16
View File
@@ -0,0 +1,16 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
name: haproxy
namespace: haproxy
labels:
app: haproxy
spec:
targetRefs:
- group: ""
kind: Service
name: haproxy
validation:
wellKnownCACertificates: System
hostname: git.unkin.net
-18
View File
@@ -21,7 +21,6 @@ data:
jellyfin.main.unkin.net be_jellyfin
fafflix.unkin.net be_jellyfin
git.unkin.net be_gitea
grafana.unkin.net be_grafana
dashboard.ceph.unkin.net be_ceph_dashboard
auth.unkin.net be_k8s_kanidm
@@ -124,23 +123,6 @@ data:
server ausyd1nxvm2081 198.18.27.117:443 check cookie ausyd1nxvm2081 fall 2 inter 2s rise 3 ssl verify none
server ausyd1nxvm2082 198.18.28.71:443 check cookie ausyd1nxvm2082 fall 2 inter 2s rise 3 ssl verify none
backend be_grafana
description Backend for grafana nodes
balance roundrobin
cookie SRVNAME insert indirect nocache
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { dst_port 443 }
http-reuse always
option httpchk GET /
option forwardfor
option http-keep-alive
option prefer-last-server
redirect scheme https if !{ ssl_fc }
stick on src
stick-table type ip size 200k expire 30m
server ausyd1nxvm2015 198.18.27.2:443 check cookie ausyd1nxvm2015 fall 2 inter 2s rise 3 ssl verify none
server ausyd1nxvm2016 198.18.28.189:443 check cookie ausyd1nxvm2016 fall 2 inter 2s rise 3 ssl verify none
backend be_jellyfin
description Backend for au-syd1 jellyfin
balance roundrobin
+16 -8
View File
@@ -1,10 +1,8 @@
---
# External (DMZ) front for the haproxy edge on the traefik-external LB VIP
# 198.18.199.0. The :443 listener is TLS Passthrough: haproxy owns the three
# wildcard certs and terminates behind Traefik, so there are no certificateRefs
# here. Listener hostnames are deliberately unset and the routes carry the
# explicit hostname list instead; allowedRoutes Same keeps other namespaces off
# these listeners.
# 198.18.199.0. Traefik terminates TLS so HTTP/2 connections coalesced from
# other *.unkin.net hosts still route by Host; the hop to haproxy is re-encrypted via
# BackendTLSPolicy. Routes carry the explicit hostname list.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
@@ -21,11 +19,21 @@ spec:
allowedRoutes:
namespaces:
from: Same
- name: https-passthrough
- name: https
port: 443
protocol: TLS
protocol: HTTPS
tls:
mode: Passthrough
mode: Terminate
certificateRefs:
- group: ""
kind: Secret
name: wildcard-unkin-net-tls
- group: ""
kind: Secret
name: wildcard-main-unkin-net-tls
- group: ""
kind: Secret
name: wildcard-ceph-unkin-net-tls
allowedRoutes:
namespaces:
from: Same
+33 -1
View File
@@ -17,7 +17,6 @@ spec:
- jellyfin.main.unkin.net
- fafflix.unkin.net
- git.unkin.net
- grafana.unkin.net
- dashboard.ceph.unkin.net
- auth.unkin.net
parentRefs:
@@ -35,3 +34,36 @@ spec:
- path:
type: PathPrefix
value: /
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: haproxy
namespace: haproxy
labels:
app: haproxy
spec:
hostnames:
- sonarr.main.unkin.net
- radarr.main.unkin.net
- lidarr.main.unkin.net
- readarr.main.unkin.net
- prowlarr.main.unkin.net
- nzbget.main.unkin.net
- jellyfin.main.unkin.net
- fafflix.unkin.net
- git.unkin.net
- dashboard.ceph.unkin.net
- auth.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: haproxy
sectionName: https
rules:
- backendRefs:
- group: ""
kind: Service
name: haproxy
port: 443
weight: 1
+1 -1
View File
@@ -8,7 +8,7 @@ resources:
- deployment.yaml
- service.yaml
- gateway.yaml
- tlsroute.yaml
- backendtlspolicy.yaml
- httproute.yaml
- pdb.yaml
- vpa.yaml
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
namespace: haproxy
spec:
type: ClusterIP
# Reached only by the external Traefik's TLS-passthrough TLSRoute, so the
# Reached only by the external Traefik (re-encrypted HTTPRoute), so the
# peer address here is a Traefik pod, not the client. sessionAffinity is
# deliberately absent: keyed on ClientIP it would pin whole Traefik pods,
# not clients. Backend persistence rests on the per-backend SRVNAME cookie.
-34
View File
@@ -1,34 +0,0 @@
---
apiVersion: gateway.networking.k8s.io/v1
kind: TLSRoute
metadata:
name: haproxy
namespace: haproxy
labels:
app: haproxy
spec:
hostnames:
- sonarr.main.unkin.net
- radarr.main.unkin.net
- lidarr.main.unkin.net
- readarr.main.unkin.net
- prowlarr.main.unkin.net
- nzbget.main.unkin.net
- jellyfin.main.unkin.net
- fafflix.unkin.net
- git.unkin.net
- grafana.unkin.net
- dashboard.ceph.unkin.net
- auth.unkin.net
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: haproxy
sectionName: https-passthrough
rules:
- backendRefs:
- group: ""
kind: Service
name: haproxy
port: 443
weight: 1
+1
View File
@@ -4,3 +4,4 @@ kind: Kustomization
resources:
- namespace.yaml
- vmservicescrape.yaml
@@ -0,0 +1,15 @@
---
# Scrape the k8up operator metrics (k8up-metrics Service, port http :8080).
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMServiceScrape
metadata:
name: k8up
namespace: k8up-system
spec:
selector:
matchLabels:
app.kubernetes.io/name: k8up
app.kubernetes.io/instance: k8up
endpoints:
- port: http
path: /metrics
@@ -1,16 +0,0 @@
---
# Confines the agent-observability service account (in vm-system) to the
# agent-observability ClusterRole within this namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: agent-observability
namespace: logging
subjects:
- kind: ServiceAccount
name: agent-observability
namespace: vm-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: agent-observability
-43
View File
@@ -1,43 +0,0 @@
---
# S3 bucket (Ceph RGW) for the long-term raw-log archive, provisioned by the
# in-estate cephrgw-operator. The archiver Vector deployment writes here.
apiVersion: ceph.unkin.net/v1alpha1
kind: ObjectStoreUser
metadata:
name: logs-archive-owner
namespace: logging
spec:
displayName: "Logging raw-archive bucket owner"
maxBuckets: 5
quota:
enabled: true
# 5 TiB soft cap; real retention is enforced RGW-side by a bucket lifecycle
# policy (see PR notes) — the operator does not manage lifecycle.
maxSizeBytes: 5497558138880
---
apiVersion: ceph.unkin.net/v1alpha1
kind: Bucket
metadata:
name: logs-archive
namespace: logging
spec:
bucketName: logs-archive
ownerRef: logs-archive-owner
versioning: false
tags:
app: logging
purpose: raw-log-archive
# Keep the bucket (and its objects) if this CR is ever deleted.
retainOnDelete: true
---
apiVersion: ceph.unkin.net/v1alpha1
kind: BucketAccess
metadata:
name: logs-archive-writer
namespace: logging
spec:
bucketRef: logs-archive
level: read-write
# Operator writes AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY (+ RGW_UID,
# S3_ENDPOINT, BUCKET_NAME) into this Secret; the archiver consumes it.
secretName: logs-archive-s3

Some files were not shown because too many files have changed in this diff Show More