33 Commits

Author SHA1 Message Date
5879c84a05 Merge branch 'feature/multi-cloud' of https://git.forteapps.net/Forte/launchpad into feature/multi-cloud
All checks were successful
AI Code Review / ai-review (pull_request) Has been skipped
2026-04-24 10:48:08 +02:00
c7cbfc712e overlays 2026-04-24 10:48:03 +02:00
ddccdacd6d Merge branch 'main' into feature/multi-cloud
All checks were successful
AI Code Review / ai-review (pull_request) Has been skipped
2026-04-24 08:24:34 +00:00
65598c9297 karpor diffs 2026-04-24 09:47:52 +02:00
3f0f70699b karpor 2026-04-24 09:43:16 +02:00
06522b2f19 ts-mcp 2026-04-23 14:44:33 +02:00
4c65035485 ns 2026-04-23 14:11:45 +02:00
84f4bebc08 ts-mcp 2026-04-23 13:41:51 +02:00
5394b2c714 ts-mcp 2026-04-23 13:40:33 +02:00
c4e586a7be ts-mcp 2026-04-23 13:38:47 +02:00
1fa070b041 argo 2026-04-23 13:35:42 +02:00
9c905355e3 argocd known host 2026-04-23 13:28:34 +02:00
6b1115ec28 argocd disable submodule 2026-04-23 13:09:02 +02:00
2fb276a62c ts-mcp 2026-04-23 13:02:00 +02:00
3efe1b68ef auth doc 2026-04-23 10:05:15 +02:00
a89f2f30ce details 2026-04-22 22:26:57 +02:00
9a7e03b794 Merge branch 'feature/cloud-agnostic' into feature/multi-cloud 2026-04-22 22:06:31 +02:00
f1dd61cece sync 2026-04-22 21:56:43 +02:00
acc9bb1a85 sync 2026-04-22 21:53:44 +02:00
c8c2dedea5 rename 2026-04-22 21:48:02 +02:00
a471f11740 repo url 2026-04-22 14:45:23 +02:00
92ddc22322 azure>aks 2026-04-22 14:42:02 +02:00
7d2fb8bc0c azure>aks 2026-04-22 14:41:42 +02:00
79f9c62012 azure>aks 2026-04-22 14:35:59 +02:00
dea54e469e repo url 2026-04-22 14:34:20 +02:00
333acdea26 multi-cloud overlays
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 6s
2026-04-22 14:30:13 +02:00
03d526208b Merge branch 'main' into feature/cloud-agnostic
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 7s
2026-04-22 12:08:08 +00:00
458f7b23ad Merge branch 'main' into feature/multi-cloud
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 28s
2026-04-22 11:55:05 +00:00
5df104beec sp 2026-04-22 13:54:51 +02:00
41c8b85bf8 Merge branch 'main' into feature/multi-cloud
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 26s
2026-04-22 11:52:22 +00:00
0ecfee3cf8 prompts 2026-04-22 13:51:38 +02:00
4e6a84785a token
All checks were successful
AI Code Review / ai-review (pull_request) Successful in 28s
2026-04-22 13:37:32 +02:00
e0bdaab422 multi-cloud + mcp
Some checks failed
AI Code Review / ai-review (pull_request) Failing after 2s
2026-04-22 13:34:48 +02:00
126 changed files with 1372 additions and 637 deletions

View File

@@ -98,23 +98,23 @@ This repository contains the complete GitOps configuration for our Kubernetes cl
│ ├── overlays/ # Per-cluster overrides (Kustomize) │ ├── overlays/ # Per-cluster overrides (Kustomize)
│ │ ├── upc-dev/ # UpCloud Dev (uses base as-is) │ │ ├── upc-dev/ # UpCloud Dev (uses base as-is)
│ │ ├── upc-prod/ # UpCloud Prod (patches value paths) │ │ ├── upc-prod/ # UpCloud Prod (patches value paths)
│ │ ├── aws-dev/ # AWS EKS Dev │ │ ├── eks-dev/ # AWS EKS Dev
│ │ ├── aws-prod/ # AWS EKS Prod │ │ ├── eks-prod/ # AWS EKS Prod
│ │ ├── azure-dev/ # Azure AKS Dev │ │ ├── aks-dev/ # Azure AKS Dev
│ │ ├── azure-prod/ # Azure AKS Prod │ │ ├── aks-prod/ # Azure AKS Prod
│ │ ├── gcp-dev/ # GCP GKE Dev │ │ ├── gke-dev/ # GCP GKE Dev
│ │ └── gcp-prod/ # GCP GKE Prod │ │ └── gke-prod/ # GCP GKE Prod
│ ├── dashboards/ # Grafana dashboard ConfigMaps │ ├── dashboards/ # Grafana dashboard ConfigMaps
│ └── values/ # Helm value overrides │ └── values/ # Helm value overrides
│ ├── base/ # Shared cloud-agnostic values │ ├── base/ # Shared cloud-agnostic values
│ ├── upc-dev/ # UpCloud Dev (storage, LB, pricing) │ ├── upc-dev/ # UpCloud Dev (storage, LB, pricing)
│ ├── upc-prod/ # UpCloud Prod │ ├── upc-prod/ # UpCloud Prod
│ ├── aws-dev/ # AWS EKS Dev │ ├── eks-dev/ # AWS EKS Dev
│ ├── aws-prod/ # AWS EKS Prod │ ├── eks-prod/ # AWS EKS Prod
│ ├── azure-dev/ # Azure AKS Dev │ ├── aks-dev/ # Azure AKS Dev
│ ├── azure-prod/ # Azure AKS Prod │ ├── aks-prod/ # Azure AKS Prod
│ ├── gcp-dev/ # GCP GKE Dev │ ├── gke-dev/ # GCP GKE Dev
│ └── gcp-prod/ # GCP GKE Prod │ └── gke-prod/ # GCP GKE Prod
├── apps/ # Business Applications ├── apps/ # Business Applications
│ ├── mcp10x.yaml │ ├── mcp10x.yaml
@@ -373,7 +373,7 @@ kubectl patch application myapp -n argocd \
## 📖 Key Concepts ## 📖 Key Concepts
### App-of-Apps Pattern ### App-of-Apps Pattern
`_app-of-apps-{cluster}.yaml` is the root Application that manages all other Applications in `infra/`. Kustomize overlays in `infra/overlays/{cluster}/` render the base Applications with per-cluster patches (e.g., swapping value file paths). Supported clusters: `upc-dev`, `upc-prod`, `aws-dev`, `aws-prod`, `azure-dev`, `azure-prod`, `gcp-dev`, `gcp-prod`. `_app-of-apps-{cluster}.yaml` is the root Application that manages all other Applications in `infra/`. Kustomize overlays in `infra/overlays/{cluster}/` render the base Applications with per-cluster patches (e.g., swapping value file paths). Supported clusters: `upc-dev`, `upc-prod`, `eks-dev`, `eks-prod`, `aks-dev`, `aks-prod`, `gke-dev`, `gke-prod`.
### Multi-Source Pattern ### Multi-Source Pattern
Applications reference both: Applications reference both:

View File

@@ -18,9 +18,9 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
path: infra/overlays/aws-dev path: infra/overlays/aks-dev
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: default namespace: default

View File

@@ -18,9 +18,9 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
path: infra/overlays/azure-prod path: infra/overlays/aks-prod
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: default namespace: default

View File

@@ -18,9 +18,9 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
path: infra/overlays/aws-prod path: infra/overlays/eks-dev
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: default namespace: default

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure-apps
namespace: argocd
labels:
app.kubernetes.io/name: infrastructure-apps
app.kubernetes.io/part-of: platform
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD
path: infra/overlays/eks-prod
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -1,32 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure-apps
namespace: argocd
labels:
app.kubernetes.io/name: infrastructure-apps
app.kubernetes.io/part-of: platform
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git
targetRevision: HEAD
path: infra/overlays/gcp-dev
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -1,32 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure-apps
namespace: argocd
labels:
app.kubernetes.io/name: infrastructure-apps
app.kubernetes.io/part-of: platform
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git
targetRevision: HEAD
path: infra/overlays/gcp-prod
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -18,9 +18,9 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
path: infra/overlays/azure-dev path: infra/overlays/gke-dev
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: default namespace: default

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infrastructure-apps
namespace: argocd
labels:
app.kubernetes.io/name: infrastructure-apps
app.kubernetes.io/part-of: platform
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD
path: infra/overlays/gke-prod
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -18,7 +18,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: git@github.com:fortedigital/sturdy-adventure.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
path: infra/overlays/upc-prod path: infra/overlays/upc-prod
destination: destination:

