Initial argo deployment

This commit is contained in:
2026-05-17 20:44:31 -05:00
parent 97e9889251
commit 905b4619d6
33 changed files with 1322 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
# ------------------------------------------------------------------------------
# Platform: ArgoCD Configuration (post-bootstrap)
# Wave 2 — after ESO (wave 1), needs 1Password for Authentik client secret
#
# This is NOT the ArgoCD install (that's a manual bootstrap step).
# This Application manages ArgoCD's own configuration declaratively:
# - argocd-cm (URL, Dex/OIDC config, repo credentials)
# - argocd-rbac-cm (RBAC policies mapped from Authentik groups)
# - argocd-secret (Authentik client secret via ESO)
#
# ArgoCD managing its own config is intentional and works cleanly —
# it's the "self-managed ArgoCD" pattern.
# ------------------------------------------------------------------------------
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: argocd-config
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "2"
spec:
project: default
source:
repoURL: https://gitea.mk-labs.cloud/rblundon/homelab.git
targetRevision: main
path: cluster/platform/argocd
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- ServerSideApply=true
ignoreDifferences:
# ArgoCD mutates its own secret — ignore those fields
- group: ""
kind: Secret
name: argocd-secret
jsonPointers:
- /data/admin.password
- /data/admin.passwordMtime
- /data/server.secretkey

View File

@@ -0,0 +1,69 @@
# ------------------------------------------------------------------------------
# argocd-cm — ArgoCD Core Configuration
#
# Configures:
# - ArgoCD public URL (used in Dex redirect URIs)
# - Dex connector to Authentik OIDC
# - Gitea repo credentials reference
#
# Authentik side setup (manual — do this in guest-relations before bootstrapping):
# 1. Admin UI → Applications → Create New Application
# 2. Provider type: OAuth2/OpenID Connect
# 3. Name: argocd
# 4. Authorization flow: default-provider-authorization-explicit-consent
# 5. Client type: Confidential
# 6. Strict redirect URIs:
# https://argocd.local.mk-labs.cloud/api/dex/callback
# http://localhost:8085/auth/callback (ArgoCD CLI)
# 7. Scopes: openid, profile, email, groups
# 8. Note the Client ID and Client Secret → store in 1Password as:
# Item: "argocd-oidc"
# Fields: client-id, client-secret
# 9. Create two groups in Authentik:
# - argocd-admins (add your user)
# - argocd-viewers (read-only users)
# ------------------------------------------------------------------------------
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
# Public URL — must match the HTTPRoute hostname
url: https://argocd.local.mk-labs.cloud
# Dex connector to Authentik
# Using Dex (not native OIDC) to preserve ArgoCD CLI functionality
dex.config: |
connectors:
- type: oidc
id: authentik
name: Authentik
config:
# Authentik OIDC issuer — slug must match the Application slug in Authentik
# Slug is auto-generated from the app name, usually lowercase with hyphens
issuer: https://authentik.local.mk-labs.cloud/application/o/argocd/
clientID: $dex.authentik.clientID
clientSecret: $dex.authentik.clientSecret
redirectURI: https://argocd.local.mk-labs.cloud/api/dex/callback
scopes:
- openid
- profile
- email
- groups
insecureEnableGroups: true
groupsKey: groups
userIDKey: sub
userNameKey: preferred_username
emailKey: email
# Gitea repo — ArgoCD needs credentials to pull from your private repo
# Credentials are stored as a Repository secret (see repository-secret.yaml)
# This tells ArgoCD to use SSH for the repo
repositories: |
- url: git@gitea.mk-labs.cloud:rblundon/homelab.git
type: git
name: homelab
# Resource tracking via annotation (recommended over label tracking)
application.resourceTrackingMethod: annotation

View File

@@ -0,0 +1,30 @@
# ------------------------------------------------------------------------------
# argocd-rbac-cm — RBAC Policy
#
# Maps Authentik groups to ArgoCD roles.
# Groups must exist in Authentik and be assigned to users there.
#
# Roles:
# role:admin — full access, all operations
# role:readonly — read-only, can view but not sync/modify
#
# Single-user homelab: your user should be in argocd-admins in Authentik.
# Add argocd-viewers later when you have guests/collaborators.
# ------------------------------------------------------------------------------
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
# Default policy for any authenticated user not in a mapped group
# readonly is safe — they can see but not touch
policy.default: role:readonly
policy.csv: |
# Authentik group → ArgoCD role mappings
g, argocd-admins, role:admin
g, argocd-viewers, role:readonly
# Tell ArgoCD which OIDC claims to use for group mapping
scopes: '[groups, email]'

View File

