posted on Sat, Aug 04 '18 under tag: devops

Who wants to manage servers logging in via ssh?

I was having a hard time managing several servers logging in through flaky internet connections on ssh and then keep getting broken pipes.

Then I remembered that Mozilla Participation team uses terraform which is some kind of infrastructure as code system. Can I use the same?


Terraform looked intimidating. But searching more I found ansible which looked pretty cute with yaml configuration and python based.


I searched more for ansible based setup of mail servers and found out the wonderful sovereign which helps you create your own cloud empire. But it looked outdated with the letsencrypt roles not supporting wildcard, etc.


Sovereign is listed as an alternative in debops wiki. Though the documentation is confusing, debops has a larger and newer set of roles and playbooks.

I decided to stick with debops.


I’m running archlinux and installing ansible is as easy as sudo pacman -S ansible

Also had to do pip install --user debops for debops.

I ran debops-update just for fun and it cloned the debops repository to ~/.local/share/debops

Remote Host

I stopped my Amazon EC2 instance and created a new one with Ubuntu 16.04 server.

I reused the previous security group which already had a few ports (like HTTP, IMAP) open along with SSH port.

Also, I downloaded keypair to my local computer.


I followed the guide here and created an ansible-projects directory in my folder hierarchy within which I created a new project for my personal server infrastructure with debops-init personal-server

At the end of this getting started guide I found something very insightful about how to organize the files.

However, to make this process faster, DebOps provides separate “service playbooks” for each of the roles. To use these playbooks, you can specify them as the first argument to the debops command:

alice@laptop:~/myproject$ debops service/dokuwiki -l server

This will tell the script to look for the playbook in several places:

  • playbooks/ and ansible/playbooks/ subdirectories in the project directory;
  • debops-playbooks/playbooks/ subdirectory of the project directory, if DebOps playbooks and roles are installed inside of it;
  • ~/.local/share/debops/debops-playbooks/playbooks/ directory (default install location);

The first one found will be executed. You can use this to your advantage by adding custom playbooks in playbooks/ or ansible/playbooks/ directories, they need the be named with .yml extension. Custom roles can be placed in the roles/ or ansible/roles/ subdirectories located in the project directory.

In essence, we can customize playbooks by copying them to the playbooks directory and playing around!

So, I set inventory/hosts to contain server

and then even copy pasted the bootstrap.yml playbook to the project’s playbook directory.


This step is just to ensure a few things like sudo, python, etc are installed.

debops bootstrap --user defaultuser --become --key-file ~/path/to/keyfile.pem

The --become makes the commands use sudo, so it’s important. If you have root, you can use --user root -k

This being the first command I run via ansible, I did not quite know what to expect. There will be a spew of lines starting with [WARNING]: Could not match supplied host pattern, ignoring: debops_service_bootstrap (Remember we haven’t added any hostname in that group)

Since well written playbooks are idempotent, even if you lose ssh connection in between thereby dropping your task halfway, you can just re-run the command and it will continue to work.

If all goes well, there will be a play recap at the end with a line that reads something like server : ok=26 changed=4 unreachable=0 failed=0

If failed=0, that is good, right?

Common Playbook

Next is the most important playbook to run. The common book. This does a lot of housekeeping work. Before that I needed to make sure it didn’t do anything I didn’t want it to.

I figured out we need to specify the time zone. Where though? Searched some github repos and figured out ansible/inventory/group_vars/all/all.yml would be a nice place for it

Set up the file like

ntp__timezone: 'Asia/Kolkata'

I did not want the nullmailer to be set up because I would use postfix anyhow.

Reading on the debops.postfix doc I found that we can skip certain roles being run by using --skip-tags. Maybe we can then skip nullmailer? (role::nullmailer)

(Update: Later found that setting nullmailer__enabled: False does the trick)

How about PKI? I want certificates from letsencrypt. I read this very very insightful comment on an issue about why first we should let the server generate a self-generated certificate.

At this point I decided I will point the root of my domain to my server and changed the DNS.

The PKI documentation was getting too complex and nobody was telling me how to configure it. So I thought, maybe it has an interactive interface? And decided to run the next command:

$ debops -l server


Your server is ready.


I ran this for 2 days and then decided it was an overkill to use ansible for personal server as I will keep wanting to go inside and do dirty things.

And I decided to follow the playbook and do things manually.

Like what you are reading? Subscribe (by RSS, email, mastodon, or telegram)!