# StackOps Infrastructure ## Architecture ``` ┌─────────────────────────────────────┐ │ Cloudflare DNS │ │ nodeup.ru → 82.114.226.118 │ │ *.app.nodeup.ru (wildcard) │ └──────────────┬──────────────────────┘ │ ▼ ┌───────────────────────────────────────────┐ │ VPS 82.114.226.118 │ │ Debian 13, 6 CPU, 6GB RAM │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ k3s v1.34.6 │ │ │ │ (traefik disabled) │ │ │ │ │ │ │ │ ┌────────────────────────────────┐ │ │ │ │ │ ingress-nginx (DaemonSet) │ │ │ │ │ │ ports 80/443 via ServiceLB│ │ │ │ │ └──────────┬─────────────────────┘ │ │ │ │ │ │ │ │ │ ┌──────────▼─────────────────────┐ │ │ │ │ │ cert-manager (HTTP-01) │ │ │ │ │ │ ClusterIssuer: letsencrypt │ │ │ │ │ └────────────────────────────────┘ │ │ │ │ │ │ │ │ ┌─── Namespaces ──────────────────┐ │ │ │ │ │ │ │ │ │ │ │ stackops/ │ │ │ │ │ │ stackops-api (Go + React UI) │ │ │ │ │ │ SQLite PVC, ClusterRole RBAC │ │ │ │ │ │ → app.nodeup.ru │ │ │ │ │ │ │ │ │ │ │ │ gitea/ │ │ │ │ │ │ Gitea (SQLite + Valkey) │ │ │ │ │ │ → git.nodeup.ru │ │ │ │ │ │ │ │ │ │ │ │ monitoring/ │ │ │ │ │ │ Prometheus (20Gi PV) │ │ │ │ │ │ Grafana → grafana.nodeup.ru │ │ │ │ │ │ Loki + Promtail (10Gi PV) │ │ │ │ │ │ │ │ │ │ │ │ vela-system/ │ │ │ │ │ │ KubeVela (OAM engine) │ │ │ │ │ │ │ │ │ │ │ │ cnpg-system/ │ │ │ │ │ │ CloudNativePG operator │ │ │ │ │ │ │ │ │ │ │ │ redis-operator/ │ │ │ │ │ │ OT Systems Redis operator │ │ │ │ │ │ │ │ │ │ │ │ whoami/ (test app) │ │ │ │ │ │ whoami + PostgreSQL (PV) │ │ │ │ │ │ → whoami.app.nodeup.ru │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────┘ │ │ │ └─────────────────────────────────────┘ │ └───────────────────────────────────────────┘ ``` ## Domains | Domain | Service | TLS | |--------|---------|-----| | `app.nodeup.ru` | StackOps API + UI | Let's Encrypt | | `git.nodeup.ru` | Gitea | Let's Encrypt | | `grafana.nodeup.ru` | Grafana | Let's Encrypt | | `prom.nodeup.ru` | Prometheus (reserved) | — | | `*.app.nodeup.ru` | User apps (wildcard) | Let's Encrypt per-app | ## Deploy Flow ``` Developer writes stackfile.toml │ ▼ StackOps API (app.nodeup.ru) │ ├── git clone → reads stackfile.toml + commit SHA │ ├── toml-converter → KubeVela Application YAML │ ├── kubectl apply -n │ └── KubeVela orchestrates: 1. CloudNativePG → PostgreSQL cluster + secrets 2. Redis operator → Redis instance 3. webservice → Deployment + Service 4. gateway trait → Ingress (nginx + cert-manager TLS) ``` ## Components | Component | Version | Namespace | Purpose | |-----------|---------|-----------|---------| | k3s | v1.34.6 | — | Kubernetes distribution | | nginx-ingress | 4.15.1 | ingress-nginx | Ingress controller | | cert-manager | v1.20.1 | cert-manager | TLS certificates (HTTP-01) | | KubeVela | 1.10.8 | vela-system | OAM application engine | | CloudNativePG | 1.23.0 | cnpg-system | PostgreSQL operator | | Redis operator | 0.24.0 | redis-operator | Redis operator | | Gitea | 1.25.4 | gitea | Git hosting | | Prometheus | v0.90.1 | monitoring | Metrics | | Grafana | (bundled) | monitoring | Dashboards | | Loki | v2.9.3 | monitoring | Log aggregation | | Promtail | (bundled) | monitoring | Log shipping | ## Credentials | Service | Login | Password | |---------|-------|----------| | Gitea | `stackops` | `stackops-admin-2026` | | Grafana | `admin` | `stackops-grafana-2026` | | StackOps API | token | `dev-secret-token` | ## Kubeconfig ```bash export KUBECONFIG=~/.kube/config-nodeup # or export KUBECONFIG=infra/kubeconfig.yaml ``` **Note:** `kubeconfig.yaml` is in `.gitignore` — it contains the cluster admin token. Copy it manually from `~/.kube/config-nodeup`. ## Gitea Repositories | Repo | URL | Content | |------|-----|---------| | `stackops/infra` | https://git.nodeup.ru/stackops/infra | This repo — IaC manifests | | `stackops/stackops` | https://git.nodeup.ru/stackops/stackops | Application source code | ## Reproduce from Scratch ```bash # 0. DNS bash 00-dns/cloudflare-records.sh # 1. k3s bash 01-k3s/install.sh # 2. Core (nginx-ingress + cert-manager + ClusterIssuer) make core # 3. KubeVela + operators + ComponentDefinitions make kubevela # 4. Gitea make gitea # 5. Monitoring (Prometheus + Grafana + Loki) make monitoring # 6. StackOps app make stackops # 7. Test app make test-app ``` Or all at once: `make all` (sequential). ## Directory Structure ``` infra/ ├── README.md ├── Makefile # Top-level automation ├── 00-dns/ │ └── cloudflare-records.sh # DNS A records via CF API ├── 01-k3s/ │ └── install.sh # k3s install + kubeconfig ├── 02-core/ │ └── clusterissuer.yaml # cert-manager ClusterIssuer (HTTP-01) ├── 03-kubevela/ # (manifests in ../kubevela/components/) ├── 04-gitea/ │ └── values.yaml # Gitea helm values ├── 05-monitoring/ │ ├── values-prometheus.yaml # kube-prometheus-stack values │ └── values-loki.yaml # loki-stack values ├── 06-stackops/ │ ├── rbac.yaml # Namespace, SA, ClusterRole, PVC │ └── deployment.yaml # Deployment, Service, Ingress └── 07-test-app/ └── stackfile.toml # whoami test app stackfile ```