@@ -0,0 +1,23 @@
# ------------------------------------------------------------------------------
# ArgoCD Server — Insecure Mode Patch
#
# When TLS is terminated at the Gateway (not at argocd-server itself),
# argocd-server must run in --insecure mode. Without this, it tries to
# do double TLS and the Gateway connection fails.
#
# This patches the argocd-server Deployment to add the --insecure flag.
# Applied as part of the argocd-config Application (same path/namespace).
# ------------------------------------------------------------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-server
namespace: argocd
spec:
template:
spec:
containers:
- name: argocd-server
command:
- argocd-server
- --insecure

View File

@@ -0,0 +1,41 @@
# ------------------------------------------------------------------------------
# Certificate — ArgoCD TLS
# Issued by cert-manager via letsencrypt-prod + Cloudflare DNS-01
#
# The secret produced (argocd-tls) is referenced by the Gateway listener
# in cluster/platform/gateway-api/gateway.yaml via ReferenceGrant.
#
# Per the thematic naming convention: argocd.local.mk-labs.cloud is the
# service DNS name. No VM hostname alias needed here.
# ------------------------------------------------------------------------------
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: argocd-tls
namespace: argocd
spec:
secretName: argocd-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:
- argocd.local.mk-labs.cloud
---
# ReferenceGrant — allows the Gateway in gateway-system to reference
# the TLS secret in the argocd namespace
# Without this, cross-namespace secret references are denied
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: argocd-tls-grant
namespace: argocd
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: gateway-system
to:
- group: ""
kind: Secret
name: argocd-tls

View File

@@ -0,0 +1,49 @@
# ------------------------------------------------------------------------------
# ExternalSecret — ArgoCD Secrets
#
# Pulls two secrets from 1Password:
# 1. Authentik OIDC client ID + secret (for Dex connector)
# 2. Gitea personal access token (for repo access)
#
# In 1Password (mk-labs vault), create:
# Item: "argocd-oidc"
# Field: client-id → Authentik OAuth2 client ID
# Field: client-secret → Authentik OAuth2 client secret
#
# Item: "gitea-argocd-token"
# Field: token → Gitea personal access token with repo read permissions
# (Create in Gitea: Settings → Applications → Generate Token)
#
# These materialize into argocd-secret, which ArgoCD reads natively.
# The $dex.authentik.clientID / $dex.authentik.clientSecret references
# in argocd-cm.yaml are resolved by ArgoCD from this secret automatically.
# ------------------------------------------------------------------------------
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: argocd-secrets
namespace: argocd
spec:
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-connect
refreshInterval: "1h"
target:
# Must be named argocd-secret — ArgoCD reads this specific secret name
name: argocd-secret
creationPolicy: Merge # Merge into existing argocd-secret, don't replace it
data:
# Authentik OIDC credentials — referenced as $dex.authentik.* in argocd-cm
- secretKey: dex.authentik.clientID
remoteRef:
key: argocd-oidc
property: client-id
- secretKey: dex.authentik.clientSecret
remoteRef:
key: argocd-oidc
property: client-secret
# Gitea token — used by the Repository credential below
- secretKey: sshPrivateKey
remoteRef:
key: gitea-argocd-ssh
property: private-key

View File

@@ -0,0 +1,54 @@
# ------------------------------------------------------------------------------
# HTTPRoute — ArgoCD
# Routes argocd.local.mk-labs.cloud → argocd-server service
#
# This is the first real Gateway API HTTPRoute in the cluster — ArgoCD
# dogfoods the Gateway it manages. Satisfying.
#
# TLS is terminated at the Gateway. cert-manager issues the certificate
# via the Certificate resource below. The Gateway listener references it.
#
# ArgoCD server runs in insecure mode (--insecure) when TLS is terminated
# upstream — this is correct and expected with a Gateway/proxy in front.
# ------------------------------------------------------------------------------
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: argocd
namespace: argocd
spec:
parentRefs:
- name: fastpass-gateway
namespace: gateway-system
sectionName: https
hostnames:
- argocd.local.mk-labs.cloud
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: argocd-server
port: 80 # argocd-server listens on 80 in insecure mode
---
# HTTP → HTTPS redirect
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: argocd-http-redirect
namespace: argocd
spec:
parentRefs:
- name: fastpass-gateway
namespace: gateway-system
sectionName: http
hostnames:
- argocd.local.mk-labs.cloud
rules:
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301

View File

@@ -0,0 +1,26 @@
# ------------------------------------------------------------------------------
# Repository Credential Secret — Gitea homelab repo (SSH)
#
# ArgoCD discovers repository credentials via secrets with the label
# argocd.argoproj.io/secret-type: repository
#
# The SSH private key is injected by ESO from 1Password.
# In 1Password (mk-labs vault):
# Item: "gitea-argocd-ssh"
# Field: private-key → full contents of the ed25519 private key PEM block
# ------------------------------------------------------------------------------
apiVersion: v1
kind: Secret
metadata:
name: repo-homelab-gitea
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: git@gitea.mk-labs.cloud:rblundon/homelab.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
# This value is overwritten by ESO — placeholder only
# See externalsecret.yaml
-----END OPENSSH PRIVATE KEY-----