Last year, I built myself a TrueNAS-based file server. It's working well for me, but it's been a fairly steep learning curve, and I thought it might be helpful to document some of the approaches I'm using.

One of the goals in having my own file server was to run various background administrative tasks--things like backing up the releases of my various GitHub hosted projects, downloading the latest r/EarthPorn images from Reddit (they make great desktop backgrounds), or archiving the podcasts I listen to.

In order to do this cleanly, it's best to set up some scaffolding using BSD jails (the idiomatic containerisation mechanism in BSD on which TrueNAS is built). These let you isolate the task and all the software you require from the rest of the system, and limit what files tasks can access. Unfortunately, by default, jails are created with just the root user so a naive approach will mean jails have too much access over the files in any mount points, and new files created within jails will be root-owned.

This post discusses the process of setting up a jail, creating an appropriate user, and running tasks as that new user. It is intended--as much as anything--as a reminder for me when I need to do this in the future.

Create a Jail

So far, I've been using the TrueNAS UI to create jails:

Choose a jail name, type and release version--I try to keep my names simple select the most recent release

Choose the networking type--NAT is sufficient unless you need your jail to accept incoming connections

Confirm your choices

Configure the Basics

Once you've created your jail, you'll need to configure a few things. I find it easiest to do this over SSH.

First, as root, start your new jail:

iocage start <jail name>

Then, load a console for your newly created jail:

iocage console <jail name>

Before anything else, I find it helpful to install some additional packages that suit my preferences and ensure I have tools like git and python:

pkg install bash emacs git python3 py39-pip

Add Mount Points

In order for your jail to be able to access the files on your TrueNAS server, you will need to expose them using a mount point. I have found the easiest way to do this is through the UI.

With your jail stopped1, add a mount point:

iocage fstab --add plex "/mnt/Storage/Data/Podcasts /mnt nullfs rw 0 0"

Adding a User

From the console in your newly created jail:

  • Add a new user corresponding to the username and UID you want to run your task as. Right now, the syn

    pw useradd -n <username> -u <uid> -d /home/<username> -s /bin/csh
    

    For example, the syncthing user rules supreme on my NAS, meaning I want to make sure it owns the newly created files. The syncthing plugin creates the user syncthing with a user id of 983 (and I prefer to work with bash), so my command is:

    pw useradd -n syncthing -u 983 -d /home/syncthing -s /bin/csh
    
  • Create the home directory for the new user and ensure it's accessible by that user:

    mkdir -p /home/<username>
    chown <username>:<username> /home/<username>
    

    Specifically:

    mkdir -p /home/syncthing
    chown syncthing:syncthing /home/syncthing
    

You should now be able to check your new user:

su syncthing

Bootstrapping the Task

The goal is to have a minimal script that can be run from outside our jail that will drop us down to the user we want to run our scheduled task as. I have a script in /root/run.sh, which calls the corresponding script /home/syncthing/run.sh which does the actual work:

#!/usr/bin/env bash

su syncthing -c /home/syncthing/run.sh

If you're using a different user, you would obviously want to substitute the two instances of syncthing with your username of choice.

Debugging Tasks

iocage console backup-instagram

Running the Task

In order to simplify the management, it's best to use the cron frontend in the TrueNAS UI.

iocage exec backup-instagram sh /home/run.sh

Scheduling Task


I'm still new to TrueNAS and BSD and I'm writing these notes as I go along, meaning I'm sure there are things I could be doing better. I'd love to hear any suggestions or improvements you have.


  1. iocage stop <jail name>