dot CMS

Managing dotCMS Helm Deployments with GitOps

Managing dotCMS Helm Deployments with GitOps
Daniel

Daniel Colina

Daniel

Share this article on:

In our previous post, How to Deploy dotCMS Using Helm Charts on Kubernetes – A Step-by-Step Guide, we walked through the basics of deploying dotCMS using Helm on a local Kubernetes cluster. That guide covered how to get dotCMS up and running quickly with a straightforward setup.

In this follow-up, we take a step further into GitOps by introducing ArgoCD, a continuous delivery tool designed for Kubernetes. While Helm packages and templates your application, ArgoCD continuously ensures that your cluster matches the desired state stored in Git. Together, Helm and ArgoCD provide a powerful, automated, and GitOps-friendly workflow for managing dotCMS deployments.


What is ArgoCD?

ArgoCD is a declarative GitOps continuous delivery tool for Kubernetes. It continuously monitors your Git repositories and ensures that what’s running in your cluster matches what’s defined there.

Instead of manually applying YAML files or running helm install, ArgoCD automatically reconciles your environment whenever changes are committed to Git.

Key features include:

  • Applications as code: Deployments are defined declaratively as Kubernetes CRDs.

  • Automated sync: Changes pushed to Git are reflected automatically in the cluster.

  • Health & drift detection: Monitors resource health and reverts unexpected changes.

  • Auditability: Every change is traceable through Git history.


Why Use ArgoCD with dotCMS?

Deploying dotCMS via Helm already simplifies packaging and configuration. Adding ArgoCD brings consistency, automation, and transparency:

  • A visual dashboard to monitor the health and sync status of dotCMS over time.

  • Version-controlled configurations being the single source of truth.

  • Rapid and safe updates: push a change in Git (e.g. bump version), ArgoCD picks it up.

  • Easy rollbacks by reverting Git commits.

  • Stronger audit trails and consistency across environments (dev, staging, prod).

Also, dotCMS publishes stable and unique Docker image tags (for example, dotcms/dotcms:latest or dotcms/dotcms:<release-number>) which makes version upgrades clean.


Technical Specifications for Local Deployment (Assumptions)

These are the assumptions for the examples in this post:

  • Local Kubernetes cluster via Docker Desktop (macOS or similar).

  • kubectl and helm already installed and working.

  • Access to ArgoCD (you’ll install it).

  • Git repository (public or private) for storing Helm chart configuration (values, etc.) for dotCMS.


Step-by-Step Example: Deploy dotCMS with ArgoCD

Let’s walk through setting up ArgoCD and deploying dotCMS via its Helm chart.

Step 1: Install ArgoCD

This installs the ArgoCD controllers, API server and CRDs via the official Helm chart.

helm install argocd argo/argo-cd -n argocd --create-namespace

Step 2: Access the ArgoCD UI

Forward the ArgoCD server port:

kubectl port-forward svc/argocd-server -n argocd 8080:443

Now open https://localhost:8080.

firstimage.png

Step 3: Login to ArgoCD

Retrieve the initial admin password:

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

Username: admin
Password: the decoded value above.

secondimage.png

Organizing Your dotCMS Helm Values

Rather than embedding Helm values directly inside your Application definition, it’s a better GitOps practice to store your values.yaml files in a dedicated configuration repository.

This separation keeps the Helm chart immutable and lets you version and promote configurations easily across environments.

Recommended structure:

dotcms-gitops-argocd/
└── environments/
    ├── dev/
    │   └── values.yaml
    ├── staging/
    │   └── values.yaml
    └── prod/
        └── values.yaml

Example values.yaml (dev):

# dotCMS Development Environment Configuration
# This file contains environment-specific values for dotCMS deployment
#
# Note: Database secrets are preserved across deployments (prune: false)
# to maintain compatibility with the persistent PostgreSQL instance

# Use the latest stable image for development
repository: dotcms/dotcms
tag: "25.09.18-1"

# Single replica for development
replicas: 1

# Reduced resources for development
resources:
  requests:
    cpu: "500m"
    memory: "2Gi"
  limits:
    cpu: "1"
    memory: "3Gi"

# Enable local services (database, opensearch, redis)
database:
  local:
    enabled: true

opensearch:
  local:
    enabled: true

redis:
  local:
    enabled: true

# Ingress configuration for local development
ingress:
  host: "dev.dotcms.local"
  hostSuffix: "dotcms.local"
  type: "nginx"

# Enable management port for health checks
management:
  enabled: true
  port: 8090

# Enable Prometheus metrics
prometheus:
  enabled: true
# Force pod restart with annotation
podAnnotations:
  restart: "2025-09-22-17-50"

This way, any update (e.g., changing the dotCMS version tag) is committed and version-controlled in Git.


Step 4: Creating the ArgoCD Application for dotCMS

With ArgoCD ≥ 2.6, you can use multi-source applications:

  • One source points to the official dotCMS Helm chart.

  • Another source points to your repo containing the values.yaml.

