Commit Graph
17 Commits
Author SHA1 Message Date
Mukul SharmaandClaude Opus 5 adb514c3be Issue public certificates for the real domain
The deployment has a domain of its own now, which is the first time a
public certificate has been possible here at all. The registry issuer
beside this one explains why: nip.io is not on the public suffix list and
every *.nip.io certificate shares one rate limit, so Let's Encrypt could
never serve the addresses this cluster has been using.

DNS-01 rather than HTTP-01, because every deployed app lives at
<app>.apps.<domain> and only a DNS-01 challenge can issue the wildcard
that covers all of them. HTTP-01 would mean a certificate per app,
requested the moment each one is created.

Two issuers, staging and production. Production allows five duplicate
certificates a week and a failing solver spends that allowance without
issuing anything, which can lock a domain out of certificates for days.
Staging has no meaningful limit and issues from an untrusted root, so a
browser warning is the signal that the plumbing works. Move to the
production issuer once a staging certificate appears.

The token reaches cert-manager the same way every other credential here
does: Vault, through External Secrets. It wants Zone -> DNS -> Edit on the
one zone and nothing else — enough to write the TXT record a challenge
needs, and no more. Until `vault kv put secret/cloudflare/dns-token` has
run, the ExternalSecret stays unfulfilled and the issuers cannot register.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
2026-09-17 01:24:54 +05:30
Mukul SharmaandClaude Opus 5 9c67afd5e0 GKE: register the remaining tools, add the registry CA issuer
Adds nine Applications — external-secrets, harbor, jenkins, postgresql,
redis, victoria-metrics-single, vmagent, node-exporter, grafana — bringing
the cluster to the homelab's full set. Every nameOverride is pinned, which
is load-bearing rather than cosmetic in at least three cases:
external-secrets (its service account name is what vault-backend's
serviceAccountRef and Vault's auth role bind to), victoria-metrics-single
(its Service renders as <release>-server, the address vmagent and Grafana
both hardcode) and harbor (the pipeline refers to its object names).

extra-manifests gains the ClusterIssuer that makes cert-manager useful
here: a CA issuer over the registry-ca Secret, which is created by hand
from terraform output because the CA's private key exists only in
Terraform state and nothing can reconcile it from git.

Two homelab-only things removed rather than left to confuse: the Tailscale
Harbor Ingress, and the homelab cluster's own entry point and values file,
which have no meaning in a GCP-only repo. app-of-secretstores and
app-of-extra-manifests now point at this cluster's Gitea over cluster DNS,
and harbor-robot-dockerconfig is keyed to this cluster's registry hostname
— docker matches stored credentials by exact host, so the homelab's would
have silently pushed unauthenticated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
2026-09-12 15:01:59 +05:30
Mukul SharmaandClaude Opus 5 dcd3583656 Deploy Redis, backing toolshed's managed cache add-on
Registers the new hand-written redis chart (devops-infra-helm-charts,
separate commit) and the ExternalSecret feeding its admin password from
Vault. Own namespace, addressed over cluster DNS like every other platform
component here:

  redis.redis.svc.cluster.local:6379

Only one consumer for the credential, unlike the Postgres one next door:
the server itself, to seed its ACL file on first boot. toolshed's api gets
it from the connection an operator configures in the dashboard, encrypted
in toolshed's own database — so there is deliberately no second
ExternalSecret into the toolshed namespace.

Order matters: put the password in Vault at secret/toolshed/redis before
syncing, or the init container sits in CreateContainerConfigError. The
exact command, the reason the password must be alphanumeric (it is written
into an ACL directive where a space or quote would split it), and the
manual rotation procedure are all recorded in the ExternalSecret's own
header.

Nothing here needs to change for Postgres: toolshed's managed database
add-on points at the existing postgresql.postgres.svc.cluster.local, whose
POSTGRES_USER is the initdb superuser and so already has the CREATEDB and
CREATEROLE that provisioning needs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF
2026-09-09 12:35:46 +05:30
Mukul Sharma 94a055b341 Add quant-agent ExternalSecrets 2026-09-07 07:10:56 +05:30
Mukul SharmaandClaude Opus 5 89a0aacbd7 Add toolshed-harbor-cleanup: a delete-scoped Harbor robot for builder
Deliberately separate from harbor-robot-dockerconfig, which is mounted
into build pods running arbitrary user Dockerfiles and is scoped to
push+pull only. This one is held by builder itself — a trusted platform
service that never executes user code directly — and carries a
permission the other should never have: delete. A leaked build-pod
credential can never delete anything this way, and a leaked cleanup
credential can never push.

Used by toolshed's cleanupImage (internal/builder/builder.go) to remove
an app's Harbor repository when the app itself is deleted. Nothing
destructive happens until the Vault path this pulls from is actually
populated — builder logs and skips that step otherwise, per its own
code comment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF
2026-09-06 21:17:45 +05:30
Mukul SharmaandClaude Opus 5 cab110c268 Add grafana appSpec entry and its admin-credentials ExternalSecret
Matches the chart-side addition in devops-infra-helm-charts. The
ExternalSecret needs its Vault path populated before either this or
the grafana Application syncs — see that file's own header for the
exact vault kv put command, same requirement postgres and every other
admin credential in this repo already has.

app-of-secretstores.yaml is automated (prune: true), so this new
secretstore file needs no separate manual sync of its own — only that
app-of-apps wrapper, same as any other new file under secretstores/.

Verified with `helm template` against generic-argo-apps-chart and this
values file: 12 Applications render, grafana present and correctly
formed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF
2026-09-06 08:57:42 +05:30
Mukul Sharma 9f770e5ac7 Add toolshed's credential encryption keys 2026-09-05 08:54:14 +05:30
Mukul Sharma 48ecd1db73 Add Gitea API token for toolshed's webhook management 2026-09-05 02:22:42 +05:30
Mukul Sharma 0eeef50781 Add Jenkins API credentials for toolshed's builder
A dedicated Jenkins user with an API token, not the admin account. Needs
Job/Create as well as Build and Read, because builder creates an app's job
on first deploy — which is what guarantees the SCM polling trigger exists
and so that a webhook can ever find it (issue #30).
2026-09-04 20:33:21 +05:30
Mukul Sharma 83f4aa0259 Add the toolshed session signing key from Vault
Only api gets the private half. The gateway is given the public half in
plain Helm values, and that asymmetry is the point: the gateway
terminates traffic for every deployed app, so holding only a verification
key means compromising it cannot forge a session for anyone.

The two halves must be installed together — a private key here that does
not match the public key in the gateway's values means every session api
issues is rejected and every app redirects to login forever.
2026-09-04 17:06:50 +05:30
Mukul Sharma 84f5e27238 Add postgresql to appSpec and its Vault-backed credentials
One Vault path (secret/toolshed/postgres) into two namespaces: the server
needs the credential to initialise, api needs it to connect. Kept in one
file because it is one credential with two consumers — split, they drift,
and drift surfaces as an authentication error that looks nothing like a
config mistake.

The api-side Secret also carries a composed libpq URL, so host, port and
database name live in one place instead of across several environment
variables that can disagree.

Postgres gets its own namespace rather than living inside toolshed, so it
is addressed over cluster DNS like any other platform component and
outlives whatever consumes it.
2026-09-04 16:21:36 +05:30
Mukul Sharma ec049c0671 Remove demo-go-app-image-pull-secret (homelab Harbor project now public)
No longer needed now that anonymous pull works — pairs with
devops-helm-charts#efc2c4f dropping the corresponding pullSecret
reference from demo-go-app's values. app-of-secretstores has automated
prune, so this deletion applies on its own on next sync.
2026-09-03 06:41:24 +05:30
Mukul Sharma 33ae7a2104 Add demo-go-app-image-pull-secret; rekey harbor-robot-dockerconfig
Both needed for the registry hostname switch to
harbor.192.168.1.7.nip.io (devops-lib#3ffa2d8):

- harbor-robot-dockerconfig's auths key was hardcoded to
  harbor-core.harbor.svc.cluster.local — docker matches stored
  credentials by exact registry hostname, so this had to move with
  the image reference or push would go back to unauthorized.
- New demo-go-app-image-pull-secret, in the demo-go-app namespace
  (imagePullSecrets must be same-namespace as the pod), for the
  Deployment's own pull — separate from harbor-robot-dockerconfig,
  which only ever lived in the jenkins namespace for the build pod's
  push. Same underlying robot account/Vault path.
2026-09-02 23:54:50 +05:30
Mukul Sharma 27c0445074 Add PriorityClass, ArgoCD jenkins-ci token, and Harbor robot secretstores
extra-manifests/priorityclass-high-priority.yaml: cluster-side
PriorityClass backing the app chart's hardcoded priorityClassName.
secretstores/argocd-jenkins-ci-token.yaml: ExternalSecret for the
scoped ArgoCD account devops-lib's syncArgoApp stage authenticates
with.
secretstores/harbor-robot-dockerconfig.yaml: ExternalSecret building a
dockerconfigjson from the Harbor robot account for image pulls.
2026-09-02 01:29:39 +05:30
Mukul Sharma f7e37d18b4 added harbor app 2026-08-31 13:18:18 +05:30
Mukul Sharma f722a8bc9c added jenkins 2026-08-31 09:40:54 +05:30
Mukul Sharma 4719d0305f added secret 2026-08-31 09:02:30 +05:30