Files
cloud-host/backend/k8s/nixpacks-spike/nixpacks-spike.yaml
T
keyhan 3eff38f8d2 feat(build): revamp app build pipeline (queue, Nixpacks, MinIO, Trivy, registry GC)
Rework the application build/deploy pipeline for scalability, reproducibility,
and security:

- Build queue: deploys run through a bounded-concurrency Bull queue
  (BUILD_CONCURRENCY, default 3) so concurrent user deploys can't flood the
  cluster with Kaniko jobs. Build state (progress / cancel / session) moves from
  in-memory Maps to Redis, so cancel + live logs work across backend replicas.
- Nixpacks + BYO Dockerfile: code runtimes build via Nixpacks (or the user's own
  Dockerfile when present); the hand-written per-runtime Dockerfile generators
  and runtime auto-detection are removed. WordPress keeps its templated path.
  Build-time mirror env (NIXPACKS_BUILD_ENV) supports the Iran network.
- Source upload to MinIO: archives stream to in-cluster MinIO; build pods pull
  via a presigned URL. Removes the PVC + helper pod + kubectl cp upload path.
- Report-only Trivy scan after build; per-severity summary stored on the
  deployment and shown as a badge in the dashboard. Never gates a deploy.
- Registry GC: a Redis-locked daily job keeps the newest N image tags per app
  (REGISTRY_KEEP_VERSIONS, default 3) and reclaims disk via garbage-collect.
- Hardening: git tokens are delivered via a per-build Secret + git credential
  store instead of being embedded in the clone URL / Job manifest; build timeout
  is configurable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:58:58 +03:30