Here’s an example Application manifest:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: dotcms-dev
  namespace: argocd
spec:
  project: default
  sources:
    - repoURL: https://dotcms.github.io/helm-charts/
      chart: dotcms
      targetRevision: 1.0.34
      helm:
        valueFiles:
          - $values/dotcms-gitops-argocd/environments/dev/values.yaml
    - repoURL: https://github.com/dotCMS/examples.git
      targetRevision: main
      ref: values
  destination:
    server: https://kubernetes.default.svc
    namespace: dotcms-dev
 syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - RespectIgnoreDifferences=true

  # Ignore database secrets to prevent password regeneration on re-sync
  # This is critical for stateful databases that persist credentials in PVCs
  # Without this, ArgoCD regenerates random passwords that don't match the DB
  ignoreDifferences:
    - group: ""
      kind: Secret
      name: corp-dotcms-dev-localsecret-prod-database
      jsonPointers:
        - /data/password
        - /data/username
    - group: ""
      kind: Secret
      name: corp-dotcms-dev-localsecret-db-local-admin
      jsonPointers:
        - /data/password
        - /data/username

Why ignoreDifferences for dotcms local databases: When using local PostgreSQL with persistent volumes (PVCs), the database credentials are initialized once and stored in the persistent storage. On subsequent ArgoCD syncs, Helm regenerates secrets with new random passwords, but the database continues using the original credentials stored in the PVC. This mismatch causes authentication failures. By using ignoreDifferences, ArgoCD preserves the original secret values across deployments, maintaining consistency with the persisted database credentials. This issue doesn't occur with external databases where credentials are managed outside the Kubernetes cluster and remain static across deployments.

Apply the Application:

kubectl apply -f dotcms-application.yaml

ArgoCD now deploys dotCMS using the Helm chart and the values defined in your Git repo.

Watch the Sync in Action

ArgoCD automatically deploys dotCMS via Helm. From the UI, you’ll see your dotCMS application, its sync status, and the health of each Kubernetes object.

thirdimage.png

We can also see the docker image deployed.

fourthimage.png


Step 5: Upgrading dotCMS Version via Git

Here’s a more concrete illustration of how you can change your dotCMS version and let ArgoCD do the rest.

Change the image tag in your repo

In environments/dev/values.yaml:

image:
  repository: dotcms/dotcms
  tag: "25.09.18-01"

You want to upgrade to a newer (stable) version, e.g.:

image:
  repository: dotcms/dotcms
  tag: "latest" # or "25.10.20-01" (if available) or any unique/stable 

Commit and push

git add environments/dev/values.yaml
git commit -m "Upgrade dotCMS to 25.10.20-01"
git push

ArgoCD Detects and Syncs

  • ArgoCD monitors the Git repo, detects the new commit.

  • Marks the Application as OutOfSync.

  • Because syncPolicy.automated.selfHeal is enabled, it starts the sync process.

  • Kubernetes deployment will roll out new pods with dotcms/dotcms:25.10.20-01 (or the version you specified).

  • Old pods are terminated once new ones are healthy.

fifthimage.png

View Progress in the ArgoCD Dashboard

  • Watch for status to move from OutOfSync → Synced.

  • Check health status (should become Healthy).

  • Check the changes you made before (image tag: 25.10.20-01)

  • Optionally inspect events/logs to see rollout, image pull, etc.

sixthimage.png

Status synced and healthy.

seventhimage.png

New image deployed.


Observability and Drift Detection

  • Dashboard gives you real-time view: sync status, health of Deployments, Services, etc.

  • Drift detection: when someone manually applies changes outside Git, ArgoCD will show the divergence.

  • Rollbacks are easy: just revert the Git change (e.g. version tag) and ArgoCD syncs back.

  • You can manage multiple environments by having different branches or directories in Git, each with different values files (e.g. dev vs prod).


Best Practices (Related to ArgoCD + dotCMS)

Here are some tips to make your setup more robust:

  • Always use immutable image tags (not just latest) for production—unique tags reduce the risk of unexpected changes.

  • Separate configuration and application code repos (or separate directories) to keep things clean.

  • Keep your Helm chart versions and dotCMS image versions in your Git repo, so everything that defines your infrastructure and app state is versioned.

  • Enable automated sync and self-heal cautiously; test in dev first.

  • Monitor resource usage; dotCMS can need non-trivial CPU/RAM depending on usage.


Conclusion

With ArgoCD, you move from manual or semi-manual deployments to a fully automated GitOps workflow. For dotCMS teams, this means more consistency, faster updates, and clearer visibility into what is running in each environment. By storing deployments in Git and letting ArgoCD handle the syncs, you reduce the chance of drift and deployment surprises.

If you enjoyed the first post (How to Deploy dotCMS Using Helm Charts on Kubernetes – A Step-by-Step Guide) this deeper dive into ArgoCD shows how to build on that foundation.


References