ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
9 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,200 @@
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: forgejo
namespace: forgejo
spec:
interval: 15m
releaseName: forgejo
targetNamespace: forgejo
chart:
spec:
chart: forgejo
version: 17.3.2
sourceRef:
kind: HelmRepository
name: forgejo
namespace: flux-system
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
# Chart merges deployment.labels into spec.selector (immutable). Pod-only label.
postRenderers:
- kustomize:
patches:
- target:
kind: Deployment
name: forgejo
patch: |-
- op: add
path: /spec/template/metadata/labels/gateway.quorate.internal~1allow-gateway-client
value: "true"
- op: add
path: /spec/template/metadata/labels/quorate.dev~1zitadel-relay
value: "true"
values:
image:
registry: code.forgejo.org
repository: forgejo/forgejo
tag: 17.0.1
digest: sha256:5ef02fbcf22beef56b8c844952ffad58cfe177b6f98e46e6abb5df90b88dc8d3
rootless: true
replicaCount: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
minReadySeconds: 5
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo
initPreScript: |
mkdir -p /data/gitea/log
chmod ug+rwx /data/gitea/log
serviceAccount:
create: false
name: forgejo
podSecurityContext:
fsGroup: 1000
containerSecurityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL
add:
- SYS_CHROOT
deployment:
env:
# Forgejo MinIO uses Go http.Transport; SSL_CERT_DIR is reliable for custom CAs.
- name: SSL_CERT_DIR
value: /usr/local/share/ca-certificates
extraVolumes:
- name: internal-ca
secret:
secretName: forgejo-internal-ca
extraContainerVolumeMounts:
- name: internal-ca
mountPath: /usr/local/share/ca-certificates
readOnly: true
service:
http:
type: ClusterIP
port: 3000
ssh:
type: LoadBalancer
port: 22
externalTrafficPolicy: Local
annotations:
lbipam.cilium.io/ips: "10.190.165.53"
labels:
io.cilium/bgp-announce: "true"
persistence:
enabled: true
create: false
claimName: forgejo-shared-storage-rwx
size: 20Gi
accessModes:
- ReadWriteMany
storageClass: longhorn-rwx
resources:
requests:
cpu: 250m
memory: 512Mi
limits:
memory: 2Gi
gitea:
admin:
existingSecret: ""
username: ""
oauth:
- name: Zitadel
provider: openidConnect
existingSecret: forgejo-oidc-zitadel
autoDiscoverUrl: https://auth.quorate.dev/.well-known/openid-configuration
scopes: "openid profile email groups"
requiredClaimName: "groups"
requiredClaimValue: "forgejo_login"
groupClaimName: "groups"
adminGroup: "forgejo_admin"
restrictedGroup: "forgejo_restricted"
additionalConfigSources:
- secret:
secretName: forgejo-secrets
additionalConfigFromEnvs:
- name: FORGEJO__DATABASE__PASSWD
valueFrom:
secretKeyRef:
name: forgejo-db
key: password
config:
APP_NAME: "Quorate Forge"
log:
LEVEL: info
LOGGER_ROUTER_MODE: console
ROOT_PATH: /data/gitea/log
server:
DOMAIN: forge.quorate.internal
ROOT_URL: https://forge.quorate.internal/
PROTOCOL: http
HTTP_PORT: 3000
SSH_DOMAIN: forge-ssh.quorate.internal
SSH_PORT: 22
SSH_LISTEN_PORT: 2222
LFS_START_SERVER: false
database:
DB_TYPE: postgres
HOST: main-rw.postgres.svc.cluster.local:5432
NAME: forgejo
USER: forgejo
SSL_MODE: require
openid:
ENABLE_OPENID_SIGNIN: false
ENABLE_OPENID_SIGNUP: false
oauth2_client:
OPENID_CONNECT_SCOPES: "openid profile email groups"
ENABLE_AUTO_REGISTRATION: true
USERNAME: nickname
ACCOUNT_LINKING: disabled
UPDATE_AVATAR: true
GROUP_CLAIM_NAME: "groups"
ADMIN_GROUP: "forgejo_admin"
ENABLE_OIDC_GROUP_CLAIM: true
RE_MANAGE_GROUPS_ON_SIGNIN: true
FETCH_USER_INFO_FROM_USERINFO_ENDPOINT: true
service:
DISABLE_REGISTRATION: false
ALLOW_ONLY_EXTERNAL_REGISTRATION: true
REQUIRE_SIGNIN_VIEW: true
SHOW_REGISTRATION_BUTTON: false
ENABLE_INTERNAL_SIGNIN: false
repository:
ROOT: /data/git/repositories
DISABLED_REPO_UNITS: "repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions,repo.ext_issues,repo.ext_wiki"
DEFAULT_REPO_UNITS: "repo.code,repo.releases"
DISABLE_MIGRATIONS: true
indexer:
REPO_INDEXER_ENABLED: false
cron:
ENABLED: false
mirror:
ENABLED: false
actions:
ENABLED: false
metrics:
ENABLED: false
test:
enabled: false

