docs(self-host/kubernetes): add Kubernetes deployment guides with Helm, Kustomize, Helmfile, and GitOps for Newt and Pangolin

Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
This commit is contained in:
Marc Schäfer
2026-05-10 22:08:27 +02:00
parent d9a68a2e15
commit f1ae04d36d
18 changed files with 8964 additions and 1 deletions
@@ -0,0 +1,468 @@
---
title: "Argo CD"
description: "Deploy Pangolin and Newt using Argo CD for Git-driven GitOps reconciliation."
---
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
<PangolinCloudTocCta />
Argo CD is a declarative GitOps tool that continuously syncs your cluster state to your Git repository. This guide covers installing Pangolin and Newt using Argo CD.
## Argo CD overview
Argo CD watches your Git repository (or Helm chart repository) and automatically reconciles Kubernetes resources to match the desired state defined in Git.
**Key concepts**:
- **Application**: Argo CD custom resource that defines what to deploy, where, and how
- **Helm source**: Argo CD uses Helm to render charts; you provide values
- **Kustomize source**: Argo CD uses Kustomize to build manifests
- **Sync**: Process of applying desired state to the cluster
- **Drift**: When cluster state diverges from Git (Argo CD can detect and correct)
## Prerequisites
- Argo CD installed in your cluster (in `argocd` namespace, typically)
- Helm repo configured: `helm repo add fossorial https://charts.fossorial.io`
- Git repository with Argo CD configuration (optional, can use chart repo as source)
- Newt auth secret (if installing Newt)
## Install Argo CD
If you don't have Argo CD yet:
```bash
# Create namespace
kubectl create namespace argocd
# Install Argo CD
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update argo
helm install argocd argo/argo-cd -n argocd
```
Access the Argo CD UI:
```bash
# Port-forward
kubectl port-forward -n argocd svc/argocd-server 8080:443
# Visit https://localhost:8080
# Default username: admin
# Password: kubectl get secret -n argocd argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
```
## Install Pangolin with Argo CD using Helm
### Step 1: Create Pangolin namespace
```bash
kubectl create namespace pangolin
```
### Step 2: Create Application
Create an Argo CD Application resource that tells Argo CD to deploy Pangolin using the Helm chart:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pangolin
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.fossorial.io
chart: pangolin
targetRevision: 0.1.0-alpha.0 # or use ~0.1.0 for range
helm:
values: |
deployment:
type: controller
mode: multi
database:
mode: cloudnativepg
pangolin:
config:
app:
dashboard_url: https://pangolin.example.com
domains:
domain1:
base_domain: example.com
gerbil:
base_endpoint: vpn.example.com
ingress:
enabled: true
className: traefik
hosts:
- host: pangolin.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: pangolin-tls
hosts:
- pangolin.example.com
destination:
server: https://kubernetes.default.svc
namespace: pangolin
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true
```
Apply the Application:
```bash
kubectl apply -f pangolin-app.yaml
```
### Step 3: Monitor in Argo CD
In the Argo CD UI, you should see the `pangolin` application. Argo CD will:
1. Fetch the Helm chart from `https://charts.fossorial.io`
2. Render the chart with your inline `values`
3. Create all resources in the `pangolin` namespace
4. Continuously monitor for drift
### Step 4: Verify deployment
```bash
# Check Argo CD status
kubectl describe app -n argocd pangolin
# Check pod status
kubectl get pods -n pangolin
```
## Install Newt with Argo CD using Helm
### Step 1: Create Newt auth secret
```bash
kubectl create secret generic newt-auth \
-n pangolin \
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
--from-literal=NEWT_ID=<your-newt-id> \
--from-literal=NEWT_SECRET=<your-newt-secret>
```
### Step 2: Create Newt Application
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: newt
namespace: argocd
spec:
project: default
source:
repoURL: https://charts.fossorial.io
chart: newt
targetRevision: 1.4.0
helm:
values: |
newtInstances:
- name: main-tunnel
enabled: true
auth:
existingSecretName: newt-auth
destination:
server: https://kubernetes.default.svc
namespace: pangolin
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true
```
Apply:
```bash
kubectl apply -f newt-app.yaml
```
## Using Argo CD with Git repository
Instead of inline values, you can store configuration in Git and have Argo CD deploy from there:
### Repository structure
```
infrastructure/
├── apps/
│ ├── pangolin/
│ │ ├── values-base.yaml
│ │ ├── values-prod.yaml
│ │ └── app.yaml (Argo CD Application CRD)
│ └── newt/
│ ├── values.yaml
│ └── app.yaml
└── clusters/
└── production/
├── pangolin.yaml (reference to app)
└── newt.yaml
```
### Git-based Application
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pangolin
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/infrastructure
path: apps/pangolin
targetRevision: main
helm:
valuesObject:
deployment:
type: controller
mode: multi
releaseName: pangolin
destination:
server: https://kubernetes.default.svc
namespace: pangolin
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true
```
Argo CD will watch the Git repository and auto-sync on changes to `apps/pangolin`.
## Using Argo CD with Kustomize
Deploy Pangolin using Kustomize overlays:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pangolin
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/infrastructure
path: overlays/production
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: pangolin
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true
```
## Sync policies
### Automated sync
**prune: true**: Deletes resources in cluster that are no longer in Git
**selfHeal: true**: Resyncs if cluster drifts from Git (e.g., manual `kubectl apply`)
```yaml
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false # prevent accidental deletion of all resources
```
### Manual sync
Sync only when you explicitly trigger it:
```yaml
syncPolicy:
syncOptions:
- CreateNamespace=true
```
Manually sync:
```bash
argocd app sync pangolin
# or use UI
```
## Advanced: ApplicationSet for multi-environment
Deploy Pangolin and Newt across multiple clusters or environments:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pangolin-multienv
namespace: argocd
spec:
generators:
- list:
elements:
- cluster: production
env: prod
- cluster: staging
env: staging
template:
metadata:
name: pangolin-{{ .cluster }}
spec:
project: default
source:
repoURL: https://github.com/my-org/infrastructure
path: clusters/{{ .cluster }}/pangolin
targetRevision: main
destination:
name: '{{ .cluster }}'
namespace: pangolin
syncPolicy:
automated:
prune: true
selfHeal: true
```
## OCI Helm sources (if available)
If the Helm chart is available in an OCI registry:
```yaml
source:
repoURL: oci://registry.example.com/fossorial
chart: pangolin
targetRevision: 0.1.0-alpha.0
helm:
values: |
# ... values ...
```
OCI chart references work the same as traditional Helm repository references in Argo CD.
## Troubleshooting Argo CD deployments
### Check Application status
```bash
kubectl describe app -n argocd pangolin
kubectl get app -n argocd pangolin -o yaml
```
### Check sync status
```bash
argocd app get pangolin
argocd app logs pangolin
```
### Manual sync
```bash
argocd app sync pangolin --force
```
### Refresh from repository
```bash
argocd app diff pangolin
```
### Delete Application
```bash
kubectl delete app -n argocd pangolin
```
## Common patterns
### Different values per environment
Use multiple Applications:
```yaml
# production/pangolin-app.yaml
spec:
source:
helm:
values: |
resources:
limits:
cpu: 2000m
memory: 2Gi
replicas: 3
# staging/pangolin-app.yaml
spec:
source:
helm:
values: |
resources:
limits:
cpu: 500m
memory: 512Mi
replicas: 1
```
### Secrets with sealed-secrets
Use sealed-secrets to safely store secrets in Git:
```yaml
# In Git
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: newt-auth
namespace: pangolin
spec:
encryptedData:
PANGOLIN_ENDPOINT: AgC4F5qd...
NEWT_ID: AgB9l2pK...
NEWT_SECRET: AgDq3jX...
```
Argo CD applies the sealed secret; the cluster decrypts it.
## Next steps
<CardGroup cols={2}>
<Card title="GitOps Overview" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch" />
<Card title="Flux" href="/self-host/manual/kubernetes/gitops/flux" icon="code-branch" />
<Card title="Pangolin Configuration" href="/self-host/manual/kubernetes/pangolin/configuration" icon="sliders" />
<Card title="Troubleshooting" href="/self-host/manual/kubernetes/pangolin/troubleshooting" icon="circle-question" />
</CardGroup>
+559
View File
@@ -0,0 +1,559 @@
---
title: "Flux"
description: "Deploy Pangolin and Newt using Flux for Git-driven GitOps reconciliation."
---
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
<PangolinCloudTocCta />
Flux is a declarative GitOps tool that uses Kubernetes-native Custom Resources to manage deployments. This guide covers installing Pangolin and Newt using Flux.
## Flux overview
Flux watches your Git repository and continuous reconciles cluster state using Kubernetes CRDs:
- **HelmRepository**: Defines a Helm chart repository
- **HelmRelease**: Declaratively manages a Helm chart deployment
- **GitRepository**: References a Git repository
- **Kustomization**: Reconciles Kustomize overlays
- **OCIRepository**: References an OCI-based container registry (for Helm charts)
**Key benefits**:
- Native Kubernetes reconciliation (no separate UI needed, though one exists)
- Lightweight footprint
- Excellent for multi-cluster deployments
- Declarative everything: sources, releases, dependencies
## Flux prerequisites
- Kubernetes 1.25+
- `flux` CLI installed: [Flux install guide](https://fluxcd.io/flux/installation/)
- Git repository for configuration (optional, can use built-in sources)
- GitHub, GitLab, or other Git provider account (optional)
Install Flux CLI:
```bash
# macOS/Linux with brew
brew install flux
# or curl
curl -s https://fluxcd.io/install.sh | sudo bash
# Verify
flux --version
```
## Install Flux on your cluster
### Option 1: Bootstrap Flux from GitHub
Flux `bootstrap` automatically installs Flux and configures Git sync:
```bash
flux bootstrap github \
--owner=my-org \
--repo=infrastructure \
--personal \
--path=clusters/production
```
This creates the Git repository structure and installs Flux components.
### Option 2: Manual Flux installation
```bash
# Create flux-system namespace and install Flux
flux install --namespace=flux-system --network-policy=true
```
## Install Pangolin with Flux using HelmRelease
### Step 1: Create HelmRepository
Define the Fossorial Helm chart repository:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository
metadata:
name: fossorial
namespace: flux-system
spec:
interval: 5m
url: https://charts.fossorial.io
```
Apply:
```bash
kubectl apply -f helmrepo.yaml
# Verify
kubectl get helmrepo -n flux-system
```
### Step 2: Create Pangolin HelmRelease
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
namespace: pangolin
spec:
interval: 10m
chart:
spec:
chart: pangolin
version: 0.1.0-alpha.0 # or use ~0.1.0 for auto-upgrades
sourceRef:
kind: HelmRepository
name: fossorial
namespace: flux-system
install:
crds: Create
upgrade:
crds: CreateReplace
values:
deployment:
type: controller
mode: multi
database:
mode: cloudnativepg
pangolin:
config:
app:
dashboard_url: https://pangolin.example.com
domains:
domain1:
base_domain: example.com
gerbil:
base_endpoint: vpn.example.com
ingress:
enabled: true
className: traefik
hosts:
- host: pangolin.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: pangolin-tls
hosts:
- pangolin.example.com
```
Create namespace:
```bash
kubectl create namespace pangolin
```
Apply:
```bash
kubectl apply -f pangolin-helmrelease.yaml
```
### Step 3: Monitor reconciliation
```bash
# Check HelmRelease status
kubectl get helmrelease -n pangolin
# Watch live
kubectl get helmrelease -n pangolin -w
# Describe for details
kubectl describe helmrelease pangolin -n pangolin
# Check Flux logs
flux logs --all-namespaces --follow
```
## Install Newt with Flux using HelmRelease
### Step 1: Create Newt auth secret
```bash
kubectl create secret generic newt-auth \
-n pangolin \
--from-literal=PANGOLIN_ENDPOINT=https://pangolin.example.com \
--from-literal=NEWT_ID=<your-newt-id> \
--from-literal=NEWT_SECRET=<your-newt-secret>
```
### Step 2: Create Newt HelmRelease
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: newt
namespace: pangolin
spec:
interval: 10m
chart:
spec:
chart: newt
version: 1.4.0
sourceRef:
kind: HelmRepository
name: fossorial
namespace: flux-system
values:
newtInstances:
- name: main-tunnel
enabled: true
auth:
existingSecretName: newt-auth
```
Apply:
```bash
kubectl apply -f newt-helmrelease.yaml
```
### Step 3: Verify
```bash
kubectl get helmrelease -n pangolin
kubectl describe helmrelease newt -n pangolin
```
## Using Flux with Git repository (GitOps)
Store Flux configuration in Git and have Flux automatically reconcile changes:
### Repository structure
```
infrastructure/
├── clusters/
│ └── production/
│ ├── flux-system/
│ │ └── gotk-components.yaml (auto-generated)
│ ├── pangolin/
│ │ ├── helmrepo.yaml
│ │ ├── pangolin-helmrelease.yaml
│ │ └── newt-helmrelease.yaml
│ └── kustomization.yaml
└── apps/
├── pangolin/
│ └── values.yaml
└── newt/
└── values.yaml
```
### GitRepository for configuration
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: infrastructure
namespace: flux-system
spec:
interval: 1m
url: https://github.com/my-org/infrastructure
ref:
branch: main
```
### Kustomization for syncing
```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: production
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: infrastructure
path: ./clusters/production
prune: true
wait: true
```
Flux watches `clusters/production` in Git and auto-applies all resources.
## Using Flux with Kustomize overlays
Manage environment-specific overlays with Flux:
### Repository structure
```
overlays/
├── dev/
│ ├── kustomization.yaml
│ └── pangolin-patch.yaml
├── staging/
│ └── kustomization.yaml
└── prod/
├── kustomization.yaml
└── pangolin-patch.yaml
```
### Kustomization resource
```yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: pangolin-prod
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: infrastructure
path: ./overlays/prod
prune: true
wait: true
```
Flux builds and applies the Kustomize overlay automatically.
## Using Flux with OCI Helm charts
If Helm charts are available in an OCI registry:
```yaml
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: fossorial-oci
namespace: flux-system
spec:
interval: 5m
url: oci://registry.example.com/fossorial
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
namespace: pangolin
spec:
interval: 10m
chart:
spec:
chart: pangolin
version: 0.1.0-alpha.0
sourceRef:
kind: OCIRepository
name: fossorial-oci
namespace: flux-system
values:
# ... values ...
```
## Advanced: Dependency ordering
Order HelmReleases to install dependencies first:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: cert-manager
namespace: cert-manager
spec:
interval: 10m
chart:
spec:
chart: cert-manager
# ...
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
namespace: pangolin
spec:
interval: 10m
dependsOn:
- name: cert-manager
namespace: cert-manager
chart:
spec:
chart: pangolin
# ...
```
Flux ensures `cert-manager` reconciles before `pangolin`.
## Advanced: valuesFrom ConfigMap/Secret
Store values in ConfigMaps or Secrets, referenced from HelmRelease:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: pangolin-values
namespace: pangolin
data:
values.yaml: |
deployment:
type: controller
mode: multi
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
namespace: pangolin
spec:
interval: 10m
chart:
spec:
chart: pangolin
# ...
valuesFrom:
- kind: ConfigMap
name: pangolin-values
```
Flux extracts values from the ConfigMap and applies them to the HelmRelease.
## Troubleshooting Flux
### Check Flux components
```bash
kubectl get deployments -n flux-system
flux check --all-namespaces
```
### Check HelmRelease status
```bash
kubectl get helmrelease -n pangolin
kubectl describe helmrelease pangolin -n pangolin
kubectl get helmrelease pangolin -n pangolin -o yaml
```
### View reconciliation logs
```bash
flux logs --all-namespaces --follow
# Specific resource
kubectl logs -n pangolin deployment/helm-operator -f
```
### Manual reconciliation
```bash
flux reconcile helmrelease pangolin -n pangolin
flux reconcile kustomization production -n flux-system
```
### Suspend reconciliation
```bash
flux suspend helmrelease pangolin -n pangolin
```
### Resume reconciliation
```bash
flux resume helmrelease pangolin -n pangolin
```
## Multi-environment example
### Bootstrap multiple clusters
```bash
# Production cluster
flux bootstrap github \
--owner=my-org \
--repo=infrastructure \
--personal \
--path=clusters/production
# Staging cluster (from different checkout)
flux bootstrap github \
--owner=my-org \
--repo=infrastructure \
--personal \
--path=clusters/staging
```
Each cluster reconciles its own `clusters/*/` directory.
### Repository structure
```
clusters/
├── production/
│ ├── kustomization.yaml
│ └── pangolin/
│ ├── helmrepo.yaml
│ └── helmrelease.yaml (prod values)
├── staging/
│ ├── kustomization.yaml
│ └── pangolin/
│ ├── helmrepo.yaml
│ └── helmrelease.yaml (staging values)
└── dev/
├── kustomization.yaml
└── pangolin/
└── helmrelease.yaml (dev values)
```
Each environment's HelmRelease uses environment-specific values.
## Important notes
### CRD management
When using Flux with Helm charts that include CRDs:
```yaml
spec:
install:
crds: Create # Create CRDs on first install
upgrade:
crds: CreateReplace # Update CRDs on upgrade
```
### Namespace creation
Flux automatically creates namespaces if they don't exist. Ensure appropriate RBAC.
### GitOps best practices
- Use branches for different environments
- Protect production branches with review requirements
- Store secrets using sealed-secrets or external-secrets
- Track all changes in Git
- Use consistent naming conventions
## Next steps
<CardGroup cols={2}>
<Card title="GitOps Overview" href="/self-host/manual/kubernetes/gitops/overview" icon="code-branch" />
<Card title="Argo CD" href="/self-host/manual/kubernetes/gitops/argocd" icon="code-branch" />
<Card title="Pangolin Configuration" href="/self-host/manual/kubernetes/pangolin/configuration" icon="sliders" />
<Card title="Troubleshooting" href="/self-host/manual/kubernetes/pangolin/troubleshooting" icon="circle-question" />
</CardGroup>
@@ -0,0 +1,351 @@
---
title: "GitOps Overview"
description: "Git-driven Kubernetes deployments for Pangolin and Newt using Argo CD or Flux."
---
import PangolinCloudTocCta from "/snippets/pangolin-cloud-toc-cta.mdx";
<PangolinCloudTocCta />
GitOps is a declarative approach to infrastructure management where your Git repository is the single source of truth for cluster state. Changes go through Git; the GitOps tool automatically reconciles the cluster to match.
## What is GitOps?
GitOps reconciliation loop:
<Steps>
<Step title="Declare desired state in Git">
**Git repository** contains desired state (manifests, Helm values, Kustomize overlays).
</Step>
<Step title="GitOps controller watches source">
**GitOps tool** (Argo CD or Flux) watches the Git repository.
</Step>
<Step title="Detect changes and drift">
The controller detects new commits or drift between Git and the live cluster.
</Step>
<Step title="Reconcile cluster">
The controller syncs cluster state to match Git state.
</Step>
<Step title="Continuous convergence">
**Result**: Cluster stays aligned with the declared Git configuration.
</Step>
</Steps>
## Benefits
- **Version control**: All infrastructure changes tracked in Git
- **Audit trail**: See who changed what and when
- **Rollback**: Revert to previous state by reverting Git commits
- **Automation**: No manual `kubectl apply` commands needed
- **Drift detection**: Automatic alerts if cluster diverges from Git
## GitOps tools for Kubernetes
### Argo CD
- **UI**: Web-based dashboard for monitoring and manual syncs
- **Approach**: External reconciler (watches Git, applies to cluster)
- **Supports**: Helm charts, Kustomize overlays, raw YAML
- **Best for**: Teams who want GitOps with a UI, hybrid manual/automated workflows
**Use Argo CD if**:
- You want a visual dashboard
- You need frequent manual sync capabilities
- You're already using Argo CD for other workloads
See: [Argo CD Install Guide](/self-host/manual/kubernetes/gitops/argocd)
### Flux
- **CRDs**: Kubernetes-native Custom Resources (HelmRelease, Kustomization, GitRepository)
- **Approach**: Declarative reconciliation using Kubernetes resources
- **Supports**: Helm charts, Kustomize overlays, raw YAML, OCI registries
- **Best for**: Teams who want declarative Kubernetes-way GitOps, lightweight controllers
**Use Flux if**:
- You prefer Kubernetes-native CRDs
- You want a lightweight, modern GitOps tool
- You're already using Flux for other workloads
See: [Flux Install Guide](/self-host/manual/kubernetes/gitops/flux)
## Recommended repository structure
For multi-environment Pangolin/Newt deployments, organize your Git repository like this:
```
my-org/infrastructure/
├── clusters/
│ ├── production/
│ │ ├── pangolin/
│ │ │ ├── values.yaml
│ │ │ └── kustomization.yaml (if using Kustomize)
│ │ └── newt/
│ │ ├── values.yaml
│ │ └── kustomization.yaml
│ ├── staging/
│ │ ├── pangolin/
│ │ └── newt/
│ └── dev/
│ ├── pangolin/
│ └── newt/
├── apps/
│ ├── pangolin/
│ │ ├── helm/
│ │ │ ├── values-base.yaml
│ │ │ ├── values-prod.yaml
│ │ │ └── values-staging.yaml
│ │ └── kustomize/
│ │ ├── base/
│ │ └── overlays/
│ └── newt/
│ ├── helm/
│ └── kustomize/
└── .gitignore
```
**Pattern**:
- `clusters/` → environment-specific configuration
- `apps/` → shared, reusable application configuration
- Environment overlays layer on top of app definitions
## Secrets in GitOps
<Warning>
**Never commit plaintext secrets to Git.** Use secret management tools instead.
</Warning>
Options for managing secrets in GitOps:
### Sealed Secrets
- **Tool**: [sealed-secrets](https://github.com/bitnami-labs/sealed-secrets)
- **How**: Encrypt secrets with cluster-specific key; safe to commit encrypted secrets
- **Decrypt**: Only the cluster can decrypt (uses private key)
```bash
# Encrypt a secret
echo -n mypassword | kubeseal -f - > secret.yaml
# Git tracks encrypted secret.yaml
# Cluster auto-decrypts on apply
```
### External Secrets Operator
- **Tool**: [external-secrets](https://external-secrets.io/)
- **How**: Reference secrets stored in external vault (AWS Secrets Manager, Azure Key Vault, HashiCorp Vault)
- **Git**: Stores reference only, not secret values
```yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "https://vault.example.com"
```
### SOPS (Secrets Operations)
- **Tool**: [SOPS](https://github.com/mozilla/sops)
- **How**: Encrypt YAML files; decrypt at deploy time
- **Git**: Stores encrypted files
```bash
sops --encrypt secrets.yaml > secrets.enc.yaml
# Commit secrets.enc.yaml; tool decrypts on apply
```
### Cloud Provider Secrets
- **AWS**: Use AWS Secrets Manager or Parameter Store with IRSA (IAM Roles for Service Accounts)
- **Azure**: Use Azure Key Vault with pod identity
- **GCP**: Use Google Secret Manager with workload identity
<Tip>
Choose a secret management strategy **before** setting up GitOps. Seal secrets once; keep approach consistent.
</Tip>
## GitOps workflow example
### 1. Set up Git repository
```bash
git clone https://github.com/my-org/infrastructure.git
cd infrastructure
mkdir -p clusters/production/pangolin
cd clusters/production/pangolin
```
### 2. Create configuration
```bash
# values.yaml with Pangolin config
cat > values.yaml <<EOF
deployment:
type: controller
mode: multi
database:
mode: cloudnativepg
pangolin:
config:
app:
dashboard_url: https://pangolin.example.com
domains:
domain1:
base_domain: example.com
gerbil:
base_endpoint: vpn.example.com
EOF
git add values.yaml
git commit -m "Add production Pangolin config"
git push
```
### 3. Install GitOps tool
```bash
# For Argo CD
kubectl create namespace argocd
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd -n argocd
# For Flux
flux bootstrap github \
--owner=my-org \
--repo=infrastructure \
--personal \
--path=clusters/production
```
### 4. Create Application/HelmRelease
**With Argo CD**:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: pangolin
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/infrastructure
targetRevision: main
path: clusters/production/pangolin
helm:
values: values.yaml
destination:
server: https://kubernetes.default.svc
namespace: pangolin
syncPolicy:
automated:
prune: true
selfHeal: true
```
**With Flux**:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
namespace: pangolin
spec:
interval: 10m
chart:
spec:
chart: pangolin
sourceRef:
kind: HelmRepository
name: fossorial
namespace: flux-system
values:
deployment:
type: controller
mode: multi
```
### 5. Push to Git
```bash
git add pangolin-app.yaml
git commit -m "Add Argo CD Application for Pangolin"
git push
```
**Result**: GitOps tool automatically detects the new Application and begins reconciliation.
### 6. Monitor
**Argo CD**:
```bash
# Port-forward to UI
kubectl port-forward -n argocd svc/argocd-server 8080:443
# Visit https://localhost:8080
```
**Flux**:
```bash
# Check reconciliation status
flux get all
# View logs
flux logs --all-namespaces --follow
```
## Common use cases
### Multi-environment deployments
Use Git branches, directories, or environments to manage dev, staging, production:
```
clusters/dev/pangolin → helm values for dev
clusters/staging/pangolin → helm values for staging
clusters/production/pangolin → helm values for production
```
Each environment syncs independently.
### Automatic deployments on chart update
Flux or Argo CD can watch a Helm repository and auto-update when a new chart version is released:
```yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: pangolin
spec:
chart:
spec:
chart: pangolin
version: ">=0.1.0" # auto-upgrade to latest 0.1.x
```
### Drift detection and remediation
Argo CD and Flux both support continuous drift detection:
- **Argo CD**: Detects drift on demand or continuously; can auto-sync on drift
- **Flux**: Reconciles on interval; rolls back manual cluster changes
## Next steps
<CardGroup cols={2}>
<Card title="Argo CD Install" href="/self-host/manual/kubernetes/gitops/argocd" icon="code-branch" />
<Card title="Flux Install" href="/self-host/manual/kubernetes/gitops/flux" icon="code-branch" />
<Card title="Helm Quick-Start" href="/self-host/manual/kubernetes/helm" icon="box" />
<Card title="Kustomize Quick-Start" href="/self-host/manual/kubernetes/kustomize" icon="layer-group" />
</CardGroup>