Effective configuration file management is crucial for maintaining Alpine Linux systems, ensuring consistent deployments, and enabling reliable rollbacks. This comprehensive guide covers advanced techniques for tracking, versioning, and automating package configuration management across different environments.
🔍 Understanding Alpine Configuration Architecture
Alpine Linux follows the Unix philosophy of storing configuration in plain text files, making configuration management both powerful and accessible through standard tools.
Configuration File Hierarchy
- System-wide configs -
/etc/
directory 🌐 - Service-specific configs -
/etc/service-name/
📋 - User-specific configs -
~/.config/
and~/
👤 - Runtime configs -
/var/lib/
,/var/run/
⚡
Package Configuration Categories
# Essential system configurations
/etc/passwd # User accounts
/etc/group # Group definitions
/etc/shadow # Password hashes
/etc/fstab # Filesystem table
/etc/hostname # System hostname
/etc/hosts # Host name resolution
/etc/resolv.conf # DNS configuration
# Service configurations
/etc/nginx/ # Nginx web server
/etc/ssh/ # SSH daemon
/etc/mysql/ # MySQL/MariaDB
/etc/postgresql/ # PostgreSQL
/etc/redis/ # Redis
/etc/docker/ # Docker daemon
# Network configurations
/etc/network/ # Network interfaces
/etc/iptables/ # Firewall rules
/etc/wireguard/ # VPN configurations
🛠️ Configuration Management Strategies
Version Control with Git
# Initialize configuration repository
cd /etc
git init
git config user.name "System Administrator"
git config user.email "[email protected]"
# Create comprehensive .gitignore
cat > .gitignore << 'EOF'
# Sensitive files
shadow*
gshadow*
ssh/ssh_host_*
ssl/private/
*.key
*.pem
# Runtime files
mtab
resolv.conf.auto
*.pid
*.sock
# Backup files
*.bak
*.orig
*~
.#*
# Log files
*.log
*.log.*
# Temporary files
*.tmp
*.swp
*.cache
EOF
# Add initial configuration
git add .
git commit -m "Initial configuration snapshot"
# Create configuration tracking script
cat > /usr/local/bin/track-config-changes << 'EOF'
#!/bin/sh
# Configuration change tracking
cd /etc
# Check for changes
if git diff --quiet && git diff --cached --quiet; then
echo "No configuration changes detected"
exit 0
fi
# Show changes
echo "Configuration changes detected:"
git status --porcelain
# Interactive commit (for manual use)
if [ "$1" = "--interactive" ]; then
git add -i
git commit
else
# Automatic commit with timestamp
git add .
git commit -m "Auto-commit: $(date '+%Y-%m-%d %H:%M:%S') - $(git status --porcelain | wc -l) files changed"
fi
echo "Configuration changes committed"
EOF
chmod +x /usr/local/bin/track-config-changes
Configuration Templates and Environment Management
# Create configuration template system
mkdir -p /etc/config-templates/{production,staging,development}
# Example: Nginx configuration template
cat > /etc/config-templates/nginx.conf.template << 'EOF'
user ${NGINX_USER:-nginx};
worker_processes ${NGINX_WORKERS:-auto};
error_log /var/log/nginx/error.log ${LOG_LEVEL:-warn};
pid /run/nginx.pid;
events {
worker_connections ${WORKER_CONNECTIONS:-1024};
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Security headers
add_header X-Frame-Options "${X_FRAME_OPTIONS:-SAMEORIGIN}" always;
add_header X-Content-Type-Options "${X_CONTENT_TYPE_OPTIONS:-nosniff}" always;
# Performance settings
sendfile ${SENDFILE:-on};
tcp_nopush ${TCP_NOPUSH:-on};
tcp_nodelay ${TCP_NODELAY:-on};
keepalive_timeout ${KEEPALIVE_TIMEOUT:-65};
# Gzip compression
gzip ${GZIP_ENABLED:-on};
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=${API_RATE_LIMIT:-10r/s};
# Include additional configurations
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
EOF
# Environment-specific variable files
cat > /etc/config-templates/production/nginx.env << 'EOF'
NGINX_USER=nginx
NGINX_WORKERS=auto
LOG_LEVEL=error
WORKER_CONNECTIONS=2048
X_FRAME_OPTIONS=DENY
X_CONTENT_TYPE_OPTIONS=nosniff
SENDFILE=on
TCP_NOPUSH=on
TCP_NODELAY=on
KEEPALIVE_TIMEOUT=30
GZIP_ENABLED=on
API_RATE_LIMIT=5r/s
EOF
cat > /etc/config-templates/development/nginx.env << 'EOF'
NGINX_USER=nginx
NGINX_WORKERS=1
LOG_LEVEL=debug
WORKER_CONNECTIONS=1024
X_FRAME_OPTIONS=SAMEORIGIN
X_CONTENT_TYPE_OPTIONS=nosniff
SENDFILE=off
TCP_NOPUSH=off
TCP_NODELAY=on
KEEPALIVE_TIMEOUT=65
GZIP_ENABLED=off
API_RATE_LIMIT=100r/s
EOF
# Configuration deployment script
cat > /usr/local/bin/deploy-config << 'EOF'
#!/bin/sh
# Configuration deployment system
ENVIRONMENT="${1:-production}"
SERVICE="$2"
TEMPLATE_DIR="/etc/config-templates"
BACKUP_DIR="/var/backups/configs"
if [ -z "$SERVICE" ]; then
echo "Usage: $0 <environment> <service>"
echo "Environments: production, staging, development"
echo "Services: nginx, ssh, mysql, postgresql, etc."
exit 1
fi
# Load environment variables
ENV_FILE="$TEMPLATE_DIR/$ENVIRONMENT/$SERVICE.env"
if [ -f "$ENV_FILE" ]; then
source "$ENV_FILE"
else
echo "Warning: No environment file found at $ENV_FILE"
fi
# Template file
TEMPLATE_FILE="$TEMPLATE_DIR/$SERVICE.conf.template"
if [ ! -f "$TEMPLATE_FILE" ]; then
echo "Error: Template file not found: $TEMPLATE_FILE"
exit 1
fi
# Determine target configuration file
case "$SERVICE" in
nginx)
TARGET_FILE="/etc/nginx/nginx.conf"
;;
ssh)
TARGET_FILE="/etc/ssh/sshd_config"
;;
mysql)
TARGET_FILE="/etc/my.cnf"
;;
postgresql)
TARGET_FILE="/etc/postgresql/postgresql.conf"
;;
*)
TARGET_FILE="/etc/$SERVICE/$SERVICE.conf"
;;
esac
# Create backup
mkdir -p "$BACKUP_DIR/$(date +%Y%m%d)"
if [ -f "$TARGET_FILE" ]; then
cp "$TARGET_FILE" "$BACKUP_DIR/$(date +%Y%m%d)/$(basename "$TARGET_FILE").$(date +%H%M%S)"
fi
# Process template
echo "Deploying $SERVICE configuration for $ENVIRONMENT environment"
envsubst < "$TEMPLATE_FILE" > "$TARGET_FILE"
# Validate configuration
case "$SERVICE" in
nginx)
if nginx -t 2>/dev/null; then
echo "✅ Nginx configuration valid"
rc-service nginx reload
else
echo "❌ Nginx configuration invalid, restoring backup"
cp "$BACKUP_DIR/$(date +%Y%m%d)/$(basename "$TARGET_FILE")".* "$TARGET_FILE"
exit 1
fi
;;
ssh)
if sshd -t 2>/dev/null; then
echo "✅ SSH configuration valid"
rc-service sshd reload
else
echo "❌ SSH configuration invalid, restoring backup"
cp "$BACKUP_DIR/$(date +%Y%m%d)/$(basename "$TARGET_FILE")".* "$TARGET_FILE"
exit 1
fi
;;
esac
echo "Configuration deployment completed"
EOF
chmod +x /usr/local/bin/deploy-config
# Deploy configurations
deploy-config production nginx
deploy-config development nginx
📊 Configuration Change Management
Automated Configuration Monitoring
# Create configuration monitoring system
cat > /usr/local/bin/monitor-config-changes << 'EOF'
#!/bin/sh
# Configuration change monitoring and alerting
CONFIG_DIR="/etc"
MONITOR_FILE="/var/lib/config-monitor/checksums"
ALERT_EMAIL="[email protected]"
LOG_FILE="/var/log/config-changes.log"
# Create monitoring directory
mkdir -p "$(dirname "$MONITOR_FILE")"
# Generate current checksums
generate_checksums() {
find "$CONFIG_DIR" -type f \
! -path "*/.*" \
! -name "*.log" \
! -name "*.tmp" \
! -name "*.pid" \
! -name "*.sock" \
! -name "resolv.conf.auto" \
-exec sha256sum {} \; 2>/dev/null | sort
}
# Load previous checksums
if [ -f "$MONITOR_FILE" ]; then
PREVIOUS_CHECKSUMS=$(cat "$MONITOR_FILE")
else
PREVIOUS_CHECKSUMS=""
fi
# Generate current checksums
CURRENT_CHECKSUMS=$(generate_checksums)
# Compare checksums
if [ "$PREVIOUS_CHECKSUMS" != "$CURRENT_CHECKSUMS" ]; then
echo "$(date): Configuration changes detected" | tee -a "$LOG_FILE"
# Find changed files
echo "$PREVIOUS_CHECKSUMS" > /tmp/previous_checksums
echo "$CURRENT_CHECKSUMS" > /tmp/current_checksums
# Files that were modified
MODIFIED_FILES=$(comm -13 /tmp/previous_checksums /tmp/current_checksums | awk '{print $2}')
# Files that were deleted
DELETED_FILES=$(comm -23 /tmp/previous_checksums /tmp/current_checksums | awk '{print $2}')
# Log changes
if [ -n "$MODIFIED_FILES" ]; then
echo "Modified/Added files:" | tee -a "$LOG_FILE"
echo "$MODIFIED_FILES" | while read file; do
echo " - $file" | tee -a "$LOG_FILE"
done
fi
if [ -n "$DELETED_FILES" ]; then
echo "Deleted files:" | tee -a "$LOG_FILE"
echo "$DELETED_FILES" | while read file; do
echo " - $file" | tee -a "$LOG_FILE"
done
fi
# Send alert email
if [ -n "$ALERT_EMAIL" ]; then
{
echo "Configuration changes detected on $(hostname) at $(date)"
echo ""
echo "Modified/Added files:"
echo "$MODIFIED_FILES"
echo ""
echo "Deleted files:"
echo "$DELETED_FILES"
echo ""
echo "Please review these changes immediately."
} | mail -s "Configuration Change Alert - $(hostname)" "$ALERT_EMAIL" 2>/dev/null || true
fi
# Update stored checksums
echo "$CURRENT_CHECKSUMS" > "$MONITOR_FILE"
# Track changes in git if available
if [ -d "$CONFIG_DIR/.git" ]; then
cd "$CONFIG_DIR"
track-config-changes
fi
else
echo "$(date): No configuration changes detected" >> "$LOG_FILE"
fi
# Cleanup
rm -f /tmp/previous_checksums /tmp/current_checksums
EOF
chmod +x /usr/local/bin/monitor-config-changes
# Add to cron for regular monitoring
echo "*/15 * * * * /usr/local/bin/monitor-config-changes >/dev/null 2>&1" >> /etc/crontabs/root
Configuration Rollback System
# Create configuration rollback system
cat > /usr/local/bin/rollback-config << 'EOF'
#!/bin/sh
# Configuration rollback system
BACKUP_DIR="/var/backups/configs"
SERVICE="$1"
DATE="$2"
usage() {
echo "Usage: $0 <service> [date]"
echo ""
echo "Available services:"
ls -1 "$BACKUP_DIR" 2>/dev/null | head -5
echo ""
echo "Available dates:"
ls -1 "$BACKUP_DIR/" 2>/dev/null | head -10
echo ""
echo "Examples:"
echo " $0 nginx # Rollback to latest backup"
echo " $0 nginx 20250603 # Rollback to specific date"
echo " $0 list # List available backups"
}
list_backups() {
echo "Available configuration backups:"
echo ""
for date_dir in $(ls -1r "$BACKUP_DIR" 2>/dev/null | head -10); do
echo "Date: $date_dir"
ls -la "$BACKUP_DIR/$date_dir/" | while read line; do
echo " $line"
done
echo ""
done
}
if [ "$1" = "list" ]; then
list_backups
exit 0
fi
if [ -z "$SERVICE" ]; then
usage
exit 1
fi
# Determine target configuration file
case "$SERVICE" in
nginx)
TARGET_FILE="/etc/nginx/nginx.conf"
RESTART_CMD="rc-service nginx restart"
TEST_CMD="nginx -t"
;;
ssh)
TARGET_FILE="/etc/ssh/sshd_config"
RESTART_CMD="rc-service sshd restart"
TEST_CMD="sshd -t"
;;
mysql)
TARGET_FILE="/etc/my.cnf"
RESTART_CMD="rc-service mysql restart"
TEST_CMD="mysqld --help --verbose > /dev/null"
;;
apache2)
TARGET_FILE="/etc/apache2/httpd.conf"
RESTART_CMD="rc-service apache2 restart"
TEST_CMD="httpd -t"
;;
*)
TARGET_FILE="/etc/$SERVICE/$SERVICE.conf"
RESTART_CMD="rc-service $SERVICE restart"
TEST_CMD="true"
;;
esac
# Find backup file
if [ -n "$DATE" ]; then
BACKUP_FILE=$(find "$BACKUP_DIR/$DATE" -name "$(basename "$TARGET_FILE")*" | head -1)
else
BACKUP_FILE=$(find "$BACKUP_DIR" -name "$(basename "$TARGET_FILE")*" | sort -r | head -1)
fi
if [ -z "$BACKUP_FILE" ] || [ ! -f "$BACKUP_FILE" ]; then
echo "❌ No backup found for $SERVICE"
list_backups
exit 1
fi
echo "Rolling back $SERVICE configuration"
echo "Target: $TARGET_FILE"
echo "Backup: $BACKUP_FILE"
echo ""
# Create emergency backup of current config
EMERGENCY_BACKUP="/tmp/$(basename "$TARGET_FILE").emergency.$(date +%Y%m%d_%H%M%S)"
cp "$TARGET_FILE" "$EMERGENCY_BACKUP"
echo "Emergency backup created: $EMERGENCY_BACKUP"
# Restore configuration
cp "$BACKUP_FILE" "$TARGET_FILE"
# Test configuration
echo "Testing configuration..."
if eval "$TEST_CMD"; then
echo "✅ Configuration test passed"
# Restart service
echo "Restarting $SERVICE..."
if eval "$RESTART_CMD"; then
echo "✅ Service restarted successfully"
echo "Configuration rollback completed"
# Remove emergency backup
rm -f "$EMERGENCY_BACKUP"
else
echo "❌ Service restart failed, restoring emergency backup"
cp "$EMERGENCY_BACKUP" "$TARGET_FILE"
eval "$RESTART_CMD"
exit 1
fi
else
echo "❌ Configuration test failed, restoring emergency backup"
cp "$EMERGENCY_BACKUP" "$TARGET_FILE"
exit 1
fi
EOF
chmod +x /usr/local/bin/rollback-config
# Example usage
# rollback-config nginx
# rollback-config nginx 20250603
# rollback-config list
🔧 Advanced Configuration Techniques
Configuration Validation Framework
# Create configuration validation framework
mkdir -p /etc/config-validators
# Nginx validator
cat > /etc/config-validators/nginx << 'EOF'
#!/bin/sh
# Nginx configuration validator
CONFIG_FILE="/etc/nginx/nginx.conf"
validate_nginx_config() {
local errors=""
# Basic syntax check
if ! nginx -t 2>/dev/null; then
errors="$errors\n- Nginx syntax check failed"
fi
# Security checks
if grep -q "server_tokens on" "$CONFIG_FILE"; then
errors="$errors\n- Security: server_tokens should be off"
fi
if ! grep -q "X-Frame-Options" "$CONFIG_FILE"; then
errors="$errors\n- Security: Missing X-Frame-Options header"
fi
# Performance checks
if ! grep -q "gzip on" "$CONFIG_FILE"; then
errors="$errors\n- Performance: gzip compression not enabled"
fi
# Configuration completeness
if ! grep -q "error_log" "$CONFIG_FILE"; then
errors="$errors\n- Missing error_log directive"
fi
if [ -n "$errors" ]; then
echo "❌ Nginx configuration validation failed:"
echo "$errors"
return 1
else
echo "✅ Nginx configuration validation passed"
return 0
fi
}
validate_nginx_config
EOF
# SSH validator
cat > /etc/config-validators/ssh << 'EOF'
#!/bin/sh
# SSH configuration validator
CONFIG_FILE="/etc/ssh/sshd_config"
validate_ssh_config() {
local errors=""
# Basic syntax check
if ! sshd -t 2>/dev/null; then
errors="$errors\n- SSH syntax check failed"
fi
# Security checks
if grep -q "^PermitRootLogin yes" "$CONFIG_FILE"; then
errors="$errors\n- Security: Root login should be disabled"
fi
if grep -q "^PasswordAuthentication yes" "$CONFIG_FILE"; then
errors="$errors\n- Security: Password authentication should be disabled"
fi
if grep -q "^PermitEmptyPasswords yes" "$CONFIG_FILE"; then
errors="$errors\n- Security: Empty passwords should not be permitted"
fi
# Protocol version check
if grep -q "^Protocol 1" "$CONFIG_FILE"; then
errors="$errors\n- Security: SSH Protocol 1 is deprecated"
fi
if [ -n "$errors" ]; then
echo "❌ SSH configuration validation failed:"
echo "$errors"
return 1
else
echo "✅ SSH configuration validation passed"
return 0
fi
}
validate_ssh_config
EOF
# Make validators executable
chmod +x /etc/config-validators/*
# Configuration validation runner
cat > /usr/local/bin/validate-configs << 'EOF'
#!/bin/sh
# Run all configuration validators
VALIDATOR_DIR="/etc/config-validators"
FAILED_SERVICES=""
echo "Running configuration validation..."
echo "================================="
for validator in "$VALIDATOR_DIR"/*; do
if [ -x "$validator" ]; then
service_name=$(basename "$validator")
echo ""
echo "Validating $service_name:"
if "$validator"; then
echo "✅ $service_name validation passed"
else
echo "❌ $service_name validation failed"
FAILED_SERVICES="$FAILED_SERVICES $service_name"
fi
fi
done
echo ""
echo "Validation Summary:"
echo "=================="
if [ -n "$FAILED_SERVICES" ]; then
echo "❌ Failed services:$FAILED_SERVICES"
exit 1
else
echo "✅ All configuration validations passed"
exit 0
fi
EOF
chmod +x /usr/local/bin/validate-configs
# Run validation
validate-configs
Configuration Automation with Ansible
# Create Ansible-compatible configuration management
mkdir -p /etc/ansible/{playbooks,roles,inventory}
# Ansible inventory
cat > /etc/ansible/inventory/hosts << 'EOF'
[alpine_servers]
server1 ansible_host=192.168.1.10
server2 ansible_host=192.168.1.11
server3 ansible_host=192.168.1.12
[alpine_servers:vars]
ansible_user=root
ansible_ssh_private_key_file=/root/.ssh/id_rsa
EOF
# Nginx configuration playbook
cat > /etc/ansible/playbooks/configure_nginx.yml << 'EOF'
---
- name: Configure Nginx on Alpine Linux
hosts: alpine_servers
vars:
nginx_user: nginx
nginx_workers: auto
nginx_worker_connections: 1024
tasks:
- name: Install Nginx
apk:
name: nginx
state: present
- name: Create nginx user
user:
name: "{{ nginx_user }}"
system: yes
shell: /sbin/nologin
- name: Deploy nginx configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
backup: yes
notify: restart nginx
- name: Validate nginx configuration
command: nginx -t
changed_when: false
- name: Enable and start nginx
service:
name: nginx
enabled: yes
state: started
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
EOF
# Nginx Jinja2 template
cat > /etc/ansible/playbooks/templates/nginx.conf.j2 << 'EOF'
user {{ nginx_user }};
worker_processes {{ nginx_workers }};
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# Performance
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
# Hide nginx version
server_tokens off;
# Include additional configurations
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
EOF
# Configuration deployment script
cat > /usr/local/bin/deploy-ansible-config << 'EOF'
#!/bin/sh
# Deploy configurations using Ansible
PLAYBOOK="$1"
ENVIRONMENT="${2:-production}"
if [ -z "$PLAYBOOK" ]; then
echo "Usage: $0 <playbook> [environment]"
echo "Available playbooks:"
ls -1 /etc/ansible/playbooks/*.yml | xargs basename -s .yml
exit 1
fi
echo "Deploying $PLAYBOOK configuration to $ENVIRONMENT environment"
# Run ansible playbook
ansible-playbook \
-i /etc/ansible/inventory/hosts \
-l "$ENVIRONMENT" \
--check \
"/etc/ansible/playbooks/$PLAYBOOK.yml"
if [ $? -eq 0 ]; then
echo "Dry run completed successfully. Deploy for real? (y/N)"
read -r confirmation
if [ "$confirmation" = "y" ] || [ "$confirmation" = "Y" ]; then
ansible-playbook \
-i /etc/ansible/inventory/hosts \
-l "$ENVIRONMENT" \
"/etc/ansible/playbooks/$PLAYBOOK.yml"
fi
else
echo "❌ Dry run failed. Please check the configuration."
exit 1
fi
EOF
chmod +x /usr/local/bin/deploy-ansible-config
🔒 Security and Compliance
Configuration Security Scanning
# Create security scanner for configurations
cat > /usr/local/bin/scan-config-security << 'EOF'
#!/bin/sh
# Configuration security scanner
SCAN_RESULTS="/tmp/config-security-scan.txt"
CRITICAL_ISSUES=""
WARNING_ISSUES=""
scan_file_permissions() {
echo "=== File Permission Security Scan ===" >> "$SCAN_RESULTS"
# Check for world-writable config files
find /etc -type f -perm -002 2>/dev/null | while read file; do
echo "CRITICAL: World-writable config file: $file" >> "$SCAN_RESULTS"
CRITICAL_ISSUES="$CRITICAL_ISSUES\n- World-writable: $file"
done
# Check for files with incorrect ownership
find /etc -type f ! -user root 2>/dev/null | while read file; do
owner=$(stat -c "%U" "$file")
echo "WARNING: Non-root owned config file: $file (owner: $owner)" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- Non-root owned: $file"
done
}
scan_ssh_security() {
echo "=== SSH Security Scan ===" >> "$SCAN_RESULTS"
if [ -f "/etc/ssh/sshd_config" ]; then
# Check for dangerous SSH settings
if grep -q "^PermitRootLogin yes" /etc/ssh/sshd_config; then
echo "CRITICAL: SSH root login enabled" >> "$SCAN_RESULTS"
CRITICAL_ISSUES="$CRITICAL_ISSUES\n- SSH root login enabled"
fi
if grep -q "^PasswordAuthentication yes" /etc/ssh/sshd_config; then
echo "WARNING: SSH password authentication enabled" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- SSH password auth enabled"
fi
if grep -q "^PermitEmptyPasswords yes" /etc/ssh/sshd_config; then
echo "CRITICAL: SSH empty passwords permitted" >> "$SCAN_RESULTS"
CRITICAL_ISSUES="$CRITICAL_ISSUES\n- SSH empty passwords allowed"
fi
fi
}
scan_web_server_security() {
echo "=== Web Server Security Scan ===" >> "$SCAN_RESULTS"
# Nginx security
if [ -f "/etc/nginx/nginx.conf" ]; then
if grep -q "server_tokens on" /etc/nginx/nginx.conf; then
echo "WARNING: Nginx server tokens enabled" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- Nginx server tokens exposed"
fi
if ! grep -q "X-Frame-Options" /etc/nginx/nginx.conf; then
echo "WARNING: Nginx missing X-Frame-Options header" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- Missing X-Frame-Options"
fi
fi
# Apache security
if [ -f "/etc/apache2/httpd.conf" ]; then
if grep -q "ServerTokens Full" /etc/apache2/httpd.conf; then
echo "WARNING: Apache server tokens full" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- Apache server tokens exposed"
fi
fi
}
scan_database_security() {
echo "=== Database Security Scan ===" >> "$SCAN_RESULTS"
# MySQL security
if [ -f "/etc/my.cnf" ]; then
if grep -q "bind-address.*0.0.0.0" /etc/my.cnf; then
echo "WARNING: MySQL bound to all interfaces" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- MySQL exposed to all interfaces"
fi
fi
# PostgreSQL security
if [ -f "/etc/postgresql/postgresql.conf" ]; then
if grep -q "listen_addresses.*'\*'" /etc/postgresql/postgresql.conf; then
echo "WARNING: PostgreSQL listening on all interfaces" >> "$SCAN_RESULTS"
WARNING_ISSUES="$WARNING_ISSUES\n- PostgreSQL exposed to all interfaces"
fi
fi
}
# Run all scans
echo "Starting configuration security scan..."
echo "========================================"
> "$SCAN_RESULTS" # Clear results file
scan_file_permissions
scan_ssh_security
scan_web_server_security
scan_database_security
# Generate report
echo ""
echo "Security Scan Results:"
echo "====================="
cat "$SCAN_RESULTS"
echo ""
echo "Summary:"
echo "========"
if [ -n "$CRITICAL_ISSUES" ]; then
echo "🚨 CRITICAL ISSUES FOUND:"
echo "$CRITICAL_ISSUES"
fi
if [ -n "$WARNING_ISSUES" ]; then
echo "⚠️ WARNING ISSUES FOUND:"
echo "$WARNING_ISSUES"
fi
if [ -z "$CRITICAL_ISSUES" ] && [ -z "$WARNING_ISSUES" ]; then
echo "✅ No security issues found"
fi
# Cleanup
rm -f "$SCAN_RESULTS"
EOF
chmod +x /usr/local/bin/scan-config-security
# Run security scan
scan-config-security
🎯 Best Practices and Guidelines
Configuration Management Checklist
# Create configuration management checklist
cat > /usr/local/share/config-management-checklist.md << 'EOF'
# Configuration Management Checklist
## Before Making Changes
- [ ] Document the reason for configuration changes
- [ ] Create backup of current configuration
- [ ] Test changes in non-production environment
- [ ] Review security implications
- [ ] Check for dependencies and conflicts
## During Changes
- [ ] Use version control for tracking
- [ ] Apply principle of least privilege
- [ ] Validate configuration syntax
- [ ] Test configuration in isolated environment
- [ ] Document all modifications
## After Changes
- [ ] Verify service functionality
- [ ] Run security scans
- [ ] Update monitoring and alerts
- [ ] Document rollback procedures
- [ ] Commit changes to version control
## Regular Maintenance
- [ ] Review configuration changes monthly
- [ ] Audit file permissions quarterly
- [ ] Update configuration templates
- [ ] Test rollback procedures
- [ ] Clean up old backups
EOF
🎉 Conclusion
Effective package configuration management in Alpine Linux requires systematic approaches, proper tooling, and consistent practices. By implementing version control, automation, and monitoring, you can maintain reliable, secure, and scalable configuration management systems.
Key takeaways:
- Use version control for all configuration changes 📝
- Implement automated validation and testing ✅
- Create comprehensive backup and rollback procedures 🔄
- Monitor configuration changes continuously 📊
- Apply security best practices consistently 🔒
With proper configuration management, your Alpine Linux systems will be more reliable, secure, and maintainable! 🚀