hannseman.raspbian
ansible-raspbian
This role sets up a secure basic Raspbian environment with sensible defaults.
It will:
- Install specified system packages.
- Set the hostname.
- Set the locale.
- Use tmpfs for write-heavy directories to extend the SD-card lifespan.
- Change the default user's password.
- Set the default editor.
- Configure a secure SSH setup.
- Set up UFW (Uncomplicated Firewall).
- Modify the /boot/config.txt file.
- Run raspi-config.
- Configure Postfix to send emails through an SMTP relay.
- Enable unattended upgrades.
- Install Fail2ban.
- Set up Logwatch to send weekly reports.
It will not:
- Update system packages.
- Run
apt-get update
. Please do this in a pre_task. See Example Playbook. - Install security patches, but unattended upgrades will handle that.
Setup
- Install Python requirements by running
pip install -r requirements.txt
. - Install sshpass with
sudo apt-get install sshpass
. - Flash the SD-card with Raspbian Stretch Lite.
- Create an empty file named
ssh
in the boot partition of the flashed SD-card. - (Optional) To enable Wi-Fi, create a file called
wpa_supplicant.conf
in the boot partition of the flashed SD-card with this content:network={ ssid="your ssid" psk="your password" }
- Run the playbook.
Inventory
You need sshpass to run Ansible for the first time with the default password raspberry
. After that, password authentication over SSH will be disabled in favor of public key authentication, using keys defined in ssh_public_keys
. Your inventory should have:
[all:vars]
ansible_connection=ssh
ansible_user=pi
ansible_ssh_pass=raspberry
Variables
# Set the system hostname
system_hostname: "raspberrypi"
# Password for ansible_ssh_user (usually set to pi).
# NOTE: Change to something secure.
system_ssh_user_password: "raspberry"
# Salt for password encryption.
# NOTE: Change to something secure and random.
system_ssh_user_salt: "salt"
# System locale
system_locale: "en_US.UTF-8"
# System timezone
system_timezone: "Europe/Stockholm"
# List of tmpfs mounts to create.
system_tmpfs_mounts:
- { src: "/run", size: "10%", options: "nodev,noexec,nosuid" }
- { src: "/tmp", size: "10%", options: "nodev,nosuid" }
- { src: "/var/log", size: "10%", options: "nodev,noexec,nosuid" }
# Packages to install with apt-get
system_packages: []
# Default editor path
system_default_editor_path: "/usr/bin/vi"
# Logwatch settings
logwatch_tmp_dir: /var/cache/logwatch
logwatch_mailto: "root"
logwatch_detail: "Low"
logwatch_interval: "weekly"
postfix_hostname: "{{ ansible_hostname }}"
postfix_mailname: "{{ ansible_hostname }}"
postfix_mydestination:
- "{{ postfix_hostname }}"
- localdomain
- localhost
- localhost.localdomain
postfix_relayhost: smtp.gmail.com
postfix_relayhost_port: 587
# Your Gmail address
postfix_sasl_user:
# Your Gmail password
postfix_sasl_password:
postfix_smtp_tls_cafile: /etc/ssl/certs/ca-certificates.crt
# Update /boot/config.txt with `{{ key }}: {{ value }}`
rpi_boot_config: {}
# Run raspi-config commands
rpi_cmdline_config: {}
ssh_sshd_config: "/etc/ssh/sshd_config"
# List of public keys for SSH
ssh_public_keys: []
# Banner for SSH connection
ssh_banner:
# UFW rules to allow SSH
ufw_rules:
- { rule: "allow", port: "22", proto: "tcp" }
# Allow IGMP traffic setting
ufw_allow_igmp: false
# Recipient for unattended upgrades report
unattended_upgrades_email_address: root
# Should the system reboot if /var/run/reboot-required is found?
unattended_upgrades_auto_reboot: false
# Internal variable for testing - do not use.
ansible_raspbian_testing: false
Example Playbook
- hosts: servers
become: true
pre_tasks:
- name: Update apt cache
apt:
cache_valid_time: 600
roles:
- role: hannseman.raspbian
vars:
system_packages:
- apt-transport-https
- vim
system_default_editor_path: "/usr/bin/vim.basic"
system_ssh_user_password: hunter2
system_ssh_user_salt: pepper
postfix_sasl_user: [email protected]
postfix_sasl_password: hunter2
ssh_public_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJXTGInmtpoG9rYmT/3DpL+0o/sH2shys+NwJLo8NnCj