f#
+
+
atom
+
+
+
dask
+
+
ada
esbuild
+
+
+
+
stencil
ionic
c
ios
+
+
+
+
cobol
+
+
firebase
+
+
+
+
+
+
>=
+
gin
+
elm
js
http
+
meteor
+
composer
quarkus
junit
+
+
cobol
+
+
+
+
echo
+
+
+
+
fortran
ray
+
+
abap
+
+
next
$
vb
weaviate
+
windows
elm
+
+
symfony
elasticsearch
junit
+
+
chef
vercel
+
svelte
+
+
+
Back to Blog
🤖 AlmaLinux Automation: Complete Ansible & Scripts Guide for DevOps Excellence
AlmaLinux Automation Ansible

🤖 AlmaLinux Automation: Complete Ansible & Scripts Guide for DevOps Excellence

Published Sep 18, 2025

Master automation on AlmaLinux! Learn Ansible playbooks, shell scripting, configuration management, deployment automation, and DevOps best practices. Complete guide with real examples.

61 min read
0 views
Table of Contents

🤖 AlmaLinux Automation: Complete Ansible & Scripts Guide for DevOps Excellence

Hey there, automation maestro! 🎉 Ready to eliminate repetitive tasks forever and become a DevOps wizard? Today we’re diving deep into automation with Ansible and scripting on AlmaLinux – the tools that will make you 10x more productive and turn manual work into one-click magic! 🚀

Whether you’re managing one server or a thousand, this guide will transform you from a manual laborer into an automation architect who gets things done while sipping coffee! ☕💪

🤔 Why is Automation Important?

Imagine doing the same server setup 100 times manually – that’s weeks of boring, error-prone work! 😱 Automation turns hours of work into seconds and makes you look like a superhero to your team!

Here’s why automation on AlmaLinux is absolutely essential:

  • Lightning Speed - Deploy infrastructure in minutes, not hours
  • 🎯 Perfect Consistency - Every deployment exactly the same
  • 🛡️ Error Elimination - No more “oops, I forgot that step”
  • 📈 Massive Scalability - Manage thousands of servers effortlessly
  • 💰 Cost Savings - Your time is worth more than manual work
  • 🔄 Repeatable Processes - Document everything as code
  • 📊 Compliance Assurance - Enforce standards automatically
  • 🌟 Career Advancement - Automation skills are in huge demand

🎯 What You Need

Before we build your automation empire, let’s gather our tools:

AlmaLinux 9.x control machine (your automation hub) ✅ Target servers to manage (can be VMs or containers) ✅ SSH key authentication set up ✅ Python 3 installed (usually included) ✅ Text editor for writing scripts and playbooks ✅ Basic understanding of YAML and shell scripting ✅ Patience for learning (the payoff is huge!) ✅ Love for efficiency and elegant solutions 🎭

📝 Step 1: Install and Configure Ansible

Let’s start with Ansible, the king of infrastructure automation! 🎯

# Install Ansible and dependencies
sudo dnf install -y ansible ansible-core python3-pip git

# Verify Ansible installation
ansible --version

# Create Ansible directory structure
mkdir -p ~/ansible/{inventories,playbooks,roles,group_vars,host_vars,files,templates}

# Create main inventory file
cat > ~/ansible/inventories/production << 'EOF'
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
web3 ansible_host=192.168.1.12

[databases]
db1 ansible_host=192.168.1.20
db2 ansible_host=192.168.1.21

[loadbalancers]
lb1 ansible_host=192.168.1.30

[production:children]
webservers
databases
loadbalancers

[production:vars]
ansible_user=admin
ansible_ssh_private_key_file=~/.ssh/id_rsa
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
EOF

# Create Ansible configuration file
cat > ~/ansible/ansible.cfg << 'EOF'
[defaults]
# Basic Configuration
inventory = inventories/production
remote_user = admin
private_key_file = ~/.ssh/id_rsa
host_key_checking = False

# Performance
forks = 10
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 3600

# Logging
log_path = ansible.log
display_skipped_hosts = False

# SSH
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
EOF

