In our last Ansible tutorial, we covered the basics of using Ansible for configuration management, which can help you get new servers set up faster and more reliably.
But the Ansible security playbook that we created there was pretty basic, so I thought we would show create a new playbook that supports more security out of the box without sacrificing normal access to the server.
The goals for this Ansible security playbook are:
- Set up a non-root user with sudo access
- Upgrade all installed packages
- Install a few basic packages to make initial management easier, like
nano
. These can be easily customized according to your needs - Copy your SSH key to the VPS to enable password-less logins
- Harden SSH with some basic security measures, such as disabling root and password-based logins
- Install
iptables
if needed, and set up some basic restrictions to improve security - Install
fail2ban
to help prevent brute force attacks
(The final two steps will be outlined in part 2 of this Ansible security tutorial).
The goal here isn't to have you copy the code here and recreate your own playbook-- it's to teach you how to do it for yourself.
We'll walk you through the various components step-by-step so that you can use this playbook as a foundation for your own customizations.
And this playbook isn't comprehensive when it comes to security for your VPS—once you provision the server using this playbook, you may want to research some additional steps, such as using Lynis to audit your security.
Prerequisites
- A newly-provisioned or rebuilt server running any of our OS options—CentOS, Debian, or Ubuntu.
- Ansible installed on your local machine— see these instructions for more details
- An Ansible hosts file set up with the IP(s) of your server(s)—see Step 2 of our previous tutorial
[cta_inline]
Step 1. Setting up the playbook structure
Ansible playbooks can be structured in a number of different ways, but the developers do have their recommendations.
This Ansible script is still relatively simple compared to what's possible with the system, so our structure is going to be far simpler as well.
Here's the general structure we're following:
provision.yml
roles
common/
tasks/
main.yml
ssh
tasks/
main.yml
packages
tasks/
main.yml
iptables
tasks/
main.yml
If you want, you can go ahead and create the directories now, just to give you a better sense as to how the playbook separates its logic into different areas.
Step 2. Creating provision.yml
The provision.yml
file is the core of our playbook—it's where we define which servers we're going to be working with, a few global variables, and tell Ansible where to look for its tasks.
--- - name: Provision a new server with hardened SSH and basic iptables. # Specify the hosts you want to target hosts: HOSTNAME # Specify the user you want to connect to the server. # With a new installation, you will connect with
root
. If you want to # re-run this playbook at a later date, you should changeremote_user
to # the user you specified undervars/username
below and uncomment the #become: true
line. You should then run the playbook using the #--ask-become-pass
flag, like so: #ansible-playbook -k provision.yml --ask-become-pass
. remote_user: root # become: true vars: username: USER # Before first using the playbook, run the below command to create a hashed # password that Ansible will assign to your new user. # python
by subscribing to our newsletter.
A note about tutorials: We encourage our users to try out tutorials, but they aren't fully supported by our team—we can't always provide support when things go wrong. Be sure to check which OS and version it was tested with before you proceed.
If you want a fully managed experience, with dedicated support for any application you might want to run, contact us for more information.