Quick start guide

For the users who want to try the role quickly this guide provides an example of how to:

  • Configure Ansible and install the role

  • Create inventory and playbook

Then, on the controller, run the playbook and configure the remote host:

  • Set hostname and timezone

  • Install packages

  • Create users and update authorized SSH keys

  • Configure sshd and sudo.

Requirements on the remote host

  • Password-less ssh by admin (or any other user by your choice)

  • Login shell for admin is /bin/sh

  • User admin is granted unlimited sudo

  • Python and Perl are installed.


Configure Ansible. Fit the paths to the inventory (3) and to the roles (4) to your needs. Disable retry_files (5). Don’t’ display ok and skipped hosts (6-8). Pipelining (12) should speedup the execution of the playbook

 1shell> cat ansible.cfg
 3inventory = $PWD/hosts
 4roles_path = $HOME/.ansible/roles
 5retry_files_enabled = false
 6stdout_callback = default
 9log_path = /var/log/ansible.log
12pipelining = true

Install the role vbotka.freebsd_postinstall

shell> ansible-galaxy role install vbotka.freebsd_postinstall

Install the library vbotka.ansible_lib

shell> ansible-galaxy role install vbotka.ansible_lib

Install the collections if necessary

shell> ansible-galaxy collection install ansible.posix
shell> ansible-galaxy collection install community.general

Review the role

1shell> ls ~/.ansible/roles/vbotka.freebsd_postinstall
2contrib  defaults  docs  handlers  LICENSE  meta  README.md
3tasks  templates  tests  vars

Inventory and playbook

Create the inventory hosts

1shell> cat hosts
2test_14.example.com ansible_host=

Create the playbook playbook.yml for single host test_14.example.com

 1shell> cat playbook.yml
 2- hosts: test_14.example.com
 3  gather_facts: true
 4  connection: ssh
 5  remote_user: admin
 6  become: true
 7  become_user: root
 8  become_method: sudo
 9  roles:
10    - vbotka.freebsd_postinstall

Test syntax of the playbook

1shell> ansible-playbook playbook.yml --syntax-check
3playbook: playbook.yml

Set hostname and timezone

Create host_vars with customized variables. Enable hostname (2) and timezone (5). Disable debug output (7) and backup of changed files (8)

1shell> cat host_vars/test_14.example.com/fp-common.yml
2fp_hostname: true
3rc_conf_hostname: test_14.example.com
4fp_domain: example.com
5fp_timezone: true
6fp_zoneinfo: UTC
7fp_debug: false
8fp_backup: false

Set hostname and timezone

 1shell> ansible-playbook playbook.yml -t fp_hostname,fp_timezone
 3PLAY [test_14.example.com] *******************************************************************
 5TASK [vbotka.freebsd_postinstall : hostname: Configure hostname in /etc/rc.conf] *************
 6changed: [test_14.example.com] => (item={'key': 'hostname', 'value': 'test_14.example.com'})
 8RUNNING HANDLER [vbotka.freebsd_postinstall : set hostname] **********************************
 9changed: [test_14.example.com]
11PLAY RECAP ***********************************************************************************
12test_14.example.com: ok=4 changed=2 unreachable=0 failed=0 skipped=22 rescued=0 ignored=0

UTC is the default timezone. Therefore, no changes were reported.

Install packages

Enable the installation of packages (2) and pick the lists to be installed (3). See available lists in defaults/main/pkgdict_*.yml

1shell> cat host_vars/test_14.example.com/fp-packages.yml
2fp_install: true
4  - {list: minimal, enabled: true}

Install packages

1shell> ansible-playbook playbook.yml -t fp_packages
2  ...

Create users

Enable the management of users (2) and create the configuration data (3). Delete default user (7)

1shell> cat host_vars/test_14.example.com/fp-users.yml
2fp_users: true
4  - {name: admin, shell: /bin/sh, groups: [wheel]}
5  - {name: devel, shell: /usr/local/bin/bash, groups: [wheel]}
6  - {name: responder, shell: /usr/sbin/nologin}
7  - {name: freebsd, state: absent}

Manage users

 1shell> ansible-playbook playbook.yml -t fp_users
 3PLAY [test_14.example.com] *******************************************************************
 5TASK [vbotka.freebsd_postinstall : users: Manage user accounts] ******************************
 6changed: [test_14.example.com] => (item=admin)
 7changed: [test_14.example.com] => (item=devel)
 8changed: [test_14.example.com] => (item=responder)
10PLAY RECAP ***********************************************************************************
11test_14.example.com: ok=2 changed=1 unreachable=0 failed=0 skipped=22 rescued=0 ignored=0

Update authorized SSH keys

Enable the installation of authorized keys (2). Remove other keys if already configured (3). Install the keys in batches (4). Create the list of the public keys to be installed (5)

1shell> cat host_vars/test_14.example.com/fp-authorized-key.yml
2fp_authorized_key: true
3fp_authorized_key_install_exclusive: true
4fp_authorized_key_install_individually: false
6  - user: admin
7    key: "{{ lookup('file', '~/.ansible/ssh-pub-keys/devel-srv1/id_rsa.pub') }}"
8  - user: admin
9    key: "{{ lookup('file', '~/.ansible/ssh-pub-keys/devel-srv2/id_rsa.pub') }}"

