+
nim
sublime
+
+
delphi
+
vb
+
mysql
adonis
+
+
+
+
azure
terraform
+
+
suse
+
+
+
+
โˆˆ
!!
+
eslint
+
+
+
notepad++
+=
centos
react
npm
+
+
+
k8s
css
+
+
+
+
tcl
+
+
+
+
gcp
+
numpy
supabase
+
+
mint
pip
+
+
+
+
marko
+
preact
+
ractive
+
+
+
+
+
+
->
+
cypress
+
+
+
+
0x
+
+
clickhouse
surrealdb
htmx
prometheus
+
+
+
Back to Blog
๐Ÿš€ AlmaLinux GitLab CI/CD: Complete DevOps Pipeline Guide
AlmaLinux GitLab CI/CD

๐Ÿš€ AlmaLinux GitLab CI/CD: Complete DevOps Pipeline Guide

Published Sep 18, 2025

Build enterprise DevOps pipelines on AlmaLinux with GitLab! Master CI/CD automation, Docker integration, Kubernetes deployments, and GitOps workflows. Complete guide for modern software delivery.

69 min read
0 views
Table of Contents

๐Ÿš€ AlmaLinux GitLab CI/CD: Complete DevOps Pipeline Guide

Welcome to the world of automated software delivery on AlmaLinux! ๐ŸŽ‰ Whether youโ€™re shipping code hourly, managing complex deployments, or building a DevOps culture, this comprehensive guide will transform you into a CI/CD master who can build pipelines that deploy code from commit to production automatically! ๐Ÿ”„

GitLab on AlmaLinux provides everything you need for modern DevOps โ€“ source control, CI/CD, container registry, and Kubernetes integration all in one platform! Letโ€™s build deployment pipelines that make releases boring (in the best way)! ๐Ÿ’ช

๐Ÿค” Why is GitLab CI/CD Important?

Imagine deploying to production 100 times a day with zero fear โ€“ thatโ€™s the power of CI/CD! ๐ŸŽฏ Hereโ€™s why mastering GitLab on AlmaLinux is absolutely game-changing:

  • ๐Ÿš€ Continuous Delivery - Ship features to users in minutes, not months
  • ๐Ÿ”„ Automated Testing - Catch bugs before they reach production
  • ๐Ÿ“ฆ Container Integration - Build, test, and deploy Docker images
  • ๐Ÿ›ก๏ธ Security Scanning - Detect vulnerabilities automatically
  • ๐Ÿ“Š Pipeline Visibility - Track every deployment and its status
  • ๐Ÿ”ง Infrastructure as Code - Version control your entire stack
  • ๐Ÿ’ฐ Cost Reduction - Eliminate manual deployment errors
  • ๐ŸŒ GitOps Ready - Git as single source of truth

๐ŸŽฏ What You Need

Letโ€™s prepare your environment for DevOps excellence! โœ…

System Requirements:

  • โœ… AlmaLinux 8.x or 9.x server
  • โœ… Minimum 4 CPUs and 8GB RAM
  • โœ… 50GB+ available disk space
  • โœ… Domain name or static IP
  • โœ… Root or sudo access

Software Weโ€™ll Install:

  • โœ… GitLab Community Edition
  • โœ… GitLab Runner for job execution
  • โœ… Docker for containerization
  • โœ… Kubernetes CLI (kubectl)
  • โœ… SSL certificates for HTTPS

๐Ÿ“ Installing GitLab on AlmaLinux

Letโ€™s install and configure GitLab for your DevOps platform! ๐Ÿ”ง

Installing GitLab CE

# Install dependencies
sudo dnf install -y curl policycoreutils openssh-server openssh-clients
sudo dnf install -y postfix

# Enable services
sudo systemctl enable sshd
sudo systemctl start sshd
sudo systemctl enable postfix
sudo systemctl start postfix

# Add GitLab repository
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

# Install GitLab CE
# Replace gitlab.example.com with your domain
sudo EXTERNAL_URL="https://gitlab.example.com" dnf install -y gitlab-ce

# Configure GitLab
sudo gitlab-ctl reconfigure

# Check status
sudo gitlab-ctl status

# Get initial root password
sudo cat /etc/gitlab/initial_root_password

# Configure firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

Configuring GitLab Settings

# Edit GitLab configuration
sudo vi /etc/gitlab/gitlab.rb

# Essential configurations to add/modify:
external_url 'https://gitlab.example.com'
gitlab_rails['time_zone'] = 'UTC'

# Email configuration
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.gmail.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "[email protected]"
gitlab_rails['smtp_password'] = "your-app-password"
gitlab_rails['smtp_domain'] = "gmail.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true

# Backup settings
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
gitlab_rails['backup_keep_time'] = 604800  # 7 days

# Container Registry
registry_external_url 'https://registry.example.com'
gitlab_rails['registry_enabled'] = true

