|
|
||
|---|---|---|
| defaults | ||
| files | ||
| handlers | ||
| meta | ||
| tasks | ||
| templates | ||
| tests | ||
| vars | ||
| .ansible-lint | ||
| .gitignore | ||
| LICENSE | ||
| README.md | ||
README.md
os-bootstrap
An Ansible role that performs early-stage OS bootstrapping for Linux servers. It runs before any role dependencies (rsyslog, firewall, NTP, etc.) and establishes the baseline system state: locale, timezone, hostname, package prerequisites, network configuration, disk management, sysctl tuning, and PKI infrastructure.
This role is designed to be the first dependency of higher-level roles such as basic-system-setup.
Requirements
- Ansible >= 2.9
- Python 3 on target hosts (this role installs additional Python packages needed by subsequent Ansible tasks)
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
Tasks run in the following order:
| Task File | Description | Condition |
|---|---|---|
http_client_proxy.yml |
Configures system-wide HTTP/HTTPS proxy environment variables | enable_env_proxy |
ansible-python3-pkgs.yml |
Installs Python 3 packages required by Ansible modules | always |
hostname.yml |
Sets the system hostname from inventory | explicitly_set_hostname |
locale.yml |
Generates and configures system locales | always |
timezone.yml |
Sets the system timezone | always |
etchosts-customizations.yml |
Adds custom entries to /etc/hosts |
always |
network-interfaces.yml |
Configures additional network interfaces via Netplan (Ubuntu) | ubuntu_configure_additional_interfaces |
additional_disks.yml |
Partitions, formats, and mounts additional disks | additional_disks |
swap_device.yml |
Configures a swap device | swap_device |
external_repos_el.yml |
Installs EPEL and optional elrepo repositories | RedHat family only |
basic_setup_el.yml |
EL/RedHat package install, SELinux configuration, service management | RedHat family only |
deb_general.yml |
Debian/Ubuntu package install, apt proxy, unattended upgrades, service cleanup | Debian family only |
sysctl.yml |
Writes custom kernel parameters to /etc/sysctl.d/ |
always |
grub_cmdline_parameters.yml |
Appends parameters to GRUB_CMDLINE_LINUX |
configure_grub_cmdline_parameters |
pki_dir.yml |
Creates the PKI directory hierarchy | always |
self_signed_certificate.yml |
Generates a self-signed certificate with mkcert | letsencrypt_acme_install is defined and true |
trusted_ca.yml |
Installs Let’s Encrypt and custom CA certificates into the system trust store | always |
certificate_from_private_ca.yml |
Requests a certificate from a private CA (mkcert) | mkcert_create_certificate and no Let’s Encrypt |
Sub-tasks for
deb_general.yml
| Task File | Description | Condition |
|---|---|---|
apt_proxy.yml |
Configures APT proxy in
/etc/apt/apt.conf.d/02proxy |
use_apt_proxy |
dist_upgrade.yml |
Performs a full distribution upgrade | dist_upgrade |
packages_deb.yml |
Installs common and additional packages | always |
remove_unneeded_pkgs.yml |
Removes unwanted packages (exim, snapd, lxd, etc.) | always |
pubkeys.yml |
Manages root SSH authorized keys | manage_root_ssh_keys |
unattended_upgrades.yml |
Configures unattended-upgrades for automatic security
updates |
always |
disable_services.yml |
Disables unwanted services | disable_some_not_needed_services |
Role Variables
Timezone and Locale
timezone: Europe/Rome
default_locale_lang: en_US.UTF-8
default_deb_locale_messages: C.UTF-8
default_el_locale_messages: en_US.UTF-8
locales_list:
- { name: "{{ default_locale_lang }}" }
- { name: en_US.UTF-8 }
- { name: en_US }
- { name: it_IT.UTF-8 }
- { name: it_IT }Hostname and /etc/hosts
explicitly_set_hostname: true
domain_name: "{{ ansible_domain }}"
# Inline block of hosts entries, e.g.:
# "192.168.1.10 host1.example.com host1"
custom_etc_hosts_entries: ""
custom_etc_hosts_entries_adjunct: ""Network Interfaces (Ubuntu / Netplan)
ubuntu_configure_additional_interfaces: false
ubuntu_configure_additional_int_dhcp_overrides: true
ubuntu_configure_additional_ints_list: []
# Example:
# ubuntu_configure_additional_ints_list:
# - name: eth1
# dhcp4: true
disable_ipv6: false
ipv6_sysctl_value: 1
ipv6_sysctl_file: /etc/sysctl.d/10-ipv6-disable.confSysctl
sysctl_custom_file: /etc/sysctl.d/90-custom-values.conf
sysctl_opts_reload: true
sysctl_custom_file_state: present
# Only name and value are mandatory
sysctl_custom_options: []
# - name: 'net.nf_conntrack_max'
# value: '32768'
# sysctlfile: '{{ sysctl_custom_file }}'
# sysctl_reload: '{{ sysctl_opts_reload }}'
# sysctlfile_state: '{{ sysctl_custom_file_state }}'GRUB
configure_grub_cmdline_parameters: false
grub_cmdline_additional_parameters: ""
# Example: "intel_iommu=on quiet"Additional Disks
additional_disks: false
disks_and_mountpoints_list: []
# - mountpoint: '/data'
# device: 'xvda3'
# fstype: 'xfs'
# opts: 'noatime'
# state: 'mounted'
# create_filesystem: trueSwap Device
swap_device: false
swap_device_name: /dev/vdxxxxxHTTP Client Proxy
enable_env_proxy: false
env_proxy_http_host: localhost
env_proxy_http_port: "3128"
env_proxy_http_protocol: http
env_proxy_https_protocol: "{{ env_proxy_http_protocol }}"
env_proxy_http_url: "{{ env_proxy_http_protocol }}://{{ env_proxy_http_host }}:{{ env_proxy_http_port }}"
env_proxy_https_url: "{{ env_proxy_http_url }}"
env_proxy_use_authentication: false
env_proxy_username: ""
env_proxy_password: ""
no_proxy_targets:
- ::1
- 127.0.0.1
- localhostPython 3 Packages for Ansible
ansible_python3_debs:
- python3-lxml
ansible_python3_el:
- python3-lxmlPKI Directory and Certificates
pki_dir: /etc/pki
pki_subdirs:
- certs
- keys
pki_install_a_custom_ca: false
# Self-signed certificate paths (used when letsencrypt is not available)
self_signed_cert: "{{ pki_dir }}/selfsigned/cert"
self_signed_fullchain: "{{ pki_dir }}/selfsigned/fullchain"
self_signed_key: "{{ pki_dir }}/selfsigned/privkey"
self_signed_subject: /CN={{ ansible_fqdn }} self signed
# Certificate from private CA (mkcert)
mkcert_create_certificate: false
mkcert_cert_name: "{{ ansible_fqdn }}.pem"
mkcert_cert_dest_path: "{{ pki_dir }}/certs"
mkcert_key_name: "{{ ansible_fqdn }}-key.pem"
mkcert_key_dest_path: "{{ pki_dir }}/keys"
mkcert_dsn_and_ip_list: "{{ ansible_fqdn }} {% for ip in ansible_all_ipv4_addresses %}{{ ip }} {% endfor %}"
mkcert_ca_host: localhostTrusted CA Certificates
trusted_ca_el_anchors_path: /etc/pki/ca-trust/source/anchors
trusted_ca_deb_path: /usr/local/share/ca-certificates
# Let's Encrypt intermediate CAs (normally already trusted by the OS)
trusted_ca_letsencrypt_install: false
trusted_ca_letsencrypt_ca_certificates_url: https://letsencrypt.org/certs
# Additional custom CAs to install
trusted_ca_additional_ca_files: []
# - { ca_url: 'https://example.com/foo-ca.pem', ca: 'foo-ca.pem', name: 'foo-ca' }EL/RedHat — External Repositories
centos_install_epel: true
centos_epel_repo_url: epel-release
centos_install_release_scl: false
rh_install_elrepo: falseEL/RedHat — Basic Setup
centos_pkg_state: latest
centos_packages_cleanup: true
# SELinux
selinux_policy_type: targeted
selinux_policy_state: enforcing
centos_selinux_daemons_dump_core: false
# Services
centos_disable_avahi: true
centos_remove_avahi: false
centos_disable_networkmanager: false
centos_remove_networkmanager: false
centos_services_to_be_disabled:
- acpid
# DNS (optional, for static resolver configuration)
centos_set_dns_servers: false
dns1: 208.67.220.220
dns2: 208.67.222.222
# Root SSH keys
manage_root_ssh_keys: trueDebian/Ubuntu — Package Management
use_apt_proxy: false
apt_proxy_url: http://localhost:3128
dist_upgrade: false
pkg_state: present
common_packages:
- acl
- curl
- wget
- htop
- vim-tiny
- psmisc
- tcpdump
- lsof
- strace
- rsync
- unzip
- tree
- bash-completion
- sudo
- less
# ... see defaults/main.yml for the full list
# Additional packages (define in your playbook or group_vars)
# additional_packages:
# - pkg1
# - pkg2Debian/Ubuntu — Package Cleanup
cleanup_base_packages: true
base_packages_to_remove:
- ppp
- at
- snapd
cleanup_exim_email_server: true
disable_apport_service: true
ubuntu_remove_lxd: trueDebian/Ubuntu — Unattended Upgrades
unatt_allowed_origins:
- ${distro_id}:${distro_codename}-security
unatt_autofix: "true"
unatt_minimalsteps: "false"
unatt_install_on_shutdown: "false"
unatt_email_on_error: "false"
unatt_autoremove: "true"
unatt_autoreboot: "false"
unatt_autoreboot_time: nowDebian/Ubuntu — Service Management
disable_some_not_needed_services: false
services_to_be_disabled:
- rpcbind
- atd
- acpidDependencies
None. This role is intentionally dependency-free so it can run before any other role.
Example Playbook
Normally you do not invoke os-bootstrap directly — it is
pulled in automatically as a dependency. If you need to run it
standalone:
---
- hosts: servers
become: true
roles:
- role: adellam.os_bootstrap
vars:
timezone: Europe/Rome
explicitly_set_hostname: true
disable_ipv6: false
sysctl_custom_options:
- name: net.nf_conntrack_max
value: "65536"With proxy and extra disk
---
- hosts: servers
become: true
roles:
- role: adellam.os_bootstrap
vars:
enable_env_proxy: true
env_proxy_http_host: proxy.example.com
env_proxy_http_port: "3128"
additional_disks: true
disks_and_mountpoints_list:
- mountpoint: /data
device: sdb1
fstype: xfs
opts: noatime
state: mounted
create_filesystem: trueEL with custom SELinux and EPEL
---
- hosts: el_servers
become: true
roles:
- role: adellam.os_bootstrap
vars:
centos_install_epel: true
selinux_policy_state: enforcing
selinux_policy_type: targeted
centos_pkg_state: latestTesting
source ~/ansible/ansible6/bin/activate
ansible-lintBasic test playbook is in tests/test.yml.
License
EUPL-1.2
Author Information
Andrea Dell’Amico andrea.dellamico@isti.cnr.it
ISTI-CNR, Pisa, Italy