Update authorized keys

1shell> ansible-playbook playbook.yml -t fp_authorized_key
2  ...

Configure sshd

Enable the configuration of sshd (2), enable sshd service (3), and create the configuration data (10)

 1shell> cat host_vars/test_14.example.com/fp-sshd.yml
 2fp_sshd: true
 3fp_sshd_enable: true
 4fp_sshd_passwordauthentication: 'no'
 5fp_sshd_challengeresponseauthentication: 'no'
 6fp_sshd_permitrootlogin: 'no'
 7fp_sshd_permittunnel: 'no'
 8fp_sshd_allowtcpforwarding: 'yes'
 9fp_sshd_x11forwarding: 'no'
11  - {key: PasswordAuthentication, value: "{{ fp_sshd_passwordauthentication }}"}
12  - {key: ChallengeResponseAuthentication, value: "{{ fp_sshd_challengeresponseauthentication }}"}
13  - {key: PermitRootLogin, value: "{{ fp_sshd_permitrootlogin }}"}
14  - {key: PermitTunnel, value: "{{ fp_sshd_permittunnel }}"}
15  - {key: AllowTcpForwarding, value: "{{ fp_sshd_allowtcpforwarding }}"}
16  - {key: X11Forwarding, value: "{{ fp_sshd_x11forwarding }}"}
17  - {key: UseBlacklist, value: 'yes'}

Configure sshd

 1shell> ansible-playbook playbook.yml -t fp_sshd
 3PLAY [test_14.example.com] *******************************************************************
 5TASK [vbotka.freebsd_postinstall : sshd: Configure /etc/ssh/sshd_config] *********************
 6changed: [test_14.example.com] => (item={'key': 'PasswordAuthentication', 'value': 'no'})
 7changed: [test_14.example.com] => (item={'key': 'ChallengeResponseAuthentication', 'value': 'no'})
 8changed: [test_14.example.com] => (item={'key': 'PermitRootLogin', 'value': 'no'})
 9changed: [test_14.example.com] => (item={'key': 'PermitTunnel', 'value': 'no'})
10changed: [test_14.example.com] => (item={'key': 'AllowTcpForwarding', 'value': 'yes'})
11changed: [test_14.example.com] => (item={'key': 'X11Forwarding', 'value': 'no'})
12changed: [test_14.example.com] => (item={'key': 'UseBlacklist', 'value': 'yes'})
14RUNNING HANDLER [vbotka.freebsd_postinstall : reload sshd] ***********************************
15changed: [test_14.example.com]
17PLAY RECAP ***********************************************************************************
18test_14.example.com: ok=4 changed=2 unreachable=0 failed=0 skipped=23 rescued=0 ignored=0

Configure sudo

Enable the configuration of sudoers (2) and create the configuration data (3)

1shell> cat host_vars/test_14.example.com/fp-sudoers.yml
2fp_sudoers: true
4  - {key: admin, value: "ALL=(ALL) NOPASSWD: ALL"}
5  - {key: devel, value: "ALL=(ALL) NOPASSWD: ALL"}

Configure sudoers

1shell> ansible-playbook playbook.yml -t fp_sudoers
3PLAY [test_14.example.com] *******************************************************************
5TASK [vbotka.freebsd_postinstall : sudoers: Configure /usr/local/etc/sudoers] ****************
6changed: [test_14.example.com] => (item={'key': 'devel', 'value': 'ALL=(ALL) NOPASSWD: ALL'})
8PLAY RECAP ***********************************************************************************
9test_14.example.com: ok=2 changed=1 unreachable=0 failed=0 skipped=22 rescued=0 ignored=0

The user admin has already been enabled. Otherwise the Ansible escalation become: true wouldn’t work. Therefore, only the user devel reported changes.

Complete role

To show the functionality of the role, the tasks in the previous examples (fp_hostname, fp_timezone, fp_packages, fp_users, fp_authorized_key, fp_sshd, fp_sudoers) were run separately. You can create the data and run the tasks all in one play

 1shell> tree .
 3├── ansible.cfg
 4├── playbook.yml
 5├── hosts
 6└── host_vars
 7    └── test_14.example.com
 8        ├── fp-authorized-key.yml
 9        ├── fp-common.yml
10        ├── fp-packages.yml
11        ├── fp-sshd.yml
12        ├── fp-sudoers.yml
13        └── fp-users.yml
152 directories, 9 files

Run all enabled tasks in the playbook again. Optionally, disable installation to speedup the execution

1shell> ansible-playbook playbook.yml -e fp_install=false
3PLAY [test_14.example.com] *******************************************************************
5PLAY RECAP ***********************************************************************************
6test_14.example.com: ok=10 changed=0 unreachable=0 failed=0 skipped=172 rescued=0 ignored=0


The host has not been secured by this playbook and should be used for testing only.