Docker
Prerequisite: Tailscale
This page is where your NixOS VM becomes a practical application host.
Docker is not the only way to self-host software, and NixOS can absolutely run many services natively, but Docker remains the easiest common denominator for a mixed stack of popular applications.
The goal here is not just “install Docker”. The goal is to put a clean structure in place so the rest of your services do not devolve into a pile of random directories and half-remembered commands.
Confirm Docker Is Enabled
If you followed the NixOS page, Docker should already be enabled in configuration.nix.
Confirm that it is available:
docker version
docker compose version
If docker compose version fails but docker-compose works, that is acceptable. The rest of this guide uses docker compose for readability.
Create a Directory Layout
Pick a home for your compose files and persistent application data.
I recommend this layout inside your normal user’s home directory:
mkdir -p ~/docker/compose
mkdir -p ~/docker/appdata
mkdir -p ~/docker/compose/{core,downloads,media,minecraft,photos,documents,automation,llm}
This separation matters:
~/docker/composeholds your compose files~/docker/appdataholds persistent config/state for containers
When things break later, you will be glad you kept those concerns separate.
Decide What Lives on NAS vs Local SSD
Not all data should live in the same place.
As a general rule:
- Put bulk media and documents on the NAS
- Put databases, caches, thumbnails and app configs on the local SSD in the VM unless there is a good reason not to
That means:
/mnt/nas/mediafor movies, TV, music, downloads/mnt/nas/photosfor large photo libraries/mnt/nas/documentsfor archived documents~/docker/appdata/...for per-app config, databases, cache and metadata
This gives you good performance while still keeping your large data sets on resilient storage.
Create a Shared Docker Network
Later, if you use a reverse proxy such as Caddy or NGINX, it is helpful for multiple containers to share a common Docker network.
Create one now:
docker network create proxy
You only need to do this once.
Sensible Utility Packages
If you want a few useful tools on the NixOS VM itself, add them to environment.systemPackages in configuration.nix.
For example:
environment.systemPackages = with pkgs; [
git
curl
vim
htop
ncdu
iotop
docker-compose
];
Then rebuild:
sudo nixos-rebuild switch
Firewall Philosophy
NixOS already has a firewall framework. Docker can also manipulate firewall rules on its own.
For beginners, the simplest good default is:
- keep the host private behind your LAN
- use Tailscale for remote access
- only expose ports intentionally
Do not start by opening a giant list of ports “just in case”.
Instead, each service page will mention the port it uses, and you can decide whether that service should be reachable:
- only from LAN/Tailscale
- or eventually via a reverse proxy and domain
Compose File Strategy
I recommend one compose file per logical stack.
For example:
~/docker/compose/core/filebrowser.compose.yml~/docker/compose/downloads/bittorrent.compose.yml~/docker/compose/media/movies-tv.compose.yml~/docker/compose/media/jellyfin.compose.yml
That gives you enough separation to manage services cleanly without making everything so fragmented that you hate working with it.
A Few Ground Rules Before You Start Deploying Apps
- Prefer bind mounts you understand over clever abstractions you do not
- Avoid exposing admin panels publicly unless you truly need to
- Keep secrets out of compose files when possible
- Name containers clearly
- Use restart policies such as
unless-stopped - Do not blindly auto-update every stateful service without backups
That last point matters a lot more than people think.
Next Steps
Next, we will deploy a simple but genuinely useful service so you can verify your Docker host, storage mounts and networking all work together.
Proceed to FileBrowser.
Last updated: March 2026