# Docker Compose NAS This project provides a comprehensive, self-hosted media and utility server setup using Docker Compose. It aims to replicate and enhance the functionality of a typical NAS using containerized applications on a standard Linux host. The core idea is to manage media libraries (movies, TV shows, music), automate downloads securely, provide easy access via a dashboard, and enable remote access through Tailscale. ## Features This stack includes: * **Reverse Proxy & Service Discovery:** [Traefik](https://traefik.io) automatically routes traffic to services. * **Media Management:** * [Sonarr](https://sonarr.tv): TV show management. * [Radarr](https://radarr.video): Movie management. * [Lidarr](https://lidarr.audio) (Optional): Music management. * [Bazarr](https://www.bazarr.media/): Subtitle management. * **Indexers & Downloads:** * [Prowlarr](https://github.com/Prowlarr/Prowlarr): Indexer management for *arr apps. * [qBittorrent](https://www.qbittorrent.org): Bittorrent client (can be configured to run through a VPN). * [SABnzbd](https://sabnzbd.org/) (Optional): Usenet download client. * **Media Server:** [Jellyfin](https://jellyfin.org) organizes and streams your media. * **Request Management:** [Jellyseerr](https://github.com/FallenBagel/jellyseerr) allows users (including Jellyfin users) to request media. * **Dashboard:** [Homepage](https://gethomepage.dev) provides a central dashboard to access all services. * **Remote Access:** [Tailscale](https://tailscale.com) provides secure access to your services from anywhere without opening firewall ports. It handles HTTPS termination. * **Utilities:** * [Watchtower](https://containrrr.dev/watchtower/): Automatically updates running containers to the latest image. * [Autoheal](https://github.com/willfarrell/docker-autoheal/): Monitors and restarts unhealthy containers. * [Unpackerr](https://unpackerr.zip): Automatically extracts downloaded archives. * **Other Optional Services:** AdGuard Home, Calibre-Web, Decluttarr, Tandoor Recipes, Joplin Server, Home Assistant, Immich Photos (enable via profiles). ## Prerequisites * **Linux Host:** Any recent Linux distribution capable of running Docker. Tested on Ubuntu Server 22.04. * **Docker Engine:** Install the latest version of Docker Engine. [Official Installation Guide](https://docs.docker.com/engine/install/). * **Docker Compose V2:** Ensure you have Docker Compose V2 (usually installed as a Docker plugin, invoked via `docker compose`). [Official Installation Guide](https://docs.docker.com/compose/install/). * **User Permissions:** You'll need a user account that can run `docker` commands (usually by adding the user to the `docker` group) or run `docker compose` via `sudo`. * **SELinux (If Enabled):** If your host uses SELinux (e.g., Fedora, CentOS, RHEL), you might need additional host configuration. See the [Troubleshooting](#selinux-socket-permissions) section. ## Quick Start 1. **Clone the Repository:** ```bash git clone https://github.com/AdrienPoupa/docker-compose-nas.git cd docker-compose-nas ``` 2. **Create Configuration File:** Copy the example environment file: ```bash cp .env.example .env ``` 3. **Edit `.env` File:** Open the `.env` file with a text editor and configure it according to your system and preferences. **This is the most crucial step.** See the detailed [Configuration (`.env` File)](#configuration-env-file) section below for explanations of each variable. Minimally, you **must** set `USER_ID`, `GROUP_ID`, `TIMEZONE`, `HOSTNAME`, and `TAILSCALE_AUTHKEY`. 4. **Start the Stack:** Run Docker Compose (use `sudo` if your user isn't in the `docker` group): ```bash docker compose up -d ``` This will pull the necessary images and start all the core services in the background. 5. **Run Initial Configuration Script:** This script helps configure base URLs and API keys within the running *arr applications based on your `.env` file. ```bash ./update-config.sh ``` *(Note: You might need to make it executable first: `chmod +x ./update-config.sh`)* 6. **Access Services:** Once Tailscale is connected, you should be able to access your services via `https://..ts.net/` or `https:///`. If you set up DNS for your `HOSTNAME`, you can use `https:///`. The main dashboard is at `/`. ## Configuration (`.env` File) This file controls all the essential settings for your Docker Compose stack. Copy `.env.example` to `.env` and edit the values. --- ### **Core Settings (Required)** These are fundamental for basic operation and permissions. * `USER_ID`: The Linux user ID that the containers will run as. Find yours with `id -u`. * *Default:* `1000` * `GROUP_ID`: The Linux group ID that the containers will run as. Find yours with `id -g`. * *Default:* `1000` * **Note:** Using the correct IDs is crucial for file permissions, especially for accessing media files on the host. * `TIMEZONE`: Your local timezone (e.g., `America/New_York`, `Europe/London`, `Asia/Manila`). Find yours from [this list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). * *Default:* `America/New_York` * `HOSTNAME`: **(Deprecated - Now derived)** The primary hostname used by Traefik for routing. This is now automatically constructed from `TAILSCALE_HOSTNAME` and `TAILSCALE_TAILNET_DOMAIN`. You generally don't need to set this directly unless overriding the default behavior. * *Default:* `${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}` --- ### **Host Paths (Required)** Define where container data and configuration are stored on your host machine. * `CONFIG_ROOT`: The base directory on your host where configuration files for each service will be stored. Using `.` stores them in subdirectories within the project folder. * *Default:* `.` * `DATA_ROOT`: The main directory on your host containing your media libraries (movies, TV shows, music, books). * *Default:* `/mnt/data` * `DOWNLOAD_ROOT`: The directory on your host where the download client (qBittorrent/SABnzbd) will store downloads in progress and completed files *before* they are imported by *arr apps. * *Default:* `/mnt/data/torrents` * **Hardlink Note:** For efficient storage (avoiding duplicate files), it's highly recommended that `DOWNLOAD_ROOT` is on the **same filesystem** as `DATA_ROOT` (e.g., `/mnt/data/torrents` is inside `/mnt/data`). This allows instant moves via hardlinks instead of slow copies. --- ### **Tailscale Access (Required)** Controls secure remote access via Tailscale. * `TAILSCALE_AUTHKEY`: **Required.** An authentication key from your Tailscale account. Generate one in the Tailscale Admin Console under Settings > Keys. You can use a reusable key or an ephemeral key (recommended for containers). * *Default:* (None - **Must be set**) * `TAILSCALE_HOSTNAME`: The desired hostname for this NAS within your Tailscale network. * *Default:* `tailscale-nas` * `TAILSCALE_TAILNET_DOMAIN`: **Required.** The domain of your Tailnet, including your Tailnet's unique name * *Default:* `your-tailnet.ts.net` (**Must be set**) * `TAILSCALE_TAGS`: Optional tags to apply to the Tailscale node (e.g., `tag:nas`). * *Default:* `tag:nas` * `ENABLE_FUNNEL_HTTPS`: Controls Tailscale's public accessibility. * `true`: Enables Tailscale Funnel, making services accessible publicly via the Tailscale domain (`..ts.net`). Use with caution. * `false`: Uses Tailscale Serve, making services accessible *only* to devices logged into your Tailnet. (Recommended) * *Default:* `false` --- ### **Homepage Widgets (Optional)** API keys needed *only* if you want to display real-time information from these services on the Homepage dashboard. Find the API keys within each application's settings (usually under Settings > General or Settings > Security). * `SONARR_API_KEY` * `RADARR_API_KEY` * `LIDARR_API_KEY` (If Lidarr profile is enabled) * `BAZARR_API_KEY` * `PROWLARR_API_KEY` * `JELLYFIN_API_KEY` * `JELLYSEERR_API_KEY` * `SABNZBD_API_KEY` (If SABnzbd profile is enabled) * `ADGUARD_USERNAME` / `ADGUARD_PASSWORD` (If AdGuard Home profile is enabled) * `CALIBRE_USERNAME` / `CALIBRE_PASSWORD` (If Calibre-Web profile is enabled) --- ### **Homepage Customization (Optional)** Control the appearance and behavior of the Homepage dashboard. * `HOMEPAGE_VAR_TITLE`: Title shown on the dashboard. * *Default:* `Docker-Compose NAS` * `HOMEPAGE_VAR_SEARCH_PROVIDER`: Default search engine. [See options](https://gethomepage.dev/en/widgets/search/). * *Default:* `google` * `HOMEPAGE_VAR_HEADER_STYLE`: Dashboard header style. [See options](https://gethomepage.dev/en/configs/settings/#header-style). * *Default:* `boxed` * `HOMEPAGE_VAR_WEATHER_CITY`, `_LAT`, `_LONG`, `_UNIT`: Configure the weather widget. --- ### **Download Client Settings** Credentials for included download clients. * `QBITTORRENT_USERNAME`: Username for qBittorrent Web UI. * *Default:* `admin` * `QBITTORRENT_PASSWORD`: Password for qBittorrent Web UI. * *Default:* `adminadmin` * **Note:** On first run, qBittorrent might generate a temporary password shown in its logs (`docker compose logs qbittorrent`). Log in with that, change the password in qBittorrent settings, and update this `.env` variable accordingly. --- ### **VPN Configuration (Example: PIA - Optional)** These variables are specific to the example `thrnz/docker-wireguard-pia` VPN container used for qBittorrent in the default setup. If you use a different VPN provider or container, you'll need different variables. **If you don't use the VPN, you can ignore these.** * `PIA_USER`: Private Internet Access username. * `PIA_PASS`: Private Internet Access password. * `PIA_LOCATION`: PIA server location code (e.g., `ca_montreal`, `us_east`). [See list](https://serverlist.piaservers.net/vpninfo/servers/v6). * *Default:* `ca` * `PIA_LOCAL_NETWORK`: Your local network CIDR (e.g., `192.168.1.0/24`). Allows local access to the qBittorrent UI when the VPN is active. * *Default:* `192.168.0.0/16` --- ### **Traefik DNS Challenge (Optional)** These settings are for enabling automatic HTTPS certificate generation via Let's Encrypt using the DNS-01 challenge method. **This is generally NOT needed** because Tailscale handles HTTPS termination by default in this setup. Only configure this if you have a specific reason to manage your own certificates via Traefik (e.g., accessing services without Tailscale). * `DNS_CHALLENGE`: Set to `true` to enable DNS challenge. * *Default:* `true` (Consider setting to `false` if using Tailscale for HTTPS) * `DNS_CHALLENGE_PROVIDER`: Your DNS provider supported by Traefik/Lego (e.g., `cloudflare`, `godaddy`). [See providers](https://doc.traefik.io/traefik/https/acme/#providers). * *Default:* `cloudflare` * `LETS_ENCRYPT_EMAIL`: Your email address for Let's Encrypt notifications. * `LETS_ENCRYPT_CA_SERVER`: Let's Encrypt server URL (use staging for testing). * *Default:* `https://acme-v02.api.letsencrypt.org/directory` (Production) * Provider-Specific Variables (e.g., `CLOUDFLARE_EMAIL`, `CLOUDFLARE_DNS_API_TOKEN`, `CLOUDFLARE_ZONE_API_TOKEN`): Credentials required by your chosen `DNS_CHALLENGE_PROVIDER`. Refer to Traefik documentation. --- ### **Compose Profiles & Files (Advanced)** * `COMPOSE_PROFILES`: Comma-separated list of optional service profiles to enable (e.g., `lidarr,sabnzbd,adguardhome`). See [Optional Services](#optional-services). * `COMPOSE_FILE`: Colon-separated list of compose files to use. Allows extending the base configuration. * *Default:* `docker-compose.yml` ## Service Access With the default Tailscale setup, services are securely accessible via HTTPS using your Tailscale node's name or IP, followed by the service path. Replace `` with your Tailscale device name (e.g., `tailscale-nas.your-tailnet.ts.net`) or its Tailscale IP address. * **Homepage:** `https:///home` * **Sonarr:** `https:///sonarr` * **Radarr:** `https:///radarr` * **Lidarr:** `https:///lidarr` (If profile enabled) * **Bazarr:** `https:///bazarr` * **Jellyseerr:** `https:///jellyseerr` * **Prowlarr:** `https:///prowlarr` * **qBittorrent:** `https:///qbittorrent` * **SABnzbd:** `https:///sabnzbd` (If profile enabled) * **Jellyfin:** `https:///jellyfin` * **Calibre-Web:** `https:///calibre` (If profile enabled) * **AdGuard Home:** `http://:3000` (If profile enabled, access via IP/port initially) * **Tandoor Recipes:** `https:///recipes` (If profile enabled) * **Joplin Server:** `https:///joplin` (If profile enabled) * **Home Assistant:** `http://:8123` (If profile enabled, access via IP/port initially) * **Immich:** `http://:2283` (If profile enabled, access via IP/port initially) **Note:** * `` refers to the full Tailscale name (e.g., `tailscale-nas.your-tailnet.ts.net`). * `` refers to the Tailscale IP address of the NAS. * Some services (AdGuard, HA, Immich) might require initial setup via their direct IP and port before Tailscale/Traefik routing is fully effective or configured within the application. Authentication for most services will be handled by Authelia (configured later). ## Optional Services Several services are included but disabled by default. Enable them by adding their profile name to the `COMPOSE_PROFILES` variable in your `.env` file (separate multiple profiles with commas). Example: Enable Lidarr and SABnzbd ```dotenv COMPOSE_PROFILES=lidarr,sabnzbd ``` Available Profiles: * `lidarr`: Music management. * `sabnzbd`: Usenet download client. * `flaresolverr`: Bypasses Cloudflare challenges for Prowlarr. * `adguardhome`: Network-wide ad blocking (see `adguardhome/README.md`). * `calibre-web`: E-book library management. * `decluttarr`: Automated download cleanup. * `tandoor`: Recipe management (see `tandoor/README.md`). * `joplin`: Note-taking server (see `joplin/README.md`). * `homeassistant`: Home automation (see `homeassistant/README.md`). * `immich`: Photo management (see `immich/README.md`). ## Troubleshooting ### SELinux Socket Permissions (Docker) If you are running Docker on a host with SELinux enabled (like Fedora, CentOS, RHEL) and services like Traefik, Watchtower, or Autoheal fail with "permission denied" errors when trying to access `/var/run/docker.sock`: 1. **Check Audit Logs:** Immediately after seeing the error, check the SELinux audit log on the host: ```bash sudo ausearch -m avc -ts recent ``` Look for lines containing `denied`, `docker.sock`, and the name of the failing service (e.g., `traefik`, `watchtower`). 2. **Generate Custom Policy:** If denials are found, you may need to create a custom SELinux policy module using `audit2allow`. Pipe the denial messages into it: ```bash # Generate policy files (my-dockersock.te and my-dockersock.pp) sudo ausearch -m avc -ts recent | audit2allow -M my-dockersock # Install the policy module sudo semodule -i my-dockersock.pp ``` This allows the specific actions that were being denied. You might need to repeat this if different denials appear after applying the first policy. ### Tailscale Issues * **Authentication:** Ensure your `TAILSCALE_AUTHKEY` in `.env` is valid and hasn't expired (especially if using ephemeral keys). Check the `tailscale` container logs (`docker compose logs tailscale`) for authentication errors. * **Connectivity:** Verify the `tailscale` container is running and connected to your Tailnet (`docker compose exec tailscale tailscale status`). * **Funnel/Serve Command:** If you modified the Tailscale command, ensure the syntax for `tailscale funnel` or `tailscale serve` is correct. ### File Permissions If services report permission errors when accessing `/config` or `/data` directories, double-check that: * The `USER_ID` and `GROUP_ID` in your `.env` file match the owner/group of the corresponding `CONFIG_ROOT` and `DATA_ROOT` directories on your host. * The host directories have appropriate read/write permissions for that user/group. * If using SELinux, the `:Z` flag on the volume mounts in `docker-compose.yml` is correctly applied to allow the container to write to the host paths. ## Advanced Topics *(Relevant sections like Synology Quirks, NFS Share, Static IP, etc., can be kept here, but review them to ensure they align with a standard Docker setup rather than Podman specifics where applicable.)* *(Example: Synology section should focus on Docker package setup, port conflicts, user IDs, etc., relevant to DSM.)* *(Example: Remove Podman-specific commands or troubleshooting steps from these sections.)* --- *Self-hosted media stack powered by Docker, Traefik, Tailscale, and the \*arr suite.*