🤖 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
Command | Purpose |
---|---|
ansible all -m ping | Test connectivity to all hosts |
ansible-playbook playbook.yml | Run Ansible playbook |
ansible-playbook --check playbook.yml | Dry run playbook |
ansible-galaxy install role-name | Install Ansible role |
~/scripts/system-monitor.sh | Run system monitoring |
~/scripts/auto-deploy.sh app v1.2 | Deploy application |
ansible-vault create secrets.yml | Create 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! ⭐🙌