Self-hosting apps using ansible-nas on DIY home server

11 Nov, 2024 (updated: 11 Nov, 2024)
2442 words | 12 min to read | 7 hr, 20 min to write

In previous articles I described my hardware and software setup for a DIY home server. In this article I will go over apps that I host on my server using ansible-nas.

I must make a quick remark here, - my apps are only available on my local network for now.

Maintaining a home server is a journey of constant tinkering whenever free time is available, and I have a HUGE problem with free time.

I will definitely either update this post or write a new article on the matter of exposing apps to the internet once I get my hands on it.

Setting up ansible-nas

First of all I forked the project (https://github.com/nemoden/ansible-nas) and cloned it to my local machine:

git clone git@github.com:Nemoden/ansible-nas.git

Then I added the original origin so I can pull changes from the original project:

git remote add orig git@github.com:davestephens/ansible-nas.git

Since I want main to be clean of my local and be in sync with orig, I created a new branch that would manage my workhorse:

git checkout -b workhorse

Next up I created my own inventory file and group vars overrides file for my inventory. cat inventories/workhorse/inventory:

[all]
ansible-nas ansible_host=192.168.100.200
[nas]
ansible-nas

The overrides file is located under inventories/workhorse/group_vars/nas.yml, and a few things I’ve added there from the get go were the things specific to my setup:

ansible_nas_hostname: workhorse
ansible_nas_timezone: Etc/UTC
# spinning rust root
rust_root: "/rust"
# docker persistent data
docker_root: "{{ rust_root }}/docker"
# find the relevant name and environment variables for your DNS provider at https://go-acme.github.io/lego/dns/
traefik_dns_provider: netlify
traefik_environment_variables:
NETLIFY_TOKEN: "nfp_r3dact3dN3t1ifyT0k3n"
# Will be added to the docker group to give user command line access to docker
ansible_nas_user: nemoden
# Your email and domain, used for Let's Encrypt SSL certs
ansible_nas_email: myemail@example.com
# Applications will have subdomain SSL certificates created if Traefik is enabled, e.g. ansible-nas.<your-domain>, nextcloud.<your-domain>
ansible_nas_domain: home.nas
# What version of python ansible should use on target system (path to spesific binary)
ansible_python_interpreter: /usr/bin/python3
# db files (mysql, postgres, etc)
db_root: "{{ rust_root }}/db/data"
db_logs: "{{ rust_root }}/db/logs"
media_root: "{{ rust_root }}/media"
encrypted_root: "{{ rust_root }}/encrypted"
downloads_root: "{{ rust_root }}/downloads"
documents_root: "{{ rust_root }}/documents"
# etc...

Traefik and Netly token has been covered in the previous blog post - Choosing Home Server OS and setting up ansible-nas

Next thing is to configure the ansible.cfg:

[defaults]
inventory = inventories/workhorse/inventory
retry_files_enabled = False
remote_user = nemoden
host_key_checking = False

listhosts = all

# fact caching
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/facts_cache

# two hours timeout
fact_caching_timeout = 7200

nocows=1

[privilege_escalation]
become_method = sudo
become_user = root
become = True

All the options seem to be fairly self-explanatory. You can read more about them in the ansible documentation. In addition, you can generate ansible.cfg file with all the options using

ansible-config init --disabled > ansible.cfg

and remove the options you don’t need, or tweak them to your liking.

Now I can run the playbook:

ansible-playbook nas.yml

Except for it will do nothing for now, because none of the apps are enabled 😄. So let’s enable some apps, shall we?

Enabling apps

ansible-nas ships with quite a library of apps of all sorts all managed by the communite that emerged around the project. Configuring and enabling the apps is as easy as adding a few lines to the group_vars/nas.yml file.

In my case, since I want my docker home to be /rust/docker, I typically add one more like like <app_name>_data_dir="{{ docker_root }}/<app_name>", so enabling something like wallabag would look like this:

wallabag_enabled: true
wallabag_available_externally: true
wallabag_data_directory: "{{ docker_root }}/wallabag"
wallabag_hostname: "save" # I want to access wallabag at https://save.home.nas/ instead of https://wallabag.home.nas/

wallabag_available_externally: true in my case means only on local netowrk. I think the variable name isn’t the best, but it is what it is. All it does is enables apps to be accessed via traefik which configures a nice domain name for the app.

By default wallabag will not download images. If the article will get deleted from the original source, you will lose the images.

I prefer to have everything locally. If you are with me, go to My Account -> Internal settings -> Misc and change “Download images locally” to 1 and hit save. Thank me later now! xD

Custom apps

There are some apps which are not in the ansible-nas library, and some of those are really specific to my setup. I simply add a role for them using ansible-galaxy role init <app_name> and add the necessary stuff (and get rid of the rest) in the tasks/main.yml file while maintaing the same structure as the other apps in the library.

My first app that I’ve added that is specific to my setup was wireguard which, in my case, a VPN client. And some of the apps use the wireguard network rather than the host network. A simple example of this is when I’d like to route a youtube downloader via a VPN that points to a different country.

I’ll definitely write a whole blog post about how to route apps running inside docker containers via a VPN-client container, but for now I’ll just leave it at that.

Some of the apps that I’ve added are:

Basically what I achieve with all the databases is being able to develop apps on my laptop while the databases are running on the home server so I don’t need to run docker on my MacOS laptop, which is a huge resource hog (because docker runs on a VM inside MacOS and hypervisor just chewing up all the CPU and RAM even on the top of the shelf MacBooks).

With the custom stuff discussed, let’s see what I used from the box.

Apps I’m running

First thing, I want to route via traefik, which is as easy as adding

traefik_enabled: true

to the group_vars/nas.yml file.

Monitoring

Monitoring apps were the first apps I enabled. Specifically, glances and grafana. Relevant entries from the group vars file:

glances_available_externally: true
glances_enabled: true
stats_enabled: true
stats_grafana_available_externally: true
stats_internet_speed_test_enabled: true
stats_prometheus_available_externally: true

Now I can access glances at https://glances.home.nas/ and grafana at https://grafana.home.nas/ and get a nice overview of the server’s health.

glances

Development

My private git server? Yes, please! I’m using gitea for that:

gitea_available_externally: true
gitea_enabled: true
gitea_hostname: "git"
gitea

Now I can create ansible-nas repo on my fresh install of gitea and push my own changes after adding new remote:

git remote add horse https://git.home.nas/nemoden/ansible-nas.git
git push horse workhorse

Media

Jellyfin

Jellyfin seemed like a good choice for a media server. It’s good enough and it’s FOSS enough for me to look into any other solution. Again, very straightforward to setup with ansible-nas:

jellyfin_available_externally: true
jellyfin_enabled: true

The only gripe I have is not being able to cast (I’m using Google Chromecast) to my TV from the Jellyfin iOS app. Casting from the browser on my laptop works fine, but I pretty much never use jellyfin on my laptop. The Chromecast Jellyfin app works fine though, it’s a little less convenient than casting, but I can live with this.

Immich

My entire home server has been built for the primary reason of unlocking myself (and my wife) from using iCloud. Or at least only relying on iCloud for syncing things like calendars and notes. I want my private photos in my private chamber. And this is what immich is for.

immich got you covered

Immich has multi-user support, BUT I’m running 2 instances of immich - one for me and one for my wife. It just separates our collections completely, and thus can be managed separately.

I took this unmerged PR as the base and tweaked it a little.

Syncing phone images onto a home server IS NOT A BACKUP. If your server catches fire, short circuits, or gets stolen, you lose all your photos.

For properly backing up your valuable stuff you can not risk to lose use the 3-2-1 strategy.

I must admit that as per the time of writing, I have not implmeneted it myself, so I’m still relying on iCloud, but I’m working on it, and in the next article I’ll share my experience setting up proper backups and testing them.

immich

Immich has a fairly good iOS app:

Be mindful that immich is still in BETA and under very active development. So as per the moment of writing (11th of Nov, 2024) it’s still not stable.

Paperless-ngx

Now let’s talk about documents. Receipts for taxation office, marriage and birth certificates, paid utility bills, driver licensed, etc. I want to keep all of that in one place, and I want it to be private. Paperless-ngx does a fantastic job in this department.

It has a very capable OCR (Optical Character Recognition), and it’s very easy to use. Each document has a few attributes like title, archive serial number (I don’t really know what it is tbh xD), created date, correspondent, document type, and tags. Corresponded, doucment type, and tags allow for easy filtering and searching. If I want to find only my documents, I can filter by correspondent. Would I require to fetch all electricity bills, I can filter by document type. You can come up with your own taxonomy.

There are quite a few moving parts to paperless-ngx, but ansible-nas makes installing it a breeze:

paperless_ng_available_externally: true
paperless_ng_enabled: true
paperless_ng_hostname: "paperless"

I’d love to provide a screenshot, but I don’t like pixelating half of the screen, sorry :) I’m sure quick google search will provide you with a few screenshots and some youtube videos…