# Generate SSH key if not exists
if [ ! -f ~/.ssh/id_rsa ]; then
    ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
    echo "SSH key generated. Copy public key to target servers:"
    cat ~/.ssh/id_rsa.pub
fi

# Test Ansible connectivity
cd ~/ansible
ansible all -m ping

Perfect! Ansible is configured and ready! 🎉

🔧 Step 2: Create Essential Ansible Playbooks

Let’s build powerful playbooks for common tasks:

# Create system update playbook
cat > ~/ansible/playbooks/system-update.yml << 'EOF'
---
- name: System Update and Maintenance
  hosts: all
  become: yes
  vars:
    reboot_required: false

  tasks:
    - name: Update package cache
      dnf:
        update_cache: yes

    - name: Upgrade all packages
      dnf:
        name: "*"
        state: latest
      register: package_update

    - name: Install essential packages
      dnf:
        name:
          - htop
          - vim
          - git
          - curl
          - wget
          - unzip
          - rsync
        state: present

    - name: Check if reboot is required
      stat:
        path: /var/run/reboot-required
      register: reboot_required_file

    - name: Set reboot fact
      set_fact:
        reboot_required: true
      when: reboot_required_file.stat.exists

    - name: Reboot system if required
      reboot:
        msg: "Reboot initiated by Ansible for system updates"
        reboot_timeout: 300
      when: reboot_required

    - name: Wait for system to come back online
      wait_for_connection:
        timeout: 300
      when: reboot_required

    - name: Verify system is responsive
      ping:
      when: reboot_required
EOF

# Create web server deployment playbook
cat > ~/ansible/playbooks/deploy-webserver.yml << 'EOF'
---
- name: Deploy and Configure Web Server
  hosts: webservers
  become: yes
  vars:
    nginx_user: nginx
    nginx_worker_processes: auto
    nginx_worker_connections: 2048

  tasks:
    - name: Install Nginx
      dnf:
        name: nginx
        state: present

    - name: Create web directory
      file:
        path: /var/www/{{ inventory_hostname }}
        state: directory
        owner: "{{ nginx_user }}"
        group: "{{ nginx_user }}"
        mode: '0755'

    - name: Configure Nginx main config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        backup: yes
      notify: restart nginx

    - name: Configure virtual host
      template:
        src: vhost.conf.j2
        dest: /etc/nginx/conf.d/{{ inventory_hostname }}.conf
      notify: restart nginx

    - name: Deploy website content
      template:
        src: index.html.j2
        dest: /var/www/{{ inventory_hostname }}/index.html
        owner: "{{ nginx_user }}"
        group: "{{ nginx_user }}"
        mode: '0644'

    - name: Start and enable Nginx
      systemd:
        name: nginx
        state: started
        enabled: yes

    - name: Configure firewall
      firewalld:
        service: http
        permanent: yes
        state: enabled
        immediate: yes

    - name: Configure HTTPS firewall
      firewalld:
        service: https
        permanent: yes
        state: enabled
        immediate: yes

  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted
EOF

# Create security hardening playbook
cat > ~/ansible/playbooks/security-hardening.yml << 'EOF'
---
- name: Security Hardening for AlmaLinux
  hosts: all
  become: yes

  tasks:
    - name: Configure SSH security
      blockinfile:
        path: /etc/ssh/sshd_config
        block: |
          # Security hardening
          PermitRootLogin no
          PasswordAuthentication no
          X11Forwarding no
          MaxAuthTries 3
          ClientAliveInterval 300
          ClientAliveCountMax 2
          Protocol 2
        backup: yes
      notify: restart ssh

    - name: Install fail2ban
      dnf:
        name: fail2ban
        state: present

    - name: Configure fail2ban
      copy:
        content: |
          [DEFAULT]
          bantime = 3600
          findtime = 600
          maxretry = 3

          [sshd]
          enabled = true
          port = ssh
          logpath = /var/log/secure
          backend = systemd
        dest: /etc/fail2ban/jail.local
      notify: restart fail2ban

    - name: Start and enable fail2ban
      systemd:
        name: fail2ban
        state: started
        enabled: yes

    - name: Configure automatic updates
      dnf:
        name: dnf-automatic
        state: present

    - name: Configure dnf-automatic
      blockinfile:
        path: /etc/dnf/automatic.conf
        block: |
          [commands]
          upgrade_type = security
          download_updates = yes
          apply_updates = yes
        backup: yes

    - name: Enable automatic updates
      systemd:
        name: dnf-automatic.timer
        state: started
        enabled: yes

    - name: Set up log monitoring
      copy:
        content: |
          #!/bin/bash
          # Security log monitor
          tail -f /var/log/secure | grep -E "(Failed|Invalid|Illegal)" | \
          while read line; do
              echo "$(date): SECURITY ALERT - $line" >> /var/log/security-alerts.log
          done
        dest: /usr/local/bin/security-monitor.sh
        mode: '0755'

  handlers:
    - name: restart ssh
      systemd:
        name: sshd
        state: restarted

    - name: restart fail2ban
      systemd:
        name: fail2ban
        state: restarted
