How to Set Up ArgoCD for GitOps on RHEL 7
GitOps is an operational model in which the desired state of your infrastructure and applications is stored declaratively in a Git repository, and an automated agent continuously reconciles that desired state with the actual running state in your Kubernetes cluster. ArgoCD is the leading open-source GitOps controller for Kubernetes, providing a powerful web UI, CLI, and API for managing deployments. On RHEL 7 — a common OS for enterprise Kubernetes nodes and management hosts — ArgoCD enables engineering teams to turn Git merges into deployments without manual kubectl apply commands. This tutorial covers installing ArgoCD into Kubernetes, connecting Git repositories, defining Application manifests, using sync wave annotations, configuring automated sync policies, the app-of-apps pattern, and operating ArgoCD from the command line.
Prerequisites
- RHEL 7 host with
kubectlconfigured to reach a Kubernetes cluster (v1.19+) - Sufficient cluster permissions to create namespaces, CRDs, RBAC resources, and deployments
- A Git repository (GitHub, GitLab, Bitbucket, or self-hosted Gitea) accessible from the cluster
curlinstalled on the RHEL 7 host for downloading the ArgoCD CLI- Optional: an Ingress controller or LoadBalancer to expose the ArgoCD UI externally
Step 1: Installing ArgoCD into Kubernetes
ArgoCD is deployed as a set of Kubernetes workloads inside its own namespace. The project provides an official installation manifest that creates all required CRDs, RBAC, services, and deployments in a single apply:
# Create the ArgoCD namespace
kubectl create namespace argocd
# Apply the official installation manifest
kubectl apply -n argocd -f
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait until all pods are running
kubectl rollout status deployment argocd-server -n argocd --timeout=300s
kubectl get pods -n argocd
Expected pods once installation is complete:
argocd-application-controller-0
argocd-applicationset-controller-xxxxxxxxx
argocd-dex-server-xxxxxxxxx
argocd-notifications-controller-xxxxxxxxx
argocd-redis-xxxxxxxxx
argocd-repo-server-xxxxxxxxx
argocd-server-xxxxxxxxx
Step 2: Accessing the ArgoCD API Server
By default the argocd-server service is of type ClusterIP. You have several options to expose it:
# Option 1: Port-forward for local testing
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Option 2: Change service type to LoadBalancer
kubectl patch svc argocd-server -n argocd
-p '{"spec": {"type": "LoadBalancer"}}'
# Option 3: Create an Ingress resource (requires ingress controller)
cat >>/tmp/argocd-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-server-ingress
namespace: argocd
annotations:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
ingressClassName: nginx
rules:
- host: argocd.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
EOF
kubectl apply -f /tmp/argocd-ingress.yaml
Retrieve the initial admin password (it is stored as a Kubernetes secret and must be rotated after first login):
kubectl -n argocd get secret argocd-initial-admin-secret
-o jsonpath="{.data.password}" | base64 -d; echo
Step 3: Installing the ArgoCD CLI on RHEL 7
# Download the latest stable ArgoCD CLI binary
ARGOCD_VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest
| grep tag_name | cut -d '"' -f 4)
curl -sSL -o /usr/local/bin/argocd
"https://github.com/argoproj/argo-cd/releases/download/${ARGOCD_VERSION}/argocd-linux-amd64"
chmod +x /usr/local/bin/argocd
argocd version --client
Log in to the ArgoCD server (replace the address with your actual endpoint):
# If using port-forward, the server is localhost:8080
argocd login localhost:8080
--username admin
--password "$(kubectl -n argocd get secret argocd-initial-admin-secret
-o jsonpath='{.data.password}' | base64 -d)"
--insecure
# Update the admin password immediately
argocd account update-password
Step 4: Connecting a Git Repository
ArgoCD needs read access to your Git repository. For public repositories no credentials are required. For private repositories you must provide either HTTPS credentials or an SSH key.
Option A: HTTPS with username/token
argocd repo add https://github.com/your-org/your-app-config.git
--username your-github-username
--password your-personal-access-token
Option B: SSH key authentication
# Generate an SSH key pair (do NOT set a passphrase for automation)
ssh-keygen -t ed25519 -C "argocd@cluster" -f ~/.ssh/argocd_deploy_key -N ""
# Add the public key as a deploy key in your Git repository UI
cat ~/.ssh/argocd_deploy_key.pub
# Register the private key with ArgoCD
argocd repo add [email protected]:your-org/your-app-config.git
--ssh-private-key-path ~/.ssh/argocd_deploy_key
Verify the repository shows as Successful:
argocd repo list
Step 5: Creating an Application Manifest
An ArgoCD Application is a Kubernetes custom resource that tells ArgoCD where to find source manifests (Git) and where to deploy them (Kubernetes cluster and namespace). Create the manifest file:
cat > /tmp/my-app.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
labels:
app.kubernetes.io/name: my-app
environment: production
spec:
project: default
source:
repoURL: https://github.com/your-org/your-app-config.git
targetRevision: main
path: apps/my-app
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF
kubectl apply -f /tmp/my-app.yaml
Key fields in the Application spec:
source.repoURL— the Git repository URLsource.targetRevision— branch, tag, or commit SHA to tracksource.path— directory within the repository containing Kubernetes manifestsdestination.server— Kubernetes API server URL (https://kubernetes.default.svcfor in-cluster)destination.namespace— target namespace for deployed resources
Step 6: Using Sync Wave Annotations
When an Application contains multiple resources, ArgoCD applies them concurrently by default. Sync waves let you control the order, ensuring, for example, that a database is ready before the application that depends on it:
# database.yaml — deploy in wave 0 (first)
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
annotations:
argocd.argoproj.io/sync-wave: "0"
spec:
# ...
---
# migration-job.yaml — run migrations in wave 1 (after DB is up)
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
# ...
---
# app.yaml — deploy the application in wave 2 (after migrations)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "2"
spec:
# ...
Resources within the same wave are applied together. ArgoCD waits for all resources in wave N to be healthy before moving to wave N+1.
Step 7: Configuring Automated Sync Policy
By default ArgoCD detects drift (differences between Git and live state) but does not automatically apply changes. Enable automated sync for fully hands-off GitOps deployments:
cat > /tmp/my-app-autosync.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/your-app-config.git
targetRevision: main
path: apps/my-app
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Delete resources removed from Git
selfHeal: true # Re-apply if someone manually changes the cluster
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- ApplyOutOfSyncOnly=true
EOF
kubectl apply -f /tmp/my-app-autosync.yaml
With prune: true and selfHeal: true, ArgoCD becomes the single source of truth: any manual cluster change will be reverted, and any Git deletion will be propagated to the cluster.
Step 8: The App-of-Apps Pattern
For managing many applications at scale, the app-of-apps pattern uses a parent ArgoCD Application whose source repository contains child Application manifests. A single sync of the parent bootstraps the entire platform:
# Repository structure:
# platform/
# ├── Chart.yaml (optional, if using Helm)
# ├── apps/
# │ ├── nginx-ingress.yaml (Application CRD)
# │ ├── cert-manager.yaml (Application CRD)
# │ ├── prometheus.yaml (Application CRD)
# │ └── my-app.yaml (Application CRD)
# Parent application pointing at the apps/ directory
cat > /tmp/platform-app.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/platform-config.git
targetRevision: main
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
kubectl apply -f /tmp/platform-app.yaml
Step 9: Operating ArgoCD with the CLI
# List all applications
argocd app list
# Get detailed status of a specific app
argocd app get my-app
# Manually trigger a sync
argocd app sync my-app
# Sync and wait for completion
argocd app sync my-app --timeout 300
# View live resource tree
argocd app resources my-app
# Show diff between Git desired state and live state
argocd app diff my-app
# Hard refresh (bypass cache and re-query Git)
argocd app get my-app --hard-refresh
# Rollback to a previous revision
argocd app history my-app
argocd app rollback my-app 3
ArgoCD transforms Kubernetes operations on RHEL 7 from a manual, error-prone process into a reliable, auditable, Git-driven workflow. By storing every application configuration in version control and letting ArgoCD reconcile live state against that source of truth, teams gain an automatic audit trail, easy rollback, environment promotion via branch or tag targeting, and the confidence that what you see in Git is exactly what is running in your cluster. Combined with the app-of-apps pattern and sync waves, ArgoCD scales from managing a handful of microservices to governing an entire enterprise platform from a single Git repository.