Oh, youtube videos! Let’s talk about that next.

YouTube downloader

I’m using youtubedl-material, a self-hosted youtube downloader that uses youtube-dl under the hood. Basically it can download videos from a lot of websites, not just youtube (yes, and those sites too). The list is massive and can be found here

Should I continue providing snippets from the group_vars/nas.yml file? I think you get the idea by now. Maybe last one time:

youtubedlmaterial_available_externally: true
youtubedlmaterial_enabled: true
youtubedlmaterial_hostname: "ydl"

I have a huge problem with youtubedl-material though.

😢

It can not download youtube playlists

So, I’m looking to replace it with tubearchivist which isn’t supported by ansible-nas yet. Hopefully I’ll get to it soon, I promise I’ll create PR to add it back to ansible-nas project.

youtubedl-material

News, Reading, and Recipes

Miniflux

I’m using miniflux as a minimalistic RSS reader and pretty happy with it.

If you like to follow any subreddits, you can add them to miniflux as well. Just add https://www.reddit.com/r/<subreddit>.rss to the feed list.

For example, the RSS feed for the r/selfhosted subreddit is https://www.reddit.com/r/selfhosted.rss.

miniflux

Wallabag

Just like youtube videos, I want to preserve some articles for reading later. Wallabag is what ansible-nas provides out of the box. I wouldn’t say I’m totally happy with it, in most cases it does the job very well, in some cases it messes up formatting/css/layout of the page. But it’s good enough for me to keep using it for now.

