My goal is to automate configuration of everything on the server, while keeping it up and secure.
The virtual private server has a minimal Debian stable/jessie (Debian 8.3). I access it using ssh.
-
Vagrant and VirtualBox - installed on my Mac using Homebrew
-
OpenSSH - for generating ssh-keys
-
Ansible - for provisioning and running commands on server
To reduce the risk of making changes I use two local virtual machines (VMs running in VirtualBox). These are set up using Vagrant; see the Vagrantfile for details:
-
devmain
- I poke around in this manually -
stagemain
- I use this to make sure my automation works as it should
The installations of Debian in these VMs differ in the packages installed as they have more than the VPS. I’ll guess I’ll figure out how to handle that as I go along. For now I am making sure the VMs and the VPS are using the same repos.
To secure communication with the server I have generated a public/private key-pair using OpenSSH. I then copy the public keys to the VMs and the VPS.
cd provision // (1) ssh-keygen -t rsa -b 4096 -C "formasjon" // (2) ./copy-public-key-dev.sh // (3) ./copy-public-key-stage.sh ./copy-public-key-prod.sh <sshuser> <vps-server-ip> // (4)
-
I do provisioning operations in this folder
-
Make sure to save the keys in the provision/ssh-folder
-
I made a couple of helper scripts for doing the copying (yeah, I know, duplication)
-
The user and IP is not in the "prod"-script
I use three inventory files for Ansible, dev
, stage
, and an encrypted one for prod
. The inventory files contain information about the server(s) in each environment. They also show how to connect to each server. By encrypting the prod-inventory I can hide sensitive information. Ansible Vault makes it quite easy to work with encrypted files.
To edit the prod inventory: ansible-vault edit prod
If you get tired of typing the vault passphrase you can add: --vault-password-file ~/.vault_pass
and store the passphrase there.
My main playbook is site.yml
. This playbook should be possible to run at all times.
The complete ansible command to run it is:
ansible-playbook -v --vault-password-file ~/.vault_pass --key-file=ssh/id_rsa -i prod site.yml
My VPS did not have all the required packages for many ansible modules, e.g python.
To fix this I started with a role for getting the prereq’s in place.
I use ufw for my firewall; it is a bit easier to use than iptables. Ansible also has a module for it. The role has a simple set of tasks.
Also, to limit the chance of brute-forcing password-based SSH-users I added fail2ban. Thankfully someone has already created a role for fail2ban (pulled from Ansible Galaxy), all I did was put it in my base-setup, add some host-specific variables and press play.
I use roles from Ansible Galaxy. You need to run ansible-galaxy install <name.role>
before provisioning to install these roles.
List of roles in use:
-
nickjj.fail2ban - for installing fail2ban
-
dochang.docker - for installing Docker
To use the same arguments over and over is a bit tedious so I have made a couple of helper scripts:
A first step in making my server a bit more secure is to upgrade packages. To check if there is a need I can do:
./run all -i dev -a "apt list --upgradable"
To upgrade I use a short Ansible playbook. To run the playbook I can do:
./play -i dev upgrade.yml