# Apply configuration
sudo gitlab-ctl reconfigure

# Create backup schedule
echo "0 2 * * * /opt/gitlab/bin/gitlab-backup create SKIP=artifacts,registry,pages,uploads" | sudo crontab -

๐Ÿ”ง Setting Up GitLab Runners

GitLab Runners execute your CI/CD jobs. Letโ€™s set them up! ๐Ÿƒโ€โ™‚๏ธ

Installing GitLab Runner

# Add GitLab Runner repository
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash

# Install GitLab Runner
sudo dnf install -y gitlab-runner

# Install Docker for container jobs
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker

# Add gitlab-runner to docker group
sudo usermod -aG docker gitlab-runner

# Register runner with GitLab
sudo gitlab-runner register

# Interactive prompts:
# GitLab URL: https://gitlab.example.com
# Registration token: (get from GitLab Admin Area > Runners)
# Description: docker-runner
# Tags: docker,linux
# Executor: docker
# Docker image: alpine:latest

# Start GitLab Runner
sudo systemctl enable --now gitlab-runner

# Verify runner
sudo gitlab-runner verify
sudo gitlab-runner list

Configuring Shared Runners

# Edit runner configuration
sudo vi /etc/gitlab-runner/config.toml

# Add/modify runner configuration:
concurrent = 4
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "docker-runner"
  url = "https://gitlab.example.com/"
  token = "YOUR_RUNNER_TOKEN"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 0

# Restart runner
sudo gitlab-runner restart

๐ŸŒŸ Creating CI/CD Pipelines

Letโ€™s build powerful CI/CD pipelines! ๐Ÿš€

Basic Pipeline Configuration

# Create .gitlab-ci.yml in your project root
stages:
  - build
  - test
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"
  IMAGE_NAME: "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"

before_script:
  - echo "Starting CI/CD Pipeline..."
  - echo "Project: $CI_PROJECT_NAME"
  - echo "Branch: $CI_COMMIT_REF_NAME"

# Build stage
build-job:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $IMAGE_NAME .
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $IMAGE_NAME
  only:
    - main
    - develop

# Test stage
test-job:
  stage: test
  image: node:16-alpine
  script:
    - npm install
    - npm test
    - npm run lint
  coverage: '/Lines\s*:\s*(\d+\.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

# Deploy to staging
deploy-staging:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
  script:
    - ssh -o StrictHostKeyChecking=no [email protected] "
        docker pull $IMAGE_NAME &&
        docker stop app || true &&
        docker rm app || true &&
        docker run -d --name app -p 80:80 $IMAGE_NAME
      "
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

# Deploy to production
deploy-production:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
  script:
    - ssh -o StrictHostKeyChecking=no [email protected] "
        docker pull $IMAGE_NAME &&
        docker stop app || true &&
        docker rm app || true &&
        docker run -d --name app -p 80:80 $IMAGE_NAME
      "
  environment:
    name: production
    url: https://production.example.com
  when: manual
  only:
    - main

Advanced Pipeline with Security Scanning

# Advanced .gitlab-ci.yml with security and quality gates
include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Security/Container-Scanning.gitlab-ci.yml
  - template: Security/Dependency-Scanning.gitlab-ci.yml

stages:
  - build
  - test
  - security
  - deploy
  - monitor

# Build Docker image
build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

# Run unit tests
unit-tests:
  stage: test
  image: python:3.9
  script:
    - pip install -r requirements.txt
    - pytest tests/ --cov=app --cov-report=xml
  artifacts:
    reports:
      junit: test-results.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

# Code quality check
code-quality:
  stage: test
  image: python:3.9
  script:
    - pip install pylint black flake8
    - black --check .
    - flake8 .
    - pylint app/

# Security scanning (using GitLab templates)
sast:
  stage: security

container_scanning:
  stage: security
  variables:
    CS_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

dependency_scanning:
  stage: security

# Deploy to Kubernetes
deploy-k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $KUBE_CONTEXT
    - sed -i "s|IMAGE_TAG|$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/
    - kubectl rollout status deployment/app -n production
  environment:
    name: production
    url: https://app.example.com
  only:
    - main

โœ… Kubernetes Integration

Letโ€™s deploy to Kubernetes directly from GitLab! โ˜ธ๏ธ

Setting Up Kubernetes Integration

# Create Kubernetes manifests
mkdir k8s
cat > k8s/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: app
        image: registry.example.com/project:IMAGE_TAG
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: app-secrets
              key: database-url
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
  name: app-service
  namespace: production
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer
EOF