View File

@@ -37,7 +37,7 @@ spec:
- $values/infra/values/base/dot-ai-stack-values.yaml - $values/infra/values/base/dot-ai-stack-values.yaml
- $values/infra/values/upc-dev/dot-ai-stack-values.yaml - $values/infra/values/upc-dev/dot-ai-stack-values.yaml
- repoURL: git@github.com:fortedigital/sturdy-adventure.git - repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
ref: values ref: values

View File

@@ -4,4 +4,5 @@ resources:
- dot-ai-stack.yaml - dot-ai-stack.yaml
- mcp10x.yaml - mcp10x.yaml
- musicman.yaml - musicman.yaml
- ts-mcp.yaml
- argo-mcp.yaml - argo-mcp.yaml

40
apps/base/ts-mcp.yaml Normal file
View File

@@ -0,0 +1,40 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ts-mcp
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "11"
notifications.argoproj.io/subscribe.on-sync-succeeded.slack: ""
notifications.argoproj.io/subscribe.on-sync-failed.slack: ""
notifications.argoproj.io/subscribe.on-degraded.slack: ""
labels:
app.kubernetes.io/name: ts-mcp
app.kubernetes.io/part-of: apps
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: ssh://git@git.forteapps.net:2222/Forte/forte-helm.git
path: forteapp
targetRevision: HEAD
helm:
valueFiles:
- $values/ts-mcp/values.yaml
- repoURL: ssh://git@git.forteapps.net:2222/Forte/helm-prod-values.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: ts-mcp
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

View File

@@ -2,7 +2,7 @@
# in case of $'\r': command not found error, run command below first # in case of $'\r': command not found error, run command below first
# sed -i 's/\r$//' ./bootstrap.sh # sed -i 's/\r$//' ./bootstrap.sh
CLUSTER="${1:?Usage: ./bootstrap.sh <cluster> (upc-dev|upc-prod)}" CLUSTER="${1:?Usage: ./bootstrap.sh <cluster> (upc-dev|upc-prod|aks-dev|aks-prod|eks-dev|eks-prod|gke-dev|gke-prod)}"
echo "running $0 for cluster: ${CLUSTER}..." echo "running $0 for cluster: ${CLUSTER}..."

12
clusters/aks-dev.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: dev-aks # → infra/values/aks-dev/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/aks-dev/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/aks-dev/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/aks-dev/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/aks-dev/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/aks-dev/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # → infra/values/aks-dev/traefik-values.yaml (ports.*.trustedIPs) — VNet CIDR + Azure health probe
cloudProvider: azure # → determines overlay directory and cloud-specific LB/storage annotations

12
clusters/aks-prod.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: prod-aks # → infra/values/aks-prod/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/aks-prod/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/aks-prod/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/aks-prod/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/aks-prod/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/aks-prod/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # → infra/values/aks-prod/traefik-values.yaml (ports.*.trustedIPs) — VNet CIDR + Azure health probe
cloudProvider: azure # → determines overlay directory and cloud-specific LB/storage annotations

View File

@@ -1,10 +0,0 @@
clusterName: dev-eks # <- adjust to your EKS cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8" # <- adjust to your VPC CIDR
cloudProvider: aws

View File

@@ -1,10 +0,0 @@
clusterName: prod-eks # <- adjust to your EKS cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8" # <- adjust to your VPC CIDR
cloudProvider: aws

View File

@@ -1,10 +0,0 @@
clusterName: dev-aks # <- adjust to your AKS cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # <- VNet CIDR + Azure health probe
cloudProvider: azure

View File

@@ -1,10 +0,0 @@
clusterName: prod-aks # <- adjust to your AKS cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # <- VNet CIDR + Azure health probe
cloudProvider: azure

12
clusters/eks-dev.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: dev-eks # → infra/values/eks-dev/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/eks-dev/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/eks-dev/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/eks-dev/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/eks-dev/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/eks-dev/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8" # → infra/values/eks-dev/traefik-values.yaml (ports.*.trustedIPs) — VPC CIDR
cloudProvider: eks # → determines overlay directory and cloud-specific LB/storage annotations

12
clusters/eks-prod.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: prod-eks # → infra/values/eks-prod/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/eks-prod/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/eks-prod/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/eks-prod/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/eks-prod/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/eks-prod/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8" # → infra/values/eks-prod/traefik-values.yaml (ports.*.trustedIPs) — VPC CIDR
cloudProvider: eks # → determines overlay directory and cloud-specific LB/storage annotations

View File

@@ -1,10 +0,0 @@
clusterName: dev-gke # <- adjust to your GKE cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # <- subnet CIDR + GCP health checks
cloudProvider: gcp

View File

@@ -1,10 +0,0 @@
clusterName: prod-gke # <- adjust to your GKE cluster name
domain: example.com # <- adjust to your domain
argocdDomain: argocd.example.com
grafanaDomain: grafana.example.com
keycloakDomain: id.example.com
dotaiDomain: kubemcp.example.com
dotaiUiDomain: kubemcpui.example.com
letsencryptEmail: admin@example.com # <- adjust
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # <- subnet CIDR + GCP health checks
cloudProvider: gcp

12
clusters/gke-dev.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: dev-gke # → infra/values/gke-dev/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/gke-dev/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/gke-dev/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/gke-dev/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/gke-dev/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/gke-dev/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # → infra/values/gke-dev/traefik-values.yaml (ports.*.trustedIPs) — subnet + GCP health checks
cloudProvider: gke # → determines overlay directory and cloud-specific LB/storage annotations

12
clusters/gke-prod.yaml Normal file
View File

@@ -0,0 +1,12 @@
# Cluster config reference — values must match the corresponding overlay files.
# Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
clusterName: prod-gke # → infra/values/gke-prod/argocd-values.yaml (notifications.context.clusterName)
domain: example.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
argocdDomain: argocd.example.com # → infra/values/gke-prod/argocd-values.yaml (global.domain)
grafanaDomain: grafana.example.com # → infra/values/gke-prod/grafana-values.yaml (ingress.hosts)
keycloakDomain: id.example.com # → infra/values/gke-prod/keycloak-values.yaml (ingress.hostname)
dotaiDomain: kubemcp.example.com # → infra/values/gke-prod/dot-ai-stack-values.yaml (dot-ai.ingress.host) — create if needed
dotaiUiDomain: kubemcpui.example.com # → infra/values/gke-prod/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host) — create if needed
letsencryptEmail: admin@example.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # → infra/values/gke-prod/traefik-values.yaml (ports.*.trustedIPs) — subnet + GCP health checks
cloudProvider: gke # → determines overlay directory and cloud-specific LB/storage annotations

View File

@@ -1,10 +1,12 @@
clusterName: dev-fd-no-svg1 # Cluster config reference — values must match the corresponding overlay files.
domain: forteapps.net # Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
argocdDomain: argocd.127.0.0.1.nip.io clusterName: dev-fd-no-svg1 # → infra/values/upc-dev/argocd-values.yaml (notifications.context.clusterName)
grafanaDomain: grafana.forteapps.net domain: forteapps.net # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
keycloakDomain: id.forteapps.net argocdDomain: argocd.127.0.0.1.nip.io # → infra/values/upc-dev/argocd-values.yaml (global.domain)
dotaiDomain: kubemcp.forteapps.net grafanaDomain: grafana.forteapps.net # → infra/values/upc-dev/grafana-values.yaml (ingress.hosts)
dotaiUiDomain: kubemcpui.forteapps.net keycloakDomain: id.forteapps.net # → infra/values/upc-dev/keycloak-values.yaml (ingress.hostname)
letsencryptEmail: danijels@gmail.com dotaiDomain: kubemcp.forteapps.net # → infra/values/upc-dev/dot-ai-stack-values.yaml (dot-ai.ingress.host)
trustedIPs: "172.16.1.0/24" dotaiUiDomain: kubemcpui.forteapps.net # → infra/values/upc-dev/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host)
cloudProvider: upcloud letsencryptEmail: danijels@gmail.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "172.16.1.0/24" # → infra/values/upc-dev/traefik-values.yaml (ports.*.trustedIPs)
cloudProvider: upcloud # → determines overlay directory and cloud-specific LB/storage annotations

View File

