Setup of a multi-purpose home-server using Ansible: systemd, nftables, port-knocking, etckeeper, Let’s Encrypt, dynamic DNS, OpenLDAP, SSO, mail, PostgreSQL, Dotclear, Gitea, Nextcloud, NFS, XMPP, print & scan, DLNA, Transmission, iodine…
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Y 7f6725225f mediaplayer/kodi: disable X11 DPMS 1 month ago
group_vars ihmgit_back: user “gitea” instead of “git” 3 months ago
roles mediaplayer/kodi: disable X11 DPMS 1 month ago
tools 1yr-old; first commit 9 months ago
LICENSE 1yr-old; first commit 9 months ago
README.adoc 1yr-old; first commit 9 months ago
bootstrap.adoc 1yr-old; first commit 9 months ago
production 1yr-old; first commit 9 months ago
site.yml 1yr-old; first commit 9 months ago




This project contains a collection of Ansible rules, that:

  • both automate and document the setup of a home-server, as secure as possible;

  • should greatly ease the quick setup of a replacement server, in case the main one has a hardware failure (this is for a single machine, not a datacenter).

Let it be clear, that the target is a home-server, not an entreprise solution, not a personal VM “in the Cloud”, but a real hardware machine plugged at home to the xDSL or fiber router, that links you to an ISP. Besides, this project should not be used without solid knowledge of Linux and its command-line, as well as Git!

Oh! And I decided to let go of Debian, and use Archlinux instead. Someone once questionned me about such a choice for a server; here was my answer:

In practice, Archlinux is working pretty well on a server. Before that, I was using Debian. My experience (for a server) is such:

  • There is almost always something to handle after software upgrades ⇒ I never let these upgrades run automatically unsupervised.

  • + On the other hand, the solutions to the problems that arise are always simple, and I know that I can handle them.

  • + Moreover, the software is always up-to-date, which makes exploring new use-cases so much easier!

  • + Finally, it is trivial to package new software, as I did with Pyruse; this allows me to avoid ./configure && make install steps in my Ansible playbook.

  • + Updates usually just happen, almost unnoticed.

  • But when there is a failure, I have to delve into Debian’s idiosyncrasies, and this is not always easy…

  • + Security updates are done in a serious way, which compensates for the age of the packets.

  • But as time passes, some software becomes complicated, or even impossible in some cases, to test.

Everything is in the personal balance that suits you. I am perfectly comfortable with the command line, and Archlinux is better suited to my goals. But one should not be dogmatic: other Linux distributions may be better suited to other situations.

What can the server do?

Here is what is currently available (I will not repeat “automated” every time, since everything is done with Ansible):

  • a container acting as a DMZ, which is the only part of the server, that the Internet can reach;

  • firewalls (one for the DMZ, the other for the backend server);

  • as much systemd as possible (almost all logs, the DMZ, network, ntp, dns…);

  • systemd journals’ scrutation with automatic reporting of urgent situations, and a daily report;

  • /etc changes followed in Git, with a separation between the upstream state (branch master) and the everyday state (branch run);

  • certificate renewal using the ACME protocol, and certificate deployment to the locations where the software needs it;

  • software upgrades;

  • dynamic DNS handling (remember, this is a home server, where a fixed IPv4 address is not a given);

  • centralized handling of users in LDAP;

  • a web portal and SSO, to reach the different web services for registered users;

  • a web UI for handling LDAP entries and mail aliases (also in LDAP);

  • mail handling, with SMTP and IMAP;

  • a PostgreSQL database;

  • an SSH server, hidden with port-knocking;

  • a web server configured to allow additional contents for clients who port-knocked properly;

  • a blog;

  • a web UI for the Git projects hosted on the server;

  • a “personal cloud”, for files (WebDAV), contacts (CardDAV), and calendars (CalDAV), all (and more!) freely synchronizable with an Android smartphone;

  • automatic mounting of the “personal cloud” files when logging in on the server;

  • an NFS server;

  • an XMPP server;

  • a print server;

  • a scan server;

  • a remote-controlled media server (requires audio and video outputs);

  • a DLNA/uPNP server;

  • a private pastebin-like service;

  • a BitTorrent server;

  • a DNS tunnel;

  • a SSH-over-TLS tunnel;

  • Bonjour-SD (Service-Discovery);

  • a web UI for bookmarks (work in progress…);

  • a web XMPP client (work in progress…).

Current status

This configuration has led to a working server, which has been up and running for more than a year. However:

  • the Ansible rules written here still have rough edges;

  • this is a quick (one might say hasty) publishing of the current Ansible rules, and they’re in need of way more documentation…

This project is also a way for me to learn Ansible, and I’d be happy to know if I misused Ansible somewhere :-)


A domain name is needed. It is expected that DNS entries are handled by an external service, because the home-server does not do that itself. For example, Hurricane Electric can be used.
For testing purposes, a free temporary domain may be used, for example at Free DNS.

At home, the server needs to be connected to a router that has these properties:

  • allows machines on the LAN to have a fixed IP: the server, and also all terminals (PC, Android…) that shall be trusted;

  • has a “DMZ mode” (ie. route all incoming Internet traffic — with possible exceptions — to a chosen IP on the LAN), or at least port-by-port NAT;

  • is a gateway to the Internet for LAN machines;

  • allows all incoming and outgoing traffic (most notably SMTP, which tends to be blocked by default);

The server itself should have at least 2GB of RAM, and at least 2 CPU cores (for better multitasking). On my Basic Udoo X86 (2GB RAM and 4× x5-E8000@1.04GHz CPU), with all of the above services running, I get good performance, 60% RAM used, and an average system load of 8%, which is rather good!

Last but not least, the machine that will run the Ansible playbook should have a version of Ansible greater than 2.2:

  • module include_role runs dynamically (available since version 2.4);

  • modules ini_file, lineinfile, mount, and replace use the path parameter (available since version 2.3);

  • modules ldap_attr and ldap_entry are used (available since version 2.3);

  • module lineinfile uses the firstmatch parameter (available since version 2.5);

  • module user uses the create_home parameter (available since version 2.5).

Also, this machine must have a static IP address on the LAN, because only this computer will be allowed to run Ansible commands on the server, using the dedicated SSH key.


Then the rules are run by launching this command at the root of the project:

$ ansible-playbook -i production site.yml
# The home-server project produces a multi-purpose setup using Ansible.
# Copyright © 2018 Y. Gablin, under the GPL-3.0-or-later license.
# Full licensing information in the LICENSE file, or if the file is missing.