# Create GitLab CI for Kubernetes deployment
cat > .gitlab-ci-k8s.yml << 'EOF'
deploy-kubernetes:
  stage: deploy
  image:
    name: bitnami/kubectl:latest
    entrypoint: [""]
  before_script:
    - kubectl config set-cluster k8s --server="$KUBE_URL" --insecure-skip-tls-verify=true
    - kubectl config set-credentials gitlab --token="$KUBE_TOKEN"
    - kubectl config set-context default --cluster=k8s --user=gitlab
    - kubectl config use-context default
  script:
    - sed -i "s|IMAGE_TAG|$CI_COMMIT_SHA|g" k8s/deployment.yaml
    - kubectl apply -f k8s/deployment.yaml
    - kubectl rollout status deployment/app -n production
  environment:
    name: production
    url: https://app.example.com
  only:
    - main
EOF

GitOps with ArgoCD

# Install ArgoCD on Kubernetes
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Create ArgoCD application
cat > argocd-app.yaml << 'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://gitlab.example.com/team/app.git
    targetRevision: HEAD
    path: k8s
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
EOF

kubectl apply -f argocd-app.yaml

๐ŸŽฎ Quick Examples

Example 1: Multi-Environment Pipeline

# Pipeline with multiple environments
stages:
  - build
  - deploy-dev
  - deploy-staging
  - deploy-prod

.deploy-template: &deploy-template
  image: alpine:latest
  before_script:
    - apk add --no-cache curl
  script:
    - echo "Deploying to $CI_ENVIRONMENT_NAME"
    - curl -X POST $DEPLOY_WEBHOOK_URL

build:
  stage: build
  script:
    - echo "Building application..."
    - docker build -t app:$CI_COMMIT_SHA .

deploy-dev:
  <<: *deploy-template
  stage: deploy-dev
  environment:
    name: development
    url: https://dev.example.com
  variables:
    DEPLOY_WEBHOOK_URL: $DEV_WEBHOOK
  only:
    - develop

deploy-staging:
  <<: *deploy-template
  stage: deploy-staging
  environment:
    name: staging
    url: https://staging.example.com
  variables:
    DEPLOY_WEBHOOK_URL: $STAGING_WEBHOOK
  only:
    - main

deploy-production:
  <<: *deploy-template
  stage: deploy-prod
  environment:
    name: production
    url: https://www.example.com
  variables:
    DEPLOY_WEBHOOK_URL: $PROD_WEBHOOK
  when: manual
  only:
    - main

Example 2: Database Migration Pipeline

# Pipeline with database migrations
stages:
  - test
  - migrate
  - deploy

test-migrations:
  stage: test
  image: postgres:14
  services:
    - postgres:14
  variables:
    POSTGRES_DB: test_db
    POSTGRES_USER: test_user
    POSTGRES_PASSWORD: test_pass
  script:
    - apt-get update && apt-get install -y postgresql-client
    - PGPASSWORD=$POSTGRES_PASSWORD psql -h postgres -U $POSTGRES_USER -d $POSTGRES_DB < schema.sql
    - ./run-migration-tests.sh

migrate-staging:
  stage: migrate
  image: migrate/migrate
  script:
    - migrate -path ./migrations -database "$STAGING_DB_URL" up
  environment:
    name: staging
  only:
    - main

migrate-production:
  stage: migrate
  image: migrate/migrate
  script:
    - migrate -path ./migrations -database "$PROD_DB_URL" up
  environment:
    name: production
  when: manual
  only:
    - main

deploy-app:
  stage: deploy
  script:
    - echo "Deploying application after migrations..."
  needs: ["migrate-staging"]

Example 3: Monitoring and Alerting Integration

# Create monitoring job in pipeline
cat >> .gitlab-ci.yml << 'EOF'
# Health check after deployment
health-check:
  stage: monitor
  image: curlimages/curl:latest
  script:
    - |
      for i in {1..30}; do
        if curl -f https://app.example.com/health; then
          echo "Application is healthy!"
          exit 0
        fi
        echo "Waiting for application to be ready... ($i/30)"
        sleep 10
      done
      echo "Application health check failed!"
      exit 1
  needs: ["deploy-production"]

# Send notification to Slack
notify-slack:
  stage: .post
  image: curlimages/curl:latest
  script:
    - |
      curl -X POST $SLACK_WEBHOOK_URL \
        -H 'Content-Type: application/json' \
        -d "{
          \"text\": \"Deployment to production completed!\",
          \"attachments\": [{
            \"color\": \"good\",
            \"fields\": [{
              \"title\": \"Project\",
              \"value\": \"$CI_PROJECT_NAME\",
              \"short\": true
            },{
              \"title\": \"Environment\",
              \"value\": \"Production\",
              \"short\": true
            },{
              \"title\": \"Version\",
              \"value\": \"$CI_COMMIT_SHORT_SHA\",
              \"short\": true
            }]
          }]
        }"
  when: on_success
  only:
    - main
EOF

๐Ÿšจ Fix Common CI/CD Problems

