Notes on self-hosting essential apps

11 minute read

These notes contain a relatively simple guide to set-up a fresh Ubuntu server and self-host a number of (what I consider) essential apps.

There are plenty of reasons you want to self-host applications (privacy, who owns your data, your data being stolen, etc.). On the other hand, self-hosting forces you to be very proactive about your data, chiefly:

  • establish a rock-solid backup policy
  • keep your server secure

Both back-up and security are not easy feat to get right, so self-hosting requires a certain degree of discipline. Having said that, with a relatively small time-investment, I have never suffered any major (or minor) data-loss or data breach.

I started to look for a self-hosted alternative to Dropbox back in 2013, mostly out of privacy concerns, and I continued to add more self-hosted applications to my server (a 4GB RAM box hosted with Hetzner). At this point (end of 2016), my digital backbone is almost completely self-hosted, except for an e-mail server, which I happily leave to Fastmail.

The configuration process described here is based on Ubuntu 16.04 LTS and does install and configure the following applications:

All the web-facing applications use HTTPS (thanks Let’s Encrypt!).

It is assumed that the server IP address is associated to a DNS entry and that all the applications have a sub domain, like so:

- btsync.mydomain.com
- dav.mydomain.com
- wiki.mydomain.com

… and so on.

There is an incredible number of self-hosted applications which can be used to replace closed-source, paid applications. A good starting point is this ‘awesome’ list and this sub-reddit.

OS

I assume that Ubuntu 16.04 LTS is installed on a new server and the logged in user is root.

The very first commands to run will update the package repositories and the system.

apt update && sudo apt upgrade

Change the root password:

passw

Setup a login user, with sudo permission

adduser youruser
gpasswd -a youruser sudo

Hardening

I don’t want to be hacked, rooted or my server to turn into a remotely controlled zombie. Harden.Your.Server. I have been using this excellent collection of security recomendations to harden my box, and you should do the same.

The crucial bits are documented here. I warmly recommend to read the above guide and decide for yourself how paranoid you want to be when hardening your server.

Firewall

# install UFW (Uncomplicated Firewall)
sudo apt-get install ufw

# allow ssh and apache 80/443
sudo ufw allow ssh
sudo ufw allow "Apache Full"

# enable the firewall
sudo ufw enable

Harden SSH

Just follow this setup. It shows how to set up public key authentication for the new user and disable password authentication.

Be extra careful when editing the server’s SSL configuration. It is scary simple to get locked out of a server.

Secure shared memory

Shared memory can be used in an attack against a running service, apache2 or httpd for example. More info here. To secure the shared memory:

sudo vim /etc/fstab

Add the following line:

tmpfs     /run/shm     tmpfs     defaults,noexec,nosuid     0     0

Save and reboot.

Disable SSL v3

Here’s why you want to disable SSL v3.

TLTR; it’s broken and vulnerable.

sudo vim /etc/apache2/mods-available/ssl.conf

Change the line:

SSLProtocol all -SSLv3

To:

SSLProtocol all -SSLv2 -SSLv3

Restart apache:

sudo apache2ctl configtest && sudo service apache2 restart 

Setup fail2ban

Fail2ban temporarily rejects IP addresses that are trying to do something dodgy with your server. A classical example is a client try to brute force the SSH password. The default Fail2ban configuration only protectes SSH, but it’s (relatively) easy to configure it to add more checks (eg. apache HTTP server)

sudo apt-get install fail2ban -y

Installing applications

LAMP Stack

Before installing any application, we want to install Apache2, MySQL and PHP.

You can get away with a one liner:

sudo apt-get install apache2 mysql-server php libapache2-mod-php php-mcrypt php-mysql

But you really want to follow this thorough guide, from the guys @DigitalOcean .

Resilio Sync

Resilio Sync is the new incarnation of (the formerly known) BitTorrent Sync. In June, BitTorrent inc. announced that the Sync product was going to be moved into a new company, called Resilio. This news made me a bit nervous, but so far it seems that the new company is delivering. They recently released version 2.4 of the Sync client.

Resilio Sync is essentially a Dropbox replacement: you should be aware that it is a closed-source software. There are open-source alternatives, such as SyncThing or Seafile. I consider BitTorrent Sync (now Resilio Sync) the easiest to setup and to run and the more reliable.

Silvrback blog image

Before installing the Sync client, create the folder where the synchronized files will be stored.

# change your-user with the directory name of the user created before
sudo apt-get install acl 
mkdir /home/your-user/btsync_share/

sudo setfacl -R -m "u:rslsync:rwx" /home/your-user/btsync_share/

To install Resilio Sync, start by creating a new apt source file

echo 'deb http://linux-packages.getsync.com/resilio-sync/deb resilio-sync non-free' | sudo tee --append /etc/apt/sources.list.d/resilio-sync.list

Add public key with the following command:

wget -qO - https://linux-packages.getsync.com/resilio-sync/key.asc | sudo apt-key add -

Install

sudo apt-get update && sudo apt-get install resilio-sync

Start Resilio Sync

sudo service resilio-sync start

The Linux version of Resilio Sync has a web-based UI available at 127.0.0.1:8888. The web UI is not accessible from the Internet, so we need to set up a reverse proxy.

First enable the Apache modules required for the reverse proxy to work:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod rewrite
sudo a2enmod deflate
sudo a2enmod headers
sudo a2enmod proxy_balancer
sudo a2enmod proxy_connect
sudo a2enmod proxy_html

Create the Apache configuration for the Resilio Sync UI. Here, I assume that you have a domain name associated to your server and that each application will correspond to a sub-domain

Let’s pretend that the domain name is awesomehosted.com

Create a new Apache configuration file

sudo touch /etc/apache2/sites-available/btsync.awesomehosted.com.conf

Copy the following text to the new file

Enable the configuration and restart Apache

sudo a2ensite btsync.awesomehosted.com.conf
sudo service apache2 restart

If the sub domains are already configured and propagated, you should be able to access the Resilio Sync console

http://btsync.awesomehosted.com

In case you haven’t configured the A records yet, just add an entry to the /etc/hosts of the computer testing the connection

[server ip] btsync.awesomehosted.com

Baïkal

Baïkal is an excellent CalDav and CardDav server. I have been using it for a couple of years, and it totally replaced any other cloud service for syncing contacts and calendar (Apple Cloud, etc.). It is very stable and (kind of) easy to setup. The data are stored on SQLite, but for large dataset it is reccommended to use MySQL. I use SQLite because it’s easy to back up :)

Silvrback blog image

# install the dependencies
sudo apt-get install php7.0-sqlite3 php-xml php7.0-mbstring unzip

# fetch baikal
cd /var/www
sudo wget https://github.com/fruux/Baikal/releases/download/0.4.6/baikal-0.4.6.zip
sudo unzip baikal-0.4.6.zip 

# rename the baikal folder 
sudo mv baikal dav.awesomehosted.com
sudo rm baikal-0.4.6.zip

# fix permissions
sudo chown -R www-data:www-data dav.awesomehosted.com

Create a new Apache configuration file

sudo touch /etc/apache2/sites-available/dav.awesomehosted.com.conf

Copy the following text to the new file

And enable the configuration

sudo a2ensite dav.awesomehosted.com.conf
sudo service apache2 restart

Hit dav.awesomehosted.com on your browser and you should access the configuration page. Choose an admin password and pick MySQL or SQLite. If you choose MySQL, you’ll have to create a database first. I don’t bother creating a MySQL db for Baikal. I have around 1000 contacts and a relatively low number of entries in my calendars and never had a problem. Bonus: SQLite is easier to backup!

As an Android user, I use CardDAV-Sync to syncronize my contacts and CalDav-Sync for the calendar syncronization.

Once you have created a new user (eg. johndoe), the url for the contacts is: http://dav.awesomehosted.com/card.php/addressbooks/johndoe/default/. The url for the calendar is: http://dav.awesomehosted.com/cal.php/calendars/johndoe/default/.

Tiny Tiny RSS

Tiny Tiny RSS (tt-rss for brevity) is a marvellous feed reader, which I use daily. There are lots of self-hosted feed readers out there: I have tried few of them, and I settled with tt-rss. The set-up process is similar to the one used for the other applications.

Silvrback blog image

Install some required PHP dependencies.

sudo apt-get install php-curl php7.0-mbstring php-xml
sudo service apache2 restart

Clone tt-rss

cd /var/www

sudo git clone https://tt-rss.org/git/tt-rss.git tt-rss

sudo mv tt-rss rss.awesomehosted.com

sudo chown -R www-data:www-data rss.awesomehosted.com

Create a new Apache configuration file

sudo touch /etc/apache2/sites-available/rss.awesomehosted.com.conf

Copy the following text to the new file

And enable the configuration

sudo a2ensite rss.awesomehosted.com.conf
sudo service apache2 restart

Create the Tiny Tiny RSS database. Don’t forget to keep the password in a safe place.

mysql -u root -p

mysql> create database ttRssDB;
mysql> grant all on ttRssDB.* to ttRss@localhost identified by 'password';
mysql> flush privileges;
mysql> \q

The first time you hit the url ‘http://rss.awesomehosted.com’, a set-up page is displayed. Admittedly, the setup process of tt-rss it’s a bit quirky. Fill the configuration form with the information provided during the db creation stage. Click on the “Test Configuration” button to double-check you can access the database and all required libraries are present. Finally, select “Initialize Database”. Now you should be presented with a textbox containing the php configuration code required to run tt-rss. Press the “Install Configution” button. This will create a config.php file in the root of the main application directory.