@@ -1,10 +1,12 @@
clusterName: prod-fd-no-svg1 # Cluster config reference — values must match the corresponding overlay files.
domain: fortedigital.com # Read by bootstrap.sh at install time; NOT auto-propagated to ArgoCD value files.
argocdDomain: argocd.127.0.0.1.nip.io clusterName: prod-fd-no-svg1 # → infra/values/upc-prod/argocd-values.yaml (notifications.context.clusterName)
grafanaDomain: grafana.fortedigital.com domain: fortedigital.com # → infra/values/base/gitea-values.yaml, renovate-values.yaml, keycloak-values.yaml (subdomains)
keycloakDomain: id.fortedigital.com argocdDomain: argocd.127.0.0.1.nip.io # → infra/values/upc-prod/argocd-values.yaml (global.domain)
dotaiDomain: kubemcp.fortedigital.com grafanaDomain: grafana.fortedigital.com # → infra/values/upc-prod/grafana-values.yaml (ingress.hosts)
dotaiUiDomain: kubemcpui.fortedigital.com keycloakDomain: id.fortedigital.com # → infra/values/upc-prod/keycloak-values.yaml (ingress.hostname)
letsencryptEmail: danijel.simeunovic@fortedigital.com dotaiDomain: kubemcp.fortedigital.com # → infra/values/upc-prod/dot-ai-stack-values.yaml (dot-ai.ingress.host)
trustedIPs: "172.16.1.0/24" dotaiUiDomain: kubemcpui.fortedigital.com # → infra/values/upc-prod/dot-ai-stack-values.yaml (dot-ai-ui.ingress.host)
cloudProvider: upcloud letsencryptEmail: danijel.simeunovic@fortedigital.com # → cluster-resources/letsencrypt-issuer.yaml (spec.acme.email)
trustedIPs: "172.16.1.0/24" # → infra/values/upc-prod/traefik-values.yaml (ports.*.trustedIPs)
cloudProvider: upcloud # → determines overlay directory and cloud-specific LB/storage annotations

View File

@@ -962,6 +962,46 @@ User sees application (authenticated)
--- ---
### Accessing Authenticated User Information
The auth sidecar handles all authentication before requests reach your application. Your app never sees unauthenticated traffic — the sidecar returns 401 or redirects to the IdP first.
After successful authentication, the sidecar forwards the request to your application with user identity injected as HTTP headers:
| Header | Description | Available in |
|--------|-------------|-------------|
| `X-Auth-User` | Username or display name | Token, OIDC, MCP |
| `X-Auth-Email` | User email address | OIDC |
| `X-Auth-Subject` | OIDC `sub` claim (stable user ID) | OIDC, MCP |
| `X-Auth-Groups` | Comma-separated group memberships | OIDC (if scope includes `groups`) |
| `X-Auth-Token` | The validated access token | All modes |
**Your application reads these headers — no auth library needed:**
```javascript
// Express.js example
app.get('/profile', (req, res) => {
const user = req.headers['x-auth-user'];
const email = req.headers['x-auth-email'];
res.json({ user, email });
});
```
```python
# Flask example
@app.route('/profile')
def profile():
user = request.headers.get('X-Auth-User')
email = request.headers.get('X-Auth-Email')
return jsonify(user=user, email=email)
```
**Why this is safe**: The Kyverno-generated NetworkPolicy restricts ingress to the sidecar port only. Traffic cannot bypass the sidecar to reach the application port directly, so the `X-Auth-*` headers can be trusted unconditionally.
**Key principle**: Your application is zero-trust-unaware by design. It reads headers and renders UI. All authentication complexity lives in the sidecar and Kyverno policy.
---
### Authentication Configuration Reference ### Authentication Configuration Reference
#### Helm Values Schema #### Helm Values Schema

View File

@@ -134,18 +134,18 @@ launchpad/
│ ├── overlays/ # Per-cluster Kustomize overrides │ ├── overlays/ # Per-cluster Kustomize overrides
│ │ ├── upc-dev/ # UpCloud Dev (uses base as-is) │ │ ├── upc-dev/ # UpCloud Dev (uses base as-is)
│ │ ├── upc-prod/ # UpCloud Prod (patches value paths) │ │ ├── upc-prod/ # UpCloud Prod (patches value paths)
│ │ ├── aws-dev/ # AWS EKS Dev │ │ ├── eks-dev/ # AWS EKS Dev
│ │ ├── aws-prod/ # AWS EKS Prod │ │ ├── eks-prod/ # AWS EKS Prod
│ │ ├── azure-dev/ # Azure AKS Dev │ │ ├── aks-dev/ # Azure AKS Dev
│ │ ├── azure-prod/ # Azure AKS Prod │ │ ├── aks-prod/ # Azure AKS Prod
│ │ ├── gcp-dev/ # GCP GKE Dev │ │ ├── gke-dev/ # GCP GKE Dev
│ │ └── gcp-prod/ # GCP GKE Prod │ │ └── gke-prod/ # GCP GKE Prod
│ ├── dashboards/ # Grafana dashboard ConfigMaps │ ├── dashboards/ # Grafana dashboard ConfigMaps
│ └── values/ # Helm value overrides for infra │ └── values/ # Helm value overrides for infra
│ ├── base/ # Cloud-agnostic shared values │ ├── base/ # Cloud-agnostic shared values
│ ├── upc-{dev,prod}/ # UpCloud: storage class, LB, pricing │ ├── upc-{dev,prod}/ # UpCloud: storage class, LB, pricing
│ ├── aws-{dev,prod}/ # AWS: gp3, NLB, CUR pricing │ ├── aws-{dev,prod}/ # AWS: gp3, NLB, CUR pricing
│ ├── azure-{dev,prod}/ # Azure: managed-csi-premium, Standard LB │ ├── aks-{dev,prod}/ # Azure: managed-csi-premium, Standard LB
│ └── gcp-{dev,prod}/ # GCP: premium-rwo, L4 LB │ └── gcp-{dev,prod}/ # GCP: premium-rwo, L4 LB
├── apps/ # Business Application ArgoCD manifests (Kustomize) ├── apps/ # Business Application ArgoCD manifests (Kustomize)
@@ -283,7 +283,7 @@ app-repository/
### The App-of-Apps Pattern ### The App-of-Apps Pattern
``` ```
_app-of-apps-{cluster}.yaml (Root, per cluster — e.g. upc-dev, aws-prod, gcp-dev) _app-of-apps-{cluster}.yaml (Root, per cluster — e.g. upc-dev, eks-prod, gke-dev)
├── infrastructure-apps (manages infra/) ├── infrastructure-apps (manages infra/)
│ ├── cluster-resources-application │ ├── cluster-resources-application

View File

@@ -55,8 +55,8 @@ git clone https://git.forteapps.net/Forte/launchpad
cd launchpad cd launchpad
# 2. Run bootstrap script with cluster target # 2. Run bootstrap script with cluster target
# Available clusters: upc-dev, upc-prod, aws-dev, aws-prod, # Available clusters: upc-dev, upc-prod, eks-dev, eks-prod,
# azure-dev, azure-prod, gcp-dev, gcp-prod # aks-dev, aks-prod, gke-dev, gke-prod
./bootstrap.sh upc-dev ./bootstrap.sh upc-dev
# Cluster config is loaded from clusters/<cluster>.yaml # Cluster config is loaded from clusters/<cluster>.yaml
@@ -1276,9 +1276,9 @@ spec:
- ❌ Other persistent volumes (Prometheus, Loki, Tempo data) - ❌ Other persistent volumes (Prometheus, Loki, Tempo data)
**Per-cloud backup scripts** (manual restore helpers): **Per-cloud backup scripts** (manual restore helpers):
- UpCloud/AWS: `scripts/gitea-backup.sh` / `scripts/gitea-backup-aws.sh` (MinIO CLI, S3-compatible) - UpCloud/AWS: `scripts/gitea-backup.sh` / `scripts/gitea-backup-eks.sh` (MinIO CLI, S3-compatible)
- Azure: `scripts/gitea-backup-azure.sh` (Azure CLI + Blob Storage) - Azure: `scripts/gitea-backup-aks.sh` (Azure CLI + Blob Storage)
- GCP: `scripts/gitea-backup-gcp.sh` (gsutil + GCS) - GCP: `scripts/gitea-backup-gke.sh` (gsutil + GCS)
### Cluster Rebuild ### Cluster Rebuild
@@ -1527,9 +1527,9 @@ The repository supports multiple clusters across multiple clouds via Kustomize o
- **upc-prod**: `infra/overlays/upc-prod/` — patches value file paths from `upc-dev` to `upc-prod` - **upc-prod**: `infra/overlays/upc-prod/` — patches value file paths from `upc-dev` to `upc-prod`
**Cloud-ready templates (fill in `clusters/*.yaml` before use):** **Cloud-ready templates (fill in `clusters/*.yaml` before use):**
- **aws-dev** / **aws-prod**: AWS EKS with NLB, gp3 storage, AWS CUR pricing - **eks-dev** / **eks-prod**: AWS EKS with NLB, gp3 storage, AWS CUR pricing
- **azure-dev** / **azure-prod**: Azure AKS with Standard LB, managed-csi-premium storage - **aks-dev** / **aks-prod**: Azure AKS with Standard LB, managed-csi-premium storage
- **gcp-dev** / **gcp-prod**: GCP GKE with L4 LB, premium-rwo storage - **gke-dev** / **gke-prod**: GCP GKE with L4 LB, premium-rwo storage
Each cluster has its own: Each cluster has its own:
- Root app-of-apps: `_app-of-apps-{cluster}.yaml` - Root app-of-apps: `_app-of-apps-{cluster}.yaml`
@@ -1548,7 +1548,7 @@ Cloud-specific values handled per-cluster:
| **Cost monitoring** | Custom pricing | AWS CUR | Azure Billing API | GCP Cloud Billing | | **Cost monitoring** | Custom pricing | AWS CUR | Azure Billing API | GCP Cloud Billing |
| **Backup storage** | UpCloud S3-compat | AWS S3 (native) | Azure Blob Storage | GCS | | **Backup storage** | UpCloud S3-compat | AWS S3 (native) | Azure Blob Storage | GCS |
To add a new cluster, create a new overlay directory (e.g., `infra/overlays/aws-staging/`) with patches that swap the value file paths, and a matching `clusters/aws-staging.yaml`. To add a new cluster, create a new overlay directory (e.g., `infra/overlays/eks-staging/`) with patches that swap the value file paths, and a matching `clusters/eks-staging.yaml`.
### Blue-Green Deployments ### Blue-Green Deployments

