diff --git a/infra/inttest/run_pipeline.sh b/infra/inttest/run_pipeline.sh index ffa3c8c..a595db1 100755 --- a/infra/inttest/run_pipeline.sh +++ b/infra/inttest/run_pipeline.sh @@ -343,7 +343,7 @@ if ! kubectl run seed-sandbox \ --image-pull-policy=Always \ --overrides='{ "spec": { - "imagePullSecrets": [{"name": "ghcr-credentials"}], + "securityContext": {"runAsNonRoot": true, "runAsUser": 1000, "runAsGroup": 1000} } }' \ @@ -375,7 +375,7 @@ if ! kubectl run seed-minio \ --image-pull-policy=Always \ --overrides='{ "spec": { - "imagePullSecrets": [{"name": "ghcr-credentials"}], + "securityContext": {"runAsNonRoot": true, "runAsUser": 1000, "runAsGroup": 1000} } }' \ diff --git a/pipelines/harbor/pvcs.yaml b/pipelines/harbor/pvcs.yaml new file mode 100644 index 0000000..71a44f1 --- /dev/null +++ b/pipelines/harbor/pvcs.yaml @@ -0,0 +1,86 @@ +# Harbor PersistentVolumeClaims — bind to NFS PVs +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: harbor-registry-pvc + namespace: harbor-service + labels: + app: harbor + component: registry +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 100Gi + storageClassName: "" + volumeName: harbor-registry-pv +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: harbor-jobservice-pvc + namespace: harbor-service + labels: + app: harbor + component: jobservice +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: "" + volumeName: harbor-jobservice-pv +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: harbor-database-pvc + namespace: harbor-service + labels: + app: harbor + component: database +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: "" + volumeName: harbor-database-pv +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: harbor-redis-pvc + namespace: harbor-service + labels: + app: harbor + component: redis +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi + storageClassName: "" + volumeName: harbor-redis-pv +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: harbor-trivy-pvc + namespace: harbor-service + labels: + app: harbor + component: trivy +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 5Gi + storageClassName: "" + volumeName: harbor-trivy-pv diff --git a/pipelines/harbor/values.yaml b/pipelines/harbor/values.yaml new file mode 100644 index 0000000..5ed9f97 --- /dev/null +++ b/pipelines/harbor/values.yaml @@ -0,0 +1,100 @@ +# Harbor Helm values — Stonks Oracle registry +# Domain: registry.celestium.life +# Ingress: Traefik with cert-manager (letsencrypt-prod) +# Storage: NFS PVs on 192.168.42.8 + +expose: + type: ingress + tls: + enabled: true + certSource: secret + secret: + secretName: harbor-tls + ingress: + hosts: + core: registry.celestium.life + controller: default + className: traefik + annotations: + cert-manager.io/cluster-issuer: letsencrypt-prod + traefik.ingress.kubernetes.io/router.entrypoints: websecure + ingress.kubernetes.io/ssl-redirect: "true" + ingress.kubernetes.io/proxy-body-size: "0" + +externalURL: https://registry.celestium.life + +# Initial admin password — change after first login +harborAdminPassword: "St0nks0racl3!" + +# Use internal database and redis (bundled with Harbor) +database: + type: internal + +redis: + type: internal + +persistence: + enabled: true + resourcePolicy: "keep" + persistentVolumeClaim: + registry: + existingClaim: harbor-registry-pvc + size: 100Gi + jobservice: + jobLog: + existingClaim: harbor-jobservice-pvc + size: 2Gi + database: + existingClaim: harbor-database-pvc + size: 5Gi + redis: + existingClaim: harbor-redis-pvc + size: 2Gi + trivy: + existingClaim: harbor-trivy-pvc + size: 5Gi + +# Trivy vulnerability scanner +trivy: + enabled: true + +# Metrics for Prometheus (optional, enable if you have monitoring) +metrics: + enabled: false + +# Resource limits — conservative for a 4-node cluster +core: + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi + +jobservice: + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + +registry: + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 1000m + memory: 1Gi + +portal: + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 500m + memory: 256Mi diff --git a/pipelines/pvs/harbor-pv.yaml b/pipelines/pvs/harbor-pv.yaml new file mode 100644 index 0000000..14df478 --- /dev/null +++ b/pipelines/pvs/harbor-pv.yaml @@ -0,0 +1,87 @@ +# Harbor NFS PersistentVolumes +# NFS path: nfs://192.168.42.8:/volume1/Kubernetes/harbor/data/ +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: harbor-registry-pv + labels: + app: harbor + component: registry +spec: + capacity: + storage: 100Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: 192.168.42.8 + path: /volume1/Kubernetes/harbor/data/registry +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: harbor-database-pv + labels: + app: harbor + component: database +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: 192.168.42.8 + path: /volume1/Kubernetes/harbor/data/database +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: harbor-redis-pv + labels: + app: harbor + component: redis +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: 192.168.42.8 + path: /volume1/Kubernetes/harbor/data/redis +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: harbor-jobservice-pv + labels: + app: harbor + component: jobservice +spec: + capacity: + storage: 2Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: 192.168.42.8 + path: /volume1/Kubernetes/harbor/data/jobservice +--- +apiVersion: v1 +kind: PersistentVolume +metadata: + name: harbor-trivy-pv + labels: + app: harbor + component: trivy +spec: + capacity: + storage: 5Gi + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + nfs: + server: 192.168.42.8 + path: /volume1/Kubernetes/harbor/data/trivy diff --git a/pipelines/runmefirst.sh b/pipelines/runmefirst.sh index 07d8453..7a066d0 100755 --- a/pipelines/runmefirst.sh +++ b/pipelines/runmefirst.sh @@ -15,7 +15,7 @@ GITEA_API="http://10.1.1.12:30300/api/v1" # 1. Create namespaces # ------------------------------------------------------- echo "--- Step 1: Creating namespaces ---" -for ns in woodpecker argocd kargo stonks-beta stonks-paper; do +for ns in woodpecker argocd kargo stonks-beta stonks-paper harbor-service; do kubectl create namespace "$ns" --dry-run=client -o yaml | kubectl apply -f - echo " ✓ namespace/$ns" done @@ -27,7 +27,7 @@ echo "" echo "--- Step 2: Proxy CA cert and Kyverno policies ---" CA_CERT_PATH="${SCRIPT_DIR}/home.crt" curl -sf http://192.168.42.1/home.crt -o "$CA_CERT_PATH" -for ns in woodpecker argocd kargo; do +for ns in woodpecker argocd kargo harbor-service; do if ! kubectl get configmap proxy-ca-cert -n "$ns" > /dev/null 2>&1; then kubectl create configmap proxy-ca-cert --from-file=ca.crt="$CA_CERT_PATH" -n "$ns" echo " ✓ proxy-ca-cert created in $ns" @@ -55,9 +55,65 @@ echo "--- Step 3: Applying NFS PersistentVolumes ---" kubectl apply -f pvs/argocd-pv.yaml kubectl apply -f pvs/kargo-pv.yaml kubectl apply -f pvs/woodpecker-pv.yaml +kubectl apply -f pvs/harbor-pv.yaml echo " ✓ PVs applied" echo "" +# ------------------------------------------------------- +# 3b. Install Harbor container registry +# ------------------------------------------------------- +echo "--- Step 3b: Installing Harbor ---" +kubectl create namespace harbor-service --dry-run=client -o yaml | kubectl apply -f - + +# Remove old plain Docker Registry ingress (registry.celestium.life) if it exists +# Harbor will take over that domain +if kubectl get ingress registry-ingress -n git-server > /dev/null 2>&1; then + echo " Removing old registry ingress from git-server namespace..." + kubectl delete ingress registry-ingress -n git-server + echo " ✓ Old registry ingress removed" +fi + +# Create NFS directories on the NAS (via a temporary pod) +echo " Ensuring NFS directories exist..." +ssh root@gremlin-1 " + mkdir -p /tmp/harbor-nfs-init + mount -t nfs 192.168.42.8:/volume1/Kubernetes/harbor /tmp/harbor-nfs-init 2>/dev/null || true + mkdir -p /tmp/harbor-nfs-init/data/registry + mkdir -p /tmp/harbor-nfs-init/data/database + mkdir -p /tmp/harbor-nfs-init/data/redis + mkdir -p /tmp/harbor-nfs-init/data/jobservice + mkdir -p /tmp/harbor-nfs-init/data/trivy + umount /tmp/harbor-nfs-init 2>/dev/null || true + rmdir /tmp/harbor-nfs-init 2>/dev/null || true +" 2>/dev/null || echo " ⚠ Could not create NFS dirs via SSH (non-fatal, they may already exist)" + +# Apply PVCs +kubectl apply -f harbor/pvcs.yaml +echo " ✓ Harbor PVCs applied" + +# Install/upgrade Harbor via Helm +helm repo add harbor https://helm.goharbor.io 2>/dev/null || true +helm repo update harbor 2>/dev/null || true + +HARBOR_EXISTS=$(helm list -n harbor-service -q 2>/dev/null | grep -c harbor || true) +if [ "${HARBOR_EXISTS:-0}" -gt 0 ]; then + echo " Harbor already installed — upgrading..." +else + echo " Fresh Harbor install..." +fi + +helm upgrade --install harbor harbor/harbor \ + --namespace harbor-service \ + --values harbor/values.yaml \ + --timeout 10m \ + --wait + +echo " Waiting for Harbor core to be ready..." +kubectl wait --for=condition=ready pod -l app=harbor,component=core -n harbor-service --timeout=180s > /dev/null 2>&1 || true +echo " ✓ Harbor installed at https://registry.celestium.life" +echo " Default login: admin / St0nks0racl3!" +echo "" + # ------------------------------------------------------- # 4. Configure Gitea (admin user, repo, webhook config) # ------------------------------------------------------- @@ -246,6 +302,7 @@ echo "" echo "=== Pipeline Infrastructure Install Complete ===" echo "" echo "Endpoints:" +echo " Harbor: https://registry.celestium.life" echo " Woodpecker CI: https://stonks-ci.celestium.life" echo " ArgoCD: https://stonks-argocd.celestium.life" echo " Kargo: https://stonks-kargo.celestium.life"