# 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 ISTI-CNR, Pisa, Italy