diff --git a/k8s/infrastructure/harbor/helmrelease.yaml b/k8s/infrastructure/harbor/helmrelease.yaml new file mode 100644 index 0000000..3dd6e24 --- /dev/null +++ b/k8s/infrastructure/harbor/helmrelease.yaml @@ -0,0 +1,64 @@ +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: harbor + namespace: harbor +spec: + interval: 10m + timeout: 15m + chart: + spec: + chart: harbor + version: "1.16.x" + sourceRef: + kind: HelmRepository + name: harbor + namespace: flux-system + install: + remediation: + retries: 3 + upgrade: + remediation: + retries: 3 + remediateLastFailure: true + values: + externalURL: https://harbor.n0ball.tw + expose: + type: ingress + tls: + enabled: true + certSource: secret + secret: + secretName: harbor-tls + ingress: + hosts: + core: harbor.n0ball.tw + className: traefik + annotations: + cert-manager.io/cluster-issuer: "n0ball-tw-issuer" + persistence: + enabled: true + persistentVolumeClaim: + registry: + storageClass: longhorn + size: 20Gi + jobservice: + jobLog: + storageClass: longhorn + size: 1Gi + existingSecretAdminPassword: harbor-admin-secret + existingSecretAdminPasswordKey: HARBOR_ADMIN_PASSWORD + database: + type: external + external: + host: pgbouncer.default.svc.cluster.local + port: "6432" + username: harbor + coreDatabase: harbor + existingSecret: harbor-db-secret + sslmode: disable + redis: + type: internal + existingSecretSecretKey: harbor-secret-key + trivy: + enabled: true diff --git a/k8s/infrastructure/harbor/kustomization.yaml b/k8s/infrastructure/harbor/kustomization.yaml new file mode 100644 index 0000000..0370974 --- /dev/null +++ b/k8s/infrastructure/harbor/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - namespace.yaml + - helmrelease.yaml diff --git a/k8s/infrastructure/harbor/namespace.yaml b/k8s/infrastructure/harbor/namespace.yaml new file mode 100644 index 0000000..0a27fb7 --- /dev/null +++ b/k8s/infrastructure/harbor/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: harbor diff --git a/k8s/infrastructure/helmrepositories.yaml b/k8s/infrastructure/helmrepositories.yaml index a197b6e..d2865c3 100644 --- a/k8s/infrastructure/helmrepositories.yaml +++ b/k8s/infrastructure/helmrepositories.yaml @@ -71,3 +71,12 @@ metadata: spec: interval: 1h url: https://codecentric.github.io/helm-charts +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: harbor + namespace: flux-system +spec: + interval: 1h + url: https://helm.goharbor.io diff --git a/k8s/infrastructure/kustomization.yaml b/k8s/infrastructure/kustomization.yaml index caf78b3..555ab18 100644 --- a/k8s/infrastructure/kustomization.yaml +++ b/k8s/infrastructure/kustomization.yaml @@ -12,3 +12,4 @@ resources: - oidc-rbac.yaml - coredns-custom.yaml - coredns-ci-rbac.yaml + - harbor diff --git a/k8s/infrastructure/sops/harbor-admin-secret.yaml b/k8s/infrastructure/sops/harbor-admin-secret.yaml new file mode 100644 index 0000000..a630d55 --- /dev/null +++ b/k8s/infrastructure/sops/harbor-admin-secret.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Secret +metadata: + name: harbor-admin-secret + namespace: harbor +stringData: + HARBOR_ADMIN_PASSWORD: ENC[AES256_GCM,data:mP4EXiVJYNjEp3mNFVARIhdIaFDGMlJm,iv:KiDtckSsxqpX4JAApEbRdKTdaaL8yymBoufV1JwuHt8=,tag:VeVBK1p/B/dZp9bmJVpT+w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1y5rw08wm2s2hemapzf43c0l4xass7fhc55qh3n4cxtuxzrj8q3cqtydy7m + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvNWQyNFp4N1lMdDZmOTZx + Tmo1cDlqQklWUHN4NFlxV2E2bmJLdk9LUkZrCjFLanhVNkpSNGdIMHUxclhlRmtk + LzJPcStFSEo0d3QzN2xjZmkycExKY1kKLS0tIHY1UHMyZExUazZtcHpoalFHYUlI + WE4rK3VYMG92bnpEMUV2dHRhT2N4bjQKPAs6s4jPd15UD6BycVwqPssZeqKximN9 + 9XLjRxN8Eb4tdz7FIf4o2xvIIIV/mcvI0U8/afvtCo48IMXSYwQRDw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-10T15:07:53Z" + mac: ENC[AES256_GCM,data:NYoIeqqC2AWIMTGFxWyrhcJ0iDhhTtIaCno/kVu9a46bgzeGbLhiAngSFI+4eCj/PAk0g2YShWTXSk9SOBH3XyfzdTB325qHddCYktzdQJWzlK6kBAN2WbbWpmTOlvwdms8JSK8aUXScBNvhWvwkTTGaMSxN1mL448RO2u8TjDM=,iv:rhF70zPjAY9AyoK+4iHwy1HhzQQNv+bQQid6EcAVz/o=,tag:40oSCOCsxOfCfoQZMr64Qg==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/k8s/infrastructure/sops/harbor-db-secret.yaml b/k8s/infrastructure/sops/harbor-db-secret.yaml new file mode 100644 index 0000000..793f29b --- /dev/null +++ b/k8s/infrastructure/sops/harbor-db-secret.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Secret +metadata: + name: harbor-db-secret + namespace: harbor +stringData: + password: ENC[AES256_GCM,data:wADvFVqko4CET0zldtHtRcjrrpkhGK5/,iv:iy9SFHnBz+QVj0Wr6d+0WDH8hfcAUmyeV0NMiTkoV2g=,tag:geN4OjZULqkiiltqe4gNEw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1y5rw08wm2s2hemapzf43c0l4xass7fhc55qh3n4cxtuxzrj8q3cqtydy7m + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpbW5JVmpoRzV6VjI5Y0JN + WnVBaXlHdmd5UEo3MjlwWnpJUXluSzZIZ1F3CitLMHBYZ2tadVdEQnViNS9yWHJr + d1dEWWJsOXFKV3g4ZjR4MXpGb2lKdXMKLS0tIFRMSHV5dkRFdVY1OXVaWjhiTTZK + UENrNmQ1dXhVSWk0QjRHM2NvUW5SL3cKHym0eHR4pzTBoEsFz69DHY9OdP4UPTmH + /T5kPU1BE0ywr7so7XqAeYI6Wq7/4snpixdkvQjLvumUlgmqn4lAsg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-10T15:07:53Z" + mac: ENC[AES256_GCM,data:+fQR4HmyRn8IcGUTiz1RP4idmkiUJfoCqxoa1R8jM/Ld7UNBZI8hW2mvcOrdiGRYsRZb/3U/6Isd8eEtmFuyFSRtUeVczd1E1c8BVj2Oze+qDZ096hC1pi2S8libMujMJdMNrodFZVPUcGOJ0VklegWyiwl6fugE/2yXP8xRuQk=,iv:YpzaQm55HMGtMctIURBAWhRyDYbnwu/1v0HI0NJFOJE=,tag:nE6Q5lPbgRrTbQ7xDjVlpw==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/k8s/infrastructure/sops/harbor-secret-key.yaml b/k8s/infrastructure/sops/harbor-secret-key.yaml new file mode 100644 index 0000000..61d9651 --- /dev/null +++ b/k8s/infrastructure/sops/harbor-secret-key.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Secret +metadata: + name: harbor-secret-key + namespace: harbor +stringData: + secretKey: ENC[AES256_GCM,data:iw3KA9fgCmseqtRRATlRmQ==,iv:mPaHpSO2NAMZYkdBJCvmP94Pfpjq0278VHNhWfdoRtQ=,tag:zBsRUCRiZM5yNFWarUoQdw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1y5rw08wm2s2hemapzf43c0l4xass7fhc55qh3n4cxtuxzrj8q3cqtydy7m + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDdW1GVDY0UFdMdnd6WDJK + TU1vR28zeG5lbmFkMUdXOXpmblhJVGlxQ3pRClk1M0J0M0p0QmRSMitUWWdpckRh + VkhwRC9HWmlxTFk0V1N3ODV6ZTJHMFUKLS0tIGRwZk5STFNXRHhMT3NDd1QrVk5M + Zm14dHlibkxzR3Y4VWhSRk9rcXVGeWMKL4Tm7o3VOcIvTUetNCFKmJ+Qqq1BONoC + mgGyGnQzSY/jJCAw4tZUVljNAeHX6xa7xfLXT0/L0N6Vu+1M7oofiA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-10T15:09:02Z" + mac: ENC[AES256_GCM,data:fcS7WIMhqduOu7V7GBvilhipMClwvv9BYJrLXkijqQqHvbtG2ajI+xgcI+Ms4w5I85NZOFSpC24TMxMc/KoKvu6NJ6ZRNxnaT9JnnQRhKeHJFIvlCdQzZVJHKT56xNtixxKWl8X9HRw/DqfcFmpwgguF7opsdS62w03b0Nmis6o=,iv:+oAD98VDuwTY5deoJrt/5ZADQKoVPtSGxX+h1tZPv6I=,tag:cHeERvYHkAqfr6R9mEwnAA==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/k8s/infrastructure/sops/kustomization.yaml b/k8s/infrastructure/sops/kustomization.yaml index f3922cd..2fb16f3 100644 --- a/k8s/infrastructure/sops/kustomization.yaml +++ b/k8s/infrastructure/sops/kustomization.yaml @@ -12,3 +12,6 @@ resources: - grafana-smtp-secret.yaml - vaultwarden-smtp-secret.yaml - repo-gpg-key-secret.yaml + - harbor-admin-secret.yaml + - harbor-db-secret.yaml + - harbor-secret-key.yaml diff --git a/k8s/pg-init/harbor-db-bootstrap-secret.yaml b/k8s/pg-init/harbor-db-bootstrap-secret.yaml new file mode 100644 index 0000000..897df98 --- /dev/null +++ b/k8s/pg-init/harbor-db-bootstrap-secret.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Secret +metadata: + name: harbor-db-bootstrap-secret + namespace: pg-init +stringData: + password: ENC[AES256_GCM,data:OJBe4FyWvZ2nS67cFqJ3qqiTqdeefB3W,iv:18/yf68XBn5wgQYnvbMOPcGtoBFnu9NyvqHfBuNhSPU=,tag:keAge6nYnmgJiFeGJ9ZwCg==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1y5rw08wm2s2hemapzf43c0l4xass7fhc55qh3n4cxtuxzrj8q3cqtydy7m + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHdkV2TElTRThqclRIejJ3 + NmZRSTUxR0k3a3hBVWtkRXRZWHlEMnhlK2xvClNpR20xdWl3cFg2TnMzRGVwOUhW + MHREM3hnU1pvZVdKaHBsaDVqL0dMbFEKLS0tIDZDTWVOejNScXhFN3hBdnlxbzJF + Q2l0NXlPekNoZGV2MWhWQzdKWnBEY2sKUZhXXzrDguN8MyWrAGFv3E49O4/LlsXc + Ep1fuFnQze7oRiLfaCuEi3Mzy6P5zlH4A5KfOLTE8TxIkrta9UlWAg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-03-10T15:08:09Z" + mac: ENC[AES256_GCM,data:Y8jjuSB+VYf2JXffxwjnfaOZZGJkJh4e45Aj5cc31kA186rBnY5+OhOocIhrV2Nm44JQ00XhaRsqbdNmpFn2/RsDEN42zuqyv15rwRzGgJ74L9rVE7aFpoLQUcHMN+rehjlLw5Pz53IvCrWmwWBa7z6RfM2cXGch2Cnd3ITosuQ=,iv:KtT9PW+2wnszojDvvic1J0LWMvDC8TQjzWurAvEwxb8=,tag:qzqtcPcyCFPGeLLTs2WrXw==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/k8s/pg-init/harbor-db.yaml b/k8s/pg-init/harbor-db.yaml new file mode 100644 index 0000000..7d8d89d --- /dev/null +++ b/k8s/pg-init/harbor-db.yaml @@ -0,0 +1,43 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: harbor-db-init-v1 + namespace: pg-init +spec: + ttlSecondsAfterFinished: 300 + template: + spec: + restartPolicy: OnFailure + containers: + - name: db-init + image: postgres:17 + env: + - name: PGHOST + value: pgbouncer.default.svc.cluster.local + - name: PGPORT + value: "6432" + - name: PGUSER + value: pginit + - name: PGDATABASE + value: postgres + - name: PGPASSWORD + valueFrom: + secretKeyRef: + name: pg-init-secret + key: password + - name: HARBOR_DB_PASSWORD + valueFrom: + secretKeyRef: + name: harbor-db-bootstrap-secret + key: password + command: + - bash + - -ec + - | + psql -c "SELECT 1 FROM pg_roles WHERE rolname='harbor'" | grep -q 1 || \ + psql -c "CREATE USER harbor WITH PASSWORD '${HARBOR_DB_PASSWORD}';" + psql -c "GRANT harbor TO pginit;" + psql -c "SELECT 1 FROM pg_database WHERE datname='harbor'" | grep -q 1 || \ + psql -c "CREATE DATABASE harbor OWNER harbor;" + psql -c "GRANT ALL PRIVILEGES ON DATABASE harbor TO harbor;" + psql -d harbor -c "GRANT ALL ON SCHEMA public TO harbor;" diff --git a/k8s/pg-init/kustomization.yaml b/k8s/pg-init/kustomization.yaml index f6eac90..75a6112 100644 --- a/k8s/pg-init/kustomization.yaml +++ b/k8s/pg-init/kustomization.yaml @@ -7,3 +7,5 @@ resources: - vaultwarden-db-bootstrap-secret.yaml - keycloak-db.yaml - vaultwarden-db.yaml + - harbor-db-bootstrap-secret.yaml + - harbor-db.yaml