Introduction
This guide will show you how to automate the initial OpenBSD 7 server configuration with Ansible. Ansible is a software tool that automates the configuration of one or more remote nodes from a local control node. The local node can be another Linux system, a Mac, or a Windows PC. If you are using a Windows PC, you can install Linux using the Windows Subsystem for Linux. This guide will focus on using a Mac as the control node to set up a fresh RCS OpenBSD 7 server.
The OpenBSD 7 Ansible setup playbook is listed at the end of this guide. In addition, instructions are provided on how to install and use it.
It takes a little work to set up and start using Ansible, but once it is set up and you become familiar with it, using Ansible will save a lot of time and effort. For example, you may want to experiment with different applications. Using the Ansible setup playbook described in this guide, you can quickly reinstall your OpenBSD 7 instance and then run the playbook to configure your base server. This playbook is a good base for installing web servers, database servers, or email server.
We will use a single Ansible playbook that will do the following:
Apply all the available OpenBSD system patches.
Upgrade the installed OpenBSD packages.
Reboot the server if needed and wait for it to become active.
Install a base set of useful software packages.
Set a fully qualified domain name (FQDN).
Set the timezone.
Set the SSH port number.
Disable SSH password authentication for root.
Disable tunneled clear-text passwords.
Configure /etc/doas.conf.
Create regular user group.
Create a regular user with doas privileges.
Install SSH Keys for the regular user.
Ensure authorized key for root user is installed.
Update/Change the root password.
Create a .vimrc resource file that disables vi visual mode for root and the user.
Create a 2-line prompt and bash ls aliases for the user.
Create ksh ls aliases for root.
Configure the OpenBSD PF firewall.
Packet Filter (PF) is the OpenBSD system for creating a network firewall and for doing Network Address Translation. In this guide, we will show how to use PF to create a basic firewall. Refer to the OpenBSD PF User's Guide for more details. The PF configuration also provides brute force protection for SSH. It will ban host IPs that try to make five or more SSH connection attempts within a three-second interval.
OpenBSD uses ksh as the default shell for both root and regular users. This ansible playbook will install the bash
shell and configure it for the regular user. The root user continues to use the OpenBSD ksh environment.
Prerequisites
A RCS server with a freshly installed OpenBSD 7.0 instance.
A local Mac, Windows with WSL, or Linux system. This guide focuses on Mac, but the procedures are similar for any Linux control node.
If using a Mac, Homebrew should be installed.
A previously generated SSH Key for the RCS host, and the SSH public key should be installed for the root user.
Ansible 2.9.x, or later stable version. This guide is tested with Ansible version 2.9.27 on a Mac, installed via Homebrew.
1. Install Ansible on the Local System
For this guide, we are using the Ansible 2.9.x Red Hat released version.
Using a Mac with Homebrew installed:
$ brew install ansible@2.9
$ brew link --force --overwrite ansible@2.9
This will install Ansible along with all the required dependencies, including python version 3.9.x. You can quickly test you your installation by doing:
$ ansible --version
ansible 2.9.27
config file = /Users/george/.ansible.cfg
configured module search path = ['/Users/george/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/Cellar/ansible@2.9/2.9.27_2/libexec/lib/python3.9/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 3.9.10 (main, Jan 15 2022, 11:48:00) [Clang 13.0.0 (clang-1300.0.29.3)]
Create a Simple Ansible Configuration
Create the .ansible.cfg
configuration file in the user home directory. This tells Ansible how to locate the host's inventory file.
Add the following content to ~/.ansible.cfg
:
[defaults]
inventory = /Users/user/ansible/hosts.yml
interpreter_python = auto
Be sure to replace user with your actual user name.
Create the folder to store the hosts.yml
hosts inventory file:
$ mkdir ~/ansible
$ cd ~/ansible
Of course, you can put it anywhere you want to and give it any name. Just make sure that your .ansible.cfg
file points to the correct location.
Add the following content to ~/ansible/hosts.yml
:
all:
vars:
ansible_python_interpreter: /usr/bin/python3
ansible_become: yes
ansible_become_method: sudo
children:
RCS:
hosts:
host.example.com:
user: user
user_passwd: "{{ host_user_passwd }}"
root_passwd: "{{ host_root_passwd }}"
ssh_pub_key: "{{ lookup('file', '~/.ssh/host_ed25519.pub') }}"
ansible_become_pass: "{{ host_user_passwd }}"
ansible_python_interpreter: /usr/local/bin/python3
vmware:
hosts:
debian1.local:
user: george
user_passwd: "{{ db1_user_passwd }}"
root_passwd: "{{ db1_root_passwd }}"
ssh_pub_key: "{{ lookup('file', '~/.ssh/db1_ed25519.pub') }}"
ansible_become_pass: "{{ db1_user_passwd }}"
The first block defines ansible variables that are global to the host's inventory file. Hosts are listed under children groups.
Replace host
with your actual host name. The vmware
group shows a working example for setting up a VMware host on my Mac.
The user
is the regular user to be created. The host_user_passwd
and host_root_passwd
are the user and root passwords that are stored in an ansible vault, described below. ssh_pub_key
points to the SSH public key for the RCS host. The ansible_become
lines provide the ability for the newly created user to execute doas commands in future ansible playbooks.
The python3 executable location is different for OpenBSD, so the "child" ansible_python_interpreter
defines the OpenBSD python3 location.
Using the Ansible Vault
Create the directory for the Ansible password vault and set-up playbook:
$ mkdir -p ~/ansible/openbsd
$ cd ~/ansible/openbsd
Create the Ansible password vault:
$ ansible-vault create passwd.yml
New Vault password:
Confirm New Vault password:
This will start up your default system editor. Add the following content:
host_user_passwd: ELqZ9L70SSOTjnE0Jq
host_root_passwd: tgM2Q5h8WCeibIdJtd
Replace host
with your actual hostname. Generate your own secure passwords. Save and exit your editor. This creates an encrypted file that only Ansible can read. You can add other host passwords to the same file.
pwgen
is a very handy tool that you can use to generate secure passwords. Install it on a Mac via Homebrew: brew install pwgen
. Use it as follows:
$ pwgen -s 18 2
ELqZ9L70SSOTjnE0Jq tgM2Q5h8WCeibIdJtd
You can view the contents of the ansible-vault file with:
$ ansible-vault view passwd.yml
Vault password:
You can edit the the file with:
$ ansible-vault edit passwd.yml
Vault password:
2. Create an SSH Config File for the RCS Host
Next, we need to define the RCS hostname and SSH port number that Ansible will use to connect to the remote host.
The SSH configuration for the server host is stored in ~/.ssh/config
. An example configuration on a Mac looks like:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentitiesOnly yes
AddressFamily inet
Host host.example.com host
Hostname host.example.com
Port 22
User user
IdentityFile ~/.ssh/host_ed25519
Using the SSH config file, you can change the default SSH port number if changed by the ansible playbook. The playbook is always executed the first time with SSH port 22. If the SSH port number is changed by the playbook, then the SSH port number in the SSH config file needs to be changed after the playbook runs.
With this SSH configuration file, you can use a shorthand host name to log into the server.
For the user login:
$ ssh host
For the root login:
$ ssh root@host
UserKeychain
is specific to macOS. It stores the SSH public key in the macOS key chain.
host.example.com
is your RCS server FQDN (Fully Qualified Domain Name) that needs to be defined in your DNS or /etc/hosts file on your local system. Port 22
is optional, but required if you define a non-standard SSH port.
Important: Install your SSH Key for the root user if you have not done so already:
$ ssh-copy-id -i ~/.ssh/host_ed25519 root@host
and verify that you can login without using a password.
Note: If you reinstall your RCS instance, be sure to delete your RCS hostname from ~/.ssh/known_hosts
on your local control node. Otherwise, you will see an SSH error when you try to log into your reinstalled host. The hostname is added to this file the during the first login attempt:
$ ssh root@ap1
The authenticity of host 'np1.example.com (216.128.149.25)' can't be established.
ECDSA key fingerprint is SHA256:oNczYD+xuXx0L6CM17Ciy+DWu3jOEbfVclIj9wUT7Y8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Answer yes to the question. If you don't delete the hostname from this file after reinstalling your instance, you will see an error like:
$ ssh root@ap1
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
o o o
If this happens, just delete the line entered for your hostname in the known_hosts file and run the ssh command again.
3. Test Your SSH/Ansible Configuration
Before trying to run the setup ansible playbook, we need to verify that Ansible is working correctly, that you can access your Ansible vault, and connect to your RCS host. First, verify that Ansible is installed correctly on a Mac:
$ ansible --version
ansible 2.9.27
config file = /Users/user/.ansible.cfg
o o o
This is the latest versions of Ansible on a Mac/Homebrew when this guide was written.
Run this command to test your Ansible configuration (also, your SSH configuration):
$ cd ~/ansible/openbsd
$ ansible -m ping --ask-vault-pass --extra-vars '@passwd.yml' host.example.com -u root
Vault password:
host.example.com | SUCCESS => {
"changed": false,
"ping": "pong"
}
If you see the above output, then everything is working fine. If not, go back and double-check all your SSH and Ansible configuration settings. Start by verifying that you can execute:
$ ssh root@host
and login in without a password, because you have installed your SSH key for root.
4. Running the Ansible OpenBSD Server Setup Playbook
Note: See Section 6. OpenBSD 7.0 PF and Ansible Setup Playbook Listings for the PF and playbook file listing details.
Copy and paste the Ansible PF configuration file into ~/ansible/openbsd/templates/etc/pf.conf.j2
.
Copy and paste the OpenBSD setup playbook into ~/ansible/openbsd/setup-pb.yml
.
You are ready to run the playbook. When you execute the playbook, you will be prompted for your vault password. The playbook will execute a number of tasks with a PLAY RECAP
at the end. You can rerun the playbook multiple times; for example, you may want to change the SSH port number. It will only execute tasks when needed. Be sure to update variables at the beginning of the playbook, such as your SSH port number and your timezone.
Be sure that you are in the ~/ansible/openbsd
directory. This is the command to run:
$ ansible-playbook --ask-vault-pass --extra-vars '@passwd.yml' setup-pb.yml -l host.example.com -u root
Vault password:
Depending on the speed of your Mac, it make take a few seconds to start up. If it completes successfully, you will see PLAY RECAP
like:
PLAY RECAP *************************************************************************************************************************
np1.nimbusplace.com : ok=38 changed=27 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0
The most important thing to note is that there should be no failed tasks.
Next, are some basic tests that you can run to verify your server setup.
5. OpenBSD 7.0 Server Verification
After you have successfully executed the Ansible setup playbook, here are some basic tests that you can execute to verify your sever setup. Here are some real-life examples with the server host that was used to test the setup playbook (the hostname is np1.nimbusplace.com
and the user name is george
).
Verify your user login
Verify that you can log into your new user account using your host's public SSH key:
â•â”€george@imac1 ~/ansible/openbsd
╰─$ ssh np1
Last login: Tue Feb 8 11:38:49 2022 from 72.34.15.207
OpenBSD 7.0 (GENERIC.MP) #5: Mon Jan 31 09:09:02 MST 2022
Welcome to OpenBSD: The proactively secure Unix-like operating system.
Please use the sendbug(1) utility to report bugs in the system.
Before reporting a bug, please try to reproduce it with the latest
version of the code. With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.
george@np1:~
$
Note the two-line prompt. The first line shows user@host
and the current directory.
Now, note how the l
, la
, and ls
LS aliases work and the presence of the .vimrc
file:
george@np1:~
$ touch tmpfile
george@np1:~
$ l
tmpfile
george@np1:~
$ la
.Xdefaults .bashrc .cvsrc .mailrc .ssh/ tmpfile
.bash_history .cshrc .login .profile .vimrc
george@np1:~
$ ll
total 48
drwxr-xr-x 3 george george 512 Feb 17 14:04 ./
drwxr-xr-x 3 root wheel 512 Feb 17 13:17 ../
-rw-r--r-- 1 george george 87 Sep 30 15:00 .Xdefaults
-rw------- 1 george george 5 Feb 17 13:25 .bash_history
-rw-r--r-- 1 george george 54 Feb 17 13:17 .bashrc
-rw-r--r-- 1 george george 769 Sep 30 15:00 .cshrc
-rw-r--r-- 1 george george 101 Sep 30 15:00 .cvsrc
-rw-r--r-- 1 george george 359 Sep 30 15:00 .login
-rw-r--r-- 1 george george 175 Sep 30 15:00 .mailrc
-rw-r--r-- 1 george george 388 Feb 17 13:17 .profile
drwx------ 2 george george 512 Feb 17 13:17 .ssh/
-rw-r--r-- 1 george george 13 Feb 17 13:17 .vimrc
-rw-r--r-- 1 george george 0 Feb 17 14:04 tmpfile
george@np1:~
$ cat .vimrc
set mouse-=a
The .vimrc
set mouse-=a option turns off the VI visual mode, which makes it possible to use your mouse to select and copy a block of text in a VI window.
Verify the root login
You can still login to the root account via the host SSH key. Logging in via SSH using a password is disabled. You can still login as root with a password when using the RCS VNC console.
$ ssh root@np1
Last login: Thu Feb 17 14:50:42 2022
OpenBSD 7.0 (GENERIC.MP) #5: Mon Jan 31 09:09:02 MST 2022
o o o
np1#
The default root environment still uses ksh. The only changes were to add the l
and ll
LS aliases and the .vimrc
VI configuration file:
np1# l
.Xdefaults .bash_history .cvsrc .login .ssh/
.ansible/ .cshrc .kshrc .profile .vimrc
np1# ll
total 48
drwx------ 4 root wheel 512 Feb 17 14:12 ./
drwxr-xr-x 13 root wheel 512 Feb 17 13:16 ../
-rw-r--r-- 1 root wheel 87 Sep 30 15:00 .Xdefaults
drwx------ 3 root wheel 512 Feb 17 13:15 .ansible/
-rw------- 1 root wheel 14 Feb 17 14:13 .bash_history
-rw-r--r-- 1 root wheel 578 Sep 30 15:00 .cshrc
-rw-r--r-- 1 root wheel 94 Sep 30 15:00 .cvsrc
-rw-r--r-- 1 root wheel 36 Feb 17 13:17 .kshrc
-rw-r--r-- 1 root wheel 328 Sep 30 15:00 .login
-rw-r--r-- 1 root wheel 611 Feb 17 13:17 .profile
drwx------ 2 root wheel 512 Feb 7 23:28 .ssh/
-rw-r--r-- 1 root wheel 13 Feb 17 13:17 .vimrc
np1# cat .vimrc
set mouse-=a
Verify your user password
Even though you use an SSH public key to login to your user account, you still need to use your user password with the doas
command. For example, use the doas command to change to the root account (enter your user password when prompted):
george@np1:~
$ doas -s
doas (george@np1.nimbusplace.com) password:
bash-5.1# pwd
/home/george
bash-5.1# exit
exit
Verify the root password
While in your user account, you can also use su -
to change to the root account. One difference is that you will have to enter your root password:
george@np1:~
$ su -
Password:
np1#
Verify your hostname
While we are in the root account, lets verify our hostname and some other features that the playbook set up for us:
np1# hostname -s
np1
np1# hostname
np1.nimbusplace.com
np1# date
Thu Feb 17 14:18:21 CST 2022
Here we verified both the short and FQDN host names. With the date command, verify that the timezone is set correctly.
Verify that the PF firewall rule set is protecting the SSH port
A complete discussion of PF is beyond the scope of this guide, but here are some examples to start with.
To see the current installed PF rule set:
george@np1:~
$ doas pfctl -sr
doas (george@np1.nimbusplace.com) password:
match in all scrub (no-df random-id max-mss 1440)
block drop in quick on ! egress inet from 66.42.112.0/23 to any
block drop in quick on ! egress inet6 from 2001:19f0:5c01:1a41::/64 to any
block drop in quick on vio0 inet6 from fe80::5400:3ff:fed4:1b5c to any
block drop in quick inet6 from 2001:19f0:5c01:1a41:5400:3ff:fed4:1b5c to any
block drop in quick on ! vio0 inet6 from 2001:19f0:5c01:1a41::/64 to any
block drop in quick inet from 66.42.112.216 to any
block drop in quick on ! vio0 inet from 66.42.112.0/23 to any
block return quick from <bruteforce> to any
block return in quick on egress from <martians> to any
block return out quick on egress from any to <martians>
block return all
pass in log on vio0 proto tcp from any to any port = 22 flags S/SA keep state (source-track rule, max-src-conn 15, max-src-conn-rate 5/3, overload <bruteforce> flush global, src.track 3) label "ssh-traffic"
pass out quick all flags S/SA
pass in on egress inet6 proto ipv6-icmp all icmp6-type echoreq
pass in on egress inet6 proto ipv6-icmp all icmp6-type unreach
pass in on egress inet6 proto ipv6-icmp all icmp6-type routeradv
pass in on egress inet6 proto ipv6-icmp all icmp6-type neighbrsol
pass in on egress inet6 proto ipv6-icmp all icmp6-type neighbradv
pass in on egress inet proto icmp all icmp-type echoreq
pass in on egress inet proto icmp all icmp-type unreach
To see the contents of the martians PF table:
george@np1:~
$ doas pfctl -t martians -Ts
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.0.0.0/24
192.0.2.0/24
192.88.99.0/24
192.168.0.0/16
198.18.0.0/15
198.51.100.0/24
203.0.113.0/24
224.0.0.0/3
255.255.255.255
::/96
::1
::ffff:0.0.0.0/96
100::/64
2001:2::/48
2001:10::/28
2001:db8::/32
3ffe::/16
fc00::/7
fec0::/10
To see the contents of the SSH bruteforce table:
george@np1:~
$ doas pfctl -t bruteforce -Ts
12.34.56.78
These are hosts that have made multiple SSH connection attempts in a short interval. You can test that it's working by trying to rapidly log into your host multiple times with an invalid password and no SSH key. Be careful to not lock yourself out.
If you accidentally lock yourself out:
george@imac1:~/ansible/openbsd
$ ssh np1
ssh: connect to host np1.nimbusplace.com port 22: Connection refused
Log into your OpenBSD host as root via the RCS VNC Console and execute:
np1# pfctl -t bruteforce -T delete 12.34.56.78
1/1 addresses deleted.
Then you will be able to SSH into your host.
6. OpenBSD 7.0 PF and Ansible Setup Playbook Listings
Here are the listings for the PF configuration file and the Ansible setup playbook.
The Ansible PF Configuration File (pf.conf.j2)
This PF configuration will create a basic firewall that allows SSH and ICMP traffic. All other external traffic is blocked. Internal traffic is allowed.
Create the Ansible PF configuration file directory:
mkdir -p ~/ansible/openbsd/templates/etc
Create the Ansible PF configuration file:
cd ~/ansible/openbsd/templates/etc
and add the following to pf.conf.j2
:
wan0 = "{{ ansible_default_ipv4.interface }}"
icmp_types = "{ echoreq unreach }"
# pfctl -t "table" -T show
# Display table contents.
# pfctl -t bruteforce -T expire 86400
# Remove bruteforce table entries older than 86400 seconds.
# pfctl -t bruteforce -T delete 12.34.56.78
# Immediately delete bruteforce table entry
table <bruteforce> persist
table <martians> {
0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 \
127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 \
192.0.0.0/24 192.0.2.0/24 192.88.99.0/24 \
192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 \
203.0.113.0/24 224.0.0.0/3 255.255.255.255/32 \
::/128 ::/96 ::1/128 ::ffff:0:0/96 100::/64 \
2001:10::/28 2001:2::/48 2001:db8::/32 \
3ffe::/16 fec0::/10 fc00::/7 }
set block-policy return
set loginterface egress
set skip on lo0
match in all scrub (no-df random-id max-mss 1440)
antispoof quick for { egress $wan0 }
block quick from <bruteforce>
block in quick on egress from <martians> to any
block return out quick on egress from any to <martians>
block all
# SSH
# Add brute force hosts (5 attempts within 3 seconds)
# to the bruteforce table.
pass in log on $wan0 proto tcp to port { {{ ssh_port }} } \
keep state (max-src-conn 15, max-src-conn-rate 5/3, \
overload <bruteforce> flush global) label ssh-traffic
pass out quick
# ICMP
pass in on egress inet proto icmp all icmp-type $icmp_types
pass in on egress inet6 proto icmp6 all icmp6-type $icmp_types
pass in on egress inet6 proto icmp6 all \
icmp6-type { routeradv neighbrsol neighbradv }
Create the OpenBSD Setup Playbook
cd ~/ansible/openbsd
and add the following to setup-pb.yml
:
# Initial server setup
#
---
- hosts: all
become: true
vars:
ssh_port: "22"
tmzone: America/Chicago
user_shell: /usr/local/bin/bash
doas: |
permit persist :wheel
vimrc: |
set mouse-=a
dot_profile: |
export PATH HOME TERM
# This is the standard OpenBSD PATH,
# defined for easy customization.
PATH=/bin:/sbin:/usr/bin:/usr/sbin
PATH=$PATH:/usr/X11R6/bin
PATH=$PATH:/usr/local/bin:/usr/local/sbin
PATH=$PATH:/usr/games
PATH=$HOME/bin:$PATH
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
# Set two-line user prompt
PS1="\e[0;32m\u@\h\e[m:\w\n$ "
dot_root_profile: |
# include .kshrc if it exists
if [ -f "$HOME/.kshrc" ]; then
. "$HOME/.kshrc"
fi
dot_bashrc: |
alias l='ls -CF'
alias la='ls -AF'
alias ll='ls -alF'
dot_kshrc: |
alias l='ls -CF'
alias ll='ls -alF'
tasks:
# Update and install the base software
- name: Apply all available system patches.
command: syspatch
register: syspatch
failed_when: syspatch.rc != 0 and syspatch.rc != 2
changed_when: syspatch.rc == 0
- name: Update all packages on the system.
command: pkg_add -u
- name: Reboot the server if needed.
reboot:
msg: "Reboot initiated by Ansible because of syspatch updates."
connect_timeout: 5
reboot_timeout: 600
pre_reboot_delay: 0
post_reboot_delay: 15
test_command: whoami
when: syspatch.rc == 0
- name: Install a base set of software packages.
openbsd_pkg:
name:
- bash
- curl
- git
- htop
- pwgen
- rsync--
- vim--no_x11
state: present
# Host Setup
- name: Set static hostname.
hostname:
name: "{{ inventory_hostname }}"
- name: Add IPv4 FQDN to /etc/hosts.
lineinfile:
dest: /etc/hosts
regexp: '^127\.0\.0\.1'
line: "127.0.0.1 {{ inventory_hostname }}"
state: present
- name: Add IPv6 FQDN to /etc/hosts.
lineinfile:
dest: /etc/hosts
regexp: '^\:\:1'
line: "::1 {{ inventory_hostname }}"
state: present
- name: Add FQDN to /etc/myname.
lineinfile:
dest: /etc/myname
regexp: '^(.*)'
line: "{{ inventory_hostname }}"
state: present
- name: Set timezone.
timezone:
name: "{{ tmzone }}"
notify:
- restart cron
- name: Set ssh port port number.
lineinfile:
dest: /etc/ssh/sshd_config
regexp: 'Port '
line: 'Port {{ ssh_port }}'
state: present
notify:
- restart sshd
- name: Disable root password login via SSH.
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PermitRootLogin'
line: 'PermitRootLogin prohibit-password'
notify:
- restart sshd
- name: Disable tunneled clear-text passwords.
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
notify:
- restart sshd
- name: Configure /etc/doas.conf.
copy:
dest: /etc/doas.conf
content: "{{ doas }}"
owner: root
group: wheel
mode: 0644
- name: Create regular user group.
group:
name: "{{ user }}"
state: present
- name: Create regular user with doas privileges.
user:
name: "{{ user }}"
group: "{{ user }}"
password: "{{ user_passwd | password_hash('bcrypt') }}"
groups: wheel
append: true
shell: /usr/local/bin/bash
- name: Ensure authorized keys for remote user is installed.
authorized_key:
user: "{{ user }}"
key: "{{ ssh_pub_key }}"
- name: Ensure authorized key for root user is installed.
authorized_key:
user: root
key: "{{ ssh_pub_key }}"
- name: Update root user password.
user:
name: root
password: "{{ root_passwd | password_hash('bcrypt') }}"
- name: Configure user .vimrc.
copy:
dest: /home/{{ user }}/.vimrc
content: "{{ vimrc }}"
owner: "{{ user }}"
group: "{{ user }}"
mode: 0644
- name: Configure root .vimrc.
copy:
dest: /root/.vimrc
content: "{{ vimrc }}"
owner: root
group: wheel
mode: 0644
- name: Configure user .profile,
copy:
dest: /home/{{ user }}/.profile
content: "{{ dot_profile }}"
owner: "{{ user }}"
group: "{{ user }}"
mode: 0644
- name: Configure user .bashrc,
copy:
dest: /home/{{ user }}/.bashrc
content: "{{ dot_bashrc }}"
owner: "{{ user }}"
group: "{{ user }}"
mode: 0644
- name: Update root .profile
blockinfile:
path: /root/.profile
content: "{{ dot_root_profile }}"
owner: root
group: wheel
mode: 0644
- name: Configure root .kshrc.
copy:
dest: /root/.kshrc
content: "{{ dot_kshrc }}"
owner: root
group: wheel
mode: 0644
- name: Configure pf firewall.
template:
src: etc/pf.conf.j2
dest: /etc/pf.conf
owner: root
group: wheel
mode: 0600
notify:
- reload pf.conf
- meta: end_play
handlers:
- name: restart cron
service:
name: cron
state: restarted
- name: restart sshd
service:
name: sshd
state: restarted
- name: reload pf.conf
command: pfctl -f /etc/pf.conf
You can read the Ansible Documentation to learn more about Ansible.
You should only have to update the vars:
section to change the settings for your specific situation. Most likely, you may want to update the SSH port number and timezone.
Conclusion
In this guide, we have introduced Ansible for automating the initial OpenBSD 7.0 server setup. This is very useful for deploying or redeploying a server after testing an application. It also creates a solid foundation for creating a web, database, or email server.