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.
Yves G 3f8dd657f3 mediaplayer: add DRM ability to Kodi, for e.g. Netflix 6 months ago


# 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.

= Automated configuration of a home-server

== Introduction

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:

[quote, Yves,]
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<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>&&<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>make<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>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-link:[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.

* 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 `:-)`

== Requirements

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<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>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 —<span class="escaped-code-point" data-escaped="[U+202F]"><span class="char"> </span></span>with possible exceptions<span class="escaped-code-point" data-escaped="[U+202F]"><span class="char"> </span></span>— 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),
** module `ldap_attrs` is used (available since version 3.4),
** module `lineinfile` uses the `firstmatch` parameter (available since version 2.5),
** module `user` uses the `create_home` parameter (available since version 2.5);

* 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;

* have the following software installed: `dig` (DNS lookup), `python-netaddr` (Python3).

== Usage

First, the server must be link:bootstrap.adoc[prepared, so that Ansible can connect and run the rules].

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.