Compare commits
1 Commits
feature/tr
...
8a52e6894f
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a52e6894f |
23
.env.example
23
.env.example
@@ -36,10 +36,9 @@ TAILSCALE_TAGS=tag:nas
|
|||||||
# Enable Tailscale Funnel (public access) for HTTPS? Set to 'true' or 'false'. 'false' uses Serve (Tailnet only, recommended).
|
# Enable Tailscale Funnel (public access) for HTTPS? Set to 'true' or 'false'. 'false' uses Serve (Tailnet only, recommended).
|
||||||
ENABLE_FUNNEL_HTTPS=false
|
ENABLE_FUNNEL_HTTPS=false
|
||||||
|
|
||||||
# --- Primary Application Hostname ---
|
# --- Primary Hostname ---
|
||||||
# Primary hostname used by Traefik/Authelia. Derived from Tailscale settings by default.
|
# Primary hostname used by Traefik for routing. Derived from Tailscale settings by default.
|
||||||
# Renamed from HOSTNAME to avoid collision with host system environment variable.
|
HOSTNAME=${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}
|
||||||
APP_HOSTNAME=${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}
|
|
||||||
|
|
||||||
# --- Application Credentials ---
|
# --- Application Credentials ---
|
||||||
# qBittorrent Web UI Credentials (change default!)
|
# qBittorrent Web UI Credentials (change default!)
|
||||||
@@ -63,16 +62,14 @@ HOMEPAGE_VAR_WEATHER_UNIT=metric
|
|||||||
|
|
||||||
# --- Authelia Settings ---
|
# --- Authelia Settings ---
|
||||||
# Generate strong random secrets for these using tools like `openssl rand -hex 32`
|
# Generate strong random secrets for these using tools like `openssl rand -hex 32`
|
||||||
# These are all REQUIRED for Authelia to function properly
|
AUTHELIA_JWT_SECRET= # Example: your_strong_jwt_secret
|
||||||
AUTHELIA_JWT_SECRET= # Secret used for JWT tokens (password reset, etc)
|
AUTHELIA_SESSION_SECRET= # Example: your_strong_session_secret
|
||||||
AUTHELIA_SESSION_SECRET= # Secret for encrypting session cookies
|
AUTHELIA_STORAGE_ENCRYPTION_KEY= # Example: your_strong_storage_encryption_key
|
||||||
AUTHELIA_STORAGE_ENCRYPTION_KEY= # Secret for encrypting stored data
|
AUTHELIA_REDIS_PASSWORD= # Example: your_strong_redis_password
|
||||||
AUTHELIA_REDIS_PASSWORD= # Password for Redis session storage
|
|
||||||
|
|
||||||
# Note: The following variables are no longer needed with Authelia 4.38+ and the updated configuration
|
# Authelia Session Configuration
|
||||||
# They are preserved for backward compatibility but will be automatically mapped to the new structure
|
AUTHELIA_SESSION_DOMAIN=${HOSTNAME}
|
||||||
# AUTHELIA_SESSION_DOMAIN=${APP_HOSTNAME}
|
AUTHELIA_DEFAULT_REDIRECT_URL=https://${HOSTNAME}/home
|
||||||
# AUTHELIA_DEFAULT_REDIRECT_URL=https://${APP_HOSTNAME}/home
|
|
||||||
|
|
||||||
# --- API Keys & Integration Tokens (Optional - Mainly for Homepage Widgets) ---
|
# --- API Keys & Integration Tokens (Optional - Mainly for Homepage Widgets) ---
|
||||||
# Find API keys within each application's settings (usually Settings > General or Security)
|
# Find API keys within each application's settings (usually Settings > General or Security)
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,9 +1,6 @@
|
|||||||
*.env
|
*.env
|
||||||
*.bak
|
|
||||||
.idea
|
.idea
|
||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
/authelia/*.yml
|
|
||||||
!/authelia/*.example.yml
|
|
||||||
/homepage/logs
|
/homepage/logs
|
||||||
/homepage/*.yaml
|
/homepage/*.yaml
|
||||||
/homepage/*.css
|
/homepage/*.css
|
||||||
|
|||||||
364
README.md
364
README.md
@@ -11,7 +11,6 @@ The core idea is to manage media libraries (movies, TV shows, music), automate d
|
|||||||
- [Architecture Overview](#architecture-overview)
|
- [Architecture Overview](#architecture-overview)
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- [Prerequisites](#prerequisites)
|
- [Prerequisites](#prerequisites)
|
||||||
- [Required Setup Steps](#required-setup-steps)
|
|
||||||
- [Quick Start Guide](#quick-start-guide)
|
- [Quick Start Guide](#quick-start-guide)
|
||||||
- [Configuration (`.env` Variables)](#configuration-env-variables)
|
- [Configuration (`.env` Variables)](#configuration-env-variables)
|
||||||
- [Core System \& Paths](#core-system--paths)
|
- [Core System \& Paths](#core-system--paths)
|
||||||
@@ -25,13 +24,9 @@ The core idea is to manage media libraries (movies, TV shows, music), automate d
|
|||||||
- [(Optional) VPN Configuration](#optional-vpn-configuration)
|
- [(Optional) VPN Configuration](#optional-vpn-configuration)
|
||||||
- [(Optional) Traefik DNS Challenge](#optional-traefik-dns-challenge)
|
- [(Optional) Traefik DNS Challenge](#optional-traefik-dns-challenge)
|
||||||
- [Service Access](#service-access)
|
- [Service Access](#service-access)
|
||||||
- [Setup Script Commands (`update-setup.sh`)](#setup-script-commands-update-setupsh)
|
|
||||||
- [Managing Service Authentication](#managing-service-authentication-authelia-policies)
|
|
||||||
- [Optional Services](#optional-services)
|
- [Optional Services](#optional-services)
|
||||||
- [Troubleshooting](#troubleshooting)
|
- [Troubleshooting](#troubleshooting)
|
||||||
- [Middleware Not Found Errors](#middleware-not-found-errors)
|
|
||||||
- [SELinux Socket Permissions (Docker)](#selinux-socket-permissions-docker)
|
- [SELinux Socket Permissions (Docker)](#selinux-socket-permissions-docker)
|
||||||
- [Authelia v4.38+ Configuration](#authelia-v438-configuration)
|
|
||||||
- [Tailscale Issues](#tailscale-issues)
|
- [Tailscale Issues](#tailscale-issues)
|
||||||
- [File Permissions](#file-permissions)
|
- [File Permissions](#file-permissions)
|
||||||
- [Advanced Topics](#advanced-topics)
|
- [Advanced Topics](#advanced-topics)
|
||||||
@@ -40,175 +35,104 @@ The core idea is to manage media libraries (movies, TV shows, music), automate d
|
|||||||
|
|
||||||
This stack uses a combination of key services for routing, access, and security:
|
This stack uses a combination of key services for routing, access, and security:
|
||||||
|
|
||||||
- **[Tailscale](https://tailscale.com):** Provides a secure overlay network (WireGuard-based VPN) connecting your devices. It allows access to the NAS services from anywhere without opening firewall ports and handles HTTPS termination via its built-in `tailscale serve` or `tailscale funnel` features. All other services run within Tailscale's network namespace.
|
* **[Tailscale](https://tailscale.com):** Provides a secure overlay network (WireGuard-based VPN) connecting your devices. It allows access to the NAS services from anywhere without opening firewall ports and handles HTTPS termination via its built-in `tailscale serve` or `tailscale funnel` features. All other services run within Tailscale's network namespace.
|
||||||
- **[Traefik](https://traefik.io):** Acts as a reverse proxy *within* the Tailscale network. It discovers services via Docker labels and routes incoming requests (from Tailscale) to the appropriate container based on paths (e.g., `/sonarr`, `/radarr`).
|
* **[Traefik](https://traefik.io):** Acts as a reverse proxy *within* the Tailscale network. It discovers services via Docker labels and routes incoming requests (from Tailscale) to the appropriate container based on paths (e.g., `/sonarr`, `/radarr`).
|
||||||
- **[Authelia](https://www.authelia.com):** Serves as the authentication gateway. Traefik forwards requests to Authelia for verification. If a user isn't logged in, they are redirected to the Authelia portal (`/`). Once authenticated, Authelia sets a session cookie (stored in Redis), and Traefik allows access to the requested service. You can configure which services require authentication via environment variables.
|
* **[Authelia](https://www.authelia.com):** Serves as the authentication gateway. Traefik forwards requests to Authelia for verification. If a user isn't logged in, they are redirected to the Authelia portal (`/`). Once authenticated, Authelia sets a session cookie (stored in Redis), and Traefik allows access to the requested service.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
This stack includes the following services, categorized for clarity:
|
This stack includes the following services, categorized for clarity:
|
||||||
|
|
||||||
**Core Infrastructure:**
|
**Core Infrastructure:**
|
||||||
|
* **Reverse Proxy:** [Traefik](https://traefik.io) - Manages internal routing and service discovery.
|
||||||
- **Reverse Proxy:** [Traefik](https://traefik.io) - Manages internal routing and service discovery.
|
* **Secure Remote Access:** [Tailscale](https://tailscale.com) - Provides VPN access and HTTPS.
|
||||||
- **Secure Remote Access:** [Tailscale](https://tailscale.com) - Provides VPN access and HTTPS.
|
* **Authentication:** [Authelia](https://www.authelia.com) & [Redis](https://redis.io) - Single sign-on portal and session management.
|
||||||
- **Authentication:** [Authelia](https://www.authelia.com) & [Redis](https://redis.io) - Single sign-on portal and session management.
|
* **Dashboard:** [Homepage](https://gethomepage.dev) - Centralized access point (at `/home`).
|
||||||
- **Dashboard:** [Homepage](https://gethomepage.dev) - Centralized access point (at `/home`).
|
|
||||||
|
|
||||||
**Media Management (\*Arr Suite):**
|
**Media Management (\*Arr Suite):**
|
||||||
|
* [Sonarr](https://sonarr.tv): TV show management.
|
||||||
- [Sonarr](https://sonarr.tv): TV show management.
|
* [Radarr](https://radarr.video): Movie management.
|
||||||
- [Radarr](https://radarr.video): Movie management.
|
* [Lidarr](https://lidarr.audio) (Optional): Music management.
|
||||||
- [Lidarr](https://lidarr.audio) (Optional): Music management.
|
* [Bazarr](https://www.bazarr.media/): Subtitle management.
|
||||||
- [Bazarr](https://www.bazarr.media/): Subtitle management.
|
* [Prowlarr](https://github.com/Prowlarr/Prowlarr): Indexer management for *arr apps.
|
||||||
- [Prowlarr](https://github.com/Prowlarr/Prowlarr): Indexer management for *arr apps.
|
|
||||||
|
|
||||||
**Download Clients:**
|
**Download Clients:**
|
||||||
|
* [qBittorrent](https://www.qbittorrent.org): Bittorrent client.
|
||||||
- [qBittorrent](https://www.qbittorrent.org): Bittorrent client.
|
* [SABnzbd](https://sabnzbd.org/) (Optional): Usenet download client.
|
||||||
- [SABnzbd](https://sabnzbd.org/) (Optional): Usenet download client.
|
|
||||||
|
|
||||||
**Media Serving & Requests:**
|
**Media Serving & Requests:**
|
||||||
|
* [Jellyfin](https://jellyfin.org): Media server for streaming.
|
||||||
- [Jellyfin](https://jellyfin.org): Media server for streaming.
|
* [Jellyseerr](https://github.com/FallenBagel/jellyseerr): Media request management.
|
||||||
- [Jellyseerr](https://github.com/FallenBagel/jellyseerr): Media request management.
|
|
||||||
|
|
||||||
**Utilities:**
|
**Utilities:**
|
||||||
|
* [Watchtower](https://containrrr.dev/watchtower/): Automatic container updates.
|
||||||
- [Watchtower](https://containrrr.dev/watchtower/): Automatic container updates.
|
* [Autoheal](https://github.com/willfarrell/docker-autoheal/): Automatic container restarts on failure.
|
||||||
- [Autoheal](https://github.com/willfarrell/docker-autoheal/): Automatic container restarts on failure.
|
* [Unpackerr](https://unpackerr.zip): Automated archive extraction.
|
||||||
- [Unpackerr](https://unpackerr.zip): Automated archive extraction.
|
|
||||||
|
|
||||||
**Optional Services (Enabled via Profiles):**
|
**Optional Services (Enabled via Profiles):**
|
||||||
|
* [AdGuard Home](https://adguard.com/en/adguard-home/overview.html): Network-wide ad blocking.
|
||||||
- [AdGuard Home](https://adguard.com/en/adguard-home/overview.html): Network-wide ad blocking.
|
* [Calibre-Web](https://github.com/janeczku/calibre-web): E-book library management.
|
||||||
- [Calibre-Web](https://github.com/janeczku/calibre-web): E-book library management.
|
* [Decluttarr](https://github.com/manimatter/decluttarr): Automated download cleanup.
|
||||||
- [Decluttarr](https://github.com/manimatter/decluttarr): Automated download cleanup.
|
* [Tandoor Recipes](https://docs.tandoor.dev/): Recipe management.
|
||||||
- [Tandoor Recipes](https://docs.tandoor.dev/): Recipe management.
|
* [Joplin Server](https://joplinapp.org/): Note-taking synchronization server.
|
||||||
- [Joplin Server](https://joplinapp.org/): Note-taking synchronization server.
|
* [Home Assistant](https://www.home-assistant.io/): Home automation platform.
|
||||||
- [Home Assistant](https://www.home-assistant.io/): Home automation platform.
|
* [Immich](https://immich.app/): Self-hosted photo and video backup.
|
||||||
- [Immich](https://immich.app/): Self-hosted photo and video backup.
|
* [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr): Bypasses Cloudflare challenges (e.g., for Prowlarr).
|
||||||
- [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr): Bypasses Cloudflare challenges (e.g., for Prowlarr).
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- **Linux Host:** A system capable of running Docker (e.g., Ubuntu, Debian, Fedora).
|
* **Linux Host:** A system capable of running Docker (e.g., Ubuntu, Debian, Fedora).
|
||||||
- **Docker & Docker Compose:** Latest versions installed. See [Docker Engine Install](https://docs.docker.com/engine/install/) and [Docker Compose Install](https://docs.docker.com/compose/install/).
|
* **Docker & Docker Compose:** Latest versions installed. See [Docker Engine Install](https://docs.docker.com/engine/install/) and [Docker Compose Install](https://docs.docker.com/compose/install/).
|
||||||
- **User Permissions:** Ability to run `docker` commands (user in `docker` group or use `sudo`).
|
* **User Permissions:** Ability to run `docker` commands (user in `docker` group or use `sudo`).
|
||||||
- **Basic Linux Knowledge:** Familiarity with command line, text editors, and file permissions.
|
* **Basic Linux Knowledge:** Familiarity with command line, text editors, and file permissions.
|
||||||
- **Tailscale Account:** Required for remote access. [Sign up here](https://tailscale.com/login).
|
* **Tailscale Account:** Required for remote access. [Sign up here](https://tailscale.com/login).
|
||||||
- **(Optional) SELinux:** If enabled, see [Troubleshooting](#selinux-socket-permissions-docker).
|
* **(Optional) SELinux:** If enabled, see [Troubleshooting](#selinux-socket-permissions).
|
||||||
|
|
||||||
## Required Setup Steps
|
|
||||||
|
|
||||||
These steps are **mandatory** for a working installation. Without properly completing these, the stack will not function correctly.
|
|
||||||
|
|
||||||
1. **⚠️ Required: System User Information**
|
|
||||||
- Set `USER_ID` and `GROUP_ID` in `.env` (run `id -u` and `id -g` to get yours)
|
|
||||||
- Incorrect values will cause permission errors with mounted volumes
|
|
||||||
|
|
||||||
2. **⚠️ Required: Directory Paths**
|
|
||||||
- Set `CONFIG_ROOT` (where service configurations will be stored)
|
|
||||||
- Set `DATA_ROOT` (where your media libraries will be stored)
|
|
||||||
- Set `DOWNLOAD_ROOT` (must be on same filesystem as DATA_ROOT for hardlinks)
|
|
||||||
|
|
||||||
3. **⚠️ Required: Tailscale Configuration**
|
|
||||||
- Create a Tailscale account at [tailscale.com](https://tailscale.com)
|
|
||||||
- Generate an Auth Key in the [Tailscale Admin Console](https://login.tailscale.com/admin/settings/keys)
|
|
||||||
- Set `TAILSCALE_AUTHKEY` in `.env`
|
|
||||||
- Set `TAILSCALE_TAILNET_DOMAIN` to your Tailnet domain (e.g., `your-name.ts.net`)
|
|
||||||
|
|
||||||
4. **⚠️ Required: Security Credentials**
|
|
||||||
- Generate four strong random secrets using `openssl rand -hex 32`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
echo "AUTHELIA_JWT_SECRET=$(openssl rand -hex 32)"
|
|
||||||
echo "AUTHELIA_SESSION_SECRET=$(openssl rand -hex 32)"
|
|
||||||
echo "AUTHELIA_STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)"
|
|
||||||
echo "AUTHELIA_REDIS_PASSWORD=$(openssl rand -hex 32)"
|
|
||||||
```
|
|
||||||
|
|
||||||
- Add these to your `.env` file as shown
|
|
||||||
|
|
||||||
5. **⚠️ Required: Create Authelia Account**
|
|
||||||
- Create an Authelia account (only for yourself and those you trust!)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
|
||||||
```
|
|
||||||
|
|
||||||
6. **ℹ️ Optional: Set up**
|
|
||||||
- Generate a password hash for Authelia:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
|
||||||
```
|
|
||||||
|
|
||||||
- Replace the example hash in `authelia/users_database.yml` with your generated hash
|
|
||||||
|
|
||||||
## Quick Start Guide
|
## Quick Start Guide
|
||||||
|
|
||||||
After completing all [Required Setup Steps](#required-setup-steps) above, follow these steps to get up and running:
|
This guide gets the core stack running quickly. **Read the full [Configuration](#configuration-env-variables) section afterwards for details.**
|
||||||
|
|
||||||
1. **Clone Repository:**
|
1. **Clone Repository:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/AdrienPoupa/docker-compose-nas.git
|
git clone https://github.com/AdrienPoupa/docker-compose-nas.git
|
||||||
cd docker-compose-nas
|
cd docker-compose-nas
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Configure Environment:**
|
2. **Create `.env` File:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create an .env file from the example
|
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
|
|
||||||
# Edit the .env file and fill in ALL required values
|
|
||||||
nano .env
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Configure Authelia Admin:**
|
3. **Critical `.env` Edits:** Open `.env` and set **at minimum**:
|
||||||
|
* `USER_ID` & `GROUP_ID`: Run `id -u` and `id -g` on your host to find these.
|
||||||
|
* `TIMEZONE`: Your local timezone (e.g., `Asia/Manila`).
|
||||||
|
* `TAILSCALE_AUTHKEY`: Generate an auth key in your [Tailscale Admin Console](https://login.tailscale.com/admin/settings/keys).
|
||||||
|
* `TAILSCALE_TAILNET_DOMAIN`: Your unique Tailnet domain (e.g., `your-name.ts.net`).
|
||||||
|
* `AUTHELIA_JWT_SECRET`, `AUTHELIA_SESSION_SECRET`, `AUTHELIA_STORAGE_ENCRYPTION_KEY`, `AUTHELIA_REDIS_PASSWORD`: **Generate unique, strong secrets** for these (e.g., using `openssl rand -hex 32`). **Do not use the examples!**
|
||||||
|
|
||||||
|
4. **Set Authelia Admin Password:**
|
||||||
|
* Generate a password hash (replace `'your_secure_password'`):
|
||||||
```bash
|
```bash
|
||||||
# Generate a password hash
|
|
||||||
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
||||||
|
|
||||||
# Edit the users_database.yml with the generated hash
|
|
||||||
nano authelia/users_database.yml
|
|
||||||
```
|
```
|
||||||
|
* Copy the **entire output hash** (starting with `$argon2id...`).
|
||||||
4. **Run the Setup Script:**
|
* Open `authelia/users_database.yml` and replace the example `password:` value under `admin:` with your generated hash.
|
||||||
|
|
||||||
```bash
|
|
||||||
# Make the script executable
|
|
||||||
chmod +x ./update-setup.sh
|
|
||||||
|
|
||||||
# Run the setup tool (use 'all' for initial setup)
|
|
||||||
./update-setup.sh all
|
|
||||||
```
|
|
||||||
|
|
||||||
This script will:
|
|
||||||
- Update your `.env` file while preserving existing values (`update-env`).
|
|
||||||
- Configure Authelia with your Tailscale domain settings (`update-authelia`).
|
|
||||||
- Set up service configurations and retrieve API keys (`update-services`).
|
|
||||||
|
|
||||||
You can also run individual commands like `./update-setup.sh update-authelia`. Run `./update-setup.sh help` for all options.
|
|
||||||
|
|
||||||
5. **Start the Stack:**
|
5. **Start the Stack:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Make helper script executable (if needed)
|
||||||
|
chmod +x ./update-config.sh
|
||||||
# Start containers
|
# Start containers
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
*(Wait for containers to download and start)*
|
*(Wait for containers to download and start)*
|
||||||
|
|
||||||
6. **Access Your NAS:**
|
6. **(Optional) Run Config Script:** This attempts to set API keys/URLs in *arr apps based on `.env`. May require manual adjustments in apps later.
|
||||||
- Open `https://<TAILSCALE_HOSTNAME>.<TAILSCALE_TAILNET_DOMAIN>/`
|
```bash
|
||||||
- Log in with username `admin` and the password you set
|
./update-config.sh
|
||||||
- After login, you'll land on the Homepage dashboard at `/home`
|
```
|
||||||
|
|
||||||
> ⚠️ **IMPORTANT:** If the stack fails to start, check the [Troubleshooting](#troubleshooting) section and verify you've properly completed all [Required Setup Steps](#required-setup-steps).
|
7. **Access:** Navigate to `https://<TAILSCALE_HOSTNAME>.<TAILSCALE_TAILNET_DOMAIN>/`. You should be redirected to the Authelia login. Use `admin` and the password you set in step 4. After login, you'll land on the Homepage dashboard at `/home`.
|
||||||
|
|
||||||
## Configuration (`.env` Variables)
|
## Configuration (`.env` Variables)
|
||||||
|
|
||||||
@@ -235,16 +159,18 @@ This file controls essential settings. Copy `.env.example` to `.env` and modify
|
|||||||
| `TAILSCALE_HOSTNAME` | Desired hostname for this NAS within Tailscale. | `tailscale-nas` |
|
| `TAILSCALE_HOSTNAME` | Desired hostname for this NAS within Tailscale. | `tailscale-nas` |
|
||||||
| `TAILSCALE_TAGS` | Optional tags for the Tailscale node (e.g., `tag:nas`). | `tag:nas` |
|
| `TAILSCALE_TAGS` | Optional tags for the Tailscale node (e.g., `tag:nas`). | `tag:nas` |
|
||||||
| `ENABLE_FUNNEL_HTTPS` | Use Tailscale Funnel (`true` = public access via Tailscale domain) or Serve (`false` = Tailnet-only access, recommended). | `false` |
|
| `ENABLE_FUNNEL_HTTPS` | Use Tailscale Funnel (`true` = public access via Tailscale domain) or Serve (`false` = Tailnet-only access, recommended). | `false` |
|
||||||
| `APP_HOSTNAME` | Primary hostname used by Traefik/Authelia. Defaults to Tailscale FQDN. Renamed from `HOSTNAME` to avoid host system conflicts. Can be overridden if using custom DNS. | `${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}` |
|
| `HOSTNAME` | Primary hostname used by Traefik/Authelia. Defaults to Tailscale FQDN. Can be overridden if using custom DNS pointing to Tailscale IP. | `${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}` |
|
||||||
|
|
||||||
#### Authentication (Authelia)
|
#### Authentication (Authelia)
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default |
|
||||||
| :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------- |
|
| :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------- |
|
||||||
| **`AUTHELIA_JWT_SECRET`** | **Required.** Random secret for Authelia (used for password reset JWT). **Generate your own!** | *(None - Example in file)* |
|
| **`AUTHELIA_JWT_SECRET`** | **Required.** Random secret for signing JWTs. **Generate your own!** | *(None - Example in file)* |
|
||||||
| **`AUTHELIA_SESSION_SECRET`** | **Required.** Random secret for session cookies. **Generate your own!** | *(None - Example in file)* |
|
| **`AUTHELIA_SESSION_SECRET`** | **Required.** Random secret for session cookies. **Generate your own!** | *(None - Example in file)* |
|
||||||
| **`AUTHELIA_STORAGE_ENCRYPTION_KEY`** | **Required.** Random secret for encrypting data at rest (e.g., SQLite DB). **Generate your own!** | *(None - Example in file)* |
|
| **`AUTHELIA_STORAGE_ENCRYPTION_KEY`** | **Required.** Random secret for encrypting data at rest. **Generate your own!** | *(None - Example in file)* |
|
||||||
| **`AUTHELIA_REDIS_PASSWORD`** | **Required.** Password for the Redis database (used for session storage). **Generate your own!** | *(None - Example in file)* |
|
| **`AUTHELIA_REDIS_PASSWORD`** | **Required.** Password for the Redis database. **Generate your own!** | *(None - Example in file)* |
|
||||||
|
| `AUTHELIA_SESSION_DOMAIN` | Domain for session cookies. Should match `HOSTNAME`. | `${HOSTNAME}` |
|
||||||
|
| `AUTHELIA_DEFAULT_REDIRECT_URL` | Where users land after login. | `https://${HOSTNAME}/home` |
|
||||||
|
|
||||||
#### Service Credentials
|
#### Service Credentials
|
||||||
|
|
||||||
@@ -307,23 +233,20 @@ This file controls essential settings. Copy `.env.example` to `.env` and modify
|
|||||||
|
|
||||||
Authelia uses the `authelia/users_database.yml` file to manage users.
|
Authelia uses the `authelia/users_database.yml` file to manage users.
|
||||||
|
|
||||||
- **Setting the Initial Admin Password:**
|
* **Setting the Initial Admin Password:**
|
||||||
1. As mentioned in the Quick Start, you **must** set a strong password for the default `admin` user.
|
1. As mentioned in the Quick Start, you **must** set a strong password for the default `admin` user.
|
||||||
2. Generate a hash using Docker (replace `'your_secure_password'`):
|
2. Generate a hash using Docker (replace `'your_secure_password'`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
docker run --rm authelia/authelia:latest authelia hash-password 'your_secure_password'
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Copy the **entire output hash** (starting with `$argon2id...`).
|
3. Copy the **entire output hash** (starting with `$argon2id...`).
|
||||||
4. Open `authelia/users_database.yml` and replace the example `password:` value under `admin:` with your generated hash.
|
4. Open `authelia/users_database.yml` and replace the example `password:` value under `admin:` with your generated hash.
|
||||||
5. Ensure the `admin` user belongs to the `admins` and `users` groups as shown in the example.
|
5. Ensure the `admin` user belongs to the `admins` and `users` groups as shown in the example.
|
||||||
|
|
||||||
- **Adding More Users:**
|
* **Adding More Users:**
|
||||||
1. Generate a password hash for the new user as shown above.
|
1. Generate a password hash for the new user as shown above.
|
||||||
2. Edit `authelia/users_database.yml`.
|
2. Edit `authelia/users_database.yml`.
|
||||||
3. Add a new entry under `users:`, following the format of the `admin` user:
|
3. Add a new entry under `users:`, following the format of the `admin` user:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
users:
|
users:
|
||||||
admin:
|
admin:
|
||||||
@@ -335,26 +258,25 @@ Authelia uses the `authelia/users_database.yml` file to manage users.
|
|||||||
groups:
|
groups:
|
||||||
- users # Add to 'admins' group if needed
|
- users # Add to 'admins' group if needed
|
||||||
```
|
```
|
||||||
|
4. Save the file. Authelia should pick up the changes automatically (or restart the Authelia container: `docker compose restart authelia`).
|
||||||
|
|
||||||
4. Save the file and restart Authelia: `docker compose restart authelia`.
|
* **Enabling User Registration (Optional):**
|
||||||
|
|
||||||
- **Adding/Updating Users (Recommended Method):**
|
|
||||||
Use the setup script's interactive tool:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./update-setup.sh manage-accounts
|
|
||||||
```
|
|
||||||
|
|
||||||
This script handles password hashing and file formatting, reducing the chance of errors. It will prompt you for the username, display name, email, and groups, then generate a secure password hash.
|
|
||||||
|
|
||||||
- **Enabling User Registration (Optional):**
|
|
||||||
1. Edit `authelia/configuration.yml`.
|
1. Edit `authelia/configuration.yml`.
|
||||||
2. Find the commented-out `registration:` section near the bottom.
|
2. Find the commented-out `registration:` section near the bottom.
|
||||||
3. Uncomment it and set `enable: true`.
|
3. Uncomment it and set `enable: true`:
|
||||||
|
```yaml
|
||||||
|
# registration:
|
||||||
|
# enable: false # Set to true to enable registration form
|
||||||
|
```
|
||||||
|
becomes:
|
||||||
|
```yaml
|
||||||
|
registration:
|
||||||
|
enable: true
|
||||||
|
```
|
||||||
4. Save the file and restart Authelia (`docker compose restart authelia`).
|
4. Save the file and restart Authelia (`docker compose restart authelia`).
|
||||||
5. A "Register" link will now appear on the Authelia login page.
|
5. A "Register" link will now appear on the Authelia login page.
|
||||||
|
|
||||||
- **Approving Registered Users:**
|
* **Approving Registered Users:**
|
||||||
1. When a user registers (if enabled), their details are added to `authelia/users_database.yml` but marked as `disabled: true`.
|
1. When a user registers (if enabled), their details are added to `authelia/users_database.yml` but marked as `disabled: true`.
|
||||||
2. To approve them, edit `authelia/users_database.yml`.
|
2. To approve them, edit `authelia/users_database.yml`.
|
||||||
3. Find the new user's entry.
|
3. Find the new user's entry.
|
||||||
@@ -371,103 +293,54 @@ Authelia uses the `authelia/users_database.yml` file to manage users.
|
|||||||
|
|
||||||
## Service Access
|
## Service Access
|
||||||
|
|
||||||
With the default Tailscale setup and Authelia enabled, services are securely accessible via HTTPS using your Tailscale node's name or IP. Authentication is controlled by the included `update-setup.sh` script.
|
With the default Tailscale setup and Authelia enabled, services are securely accessible via HTTPS using your Tailscale node's name or IP. Access requires authentication via Authelia.
|
||||||
|
|
||||||
- **Login Portal:** `https://<TAILSCALE_NODE>/` (Redirects unauthenticated users here for secured services)
|
* **Login Portal:** `https://<TAILSCALE_NODE>/` (Redirects unauthenticated users here)
|
||||||
- **Homepage Dashboard:** `https://<TAILSCALE_NODE>/home` (Requires login by default)
|
* **Homepage Dashboard:** `https://<TAILSCALE_NODE>/home` (Accessible after login)
|
||||||
- **Sonarr:** `https://<TAILSCALE_NODE>/sonarr` (Requires login by default)
|
* **Sonarr:** `https://<TAILSCALE_NODE>/sonarr` (Requires login)
|
||||||
- **Radarr:** `https://<TAILSCALE_NODE>/radarr` (Requires login by default)
|
* **Radarr:** `https://<TAILSCALE_NODE>/radarr` (Requires login)
|
||||||
- **qBittorrent:** `https://<TAILSCALE_NODE>/qbittorrent` (Requires login by default)
|
* **qBittorrent:** `https://<TAILSCALE_NODE>/qbittorrent`
|
||||||
- **Jellyfin:** `https://<TAILSCALE_NODE>/jellyfin` (Requires login by default)
|
* **Jellyfin:** `https://<TAILSCALE_NODE>/jellyfin`
|
||||||
- ...and so on.
|
* ...and so on.
|
||||||
|
|
||||||
Replace `<TAILSCALE_NODE>` with your Tailscale device name (e.g., `tailscale-nas.your-tailnet.ts.net`) or its Tailscale IP address.
|
Replace `<TAILSCALE_NODE>` with your Tailscale device name (e.g., `tailscale-nas.your-tailnet.ts.net`) or its Tailscale IP address.
|
||||||
|
|
||||||
If you configure DNS for your `APP_HOSTNAME` variable to point to the Tailscale IP, you can use `https://<APP_HOSTNAME>/<service_path>`.
|
If you configure DNS for your `HOSTNAME` variable to point to the Tailscale IP, you can use `https://<HOSTNAME>/<service_path>`.
|
||||||
|
|
||||||
### Setup Script Commands (`update-setup.sh`)
|
|
||||||
|
|
||||||
The `update-setup.sh` script provides various commands to manage your configuration. Run `./update-setup.sh help` to see all options.
|
|
||||||
|
|
||||||
**Core Setup & Updates:**
|
|
||||||
|
|
||||||
- `./update-setup.sh update-env`: Updates `.env` from `.env.example`, preserving existing values and highlighting new/deprecated keys.
|
|
||||||
- `./update-setup.sh update-authelia`: Updates `authelia/configuration.yml` from the example, applying domain settings from `.env` and attempting to preserve secrets (uses `yq` if available).
|
|
||||||
- `./update-setup.sh update-services`: Updates configurations for running *arr/qBittorrent/Bazarr containers (sets URL base, extracts API keys to `.env`). Restarts affected containers.
|
|
||||||
- `./update-setup.sh all`: Runs `update-env`, `update-authelia`, and `update-services` sequentially. Recommended for initial setup and major updates.
|
|
||||||
|
|
||||||
**Authelia Policy Management:**
|
|
||||||
|
|
||||||
- `./update-setup.sh manage-policies`: Starts an interactive menu to list or set Authelia access policies (`one_factor`, `two_factor`, `bypass`, `deny`) for specific services defined in `authelia/configuration.yml`.
|
|
||||||
- `./update-setup.sh list-policies`: Lists services defined in `authelia/configuration.yml` and their current access policy.
|
|
||||||
- `./update-setup.sh set-policy <service> <policy>`: Directly sets the Authelia access policy for the specified `<service>` to the given `<policy>` (e.g., `one_factor`, `two_factor`, `bypass`, `deny`).
|
|
||||||
|
|
||||||
> **Important:** After changing Authelia policies using `manage-policies` or `set-policy`, you **must** restart Authelia for the changes to take effect:
|
|
||||||
>
|
|
||||||
> ```bash
|
|
||||||
> docker compose restart authelia
|
|
||||||
> ```
|
|
||||||
|
|
||||||
**User & File Management:**
|
|
||||||
|
|
||||||
- `./update-setup.sh manage-accounts`: Starts an interactive tool to add or update users in `authelia/users_database.yml`. It generates password hashes and prompts for user details.
|
|
||||||
- `./update-setup.sh cleanup`: Interactively finds and deletes old backup files (`.bak`) created by the script. Allows keeping the most recent backup of each type.
|
|
||||||
|
|
||||||
**Help:**
|
|
||||||
|
|
||||||
- `./update-setup.sh help`: Displays the full list of commands and usage instructions.
|
|
||||||
|
|
||||||
### Managing Service Authentication (Authelia Policies)
|
|
||||||
|
|
||||||
Use the `update-setup.sh` script to easily control which services require Authelia login and what level of authentication is needed. This is done by managing *access control rules* within Authelia's configuration (`authelia/configuration.yml`).
|
|
||||||
|
|
||||||
See the `Authelia Policy Management` commands in the [Setup Script Commands](#setup-script-commands-update-setupsh) section above for details on how to list and set policies like `one_factor`, `two_factor`, `bypass`, or `deny` for each service.
|
|
||||||
|
|
||||||
## Optional Services
|
## 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).
|
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
|
Example: Enable Lidarr and SABnzbd
|
||||||
|
|
||||||
```dotenv
|
```dotenv
|
||||||
COMPOSE_PROFILES=lidarr,sabnzbd
|
COMPOSE_PROFILES=lidarr,sabnzbd
|
||||||
```
|
```
|
||||||
|
|
||||||
Available Profiles:
|
Available Profiles:
|
||||||
|
* `lidarr`: Music management.
|
||||||
- `lidarr`: Music management.
|
* `sabnzbd`: Usenet download client.
|
||||||
- `sabnzbd`: Usenet download client.
|
* `flaresolverr`: Bypasses Cloudflare challenges for Prowlarr.
|
||||||
- `flaresolverr`: Bypasses Cloudflare challenges for Prowlarr.
|
* `adguardhome`: Network-wide ad blocking (see `adguardhome/README.md`).
|
||||||
- `adguardhome`: Network-wide ad blocking (see `adguardhome/README.md`).
|
* `calibre-web`: E-book library management.
|
||||||
- `calibre-web`: E-book library management.
|
* `decluttarr`: Automated download cleanup.
|
||||||
- `decluttarr`: Automated download cleanup.
|
* `tandoor`: Recipe management (see `tandoor/README.md`).
|
||||||
- `tandoor`: Recipe management (see `tandoor/README.md`).
|
* `joplin`: Note-taking server (see `joplin/README.md`).
|
||||||
- `joplin`: Note-taking server (see `joplin/README.md`).
|
* `homeassistant`: Home automation (see `homeassistant/README.md`).
|
||||||
- `homeassistant`: Home automation (see `homeassistant/README.md`).
|
* `immich`: Photo management (see `immich/README.md`).
|
||||||
- `immich`: Photo management (see `immich/README.md`).
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Middleware Not Found Errors
|
|
||||||
|
|
||||||
If you see error messages like `middleware "authelia-auth@docker" does not exist` in the Traefik logs, please check Authelia logs for any fatal errors. It is likely due to a misconfigured `configuration.yml` in `authelia/configuration.yml`
|
|
||||||
|
|
||||||
Make sure Traefik can access the Docker socket. See the [SELinux Socket Permissions](#selinux-socket-permissions-docker) section below for more details.
|
|
||||||
|
|
||||||
### SELinux Socket Permissions (Docker)
|
### 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`:
|
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:
|
1. **Check Audit Logs:** Immediately after seeing the error, check the SELinux audit log on the host:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo ausearch -m avc -ts recent
|
sudo ausearch -m avc -ts recent
|
||||||
```
|
```
|
||||||
|
|
||||||
Look for lines containing `denied`, `docker.sock`, and the name of the failing service (e.g., `traefik`, `watchtower`).
|
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:
|
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
|
```bash
|
||||||
# Generate policy files (my-dockersock.te and my-dockersock.pp)
|
# Generate policy files (my-dockersock.te and my-dockersock.pp)
|
||||||
sudo ausearch -m avc -ts recent | audit2allow -M my-dockersock
|
sudo ausearch -m avc -ts recent | audit2allow -M my-dockersock
|
||||||
@@ -475,61 +348,20 @@ If you are running Docker on a host with SELinux enabled (like Fedora, CentOS, R
|
|||||||
# Install the policy module
|
# Install the policy module
|
||||||
sudo semodule -i my-dockersock.pp
|
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.
|
This allows the specific actions that were being denied. You might need to repeat this if different denials appear after applying the first policy.
|
||||||
|
|
||||||
### Authelia v4.38+ Configuration
|
|
||||||
|
|
||||||
Authelia v4.38+ introduces significant changes to its configuration structure, particularly for session domains and authentication flows. The setup in this repository has been carefully configured to work with these changes:
|
|
||||||
|
|
||||||
1. **Domain Configuration**:
|
|
||||||
- You must use your specific Tailnet domain (e.g., `example.ts.net`) for cookies, not just `ts.net`
|
|
||||||
- The domain `ts.net` is part of the [Public Suffix List](https://publicsuffix.org/), which means browsers restrict cookies on it for security reasons
|
|
||||||
- Authelia will refuse to start if you try to use a domain from this list
|
|
||||||
|
|
||||||
2. **Required Secret Variables**: You must set these four variables in your `.env` file:
|
|
||||||
- `AUTHELIA_JWT_SECRET`: Used for password reset tokens
|
|
||||||
- `AUTHELIA_SESSION_SECRET`: Used for session cookie encryption
|
|
||||||
- `AUTHELIA_STORAGE_ENCRYPTION_KEY`: Used for database encryption
|
|
||||||
- `AUTHELIA_REDIS_PASSWORD`: Used for Redis authentication
|
|
||||||
|
|
||||||
Generate strong random values for these with: `openssl rand -hex 32`
|
|
||||||
|
|
||||||
3. **Automatic Domain Setup**: The `update-setup.sh` script automatically:
|
|
||||||
- Uses your specific Tailnet domain (e.g., `example.ts.net`) from your `.env` file
|
|
||||||
- Configures cookie domains properly to avoid Public Suffix List issues
|
|
||||||
- Sets up proper access control rules for both your domain and its subdomains
|
|
||||||
|
|
||||||
If you encounter any of these common errors:
|
|
||||||
|
|
||||||
```log
|
|
||||||
error: option 'domain' is not a valid cookie domain: the domain is part of the special public suffix list
|
|
||||||
error: option 'authelia_url' does not share a cookie scope with domain
|
|
||||||
error: can't be specified at the same time: option 'domain' and option 'cookies'
|
|
||||||
configuration key 'jwt_secret' is deprecated in 4.38.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Running the setup script should resolve them. After making changes to the configuration, restart Authelia with:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose restart authelia
|
|
||||||
```
|
|
||||||
|
|
||||||
See the [Authelia documentation](https://www.authelia.com/configuration/session/introduction/) for more details on the v4.38+ configuration structure.
|
|
||||||
|
|
||||||
### Tailscale Issues
|
### 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.
|
* **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`).
|
* **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.
|
* **Funnel/Serve Command:** If you modified the Tailscale command, ensure the syntax for `tailscale funnel` or `tailscale serve` is correct.
|
||||||
|
|
||||||
### File Permissions
|
### File Permissions
|
||||||
|
|
||||||
If services report permission errors when accessing `/config` or `/data` directories, double-check that:
|
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 `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.
|
||||||
- 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.
|
||||||
- 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
|
## Advanced Topics
|
||||||
|
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
# Authelia Configuration File v4.38+
|
|
||||||
# Documentation: https://www.authelia.com/configuration/
|
|
||||||
|
|
||||||
# Server settings
|
|
||||||
server:
|
|
||||||
address: 'tcp://0.0.0.0:9091'
|
|
||||||
|
|
||||||
# Logging configuration
|
|
||||||
log:
|
|
||||||
level: info
|
|
||||||
format: text
|
|
||||||
|
|
||||||
# Session configuration for v4.38+
|
|
||||||
session:
|
|
||||||
name: authelia_session
|
|
||||||
secret: ${AUTHELIA_SESSION_SECRET}
|
|
||||||
expiration: 1h
|
|
||||||
inactivity: 5m
|
|
||||||
redis:
|
|
||||||
host: redis
|
|
||||||
port: 6379
|
|
||||||
password: ${AUTHELIA_SESSION_REDIS_PASSWORD}
|
|
||||||
database_index: 0
|
|
||||||
cookies:
|
|
||||||
# Using your specific Tailscale domain (e.g. example.ts.net) not just ts.net
|
|
||||||
- domain: 'your-tailnet.ts.net'
|
|
||||||
authelia_url: 'https://tailscale-nas.your-tailnet.ts.net'
|
|
||||||
default_redirection_url: 'https://tailscale-nas.your-tailnet.ts.net/home'
|
|
||||||
same_site: lax
|
|
||||||
|
|
||||||
# Regulation (brute force protection)
|
|
||||||
regulation:
|
|
||||||
max_retries: 3
|
|
||||||
find_time: 2m
|
|
||||||
ban_time: 5m
|
|
||||||
|
|
||||||
# Storage (for user preferences, etc. - encrypted using storage key)
|
|
||||||
storage:
|
|
||||||
encryption_key: ${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
|
||||||
local:
|
|
||||||
path: /config/db.sqlite3
|
|
||||||
|
|
||||||
# Authentication backend (using file-based user database)
|
|
||||||
authentication_backend:
|
|
||||||
file:
|
|
||||||
path: /config/users_database.yml
|
|
||||||
password:
|
|
||||||
algorithm: argon2id
|
|
||||||
iterations: 1
|
|
||||||
memory: 1024
|
|
||||||
parallelism: 8
|
|
||||||
salt_length: 16
|
|
||||||
key_length: 32
|
|
||||||
|
|
||||||
# Access control rules
|
|
||||||
access_control:
|
|
||||||
default_policy: deny # Deny access by default
|
|
||||||
rules:
|
|
||||||
# Rules are processed in order. First match wins.
|
|
||||||
# It's recommended to put more specific rules first.
|
|
||||||
|
|
||||||
# 1. Bypass rules (No authentication required)
|
|
||||||
# Allow access to Authelia's own endpoints
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/auth.*' # Match /auth and anything after it
|
|
||||||
policy: bypass
|
|
||||||
# Allow access to the root path (will be redirected by Traefik later)
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path: '/'
|
|
||||||
policy: bypass
|
|
||||||
# Allow access to API endpoints (as requested, review security implications)
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/api.*' # Match /api and anything after it
|
|
||||||
policy: bypass
|
|
||||||
|
|
||||||
# 2. One-Factor Authentication Rules (Requires login)
|
|
||||||
# Add rules for each service you want to protect.
|
|
||||||
# The domain should match your Tailscale domain.
|
|
||||||
# The path should match the Traefik PathPrefix for the service.
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/sonarr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/radarr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/lidarr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/bazarr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/qbittorrent.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/sabnzbd.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/calibre.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/home.*' # Protect the homepage
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/jellyseerr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/prowlarr.*'
|
|
||||||
policy: one_factor
|
|
||||||
- domain: '*.your-tailnet.ts.net'
|
|
||||||
path_regex: '^/flaresolverr.*'
|
|
||||||
policy: one_factor
|
|
||||||
# Add other services here following the pattern:
|
|
||||||
# - domain: '*.your-tailnet.ts.net'
|
|
||||||
# path_regex: '^/<service_path>.*'
|
|
||||||
# policy: one_factor
|
|
||||||
|
|
||||||
# 3. Default rule for the domain (optional, if you want a catch-all)
|
|
||||||
# This rule will apply if no path-specific rule above matches.
|
|
||||||
# You might want to deny or require one_factor for unmatched paths.
|
|
||||||
# Example: Deny any other path on the domain
|
|
||||||
# - domain: '*.your-tailnet.ts.net'
|
|
||||||
# policy: deny
|
|
||||||
# Example: Require login for any other path
|
|
||||||
# - domain: '*.your-tailnet.ts.net'
|
|
||||||
# policy: one_factor
|
|
||||||
|
|
||||||
# Notifier configuration
|
|
||||||
notifier:
|
|
||||||
filesystem:
|
|
||||||
filename: /config/notification.txt
|
|
||||||
|
|
||||||
# Identity Validation (includes JWT secret for password reset)
|
|
||||||
identity_validation:
|
|
||||||
reset_password:
|
|
||||||
jwt_secret: ${AUTHELIA_JWT_SECRET}
|
|
||||||
|
|
||||||
# Identity Providers
|
|
||||||
identity_providers:
|
|
||||||
oidc: null
|
|
||||||
83
authelia/configuration.yml
Normal file
83
authelia/configuration.yml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Authelia Configuration File
|
||||||
|
# Documentation: https://www.authelia.com/configuration/
|
||||||
|
|
||||||
|
# Default configuration options affecting multiple sections.
|
||||||
|
default_redirection_url: ${AUTHELIA_DEFAULT_REDIRECT_URL}
|
||||||
|
|
||||||
|
# Server settings (listening address, paths, etc.)
|
||||||
|
server:
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 9091
|
||||||
|
|
||||||
|
# Logging configuration
|
||||||
|
log:
|
||||||
|
level: info
|
||||||
|
format: text # or json
|
||||||
|
|
||||||
|
# Session configuration
|
||||||
|
session:
|
||||||
|
name: authelia_session
|
||||||
|
secret: ${AUTHELIA_SESSION_SECRET}
|
||||||
|
expiration: 1h # Adjust as needed
|
||||||
|
inactivity: 5m # Adjust as needed
|
||||||
|
domain: ${AUTHELIA_SESSION_DOMAIN} # Set from .env
|
||||||
|
redis:
|
||||||
|
host: redis
|
||||||
|
port: 6379
|
||||||
|
password: ${AUTHELIA_REDIS_PASSWORD}
|
||||||
|
database_index: 0
|
||||||
|
|
||||||
|
# Regulation (brute force protection)
|
||||||
|
regulation:
|
||||||
|
max_retries: 3
|
||||||
|
find_time: 2m
|
||||||
|
ban_time: 5m
|
||||||
|
|
||||||
|
# Storage (for user preferences, etc. - encrypted using storage key)
|
||||||
|
storage:
|
||||||
|
encryption_key: ${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
||||||
|
local:
|
||||||
|
path: /config/db.sqlite3 # Example using SQLite for simple storage needs
|
||||||
|
|
||||||
|
# Authentication backend (using file-based user database)
|
||||||
|
authentication_backend:
|
||||||
|
file:
|
||||||
|
path: /config/users_database.yml
|
||||||
|
password:
|
||||||
|
algorithm: argon2id # Recommended hashing algorithm
|
||||||
|
iterations: 1
|
||||||
|
memory: 1024 # MiB
|
||||||
|
parallelism: 8
|
||||||
|
salt_length: 16
|
||||||
|
key_length: 32
|
||||||
|
|
||||||
|
# Access control rules
|
||||||
|
access_control:
|
||||||
|
default_policy: deny # Deny access by default
|
||||||
|
rules:
|
||||||
|
# Rule to allow authenticated users access to the domain
|
||||||
|
- domain: ${AUTHELIA_SESSION_DOMAIN}
|
||||||
|
policy: one_factor # Requires username/password
|
||||||
|
|
||||||
|
# Notifier (Optional, for password resets, etc. - configure if needed)
|
||||||
|
# notifier:
|
||||||
|
# smtp:
|
||||||
|
# address: smtp.example.com:587
|
||||||
|
# username: user@example.com
|
||||||
|
# password: password
|
||||||
|
# sender: Authelia <authelia@example.com>
|
||||||
|
# subject: "[Authelia] {title}"
|
||||||
|
# startup_check_address: test@authelia.com
|
||||||
|
|
||||||
|
# JWT configuration (used for forwardAuth)
|
||||||
|
jwt_secret: ${AUTHELIA_JWT_SECRET}
|
||||||
|
|
||||||
|
# Identity Providers (None configured for this setup)
|
||||||
|
identity_providers:
|
||||||
|
oidc: null # Explicitly disable OIDC
|
||||||
|
|
||||||
|
# Enable registration (requires manual approval by editing users_database.yml)
|
||||||
|
# Set 'enable: true' to allow users to register.
|
||||||
|
# They will be added to users_database.yml commented out or with disabled: true.
|
||||||
|
# registration:
|
||||||
|
# enable: false # Set to true to enable registration form
|
||||||
@@ -13,11 +13,14 @@ services:
|
|||||||
- --experimental.plugins.rewrite-body.version=v1.2.0
|
- --experimental.plugins.rewrite-body.version=v1.2.0
|
||||||
- --experimental.plugins.rewriteHeaders.modulename=github.com/XciD/traefik-plugin-rewrite-headers
|
- --experimental.plugins.rewriteHeaders.modulename=github.com/XciD/traefik-plugin-rewrite-headers
|
||||||
- --experimental.plugins.rewriteHeaders.version=v0.0.3
|
- --experimental.plugins.rewriteHeaders.version=v0.0.3
|
||||||
- --providers.docker.network=docker-compose-nas
|
network_mode: service:tailscale # Add this line
|
||||||
- --providers.docker.endpoint=unix:///var/run/docker.sock
|
# ports: # Remove this section
|
||||||
network_mode: service:tailscale
|
# - "80:80"
|
||||||
|
# - "443:443"
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
# extra_hosts: # Remove this section
|
||||||
|
# - host.docker.internal:172.17.0.1
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "traefik", "healthcheck", "--ping"]
|
test: ["CMD", "traefik", "healthcheck", "--ping"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@@ -28,11 +31,11 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- REDIS_PASSWORD=${AUTHELIA_REDIS_PASSWORD}
|
- REDIS_PASSWORD=${AUTHELIA_REDIS_PASSWORD}
|
||||||
command: ["redis-server", "--requirepass", "${AUTHELIA_REDIS_PASSWORD}"]
|
command: ["redis-server", "--requirepass", "$$REDIS_PASSWORD"] # Use $$ to escape $ for compose
|
||||||
volumes:
|
volumes:
|
||||||
- ${CONFIG_ROOT:-.}/redis:/data:Z
|
- ${CONFIG_ROOT:-.}/redis:/data:Z
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "redis-cli", "-a", "${AUTHELIA_REDIS_PASSWORD}", "ping"]
|
test: ["CMD", "redis-cli", "-a", "$$REDIS_PASSWORD", "ping"] # Use $$ to escape $ for compose
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
retries: 5
|
retries: 5
|
||||||
@@ -40,29 +43,32 @@ services:
|
|||||||
image: authelia/authelia:latest
|
image: authelia/authelia:latest
|
||||||
container_name: authelia
|
container_name: authelia
|
||||||
restart: always
|
restart: always
|
||||||
user: ${USER_ID}:${GROUP_ID}
|
|
||||||
volumes:
|
volumes:
|
||||||
- ${CONFIG_ROOT:-.}/authelia:/config:Z
|
- ${CONFIG_ROOT:-.}/authelia:/config:Z
|
||||||
environment:
|
environment:
|
||||||
|
- AUTHELIA_JWT_SECRET=${AUTHELIA_JWT_SECRET}
|
||||||
- AUTHELIA_SESSION_SECRET=${AUTHELIA_SESSION_SECRET}
|
- AUTHELIA_SESSION_SECRET=${AUTHELIA_SESSION_SECRET}
|
||||||
- AUTHELIA_STORAGE_ENCRYPTION_KEY=${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
- AUTHELIA_STORAGE_ENCRYPTION_KEY=${AUTHELIA_STORAGE_ENCRYPTION_KEY}
|
||||||
- AUTHELIA_SESSION_REDIS_PASSWORD=${AUTHELIA_REDIS_PASSWORD}
|
- AUTHELIA_REDIS_PASSWORD=${AUTHELIA_REDIS_PASSWORD}
|
||||||
- AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET=${AUTHELIA_JWT_SECRET}
|
- AUTHELIA_SESSION_DOMAIN=${AUTHELIA_SESSION_DOMAIN}
|
||||||
|
- AUTHELIA_DEFAULT_REDIRECT_URL=${AUTHELIA_DEFAULT_REDIRECT_URL}
|
||||||
- TZ=${TIMEZONE}
|
- TZ=${TIMEZONE}
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.authelia.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/auth`) # Changed rule
|
# Rule for Authelia portal itself (handles internal paths like /api, /logout etc.)
|
||||||
|
- traefik.http.routers.authelia.rule=Host(`${HOSTNAME}`)
|
||||||
- traefik.http.routers.authelia.entrypoints=web
|
- traefik.http.routers.authelia.entrypoints=web
|
||||||
# - traefik.http.routers.authelia.priority=100 # Removed priority
|
- traefik.http.routers.authelia.priority=100 # High priority to catch root path
|
||||||
- traefik.http.services.authelia.loadbalancer.server.port=9091
|
- traefik.http.services.authelia.loadbalancer.server.port=9091
|
||||||
- traefik.http.middlewares.authelia-auth.forwardAuth.address=http://authelia:9091/api/verify # Simplified forwardAuth address
|
# Define the forwardAuth middleware
|
||||||
- traefik.http.routers.authelia.middlewares=https-proto@docker
|
- traefik.http.middlewares.authelia-auth.forwardAuth.address=http://authelia:9091/api/verify?rd=https://${HOSTNAME}/
|
||||||
- traefik.http.middlewares.authelia-auth.forwardAuth.trustForwardHeader=true
|
- traefik.http.middlewares.authelia-auth.forwardAuth.trustForwardHeader=true
|
||||||
- traefik.http.middlewares.authelia-auth.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email
|
- traefik.http.middlewares.authelia-auth.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email
|
||||||
|
# Homepage labels for Authelia itself (optional, but can be nice)
|
||||||
- homepage.group=Security
|
- homepage.group=Security
|
||||||
- homepage.name=Authelia
|
- homepage.name=Authelia
|
||||||
- homepage.icon=authelia.png
|
- homepage.icon=authelia.png # You might need to add this icon
|
||||||
- homepage.href=/auth # Updated href
|
- homepage.href=https://${HOSTNAME}/ # Link to the login portal
|
||||||
- homepage.description=Authentication Portal
|
- homepage.description=Authentication Portal
|
||||||
sonarr:
|
sonarr:
|
||||||
image: lscr.io/linuxserver/sonarr
|
image: lscr.io/linuxserver/sonarr
|
||||||
@@ -81,9 +87,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.sonarr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/sonarr`) # Added Host check
|
- traefik.http.routers.sonarr.rule=PathPrefix(`/sonarr`)
|
||||||
- traefik.http.routers.sonarr.entrypoints=web
|
- traefik.http.routers.sonarr.entrypoints=web
|
||||||
- traefik.http.routers.sonarr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.sonarr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.sonarr.loadbalancer.server.port=8989
|
- traefik.http.services.sonarr.loadbalancer.server.port=8989
|
||||||
- homepage.group=Media
|
- homepage.group=Media
|
||||||
- homepage.name=Sonarr
|
- homepage.name=Sonarr
|
||||||
@@ -111,9 +117,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.radarr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/radarr`) # Added Host check
|
- traefik.http.routers.radarr.rule=PathPrefix(`/radarr`)
|
||||||
- traefik.http.routers.radarr.entrypoints=web
|
- traefik.http.routers.radarr.entrypoints=web
|
||||||
- traefik.http.routers.radarr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.radarr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.radarr.loadbalancer.server.port=7878
|
- traefik.http.services.radarr.loadbalancer.server.port=7878
|
||||||
- homepage.group=Media
|
- homepage.group=Media
|
||||||
- homepage.name=Radarr
|
- homepage.name=Radarr
|
||||||
@@ -141,9 +147,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.lidarr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/lidarr`) # Added Host check
|
- traefik.http.routers.lidarr.rule=PathPrefix(`/lidarr`)
|
||||||
- traefik.http.routers.lidarr.entrypoints=web
|
- traefik.http.routers.lidarr.entrypoints=web
|
||||||
- traefik.http.routers.lidarr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.lidarr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.lidarr.loadbalancer.server.port=8686
|
- traefik.http.services.lidarr.loadbalancer.server.port=8686
|
||||||
- homepage.group=Media
|
- homepage.group=Media
|
||||||
- homepage.name=Lidarr
|
- homepage.name=Lidarr
|
||||||
@@ -173,9 +179,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.bazarr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/bazarr`) # Added Host check
|
- traefik.http.routers.bazarr.rule=PathPrefix(`/bazarr`)
|
||||||
- traefik.http.routers.bazarr.entrypoints=web
|
- traefik.http.routers.bazarr.entrypoints=web
|
||||||
- traefik.http.routers.bazarr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.bazarr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.bazarr.loadbalancer.server.port=6767
|
- traefik.http.services.bazarr.loadbalancer.server.port=6767
|
||||||
- homepage.group=Download
|
- homepage.group=Download
|
||||||
- homepage.name=Bazarr
|
- homepage.name=Bazarr
|
||||||
@@ -208,10 +214,10 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.jellyseerr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/jellyseerr`) # Added Host check
|
- traefik.http.routers.jellyseerr.rule=PathPrefix(`/jellyseerr`)
|
||||||
- traefik.http.routers.jellyseerr.entrypoints=web
|
- traefik.http.routers.jellyseerr.entrypoints=web
|
||||||
- traefik.http.services.jellyseerr.loadbalancer.server.port=5055
|
- traefik.http.services.jellyseerr.loadbalancer.server.port=5055
|
||||||
- traefik.http.routers.jellyseerr.middlewares=https-proto@docker,jellyseerr-stripprefix,jellyseerr-rewrite,jellyseerr-rewriteHeaders,authelia-auth@docker
|
- traefik.http.routers.jellyseerr.middlewares=jellyseerr-stripprefix,jellyseerr-rewrite,jellyseerr-rewriteHeaders,authelia-auth@docker
|
||||||
- traefik.http.middlewares.jellyseerr-stripprefix.stripPrefix.prefixes=/jellyseerr
|
- traefik.http.middlewares.jellyseerr-stripprefix.stripPrefix.prefixes=/jellyseerr
|
||||||
- traefik.http.middlewares.jellyseerr-rewriteHeaders.plugin.rewriteHeaders.rewrites[0].header=location
|
- traefik.http.middlewares.jellyseerr-rewriteHeaders.plugin.rewriteHeaders.rewrites[0].header=location
|
||||||
- traefik.http.middlewares.jellyseerr-rewriteHeaders.plugin.rewriteHeaders.rewrites[0].regex=^/(.+)$
|
- traefik.http.middlewares.jellyseerr-rewriteHeaders.plugin.rewriteHeaders.rewrites[0].regex=^/(.+)$
|
||||||
@@ -282,9 +288,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.prowlarr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/prowlarr`) # Added Host check
|
- traefik.http.routers.prowlarr.rule=PathPrefix(`/prowlarr`)
|
||||||
- traefik.http.routers.prowlarr.entrypoints=web
|
- traefik.http.routers.prowlarr.entrypoints=web
|
||||||
- traefik.http.routers.prowlarr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.prowlarr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.prowlarr.loadbalancer.server.port=9696
|
- traefik.http.services.prowlarr.loadbalancer.server.port=9696
|
||||||
- homepage.group=Download
|
- homepage.group=Download
|
||||||
- homepage.name=Prowlarr
|
- homepage.name=Prowlarr
|
||||||
@@ -306,9 +312,9 @@ services:
|
|||||||
- TZ=${TIMEZONE}
|
- TZ=${TIMEZONE}
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.flaresolverr.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/flaresolverr`) # Added Host check
|
- traefik.http.routers.flaresolverr.rule=PathPrefix(`/flaresolverr`)
|
||||||
- traefik.http.routers.flaresolverr.entrypoints=web
|
- traefik.http.routers.flaresolverr.entrypoints=web
|
||||||
- traefik.http.routers.flaresolverr.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.flaresolverr.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.flaresolverr.loadbalancer.server.port=8191
|
- traefik.http.services.flaresolverr.loadbalancer.server.port=8191
|
||||||
profiles:
|
profiles:
|
||||||
- flaresolverr
|
- flaresolverr
|
||||||
@@ -326,20 +332,25 @@ services:
|
|||||||
- ${DOWNLOAD_ROOT}:/data/torrents:Z
|
- ${DOWNLOAD_ROOT}:/data/torrents:Z
|
||||||
restart: always
|
restart: always
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
# Container may fail if the PIA's token expired, so mark as unhealthy when there is no internet connection
|
||||||
|
# see: https://github.com/qdm12/gluetun/issues/641#issuecomment-933856220
|
||||||
test:
|
test:
|
||||||
["CMD", "curl", "--fail", "http://127.0.0.1:8080", "https://google.com"]
|
["CMD", "curl", "--fail", "http://127.0.0.1:8080", "https://google.com"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.qbittorrent.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/qbittorrent`) # Added Host check
|
- traefik.http.routers.qbittorrent.rule=PathPrefix(`/qbittorrent`)
|
||||||
- traefik.http.routers.qbittorrent.entrypoints=web
|
- traefik.http.routers.qbittorrent.entrypoints=web
|
||||||
- traefik.http.services.qbittorrent.loadbalancer.server.port=8080
|
- traefik.http.services.qbittorrent.loadbalancer.server.port=8080
|
||||||
- traefik.http.routers.qbittorrent.middlewares=https-proto@docker,qbittorrent-strip-slash,qbittorrent-stripprefix,authelia-auth@docker
|
- traefik.http.routers.qbittorrent.middlewares=qbittorrent-strip-slash,qbittorrent-stripprefix,authelia-auth@docker
|
||||||
|
# https://github.com/qbittorrent/qBittorrent/issues/5693#issuecomment-552146296
|
||||||
- traefik.http.middlewares.qbittorrent-stripprefix.stripPrefix.prefixes=/qbittorrent
|
- traefik.http.middlewares.qbittorrent-stripprefix.stripPrefix.prefixes=/qbittorrent
|
||||||
|
# https://community.traefik.io/t/middleware-to-add-the-if-needed/1895/19
|
||||||
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.regex=(^.*\/qbittorrent$$)
|
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.regex=(^.*\/qbittorrent$$)
|
||||||
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.replacement=$$1/
|
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.replacement=$$1/
|
||||||
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.permanent=false
|
- traefik.http.middlewares.qbittorrent-strip-slash.redirectregex.permanent=false
|
||||||
|
#- com.centurylinklabs.watchtower.depends-on=/vpn
|
||||||
- homepage.group=Download
|
- homepage.group=Download
|
||||||
- homepage.name=qBittorrent
|
- homepage.name=qBittorrent
|
||||||
- homepage.icon=qbittorrent.png
|
- homepage.icon=qbittorrent.png
|
||||||
@@ -378,9 +389,9 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.sabnzbd.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/sabnzbd`) # Added Host check
|
- traefik.http.routers.sabnzbd.rule=PathPrefix(`/sabnzbd`) # Simplified rule
|
||||||
- traefik.http.routers.sabnzbd.entrypoints=web
|
- traefik.http.routers.sabnzbd.entrypoints=web
|
||||||
- traefik.http.routers.sabnzbd.middlewares=https-proto@docker,authelia-auth@docker
|
- traefik.http.routers.sabnzbd.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.sabnzbd.loadbalancer.server.port=8080
|
- traefik.http.services.sabnzbd.loadbalancer.server.port=8080
|
||||||
- homepage.group=Download
|
- homepage.group=Download
|
||||||
- homepage.name=Sabnzbd
|
- homepage.name=Sabnzbd
|
||||||
@@ -400,7 +411,7 @@ services:
|
|||||||
- PUID=${USER_ID}
|
- PUID=${USER_ID}
|
||||||
- PGID=${GROUP_ID}
|
- PGID=${GROUP_ID}
|
||||||
- TZ=${TIMEZONE}
|
- TZ=${TIMEZONE}
|
||||||
- JELLYFIN_PublishedServerUrl=https://${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}/jellyfin
|
- JELLYFIN_PublishedServerUrl=${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}/jellyfin
|
||||||
volumes:
|
volumes:
|
||||||
- ${CONFIG_ROOT:-.}/jellyfin:/config:Z
|
- ${CONFIG_ROOT:-.}/jellyfin:/config:Z
|
||||||
- ${DATA_ROOT}:/data:Z
|
- ${DATA_ROOT}:/data:Z
|
||||||
@@ -414,9 +425,9 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.jellyfin.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/jellyfin`) # Added Host check
|
- traefik.http.routers.jellyfin.rule=PathPrefix(`/jellyfin`)
|
||||||
- traefik.http.routers.jellyfin.entrypoints=web
|
- traefik.http.routers.jellyfin.entrypoints=web
|
||||||
- traefik.http.routers.jellyfin.middlewares=https-proto@docker # Only HTTPS, no auth
|
- traefik.http.routers.jellyfin.middlewares=authelia-auth@docker
|
||||||
- traefik.http.services.jellyfin.loadbalancer.server.port=8096
|
- traefik.http.services.jellyfin.loadbalancer.server.port=8096
|
||||||
- homepage.group=Media
|
- homepage.group=Media
|
||||||
- homepage.name=Jellyfin
|
- homepage.name=Jellyfin
|
||||||
@@ -445,8 +456,8 @@ services:
|
|||||||
- traefik.http.middlewares.calibre-headers.headers.customRequestHeaders.X-Scheme=https
|
- traefik.http.middlewares.calibre-headers.headers.customRequestHeaders.X-Scheme=https
|
||||||
- traefik.http.middlewares.calibre-headers.headers.customRequestHeaders.X-Script-Name=/calibre
|
- traefik.http.middlewares.calibre-headers.headers.customRequestHeaders.X-Script-Name=/calibre
|
||||||
- traefik.http.middlewares.calibre-stripprefixregex.stripPrefixRegex.regex=/calibre
|
- traefik.http.middlewares.calibre-stripprefixregex.stripPrefixRegex.regex=/calibre
|
||||||
- traefik.http.routers.calibre.middlewares=https-proto@docker,calibre-headers,calibre-stripprefixregex,authelia-auth@docker
|
- traefik.http.routers.calibre.middlewares=calibre-headers,calibre-stripprefixregex,authelia-auth@docker
|
||||||
- traefik.http.routers.calibre.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/calibre`) # Added Host check
|
- traefik.http.routers.calibre.rule=PathPrefix(`/calibre`)
|
||||||
- traefik.http.routers.calibre.entrypoints=web
|
- traefik.http.routers.calibre.entrypoints=web
|
||||||
- traefik.http.services.calibre.loadbalancer.server.port=8083
|
- traefik.http.services.calibre.loadbalancer.server.port=8083
|
||||||
- homepage.group=Media
|
- homepage.group=Media
|
||||||
@@ -509,6 +520,7 @@ services:
|
|||||||
- HOMEPAGE_VAR_WEATHER_LONG=${HOMEPAGE_VAR_WEATHER_LONG}
|
- HOMEPAGE_VAR_WEATHER_LONG=${HOMEPAGE_VAR_WEATHER_LONG}
|
||||||
- HOMEPAGE_VAR_WEATHER_TIME=${TIMEZONE}
|
- HOMEPAGE_VAR_WEATHER_TIME=${TIMEZONE}
|
||||||
- HOMEPAGE_VAR_WEATHER_UNIT=${HOMEPAGE_VAR_WEATHER_UNIT}
|
- HOMEPAGE_VAR_WEATHER_UNIT=${HOMEPAGE_VAR_WEATHER_UNIT}
|
||||||
|
# Explicitly allow the hostname constructed from Tailscale variables
|
||||||
- HOMEPAGE_ALLOWED_HOSTS=${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}
|
- HOMEPAGE_ALLOWED_HOSTS=${TAILSCALE_HOSTNAME}.${TAILSCALE_TAILNET_DOMAIN}
|
||||||
volumes:
|
volumes:
|
||||||
- ${CONFIG_ROOT:-.}/homepage:/app/config:Z
|
- ${CONFIG_ROOT:-.}/homepage:/app/config:Z
|
||||||
@@ -519,16 +531,17 @@ services:
|
|||||||
[sh, -c, "cp -n /app/config/tpl/*.yaml /app/config && node server.js"]
|
[sh, -c, "cp -n /app/config/tpl/*.yaml /app/config && node server.js"]
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.http.routers.homepage.rule=Host(`${APP_HOSTNAME}`) && PathPrefix(`/home`) # Changed rule to root
|
# Rule for homepage, now at /home, needs auth
|
||||||
|
- traefik.http.routers.homepage.rule=Host(`${HOSTNAME}`) && PathPrefix(`/home`)
|
||||||
- traefik.http.routers.homepage.entrypoints=web
|
- traefik.http.routers.homepage.entrypoints=web
|
||||||
# - traefik.http.routers.homepage.priority=10 # Removed priority
|
- traefik.http.routers.homepage.priority=10 # Lower priority than Authelia's root rule
|
||||||
# Global middleware for setting HTTPS header
|
- traefik.http.middlewares.homepage-stripprefix.stripPrefix.prefixes=/home
|
||||||
- traefik.http.middlewares.https-proto.headers.customrequestheaders.X-Forwarded-Proto=https
|
- traefik.http.routers.homepage.middlewares=homepage-stripprefix,authelia-auth@docker
|
||||||
- traefik.http.routers.homepage.middlewares=https-proto@docker,authelia-auth@docker
|
# Homepage's own labels for discovery (unchanged)
|
||||||
- homepage.group=Dashboard
|
- homepage.group=Dashboard
|
||||||
- homepage.name=Homepage
|
- homepage.name=Homepage
|
||||||
- homepage.icon=homepage.png
|
- homepage.icon=homepage.png
|
||||||
- homepage.href=/ # Updated href
|
- homepage.href=/home # Update link to new path
|
||||||
- homepage.description=Service Dashboard
|
- homepage.description=Service Dashboard
|
||||||
watchtower:
|
watchtower:
|
||||||
image: ghcr.io/containrrr/watchtower:latest
|
image: ghcr.io/containrrr/watchtower:latest
|
||||||
@@ -549,22 +562,23 @@ services:
|
|||||||
tailscale:
|
tailscale:
|
||||||
image: tailscale/tailscale:latest
|
image: tailscale/tailscale:latest
|
||||||
container_name: tailscale
|
container_name: tailscale
|
||||||
hostname: ${TAILSCALE_HOSTNAME:-tailscale-nas}
|
hostname: ${TAILSCALE_HOSTNAME:-tailscale-nas} # Hostname for Tailscale access
|
||||||
environment:
|
environment:
|
||||||
TS_AUTHKEY: ${TAILSCALE_AUTHKEY}
|
TS_AUTHKEY: ${TAILSCALE_AUTHKEY} # Needs to be set in .env
|
||||||
TS_EXTRA_ARGS: "--advertise-tags=${TAILSCALE_TAGS:-tag:nas}"
|
TS_EXTRA_ARGS: "--advertise-tags=${TAILSCALE_TAGS:-tag:nas}" # Keep tags if desired
|
||||||
TS_STATE_DIR: "/var/lib/tailscale"
|
TS_STATE_DIR: "/var/lib/tailscale"
|
||||||
TS_USERSPACE: "false"
|
TS_USERSPACE: "false"
|
||||||
|
# Switch to enable Funnel (public access) or Serve (Tailnet only)
|
||||||
ENABLE_FUNNEL_HTTPS: ${ENABLE_FUNNEL_HTTPS:-false}
|
ENABLE_FUNNEL_HTTPS: ${ENABLE_FUNNEL_HTTPS:-false}
|
||||||
volumes:
|
volumes:
|
||||||
- ${CONFIG_ROOT:-.}/tailscale/state:/var/lib/tailscale:Z
|
- ${CONFIG_ROOT:-.}/tailscale/state:/var/lib/tailscale:Z # Persist state
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock # Optional, keep if needed
|
||||||
devices:
|
devices:
|
||||||
- /dev/net/tun:/dev/net/tun
|
- /dev/net/tun:/dev/net/tun
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
- NET_RAW
|
- NET_RAW
|
||||||
extra_hosts:
|
extra_hosts: # Add this section
|
||||||
- host.docker.internal:172.17.0.1
|
- host.docker.internal:172.17.0.1
|
||||||
restart: always
|
restart: always
|
||||||
command:
|
command:
|
||||||
@@ -588,6 +602,8 @@ services:
|
|||||||
done
|
done
|
||||||
echo " Tailscaled is running."
|
echo " Tailscaled is running."
|
||||||
|
|
||||||
|
# --- Start Tailscale Funnel/Serve ---
|
||||||
|
# Check the ENABLE_FUNNEL_HTTPS variable
|
||||||
if [ "${ENABLE_FUNNEL_HTTPS}" = "true" ]; then
|
if [ "${ENABLE_FUNNEL_HTTPS}" = "true" ]; then
|
||||||
echo "ENABLE_FUNNEL_HTTPS is true. Setting up Funnel -> http://localhost:80..."
|
echo "ENABLE_FUNNEL_HTTPS is true. Setting up Funnel -> http://localhost:80..."
|
||||||
tailscale funnel --bg http://localhost:80
|
tailscale funnel --bg http://localhost:80
|
||||||
@@ -597,9 +613,10 @@ services:
|
|||||||
tailscale serve --bg http://localhost:80
|
tailscale serve --bg http://localhost:80
|
||||||
echo "Tailscale Serve configured."
|
echo "Tailscale Serve configured."
|
||||||
fi
|
fi
|
||||||
|
# --- End Tailscale Funnel/Serve ---
|
||||||
|
|
||||||
echo "Tailscale forwarding configured. Container will remain running."
|
echo "Tailscale forwarding configured. Container will remain running."
|
||||||
wait
|
wait # Wait indefinitely for background processes
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
|
|||||||
49
update-config.sh
Executable file
49
update-config.sh
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# See https://stackoverflow.com/a/44864004 for the sed GNU/BSD compatible hack
|
||||||
|
|
||||||
|
function update_arr_config {
|
||||||
|
echo "Updating ${container} configuration..."
|
||||||
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/config.xml ]; do sleep 1; done
|
||||||
|
sed -i.bak "s/<UrlBase><\/UrlBase>/<UrlBase>\/$1<\/UrlBase>/" "${CONFIG_ROOT:-.}"/"$container"/config.xml && rm "${CONFIG_ROOT:-.}"/"$container"/config.xml.bak
|
||||||
|
CONTAINER_NAME_UPPER=$(echo "$container" | tr '[:lower:]' '[:upper:]')
|
||||||
|
sed -i.bak 's/^'"${CONTAINER_NAME_UPPER}"'_API_KEY=.*/'"${CONTAINER_NAME_UPPER}"'_API_KEY='"$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/"$container"/config.xml)"'/' .env && rm .env.bak
|
||||||
|
echo "Update of ${container} configuration complete, restarting..."
|
||||||
|
docker compose restart "$container"
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_qbittorrent_config {
|
||||||
|
echo "Updating ${container} configuration..."
|
||||||
|
docker compose stop "$container"
|
||||||
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf ]; do sleep 1; done
|
||||||
|
sed -i.bak '/WebUI\\ServerDomains=*/a WebUI\\Password_PBKDF2="@ByteArray(ARQ77eY1NUZaQsuDHbIMCA==:0WMRkYTUWVT9wVvdDtHAjU9b3b7uB8NR1Gur2hmQCvCDpm39Q+PsJRJPaCU51dEiz+dTzh8qbPsL8WkFljQYFQ==)"' "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf && rm "${CONFIG_ROOT:-.}"/"$container"/qBittorrent/qBittorrent.conf.bak
|
||||||
|
echo "Update of ${container} configuration complete, restarting..."
|
||||||
|
docker compose start "$container"
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_bazarr_config {
|
||||||
|
echo "Updating ${container} configuration..."
|
||||||
|
until [ -f "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml ]; do sleep 1; done
|
||||||
|
sed -i.bak "s/base_url: ''/base_url: '\/$container'/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
||||||
|
sed -i.bak "s/use_radarr: false/use_radarr: true/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
||||||
|
sed -i.bak "s/use_sonarr: false/use_sonarr: true/" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
||||||
|
until [ -f "${CONFIG_ROOT:-.}"/sonarr/config.xml ]; do sleep 1; done
|
||||||
|
SONARR_API_KEY=$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/sonarr/config.xml)
|
||||||
|
sed -i.bak "/sonarr:/,/^radarr:/ { s/apikey: .*/apikey: $SONARR_API_KEY/; s/base_url: .*/base_url: \/sonarr/; s/ip: .*/ip: sonarr/ }" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
||||||
|
until [ -f "${CONFIG_ROOT:-.}"/radarr/config.xml ]; do sleep 1; done
|
||||||
|
RADARR_API_KEY=$(sed -n 's/.*<ApiKey>\(.*\)<\/ApiKey>.*/\1/p' "${CONFIG_ROOT:-.}"/radarr/config.xml)
|
||||||
|
sed -i.bak "/radarr:/,/^sonarr:/ { s/apikey: .*/apikey: $RADARR_API_KEY/; s/base_url: .*/base_url: \/radarr/; s/ip: .*/ip: radarr/ }" "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml && rm "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml.bak
|
||||||
|
sed -i.bak 's/^BAZARR_API_KEY=.*/BAZARR_API_KEY='"$(sed -n 's/.*apikey: \(.*\)*/\1/p' "${CONFIG_ROOT:-.}"/"$container"/config/config/config.yaml | head -n 1)"'/' .env && rm .env.bak
|
||||||
|
echo "Update of ${container} configuration complete, restarting..."
|
||||||
|
docker compose restart "$container"
|
||||||
|
}
|
||||||
|
|
||||||
|
for container in $(docker ps --format '{{.Names}}'); do
|
||||||
|
if [[ "$container" =~ ^(radarr|sonarr|lidarr|prowlarr)$ ]]; then
|
||||||
|
update_arr_config "$container"
|
||||||
|
elif [[ "$container" =~ ^(bazarr)$ ]]; then
|
||||||
|
update_bazarr_config "$container"
|
||||||
|
elif [[ "$container" =~ ^(qbittorrent)$ ]]; then
|
||||||
|
update_qbittorrent_config "$container"
|
||||||
|
fi
|
||||||
|
done
|
||||||
1370
update-setup.sh
1370
update-setup.sh
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user