Add GitOps stack for abrban.com with Gitea Actions CI/CD.
Build and Deploy Platform / build-push-deploy (push) Has been cancelled

Harbor in-cluster builds via Kaniko, ArgoCD auto-sync, and production Helm values for abrban.com domains.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-07-02 01:27:20 +03:30
parent ee5bd0a291
commit 5ed2ef0958
39 changed files with 1841 additions and 99 deletions
+76
View File
@@ -0,0 +1,76 @@
# GitOps stack for abrban.com
## DNS (A record → cluster IP `78.157.39.52`)
| Host | Purpose |
|------|---------|
| `abrban.com` | Landing / frontend |
| `panel.abrban.com` | Authenticated panel |
| `api.abrban.com` | Backend API |
| `registry.abrban.com` | Harbor |
| `git.abrban.com` | Gitea |
| `argocd.abrban.com` | Argo CD |
## Harbor proxy-cache (بدون mirror دستی)
Harbor ایمیج‌های upstream را on-demand می‌کشد و cache می‌کند:
| پروژه Harbor | upstream | مثال |
|--------------|----------|------|
| `proxy-dockerhub` | docker.io | `registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0` |
| `proxy-quay` | quay.io | `registry.abrban.com/proxy-quay/argoproj/argocd:v3.4.4` |
| `proxy-k8s` | registry.k8s.io | CSI sidecarها |
| `proxy-gitea` | docker.gitea.com | `registry.abrban.com/proxy-gitea/gitea:1.26.1-rootless` |
| `proxy-gcr` | gcr.io | `registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2` |
| `abrban` | — | ایمیج‌های ساخته‌شده (backend/frontend) |
اولین pull هر ایمیج کمی طول می‌کشد (Harbor از upstream می‌کشد). **نیازی به Job skopeo جداگانه نیست.**
k3s باید `registry.abrban.com` را به Harbor داخلی route کند:
```bash
./scripts/apply-k3s-registries.sh
```
## Install order
```bash
# 1. k3s → Harbor داخلی (بدون Traefik timeout)
./scripts/apply-k3s-registries.sh
# 2. Argo CD
helm upgrade --install argocd argo/argo-cd -n argocd --create-namespace \
-f gitops/argocd/values-bootstrap.yaml --timeout 15m --wait
# 3. Gitea (ایمیج‌ها از Harbor proxy-gitea)
helm upgrade --install gitea gitea-charts/gitea -n gitea --create-namespace \
-f gitops/gitea/values.yaml --timeout 15m --wait
# 4. TLS + registry secrets در namespaceهای argocd/gitea/cloudhost-builds
for ns in argocd gitea cloudhost-builds; do
kubectl -n cloudhost get secret abrban-wildcard-tls -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
kubectl -n cloudhost get secret registry-pull-secret -o yaml | sed "s/namespace: cloudhost/namespace: ${ns}/" | kubectl apply -f -
done
# 5. git push سورس به Gitea (نه docker push)
# git remote add gitea https://git.abrban.com/abrban/cloud-host.git
# git push gitea main
# 6. اولین build در کلاستر (Kaniko → abrban/)
./scripts/trigger-platform-build.sh
# 7. Deploy
./scripts/gitops-deploy.sh
# 8. Gitea Actions runner
kubectl apply -f gitops/gitea/act-runner.yaml
# 9. Argo CD Application
kubectl apply -f gitops/argocd/application-platform.yaml
```
## CI/CD
Gitea Actions: [.gitea/workflows/build-deploy.yaml](../.gitea/workflows/build-deploy.yaml)
Push به `main` → Kaniko (از Harbor proxy) → push به `abrban/` → ArgoCD sync.
+25
View File
@@ -0,0 +1,25 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: abrban-platform
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://git.abrban.com/abrban/cloud-host.git
targetRevision: main
path: backend/helm/cloudhost-platform
helm:
valueFiles:
- ../../../gitops/platform/values-abrban.yaml
destination:
server: https://kubernetes.default.svc
namespace: cloudhost
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=false
+32
View File
@@ -0,0 +1,32 @@
# Bootstrap install — uses images already cached on node (no Harbor push required)
configs:
params:
server.insecure: true
global:
image:
repository: quay.io/argoproj/argocd
tag: v3.4.4
redis:
image:
repository: ecr-public.aws.com/docker/library/redis
tag: 8.2.3-alpine
dex:
image:
repository: ghcr.io/dexidp/dex
tag: v2.45.1
server:
ingress:
enabled: true
ingressClassName: traefik
hostname: argocd.abrban.com
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
tls: true
extraTls:
- secretName: abrban-wildcard-tls
hosts:
- argocd.abrban.com
+33
View File
@@ -0,0 +1,33 @@
global:
image:
repository: registry.abrban.com/proxy-quay/argoproj/argocd
tag: v3.4.4
imagePullSecrets:
- name: registry-pull-secret
redis:
image:
repository: registry.abrban.com/proxy-dockerhub/library/redis
tag: 8.2.3-alpine
dex:
image:
repository: registry.abrban.com/proxy-dockerhub/dexidp/dex
tag: v2.45.1
configs:
params:
server.insecure: true
server:
ingress:
enabled: true
ingressClassName: traefik
hostname: argocd.abrban.com
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
tls: true
extraTls:
- secretName: abrban-wildcard-tls
hosts:
- argocd.abrban.com
+57
View File
@@ -0,0 +1,57 @@
# Gitea Actions runner — host mode + Kaniko (no docker.sock; k3s uses containerd)
apiVersion: v1
kind: Secret
metadata:
name: gitea-act-runner-token
namespace: gitea
type: Opaque
stringData:
token: "nL63VkZEyqpCNFdF3AMM9wzQLdLlATUvXSe5Tj0R"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitea-act-runner
namespace: gitea
spec:
replicas: 1
selector:
matchLabels:
app: gitea-act-runner
template:
metadata:
labels:
app: gitea-act-runner
spec:
imagePullSecrets:
- name: registry-pull-secret
initContainers:
- name: kaniko-bin
image: registry.abrban.com/abrban/kaniko-executor:v1.23.2
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "cp /kaniko/executor /kaniko-bin/executor && chmod +x /kaniko-bin/executor"]
volumeMounts:
- name: kaniko-bin
mountPath: /kaniko-bin
containers:
- name: runner
image: registry.abrban.com/abrban/act-runner:0.2.11
imagePullPolicy: IfNotPresent
env:
- name: GITEA_INSTANCE_URL
value: https://git.abrban.com
- name: GITEA_RUNNER_REGISTRATION_TOKEN
valueFrom:
secretKeyRef:
name: gitea-act-runner-token
key: token
- name: GITEA_RUNNER_NAME
value: k8s-abr-runner
- name: GITEA_RUNNER_LABELS
value: abrban-kaniko:host
volumeMounts:
- name: kaniko-bin
mountPath: /kaniko
volumes:
- name: kaniko-bin
emptyDir: {}
+55
View File
@@ -0,0 +1,55 @@
global:
imagePullSecrets:
- registry-pull-secret
storageClass: local-path
# Local copy in abrban/ (seeded by copy-gitea-image job) — kubelet pulls without proxy-cache
image:
registry: registry.abrban.com
repository: abrban/gitea
tag: 1.26.1
rootless: true
gitea:
config:
database:
DB_TYPE: sqlite3
server:
DOMAIN: git.abrban.com
ROOT_URL: https://git.abrban.com/
SSH_DOMAIN: git.abrban.com
actions:
ENABLED: true
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
hosts:
- host: git.abrban.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: abrban-wildcard-tls
hosts:
- git.abrban.com
persistence:
enabled: true
storageClass: local-path
size: 10Gi
# SQLite — no extra DB images to pull
postgresql:
enabled: false
valkey-cluster:
enabled: false
valkey:
enabled: false
postgresql-ha:
enabled: false
+60
View File
@@ -0,0 +1,60 @@
# In-cluster platform build (Kaniko → Harbor abrban/). Apply via scripts/trigger-platform-build.sh
# Base images pulled via Harbor proxy-cache — no separate mirror job.
apiVersion: batch/v1
kind: Job
metadata:
name: build-platform-images
namespace: cloudhost-builds
spec:
ttlSecondsAfterFinished: 3600
backoffLimit: 1
template:
spec:
restartPolicy: Never
imagePullSecrets:
- name: registry-pull-secret
initContainers:
- name: git-clone
image: registry.abrban.com/proxy-dockerhub/alpine/git:2.43.0
env:
- name: GIT_REPO
value: http://gitea-http.gitea.svc.cluster.local:3000/abrban/cloud-host.git
- name: GIT_REF
value: main
command:
- sh
- -ec
- |
git clone --depth=1 --branch "${GIT_REF}" "${GIT_REPO}" /workspace
volumeMounts:
- name: workspace
mountPath: /workspace
containers:
- name: kaniko
image: registry.abrban.com/proxy-gcr/kaniko-project/executor:v1.23.2
env:
- name: IMAGE_TAG
value: bootstrap
command:
- sh
- -ec
- |
set -eux
REG="harbor-registry.cloudhost.svc.cluster.local:5000/abrban"
/kaniko/executor \
--dockerfile=/workspace/backend/Dockerfile \
--context=dir:///workspace/backend \
--destination="${REG}/cloudhost-backend:${IMAGE_TAG}" \
--insecure --skip-tls-verify
/kaniko/executor \
--dockerfile=/workspace/frontend/Dockerfile \
--context=dir:///workspace/frontend \
--build-arg=NEXT_PUBLIC_API_URL=https://api.abrban.com \
--destination="${REG}/cloudhost-frontend:${IMAGE_TAG}" \
--insecure --skip-tls-verify
volumeMounts:
- name: workspace
mountPath: /workspace
volumes:
- name: workspace
emptyDir: {}
+37
View File
@@ -0,0 +1,37 @@
apiVersion: v1
kind: Pod
metadata:
name: image-import
namespace: cloudhost
spec:
nodeName: abr
restartPolicy: Never
hostNetwork: true
containers:
- name: import
image: quay.io/skopeo/stable:latest
command:
- sh
- -ec
- |
sleep 3600
securityContext:
privileged: true
volumeMounts:
- name: containerd-sock
mountPath: /run/containerd/containerd.sock
- name: containerd-sock-k3s
mountPath: /run/k3s/containerd/containerd.sock
- name: import-dir
mountPath: /import
volumes:
- name: containerd-sock
hostPath:
path: /run/k3s/containerd/containerd.sock
type: Socket
- name: containerd-sock-k3s
hostPath:
path: /run/k3s/containerd/containerd.sock
type: Socket
- name: import-dir
emptyDir: {}
+33
View File
@@ -0,0 +1,33 @@
# Bootstrap: copy act_runner + kaniko into abrban/ (kubelet cannot use proxy-cache reliably)
apiVersion: batch/v1
kind: Job
metadata:
name: seed-ci-images
namespace: cloudhost
spec:
ttlSecondsAfterFinished: 3600
backoffLimit: 2
template:
spec:
restartPolicy: Never
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: skopeo
image: registry.abrban.com/proxy-quay/skopeo/stable:latest
envFrom:
- secretRef:
name: registry-egress-proxy
command:
- sh
- -ec
- |
set -eux
DEST="docker://harbor-registry.cloudhost.svc.cluster.local:5000/abrban"
skopeo copy --dest-tls-verify=false \
docker://docker.gitea.com/gitea/act_runner:0.2.11 \
"${DEST}/act-runner:0.2.11"
skopeo copy --dest-tls-verify=false \
docker://gcr.io/kaniko-project/executor:v1.23.2 \
"${DEST}/kaniko-executor:v1.23.2"
echo SEED_OK
+15
View File
@@ -0,0 +1,15 @@
# k3s containerd registry config — apply on each node at /etc/rancher/k3s/registries.yaml
# Proxy-cache only works through harbor-core (not harbor-registry or Traefik /v2/ alone).
#
# Apply: ./scripts/apply-k3s-registries.sh
mirrors:
registry.abrban.com:
endpoint:
- http://harbor-core.cloudhost.svc.cluster.local # use ClusterIP on single-node (see script)
configs:
registry.abrban.com:
auth:
username: harbor_registry_user
password: REPLACE_WITH_REGISTRY_CREDENTIAL_PASSWORD
+56
View File
@@ -0,0 +1,56 @@
# Production values for abrban.com — used by ArgoCD / Gitea Actions GitOps
namespace: cloudhost
createNamespace: false
global:
storageClass: local-path
images:
backend:
repository: registry.abrban.com/abrban/cloudhost-backend
tag: "1.0.0"
pullPolicy: Always
frontend:
repository: registry.abrban.com/abrban/cloudhost-frontend
tag: "1.0.0"
pullPolicy: Always
backend:
imagePullSecrets:
- name: registry-pull-secret
sourceStorage:
enabled: true
existingSecret: ceph-app-sources-credentials
env:
NODE_ENV: production
PORT: "4000"
PLATFORM_DOMAIN: apps.abrban.com
REGISTRY_URL: registry.abrban.com
REGISTRY_PULL_URL: registry.abrban.com
BUILD_NAMESPACE: cloudhost-builds
BUILD_SERVICE_ACCOUNT: kaniko-builder
UPLOAD_DIR: /app/uploads
PLATFORM_CREATE_STORAGE_CLASS: "false"
PLATFORM_STORAGE_CLASS: rook-ceph-block
PLATFORM_STORAGE_PROVISIONER: rook-ceph.rbd.csi.ceph.com
ELASTICSEARCH_HOST: elasticsearch.logging.svc.cluster.local
ELASTICSEARCH_AUTO_PORT_FORWARD: "false"
frontend:
imagePullSecrets:
- name: registry-pull-secret
ingress:
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
frontend:
host: abrban.com
panel:
host: panel.abrban.com
api:
host: api.abrban.com
tls:
enabled: true
secretName: abrban-wildcard-tls
@@ -0,0 +1,12 @@
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: long-timeout
namespace: cloudhost
spec:
buffering:
maxRequestBodyBytes: 0
memRequestBodyBytes: 0
maxResponseBodyBytes: 0
memResponseBodyBytes: 0
retryExpression: "IsNetworkError() && Attempts() < 3"