You should now be able to access tt-rss. The default username and password is: admin/password. Don’t forget to create a new user and change the administrative password!

The last step required for a fully functional feed reader is creating a cronjob to refresh the feeds at a specified interval.

crontab -e

*/30 * * * \* /usr/bin/php /var/www/tt-rss/update.php --feeds --quiet

Docuwiki

My wiki is probably the most important part of my digital life. I keep track of books I read or I want to read, movies, a ’90s style weblog, ideas and notes. Before starting a personal wiki, I was an heavy user of Evernote. The problem with a note-style knowledge management system, such has Evernote, is that it quickly becomes a huge knowledge sink and the truly important bits of information that I want to retain were lost in the noise of the less important data.

A wiki instead forces me to curate the information that I want to preserve. A wiki is akin to having a paper notebook. It is slower, but it forces me to think about the actual bit of data that I’m working on.

Silvrback blog image

Docuwiki is a very simple wiki platform with a couple of advantages over other wikis: it has a large plugin ecosystem and it is file-based, so super-easy to back-up. No database, less attack-surface. The installation is also straightforward.

cd ~

# download the latest version of docuwiki
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-stable.tgz
tar xvf dokuwiki-stable.tgz
sudo mv dokuwiki-2016-06-26a/ /var/www/wiki

# setup folder permissions
sudo chown www-data:www-data -R /var/www/wiki/

# create apache conf file
touch /etc/apache2/sites-available/wiki.awesomehosted.com.conf

Copy the following configuration snippet to the new file

Restart Apache and test the installation by browsing to http://wiki.awesomehosted.com.

Piwigo

Piwigo is a photo gallery web-application. I use it to share photo galleries with my family. I switched from the very stylish-looking Lychee to Piwigo because Lychee doesn’t support custom ordering of photos in a gallery.

Silvrback blog image

Piwigo setup is straightforward. Start by creating a database. Don’t forget to change the password.

mysql -u root -p

CREATE DATABASE piwigo;

CREATE USER piwigouser@localhost IDENTIFIED BY 'password';

GRANT ALL PRIVILEGES ON piwigo.* TO piwigouser@localhost;

FLUSH PRIVILEGES;

exit
cd ~

sudo apt-get install unzip php-gd

wget "http://piwigo.org/download/dlcounter.php?code=latest" -O piwigo-gallery.zip

sudo unzip piwigo-gallery.zip -d /var/www

sudo mv /var/www/piwigo /var/www/gallery.awesomehosted.nl

sudo chown www-data: -R /var/www/gallery.cryptonomicon.nl/

Create the Apache config file

sudo touch /etc/apache2/sites-available/gallery.awesomehosted.com.conf

Copy the following configuration to gallery.awesomehosted.com.conf

Finally, add the following lines to my.cnf

sudo vim /etc/mysql/my.cnf

[mysqld]
sql-mode=""

This is required to avoid a weird error when changing the order of the photos in the gallery.

Secure the applications with TLS/SSL

Once all the applications are installed, configured and running on port 80 within Apache 2, it’s time to install a TLS/SSL certificate in order to encrypt the traffic between client and server. The obvious choice these days is to use Let’s Encrypt

Let’s Encrypt is a new SSL authority that provides free SSL certificates and a super-simple command line tool to streamline the creation and renewal of certificates.

Let’s start by installing the command line tool.

sudo apt-get install python-letsencrypt-apache

Modify the Apache 2 default virtual host file, 000-default.conf so that the domain name of your server is properly defined.

sudo vim /etc/apache2/sites-available/000-default.conf

Make sure that the ServerName and ServerAlias are pointing to the correct domain name - let’s continue using the fictional awesomehosted.com domain name:

ServerName awesomehosted.com
ServerAlias www.awesomehosted.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/awesomehosted

I like to configure the root directory with my own index.html, hence DocumentRoot pointing to a non default folder.

Finally, execute the command that will magically install and configure the SSL certificate for the main domain and the subdomains.

letsencrypt --apache -d awesomehosted.com -d www.awesomehosted.com -d btsync.awesomehosted.com -d dav.awesomehosted.com -d rss.awesomehosted.com -d wiki.awesomehosted.com -d gallery.awesomehosted.com

Note that his command will fail if the DNS settings for the domains and subdomains are not properly configured and propagated.

Stay tuned for the second part of these notes, concerning my backup strategy.

Comments

Luciano Fiandesio

Zombie Vampirro If you added up all the time I’ve spent on the site over the years it’s probably a :poop: ton! Writing articles definitely eats up most of the time. It takes me forever to write even the simplest post… which is why I don’t post all that often.

Articles of this length tend to take me 5–20 hours to produce over the course of a week or two. Just from all the distractions and other commitments in my life… can be hard to focus on a single thing at onc

Leave a Comment

Your email is used for Gravatar image and reply notifications only. Address will not be published. *

Loading...