20 Essential Ansible Playbook Examples for Linux System Administration
This guide provides 20 practical Ansible playbook examples that you can use immediately for Linux system administration. Each example is production-ready and follows Ansible best practices. Copy, customize, and automate your infrastructure.
📑 Table of Contents
- 1. Update All Packages
- 2. Create Users with SSH Keys
- 3. Install and Configure Nginx
- 4. Configure Firewall Rules
- 5. Deploy Docker and Docker Compose
- 6. Setup PostgreSQL Database
- 7. Configure SSH Hardening
- 8. Setup Automated Backups
- 9. Install and Configure Fail2ban
- 10. Deploy SSL Certificates with Certbot
- 11. Configure NTP Time Sync
- 12. Setup Log Rotation
- 13. Deploy Application from Git
- 14. Check Disk Space and Alert
- 15. Configure Swap Space
- Quick Reference
- Conclusion
1. Update All Packages
---
- name: Update all packages on servers
hosts: all
become: true
tasks:
- name: Update packages (RHEL/CentOS)
ansible.builtin.dnf:
name: "*"
state: latest
update_cache: true
when: ansible_os_family == "RedHat"
- name: Update packages (Ubuntu/Debian)
ansible.builtin.apt:
upgrade: dist
update_cache: true
when: ansible_os_family == "Debian"
2. Create Users with SSH Keys
---
- name: Create users with SSH keys
hosts: all
become: true
vars:
users:
- name: john
ssh_key: "ssh-rsa AAAA... john@example.com"
groups: ["wheel", "docker"]
- name: jane
ssh_key: "ssh-rsa AAAA... jane@example.com"
groups: ["developers"]
tasks:
- name: Create user accounts
ansible.builtin.user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: /bin/bash
create_home: true
state: present
loop: "{{ users }}"
- name: Add SSH authorized keys
ansible.posix.authorized_key:
user: "{{ item.name }}"
key: "{{ item.ssh_key }}"
state: present
loop: "{{ users }}"
3. Install and Configure Nginx
---
- name: Install and configure Nginx
hosts: webservers
become: true
vars:
nginx_port: 80
server_name: example.com
tasks:
- name: Install Nginx
ansible.builtin.package:
name: nginx
state: present
- name: Deploy nginx configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/{{ server_name }}.conf
mode: "0644"
notify: Reload nginx
- name: Ensure nginx is running
ansible.builtin.service:
name: nginx
state: started
enabled: true
handlers:
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
4. Configure Firewall Rules
---
- name: Configure firewall
hosts: all
become: true
vars:
allowed_ports:
- { port: 22, proto: tcp }
- { port: 80, proto: tcp }
- { port: 443, proto: tcp }
tasks:
- name: Install firewalld
ansible.builtin.package:
name: firewalld
state: present
- name: Start firewalld
ansible.builtin.service:
name: firewalld
state: started
enabled: true
- name: Allow ports through firewall
ansible.posix.firewalld:
port: "{{ item.port }}/{{ item.proto }}"
permanent: true
immediate: true
state: enabled
loop: "{{ allowed_ports }}"
5. Deploy Docker and Docker Compose
---
- name: Install Docker
hosts: docker_hosts
become: true
tasks:
- name: Install required packages
ansible.builtin.package:
name:
- dnf-plugins-core
- curl
state: present
- name: Add Docker repository
ansible.builtin.yum_repository:
name: docker-ce
description: Docker CE Repository
baseurl: https://download.docker.com/linux/centos/$releasever/$basearch/stable
gpgcheck: true
gpgkey: https://download.docker.com/linux/centos/gpg
enabled: true
- name: Install Docker
ansible.builtin.package:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
- name: Start Docker service
ansible.builtin.service:
name: docker
state: started
enabled: true
- name: Add user to docker group
ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: true
6. Setup PostgreSQL Database
---
- name: Install and configure PostgreSQL
hosts: databases
become: true
vars:
postgres_version: 15
db_name: myapp
db_user: appuser
db_password: "{{ vault_db_password }}"
tasks:
- name: Install PostgreSQL
ansible.builtin.package:
name:
- postgresql-server
- postgresql-contrib
- python3-psycopg2
state: present
- name: Initialize PostgreSQL
ansible.builtin.command: postgresql-setup --initdb
args:
creates: /var/lib/pgsql/data/PG_VERSION
- name: Start PostgreSQL
ansible.builtin.service:
name: postgresql
state: started
enabled: true
- name: Create database
community.postgresql.postgresql_db:
name: "{{ db_name }}"
state: present
become_user: postgres
- name: Create database user
community.postgresql.postgresql_user:
name: "{{ db_user }}"
password: "{{ db_password }}"
db: "{{ db_name }}"
priv: ALL
state: present
become_user: postgres
7. Configure SSH Hardening
---
- name: Harden SSH configuration
hosts: all
become: true
tasks:
- name: Configure SSH settings
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
validate: sshd -t -f %s
loop:
- { regexp: "^#?PermitRootLogin", line: "PermitRootLogin no" }
- { regexp: "^#?PasswordAuthentication", line: "PasswordAuthentication no" }
- { regexp: "^#?X11Forwarding", line: "X11Forwarding no" }
- { regexp: "^#?MaxAuthTries", line: "MaxAuthTries 3" }
- { regexp: "^#?Protocol", line: "Protocol 2" }
notify: Restart sshd
handlers:
- name: Restart sshd
ansible.builtin.service:
name: sshd
state: restarted
8. Setup Automated Backups
---
- name: Configure automated backups
hosts: all
become: true
vars:
backup_dirs:
- /etc
- /home
- /var/www
backup_destination: /backup
retention_days: 30
tasks:
- name: Create backup directory
ansible.builtin.file:
path: "{{ backup_destination }}"
state: directory
mode: "0700"
- name: Deploy backup script
ansible.builtin.template:
src: backup.sh.j2
dest: /usr/local/bin/backup.sh
mode: "0755"
- name: Schedule daily backup
ansible.builtin.cron:
name: "Daily backup"
minute: "0"
hour: "2"
job: "/usr/local/bin/backup.sh >> /var/log/backup.log 2>&1"
9. Install and Configure Fail2ban
---
- name: Install and configure Fail2ban
hosts: all
become: true
tasks:
- name: Install Fail2ban
ansible.builtin.package:
name: fail2ban
state: present
- name: Configure Fail2ban jail
ansible.builtin.copy:
dest: /etc/fail2ban/jail.local
content: |
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 3
mode: "0644"
notify: Restart fail2ban
- name: Start Fail2ban
ansible.builtin.service:
name: fail2ban
state: started
enabled: true
handlers:
- name: Restart fail2ban
ansible.builtin.service:
name: fail2ban
state: restarted
10. Deploy SSL Certificates with Certbot
---
- name: Setup SSL with Certbot
hosts: webservers
become: true
vars:
domain: example.com
email: admin@example.com
tasks:
- name: Install Certbot
ansible.builtin.package:
name:
- certbot
- python3-certbot-nginx
state: present
- name: Obtain SSL certificate
ansible.builtin.command: >
certbot --nginx -d {{ domain }} -d www.{{ domain }}
--email {{ email }}
--agree-tos
--non-interactive
args:
creates: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
- name: Setup auto-renewal cron
ansible.builtin.cron:
name: "Certbot renewal"
minute: "0"
hour: "3"
job: "certbot renew --quiet"
11. Configure NTP Time Sync
---
- name: Configure time synchronization
hosts: all
become: true
vars:
ntp_servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
tasks:
- name: Install chrony
ansible.builtin.package:
name: chrony
state: present
- name: Configure chrony
ansible.builtin.template:
src: chrony.conf.j2
dest: /etc/chrony.conf
mode: "0644"
notify: Restart chrony
- name: Enable chrony service
ansible.builtin.service:
name: chronyd
state: started
enabled: true
handlers:
- name: Restart chrony
ansible.builtin.service:
name: chronyd
state: restarted
12. Setup Log Rotation
---
- name: Configure log rotation
hosts: all
become: true
tasks:
- name: Configure application log rotation
ansible.builtin.copy:
dest: /etc/logrotate.d/myapp
content: |
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 root root
sharedscripts
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
mode: "0644"
13. Deploy Application from Git
---
- name: Deploy application from Git
hosts: webservers
become: true
vars:
app_repo: https://github.com/myorg/myapp.git
app_path: /var/www/myapp
app_branch: main
tasks:
- name: Install Git
ansible.builtin.package:
name: git
state: present
- name: Clone/update repository
ansible.builtin.git:
repo: "{{ app_repo }}"
dest: "{{ app_path }}"
version: "{{ app_branch }}"
force: true
notify: Restart application
- name: Set permissions
ansible.builtin.file:
path: "{{ app_path }}"
owner: www-data
group: www-data
recurse: true
handlers:
- name: Restart application
ansible.builtin.service:
name: myapp
state: restarted
14. Check Disk Space and Alert
---
- name: Check disk space
hosts: all
vars:
disk_threshold: 80
tasks:
- name: Get disk usage
ansible.builtin.shell: df -h / | tail -1 | awk "{print $5}" | tr -d "%"
register: disk_usage
changed_when: false
- name: Alert if disk usage is high
ansible.builtin.debug:
msg: "WARNING: Disk usage is {{ disk_usage.stdout }}% on {{ inventory_hostname }}"
when: disk_usage.stdout | int > disk_threshold
- name: Fail if disk critically full
ansible.builtin.fail:
msg: "CRITICAL: Disk usage is {{ disk_usage.stdout }}%"
when: disk_usage.stdout | int > 95
15. Configure Swap Space
---
- name: Configure swap space
hosts: all
become: true
vars:
swap_size: 2G
swap_file: /swapfile
tasks:
- name: Check if swap exists
ansible.builtin.stat:
path: "{{ swap_file }}"
register: swap_status
- name: Create swap file
ansible.builtin.command: fallocate -l {{ swap_size }} {{ swap_file }}
when: not swap_status.stat.exists
- name: Set swap file permissions
ansible.builtin.file:
path: "{{ swap_file }}"
mode: "0600"
when: not swap_status.stat.exists
- name: Make swap
ansible.builtin.command: mkswap {{ swap_file }}
when: not swap_status.stat.exists
- name: Enable swap
ansible.builtin.command: swapon {{ swap_file }}
when: not swap_status.stat.exists
- name: Add to fstab
ansible.builtin.lineinfile:
path: /etc/fstab
line: "{{ swap_file }} none swap sw 0 0"
state: present
Quick Reference
| Example | Use Case |
|---|---|
| 1-5 | Basic server setup |
| 6 | Database provisioning |
| 7-9 | Security hardening |
| 10-11 | SSL and time sync |
| 12-15 | Maintenance tasks |
Conclusion
These playbook examples cover common Linux administration tasks. Customize them for your environment, store them in Git, and build your automation library over time. Remember to test in staging before production deployment.
Was this article helpful?
R
About Ramesh Sundararamaiah
Red Hat Certified Architect
Expert in Linux system administration, DevOps automation, and cloud infrastructure. Specializing in Red Hat Enterprise Linux, CentOS, Ubuntu, Docker, Ansible, and enterprise IT solutions.