CI/CD
Current Architecture
ArgoCD is deployed in the cluster for GitOps continuous delivery. GitLab CI handles builds using cloud runners. GitLab Runner is deployed in the K8s cluster using Helm.
graph LR
DEV[Developer Push] -->|git push| GL[GitLab]
GL -->|triggers| RUNNER[GitLab Runner in K8s]
RUNNER -->|builds image| REG[Container Registry]
REG -->|image available| ARGO[ArgoCD]
ARGO -->|syncs| K8S[Kubernetes - quinza]ArgoCD
ArgoCD watches GitLab repositories and automatically syncs K8s manifests to the cluster.
| Property | Value |
|---|---|
| Namespace | argocd |
| URL | https://argocd.quinza.dev (proxied by Cloudflare) |
| Internal access | http://10.10.1.1 with Host header argocd.quinza.dev |
| Helm chart | argo/argo-cd |
| Mode | --insecure (TLS terminated at Caddy/Cloudflare) |
| Credentials | Stored in 1Password |
Applications
Each project has its own ArgoCD Application resource pointing to a GitLab repo:
| Application | Repository | Path | Namespace | Sync |
|---|---|---|---|---|
| carzying | gitlab.com/aitorquinza/carzying | k8s/ | carzying | Auto (prune + selfHeal) |
To add a new project:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-project
namespace: argocd
spec:
project: default
source:
repoURL: https://gitlab.com/aitorquinza/my-project.git
targetRevision: main
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: my-project
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=truePrivate Repositories
ArgoCD uses credential templates to authenticate with private GitLab repos. A SOPS-encrypted Secret with a deploy token is stored at talos/manifests/argocd/repo-creds-gitlab.enc.yaml.
The credential template uses the label argocd.argoproj.io/secret-type: repo-creds and matches any repository URL starting with https://gitlab.com/carzying. This means new repos under that prefix are automatically authenticated -- no per-repo Secret needed.
To apply the credentials:
sops decrypt talos/manifests/argocd/repo-creds-gitlab.enc.yaml | kubectl apply -f -KSOPS planned
Currently credentials are applied manually via sops decrypt | kubectl apply. KSOPS integration with ArgoCD is planned so that encrypted Secrets can be synced via GitOps automatically.
GitLab CI Pipeline
The pipeline builds Docker images and pushes to GitLab Container Registry. ArgoCD then detects manifest changes and deploys.
| Stage | Action | Runner |
|---|---|---|
| quality | Lint, typecheck, tests | GitLab Runner (K8s) |
| build | Docker build + push to registry | GitLab Runner (K8s) |
| deploy-preview | Apply preview manifests to K8s | GitLab Runner (K8s) |
| deploy-prod | Managed by ArgoCD (not pipeline) | ArgoCD |
GitLab Runner
GitLab Runner is deployed in the cluster using the official Helm chart (gitlab/gitlab-runner) with the Kubernetes executor.
| Property | Value |
|---|---|
| Namespace | gitlab-runner |
| Helm chart | gitlab/gitlab-runner |
| Executor | Kubernetes |
| Concurrency | 2 |
| Default image | alpine:3.21 |
| Tags | k8s, homelab |
| Registered project | aitorquinza/carzying |
| Runner token | Stored as a K8s Secret |
Manifests: talos/manifests/gitlab-runner/values.yaml and install.yaml.
CI Deploy Service Account
A dedicated ServiceAccount gitlab-ci-deploy in kube-system provides least-privilege access for GitLab CI deploy jobs.
| Resource | File |
|---|---|
| ServiceAccount | talos/manifests/ci-deploy/service-account.yaml |
| RBAC | talos/manifests/ci-deploy/rbac.yaml |
The ClusterRole grants access to deployments, services, ingresses, secrets, HPA, and PDB resources in the carzying and carzying-preview namespaces only.
To generate a kubeconfig for GitLab CI:
./scripts/generate-ci-kubeconfig.shPreview Environments
Feature branches get ephemeral preview deployments:
| Property | Value |
|---|---|
| Trigger | Merge request opened |
| DNS | *.preview.quinza.dev (wildcard, points to bastion) |
| URL pattern | carzying-{branch}.preview.quinza.dev |
| Cleanup | Auto-destroyed on MR close or after 3 days |
Not yet configured
Preview environments require Caddy wildcard config for *.preview.quinza.dev. GitLab Runner is deployed in K8s but the preview cleanup automation is not yet implemented.