12 KiB
basic-system-setup
An Ansible role that configures Linux servers at the service layer: SSH hardening, intrusion prevention (Fail2ban), Message of the Day, cloud-init management, NFS serving, autofs, tmpreaper, and Dell server utilities.
Early-stage OS bootstrap tasks (locale, timezone, hostname, packages, sysctl, PKI, etc.) are handled by the os-bootstrap dependency, which always runs first.
Requirements
- Ansible >= 2.9
- The
os-bootstrapdependency role (declared inmeta/main.yml, resolved automatically)
Ansible Collections Required
ansible-galaxy collection install ansible.posix
ansible-galaxy collection install community.generalSupported Platforms
- Ubuntu 20.04 (Focal), 22.04 (Jammy), 24.04 (Noble)
- Debian 11 (Bullseye), 12 (Bookworm)
- RHEL / CentOS Stream / Rocky Linux / AlmaLinux 8, 9, 10
Task Descriptions
| Task File | Description | Condition |
|---|---|---|
cloud_init.yml |
Disables cloud-init network config; optionally removes the package | always |
sshd_config.yml |
Deploys a hardened /etc/ssh/sshd_config from
template |
sshd_install_config |
motd.yml |
Configures the Message of the Day | motd_setup |
fail2ban.yml |
Installs and configures Fail2ban with SSH, DDoS, and recidive jails | fail2ban_enabled |
dell_utilities.yml |
Installs Dell DSU, srvadmin, and syscfg on bare-metal Dell servers | Dell hardware + bare metal |
tuned_el.yml |
Applies a tuned profile on EL/RedHat | RedHat family only |
autofs.yml |
Manages autofs configuration and NFS/CIFS mount maps | autofs_client_mountpoint |
tmpreaper.yml |
Installs and configures tmpreaper for /tmp cleanup |
always |
ganesha-nfs.yml |
Installs and configures NFS Ganesha user-space NFS server | nfs_server_ganesha_enabled |
nfs-kernel-server.yml |
Installs and configures the kernel NFS server | nfs_server_enabled and not Ganesha |
custom_bashrc.yml |
Deploys custom .bashrc and shell history settings |
always |
Role Variables
Cloud-init
cloud_init_disable_netconfig: false # write 99-disable-network-config.cfg
cloud_init_remove_pkg: true # remove cloud-init after first bootSSHD Configuration
sshd_install_config: true
sshd_port: 22
sshd_config_dir: /etc/ssh
sshd_config_file: sshd_config
# Authentication
sshd_password_authentication: "no"
sshd_permit_empty_passwords: "no"
sshd_permit_root_login: prohibit-password # "no", "yes", "prohibit-password"
sshd_pubkey_authentication: "yes"
sshd_strict_mode: "yes"
sshd_max_auth_tries: 6
sshd_max_sessions: 10
sshd_login_grace_time: 120
# PAM
sshd_use_pam: "yes"
sshd_pam_service_name: "" # OpenSSH 9.8+ only
# Keyboard-interactive (OTP/s-key only)
sshd_kbd_interactive_authentication: "no"
# Tunneling / forwarding
sshd_permit_tunnel: "no"
sshd_x11_forwarding: "no"
sshd_agent_forwarding: "yes"
sshd_tcp_forwarding: "no"
sshd_permit_user_environment: "no"
sshd_gateway_ports: "no"
# GSSAPI
sshd_gssapi_authentication: "no"
sshd_gssapi_cleanup_credentials: "yes"
# Logging
sshd_syslog_facility: AUTH
sshd_log_level: INFO
# Connection keepalive / rate limiting
sshd_tcp_keep_alive: "yes"
sshd_client_alive_interval: 0
sshd_client_alive_count_max: 3
sshd_max_startups: 10:30:100 # start:rate:full
# Display
sshd_print_motd: "no"
sshd_print_last_log: "yes"
sshd_banner_path: none # e.g. /etc/issue.net
# Host keys (override only for custom paths)
sshd_host_keys:
- /etc/ssh/ssh_host_rsa_key
- /etc/ssh/ssh_host_ecdsa_key
- /etc/ssh/ssh_host_ed25519_key
# Ciphers / MACs / KEX — leave empty to use distribution defaults
sshd_ciphers: ""
sshd_macs: ""
sshd_kex_algorithms: ""
sshd_host_key_algorithms: ""
# Version-specific options (included only when the distribution's OpenSSH supports them)
sshd_include_config_d: true # Include sshd_config.d/*.conf (OpenSSH 8.2+)
sshd_per_source_max_startups: "" # Max connections per source IP (OpenSSH 8.5+)
sshd_per_source_net_block_size: "" # CIDR grouping for source IPs (OpenSSH 8.5+)
sshd_required_rsa_size: "" # Min RSA key size in bits (OpenSSH 9.1+)
sshd_channel_timeout: "" # e.g. "session:*=30m" (OpenSSH 9.2+)
sshd_unused_connection_timeout: "" # Close idle connections (OpenSSH 9.2+)
sshd_per_source_penalties: "" # Penalty-based rate limiting (OpenSSH 9.8+)
sshd_per_source_penalty_exempt_list: ""
# SFTP
sshd_enable_sftp_subsystem: true
sshd_enable_sftp_jail: false
sshd_sftp_chroot_match_group: filetransfer
sshd_sftp_chroot_directory: "%h"
sshd_sftp_force_command: internal-sftp
# Additional Match blocks
sshd_match_blocks: []
# Example:
# sshd_match_blocks:
# - criteria: "User admin"
# options:
# - PasswordAuthentication: "yes"
# - AllowTcpForwarding: "yes"OpenSSH version reference:
| Distribution | OpenSSH version |
|---|---|
| Ubuntu 20.04 (Focal) | 8.2 |
| Ubuntu 22.04 (Jammy) | 8.9 |
| Ubuntu 24.04 (Noble) | 9.6 |
| Debian 11 (Bullseye) | 8.4 |
| Debian 12 (Bookworm) | 9.2 |
| EL 8 | 8.0 |
| EL 9 | 8.7 |
| EL 10 | 9.8 |
Fail2ban — Debian/Ubuntu
fail2ban_enabled: true
f2b_ban_time: 86400 # seconds; 86400 = 1 day
f2b_findtime: 600
f2b_maxretry: 5
f2b_ddos_findtime: 120
f2b_ddos_maxretry: 200
f2b_default_backend: auto
f2b_usedns: warn
f2b_dest_email: sysadmin@{{ domain_name }}
f2b_sender_email: sysadmin@{{ domain_name }}
f2b_default_banaction: iptables-multiport
f2b_default_action: action_ # ban only, no email
f2b_default_iptableschain: INPUT
# Jail toggles
f2b_ssh_enabled: true
f2b_ssh_ddos_enabled: true
f2b_apache_ddos_enabled: false
f2b_apache_auth_enabled: false
f2b_apache_noscript_enabled: false
f2b_apache_overflow_enabled: false
f2b_php_url_fopen: false
f2b_nginx_auth_enabled: false
f2b_nginx_ddos_enabled: false
f2b_vsftpd_enabled: false
f2b_vsftpd_logpath: /var/log/vsftpd.log
f2b_recidive_enabled: true
f2b_recidive_findtime: 604800 # 1 week
f2b_recidive_ban_time: 14515200 # 24 weeksFail2ban — EL/RedHat
fail2ban_logtarget: SYSLOG
fail2ban_bantime: 600000
fail2ban_findtime: 4800
fail2ban_maxretry: 2
fail2ban_sshd_enabled: true
fail2ban_sshd_ddos_enabled: true
fail2ban_nginx_auth_enabled: false
fail2ban_apache_auth_enabled: false
fail2ban_php_url_fopen_enabled: false
fail2ban_vsftpd_enabled: falseMOTD
motd_setup: true
motd_additional_text: "\nThis host runs services\n"
# Debian/Ubuntu packages installed for dynamic MOTD
deb_motd_packages:
- update-notifier-common
- landscape-commonAutofs
autofs_client_mountpoint: false # set to true to manage autofs
autofs_maps: []
# - map_name: 'data'
# mountpoint_prefix: '/'
# path: 'data'
# nfs_server: 'nfs.example.com'
# remote_export: '/export'
# is_home: false
# force_ownership: false
# owner_uid: 1000
# owner_gid: 1000
# permissions: "0750"Tmpreaper
tmpreaper_install: false
tmpreaper_time: 7d
tmpreaper_dirs: /tmp/.
tmpreaper_use_ctime: true
tmpreaper_protect_extra: ""
tmpreaper_extra_dirs: ""
tmpreaper_delay: "256"
tmpreaper_additional_options: ""NFS Kernel Server
nfs_server_enabled: false
nfs_server_exports: []
# - name: export_filename
# id: 1
# path: /export
# options: 'rw,sync,fsid=1,root_squash,no_wdelay'
# clients:
# - host1
# - hostNNFS Ganesha Server
nfs_server_ganesha_enabled: false # mirrors nfs_server_enabled by default
nfs_server_ganesha_server_protocols: "4"
nfs_server_ganesha_path_pseudo: false
nfs_server_ganesha_mdcache: false
nfs_server_ganesha_mdcache_hwmark: 100000
nfs_server_ganesha_exports: []
# - name: export_filename
# id: 1
# path: /export
# pseudo: /nfs_export
# access_type: 'RW' # optional, default RW
# protocols: '4' # optional
# squash: 'root_squash' # optional
# disable_acl: 'false' # optional
# sectype: 'sys' # optional
# nfs_commit: 'false' # optional
# delegations: 'none' # optional
# fsal: 'VFS'
# clients:
# - host1Tuned (EL/RedHat only)
centos_tuned_enabled: true
centos_tuned_profile: "{{ centos_guest_tuned_profile }}"
centos_guest_tuned_profile: virtual-guest
centos_host_tuned_profile: virtual-hostDell Server Utilities
Runs automatically on bare-metal Dell servers
('Dell' in ansible_system_vendor and
ansible_virtualization_role == 'host'). No variables to set
for basic operation.
dell_utilities_installer_url: http://linux.dell.com/repo/hardware/dsu/bootstrap.cgi
dell_utilities_base_dir: /opt/dell_dsu
dell_utilities_packages:
- dell-system-update
- srvadmin-all
- syscfg
dell_utilities_raid_packages:
- raidcfgCustom Bash Configuration
bash_customize_skel_bashrc: false # deploy custom /etc/skel/.bashrc
bash_customize_root_bashrc: false # deploy custom /root/.bashrc
bash_customize_root_history_settings: false # deploy extended history settings for root
bash_custom_history_directory: /var/log/users_root_historyDependencies
This role declares the following dependencies in
meta/main.yml. They are resolved automatically when the
role is installed.
| Role | Required | Condition | Purpose |
|---|---|---|---|
| os-bootstrap | yes | always | Early-stage OS setup (locale, timezone, hostname, packages, sysctl, PKI, etc.) |
| rsyslog | yes | always | Centralized logging |
| linux-firewall | yes | always | Firewall management |
| ntp | yes | always | Time synchronization |
| letsencrypt-acme-sh-client | no | letsencrypt_acme_install: true |
TLS certificate provisioning |
| zabbix-agent | no | zabbix_agent_install: true |
Monitoring agent |
| prometheus-node-exporter | no | prometheus_enabled: true |
Metrics exporter |
Example Playbook
Minimal
---
- hosts: servers
become: true
roles:
- role: basic-system-setupSSH hardening + Fail2ban with nginx protection
---
- hosts: webservers
become: true
roles:
- role: basic-system-setup
vars:
sshd_permit_root_login: "no"
sshd_password_authentication: "no"
fail2ban_enabled: true
f2b_nginx_ddos_enabled: true
f2b_nginx_auth_enabled: true
motd_additional_text: "\nWeb Server - Production\n"NFS kernel server
---
- hosts: nfs_servers
become: true
roles:
- role: basic-system-setup
vars:
nfs_server_enabled: true
nfs_server_ganesha_enabled: false
nfs_server_exports:
- name: data_export
id: 1
path: /srv/nfs/data
options: 'rw,sync,no_subtree_check,root_squash'
clients:
- 10.0.0.0/8Autofs NFS mounts
---
- hosts: clients
become: true
roles:
- role: basic-system-setup
vars:
autofs_client_mountpoint: true
autofs_maps:
- map_name: data
mountpoint_prefix: /
path: data
nfs_server: nfs.example.com
remote_export: /export/data
is_home: falseTesting
source ~/ansible/ansible6/bin/activate
ansible-lintMolecule tests are available under molecule/default/ and
target Ubuntu 22.04 (Jammy) and Rocky Linux 9.
molecule test # full cycle
molecule converge # apply only
molecule verify # idempotency / verification
molecule destroy # teardownLicense
EUPL-1.2
Author Information
Andrea Dell’Amico andrea.dellamico@isti.cnr.it
ISTI-CNR, Pisa, Italy