Core
Overview
The Core stack provides foundational infrastructure components required by all other Edge Developer Platform stacks. It establishes the base layer for continuous deployment, database services, and centralized authentication, enabling a secure, scalable platform architecture.
The Core stack deploys ArgoCD for GitOps orchestration, CloudNativePG for PostgreSQL database management, and Dex for OpenID Connect single sign-on capabilities.
Key Features
- GitOps Continuous Deployment: ArgoCD manages declarative infrastructure and application deployments
- Database Operator: CloudNativePG provides enterprise-grade PostgreSQL clusters for platform services
- Single Sign-On: Dex offers centralized OIDC authentication across platform components
- Automated Synchronization: Self-healing deployments with automatic drift correction
- Role-Based Access Control: Integrated RBAC for secure platform administration
- TLS Certificate Management: Automated certificate provisioning and renewal
Repository
Code: Core Stack Templates
Documentation:
Getting Started
Prerequisites
- Kubernetes cluster (1.24+)
- kubectl configured with cluster access
- Ingress controller (nginx recommended)
- cert-manager for TLS certificate management
- Domain names configured for platform services
Quick Start
The Core stack is deployed as the foundation of the EDP installation:
Trigger Deploy Pipeline
- Go to Infra Deploy Pipeline
- Click on Run workflow
- Enter a name in “Select environment directory to deploy”. This must be DNS Compatible. (if you enter
test-methen domains will beargocd.test-me.t09.de,dex.test-me.t09.de) - Execute workflow
ArgoCD Bootstrap The deployment automatically provisions:
- ArgoCD control plane in
argocdnamespace - CloudNativePG operator in
cloudnative-pgnamespace - Dex identity provider in
dexnamespace - Ingress configurations with TLS certificates
- OIDC authentication integration
- ArgoCD control plane in
Verification
Verify the Core stack deployment:
# Check ArgoCD installation
kubectl get application -n argocd
kubectl get pods -n argocd
# Verify CloudNativePG operator
kubectl get pods -n cloudnative-pg
kubectl get crd | grep cnpg.io
# Check Dex deployment
kubectl get pods -n dex
kubectl get ingress -n dex
# Verify ingress configurations
kubectl get ingress -n argocd
Access ArgoCD at https://argocd.{DOMAIN} and authenticate via Dex SSO. Or use username admin and the secret inside of kubernetes argocd/argocd-initial-admin-secret as password kubectl get secret -n argocd argocd-initial-admin-secret -ojson | jq -r .data.password | base64 -d.
Architecture
Component Architecture
The Core stack establishes a three-tier foundation:
ArgoCD Control Plane:
- Application management and GitOps reconciliation
- Multi-repository tracking with automated sync
- Resource health monitoring and drift detection
- Integrated RBAC with SSO authentication
CloudNativePG Operator:
- PostgreSQL cluster lifecycle management
- Automated backup and recovery
- High availability and failover
- Storage provisioning via CSI drivers
Dex Identity Provider:
- OpenID Connect authentication service
- Multiple connector support (Forgejo/Gitea, LDAP, SAML)
- Static client registration for platform services
- Token issuance and validation
Networking
Ingress Architecture:
- nginx ingress controller for external access
- TLS termination with cert-manager integration
- Domain-based routing for platform services
Kubernetes Services:
- Internal service communication via ClusterIP
- DNS-based service discovery
- Network policies for security segmentation
Configuration
ArgoCD Configuration
Deployed via Helm chart v9.1.5 with custom values in stacks/core/argocd/values.yaml:
OIDC Authentication:
configs:
cm:
url: "https://{DOMAIN_ARGOCD}"
oidc.config: |
name: Forgejo
issuer: https://{DOMAIN_DEX}
clientID: controller-argocd-dex
clientSecret: $dex-controller-argocd-dex:dex-controller-argocd-dex
requestedScopes: ["openid", "profile", "email", "groups"]
RBAC Policy:
policy.csv: |
g, DevFW, role:admin
Server Settings:
- Insecure mode enabled (TLS handled by ingress)
- Annotation-based resource tracking
- 60-second reconciliation timeout
- Resource exclusions for ProviderConfigUsage and CiliumIdentity
CloudNativePG Configuration
Deployed via Helm chart v0.26.1 with values in stacks/core/cloudnative-pg/values.yaml:
Operator Settings:
- Namespace:
cloudnative-pg - Automated database cluster provisioning
- Custom resource definitions for Cluster, Database, and Pooler resources
Storage Configuration:
- Uses
csi-diskstorage class by default - PVC provisioning for PostgreSQL data
- Backup storage integration (S3-compatible)
Dex Configuration
Deployed via Helm chart v0.23.0 with values in stacks/core/dex/values.yaml:
Issuer Configuration:
config:
issuer: https://{DOMAIN_DEX}
storage:
type: memory # Use persistent storage for production
oauth2:
skipApprovalScreen: true
alwaysShowLoginScreen: false
Forgejo Connector:
connectors:
- type: gitea
id: forgejo
name: Forgejo
config:
clientID: $FORGEJO_CLIENT_ID
clientSecret: $FORGEJO_CLIENT_SECRET
redirectURI: https://{DOMAIN_DEX}/callback
baseURL: https://edp.buildth.ing
orgs:
- name: DevFW
Static OAuth2 Clients:
- ArgoCD:
controller-argocd-dex - Grafana:
controller-grafana-dex
Environment Variables
Core stack services use the following environment variables:
Domain Configuration:
DOMAIN_ARGOCD: ArgoCD web interface URLDOMAIN_DEX: Dex authentication service URLDOMAIN_GITEA: Forgejo/Gitea repository URLDOMAIN_GRAFANA: Grafana observability dashboard URL
Repository Configuration:
CLIENT_REPO_ID: Repository identifier for stack configurationsCLIENT_REPO_DOMAIN: Git repository domainCLIENT_REPO_ORG_NAME: Organization name for stack instances
Usage Examples
Managing Applications with ArgoCD
Access and manage applications through ArgoCD:
# Login to ArgoCD CLI
argocd login argocd.${DOMAIN} --sso
# List all applications
argocd app list
# Get application status
argocd app get coder
# Sync application manually
argocd app sync coder
# View application logs
argocd app logs coder
# Diff application state
argocd app diff coder
Creating a PostgreSQL Database
Deploy a PostgreSQL cluster using CloudNativePG:
# database-cluster.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: app-db
namespace: my-app
spec:
instances: 3
storage:
size: 20Gi
storageClass: csi-disk
postgresql:
parameters:
max_connections: "100"
shared_buffers: "256MB"
bootstrap:
initdb:
database: appdb
owner: appuser
Apply the configuration:
kubectl apply -f database-cluster.yaml
# Check cluster status
kubectl get cluster app-db -n my-app
kubectl get pods -n my-app -l cnpg.io/cluster=app-db
# Get connection credentials
kubectl get secret app-db-app -n my-app -o jsonpath='{.data.password}' | base64 -d
Configuring SSO for Applications
Add OAuth2 applications to Dex for SSO integration:
# Add to dex values.yaml
staticClients:
- id: my-app-client
redirectURIs:
- 'https://myapp.{DOMAIN}/callback'
name: 'My Application'
secretEnv: MY_APP_CLIENT_SECRET
Configure the application to use Dex:
# Application OIDC configuration
OIDC_ISSUER=https://dex.${DOMAIN}
OIDC_CLIENT_ID=my-app-client
OIDC_CLIENT_SECRET=${MY_APP_CLIENT_SECRET}
OIDC_REDIRECT_URI=https://myapp.${DOMAIN}/callback
Deploying Applications via ArgoCD
Create an ArgoCD Application manifest:
# my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: 'https://github.com/myorg/my-app'
targetRevision: main
path: k8s
destination:
server: 'https://kubernetes.default.svc'
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Push it to stacks instances to be picked up by argo
Integration Points
- All Stacks: Core stack is a prerequisite for all other EDP stacks
- OTC Stack: Provides ingress-nginx and cert-manager dependencies
- Coder Stack: Uses CloudNativePG for workspace database management
- Forgejo Stack: Integrates with Dex for SSO and ArgoCD for deployment
- Observability Stack: Uses Dex for Grafana authentication and ArgoCD for deployment
- Provider Stack: Deploys Terraform providers via ArgoCD
Troubleshooting
ArgoCD Not Accessible
Problem: Cannot access ArgoCD web interface
Solution:
Verify ingress configuration:
kubectl get ingress -n argocd kubectl describe ingress -n argocdCheck ArgoCD server status:
kubectl get pods -n argocd kubectl logs -n argocd -l app.kubernetes.io/name=argocd-serverVerify TLS certificate:
kubectl get certificate -n argocd kubectl describe certificate -n argocdTest DNS resolution:
nslookup argocd.${DOMAIN}
Dex Authentication Failing
Problem: SSO login fails or redirects incorrectly
Solution:
Check Dex logs:
kubectl logs -n dex -l app.kubernetes.io/name=dexVerify Forgejo connector configuration:
kubectl get secret -n dex kubectl get configmap -n dex dex -o yamlTest Dex issuer endpoint:
curl https://dex.${DOMAIN}/.well-known/openid-configurationVerify OAuth2 client credentials match in both Dex and consuming application
CloudNativePG Operator Not Running
Problem: PostgreSQL clusters fail to provision
Solution:
Check operator status:
kubectl get pods -n cloudnative-pg kubectl logs -n cloudnative-pg -l app.kubernetes.io/name=cloudnative-pgVerify CRDs are installed:
kubectl get crd | grep cnpg.io kubectl describe crd clusters.postgresql.cnpg.ioCheck operator logs for errors:
kubectl logs -n cloudnative-pg -l app.kubernetes.io/name=cloudnative-pg --tail=100
Application Sync Failures
Problem: ArgoCD applications remain out of sync or fail to deploy
Solution:
Check application status:
argocd app get <app-name> kubectl describe application <app-name> -n argocdReview sync operation logs:
argocd app logs <app-name>Verify repository access:
argocd repo list argocd repo get <repo-url>Check for resource conflicts or missing dependencies:
kubectl get events -n <app-namespace> --sort-by='.lastTimestamp'
Database Connection Issues
Problem: Applications cannot connect to CloudNativePG databases
Solution:
Verify cluster is ready:
kubectl get cluster <cluster-name> -n <namespace> kubectl describe cluster <cluster-name> -n <namespace>Check database credentials secret:
kubectl get secret <cluster-name>-app -n <namespace> kubectl get secret <cluster-name>-app -n <namespace> -o yamlTest connection from a pod:
kubectl run -it --rm psql-test --image=postgres:16 --restart=Never -- \ psql "$(kubectl get secret <cluster-name>-app -n <namespace> -o jsonpath='{.data.uri}' | base64 -d)"Review PostgreSQL logs:
kubectl logs -n <namespace> <cluster-name>-1