EOF

# Create templates directory and files
mkdir -p ~/ansible/templates

cat > ~/ansible/templates/nginx.conf.j2 << 'EOF'
user {{ nginx_user }};
worker_processes {{ nginx_worker_processes }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections {{ nginx_worker_connections }};
    use epoll;
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log /var/log/nginx/access.log;

    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    include /etc/nginx/conf.d/*.conf;
}
EOF

cat > ~/ansible/templates/vhost.conf.j2 << 'EOF'
server {
    listen 80;
    server_name {{ inventory_hostname }};
    root /var/www/{{ inventory_hostname }};
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ /\. {
        deny all;
    }

    access_log /var/log/nginx/{{ inventory_hostname }}_access.log;
    error_log /var/log/nginx/{{ inventory_hostname }}_error.log;
}
EOF

cat > ~/ansible/templates/index.html.j2 << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>{{ inventory_hostname }} - Deployed by Ansible</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; background: #f0f8ff; }
        .container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
        .success { color: #28a745; }
        .info { background: #e7f3ff; padding: 15px; border-radius: 5px; margin: 20px 0; }
    </style>
</head>
<body>
    <div class="container">
        <h1 class="success">🤖 Deployed by Ansible!</h1>
        <p>This web server was automatically configured using Ansible automation.</p>

        <div class="info">
            <h3>📋 Server Information:</h3>
            <ul>
                <li><strong>Hostname:</strong> {{ inventory_hostname }}</li>
                <li><strong>Deployed:</strong> {{ ansible_date_time.iso8601 }}</li>
                <li><strong>OS:</strong> {{ ansible_distribution }} {{ ansible_distribution_version }}</li>
                <li><strong>Architecture:</strong> {{ ansible_architecture }}</li>
                <li><strong>Memory:</strong> {{ (ansible_memtotal_mb / 1024) | round(1) }} GB</li>
            </ul>
        </div>

        <p class="success">✅ Automation Status: Active and Working!</p>
    </div>
</body>
</html>
EOF

Excellent! Essential playbooks are ready! 🌟

🌟 Step 3: Advanced Shell Scripting

Let’s create powerful shell scripts for automation:

# Create script directory
mkdir -p ~/scripts

# Create system monitoring script
cat > ~/scripts/system-monitor.sh << 'EOF'
#!/bin/bash
# Advanced System Monitoring and Alerting

# Configuration
ALERT_EMAIL="[email protected]"
LOG_FILE="/var/log/system-monitor.log"
TEMP_DIR="/tmp/monitor-$$"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Create temp directory
mkdir -p "$TEMP_DIR"

# Logging function
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Alert function
send_alert() {
    local subject="$1"
    local message="$2"
    echo "$message" | mail -s "$subject - $(hostname)" "$ALERT_EMAIL" 2>/dev/null
    log_message "ALERT: $subject - $message"
}

# Check system load
check_load() {
    local load_1min=$(uptime | awk -F'load average:' '{print $2}' | awk -F',' '{print $1}' | tr -d ' ')
    local cpu_cores=$(nproc)
    local load_threshold=$(echo "scale=2; $cpu_cores * 0.8" | bc)

    if (( $(echo "$load_1min > $load_threshold" | bc -l) )); then
        send_alert "HIGH LOAD" "System load is $load_1min (threshold: $load_threshold)"
        echo -e "${RED}⚠️  HIGH LOAD: $load_1min${NC}"
    else
        echo -e "${GREEN}✅ Load: $load_1min${NC}"
    fi
}

# Check memory usage
check_memory() {
    local mem_usage=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
    local mem_threshold=85

    if (( $(echo "$mem_usage > $mem_threshold" | bc -l) )); then
        send_alert "HIGH MEMORY" "Memory usage is ${mem_usage}% (threshold: ${mem_threshold}%)"
        echo -e "${RED}⚠️  HIGH MEMORY: ${mem_usage}%${NC}"
    else
        echo -e "${GREEN}✅ Memory: ${mem_usage}%${NC}"
    fi
}

# Check disk usage
check_disk() {
    df -h | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{print $5,$1}' | while read output; do
        usage=$(echo $output | awk '{print $1}' | cut -d'%' -f1)
        partition=$(echo $output | awk '{print $2}')

        if [ $usage -ge 90 ]; then
            send_alert "DISK FULL" "Partition $partition is ${usage}% full"
            echo -e "${RED}⚠️  DISK FULL: $partition ${usage}%${NC}"
        elif [ $usage -ge 80 ]; then
            echo -e "${YELLOW}⚠️  DISK WARNING: $partition ${usage}%${NC}"
        else
            echo -e "${GREEN}✅ Disk: $partition ${usage}%${NC}"
        fi
    done
}

# Check services
check_services() {
    local services=("sshd" "firewalld" "NetworkManager")

    for service in "${services[@]}"; do
        if systemctl is-active --quiet "$service"; then
            echo -e "${GREEN}✅ Service: $service${NC}"
        else
            send_alert "SERVICE DOWN" "Service $service is not running"
            echo -e "${RED}❌ Service: $service${NC}"
        fi
    done
}

# Check security
check_security() {
    # Check for failed login attempts
    local failed_logins=$(grep "Failed password" /var/log/secure | grep "$(date '+%b %d')" | wc -l)

    if [ $failed_logins -gt 10 ]; then
        send_alert "SECURITY ALERT" "Multiple failed login attempts: $failed_logins"
        echo -e "${RED}⚠️  SECURITY: $failed_logins failed logins today${NC}"
    else
        echo -e "${GREEN}✅ Security: $failed_logins failed logins${NC}"
    fi

    # Check for root logins
    local root_logins=$(grep "Accepted.*root" /var/log/secure | grep "$(date '+%b %d')" | wc -l)
    if [ $root_logins -gt 0 ]; then
        send_alert "ROOT LOGIN" "Root login detected: $root_logins times today"
        echo -e "${YELLOW}⚠️  ROOT LOGIN: $root_logins times today${NC}"
    fi
}

# Main monitoring function
main() {
    echo "🔍 System Monitor - $(date)"
    echo "=========================="

    check_load
    check_memory
    check_disk
    check_services
    check_security

    log_message "System check completed"

    # Cleanup
    rm -rf "$TEMP_DIR"
}

# Run main function
main
EOF

chmod +x ~/scripts/system-monitor.sh

# Create deployment automation script
cat > ~/scripts/auto-deploy.sh << 'EOF'
#!/bin/bash
# Automated Application Deployment Script

# Configuration
APP_NAME="${1:-myapp}"
VERSION="${2:-latest}"
DEPLOY_DIR="/opt/apps"
BACKUP_DIR="/opt/backups"
GIT_REPO="${3:-https://github.com/company/myapp.git}"
SERVICE_NAME="$APP_NAME"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'

# Logging
log() {
    echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1"
}

error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}

success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

# Pre-deployment checks
pre_checks() {
    log "Starting pre-deployment checks..."

    # Check if we have enough disk space
    local available_space=$(df "$DEPLOY_DIR" | tail -1 | awk '{print $4}')
    if [ $available_space -lt 1048576 ]; then  # Less than 1GB
        error "Insufficient disk space"
        exit 1
    fi

    # Check if git is available
    if ! command -v git &> /dev/null; then
        error "Git is not installed"
        exit 1
    fi

    success "Pre-deployment checks passed"
}

# Backup current version
backup_current() {
    if [ -d "$DEPLOY_DIR/$APP_NAME" ]; then
        log "Backing up current version..."
        local backup_name="${APP_NAME}_$(date '+%Y%m%d_%H%M%S')"
        mkdir -p "$BACKUP_DIR"
        cp -r "$DEPLOY_DIR/$APP_NAME" "$BACKUP_DIR/$backup_name"
        success "Backup created: $backup_name"
    fi
}

# Deploy new version
deploy() {
    log "Deploying $APP_NAME version $VERSION..."

    # Create deployment directory
    mkdir -p "$DEPLOY_DIR"

    # Clone or update repository
    if [ -d "$DEPLOY_DIR/$APP_NAME/.git" ]; then
        cd "$DEPLOY_DIR/$APP_NAME"
        git fetch origin
        git reset --hard "origin/$VERSION"
    else
        rm -rf "$DEPLOY_DIR/$APP_NAME"
        git clone -b "$VERSION" "$GIT_REPO" "$DEPLOY_DIR/$APP_NAME"
    fi

    cd "$DEPLOY_DIR/$APP_NAME"

    # Install dependencies if package.json exists
    if [ -f "package.json" ]; then
        log "Installing Node.js dependencies..."
        npm install --production
    fi

    # Install Python dependencies if requirements.txt exists
    if [ -f "requirements.txt" ]; then
        log "Installing Python dependencies..."
        pip3 install -r requirements.txt
    fi

    # Make scripts executable
    find . -name "*.sh" -exec chmod +x {} \;

    success "Deployment completed"
}

# Health check
health_check() {
    log "Performing health check..."

    # Check if service is running
    if systemctl is-active --quiet "$SERVICE_NAME"; then
        success "Service $SERVICE_NAME is running"
    else
        error "Service $SERVICE_NAME is not running"
        return 1
    fi

    # HTTP health check if applicable
    if [ -f "/etc/systemd/system/$SERVICE_NAME.service" ]; then
        local port=$(grep -o 'PORT=[0-9]*' "/etc/systemd/system/$SERVICE_NAME.service" | cut -d'=' -f2)
        if [ -n "$port" ]; then
            if curl -s "http://localhost:$port/health" &> /dev/null; then
                success "HTTP health check passed"
            else
                error "HTTP health check failed"
                return 1
            fi
        fi
    fi
}

# Rollback function
rollback() {
    error "Deployment failed, initiating rollback..."

    local latest_backup=$(ls -t "$BACKUP_DIR" | grep "$APP_NAME" | head -1)
    if [ -n "$latest_backup" ]; then
        rm -rf "$DEPLOY_DIR/$APP_NAME"
        cp -r "$BACKUP_DIR/$latest_backup" "$DEPLOY_DIR/$APP_NAME"
        systemctl restart "$SERVICE_NAME"
        success "Rollback completed"
    else
        error "No backup found for rollback"
    fi
}

# Main deployment function
main() {
    echo "🚀 Automated Deployment Starting"
    echo "================================"
    echo "App: $APP_NAME"
    echo "Version: $VERSION"
    echo "Repository: $GIT_REPO"
    echo ""

    # Execute deployment steps
    pre_checks
    backup_current
    deploy

    # Restart service if it exists
    if systemctl list-unit-files | grep -q "$SERVICE_NAME.service"; then
        log "Restarting service $SERVICE_NAME..."
        systemctl restart "$SERVICE_NAME"
    fi

    # Health check
    if health_check; then
        success "🎉 Deployment successful!"
    else
        rollback
        exit 1
    fi
}

# Run main function
main
EOF

chmod +x ~/scripts/auto-deploy.sh

# Create server provisioning script
cat > ~/scripts/provision-server.sh << 'EOF'
#!/bin/bash
# Complete Server Provisioning Script

# Configuration
NEW_USER="${1:-admin}"
SSH_KEY_FILE="${2:-~/.ssh/id_rsa.pub}"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'

log() { echo -e "${BLUE}[PROVISION]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Update system
update_system() {
    log "Updating system packages..."
    dnf update -y
    success "System updated"
}

# Create admin user
create_user() {
    log "Creating user: $NEW_USER"
    useradd -m -s /bin/bash "$NEW_USER"
    usermod -aG wheel "$NEW_USER"

    # Set up SSH key
    if [ -f "$SSH_KEY_FILE" ]; then
        mkdir -p "/home/$NEW_USER/.ssh"
        cp "$SSH_KEY_FILE" "/home/$NEW_USER/.ssh/authorized_keys"
        chown -R "$NEW_USER:$NEW_USER" "/home/$NEW_USER/.ssh"
        chmod 700 "/home/$NEW_USER/.ssh"
        chmod 600 "/home/$NEW_USER/.ssh/authorized_keys"
        success "SSH key configured for $NEW_USER"
    fi
}

# Configure security
configure_security() {
    log "Configuring security settings..."

    # Update SSH config
    sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
    sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
    systemctl restart sshd

    # Install and configure firewall
    systemctl enable --now firewalld
    firewall-cmd --add-service=ssh --permanent
    firewall-cmd --reload

    success "Security configured"
}

# Install essential packages
install_packages() {
    log "Installing essential packages..."
    dnf install -y \
        htop vim git curl wget unzip \
        python3 python3-pip \
        docker-ce docker-ce-cli containerd.io \
        ansible fail2ban

    systemctl enable --now docker
    usermod -aG docker "$NEW_USER"

    success "Essential packages installed"
}

# Main provisioning
main() {
    echo "🔧 Server Provisioning Starting"
    echo "==============================="
    echo "User: $NEW_USER"
    echo "SSH Key: $SSH_KEY_FILE"
    echo ""

    update_system
    create_user
    configure_security
    install_packages

    success "🎉 Server provisioning completed!"
    echo ""
    echo "Next steps:"
    echo "1. Test SSH access: ssh $NEW_USER@$(hostname -I | awk '{print $1}')"
    echo "2. Configure additional services as needed"
    echo "3. Run security hardening playbook"
}

main
EOF

chmod +x ~/scripts/provision-server.sh

✅ Step 4: Infrastructure as Code

Let’s create Infrastructure as Code templates:

# Create Ansible role structure
mkdir -p ~/ansible/roles/lamp-stack/{tasks,handlers,templates,vars,defaults,files}

# Create LAMP stack role
cat > ~/ansible/roles/lamp-stack/tasks/main.yml << 'EOF'
---
- name: Install Apache
  dnf:
    name: httpd
    state: present

- name: Install MariaDB
  dnf:
    name:
      - mariadb-server
      - mariadb
      - python3-PyMySQL
    state: present

- name: Install PHP
  dnf:
    name:
      - php
      - php-mysqlnd
      - php-fpm
      - php-json
      - php-curl
      - php-xml
    state: present

- name: Start and enable services
  systemd:
    name: "{{ item }}"
    state: started
    enabled: yes
  loop:
    - httpd
    - mariadb
    - php-fpm

- name: Secure MariaDB installation
  mysql_user:
    name: root
    password: "{{ mysql_root_password }}"
    login_unix_socket: /var/lib/mysql/mysql.sock
    state: present

- name: Create database
  mysql_db:
    name: "{{ app_database }}"
    state: present
    login_user: root
    login_password: "{{ mysql_root_password }}"

- name: Create database user
  mysql_user:
    name: "{{ app_db_user }}"
    password: "{{ app_db_password }}"
    priv: "{{ app_database }}.*:ALL"
    state: present
    login_user: root
    login_password: "{{ mysql_root_password }}"

- name: Configure firewall
  firewalld:
    service: "{{ item }}"
    permanent: yes
    state: enabled
    immediate: yes
  loop:
    - http
    - https
EOF

cat > ~/ansible/roles/lamp-stack/defaults/main.yml << 'EOF'
---
mysql_root_password: "SecureRootPass123"
app_database: "webapp"
app_db_user: "webapp_user"
app_db_password: "SecureAppPass456"
EOF

# Create comprehensive infrastructure playbook
cat > ~/ansible/playbooks/infrastructure.yml << 'EOF'
---
- name: Complete Infrastructure Deployment
  hosts: all
  become: yes

  vars:
    common_packages:
      - htop
      - vim
      - git
      - curl
      - wget
      - unzip
      - rsync
      - fail2ban

  pre_tasks:
    - name: Update system
      dnf:
        name: "*"
        state: latest

    - name: Install common packages
      dnf:
        name: "{{ common_packages }}"
        state: present

- name: Configure Web Servers
  hosts: webservers
  become: yes
  roles:
    - lamp-stack

- name: Configure Database Servers
  hosts: databases
  become: yes
  tasks:
    - name: Install MariaDB
      dnf:
        name:
          - mariadb-server
          - mariadb
        state: present

    - name: Start and enable MariaDB
      systemd:
        name: mariadb
        state: started
        enabled: yes

    - name: Configure MariaDB for production
      template:
        src: my.cnf.j2
        dest: /etc/my.cnf
        backup: yes
      notify: restart mariadb

- name: Configure Load Balancers
  hosts: loadbalancers
  become: yes
  tasks:
    - name: Install HAProxy
      dnf:
        name: haproxy
        state: present

    - name: Configure HAProxy
      template:
        src: haproxy.cfg.j2
        dest: /etc/haproxy/haproxy.cfg
        backup: yes
      notify: restart haproxy

    - name: Start and enable HAProxy
      systemd:
        name: haproxy
        state: started
        enabled: yes

  handlers:
    - name: restart mariadb
      systemd:
        name: mariadb
        state: restarted

    - name: restart haproxy
      systemd:
        name: haproxy
        state: restarted
EOF

🎮 Quick Examples

Example 1: Application Deployment Pipeline

# Create CI/CD pipeline script
cat > ~/scripts/cicd-pipeline.sh << 'EOF'
#!/bin/bash
# Complete CI/CD Pipeline

REPO_URL="$1"
BRANCH="${2:-main}"
ENV="${3:-staging}"

# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'

log() { echo -e "${BLUE}[PIPELINE]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Pipeline stages
stage_checkout() {
    log "Stage 1: Checkout code"
    rm -rf /tmp/build
    git clone -b "$BRANCH" "$REPO_URL" /tmp/build
    cd /tmp/build
    success "Code checked out"
}

stage_test() {
    log "Stage 2: Run tests"
    cd /tmp/build

    if [ -f "package.json" ]; then
        npm install
        npm test
    elif [ -f "requirements.txt" ]; then
        pip3 install -r requirements.txt
        python3 -m pytest
    fi

    success "Tests passed"
}

stage_build() {
    log "Stage 3: Build application"
    cd /tmp/build

    # Build Docker image
    if [ -f "Dockerfile" ]; then
        docker build -t "myapp:$BRANCH-$(date +%s)" .
        success "Docker image built"
    fi
}

stage_deploy() {
    log "Stage 4: Deploy to $ENV"

    # Run Ansible deployment
    ansible-playbook -i "inventories/$ENV" \
        -e "git_branch=$BRANCH" \
        playbooks/deploy-app.yml

    success "Deployed to $ENV"
}

# Main pipeline
main() {
    echo "🚀 CI/CD Pipeline Starting"
    echo "=========================="
    echo "Repository: $REPO_URL"
    echo "Branch: $BRANCH"
    echo "Environment: $ENV"
    echo ""

    stage_checkout || exit 1
    stage_test || exit 1
    stage_build || exit 1
    stage_deploy || exit 1

    success "🎉 Pipeline completed successfully!"
}

main
EOF

chmod +x ~/scripts/cicd-pipeline.sh

Example 2: Configuration Management

# Create configuration drift detection
cat > ~/scripts/config-drift.sh << 'EOF'
#!/bin/bash
# Configuration Drift Detection

CONFIG_DIR="/etc/config-baseline"
REPORT_FILE="/tmp/config-drift-$(date +%Y%m%d).report"

# Create baseline if not exists
if [ ! -d "$CONFIG_DIR" ]; then
    echo "Creating configuration baseline..."
    mkdir -p "$CONFIG_DIR"

    # Backup important configs
    cp /etc/ssh/sshd_config "$CONFIG_DIR/"
    cp /etc/httpd/conf/httpd.conf "$CONFIG_DIR/" 2>/dev/null
    cp /etc/nginx/nginx.conf "$CONFIG_DIR/" 2>/dev/null

    echo "Baseline created"
    exit 0
fi

# Check for drift
echo "Configuration Drift Report - $(date)" > "$REPORT_FILE"
echo "======================================" >> "$REPORT_FILE"

check_file() {
    local file="$1"
    local basename=$(basename "$file")

    if [ -f "$CONFIG_DIR/$basename" ]; then
        if ! diff -q "$file" "$CONFIG_DIR/$basename" &>/dev/null; then
            echo "DRIFT DETECTED: $file" >> "$REPORT_FILE"
            echo "Changes:" >> "$REPORT_FILE"
            diff "$CONFIG_DIR/$basename" "$file" >> "$REPORT_FILE"
            echo "" >> "$REPORT_FILE"
        fi
    fi
}

# Check configuration files
check_file "/etc/ssh/sshd_config"
check_file "/etc/httpd/conf/httpd.conf"
check_file "/etc/nginx/nginx.conf"

echo "Configuration drift report: $REPORT_FILE"
EOF

chmod +x ~/scripts/config-drift.sh

🚨 Fix Common Problems

Problem 1: Ansible Connection Issues

# Debug Ansible connectivity
ansible all -m ping -vvv

# Fix SSH key issues
ssh-copy-id user@target-host

# Test SSH manually
ssh -i ~/.ssh/id_rsa user@target-host

# Update inventory with correct details
vim ~/ansible/inventories/production

Problem 2: Playbook Failures

# Run with verbose output
ansible-playbook -vvv playbook.yml

# Check syntax
ansible-playbook --syntax-check playbook.yml

# Dry run
ansible-playbook --check playbook.yml

# Debug specific tasks
ansible-playbook --start-at-task="task name" playbook.yml

Problem 3: Script Permission Issues

# Fix script permissions
chmod +x ~/scripts/*.sh

# Fix SELinux contexts
restorecon -R ~/scripts/

# Add to PATH if needed
echo 'export PATH=$PATH:~/scripts' >> ~/.bashrc

📋 Simple Commands Summary

CommandPurpose
ansible all -m pingTest connectivity to all hosts
ansible-playbook playbook.ymlRun Ansible playbook
ansible-playbook --check playbook.ymlDry run playbook
ansible-galaxy install role-nameInstall Ansible role
~/scripts/system-monitor.shRun system monitoring
~/scripts/auto-deploy.sh app v1.2Deploy application
ansible-vault create secrets.ymlCreate encrypted variables
ansible all -a "uptime"Run command on all hosts

🏆 What You Learned

Congratulations! You’ve mastered automation on AlmaLinux! 🎉

Installed and configured Ansible for infrastructure automation ✅ Created comprehensive playbooks for common tasks ✅ Built advanced shell scripts for system management ✅ Implemented Infrastructure as Code practices ✅ Developed CI/CD pipeline automation ✅ Created monitoring and alerting systems ✅ Learned troubleshooting automation issues ✅ Built reusable automation components

🎯 Why This Matters

Automation is the foundation of modern IT operations! 🌟 With your AlmaLinux automation skills, you now have:

  • 10x productivity through elimination of manual tasks
  • Consistent deployments that work the same every time
  • Rapid scaling capabilities for infrastructure growth
  • Error reduction through automated processes
  • Career advancement with in-demand DevOps skills

You’re now equipped to automate entire infrastructures and deploy applications with the push of a button! Your automation expertise puts you in the league of DevOps engineers who make the impossible look easy! 🚀

Keep automating, keep improving, and remember – if you’re doing it twice, automate it! You’ve got this! ⭐🙌