ansible-role-basic-system-s.../README.md

424 lines
12 KiB
Markdown

# 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](https://gitea-s2i2s.isti.cnr.it/ISTI-ansible-roles/ansible-role-os-bootstrap) dependency, which always runs first.
## Requirements
- Ansible >= 2.9
- The `os-bootstrap` dependency role (declared in `meta/main.yml`, resolved automatically)
### Ansible Collections Required
```bash
ansible-galaxy collection install ansible.posix
ansible-galaxy collection install community.general
```
## Supported 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
```yaml
cloud_init_disable_netconfig: false # write 99-disable-network-config.cfg
cloud_init_remove_pkg: true # remove cloud-init after first boot
```
### SSHD Configuration
```yaml
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
```yaml
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 weeks
```
### Fail2ban — EL/RedHat
```yaml
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: false
```
### MOTD
```yaml
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-common
```
### Autofs
```yaml
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
```yaml
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
```yaml
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
# - hostN
```
### NFS Ganesha Server
```yaml
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:
# - host1
```
### Tuned (EL/RedHat only)
```yaml
centos_tuned_enabled: true
centos_tuned_profile: "{{ centos_guest_tuned_profile }}"
centos_guest_tuned_profile: virtual-guest
centos_host_tuned_profile: virtual-host
```
### Dell 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.
```yaml
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:
- raidcfg
```
### Custom Bash Configuration
```yaml
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_history
```
## Dependencies
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
```yaml
---
- hosts: servers
become: true
roles:
- role: basic-system-setup
```
### SSH hardening + Fail2ban with nginx protection
```yaml
---
- 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
```yaml
---
- 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/8
```
### Autofs NFS mounts
```yaml
---
- 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: false
```
## Testing
```bash
source ~/ansible/ansible6/bin/activate
ansible-lint
```
Molecule tests are available under `molecule/default/` and target Ubuntu 22.04 (Jammy) and Rocky Linux 9.
```bash
molecule test # full cycle
molecule converge # apply only
molecule verify # idempotency / verification
molecule destroy # teardown
```
## License
EUPL-1.2
## Author Information
Andrea Dell'Amico <andrea.dellamico@isti.cnr.it>
ISTI-CNR, Pisa, Italy