213 lines
8.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ─────────────────────────────────────────────────────────────────────────────
# فاز ۰ — Spike ریسک Nixpacks روی شبکه‌ی ایران (abrban / cloudhost-builds)
#
# هدف: قبل از مهاجرت سیستم بیلد به Nixpacks (فاز ۲)، مطمئن شویم زنجیره‌ی
# nixpacks (تولید Dockerfile) → kaniko (build واقعی + نصب وابستگی‌ها)
# پشت شبکه‌ی ایران کار می‌کند و کشف کنیم چه mirror/proxy لازم است.
#
# چرا این ساختار: `nixpacks build --out` فقط Dockerfile می‌سازد و دانلودی ندارد؛
# دانلود سنگین (nixpkgs + npm/go modules) داخل مرحله‌ی Docker build اتفاق می‌افتد.
# پس برای تست واقعی شبکه باید kaniko همان Dockerfile تولیدی را build کند.
# با --no-push نیازی به رجیستری/کردنشال نیست — فقط build تست می‌شود.
#
# اجرا:
# kubectl apply -f nixpacks-spike.yaml
# kubectl -n cloudhost-builds logs -f job/nixpacks-spike-node
# kubectl -n cloudhost-builds logs -f job/nixpacks-spike-go
# # بعد از اتمام:
# kubectl -n cloudhost-builds delete -f nixpacks-spike.yaml
#
# اگر kaniko سرِ `RUN ... npm install` یا fetch nixpkgs گیر کرد → شبکه‌ی ایران
# مانع است؛ env های mirror را (بخش «نکات mirror» پایین فایل) فعال/تنظیم کنید و
# دوباره اجرا کنید. نتیجه را برای تصمیم فاز ۲ مستند کنید.
# ─────────────────────────────────────────────────────────────────────────────
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nixpacks-spike-node-src
namespace: cloudhost-builds
data:
package.json: |
{
"name": "nixpacks-spike",
"version": "1.0.0",
"private": true,
"scripts": { "start": "node index.js" },
"dependencies": { "express": "^4.18.2" }
}
index.js: |
const express = require('express');
const app = express();
app.get('/', (_req, res) => res.send('nixpacks spike ok'));
app.listen(process.env.PORT || 3000, () => console.log('up'));
---
apiVersion: batch/v1
kind: Job
metadata:
name: nixpacks-spike-node
namespace: cloudhost-builds
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 1800
template:
spec:
restartPolicy: Never
volumes:
- name: workspace
emptyDir: {}
- name: src
configMap:
name: nixpacks-spike-node-src
initContainers:
# 1) staging سورس نمونه از ConfigMap به workspace
- name: stage-source
image: alpine:3.19
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
set -e
mkdir -p /workspace/source
cp /src/package.json /workspace/source/package.json
cp /src/index.js /workspace/source/index.js
echo ">>> staged source:" && ls -la /workspace/source
volumeMounts:
- { name: workspace, mountPath: /workspace }
- { name: src, mountPath: /src }
# 2) Nixpacks: تولید Dockerfile در /workspace/source/.nixpacks/Dockerfile
- name: nixpacks-plan
image: ghcr.io/railwayapp/nixpacks:latest
imagePullPolicy: IfNotPresent
# نگاشت همان تنظیماتی که فاز ۲ پاس می‌دهد (نسخه‌ی Node و PORT)
env:
- { name: NIXPACKS_NODE_VERSION, value: "20" }
# - { name: NPM_CONFIG_REGISTRY, value: "https://registry.npmmirror.com" } # ← در صورت نیاز
command:
- nixpacks
- build
- /workspace/source
- --out
- /workspace/source
volumeMounts:
- { name: workspace, mountPath: /workspace }
containers:
# 3) Kaniko: build واقعی Dockerfile تولیدی (تست دانلود وابستگی‌ها). بدون push.
- name: kaniko
image: gcr.io/kaniko-project/executor:v1.23.2
imagePullPolicy: IfNotPresent
args:
- --dockerfile=/workspace/source/.nixpacks/Dockerfile
- --context=dir:///workspace/source
- --no-push
- --verbosity=info
volumeMounts:
- { name: workspace, mountPath: /workspace }
resources:
requests: { cpu: "500m", memory: "1Gi" }
limits: { cpu: "2", memory: "4Gi" }
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nixpacks-spike-go-src
namespace: cloudhost-builds
data:
go.mod: |
module nixpacksspike
go 1.22
main.go: |
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
fmt.Fprintln(w, "nixpacks spike ok")
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
http.ListenAndServe(":"+port, nil)
}
---
apiVersion: batch/v1
kind: Job
metadata:
name: nixpacks-spike-go
namespace: cloudhost-builds
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 1800
template:
spec:
restartPolicy: Never
volumes:
- name: workspace
emptyDir: {}
- name: src
configMap:
name: nixpacks-spike-go-src
initContainers:
- name: stage-source
image: alpine:3.19
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- |
set -e
mkdir -p /workspace/source
cp /src/go.mod /workspace/source/go.mod
cp /src/main.go /workspace/source/main.go
echo ">>> staged source:" && ls -la /workspace/source
volumeMounts:
- { name: workspace, mountPath: /workspace }
- { name: src, mountPath: /src }
- name: nixpacks-plan
image: ghcr.io/railwayapp/nixpacks:latest
imagePullPolicy: IfNotPresent
env:
# - { name: GOPROXY, value: "https://goproxy.cn,direct" } # ← در صورت نیاز (mirror چین)
command:
- nixpacks
- build
- /workspace/source
- --out
- /workspace/source
volumeMounts:
- { name: workspace, mountPath: /workspace }
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:v1.23.2
imagePullPolicy: IfNotPresent
args:
- --dockerfile=/workspace/source/.nixpacks/Dockerfile
- --context=dir:///workspace/source
- --no-push
- --verbosity=info
volumeMounts:
- { name: workspace, mountPath: /workspace }
resources:
requests: { cpu: "500m", memory: "1Gi" }
limits: { cpu: "2", memory: "4Gi" }
# ─────────────────────────────────────────────────────────────────────────────
# نکات mirror (اگر build گیر کرد، uncomment/تنظیم و دوباره اجرا کنید):
# • npm: NPM_CONFIG_REGISTRY=https://registry.npmmirror.com (روی container kaniko
# اثر ندارد چون Dockerfile تولیدی است؛ بهتر است در فاز ۲ به‌صورت ARG/ENV
# داخل مرحله‌ی نصب تزریق شود — اینجا فقط برای nixpacks-plan گذاشته شده.)
# • nix: اگر دانلود nixpkgs (https://github.com/NixOS/...) شکست خورد، احتمال نیاز به
# HTTP(S)_PROXY روی container kaniko یا آینه‌سازی nixpkgs. در لاگ kaniko دنبال
# خطوط fetch tarball بگردید.
# • go: GOPROXY=https://goproxy.cn,direct یا proxy داخلی.
# • اگر pull از ghcr.io/gcr.io خود مشکل داشت → image ها را به رجیستری داخلی mirror کنید
# (همان الگوی LOGGING_*_IMAGE در configuration.ts).
# ─────────────────────────────────────────────────────────────────────────────