If you are building a NAS, a quick google search will most likely land you on FreeNAS (Core/Scale), Unraid, OpenMediaVault (OMV), CasaOS, etc.
Iāve tried FreeNAS Scale and OMV and very quickly I realised those arenāt great options for my needs. Letās see what I ruled out and why:
- FreeNAS is designed to only be a NAS appliance. It gets in a way of admining the server, and I didnāt like that.
- OMV spat out errors whatever I did on the UI, the amount of troubleshooting I had to do was just not worth it.
- UNRAID is a paid option, and I didnāt want to pay for something I can get for free. Besides this, running OS from a USB stick seemed like a bad idea to me.
- CasaOS seemed to be a great option. Basically itās not an OS in classic sense, itās just an app that provides a UI for management, but is a new player in the market, and I didnāt want to be a guinea pig. I also donāt really need a UI, Iād much prefer to have everything automated via
ansibleand for other things I can justSSHinto the server. - Proxmox is another option that I considered, but running a hypervisor and VMs would require beefier hardware. Had I had a server with more RAM and CPU cores, Iād definitely go with Proxmox.
Even before considering all these options I felt like I wanted to have a setup what Iām familiar with. I used to administer CentOS servers at work, I also had some of those running in EC2. So my first thought was to run old good CentOS. And I would if I didnāt find ansible-nas project, which requires Ubuntu Server
NixOS. Which seemed a lot of fun and has out-of-the-box support for zfs. One day, Iāll certainly lay my hands on it, but at the moment when I needed to get my stuff done I didnāt have time to learn the new waysMay 2025 UPDATE: This day has come! My old MacBook is rocking NixOS now.
ansible-nas
I got sold on ansible-nas the moment Iāve read the very first paragraph of the README:
After getting burned by broken FreeNAS updates one too many times, I figured I could do a much better job myself using just a stock Ubuntu install, some clever Ansible config and a bunch of Docker containers.
(c) Dave Stephens - creator of
ansible-nas
Also read Why I Ditched FreeNAS And Replaced It With Ubuntu Server And Ansible by David if you are still convinced you need NAS-only OS.
It seemed like the right solution to me, so I quickly flushed Ubuntu 22.04.3 LTS onto my machine, forked the repo and started modifying it to my needs. Over time Iāve added some more apps like wireguard, immich, mysql, and valkey and working on some others like tubearchivist and tailscale.
Overall the whole setup is very easy to maintain. The official documentation is very detailed and easy to follow. Basically, to enable an app all you need is to see what variables are available in the roles/<app>/defaults/main.yml file, and override them in the inventories/<your-inventory>/group_vars/nas.yml file.
The very first thing I was obliged to do is to give my server a name. Since I have a very poor imagination I called my workhorse⦠a workhorse:
ansible_nas_hostname: workhorseI also created a Makefile with some useful commands like these:
all: ansible-playbook nas.yml
deps: ansible-galaxy install -r requirements.yml
check: ansible-playbook --check --diff nas.yml
samba.check: ansible-playbook --check --diff --tags "samba" nas.yml
samba: ansible-playbook --tags "samba" nas.yml
immich.check: ansible-playbook --check --diff --tags "immich" nas.yml
immich: ansible-playbook --tags "immich" nas.yml
# etcAnd I gave my server a static IP address (by making DHCP server on my router to always assign the same IP to the MAC address of my server):
Finally, Iāve created a zfs pool and called it rust:
zpool create rust mirror \ /dev/disk/by-id/wwn-0x5000c500db125622 \ /dev/disk/by-id/wwn-0x5000c500db13fa95
zpool status pool: rust state: ONLINE scan: scrub repaired 0B in 04:10:47 with 0 errors on Sun Oct 30 04:34:48 2024config:
NAME STATE READ WRITE CKSUM rust ONLINE 0 0 0 mirror-0 ONLINE 0 0 0 wwn-0x5000c500db125622 ONLINE 0 0 0 wwn-0x5000c500db13fa95 ONLINE 0 0 0
errors: No known data errorsBut more on zfs in the next post.
Samba
Samba (SMB) is open-source software that enables file and printer sharing across Linux, macOS, and Windows by implementing the SMB/CIFS network protocol for easy cross-platform access.
Among other samba shares Iāve got one for the file exchange. I treat it similar to Downloads directory. Once itās mounted on the client machine and I need to transfer a file, but I donāt yet know what would be the best place for it, I just drop it there. Later I can opt to move it to a more appropriate place:
samba_shares: - name: exchange comment: "File exchange" guest_ok: yes read_only: no public: yes writable: yes browseable: yes path: "{{ rust_root }}/exchange"Mounting on MacOS
To mount the share on MacOS I use the following command:
mount_smbfs //guest@workhorse/exchange /Volumes/workhorse/exchangeMounting on iOS
Just use Files app. Click on ... -> Connect to Server and type in smb://<ip address>, select to connect either as a guest or with a username and password, and voila!
Nice domain name
By default, when you install an application using ansible-nas you can configure the port itās available on (or leave it default), but memorizing what app runs on what port is a bit of a mental gymnastics Iād rather not engage in on a daily basis. So I decided to use traefik as a reverse proxy and give each app a subdomain. I also wanted my app run over HTTPS, so Iāve configured traefik to use letsencrypt to provision SSL certificates automagically. For all these to happen I need a domain name, and I need my DNS provider to pass the letsencrypt challenge. Iāve registered an easy to remember 3-character domain in the .me tld using namecheap and delegated DNS management to Netlify mainly because to get namecheap API, according to their policy, Iād need to either have 20 domains registered with them, or have at least $50 on my account, or have at least $50 spent within the last 2 years, and I didnāt meet any of these criteria. Netlify, on the other hand, provides API free of any conditions.
Registering a domain name and setting up DNS
Just register a domain name and head to DNS management settings. Just make sure the DNS management provider is listed on the traefik dns challenge providers list. Than add an A record pointing to your serverās IP address:
nas.home, I redacted it for security reasons even though for now my DNS records point to my local IP which isnāt available from āoutsideāLetās Encrypt Challenge and Traefik
The Letās Encrypt challenge is a process to verify domain ownership before issuing an SSL certificate. Typically, it uses HTTP-01 or DNS-01 challenges, where the server either hosts a specific file at a URL or adds a DNS record, proving control over the domain.
Traefik automates the whole process. The only bit is traefik needs a way to talk to the DNS provider to add a challenge record and a little bit of configuration of the traefik itself - it needs to know what ACME (Automatic Certificate Management Environment) provider to use for automatic SSL provisioning (which is Let's Encrypt in our case). This part of the configuration comes with the ansible-nas project, and only needs to be modified if you wish to use a different ACME provider.
For traefik to be able to talk to Netlify API I created an API key and specified it in the traefik configuration in the inventories/workhorse/group_vars/nas.yml file:
traefik_enabled: true# find the relevant name and environment variables for your DNS provider at https://go-acme.github.io/lego/dns/traefik_dns_provider: netlifytraefik_environment_variables: NETLIFY_TOKEN: "nfp_th1sIsnotMyR3alN3tl1fyAPIt0kEn"To enable individual app custom domain name all that is required to do is to add a few lines in the inventories/<your inventory>/group_vars/nas.yml file like:
wallabag_enabled: truewallabag_available_externally: truewallabag_hostname: "save"the <app-name>_hostname is optional, ansible-nas provides some sane defaults. Like if I want to access wallabag on save.nas.home, I do need to specify wallabag_hostname, if I donāt, the app will be available on wallabag.nas.home.
And VOILA! Now I can access my stuff using nice subdomains like read.nas.home (calibreweb), save.nas.home (wallabag), git.nas.home (gitea), grafana.nas.home, etc.
Thatās it for now. In the next article Iāll cover zfs and how I use it to ensure data safety.