View file

@ -0,0 +1,11 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
- pvc-rwx.yaml
- vso.yaml
- vso-internal-ca.yaml
- helm-release.yaml
- poddisruptionbudget.yaml
- network-policies.yaml
- route.yaml

13
vendor/platform/forgejo/namespace.yaml vendored Normal file
View file

@ -0,0 +1,13 @@
---
apiVersion: v1
kind: Namespace
metadata:
labels:
gateway.quorate.internal/allow-internal: "true"
name: forgejo
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: forgejo
namespace: forgejo

View file

@ -0,0 +1,163 @@
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: forgejo
namespace: forgejo
spec:
endpointSelector:
matchLabels:
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo
ingress:
# Kubelet probes, local port-forwarding, and same-node LoadBalancer backend flows.
- fromEntities:
- host
toPorts:
- ports:
- port: "3000"
protocol: TCP
- port: "2222"
protocol: TCP
# Gateway I Envoy proxy: outbound connections use reserved:ingress identity.
- fromEntities:
- ingress
toPorts:
- ports:
- port: "3000"
protocol: TCP
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
gateway.networking.k8s.io/gateway-name: gateway-internal
toPorts:
- ports:
- port: "3000"
protocol: TCP
# Flux source-controller clones the GitOps repository over in-cluster SSH.
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: flux-system
app: source-controller
toPorts:
- ports:
- port: "2222"
protocol: TCP
# Internal SSH clients hit the dedicated forgejo-ssh LoadBalancer service.
- fromCIDR:
- 10.115.187.218/24
- 10.63.81.107/24
- 10.162.8.60/24
toPorts:
- ports:
- port: "2222"
protocol: TCP
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: postgres
cnpg.io/cluster: main
toPorts:
- ports:
- port: "5432"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: dragonfly
app.kubernetes.io/name: dragonfly
app: forgejo
toPorts:
- ports:
- port: "6379"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: versitygw
app.kubernetes.io/name: versitygw
app.kubernetes.io/instance: versitygw
toPorts:
- ports:
- port: "7070"
protocol: TCP
# In-cluster clients reach S3 through versitygw-direct BGP LoadBalancer (socket-LB VIP).
- toCIDR:
- 10.66.127.81/32
toPorts:
- ports:
- port: "443"
protocol: TCP
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- port: "53"
protocol: UDP
- port: "53"
protocol: TCP
# OIDC discovery/token exchange and future repository migrations over HTTPS.
- toEntities:
- world
toPorts:
- ports:
- port: "443"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: gateway-internal-egress-forgejo
spec:
endpointSelector:
matchLabels:
"reserved:ingress": ""
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: forgejo
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo
toPorts:
- ports:
- port: "3000"
protocol: TCP
---
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-egress-forgejo
spec:
nodeSelector: {}
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: forgejo
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo
toPorts:
- ports:
- port: "3000"
protocol: TCP
- port: "2222"
protocol: TCP
---
# Same-node Gateway/LB backend selections can return to node-local ephemeral
# source ports via the host path.
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
name: host-ingress-forgejo-replies
spec:
nodeSelector: {}
ingress:
- fromEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: forgejo
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo
toPorts:
- ports:
- port: "32768"
endPort: 60999
protocol: TCP

View file

@ -0,0 +1,11 @@
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: forgejo
namespace: forgejo
spec:
minAvailable: 1
selector:
matchLabels:
app.kubernetes.io/name: forgejo
app.kubernetes.io/instance: forgejo

13
vendor/platform/forgejo/pvc-rwx.yaml vendored Normal file
View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: forgejo-shared-storage-rwx
namespace: forgejo
spec:
accessModes:
- ReadWriteMany
storageClassName: longhorn-rwx
volumeMode: Filesystem
resources:
requests:
storage: 20Gi

16
vendor/platform/forgejo/route.yaml vendored Normal file
View file

