Argo CD Configuration
Guide for setting up GitHub App integration and applications in Argo CD.
GitHub App Setup
1. Create GitHub App
Go to https://github.com/settings/apps/new (or org settings for org repos)
Basic Info:
- App name:
ArgoCD-<your-name>(e.g.,ArgoCD-losol) - Homepage URL:
https://argo.app.domain.no - Webhook: Uncheck "Active" (not needed for polling)
Permissions:
- Repository permissions → Contents: Read-only
- Repository permissions → Metadata: Read-only
Installation:
- Where can this app be installed: Only on this account
Click Create GitHub App
2. Generate Private Key
After creation:
- Note the App ID (shown at top of page)
- Scroll down to "Private keys"
- Click Generate a private key
- Save the downloaded
.pemfile securely
3. Install the App
- Go to https://github.com/settings/apps
- Click on your app
- Click Install App in sidebar
- Select your account/org
- Choose Only select repositories → select
eventuras - Click Install
- Note the Installation ID from the URL:
https://github.com/settings/installations/<ID>
4. Connect in Argo CD
- Log in to Argo CD: https://argo.app.domain.no
- Go to Settings → Repositories → Connect Repo
- Choose VIA GITHUB APP
- Fill in:
- Repository URL:
https://github.com/losol/eventuras - GitHub App ID: (from step 2)
- GitHub App Installation ID: (from step 3)
- GitHub App Private Key: (paste contents of
.pemfile)
- Repository URL:
- Click Connect
Creating Applications
In Argo CD UI:
-
Applications → New App
-
Fill in:
- Application Name:
<app>-<env>(e.g.,myapp-dev) - Project:
default - Sync Policy: Automatic (dev/staging) or Manual (prod)
- ✓ Prune Resources
- ✓ Self Heal
- Auto-Create Namespace: ✓
- Application Name:
-
Source:
- Repository URL:
https://github.com/losol/eventuras - Revision:
HEAD - Path:
apps/<app>/k8s/chart
- Repository URL:
-
Destination:
- Cluster URL:
https://kubernetes.default.svc - Namespace:
<app>-<env>
- Cluster URL:
-
Helm section - add environment-specific parameters (see each app's chart README)
-
Click Create
Application-specific Setup
See each application's Kubernetes deployment documentation for detailed setup instructions:
Secrets Setup
Before syncing applications, create required secrets in each namespace. See each application's k8s/README.md for specific secret requirements:
Generic Pattern
# Create namespacekubectl create namespace <app>-<env># Create secret with required valueskubectl create secret generic <app>-secrets -n <app>-<env> \--from-literal=KEY1='value1' \--from-literal=KEY2='value2'
Updating Secrets
To update a single secret value:
# Patch a single keykubectl patch secret <secret-name> -n <namespace> --type='json' \-p='[{"op": "replace", "path": "/data/<KEY>", "value": "'$(echo -n 'new-value' | base64)'"}]'
TLS Configuration
TLS is handled by a wildcard certificate (*.app.domain.no) in the traefik namespace.
- No per-app certificates needed
- No ReferenceGrants needed
- All HTTPRoutes use the
httpslistener automatically
See Kubernetes Setup for the infrastructure configuration.
Image Tagging Strategy
| Tag | Description | Used in |
|---|---|---|
edge | Every CI build from PR/branch | dev |
canary | CI build from main branch | staging |
v1.2.3 | Semantic version release | prod |
sha-abc123 | Specific commit | debugging |
Deployment Flow
- PR/branch push → CI builds and pushes
edgetag → dev auto-syncs - PR merged to main → CI builds and pushes
canarytag → staging auto-syncs - Release created → CI builds and pushes
v1.2.3tag → prod manual sync
Multi-Tenant Setup
For managing multiple environments and customer tenants, use the following pattern:
Namespace Strategy
Internal Eventuras environments:
eventuras-api-dev→ dev.api.eventuras.dev (auto-sync)eventuras-api-staging→ staging.api.eventuras.dev (auto-sync)eventuras-api-prod→ api.eventuras.no (manual sync)
Customer tenants:
<customer>→ api.customer.com (manual sync, separate project)- Example:
acmenamespace for ACME Corp customer
- Example:
AppProject Pattern
Create separate projects for isolation:
eventuras-internal project:
apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata:name: eventuras-internalnamespace: argocdspec:description: Eventuras internal applications (dev, staging, prod)sourceRepos:- https://github.com/losol/eventurasdestinations:- namespace: 'eventuras-*'server: https://kubernetes.default.svcclusterResourceWhitelist:- group: ''kind: NamespacenamespaceResourceWhitelist:- group: '*'kind: '*'
Customer project (example):
apiVersion: argoproj.io/v1alpha1kind: AppProjectmetadata:name: acmenamespace: argocdlabels:eventuras.io/customer: acmespec:description: ACME Corp customer applicationssourceRepos:- https://github.com/losol/eventurasdestinations:- namespace: acmeserver: https://kubernetes.default.svcclusterResourceWhitelist:- group: ''kind: NamespacenamespaceResourceWhitelist:- group: '*'kind: '*'
Application Examples
Development environment:
apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata:name: eventuras-api-devnamespace: argocdlabels:app.kubernetes.io/name: eventuras-apieventuras.io/environment: deveventuras.io/customer: internalspec:project: eventuras-internalsource:repoURL: https://github.com/losol/eventurastargetRevision: mainpath: apps/api/k8s/charthelm:parameters:- name: image.registryvalue: docker.io- name: image.repositoryvalue: losolio/eventuras-api- name: image.tagvalue: main-latest- name: dns.domainvalue: eventuras.dev- name: dns.appNamevalue: api- name: dns.prefixvalue: dev.destination:server: https://kubernetes.default.svcnamespace: eventuras-api-devsyncPolicy:automated:prune: trueselfHeal: truesyncOptions:- CreateNamespace=true
Customer production:
apiVersion: argoproj.io/v1alpha1kind: Applicationmetadata:name: acme-apinamespace: argocdlabels:app.kubernetes.io/name: eventuras-apieventuras.io/environment: productioneventuras.io/customer: acmeeventuras.io/tenant: acmeannotations:description: "ACME Corp Production API"spec:project: acmesource:repoURL: https://github.com/losol/eventurastargetRevision: mainpath: apps/api/k8s/charthelm:parameters:- name: image.registryvalue: docker.io- name: image.repositoryvalue: losolio/eventuras-api- name: image.tagvalue: v1.0.0 # Specific stable version- name: dns.domainvalue: acme.example.com- name: dns.appNamevalue: api- name: dns.prefixvalue: ""# Customer-specific resource overrides- name: resources.requests.memoryvalue: 512Mi- name: resources.limits.memoryvalue: 2Gidestination:server: https://kubernetes.default.svcnamespace: acmesyncPolicy:# Manual sync for customer productionsyncOptions:- CreateNamespace=true
Identifying Customer Tenants in Argo CD
Use labels for clear identification:
labels:eventuras.io/customer: acme # Customer identifiereventuras.io/tenant: acme # Tenant (same as customer for single-tenant)eventuras.io/environment: production # Always production for customers
Filter in Argo CD UI:
- Project:
acme - Label:
eventuras.io/customer=acme - Label:
eventuras.io/environment=production
Customer-Specific Configuration
Separate Database: Each customer should have their own database instance. Configure connection string in namespace secrets:
kubectl create secret generic eventuras-api-secrets -n acme \--from-literal=ConnectionStrings__DefaultConnection="Host=acme-db;Database=acme;..."
Resource Allocation: Customer production typically needs more resources than dev/staging:
- Memory: 512Mi - 2Gi (vs 256Mi - 1Gi for dev)
- CPU: 200m - 1000m (vs 100m - 500m for dev)
Monitoring: Configure customer-specific monitoring and alerts in the Application annotations:
annotations:notifications.argoproj.io/subscribe.on-sync-succeeded.slack: acme-deploymentsnotifications.argoproj.io/subscribe.on-sync-failed.slack: acme-alerts
Best Practices
For Internal Environments (dev/staging)
- ✅ Use auto-sync for rapid iteration
- ✅ Use
mainbranch as targetRevision - ✅ Lower resource limits to save costs
- ✅ Shared infrastructure (databases, caches)
For Production (internal)
- ⚠️ Manual sync to control deployments
- ⚠️ Use specific version tags (
v1.2.3) - ⚠️ Higher resource limits for stability
- ⚠️ Production-grade infrastructure
For Customer Tenants
- 🔒 Always manual sync - no auto-deploy
- 🔒 Dedicated AppProject per customer
- 🔒 Separate namespace:
<customer> - 🔒 Separate database instance
- 🔒 Specific stable version tags only
- 🔒 Customer-specific monitoring/alerts
- 🔒 Higher resource allocations
- 🔒 Use labels:
eventuras.io/customer=<name>
Sync Windows (Optional)
For customer production, consider restricting sync times:
spec:syncWindows:- kind: allowschedule: '0 9-17 * * 1-5' # Business hours onlyduration: 8happlications:- '*'manualSync: true
Updating Customer Production
# Via Argo CD UI:# 1. Filter by project: acme# 2. Click "acme-api"# 3. Update image tag in parameters# 4. Click "Sync" and review changes# 5. Confirm# Via kubectl (update image tag):kubectl patch application acme-api -n argocd --type merge \-p '{"spec":{"source":{"helm":{"parameters":[{"name":"image.tag","value":"v1.2.3"}]}}}}'# Then sync:argocd app sync acme-api --prune
Adding New Customers
- Create AppProject:
kubectl apply -f customer-project.yaml - Create Application:
kubectl apply -f customer-app.yaml - Create namespace secrets:
kubectl create secret generic eventuras-api-secrets -n <customer> - Sync application:
argocd app sync <customer>-api - Verify:
kubectl get pods -n <customer> - Release created → CI builds and pushes
v1.2.3tag → prod manual sync