From a6b95f49de26da35b8d333386d29499f225fbb34 Mon Sep 17 00:00:00 2001
From: Djeex
+
+ The CPU (Central Processing Unit) is the computer's calculator. It processes most software tasks. Modern CPUs have multiple cores, often with virtual threads, to better handle workloads. They need to be cooled using either an active cooler (with a fan) or a passive one (fanless), depending on power consumption (watts). Choose your CPU based on how you plan to use the server.
+
+
+ The case is also an essential component of your machine. It plays a key role in cooling, through its fans and airflow design, and it determines the form factor compatibility for your motherboard, power supply, and any dedicated GPU you may install.
+ Yet another minimalist, lightweight photo gallery static site generator.
`123.45.67.89` |
+| `source port` | Incoming port on the router | `443` |
+| `destination port` | Port on the destination machine | `3000` |
+| `destination machine` | IP of the target machine (on your local network) | `192.168.1.50` |
+
+According to the table:
+If we remove `All` and keep the IP `123.45.67.89`, all traffic from this IP sent to port `443` on your router will be forwarded to port `3000` on the local IP `192.168.1.50`.
+
+If we remove the IP and keep `All`, then all traffic from the internet on port `443` will be redirected to port `3000` on `192.168.1.50`.
+
+This is useful when you have a server that must be accessible from the internet. For instance, a website uses port `80` (non-secure) or `443` (SSL-secured).
+To make the website accessible, you'll configure your router to redirect the domain request to your local server.
+Assume your service runs on port `3000` locally (`http://192.168.1.50:3000`), you would redirect all traffic from port `443` on the router to port `3000` on the local server.
+
+::alert{type="warning"}
+:::list{type="warning"}
+- __Warning:__ If you have multiple services to expose like `subdomain1.mydomain.com` and `subdomain2.mydomain.com`, your router cannot differentiate requests and forward to different ports.
+ You must use a [Reverse Proxy](../../serveex/core/swag) to route traffic based on the request.
+:::
+::
+
+## DHCP
+---
+Every time a device connects to your local network, your router assigns it an IP address using DHCP rules.
+This IP is randomly selected from a predefined pool.
+At every device reboot, the IP may change — which is problematic if you're forwarding ports, as the target IP may no longer be valid.
+
+To avoid this, use your router's DHCP server to assign a static IP address.
+
+Each device has a physical "MAC address".
+To assign a fixed IP, you must know your device's MAC address (visible in your router when it's connected), and assign it a static IP.
+This is called a "static DHCP lease."
+
+That way, your machine's IP never changes and your port forwarding rules remain effective.
+
+| Variable | Description | Example |
+|---------------|----------------------------------|---------------------|
+| `IP` | Fixed local IP to assign | `192.168.1.50` |
+| `MAC Address` | Physical address of the device | `5E:FF:56:A2:AF:15` |
+
+For more information, refer to your router's documentation.
diff --git a/content/2.general/1.networking/2.dns.md b/content/2.general/1.networking/2.dns.md
new file mode 100644
index 0000000..fd3d702
--- /dev/null
+++ b/content/2.general/1.networking/2.dns.md
@@ -0,0 +1,70 @@
+---
+navigation: true
+title: DNS Zone
+description: Comprendre le fonctionnement du DNS, lire et éditer une zone DNS, et configurer des noms de domaine pour vos services auto-hébergés.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# Domain Names and DNS Zones
+
+::alert{type="info"}
+🎯 __Objectives:__
+- Understand how a DNS server works
+- Learn how to edit a DNS zone
+::
+
+## Introduction
+---
+When you browse a website or use an app, requests are made to one or more domains to fetch content for the page. Your device doesn't know the IP addresses of these servers, so it contacts a _name server_ (Domain Name Server), which responds with the most up-to-date IP address for the domain being requested.
+
+The DNS zone is like a registry with signposts that direct your requests to the correct destination.
+
+
+
+## The DNS Zone
+---
+When you purchase a domain from a registrar (Cloudflare, OVH, etc.), the registrar assigns you a DNS zone that you can customize.
+
+You can enter _records_ into this DNS zone to direct requests properly. You can find [more information here](https://help.ovhcloud.com/csm/fr-dns-servers-general-information?id=kb_article_view&sysparm_article=KB0051661).
+
+Example of a DNS zone for the domain `mydomain.com`:
+
+
+```
+@ IN SOA ns1.dns.me. dns.net. (2024051800 86400 3600 3600000 60)
+ IN NS ns1.dns.me.
+ IN NS ns2.dns.me.
+ IN A 203.0.113.0
+www IN CNAME mydomain.com
+sousdomaine IN CNAME mydomain.com
+```
+
+
+In this example:
+
+- `$TTL 3600` tells global name servers that the records are valid for 1 hour (after which they need to re-check).
+- `IN SOA ns1.dns.me. dns.net. (...)` indicates `ns1.dns.me` as the primary DNS server, with refresh intervals.
+- `IN NS` records define the authoritative name servers for the domain.
+- `IN A 203.0.113.0` means `mydomain.com` points to IP `203.0.113.0`.
+- `subdomain IN CNAME mydomain.com` means `subdomain.mydomain.com` points to the same destination as `mydomain.com`.
+
+So, if you want to point `mydomain.com` to your server, you can do it by adding an `A` record pointing to your server's public IP address.
+
+::alert{type="warning"}
+:::list{type="warning"}
+- __Warning:__ If your server is hosted at home:
+:::
+- Your public IP is the one assigned to your home router. Make sure it's static, or configure [DDNS](https://aws.amazon.com/fr/what-is/dynamic-dns/).
+- Make sure you've [set up port 443 forwarding to your server's listening port](/general/networking/nat).
+::
+
+If you're adding a subdomain that should also point to your server, use a `CNAME` record pointing to `mydomain.com`.
+
+::alert{type="info"}
+:::list{type="info"}
+- __Why not use an `A` record for the subdomain?__ If your subdomain points to the same server as `mydomain.com`, it's better to use a `CNAME` record because if the server's IP changes, you won’t need to update the subdomain record.
+:::
+::
+
+Most registrars offer user-friendly interfaces to manage DNS records. Refer to your registrar’s documentation for specific instructions.
diff --git a/content/2.general/1.networking/3.samba.md b/content/2.general/1.networking/3.samba.md
new file mode 100644
index 0000000..cc93eda
--- /dev/null
+++ b/content/2.general/1.networking/3.samba.md
@@ -0,0 +1,229 @@
+---
+navigation: true
+title: Samba
+description: Configurer Samba sur Debian pour partager des dossiers sur votre réseau local et y accéder depuis Windows, macOS ou Linux.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# Samba
+
+Samba is a protocol that allows access to a folder located on a network drive. It can be configured on macOS, Windows, or Linux.
+
+There are many tutorials for setting up Samba on Windows or on NAS systems like Synology, but here we focus on Debian.
+
+::alert{type="info"}
+🎯 __Objectives:__
+- Create a network folder on a remote machine
+- Access the network folder from our server
+::
+
+
+
+## Sharing a Network Folder
+---
+::alert{type="info"}
+:::list{type="info"}
+- In this example, we will share the `/video` folder from a remote machine called `remote-machine`. We will access this folder from a machine called `local-machine`. The user connecting to the network drive will be `sambauser`.
+:::
+::
+
+### Install Samba Server
+
+```sh
+sudo apt update && sudo apt upgrade
+sudo apt install samba smbclient cifs-utils
+```
+
+### Create the `/video` Folder
+
+```sh
+sudo mkdir /video
+```
+
+### Configure the Share
+
+Now, edit the file `/etc/samba/smb.conf`.
+
+::alert{type="success"}
+✨ __Tip:__ You can use [File Browser](/serveex/files/file-browser) to navigate and edit your files instead of using terminal commands.
+::
+
+```sh
+sudo vim /etc/samba/smb.conf
+```
+
+Find the `workgroup` variable, press `i` to enter insert mode, and name your workgroup (e.g., `workgroup = WORKGROUP`).
+
+Then scroll to the end of the file and add the following configuration:
+
+```properties
+[video]
+ comment = Video folder
+ path = /video
+ writable = yes
+ guest ok = no
+ valid users = @smbshare
+ force create mode = 770
+ force directory mode = 770
+ inherit permissions = yes
+```
+
+Press `Esc` to exit insert mode, then type `:x` and press `Enter` to save and exit.
+
+### Create a Samba User and Group
+
+Since we're using a secured share, we need to create a user and group to access it remotely.
+
+Create the group:
+
+```sh
+sudo groupadd smbshare
+```
+
+Give the group control over the `/video` folder:
+
+```sh
+sudo chgrp -R smbshare /video
+```
+
+Set inherited permissions:
+
+```sh
+sudo chmod 2775 /video
+```
+
+Now add a no-login user — this user cannot log into the server but can access Samba.
+
+```sh
+sudo useradd -M -s /sbin/nologin sambauser
+```
+
+Add the user to the `smbshare` group:
+
+```sh
+sudo usermod -aG smbshare sambauser
+```
+
+Set a Samba password:
+
+```sh
+sudo smbpasswd -a sambauser
+```
+
+Enable the Samba account:
+
+```sh
+sudo smbpasswd -e sambauser
+```
+
+```sh
+sudo ufw allow from remote-ip to any app Samba
+::
+```
+
+## Accessing a Shared Folder
+
+---
+
+\::
+
+### Install Required Packages
+
+```sh
+sudo apt update && sudo apt upgrade
+sudo apt install cifs-utils
+```
+
+### Create the Mount Destination
+
+We will create a folder on our local machine where the remote `/video` folder will be mounted — e.g., `/mnt/video`.
+
+```sh
+sudo mkdir /mnt/video
+```
+
+### Prepare the .credentials File
+
+To avoid typing our username and password every time, create a `.credentials` file storing the login info.
+
+Create it in the `/smb` folder:
+
+```sh
+sudo mkdir /smb
+sudo vi /smb/.credentials
+```
+
+Enter insert mode (`i`) and write:
+
+```properties
+username=smbuser
+password=password
+```
+
+* `smbuser`: the user we created on the `remote-machine`
+* `password`: the password set earlier
+
+Press `Esc`, then `:x` and `Enter` to save and exit.
+
+Set proper file permissions:
+
+```sh
+sudo chmod 600 /smb/.credentials
+```
+
+### Mount the Shared Folder
+
+Now mount the folder:
+
+```sh
+sudo mount -t cifs -o credentials=/smb/.credentials //remote-ip/video /mnt/video
+```
+
+Replace `remote-ip` with your `remote-machine`'s IP address.
+
+Verify the mount:
+
+```sh
+sudo mount -t cifs
+```
+
+You’ll see details confirming the mount is successful.
+
+Now you can access the `/video` folder of the `remote-machine` from your `local-machine`!
+
+### Auto-mount on Boot
+
+By default, shares aren't auto-mounted after reboot. To automate this, edit the `/etc/fstab` file.
+
+First, back it up:
+
+```sh
+sudo cp /etc/fstab /etc/fstab.bak
+```
+
+Then add the mount configuration line:
+
+```sh
+sudo echo //remote-ip/video /mnt/video cifs _netdev,nofail,credentials=/smb/.credentials,x-systemd.automount,x-systemd.device-timeout=15 0 0 >> /etc/fstab
+```
+
+Reboot the machine:
+
+```sh
+sudo reboot
+```
+
+After rebooting, verify the mount:
+
+```sh
+sudo mount -t cifs
+```
+
+And done!
+
+### Unmount the Shared Folder
+
+```sh
+sudo umount -t cifs /mnt/video
+```
\ No newline at end of file
diff --git a/content/2.general/2.storage/1.raid.md b/content/2.general/2.storage/1.raid.md
new file mode 100644
index 0000000..6876249
--- /dev/null
+++ b/content/2.general/2.storage/1.raid.md
@@ -0,0 +1,112 @@
+---
+navigation: true
+title: RAID
+description: Comprendre le RAID — matériel vs logiciel, niveaux RAID, et comment mettre en place des grappes de disques redondants pour votre homelab.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# RAID
+
+_Redundant Array of Independent Disks_
+
+In computing, RAID (Redundant Array of Independent Disks) is a system that allows multiple hard drives to be combined to improve performance and/or reliability. It works by restructuring and distributing data blocks across the drives.
+
+Originally, RAID systems were hardware-based, meaning a dedicated controller (a specific chip) managed data distribution and RAID operations. Today, most RAID systems (or their equivalents) are software-based. In fact, many software technologies can create RAID-like systems with features not available in hardware RAID, such as automatic repair (data scrubbing), snapshots, and more.
+
+## Different Types of RAID
+
+There are several types of RAID, each offering its own pros and cons. In general, RAID impacts the following five factors:
+
+- Number of drives
+- Total storage capacity
+- Read speed
+- Write speed
+- Fault tolerance (resistance to hardware failure)
+
+::alert{type="warning"}
+:::list{type="warning"}
+ - RAID is not a backup system but a service continuity system! It only allows hot-swapping of drives without interrupting your server or restoring from backup. You still need an external backup system.
+::
+
+### No RAID
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`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:
+
+::alert{type="success"}
+✨ __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
+---
+::alert{type="info"}
+📋 __Prerequisite:__
+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`.
+
+::alert{type="warning"}
+:::list{type="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.
+
+::alert{type="info"}
+:::list{type="info"}
+- 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
+```
+
+::alert{type="info"}
+:::list{type="info"}
+- 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
+```
+
+::alert{type="danger"}
+:::list{type="danger"}
+- __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`.
\ No newline at end of file
diff --git a/content/3.serveex/3.security/1.wireguard.md b/content/3.serveex/3.security/1.wireguard.md
new file mode 100644
index 0000000..8905514
--- /dev/null
+++ b/content/3.serveex/3.security/1.wireguard.md
@@ -0,0 +1,249 @@
+---
+navigation: true
+title: Wireguard
+description: Installer et configurer WireGuard VPN pour accéder à votre homelab de n'importe où et connecter tous vos appareils à votre réseau privé.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# Wireguard
+
+::alert{type="info"}
+🎯 __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
+---
+::alert{type="info"}
+📋 **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.
+::
+
+::alert{type="warning"}
+:::list{type="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
+```
+
+::alert{type="success"}
+✨ **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`.
+
+::alert{type="danger"}
+:::list{type="danger"}
+- 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
+---
+::alert{type="info"}
+:::list{type="info"}
+- 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
+```
+
+::alert{type="success"}
+✨ **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`).
+
+::alert{type="success"}
+✨ **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
+```
+
+::alert{type="info"}
+:::list{type="info"}
+- 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.
+
+::alert{type="warning"}
+:::list{type="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:
+
+
diff --git a/content/3.serveex/3.security/2.authentik.md b/content/3.serveex/3.security/2.authentik.md
new file mode 100644
index 0000000..fae7102
--- /dev/null
+++ b/content/3.serveex/3.security/2.authentik.md
@@ -0,0 +1,575 @@
+---
+navigation: true
+title: Authentik
+description: Installer Authentik comme fournisseur d'identité auto-hébergé — configurer le MFA et protéger vos services avec du SSO et l'authentification via reverse proxy.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# Authentik
+
+::alert{type="info"}
+🎯 __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
+```
+
+::alert{type="info"}
+:::list{type="info"}
+- 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/`
+
+::alert{type="warning"}
+:::list{type="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.
+
+::alert{type="info"}
+📋 __Prerequisites:__
+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:
+
+::alert{type="success"}
+✨ __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.
+
+::alert{type="success"}
+✨ __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.
+::
+
+::alert{type="info"}
+:::list{type="info"}
+- 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.
+
+::alert{type="info"}
+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
+```
+
+::alert{type="success"}
+✨ __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.
+
+::alert{type="info"}
+:::list{type="info"}
+- 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
+```
\ No newline at end of file
diff --git a/content/3.serveex/3.security/3.cloudflare.md b/content/3.serveex/3.security/3.cloudflare.md
new file mode 100644
index 0000000..a4171c6
--- /dev/null
+++ b/content/3.serveex/3.security/3.cloudflare.md
@@ -0,0 +1,264 @@
+---
+navigation: true
+title: Cloudflare Zero Trust
+description: Utiliser les tunnels Cloudflare et Zero Trust pour exposer des services sans ouvrir de ports — configurer SWAG et gérer plusieurs tunnels.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+# Cloudflare Zero Trust
+
+::alert{type="info"}
+🎯 __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.
+
+::alert{type="warning"}
+:::list{type="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
+---
+::alert{type="info"}
+:::list{type="info"}
+- 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`.
+
+::alert{type="success"}
+✨ __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
+```
+
+::alert{type="success"}
+✨ __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 | `you@email.com` |
+| `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).
+
+::alert{type="success"}
+✨ __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` |
\ No newline at end of file
diff --git a/content/3.serveex/4.monitoring/1.uptime-kuma.md b/content/3.serveex/4.monitoring/1.uptime-kuma.md
index 8994e14..6b95e9e 100644
--- a/content/3.serveex/4.monitoring/1.uptime-kuma.md
+++ b/content/3.serveex/4.monitoring/1.uptime-kuma.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Uptime-Kuma
+description: Installer Uptime-Kuma pour surveiller la disponibilité de vos services auto-hébergés, configurer des alertes et protéger le tableau de bord avec Authentik.
main:
fluid: false
---
diff --git a/content/3.serveex/4.monitoring/2.dozzle.md b/content/3.serveex/4.monitoring/2.dozzle.md
index 70f78b9..ad525a2 100644
--- a/content/3.serveex/4.monitoring/2.dozzle.md
+++ b/content/3.serveex/4.monitoring/2.dozzle.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Dozzle
+description: Installer Dozzle pour surveiller les logs des conteneurs Docker en temps réel depuis une interface web épurée, exposée via SWAG.
main:
fluid: false
---
diff --git a/content/3.serveex/4.monitoring/3.speedtest-tracker.md b/content/3.serveex/4.monitoring/3.speedtest-tracker.md
index 3721170..840c326 100644
--- a/content/3.serveex/4.monitoring/3.speedtest-tracker.md
+++ b/content/3.serveex/4.monitoring/3.speedtest-tracker.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Speedtest Tracker
+description: Installer Speedtest Tracker pour mesurer et enregistrer automatiquement la vitesse de votre connexion internet dans le temps, exposé avec SWAG.
main:
fluid: false
---
diff --git a/content/3.serveex/4.monitoring/4.beszel.md b/content/3.serveex/4.monitoring/4.beszel.md
index 0f38d96..5438559 100644
--- a/content/3.serveex/4.monitoring/4.beszel.md
+++ b/content/3.serveex/4.monitoring/4.beszel.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Beszel
+description: Installer Beszel pour surveiller CPU, RAM, disques et réseau de vos serveurs — y compris à distance — via un tableau de bord web léger.
main:
fluid: false
---
diff --git a/content/3.serveex/4.monitoring/5.upsnap.md b/content/3.serveex/4.monitoring/5.upsnap.md
index 68e41a2..37f907d 100644
--- a/content/3.serveex/4.monitoring/5.upsnap.md
+++ b/content/3.serveex/4.monitoring/5.upsnap.md
@@ -1,6 +1,7 @@
---
navigation: true
title: UpSnap
+description: Installer UpSnap pour allumer à distance des machines de votre réseau local via Wake-on-LAN, exposé avec SWAG.
main:
fluid: false
---
diff --git a/content/3.serveex/5.media/1.plex.md b/content/3.serveex/5.media/1.plex.md
index b4f1a87..2218b07 100644
--- a/content/3.serveex/5.media/1.plex.md
+++ b/content/3.serveex/5.media/1.plex.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Plex
+description: Installer Plex Media Server avec Tautulli sur votre homelab pour streamer films et séries depuis n'importe où sur tous vos appareils.
main:
fluid: false
---
diff --git a/content/3.serveex/5.media/2.qbittorrent.md b/content/3.serveex/5.media/2.qbittorrent.md
index 85726a3..75422cb 100644
--- a/content/3.serveex/5.media/2.qbittorrent.md
+++ b/content/3.serveex/5.media/2.qbittorrent.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Qbittorrent
+description: Installer qBittorrent avec Gluetun et ProtonVPN pour télécharger des torrents de manière sécurisée derrière un VPN sur votre serveur auto-hébergé.
main:
fluid: false
---
diff --git a/content/3.serveex/5.media/3.servarr.md b/content/3.serveex/5.media/3.servarr.md
index edd72b0..a9e4912 100644
--- a/content/3.serveex/5.media/3.servarr.md
+++ b/content/3.serveex/5.media/3.servarr.md
@@ -1,7 +1,6 @@
---
navigation: true
-title: Automatisation
-main:
+title: Automatisationdescription: Automatiser les téléchargements de médias avec la suite Servarr — Radarr, Sonarr, Bazarr, Prowlarr et Overseerr pour films et séries.main:
fluid: false
---
:ellipsis{left=0px width=40rem top=10rem blur=140px}
diff --git a/content/3.serveex/6.cloud/1.immich.md b/content/3.serveex/6.cloud/1.immich.md
index 997537f..9f41400 100644
--- a/content/3.serveex/6.cloud/1.immich.md
+++ b/content/3.serveex/6.cloud/1.immich.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Immich
+description: Installer Immich, une alternative auto-hébergée à Google Photos et iCloud avec reconnaissance faciale, géolocalisation et synchronisation multi-appareils.
main:
fluid: false
---
diff --git a/content/3.serveex/6.cloud/2.nextcloud.md b/content/3.serveex/6.cloud/2.nextcloud.md
index 7c736e6..c053d62 100644
--- a/content/3.serveex/6.cloud/2.nextcloud.md
+++ b/content/3.serveex/6.cloud/2.nextcloud.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Nextcloud
+description: Installer Nextcloud pour auto-héberger vos fichiers, photos et agenda — une alternative respectueuse de la vie privée à Google Drive, OneDrive et iCloud.
main:
fluid: false
---
diff --git a/content/3.serveex/7.files/1.file-browser.md b/content/3.serveex/7.files/1.file-browser.md
index 9668c77..ac91269 100644
--- a/content/3.serveex/7.files/1.file-browser.md
+++ b/content/3.serveex/7.files/1.file-browser.md
@@ -1,6 +1,7 @@
---
navigation: true
title: File Browser
+description: Installer File Browser pour parcourir et gérer les fichiers de votre serveur depuis une interface web, exposée de manière sécurisée avec SWAG.
main:
fluid: false
---
diff --git a/content/3.serveex/7.files/2.pingvin.md b/content/3.serveex/7.files/2.pingvin.md
index 3ac24a3..73d41f2 100644
--- a/content/3.serveex/7.files/2.pingvin.md
+++ b/content/3.serveex/7.files/2.pingvin.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Pingvin
+description: Installer Pingvin Share, une plateforme d'envoi de fichiers auto-hébergée pour partager des fichiers de façon sécurisée sans WeTransfer ni Google Drive.
main:
fluid: false
---
diff --git a/content/3.serveex/8.development/1.code-server.md b/content/3.serveex/8.development/1.code-server.md
index f0df3cf..52b5ee5 100644
--- a/content/3.serveex/8.development/1.code-server.md
+++ b/content/3.serveex/8.development/1.code-server.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Code-Serveur
+description: Installer code-server pour utiliser VS Code dans votre navigateur depuis votre homelab — montez des dossiers et exposez-le de manière sécurisée avec SWAG.
main:
fluid: false
---
diff --git a/content/3.serveex/8.development/2.gitea.md b/content/3.serveex/8.development/2.gitea.md
index 9fd50bf..e48a888 100644
--- a/content/3.serveex/8.development/2.gitea.md
+++ b/content/3.serveex/8.development/2.gitea.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Gitea
+description: Installer Gitea, un service Git auto-hébergé léger pour gérer vos dépôts de code de façon privée sur votre propre serveur.
main:
fluid: false
---
diff --git a/content/3.serveex/8.development/3.it-tools.md b/content/3.serveex/8.development/3.it-tools.md
index 8485de0..a843486 100644
--- a/content/3.serveex/8.development/3.it-tools.md
+++ b/content/3.serveex/8.development/3.it-tools.md
@@ -1,7 +1,6 @@
---
navigation: true
-title: IT-Tools
-main:
+title: IT-Toolsdescription: Installer IT Tools, une collection auto-hébergée d'utilitaires pratiques pour développeurs — convertisseurs, encodeurs, formateurs et plus encore.main:
fluid: false
---
:ellipsis{left=0px width=40rem top=10rem blur=140px}
diff --git a/content/3.serveex/9.apps/1.adguard.md b/content/3.serveex/9.apps/1.adguard.md
index b82ca32..4ba07fd 100644
--- a/content/3.serveex/9.apps/1.adguard.md
+++ b/content/3.serveex/9.apps/1.adguard.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Adguard Home
+description: Installer AdGuard Home pour bloquer publicités et trackers à l'échelle du réseau avec DNS-over-HTTPS, gestion des clients et règles de filtrage personnalisées.
main:
fluid: false
---
diff --git a/content/3.serveex/9.apps/2.vaultwarden.md b/content/3.serveex/9.apps/2.vaultwarden.md
index 6d8ffe5..2d4853f 100644
--- a/content/3.serveex/9.apps/2.vaultwarden.md
+++ b/content/3.serveex/9.apps/2.vaultwarden.md
@@ -1,6 +1,7 @@
---
navigation: true
title: Vaultwarden
+description: Installer Vaultwarden, un gestionnaire de mots de passe auto-hébergé compatible Bitwarden pour remplacer les gestionnaires Google ou Apple sur tous vos appareils.
main:
fluid: false
---
diff --git a/content/4.stockeex/1.introduction.md b/content/4.stockeex/1.introduction.md
index 0f6f109..c2cb5a9 100644
--- a/content/4.stockeex/1.introduction.md
+++ b/content/4.stockeex/1.introduction.md
@@ -2,6 +2,7 @@
icon: lucide:bookmark
navigation: true
title: Introduction
+description: Introduction à Stockeex — un projet personnel de gestion de stock et d'inventaire. Documentation en cours de rédaction.
main:
fluid: false
---
diff --git a/content/5.nonsense/1.python/1.nvidia-stock-bot.md b/content/5.nonsense/1.python/1.nvidia-stock-bot.md
new file mode 100644
index 0000000..41c2662
--- /dev/null
+++ b/content/5.nonsense/1.python/1.nvidia-stock-bot.md
@@ -0,0 +1,40 @@
+---
+navigation: true
+title: Nvidia Stock Bot
+description: Un bot Python qui surveille la disponibilité des GPU en temps réel et envoie des alertes Discord — créé lors de la pénurie de la série RTX 5000.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+
+# 🤖 Nvidia Stock Bot
+---
+
+For the past four years, the electronics hardware shortage has been relentless. Graphics cards are no exception. In 2020, I had to wait two months to get my RTX 3080. To manage it, I joined [JV Hardware](https://discord.gg/gxffg3GA96), where a small group of geeks had set up a bot that pinged users when GPUs became available.
+
+Four years later and with 5,000 members on the server, the RTX 5000 series is being released. Yet, no working stock bot seems to exist. Not to mention a certain “influencer” who charges users for access to a bot that doesn’t even work. He manually copies alerts from other servers like ours, which have already solved the issue.
+
+Anyway, eager to get an RTX 5090 for my AI-dedicated machine, I decided it was time to dive into Python—with a little help from ChatGPT. Along with another member, KevOut, who helped guide me through the APIs and initial architecture, I ended up building a clean and functional bot that sends different kinds of Discord alerts—all deployable in a simple Docker container.
+
+After many setbacks, I went from this:
+
+
+
+To this:
+
+
+
+And more recently :
+
+
+
+And I was also lucky enough to be referenced in the famous [selfhost newsletter](https://selfh.st/weekly/2025-07-11/) !
+
+More info directly on the repo:
+
+::card
+#title
+ 🐋 __Nvidia Stock Bot__
+#description
+ [Nvidia GPU stock alert bot](https://git.djeex.fr/Djeex/nvidia-stock-bot)
+::
diff --git a/content/5.nonsense/1.python/2. adguard-cidre.md b/content/5.nonsense/1.python/2. adguard-cidre.md
new file mode 100644
index 0000000..9692fbf
--- /dev/null
+++ b/content/5.nonsense/1.python/2. adguard-cidre.md
@@ -0,0 +1,39 @@
+---
+navigation: true
+title: Adguard CIDRE
+description: Un script Python pour synchroniser automatiquement les listes CIDR d'AdGuard Home et sécuriser votre serveur DNS auto-hébergé exposé sur internet.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+
+# 🤖 Adguard CIDRE Sync
+---
+
+Adguard Home is a fantastic solution for DNS-level ad blocking and rewriting requests—perfect for removing ISP DNS trackers or intrusive ads.
+
+It works great locally, but if you want all your devices (even on the go) to benefit, you’ll need to expose Adguard to the internet. Unfortunately, that means anyone can use it, potentially overloading your €1/month remote VPS.
+
+Adguard allows whitelisting or blacklisting clients. The problem? To whitelist a client, you need their IP—but for mobile phones, that IP changes often. Instead of trying to whitelist ever-changing IPs, the better approach is to block broader IP ranges by region.
+
+CIDRE is a tool that syncs geo-targeted IP ranges with firewalls. Instead of running CIDRE with a full firewall stack on the remote server, I figured I could just import those regularly updated IP ranges into Adguard’s blocklist.
+
+Thus, Adguard CIDRE Sync was born: a container that syncs Adguard’s blocklist with CIDRE’s updated IP ranges on a schedule of your choosing.
+
+The idea is to:
+- Backup Adguard’s config file on first run (original untouched version saved)
+- Download selected country IP ranges via an environment variable
+- Let you manually add custom IPs via a file
+- Concatenate, backup the config again (as the updated version), and inject the list into the correct blocklist section
+- Reload Adguard by restarting the container (using Docker socket proxy for limited permissions)
+
+All fully autonomous, with frequency set via environment variable in the `docker-compose` config.
+
+More info directly on the repo:
+
+::card
+#title
+ 🐋 __Adguard CIDRE Sync__
+#description
+ [Adguard blocklist sync bot](https://git.djeex.fr/Djeex/adguard-cidre)
+::
\ No newline at end of file
diff --git a/content/5.nonsense/1.python/3.lumeex.md b/content/5.nonsense/1.python/3.lumeex.md
new file mode 100644
index 0000000..911df24
--- /dev/null
+++ b/content/5.nonsense/1.python/3.lumeex.md
@@ -0,0 +1,69 @@
+---
+navigation: true
+title: Lumeex
+description: Lumeex est un générateur de galerie photo statique en Python — minimaliste, léger et entièrement personnalisable sans CMS.
+main:
+ fluid: false
+---
+:ellipsis{left=0px width=40rem top=10rem blur=140px}
+
+
+
+
+Mix your SDR and HDR exports into an Instagram-ready HDR photo.
+
+