@ -0,0 +1,16 @@
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: forgejo
namespace: forgejo
spec:
parentRefs:
- name: gateway-internal
namespace: kube-system
sectionName: https
hostnames:
- forge.quorate.internal
rules:
- backendRefs:
- name: forgejo-http
port: 3000

View file

@ -0,0 +1,27 @@
# Internal root CA for Forgejo S3 TLS verification.
# Kept separate from forgejo-secrets because that secret is mounted as INI config.
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: forgejo-internal-ca
namespace: forgejo
spec:
type: kv-v2
mount: secret
path: forgejo/secrets
destination:
name: forgejo-internal-ca
create: true
overwrite: true
transformation:
excludeRaw: true
excludes:
- .*
templates:
internal-ca.crt:
text: |
{{ get .Secrets "internal_ca_cert" }}
rolloutRestartTargets:
- kind: Deployment
name: forgejo
vaultAuthRef: default

116
vendor/platform/forgejo/vso.yaml vendored Normal file
View file

@ -0,0 +1,116 @@
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: default
namespace: forgejo
spec:
method: kubernetes
mount: kubernetes
kubernetes:
role: forgejo
serviceAccount: forgejo
vaultConnectionRef: vault/vault
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: forgejo-oidc-zitadel
namespace: forgejo
spec:
type: kv-v2
mount: secret
path: forgejo/oidc/zitadel
destination:
name: forgejo-oidc-zitadel
create: true
vaultAuthRef: default
---
# Vault database static role - password rotates every 7 days.
# rolloutRestartTargets triggers a rolling restart so Forgejo picks up the new credentials.
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: forgejo-db
namespace: forgejo
spec:
mount: database
path: static-creds/forgejo
destination:
name: forgejo-db
create: true
rolloutRestartTargets:
- kind: Deployment
name: forgejo
vaultAuthRef: default
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
name: forgejo-secrets
namespace: forgejo
spec:
type: kv-v2
mount: secret
path: forgejo/secrets
destination:
name: forgejo-secrets
create: true
overwrite: true
transformation:
excludeRaw: true
excludes:
- .*
templates:
cache:
text: |
ADAPTER=redis
HOST=redis://default:{{ get .Secrets "redis_password" }}@forgejo.dragonfly.svc.cluster.local:6379/0?pool_size=100&idle_timeout=180s
session:
text: |
PROVIDER=redis
PROVIDER_CONFIG=redis://default:{{ get .Secrets "redis_password" }}@forgejo.dragonfly.svc.cluster.local:6379/1?pool_size=100&idle_timeout=180s
queue:
text: |
TYPE=redis
CONN_STR=redis://default:{{ get .Secrets "redis_password" }}@forgejo.dragonfly.svc.cluster.local:6379/2?pool_size=100&idle_timeout=180s
attachment:
text: |
STORAGE_TYPE=minio
MINIO_ENDPOINT=s3.quorate.internal
MINIO_ACCESS_KEY_ID=forgejo
MINIO_SECRET_ACCESS_KEY={{ get .Secrets "s3_secret_key" }}
MINIO_BUCKET=forgejo
MINIO_BUCKET_LOOKUP=path
MINIO_LOCATION=us-east-1
MINIO_USE_SSL=true
MINIO_INSECURE_SKIP_VERIFY=false
MINIO_BASE_PATH=attachments/
avatar:
text: |
STORAGE_TYPE=minio
MINIO_ENDPOINT=s3.quorate.internal
MINIO_ACCESS_KEY_ID=forgejo
MINIO_SECRET_ACCESS_KEY={{ get .Secrets "s3_secret_key" }}
MINIO_BUCKET=forgejo
MINIO_BUCKET_LOOKUP=path
MINIO_LOCATION=us-east-1
MINIO_USE_SSL=true
MINIO_INSECURE_SKIP_VERIFY=false
MINIO_BASE_PATH=avatars/
repo-avatar:
text: |
STORAGE_TYPE=minio
MINIO_ENDPOINT=s3.quorate.internal
MINIO_ACCESS_KEY_ID=forgejo
MINIO_SECRET_ACCESS_KEY={{ get .Secrets "s3_secret_key" }}
MINIO_BUCKET=forgejo
MINIO_BUCKET_LOOKUP=path
MINIO_LOCATION=us-east-1
MINIO_USE_SSL=true
MINIO_INSECURE_SKIP_VERIFY=false
MINIO_BASE_PATH=repo-avatars/
rolloutRestartTargets:
- kind: Deployment
name: forgejo
vaultAuthRef: default