Migrate docudjeex to Docus v4 with EN/FR content
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
title: Serveex
|
||||
icon: i-noto-microscope
|
||||
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: Introduction to Serveex — a personal homelab project to self-host everyday services using Debian and Docker, replacing Google, Apple, and Netflix.
|
||||
navigation:
|
||||
icon: i-lucide-bookmark
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
## A Home Lab by a Beginner, for Beginners
|
||||
|
||||

|
||||
|
||||
**Serveex** is primarily a personal project aimed at hosting as many everyday services as possible at home, without relying on proprietary platforms (Google, Apple, Netflix, etc.). The goal was to experiment, learn, and document every step along the way. This is purely a scientific project and is not intended for production use.
|
||||
|
||||
A big thanks to **Nipah** for sharing his infinite knowledge and, above all, for his patience.
|
||||
|
||||
::note
|
||||
**Prerequisites:**
|
||||
|
||||
- Have [an online VPS](https://www.it-connect.fr/les-serveurs-prives-virtuels-vps-pour-les-debutants/) or a local machine: ideally a mini PC (you can find N100 models for around €100), but it also works on a laptop or [a virtual machine](https://openclassrooms.com/fr/courses/2035806-virtualisez-votre-architecture-et-vos-environnements-de-travail/6313946-installez-virtualbox). The [Freebox Delta/Ultra offer virtual machines](https://next.ink/3493/machines-virtuelles-et-freebox-delta-comment-heberger-votre-premiere-page-web/).
|
||||
- Know how to configure [NAT rules on a router and assign DHCP leases](/general/networking/nat)
|
||||
- Know how to configure the [DNS zone of a domain name](/general/networking/dns)
|
||||
::
|
||||
|
||||
<div align="center">
|
||||
<img src="/img/serveex/serveex.svg" align="center" width="700">
|
||||
</div>
|
||||
|
||||
The goal is to be easily deployable and easy to migrate, so here is its structure:
|
||||
|
||||
### The Core of the Server
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-logos-debian" title="Operating System" to="/serveex/core/installation"}
|
||||
Install and configure Debian 13
|
||||
::
|
||||
|
||||
::card{icon="i-logos-docker-icon" title="Container Engine" to="/serveex/core/docker"}
|
||||
Install Docker
|
||||
::
|
||||
|
||||
::card{icon="i-carbon-container-registry" title="Docker GUI" to="/serveex/core/docker#installer-dockge-pour-gérer-et-déployer-les-conteneurs"}
|
||||
Install and deploy Dockge
|
||||
::
|
||||
|
||||
::card{icon="i-noto-globe-showing-americas" title="Reverse Proxy" to="/serveex/core/swag"}
|
||||
Expose your services with SWAG
|
||||
::
|
||||
::
|
||||
|
||||
### Security
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-simple-icons-wireguard" title="VPN" to="/serveex/security/wireguard"}
|
||||
Install and deploy Wireguard
|
||||
::
|
||||
|
||||
::card{icon="i-noto-key" title="SSO & MFA" to="/serveex/security/authentik"}
|
||||
Install and deploy Authentik
|
||||
::
|
||||
|
||||
::card{icon="i-logos-cloudflare-icon" title="Zero Trust" to="/serveex/security/cloudflare"}
|
||||
Install and deploy Cloudflared
|
||||
::
|
||||
::
|
||||
|
||||
### Monitoring
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-solar-pulse-linear" title="Service Status" to="/serveex/monitoring/uptime-kuma"}
|
||||
Install and deploy Uptime-Kuma
|
||||
::
|
||||
|
||||
::card{icon="i-lucide-logs" title="Log Management" to="/serveex/monitoring/dozzle"}
|
||||
Install and deploy Dozzle
|
||||
::
|
||||
|
||||
::card{icon="i-noto-rabbit" title="Connection Management" to="/serveex/monitoring/speedtest-tracker"}
|
||||
Install and deploy Speedtest Tracker
|
||||
::
|
||||
|
||||
::card{icon="i-lucide-chart-column-decreasing" title="Resource Status" to="/serveex/monitoring/beszel"}
|
||||
Install and deploy Beszel
|
||||
::
|
||||
|
||||
::card{icon="i-lucide-circle-power" title="Wake on Lan" to="/serveex/monitoring/upsnap"}
|
||||
Install and deploy UpSnap
|
||||
::
|
||||
::
|
||||
|
||||
### Media
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-cbi-plex-alt" title="Media" to="/serveex/media/plex"}
|
||||
Install and deploy Plex
|
||||
::
|
||||
|
||||
::card{icon="i-cbi-qbittorrent" title="Seedbox" to="/serveex/media/qbittorrent"}
|
||||
Install and deploy Qbittorrent
|
||||
::
|
||||
::
|
||||
|
||||
### Cloud Drive & Photos
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-cib-nextcloud" title="Drive" to="/serveex/cloud/nextcloud"}
|
||||
Install and deploy Nextcloud
|
||||
::
|
||||
|
||||
::card{icon="i-simple-icons-immich" title="Photos" to="/serveex/cloud/immich"}
|
||||
Install and deploy Immich
|
||||
::
|
||||
::
|
||||
|
||||
### Files & Sharing
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-noto-open-file-folder" title="File Explorer" to="/serveex/files/file-browser"}
|
||||
Install and deploy file-browser
|
||||
::
|
||||
|
||||
::card{icon="i-carbon-share" title="Sharing" to="/serveex/files/pingvin"}
|
||||
Install and deploy Pingvin
|
||||
::
|
||||
::
|
||||
|
||||
### Development Tools
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-logos-visual-studio-code" title="Visual Studio Code" to="/serveex/development/code-server"}
|
||||
Install and deploy code-server
|
||||
::
|
||||
|
||||
::card{icon="i-simple-icons-gitea" title="Git Repository" to="/serveex/development/gitea"}
|
||||
Install and deploy Gitea
|
||||
::
|
||||
|
||||
::card{icon="i-noto-hammer-and-wrench" title="Tools" to="/serveex/development/it-tools"}
|
||||
Install and deploy IT Tools
|
||||
::
|
||||
::
|
||||
|
||||
### Useful Applications
|
||||
|
||||
:::div{class="relative"}
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
|
||||
:::
|
||||
|
||||
::card-group
|
||||
::card{icon="i-cbi-adguard" title="Ad-blocking DNS and Filters" to="/serveex/apps/adguard"}
|
||||
Install and deploy Adguard Home
|
||||
::
|
||||
|
||||
::card{icon="i-cbi-bitwarden" title="Password Manager" to="/serveex/apps/vaultwarden"}
|
||||
Install and deploy Vaultwarden
|
||||
::
|
||||
::
|
||||
|
||||
## Coming Soon
|
||||
---
|
||||
|
||||
- Homepage, to have all your services at a glance and access them easily
|
||||
- Mkdocs for your documentation
|
||||
- Docus, an alternative to Mkdocs
|
||||
- UpSnap to remotely wake your machines
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Server core
|
||||
icon: i-lucide-server-cog
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Debian 13
|
||||
description: Step-by-step guide to install Debian 13 on a home server and set up SSH access, essential packages, and a ready-to-use base system.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Debian 13
|
||||
::note
|
||||
🎯 __Goal:__ Install Debian 13 and the main dependencies to have a ready-to-use OS, accessible via SSH.
|
||||
::
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
1. [BIOS Setup](https://www.debian.org/releases/stable/i386/ch03s06.en.html#bios-setup)
|
||||
2. [Download Debian Image](https://www.debian.org/download.en.html)
|
||||
3. [Create Bootable USB (Rufus)](https://dev.to/devops2808/how-to-create-bootable-usb-installer-for-debian-12-4f66)
|
||||
4. [Install Debian and Set Up SSH](https://www.howtoforge.com/tutorial/debian-minimal-server/)
|
||||
5. Install sudo and add a user to the sudo group for administrative privileges.
|
||||
Log in as root:
|
||||
```sh
|
||||
su -
|
||||
```
|
||||
Enter your password, then type:
|
||||
```sh
|
||||
apt install sudo
|
||||
```
|
||||
Add the user to the sudo group:
|
||||
```sh
|
||||
adduser <username> sudo
|
||||
```
|
||||
|
||||
Next time the user logs in, they will be able to use the `sudo` command to execute commands with administrative privileges.
|
||||
|
||||
6. [Everything About Remote Console Access (SSH)](https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys)
|
||||
7. Optional - [UPS Client in Case of Power Outage](https://www.sindastra.de/p/2078/how-to-connect-linux-server-to-synology-ups-server) / [also here](https://www.reddit.com/r/synology/comments/gtkjam/use_synology_nas_as_ups_server_to_safely_power/)
|
||||
8. Optional - Wake up after power outage → configure BIOS S0 state
|
||||
9. Optional - [Wake Server Remotely (WoW - WoL)](https://dev.to/zakery1369/enable-wake-on-lan-on-debian-4ljd)
|
||||
|
||||
## Must-Have CLI Apps
|
||||
---
|
||||
Some essential apps you’ll likely need at some point, so might as well install them early:
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo apt install vim btop ranger git duf neofetch samba cifs-utils tree unzip
|
||||
```
|
||||
|
||||
Additionally:
|
||||
|
||||
- [gping](https://www.linode.com/docs/guides/how-to-use-gping-on-linux/) - Graphical ping tool
|
||||
- [lazydocker](https://github.com/jesseduffield/lazydocker) - CLI Docker container manager
|
||||
|
||||
## Useful Features
|
||||
---
|
||||
### Firewall
|
||||
|
||||
- [ufw](https://www.zenarmor.com/docs/network-security-tutorials/how-to-set-up-a-firewall-with-ufw-on-debian)
|
||||
- [Firewalld](https://linuxcapable.com/how-to-install-firewalld-on-debian-linux/)
|
||||
|
||||
### Samba Sharing (Access a Remote Network Disk)
|
||||
|
||||
- [Create and Access a Samba Share](/general/networking/samba)
|
||||
|
||||
### File Transfer via rsync
|
||||
|
||||
```sh
|
||||
sudo rsync -avhHSP /source /destination
|
||||
```
|
||||
::note
|
||||
|
||||
Add ` --exclude @eaDir`{lang=shell} if the source is a Synology NAS
|
||||
::
|
||||
@@ -0,0 +1,182 @@
|
||||
---
|
||||
title: Docker
|
||||
description: Install Docker and Dockge on Debian to deploy and manage self-hosted services with simple container stacks.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Docker
|
||||
|
||||
Docker, to install deployable services in seconds and manage them with just a few commands or clicks.
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install [Docker](https://www.docker.com/)
|
||||
- Install [Dockge](https://github.com/louislam/dockge) to manage stacks
|
||||
- Install [Watchtower](https://github.com/containrrr/watchtower) to update containers
|
||||
::
|
||||
|
||||

|
||||
|
||||
## Install Docker
|
||||
---
|
||||
Add the Docker repositories and GPG key:
|
||||
|
||||
```sh
|
||||
# Add Docker's official GPG key:
|
||||
sudo apt-get update
|
||||
sudo apt-get install ca-certificates curl
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add the repository to Apt sources:
|
||||
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt-get update
|
||||
```
|
||||
|
||||
Install the packages:
|
||||
|
||||
```sh
|
||||
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
**More options:** [Install Docker for Debian 13](https://docs.docker.com/engine/install/debian/)
|
||||
|
||||
::note
|
||||
|
||||
From here on, we assume the stacks are installed in the `/docker` folder, created using the command:
|
||||
```sh
|
||||
sudo mkdir /docker
|
||||
```
|
||||
::
|
||||
|
||||
## Install [Dockge](https://github.com/louislam/dockge) to manage and deploy containers
|
||||
---
|
||||
[Dockge](https://github.com/louislam/dockge) is a web tool to create, configure, launch, and manage Docker containers. It's a simple, intuitive interface that’s lighter and easier for beginners than using the CLI or Portainer.
|
||||
|
||||

|
||||
|
||||
### Configuration
|
||||
|
||||
File structure we will create:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── dockge
|
||||
└── compose.yml
|
||||
```
|
||||
|
||||
Create the stack folder:
|
||||
|
||||
```sh
|
||||
cd /docker
|
||||
sudo mkdir dockge
|
||||
```
|
||||
|
||||
Then create the `compose.yml` file in this folder using `vim`:
|
||||
|
||||
```sh
|
||||
cd /docker/dockge
|
||||
sudo vi compose.yml
|
||||
```
|
||||
Press `i` to enter insert mode and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
dockge:
|
||||
image: louislam/dockge:1
|
||||
restart: unless-stopped
|
||||
container_name: dockge
|
||||
ports:
|
||||
|
||||
- 3555:5001 # LAN-accessible port will be 3555
|
||||
|
||||
volumes:
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- /docker/dockge/data:/app/data
|
||||
- /docker:/docker
|
||||
environment:
|
||||
|
||||
- DOCKGE_STACKS_DIR=/docker
|
||||
```
|
||||
|
||||
Press `Esc` and type `:x` to save and exit.
|
||||
|
||||
To launch the container:
|
||||
|
||||
```sh
|
||||
cd /docker/dockge
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
Then go to `http://yourserverip:3555` in your browser to access the login page.
|
||||
|
||||
More info on [Dockge and how to use it](https://github.com/louislam/dockge)
|
||||
|
||||
And there you go — Docker and a tool to easily manage your containers are ready!
|
||||
|
||||
## [Watchtower](https://watchtower.nickfedor.com/), to auto-update containers
|
||||
---
|
||||
Watchtower is a container that checks for updates and pulls new images automatically, just by adding a label in your containers’ `compose.yml` files.
|
||||
|
||||
### Configuration
|
||||
|
||||
- Open Dockge in your browser
|
||||
- Click `compose`
|
||||
- Name the stack `watchtower`
|
||||
- Paste the config below into the default config area in Dockge
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
watchtower:
|
||||
container_name: watchtower
|
||||
image: ghcr.io/nicholas-fedor/watchtower:latest
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
- WATCHTOWER_SCHEDULE=${SCHEDULE}
|
||||
- WATCHTOWER_LABEL_ENABLE=true
|
||||
- WATCHTOWER_CLEANUP=true
|
||||
- WATCHTOWER_REMOVE_VOLUMES=true
|
||||
# Discord notifications - uncomment if used
|
||||
#- WATCHTOWER_NOTIFICATIONS=slack
|
||||
#- WATCHTOWER_NOTIFICATION_SLACK_IDENTIFIER=Watchtower
|
||||
#- WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL=${WH_URL}
|
||||
volumes:
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
```
|
||||
|
||||
Then fill in the `.env` section in Dockge with the following:
|
||||
|
||||
```properties
|
||||
SCHEDULE=
|
||||
WH_URL=
|
||||
```
|
||||
|
||||
| Property | Value | Examples |
|
||||
|----------------|--------------------------------------------------------------------|----------------------------------------------|
|
||||
| `SCHEDULE` | Cron format | `0 0 6 * * *` (every day at 6 AM) |
|
||||
| `WH_URL` | Your Discord webhook URL - append `/slack` at the end | `https://yourdiscordserver/webhook/slack` |
|
||||
|
||||
To have Watchtower monitor your other containers, add this to their `compose.yml`:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
|
||||
Then restart the modified stacks. And that's it — you now have a solid base to start deploying the services you want!
|
||||
@@ -0,0 +1,381 @@
|
||||
---
|
||||
title: SWAG
|
||||
description: Set up SWAG as a reverse proxy with automatic SSL, expose your services securely, and configure geo-blocking on your homelab.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# SWAG
|
||||
|
||||
::note
|
||||
🎯 __Objectives:__
|
||||
|
||||
- Install Swag
|
||||
- Enable SSL
|
||||
- Access the dashboard
|
||||
- Configure regional blocking
|
||||
- Expose Dockge
|
||||
::
|
||||
|
||||
[Swag](https://docs.linuxserver.io/general/swag/) is the core of this homelab. It’s a powerful reverse proxy that allows you to expose services on the internet using domain names, handling SSL certificate issuance (for encrypted connections), request routing, and access security (via HTTP auth or SSO like Authelia or Authentik). All the necessary documentation is [available here](https://docs.linuxserver.io/general/swag).
|
||||
|
||||
::warning
|
||||
|
||||
SWAG is only useful for exposing your services to the internet—i.e., accessing them via a public URL like `https://service.mydomain.com`. If you don’t want to expose your services and prefer to always use a VPN to connect remotely, you can go [here instead](/serveex/security/wireguard).
|
||||
::
|
||||
|
||||
Below is an example exposing Dockge. We will install SWAG along with the dbip mod for geolocation-based blocking, and the dashboard mod for managing swag, fail2ban, and geolocation.
|
||||
|
||||
**Reverse proxy principle and its application in our case:**
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
::note
|
||||
|
||||
This tutorial assumes you have a domain name pointing to your server, and that your router has a NAT rule forwarding port `443` to your server's IP and port `443`. The example domain will be `mydomain.com`.
|
||||
::
|
||||
|
||||
File structure to be modified:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── swag
|
||||
├── config
|
||||
│ ├── dns-conf
|
||||
│ │ └── ovh.ini
|
||||
│ └── nginx
|
||||
│ ├── dbip.conf
|
||||
│ ├── nginx.conf
|
||||
│ └── proxy-confs
|
||||
│ └── dockge.subdomain.conf
|
||||
├── compose.yml
|
||||
└── .env
|
||||
```
|
||||
|
||||
Open Dockge in your browser, click on `compose`, name the stack `swag`, and copy the following config:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
swag:
|
||||
image: lscr.io/linuxserver/swag:latest
|
||||
container_name: swag
|
||||
cap_add:
|
||||
|
||||
- NET_ADMIN
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
- URL=${DOMAIN}
|
||||
- EXTRA_DOMAINS=${DOMAINS}
|
||||
- SUBDOMAINS=wildcard
|
||||
- VALIDATION=dns
|
||||
- DNSPLUGIN=${PLUGIN}
|
||||
- EMAIL=${EMAIL}
|
||||
- DOCKER_MODS=linuxserver/mods:swag-dbip|linuxserver/mods:swag-dashboard|linuxserver/mods:swag-auto-reload
|
||||
volumes:
|
||||
|
||||
- /docker/swag/config:/config
|
||||
ports:
|
||||
|
||||
- 80:80
|
||||
- 443:443
|
||||
- 81:81
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
- swag
|
||||
|
||||
networks:
|
||||
swag:
|
||||
name: swag_default
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__
|
||||
Add the watchtower label to each container to enable automatic updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Then in the `.env` file:
|
||||
|
||||
```properties
|
||||
DOMAIN=
|
||||
DOMAINS=
|
||||
EMAIL=
|
||||
PLUGIN=
|
||||
```
|
||||
|
||||
Fill out the variables as follows:
|
||||
|
||||
| Property | Value | Examples |
|
||||
|-------------------------|---------------------------------------------------------------------------|-----------------------|
|
||||
| `DOMAIN` | Your domain (covers all subdomains too) | `mydomain.com` |
|
||||
| `DOMAINS` | Any additional domains | `myseconddomain.com` |
|
||||
| `EMAIL` | Your email for generating the certificate | `[email protected]` |
|
||||
| `PLUGIN` | Plugin for certificate generation—depends on your [DNS provider](https://docs.linuxserver.io/general/swag/) | `ovh`<br>`cloudflare` |
|
||||
|
||||
Assuming your DNS zone is managed by OVH, deploy the stack once. The logs will show a failure in creating the SSL certificate due to a missing `ovh.ini` configuration. Stop the stack.
|
||||
|
||||
In CLI, go to the dns-conf folder and edit the `ovh.ini` file:
|
||||
|
||||
::tip
|
||||
✨ __Tip for terminal-shy users:__
|
||||
You can use [File Browser](/serveex/files/file-browser) to browse and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/dns-conf/ovh.ini
|
||||
```
|
||||
|
||||
You should see:
|
||||
|
||||
```properties
|
||||
# Instructions: https://github.com/certbot/certbot/blob/master/certbot-dns-ovh/certbot_dns_ovh/__init__.py#L20
|
||||
# Replace with your values
|
||||
dns_ovh_endpoint = ovh-eu
|
||||
dns_ovh_application_key =
|
||||
dns_ovh_application_secret =
|
||||
dns_ovh_consumer_key =
|
||||
```
|
||||
|
||||
Authenticate and create [your token here](https://www.ovh.com/auth/?onsuccess=https%3A%2F%2Fwww.ovh.com%2Fauth%2Fapi%2FcreateToken).
|
||||
|
||||
Set the following permissions:
|
||||
|
||||
* `GET /domain/zone/*`
|
||||
* `PUT /domain/zone/*`
|
||||
* `POST /domain/zone/*`
|
||||
* `DELETE /domain/zone/*`
|
||||
|
||||
Note the 3 keys temporarily and enter them in `ovh.ini`. (In vim, press `i` to edit, `Esc` when done, `:x` to save and exit)
|
||||
|
||||
Save and exit the file.
|
||||
|
||||
Now configure swag to access DBIP, the geolocation-based access control module. Open the `nginx.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/nginx.conf
|
||||
```
|
||||
|
||||
Add the following line below the `http` section:
|
||||
|
||||
```nginx
|
||||
include /config/nginx/dbip.conf;
|
||||
```
|
||||
|
||||
Restart the stack in Dockge. This time, the SSL certificate should be successfully generated! Check the logs to confirm the server is ready.
|
||||
|
||||
## Dashboard
|
||||
---
|
||||
Access the dashboard locally by going to `http://yourserverip:81`
|
||||
On the left, you'll see a list of currently "proxied" services (none yet). On the right, the list of banned IPs. Below, various indicators. For more details, [click here](https://www.linuxserver.io/blog/introducing-swag-dashboard).
|
||||
|
||||

|
||||
|
||||
## DBIP
|
||||
---
|
||||
DBIP allows you to block connections based on countries. It relies on the configuration file named `dbip.conf` located in `/docker/swag/config/nginx`. [More info here](https://virtualize.link/secure/).
|
||||
|
||||
In this example, we’ll configure it to block a list of countries known to be the source of most malicious traffic. We’ll also configure a variable to allow internal server traffic, your box’s local network, and a potential VPN in the 10.x.x.x range to access your services — but not the open internet.
|
||||
|
||||
This configuration can be enabled or disabled per service (see the Dockge example below).
|
||||
|
||||
Open `dbip.conf`:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/dbip.conf
|
||||
```
|
||||
|
||||
Make your changes ([see documentation](https://github.com/linuxserver/docker-mods/tree/swag-dbip)), or use the following example:
|
||||
|
||||
```nginx
|
||||
geoip2 /config/geoip2db/dbip-country-lite.mmdb {
|
||||
auto_reload 1w;
|
||||
$geoip2_data_continent_code continent code;
|
||||
$geoip2_data_country_iso_code country iso_code;
|
||||
}
|
||||
|
||||
# Country Codes: https://en.wikipedia.org/wiki/ISO_3166-2
|
||||
|
||||
map $geoip2_data_country_iso_code $geo-whitelist {
|
||||
default no;
|
||||
FR yes;
|
||||
}
|
||||
|
||||
map $geoip2_data_country_iso_code $geo-blacklist {
|
||||
default yes;
|
||||
CN no; #China
|
||||
RU no; #Russia
|
||||
HK no; #Hong Kong
|
||||
IN no; #India
|
||||
IR no; #Iran
|
||||
VN no; #Vietnam
|
||||
TR no; #Turkey
|
||||
EG no; #Egypt
|
||||
MX no; #Mexico
|
||||
JP no; #Japan
|
||||
KR no; #South Korea
|
||||
KP no; #North Korea
|
||||
PE no; #Peru
|
||||
BR no; #Brazil
|
||||
UA no; #Ukraine
|
||||
ID no; #Indonesia
|
||||
TH no; #Thailand
|
||||
}
|
||||
|
||||
geo $lan-ip {
|
||||
default no;
|
||||
10.0.0.0/8 yes;
|
||||
172.16.0.0/12 yes;
|
||||
192.168.0.0/16 yes;
|
||||
127.0.0.1 yes;
|
||||
}
|
||||
```
|
||||
|
||||
Save and close the file. Restart the stack.
|
||||
|
||||
In the domain config files (see next section), you can enable or disable the whitelist or blacklist ([see documentation here](https://www.forum-nas.fr/threads/tuto-installer-swag-en-docker-reverse-proxy.15057/)). In our case, the whitelist allows only French requests. The blacklist blocks only the listed countries. We'll use the blacklist, like so:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name some-app.*;
|
||||
include /config/nginx/ssl.conf;
|
||||
client_max_body_size 0;
|
||||
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
location / {
|
||||
```
|
||||
|
||||
## Exposing Dockge
|
||||
---
|
||||
::note
|
||||
📋 __Prerequisite:__ <br/><br/>
|
||||
We assume that you have created a subdomain like `dockge.mydomain.com` in your [DNS zone](/general/networking/dns), with a `CNAME` pointing to `mydomain.com` and — unless you're using [Cloudflare Zero Trust](/serveex/security/cloudflare) — that you've forwarded port `443` from your router to the server's `443` in [your NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Now it's time to expose Dockge on the internet so you can access and manage your containers remotely. We assume you've set up the subdomain `dockge.mydomain.com` with a `CNAME` pointing to `mydomain.com`.
|
||||
|
||||
::warning
|
||||
|
||||
Dockge does not support multi-factor authentication. Exposing it online could compromise all connected machines. Only do this if you're using an MFA solution like [Authentik](/serveex/security/authentik/). Otherwise, don’t expose it with SWAG — use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
Open the `dockge.subdomain.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/dockge.subdomain.conf
|
||||
```
|
||||
|
||||
Configure it like this:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name dockge.*; # define the subdomain to redirect
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; } # all countries un blacklist are forbidden
|
||||
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
|
||||
set $upstream_app dockge; # container name
|
||||
set $upstream_port 5001; # internal container port (not exposed port)
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Save and exit. The configuration will update within a few seconds.
|
||||
|
||||
::note
|
||||
|
||||
By default, SWAG doesn’t recognize the name "dockge". You’ll need to add Dockge’s network to SWAG’s `compose.yml`.
|
||||
::
|
||||
|
||||
Go to the SWAG stack, click `edit`, and modify the config file like this (note the `networks` section):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: #...
|
||||
# ...
|
||||
networks: # Link the container to the custom network
|
||||
|
||||
- dockge # Network name as defined in the stack
|
||||
|
||||
networks: # Define the custom network
|
||||
# ...
|
||||
dockge: # Network name as defined in the stack
|
||||
name: dockge_default # True external network name
|
||||
external: true
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume the Dockge network is named `dockge_default`. You can verify the setup works by checking the SWAG dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
Redeploy the SWAG stack.
|
||||
|
||||
Wait a moment, then visit `https://dockge.mydomain.com` in your browser — you should be redirected to Dockge. You can also check the service status from the dashboard (`http://yourserverip:81` on your local network).
|
||||
|
||||
## Exposing Another Service with SWAG
|
||||
---
|
||||
SWAG includes templates for most known services, named `servicename.subdomain.conf.sample`. Just create the subdomain in your registrar's DNS zone (like OVH), point it to your main domain via a CNAME, then copy and rename the sample file:
|
||||
|
||||
```sh
|
||||
cd /docker/swag/config/proxy-confs
|
||||
sudo cp servicename.subdomain.conf.sample servicename.subdomain.conf
|
||||
```
|
||||
|
||||
::caution
|
||||
|
||||
- __If the subdomain is not redirected properly__
|
||||
- Open the file and verify the container name in `set $upstream_app containername;`{lang=nginx}
|
||||
- Make sure you added the container's network in SWAG’s `compose.yml`
|
||||
::
|
||||
|
||||
You can also customize the subdomain by editing `server_name yoursubdomain.*;`{lang=nginx} and renaming the file to `yoursubdomain.subdomain.conf`.
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Security
|
||||
icon: i-lucide-shield
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
title: Wireguard
|
||||
description: Install and configure WireGuard VPN to securely access your homelab from anywhere and connect all your devices to your private network.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Wireguard
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install Wireguard
|
||||
- Configure clients
|
||||
- Access the secure network
|
||||
::
|
||||
|
||||
## Introduction
|
||||
---
|
||||
Using a VPN allows remote access to a server’s local resources without exposing them to the internet. It’s a clean and secure way to access services like SSH without exposing the port publicly. With a VPN, you can securely connect to your network from anywhere and make devices on different networks communicate.
|
||||
|
||||
Here we will use [Wireguard](https://www.wireguard.com/), a secure and high-performance VPN server, using containers:
|
||||
|
||||
- [wg-easy](https://github.com/wg-easy/wg-easy) as the server, providing a very simple web UI to manage connections and download config files (including QR codes for phones)
|
||||
- [Wireguard](https://docs.linuxserver.io/images/docker-wireguard/?h=wireguard) as the client for Linux systems
|
||||
|
||||
Clients are also available for Windows, macOS, iOS, and Android.
|
||||
|
||||
The concept:
|
||||
|
||||
- On the internet, anyone can reach any internet box and thus any exposed server.
|
||||
- Your server is on your local network. It is accessible only locally unless services are explicitly exposed (as we did with Dockge). To access non-exposed resources, you must be on the same local network.
|
||||
- We want to securely access these unexposed services (like SSH) from anywhere.
|
||||
- We also want to connect services between servers, like linking two Dockge instances securely.
|
||||
|
||||
To achieve this, we’ll create a **Virtual Private Network** (VPN), i.e., a secure tunnel that only connected machines can use. They’ll appear to be on the same private network.
|
||||
|
||||
Additionally, you can add your phone, laptop, or other devices to the VPN and securely access your server resources wherever you are.
|
||||
|
||||

|
||||
|
||||
In this diagram, machine 1 is part of two networks:
|
||||
|
||||
- Its local network (devices behind the same router, e.g. `192.168.x.x` – machines 1 and 2)
|
||||
- The VPN network (VPN devices with a second IP, e.g. `10.8.x.x` – machines 1 and 4)
|
||||
|
||||
You *can* allow VPN clients to share access to their local networks, but we won’t do that here for security and subnet conflict reasons (e.g., if two remote machines use the same local IP like `192.168.1.1`).
|
||||
|
||||
So only VPN-connected devices can communicate with each other on the VPN, not with other local devices outside the VPN.
|
||||
|
||||
## Server Setup
|
||||
---
|
||||
::note
|
||||
📋 **Pre-flight Checklist:**
|
||||
|
||||
- Ensure port `51820 UDP` is free on your server and correctly forwarded from your router (`51820 UDP -> Server`).
|
||||
- Ensure port `51821 TCP` is free for the web UI.
|
||||
::
|
||||
|
||||
::warning
|
||||
|
||||
__Warning__: If your IP is not static, use a Dynamic DNS service ([DynDNS](https://en.wikipedia.org/wiki/Dynamic_DNS)). If your ISP uses [CGNAT](https://en.wikipedia.org/wiki/Carrier-grade_NAT), you’ll need to use an external VPS and connect your local server as a client.
|
||||
::
|
||||
|
||||
### Folder Structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── wg-easy
|
||||
├── config
|
||||
│ └── etc_wireguard
|
||||
├── compose.yaml
|
||||
└── .env
|
||||
```
|
||||
|
||||
Open Dockge, click **Compose**, and name the stack `wg_easy`.
|
||||
|
||||
Copy the following configuration:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
wg-easy:
|
||||
environment:
|
||||
|
||||
- INSECURE=true
|
||||
image: ghcr.io/wg-easy/wg-easy:15
|
||||
container_name: wg-easy
|
||||
networks:
|
||||
wg:
|
||||
ipv4_address: 10.42.42.42
|
||||
ipv6_address: fdcc:ad94:bacf:61a3::2a
|
||||
volumes:
|
||||
|
||||
- ./etc_wireguard:/etc/wireguard
|
||||
- /lib/modules:/lib/modules:ro
|
||||
ports:
|
||||
|
||||
- "51820:51820/udp"
|
||||
- "51821:51821/tcp"
|
||||
restart: unless-stopped
|
||||
cap_add:
|
||||
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
sysctls:
|
||||
|
||||
- net.ipv4.ip_forward=1
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
- net.ipv6.conf.all.disable_ipv6=0
|
||||
- net.ipv6.conf.all.forwarding=1
|
||||
- net.ipv6.conf.default.forwarding=1
|
||||
|
||||
networks:
|
||||
wg:
|
||||
driver: bridge
|
||||
enable_ipv6: true
|
||||
ipam:
|
||||
driver: default
|
||||
config:
|
||||
|
||||
- subnet: 10.42.42.0/24
|
||||
- subnet: fdcc:ad94:bacf:61a3::/64
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ **Tip:**
|
||||
|
||||
- You can customize WireGuard and web UI ports.
|
||||
- Add a Watchtower label for automatic updates:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
wg-easy:
|
||||
# ...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Deploy the stack and access the local web UI at `http://server-ip:51821`.
|
||||
|
||||
::caution
|
||||
|
||||
If the deployment fails, check your firewall rules.
|
||||
::
|
||||
|
||||
Once connected, follow the web UI instructions to:
|
||||
|
||||
- Create your admin account and password.
|
||||
- Set the host field (use your public IP or domain name).
|
||||
|
||||
Then go to *Administrator → Admin Panel → Config*:
|
||||
|
||||
- Change `Allowed IPs` from `0.0.0.0/24` to `10.8.0.0/24` for **split tunneling**.
|
||||
- Remove IPv6 (it often causes unnecessary issues).
|
||||
|
||||
### Retrieve Configuration Files
|
||||
|
||||
To configure clients:
|
||||
|
||||
1. Access the web UI: `http://server-ip:51821`
|
||||
2. Create a new client
|
||||
3. Edit the client and add `10.8.0.0/24` to `Server Allowed IPs`
|
||||
4. (Optional) Set `Persistent Keep Alive` to `25` if it’s a permanently connected client
|
||||
5. Save, download, and rename the file to `wg0.conf` (or `wg1.conf`, etc.)
|
||||
|
||||
## Client Server Setup
|
||||
---
|
||||
::note
|
||||
|
||||
We assume the client server runs Linux with Docker installed.
|
||||
::
|
||||
|
||||
### Folder Structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── wireguard
|
||||
└── config
|
||||
│ └── wg_confs
|
||||
└── compose.yaml
|
||||
```
|
||||
|
||||
Create the folder:
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /docker/wireguard/config/wg_confs
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ **Tip:** You can use [File Browser](/serveex/files/file-browser) instead of the terminal to edit and upload files.
|
||||
::
|
||||
|
||||
Create the `wg0.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/wireguard/config/wg_confs/wg0.conf
|
||||
```
|
||||
|
||||
Enter insert mode (`i`), paste the downloaded configuration, then save (`Esc` → `:x`).
|
||||
|
||||
::tip
|
||||
✨ **Alternative method:** Transfer the file via SFTP and move it:
|
||||
```sh
|
||||
sudo cp ~/wg0.conf /docker/wireguard/config/wg_confs
|
||||
```
|
||||
::
|
||||
|
||||
Create the `compose.yaml` file in `/docker/wireguard`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
wireguard:
|
||||
image: lscr.io/linuxserver/wireguard:latest
|
||||
container_name: wireguard
|
||||
network_mode: host
|
||||
cap_add:
|
||||
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/wireguard/config:/config
|
||||
- /lib/modules:/lib/modules
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
Start the container:
|
||||
```sh
|
||||
cd /docker/wireguard
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
Repeat this setup for each client.
|
||||
::
|
||||
|
||||
## Other Devices
|
||||
---
|
||||
|
||||
- **Mobile:** Install WireGuard and scan the QR code via the web UI (`http://server-ip:51821`)
|
||||
- **Desktop:** Install the WireGuard client and import the downloaded config file.
|
||||
|
||||
::warning
|
||||
|
||||
**Note:** If the client machine is on the same local network as the server, edit the `wg0.conf` file to use the local server IP:
|
||||
`Endpoint = server-local-ip:51820`
|
||||
::
|
||||
|
||||
And here’s the final setup overview:
|
||||
|
||||

|
||||
@@ -0,0 +1,588 @@
|
||||
---
|
||||
title: Authentik
|
||||
description: Install Authentik as a self-hosted identity provider — configure MFA and protect your services with SSO and reverse proxy authentication.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Authentik
|
||||
|
||||
::note
|
||||
🎯 __Objectives:__
|
||||
|
||||
- Install and expose Authentik
|
||||
- Configure Multi-Factor Authentication (MFA)
|
||||
- Protect a native app or an app behind a reverse proxy
|
||||
::
|
||||
|
||||
[Authentik](https://goauthentik.io) is a single sign-on (SSO) tool that allows you to log in once to all platforms compatible with OpenID. It can also secure access to your exposed services by injecting itself via SWAG into requests to those services.
|
||||
|
||||
For example, if you're exposing Dockge online at `dockge.mydomain.com`, you’ll first land on an Authentik login page when accessing it. If you've already authenticated with another Authentik-protected service, you won’t need to log in again. This allows you to authenticate only once per day for all protected services.
|
||||
|
||||
Authentik also supports multi-factor authentication, including TOTP (a code generated by the authentication app of your choice). Additionally, it allows login through Microsoft or Google accounts, provided you've configured one of those applications.
|
||||
|
||||
It's a great alternative to VPNs for securely exposing services, especially ones that lack MFA or login protection (e.g., the SWAG dashboard).
|
||||
|
||||
Authentik has [extensive documentation](https://docs.goauthentik.io/docs/installation/docker-compose) and [great tutorials from Cooptonian](https://www.youtube.com/@cooptonian). Here, we’ll cover the basics using Dockge as an example.
|
||||
|
||||
There are two main modes you should know:
|
||||
|
||||
- The first allows apps with native support for OpenID-compatible SSO to connect directly to Authentik. This is the preferred method, as the app itself decides what’s public and what’s protected.
|
||||
|
||||

|
||||
|
||||
- The second method injects Authentik authentication through SWAG before reaching the target service.
|
||||
|
||||

|
||||
|
||||
Both modes can be configured on a per-application basis.
|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure:
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── authentik
|
||||
├── .env
|
||||
├── compose.yml
|
||||
├── media
|
||||
├── certs
|
||||
├── custom-template
|
||||
└── ssh
|
||||
```
|
||||
|
||||
Create the folders:
|
||||
|
||||
```sh
|
||||
sudo mkdir -p /docker/authentik/media /docker/authentik/certs /docker/authentik/custom-template /docker/authentik/ssh
|
||||
```
|
||||
|
||||
Navigate to the `authentik` folder via `cd /docker/authentik` and generate a password and secret key to include in the `.env` file:
|
||||
|
||||
```sh
|
||||
sudo echo "PG_PASS=$(openssl rand 36 | base64)" >> .env
|
||||
sudo echo "AUTHENTIK_SECRET_KEY=$(openssl rand 60 | base64)" >> .env
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
To generate the keys, we created the folders ahead of deployment using Dockge. Dockge will prevent you from creating a stack with the same name in these folders unless a `compose.yml` file exists. So, create an empty `compose.yml` so it appears as an inactive stack:
|
||||
```sh
|
||||
sudo vi /docker/authentik/compose.yml
|
||||
```
|
||||
::
|
||||
|
||||
Open Dockge and search for "authentik" in the inactive stacks.
|
||||
Name the stack `authentik` and paste the following configuration, replacing `{AUTHENTIK_TAG:-2026.2}`{lang=properties} with [the latest version of Authentik](https://goauthentik.io/docs/releases).
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:16-alpine
|
||||
container_name: authentik-postgresql
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
|
||||
- CMD-SHELL
|
||||
- pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 5s
|
||||
volumes:
|
||||
|
||||
- database:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
|
||||
POSTGRES_USER: ${PG_USER:-authentik}
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
|
||||
redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
container_name: authentik-redis
|
||||
command: --save 60 1 --loglevel warning
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
|
||||
- CMD-SHELL
|
||||
- redis-cli ping | grep PONG
|
||||
start_period: 20s
|
||||
interval: 30s
|
||||
retries: 5
|
||||
timeout: 3s
|
||||
volumes:
|
||||
|
||||
- redis:/data
|
||||
|
||||
server:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2}
|
||||
container_name: authentik-server
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
volumes:
|
||||
|
||||
- ./media:/media
|
||||
- ./custom-templates:/templates
|
||||
- ./ssh:/authentik/.ssh
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
ports:
|
||||
|
||||
- ${COMPOSE_PORT_HTTP:-9000}:9000
|
||||
- ${COMPOSE_PORT_HTTPS:-9443}:9443
|
||||
depends_on:
|
||||
|
||||
- postgresql
|
||||
- redis
|
||||
|
||||
worker:
|
||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2}
|
||||
container_name: authentik-worker
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
# `user: root` and the docker socket volume are optional.
|
||||
# See more for the docker socket integration here:
|
||||
# https://goauthentik.io/docs/outposts/integrations/docker
|
||||
# Removing `user: root` also prevents the worker from fixing the permissions
|
||||
# on the mounted folders, so when removing this make sure the folders have the correct UID/GID
|
||||
# (1000:1000 by default)
|
||||
user: root
|
||||
volumes:
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./media:/media
|
||||
- ./certs:/certs
|
||||
- ./custom-templates:/templates
|
||||
- ./ssh:/authentik/.ssh
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
depends_on:
|
||||
|
||||
- postgresql
|
||||
- redis
|
||||
|
||||
volumes:
|
||||
database:
|
||||
driver: local
|
||||
redis:
|
||||
driver: local
|
||||
```
|
||||
|
||||
In the `.env` file, the `PG_PASS` and `AUTHENTIK_SECRET_KEY` variables are already set.
|
||||
Deploy the stack.
|
||||
|
||||
You can then begin the initial setup by visiting:
|
||||
`http://yourserverip:9000/if/flow/initial-setup/`
|
||||
|
||||
::warning
|
||||
|
||||
__Warning:__ It’s recommended to create a new admin account and **disable** the default `akadmin` account.
|
||||
::
|
||||
|
||||
## Exposing Authentik
|
||||
---
|
||||
To use Authentik outside your local network, you must expose it.
|
||||
|
||||
::note
|
||||
📋 __Prerequisites:__ <br/><br/>
|
||||
We assume you have already created a subdomain like `auth.mydomain.com` in your [DNS zone](/general/networking/dns), with a CNAME pointing to `mydomain.com`. Also, unless you're using [Cloudflare Zero Trust](/serveex/security/cloudflare), you must have already forwarded port `443` from your router to port `443` of your server in your [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Open the `authentik-server.conf` file:
|
||||
|
||||
::tip
|
||||
✨ __Tip for those who dislike terminals:__
|
||||
You can use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/authentik-server.conf
|
||||
```
|
||||
|
||||
Verify that the following variables are set correctly:
|
||||
|
||||
```nginx
|
||||
set $upstream_authentik authentik-server;
|
||||
proxy_pass http://$upstream_authentik:9000;
|
||||
```
|
||||
|
||||
If not, press `i` to enter edit mode, make the necessary changes, then save and exit by pressing `Esc` followed by `:x`.
|
||||
|
||||
Create the `auth.subdomain.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/auth.subdomain.conf
|
||||
```
|
||||
|
||||
Press `i` to enter edit mode and paste the following configuration:
|
||||
|
||||
```nginx
|
||||
## Version 2023/05/31
|
||||
# Ensure your authentik container is named authentik-server
|
||||
# Ensure your DNS has a CNAME for authentik
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name auth.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
location / {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app authentik-server;
|
||||
set $upstream_port 9000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
|
||||
location ~ (/authentik)?/api {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app authentik-server;
|
||||
set $upstream_port 9000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Save and exit by pressing `Esc` then `:x`.
|
||||
|
||||
Go to Dockge, and edit the SWAG compose file to add the Authentik network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Attach the container to the custom network
|
||||
# ...
|
||||
|
||||
- authentik # Name of the network declared in the stack
|
||||
|
||||
networks: # Define the custom network
|
||||
# ...
|
||||
authentik: # Name of the network declared in the stack
|
||||
name: authentik_default # Actual name of the external network
|
||||
external: true # Indicates it's an external network
|
||||
```
|
||||
|
||||
Restart the stack and wait for SWAG to be fully operational.
|
||||
|
||||
Done! You can now access Authentik via `https://auth.mydomain.com`
|
||||
|
||||
## Enable Multifactor Authentication
|
||||
---
|
||||
The main value of Authentik is using multifactor authentication for all protected apps.
|
||||
|
||||
- Go to `https://auth.mydomain.com`
|
||||
- Log in
|
||||
- Go to _Settings_
|
||||
- Click the _MFA_ section
|
||||
- Click _Register_
|
||||
- Choose a method like _TOTP device_ (you'll need an authenticator app like Google Authenticator)
|
||||
- Follow the steps
|
||||
|
||||
You’ll now be prompted to enter a one-time code at every login.
|
||||
|
||||
## Protecting a Native App
|
||||
---
|
||||
Authentik is natively compatible with several applications. You can find the list and [support here](https://docs.goauthentik.io/integrations/services/).
|
||||
|
||||
## Protecting an App via Reverse Proxy
|
||||
---
|
||||
SWAG lets you insert Authentik’s login page between a request and access to your service. To do this:
|
||||
|
||||
- Configure the authentication provider in Authentik.
|
||||
- Edit the domain proxy file so SWAG can intercept the request.
|
||||
|
||||
Why do this when Dockge already has authentication? Because Dockge uses weak HTTP authentication. With Authentik, you get strong MFA authentication and automatic login to all apps protected by Authentik. This secures access to Dockge and other apps without needing a VPN.
|
||||
|
||||
### Configuring Authentik
|
||||
|
||||
- Go to Authentik
|
||||
- Open the admin panel
|
||||
- Select _Applications_ then _Create with wizard_
|
||||
- Fill in the fields as shown:
|
||||
|
||||

|
||||
|
||||
- At the next step, choose "Forward authentication (single application)" and configure it as shown (flows are important):
|
||||
|
||||

|
||||
|
||||
- Next, go to the _Outposts_ menu on the left and edit _authentik Embedded Outpost_:
|
||||
|
||||

|
||||
|
||||
- Add the `dockge` application by moving it to the right column and save.
|
||||
|
||||
### Configuring SWAG
|
||||
|
||||
Edit the file `dockge.mydomain.com`:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/dockge.subdomain.conf
|
||||
```
|
||||
|
||||
Press `i` to enter edit mode and uncomment the two lines `#include /config/nginx/authentik-server.conf;`
|
||||
|
||||
Press `Esc`, type `:x`, and press `Enter` to save and exit.
|
||||
|
||||
Done! Now when accessing `https://dockge.mydomain.com`, you’ll be redirected to the Authentik login screen.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ In Dockge's settings, you can disable Dockge's authentication to avoid double login. **Warning**: this means if the port is open on your local network, there will be no authentication at all.
|
||||
::
|
||||
|
||||
::note
|
||||
|
||||
Repeat this process for each app you want to protect (unless it has native integration with Authentik).
|
||||
::
|
||||
|
||||
Your new architecture looks like this:
|
||||
|
||||

|
||||
|
||||
## Protecting a Remote Server Service
|
||||
---
|
||||
For a [native application](/serveex/security/authentik/#protecting-a-native-app) (via OAuth 2.0 or other), nothing changes.
|
||||
|
||||
For a non-native app behind a reverse proxy, you must deploy an __Outpost__. An Outpost is a container acting as a local proxy — it's the target of your app's auth requests and the only one authorized to communicate with your Authentik API.
|
||||
|
||||
::note
|
||||
Prerequisites:
|
||||
|
||||
- Install [Docker](/serveex/core/docker) on the remote server hosting the service.
|
||||
- If the app has no native integration, use a compatible reverse proxy. We will use [SWAG](/serveex/core/swag) here.
|
||||
::
|
||||
|
||||
This container will forward requests to your main [Authentik](/serveex/security/authentik#authentik) instance over the internet (or your local network). The server will perform checks and respond to the Outpost, which will allow or block access accordingly.
|
||||
|
||||

|
||||
|
||||
### Configuring Authentik
|
||||
|
||||
Create your [providers and applications](/serveex/security/authentik/#protecting-a-native-app) as shown earlier.
|
||||
|
||||
Then, in the admin panel, go to _Applications > Outposts_, and create a new outpost.
|
||||
|
||||
Fill in as follows:
|
||||
|
||||
| Field | Value |
|
||||
|----------------|------------------------------------------------------------------------|
|
||||
| `Name` | Your preferred name |
|
||||
| `Type` | `Proxy` |
|
||||
| `Integration` | Leave empty |
|
||||
| `Applications` | Select the applications you previously created |
|
||||
|
||||
In the `Advanced settings` section, clear the existing content and enter:
|
||||
|
||||
```yaml
|
||||
log_level: info
|
||||
docker_labels: null
|
||||
authentik_host: https://your_authentik_server_domain/
|
||||
object_naming_template: ak-outpost-%(name)s
|
||||
authentik_host_insecure: false
|
||||
container_image:
|
||||
docker_network: null
|
||||
docker_map_ports: true
|
||||
docker_labels: null
|
||||
```
|
||||
|
||||
Save and exit.
|
||||
|
||||
On the list of created outposts, locate the new one and click _Show details_ at the end of the line. Carefully copy the access token.
|
||||
|
||||
### Configuring the Remote Machine
|
||||
|
||||
We assume you’ve already installed [Docker](/serveex/core/docker) and [SWAG](/serveex/core/swag) on this remote machine.
|
||||
|
||||
On your remote machine, use [Dockge](/serveex/core/docker/#installer-dockge-pour-gérer-et-déployer-les-conteneurs) to create a stack named `authentik-outpost`.
|
||||
|
||||
If you haven’t installed [Dockge](/serveex/core/docker/#installer-dockge-pour-gérer-et-déployer-les-conteneurs), create a folder `/docker/authentik-outpost`, or directly via command line:
|
||||
|
||||
```sh
|
||||
sudo mkdir -P /docker/authentik-outpost
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip for terminal-averse users:__
|
||||
You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
Create the `compose.yaml` file or paste the configuration directly into Dockge if installed.
|
||||
|
||||
Via command line:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/authentik-outpost/compose.yaml
|
||||
```
|
||||
Enter edit mode by pressing `i` and paste the following configuration, updating the version in `{AUTHENTIK_TAG:proxy:2024.2.3}`{lang=properties} to match your Authentik server version.
|
||||
|
||||
```yaml
|
||||
version: "3.5"
|
||||
services:
|
||||
authentik_proxy:
|
||||
container_name: authentik-outpost
|
||||
image: ghcr.io/goauthentik/proxy:2024.2.3
|
||||
# Optionally specify which networks the container should be
|
||||
# might be needed to reach the core authentik server
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
ports:
|
||||
|
||||
- 9000:9000
|
||||
- 9443:9443
|
||||
environment:
|
||||
AUTHENTIK_HOST: ${HOST}
|
||||
AUTHENTIK_INSECURE: "false"
|
||||
AUTHENTIK_TOKEN: ${TOKEN}
|
||||
```
|
||||
|
||||
Go to the SWAG stack on the remote machine (or edit directly using Dockge) and add the authentik-outpost network in the configuration file like this (see `networks` section):
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/compose.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: #...
|
||||
# ...
|
||||
networks: # Attach the container to the custom network
|
||||
|
||||
- authentik-outpost # Network name as declared in the stack
|
||||
|
||||
networks: # Define the custom network
|
||||
#...
|
||||
authentik-outpost: # Name of the network declared in the stack
|
||||
name: authentik-outpost_default # Actual name of the external network
|
||||
external: true # Marks it as an external network
|
||||
```
|
||||
|
||||
Press `Esc`, then type `:x` and press `Enter` to save and exit.
|
||||
|
||||
::note
|
||||
|
||||
We assume the Dockge network name is `authentik-outpost_default`.
|
||||
::
|
||||
|
||||
If using [Dockge](/serveex/core/docker/#installer-dockge-pour-gérer-et-déployer-les-conteneurs), restart SWAG.
|
||||
|
||||
Otherwise, via terminal:
|
||||
|
||||
```sh
|
||||
cd /docker/swag/
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
Create (or fill using Dockge) the `.env` file in the `authentik-outpost` directory:
|
||||
|
||||
Via command line:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/authentik-outpost/.env
|
||||
```
|
||||
|
||||
Enter edit mode with `i` and paste the following configuration:
|
||||
|
||||
```properties
|
||||
HOST=
|
||||
TOKEN=
|
||||
```
|
||||
|
||||
Fill in the values:
|
||||
|
||||
| Variable | Value | Example |
|
||||
|----------|-------|---------|
|
||||
| `HOST`{lang=properties} | The URL of your Authentik server | `https://auth.domain.com` |
|
||||
| `TOKEN`{lang=properties} | The previously copied access token | `Q2pVEqsTNRkJSO9SkJzU3KZ2` |
|
||||
|
||||
Press `Esc`, then type `:x` and press `Enter` to save and exit.
|
||||
|
||||
If using Dockge, deploy the stack.
|
||||
|
||||
Otherwise, via terminal:
|
||||
|
||||
```sh
|
||||
cd /docker/authentik-outpost/
|
||||
sudo docker compose up -d
|
||||
```
|
||||
|
||||
The container is now running. You can verify its status from your Authentik instance admin panel under _Applications > Outposts_.
|
||||
|
||||
Now, let’s configure SWAG.
|
||||
|
||||
Open the `authentik-server.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/authentik-server.conf
|
||||
```
|
||||
|
||||
In the file, press `i` to enter edit mode and change `authentik-server` to `authentik-outpost` as shown:
|
||||
|
||||
```nginx
|
||||
set $upstream_authentik authentik-outpost;
|
||||
proxy_pass http://$upstream_authentik:9000;
|
||||
```
|
||||
|
||||
Save and exit with `Esc`, then `:x` and `Enter`.
|
||||
|
||||
Then configure the applications to protect as you did on your main server, whether they are [native](/serveex/security/authentik/#protecting-a-native-app) or protected via [reverse proxy](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
|
||||
## Migrating an Authentik Database
|
||||
---
|
||||
On the source machine, dump the database:
|
||||
|
||||
```sh
|
||||
sudo docker exec authentik-postgres pg_dump -U authentik -F t authentik > /path/to/mydb.tar
|
||||
```
|
||||
|
||||
Then transfer it to the target machine. On the target machine, copy the file into the Docker container:
|
||||
|
||||
```sh
|
||||
cp /path/to/mydb.tar authentik-postgres:/path/to/wherever
|
||||
```
|
||||
|
||||
(Optional) Purge existing tables:
|
||||
|
||||
```sh
|
||||
sudo docker exec -i authentik-postgres psql -U authentik -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'authentik' AND pid <> pg_backend_pid();" && sudo docker exec -i authentik-postgres psql -U authentik -d postgres -c "DROP DATABASE IF EXISTS authentik;" && sudo docker exec -i authentik-postgres psql -U authentik -d postgres -c "CREATE DATABASE authentik;"
|
||||
```
|
||||
|
||||
Restore the database:
|
||||
|
||||
```sh
|
||||
sudo docker exec authentik-postgresql pg_restore -U authentik -d authentik /path/to/wherever/mydb.tar
|
||||
```
|
||||
@@ -0,0 +1,272 @@
|
||||
---
|
||||
title: Cloudflare Zero Trust
|
||||
description: Use Cloudflare Tunnels and Zero Trust to expose homelab services without opening ports — configure SWAG and manage multiple tunnels.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Cloudflare Zero Trust
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Understand the concept of Cloudflare Tunnels
|
||||
- Configure your Cloudflare account
|
||||
- Configure SWAG
|
||||
- Manage multiple tunnels
|
||||
::
|
||||
|
||||

|
||||
|
||||
## Introduction
|
||||
---
|
||||
The _Zero Trust_ architecture is the practice of designing systems based on the principle of __"never trust, always verify"__, as opposed to the traditional principle of __"trust, but verify"__. This concept has become increasingly popular recently due to the growing number of attacks targeting user data. It’s a broad concept, but we’ll focus on how to apply _Zero Trust_ to the web services we host.
|
||||
|
||||
_Cloudflare tunnels_ offer a simple way to implement _Zero Trust_, using [SWAG](/serveex/core/swag) and [Authentik](/serveex/security/authentik).
|
||||
|
||||
Simply put, Cloudflare Tunnels allow you to:
|
||||
|
||||
- Hide your server’s IP (and your home IP if it's self-hosted)
|
||||
- Authenticate traffic
|
||||
- Benefit from Cloudflare protections (DDoS attacks, blacklists, malicious requests, etc.)
|
||||
- Use Cloudflare's CDN to cache and speed up your websites
|
||||
- Avoid opening router ports for services exposed by SWAG
|
||||
|
||||
Here we’ll explain how to integrate SWAG with Cloudflare tunnels.
|
||||
|
||||
::warning
|
||||
|
||||
- __Warning:__
|
||||
- Do not use Cloudflare tunnels to expose a mail server
|
||||
- Do not use Cloudflare tunnels to expose a video service like Plex (if you followed [this guide](/serveex/media/plex), Plex is not exposed, so it’s fine)
|
||||
- Do not use Cloudflare tunnels for the BitTorrent protocol (if you followed [this guide](/serveex/media/qbittorrent), everything is fine)
|
||||
::
|
||||
|
||||
## Cloudflare Configuration
|
||||
---
|
||||
### DNS Zone
|
||||
|
||||
First, you need to set Cloudflare as your [DNS zone](/general/networking/dns) manager. If you bought your domain from Cloudflare, that’s already done. Otherwise, check with your registrar how to add external DNS servers. Cloudflare provides [step-by-step documentation](https://developers.cloudflare.com/dns/zone-setups/full-setup/setup/) on how to configure a DNS Zone, whether your domain is external or registered with Cloudflare.
|
||||
|
||||
If you only have one server to protect behind Cloudflare, you can delete all existing DNS records. By default, your domain and all its subdomains will be redirected to the tunnel.
|
||||
|
||||
If you have subdomains pointing to other servers, you can still define them in the DNS zone using A records.
|
||||
|
||||
If you have several servers and tunnels under one domain, [see here](http://192.168.7.80:8005/serveex/cloudflare/#gerer-plusieurs-tunnels-pour-plusieurs-serveurs).
|
||||
|
||||
### API Key
|
||||
|
||||
Start by creating a new Cloudflare API token and retrieving your zone and account IDs.
|
||||
|
||||
On your Cloudflare dashboard, on your domain overview page, you’ll see the `zone` and `account` IDs at the bottom right. Save both securely.
|
||||
|
||||

|
||||
|
||||
Just below that is a link titled _Get your API token_. Click it. The token scope must include `Zone:DNS:Edit` and `Account:Cloudflare Tunnel:Edit`. Your page should look like the screenshot below.
|
||||
|
||||

|
||||
|
||||
Once created, your token will only be shown once. Save it securely, as it cannot be viewed again later.
|
||||
|
||||
### Cloudflare Zero Trust
|
||||
|
||||
You must register for _Cloudflare Teams_ to access the _Zero Trust_ dashboard that manages tunnels and access policies. This is a premium service, but there’s a free plan for up to 50 users—perfect for a home lab. Keep in mind that a valid credit card is required to register, but the free plan incurs no charges.
|
||||
|
||||
Register [via this link](https://dash.teams.cloudflare.com/).
|
||||
|
||||
## SWAG Configuration
|
||||
---
|
||||
::note
|
||||
|
||||
This guide assumes you own `mondomaine.fr` and that its DNS is correctly pointing to Cloudflare, as described above.
|
||||
::
|
||||
|
||||
SWAG supports two Docker Mods:
|
||||
|
||||
- __Cloudflared__, the container used to create and manage tunnels
|
||||
- __Cloudflared Real IP__, which allows SWAG to receive the true source IP of incoming requests instead of Docker’s internal IP (important for IP geolocation mods like DBIP).
|
||||
|
||||
These two mods, merged into the SWAG container, require some configuration.
|
||||
|
||||
### Tunnel Configuration
|
||||
|
||||
Create a file `tunnelconfig.yml` to reference in your SWAG `compose.yaml`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using the terminal.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/tunnelconfig.yml
|
||||
```
|
||||
|
||||
Press `i` to enter insert mode and paste:
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
|
||||
- hostname: mondomaine.fr
|
||||
service: https://mondomaine.fr
|
||||
|
||||
- hostname: "*.mondomaine.fr"
|
||||
service: https://mondomaine.fr
|
||||
|
||||
- service: http_status:404
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit with `:x` and `Enter`.
|
||||
|
||||
### Cloudflare Real IP Configuration
|
||||
|
||||
Now configure _Cloudflare Real IP_.
|
||||
|
||||
Open the `nginx.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/nginx.conf
|
||||
```
|
||||
|
||||
Press `i` and add the following at the end of the `http` section:
|
||||
|
||||
```nginx
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
include /config/nginx/cf_real-ip.conf;
|
||||
set_real_ip_from 127.0.0.1;
|
||||
```
|
||||
|
||||
Save and exit with `:x`.
|
||||
|
||||
### Docker Compose
|
||||
|
||||
In Dockge, edit your SWAG stack with this:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
swag:
|
||||
image: lscr.io/linuxserver/swag:latest
|
||||
container_name: swag
|
||||
cap_add:
|
||||
|
||||
- NET_ADMIN
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
environment:
|
||||
|
||||
- DOCKER_MODS=linuxserver/mods:swag-dbip|linuxserver/mods:swag-dashboard|linuxserver/mods:swag-auto-reload|linuxserver/mods:universal-cloudflared|linuxserver/mods:swag-cloudflare-real-ip
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
- URL=${DOMAIN}
|
||||
- SUBDOMAINS=wildcard
|
||||
- VALIDATION=dns
|
||||
- DNSPLUGIN=${PLUGIN}
|
||||
- EMAIL=${EMAIL}
|
||||
- CF_ZONE_ID=${ZONE_ID}
|
||||
- CF_ACCOUNT_ID=${ACCOUNT_ID}
|
||||
- CF_API_TOKEN=${API_TOKEN}
|
||||
- CF_TUNNEL_NAME=${TUNNEL_NAME}
|
||||
- CF_TUNNEL_PASSWORD=${TUNNEL_PW}
|
||||
- FILE__CF_TUNNEL_CONFIG=/config/tunnelconfig.yml
|
||||
extra_hosts:
|
||||
|
||||
- ${DOMAIN}:127.0.0.1
|
||||
ports:
|
||||
|
||||
- 81:81
|
||||
volumes:
|
||||
|
||||
- /docker/swag/config:/config
|
||||
- /docker/swag/config/fail2ban/fail2ban.sqlite3:/dashboard/fail2ban.sqlite3:ro
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add a Watchtower label to automate updates:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Fill in your `.env` file:
|
||||
|
||||
```properties
|
||||
PUID=
|
||||
PGID=
|
||||
DOMAIN=
|
||||
PLUGIN=
|
||||
EMAIL=
|
||||
ZONE_ID=
|
||||
ACCOUNT_ID=
|
||||
API_TOKEN=
|
||||
TUNNEL_NAME=
|
||||
TUNNEL_PW=
|
||||
```
|
||||
|
||||
| Variable | Value | Example |
|
||||
|----------------|-------------------------------------------------------------|--------------------------------|
|
||||
| `PUID` | User ID (`id username`) | `1000` |
|
||||
| `GUID` | Group ID (`id username`) | `1000` |
|
||||
| `DOMAIN` | Your reserved domain | `mondomaine.fr` |
|
||||
| `PLUGIN` | DNS provider (also configure `cloudflare.ini`) | `cloudflare` |
|
||||
| `EMAIL` | Email for the certificate | `[email protected]` |
|
||||
| `ZONE_ID` | Cloudflare Zone ID | `aNhcz1l3JfWbFZo2XMpzQlP2iOqk` |
|
||||
| `ACCOUNT_ID` | Cloudflare Account ID | `buKsjNHLyzKMM1qYnzOy4s7SHfly` |
|
||||
| `API_TOKEN` | API token | `53ydYus9TFFk1DOXNdP87iIcJtQjoW` |
|
||||
| `TUNNEL_NAME` | Tunnel name | `my_tunnel` |
|
||||
| `TUNNEL_PW` | Strong, random password | `iSzKRmP4VbnlsMvdSdgBEJiJi` |
|
||||
|
||||
Once done, deploy the stack. Check the logs—you should reach `server ready`.
|
||||
|
||||
Then confirm your tunnel appears under _Networks > Tunnels_ in [Cloudflare Zero Trust](https://one.dash.cloudflare.com/). By default, all subdomains will be routed through the tunnel—no need to define them [in your DNS zone](/general/networking/dns).
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ If you want to expose a service without a tunnel, just define an A record [in your DNS zone](/general/networking/dns). If resolution fails, disable the proxy function for that record—e.g., for `sub.mondomaine.fr`.
|
||||

|
||||
::
|
||||
|
||||
## Managing Multiple Tunnels for Multiple Servers
|
||||
---
|
||||
By default, all subdomains of your domain are routed through the single tunnel. But if you have a second server, just change the tunnel name in that SWAG instance.
|
||||
|
||||
In your DNS zone, redirect subdomains to the correct tunnel.
|
||||
|
||||
Go to _Networks > Tunnels_ in [Cloudflare Zero Trust](https://one.dash.cloudflare.com/).
|
||||
|
||||
Note the tunnel IDs:
|
||||
|
||||

|
||||
|
||||
Then in the [Cloudflare DNS dashboard](https://dash.cloudflare.com/), click your domain name.
|
||||
|
||||
Click `Add Record` and add these two CNAME records (include `.cfargotunnel.com`):
|
||||
|
||||
| Type | Name | Target |
|
||||
|---------|--------------|----------------------------------------|
|
||||
| `CNAME` | `subdomain1` | `yourtunnelid1.cfargotunnel.com` |
|
||||
| `CNAME` | `subdomain2` | `yourtunnelid2.cfargotunnel.com` |
|
||||
|
||||
If you have many subdomains, point them to the above reference subdomains.
|
||||
|
||||
This way, if a tunnel ID changes, you only update one DNS record.
|
||||
|
||||
Example:
|
||||
|
||||
- `sub1` and `sub2` also point to the server behind `subdomain1`:
|
||||
|
||||
| Type | Name | Target |
|
||||
|---------|--------|---------------|
|
||||
| `CNAME` | `sub1` | `subdomain1` |
|
||||
| `CNAME` | `sub2` | `subdomain1` |
|
||||
|
||||
- `sub3` and `sub4` point to the server behind `subdomain2`:
|
||||
|
||||
| Type | Name | Target |
|
||||
|---------|--------|---------------|
|
||||
| `CNAME` | `sub3` | `subdomain2` |
|
||||
| `CNAME` | `sub4` | `subdomain2` |
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Monitoring
|
||||
icon: i-lucide-chart-no-axes-column
|
||||
@@ -0,0 +1,204 @@
|
||||
---
|
||||
title: Uptime-Kuma
|
||||
description: Install Uptime-Kuma to monitor your self-hosted services uptime, set up alerts, and optionally protect the dashboard with Authentik.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Uptime-Kuma
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install and deploy Uptime-Kuma
|
||||
- Expose Uptime-Kuma
|
||||
- (Optional) Protect Uptime-Kuma with Authentik
|
||||
::
|
||||
|
||||
[Uptime-Kuma](https://github.com/louislam/uptime-kuma) is a container dedicated to service monitoring. The principle is to regularly send requests to your services to determine if they are online, and alert you if not. Uptime-Kuma is developed by the same developer as Dockge.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── uptime-kuma
|
||||
├── date
|
||||
└── compose.yaml
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `uptime-kuma`, then copy and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
uptime-kuma:
|
||||
image: louislam/uptime-kuma:2-slim
|
||||
container_name: uptime-kuma
|
||||
volumes:
|
||||
|
||||
- /docker/uptime-kuma/uptime-kuma-data:/app/data
|
||||
ports:
|
||||
|
||||
- 3200:3001 # <Host Port>:<Container Port>
|
||||
restart: always
|
||||
```
|
||||
::tip
|
||||
✨ __Tip:__ Add the Watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
uptime-kuma:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
::
|
||||
|
||||
You can now access the tool via `http://yourserverip:3200`.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Expose with Swag
|
||||
---
|
||||
::note
|
||||
📋 __Before you begin:__
|
||||
<br/><br/>
|
||||
We assume you have the subdomain `stats.mydomain.com` with a `CNAME` pointing to `mydomain.com` in your [DNS zone](/general/networking/dns). And of course, [unless you're using Cloudflare Zero Trust](/serveex/security/cloudflare), port `443` of your router should point to port `443` of your server via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
::warning
|
||||
|
||||
Uptime-Kuma does not use multi-factor authentication. Exposing Uptime-Kuma on the internet could compromise the machines it monitors. Only do this if you're using an MFA system like [Authentik](/serveex/security/authentik/). Otherwise, don’t expose it with SWAG; use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
In the Swag folders, create the `stats.subdomain.conf` file.
|
||||
|
||||
::tip
|
||||
✨ __Tip for those who dislike the terminal:__
|
||||
you can use [File Browser](/serveex/files/file-browser) to browse and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/stats.subdomain.conf
|
||||
```
|
||||
Enter insert mode with `i` and paste the following config:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name stats.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app uptime-kuma;
|
||||
set $upstream_port 3001;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit with `:x` and `Enter`.
|
||||
|
||||
In Dockge, edit the SWAG compose and add the Uptime-Kuma network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Link container to custom network
|
||||
# ...
|
||||
|
||||
- uptime-kuma # Name of the declared network
|
||||
|
||||
networks: # Define custom network
|
||||
# ...
|
||||
uptime-kuma: # Name of the declared network
|
||||
name: uptime-kuma_default # Actual name of the external network
|
||||
external: true # Specifies it's an external network
|
||||
```
|
||||
|
||||
Restart the stack and wait until SWAG is fully operational.
|
||||
|
||||
::note
|
||||
|
||||
Here we assume that the network name of Uptime-Kuma is `uptime-kuma_default`. You can verify the connection by visiting SWAG's dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
That's it! Uptime-Kuma is now exposed, and you can access it via `https://stats.mydomain.com`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__
|
||||
<br/><br>
|
||||
You can protect this app with Authentik by opening `stats.subdomain.conf` and uncommenting the lines:
|
||||
`include /config/nginx/authentik-server.conf;`
|
||||
and
|
||||
`include /config/nginx/authentik-location.conf;`.
|
||||
Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy). If you want the public stats page to be accessible without authentication:
|
||||
|
||||
- Edit the Uptime-Kuma provider
|
||||
- In *Advanced Protocol Settings > Authenticated Paths*, enter:
|
||||
|
||||
```properties
|
||||
^/$
|
||||
^/status
|
||||
^/assets/
|
||||
^/assets
|
||||
^/icon.svg
|
||||
^/api/.*
|
||||
^/upload/.*
|
||||
^/metrics
|
||||
::
|
||||
|
||||
Redeploy the stack.
|
||||
|
||||
Uptime-Kuma will then be publicly reachable via `https://stats.mydomain.com`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ If you're using Authentik and don't mind exposing the admin panel to your local network, you can disable Uptime-Kuma's native authentication in its settings and rely solely on Authentik.
|
||||
::
|
||||
@@ -0,0 +1,185 @@
|
||||
---
|
||||
title: Dozzle
|
||||
description: Install Dozzle to monitor Docker container logs in real time from a clean web interface, exposed via SWAG.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Dozzle
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install Dozzle
|
||||
- Expose Dozzle with Swag
|
||||
::
|
||||
|
||||
[Dozzle](https://dozzle.dev/) is a container that lets you access logs from your other containers and display them in real time through a user-friendly interface. It's a simple way to browse logs and retrieve information from the history.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── dozzle
|
||||
└── data
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `dozzle`, then copy and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
dozzle:
|
||||
container_name: dozzle
|
||||
image: amir20/dozzle:latest
|
||||
ports:
|
||||
|
||||
- 9135:8080
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
environment:
|
||||
|
||||
- DOZZLE_HOSTNAME=${DOMAIN}
|
||||
volumes:
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
dozzle:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Fill in your domain name in the `.env` file, for example:
|
||||
|
||||
```properties
|
||||
DOMAIN=dozzle.mydomain.com
|
||||
```
|
||||
|
||||
Deploy the container. Go to `http://yourserverip:9135`. Voilà, your Dozzle web UI is up and running!
|
||||
|
||||
## Exposing Dozzle with Swag
|
||||
---
|
||||
|
||||
::warning
|
||||
|
||||
Dozzle does not use multi-factor authentication. Exposing Dozzle to the internet could compromise the connected machines. Only do this if you use a multi-factor authentication system like [Authentik](/serveex/security/authentik/). Otherwise, do not expose it with SWAG and instead use a VPN like [Wireguard](/serveex/security/wireguard).
|
||||
::
|
||||
|
||||
You may want to access Dozzle remotely and on all your devices. To do so, we’ll expose Dozzle via Swag.
|
||||
|
||||
::note
|
||||
📋 __Before you begin:__
|
||||
<br/><br/>
|
||||
We assume you have created a subdomain like `dozzle.mydomain.com` in your [DNS zone](/general/networking/dns) with a `CNAME` pointing to `mydomain.com` and that, [unless you're using Cloudflare Zero Trust](/serveex/security/cloudflare), you’ve redirected port `443` from your router to port `443` on your server in your [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Go to Dockge and edit the SWAG compose file to add Dozzle’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to a custom network
|
||||
# ...
|
||||
|
||||
- dozzle # Network name declared in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
dozzle: # Network name declared in the stack
|
||||
name: dozzle_default # Actual name of the external network
|
||||
external: true # Indicates it's an externally defined network
|
||||
```
|
||||
|
||||
Redeploy the stack by clicking “Deploy” and wait for SWAG to be fully operational.
|
||||
|
||||
::note
|
||||
|
||||
We assume the Dozzle network name is `dozzle_default`. You can verify the connection is working by visiting the SWAG dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
In the Swag folder, create the `dozzle.subdomain.conf` file.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to browse and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/dozzle.subdomain.conf
|
||||
```
|
||||
Enter edit mode by pressing `i` and paste the configuration below:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name dozzle.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app dozzle;
|
||||
set $upstream_port 8080;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x` and pressing `Enter`.
|
||||
|
||||
And there you go, Dozzle is now exposed!
|
||||
|
||||
::tip
|
||||
✨ You can protect this app with Authentik by opening `dozzle.subdomain.conf` and removing the `#` in front of `include /config/nginx/authentik-server.conf;`{lang=nginx} and `include /config/nginx/authentik-location.conf;`{lang=nginx}. Don’t forget to [create an application and a provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,197 @@
|
||||
---
|
||||
title: Speedtest Tracker
|
||||
description: Install Speedtest Tracker to automatically measure and log your internet connection speed over time, exposed with SWAG.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Speedtest Tracker
|
||||
|
||||
::note
|
||||
🎯 **Objectives:**
|
||||
|
||||
- Install Speedtest Tracker
|
||||
- Expose Speedtest Tracker with SWAG
|
||||
::
|
||||
|
||||
[Speedtest Tracker](https://docs.speedtest-tracker.dev/) is a container that allows you to schedule regular speed tests in order to log your server's internet connection status.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
::note
|
||||
|
||||
We will use the Docker image maintained by [LinuxServer.io](https://docs.linuxserver.io/images/docker-speedtest-tracker/)
|
||||
::
|
||||
|
||||
File structure:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── speedtest-tracker
|
||||
└── data
|
||||
└── config
|
||||
```
|
||||
|
||||
In a terminal, generate a key using the following command:
|
||||
|
||||
```sh
|
||||
echo -n 'base64:'; openssl rand -base64 32;
|
||||
```
|
||||
|
||||
Take note of the key.
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `speedtest-tracker`, then paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
speedtest-tracker:
|
||||
image: lscr.io/linuxserver/speedtest-tracker:latest
|
||||
restart: unless-stopped
|
||||
container_name: speedtest-tracker
|
||||
ports:
|
||||
|
||||
- ${PORT}:80
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- TZ=Europe/Paris
|
||||
- APP_KEY=${API_KEY}
|
||||
- DB_CONNECTION=sqlite
|
||||
- SPEEDTEST_SCHEDULE=${SCHEDULE}
|
||||
volumes:
|
||||
|
||||
- /docker/speedtest-tracker/data/config:/config
|
||||
```
|
||||
|
||||
Find your `PUID` and `GUID` by running the following command:
|
||||
|
||||
```sh
|
||||
id yourusername
|
||||
```
|
||||
|
||||
In the `.env` file, set the variable `API_KEY` with the key you generated and add a cron-style test schedule, as well as your `PUID` and `GUID`, for example:
|
||||
|
||||
```properties
|
||||
SCHEDULE=15 */6 * * * # every 6 hours
|
||||
API_KEY=base64:zihejehkj8_nzhY/OjeieR= # your key
|
||||
PUID=1000
|
||||
GUID=1000
|
||||
PORT=3225 # port to access the web UI
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ **Tip:** You can configure additional environment variables by referring to the [official documentation](https://docs.speedtest-tracker.dev/getting-started/environment-variables).
|
||||
::
|
||||
|
||||
Deploy the container and go to `http://yourserverip:3225`. Log in with the account `[email protected]` and the password `password`. Don’t forget to change your ID and password once logged in!
|
||||
|
||||
## Expose Speedtest Tracker
|
||||
---
|
||||
::note
|
||||
📋 **Prerequisites:**
|
||||
We assume that you've already created a subdomain like `speedtest.yourdomain.com` in your [DNS zone](/general/networking/dns) with a `CNAME` pointing to `yourdomain.com`, and [unless you’re using Cloudflare Zero Trust](/serveex/security/cloudflare), you've also forwarded port `443` from your router to port `443` of your server in your [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Now we want to expose Speedtest Tracker to the internet so you can access it remotely. We assume you've set up the DNS `CNAME` for `speedtest.yourdomain.com` pointing to `yourdomain.com`.
|
||||
|
||||
::warning
|
||||
|
||||
Speedtest Tracker does not use multi-factor authentication. Exposing it on the internet could compromise connected devices. Do so only if you use a multi-factor system like [Authentik](/serveex/security/authentik/). Otherwise, avoid using SWAG and prefer a VPN like [Wireguard](/serveex/security/wireguard).
|
||||
::
|
||||
|
||||
Open the `speedtest.subdomain.conf` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/speedtest.subdomain.conf
|
||||
```
|
||||
|
||||
Configure it like this:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name speedtest.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# Authentication options (uncomment as needed)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# Basic auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# Per-location authentication
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
|
||||
set $upstream_app speedtest-tracker;
|
||||
set $upstream_port 3225;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Save and exit. The configuration will update in a few seconds.
|
||||
|
||||
::note
|
||||
|
||||
By default, SWAG doesn’t know the name "speedtest-tracker". To allow access, you need to add Speedtest Tracker’s network to SWAG’s `compose.yml`.
|
||||
::
|
||||
|
||||
Go to Dockge, and edit SWAG’s compose to include Speedtest Tracker’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks:
|
||||
# ...
|
||||
|
||||
- speedtest-tracker
|
||||
|
||||
networks:
|
||||
# ...
|
||||
speedtest-tracker:
|
||||
name: speedtest-tracker_default
|
||||
external: true
|
||||
```
|
||||
|
||||
Restart the stack by clicking "Deploy" and wait for SWAG to be fully up.
|
||||
|
||||
::note
|
||||
|
||||
This assumes the Speedtest Tracker network is named `speedtest-tracker_default`. You can verify the connection by visiting SWAG’s dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
Wait a moment, then visit `https://speedtest.yourdomain.com` in your browser — you should be redirected to Speedtest Tracker. You can check service status via the dashboard (`http://yourserverip:81` from the local network).
|
||||
|
||||
::tip
|
||||
✨ You can protect this app with Authentik by opening `speedtest.subdomain.conf` and uncommenting
|
||||
`include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`.
|
||||
Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: Beszel
|
||||
description: Install Beszel to monitor server CPU, RAM, disk, and network metrics — including remote servers — with a lightweight web dashboard.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Beszel
|
||||
|
||||
::note
|
||||
🎯 __Objectives:__
|
||||
|
||||
- Install Beszel
|
||||
- Monitor the local server
|
||||
- Monitor a remote server
|
||||
- Expose Beszel with Swag
|
||||
::
|
||||
|
||||
[Beszel](https://beszel.dev/) is a container that gives you real-time access to hardware information from your servers and allows historical tracking. CPU activity, disk usage, temperatures, RAM—nothing escapes your monitoring. Beszel also lets you configure notifications and alerts when your predefined thresholds are exceeded.
|
||||
|
||||
Beszel includes a hub with a web UI and an agent that collects data from your server or a remote server.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── beszel
|
||||
├── data
|
||||
└── socket
|
||||
```
|
||||
|
||||
Open Dockge, click `compose`, name the stack `beszel`, and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
beszel:
|
||||
image: henrygd/beszel:latest
|
||||
container_name: beszel
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
||||
- ${PORT}:8090
|
||||
volumes:
|
||||
|
||||
- ./data:/beszel_data
|
||||
- ./socket:/beszel_socket
|
||||
|
||||
beszel-agent:
|
||||
image: henrygd/beszel-agent:latest
|
||||
container_name: beszel-agent
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
volumes:
|
||||
|
||||
- ./socket:/beszel_socket
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
LISTEN: /beszel_socket/beszel.sock
|
||||
# Do not remove quotes around the key
|
||||
KEY: ${KEY}
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the Watchtower label to each container to automate updates.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
beszel:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Fill out the `.env` file, for example:
|
||||
|
||||
```properties
|
||||
PORT=8090 # web UI port
|
||||
KEY= # private key to retrieve from Beszel when adding a system
|
||||
```
|
||||
|
||||
For the `KEY` value, you'll need to launch Beszel once to get it.
|
||||
|
||||
Deploy the container and go to `http://yourserverip:8090`. Your Beszel web UI is now accessible!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
### Add local server information
|
||||
|
||||
Now that the web UI is accessible, you need to push local server information into it. Just add a machine via the web UI and configure it like this:
|
||||
|
||||

|
||||
|
||||
Note the private key and confirm. Enter the key in your `.env` file in Dockge and redeploy the stack. Once done, your server will appear in the web UI:
|
||||
|
||||

|
||||
|
||||
### Add a remote server
|
||||
|
||||
You can also monitor a remote server. To do so, run the agent on the remote server. Add a new machine in Beszel and fill in:
|
||||
|
||||
- The name displayed for your remote server
|
||||
- The IP address or domain name of the remote server
|
||||
- The listening port (e.g., `45876`)
|
||||
|
||||
Beszel will suggest a `compose.yaml` to deploy on the remote server, or you can use:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
beszel-agent:
|
||||
image: henrygd/beszel-agent
|
||||
container_name: beszel-agent
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
volumes:
|
||||
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
environment:
|
||||
LISTEN: ${PORT}
|
||||
KEY: ${KEY}
|
||||
```
|
||||
|
||||
And in `.env`:
|
||||
|
||||
```properties
|
||||
PORT=45876 # communication port between hub and remote agent
|
||||
KEY= # private key from Beszel when adding the system
|
||||
```
|
||||
|
||||
Deploy the stack on the remote server. Data will begin flowing into the web UI after a few seconds.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Expose Beszel with Swag
|
||||
---
|
||||
|
||||
::warning
|
||||
|
||||
Beszel does not support multi-factor authentication. Exposing it on the internet could compromise connected machines. Only do this if you're using a system like [Authentik](/serveex/security/authentik/). Otherwise, do not expose with SWAG—use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
If you want to access Beszel remotely from all your devices, expose it using Swag.
|
||||
|
||||
::note
|
||||
📋 __Prerequisite:__
|
||||
<br/><br/>
|
||||
You must have created a DNS subdomain like `beszel.mydomain.com` with a `CNAME` pointing to `mydomain.com`, and—unless you're using Cloudflare Zero Trust—you must have forwarded port `443` on your router to your server’s `443` port via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, edit Swag's compose file and add Beszel’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks:
|
||||
# ...
|
||||
|
||||
- beszel # network declared in the stack
|
||||
|
||||
networks:
|
||||
# ...
|
||||
beszel:
|
||||
name: beszel_default # actual external network name
|
||||
external: true
|
||||
```
|
||||
|
||||
Redeploy the stack and wait for Swag to become fully operational.
|
||||
|
||||
::note
|
||||
|
||||
We assume the network name is `beszel_default`. You can check connectivity by visiting Swag's dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
In Swag’s config folders, create `beszel.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Use [File Browser](/serveex/files/file-browser) to browse and edit files instead of terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/beszel.subdomain.conf
|
||||
```
|
||||
|
||||
Press `i` to enter insert mode and paste:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name beszel.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app beszel;
|
||||
set $upstream_port 8090;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, type `:x`, and hit `Enter` to save and exit.
|
||||
|
||||
That’s it—Beszel is now exposed!
|
||||
|
||||
::tip
|
||||
✨ You can protect this app with Authentik by opening `beszel.subdomain.conf` and removing the `#` in front of `include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`. Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: UpSnap
|
||||
description: Install UpSnap to remotely wake up machines on your local network via Wake-on-LAN, exposed with SWAG.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# UpSnap
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install UpSnap
|
||||
- Expose UpSnap with Swag
|
||||
::
|
||||
|
||||
[UpSnap](https://github.com/seriousm4x/UpSnap) is a container that allows you to remotely power on, shut down, or put your machines to sleep. It mainly uses Wake-On-Lan (WoL) over the network and offers advanced features.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── upsnap
|
||||
└── data
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `upsnap`, then copy and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
upsnap:
|
||||
container_name: upsnap
|
||||
image: ghcr.io/seriousm4x/upsnap:5
|
||||
network_mode: host
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
|
||||
- /docker/upsnap/data:/app/pb_data
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
- UPSNAP_SCAN_RANGE=${SCAN_RANGE}
|
||||
- UPSNAP_SCAN_TIMEOUT=500ms
|
||||
- UPSNAP_PING_PRIVILEGED=true
|
||||
dns:
|
||||
|
||||
- ${DNS}
|
||||
entrypoint: /bin/sh -c "./upsnap serve --http 0.0.0.0:8095"
|
||||
healthcheck:
|
||||
test: curl -fs "http://localhost:8095/api/health" || exit 1
|
||||
interval: 10s
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
upsnap:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Fill in the `.env`, for example:
|
||||
|
||||
```properties
|
||||
RANGE=192.168.1.0/24 # scans all devices on the local network with an IP between 192.168.0.1 and 192.168.1.255
|
||||
DNS=192.168.1.1 # DNS IP to resolve domain names, typically your router’s IP
|
||||
```
|
||||
|
||||
Deploy the container and go to `http://yourserverip:8095`. Just follow the steps to create your account!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing UpSnap with Swag
|
||||
---
|
||||
|
||||
::warning
|
||||
|
||||
UpSnap does not support multi-factor authentication. Exposing it on the internet could compromise connected machines. Do this only if you're using a multi-factor authentication system like [Authentik](/serveex/security/authentik/). Otherwise, avoid exposing it with SWAG and use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
You may want to access it remotely from all your devices. To do so, we'll expose UpSnap via Swag.
|
||||
|
||||
::note
|
||||
📋 __Beforehand:__
|
||||
<br/><br/>
|
||||
We assume you've created a subdomain in your [DNS zone](/general/networking/dns), such as `upsnap.yourdomain.com` with a `CNAME` to `yourdomain.com`. Also, unless you're using Cloudflare Zero Trust, you should have already forwarded port `443` from your router to port `443` on your server in your [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Go to Dockge, and edit the SWAG compose by adding the UpSnap network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to the custom network
|
||||
# ...
|
||||
|
||||
- upsnap # Network name declared in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
upsnap: # Network name declared in the stack
|
||||
name: upsnap_default # Actual name of the external network
|
||||
external: true # Indicates it's an external network
|
||||
```
|
||||
|
||||
Restart the stack by clicking "deploy" and wait for SWAG to be fully operational.
|
||||
|
||||
::note
|
||||
|
||||
Here we assume the network name for upsnap is `upsnap_default`. You can check the connection in the SWAG dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
In the Swag folders, create the file `upsnap.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate your files and edit documents instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/upsnap.subdomain.conf
|
||||
```
|
||||
Enter edit mode by pressing `i`, and paste the following configuration:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name upsnap.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app upsnap;
|
||||
set $upstream_port 8095;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Escape`, then save and exit by typing `:x` and pressing `Enter`.
|
||||
|
||||
And that’s it — you’ve exposed UpSnap!
|
||||
|
||||
::tip
|
||||
✨ You can protect this app with Authentik by opening `upsnap.subdomain.conf` and removing the `#` in front of `include /config/nginx/authentik-server.conf;`{lang=nginx} and `include /config/nginx/authentik-location.conf;`{lang=nginx}. Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Media & Seedbox
|
||||
icon: i-lucide-list-video
|
||||
@@ -0,0 +1,317 @@
|
||||
---
|
||||
title: Plex
|
||||
description: Install Plex Media Server with Tautulli on your homelab to stream movies and TV shows from anywhere on all your devices.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Plex
|
||||
|
||||
::note
|
||||
🎯 **Objectives:**
|
||||
|
||||
- Install Plex
|
||||
- Install Tautulli
|
||||
- Access media from outside your network
|
||||
::
|
||||
|
||||
[Plex](https://www.plex.tv/fr/) is a self-hosted video streaming platform for managing your movie or TV show library and playing them locally or remotely. Plex has apps for TV, Android, iOS, Windows, and macOS, allowing you to stream your library just like Netflix.
|
||||
|
||||
With *Plex Pass*, you can also organize and play your music content similar to Spotify, the difference being that it’s your content, hosted and streamed from your server.
|
||||
|
||||

|
||||
|
||||
We'll also install [Tautulli](https://docs.linuxserver.io/images/docker-tautulli/), a tool that provides detailed stats about Plex. As always, we'll use linuxserver.io images where possible.
|
||||
|
||||
- [More info on the Plex container](https://docs.linuxserver.io/images/docker-plex)
|
||||
- [More info on the Tautulli container](https://docs.linuxserver.io/images/docker-tautulli/)
|
||||
|
||||
::note
|
||||
|
||||
You’ll need to create a *Plex.tv* account. You don’t need to expose your Plex service; it will be accessible through the platform. Your Plex server will be manageable directly from your account.
|
||||
::
|
||||
|
||||
## Install Plex
|
||||
---
|
||||
Folder structure:
|
||||
```sh
|
||||
root
|
||||
├── docker
|
||||
│ ├── plex
|
||||
│ │ ├── compose.yml
|
||||
│ │ ├── .env
|
||||
│ │ ├── config
|
||||
│ │ └── transcode
|
||||
│ └── tautulli
|
||||
│ └── config
|
||||
└── media
|
||||
├── tvseries
|
||||
├── movies
|
||||
└── library
|
||||
```
|
||||
|
||||
Create the `movies`, `tvseries`, and `library` folders in `/media`:
|
||||
|
||||
```sh
|
||||
mkdir -p /media/movies /media/library /media/tvseries
|
||||
```
|
||||
|
||||
Open Dockge in your browser and click `compose`.
|
||||
Name the stack `plex` and add the following config:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
linuxserver_plex:
|
||||
image: ghcr.io/linuxserver/plex:amd64-latest
|
||||
container_name: plex
|
||||
network_mode: host
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- TZ=Europe/Paris
|
||||
- VERSION=docker
|
||||
volumes:
|
||||
|
||||
- /docker/plex/config:/config
|
||||
- /docker/plex/transcode:/transcode
|
||||
- /media:/media
|
||||
restart: unless-stopped
|
||||
mem_limit: 4096m
|
||||
mem_reservation: 2048m
|
||||
devices:
|
||||
|
||||
- /dev/dri:/dev/dri
|
||||
|
||||
tautulli:
|
||||
image: lscr.io/linuxserver/tautulli:latest
|
||||
container_name: tautulli
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/tautulli/config:/config
|
||||
ports:
|
||||
|
||||
- 8181:8181
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ Add the Watchtower label to each container to automate updates:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
plex:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
|
||||
tautulli:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Find your PUID and GUID by running:
|
||||
|
||||
```sh
|
||||
id username
|
||||
```
|
||||
|
||||
Fill in your `.env` file with the retrieved values, for example:
|
||||
|
||||
```properties
|
||||
PUID=1000
|
||||
GUID=1000
|
||||
```
|
||||
|
||||
Deploy the stack.
|
||||
|
||||
The local interface is available at `http://yourserverip:32400/web/index.html`.
|
||||
Tautulli is accessible at `http://yourserverip:8181`.
|
||||
|
||||
::warning
|
||||
|
||||
You must be on your local network during Plex's initial setup. Otherwise, the URL will redirect to your Plex account without detecting your server. A VPN won't help. If you have no choice, [you can handle the setup remotely via SSH tunnel](https://support.plex.tv/articles/200288586-installation/#toc-2).
|
||||
::
|
||||
|
||||
## Configure Plex
|
||||
---
|
||||
Plex offers a range of free movies/shows. After creating your account, I recommend disabling everything in the _Online Services_ section to keep your library clean.
|
||||
|
||||
Then go to the _Remote Access_ section and manually select a port (we’ll use `1234`). It's best not to use the default port.
|
||||
|
||||

|
||||
|
||||
- On your router, forward TCP port `1234` to port `32400` for your server’s IP using [NAT rules](/general/networking/nat).
|
||||
- Once done, return to Plex to verify that remote access is functional.
|
||||
|
||||
::caution
|
||||
|
||||
**If it fails:** check your firewall rules and allow port `32400` on your server.
|
||||
::
|
||||
|
||||
- If you have PlexPass and a GPU or iGPU, enable *hardware acceleration* in the _Transcoder_ section.
|
||||
- In _Settings > Library_, enable _Update my library automatically_.
|
||||
- In _Manage > Library_, add or edit libraries and point to `/media/movies` for movies and `/media/tvseries` for series.
|
||||
|
||||
And that’s it! You now have a working Plex server!
|
||||
|
||||
Simply add your media to `/media/movies` and `/media/tvseries` on your server. You can then install the Plex app on your devices and watch your favorite content locally or remotely.
|
||||
|
||||
::note
|
||||
|
||||
If your media is stored on a network disk (e.g. NAS or external hard drive over the network), refer to the [Samba mount guide](/general/networking/samba) so Plex can access it.
|
||||
::
|
||||
|
||||
## Expose Tautulli with Swag
|
||||
---
|
||||
You don’t need to expose Plex, as it's accessible via your Plex account on plex.tv.
|
||||
|
||||
However, you may want to expose Tautulli so you can view stats from a simple URL when you're not home.
|
||||
|
||||
::note
|
||||
|
||||
We assume you have the subdomain `tautulli.mydomain.com` with a `CNAME` pointing to `mydomain.com` in your [DNS zone](/general/networking/dns). And of course, [unless you use Cloudflare Zero Trust](/serveex/security/cloudflare), your box's port `443` must be forwarded to your server's port `443` in [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Go to Dockge and edit SWAG’s compose file by adding Tautulli’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Attach container to custom network
|
||||
# ...
|
||||
|
||||
- tautulli # Name of the declared network
|
||||
|
||||
networks: # Define the custom network
|
||||
# ...
|
||||
tautulli: # Declared network name
|
||||
name: tautulli_default # Actual external network name
|
||||
external: true # Marks it as externally defined
|
||||
```
|
||||
|
||||
Redeploy the stack and wait for SWAG to be fully operational.
|
||||
|
||||
::note
|
||||
|
||||
Here we assume the Tautulli network name is `tautulli_default`. You can check the connection by visiting SWAG’s dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
Copy and rename the file `tautulli.subdomain.conf.sample` to `tautulli.subdomain.conf`, then edit it:
|
||||
|
||||
::tip
|
||||
✨ **Tip:** Use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo cp /docker/swag/config/nginx/proxy-confs/tautulli.subdomain.conf.sample /docker/swag/config/nginx/proxy-confs/tautulli.subdomain.conf
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/tautulli.subdomain.conf
|
||||
```
|
||||
|
||||
Ensure the configuration matches the following. If needed, press `i` to edit:
|
||||
|
||||
```nginx
|
||||
## Version 2023/05/31
|
||||
# make sure that your tautulli container is named tautulli
|
||||
# make sure that your dns has a cname set for tautulli
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name tautulli.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app tautulli;
|
||||
set $upstream_port 8181;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location ~ (/tautulli)?/api {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app tautulli;
|
||||
set $upstream_port 8181;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location ~ (/tautulli)?/newsletter {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app tautulli;
|
||||
set $upstream_port 8181;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location ~ (/tautulli)?/image {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app tautulli;
|
||||
set $upstream_port 8181;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ You can protect this app with Authentik by removing the `#` before `include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`. Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
|
||||
Press `Esc` then save and quit by typing `:x`
|
||||
|
||||
Wait a few minutes, then open `http://tautulli.mydomain.com` in your browser.
|
||||
|
||||
::caution
|
||||
|
||||
**If it fails:** check your firewall rules.
|
||||
::
|
||||
|
||||
And you're done!
|
||||
@@ -0,0 +1,330 @@
|
||||
---
|
||||
title: Qbittorrent
|
||||
description: Install qBittorrent with Gluetun and ProtonVPN to download torrents securely behind a VPN on your self-hosted server.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Qbittorrent
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install and configure Qbittorrent
|
||||
- Securely connect to the BitTorrent network using Gluetun and Proton VPN
|
||||
::
|
||||
|
||||

|
||||
|
||||
To safely download your favorite media, we'll build a system using:
|
||||
|
||||
- [Qbittorrent](https://github.com/linuxserver/docker-qbittorrent) as the BitTorrent client
|
||||
- [Proton VPN Plus](https://protonvpn.com/torrenting), a VPN to secure your traffic. You need a subscription (promos available) to access the BitTorrent protocol. You can also use another VPN as long as it supports BitTorrent.
|
||||
- [Gluetun](https://github.com/qdm12/gluetun)
|
||||
- [Qbittorrent port update](https://codeberg.org/TechnoSam/qbittorrent-gluetun-port-update) to automatically update the VPN port (which changes regularly).
|
||||
- The [VueTorrent](https://github.com/gabe565/linuxserver-mod-vuetorrent) mod for a modern and intuitive UI.
|
||||
|
||||
Here’s the system we’ll set up:
|
||||
|
||||

|
||||
|
||||
## Configuration
|
||||
---
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
├── docker
|
||||
│ └── seedbox
|
||||
│ ├── qbittorrent
|
||||
│ │ └── config
|
||||
│ ├── gluetun
|
||||
│ ├── compose.yaml
|
||||
│ └── .env
|
||||
│
|
||||
└── media #linked to Plex and Qbittorrent
|
||||
├── downloads #generic downloads, selected in settings
|
||||
├── movies #used for downloading movies
|
||||
└── tvseries #used for downloading TV shows
|
||||
```
|
||||
|
||||
If not already done, create the `downloads` folder under `/media`:
|
||||
|
||||
```sh
|
||||
mkdir -P /media/downloads
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, and name the stack `seedbox`. Paste the following config:
|
||||
|
||||
```yaml
|
||||
|
||||
services:
|
||||
qbit:
|
||||
image: ghcr.io/linuxserver/qbittorrent:libtorrentv1
|
||||
container_name: qbittorrent
|
||||
restart: unless-stopped
|
||||
network_mode: service:gluetun
|
||||
mem_limit: 4g
|
||||
environment:
|
||||
|
||||
- DOCKER_MODS=ghcr.io/gabe565/linuxserver-mod-vuetorrent|ghcr.io/t-anc/gsp-qbittorent-gluetun-sync-port-mod:main
|
||||
- TZ=Europe/Paris
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- WEBUI_PORT=${UI_PORT}
|
||||
- GSP_GTN_API_KEY=${GSP_KEY}
|
||||
- GSP_QBT_USERNAME=${ID}
|
||||
- GSP_QBT_PASSWORD=${PW}
|
||||
volumes:
|
||||
|
||||
- /docker/seedbox/qbittorrent/config:/config
|
||||
- /media:/media
|
||||
depends_on:
|
||||
|
||||
- gluetun
|
||||
|
||||
gluetun:
|
||||
image: qmcgaw/gluetun:v3.41.3
|
||||
container_name: gluetun
|
||||
restart: unless-stopped
|
||||
mem_limit: 4g
|
||||
volumes:
|
||||
|
||||
- /docker/gluetun/config.toml:/gluetun/auth/config.toml:ro
|
||||
devices:
|
||||
|
||||
- /dev/net/tun:/dev/net/tun
|
||||
ports:
|
||||
|
||||
- ${UI_PORT}:5695 # Port de la web-ui
|
||||
- 8000:8000 # Port de controle de Gluetun
|
||||
cap_add:
|
||||
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
- VPN_SERVICE_PROVIDER=protonvpn
|
||||
- VPN_PORT_FORWARDING=on
|
||||
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
|
||||
- VPN_TYPE=wireguard
|
||||
- WIREGUARD_PRIVATE_KEY=${PR_KEY}
|
||||
- SERVER_COUNTRIES=France
|
||||
- PORT_FORWARD_ONLY=on
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the Watchtower label in each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
qbittorrent:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
gluetun:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Before editing the `.env` in Dockge, let's configure the download port update. Proton and most VPNs rotate the forwarding port, which must be communicated to Qbittorrent.
|
||||
|
||||
We’ve added the mod `ghcr.io/t-anc/gsp-qbittorent-gluetun-sync-port-mod` to the container.
|
||||
|
||||
We now need to allow the mod to fetch info from Gluetun, which only allows encrypted communication via its API.
|
||||
|
||||
Open a terminal to generate the authentication key:
|
||||
|
||||
```sh
|
||||
sudo docker run --rm qmcgaw/gluetun genkey
|
||||
```
|
||||
|
||||
Note the key, then create the `/docker/gluetun` folder:
|
||||
|
||||
```sh
|
||||
sudo mkdir /docker/gluetun
|
||||
```
|
||||
|
||||
Create the `config.toml` file:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/gluetun/config.toml
|
||||
```
|
||||
|
||||
Press `i` to edit and enter:
|
||||
|
||||
```toml
|
||||
[[roles]]
|
||||
name = "t-anc/GSP-Qbittorent-Gluetun-sync-port-mod"
|
||||
routes = ["GET /v1/portforward"]
|
||||
auth = "apikey"
|
||||
apikey = "your_key_here" # key you just generated
|
||||
```
|
||||
|
||||
Press `Esc` then type `:x` to save and exit.
|
||||
|
||||
In Dockge, fill in the variables in `.env`:
|
||||
|
||||
```properties
|
||||
PUID=
|
||||
GUID=
|
||||
UI_PORT=
|
||||
PR_KEY=
|
||||
GSP_KEY= # the key you generated and entered in config.toml
|
||||
ID=
|
||||
PW=
|
||||
```
|
||||
|
||||
Detailed info:
|
||||
|
||||
| Variable | Description | Example |
|
||||
|------------|-------------|---------|
|
||||
| `PUID` | User ID (`id yourusername`) | `1000` |
|
||||
| `GUID` | Group ID (`id yourusername`) | `1000` |
|
||||
| `UI_PORT` | Port for accessing the web UI | `5695` |
|
||||
| `PR_KEY` | Private key from Proton | `buKsjNHLyzKMM1qYnzOy4s7SHfly` |
|
||||
| `GSP_KEY` | Key you generated for port update | `MnBa47MeVmk7xiv` |
|
||||
| `ID` | Qbittorrent UI login username | `user` |
|
||||
| `PW` | Qbittorrent UI password | `password` |
|
||||
|
||||
## Deployment
|
||||
---
|
||||
Once done, deploy the container.
|
||||
|
||||
::warning
|
||||
|
||||
**Startup logs will show a temporary password for `admin` user**
|
||||
::
|
||||
|
||||
Login at `http://server-ip:5695` (or the port you set).
|
||||
|
||||
::caution
|
||||
|
||||
__If login fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
Change your username and password in the "webui" settings.
|
||||
|
||||
You're done! In Qbittorrent settings, under "Downloads", set `/media/downloads` as the default folder.
|
||||
|
||||
When adding a download, remember to select the proper directory so Plex can sync correctly (`/media/movies` or `/media/tvseries`). You can also automate this with categories and folders.
|
||||
|
||||
## Exposing the Web UI
|
||||
---
|
||||
|
||||
::warning
|
||||
|
||||
Qbittorrent does not support multi-factor authentication. Exposing it to the internet may put your system at risk. Only do this if you use MFA via [Authentik](/serveex/security/authentik/). Otherwise, don’t expose it with SWAG—use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
To start downloads from outside your home, without a VPN, you can expose the Qbittorrent web UI.
|
||||
|
||||
::note
|
||||
|
||||
We assume you have the subdomain `seedbox.mydomain.com` with a `CNAME` pointing to `mydomain.com` in [DNS zone](/general/networking/dns). And that port `443` on your router is forwarded to your server in [NAT rules](/general/networking/nat), unless you’re using Cloudflare Zero Trust.
|
||||
::
|
||||
|
||||
In Dockge, edit the SWAG compose file and add Gluetun’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks:
|
||||
# ...
|
||||
|
||||
- seedbox
|
||||
|
||||
networks:
|
||||
# ...
|
||||
seedbox:
|
||||
name: seedbox_default
|
||||
external: true
|
||||
```
|
||||
|
||||
Click "Deploy" and wait for SWAG to fully initialize.
|
||||
|
||||
::note
|
||||
|
||||
We assume the network name is `seedbox_default`. You can confirm by checking the SWAG dashboard at http://server-ip:81.
|
||||
::
|
||||
|
||||
Now create/edit `seedbox.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Terminal-free tip:__ use [File Browser](/serveex/files/file-browser) to edit files instead of using the terminal.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/seedbox.subdomain.conf
|
||||
```
|
||||
|
||||
Press `i` and paste the following config (check the port):
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name seedbox.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app gluetun;
|
||||
set $upstream_port 5555;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ You can secure this app with Authentik by uncommenting the `authentik-server.conf` and `authentik-location.conf` lines. Don’t forget to [create an app and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
|
||||
Press `Esc`, type `:x` to save and quit.
|
||||
|
||||
Wait a few minutes, then go to `https://seedbox.mydomain.com`—you should land on the Qbittorrent interface.
|
||||
|
||||
And that’s it! You now have a ready-to-use media center.
|
||||
|
||||

|
||||
@@ -0,0 +1,534 @@
|
||||
---
|
||||
title: Automation
|
||||
description: Automate media downloads with the Servarr stack — Radarr, Sonarr, Bazarr, Prowlarr, and Overseerr for movies and TV shows.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Servarr
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
Automate movie and TV show downloads using Radarr, Sonarr, Bazarr, Prowlarr, and Overseerr.
|
||||
::
|
||||
|
||||
[Servarr](https://wiki.servarr.com/) is a suite of applications developed to automate the downloading, updating, and management of media. Here, we'll focus on movies and TV shows with the goal of:
|
||||
|
||||
- Selecting a movie from a catalog through a web interface.
|
||||
- Sitting back and enjoying it on Plex a few minutes later.
|
||||
|
||||
Simple.
|
||||
|
||||

|
||||
|
||||
We’ll start by deploying the stack and then proceed to configure each app and understand how they work.
|
||||
|
||||
## Install the Apps
|
||||
---
|
||||
|
||||
### Docker Compose
|
||||
|
||||
Folder structure:
|
||||
|
||||
```sh
|
||||
root
|
||||
├── docker
|
||||
│ ├── plex
|
||||
│ │ ├── compose.yml
|
||||
│ │ ├── config
|
||||
│ │ └── transcode
|
||||
│ ├── tautulli
|
||||
│ │ └── config
|
||||
│ ├── sonarr
|
||||
│ │ └── config
|
||||
│ ├── radarr
|
||||
│ │ └── config
|
||||
│ ├── bazarr
|
||||
│ │ └── config
|
||||
│ ├── prowlarr
|
||||
│ │ └── config
|
||||
│ └── overseerr
|
||||
│ └── config
|
||||
└── media
|
||||
├── downloads
|
||||
├── tvseries
|
||||
├── movies
|
||||
└── library
|
||||
```
|
||||
|
||||
::warning
|
||||
|
||||
__Warning:__ Make sure to follow this file structure carefully, especially the `media` folder. This folder must be mounted **exactly the same way** in both the _Qbittorrent_ compose file (`/your/path/media:/media`) and the _arr_ applications.
|
||||
If not, the _arr_ apps may not recognize the path provided by Qbittorrent and will fail to create _hardlinks_.
|
||||
Without hardlinks, the _arr_ apps will copy the files instead—**doubling the space used** on your storage.
|
||||
::
|
||||
|
||||
Open Docker and your `plex` stack. Modify the compose file as follows:
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
linuxserver_plex:
|
||||
image: ghcr.io/linuxserver/plex:latest
|
||||
container_name: plex
|
||||
network_mode: host
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
- VERSION=docker
|
||||
- PLEX_CLAIM= #optional
|
||||
volumes:
|
||||
|
||||
- /docker/plex/config:/config
|
||||
- /docker/plex/transcode:/transcode #optional
|
||||
- ${MEDIA_PATH}:/media
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
restart: unless-stopped
|
||||
mem_limit: 4096m
|
||||
mem_reservation: 2048m
|
||||
devices:
|
||||
|
||||
- /dev/dri:/dev/dri
|
||||
|
||||
tautulli:
|
||||
image: lscr.io/linuxserver/tautulli:latest
|
||||
container_name: tautulli
|
||||
environment:
|
||||
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/tautulli/config:/config
|
||||
ports:
|
||||
|
||||
- 8181:8181
|
||||
restart: unless-stopped
|
||||
|
||||
sonarr:
|
||||
image: lscr.io/linuxserver/sonarr:latest
|
||||
container_name: sonarr
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/sonarr/config:/config
|
||||
- ${MEDIA_PATH}:/media
|
||||
ports:
|
||||
|
||||
- 8989:8989
|
||||
restart: unless-stopped
|
||||
|
||||
radarr:
|
||||
image: lscr.io/linuxserver/radarr:latest
|
||||
container_name: radarr
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/radarr/config:/config
|
||||
- ${MEDIA_PATH}:/media
|
||||
ports:
|
||||
|
||||
- 7878:7878
|
||||
restart: unless-stopped
|
||||
|
||||
prowlarr:
|
||||
image: lscr.io/linuxserver/prowlarr:latest
|
||||
container_name: prowlarr
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/prowlarr/data:/config
|
||||
ports:
|
||||
|
||||
- 9696:9696
|
||||
restart: unless-stopped
|
||||
|
||||
overseerr:
|
||||
image: lscr.io/linuxserver/overseerr:latest
|
||||
container_name: overseerr
|
||||
dns:
|
||||
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${PGID}
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/overseerr/config:/config
|
||||
ports:
|
||||
|
||||
- 5055:5055
|
||||
restart: unless-stopped
|
||||
|
||||
bazarr:
|
||||
image: lscr.io/linuxserver/bazarr:latest
|
||||
container_name: bazarr
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Europe/Paris
|
||||
volumes:
|
||||
|
||||
- /docker/bazarr/config:/config
|
||||
- ${MEDIA_PATH}:/media
|
||||
ports:
|
||||
|
||||
- 6767:6767
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ Add the Watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
plex:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
|
||||
tautulli:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Set your `.env` file with the variables below:
|
||||
|
||||
```properties
|
||||
PUID=
|
||||
GUID=
|
||||
MEDIA_PATH=
|
||||
```
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------------|-------------------------------------------------------------------------------------------------|-------------|
|
||||
| `PUID` | Set using your user info (check with `id yourusername`) | `1000` |
|
||||
| `GUID` | Same as above | `1000` |
|
||||
| `MEDIA_PATH` | Path to your media folder, here: `/media`. It must match the one used by Qbittorrent. | `/media` |
|
||||
|
||||
Deploy the stack.
|
||||
|
||||
### Configure Radarr
|
||||
---
|
||||
|
||||
Radarr queries your torrent sources and lets you define the type of releases to prioritize. It can also upgrade your movies if a better version is available.
|
||||
|
||||
Once deployed, visit `http://yourserverip:7878`.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
Create an account and choose *forms login*.
|
||||
|
||||
##### Add a *root folder*
|
||||
|
||||
- Go to *Settings > Media Management*.
|
||||
- Add a root folder and select `/media/movies`.
|
||||
|
||||
::warning
|
||||
|
||||
__Warning:__ If you already have movies in `movies` from Qbittorrent, do not let Radarr add them. Radarr might modify them, which could stop seeding in Qbittorrent.
|
||||
::
|
||||
|
||||
##### Configure Profiles
|
||||
|
||||
Go to *Settings > Profiles*. These are your default quality profiles. When you make a request, you're selecting one of these. For example, configure the “any” profile by unchecking everything except what is shown in the image and ordering them accordingly. This makes Radarr search for 4K REMUX first, then go down the list if unavailable.
|
||||
|
||||

|
||||
|
||||
##### Add Qbittorrent
|
||||
|
||||
In *Settings > Download Clients*, add Qbittorrent.
|
||||
|
||||
- Use your server IP as *Host* and port `5695` if following this guide.
|
||||
- Provide your Qbittorrent *Username* and *Password*.
|
||||
- Click *Test*.
|
||||
- If successful, click *Save*.
|
||||
|
||||
##### Connect to Plex
|
||||
|
||||
Go to *Settings > Connect*, add a new connection and choose *Plex Media Server*.
|
||||
|
||||
- Use `plex` or your server IP for *Host*.
|
||||
- Port: `32400`
|
||||
- Click the blue "authenticate with Plex.tv" button and log into Plex.
|
||||
- Press *Test*, then *Save* if successful.
|
||||
|
||||
##### Get API Key for Prowlarr and Overseerr
|
||||
|
||||
- Go to *Settings > General* and copy your *API Key* for later use.
|
||||
|
||||
### Configure Sonarr
|
||||
---
|
||||
|
||||
Sonarr queries torrent sources and defines what kind of TV series releases to prioritize. It also upgrades series when better versions are available.
|
||||
|
||||
- Visit `http://yourserverip:8989`.
|
||||
- Follow the same steps as for Radarr, but use `/media/tvseries` as the root folder.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
### Configure Prowlarr
|
||||
---
|
||||
|
||||
Prowlarr acts as a proxy to manage your torrent indexers and link them to Radarr and Sonarr.
|
||||
|
||||
Go to `http://yourserverip:9696` and create an account, using *forms login*.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
##### Add an Indexer
|
||||
|
||||
- Go to the *Indexers* section and add your torrent indexer.
|
||||
|
||||
##### Add Radarr and Sonarr
|
||||
|
||||
In *Settings > Apps*, add Radarr and Sonarr with the following details:
|
||||
|
||||
- Prowlarr Server: `http://prowlarr:9696` (or use server IP)
|
||||
- Sonarr / Radarr Server: `http://sonarr:8989` or `http://radarr:7878`
|
||||
- API Key: use the one copied from Radarr and Sonarr.
|
||||
- Click *Test*, then *Save* if all goes well.
|
||||
|
||||
### Configuring Bazarr
|
||||
---
|
||||
Bazarr is an app that automatically searches for the correct subtitles in your preferred languages for all the movies and TV shows added by Radarr and Sonarr.
|
||||
|
||||
Go to `http://yourserverip:6767`.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
Go to *Settings > General* and create a username and password using *forms login*.
|
||||
|
||||
#### Add a Language Profile
|
||||
|
||||
- In *Settings > Languages*, click the pink *Add new profile* button and name it.
|
||||
- Click the pink *Add Languages* button and add your preferred languages, e.g., *French* and *English*.
|
||||
- Save and exit.
|
||||
- At the bottom of the screen under *Default Language For Newly Added Show*, check both boxes and select the profile you just created.
|
||||

|
||||
|
||||
- Save using the button at the top of the screen.
|
||||
|
||||
#### Add Subtitle Providers
|
||||
|
||||
- In *Settings > Providers*, add your preferred providers, for example:
|
||||
|
||||

|
||||
|
||||
- Save using the button at the top of the screen.
|
||||
|
||||
#### Add Radarr and Sonarr
|
||||
|
||||
- Go to *Settings > Sonarr*
|
||||
- In *Address*, enter `sonarr` or your server's IP address.
|
||||
- In *Port*, enter `8989`.
|
||||
- In *API Key*, enter Sonarr’s API key.
|
||||
- Click *Test*.
|
||||
- Save using the button at the top of the screen.
|
||||
|
||||
Repeat the same steps for Radarr.
|
||||
|
||||
### Configuring Overseerr
|
||||
---
|
||||
|
||||
[Overseerr](https://overseerr.dev/) is an app that lets you browse a movie catalog and send requests to Sonarr and Radarr. Just browse movies or series, click *Request*, and the media will automatically be downloaded according to your Radarr or Sonarr settings. If the title hasn’t been released yet, it will be downloaded automatically when available. This way, episodes of a series appear in Plex without any manual intervention.
|
||||
|
||||

|
||||
|
||||
Go to `http://yourserverip:5055` and log in with your Plex account.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
#### Add Radarr and Sonarr
|
||||
|
||||
When prompted, add a Radarr server:
|
||||
|
||||
- Check *Default server*.
|
||||
- __Server name:__ Radarr
|
||||
- __Hostname or IP address:__ `radarr` or your server's IP
|
||||
- __Port:__ `7878`
|
||||
- __API Key:__ Radarr’s API key
|
||||
- Click *Test* at the bottom.
|
||||
|
||||
If the test succeeds, continue filling in the fields:
|
||||
|
||||
- __Quality Profile:__ the one you configured (e.g., `any`)
|
||||
- __Root Folder:__ the Plex folder. In our examples: `/media/movies`
|
||||
- __Minimum Availability:__ `Announced`. This allows requesting unreleased content and downloads it upon release.
|
||||
- Check all 3 boxes at the bottom.
|
||||
- Save and continue.
|
||||
|
||||
Now do the same for Sonarr:
|
||||
|
||||
- Check *Default server*.
|
||||
- __Server name:__ Sonarr
|
||||
- __Hostname or IP address:__ `sonarr` or your server's IP
|
||||
- __Port:__ `8989`
|
||||
- __API Key:__ Sonarr’s API key
|
||||
- Click *Test* at the bottom.
|
||||
|
||||
If the test succeeds, continue filling in the fields:
|
||||
|
||||
- __Quality Profile:__ the one you configured (e.g., `any`)
|
||||
- __Root Folder:__ the Plex folder. In our examples: `/media/tvseries`
|
||||
- __Language Profile:__ `Deprecated`
|
||||
- Check all 4 boxes at the bottom.
|
||||
- Save and continue.
|
||||
|
||||
And that’s it! Just request a movie or series, then check in qBittorrent or Radarr/Sonarr. Within a few minutes, your media will be available on Plex!
|
||||
|
||||
## Exposing Overseerr with SWAG
|
||||
---
|
||||
|
||||
It can be useful to expose Overseerr if you want to send requests from outside your network without a VPN, or if you've shared your Plex library with others and want them to have Overseerr access.
|
||||
|
||||
::note
|
||||
|
||||
We assume you have the subdomain `films.mydomain.com` with a `CNAME` pointing to `films.fr` in your [DNS zone](/general/networking/dns). And that [unless you’re using Cloudflare Zero Trust](/serveex/security/cloudflare), port `443` on your router is forwarded to port `443` on your server via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
Go to Dockge, edit the SWAG compose file, and add the Overseerr network, which is the same as Plex (since it’s in the Plex stack):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to a custom network
|
||||
# ...
|
||||
|
||||
- plex # Name of the network declared in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
plex: # Name of the declared network
|
||||
name: plex_default # Actual name of the external network
|
||||
external: true # Indicates it’s an external network
|
||||
```
|
||||
|
||||
Restart the stack by clicking “Deploy” and wait until SWAG is fully operational.
|
||||
|
||||
::note
|
||||
|
||||
Here we assume the Tautulli network is named `plex_default`. You can verify the connection works by visiting the SWAG dashboard at `http://yourserverip:81`.
|
||||
::
|
||||
|
||||
Create and edit the file `films.subdomain.conf`:
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ you can use [File Browser](/serveex/files/file-browser) to browse and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/films.subdomain.conf
|
||||
```
|
||||
|
||||
Enter insert mode by pressing `i`:
|
||||
|
||||
```nginx
|
||||
## Version 2024/07/16
|
||||
# make sure that your overseerr container is named overseerr
|
||||
# make sure that your dns has a cname set for overseerr
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name films.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app overseerr;
|
||||
set $upstream_port 5055;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location ~ (/overseerr)?/api {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app overseerr;
|
||||
set $upstream_port 5055;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Escape`, then type `:x` and press `Enter` to save and exit.
|
||||
|
||||
Wait a few minutes, then visit `http://films.mydomain.com` in your browser.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
And there you go, Overseerr is now publicly accessible!
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Cloud Drive & Photos
|
||||
icon: i-lucide-cloud-upload
|
||||
@@ -0,0 +1,166 @@
|
||||
---
|
||||
title: Immich
|
||||
description: Install Immich, a self-hosted alternative to Google Photos and iCloud with face recognition, geolocation, and multi-device sync.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Immich
|
||||
|
||||
::note
|
||||
🎯 __Goals:__ Install [Immich](https://immich.app/docs/overview/introduction) to manage your photos across all your devices.
|
||||
::
|
||||
|
||||
[Immich](https://immich.app/docs/overview/introduction) is a self-hosted photo and video management solution that replaces cloud services like Google Photos or iCloud. It offers powerful features like face recognition and geolocation.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── immich
|
||||
├── library
|
||||
├── compose.yaml
|
||||
└── .env
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `immich`, then copy and paste the latest `docker-compose.yml` [published here](https://github.com/immich-app/immich/blob/main/docker/docker-compose.yml).
|
||||
|
||||
::warning
|
||||
|
||||
__Warning__: Do not add the Watchtower label to the Immich stack. Immich evolves rapidly, and automatic updates may break your installation.
|
||||
::
|
||||
|
||||
Configure the `.env` file by copying the latest version [from here](https://github.com/immich-app/immich/blob/main/docker/example.env) and follow the comments in the file.
|
||||
|
||||
::note
|
||||
|
||||
If you're using a NAS or a network-shared drive via [Samba](/general/networking/samba/) to store your data, replace the value of `UPLOAD_LOCATION`{lang=properties} with the path to your shared folder.
|
||||
::
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ If your CPU/iGPU/GPU supports it, Immich can use hardware acceleration for video playback and image recognition. This can triple performance. Learn more about [Transcoding](https://immich.app/docs/features/hardware-transcoding/) and [Machine Learning](https://immich.app/docs/features/ml-hardware-acceleration).
|
||||
::
|
||||
|
||||
Deploy the container.
|
||||
|
||||
You're done! You can connect and follow the setup instructions at `http://yourserverip:2283`.
|
||||
|
||||
## Exposing Immich with SWAG
|
||||
---
|
||||
The main benefit of this setup is being able to access Immich remotely on all your devices. We'll expose Immich using SWAG.
|
||||
|
||||
::note
|
||||
📋 __Before you begin:__
|
||||
<br/><br/>
|
||||
We assume that you have a subdomain `immich.yourdomain.com` with a `CNAME` pointing to `yourdomain.com` in your [DNS zone](/general/networking/dns). Also, unless you're using [Cloudflare Zero Trust](/serveex/security/cloudflare), make sure port `443` on your router is forwarded to port `443` on your server via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, open the SWAG stack and edit the compose file to add Immich's network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to the custom network
|
||||
# ...
|
||||
|
||||
- immich # Network name defined in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
immich: # Network name defined in the stack
|
||||
name: immich_default # Actual external network name
|
||||
external: true # Indicates it's an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We're assuming Immich's network is named `immich_default`. You can check connectivity by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Restart the stack by clicking "deploy" and wait for SWAG to fully initialize.
|
||||
|
||||
In the SWAG folders, create a file named `immich.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
|
||||
__Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/immich.subdomain.conf
|
||||
```
|
||||
Press `i` to enter insert mode, then paste the following configuration:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name immich.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app immich_server;
|
||||
set $upstream_port 3001;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
|
||||
location ~ (/immich)?/api {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app immich_server;
|
||||
set $upstream_port 3001;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, type `:x`, then hit `Enter` to save and exit.
|
||||
|
||||
That's it! Immich is now accessible from the internet. Don’t forget to install the [iOS](https://apps.apple.com/us/app/immich/id1613945652) / [Android](https://play.google.com/store/apps/details?id=app.alextran.immich) apps to sync your devices.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can protect this app with Authentik natively by [following these instructions](https://docs.goauthentik.io/integrations/services/immich/).
|
||||
::
|
||||
@@ -0,0 +1,197 @@
|
||||
---
|
||||
title: Nextcloud
|
||||
description: Install Nextcloud to self-host your files, photos, and calendar — a privacy-friendly alternative to Google Drive, OneDrive, and iCloud.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Nextcloud
|
||||
|
||||
::note
|
||||
🎯 __Goals:__ Install [Nextcloud](https://nextcloud.com/) to manage your photos and files across all your devices.
|
||||
::
|
||||
|
||||
[Nextcloud](https://nextcloud.com/) is a self-hosted solution that allows you to access and synchronize your data across all your devices. It also includes collaboration features, calendar, and more. It’s a great alternative to services like Google Drive, iCloud, or OneDrive.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
::note
|
||||
|
||||
We'll be using the Docker image maintained by [LinuxServer.io](https://docs.linuxserver.io/images/docker-nextcloud/)
|
||||
::
|
||||
|
||||
File structure:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── nextcloud
|
||||
├── config
|
||||
├── data
|
||||
├── compose.yaml
|
||||
└── .env
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `nextcloud` and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
nextcloud:
|
||||
image: lscr.io/linuxserver/nextcloud:latest
|
||||
container_name: nextcloud
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- TZ=Etc/UTC
|
||||
volumes:
|
||||
|
||||
- /docker/nextcloud/config:/config
|
||||
- /docker/nextcloud/data:/data
|
||||
ports:
|
||||
|
||||
- ${PORT}:443
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
If you’re using a NAS or network-shared drive via [Samba](/general/networking/samba), replace `/docker/nextcloud/data` with the path to your shared folder.
|
||||
::
|
||||
|
||||
Find your `PUID` and `GUID` by running the following command:
|
||||
|
||||
```sh
|
||||
id username
|
||||
```
|
||||
|
||||
Then fill out the `.env` file with your preferred port and the values found above, for example:
|
||||
|
||||
```properties
|
||||
PUID=1000
|
||||
GUID=1000
|
||||
PORT=4545
|
||||
```
|
||||
|
||||
Deploy the stack and visit `http://yourserverip:4545` to complete the setup.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing Nextcloud with Swag
|
||||
---
|
||||
The goal of this setup is to access Nextcloud remotely from all your devices. We’ll use Swag to expose the app.
|
||||
|
||||
::note
|
||||
|
||||
We assume you have a subdomain `nextcloud.yourdomain.com` with a `CNAME` pointing to `yourdomain.com` in your [DNS zone](/general/networking/dns). And unless you’re using [Cloudflare Zero Trust](/serveex/security/cloudflare), port `443` on your router must be forwarded to port `443` on your server using [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to your SWAG stack and edit the compose to add Nextcloud's network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks:
|
||||
# ...
|
||||
|
||||
- nextcloud
|
||||
|
||||
networks:
|
||||
# ...
|
||||
nextcloud:
|
||||
name: nextcloud_default
|
||||
external: true
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume the Nextcloud network is named `nextcloud_default`. You can confirm connectivity by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Redeploy the stack and wait for SWAG to become fully operational.
|
||||
|
||||
In Nextcloud’s files, edit the `config.php` file:
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/nextcloud/config/www/nextcloud/config/config.php
|
||||
```
|
||||
|
||||
Enter edit mode with `i` and paste the following before the final `);`:
|
||||
|
||||
```php
|
||||
'trusted_proxies' => [gethostbyname('swag')],
|
||||
'overwrite.cli.url' => 'https://nextcloud.example.com/',
|
||||
'overwritehost' => 'nextcloud.example.com',
|
||||
'overwriteprotocol' => 'https',
|
||||
```
|
||||
|
||||
Also add your domain in the `array` section. It should look like this:
|
||||
|
||||
```php
|
||||
array (
|
||||
0 => '192.168.0.1:444', # This line may differ—don’t change it!
|
||||
1 => 'nextcloud.yourdomain.com', # Add your domain here
|
||||
),
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x` and hitting Enter.
|
||||
|
||||
In Swag’s folders, create the file `nextcloud.subdomain.conf`:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/nextcloud.subdomain.conf
|
||||
```
|
||||
|
||||
Enter edit mode with `i` and paste the following:
|
||||
|
||||
```nginx
|
||||
## Version 2024/04/25
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name nextcloud.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
location / {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app nextcloud;
|
||||
set $upstream_port 443;
|
||||
set $upstream_proto https;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
# Hide proxy response headers from Nextcloud that conflict with ssl.conf
|
||||
proxy_hide_header Referrer-Policy;
|
||||
proxy_hide_header X-Content-Type-Options;
|
||||
proxy_hide_header X-Frame-Options;
|
||||
proxy_hide_header X-XSS-Protection;
|
||||
|
||||
# Disable proxy buffering
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, save and exit with `:x` then Enter.
|
||||
|
||||
That’s it—you’ve exposed Nextcloud! Don’t forget to install [the desktop and mobile apps](https://nextcloud.com/install/).
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can natively protect this app with Authentik by [following these instructions](https://docs.goauthentik.io/integrations/services/nextcloud/).
|
||||
::
|
||||
@@ -0,0 +1,2 @@
|
||||
title: File & share
|
||||
icon: i-lucide-folder-tree
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
title: File Browser
|
||||
description: Install File Browser to browse and manage your server files from a web interface, exposed securely with SWAG.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# File Browser
|
||||
|
||||
::note
|
||||
🎯 __Objectives:__
|
||||
|
||||
- Install File Browser
|
||||
- Expose File Browser using Swag
|
||||
::
|
||||
|
||||
[File Browser](https://github.com/filebrowser/filebrowser) is a web-based interface that lets you access and edit the files on your server.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Open Dockge, click on `compose`, name the stack `filebrowser`, then copy and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
filebrowser:
|
||||
container_name: filebrowser
|
||||
volumes:
|
||||
|
||||
- /docker/filebrowser/config:/config/
|
||||
- /path/to/your/folders:/yourfolders #add your folders to browse as /docker:/docker for exemple
|
||||
ports:
|
||||
|
||||
- 8010:80
|
||||
image: filebrowser/filebrowser:s6
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the watchtower label to each container to automate updates.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
filebrowser:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Deploy the container and go to `http://yourserverip:8010`. That’s it—your File Browser web UI is up and running!
|
||||
|
||||
::caution
|
||||
|
||||
__If it doesn’t work:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing File Browser with Swag
|
||||
---
|
||||
|
||||
::warning
|
||||
|
||||
File Browser does not support multi-factor authentication. Exposing it publicly could put your systems at risk. Only do this if you’re using a secure authentication solution like [Authentik](/serveex/security/authentik/). Otherwise, do not expose it with SWAG—use a VPN like [Wireguard](/serveex/security/wireguard) instead.
|
||||
::
|
||||
|
||||
You may want to access File Browser remotely from all your devices. To do that, we’ll expose it through Swag.
|
||||
|
||||
::note
|
||||
|
||||
__Pre-requisite:__ We assume you've already created a subdomain like `files.yourdomain.com` in your [DNS zone](/general/networking/dns) pointing to `yourdomain.com` with a `CNAME`, and—unless you're using Cloudflare Zero Trust—have already forwarded port `443` on your router to port `443` on your server using [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add File Browser’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to the custom network
|
||||
# ...
|
||||
|
||||
- filebrowser # Name of the network declared in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
filebrowser: # Name of the network declared in the stack
|
||||
name: filebrowser_default # Actual name of the external network
|
||||
external: true # Specifies it's an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
Here, we assume the network name for File Browser is `filebrowser_default`. You can confirm the connection is working by accessing the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Restart the stack by clicking "deploy" and wait for SWAG to fully initialize.
|
||||
|
||||
In the Swag folders, create the file `files.subdomain.conf`.
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/files.subdomain.conf
|
||||
```
|
||||
|
||||
Enter insert mode by pressing `i`, and paste the following configuration:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name files.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app filebrowser;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit with `:x` followed by `Enter`.
|
||||
|
||||
That’s it—File Browser is now exposed!
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can protect this app with Authentik by opening `files.subdomain.conf` and uncommenting `include /config/nginx/authentik-server.conf;`{lang=nginx} and `include /config/nginx/authentik-location.conf;`{lang=nginx}. Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,211 @@
|
||||
---
|
||||
title: Pingvin
|
||||
description: Install Pingvin Share, a self-hosted file sharing platform to send files securely without relying on WeTransfer or Google Drive.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Pingvin
|
||||
|
||||
::note
|
||||
🎯 __Objectives:__
|
||||
|
||||
- Install Pingvin
|
||||
- Expose Pingvin
|
||||
::
|
||||
|
||||
[Pingvin](https://github.com/stonith404/pingvin-share) is a tool for quickly sharing files, similar to WeTransfer. Its many sharing options (password, expiration time, custom link, etc.) make it the ideal tool for sharing files quickly. Pingvin can also create _upload requests_, i.e. a shareable link you can send to someone so they can upload their files for you to retrieve.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Open Dockge, click `compose`, name the stack `pingvin`, then copy-paste this:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
pingvin-share:
|
||||
container_name: pingvin
|
||||
image: stonith404/pingvin-share
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
||||
- 3600:3000
|
||||
volumes:
|
||||
|
||||
- /docker/pingvin/data:/opt/app/backend/data
|
||||
- /docker/pingvin/data/img:/opt/app/frontend/public/img
|
||||
- /docker/pingvin/uploads:/opt/app/backend/uploads # path to the folder where you want to store files uploaded to pingvin. Change to your preference.
|
||||
depends_on:
|
||||
clamav:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
|
||||
- swag
|
||||
|
||||
clamav: #antivirus for the files
|
||||
restart: unless-stopped
|
||||
image: clamav/clamav
|
||||
```
|
||||
::note
|
||||
|
||||
From here on, we assume the network name for Swag is `swag_default`.
|
||||
::
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the watchtower label to each container to automate updates.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
pingvin-share:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
|
||||
clamav:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Deploy the container and go to `http://yourserverip:3600`. That's it—your Pingvin web UI instance is up and running!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing Pingvin with Swag
|
||||
---
|
||||
The whole point of a solution like this is being able to access it remotely, from all your devices. To do this, we'll expose Pingvin through Swag.
|
||||
|
||||
::note
|
||||
📋 __Prerequisite:__ <br/><br/>
|
||||
We assume you have the subdomain `pingvin.mydomain.com` with a `CNAME` pointing to `mydomain.com` in your [DNS zone](/general/networking/dns). And of course, [unless you're using Cloudflare Zero Trust](/serveex/security/cloudflare), port `443` on your router is forwarded to port `443` on your server via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add the pingvin network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to the custom network
|
||||
# ...
|
||||
|
||||
- pingvin # Name of the network declared in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
pingvin: # Name of the network declared in the stack
|
||||
name: pingvin_default # Actual name of the external network
|
||||
external: true # States that it's a network to look up externally
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
From here on, we assume the pingvin network name is `pingvin_default`. You can verify the connection is working by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Redeploy the stack by clicking "deploy" and wait for SWAG to be fully up.
|
||||
|
||||
In the Swag folders, create the `pingvin.subdomain.conf` file.
|
||||
|
||||
::tip
|
||||
|
||||
__Tip:__ you can use [File Browser](/serveex/files/file-browser) to browse your files and edit your documents instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/pingvin.subdomain.conf
|
||||
```
|
||||
Press `i` to enter edit mode and paste the configuration below:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name pingvin.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app pingvin;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Press `Escape`, then save and quit by typing `:x` and pressing `Enter`.
|
||||
|
||||
That's it, you've exposed Pingvin!
|
||||
|
||||
## Securing Pingvin with Authentik
|
||||
|
||||
You can protect this app natively with Authentik by following the instructions below.
|
||||
|
||||
1. In your Authentik admin area, create an OAuth2/OpenID provider.
|
||||
|
||||
2. Fill in each section as follows, replacing `mydomain.com` with your own domain. Copy the `Client ID` and `Client Secret` fields somewhere safe.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
3. Save and create a `pingvin` application as follows.
|
||||
|
||||

|
||||
|
||||
4. Save and go to your list of outposts. Add the pingvin provider to your outpost.
|
||||
|
||||
5. Leave Authentik, and go to Pingvin's admin interface.
|
||||
|
||||
6. In the _"OAuth"_ section, fill in the following fields:
|
||||
- `OpenID discovery URI` with `https://pingvin.mydomain.com/application/o/pingvin/.well-known/openid-configuration` (don't forget to replace `mydomain.com` with your own domain)
|
||||
- `OpenID username claim` with `preferred_username`
|
||||
- `OpenID client ID` with the ID you copied in step 2.
|
||||
- `OpenID client secret` with the token you copied in step 2.
|
||||
|
||||
That's it—from now on, when you log in to Pingvin, an "Open ID" button will be available below the login form.
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Developpement
|
||||
icon: i-lucide-code-xml
|
||||
@@ -0,0 +1,226 @@
|
||||
---
|
||||
title: Code-Server
|
||||
description: Install code-server to run VS Code in your browser from your homelab — mount folders and expose it securely with SWAG.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Code-Server
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install code-server
|
||||
- Mount folders into VS Code
|
||||
- Expose code-server with Swag
|
||||
::
|
||||
|
||||
[code-server](https://github.com/linuxserver/docker-code-server) is a container that lets you access [VS Code](https://code.visualstudio.com/) via a web UI in a Linux environment. It's literally VS Code and your projects in your pocket, available anywhere.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
::note
|
||||
|
||||
For this setup, we’ll use the [image maintained by LinuxServer.io](https://docs.linuxserver.io/images/docker-code-server/).
|
||||
::
|
||||
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
├── docker
|
||||
│ └── code-server
|
||||
│ └── config
|
||||
└── #any folder you want to mount in VS Code
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `code-server`, and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
code-server:
|
||||
image: lscr.io/linuxserver/code-server:latest
|
||||
container_name: code-server
|
||||
environment:
|
||||
|
||||
- PUID=${PUID}
|
||||
- PGID=${GUID}
|
||||
- TZ=Etc/UTC
|
||||
- HASHED_PASSWORD=${PW}
|
||||
volumes:
|
||||
|
||||
- /docker/code-server/config:/config
|
||||
# add folders to mount in VS Code
|
||||
# - /path/to/folder:/folder
|
||||
ports:
|
||||
|
||||
- 8443:8443
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ Add the Watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
code-server:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Choose a password and generate its hash:
|
||||
|
||||
```sh
|
||||
echo -n "yourpassword" | npx argon2-cli -e
|
||||
```
|
||||
|
||||
Save the result carefully. Find your PUID and GUID with:
|
||||
|
||||
```sh
|
||||
id yourusername
|
||||
```
|
||||
|
||||
Fill in the `.env` file with the values you found, for example:
|
||||
|
||||
```properties
|
||||
PW='$argon2i$v=19$m=4096,t=3,p=1$wST5QhBgk2lu1ih4DMuxvg$LS1alrVdIWtvZHwnzCM1DUGg+5DTO3Dt1d5v9XtLws4'
|
||||
PUID=1000
|
||||
GUID=1000
|
||||
```
|
||||
|
||||
::warning
|
||||
|
||||
__Note:__ Make sure to wrap the hash in single quotes `'`
|
||||
::
|
||||
|
||||
Deploy the container and go to `http://yourserverip:8443`. Voilà, your code-server instance is up and running in the browser!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Mount Folders
|
||||
---
|
||||
You can mount folders into VS Code by adding the relevant volumes in `compose.yaml` (or via Dockge), then redeploy the container.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
code-server:
|
||||
#...
|
||||
volumes:
|
||||
|
||||
- /path/to/folder:/folder
|
||||
```
|
||||
Once inside VS Code, you'll have access to the mounted folder.
|
||||
|
||||
## Expose code-server with Swag
|
||||
---
|
||||
The whole point of such a solution is to access it remotely from any device. To do this, we’ll expose code-server via Swag.
|
||||
|
||||
::note
|
||||
|
||||
__Preliminary:__ We assume you’ve created a subdomain like `code.yourdomain.com` with a `CNAME` pointing to `yourdomain.com` in your [DNS zone](/general/networking/dns), and—unless you're using [Cloudflare Zero Trust](/serveex/security/cloudflare)—that you’ve forwarded port `443` from your router to port `443` on your server using [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add code-server’s network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to a custom network
|
||||
# ...
|
||||
|
||||
- code-server # Name of the network defined in the stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
code-server: # Name of the network defined in the stack
|
||||
name: code-serveur # Actual name of the external network
|
||||
external: true # Indicates it’s an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume the network name is `code-server_default`. You can verify that the connection works by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Redeploy the stack by clicking “deploy” and wait until SWAG is fully operational.
|
||||
|
||||
Inside the Swag config folders, create the file `code.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/code.subdomain.conf
|
||||
```
|
||||
|
||||
Enter insert mode with `i` and paste the following configuration:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name code.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app code-server;
|
||||
set $upstream_port 8443;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x` and pressing `Enter`.
|
||||
|
||||
That’s it — code-server is now exposed!
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can protect this app with Authentik by opening `code.subdomain.conf` and uncommenting the lines `include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`. Don’t forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
title: Gitea
|
||||
description: Install Gitea, a lightweight self-hosted Git service to manage your code repositories privately on your own server.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Gitea
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install Gitea
|
||||
- Expose Gitea using Swag
|
||||
::
|
||||
|
||||
[Gitea](https://about.gitea.com/) is a self-hosted DevOps platform that allows you to manage repositories much like GitHub, but on your own infrastructure.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── gitea
|
||||
└── data
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `gitea`, and paste the following content:
|
||||
|
||||
```yaml
|
||||
---
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
services:
|
||||
server:
|
||||
image: gitea/gitea:1.22.0
|
||||
container_name: gitea
|
||||
environment:
|
||||
|
||||
- USER_UID=${UID}
|
||||
- USER_GID=${GID}
|
||||
- TZ=Europe/Paris
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
|
||||
- gitea
|
||||
volumes:
|
||||
|
||||
- ./data:/data
|
||||
ports:
|
||||
|
||||
- 3333:3000
|
||||
- 222:22
|
||||
```
|
||||
|
||||
Fill out the `.env` file with the required information, for example:
|
||||
|
||||
```properties
|
||||
UID=1000
|
||||
GID=1000
|
||||
```
|
||||
|
||||
Deploy the container and go to `http://yourserverip:3333`. Your Gitea instance is now up and running!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing Gitea with Swag
|
||||
---
|
||||
The benefit of this setup is being able to access it remotely from any of your devices. To do so, we’ll expose Gitea through Swag.
|
||||
|
||||
::note
|
||||
|
||||
__Prerequisite:__ We assume you have created a subdomain such as `gitea.yourdomain.com` in your [DNS zone](/general/networking/dns) with `CNAME` pointing to `yourdomain.com`, and [unless you're using Cloudflare Zero Trust](/serveex/security/cloudflare), you have already forwarded port `443` from your router to your server’s port `443` in the [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file by adding Gitea's network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connect the container to the custom network
|
||||
# ...
|
||||
|
||||
- gitea # Name of the declared network
|
||||
|
||||
networks: # Define the custom network
|
||||
# ...
|
||||
gitea: # Name of the declared network
|
||||
name: gitea_default # Actual external network name
|
||||
external: true # Indicates it's an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume the Gitea network name is `gitea_default`. You can verify connectivity by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Redeploy the stack by clicking "Deploy" and wait until SWAG is fully operational.
|
||||
|
||||
Inside the Swag folders, create the file `gitea.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/gitea.subdomain.conf
|
||||
```
|
||||
Press `i` to enter edit mode and paste the configuration below:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name gitea.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app gitea;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location ~ (/gitea)?/info/lfs {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app gitea;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x` and hitting `Enter`.
|
||||
|
||||
Now open the `app.ini` file from the container's file system:
|
||||
|
||||
```sh
|
||||
sudo vi /docker/gitea/data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
Press `i` to edit, then modify the server section with your domain information:
|
||||
|
||||
```properties
|
||||
[server]
|
||||
DOMAIN = gitea.yourdomain.com
|
||||
SSH_DOMAIN = gitea.yourdomain.com
|
||||
ROOT_URL = https://gitea.yourdomain.com/
|
||||
```
|
||||
|
||||
Press `Esc`, save and exit with `:x`, then restart the container.
|
||||
|
||||
And that’s it! Gitea is now exposed to the web.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can natively protect this app with Authentik by [following these instructions](https://docs.goauthentik.io/integrations/services/gitea/).
|
||||
::
|
||||
@@ -0,0 +1,167 @@
|
||||
---
|
||||
title: IT Tools
|
||||
description: Install IT Tools, a self-hosted collection of handy utilities for developers — converters, encoders, formatters, and more.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# IT Tools
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install IT Tools
|
||||
- Expose IT Tools with Swag
|
||||
::
|
||||
|
||||
[IT Tools](https://github.com/CorentinTh/it-tools) is a container exposing a web page that provides access to a wide range of development tools.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `it-tools`, and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
it-tools:
|
||||
container_name: it-tools
|
||||
restart: unless-stopped
|
||||
image: corentinth/it-tools:latest
|
||||
ports:
|
||||
|
||||
- 3222:80
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the Watchtower label to each container to enable automatic updates.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
it-tools:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Deploy the container and visit `http://yourserverip:3222`. That’s it, your IT Tools web UI instance is up and running!
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Expose IT Tools with Swag
|
||||
---
|
||||
You might want to access it remotely on all your devices. To do that, we'll expose IT Tools using Swag.
|
||||
|
||||
::note
|
||||
|
||||
__Pre-requisite:__ We assume you’ve created a subdomain like `tools.yourdomain.com` in your [DNS zone](/general/networking/dns) with `CNAME` set to `yourdomain.com`. Also, unless you’re using [Cloudflare Zero Trust](/serveex/security/cloudflare), make sure you’ve already forwarded port `443` from your router to port `443` on your server in the [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add the IT Tools network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects the container to the custom network
|
||||
# ...
|
||||
|
||||
- it-tools # Network name as defined in the IT Tools stack
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
it-tools: # Network name as defined in the IT Tools stack
|
||||
name: it-tools_default # Actual name of the external network
|
||||
external: true # Indicates it's an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume the IT Tools network is named `it-tools_default`. You can check connectivity by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
::note
|
||||
|
||||
We also assume the SWAG network is named `swag_default`.
|
||||
::
|
||||
|
||||
Restart the stack by clicking "deploy" and wait for SWAG to be fully operational.
|
||||
|
||||
Inside the Swag folders, create the file `tools.subdomain.conf`.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/tools.subdomain.conf
|
||||
```
|
||||
|
||||
Enter edit mode by pressing `i` and paste the configuration below:
|
||||
|
||||
```nginx
|
||||
## Version 2023/12/19
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name tools.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app it-tools;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x` and pressing `Enter`.
|
||||
|
||||
And that’s it — IT Tools is now exposed!
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can secure this app with Authentik by opening `tools.subdomain.conf` and uncommenting the lines `include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`. Don’t forget to [create an application and a provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
@@ -0,0 +1,2 @@
|
||||
title: Useful Apps
|
||||
icon: i-lucide-award
|
||||
@@ -0,0 +1,304 @@
|
||||
---
|
||||
title: Adguard Home
|
||||
description: Install AdGuard Home for network-wide ad and tracker blocking with DNS-over-HTTPS, client management, and custom filtering rules.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Adguard Home
|
||||
|
||||
::note
|
||||
🎯 __Goals:__
|
||||
|
||||
- Install and deploy Adguard
|
||||
- Expose Adguard
|
||||
- Secure DNS queries with SSL/TLS
|
||||
- Configure client devices
|
||||
::
|
||||
|
||||
[AdGuard Home](https://github.com/AdguardTeam/AdGuardHome) is a DNS server that blocks ads and tracking at the system level. Once configured, it will protect ALL your home devices without the need for any client-side software.
|
||||
|
||||
It works as a DNS server that redirects tracking domains to a “black hole,” preventing your devices from connecting to them.
|
||||
|
||||
In practice, once it's in place, all you need to do is set your devices to use Adguard as their DNS server.
|
||||
|
||||
**Quick reminder of how DNS works:**
|
||||
|
||||
When you visit a site or use an app, it makes requests to various domains to load content—ads in particular. Your device doesn’t know the IP addresses of these domains, so it contacts a _Domain Name Server_ (DNS), which returns the current IP address.
|
||||
|
||||
By default, your device uses your ISP's DNS server, which is usually configured in your router or, for mobile devices, at the carrier’s CGNAT level. You can change this in your browser settings, your device’s system settings, or even directly in your router, depending on your ISP.
|
||||
|
||||
Adguard will act as a middleman between your device and the upstream DNS servers. If you configure your devices to use Adguard:
|
||||
|
||||
- If the domain is not in a blocklist, Adguard queries the upstream DNS servers and returns the correct IP to your device.
|
||||
- If the domain *is* in a blocklist, Adguard will block the request and return nothing, so the associated content won’t load.
|
||||
|
||||
This is how ads and malicious domains are blocked—Adguard blocks only the bad domains, allowing the rest of the page to load normally.
|
||||
|
||||

|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── adguard
|
||||
├── confdir
|
||||
├── workdir
|
||||
├── compose.yaml
|
||||
└── .env
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We will also mount the `/docker/swag/config/etc/letsencrypt` folder to access Swag's SSL certificate.
|
||||
::
|
||||
|
||||
Open Dockge and click `compose`
|
||||
|
||||
Name the stack `adguardhome` and paste the configuration below:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
adguardhome:
|
||||
container_name: adguard
|
||||
image: adguard/adguardhome
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
|
||||
- 53:53/udp
|
||||
- 8080:80/tcp
|
||||
- 4443:443/tcp
|
||||
- 853:853/tcp
|
||||
- 3000:3000/tcp
|
||||
volumes:
|
||||
|
||||
- /docker/adguardhome/confdir:/opt/adguardhome/conf
|
||||
- /docker/adguardhome/workdir:/opt/adguardhome/work
|
||||
- /docker/swag/config/etc/letsencrypt:/swag-ssl:ro
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the watchtower label to each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
adguardhome:
|
||||
# ...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Deploy the stack.
|
||||
|
||||
Go to `http://yourserverip:3000` and follow the setup instructions.
|
||||
|
||||
That’s it! Adguard is deployed.
|
||||
|
||||
## Exposing AdGuard with SWAG
|
||||
---
|
||||
To make AdGuard usable from outside your home network, you need to expose it.
|
||||
|
||||
::note
|
||||
|
||||
__Prerequisites:__ We assume you've created a subdomain like `adguard.mydomain.com` in your [DNS zone](/general/networking/dns) with a `CNAME` pointing to `mydomain.com`, and that you’ve already forwarded port `443` from your router to port `443` on your server in your [NAT rules](/general/networking/nat). Also forward port `53` and port `853` to your server. These ports are used to route DNS requests.
|
||||
::
|
||||
|
||||
::warning
|
||||
|
||||
Do not use Cloudflare tunnels to expose AdGuard, and make sure any proxying is disabled.
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add the AdGuard network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connect the container to the custom network
|
||||
# ...
|
||||
|
||||
- adguard # Name of the network declared in the stack
|
||||
|
||||
networks: # Define the custom network
|
||||
# ...
|
||||
adguard: # Name of the network declared in the stack
|
||||
name: adguard_default # Actual name of the external network
|
||||
external: true # Specifies that this is an external network
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We assume here that the AdGuard network is named `adguard_default`. You can verify the connection is working by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Restart the stack by clicking "Deploy" and wait for SWAG to be fully operational.
|
||||
|
||||
Create and open the file `adguard.subdomain.conf`
|
||||
|
||||
::tip
|
||||
✨ __Tip for terminal haters:__
|
||||
You can use [File Browser](/serveex/files/file-browser) to browse and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/adguard.subdomain.conf
|
||||
```
|
||||
|
||||
Edit the file by pressing `i` and then pasting the configuration below:
|
||||
|
||||
```nginx
|
||||
## Version 2023/05/31
|
||||
# make sure that your adguard container is named adguard
|
||||
# make sure that your dns has a cname set for adguard
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name adguard.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
#if ($lan-ip = yes) { set $geo-whitelist yes; }
|
||||
#if ($geo-whitelist = no) { return 404; }
|
||||
if ($geo-blacklist = no) { return 404; }
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth (requires ldap-server.conf in the server block)
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-server.conf in the server block)
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-server.conf in the server block)
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app adguard;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location /control {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app adguard;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
|
||||
location /dns-query {
|
||||
# to properly use this please set `allow_unencrypted_doh: true` and `force_https: false` in adguard
|
||||
# see https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#configuration-file
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app adguard;
|
||||
set $upstream_port 3000;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__
|
||||
<br/><br/>
|
||||
You can protect this app with Authentik by opening `adguard.subdomain.conf` and removing the `#` in front of `include /config/nginx/authentik-server.conf;`{lang=nginx} and `include /config/nginx/authentik-location.conf;`{lang=nginx}. Don’t forget to [create an application and a provider in Authentik](/serveex/security/authentik/#protéger-une-app-par-reverse-proxy). You’ll need to exclude the URL `https://adguard.mydomain.com/dns-query` from authentication:
|
||||
|
||||
- Edit the AdGuard provider
|
||||
- Under *Advanced Protocol Settings > Authenticated Paths*, enter `^/dns-query`
|
||||
::
|
||||
|
||||
Press `Esc`, then save and exit by typing `:x`
|
||||
|
||||
And that's it! AdGuard is now exposed!
|
||||
|
||||
## Configure SSL/TLS Encryption
|
||||
---
|
||||
Encryption is essential if you want to keep your queries to AdGuard private. Encrypting your queries ensures that no one—not even your ISP—can see your history. It also ensures that only your server can respond to you.
|
||||
|
||||
To configure encryption:
|
||||
|
||||
- Go to _Settings_ then _Encryption_.
|
||||
- Set the options as follows:
|
||||
|
||||

|
||||
|
||||
- Below, in the _Certificates_ section, check _Use file path for certificate_
|
||||
- In the input field, enter `/swag-ssl/live/mydomain.com/fullchain.pem`, replacing `mydomain.com` with your actual domain.
|
||||
- For _Private Key_, check _Use file path for private key_
|
||||
- In the input field, enter `/swag-ssl/live/mydomain.com/privkey.pem`, replacing `mydomain.com` accordingly.
|
||||
- Save
|
||||
|
||||
Done! Your future DNS queries are now protected!
|
||||
|
||||
## Configure Devices
|
||||
---
|
||||
You have several options (which you can combine) to configure your devices.
|
||||
### Secure the Local Network
|
||||
You can secure your local network with AdGuard by configuring your router to direct all DNS queries by default to AdGuard instead of your ISP’s DNS. Note: your router must allow DNS changes (Orange routers do not).
|
||||
|
||||
This option is usually in the _DHCP_ settings. Make sure to add a fallback DNS server such as:
|
||||
|
||||
- Cloudflare: `1.1.1.1`
|
||||
- Google: `8.8.8.8`
|
||||
|
||||
Without this, if your server goes down, your devices will lose internet access.
|
||||
|
||||
::note
|
||||
|
||||
Some devices may have a separate DNS configured and may not use the router’s DNS.
|
||||
::
|
||||
|
||||
### Force a Browser to Use AdGuard
|
||||
|
||||
In your browser, you can configure a DNS to force it to use AdGuard Home.
|
||||
In the settings, specify the address `https://adguard.mydomain.com/dns-query`
|
||||
|
||||
### Configure AdGuard at the System Level on Windows
|
||||
|
||||
In Windows, you need to configure AdGuard for each network adapter you want to use.
|
||||
|
||||
- Go to _Home > Network & Internet_, then select the network adapter to modify
|
||||
- Click _Edit DNS_ (sometimes under _Hardware Properties_)
|
||||
- Choose `Manual`
|
||||
- Enable IPv4
|
||||
- Enter your server’s public IP (the one accessible from the internet)
|
||||
- Enable _DNS over HTTPS (manual template)_
|
||||
- Disable _Fallback to plaintext_
|
||||
- Save
|
||||
|
||||
All programs using that network adapter will now be filtered by AdGuard.
|
||||
|
||||
## Add Filters
|
||||
---
|
||||
|
||||
- Go to the settings and change the filters.
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
title: Vaultwarden
|
||||
description: Install Vaultwarden, a self-hosted Bitwarden-compatible password manager to replace Google or Apple password managers across all your devices.
|
||||
---
|
||||
|
||||
|
||||
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
||||
# Vaultwarden
|
||||
|
||||
::note
|
||||
🎯 __Goals:__ Install [Vaultwarden](https://github.com/dani-garcia/vaultwarden) to manage your passwords across all your devices (a replacement for Google or Apple password managers).
|
||||
::
|
||||
|
||||

|
||||
|
||||
[Vaultwarden](https://github.com/dani-garcia/vaultwarden) is a password management solution (generation, autofill...) that you can host directly on your server. This replaces managers like Google, Apple, or Keepass. Vaultwarden synchronizes your passwords across all your devices with end-to-end encryption.
|
||||
|
||||
Vaultwarden is a fork of [Bitwarden](https://bitwarden.com/fr-fr/help/).
|
||||
|
||||
## Installation
|
||||
---
|
||||
Folder structure:
|
||||
|
||||
```sh
|
||||
root
|
||||
└── docker
|
||||
└── vaultwarden
|
||||
├── data
|
||||
├── compose.yaml
|
||||
└── .env
|
||||
```
|
||||
|
||||
Open Dockge, click on `compose`, name the stack `vaultwarden`, and paste the following:
|
||||
|
||||
```yaml
|
||||
---
|
||||
services:
|
||||
vaultwarden:
|
||||
container_name: vaultwarden
|
||||
image: vaultwarden/server:latest
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
|
||||
- .env
|
||||
volumes:
|
||||
|
||||
- ./data/:/data/
|
||||
ports:
|
||||
|
||||
- 3050:80
|
||||
environment:
|
||||
|
||||
- DOMAIN=${URL}
|
||||
- LOGIN_RATELIMIT_MAX_BURST=10
|
||||
- LOGIN_RATELIMIT_SECONDS=60
|
||||
- ADMIN_RATELIMIT_MAX_BURST=10
|
||||
- ADMIN_RATELIMIT_SECONDS=60
|
||||
- ADMIN_TOKEN=${TOKEN}
|
||||
- SENDS_ALLOWED=true
|
||||
- EMERGENCY_ACCESS_ALLOWED=true
|
||||
- WEB_VAULT_ENABLED=true
|
||||
- SIGNUPS_ALLOWED=false
|
||||
- SIGNUPS_VERIFY=true
|
||||
- SIGNUPS_VERIFY_RESEND_TIME=3600
|
||||
- SIGNUPS_VERIFY_RESEND_LIMIT=5
|
||||
```
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Add the Watchtower label in each container to automate updates
|
||||
|
||||
```yaml
|
||||
services:
|
||||
vaultwarden:
|
||||
#...
|
||||
labels:
|
||||
|
||||
- com.centurylinklabs.watchtower.enable=true
|
||||
```
|
||||
::
|
||||
|
||||
Next, generate a password hash to put in the `TOKEN` variable in `.env`:
|
||||
|
||||
```sh
|
||||
echo -n 'yourpassword' | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4
|
||||
```
|
||||
|
||||
Copy the result securely.
|
||||
|
||||
In the `.env` file, enter the following variables:
|
||||
|
||||
```properties
|
||||
URL=
|
||||
TOKEN=
|
||||
```
|
||||
|
||||
| Variable | Value | Example |
|
||||
|----------|-------|---------|
|
||||
| `URL` | The URL of your Vaultwarden server | `https://vault.yourdomain.com` |
|
||||
| `TOKEN` | The token you previously copied | `'$argon2id$v=19$m=65540,t=3,p=4$bXBGME...` |
|
||||
|
||||
Then deploy the container.
|
||||
|
||||
Recently, Vaultwarden requires SSL to be accessed, which prevents access via a local IP. We'll expose it with SWAG, which provides an SSL certificate.
|
||||
|
||||
::caution
|
||||
|
||||
__If it fails:__ check your firewall rules.
|
||||
::
|
||||
|
||||
## Exposing Vaultwarden with SWAG
|
||||
---
|
||||
The main benefit of Vaultwarden is being able to access it remotely from any device. We'll expose it through [SWAG](/serveex/core/swag).
|
||||
|
||||
::note
|
||||
✨ __Before you start:__ Make sure you've created a DNS subdomain like `vault.yourdomain.com` with `CNAME` pointing to `yourdomain.com` and (unless using Cloudflare Zero Trust) that you've forwarded port `443` from your router to your server's `443` via [NAT rules](/general/networking/nat).
|
||||
::
|
||||
|
||||
In Dockge, go to the SWAG stack and edit the compose file to add the Vaultwarden network:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
swag:
|
||||
container_name: # ...
|
||||
# ...
|
||||
networks: # Connects container to custom network
|
||||
# ...
|
||||
|
||||
- vaultwarden # Name of the declared network
|
||||
|
||||
networks: # Defines the custom network
|
||||
# ...
|
||||
vaultwarden: # Name of the declared network
|
||||
name: vaultwarden_default # Actual name of the external network
|
||||
external: true
|
||||
```
|
||||
|
||||
::note
|
||||
|
||||
We're assuming the network name is `vaultwarden_default`. You can check connectivity by visiting the SWAG dashboard at http://yourserverip:81.
|
||||
::
|
||||
|
||||
Restart the stack by clicking "Deploy" and wait for SWAG to be fully operational.
|
||||
|
||||
In SWAG's config folder, create the file `vault.subdomain.conf`:
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ Use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using terminal commands.
|
||||
::
|
||||
|
||||
```sh
|
||||
sudo vi /docker/swag/config/nginx/proxy-confs/vault.subdomain.conf
|
||||
```
|
||||
|
||||
Press `i` to edit, and paste the following configuration:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
|
||||
server_name vault.*;
|
||||
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
client_max_body_size 128M;
|
||||
|
||||
# enable for ldap auth (requires ldap-location.conf in the location block)
|
||||
#include /config/nginx/ldap-server.conf;
|
||||
|
||||
# enable for Authelia (requires authelia-location.conf in the location block)
|
||||
#include /config/nginx/authelia-server.conf;
|
||||
|
||||
# enable for Authentik (requires authentik-location.conf in the location block)
|
||||
#include /config/nginx/authentik-server.conf;
|
||||
|
||||
location / {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app vaultwarden;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
|
||||
location ~ ^(/vaultwarden)?/admin {
|
||||
# enable the next two lines for http auth
|
||||
#auth_basic "Restricted";
|
||||
#auth_basic_user_file /config/nginx/.htpasswd;
|
||||
|
||||
# enable for ldap auth
|
||||
#include /config/nginx/ldap-location.conf;
|
||||
|
||||
# enable for Authelia
|
||||
#include /config/nginx/authelia-location.conf;
|
||||
|
||||
# enable for Authentik
|
||||
#include /config/nginx/authentik-location.conf;
|
||||
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app vaultwarden;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
|
||||
location ~ (/vaultwarden)?/api {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app vaultwarden;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
|
||||
location ~ (/vaultwarden)?/notifications/hub {
|
||||
include /config/nginx/proxy.conf;
|
||||
include /config/nginx/resolver.conf;
|
||||
set $upstream_app vaultwarden;
|
||||
set $upstream_port 80;
|
||||
set $upstream_proto http;
|
||||
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Press `Esc`, then type `:x` and press `Enter` to save and exit.
|
||||
|
||||
And there you go — Vaultwarden is now exposed! Visit `https://vault.yourdomain.com/admin` to access the admin panel and paste the password you specified when generatique the `ADMIN_TOKEN`. For more information, see the [Bitwarden documentation](https://bitwarden.com/help/).
|
||||
|
||||
Don't forget to install Bitwarden browser extensions (they work with Vaultwarden) for [Chrome](https://chromewebstore.google.com/detail/gestionnaire-de-mots-de-p/nngceckbapebfimnlniiiahkandclblb) and [Firefox](https://addons.mozilla.org/fr/firefox/addon/bitwarden-password-manager/), as well as [iOS](https://apps.apple.com/fr/app/bitwarden/id1137397744) and [Android](https://play.google.com/store/apps/details?id=com.x8bit.bitwarden&hl=fr) apps to sync your passwords.
|
||||
|
||||
::tip
|
||||
✨ __Tip:__ You can protect this app with Authentik by opening `tools.subdomain.conf` and removing the `#` in front of `include /config/nginx/authentik-server.conf;` and `include /config/nginx/authentik-location.conf;`. Don't forget to [create an application and provider in Authentik](/serveex/security/authentik#protecting-an-app-via-reverse-proxy).
|
||||
::
|
||||
Reference in New Issue
Block a user