Letโ€™s solve frequent GitLab CI/CD issues! ๐Ÿ› ๏ธ

Problem 1: Pipeline Fails with Docker Permission Denied

Symptoms: Cannot connect to Docker daemon Solution:

# Add gitlab-runner to docker group
sudo usermod -aG docker gitlab-runner

# Restart services
sudo systemctl restart docker
sudo systemctl restart gitlab-runner

# In .gitlab-ci.yml, use privileged mode:
services:
  - docker:dind
variables:
  DOCKER_TLS_CERTDIR: ""
  DOCKER_HOST: tcp://docker:2375

Problem 2: SSH Deployment Fails

Symptoms: Permission denied during deployment Solution:

# Generate SSH key for deployments
ssh-keygen -t ed25519 -C "gitlab-deploy" -f deploy_key

# Add public key to target server
ssh-copy-id -i deploy_key.pub user@server

# Add private key to GitLab CI variables
# Go to Settings > CI/CD > Variables
# Add SSH_PRIVATE_KEY with the private key content

# In pipeline, use:
before_script:
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | ssh-add -
  - mkdir -p ~/.ssh
  - ssh-keyscan -H 'server.example.com' >> ~/.ssh/known_hosts

Problem 3: Container Registry Login Fails

Symptoms: unauthorized: authentication required Solution:

# Use GitLab CI predefined variables
script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

# Or use deploy token
# Create deploy token in Settings > Repository > Deploy Tokens
script:
  - docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY

Problem 4: Job Timeout

Symptoms: Job exceeded maximum execution time Solution:

# Increase timeout in .gitlab-ci.yml
job-name:
  timeout: 2 hours
  script:
    - long-running-command

# Or globally in project settings
# Settings > CI/CD > General pipelines > Timeout

๐Ÿ“‹ GitLab CI/CD Commands Reference

Essential GitLab commands for DevOps operations! โšก

CommandPurpose
gitlab-ctl reconfigureApply configuration changes
gitlab-ctl statusCheck GitLab services
gitlab-ctl tailView GitLab logs
gitlab-backup createCreate backup
gitlab-runner registerRegister new runner
gitlab-runner verifyVerify runners
gitlab-runner execTest job locally
gitlab-rake cache:clearClear cache

๐Ÿ’ก CI/CD Best Practices

Master these DevOps best practices! ๐ŸŽฏ

  • ๐Ÿ”„ Fail Fast - Run quick tests first, expensive ones later
  • ๐Ÿ“ฆ Cache Dependencies - Speed up builds with caching
  • ๐Ÿ” Secure Secrets - Never hardcode credentials
  • ๐Ÿ“Š Monitor Pipelines - Track success rates and duration
  • ๐ŸŽฏ Small Commits - Make debugging easier
  • ๐Ÿ”ง Pipeline as Code - Version control your CI/CD
  • ๐Ÿ“ Document Pipelines - Help team understand workflow
  • ๐Ÿš€ Progressive Delivery - Use feature flags and canary deployments
  • ๐Ÿ›ก๏ธ Security Scanning - Integrate SAST/DAST/dependency scanning
  • ๐Ÿ’พ Artifact Management - Store and version build artifacts

๐Ÿ† What Youโ€™ve Accomplished

Congratulations on mastering GitLab CI/CD on AlmaLinux! ๐ŸŽ‰ Youโ€™ve achieved:

  • โœ… Complete GitLab installation and configuration
  • โœ… GitLab Runners deployed for job execution
  • โœ… CI/CD pipelines created with multiple stages
  • โœ… Docker integration for containerized workflows
  • โœ… Kubernetes deployments automated
  • โœ… Security scanning integrated in pipelines
  • โœ… Multi-environment deployment strategies
  • โœ… GitOps workflows implemented
  • โœ… Monitoring and notifications configured
  • โœ… Best practices applied throughout

๐ŸŽฏ Why These Skills Matter

Your CI/CD expertise accelerates software delivery! ๐ŸŒŸ With these skills, you can:

Immediate Benefits:

  • ๐Ÿš€ Deploy code to production in minutes
  • ๐Ÿ›ก๏ธ Catch bugs before they reach users
  • ๐Ÿ“ˆ Increase deployment frequency by 100x
  • ๐Ÿ’ฐ Reduce deployment failures by 90%

Long-term Value:

  • ๐Ÿ† Lead DevOps transformation initiatives
  • ๐Ÿ’ผ Implement enterprise CI/CD strategies
  • ๐ŸŒ Build globally distributed delivery pipelines
  • ๐Ÿš€ Enable continuous innovation culture

Youโ€™re now equipped to build and manage CI/CD pipelines that transform how software is delivered! From startup MVPs to enterprise applications, you can automate the entire software delivery lifecycle! ๐ŸŒŸ

Keep automating, keep delivering! ๐Ÿ™Œ