The usage is simple - just feed in the URL and Wabbabag will save the article for you to read later.

wallabag

Books and PDFs

I’m not a fan of reading anything from the screen, and I’d rather have a physical book in my hands. If I don’t have physical book, or I’m traveling, I have my trusty Kindle Paperwhite. In super rare cases I have some PDFs that I primarily use as reference material on my laptop and in even more rare cases, on my phone. For this I’m using calibre-web. I’m infitefy unhappy with it and can’t recommend it to anyone to be completely honest. But this is what I use sometimes.

Recipes

If I wasn’t a software engineer I’d probably be a cook. Maybe even a chef :) Over many years I perfected pasta carbonara to the point I wouldn’t be embarassed to host a dinner for any Italian :) And my egg fried rice is so good I wouldn’t be ashamed to serve it to Uncle Roger.

Unlike my gigantic reading list, my recipe list is quite short, but I want to keep it in one place. Mealie is what I’m using for that.

mealie

Just like wallabag, you copy the recipe URL and Mealie will fetch the recipe for you. And unlike wallabag it works every single time because recipe websites (at least popular ones) are using special markup for recipes. Mealie doesn’t need to parse HTML, it reads only the structured data. And of course it skips all the preambles like “I remember when I was a little my mother used to make this dish for me and I loved it so much that I decided to share it with you today” followed by several pages of ads and popups.

The only downside is it doesn’t download the images to each preparation stage even if they are available in the original recipe. Those can be added manually. I presume this is because these images are not part of the structured data. Having only bare bones recipe free of images but also free of fat and detrimental additives like ads and “my mother used to make it for me when I was a little” nonesense is a fair trade off for me.

It also has some other nice features like meal planning, shopping list, etc. I don’t use those, but I can see how they can be useful for others.

Wind-up

Hosting your own apps is fun, and it’s a great way to learn new things. Once you set your foot on this path you want more of it. Just like this I have a few more apps in my pipeline that I want to host on my home server. The downside of self-hosted apps, and thus not managed is maintenance cost. I’m looking to (at least partly) mitigate it by setting up watchtower to automatically update the docker containers. But, of course, gotta lookout for breaking changes in the apps themselves.

That’s it for now. In the next article I’ll cover backups and testing them. Happy self-hosting if you do!

This article is part of the Let's self-host! series:
  1. Building a NAS / Home Server
  2. Choosing Home Server OS and setting up ansible-nas
  3. Redundancy with ZFS
  4. Self-hosting apps using ansible-nas on DIY home server