View File

@@ -9,6 +9,7 @@
- [Kyverno Policies](#kyverno-policies) - [Kyverno Policies](#kyverno-policies)
- [Configuration Reference](#configuration-reference) - [Configuration Reference](#configuration-reference)
- [API Endpoints](#api-endpoints) - [API Endpoints](#api-endpoints)
- [Cloud Overlay Pattern](#cloud-overlay-pattern)
- [Glossary](#glossary) - [Glossary](#glossary)
--- ---
@@ -20,8 +21,9 @@
| Component | Value | | Component | Value |
|-----------|-------| |-----------|-------|
| **Provider** | Multi-cloud (UpCloud, AWS EKS, Azure AKS, GCP GKE) | | **Provider** | Multi-cloud (UpCloud, AWS EKS, Azure AKS, GCP GKE) |
| **Environment** | Dev + Production per cloud |
| **Active clusters** | UpCloud (upc-dev, upc-prod) | | **Active clusters** | UpCloud (upc-dev, upc-prod) |
| **Cloud-ready templates** | AWS, Azure, GCP (dev + prod each) | | **Cloud-ready templates** | EKS, AKS, GKE (dev + prod each) |
| **GitOps Tool** | ArgoCD | | **GitOps Tool** | ArgoCD |
| **Ingress Controller** | Traefik v2 | | **Ingress Controller** | Traefik v2 |
| **Certificate Management** | Cert-Manager + Let's Encrypt | | **Certificate Management** | Cert-Manager + Let's Encrypt |
@@ -92,16 +94,34 @@ launchpad/
│ ├── sealedsecrets.yaml │ ├── sealedsecrets.yaml
│ ├── secrets.yaml │ ├── secrets.yaml
│ ├── renovate.yaml │ ├── renovate.yaml
│ ├── base/ # ArgoCD Application manifests (Kustomize base)
│ │ ├── gitea.yaml
│ │ ├── opencost.yaml
│ │ ├── traefik-application.yaml
│ │ ├── keycloak.yaml
│ │ ├── grafana.yaml
│ │ └── ...
│ ├── overlays/
│ │ └── upc-prod/
│ │ └── kustomization.yaml # Patches upc-dev → upc-prod valueFile paths
│ └── values/ │ └── values/
│ ├── argocd-values.yaml │ ├── base/ # Cloud-agnostic Helm values
├── prometheus-values.yaml │ ├── gitea-values.yaml
├── grafana-values.yaml │ ├── opencost-values.yaml
├── loki-values.yaml │ ├── prometheus-values.yaml
├── tempo-values.yaml │ └── ...
│ ├── gitea-values.yaml │ ├── upc-dev/ # UpCloud dev overlay values
├── gitea-actions-values.yaml │ ├── traefik-values.yaml
├── fluent-bit-values.yaml │ ├── keycloak-values.yaml
└── renovate-values.yaml │ ├── grafana-values.yaml
│ │ ├── gitea-values.yaml
│ │ └── opencost-values.yaml
│ └── upc-prod/ # UpCloud prod overlay values
│ ├── traefik-values.yaml
│ ├── keycloak-values.yaml
│ ├── grafana-values.yaml
│ ├── gitea-values.yaml
│ └── opencost-values.yaml
├── apps/ # Business applications ├── apps/ # Business applications
│ ├── mcp10x.yaml │ ├── mcp10x.yaml
@@ -128,12 +148,39 @@ launchpad/
│ └── auth-sidecar-injector.yaml │ └── auth-sidecar-injector.yaml
├── secrets/ # Application secrets (sealed) ├── secrets/ # Application secrets (sealed)
│ ├── argocd-mcp-credentials.yaml │ ├── base/ # All SealedSecrets (shared across clouds)
│ ├── dot-ai-secrets.yaml │ ├── kustomization.yaml
│ ├── gitea-credentials-sealed.yaml │ ├── argocd-forte-helm-secret-sealed.yaml
│ ├── gitea-runner-token-sealed.yaml │ ├── argocd-mcp-credentials.yaml
│ ├── mcp10x-credentials-sealed.yaml │ ├── argocdmcp-auth-oidc-sealed.yaml
└── musicman-credentials.yaml │ ├── dot-ai-secrets.yaml
│ │ ├── forte10x-app-credentials-sealed.yaml
│ │ ├── gitea-backup-s3-sealed.yaml
│ │ ├── gitea-credentials-sealed.yaml
│ │ ├── gitea-runner-token-sealed.yaml
│ │ ├── gitea-smtp-secret-sealed.yaml
│ │ ├── keycloak-credentials-sealed.yaml
│ │ ├── musicman-auth-oidc-sealed.yaml
│ │ ├── musicman-credentials.yaml
│ │ └── renovate-env-sealed.yaml
│ └── overlays/ # Per-cloud overlays (reference base)
│ ├── aks-dev/kustomization.yaml
│ ├── aks-prod/kustomization.yaml
│ ├── eks-dev/kustomization.yaml
│ ├── eks-prod/kustomization.yaml
│ ├── gke-dev/kustomization.yaml
│ ├── gke-prod/kustomization.yaml
│ ├── upc-dev/kustomization.yaml
│ └── upc-prod/kustomization.yaml
├── scripts/ # Operational helper scripts
│ ├── gitea-backup.sh # S3 backup helper (list/download)
│ ├── gitea-restore.sh
│ └── backup/ # Per-cloud backup reference scripts
│ ├── s3-minio.sh # S3-compatible (UpCloud, MinIO, Wasabi)
│ ├── aws-s3.sh # Native AWS S3
│ ├── azure-blob.sh # Azure Blob Storage
│ └── gcp-gcs.sh # GCP Cloud Storage
├── private/ # Local-only (Git-ignored) ├── private/ # Local-only (Git-ignored)
│ ├── *.yaml │ ├── *.yaml
@@ -602,6 +649,15 @@ retry:
4. 40 seconds 4. 40 seconds
5. 80 seconds (capped at 3 minutes) 5. 80 seconds (capped at 3 minutes)
### Global Settings (`argocd-cm`)
| Setting | Value | Purpose |
|---------|-------|---------|
| `application.resourceTrackingMethod` | `annotation` | Track resources via annotations |
| `timeout.reconciliation` | `60s` | Reconciliation interval |
| `admin.enabled` | `true` | Enable admin account |
| `git.submodule.enabled` | `false` | Disable git submodule checkout — submodules are not needed for manifest generation |
--- ---
## Infrastructure Components ## Infrastructure Components
@@ -677,6 +733,10 @@ spec:
**Chart**: `sealed-secrets/sealed-secrets-controller` **Chart**: `sealed-secrets/sealed-secrets-controller`
**Namespace**: `kube-system` **Namespace**: `kube-system`
**Directory Structure**: `secrets/base/` contains all SealedSecrets with a `kustomization.yaml`. Per-cloud overlays in `secrets/overlays/<cloud>/` reference the base via Kustomize. The ArgoCD `secrets` Application points to the active overlay (e.g., `secrets/overlays/upc-dev`), and `infra/overlays/upc-prod` patches the path to `secrets/overlays/upc-prod`.
To add cloud-specific secrets, create a new SealedSecret in the overlay directory and add it to the overlay's `kustomization.yaml`.
**Public Certificate**: **Public Certificate**:
```bash ```bash
kubeseal --fetch-cert \ kubeseal --fetch-cert \
@@ -1069,6 +1129,33 @@ kubectl get secret keycloak-client-<app> -n keycloak -o jsonpath='{.metadata.ann
**See**: [Developer Guide - Adding a New Keycloak Client](DEVELOPER-GUIDE.md#adding-a-new-keycloak-client) **See**: [Developer Guide - Adding a New Keycloak Client](DEVELOPER-GUIDE.md#adding-a-new-keycloak-client)
### Karpor
**Chart**: `karpor` from `https://kusionstack.github.io/charts`
**Version**: 0.7.6 (app v0.6.4)
**Namespace**: `karpor`
**Sync Wave**: 1
**Purpose**: Kubernetes visualization and intelligence tool. Provides cross-cluster resource search, compliance checking, and topology visualization. Gives platform engineers a unified view of all cluster resources and their relationships.
**Architecture** (4 components):
- **Server** — main Karpor API/UI (port 7443)
- **Syncer** — syncs cluster state into the search index
- **ElasticSearch** — search backend for resource indexing
- **etcd** — persistent key-value store (10Gi PVC)
**Configuration** (`infra/values/base/karpor-values.yaml`):
- `namespaceEnabled: false` — ArgoCD manages namespace creation
- Default resource limits tuned for small clusters
- ElasticSearch: 2 CPU / 4Gi memory (the heaviest component)
- AI features available but not enabled (requires `server.ai.authToken` + backend config)
**Access**: Port-forward to reach the UI:
```bash
kubectl port-forward svc/karpor-release-server -n karpor 7443:7443
# Open https://localhost:7443
```
### Renovate ### Renovate
**Chart**: `renovate` (OCI: `ghcr.io/renovatebot/charts`) **Chart**: `renovate` (OCI: `ghcr.io/renovatebot/charts`)
@@ -1516,7 +1603,23 @@ Forward to Application (localhost:3000)
Application processes request Application processes request
``` ```
**See**: [Developer Guide - Enabling Authentication](DEVELOPER-GUIDE.md#enabling-authentication-for-applications) for usage examples. #### Forwarded Headers
After successful authentication, the sidecar injects user identity as HTTP headers before forwarding the request to the application container:
| Header | Description | Auth Modes |
|--------|-------------|------------|
| `X-Auth-User` | Username or display name | Token, OIDC, MCP |
| `X-Auth-Email` | User email address | OIDC |
| `X-Auth-Subject` | OIDC `sub` claim (stable user ID) | OIDC, MCP |
| `X-Auth-Groups` | Comma-separated group memberships | OIDC (if `groups` scope) |
| `X-Auth-Token` | The validated access token | All modes |
These headers are trustworthy because the auto-generated `NetworkPolicy` restricts pod ingress to the sidecar port only — external traffic cannot reach the application container directly, so headers cannot be spoofed.
Applications should read these headers to obtain authenticated user information (e.g. for display, authorisation decisions, or audit logging) instead of implementing their own authentication.
**See**: [Developer Guide - Accessing Authenticated User Information](DEVELOPER-GUIDE.md#accessing-authenticated-user-information) for code examples.
--- ---
@@ -1629,6 +1732,88 @@ POST /loki/api/v1/push
--- ---
## Cloud Overlay Pattern
### Overview
Cloud-specific configuration (StorageClass, LoadBalancer annotations, pricing models, etc.) lives in per-cloud overlay value files, **not** in `base/`. Adding a new cloud provider only requires a new overlay directory — no base changes.
### Supported Clouds
| Cloud | Dev overlay | Prod overlay | StorageClass | LB type |
|-------|-----------|-------------|-------------|---------|
| **UpCloud** | `upc-dev` | `upc-prod` | `upcloud-block-storage-maxiops` | UpCloud LB (proxy protocol v2) |
| **Azure AKS** | `aks-dev` | `aks-prod` | `managed-csi-premium` | Azure LB |
| **AWS EKS** | `eks-dev` | `eks-prod` | `gp3` | AWS NLB (proxy protocol) |
| **GCP GKE** | `gke-dev` | `gke-prod` | `premium-rwo` | GCP NEG |
Bootstrap any cluster with: `./bootstrap.sh <cluster>` (e.g., `./bootstrap.sh aks-dev`)
### How It Works
Each ArgoCD Application uses **multi-source Helm values** with two value files:
```yaml
# infra/base/gitea.yaml (example)
helm:
valueFiles:
- $values/infra/values/base/gitea-values.yaml # [0] cloud-agnostic
- $values/infra/values/upc-dev/gitea-values.yaml # [1] cloud-specific (default: upc-dev)
```
The `upc-prod` Kustomize overlay patches index `[1]` to swap the cloud-specific file:
```yaml
# infra/overlays/upc-prod/kustomization.yaml
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/upc-prod/gitea-values.yaml
```
### Components Using Cloud Overlays
| Component | Cloud-specific config | Overlay value file |
|-----------|----------------------|-------------------|
| **Traefik** | LB annotations, proxy protocol IPs | `traefik-values.yaml` |
| **Keycloak** | Hostname, TLS settings | `keycloak-values.yaml` |
| **Grafana** | Hostname, datasource URLs | `grafana-values.yaml` |
| **Gitea** | StorageClass (persistence + PostgreSQL) | `gitea-values.yaml` |
| **OpenCost** | Custom pricing model (CPU/RAM/storage rates) | `opencost-values.yaml` |
### Backup CronJob
The `gitea-backup` CronJob uses a generic `s3` alias for `minio/mc`. The actual endpoint and credentials come from the `gitea-backup-s3` Sealed Secret, which is per-cloud. Reference scripts for different cloud providers are in `scripts/backup/`:
| Script | Provider | Tool |
|--------|----------|------|
| `s3-minio.sh` | S3-compatible (UpCloud, MinIO, Wasabi) | `minio/mc` |
| `aws-s3.sh` | AWS S3 | `aws` CLI |
| `azure-blob.sh` | Azure Blob Storage | `az` CLI |
| `gcp-gcs.sh` | GCP Cloud Storage | `gsutil` |
### Adding a New Cloud Provider
To add support for a new cloud (e.g., `oci-dev` for Oracle Cloud):
1. **Cluster config**: `clusters/oci-dev.yaml` — clusterName, domain, trustedIPs, cloudProvider
2. **Overlay value files** in `infra/values/oci-dev/`:
- `traefik-values.yaml` — LB annotations, proxy protocol config
- `keycloak-values.yaml` — hostname
- `grafana-values.yaml` — hostname
- `gitea-values.yaml``storageClass` for persistence + PostgreSQL
- `opencost-values.yaml` — pricing model or cloud billing integration
3. **Kustomize overlay**: `infra/overlays/oci-dev/kustomization.yaml` — patch `valueFiles[1]` for each Application
4. **App-of-apps**: `_app-of-apps-oci-dev.yaml` — points to `infra/overlays/oci-dev`
5. **Secrets overlay**: `secrets/overlays/oci-dev/kustomization.yaml` — references `../../base`, add cloud-specific SealedSecrets if needed
6. **Secrets patch**: Add patch to `infra/overlays/oci-dev/kustomization.yaml` to swap secrets path to `secrets/overlays/oci-dev`
7. **Bootstrap**: `./bootstrap.sh oci-dev`
---
## Glossary ## Glossary
### Terms ### Terms

48
infra/base/karpor.yaml Normal file
View File

@@ -0,0 +1,48 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: karpor
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "1"
labels:
app.kubernetes.io/name: karpor
app.kubernetes.io/part-of: developer-portal
app.kubernetes.io/managed-by: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: https://kusionstack.github.io/charts
chart: karpor
targetRevision: "0.7.6"
helm:
releaseName: karpor
valueFiles:
- $values/infra/values/base/karpor-values.yaml
- repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD
ref: values
destination:
server: https://kubernetes.default.svc
namespace: karpor
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- Validate=true
- ServerSideApply=true
ignoreDifferences:
- group: apps
kind: StatefulSet
jsonPointers:
- /spec/volumeClaimTemplates

View File

@@ -22,3 +22,4 @@ resources:
- tempo.yaml - tempo.yaml
- grafana-dashboards.yaml - grafana-dashboards.yaml
- network-policies-application.yaml - network-policies-application.yaml
- karpor.yaml

View File

@@ -24,7 +24,7 @@ spec:
- $values/infra/values/base/opencost-values.yaml - $values/infra/values/base/opencost-values.yaml
- $values/infra/values/upc-dev/opencost-values.yaml - $values/infra/values/upc-dev/opencost-values.yaml
- repoURL: git@github.com:fortedigital/sturdy-adventure.git - repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
ref: values ref: values

View File

@@ -18,7 +18,7 @@ spec:
project: default project: default
source: source:
repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
path: secrets/upc-dev path: secrets/overlays/upc-dev
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: secrets namespace: secrets

View File

@@ -31,7 +31,7 @@ spec:
- $values/infra/values/base/traefik-values.yaml - $values/infra/values/base/traefik-values.yaml
- $values/infra/values/upc-dev/traefik-values.yaml - $values/infra/values/upc-dev/traefik-values.yaml
- repoURL: git@github.com:fortedigital/sturdy-adventure.git - repoURL: ssh://git@git.forteapps.net:2222/Forte/launchpad.git
targetRevision: HEAD targetRevision: HEAD
ref: values ref: values

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → aks-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-dev/traefik-values.yaml
# Keycloak: swap upc-dev → aks-dev
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-dev/keycloak-values.yaml
# Grafana: swap upc-dev → aks-dev
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-dev/grafana-values.yaml
# Gitea: swap upc-dev → aks-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-dev/gitea-values.yaml
# OpenCost: swap upc-dev → aks-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-dev/opencost-values.yaml
# Secrets: change path to aks-dev
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/aks-dev
# Enterprise-apps: point to aks-dev overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/aks-dev

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → aks-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-prod/traefik-values.yaml
# Keycloak: swap upc-dev → aks-prod
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-prod/keycloak-values.yaml
# Grafana: swap upc-dev → aks-prod
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-prod/grafana-values.yaml
# Gitea: swap upc-dev → aks-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-prod/gitea-values.yaml
# OpenCost: swap upc-dev → aks-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aks-prod/opencost-values.yaml
# Secrets: change path to aks-prod
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/aks-prod
# Enterprise-apps: point to aks-prod overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/aks-prod

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → aws-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-dev/traefik-values.yaml
# Gitea: swap upc-dev → aws-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-dev/gitea-values.yaml
# OpenCost: swap upc-dev → aws-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-dev/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → aws-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-prod/traefik-values.yaml
# Gitea: swap upc-dev → aws-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-prod/gitea-values.yaml
# OpenCost: swap upc-dev → aws-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/aws-prod/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → azure-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-dev/traefik-values.yaml
# Gitea: swap upc-dev → azure-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-dev/gitea-values.yaml
# OpenCost: swap upc-dev → azure-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-dev/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → azure-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-prod/traefik-values.yaml
# Gitea: swap upc-dev → azure-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-prod/gitea-values.yaml
# OpenCost: swap upc-dev → azure-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/azure-prod/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → eks-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-dev/traefik-values.yaml
# Keycloak: swap upc-dev → eks-dev
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-dev/keycloak-values.yaml
# Grafana: swap upc-dev → eks-dev
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-dev/grafana-values.yaml
# Gitea: swap upc-dev → eks-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-dev/gitea-values.yaml
# OpenCost: swap upc-dev → eks-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-dev/opencost-values.yaml
# Secrets: change path to eks-dev
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/eks-dev
# Enterprise-apps: point to eks-dev overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/eks-dev

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → eks-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-prod/traefik-values.yaml
# Keycloak: swap upc-dev → eks-prod
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-prod/keycloak-values.yaml
# Grafana: swap upc-dev → eks-prod
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-prod/grafana-values.yaml
# Gitea: swap upc-dev → eks-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-prod/gitea-values.yaml
# OpenCost: swap upc-dev → eks-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/eks-prod/opencost-values.yaml
# Secrets: change path to eks-prod
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/eks-prod
# Enterprise-apps: point to eks-prod overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/eks-prod

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → gcp-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-dev/traefik-values.yaml
# Gitea: swap upc-dev → gcp-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-dev/gitea-values.yaml
# OpenCost: swap upc-dev → gcp-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-dev/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -1,35 +0,0 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → gcp-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-prod/traefik-values.yaml
# Gitea: swap upc-dev → gcp-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-prod/gitea-values.yaml
# OpenCost: swap upc-dev → gcp-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gcp-prod/opencost-values.yaml
# TODO: add patches for keycloak, grafana, secrets, enterprise-apps
# when deploying to this cluster (these are deployment-specific, not cloud-specific)

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → gke-dev
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-dev/traefik-values.yaml
# Keycloak: swap upc-dev → gke-dev
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-dev/keycloak-values.yaml
# Grafana: swap upc-dev → gke-dev
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-dev/grafana-values.yaml
# Gitea: swap upc-dev → gke-dev
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-dev/gitea-values.yaml
# OpenCost: swap upc-dev → gke-dev
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-dev/opencost-values.yaml
# Secrets: change path to gke-dev
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/gke-dev
# Enterprise-apps: point to gke-dev overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/gke-dev

View File

@@ -0,0 +1,68 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
patches:
# Traefik: swap upc-dev → gke-prod
- target:
kind: Application
name: traefik
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-prod/traefik-values.yaml
# Keycloak: swap upc-dev → gke-prod
- target:
kind: Application
name: keycloak
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-prod/keycloak-values.yaml
# Grafana: swap upc-dev → gke-prod
- target:
kind: Application
name: grafana
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-prod/grafana-values.yaml
# Gitea: swap upc-dev → gke-prod
- target:
kind: Application
name: gitea
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-prod/gitea-values.yaml
# OpenCost: swap upc-dev → gke-prod
- target:
kind: Application
name: opencost
patch: |
- op: replace
path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/gke-prod/opencost-values.yaml
# Secrets: change path to gke-prod
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/gke-prod
# Enterprise-apps: point to gke-prod overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/gke-prod

View File

@@ -31,24 +31,6 @@ patches:
path: /spec/sources/0/helm/valueFiles/1 path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/upc-prod/grafana-values.yaml value: $values/infra/values/upc-prod/grafana-values.yaml
# Secrets: change path to upc-prod
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/upc-prod
# Enterprise-apps: point to upc-prod overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/upc-prod
# Gitea: swap upc-dev → upc-prod # Gitea: swap upc-dev → upc-prod
- target: - target:
kind: Application kind: Application
@@ -66,3 +48,21 @@ patches:
- op: replace - op: replace
path: /spec/sources/0/helm/valueFiles/1 path: /spec/sources/0/helm/valueFiles/1
value: $values/infra/values/upc-prod/opencost-values.yaml value: $values/infra/values/upc-prod/opencost-values.yaml
# Secrets: change path to upc-prod
- target:
kind: Application
name: secrets
patch: |
- op: replace
path: /spec/source/path
value: secrets/overlays/upc-prod
# Enterprise-apps: point to upc-prod overlay
- target:
kind: Application
name: enterprise-apps
patch: |
- op: replace
path: /spec/source/path
value: apps/overlays/upc-prod

View File

@@ -1,4 +1,4 @@
# Azure Managed Disk (Premium SSD via CSI driver) # AKS-specific: Azure managed disk storage class
persistence: persistence:
storageClass: managed-csi-premium storageClass: managed-csi-premium
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# AKS-specific: Grafana hostname
ingress:
hosts:
- grafana.forteapps.net

View File

@@ -0,0 +1,3 @@
# AKS-specific: Keycloak hostname
ingress:
hostname: id.forteapps.net

View File

@@ -0,0 +1,8 @@
# AKS-specific: Azure pricing via Cloud Billing API
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
azure:
secretName: opencost-azure-billing

View File

@@ -0,0 +1,11 @@
# AKS-specific: Azure Load Balancer for Traefik
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: /ping
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,4 +1,4 @@
# Azure Managed Disk (Premium SSD via CSI driver) # AKS-specific: Azure managed disk storage class (prod)
persistence: persistence:
storageClass: managed-csi-premium storageClass: managed-csi-premium
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# AKS-specific: Grafana hostname (prod)
ingress:
hosts:
- grafana.fortedigital.com

View File

@@ -0,0 +1,3 @@
# AKS-specific: Keycloak hostname (prod)
ingress:
hostname: id.fortedigital.com

View File

@@ -0,0 +1,8 @@
# AKS-specific: Azure pricing via Cloud Billing API (prod)
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
azure:
secretName: opencost-azure-billing

View File

@@ -0,0 +1,12 @@
# AKS-specific: Azure Load Balancer for Traefik (prod)
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: /ping
service.beta.kubernetes.io/azure-load-balancer-internal: "false"
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,13 +0,0 @@
# AWS native pricing via Cost and Usage Reports
opencost:
exporter:
customPricing:
enabled: true
provider: aws
aws:
service_key_name: "" # <- populate or use IRSA
service_key_secret: ""
spot_data_region: ""
spot_data_bucket: ""
spot_data_prefix: ""
account_id: ""

View File

@@ -1,18 +0,0 @@
# AWS EKS — NLB with Proxy Protocol v2 for real client IPs
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8" # <- adjust to your VPC CIDR
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,13 +0,0 @@
# AWS native pricing via Cost and Usage Reports
opencost:
exporter:
customPricing:
enabled: true
provider: aws
aws:
service_key_name: "" # <- populate or use IRSA
service_key_secret: ""
spot_data_region: ""
spot_data_bucket: ""
spot_data_prefix: ""
account_id: ""

View File

@@ -1,18 +0,0 @@
# AWS EKS — NLB with Proxy Protocol v2 for real client IPs
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8" # <- adjust to your VPC CIDR
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,11 +0,0 @@
# Azure native pricing via Billing API
opencost:
exporter:
customPricing:
enabled: true
provider: azure
azure:
subscriptionID: "" # <- populate
clientID: ""
clientSecret: ""
tenantID: ""

View File

@@ -1,16 +0,0 @@
# Azure AKS — Standard Load Balancer
# Note: Azure Standard LB does not support Proxy Protocol.
# Use externalTrafficPolicy: Local on the Traefik service to preserve
# client IPs, or deploy behind Azure Application Gateway.
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: "/ping"
spec:
externalTrafficPolicy: Local
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # <- VNet CIDR + Azure health probe
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8,168.63.129.16/32"

View File

@@ -1,11 +0,0 @@
# Azure native pricing via Billing API
opencost:
exporter:
customPricing:
enabled: true
provider: azure
azure:
subscriptionID: "" # <- populate
clientID: ""
clientSecret: ""
tenantID: ""

View File

@@ -1,16 +0,0 @@
# Azure AKS — Standard Load Balancer
# Note: Azure Standard LB does not support Proxy Protocol.
# Use externalTrafficPolicy: Local on the Traefik service to preserve
# client IPs, or deploy behind Azure Application Gateway.
service:
annotations:
service.beta.kubernetes.io/azure-load-balancer-health-probe-request-path: "/ping"
spec:
externalTrafficPolicy: Local
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8,168.63.129.16/32" # <- VNet CIDR + Azure health probe
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8,168.63.129.16/32"

View File

@@ -2,12 +2,21 @@ configs:
secret: secret:
createSecret: true createSecret: true
argocdServerAdminPassword: "$2b$12$Tmb1jH7ADvwWoUoNPXXsfOf6JqEluqhq8mL06a8DGT2AP1GzbNsCm" argocdServerAdminPassword: "$2b$12$Tmb1jH7ADvwWoUoNPXXsfOf6JqEluqhq8mL06a8DGT2AP1GzbNsCm"
ssh:
knownHosts: |
[git.forteapps.net]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDTwi40de8yTGUuRT0i/XGicQ672BLhYR6D/lDquJrp/tdrWoZhVVPy0wxSkWsq1V92iiAUuQnXagOGsLBGZT9uDLWKvEmNDnCfjzTMq3J1iA3vk2rQ8WBlCzhvmeCV/r0ufl6vsgfwxSRomLZeqa2UkLHx69gy2Njb1S2/aZK1Q53f466hCUfDULZrTn2Nn5Sj8cEbJ8EyvVN2YG9HYBxQdzKRPZEmS1vyzmn8YrYIkZseIRQElabzWGh86owuaaqnwJhTJj1j2sEUeIet04sGKJcnxx2UL4H90N66LKMldmMiuli+ve/CjJmMwDl0zGkjIniT3XR8CyEXYHli7B1hR8Z+dbK6DBgjz+28lFgMIRY70KkZJNsJcBNZLZ5fHwCI13a9U3Uhg3Pu/6s0zlosM4CrAQNQCRe95ZPtCpdFhlGrOl4m1rdSK2meL6rND0TBBuZbaFF6Py7TawLCAiO2KRaVqhu9OFVjwJ/nifgLzFGwWj+WcYmpuR+DwozrF/Hl7QYsz1x4GO1SONY07KbIFkUCHOMAh0AELY5YE4eGI4mtG6SecdPaAdLREGZYK4IcyP5i1QW9g0wmfRSsV9jy+r0ivBxixxh4yJiNpkg6NXak40gQtGIme9EJ+DxrRLruNsfDILWcdSuH/wvuorv56NpQFGB0FzB6LXMloSYptQ==
cm: cm:
application.resourceTrackingMethod: annotation application.resourceTrackingMethod: annotation
timeout.reconciliation: 60s timeout.reconciliation: 60s
admin.enabled: "true" admin.enabled: "true"
params: params:
"server.insecure": true "server.insecure": true
repoServer:
env:
# Disable git submodule checkout - submodules (e.g. shared-prompts)
# are not needed for K8s manifest generation
- name: ARGOCD_GIT_MODULES_ENABLED
value: "false"
server: server:
ingress: ingress:
enabled: false enabled: false

View File

@@ -0,0 +1,44 @@
# Karpor - Kubernetes Visualization & Intelligence Tool
# Helm chart: https://github.com/KusionStack/charts/tree/master/charts/karpor
# Let the ArgoCD Application manage the namespace
namespaceEnabled: false
server:
replicas: 1
port: 7443
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
syncer:
replicas: 1
port: 7443
resources:
requests:
cpu: 250m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
elasticsearch:
replicas: 1
port: 9200
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: "2"
memory: 4Gi
etcd:
replicas: 1
port: 2379
persistence:
size: 5Gi

View File

@@ -1,4 +1,4 @@
# AWS EBS gp3 storage class (requires EBS CSI driver) # EKS-specific: gp3 storage class
persistence: persistence:
storageClass: gp3 storageClass: gp3
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# EKS-specific: Grafana hostname
ingress:
hosts:
- grafana.forteapps.net

View File

@@ -0,0 +1,3 @@
# EKS-specific: Keycloak hostname
ingress:
hostname: id.forteapps.net

View File

@@ -0,0 +1,11 @@
# EKS-specific: AWS pricing via Cost and Usage Report
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
aws:
spot_data_region: ""
spot_data_bucket: ""
spot_data_prefix: ""
account_id: ""

View File

@@ -0,0 +1,17 @@
# EKS-specific: AWS NLB for Traefik
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,4 +1,4 @@
# AWS EBS gp3 storage class (requires EBS CSI driver) # EKS-specific: gp3 storage class (prod)
persistence: persistence:
storageClass: gp3 storageClass: gp3
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# EKS-specific: Grafana hostname (prod)
ingress:
hosts:
- grafana.fortedigital.com

View File

@@ -0,0 +1,3 @@
# EKS-specific: Keycloak hostname (prod)
ingress:
hostname: id.fortedigital.com

View File

@@ -0,0 +1,11 @@
# EKS-specific: AWS pricing via Cost and Usage Report (prod)
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
aws:
spot_data_region: ""
spot_data_bucket: ""
spot_data_prefix: ""
account_id: ""

View File

@@ -0,0 +1,18 @@
# EKS-specific: AWS NLB for Traefik (prod)
service:
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8"
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,9 +0,0 @@
# GCP native pricing via Cloud Billing API
opencost:
exporter:
customPricing:
enabled: true
provider: gcp
gcp:
projectID: "" # <- populate with your GCP project ID
key: "" # <- or use Workload Identity

View File

@@ -1,15 +0,0 @@
# GCP GKE — External passthrough Network Load Balancer
service:
annotations:
cloud.google.com/l4-rbs: "enabled"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # <- subnet CIDR + GCP health checks
forwardedHeaders:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"
forwardedHeaders:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"

View File

@@ -1,9 +0,0 @@
# GCP native pricing via Cloud Billing API
opencost:
exporter:
customPricing:
enabled: true
provider: gcp
gcp:
projectID: "" # <- populate with your GCP project ID
key: "" # <- or use Workload Identity

View File

@@ -1,15 +0,0 @@
# GCP GKE — External passthrough Network Load Balancer
service:
annotations:
cloud.google.com/l4-rbs: "enabled"
ports:
web:
proxyProtocol:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22" # <- subnet CIDR + GCP health checks
forwardedHeaders:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"
websecure:
proxyProtocol:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"
forwardedHeaders:
trustedIPs: "10.0.0.0/8,35.191.0.0/16,130.211.0.0/22"

View File

@@ -1,4 +1,4 @@
# GCP Persistent Disk (SSD via CSI driver) # GKE-specific: SSD persistent disk storage class
persistence: persistence:
storageClass: premium-rwo storageClass: premium-rwo
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# GKE-specific: Grafana hostname
ingress:
hosts:
- grafana.forteapps.net

View File

@@ -0,0 +1,3 @@
# GKE-specific: Keycloak hostname
ingress:
hostname: id.forteapps.net

View File

@@ -0,0 +1,10 @@
# GKE-specific: GCP pricing via BigQuery billing export
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
google:
key: ""
project_id: ""
billing_account: ""

View File

@@ -0,0 +1,12 @@
# GKE-specific: Google Cloud Load Balancer for Traefik
service:
annotations:
cloud.google.com/neg: '{"ingress":true}'
networking.gke.io/load-balancer-type: External
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

View File

@@ -1,4 +1,4 @@
# GCP Persistent Disk (SSD via CSI driver) # GKE-specific: SSD persistent disk storage class (prod)
persistence: persistence:
storageClass: premium-rwo storageClass: premium-rwo
postgresql: postgresql:

View File

@@ -0,0 +1,4 @@
# GKE-specific: Grafana hostname (prod)
ingress:
hosts:
- grafana.fortedigital.com

View File

@@ -0,0 +1,3 @@
# GKE-specific: Keycloak hostname (prod)
ingress:
hostname: id.fortedigital.com

View File

@@ -0,0 +1,10 @@
# GKE-specific: GCP pricing via BigQuery billing export (prod)
opencost:
exporter:
cloudProviderApiKey: ""
customPricing:
enabled: false
google:
key: ""
project_id: ""
billing_account: ""

View File

@@ -0,0 +1,12 @@
# GKE-specific: Google Cloud Load Balancer for Traefik (prod)
service:
annotations:
cloud.google.com/neg: '{"ingress":true}'
networking.gke.io/load-balancer-type: External
ports:
web:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"
websecure:
forwardedHeaders:
trustedIPs: "10.0.0.0/8"

23
scripts/backup/aws-s3.sh Normal file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
# AWS S3 backup upload (native AWS CLI)
# Uses: aws cli v2
# Env: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, S3_BUCKET
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
KEY="gitea-dump-${TIMESTAMP}.zip"
echo "Uploading ${KEY}..."
aws s3 cp "$BACKUP_FILE" "s3://${S3_BUCKET}/${KEY}"
echo "Upload complete."
# Prune backups older than 7 days
echo "Pruning backups older than 7 days..."
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%S)
aws s3api list-objects-v2 --bucket "${S3_BUCKET}" --query "Contents[?LastModified<'${CUTOFF}'].Key" --output text \
| tr '\t' '\n' \
| while read -r key; do
[ -n "$key" ] && aws s3 rm "s3://${S3_BUCKET}/${key}" && echo "Deleted: ${key}"
done
echo "Pruning complete."

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -euo pipefail
# Azure Blob Storage backup upload
# Uses: az cli
# Env: AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY, AZURE_CONTAINER
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
KEY="gitea-dump-${TIMESTAMP}.zip"
echo "Uploading ${KEY}..."
az storage blob upload \
--account-name "${AZURE_STORAGE_ACCOUNT}" \
--account-key "${AZURE_STORAGE_KEY}" \
--container-name "${AZURE_CONTAINER}" \
--name "${KEY}" \
--file "$BACKUP_FILE" \
--overwrite
echo "Upload complete."
# Prune backups older than 7 days
echo "Pruning backups older than 7 days..."
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%SZ)
az storage blob list \
--account-name "${AZURE_STORAGE_ACCOUNT}" \
--account-key "${AZURE_STORAGE_KEY}" \
--container-name "${AZURE_CONTAINER}" \
--query "[?properties.lastModified<'${CUTOFF}'].name" -o tsv \
| while read -r name; do
[ -n "$name" ] && az storage blob delete \
--account-name "${AZURE_STORAGE_ACCOUNT}" \
--account-key "${AZURE_STORAGE_KEY}" \
--container-name "${AZURE_CONTAINER}" \
--name "$name" && echo "Deleted: ${name}"
done
echo "Pruning complete."

26
scripts/backup/gcp-gcs.sh Normal file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
# GCP Cloud Storage backup upload
# Uses: gsutil (gcloud SDK)
# Env: GCS_BUCKET (e.g. gs://my-bucket)
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
KEY="gitea-dump-${TIMESTAMP}.zip"
echo "Uploading ${KEY}..."
gsutil cp "$BACKUP_FILE" "${GCS_BUCKET}/${KEY}"
echo "Upload complete."
# Prune backups older than 7 days — GCS lifecycle rules are preferred,
# but this works as a manual fallback
echo "Pruning backups older than 7 days..."
CUTOFF=$(date -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-7d +%Y-%m-%dT%H:%M:%SZ)
gsutil ls -l "${GCS_BUCKET}/" \
| grep 'gitea-dump-' \
| while read -r size date name; do
if [[ "$date" < "$CUTOFF" ]]; then
gsutil rm "$name" && echo "Deleted: ${name}"
fi
done
echo "Pruning complete."

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env bash
set -euo pipefail
# S3-compatible backup upload (UpCloud Objects, MinIO, Wasabi, etc.)
# Uses: minio/mc
# Env: S3_ENDPOINT, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_BUCKET
BACKUP_FILE="${1:?Usage: $0 <backup-file>}"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
KEY="gitea-dump-${TIMESTAMP}.zip"
mc alias set s3 "${S3_ENDPOINT}" "${AWS_ACCESS_KEY_ID}" "${AWS_SECRET_ACCESS_KEY}"
echo "Uploading ${KEY}..."
mc cp "$BACKUP_FILE" "s3/${S3_BUCKET}/${KEY}"
echo "Upload complete."
# Prune backups older than 7 days
echo "Pruning backups older than 7 days..."
mc rm --older-than 7d --force "s3/${S3_BUCKET}/" 2>&1 || true
echo "Pruning complete."

View File

@@ -2,19 +2,19 @@
set -euo pipefail set -euo pipefail
# Gitea backup helper for Azure Blob Storage # Gitea backup helper for Azure Blob Storage
# Uses the gitea-backup-azure secret in the gitea namespace # Uses the gitea-backup-aks secret in the gitea namespace
# Required secret keys: # Required secret keys:
# AZURE_STORAGE_ACCOUNT — storage account name # AZURE_STORAGE_ACCOUNT — storage account name
# AZURE_STORAGE_KEY — storage account key # AZURE_STORAGE_KEY — storage account key
# AZURE_CONTAINER — blob container name # AZURE_CONTAINER — blob container name
# #
# Usage: # Usage:
# ./scripts/gitea-backup-azure.sh list # list all backups # ./scripts/gitea-backup-aks.sh list # list all backups
# ./scripts/gitea-backup-azure.sh download <filename> # download a backup # ./scripts/gitea-backup-aks.sh download <filename> # download a backup
# ./scripts/gitea-backup-azure.sh download latest # download the most recent backup # ./scripts/gitea-backup-aks.sh download latest # download the most recent backup
NAMESPACE="gitea" NAMESPACE="gitea"
SECRET="gitea-backup-azure" SECRET="gitea-backup-aks"
IMAGE="mcr.microsoft.com/azure-cli:latest" IMAGE="mcr.microsoft.com/azure-cli:latest"
POD_NAME="gitea-backup-helper" POD_NAME="gitea-backup-helper"

View File

@@ -8,9 +8,9 @@ set -euo pipefail
# For AWS, S3_ENDPOINT is typically https://s3.<region>.amazonaws.com # For AWS, S3_ENDPOINT is typically https://s3.<region>.amazonaws.com
# #
# Usage: # Usage:
# ./scripts/gitea-backup-aws.sh list # list all backups # ./scripts/gitea-backup-eks.sh list # list all backups
# ./scripts/gitea-backup-aws.sh download <filename> # download a backup to current dir # ./scripts/gitea-backup-eks.sh download <filename> # download a backup to current dir
# ./scripts/gitea-backup-aws.sh download latest # download the most recent backup # ./scripts/gitea-backup-eks.sh download latest # download the most recent backup
NAMESPACE="gitea" NAMESPACE="gitea"
SECRET="gitea-backup-s3" SECRET="gitea-backup-s3"

Some files were not shown because too many files have changed in this diff Show More