From 11582415bdceb014d917588bd4090ac04d75156c Mon Sep 17 00:00:00 2001 From: MilesTEG Date: Tue, 10 Aug 2021 16:00:38 +0200 Subject: [PATCH] Revert "Merge pull request 'Python' (#81) from Python into master" This reverts commit 7908c218fa3a9d431bc976e5e32afd418df94757, reversing changes made to 1c57928338af18142951fb0f3e79f528b82a65ae. --- LICENSE | 20 + Plex Bot Music/README.md | 8 - Plex Discord Activity/..README.md | 76 -- Plex Discord Activity/README.md | 76 -- Plex Discord Activity/pda.py | 413 -------- README.md | 24 + README_GIT.md | 115 +++ dns-blacklists/adguard-home/liste.md | 33 + dns-blacklists/pihole/liste | 50 + dns_whitelists/adguard-home/liste.md | 16 + .../bridgemacvlan-interface.sh | 54 + .../adguard-macvlan/docker-compose.yml | 86 ++ .../docker_network_create_macvlan.sh | 59 ++ docker-compose/adguard/docker-compose.yml | 25 + docker-compose/bitwardenrs/docker-compose.yml | 21 + docker-compose/duckdns/docker-compose.yml | 19 + .../TUTO--fail2ban_docker-compose.yml | 90 ++ .../action.d/iptables-common.local | 4 + .../fail2ban--fichiers/filter.d/gitea.local | 5 + .../filter.d/vaultwarden-admin.local | 8 + .../filter.d/vaultwarden.local | 8 + .../jail.conf.du-conteneur-ne-pas-utiliser | 964 ++++++++++++++++++ .../fail2ban--fichiers/jail.d/gitea.local | 39 + .../jail.d/vaultwarden-admin.local | 37 + .../jail.d/vaultwarden.local | 37 + docker-compose/ghost/docker-compose.yml | 26 + docker-compose/gitea/Changer-Theme-Gitea.md | 171 ++++ .../data--gitea/public/css/aquamarine.css | 23 + .../gitea/data--gitea/public/css/dark.css | 23 + .../gitea/data--gitea/public/css/hotline.css | 23 + .../data--gitea/public/css/organizr-dark.css | 23 + .../gitea/data--gitea/public/css/plex.css | 23 + .../data--gitea/public/css/space-gray.css | 23 + .../gitea/data--gitea/public/styles.css | 10 + .../data--gitea/templates/custom/header.tmpl | 6 + docker-compose/gitea/docker-compose.yml | 94 ++ docker-compose/gitea/gitea-backup.sh | 272 +++++ docker-compose/gitea/gitea-restore.sh | 368 +++++++ docker-compose/gitea/tuto-1.png | Bin 0 -> 65366 bytes docker-compose/gitea/tuto-2.png | Bin 0 -> 26856 bytes docker-compose/gitea/tuto-3.png | Bin 0 -> 178296 bytes docker-compose/heimdall/docker-compose.yml | 22 + .../huginn-mariadb/docker-compose.yml | 53 + .../jackett-flaresolver/docker-compose.yml | 39 + .../jellyfin-embystat/docker-compose.yml | 56 + docker-compose/lidarr/docker-compose.yml | 23 + docker-compose/nextcloud/docker-compose.yml | 29 + .../nginx-proxy-manager/docker-compose.yml | 26 + docker-compose/ombi/docker-compose.yml | 21 + .../.env | 5 + .../docker-compose.yml | 148 +++ .../geoip-updater.env | 7 + .../rtorrent-rutorrent.env | 36 + .../bridgemacvlan-interface.sh | 46 + .../pi-hole_macvlan/docker-compose.yml | 85 ++ .../docker_network_create_macvlan.sh | 43 + docker-compose/plex/boot-HW-Transcode.sh | 17 + docker-compose/plex/docker-compose.yml | 30 + .../plex_et_tautulli/docker-compose.yml | 58 ++ docker-compose/privatebin/docker-compose.yml | 18 + docker-compose/psitransfer/docker-compose.yml | 22 + docker-compose/qbitorrent/docker-compose.yml | 26 + docker-compose/radarr/docker-compose.yml | 23 + docker-compose/requestrr/docker-compose.yml | 22 + docker-compose/scrutiny/docker-compose.yml | 37 + docker-compose/sonarr/docker-compose.yml | 23 + docker-compose/speedtest/docker-compose.yml | 22 + docker-compose/syncthing/docker-compose.yml | 31 + docker-compose/tautulli/docker-compose.yml | 22 + .../Tuto - forum-nas.bbcode | 681 +++++++++++++ .../config/rclone/rclone.conf | 3 + .../docker-compose.yml | 262 +++++ .../vaultwarden__Enable_Websocket_DSM-6.x.sh | 114 +++ .../vaultwarden__Enable_Websocket_DSM-7.sh | 129 +++ docker-compose/watchtower/docker-compose.yml | 29 + wiki/activer_skip_intro.md | 33 + .../installation_docker_portainer_raspbian.md | 51 + wiki/la_casa_de_papel.md | 72 ++ wiki/markdown.md | 43 + wiki/nvidia_transcoding.md | 9 + wiki/passmark.md | 27 + wiki/quel_serveur_acheter.md | 18 + wiki/quicksync.md | 10 + wiki/transcoder_4k.md | 27 + 84 files changed, 5297 insertions(+), 573 deletions(-) create mode 100644 LICENSE delete mode 100644 Plex Bot Music/README.md delete mode 100644 Plex Discord Activity/..README.md delete mode 100644 Plex Discord Activity/README.md delete mode 100644 Plex Discord Activity/pda.py create mode 100644 README.md create mode 100644 README_GIT.md create mode 100644 dns-blacklists/adguard-home/liste.md create mode 100644 dns-blacklists/pihole/liste create mode 100644 dns_whitelists/adguard-home/liste.md create mode 100644 docker-compose/adguard-macvlan/bridgemacvlan-interface.sh create mode 100644 docker-compose/adguard-macvlan/docker-compose.yml create mode 100644 docker-compose/adguard-macvlan/docker_network_create_macvlan.sh create mode 100755 docker-compose/adguard/docker-compose.yml create mode 100755 docker-compose/bitwardenrs/docker-compose.yml create mode 100755 docker-compose/duckdns/docker-compose.yml create mode 100644 docker-compose/fail2ban/TUTO--fail2ban_docker-compose.yml create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/action.d/iptables-common.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/filter.d/gitea.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden-admin.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/jail.conf.du-conteneur-ne-pas-utiliser create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/jail.d/gitea.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden-admin.local create mode 100644 docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden.local create mode 100644 docker-compose/ghost/docker-compose.yml create mode 100644 docker-compose/gitea/Changer-Theme-Gitea.md create mode 100644 docker-compose/gitea/data--gitea/public/css/aquamarine.css create mode 100644 docker-compose/gitea/data--gitea/public/css/dark.css create mode 100644 docker-compose/gitea/data--gitea/public/css/hotline.css create mode 100644 docker-compose/gitea/data--gitea/public/css/organizr-dark.css create mode 100644 docker-compose/gitea/data--gitea/public/css/plex.css create mode 100644 docker-compose/gitea/data--gitea/public/css/space-gray.css create mode 100644 docker-compose/gitea/data--gitea/public/styles.css create mode 100644 docker-compose/gitea/data--gitea/templates/custom/header.tmpl create mode 100644 docker-compose/gitea/docker-compose.yml create mode 100644 docker-compose/gitea/gitea-backup.sh create mode 100644 docker-compose/gitea/gitea-restore.sh create mode 100644 docker-compose/gitea/tuto-1.png create mode 100644 docker-compose/gitea/tuto-2.png create mode 100644 docker-compose/gitea/tuto-3.png create mode 100755 docker-compose/heimdall/docker-compose.yml create mode 100644 docker-compose/huginn-mariadb/docker-compose.yml create mode 100755 docker-compose/jackett-flaresolver/docker-compose.yml create mode 100644 docker-compose/jellyfin-embystat/docker-compose.yml create mode 100755 docker-compose/lidarr/docker-compose.yml create mode 100644 docker-compose/nextcloud/docker-compose.yml create mode 100755 docker-compose/nginx-proxy-manager/docker-compose.yml create mode 100755 docker-compose/ombi/docker-compose.yml create mode 100644 docker-compose/openvpn-rutorrent-jackett-flaresolver-radarr-sonarr/.env create mode 100644 docker-compose/openvpn-rutorrent-jackett-flaresolver-radarr-sonarr/docker-compose.yml create mode 100644 docker-compose/openvpn-rutorrent-jackett-flaresolver-radarr-sonarr/geoip-updater.env create mode 100644 docker-compose/openvpn-rutorrent-jackett-flaresolver-radarr-sonarr/rtorrent-rutorrent.env create mode 100644 docker-compose/pi-hole_macvlan/bridgemacvlan-interface.sh create mode 100644 docker-compose/pi-hole_macvlan/docker-compose.yml create mode 100644 docker-compose/pi-hole_macvlan/docker_network_create_macvlan.sh create mode 100644 docker-compose/plex/boot-HW-Transcode.sh create mode 100755 docker-compose/plex/docker-compose.yml create mode 100755 docker-compose/plex_et_tautulli/docker-compose.yml create mode 100755 docker-compose/privatebin/docker-compose.yml create mode 100755 docker-compose/psitransfer/docker-compose.yml create mode 100755 docker-compose/qbitorrent/docker-compose.yml create mode 100755 docker-compose/radarr/docker-compose.yml create mode 100755 docker-compose/requestrr/docker-compose.yml create mode 100644 docker-compose/scrutiny/docker-compose.yml create mode 100755 docker-compose/sonarr/docker-compose.yml create mode 100755 docker-compose/speedtest/docker-compose.yml create mode 100644 docker-compose/syncthing/docker-compose.yml create mode 100755 docker-compose/tautulli/docker-compose.yml create mode 100644 docker-compose/vaultwarden_AVEC_backup/Tuto - forum-nas.bbcode create mode 100644 docker-compose/vaultwarden_AVEC_backup/config/rclone/rclone.conf create mode 100644 docker-compose/vaultwarden_AVEC_backup/docker-compose.yml create mode 100644 docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-6.x.sh create mode 100644 docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-7.sh create mode 100755 docker-compose/watchtower/docker-compose.yml create mode 100644 wiki/activer_skip_intro.md create mode 100755 wiki/installation_docker_portainer_raspbian.md create mode 100644 wiki/la_casa_de_papel.md create mode 100755 wiki/markdown.md create mode 100755 wiki/nvidia_transcoding.md create mode 100644 wiki/passmark.md create mode 100755 wiki/quel_serveur_acheter.md create mode 100755 wiki/quicksync.md create mode 100755 wiki/transcoder_4k.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f0fd20a --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Plex Bot Music/README.md b/Plex Bot Music/README.md deleted file mode 100644 index 2fb7cdd..0000000 --- a/Plex Bot Music/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Plex Bot Music - -**Plex Bot Music est un bot écrit en Python. Il vous permettra d'écouter votre musique sur Discord au travers d'un bot, tel que Rythme mais vous serez limité à votre Bibliothèque** - - -## Lien vers le répértoire - -https://gitea.zoz-serv.org/gigidsss/Plex-Bot-Music diff --git a/Plex Discord Activity/..README.md b/Plex Discord Activity/..README.md deleted file mode 100644 index ef5cd19..0000000 --- a/Plex Discord Activity/..README.md +++ /dev/null @@ -1,76 +0,0 @@ -# Plex Discord Activity - -**Plex Discord Activity est un logiciel en Python. Il a été récuperé déjà depuis le dépot d'un utilisateur GitHub mais a été simplifié de sorte a ce que la pré-configuration soit la plus simple possible** - -Il y a eu peu de modifications par rapport à l'original, mais elles vous simplifient grandement la vie. - -## Attention - -Sachez que pour que le script fonctionne, il faut qu'il tourne sur le même PC que votre application Discord. Malheureusement faire tourner ce script sur un serveur en tâche de fond ne donnera aucun résultat... - -## Installation - -Pour cela, commencez déjà par installer Python3 sur votre ordinateur si cela n'est pas déjà fait... - -Ensuite installez ces 2 bibliothèques Python via pip3: - -```bash -pip3 install plexapi -pip3 install websocket-client==0.48.0 -``` - -## Configuration - -Éditez le document pma.py et éditez ce paragraphe seulement: -```python -### SEULEMENT CE QUE VOUS DEVEZ EDITER - -MyDomain = "https://your.plex.dns:32400" #Soit via votre nom de domaine, soit via le domaine de Plex, c'est à dire, https://app.plex.tv -Serveur = "MyPlex" #Le nom de votre Serveur Plex, visible dans Paramètres > Général > Nom d'usage -NomUser = "username" #Le nom d'utilisateur Plex pour récupérer les métadonnées et les informations de lecture en temps réel -MotDePasse = "password" #Votre mot de passe de votre compte Plex -MonToken = "your_token" #Votre Token, accessible a la fin de l'url lorsque vous consultez le fichier XML de l'un de vos médias -BlackList = ["Musique", "BackingTracks"] #séparée par des virgules avec espace, entourées par des "", entrent 2 balises [], ex: ["bib1", "bib2"] -UserOnly = "username" #Si vous avez crée des utilisateurs gérés, pour éviter de partager l'état de lecture d'un autre utilisateur que vous-même, précisez le psuedo du bon utilisateur a priori le même que le 3ème paramètre que vous... -InfosSupp = "true" #Ceci partage les métadonnées de votre épisode si c'est sur True, sinon mettez False pour n'afficher que l'état de lecture -TempsRestant = "true" #True = Afficher le temps restant de lecture / False = Afficher le nombre de minutes que vous avez déjà consulté depuis le démarrage de l'épisode - -### END DE CE QUE VOUS DEVEZ EDITER -``` - -Voici un résumé des paramètres: - -**Attention a ne pas supprimer des guillemets ou des crochets... Si vous ne voulez pas préciser de valeur, laissez les guillemets vides ou indiquez-y ``none`` !** - -**Serveur**: C'est le nom de votre serveur Plex. Vous le trouverez dans ``Paramètres > Général > Nom d'usage`` - -**NomUser**: Votre nom d'utilisateur Plex associé à votre compte. - -**MotDePasse**: Votre mot de passe de l'utilisateur Plex associé à votre compte. - -**MonToken**: Token que vous pouvez obtenir en consultant le fichier XML d'un de vos média. Allez sur un épisode ou film précis, allez dans ``Voir informations`` puis ``Voir le XML``. Ensuite regardez à la fin de votre URL, vous devriez avoir: **Plex-Token=0x0x0xx0x00xx0x0** - -**BlackList**: Vous pouvez décider de ne pas partager sur Discord les médias d'une bibliothèque définie, indiquez-y entre guillemets et eux-même entre crochets, le nom des Bibliothèques. -Exemple: -```python -BlackList = ["Musique", "BackingTracks"] -``` -**UserOnly**: Si vous avez crée des utilisateurs gérés, pour éviter de partager l'état de lecture d'un autre utilisateur que vous-même, précisez le psuedo du bon utilisateur qui à priori est le même que celui du paramètre ``username``... - -**InfosSupp**: Vous permet de partager davantage d'infos sur le média, à savoir les métadonnées, etc. (Réponse: True / False) - -**TempsRestant**: Vous permet de préciser si vous voulez indiquer le temps restant du média ou la position actuelle (Réponse: True (Il reste 05:00 minutes) / False (Vous êtes à 15:00 minutes sur 20:00 minutes)) - -## Utilisation - -``` -python3 pma.py -``` -*Patientez +/- 20 secondes pour que le script démarre... Le script lancera tout seul la page web Plex* - -## Source -https://github.com/Phineas05/discord-rich-presence-plex - - -## License -[MIT](https://choosealicense.com/licenses/mit/) diff --git a/Plex Discord Activity/README.md b/Plex Discord Activity/README.md deleted file mode 100644 index ef5cd19..0000000 --- a/Plex Discord Activity/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# Plex Discord Activity - -**Plex Discord Activity est un logiciel en Python. Il a été récuperé déjà depuis le dépot d'un utilisateur GitHub mais a été simplifié de sorte a ce que la pré-configuration soit la plus simple possible** - -Il y a eu peu de modifications par rapport à l'original, mais elles vous simplifient grandement la vie. - -## Attention - -Sachez que pour que le script fonctionne, il faut qu'il tourne sur le même PC que votre application Discord. Malheureusement faire tourner ce script sur un serveur en tâche de fond ne donnera aucun résultat... - -## Installation - -Pour cela, commencez déjà par installer Python3 sur votre ordinateur si cela n'est pas déjà fait... - -Ensuite installez ces 2 bibliothèques Python via pip3: - -```bash -pip3 install plexapi -pip3 install websocket-client==0.48.0 -``` - -## Configuration - -Éditez le document pma.py et éditez ce paragraphe seulement: -```python -### SEULEMENT CE QUE VOUS DEVEZ EDITER - -MyDomain = "https://your.plex.dns:32400" #Soit via votre nom de domaine, soit via le domaine de Plex, c'est à dire, https://app.plex.tv -Serveur = "MyPlex" #Le nom de votre Serveur Plex, visible dans Paramètres > Général > Nom d'usage -NomUser = "username" #Le nom d'utilisateur Plex pour récupérer les métadonnées et les informations de lecture en temps réel -MotDePasse = "password" #Votre mot de passe de votre compte Plex -MonToken = "your_token" #Votre Token, accessible a la fin de l'url lorsque vous consultez le fichier XML de l'un de vos médias -BlackList = ["Musique", "BackingTracks"] #séparée par des virgules avec espace, entourées par des "", entrent 2 balises [], ex: ["bib1", "bib2"] -UserOnly = "username" #Si vous avez crée des utilisateurs gérés, pour éviter de partager l'état de lecture d'un autre utilisateur que vous-même, précisez le psuedo du bon utilisateur a priori le même que le 3ème paramètre que vous... -InfosSupp = "true" #Ceci partage les métadonnées de votre épisode si c'est sur True, sinon mettez False pour n'afficher que l'état de lecture -TempsRestant = "true" #True = Afficher le temps restant de lecture / False = Afficher le nombre de minutes que vous avez déjà consulté depuis le démarrage de l'épisode - -### END DE CE QUE VOUS DEVEZ EDITER -``` - -Voici un résumé des paramètres: - -**Attention a ne pas supprimer des guillemets ou des crochets... Si vous ne voulez pas préciser de valeur, laissez les guillemets vides ou indiquez-y ``none`` !** - -**Serveur**: C'est le nom de votre serveur Plex. Vous le trouverez dans ``Paramètres > Général > Nom d'usage`` - -**NomUser**: Votre nom d'utilisateur Plex associé à votre compte. - -**MotDePasse**: Votre mot de passe de l'utilisateur Plex associé à votre compte. - -**MonToken**: Token que vous pouvez obtenir en consultant le fichier XML d'un de vos média. Allez sur un épisode ou film précis, allez dans ``Voir informations`` puis ``Voir le XML``. Ensuite regardez à la fin de votre URL, vous devriez avoir: **Plex-Token=0x0x0xx0x00xx0x0** - -**BlackList**: Vous pouvez décider de ne pas partager sur Discord les médias d'une bibliothèque définie, indiquez-y entre guillemets et eux-même entre crochets, le nom des Bibliothèques. -Exemple: -```python -BlackList = ["Musique", "BackingTracks"] -``` -**UserOnly**: Si vous avez crée des utilisateurs gérés, pour éviter de partager l'état de lecture d'un autre utilisateur que vous-même, précisez le psuedo du bon utilisateur qui à priori est le même que celui du paramètre ``username``... - -**InfosSupp**: Vous permet de partager davantage d'infos sur le média, à savoir les métadonnées, etc. (Réponse: True / False) - -**TempsRestant**: Vous permet de préciser si vous voulez indiquer le temps restant du média ou la position actuelle (Réponse: True (Il reste 05:00 minutes) / False (Vous êtes à 15:00 minutes sur 20:00 minutes)) - -## Utilisation - -``` -python3 pma.py -``` -*Patientez +/- 20 secondes pour que le script démarre... Le script lancera tout seul la page web Plex* - -## Source -https://github.com/Phineas05/discord-rich-presence-plex - - -## License -[MIT](https://choosealicense.com/licenses/mit/) diff --git a/Plex Discord Activity/pda.py b/Plex Discord Activity/pda.py deleted file mode 100644 index 39fa285..0000000 --- a/Plex Discord Activity/pda.py +++ /dev/null @@ -1,413 +0,0 @@ -import asyncio -import datetime -import hashlib -import json -import os -import plexapi.myplex -import struct -import subprocess -import sys -import tempfile -import threading -import time -import webbrowser - -### SEULEMENT CE QUE VOUS DEVEZ EDITER - -MyDomain = "https://your.plex.dns:32400" #Soit via votre nom de domaine, soit via le domaine de Plex, c'est à dire, https://app.plex.tv -Serveur = "MyPlex" #Le nom de votre Serveur Plex, visible dans Paramètres > Général > Nom d'usage -NomUser = "username" #Le nom d'utilisateur Plex pour récupérer les métadonnées et les informations de lecture en temps réel -MotDePasse = "password" #Votre mot de passe de votre compte Plex -MonToken = "your_token" #Votre Token, accessible a la fin de l'url lorsque vous consultez le fichier XML de l'un de vos médias -BlackList = ["Musique", "BackingTracks"] #séparée par des virgules avec espace, entourées par des "", entrent 2 balises [], ex: ["bib1", "bib2"] -UserOnly = "username" #Si vous avez crée des utilisateurs gérés, pour éviter de partager l'état de lecture d'un autre utilisateur que vous-même, précisez le psuedo du bon utilisateur a priori le même que le 3ème paramètre que vous... -InfosSupp = "true" #Ceci partage les métadonnées de votre épisode si c'est sur True, sinon mettez False pour n'afficher que l'état de lecture -TempsRestant = "true" #True = Afficher le temps restant de lecture / False = Afficher le nombre de minutes que vous avez déjà consulté depuis le démarrage de l'épisode - -### END DE CE QUE VOUS DEVEZ EDITER - -webbrowser.open(MyDomain) - -class plexConfig: - - extraLogging = (InfosSupp) - timeRemaining = (TempsRestant) - - def __init__(self, serverName = "", username = "", password = "", token = "", listenForUser = "", blacklistedLibraries = None, whitelistedLibraries = None, clientID = "413407336082833418"): - self.serverName = serverName - self.username = username - self.password = password - self.token = token - self.listenForUser = (username if listenForUser == "" else listenForUser).lower() - self.blacklistedLibraries = blacklistedLibraries - self.whitelistedLibraries = whitelistedLibraries - self.clientID = clientID - -plexConfigs = [ - plexConfig(serverName = (Serveur), username = (NomUser), password = (MotDePasse), token = (MonToken), blacklistedLibraries = (BlackList), listenForUser = (UserOnly)) -] - -class discordRichPresence: - - def __init__(self, clientID, child): - self.IPCPipe = ((os.environ.get("XDG_RUNTIME_DIR", None) or os.environ.get("TMPDIR", None) or os.environ.get("TMP", None) or os.environ.get("TEMP", None) or "/tmp") + "/discord-ipc-0") if isLinux else "\\\\?\\pipe\\discord-ipc-0" - self.clientID = clientID - self.pipeReader = None - self.pipeWriter = None - self.process = None - self.running = False - self.child = child - - async def read(self): - try: - data = await self.pipeReader.read(1024) - self.child.log("[READ] " + str(json.loads(data[8:].decode("utf-8")))) - except Exception as e: - self.child.log("[READ] " + str(e)) - self.stop() - - def write(self, op, payload): - payload = json.dumps(payload) - self.child.log("[WRITE] " + str(payload)) - data = self.pipeWriter.write(struct.pack(" 0] - else: - if (text["h"] == 0): - del text["h"] - text = [str(v).rjust(2, "0") for k, v in text.items()] - return joiner.join(text) - -discordRichPresencePlexInstances = [] -for config in plexConfigs: - discordRichPresencePlexInstances.append(discordRichPresencePlex(config)) -try: - for discordRichPresencePlexInstance in discordRichPresencePlexInstances: - discordRichPresencePlexInstance.run() - while (True): - time.sleep(3600) -except KeyboardInterrupt: - for discordRichPresencePlexInstance in discordRichPresencePlexInstances: - discordRichPresencePlexInstance.reset() -except Exception as e: - print("Error: " + str(e)) diff --git a/README.md b/README.md new file mode 100644 index 0000000..55ab6f7 --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +# Repo Officiel du Discord Plex FR + +## Table des matières +* [Qui sommes-nous ?](#qui-sommes-nous) +* [A quoi sert ce dépot ?](#a-quoi-sert-ce-dépot) +* [Comment contribuer à ce dépot ?](#comment-contribuer-à-ce-dépot) +* [Comment nous rejoindre ?](#comment-nous-rejoindre) + +## Qui sommes-nous ? + +Nous sommes une communauté francophone autour du logiciel Plex. +... + +## A quoi sert ce dépot ? + +Ce dépot nous sert a stocker les composes / aides / tutos / ... qui nous permettent d'aider la communauté. L'avantage du dépot est que toutes les personnes inscrites peuvent contribuer. + +## Comment contribuer à ce dépot ? + +Lisez le README "Aide pour le repo" ici : https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/src/branch/master/README_GIT.md + +## Comment nous rejoindre ? + +Nous sommes sur Discord et Guilded, a ces adresses : https://discord.gg/ERpYMqS | https://guilded.gg/PlexFR \ No newline at end of file diff --git a/README_GIT.md b/README_GIT.md new file mode 100644 index 0000000..338e8ce --- /dev/null +++ b/README_GIT.md @@ -0,0 +1,115 @@ +# AIDE POUR LE REPO + +## Table des matières +* [Comment utiliser Git](#comment-utiliser-git) +* [Docker-compose](#docker-compose) +* [Wiki](#wiki) + +## Comment utiliser Git + +Clonez le dépot sur votre machine `git clone https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo.git` + +### Pour chaque modification, attention à bien suivre cette procédure si vous voulez éviter des conflits de versions + +- Créez votre branche via la GUI Gitea (idéalement votre pseudo) ex : `Benj` + +![mabanche](https://i.imgur.com/0KLNFSG.png) + +- Rapatriez les dernières modifications : `git pull` +- Mettez vous sur votre branche : `git checkout mabranche` +- Faites vos modificatiosn (création de fichiers etc) +- Récupérez les éventuelles denrières modifications : `git pull` puis `git merge master` +- Ajoutez les nouveaux fichiers : `git add .` ou `git add -A` +- Validez les modif : `git commit -m "ma super modif"` +- Balancez sur le serveur : `git push` +- Et ouvrez une merge request via la GUI, pensez à ajouter 1 ou 2 relecteurs, petite parenthèse +le but de la relecture par les pairs permet d'éviter des erreurs (https://blog.groupe-sii.com/les-revues-de-code/) + +Quand la merge request est close et/ou mergé, le relecteur supprime votre branche, +vous pourrez la recréer plus tard quand vous aurez besoin... + +### Petit reminder + +- **ON NE TRAVAILLE JAMAIS SUR LE MASTER** + +- **Un renommage de répertoire cause un conflit généralement, nécessite intervention manuelle** + +- `git status` > donne la branche courante ainsi que l'état des fichiers modifiés +> git status +> Sur la branche master +> Votre branche est à jour avec 'origin/master'. +> +> Modifications qui ne seront pas validées : +> (utilisez "git add ..." pour mettre à jour ce qui sera validé) +> (utilisez "git checkout -- ..." pour annuler les modifications dans la copie de travail) +> +> modifié : README.md +> +> aucune modification n'a été ajoutée à la validation (utilisez "git add" ou "git commit -a") + + +- `git add toto.pouet` ou `git add .` > ajout les modifications sur toto.pouet ou sur tous les fichiers au prochain commit + + +- `git commit -m "mon super message"` > on pose le commit avec un message qui explique ce que l'on a fait (pratique pour retrouver ca plus tard si besoin) + + +- `git pull` > on récupère toutes les dernières modifs du serveur + + +- `git merge master` > (doit être fait après un `git pull`) on récupère toutes les dernières modifs du master pour les mettre sur la branche courante + +### Au secours + +#### J'ai fait mes modif sur le master (sans commit) + +- `git stash` > je sauvegarde mes modifs en local et rétablis le dernier commit +- `git pull` > je récupère des dernières modifs du serveur +- `git checkout mabranche` > je changement de branche +- `git merge master` > je récupère les dernières modifs du master sur ma branche +- `git stash apply` > j'applique ma sauvegarde local +- je poursuis mes modifs et je add/commit/push quand j'ai fini + +## Docker-compose + +### Fonctionnement + +Le répertoire `docker-compose/` contient uniquement les docker-compose de chaque service/application. + +L'arborescence doit être la suivante : +`docker-compose//docker-compose.yml` +- `` : le nom de l'application ou service à rajouter + +### Possibilité + +Le bot pourrait appeler le contenu de chaque application selon cette commande +`.docker-compose ` +Il chercherait selon l'url suivant : +`https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/docker-compose//docker-compose.yml` +Si HTTP 200 alors on affiche le contenu retourné +Sinon HTTP 404 alors on affiche `la page n'existe pas` + + +Exemple ok: +> `.docker-compose plex` +> renvoie le contenu de +> https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/docker-compose/plex/docker-compose.yml + +Exemple ko: +> `.docker-compose pouet` +> renvoie `La page que vous demandez n'existe pas` + + + +## Wiki + +fichiers au format md (markdown) + +### Possibilité + +Le bot pourrait appeler le contenu de chaque application selon cette commande +`.wiki ` +Il chercherait selon l'url suivant : +`https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/wiki/.md` +Si HTTP 200 alors on affiche le contenu retourné +Sinon HTTP 404 alors on affiche `la page n'existe pas` \ No newline at end of file diff --git a/dns-blacklists/adguard-home/liste.md b/dns-blacklists/adguard-home/liste.md new file mode 100644 index 0000000..88235e4 --- /dev/null +++ b/dns-blacklists/adguard-home/liste.md @@ -0,0 +1,33 @@ +# Liste de blocage DNS pour AdGuard-Home + +## Listes disponibles avec une simple case à cocher : + +* Il faut aller dans le menu **Filtres** -> **Liste de blocage DNS**. + +* Puis, il faut cliquer sur le bouton vert "**Ajouter une liste de blocage**. + +* Et enfin, cliquer sur le bouton "**Choisissez dans la liste**". + +* Choisir ensuite ces listes : (la première est incluse dans une liste à ajouter manuellement ensuite) + +![image](https://gitea.zoz-serv.org/attachments/640b8667-ad65-4986-aad1-05151b81ab83) + +![image](https://gitea.zoz-serv.org/attachments/2b17f2e0-66d5-4f4c-9a71-acbf1f59bc9c) + +## Listes à ajouter manuellement (pris dans le fichier de configuration AdGuardHome.yaml) : + +* `Nom de la liste` (à placer dans le champ adéquat)
+[URL de la liste](URL) +

+ +* `sebsauvage.net hosts-adguard`
+ https://sebsauvage.net/hosts/hosts-adguard + +* `firebog.net - NoTrack-blocklist`
+ https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt + +* `firebog.net - SmartTV`
+https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV.txt + +* `Firebog.net - ads-and-tracking-extended`
+ https://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txt diff --git a/dns-blacklists/pihole/liste b/dns-blacklists/pihole/liste new file mode 100644 index 0000000..c271fc6 --- /dev/null +++ b/dns-blacklists/pihole/liste @@ -0,0 +1,50 @@ +https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/mobile.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/smarttv.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/nomsdata.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/gamefake.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/jbfake.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/fakenewsde.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/adobeblock.txt +https://raw.githubusercontent.com/Akamaru/Pi-Hole-Lists/master/other.txt +https://justdomains.github.io/blocklists/lists/easylist-justdomains.txt +https://raw.githubusercontent.com/kboghdady/youTube_ads_4_pi-hole/master/black.list +https://www.github.developerdan.com/hosts/lists/amp-hosts-extended.txt +https://www.github.developerdan.com/hosts/lists/tracking-aggressive-extended.txt +https://www.github.developerdan.com/hosts/lists/ads-and-tracking-extended.txt +https://raw.githubusercontent.com/PolishFiltersTeam/KADhosts/master/KADhosts_without_controversies.txt +https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Spam/hosts +https://v.firebog.net/hosts/static/w3kbl.txt +https://adaway.org/hosts.txt +https://v.firebog.net/hosts/AdguardDNS.txt +https://v.firebog.net/hosts/Admiral.txt +https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt +https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt +https://v.firebog.net/hosts/Easylist.txt +https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext +https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts +https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts +https://v.firebog.net/hosts/Easyprivacy.txt +https://v.firebog.net/hosts/Prigent-Ads.txt +https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-blocklist.txt +https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts +https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt +https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt +https://zerodot1.gitlab.io/CoinBlockerLists/hosts_browser +https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt +https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt +https://s3.amazonaws.com/lists.disconnect.me/simple_malvertising.txt +https://mirror1.malwaredomains.com/files/justdomains +https://v.firebog.net/hosts/Prigent-Crypto.txt +https://mirror.cedia.org.ec/malwaredomains/immortal_domains.txt +https://www.malwaredomainlist.com/hostslist/hosts.txt +https://bitbucket.org/ethanr/dns-blacklists/raw/8575c9f96e5b4a1308f2f12394abd86d0927a4a0/bad_lists/Mandiant_APT1_Report_Appendix_D.txt +https://phishing.army/download/phishing_army_blocklist_extended.txt +https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt +https://v.firebog.net/hosts/Shalla-mal.txt +https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt +https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts +https://urlhaus.abuse.ch/downloads/hostfile/ +https://emmanuel-lecoq.fr/wp-content/uploads/2020/02/Pi-hole-list.txt +https://ransomwaretracker.abuse.ch/downloads/RW_DOMBL.txt +https://gitlab.com/ZeroDot1/CoinBlockerLists/raw/master/list.txt \ No newline at end of file diff --git a/dns_whitelists/adguard-home/liste.md b/dns_whitelists/adguard-home/liste.md new file mode 100644 index 0000000..b2b9c82 --- /dev/null +++ b/dns_whitelists/adguard-home/liste.md @@ -0,0 +1,16 @@ +# Listes d’autorisation DNS pour AdGuard-Home + +## Listes à ajouter manuellement (pris dans le fichier de configuration AdGuardHome.yaml) : + +- `Nom de la liste` (à placer dans le champ adéquat)
+[URL de la liste](URL) +

+ +* `anudeepND/whitelist`
+ https://raw.githubusercontent.com/anudeepND/whitelist/master/domains/whitelist.txt + +* `hg1978 / AdGuard-Home-Whitelist`
+ https://raw.githubusercontent.com/hg1978/AdGuard-Home-Whitelist/master/whitelist.txt + +* `hg1978 / AdGuard-Home-Whitelist`
+https://raw.githubusercontent.com/hg1978/AdGuard-Home-Whitelist/master/facebook-whitelist.txt \ No newline at end of file diff --git a/docker-compose/adguard-macvlan/bridgemacvlan-interface.sh b/docker-compose/adguard-macvlan/bridgemacvlan-interface.sh new file mode 100644 index 0000000..563c461 --- /dev/null +++ b/docker-compose/adguard-macvlan/bridgemacvlan-interface.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +##===========================================================================================## +## Script bridgemacvlan-interface.sh ## +## ## +## Script de création d'interface virtuelle pour les conteneurs en macvlan ## +## Voir tutos : ## +## https://www.nas-forum.com/forum/topic/69319-tuto-docker-macvlan-pi-hole/ ## +## https://www.nas-forum.com/forum/topic/67311-tuto-certificat-ssl-reverse-proxy-via-docker/ ## +## ## +## Rappels des différentes IP : ## +## - Plage d'IP macvlan : 192.168.xxx.MMM/28 == 192.168.2.208/28 ## +## - IP virtuelle unique : 192.168.xxx.zzz/32 == 192.168.2.210/32 ## +## - Plage d'IP du LAN : 192.168.xxx.0/24 == 192.168.2.0/24 ## +## - Passerelle/routeur : 192.168.xxx.1 == 192.168.2.1 ## +## - IP conteneur n°1 : 192.168.xxx.yyy == 192.168.2.209 ## +## - IP conteneur n°2 : 192.168.xxx.ooo == 192.168.2.210 AdGuard_Home ## +## ## +##============================================================================================= + +# Set timeout to wait host network is up and running +sleep 60 + +echo "$(date "+%R:%S - ") Script de création d'une interface virtuelle pour le NAS" +echo "$(date "+%R:%S - ") Exécution des commandes..." + +ip link add macv0 link eth0 type macvlan mode bridge # macv0 : est le nom données à l'interface virtuelle + # eth0 : est l'interface réseau utilisée sur le NAS (lorsque VMM n'est pas utilisé) + # si VMM est utilisé, ce sera ovs_eth0 +ip addr add 192.168.xxx.zzz/32 dev macv0 # Adresse IP virtuelle 192.168.x.zzz/32 -- Il faut que cette adresse soit libre dans le réseau + # et qu'elle ne fasse pas partie du DHCP du routeur/box + # + #### Dans mon cas, c'est cette commande : + #### ip addr add 192.168.2.230/32 dev macv0 + +ip link set dev macv0 address 5E:00:01:02:03:04 # MAC adresse pour l'adaptateur ayant l'IP virtuelle + # Il faut que l'adresse MAC respecte ces conditions : + # - Elle n'existe pas déjà sur mon hôte et sur mon réseau. + # - Elle respecte la base hexadécimale, les notations allant de 0 à F. + # - Le premier nombre doit être pair, ici 5E = 94 en base 10, c'est donc OK (vous pouvez + # utiliser un convertisseur en ligne, ou faire vos divisions euclidiennes). + # S'il est impair, vous aurez un message : + # RTNETLINK answers: Cannot assign requested address +ip link set macv0 up + +ip route add 192.168.xxx.MMM/28 dev macv0 # 192.168.xxx.MMM/28 : Plage d'adresse macvlan + # IP réellement disponible : voir les calculateurs internet + # Utiliser Portainer ou l'interface Docker ou encore le script : create-macvlan-network.sh + # + #### Dans mon cas, c'est cette commande : + #### ip route add 192.168.2.208/28 dev macv0 + +echo "$(date "+%R:%S - ") Script terminé" +exit diff --git a/docker-compose/adguard-macvlan/docker-compose.yml b/docker-compose/adguard-macvlan/docker-compose.yml new file mode 100644 index 0000000..c5c0add --- /dev/null +++ b/docker-compose/adguard-macvlan/docker-compose.yml @@ -0,0 +1,86 @@ +##============================================================================================== +## ## +## Fichier docker-compose.yml pour Adguard-Home en macvlan ## +## ## +##============================================================================================== + +##============================================================================================## +## ## +## Attention, il faut créer le réseau macvlan à l'aide du script : macvlan-network.sh ## +## Ce dernier va créer un réseau macvlan ayant comme IP unique 192.168.2.210 ## +## Cette IP doit être dans la plage d'IP mavclan définie dans le script de création du réseau.## +## Le conteneur sera donc vu comme une machine sur le réseau LAN, mais ne pourra pas être ## +## joint par le NAS lui-même. ## +## Pour celà, il faut utiliser le second script : boot-bridgemacvlan-interface.sh ## +## Ce dernier va créer une IP-interface virtuelle qui pourra être accessible par le NAS. ## +## Cette interface ne persiste pas au démarrage, il faudra mettre le script en tâche ## +## planifiée avec le planificateur de tâches dans DSM. ## +## ## +## Voir tuto : https://www.nas-forum.com/forum/topic/69319-tuto-docker-macvlan-pi-hole/ ## +## ## +## Attention ! ## +## ## +## Ces deux scripts ne sont à utiliser qu'une seule fois, quelque soit le nombre de ## +## conteneurs qui en bénéficieront. ## +## Par exemple, si vous utilisez 2 conteneurs en macvlan, une fois le réseau macvlan créé ## +## pour le 1er, il est inutile (et impossible) de le recréer. ## +## Le script boot-bridgemacvlan-interface.sh ne doit être lancé qu'une seule fois, et à ## +## chaque reboot. L'IP virtuelle est unique, il ne faut pas en recréer une seconde. ## +## ## +##============================================================================================== + +--- +version: "2.4" +services: + adguardhome_macvlan: + image: adguard/adguardhome:latest # https://github.com/AdguardTeam/AdGuardHome + # https://github.com/AdguardTeam/AdGuardHome/wiki/Docker + container_name: adguardhome_macvlan + + hostname: AdGuard-Home--DS920+ # Permet d'avoir un nom pour le conteneur dans AdGuard lui même (sinon c'est une chaine aléatoire) + + environment: + - PUID=1000 # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - PGID=100 # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - TZ=Europe/Paris + - LANG=fr_FR.UTF8 + - LANGUAGE=fr_FR.UTF8 + + # --------------------------------------------------------------------------------- + # Le label ci-dessous permet à Watchtower de faire les mises à jour automatiquement + # Cela peut-être supprimé si Watchtower n'est pas utilisé. + labels: + - "com.centurylinklabs.watchtower.enable=true" + # --------------------------------------------------------------------------------- + + volumes: + - "/volume1/docker/adguardhome_macvlan/work:/opt/adguardhome/work" + - "/volume1/docker/adguardhome_macvlan/conf:/opt/adguardhome/conf" + + # La déclaration des ports n'est pas utile lors d'une installation en macvlan, car tous les ports seront directement accessible + # avec l'IP virtuelle. + # ports: + # - "953:53" + # - "967:67/udp" + # - "968:68" + # - "8080:80/tcp" + # - "9443:443/tcp" + # - "9853:853/tcp" + # - "3030:3000/tcp" + + networks: + macvlan-network: + ipv4_address: 192.168.xxx.yyy # Mettre ici l'IP macvlan dans la plage définie dans les scripts + # Dans mon cas c'est 192.168.2.210 + + restart: unless-stopped + + healthcheck: + test: "/bin/netstat -pant | /bin/grep 53" + interval: 45s + timeout: 30s + retries: 3 + +networks: + macvlan-network: # Ce réseau devra bien entendu être créé avant avec le script annexe ou avec Portainer. + external: true \ No newline at end of file diff --git a/docker-compose/adguard-macvlan/docker_network_create_macvlan.sh b/docker-compose/adguard-macvlan/docker_network_create_macvlan.sh new file mode 100644 index 0000000..7090ff0 --- /dev/null +++ b/docker-compose/adguard-macvlan/docker_network_create_macvlan.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +##============================================================================================## +## ## +## Script docker_network_create_macvlan.sh ## +## ## +## Script de création d'interface virtuelle pour les conteneurs qui auront une IP macvlan ## +## Voir tutos : ## +## https://www.nas-forum.com/forum/topic/69319-tuto-docker-macvlan-pi-hole/ ## +## https://www.nas-forum.com/forum/topic/67311-tuto-certificat-ssl-reverse-proxy-via-docker/ ## +## ## +## Les IPs prévues pour les conteneurs sont : ## +## - Conteneur A : 192.168.xxx.yyy ## +## - AdGuard-Home : 192.168.xxx.ooo ## +## ## +## Rappels des différentes IP : ## +## - Plage d'IP macvlan : 192.168.xxx.MMM/28 ## +## - IP virtuelle unique : 192.168.xxx.zzz/32 ## +## - IP conteneur n°1 : 192.168.xxx.yyy ## +## - IP conteneur n°2 : 192.168.xxx.ooo ## +## - Plage d'IP du LAN : 192.168.xxx.0/24 ## +## - Passerelle/routeur : 192.168.xxx.1 ## +## ## +##============================================================================================== + +##============================================================================================== +## ## +## --ip-range=192.168.xxx.MMM/28 : cela correspond à la plage d'IP pour le réseau macvlan ## +## sachant que 192.168.xxx.MMM doit être la 1ère IP donnée par les calculateurs internet. ## +## Il se peut que ce ne soit pas la même que l'IP macvlan que l'on veut donner au conteneur ## +## AdGuardHome. ## +## ## +## Quelques calculateurs internet : ## +## https://cric.grenoble.cnrs.fr/Administrateurs/Outils/CalculMasque/ ## +## https://www.cidr.eu/en/calculator/+/192.168.2.208/28 ## +## ## +##============================================================================================== + + +docker network create -d macvlan \ +--subnet=192.168.xxx.0/24 \ +--ip-range=192.168.xxx.MMM/28 \ +--gateway=192.168.xxx.1 \ +-o parent=eth0 \ # Ici, eth0 est à remplacer par votre interface réseau : eth0, ovs_eth0 ou autre... +macvlan-network + +##============================================================================================== +## Pour exemple, voilà mes valeurs à moi : ## +## ## +## - Conteneur A : 192.168.2.209 ## +## - AdGuard-Home : 192.168.2.210 ## +## - Conteneur B : 192.168.2.211 ## +## ## +## Rappels des différentes IP : ## +## - Plage d'IP macvlan : 192.168.xxx.MMM/28 == 192.168.2.208/28 ## +## - IP virtuelle unique : 192.168.xxx.zzz/32 == 192.168.2.210/32 ## +## - Plage d'IP du LAN : 192.168.xxx.0/24 == 192.168.2.0/24 ## +## - Passerelle/routeur : 192.168.xxx.1 == 192.168.2.1 ## +##============================================================================================== diff --git a/docker-compose/adguard/docker-compose.yml b/docker-compose/adguard/docker-compose.yml new file mode 100755 index 0000000..2a8385a --- /dev/null +++ b/docker-compose/adguard/docker-compose.yml @@ -0,0 +1,25 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-02-26 +version: '3.3' +services: + adguardhome: + container_name: adguardhome + volumes: + - /volume1/docker/adguard/work:/opt/adguardhome/work + - /volume1/docker/adguard/conf:/opt/adguardhome/conf + ports: + - '53:53/tcp' + - '53:53/udp' + - '80:80/tcp' # WebUI suite config validé + - '3000:3000/tcp' # WebUI 1ere connexion pour configurer + - '443:443/tcp' + - '853:853/tcp' + image: adguard/adguardhome +# Network conseillé de ne pas utiliser host (pas de redirection de port) ni default_bridge car limité a 16 ip +# Si vous souhaiter utiliser le serveur dhcp il faut utiliser host + network_mode: adguard_network + restart: unless-stopped +# Decommenter les 2 lignes suivantes pour que watchtower surveille ce conteneur +# labels: +# - com.centurylinklabs.watchtower.enable=true + diff --git a/docker-compose/bitwardenrs/docker-compose.yml b/docker-compose/bitwardenrs/docker-compose.yml new file mode 100755 index 0000000..06cea11 --- /dev/null +++ b/docker-compose/bitwardenrs/docker-compose.yml @@ -0,0 +1,21 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-02-26 +version: '3' + +services: + bitwarden: + image: bitwardenrs/server + restart: unless-stopped +# Decommenter les 2 lignes suivantes pour que watchtower surveille ce conteneur +# labels: +# - com.centurylinklabs.watchtower.enable=true + ports: + - 80:80 # WebUI + volumes: + - /volume1/docker/bitwarden/bw-data:/data + environment: + - WEBSOCKET_ENABLED: 'true' # Necessaire pour utiliser websockets + - SIGNUPS_ALLOWED: 'true' # Mettre faux une fois le 1er utilisateur creer et redemarrer le conteneur +# Network conseillé de ne pas utiliser host (pas de redirection de port) ni default_bridge car limité a 16 ip + network_mode: 'bitwardenrs_network' + diff --git a/docker-compose/duckdns/docker-compose.yml b/docker-compose/duckdns/docker-compose.yml new file mode 100755 index 0000000..e59f582 --- /dev/null +++ b/docker-compose/duckdns/docker-compose.yml @@ -0,0 +1,19 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-03-03 +version: '3.3' +services: + linuxserver: + container_name: duckdns + environment: + - PUID=1000 # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - PGID=1000 # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - TZ=Europe/Paris + - SUBDOMAINS=XXXXX # Votre subdomain duckdns sans www + - TOKEN=XXXXX # A récupéré sur le site de duckdns + restart: unless-stopped +# Decommenter les 2 lignes suivantes pour que watchtower surveille ce conteneur +# labels: +# - com.centurylinklabs.watchtower.enable=true + image: 'ghcr.io/linuxserver/duckdns:latest' +# Network conseillé de ne pas utiliser host (pas de redirection de port) ni default_bridge car limité a 16 ip + network_mode: duckdns_network \ No newline at end of file diff --git a/docker-compose/fail2ban/TUTO--fail2ban_docker-compose.yml b/docker-compose/fail2ban/TUTO--fail2ban_docker-compose.yml new file mode 100644 index 0000000..04857d6 --- /dev/null +++ b/docker-compose/fail2ban/TUTO--fail2ban_docker-compose.yml @@ -0,0 +1,90 @@ +##============================================================================================== +## ## +## Docker-compose file for Fail2ban ## +## ## +##============================================================================================== + +--- +version: "2" +##============================================================================================== +## ## +## Sources utilisées pour personnaliser ce fichier et ceux dans les sous-dossiers ## +## ## +##============================================================================================== +## ## +## https://www.linode.com/docs/guides/using-fail2ban-to-secure-your-server-a-tutorial/ ## +## https://www.linuxtricks.fr/wiki/print.php?id=40 ## +## https://github.com/dani-garcia/bitwarden_rs/wiki/Fail2Ban-Setup#synology-dsm ## +## https://github.com/sosandroid/docker-fail2ban-synology ## +## ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## ## +## Cloner/télécharger le dépôt suivant qui contient les fichiers à utiliser : ## +## https://github.com/sosandroid/docker-fail2ban-synology.git ## +## Il faudra juste modifier le docker-compose.yml qui vient avec ou utiliser celui-ci. ## +## ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## ## +## Pour supprimer une IP bannie, lancer la commande suivante : ## +## sudo docker exec -t fail2ban fail2ban-client set bitwarden_rs unbanip xx.xx.xx.xx ## +## ## +## Pour Voir le log de fail2ban, lancer la commande : ## +## cat /volume1/docker/fail2ban/fail2ban.log ## +## ## +## ## +## Quelques commandes utiles : ## +## docker exec -t fail2ban fail2ban-client status ## +## docker exec -t fail2ban fail2ban-client status bitwarden_rs ## +## ## +## unbans (in all jails and database) : ## +## docker exec -t fail2ban fail2ban-client unban ... ## +## ## +## docker exec -t fail2ban fail2ban-client --help ## +## docker exec -t fail2ban fail2ban-client restart ## +## docker exec -t fail2ban fail2ban-client reload --restart --unban --all ## +## ## +## flushes the logtarget if a file and reopens it. For log rotation. : ## +## docker exec -t fail2ban fail2ban-client flushlogs ## +## ## +##============================================================================================== + +services: + fail2ban: + image: ghcr.io/crazy-max/fail2ban:latest + container_name: fail2ban + network_mode: host + + environment: + - TZ=Europe/Paris + - F2B_DB_PURGE_AGE=30d + - F2B_LOG_TARGET=/data/fail2ban.log + - F2B_LOG_LEVEL=INFO + - F2B_IPTABLES_CHAIN=INPUT + + # Il faut adapter ces variables à votre fournisseur d'email. + - SSMTP_HOST=smtp.gmail.com + - SSMTP_PORT=587 # Pour gmail : 587 + - SSMTP_HOSTNAME=Docker-Fail2ban # Ce sera le nom qui sera affiché dans les emails + - SSMTP_USER=XXxxXX@gmail.com + - SSMTP_PASSWORD=XXxxXX # Pensez à générer un mot de passe application si la 2FA est activée + - SSMTP_TLS=YES # Pour gmail : YES + - SSMTP_STARTTLS=YES # Pour gmail : YES + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + volumes: + - "/volume1/docker/fail2ban:/data" + + # Les différents chemins d'accès vers les fichiers log des services à protéger par fail2ban + # On ajoute ro pour read-only (lecture seule) + - "/volume1/docker/vaultwarden/vaultwarden-data:/vaultwarden:ro" # Vaultwarden + - "/volume1/docker/gitea/data/gitea/log:/gitea:ro" # Gitea + #- "/var/log/auth.log:/log/host_ssh_auth.log:ro" # SSH sur l'hôte (Synology) + + cap_add: + - NET_ADMIN + - NET_RAW + + restart: always \ No newline at end of file diff --git a/docker-compose/fail2ban/fail2ban--fichiers/action.d/iptables-common.local b/docker-compose/fail2ban/fail2ban--fichiers/action.d/iptables-common.local new file mode 100644 index 0000000..25299bf --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/action.d/iptables-common.local @@ -0,0 +1,4 @@ +[Init] +blocktype = DROP +[Init?family=inet6] +blocktype = DROP diff --git a/docker-compose/fail2ban/fail2ban--fichiers/filter.d/gitea.local b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/gitea.local new file mode 100644 index 0000000..5412dd8 --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/gitea.local @@ -0,0 +1,5 @@ +# /volume1/docker/fail2ban/filter.d/gitea.conf + +[Definition] +failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from +ignoreregex = \ No newline at end of file diff --git a/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden-admin.local b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden-admin.local new file mode 100644 index 0000000..2fa0ab7 --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden-admin.local @@ -0,0 +1,8 @@ +# /volume1/docker/fail2ban/filter.d/vaultwarden-admin.conf + +[INCLUDES] +before = common.conf + +[Definition] +failregex = ^.*Invalid admin token\. IP: .*$ +ignoreregex = \ No newline at end of file diff --git a/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden.local b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden.local new file mode 100644 index 0000000..31dac76 --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/filter.d/vaultwarden.local @@ -0,0 +1,8 @@ +# /volume1/docker/fail2ban/filter.d/vaultwarden.conf + +[INCLUDES] +before = common.conf + +[Definition] +failregex = ^.*Username or password is incorrect\. Try again\. IP: \. Username:.*$ +ignoreregex = diff --git a/docker-compose/fail2ban/fail2ban--fichiers/jail.conf.du-conteneur-ne-pas-utiliser b/docker-compose/fail2ban/fail2ban--fichiers/jail.conf.du-conteneur-ne-pas-utiliser new file mode 100644 index 0000000..e6961a1 --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/jail.conf.du-conteneur-ne-pas-utiliser @@ -0,0 +1,964 @@ +# +# WARNING: heavily refactored in 0.9.0 release. Please review and +# customize settings for your setup. +# +# Changes: in most of the cases you should not modify this +# file, but provide customizations in jail.local file, +# or separate .conf files under jail.d/ directory, e.g.: +# +# HOW TO ACTIVATE JAILS: +# +# YOU SHOULD NOT MODIFY THIS FILE. +# +# It will probably be overwritten or improved in a distribution update. +# +# Provide customizations in a jail.local file or a jail.d/customisation.local. +# For example to change the default bantime for all jails and to enable the +# ssh-iptables jail the following (uncommented) would appear in the .local file. +# See man 5 jail.conf for details. +# +# [DEFAULT] +# bantime = 1h +# +# [sshd] +# enabled = true +# +# See jail.conf(5) man page for more information + + + +# Comments: use '#' for comment lines and ';' (following a space) for inline comments + + +[INCLUDES] + +#before = paths-distro.conf +before = paths-debian.conf + +# The DEFAULT allows a global definition of the options. They can be overridden +# in each jail afterwards. + +[DEFAULT] + +# +# MISCELLANEOUS OPTIONS +# + +# "bantime.increment" allows to use database for searching of previously banned ip's to increase a +# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32... +#bantime.increment = true + +# "bantime.rndtime" is the max number of seconds using for mixing with random time +# to prevent "clever" botnets calculate exact time IP can be unbanned again: +#bantime.rndtime = + +# "bantime.maxtime" is the max number of seconds using the ban time can reach (doesn't grow further) +#bantime.maxtime = + +# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier, +# default value of factor is 1 and with default value of formula, the ban time +# grows by 1, 2, 4, 8, 16 ... +#bantime.factor = 1 + +# "bantime.formula" used by default to calculate next value of ban time, default value below, +# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32... +#bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor +# +# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" : +#bantime.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor) + +# "bantime.multipliers" used to calculate next value of ban time instead of formula, coresponding +# previously ban count and given "bantime.factor" (for multipliers default is 1); +# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count, +# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours +#bantime.multipliers = 1 2 4 8 16 32 64 +# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin, +# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day +#bantime.multipliers = 1 5 30 60 300 720 1440 2880 + +# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed +# cross over all jails, if false (dafault), only current jail of the ban IP will be searched +#bantime.overalljails = false + +# -------------------- + +# "ignoreself" specifies whether the local resp. own IP addresses should be ignored +# (default is true). Fail2ban will not ban a host which matches such addresses. +#ignoreself = true + +# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban +# will not ban a host which matches an address in this list. Several addresses +# can be defined using space (and/or comma) separator. +#ignoreip = 127.0.0.1/8 ::1 + +# External command that will take an tagged arguments to ignore, e.g. , +# and return true if the IP is to be ignored. False otherwise. +# +# ignorecommand = /path/to/command +ignorecommand = + +# "bantime" is the number of seconds that a host is banned. +bantime = 10m + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 10m + +# "maxretry" is the number of failures before a host get banned. +maxretry = 5 + +# "maxmatches" is the number of matches stored in ticket (resolvable via tag in actions). +maxmatches = %(maxretry)s + +# "backend" specifies the backend used to get files modification. +# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto". +# This option can be overridden in each jail as well. +# +# pyinotify: requires pyinotify (a file alteration monitor) to be installed. +# If pyinotify is not installed, Fail2ban will use auto. +# gamin: requires Gamin (a file alteration monitor) to be installed. +# If Gamin is not installed, Fail2ban will use auto. +# polling: uses a polling algorithm which does not require external libraries. +# systemd: uses systemd python library to access the systemd journal. +# Specifying "logpath" is not valid for this backend. +# See "journalmatch" in the jails associated filter config +# auto: will try to use the following backends, in order: +# pyinotify, gamin, polling. +# +# Note: if systemd backend is chosen as the default but you enable a jail +# for which logs are present only in its own log files, specify some other +# backend for that jail (e.g. polling) and provide empty value for +# journalmatch. See https://github.com/fail2ban/fail2ban/issues/959#issuecomment-74901200 +backend = auto + +# "usedns" specifies if jails should trust hostnames in logs, +# warn when DNS lookups are performed, or ignore all hostnames in logs +# +# yes: if a hostname is encountered, a DNS lookup will be performed. +# warn: if a hostname is encountered, a DNS lookup will be performed, +# but it will be logged as a warning. +# no: if a hostname is encountered, will not be used for banning, +# but it will be logged as info. +# raw: use raw value (no hostname), allow use it for no-host filters/actions (example user) +usedns = warn + +# "logencoding" specifies the encoding of the log files handled by the jail +# This is used to decode the lines from the log file. +# Typical examples: "ascii", "utf-8" +# +# auto: will use the system locale setting +logencoding = auto + +# "enabled" enables the jails. +# By default all jails are disabled, and it should stay this way. +# Enable only relevant to your setup jails in your .local or jail.d/*.conf +# +# true: jail will be enabled and log files will get monitored for changes +# false: jail is not enabled +enabled = false + + +# "mode" defines the mode of the filter (see corresponding filter implementation for more info). +mode = normal + +# "filter" defines the filter to use by the jail. +# By default jails have names matching their filter name +# +filter = %(__name__)s[mode=%(mode)s] + + +# +# ACTIONS +# + +# Some options used for actions + +# Destination email address used solely for the interpolations in +# jail.{conf,local,d/*} configuration files. +destemail = root@localhost + +# Sender email address used solely for some actions +sender = root@ + +# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the +# mailing. Change mta configuration parameter to mail if you want to +# revert to conventional 'mail'. +mta = sendmail + +# Default protocol +protocol = tcp + +# Specify chain where jumps would need to be added in ban-actions expecting parameter chain +chain = + +# Ports to be banned +# Usually should be overridden in a particular jail +port = 0:65535 + +# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3 +fail2ban_agent = Fail2Ban/%(fail2ban_version)s + +# +# Action shortcuts. To be used to define action parameter + +# Default banning action (e.g. iptables, iptables-new, +# iptables-multiport, shorewall, etc) It is used to define +# action_* variables. Can be overridden globally or per +# section within jail.local file +banaction = iptables-multiport +banaction_allports = iptables-allports + +# The simplest action to take: ban only +action_ = %(banaction)s[port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report to the destemail. +action_mw = %(action_)s + %(mta)s-whois[sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"] + +# ban & send an e-mail with whois report and relevant log lines +# to the destemail. +action_mwl = %(action_)s + %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"] + +# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action +# +# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines +# to the destemail. +action_xarf = %(action_)s + xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"] + +# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines +# to the destemail. +action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"] + %(mta)s-whois-lines[sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"] + +# Report block via blocklist.de fail2ban reporting service API +# +# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action. +# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation +# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey` +# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in +# corresponding jail.d/my-jail.local file). +# +action_blocklist_de = blocklist_de[email="%(sender)s", service="%(__name__)s", apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"] + +# Report ban via badips.com, and use as blacklist +# +# See BadIPsAction docstring in config/action.d/badips.py for +# documentation for this action. +# +# NOTE: This action relies on banaction being present on start and therefore +# should be last action defined for a jail. +# +action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"] +# +# Report ban via badips.com (uses action.d/badips.conf for reporting only) +# +action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"] + +# Report ban via abuseipdb.com. +# +# See action.d/abuseipdb.conf for usage example and details. +# +action_abuseipdb = abuseipdb + +# Choose default action. To change, just override value of 'action' with the +# interpolation to the chosen action shortcut (e.g. action_mw, action_mwl, etc) in jail.local +# globally (section [DEFAULT]) or per specific section +action = %(action_)s + + +# +# JAILS +# + +# +# SSH servers +# + +[sshd] + +# To use more aggressive sshd modes set filter parameter "mode" in jail.local: +# normal (default), ddos, extra or aggressive (combines all). +# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details. +#mode = normal +port = ssh +logpath = %(sshd_log)s +backend = %(sshd_backend)s + + +[dropbear] + +port = ssh +logpath = %(dropbear_log)s +backend = %(dropbear_backend)s + + +[selinux-ssh] + +port = ssh +logpath = %(auditd_log)s + + +# +# HTTP servers +# + +[apache-auth] + +port = http,https +logpath = %(apache_error_log)s + + +[apache-badbots] +# Ban hosts which agent identifies spammer robots crawling the web +# for email addresses. The mail outputs are buffered. +port = http,https +logpath = %(apache_access_log)s +bantime = 48h +maxretry = 1 + + +[apache-noscript] + +port = http,https +logpath = %(apache_error_log)s + + +[apache-overflows] + +port = http,https +logpath = %(apache_error_log)s +maxretry = 2 + + +[apache-nohome] + +port = http,https +logpath = %(apache_error_log)s +maxretry = 2 + + +[apache-botsearch] + +port = http,https +logpath = %(apache_error_log)s +maxretry = 2 + + +[apache-fakegooglebot] + +port = http,https +logpath = %(apache_access_log)s +maxretry = 1 +ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot + + +[apache-modsecurity] + +port = http,https +logpath = %(apache_error_log)s +maxretry = 2 + + +[apache-shellshock] + +port = http,https +logpath = %(apache_error_log)s +maxretry = 1 + + +[openhab-auth] + +filter = openhab +banaction = %(banaction_allports)s +logpath = /opt/openhab/logs/request.log + + +[nginx-http-auth] + +port = http,https +logpath = %(nginx_error_log)s + +# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module` +# and define `limit_req` and `limit_req_zone` as described in nginx documentation +# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html +# or for example see in 'config/filter.d/nginx-limit-req.conf' +[nginx-limit-req] +port = http,https +logpath = %(nginx_error_log)s + +[nginx-botsearch] + +port = http,https +logpath = %(nginx_error_log)s +maxretry = 2 + + +# Ban attackers that try to use PHP's URL-fopen() functionality +# through GET/POST variables. - Experimental, with more than a year +# of usage in production environments. + +[php-url-fopen] + +port = http,https +logpath = %(nginx_access_log)s + %(apache_access_log)s + + +[suhosin] + +port = http,https +logpath = %(suhosin_log)s + + +[lighttpd-auth] +# Same as above for Apache's mod_auth +# It catches wrong authentifications +port = http,https +logpath = %(lighttpd_error_log)s + + +# +# Webmail and groupware servers +# + +[roundcube-auth] + +port = http,https +logpath = %(roundcube_errors_log)s +# Use following line in your jail.local if roundcube logs to journal. +#backend = %(syslog_backend)s + + +[openwebmail] + +port = http,https +logpath = /var/log/openwebmail.log + + +[horde] + +port = http,https +logpath = /var/log/horde/horde.log + + +[groupoffice] + +port = http,https +logpath = /home/groupoffice/log/info.log + + +[sogo-auth] +# Monitor SOGo groupware server +# without proxy this would be: +# port = 20000 +port = http,https +logpath = /var/log/sogo/sogo.log + + +[tine20] + +logpath = /var/log/tine20/tine20.log +port = http,https + + +# +# Web Applications +# +# + +[drupal-auth] + +port = http,https +logpath = %(syslog_daemon)s +backend = %(syslog_backend)s + +[guacamole] + +port = http,https +logpath = /var/log/tomcat*/catalina.out +#logpath = /var/log/guacamole.log + +[monit] +#Ban clients brute-forcing the monit gui login +port = 2812 +logpath = /var/log/monit + /var/log/monit.log + + +[webmin-auth] + +port = 10000 +logpath = %(syslog_authpriv)s +backend = %(syslog_backend)s + + +[froxlor-auth] + +port = http,https +logpath = %(syslog_authpriv)s +backend = %(syslog_backend)s + + +# +# HTTP Proxy servers +# +# + +[squid] + +port = 80,443,3128,8080 +logpath = /var/log/squid/access.log + + +[3proxy] + +port = 3128 +logpath = /var/log/3proxy.log + + +# +# FTP servers +# + + +[proftpd] + +port = ftp,ftp-data,ftps,ftps-data +logpath = %(proftpd_log)s +backend = %(proftpd_backend)s + + +[pure-ftpd] + +port = ftp,ftp-data,ftps,ftps-data +logpath = %(pureftpd_log)s +backend = %(pureftpd_backend)s + + +[gssftpd] + +port = ftp,ftp-data,ftps,ftps-data +logpath = %(syslog_daemon)s +backend = %(syslog_backend)s + + +[wuftpd] + +port = ftp,ftp-data,ftps,ftps-data +logpath = %(wuftpd_log)s +backend = %(wuftpd_backend)s + + +[vsftpd] +# or overwrite it in jails.local to be +# logpath = %(syslog_authpriv)s +# if you want to rely on PAM failed login attempts +# vsftpd's failregex should match both of those formats +port = ftp,ftp-data,ftps,ftps-data +logpath = %(vsftpd_log)s + + +# +# Mail servers +# + +# ASSP SMTP Proxy Jail +[assp] + +port = smtp,465,submission +logpath = /root/path/to/assp/logs/maillog.txt + + +[courier-smtp] + +port = smtp,465,submission +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[postfix] +# To use another modes set filter parameter "mode" in jail.local: +mode = more +port = smtp,465,submission +logpath = %(postfix_log)s +backend = %(postfix_backend)s + + +[postfix-rbl] + +filter = postfix[mode=rbl] +port = smtp,465,submission +logpath = %(postfix_log)s +backend = %(postfix_backend)s +maxretry = 1 + + +[sendmail-auth] + +port = submission,465,smtp +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[sendmail-reject] +# To use more aggressive modes set filter parameter "mode" in jail.local: +# normal (default), extra or aggressive +# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details. +#mode = normal +port = smtp,465,submission +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[qmail-rbl] + +filter = qmail +port = smtp,465,submission +logpath = /service/qmail/log/main/current + + +# dovecot defaults to logging to the mail syslog facility +# but can be set by syslog_facility in the dovecot configuration. +[dovecot] + +port = pop3,pop3s,imap,imaps,submission,465,sieve +logpath = %(dovecot_log)s +backend = %(dovecot_backend)s + + +[sieve] + +port = smtp,465,submission +logpath = %(dovecot_log)s +backend = %(dovecot_backend)s + + +[solid-pop3d] + +port = pop3,pop3s +logpath = %(solidpop3d_log)s + + +[exim] +# see filter.d/exim.conf for further modes supported from filter: +#mode = normal +port = smtp,465,submission +logpath = %(exim_main_log)s + + +[exim-spam] + +port = smtp,465,submission +logpath = %(exim_main_log)s + + +[kerio] + +port = imap,smtp,imaps,465 +logpath = /opt/kerio/mailserver/store/logs/security.log + + +# +# Mail servers authenticators: might be used for smtp,ftp,imap servers, so +# all relevant ports get banned +# + +[courier-auth] + +port = smtp,465,submission,imap,imaps,pop3,pop3s +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[postfix-sasl] + +filter = postfix[mode=auth] +port = smtp,465,submission,imap,imaps,pop3,pop3s +# You might consider monitoring /var/log/mail.warn instead if you are +# running postfix since it would provide the same log lines at the +# "warn" level but overall at the smaller filesize. +logpath = %(postfix_log)s +backend = %(postfix_backend)s + + +[perdition] + +port = imap,imaps,pop3,pop3s +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[squirrelmail] + +port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks +logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log + + +[cyrus-imap] + +port = imap,imaps +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +[uwimap-auth] + +port = imap,imaps +logpath = %(syslog_mail)s +backend = %(syslog_backend)s + + +# +# +# DNS servers +# + + +# !!! WARNING !!! +# Since UDP is connection-less protocol, spoofing of IP and imitation +# of illegal actions is way too simple. Thus enabling of this filter +# might provide an easy way for implementing a DoS against a chosen +# victim. See +# http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html +# Please DO NOT USE this jail unless you know what you are doing. +# +# IMPORTANT: see filter.d/named-refused for instructions to enable logging +# This jail blocks UDP traffic for DNS requests. +# [named-refused-udp] +# +# filter = named-refused +# port = domain,953 +# protocol = udp +# logpath = /var/log/named/security.log + +# IMPORTANT: see filter.d/named-refused for instructions to enable logging +# This jail blocks TCP traffic for DNS requests. + +[named-refused] + +port = domain,953 +logpath = /var/log/named/security.log + + +[nsd] + +port = 53 +action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"] + %(default/action_)s[name=%(__name__)s-udp, protocol="udp"] +logpath = /var/log/nsd.log + + +# +# Miscellaneous +# + +[asterisk] + +port = 5060,5061 +action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"] + %(default/action_)s[name=%(__name__)s-udp, protocol="udp"] +logpath = /var/log/asterisk/messages +maxretry = 10 + + +[freeswitch] + +port = 5060,5061 +action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"] + %(default/action_)s[name=%(__name__)s-udp, protocol="udp"] +logpath = /var/log/freeswitch.log +maxretry = 10 + + +# enable adminlog; it will log to a file inside znc's directory by default. +[znc-adminlog] + +port = 6667 +logpath = /var/lib/znc/moddata/adminlog/znc.log + + +# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or +# equivalent section: +# log-warnings = 2 +# +# for syslog (daemon facility) +# [mysqld_safe] +# syslog +# +# for own logfile +# [mysqld] +# log-error=/var/log/mysqld.log +[mysqld-auth] + +port = 3306 +logpath = %(mysql_log)s +backend = %(mysql_backend)s + + +# Log wrong MongoDB auth (for details see filter 'filter.d/mongodb-auth.conf') +[mongodb-auth] +# change port when running with "--shardsvr" or "--configsvr" runtime operation +port = 27017 +logpath = /var/log/mongodb/mongodb.log + + +# Jail for more extended banning of persistent abusers +# !!! WARNINGS !!! +# 1. Make sure that your loglevel specified in fail2ban.conf/.local +# is not at DEBUG level -- which might then cause fail2ban to fall into +# an infinite loop constantly feeding itself with non-informative lines +# 2. Increase dbpurgeage defined in fail2ban.conf to e.g. 648000 (7.5 days) +# to maintain entries for failed logins for sufficient amount of time +[recidive] + +logpath = /var/log/fail2ban.log +banaction = %(banaction_allports)s +bantime = 1w +findtime = 1d + + +# Generic filter for PAM. Has to be used with action which bans all +# ports such as iptables-allports, shorewall + +[pam-generic] +# pam-generic filter can be customized to monitor specific subset of 'tty's +banaction = %(banaction_allports)s +logpath = %(syslog_authpriv)s +backend = %(syslog_backend)s + + +[xinetd-fail] + +banaction = iptables-multiport-log +logpath = %(syslog_daemon)s +backend = %(syslog_backend)s +maxretry = 2 + + +# stunnel - need to set port for this +[stunnel] + +logpath = /var/log/stunnel4/stunnel.log + + +[ejabberd-auth] + +port = 5222 +logpath = /var/log/ejabberd/ejabberd.log + + +[counter-strike] + +logpath = /opt/cstrike/logs/L[0-9]*.log +tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039 +udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015 +action_ = %(default/action_)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp"] + %(default/action_)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp"] + +[softethervpn] +port = 500,4500 +protocol = udp +logpath = /usr/local/vpnserver/security_log/*/sec.log + +[gitlab] +port = http,https +logpath = /var/log/gitlab/gitlab-rails/application.log + +[grafana] +port = http,https +logpath = /var/log/grafana/grafana.log + +[bitwarden] +port = http,https +logpath = /home/*/bwdata/logs/identity/Identity/log.txt + +[centreon] +port = http,https +logpath = /var/log/centreon/login.log + +# consider low maxretry and a long bantime +# nobody except your own Nagios server should ever probe nrpe +[nagios] + +logpath = %(syslog_daemon)s ; nrpe.cfg may define a different log_facility +backend = %(syslog_backend)s +maxretry = 1 + + +[oracleims] +# see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above +logpath = /opt/sun/comms/messaging64/log/mail.log_current +banaction = %(banaction_allports)s + +[directadmin] +logpath = /var/log/directadmin/login.log +port = 2222 + +[portsentry] +logpath = /var/lib/portsentry/portsentry.history +maxretry = 1 + +[pass2allow-ftp] +# this pass2allow example allows FTP traffic after successful HTTP authentication +port = ftp,ftp-data,ftps,ftps-data +# knocking_url variable must be overridden to some secret value in jail.local +knocking_url = /knocking/ +filter = apache-pass[knocking_url="%(knocking_url)s"] +# access log of the website with HTTP auth +logpath = %(apache_access_log)s +blocktype = RETURN +returntype = DROP +action = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s, + actionstart_on_demand=false, actionrepair_on_unban=true] +bantime = 1h +maxretry = 1 +findtime = 1 + + +[murmur] +# AKA mumble-server +port = 64738 +action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"] + %(default/action_)s[name=%(__name__)s-udp, protocol="udp"] +logpath = /var/log/mumble-server/mumble-server.log + + +[screensharingd] +# For Mac OS Screen Sharing Service (VNC) +logpath = /var/log/system.log +logencoding = utf-8 + +[haproxy-http-auth] +# HAProxy by default doesn't log to file you'll need to set it up to forward +# logs to a syslog server which would then write them to disk. +# See "haproxy-http-auth" filter for a brief cautionary note when setting +# maxretry and findtime. +logpath = /var/log/haproxy.log + +[slapd] +port = ldap,ldaps +logpath = /var/log/slapd.log + +[domino-smtp] +port = smtp,ssmtp +logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log + +[phpmyadmin-syslog] +port = http,https +logpath = %(syslog_authpriv)s +backend = %(syslog_backend)s + + +[zoneminder] +# Zoneminder HTTP/HTTPS web interface auth +# Logs auth failures to apache2 error log +port = http,https +logpath = %(apache_error_log)s + +[traefik-auth] +# to use 'traefik-auth' filter you have to configure your Traefik instance, +# see `filter.d/traefik-auth.conf` for details and service example. +port = http,https +logpath = /var/log/traefik/access.log diff --git a/docker-compose/fail2ban/fail2ban--fichiers/jail.d/gitea.local b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/gitea.local new file mode 100644 index 0000000..42c5a1c --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/gitea.local @@ -0,0 +1,39 @@ +# /volume1/docker/fail2ban/jail.d/gitea.conf + +[DEFAULT] +# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not +# ban a host which matches an address in this list. Several addresses can be +# defined using space separator. +ignoreip = 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 + +# Changes the default ban action from "iptables-multiport", which causes issues on some platforms, to "iptables-allports". +banaction = iptables-allports + +# "bantime" is the number of seconds that a host is banned. +bantime = 600 + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 600 + +# "maxretry" is the number of failures before a host get banned. +maxretry = 5 + +destemail = email@gmail.com +sender = email@gmail.com +sendername = Fail2Ban +action = %(action_mwl)s + +backend = auto + + +[gitea] +enabled = true + +# Doit correspondre au nom du fichier .conf dans le dossier filter.d +filter = gitea + +logpath = /gitea/gitea.log +maxretry = 10 +findtime = 3600 +bantime = 900 \ No newline at end of file diff --git a/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden-admin.local b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden-admin.local new file mode 100644 index 0000000..553bdce --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden-admin.local @@ -0,0 +1,37 @@ +# /volume1/docker/fail2ban/jail.d/vaultwarden-admin.conf + +[DEFAULT] +# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not +# ban a host which matches an address in this list. Several addresses can be +# defined using space separator. +ignoreip = 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 + +# Changes the default ban action from "iptables-multiport", which causes issues on some platforms, to "iptables-allports". +banaction = iptables-allports + +# "bantime" is the number of seconds that a host is banned. +bantime = 600 + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 600 + +# "maxretry" is the number of failures before a host get banned. +maxretry = 5 + +destemail = email@gmail.com +sender = email@gmail.com +sendername = Fail2Ban +action = %(action_mwl)s + +backend = auto + + +[vaultwarden-admin] +enabled = true +port = 882,3012 + +# Doit correspondre au nom du fichier .conf dans le dossier filter.d +filter = vaultwarden-admin + +logpath = /vaultwarden/vaultwarden.log \ No newline at end of file diff --git a/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden.local b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden.local new file mode 100644 index 0000000..51231d0 --- /dev/null +++ b/docker-compose/fail2ban/fail2ban--fichiers/jail.d/vaultwarden.local @@ -0,0 +1,37 @@ +# /volume1/docker/fail2ban/jail.d/vaultwarden.conf + +[DEFAULT] +# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not +# ban a host which matches an address in this list. Several addresses can be +# defined using space separator. +ignoreip = 172.16.0.0/12 192.168.0.0/16 10.0.0.0/8 + +# Changes the default ban action from "iptables-multiport", which causes issues on some platforms, to "iptables-allports". +banaction = iptables-allports + +# "bantime" is the number of seconds that a host is banned. +bantime = 600 + +# A host is banned if it has generated "maxretry" during the last "findtime" +# seconds. +findtime = 600 + +# "maxretry" is the number of failures before a host get banned. +maxretry = 5 + +destemail = email@gmail.com +sender = email@gmail.com +sendername = Fail2Ban +action = %(action_mwl)s + +backend = auto + + +[vaultwarden] +enabled = true +port = 882,3012 + +# Doit correspondre au nom du fichier .conf dans le dossier filter.d +filter = vaultwarden + +logpath = /vaultwarden/vaultwarden.log \ No newline at end of file diff --git a/docker-compose/ghost/docker-compose.yml b/docker-compose/ghost/docker-compose.yml new file mode 100644 index 0000000..36b6274 --- /dev/null +++ b/docker-compose/ghost/docker-compose.yml @@ -0,0 +1,26 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-04-20 + +version: '3.8' + +services: + ghost: + container_name: ghost + image: ghost:4-alpine +# Decommenter les 2 lignes suivantes pour que watchtower surveille ce conteneur +# labels: +# - com.centurylinklabs.watchtower.enable=true + networks: + - ghost-network + restart: always + ports: + - 2368:2368 + volumes: + - /mnt/volume1/docker/ghost/content:/var/lib/ghost/content + environment: + url : http://192.168.1.10:2368 + +networks: + ghost-network: + external: + name: ghost-network \ No newline at end of file diff --git a/docker-compose/gitea/Changer-Theme-Gitea.md b/docker-compose/gitea/Changer-Theme-Gitea.md new file mode 100644 index 0000000..0e83101 --- /dev/null +++ b/docker-compose/gitea/Changer-Theme-Gitea.md @@ -0,0 +1,171 @@ +Changer le thème de Gitea +============ +--- +> :pencil2: **Mise à jour :** Ajout de la possibilité de changer le style dans le menu `Configuration / Comptes / Sélectionner le thème par défaut` pour les thèmes Gitea de [theme.park](https://github.com/gilbN/theme.park/wiki/Gitea).
+*Voir* [§ 2. Ajouter les différents thèmes en laissant le choix à l'utilisateur](#2-ajouter-les-différents-thèmes-en-laissant-le-choix-à-l-utilisateur) +--- + +:arrow_forward: Vous pouvez trouver quelques thèmes ici : https://gitea.com/gitea/awesome-gitea#themes + +:book: Dans la suite de ce tuto, on ne parlera que des thèmes Gitea de [theme.park](https://github.com/gilbN/theme.park/wiki/Gitea). + +## Table des matières +- [1. Modifier le thème sans laisser le choix à l'utilisateur](#1-modifier-le-thème-sans-laisser-le-choix-à-l-utilisateur) + - [1.1. Installer le thème](#1-1-installer-le-thème) + - [1.2. Exemple avec le dernier lien du dépôt donnée précédemment](#1-2-exemple-avec-le-dernier-lien-du-dépôt-donnée-précédemment) + - [1.2.1. Installer le thème (imposé pour tous)](#1-2-1-installer-le-thème-imposé-pour-tous) + - [1.2.2. Changer le thème](#1-2-2-changer-le-thème) +- [2. Ajouter les différents thèmes en laissant le choix à l'utilisateur](#2-ajouter-les-différents-thèmes-en-laissant-le-choix-à-l-utilisateur) + - [2.1. Création des dossiers dans `/volume1/docker/gitea/data/`](#2-1-création-des-dossiers-dans-volume1-docker-gitea-data) + - [2.2. Télécharger les différents css](#2-2-télécharger-les-différents-css) + - [2.3. Création du fichier `header.tmpl`](#2-3-création-du-fichier-header-tmpl) + - [2.4. Modification du fichier `/data/gitea/conf/app.ini`](#2-4-modification-du-fichier-data-gitea-conf-app-ini) + - [2.4.1. Point info sur la modification de ce fichier](#2-4-1-point-info-sur-la-modification-de-ce-fichier) + - [2.4.2. Ce qu'il faut ajouter au fichier `/data/gitea/conf/app.ini`](#2-4-2-ce-qu-il-faut-ajouter-au-fichier-data-gitea-conf-app-ini) + - [2.4.3. Redémarrer le conteneur](#2-4-3-redémarrer-le-conteneur) + - [2.5. Choisir son thème dans l'interface graphique de Gitea](#2-5-choisir-son-thème-dans-l-interface-graphique-de-gitea) + +# 1. Modifier le thème sans laisser le choix à l'utilisateur + +## 1.1. Installer le thème + +Il faut vérifier si la variable GITEA_CUSTOM a été paramétrée. En temps normal, ce n'est pas le cas. + +Si ce n'est pas le cas, on peut aller vérifier le chemin qui est paramétré pour le dossier dit CUSTOM de gitea. Pour celà, il faut aller ici :
+`https://url-de-votre-gitea.tlds/admin/config` + +Puis chercher la ligne `GITEA_CUSTOM` où apparaîtra le chemin d'accès : `/data/gitea`. + +Dans le cas d'une installation Docker, ça donnerait ceci : `/docker/gitea/data/gitea` +
(voir le fichier **docker-compose.yml** pour le chemin d'accès avant le `/data/gitea`) + +Il faudra alors créer les dossiers suivants : + +- `public` +- `templates` +- `templates/custom` + +Puis il faudra suivre les instructions du thème choisi. Pour ceux qui n'auraient pas d'instructions, le fichier `styles.css` devra se trouver dans le dossier `public`. + +## 1.2. Exemple avec le dernier lien du dépôt donnée précédemment + +### 1.2.1. Installer le thème (imposé pour tous) + +Je vais prendre le dernier lien présent dans le dépôt donné avant la table des matières. + +> - [theme.park](https://github.com/gilbN/theme.park/wiki/Gitea) - A theme suite for Gitea. + +Dans ce nouveau dépôt ( https://github.com/gilbN/theme.park/wiki/Gitea ) vous trouverez plusieurs thèmes. + +Je trouve les thèmes plex, dark et space-gray relativement sympas. +Des captures sont présentes plus bas dans la page : https://github.com/gilbN/theme.park/wiki/Gitea#screenshots + +Il faut créer deux fichiers : + +- `public/styles.css` qui contient (avec des commentaires perso) : +```css +/* Source : https://github.com/gilbN/theme.park/wiki/Gitea + Possibilités : https://gilbn.github.io/theme.park/CSS/themes/gitea/XXX.css + aquamarine.css <--- pas terrible + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP + organizr-dark.css +*/ +@import url("https://gilbn.github.io/theme.park/CSS/themes/gitea/plex.css"); +``` + +- `templates/custom/header.tmpl` qui contient : +```html + +``` +Une fois les fichiers créés et placés dans ces dossiers (faire attention aux permissions), il suffit de redémarrer Gitea (ou le conteneur si installation en Docker). + +### 1.2.2. Changer le thème + +Pour changer le thème, il suffit de : + +- modifier le `public/styles.css` avec le nom du css désiré ; +- redémarrer Gitea ; +- ne pas oublier de vider le cache du navigateur... sinon le nouveau thème ne sera pas visible... (ça m'a pris 15 minutes d'essais et au bout de ce temps l'utilisation d'un autre navigateur pour le comprendre...). + +--- +--- + +# 2. Ajouter les différents thèmes en laissant le choix à l'utilisateur + +> :memo: Cette partie devrait être compatible avec d'autres thèmes qui n'apportent qu'un seul fichier `.css`. ***À confirmer...*** + +## 2.1. Création des dossiers dans `/volume1/docker/gitea/data/` + +- Il faut vérifier si la variable GITEA_CUSTOM a été paramétrée. En temps normal, ce n'est pas le cas. + +- Si ce n'est pas le cas, on peut aller vérifier le chemin qui est paramétré pour le dossier dit CUSTOM de gitea. Pour celà, il faut aller ici : +`https://url-de-votre-gitea.tlds/admin/config` + +- Puis chercher la ligne `GITEA_CUSTOM` où apparaîtra le chemin d'accès : `/data/gitea`. + +- Dans le cas d'une installation Docker, ça donnerait ceci : `/docker/gitea/data/gitea` +
(voir le fichier **docker-compose.yml** pour le chemin d'accès avant le `/data/gitea`) + +- Il faudra alors créer les dossiers suivants : + + - `public` + - `public/css` + - `templates` + - `templates/custom` + +## 2.2. Télécharger les différents css + +- Télécharger les différents thèmes .css ici : https://github.com/gilbN/theme.park/tree/master/CSS/themes/gitea. +*(Ne pas les renommer.)* +- Placer ces fichiers dans le dossier `...public/css` créé précédemment. + +## 2.3. Création du fichier `header.tmpl` + +- Créer le fichier `header.tmpl` et l'enregistrer dans le dossier `.../templates/custom/` créé précédemment. +```html + + +``` + +## 2.4. Modification du fichier `/data/gitea/conf/app.ini` + +### 2.4.1. Point info sur la modification de ce fichier + +Pour modifier ce fichier, il se peut que vous n'ayez pas les permissions d'enregistrer les modifications apportées... Il faudra alors le copier ailleurs, faire les modifications et sauvegarder, puis re-copier dans l'autre sens le fichier dans son dossier d'origine. + +C'est ce que je dois faire. Depuis une ligne de commande SSH, je fais : +- Je copie le fichier dans un dossier où mon utilisateur Admin à les droits en écriture (je ne me logue pas avec l'utilisateur choisir pour Gitea) :
`cp /volume1/docker/gitea/data/gitea/conf/app.ini /volume1/docker/gitea/` +- Je modifie et sauvegarde mon fichier... +- puis je copie en retour le fichier modifier : `cp /volume1/docker/gitea/app.ini /volume1/docker/gitea/data/gitea/conf/` +- Il faut ensuite relancer le conteneur Gitea avec Portainer/DSM ou en CLI : `docker restart gitea` + +### 2.4.2. Ce qu'il faut ajouter au fichier `/data/gitea/conf/app.ini` + +Il faut ajouter ceci au fichier `app.ini` : + +```ini +[ui] +THEMES = gitea,arc-green,plex,aquamarine,dark,hotline,organizr-dark,space-gray +DEFAULT_THEME = arc-green +``` +> :memo: Note : Il se peut que la section `[ui]` soit déjà présente dans votre `app.ini`, il faudra alors modifier la ligne `THEMES`. + +### 2.4.3. Redémarrer le conteneur + +Il faut bien penser à redémarrer le conteneur. + +## 2.5. Choisir son thème dans l'interface graphique de Gitea + +![](https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/docker-compose/gitea/tuto-1.png) + +![](https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/docker-compose/gitea/tuto-2.png) + +![](https://gitea.zoz-serv.org/Zoz/plex_fr_discord_repo/raw/branch/master/docker-compose/gitea/tuto-3.png) + + +--- + +Voilà, c'est la fin :D \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/aquamarine.css b/docker-compose/gitea/data--gitea/public/css/aquamarine.css new file mode 100644 index 0000000..108b110 --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/aquamarine.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/aquamarine.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/dark.css b/docker-compose/gitea/data--gitea/public/css/dark.css new file mode 100644 index 0000000..4704d46 --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/dark.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/dark.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/hotline.css b/docker-compose/gitea/data--gitea/public/css/hotline.css new file mode 100644 index 0000000..a055f0b --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/hotline.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/hotline.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/organizr-dark.css b/docker-compose/gitea/data--gitea/public/css/organizr-dark.css new file mode 100644 index 0000000..a9387eb --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/organizr-dark.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/organizr-dark.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/plex.css b/docker-compose/gitea/data--gitea/public/css/plex.css new file mode 100644 index 0000000..20705c0 --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/plex.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/plex.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/css/space-gray.css b/docker-compose/gitea/data--gitea/public/css/space-gray.css new file mode 100644 index 0000000..24f8526 --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/css/space-gray.css @@ -0,0 +1,23 @@ +/* dP dP dP */ +/* 88 88 88 */ +/* d8888P 88d888b. .d8888b. 88d8b.d8b. .d8888b. 88d888b. .d8888b. 88d888b. 88 .dP */ +/* 88 88' `88 88ooood8 88'`88'`88 88ooood8 88' `88 88' `88 88' `88 88888" */ +/* 88 88 88 88. ... 88 88 88 88. ... 88. .88 88. .88 88 88 `8b. */ +/* dP dP dP `88888P' dP dP dP `88888P' 88 88Y888P' `88888P8 dP dP `YP */ +/* 88 */ +/* dP */ + +/* Made by @gilbN */ +/* https://github.com/gilbN/theme.park */ + +/* Source : https://docs.theme-park.dev/themes/gitea/ + Possibilités : https://theme-park.dev/CSS/themes/gitea/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ + +@import url("https://theme-park.dev/CSS/themes/gitea/space-gray.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/public/styles.css b/docker-compose/gitea/data--gitea/public/styles.css new file mode 100644 index 0000000..0230abf --- /dev/null +++ b/docker-compose/gitea/data--gitea/public/styles.css @@ -0,0 +1,10 @@ +/* Source : https://github.com/gilbN/theme.park/wiki/Gitea + Possibilités : https://gilbn.github.io/theme.park/CSS/themes/gitea/XXX.css + aquamarine.css <--- Pas mal celui là. + hotline.css + plex.css <--- TOP + dark.css <--- TOP + space-gray.css <--- TOP, mon préféré ! + organizr-dark.css +*/ +@import url("https://gilbn.github.io/theme.park/CSS/themes/gitea/space-gray.css"); \ No newline at end of file diff --git a/docker-compose/gitea/data--gitea/templates/custom/header.tmpl b/docker-compose/gitea/data--gitea/templates/custom/header.tmpl new file mode 100644 index 0000000..a7d6809 --- /dev/null +++ b/docker-compose/gitea/data--gitea/templates/custom/header.tmpl @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/docker-compose/gitea/docker-compose.yml b/docker-compose/gitea/docker-compose.yml new file mode 100644 index 0000000..d9ef8b5 --- /dev/null +++ b/docker-compose/gitea/docker-compose.yml @@ -0,0 +1,94 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-04-19 +##============================================================================================== +## ## +## Fichier docker-compose.yml pour Gitea ## +## ## +##============================================================================================== +## ## +## Pour que Gitea fonctionne correctement et que l'on puisse faire des git clone depuis ## +## un ordinateur, il faut un nom de domaine ! Je n'ai pas trouver comment faire sans... ## +## ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## ## +## Pense-bête pour la configuration du serveur : ## +## ## +## - URL locale d'accès (pour l'installation): http://192.168.xxx.xxxx:8196 ## +## - URL d'accès : https://gitea.ndd.tld ## +## - Parmètres emailer : ## +## - ENABLED = true ## +## - HOST = smtp.gmail.com:465 ## +## - FROM = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx ## +## - USER = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx ## +## - PASSWD = xxxxxxxxxxxxxxxxxxxxxxxxxxxxx ## +## - MAILER_TYPE = smtp ## +## - IS_TLS_ENABLED = true ## +## ## +##============================================================================================== + +--- +version: "2.4" + +services: + server: + image: gitea/gitea:1 # On reste ici avec la dernière version stable de la branche 1.x.x + # https://docs.gitea.io/en-us/install-with-docker/ + # https://docs.gitea.io/fr-fr/install-with-docker/ + # https://github.com/go-gitea/gitea + container_name: gitea + + #network_mode: "bridge" + networks: + - gitea_network + + environment: + - USER_UID=1000 # Utiliser la commande : id user + - USER_GID=100 # Utiliser la commande : id user + - APP_NAME=Mon Gitea perso + - RUN_MODE=prod + + # Les deux paramètres ci-dessous ne semblent pas fonctionner puisqu'il faut faire manuellement le réglage lors du setup... + - REQUIRE_SIGNIN_VIEW=true # Enable this to force users to log in to view any page. + - DISABLE_REGISTRATION=true # Disable registration, after which only admin can create accounts for users. + + - DOMAIN=gitea.ndd.tld + - SSH_DOMAIN=gitea.ndd.tld + - ROOT_URL=https://gitea.ndd.tld + - DB_TYPE=sqlite3 + - DB_HOST=localhost:3306 + - DB_NAME=gitea + - DB_USER=root + - DB_PASSWD="gitea_db_blabla" + + - INSTALL_LOCK=false # Disallow access to the install page + # À passer en true une fois installer la première fois. + - GITEA__PICTURE__DISABLE_GRAVATAR=true + - GITEA__PICTURE__ENABLE_FEDERATED_AVATAR=false + + - GITEA__SERVICE__REGISTER_EMAIL_CONFIRM=true # Ne semble pas fonctionner puisqu'il faut cocher manuellement la case lors du setup... + - GITEA__SERVICE__ENABLE_NOTIFY_MAIL=true # Ne semble pas fonctionner puisqu'il faut cocher manuellement la case lors du setup... + + + # ############### + # Le label ci-dessous permet à Watchtower de faire les mises à jour automatiquement + # Cela peut-être supprimé si Watchtower n'est pas utilisé. + labels: + - "com.centurylinklabs.watchtower.enable=true" + # ############### + + volumes: + - "/volume1/docker/gitea/data:/data" # Dossier pour les données de Gitea (Dépôts, BDD, config...) + - "/volume1/docker/gitea/backup-data:/backup-data" # Dossier pour les sauvegardes régulières à lancer avec un script en tâche planifiée. + - "/etc/localtime:/etc/localtime:ro" # Nécessaire pour avoir le temps local correct (vu que la variable TZ=Europe/Paris n'existe pas pour ce conteneur...) + + ports: + - "8196:3000" # Choisir un port de connexion libre sur votre machine, ce sera la port de connexion pour l'interface graphique + # - "8197:22" # Idem ici, sauf que ce sera pour le port SSH, mais ça ne fonctionne pas avec une installation en Bridge... + + restart: unless-stopped + +networks: + gitea_network: + external: false + driver: bridge + name: gitea_network \ No newline at end of file diff --git a/docker-compose/gitea/gitea-backup.sh b/docker-compose/gitea/gitea-backup.sh new file mode 100644 index 0000000..9f0c625 --- /dev/null +++ b/docker-compose/gitea/gitea-backup.sh @@ -0,0 +1,272 @@ +#!/bin/bash +##============================================================================================== +## ## +## Script gitea-backup.sh ## +## ## +##============================================================================================== +## ## +## gitea-backup.sh [] ## +## est facultatif. S'il n'est pas spécifié, on fait les deux ! ## +## = gitea_dump ## +## = archive_dossier ## +## ## +##============================================================================================== + +##============================================================================================== +## ## +## MAJ du 19.04.2021 : La partie de sauvegarde gite_dump a été commentée, et n'est donc ## +## plus utilisée, car la restauration de cette archive est trop galère à mettre en place. ## +## Donc soit on ne donne aucun paramètre en argument au script, soit on met archive_dossier. ## +## L'autre paramètre n'aura donc plus aucun effet. ## +## ## +##============================================================================================== + +##============================================================================================== +## ## +## Objectif du script : faire une sauvegarde de l'installation Gitea @ Docker ## +## Il y a aura un shutdown du conteneur le temps de la sauvegarde afin que la base de ## +## données ne soit pas modifiée pendant le backup, puis le conteneur sera redémarré. ## +## ## +## Il faudra créer une tâche planifiée pour lancer la sauvegarde toutes les nuits, par ## +## exemple à 3h du matin. ## +## ## +##============================================================================================== +## ## +## Une méthode officielle de backup de la base de données est présente ici : ## +## https://docs.gitea.io/en-us/backup-and-restore/#backup-command-dump ## +## ## +##============================================================================================== + + + +# Récupération des arguments qu'on place dans des variables constantes +declare -r nb_arg=$# # Nombre d'argument(s) fourni(s) au script. +declare -r methode="$1" # 1er argument fourni + +if [ "$methode" = "--help" ] || [ "$methode" = "-help" ] || [ "$methode" = "-h" ] || [ "$methode" = "--h" ]; then + echo "Le script gitea-backup.sh permet de faire une sauvegarde des données du conteneur Gitea." + echo "Utilisation : gitea-backup.sh []" + echo "L'argument est facultatif. S'il n'est pas spécifié, on fait les deux !" + echo " = gitea_dump" + echo " = archive_dossier" + echo + exit 0 +fi + +mode_backup=0 # 0 = aucune méthode indiquée ; 1 = gitea_dump ; 2 = archive_dossier + +##──── ──────────────────────────────────────────────────────────────────────────────────────── +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## ## +## VALEURS À PERSONNALISER ## +## ## +## Chemin d'accès vers votre dossier docker et vers le dossier de backup de gitea ## + +# Chemin du dossier qui contient le dossier des données (data) et des backups (backup-data) +GITEA_DOCKER_DIR=/volume1/docker/gitea + +# Les noms des dossiers montés dans le conteneur doivent êtres identiques à ceux présents sur la machine hôte. Sinon faudra modifier le script... +# Nom du dossier contenant les backups qui doit exister car il doit être monté dans le conteneur à l'aide du docker-compose.yml. +GITEA_BACKUP_DIR=backup-data + +# Nom du dossier contenant les donneés de Gitea (data) +GITEA_DATA_DIR=data + +# Nom du conteneur +NOM_CONTENEUR=gitea + +# ID de l'utilisateur du NAS qui a les droits sur le conteneur +ID_USER_NAS=1060 + +# Nombre de jours d'archives-backup à garder (ça inclus le jour actuel) +NB_JOURS_A_GARDER=10 + +##──── ──────────────────────────────────────────────────────────────────────────────────────── +##──── ──────────────────────────────────────────────────────────────────────────────────────── + +function pause() { + read -p "$*" +} + +echo "$(date "+%R:%S - ") Script de sauvegarde des données du conteneur Gitea" + + +##============================================================================================== +## Vérification de la présence des dossiers du conteneur ## + +cd $GITEA_DOCKER_DIR +num_erreur=$? # On stocke le code de retour de la commande précédente. +if [ $num_erreur -ne 0 ]; then # Si ce code n'est pas 0, il y a eu une erreur, on arrète le script. + echo " Le chemin '$GITEA_DOCKER_DIR' est invalide ! Veuillez vérifier le chemin d'accès..." + echo " Abandon, avec code d'erreur $num_erreur" + exit $num_erreur +fi + +dossier_manquant="" +if [ ! -d "$GITEA_BACKUP_DIR" ]; then + dossier_manquant = "$GITEA_BACKUP_DIR" +fi +if [ ! -d "$GITEA_DATA_DIR" ]; then + dossier_manquant = dossier_manquant + " ; $GITEA_DATA_DIR" +fi +if [ "$dossier_manquant" != "" ]; then + echo " Le(s) dossier(s) suivant(s) n'existe(nt) pas : $dossier_manquant ." + echo " Abandon, avec code d'erreur 999." + exit 999 +else + echo "-- Les dossiers $GITEA_BACKUP_DIR et $GITEA_DATA_DIR existent bien. Le script peut continuer." +fi + +# Autre méthode, effectuant davantage de tests... donc moins efficace... +# if [ ! -d "$GITEA_BACKUP_DIR" ] || [ ! -d "$GITEA_DATA_DIR" ]; then # Au moins un des dossiers n'existe pas +# if [ ! -d "$GITEA_BACKUP_DIR" ]; then # Le dossier $GITEA_BACKUP_DIR n'existe pas ! +# echo " Le dossier '$GITEA_BACKUP_DIR' n'existe pas !" +# fi +# if [ ! -d "$GITEA_DATA_DIR" ]; then # Le dossier $GITEA_DATA_DIR n'existe pas ! +# echo " Le dossier '$GITEA_DATA_DIR' n'existe pas !" +# fi +# echo " Abandon, avec code d'erreur 999" +# exit 999 +# else +# echo "-- Les dossiers $GITEA_BACKUP_DIR et $GITEA_DATA_DIR existent bien. On peut continuer." +# fi +##============================================================================================== + + +##============================================================================================== +## ## +## Définition du mode de backup à faire en fonction de la méthode donnée en argument ## +case $methode in + gitea_dump) # Méthode gitea_dump sélectionnée ## + mode_backup=1 + #echo "mode_backup=$mode_backup" + ;; + + archive_dossier) # Méthode archive_dossier sélectionnée ## + mode_backup=2 + #echo "mode_backup=$mode_backup" + ;; + + *) # Aucune méthode sélectionnée ## + mode_backup=0 + #echo "mode_backup=$mode_backup" + ;; +esac +##============================================================================================== + + +##============================================================================================== +## ## +## Partie concernant les sauvegardes ## +# if [ $mode_backup -eq 0 ] || [ $mode_backup -eq 1 ]; then +# # Aucune méthode n'est choisie ou bien méthode gitea_dump sélectionnée + +# # Rappel des variables : +# # GITEA_DOCKER_DIR=/volume1/docker/gitea +# # GITEA_BACKUP_DIR=backup-data +# # GITEA_DATA_DIR=data +# # NOM_CONTENEUR=gitea +# # ID_USER_NAS=1060 + +# echo "-- Sauvegarde via Gitea dump. (un peu chiant à restaurer...)" +# echo "###############################################################################" +# # Dans la commande suivante, les chemins d'accès donnés en paramètres sont des chemins d'accès à l'intérieur du conteneur, montés avec le docker-compose.yml. +# # Exemple de commande sans variables : +# # docker exec -u 1060 -i -w /backup-data $(docker ps -qf "name=^gitea$") bash -c '/app/gitea/gitea dump -c /data/gitea/conf/app.ini' +# # Note : La commande lancée dans une tâche CRON (planifiée) ne permet pas l'utilisation du paramètre -t. +# # Commande à lancer dans un terminal : +# # docker exec -u 1060 -i -w /backup-data $(docker ps -qf "name=^gitea$") bash -c '/app/gitea/gitea dump -c /data/gitea/conf/app.ini' +# # Explication pour $(docker ps -qf "name=^gitea$") ici : https://stackoverflow.com/a/34497614 + +# docker exec -u $ID_USER_NAS -i -w /$GITEA_BACKUP_DIR $(docker ps -qf "name=^$NOM_CONTENEUR$") bash -c "/app/gitea/gitea dump -c /$GITEA_DATA_DIR/gitea/conf/app.ini" +# num_erreur=$? # On stocke le code de retour de la commande précédente. +# if [ $num_erreur -ne 0 ]; then # Si ce code n'est pas 0, il y a eu une erreur, on arrète le script. +# echo "!!!!!! Erreur lors de la commande de backup gitea dump." +# #echo "!!!!!! Commande lancée :" +# #echo " docker exec -u $ID_USER_NAS -it -w /$GITEA_BACKUP_DIR $(docker ps -qf "name=$NOM_CONTENEUR") bash -c "/app/gitea/gitea dump -c /$GITEA_DATA_DIR/gitea/conf/app.ini"" +# echo "!!!!!! Abandon, avec code d'erreur $num_erreur" +# exit $num_erreur +# fi +# echo "###############################################################################" +# echo "-- Sauvegarde via Gitea dump terminée." +# fi + + +if [ $mode_backup -eq 0 ] || [ $mode_backup -eq 2 ]; then + # Aucune méthode n'est choisie ou bien méthode archive_dossier sélectionnée + echo "-- Sauvegarde par création d'une archive de tout le dossier $GITEA_DATA_DIR" + echo "###############################################################################" + cd $GITEA_DOCKER_DIR # Même si on est censé déjà être là... + + #retour_cmd=1111 # Valeur reset + echo "-- Extinction du conteneur $(docker stop $NOM_CONTENEUR) : OK." + # retour_cmd=$? # Le code d'exit de la fonction est stocké dans cette variable. + # if [ $retour_cmd -ne 0 ]; then + # if [ $retour_cmd -eq 1111 ]; then + # echo "### DEBUG : soucis avec la récupération du retour de commande #1470000 " + # exit 1470000 + # fi + # echo "!! Le conteneur $NOM_CONTENEUR ne peut pas être arrêté..." + # echo "!! Fin du script. Erreur 777" + # echo + # exit 777 + # fi + echo "-- Création de l'archive du dossier $GITEA_DATA_DIR" + + # Compression tar.gz : + #tar -czf $GITEA_BACKUP_DIR/Gitea-Data-Backup-`date +%Y-%m-%d--%Hh%Mm%Ss`.tar.gz ./$GITEA_DATA_DIR + + # Compression 7z après obtention d'un .tar + # On Linux/Unix, in order to backup directories you must use tar : + # - to backup a directory : tar cf - directory | 7z a -si directory.tar.7z + # - to restore your backup : 7z x -so directory.tar.7z | tar xf - + tar cf - ./$GITEA_DATA_DIR | 7z a -si $GITEA_BACKUP_DIR/Gitea-Data-Backup-`date +%Y-%m-%d--%Hh%Mm%Ss`.7z + + echo "-- Archive de tout le dossier $GITEA_DATA_DIR créée." + + # retour_cmd=1111 # Valeur reset + echo "-- Redémarrage du conteneur $(docker start $NOM_CONTENEUR) : OK." + # retour_cmd=$? # Le code d'exit de la fonction est stocké dans cette variable. + # if [ $retour_cmd -ne 0 ]; then + # if [ $retour_cmd -eq 1111 ]; then + # echo "### DEBUG : soucis avec la récupération du retour de commande #1470000 " + # exit 1470000 + # fi + # echo "!! Le conteneur $NOM_CONTENEUR ne peut pas être redémarré..." + # echo "!! Fin du script. Erreur 777" + # echo + # exit 777 + # fi + + # Section concernant la rotation des sauvegardes. + echo + echo "-- Rotation des sauvegardes anciennes selon le nombre de jours d'archives à garder (=$NB_JOURS_A_GARDER) incluant ce jour :" + echo + echo + echo "-- -- Utilisation de la fonction find pour trouver les fichiers de plus de $nb_jours_a_garder jours (incluant ce jour)." + echo "-- -- Les fichiers suivants seront supprimés :" + find $GITEA_BACKUP_DIR/* -name 'Gitea-Data-Backup*' -mtime +"$((NB_JOURS_A_GARDER - 1))" -exec ls -lat --color {} \; + + # Utile pour débugguer avant de supprimer réellement les fichiers. + #pause '--DEBUG-- Appuyer sur la touche [Entrer] pour continuer...' + + echo "-- -- Suppression de ces fichiers..." + find $GITEA_BACKUP_DIR/* -name 'Gitea-Data-Backup*' -mtime +"$((NB_JOURS_A_GARDER - 1))" -exec rm -v {} \; + + ############################################################ + # Cette partie peut être commentée + echo + echo "-- -- Il reste donc les fichiers suivants :" + ls -lat --color $GITEA_BACKUP_DIR/Gitea-Data-Backup* + ############################################################ + + + echo "###############################################################################" + echo "-- Processus de sauvegarde par création d'archive terminé." + +fi + +echo "$(date "+%R:%S - ") Fin du script de sauvegarde des donneés du conteneur Gitea" +exit 0 +## ## +##============================================================================================== \ No newline at end of file diff --git a/docker-compose/gitea/gitea-restore.sh b/docker-compose/gitea/gitea-restore.sh new file mode 100644 index 0000000..ee9562b --- /dev/null +++ b/docker-compose/gitea/gitea-restore.sh @@ -0,0 +1,368 @@ +##============================================================================================== +## ## +## Script gitea-restore.sh ## +## ## +##============================================================================================== +## ## +## gitea-restore.sh ## +## = --gitea_dump ou --gdmp ## +## = --archive_dossier ou --ad ## +## = le nom du fichier archive à utiliser pour la restauration. ## +## Ne peut être qu'un .zip pour la méthode --gitea_dump, ## +## ou bien ## +## ne peut être qu'un .tar.gz pour la méthode --archive_dossier # +## Il faut impérativement donner le chemin d'accès complet de ce fichier archive... ## +## ## +##============================================================================================== + +##============================================================================================== +## ## +## Objectif du script : Restaurer la sauvegarde de Gitea passée en paramètre ## +## Il faudra indiquer la méthode de restauration basée sur le type de sauvegarde à restaurer. ## +## Il faudra également indiquer l'archive à utiliser pour la restauration. ## +## ## +##============================================================================================== +## ## +## Une méthode officielle de restauration, de la base de données est présente ici : ## +## https://docs.gitea.io/en-us/backup-and-restore/#restore-command-restore ## +## ## +##============================================================================================== + +##============================================================================================== +## ## +## MAJ du 19.04.2021 : La partie de sauvegarde gite_dump ne sera pas programmée car c'est ## +## trop galère à mettre en place. ## +## Donc soit on ne donne aucun paramètre en argument au script, soit on met archive_dossier. ## +## L'autre paramètre n'aura donc plus aucun effet. Ne pas l'utiliser ! ## +## Cependant le code pour distinguer les deux paramètres reste, mais il n'y aura rien dans ## +## la partie gitea_dump. ## +## ## +##============================================================================================== + + +# Récupération des arguments qu'on place dans des variables constantes +declare -r nb_arg=$# # Nombre d'argument(s) fourni(s) au script. +declare -r methode="$1" # 1er argument fourni +declare -r fichier="$2" # 2ème argument fourni +declare -r tous_les_args="$*" # Tous les arguments + +##============================================================================================== +## VALEURS À PERSONNALISER ## +## ## +## Chemin d'accès vers votre dossier docker et vers le dossier de backup de gitea ## +##============================================================================================== +# Chemin complet du dossier qui contient le dossier des données (data) et des backups (backup-data) +GITEA_DOCKER_DIR=/volume1/docker/gitea + +# Les noms des dossiers montés dans le conteneur doivent êtres identiques à ceux présents sur la machine hôte. Sinon faudra modifier le script... +# Nom du dossier contenant les backups qui doit exister car il doit être monté dans le conteneur à l'aide du docker-compose.yml. +GITEA_BACKUP_DIR=backup-data + +# Nom du dossier contenant les donneés de Gitea (data) +GITEA_DATA_DIR=data + +# Nom du conteneur +NOM_CONTENEUR=gitea + +# ID de l'utilisateur du NAS qui a les droits sur le conteneur +ID_USER_NAS=1000 +##============================================================================================== +##============================================================================================== + +echo +echo "Le script gitea-restore.sh permet de faire une restauration des données du conteneur Gitea." +echo + +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## Début de la section concernant les fonctions ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── + +f_affiche_syntaxe(){ + # Fonction pour afficher la syntaxe d'utilisation du fichier script. + # syntax: f_affiche_syntaxe [] + # 1er paramètre : $1 + # 2nd paramètre éventuel : $2 Ce sera ce qui a été fourni en argument du script. + local f_nb_arg=$# + local f_param_1=$1 + local f_param_2=$2 + echo + if [ "$f_param_1" = "#1" ]; then + echo "La méthode de restauration choisie '$f_param_2' est incorrecte." + echo + elif [ "$f_param_1" = "#2" ]; then + if [ -z "$f_param_2" ]; then + echo "Aucun paramètre n'a été fourni au script..." + else + echo "Le nombre de paramètre fourni n'est pas correct. Paramètres fournis : '$f_param_2'" + fi + echo + fi + echo "Utilisation : gitea-restore.sh " + #echo " * : --gitea_dump ou --gdmp pour utiliser la méthode gitea dump." + + echo " * : --archive_dossier ou --ad pour utiliser la méthode archive dossier." + echo " * : le nom du fichier archive à utiliser pour la restauration." + #echo " Ne peut être qu'un .zip pour la méthode --gitea_dump," + #echo " ou bien ne peut être qu'un .7z ou .tar.gz pour la méthode --archive_dossier" + echo " Ne peut être qu'un .7z ou un .tar.gz pour la méthode --archive_dossier." + echo " Il faut impérativement donner le chemin d'accès complet de ce fichier archive..." + echo + + if [ "$f_param_1" = "#3" ]; then + exit 1 + fi + exit 3 +} + +f_verif_fichier_existe() { + # Fonction qui vérifie si le fichier fourni en paramètre existe, et qu'il s'agit d'un + # fichier zip ou d'un fichier 7z. + # Quoiqu'il arrive, l'appel à cette fonction marque la fin du script. + # + # syntax: f_verif_fichier_existe [] + + local fichier_a_tester=$1 + + if [ -z "$fichier_a_tester" ]; then + echo "!! Erreur fatale, le paramètre à tester de la fonction f_verif_fichier_existe() est vide ! Revoir l'appel à la fonction..." + echo "!! Fin du script. Code d'erreur 10." + return 11 # On stoppe immédiatement l'exécution de la fonction ! + fi + if [ ! -s "$fichier_a_tester" ]; then # Le fichier 'fichier_a_tester' n'existe pas ou a un taille de 0 ! + return 1 # C'est le code d'erreur pour indiquer que le fichier n'existe pas. + fi + + # Quelle est l'extension du fichier fichier_a_tester ? + fullfilename="$fichier_a_tester" + filename=$(basename "$fullfilename") + ext="${filename#*.}" + echo $ext + return 0 +} + +f_verif_dossier_existe() { + # Fonction qui vérifie si le dossier fourni en paramètre existe. + # + # syntax: f_verif_dossier_existe + + local dossier_a_tester=$1 # On récupère le 1er paramètre passé en argument à la fonction. + + if [ -d "$dossier_a_tester" ]; then # Le dossier 'dossier_a_tester' existe ! Il sera renommé. + return 0 # C'est le code d'erreur pour indiquer que le dossier existe bien. + else + return 1 # C'est le code d'erreur pour indiquer que le dossier n'existe pas. + fi + + # Si le script arrive ici, c'est qu'il y a un soucis... + echo "BLABLA Si tu lis ça, c'est que y a une couille dans le paté !!! 9988" + exit 9988 +} +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## Fin de la section concernant les fonctions ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── + + +##──── ──────────────────────────────────────────────────────────────────────────────────────── +## Début du programme principal ## +##──── ──────────────────────────────────────────────────────────────────────────────────────── +if [ $nb_arg -ne 2 ]; then + f_affiche_syntaxe "#2" "$tous_les_args" # On affiche la syntaxe car le nombre de paramètres n'est pas correct. +fi + +mode_backup="" +case "$methode" in + --[hH][eE][lL][pP] | --[hH] | -[hH][eE][lL][pP] | -[hH] ) # Premier argument --help ou --h + f_affiche_syntaxe # On affiche la syntaxe + ;; + + --gitea_dump | --gdmp) + mode_backup="gitea_dump" + ;; # On ne surcharge pas cette partie avec le code de restauration, ce sera fait plus bas. + + --archive_dossier | --ad) + mode_backup="archive_dossier" + ;; # On ne surcharge pas cette partie avec le code de restauration, ce sera fait plus bas. + + *) # Aucune méthode sélectionnée valide ou bien trop d'arguments + mode_backup="non_choisi" + f_affiche_syntaxe "#1" "$methode" # On affiche la syntaxe car le paramètre de méthode est incorrect. + echo "BLABLA Si tu lis ça, c'est que y a une couille dans le paté !!! 9999" + exit 9999 + ;; +esac + +echo "La méthode de restauration choisie est : $methode " +echo + +# Test si le fichier en argument existe et est valide (archive zip pour ). +ext_fichier="" +ext_fichier="$(f_verif_fichier_existe $fichier)" # Vérification que le fichier à restaurer existe bien et est bien un .zip ou un .7z +retour_fct=$? # Le code d'exit de la fonction est stocké dans cette variable. +if [ $retour_fct -ne 0 ]; then + case "$retour_fct" in + 1) # Le fichier n'existe pas. + echo "!! Le fichier $fichier n'existe pas. La restauration ne peut pas s'effectuer." + echo "!! Fin du script. Erreur 10" + echo + exit 10 + ;; + 11) # Problème avec l'appelle de la fonction, revoir le code ci-dessus... + exit 11 + ;; + *) # Toutes autres valeurs ne devrait pas exister ! + echo "!! Erreur fatale qui ne devrait pas exister !" + echo "!! Code d'erreur 1000" + exit 1000 + ;; + esac +else + echo "Le fichier existe et a une taille non nulle. Le script peut continuer." + echo + echo "Début de la restauration ---" +fi + +cd $GITEA_DOCKER_DIR # On se place dans le dossier du conteneur gitea +retour_cmd=$? # Le code d'exit de la fonction est stocké dans cette variable. +if [ $retour_cmd -ne 0 ]; then + echo "!! Le dossier $GITEA_DOCKER_DIR semble ne pas exister. Vérifier la variable GITEA_DOCKER_DIR dans le script." + echo "!! Fin du script. Erreur 333" + echo + exit 333 +fi + +# Note : Si le dossier GITEA_DATA_DIR existe il sera renommé en GITEA_DATA_DIR--$(date +%Y-%m-%d--%Hh%M) +# avec la commande mv "$GITEA_DATA_DIR" "$GITEA_DATA_DIR--$(date +%Y-%m-%d--%Hh%M)" +# Ce test sera fait lors de l'appel de la fonction verif_dossier_existe(). +# Aucun choix ne sera possible, le dossier existant sera forcément renommé. +# +# Note : Il faut que le dossier GITEA_BACKUP_DIR existe, ce qui semble acquis vu que le fichier backup +# à restaurer doit être dedans... Mais il est vital que ce dossier existe car un dossier 'TEMP' +# y sera créé pour extraire les données de l'archive (zip, 7z, ou tar.gz)... +# +# On teste maintenant l'existence des deux dossiers précédents. +# Si un des deux dossiers n'est pas présents, le script sera interrompu. + +# 1er test : GITEA_DATA_DIR +retour_fct=11111 # Valeur reset. +f_verif_dossier_existe $GITEA_DATA_DIR +retour_fct=$? # Le code d'exit de la fonction est stocké dans cette variable. +if [ $retour_fct -eq 0 ]; then # Le dossier existe, on peut continuer + echo "-- Le dossier $dossier_a_tester existe et va être renommé en $dossier_a_tester--$(date +%Y-%m-%d--%Hh%M)" +else # Le dossier n'existe pas + echo "!! Le dossier $dossier_a_tester n'existe ! Veuillez créer le dossier $dossier_a_tester puis relancer le script." + echo "!! Interruption de l'exécution du script. Code 444" + exit 444 # C'est le code d'erreur pour indiquer que le dossier n'existe pas et que le script a été interrompu. +fi + +# 2ème test : GITEA_BACKUP_DIR +retour_fct=11111 # Valeur reset. +f_verif_dossier_existe $GITEA_BACKUP_DIR +retour_fct=$? # Le code d'exit de la fonction est stocké dans cette variable. +if [ $retour_fct -eq 0 ]; then # Le dossier existe, on peut continuer + echo "-- Le dossier $dossier_a_tester existe bien. La restauration peut continuer." +else # Le dossier n'existe pas + echo "!! Le dossier $dossier_a_tester n'existe ! Vérifier que ce dossier est bien paramétré dans le script." + echo "!! Interruption de l'exécution du script. Code 555" + exit 555 # C'est le code d'erreur pour indiquer que le dossier n'existe pas et que le script a été interrompu. +fi + +# Maintenant on sait que les deux dossiers GITEA_BACKUP_DIR et GITEA_DATA_DIR existent. + +case "$mode_backup" in + gitea_dump) + + if [ $ext_fichier != "zip" ]; then + echo "!! Le fichier archive $(basename "$fichier") n'est pas une archive ZIP." + echo "!! Fin du script." + f_affiche_syntaxe "#3" + fi + + echo -e "\t-- Méthode de restauration à venir, un jour si j'ai le courage...\n" + echo -e "\t-- Donc, pour le moment il ne se passera rien avec cette méthode...\n" + exit 0 + + # Extraction de l'archive zip créé avec gitea dump avec 7z : + # 7z x -o/volume1/docker/gitea/backup-data -tzip /volume1/docker/gitea/backup-data/gitea-dump-1618217429.zip + + echo + ;; + + archive_dossier) + + if [ $ext_fichier != "7z" ] && [ $ext_fichier != "tar.gz" ]; then + echo "!! Le fichier archive $(basename "$fichier") n'est pas une archive 7z ou tar.gz." + echo "!! Fin du script." + f_affiche_syntaxe "#3" # Le script est interrompu. + fi + + echo -e "\t-- Restauration de la sauvegarde $fichier \n\t par extraction de l'archive dans le dossier $GITEA_DATA_DIR\n" + + # Comme on sait que le dossier existe, il est renommée après avoir éteint le conteneur. + retour_cmd=1111 # Valeur reset + echo -e "\t-- Extinction du conteneur $(docker stop $NOM_CONTENEUR)\n" + retour_cmd=$? # Le code d'exit de la fonction est stocké dans cette variable. + if [ $retour_cmd -ne 0 ]; then + if [ $retour_cmd -eq 1111 ]; then + echo "### DEBUG : soucis avec la récupération du retour de commande #1470000 " + exit 1470000 + fi + echo "!! Le conteneur $NOM_CONTENEUR ne peut pas être arrêté..." + echo "!! Fin du script. Erreur 777" + echo + exit 777 + fi + + mv "$GITEA_DATA_DIR" "$GITEA_DATA_DIR--$(date +%Y-%m-%d--%Hh%M)" + + # En fonction du type d'archive donnée en paramètre au script, ce n'est pas la même manière d'extraire les données. + # Mais quoiqu'il arrive on crée un dossier TEMP dans le dossier GITEA_BACKUP_DIR pour y placer les données extraites. + # Ce dossier TEMP sera supprimé à la fin de la restauration. + mkdir "$GITEA_BACKUP_DIR/TEMP" + + case "$ext_fichier" in + 7z) + echo -e "\t-- Extraction des données de l'archive 7z utilisée.\n" + # Restauration d'un fichier 7z : + 7z x -so $fichier | tar xf - -C "$GITEA_BACKUP_DIR/TEMP" + ;; + tar.gz) + echo -e "\t-- Extraction des données de l'archive tar.gz utilisée.\n" + # Restauration d'un fichier tar.gz : + tar -xzf $fichier -C "$GITEA_BACKUP_DIR/TEMP" + ;; + *) + echo "Erreur d'extension non prévue ! Revoir le code. Erreur 88." + exit 88 + esac + + # On déplace le dossier extrait data dans GITEA_DOCKER_DIR (Rappel on est dans le dossier gitea qui contient le dossiers GITEA_BACKUP_DIR) + mv "$GITEA_BACKUP_DIR/TEMP/data" "$GITEA_DOCKER_DIR" # On pourrait utiliser "./" à la place de "$GITEA_DOCKER_DIR" + + # Le dossier TEMP étant maintenant vide, on le supprime + rm -rf "$GITEA_BACKUP_DIR/TEMP" + + retour_cmd=1111 # Valeur reset + echo -e "\t-- Redémarrage du conteneur $(docker start $NOM_CONTENEUR)\n" + retour_cmd=$? # Le code d'exit de la fonction est stocké dans cette variable. + if [ $retour_cmd -ne 0 ]; then + if [ $retour_cmd -eq 1111 ]; then + echo "### DEBUG : soucis avec la récupération du retour de commande #1470000 " + exit 1470000 + fi + echo "!! Le conteneur $NOM_CONTENEUR ne peut pas être redémarré..." + echo "!! Fin du script. Erreur 777" + echo + exit 777 + fi + ;; + + *) + echo "!! Un problème est survenu ! Revoir le script. Code XYZ = 199 !" + echo + return 199 + ;; +esac + +echo +echo "Restauration terminée. Bonne journée :)" +echo \ No newline at end of file diff --git a/docker-compose/gitea/tuto-1.png b/docker-compose/gitea/tuto-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ad1f7a470ab6e6369734dbdfc056f6f119fdd4 GIT binary patch literal 65366 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®2x) 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 Muj-)+uH1X}Kc*80djJ3c literal 0 HcmV?d00001 diff --git a/docker-compose/gitea/tuto-3.png b/docker-compose/gitea/tuto-3.png new file mode 100644 index 0000000000000000000000000000000000000000..2e177fbcc6229e54f35d230641f0c61046ddf0b1 GIT binary patch literal 178296 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

|0x_RcXMvR}78@*7SMmdDOI1Ir}t(8hZ0$%2b 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 i0HcAwv TUTO mis à jour - v4.3 < [/u] )[/b][/color][/size] +[color=#800000][list][*] 3.1 : ajout d'une capture d'écran de la configuration du reverse-proxy de DSM + ajout d'une mention concernant ce qui est à remplacer dans le docker-compose.yml +[*] 4.0 : changement d'image pour le backup, donc le docker-compose est modifié.` +[*] 4.1 : actualisation de certaines captures d'écrans +[*] 4.2 : correction de quelques coquilles, et mise à jour de la ligne de commande de création des dossiers en ligne de commande. +[*] 4.3 : Ajout d'un avertissement + explications pour la variable SIGNUPS_ALLOWED=false dans mon tuto +[/list][/color] + +Bonjour à toutes et à tous, + + + +[color=#4040BF][b][size=200]Sommaire :[/size][/b] +0. Fichiers joints +1. Note à lire : Mise à jour v3.0 (changement de nom de l'image) +2. Préambule & Prérequis +3- Mise en place et création des conteneurs [color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b][/color] + 3.1- Petites explications sur ce qui suivra + 3.2- Création du docker-compose.yml [color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b][/color] + 3.3- Configuration de rclone pour le backup [color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b][/color] + 3.4- Création des dossiers et du réseau + 3.5- Création des conteneurs (2 méthodes) +4- 1er lancement et sécurisation 2FA +5- Ajout d'un script pour les notifications Websocket [color=#800000][b]( [u] > Ajout v3.0 < [/u] )[/b][/color] + 5.1- Explications : Pourquoi ? Comment ? [color=#800000][b]( [u] > Ajout v3.0 < [/u] )[/b][/color] + 5.2- Comment lancer le script ? [color=#800000][b]( [u] > Ajout v3.0 < [/u] )[/b][/color] + 5.3- Enfin le script lui même ! [color=#800000][b]( [u] > Ajout v3.0 < [/u] )[/b][/color] +... +[/color] + +[color=#BF40BF][b][size=200]0. Fichiers joints[/size][/b][/color] +[list] +[*] docker-compose-v1.0.yml (plus maintenu, mais laissé pour la postérité) : [attachment=5]docker-compose-v1.0.yml.7z[/attachment] +[*] docker-compose-v2.0.yml (plus maintenu, mais laissé pour la postérité) : [attachment=4]docker-compose-v2.0.yml.7z[/attachment] +[*] docker-compose-v3.0.yml (plus maintenu, mais laissé pour la postérité) : [attachment=3]docker-compose-v3.0.yml.7z[/attachment] +[*] docker-compose-v4.0.yml (La dernière version) : [attachment=1]docker-compose-v4.0.yml.7z[/attachment] +[*] Le fichier rclone.conf : [attachment=0]config-rclone.conf.7z[/attachment] +[*] Le script pour les notifications Websockets : [attachment=2]vaultwarden__Enable_Websocket.7z[/attachment] + +[/list] + + +[color=#BF40BF][b][size=200]1. Note à lire : Mise à jour v3.0 (changement de nom de l'image)[/size][/b][/color] +L'auteur de Bitwarden_RS, dani-garcia, a renommé son image en Vaultwarden. +[quote][img]https://gitlab.com/BZHDeveloper/HFR/raw/master/emojis-micro/1f4e2.png[/img] Note: This project was known as Bitwarden_RS and has been renamed to separate itself from the official Bitwarden server in the hopes of avoiding confusion and trademark/branding issues. Please see [url=https://github.com/dani-garcia/vaultwarden/discussions/1642]#1642[/url] for more explanation.[/quote] +Je viens de mettre à jour l'intégralité du tuto pour que tout soit cohérent avec ce nouveau nom. Les noms des dossiers, fichier log, nom du conteneur, du réseau etc, sont donc renommé pour tenir compte du nouveau nom. +Pour ceux qui veulent aller vite : +[list=1] +[*] Arrêter le conteneur Bitwarden_RS +[*] Faire une copie de sauvegarde du dossier complet .../docker/bitwarden_rs +[*] Renommer les trois dossiers en remplaçant bitwarden (ou bitwarden_rs) par vaultwarden : bitwarden_rs/bitwarden-data/ + [list] + [*] bitwarden_rs/bitwarden-data/ ---> vaultwarden/vaultwarden-data/ + [*] bitwarden_rs/bitwarden-backup ---> vaultwarden/vaultwarden-backup/ + [/list] +[*] Supprimer la stack dans Portainer, ou supprimer le conteneur via la ligne de commande. +[*] Créer une nouvelle stack dans Portainer avec le fichier docker compose v3.0 (pensez à modifier les valeurs perso). +[*] Vous reconnecter. +[*] Annexe : si vous souhaitez changer de nom de domaine, créer le nouveau, et mettez le dans le docker-compose à la place de l'ancien. +[/list] + + +[color=#BF40BF][b][size=200]2- Préambule & Prérequis[/size][/b][/color] +Tout d'abord, pourquoi je fais un nouveau tuto d'installation de [url=https://github.com/dani-garcia/vaultwarden]vaultwarden[/url]... En fait je n'ai pas vu de tuto vraiment à mon goût sur l'installation de [url=https://github.com/dani-garcia/vaultwarden]vaultwarden[/url], soit il manque des explications, soit c'est fait via l'interface DSM de docker... Donc je me décide à en faire un moi-même. +Je précise qu'il n'y aura pas beaucoup de différences avec ceux trouvés sur le NET, si ce n'est ceci : +[list] +[*] L'utilisation de Portainer ou de la ligne de commande (=CLI) avec docker-compose +[*] Des commentaires expliquants la plupart des options utilisées tout le long du docker-compose.yml +[*] Une utilisation combinée avec un conteneur faisant automatiquement des sauvegardes de la base de données, là aussi avec des commentaires dans le docker-compose.yml : [url]https://gitlab.com/1O/vaultwarden-backup[/url] + [/list] + + +Pour mettre en oeuvre ce tuto, il faudra au préalable : +[list][*] que vous ayez mis en place [b][u]Portainer[/u][/b] ([url=https://www.forum-nas.fr/viewtopic.php?f=56&t=14030]voir le tuto d'EVOTk[/url]) ; +[*] que vous sachiez vous connecter en SSH au NAS et lancer [i]docker-compose up -d[/i] si vous optez pour la création des conteneurs en ligne de commande (vous trouverez ici un tuto explicatif : [url=https://www.forum-nas.fr/viewtopic.php?f=56&t=11461][Tuto] Acceder à son NAS en lignes de commande[/url]) ; +[*] savoir identifier les PUID et PGID d'un utilisateur avec une ligne de commande en SSH sur le NAS. + [/list] + + +[size=200][color=#BF40BF][b]43- Mise en place et création des conteneurs[/b][/color] [color=#800000][b]( [u] > Mise à jour < [/u] )[/b][/color][/size] + +[color=#BF40BF][b][size=150]3.1- Petites explications sur ce qui suivra[/size][/b][/color] + +Le but de ce tuto est de tout préparer sur l'ordinateur avant de placer les fichiers/dossiers au bon endroit, tout en comprenant bien ce qui est fait et les implications de certaines options. +On va tout d'abord commencer par créer un fichier [i]docker-compose.yml[/i] qui pourra servir pour les deux méthodes d'installation (Portainer, ou CLI). +J'opte pour combiner la création des deux conteneurs ([b]vaultwarden[/b] et [b]vaultwarden Backup[/b]) en un seul fichier [i]docker-compose.yml[/i]. J'ai également choisi de placer ces deux conteneurs dans un même réseau (network) que je nomme [i]vaultwarden_network[/i]. +Ensuite il faudra créer ce réseau et les dossiers utilisés avant de créer les conteneurs. +Pour les dossiers, je pars sur cette organisation : (sur le volume1) +[url=https://i.imgur.com/xs3kngV.png][img]https://i.imgur.com/xs3kngV.png[/img][/url] +(Note : j'ai conservé pour quelques semaines encore, l'ancien dossier de backup : vaultwarden_backup, il n'est pas nécessaire pour vous de le créer...) + +[b][color=#800000]Note : Tout ce qui sera XXxxXX sera à remplacer par vos valeurs. J'indiquerais comment les obtenir si ce n'est pas évident.[/color][/b] + +[size=150][color=#BF40BF][b]3.2- Création du docker-compose.yml[/b][/color] [color=#800000][b]( [u] > Mise à jour < [/u] )[/b][/color][/size] +Voir le fichier ci-joint dans le §0. +[size=150][color=#800000][b]( Dans la mise à jour du tuto (v2.0), j'ai ajouté pas mal de commentaires dans le fichier docker-compose.yml. Lisez-les attentivement )[/b][/color][/size] + +Ce fichier est composé de trois parties : une partie dédiée à vaultwarden et à sa configuration, et une autre partie dédiée à vaultwarden backup et à sa configuration, et enfin une pour le réseau. + +[u][b]Explications sur la partie configuration ([b][color=#4040FF]partie 1[/color][/b]) de vaultwarden (1ère partie du docker-compose.yml) :[/b][/u] + +Ce qui suit met en place la version de docker-compose à utiliser : pour plus de compatibilité (et par simplicité car je ne maitrise pas la v3...) on part sur une v2. + +[color=#13A8BD]Il y a dans l'extrait ci-dessous des commentaires qui permettent de comprendre ce qui est fait. +Il faudra remplacer les [b]XXxxXX[/b] par vos valeurs à vous. +[/color] + +[size=150][color=#BF0040][b][u]Avertissement concernant la variable SIGNUPS_ALLOWED[/u][/b][/color][/size] +[color=#BF0040]Dans la partie du docker-compose concernant Vaultwarden, il y a une variable d'environnement particulière qui bloque l'inscription de nouveaux comptes si elle a comme valeur false :[/color] +[code]- SIGNUPS_ALLOWED=false[/code] +[color=#BF0040]Ce faisant, il vous sera impossible de créer votre premier compte via l'interface web de Vaultwarden si vous la laissez sur [b]false[/b]. +[b][i]Mais...[/i][/b] Il y a deux possibilités pour quand même avoir un compte (sinon ce n'est pas très utile comme outils...). +[list][*] La première est peut-être la plus pratique : il suffit d'aller dans l'interface admin ( https://votre-nom-de-domaine.tld/admin ) en utilisant le ADMIN_TOKEN, et de remplir le champ email dans "Invite User" avec votre email pour vous "auto-inviter". Il faut bien entendu que l'envoi d'email soit fonctionnel, ce qui sera obligatoire pour le 2FA. +[img]https://i.imgur.com/wquYyII.png[/img] + + + +[*] La deuxième méthode c'est de mettre la variable SIGNUPS_ALLOWED sur true :[/color] +[code]- SIGNUPS_ALLOWED=true[/code] +[color=#BF0040] Et là aussi, deux possibilités : +[list][*] Soit vous créer de base le conteneur cette variable sur true, et alors au premier lancement vous pourrez créer votre compte. Mais il faudra ensuite soit passer par l'interface admin pour passer le paramètre "Allow new signups" à false en décochant la case à cocher (chez moi c'est par défaut à false à cause de la variable SIGNUPS_ALLOWED). +[url=https://i.imgur.com/oYxpiwZ.png][img]https://i.imgur.com/oYxpiwZ.png[/img][/url] + +[*] Soit vous modifiez (après le premier lancement et la création du compte) le docker-compose en repassant la variable SIGNUPS_ALLOWED à false, et vous recréez le conteneur. [/list] +[/list] + +Quoique vous fassiez, je vous conseil vivement de désactiver l'inscription via la variable SIGNUPS_ALLOWED, et d'inviter chaque utilisateur avec la console admin, puis de désactiver la console admin en commentant la variable ADMIN_TOKEN (donc en recréant le conteneur). (ce n'est qu'un conseil). +[/color] + + + + +[code]##============================================================================================== +## ## +## Fichier docker-compose.yml pour Vaultwarden avec ttionya/vaultwarden-backup ## +## Révision du fichier : v4.0 ## +## ## +##============================================================================================== +## ## +## Attention, avec ce fichier, il faut avoir créer le réseau "vaultwarden_network" avant de ## +## créer les conteneurs. ## +## ## +## La mise en place de fail2ban se fera avec un docker-compose dédié. ## +## ## +##============================================================================================== +## ## +## NOTE IMPORTANTE ## +## ----------------- ## +## ## +## Lors de l'importation d'un fichier contenant beaucoup d'entrées, j'ai eu une erreur ## +## 405 Not Allowed - Nginx ## +## Après quelques recherches, et un certains nombre de minutes, il s'est avéré que les ## +## expiration du délai ... (les timeout) dans le reverse proxy par défaut de 60s étaient ## +## trop faible. ## +## En passant les 3 valeurs à 300s (5min), ça a réglé mon problème. ## +## (Pensez à relancer le script vaultwarden__Enable_Websocket.sh après ces modifications) ## +## ## +##============================================================================================== +## ## +## Ajout des Notifications Websocket ## +## ## +## Pour qu'elles'fonctionnent, il faut configurer le reverse-proxy correctement. ## +## Pour celui de DSM, il n'est malheureusement pas possible de configurer les ## +## redirections /notifications/hub vers le serveur WebSocket ni celles vers le port normal ## +## /notifications/hub/negotiate ## +## Voir cet article pour tout ce qui n'est pas possible via l'interface de DSM : ## +## https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications ## +## ## +## Dès lors, il faut ruser et passer par l'exécution d'un petit script qui va créer un ## +## fchier ws.locations contenant les modifications précédentes, et qui va écrire une ## +## ligne dans le fichier /etc/nginx/app.d/server.ReverseProxy.conf pour inclure le ## +## fichier ws.locations au niveau de la section concernant le nom de domaine pour ## +## vaultwarden. ## +## Comme cela, il n'est pas nécessaire de passer par le changement de reverse-proxy, assez ## +## complexe à mettre en oeuvre... ## +## ## +## Le script est : vaultwarden__Enable_Websocket.sh ## +## ## +## Il faudra la lancer régulièrement et à chaque redémarrage du NAS, via deux tâches ## +## plannifiées dédiées, en donnant 3 paramètres au fichier : ## +## - le nom de domaine de vaultwarden ## +## - le port HTTP exposé (donc pas l'interne du conteneur) pour l'interface graphique ## +## - le port websocket exposé (donc pas l'interne du conteneur) ## +## Voir les commentaires de ce fichier vaultwarden__Enable_Websocket.sh pour plus ## +## d'explications. ## +## ## +##============================================================================================== + +--- +version: "2.4" + +services: + vaultwarden: + image: vaultwarden/server:latest # https://github.com/dani-garcia/vaultwarden + # https://github.com/dani-garcia/vaultwarden/wiki + container_name: vaultwarden + networks: + - vaultwarden_network + environment: + # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - PUID=1000 + - PGID=100 + - TZ=Europe/Paris + + # Pour l'envoi d'emails + - SMTP_HOST=XXxxXX + - SMTP_FROM=XXxxXX + - SMTP_FROM_NAME=BlaBla + - SMTP_PORT=XXxxXX + - SMTP_SSL=true + - SMTP_USERNAME=XXxxXX + - SMTP_PASSWORD=XXxxXX + + - INVITATION_ORG_NAME=Vaultwarden [Votre Nom, pseudo...] # Permet de spécifier un nom d'application pour les invitations d'organisation + + # Nécessaire pour activer le 2FA pour la connexion à notre serveur Vaultwarden + # Il est possible de spécifier un port de connexion dans l'URL. Le https:// est obligatoire. + # Pour cette option, il est donc OBLIGATOIRE d'avoir fait le nécessaire pour avoir du HTTPS (certificats, reverse-proxy, ...) + - DOMAIN=XXxxXX + + # Pour enregistrer les log avec un niveau particulier + - LOG_FILE=/data/vaultwarden.log + - LOG_LEVEL=warn + - EXTENDED_LOGGING=true + + # je n'aime pas les indices pour les mots de passe... + - SHOW_PASSWORD_HINT=false + + # Pour activer la console d'administation, accessible via : https://mon.domaine.tld/admin/ + # Voir détails ici : https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page + # /!\ + # /!\ N'importe qui pourra accéder à la page de connexion, alors blinder le token d'amdin ci-dessous (64 caractères pour moi) ! + # /!\ Il est de plus TRÈS important d'avoir ACTIVÉ le HTTPS avant l'activation de cette option. + # /!\ + # Je conseille de ne l'activer qu'en cas de nécessité, et de la désactiver après. + # Pour désactiver, il suffit de commenter la ligne ci-dessous. + - ADMIN_TOKEN=XXxxXX + # À noter : + # La première fois que vous enregistrez un paramètre dans la page d'administration, 'config.json' sera généré + # dans votre 'DATA_FOLDER'. Les valeurs de ce fichier auront priorité sur les valeurs 'environnement'. + + - SIGNUPS_ALLOWED=false # Fait en sorte que les inscriptions soient bloquées, seul l'admin pourra inviter + # des utilisateurs avec un envoi d'email depuis la console d'administation + + - WEBSOCKET_ENABLED=true # Active les WebSocket notifications (Nécessite la configuration du reverse-proxy) + # Durant le nombre importants d'essais, j'en suis venu à laisser le port par défaut + # pour le WEBSOCKET_PORT. Il est possible que ça fonctionne avec un port différent. + # Il faudra alors décommenter la ligne suivante, et changer le port exposé plus bas. + #- WEBSOCKET_PORT=3012 # Par défaut = 3012 + + # Pour activer la récupération des icones des IP LAN, il faut mettre sur false la variable ICON_BLACKLIST_NON_GLOBAL_IPS + - ICON_BLACKLIST_NON_GLOBAL_IPS=false # Par défaut = true + + # On défini ici quelques chemins de dossiers qu'il faudra créer (pas sur que le conteneur les crées lui-même...) + - ICON_CACHE_FOLDER=data/icon_cache + - ATTACHMENTS_FOLDER=data/attachments + - SENDS_FOLDER=data/sends + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + volumes: + - "/volume1/docker/vaultwarden/vaultwarden-data/:/data/" + ports: + - XXxxXX:3012 # Choisir un port libre pour le websocket + - XXxxXX:80 # Choisir un port libre pour l'interface WEB + restart: unless-stopped +[/code] + + +[u][b]Maintenant la deuxième partie ([b][color=#4040FF]partie 2[/color][/b]) qui peut ne pas être utilisée si vous ne souhaitez pas sauvegarder automatiquement la BDD :[/b][/u] [color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b][/color] + +[color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b] +Je change la méthode de sauvegarde pour une nouvelle image qui permet davantage de choses, dont la sauvegarde des dossiers attachements, et sends en plus de la base de données. +[img]https://i.imgur.com/2T2U5QL.png[/img] +Il est possible de faire un backup local (méthode utilisée ici) mais il est également possible de faire une sauvegarde dans un cloud parmis une liste assez grande (voir plus bas). +Le fichier 7z obtenu est protégé par un mot de passe, celui présent dans le docker-compose dans la variable ZIP_PASSWORD. +La méthode de compression peut être changée pour zip, moins compressé, mais moins demandeur de ressources... +[/color] + +Comme précédemment, les indications sont en commentaires) +[code] vaultwarden_backup_ttionya: # Voir : https://github.com/ttionya/vaultwarden-backup + image: ttionya/vaultwarden-backup:latest + container_name: vaultwarden_backup_ttionya + networks: + - vaultwarden_network + + restart: always + + depends_on: + vaultwarden: + condition: service_healthy + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + volumes: + - /volume1/docker/vaultwarden/vaultwarden-data:/data + # Chemin d'accès pour stocker le backup et la configuration rclone, voir https://github.com/ttionya/vaultwarden-backup + - /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config:/config + - /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/rclone_backup:/rclone_backup + + environment: + - DATA_DIR=/data # Dossier de données de Vaultwarden monté avec les volumes + - RCLONE_REMOTE_NAME=Backup_Syno # Nom de la config rclone utilisée (voir note plus bas) + - RCLONE_REMOTE_DIR=/rclone_backup/ # Dossier qui doit monté avec les volumes + + # Utiliser soit SCHEDULE soit INTERVAL (ce dernier en sec) + # Pour SCHEDULE : https://crontab.guru/#0_22_*_*_* + # Dans la ligne suivante, on programme l'exécution tous les jours à 22h + - CRON=0 22 * * * + - ZIP_ENABLE=TRUE + - ZIP_PASSWORD=WHEREISMYPASSWORD? + - ZIP_TYPE=7z + - BACKUP_FILE_DATE_SUFFIX=--%Hh%Mm%Ss + - BACKUP_KEEP_DAYS=7 + # - MAIL_SMTP_ENABLE=FALSE + # - MAIL_SMTP_VARIABLES='' + # - MAIL_TO='' + # - MAIL_WHEN_SUCCESS='TRUE' + # - MAIL_WHEN_FAILURE='TRUE' + - TIMEZONE=Europe/Paris + + ############################################# + # Note à propos de la configuration de rclone + ############################################# + # Si vous voulez faire une sauvegarde locale, il faut juste placer le fichier rclone.conf dans le dossier ../config/rclone/ + # Dans ce fichier vous trouverez ceci : + # [Backup_Syno] + # type = local + # + # Il faudra remplacer Backup_Syno par un autre nom au besoin. + # Ce fichier est donc prévu pour une sauvegarde locale. + # Pour configurer d'autres types de sauvegarde, il faut lancer la configuration de rclone avec cette commande : + # docker run --rm -it -v /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config:/config ttionya/vaultwarden-backup:latest rclone config +[/code] + + +[u][b]Et enfin une dernière partie ([b][color=#4040FF]partie 3[/color][/b]) qui est obligatoire, celle qui concerne le réseau :[/b][/u] +[code]networks: # On indique ici de quel réseau on parlait précédement + vaultwarden_network: + external: # C'est un réseau créé en dehors du docker-compose. + name: vaultwarden_network # Je précise toujours un nom, car sinon ça va prendre un nom à rallonge avec + # le nom du conteneur et du réseau voulu... +[/code] + +Il est à préciser que ces trois parties sont à fusionner en un seul et même fichier. Je les ai séparer pour les explications. +Voir le fichier docker-compose.yml joint précédement. + +[color=#BF40BF][b][size=150]3.3- Configuration de rclone pour le backup[/size][/b][/color] [color=#800000][b]( [u] > Mise à jour v4.0 < [/u] )[/b][/color] +Pour que la sauvegarde se fasse sans erreur, il faut configurer un fichier rclone.conf qui devra se trouver dans /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config/rclone/ + +Deux possiblités en fonction de ce que vous voudrez faire. +[list][*] La première si vous faites comme moi, une sauvegarde locale (dans un dossier du NAS, monté dans les volumes, voir paragraphe précédent). +Pour cette méthode, il suffit de créer un fichier rclone.conf dans /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config/rclone/ (ou de copier le fichier joint) contenant : +[code][Backup_Syno] +type = local +[/code] +Vous remarquerez que Backup_Syno est le nom donné dans le docker compore à la variable RCLONE_REMOTE_NAME. +Il faudra donc bien configurer la variable RCLONE_REMOTE_DIR avec le chemin d'accès à l'intérieur du conteneur. + +Je tiens à préciser que ce mode de sauvegarde doit être complété par une tâche de backup planifiée (Hyperbackup) du dossier docker contenant le dossier Vaultwarden dans un cloud ou ailleurs. + +[*] La seconde si vous voulez ajouter des options, ou bien faire une sauvegarde dans un cloud. +Pour cela, il faut lancer une commande en ligne de commande SSH (donc se connecter en SSH au NAS) : +[code]docker run --rm -it \ + -v /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config:/config \ + ttionya/vaultwarden-backup:latest \ + rclone config +[/code] + +[b]NOTE : Attention, pour ceux qui utilise Portainer, il se pourrait que cette commande, lancée avant la création du conteneur, fasse que la stack ne soit pas gérable par Portainer... Créer d'abord le conteneur, puis stopper le, avant de lancer cette commande.[/b] + +Cette commande ne crée pas le conteneur, elle va juste lancer le processus de configuration de rclone : +[url=https://i.imgur.com/6QD37JW.png][img]https://i.imgur.com/6QD37JW.png[/img][/url] + +Vous pourrez éditer la configuration précédemment enregistrée (dans mon exemple, celle utilisée pour le backup local), en créer une nouvelle, etc... +Pour la création, il faut donc taper n (new remote). +Une fois donné un nom, vous aurez le choix entre toutes ces possibilités de cloud (sauf n°22 qui est la sauvegarde locale) : +[url=https://i.imgur.com/xSWPKVz.png][img]https://i.imgur.com/xSWPKVz.png[/img][/url] [url=https://i.imgur.com/kxO3LcS.png][img]https://i.imgur.com/kxO3LcS.png[/img][/url] +Je n'ai pas poursuivi une de ces méthodes de cloud, à vous d'essayer ;) (si vous le faites, n'hésiter pas à revenir faire un petit retour ;) ). + +À l'issue de l'exécution de cette configuration, vous aurez automatiquement le fichier rclone.conf écrit dans le dossier .../config/rclone/ (ou bien celui déjà existant sera modifié). [/list] + + + +[color=#BF40BF][b][size=150]3.4- Création des dossiers et du réseau[/size][/b][/color] + +La partie explications des options à placer dans le fichier [i]docker-compose.yml[/i] étant faite, passons à la [b]création des dossiers sur le NAS[/b]. +Vous pouvez soit passer par DSM, soit par la ligne de commande. +Si vous optez pour la CLI, voilà les commandes à taper : +[code]sudo -i +cd /volume1/docker +mkdir -p vaultwarden vaultwarden/vaultwarden-data vaultwarden/vaultwarden-backup_ttionya/config/rclone vaultwarden/vaultwarden-backup_ttionya/rclone_backup[/code] +Une fois ces dossiers créés, copier votre [i]docker-compose.yml[/i] dans le dossier [b]/volume1/docker/vaultwarden[/b]. + +Il faut maintenant créer le réseau. Plusieurs possibilités existent. +Soit vous passez par DSM (non expliquée ici), soit vous passez par Portainer, soit enfin via la CLI. +[list][*] [b][color=#008040] Utilisation de Portainer :[/color][/b] +Dans Portainer, il faut aller dans la section [b]Networks[/b], et ensuite cliquer sur le bouton [b]Add Network[/b] : +[url=https://i.imgur.com/GleZg5t.png][img]https://i.imgur.com/GleZg5t.png[/img][/url] +Ensuite, il suffit juste de rentrer le nom du réseau à créer (ici : ) et de bien choisir Bridge comme Driver : +[url=https://i.imgur.com/U30Nab4.png][img]https://i.imgur.com/U30Nab4.png[/img][/url] +Il n'y a pas besoin de toucher au reste. Portainer choisir les IP en fonction de ce qui est déjà créé chez vous. +________________ + +[*] [b][color=#008040] Utilisation de la CLI :[/color][/b] +Pour créer le réseau vaultwarden_network : +[code]sudo docker network create vaultwarden_network[/code] +Si vous voulez supprimer le réseau ainsi créé, il faut taper : +[code]sudo docker network rm vaultwarden_network[/code] +Au besoin, si vous voulez lister les réseeaux : +[code]sudo docker network ls[/code] +Note : Si vous avez plusieurs commandes à taper en mode root, il faut faire : [i]sudo -i[/i] +Et ensuite taper vos commande sans le [i]sudo[/i] devant. +[/list] + + + +[color=#BF40BF][b][size=150]3.5- Création des conteneurs (2 méthodes)[/size][/b][/color] +Maintenant tout est prêt pour qu'on se lance dans la création des conteneurs. +Deux possibilités : passer par Portainer, ou bien la CLI. +[list] +[*] [b][color=#008040] Par [u]Portainer[/u] :[/color][/b] +Il faut aller dans la section "[b]Stacks[/b]", puis cliquer sur le bouton "[b]+ Add stack[/b]" : +[url=https://i.imgur.com/CIMB1gp.png][img]https://i.imgur.com/CIMB1gp.png[/img][/url] +Ensuite, on donne un nom à la stack que l'on va créer et on copie/colle le contenu du fichier [b][i]docker-compose.yml[/i][/b] créé précédemment : +[url=https://i.imgur.com/68iYBEr.png][img]https://i.imgur.com/68iYBEr.png[/img][/url] +Il est également possible d'uploader ce dit fichier en utilisant le bouton "Upload" : (je n'ai personnellement jamais utiliser cette option, mais il n'y a pas de raison pour qu'elle ne fonctionne pas) +[url=https://i.imgur.com/W57Jw4G.png][img]https://i.imgur.com/W57Jw4G.png[/img][/url] + +Il ne reste plus qu'à cliquer sur le bouton "Deploy the stack" tout en bas à gauche de la page : +[url=https://i.imgur.com/ayxVdBT.png][img]https://i.imgur.com/ayxVdBT.png[/img][/url] + +Si une erreur apparait, ce sera dans le coin supérieur droit dans un rectangle rouge, essayer d'en faire une capture avant sa disparition. +Si non, un message en vert apparait et les conteneurs seront créés : +[url=https://i.imgur.com/3jMl1BF.png][img]https://i.imgur.com/3jMl1BF.png[/img][/url] +[url=https://i.imgur.com/tVvnL7U.png][img]https://i.imgur.com/tVvnL7U.png[/img][/url] +Vous noterez dans cette stack, il est possible de l'éditer pour la modifier avec l'onglet [b]Editor[/b] : +[url=https://i.imgur.com/wKptW0e.png][img]https://i.imgur.com/wKptW0e.png[/img][/url] +__________ + +[*] [b][color=#008040] Par [u]la CLI[/u] :[/color][/b] +Avec la ligne de commande, il faut être en root (voir remarque faite précédemment à ce propos...). +Il faut aussi être dans le dossier contenant le fichier [b][i]docker-compose.yml[/i][/b] (attention au nom, il doit être exactement [b][i]docker-compose.yml[/i][/b]), sinon il faut spécifier avec un argument supplémentaire le fichier et son chemin. Je choisi la facilité : on se place dans le bon dossier : +[code]cd /volume1/docker/Vaultwarden +sudo docker-compose up -d[/code] +La création des deux conteneurs se fait et ils démarrent. +[/list] + + + +[color=#BF40BF][b][size=200]4- 1er lancement et sécurisation 2FA[/size][/b][/color] +Une fois les étapes précédentes accomplies, il faut accéder au serveur avec l'url que vous avez indiqué dans la configuration. +Si vous essayer d'accéder via l'IP LAN en http ça ne fonctionnera pas, car le HTTPS est activé, vous aurez l'erreur suivante : +[url=https://i.imgur.com/fgfVIHs.png][img]https://i.imgur.com/fgfVIHs.png[/img][/url] +Et si vous essayer toujours avec l'IP mais en HTTPS, vous aurez cette erreur : +[url=https://i.imgur.com/NpwOycm.png][img]https://i.imgur.com/NpwOycml.png[/img][/url] + +[color=#13A8BD][b]( [u] > Mise à jour - v3.1 < [/u] )[/b] +Bref, il faut y accéder avec votre nom de domaine. Mais pour cela il faut paramétrer le reverse-proxy de DSM. +[url=https://i.imgur.com/iP47nZm.png][img]https://i.imgur.com/iP47nZm.png[/img][/url] +Une fois cette entrée créé, vous pouvez accéder en HTTPS avec votre nom de domain à Vaultwarden :[/color] +[url=https://i.imgur.com/kbZkHCF.png][img]https://i.imgur.com/kbZkHCF.png[/img][/url] + +[color=#800000][b]( [u] > Mise à jour - v3.0 < [/u] )[/b] +Vous devriez voir ici "© 2021, Bitwarden Inc. (Powered by Vaultwarden)", ceci marque le changement de nom de l'image, voir §1) +[/color] + +Il faut ensuite créer votre compte et vous pourrez alors créer vos mots de passe, importer depuis un autre logiciel de mot de passe... + +Voilà voilà. +Reste plus qu'à sécuriser le compte avec le 2FA. Pour cela, il faut aller dans le compte : +[url=https://i.imgur.com/f9Kfhru.png][img]https://i.imgur.com/f9Kfhru.png[/img][/url] +[url=https://i.imgur.com/IlJMcNs.png][img]https://i.imgur.com/IlJMcNsl.png[/img][/url] +Puis il faut choisir votre méthode. J'ai choisi de passer par une application d'authentification comme MS Authenticator, ou Authy, ou même une autre application de mot de passe comme EnPass que j'utilise aussi. +Cliquer sur le bouton Gérer de la méthode choisie : [url=https://i.imgur.com/SX17nHB.png][img]https://i.imgur.com/SX17nHB.png[/img][/url] +Entre votre mot de passe maitre (celui du compte BW) : +[url=https://i.imgur.com/wiwWUcd.png][img]https://i.imgur.com/wiwWUcdl.png[/img][/url] +À l'aide de l'application d'authentification, après y avoir entrer les infos (QR-Code ou Code alphanumérique), entrer le code à usage unique générer pour valider le 2FA : +[url=https://i.imgur.com/dCv6lEB.png][img]https://i.imgur.com/dCv6lEBl.png[/img][/url] + +Voilà, le compte est protégé :) + +PS : si vous n'avez plus besoin de compte sur votre serveur, il est possible de désactiver la création des comptes. +Dans la section : +[code] environment:[/code] +Il faut ajouter ceci : +[code] - SIGNUPS_ALLOWED=false[/code] + + + + +[size=200][color=#800000][b]( [u] > Mise à jour : AJOUT < [/u] )[/b][/color][/size] + + +[color=#BF00BF][size=200][b]5- Ajout d'un script pour les notifications Websocket[/b][/size][/color] +Alors, après pas mal de temps de recherche, j'ai finalement trouvé comment activer les notifications Websocket et j'ai aussi compris leur utilité. +J'ai trouvé la méthode sur le forum officiel de Vaultwarden, où ce lien a été posté : https://gist.github.com/nstanke/3949ae1c4706854d8f166d1fb3dadc81 +J'ai pris ce script, et je l'ai amélioré selon mes goûts de sureté, et d'explications (vous verrez plus bas de quoi je parle). + +[color=#BF40BF][b][size=150]5.1- Explications : Pourquoi ? Comment ?[/size][/b][/color] + +Ces notifications servent à mettre à jour automatiquement les extensions navigateurs et les clients non mobiles, donc les applications windows, macos, etc, mais pas android et iOS. Pour ces derniers OS, ce n'est juste pas possible avec Vaultwarden, car il faudrait passer par les serveurs de Bitwarden pour les notifications push. Et Vaultwarden ne peut pas le faire. + +Pour activer ces notifications Websocket, il faut faire plusieurs choses. Seul ce qui suit est faisable directement depuis DSM, dans le reverse-proxy : +[url=https://i.imgur.com/LP6lRid.png][img]https://i.imgur.com/LP6lRid.png[/img][/url] +Lors de la création de la règle pour Vaultwarden, il faut ajouter les entêtes personnalisés suivants : (pensez à utiliser le bouton pour créer automatiquement les deux premières lignes) +[url=https://i.imgur.com/PenfXww.png][img]https://i.imgur.com/PenfXww.png[/img][/url] [url=https://i.imgur.com/B3nlyXP.png][img]https://i.imgur.com/B3nlyXP.png[/img][/url] + +Pour le reste, malheureusement il n'est pas possible de le faire depuis DSM... car bien le moteur du reverse-proxy est nginx, il n'y a pas d'interface graphique pour le faire. +Il faut faire passer /notifications/hub avec les mêmes entêtes et /notifications/hub/negotiate au conteneur. Et ça, pas moyen de le faire depuis DSM. +Il faut passer par un script qui va créer un fichier [b]ws.locations[/b] contenant ces propriétés, et modifier le fichier de configuration [b]/etc/nginx/app.d/server.ReverseProxy.conf[/b] afin d'inclure le fichier créé [b]ws.locations[/b] au bon endroit, c'est-à-dire dans la section du nom de domaine pour bitwardenRS. +C'est donc un prérequis (voir les captures précédentes). +Le fichier qui sera créé ressemblera à ceci : +[url=https://i.imgur.com/BFfTHvA.png][img]https://i.imgur.com/BFfTHvA.png[/img][/url] +[color=#800040][b]Il faudra adapter le script suivant [u]pour tenir compte de votre adresse IP de l'hôte[/u] du conteneur vaultwarden.[/b][/color] C'est-à-dire remplacer 192.168.2.200 par l'IP de votre NAS. + +Il est à noter que le fichier [b]/etc/nginx/app.d/server.ReverseProxy.conf[/b] est réinitialisé à chaque démarrage du NAS, mais aussi à chaque changement dans l'interface graphique du reverse-proxy dans DSM. Il faut donc le lancer périodiquement. +Il faudra créer une tâche planifiée en conséquence. +En ce qui me concerne j'ai créé une tâche déclenchée à chaque démarrage du NAS, et une programmée toutes les 6h. Vous pouvez mettre une fréquence plus grande (toutes les 1h) ou moins, c'est selon votre utilisation du NAS et des modifications dans le reverse-proxy. +La modification du fichier ressemblera à ceci : +[url=https://i.imgur.com/TPJOBIk.png][img]https://i.imgur.com/TPJOBIk.png[/img][/url] + +[color=#BF40BF][b][size=150]5.2- Comment lancer le script ?[/size][/b][/color] + +Le script (présent dans le § suivant) doit être lancé avec 3 arguments, sinon vous aurez un beau message indiquant que vous avez fait n'importe quoi... (mais sans rien casser, j'ai bien fait les choses). +Si le script n'est pas lancé avec le bon nombre d'arguments, vous aurez ce message : +[url=https://i.imgur.com/bRkCtSF.png][img]https://i.imgur.com/bRkCtSF.png[/img][/url] + +Attention, s'il y a bien 3 arguments, je n'ai pas fait de vérification, à vous de savoir ce que vous faites ! +Voici quelques explications sur les arguments à placer. +[list=][*] Le premier est votre nom de domaine pour Vaultwarden. +[*] Le second est le port déclaré dans le reverse proxy pour accéder à l'interface web : par défaut c'est 80. Il sera probablement modifié dans votre installation (voir fichier docker-compose). +[*] Le troisième est le port websocket qui par défaut est le 3012. Il sera probablement modifié dans votre installation (voir fichier docker-compose).[/list] + +Exemple de commande à placer dans le planificateur de tâches : +[code]bash /volume1/docker/_Scripts-DOCKER/vaultwarden_RS__Enable_Websocket.sh mon-ndd-a-moi.tld 8001 3012[/code] + +Voilà voilà pour les explications. +Il faudra le lancer une fois après avoir paramétré les tâches. + +[color=#BF40BF][b][size=150]5.3- Enfin le script lui même ![/size][/b][/color] + +Voir §0 pour télécharger le fichier. +Attention, j'ai mis pas mal de commentaires dans le script, et que j'ai mis des lignes echo permettant d'avoir un retour d'exécution pour le log qu'on obtient. +Lisez bien les commentaire ;) + +[code]#!/bin/bash +##============================================================================================== +## ## +## Script vaultwarden__Enable_Websocket.sh ## +## ## +## Source : https://gist.github.com/nstanke/3949ae1c4706854d8f166d1fb3dadc81 ## +## ## +##============================================================================================== +## ## +## Ce script pemet de router ce qui ne peut pas être fait avec le reverse-proxy ## +## de DSM (Synology) pour faire fonctionner les notifications Websocket ## +## Doc. vaultwarden : ## +## Route the /notifications/hub endpoint to the WebSocket server, by default ## +## at port 3012, making sure to pass the Connection and Upgrade headers. ## +## (Note the port can be changed with WEBSOCKET_PORT variable) ## +## https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications ## +## ## +##============================================================================================== +## ## +## Principe de Tâche planifier à créer ## +## ## +## Il faut lancer régulièrement le script car toutes modifications faites dans l'interface ## +## graphique du Reverse-Proxy de DSM va modifier le fichier de configuration. Il en va de ## +## même lorsque le NAS redémarre. ## +## ## +##============================================================================================== +## ## +## /!\ Il faut modifier l'adresse IP en ligne 79 et 85 par l'IP du NAS /!\ ## +## ## +##============================================================================================== +## ## +## Paramètres de lancement du script : ## +## bash /volume1/docker/vaultwarden/enable_ws.sh vault.example.com 5555 5556 ## +## ## +## -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) ## +## -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM) ## +## -- 5556 = Port exposé WEBSOCKET_PORT par Docker ## +## ## +##============================================================================================== + +LOC_DIR="/etc/nginx" +part1=0 +part2=0 + +echo -e "\n$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh pour activer les Notifications Websockets" + +f_affiche_parametre() { + echo " bash /volume1/docker/_Scripts-DOCKER/vaultwarden__Enable_Websocket.sh vault.example.com 5555 5556 " + echo " -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) " + echo " -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM)" + echo " -- 5556 = Port exposé WEBSOCKET_PORT par Docker" +} + +if [ ! $# -eq 3 ]; then + if [ $# -eq 0 ]; then + # Aucun paramètre n'a été fourni. On va afficher la liste de ce qui peut être utilisé. + echo "$(date "+%R:%S - ") Aucun paramètre fourni ! Revoir l'appel du script :" + f_affiche_parametre + else + echo "$(date "+%R:%S - ") Le nombre de paramètres fournis n'est pas correct ! Revoir l'appel du script :" + f_affiche_parametre + fi + echo -e "$(date "+%R:%S - ") ECHEC de lancement du script !!!!!!!!!\n" + exit 1 +fi + +echo "$(date "+%R:%S - ") Exécution des commandes..." + + +############################################################################################################# +## Début de la partie de création/modification de fichiers +## +if [ -f $LOC_DIR/ws.locations ]; then + rm /etc/nginx/ws.locations + part1=1 +fi +echo """ +location /notifications/hub { + proxy_pass http://192.168.2.200:$3; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; +} + +location /notifications/hub/negotiate { + proxy_pass http://192.168.2.200:$2; +} +""" >> $LOC_DIR/ws.locations + + +if ! grep -q "ws.locations" /etc/nginx/app.d/server.ReverseProxy.conf; then + sed -i "/$1;/ a\ include $LOC_DIR/ws.locations;" /etc/nginx/app.d/server.ReverseProxy.conf + if nginx -t 2>/dev/null; then synoservicecfg --reload nginx; else exit 1; fi + + part2=1 # Variable pour indiquer que cette partie a été exécutée +fi +## +## Fin de la partie de création/modification de fichiers +############################################################################################################# + +if [ $part1 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/ws.locations existait déjà, il a été supprimé puis recréé." +else + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/ws.locations n'existait pas, il a été créé." +fi +if [ $part2 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- !!!!!! ---> La modification dans le fichier /etc/nginx/app.d/server.ReverseProxy.conf n'existait pas. Elle a été écrite." + echo "$(date "+%R:%S - ") -- !!!!!! ---> Le fichier /etc/nginx/app.d/server.ReverseProxy.conf a du être réinitialisé après un reboot ou lors d'une modification du reverse-proxy dans DSM." +else + echo "$(date "+%R:%S - ") -- La modification du fichier /etc/nginx/app.d/server.ReverseProxy.conf a déjà été effectuée lors d'une précédente exécution. Aucune modification n'est donc nécessaire." +fi + +echo "$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh terminé" + +exit[/code] + + + +[i][size=150]Plus tard viendra la partie fail2ban.[/size][/i] + + + + + + + + + + + +________________ + +[size=150][color=#00BF80]À venir : intégration de fail2ban pour sécuriser un poil plus, même si avec le HTTPS et la 2FA c'est déjà bien :) +[/color][/size] \ No newline at end of file diff --git a/docker-compose/vaultwarden_AVEC_backup/config/rclone/rclone.conf b/docker-compose/vaultwarden_AVEC_backup/config/rclone/rclone.conf new file mode 100644 index 0000000..45fe51d --- /dev/null +++ b/docker-compose/vaultwarden_AVEC_backup/config/rclone/rclone.conf @@ -0,0 +1,3 @@ +[Backup_Syno] +type = local + diff --git a/docker-compose/vaultwarden_AVEC_backup/docker-compose.yml b/docker-compose/vaultwarden_AVEC_backup/docker-compose.yml new file mode 100644 index 0000000..490af46 --- /dev/null +++ b/docker-compose/vaultwarden_AVEC_backup/docker-compose.yml @@ -0,0 +1,262 @@ +##============================================================================================== +## ## +## Fichier docker-compose.yml pour Vaultwarden avec ttionya/vaultwarden-backup ## +## Révision du fichier : v4.0 ## +## ## +## Voir tuto : https://www.forum-nas.fr/viewtopic.php?f=56&t=15341&p=99007#p99007 ## +## ## +##============================================================================================== +## ## +## Attention, avec ce fichier, il faut avoir créer le réseau "vaultwarden_network" avant de ## +## créer les conteneurs. ## +## ## +## La mise en place de fail2ban se fera avec un docker-compose dédié. ## +## ## +##============================================================================================== +## ## +## NOTE IMPORTANTE ## +## ----------------- ## +## ## +## Lors de l'importation d'un fichier contenant beaucoup d'entrées, j'ai eu une erreur ## +## 405 Not Allowed - Nginx ## +## Après quelques recherches, et un certains nombre de minutes, il s'est avéré que les ## +## expiration du délai ... (les timeout) dans le reverse proxy par défaut de 60s étaient ## +## trop faible. ## +## En passant les 3 valeurs à 300s (5min), ça a réglé mon problème. ## +## (Pensez à relancer le script vaultwarden__Enable_Websocket.sh après ces modifications) ## +## ## +##============================================================================================== +## ## +## Ajout des Notifications Websocket ## +## ## +## Pour qu'elles'fonctionnent, il faut configurer le reverse-proxy correctement. ## +## Pour celui de DSM, il n'est malheureusement pas possible de configurer les ## +## redirections /notifications/hub vers le serveur WebSocket ni celles vers le port normal ## +## /notifications/hub/negotiate ## +## Voir cet article pour tout ce qui n'est pas possible via l'interface de DSM : ## +## https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications ## +## ## +## Dès lors, il faut ruser et passer par l'exécution d'un petit script qui va créer un ## +## fchier ws.locations contenant les modifications précédentes, et qui va écrire une ## +## ligne dans le fichier /etc/nginx/app.d/server.ReverseProxy.conf pour inclure le ## +## fichier ws.locations au niveau de la section concernant le nom de domaine pour ## +## vaultwarden. ## +## Comme cela, il n'est pas nécessaire de passer par le changement de reverse-proxy, assez ## +## complexe à mettre en oeuvre... ## +## ## +## Le script est : vaultwarden__Enable_Websocket.sh ## +## ## +## Il faudra la lancer régulièrement et à chaque redémarrage du NAS, via deux tâches ## +## plannifiées dédiées, en donnant 3 paramètres au fichier : ## +## - le nom de domaine de vaultwarden ## +## - le port HTTP exposé (donc pas l'interne du conteneur) pour l'interface graphique ## +## - le port websocket exposé (donc pas l'interne du conteneur) ## +## Voir les commentaires de ce fichier vaultwarden__Enable_Websocket.sh pour plus ## +## d'explications. ## +## ## +##============================================================================================== + +--- + version: "2.4" + + services: + vaultwarden: + image: vaultwarden/server:latest # https://github.com/dani-garcia/vaultwarden + # https://github.com/dani-garcia/vaultwarden/wiki + container_name: vaultwarden + networks: + - vaultwarden_network + environment: + # Utiliser la commande (en SSH) : id NOM_UTILISATEUR + - PUID=1000 + - PGID=100 + - TZ=Europe/Paris + + # Pour l'envoi d'emails + - SMTP_HOST=XXxxXX + - SMTP_FROM=XXxxXX + - SMTP_FROM_NAME=BlaBla + - SMTP_PORT=XXxxXX + - SMTP_SSL=true + - SMTP_USERNAME=XXxxXX + - SMTP_PASSWORD=XXxxXX + + - INVITATION_ORG_NAME=Vaultwarden [Votre Nom, pseudo...] # Permet de spécifier un nom d'application pour les invitations d'organisation + + # Nécessaire pour activer le 2FA pour la connexion à notre serveur Vaultwarden + # Il est possible de spécifier un port de connexion dans l'URL. Le https:// est obligatoire. + # Pour cette option, il est donc OBLIGATOIRE d'avoir fait le nécessaire pour avoir du HTTPS (certificats, reverse-proxy, ...) + - DOMAIN=XXxxXX + + # Pour enregistrer les log avec un niveau particulier + - LOG_FILE=/data/vaultwarden.log + - LOG_LEVEL=warn + - EXTENDED_LOGGING=true + + # je n'aime pas les indices pour les mots de passe... + - SHOW_PASSWORD_HINT=false + + # Pour activer la console d'administation, accessible via : https://mon.domaine.tld/admin/ + # Voir détails ici : https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page + # /!\ + # /!\ N'importe qui pourra accéder à la page de connexion, alors blinder le token d'amdin ci-dessous (64 caractères pour moi) ! + # /!\ Il est de plus TRÈS important d'avoir ACTIVÉ le HTTPS avant l'activation de cette option. + # /!\ + # Je conseille de ne l'activer qu'en cas de nécessité, et de la désactiver après. + # Pour désactiver, il suffit de commenter la ligne ci-dessous. + - ADMIN_TOKEN=XXxxXX + # À noter : + # La première fois que vous enregistrez un paramètre dans la page d'administration, 'config.json' sera généré + # dans votre 'DATA_FOLDER'. Les valeurs de ce fichier auront priorité sur les valeurs 'environnement'. + + - SIGNUPS_ALLOWED=false # Fait en sorte que les inscriptions soient bloquées, seul l'admin pourra inviter + # des utilisateurs avec un envoi d'email depuis la console d'administation + + - WEBSOCKET_ENABLED=true # Active les WebSocket notifications (Nécessite la configuration du reverse-proxy) + # Durant le nombre importants d'essais, j'en suis venu à laisser le port par défaut + # pour le WEBSOCKET_PORT. Il est possible que ça fonctionne avec un port différent. + # Il faudra alors décommenter la ligne suivante, et changer le port exposé plus bas. + #- WEBSOCKET_PORT=3012 # Par défaut = 3012 + + # Pour activer la récupération des icones des IP LAN, il faut mettre sur false la variable ICON_BLACKLIST_NON_GLOBAL_IPS + - ICON_BLACKLIST_NON_GLOBAL_IPS=false # Par défaut = true + + # On défini ici quelques chemins de dossiers qu'il faudra créer (pas sur que le conteneur les crées lui-même...) + - ICON_CACHE_FOLDER=data/icon_cache + - ATTACHMENTS_FOLDER=data/attachments + - SENDS_FOLDER=data/sends + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + volumes: + - "/volume1/docker/vaultwarden/vaultwarden-data/:/data/" + ports: + - XXxxXX:3012 # Choisir un port libre pour le websocket + - XXxxXX:80 # Choisir un port libre pour l'interface WEB + restart: unless-stopped + + vaultwarden_backup_ttionya: # Voir : https://github.com/ttionya/vaultwarden-backup + image: ttionya/vaultwarden-backup:latest + container_name: vaultwarden_backup_ttionya + networks: + - vaultwarden_network + + restart: always + + depends_on: + vaultwarden: + condition: service_healthy + + labels: + - "com.centurylinklabs.watchtower.enable=true" + + volumes: + - /volume1/docker/vaultwarden/vaultwarden-data:/data + # Chemin d'accès pour stocker le backup et la configuration rclone, voir https://github.com/ttionya/vaultwarden-backup + - /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config:/config + - /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/rclone_backup:/rclone_backup + + environment: + - DATA_DIR=/data # Dossier de données de Vaultwarden monté avec les volumes + - RCLONE_REMOTE_NAME=Backup_Syno # Nom de la config rclone utilisée (voir note plus bas) + - RCLONE_REMOTE_DIR=/rclone_backup/ # Dossier qui doit monté avec les volumes + + # Utiliser soit SCHEDULE soit INTERVAL (ce dernier en sec) + # Pour SCHEDULE : https://crontab.guru/#0_22_*_*_* + # Dans la ligne suivante, on programme l'exécution tous les jours à 22h + - CRON=0 22 * * * + - ZIP_ENABLE=TRUE + - ZIP_PASSWORD=WHEREISMYPASSWORD? + - ZIP_TYPE=7z + - BACKUP_FILE_DATE_SUFFIX=--%Hh%Mm%Ss + - BACKUP_KEEP_DAYS=7 + # - MAIL_SMTP_ENABLE=FALSE + # - MAIL_SMTP_VARIABLES='' + # - MAIL_TO='' + # - MAIL_WHEN_SUCCESS='TRUE' + # - MAIL_WHEN_FAILURE='TRUE' + - TIMEZONE=Europe/Paris + + ############################################# + # Note à propos de la configuration de rclone + ############################################# + # Si vous voulez faire une sauvegarde locale, il faut juste placer le fichier rclone.conf dans le dossier ../config/rclone/ + # Dans ce fichier vous trouverez ceci : + # [Backup_Syno] + # type = local + # + # Il faudra remplacer Backup_Syno par un autre nom au besoin. + # Ce fichier est donc prévu pour une sauvegarde locale. + # Pour configurer d'autres types de sauvegarde, il faut lancer la configuration de rclone avec cette commande : + # docker run --rm -it -v /volume1/docker/vaultwarden/vaultwarden-backup_ttionya/config:/config ttionya/vaultwarden-backup:latest rclone config + + + ############################################################################################### + # Ancienne version de la partie sauvegarde + ############################################################################################### + # Sauvegarde automatique de la base de données, au-cas-où ! + # vaultwarden_backup: # Voir : https://gitlab.com/1O/bitwarden_rs-backup + # image: bruceforce/bw_backup:latest + # container_name: vaultwarden_backup + # networks: + # - vaultwarden_network + # restart: always + # depends_on: + # vaultwarden: + # condition: service_healthy + # labels: + # - "com.centurylinklabs.watchtower.enable=true" + # volumes: + # - /volume1/docker/vaultwarden/vaultwarden-data/:/data/ + # # Chemin d'accès pour stocker le backup, voir https://gitlab.com/1O/bitwarden_rs-backup#wrong-permissions + # - /volume1/docker/vaultwarden/vaultwarden-backup:/backup_folder/ + + # environment: + # # Path to the vaultwarden sqlite3 database inside the container + # - DB_FILE=/data/db.sqlite3 + + # # Path to the desired backup location inside the container + # # - BACKUP_FILE=/data/db_backup/backup.sqlite3 + # - BACKUP_FILE=/backup_folder/backup.sqlite3 + + # # Sets the permissions of the backup file + # # The permissions should at least be 700 since the backup folder itself gets the same permissions + # # and with 600 it would not be accessible. + # - BACKUP_FILE_PERMISSIONS=700 + + # # Cronjob format "Minute Hour Day_of_month Month_of_year Day_of_week Year" + # # https://crontab.guru/#0_9_*_*_* + # # minutes | heures | jour du mois | mois | jour de la semaine + # - CRON_TIME=0 18 * * * + + # # Set to true to append timestamp to the BACKUP_FILE + # - TIMESTAMP=true + + # # User ID to run the cron job with + # - UID=1038 # J'ai créé un utilisateur dédié à vaultwarden, utiliser la commande 'id nom_user' + + # # Group ID to run the cron job with + # - GID=100 + + # # Path to the logfile inside the container + # #- LOGFILE + + # # Path to the cron file inside the container + # #- CRONFILE + + # # Delete old backups after X many days + # - DELETE_AFTER=14 + + # # If you need timestamps in your local timezone you should mount /etc/timezone:/etc/timezone:ro and + # # /etc/localtime:/etc/localtime:ro like it's done in the docker-compose.yml. + # # An other possible solution is to set the environment variable accordingly (like TZ=Europe/Berlin) + # # (see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for more information). + # - TZ=Europe/Paris + ############################################################################################### + + networks: + vaultwarden_network: + external: + name: vaultwarden_network + \ No newline at end of file diff --git a/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-6.x.sh b/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-6.x.sh new file mode 100644 index 0000000..da0f61e --- /dev/null +++ b/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-6.x.sh @@ -0,0 +1,114 @@ +#!/bin/bash +##============================================================================================== +## ## +## Script vaultwarden__Enable_Websocket-DSM_6.x.sh ## +## ## +## Source : https://gist.github.com/nstanke/3949ae1c4706854d8f166d1fb3dadc81 ## +## ## +##============================================================================================== +## ## +## Ce script pemet de router ce qui ne peut pas être fait avec le reverse-proxy ## +## de DSM (Synology) pour faire fonctionner les notifications Websocket ## +## Doc. vaultwarden : ## +## Route the /notifications/hub endpoint to the WebSocket server, by default ## +## at port 3012, making sure to pass the Connection and Upgrade headers. ## +## (Note the port can be changed with WEBSOCKET_PORT variable) ## +## https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications ## +## ## +##============================================================================================== +## ## +## Principe de Tâche planifier à créer ## +## ## +## Il faut lancer régulièrement le script car toutes modifications faites dans l'interface ## +## graphique du Reverse-Proxy de DSM va modifier le fichier de configuration. Il en va de ## +## même lorsque le NAS redémarre. ## +## ## +##============================================================================================== +## ## +## /!\ Il faut modifier l'adresse IP en ligne 79 et 85 par l'IP du NAS /!\ ## +## ## +##============================================================================================== +## ## +## Paramètres de lancement du script : ## +## bash /volume1/docker/bitwarden/enable_ws.sh vault.example.com 5555 5556 ## +## ## +## -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) ## +## -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM) ## +## -- 5556 = Port exposé WEBSOCKET_PORT par Docker ## +## ## +##============================================================================================== + +LOC_DIR="/etc/nginx" +part1=0 +part2=0 + +echo -e "\n$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh pour activer les Notifications Websockets" + +f_affiche_parametre() { + echo " bash /volume1/docker/_Scripts-DOCKER/vaultwarden__Enable_Websocket.sh vault.example.com 5555 5556 " + echo " -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) " + echo " -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM)" + echo " -- 5556 = Port exposé WEBSOCKET_PORT par Docker" +} + +if [ ! $# -eq 3 ]; then + if [ $# -eq 0 ]; then + # Aucun paramètre n'a été fourni. On va afficher la liste de ce qui peut être utilisé. + echo "$(date "+%R:%S - ") Aucun paramètre fourni ! Revoir l'appel du script :" + f_affiche_parametre + else + echo "$(date "+%R:%S - ") Le nombre de paramètres fournis n'est pas correct ! Revoir l'appel du script :" + f_affiche_parametre + fi + echo -e "$(date "+%R:%S - ") ECHEC de lancement du script !!!!!!!!!\n" + exit 1 +fi + +echo "$(date "+%R:%S - ") Exécution des commandes..." + + +############################################################################################################# +## Début de la partie de création/modification de fichiers +## +if [ -f $LOC_DIR/ws.locations ]; then + rm /etc/nginx/ws.locations + part1=1 +fi +echo """ +location /notifications/hub { + proxy_pass http://192.168.2.200:$3; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; +} + +location /notifications/hub/negotiate { + proxy_pass http://192.168.2.200:$2; +} +""" >> $LOC_DIR/ws.locations + + +if ! grep -q "ws.locations" /etc/nginx/app.d/server.ReverseProxy.conf; then + sed -i "/$1;/ a\ include $LOC_DIR/ws.locations;" /etc/nginx/app.d/server.ReverseProxy.conf + if nginx -t 2>/dev/null; then synoservicecfg --reload nginx; else exit 1; fi + + part2=1 # Variable pour indiquer que cette partie a été exécutée +fi +## +## Fin de la partie de création/modification de fichiers +############################################################################################################# + +if [ $part1 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/ws.locations existait déjà, il a été supprimé puis recréé." +else + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/ws.locations n'existait pas, il a été créé." +fi +if [ $part2 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- !!!!!! ---> La modification dans le fichier /etc/nginx/app.d/server.ReverseProxy.conf n'existait pas. Elle a été écrite." + echo "$(date "+%R:%S - ") -- !!!!!! ---> Le fichier /etc/nginx/app.d/server.ReverseProxy.conf a du être réinitialisé après un reboot ou lors d'une modification du reverse-proxy dans DSM." +else + echo "$(date "+%R:%S - ") -- La modification du fichier /etc/nginx/app.d/server.ReverseProxy.conf a déjà été effectuée lors d'une précédente exécution. Aucune modification n'est donc nécessaire." +fi + +echo "$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh terminé" + +exit \ No newline at end of file diff --git a/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-7.sh b/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-7.sh new file mode 100644 index 0000000..dd59d5d --- /dev/null +++ b/docker-compose/vaultwarden_AVEC_backup/vaultwarden__Enable_Websocket_DSM-7.sh @@ -0,0 +1,129 @@ +#!/bin/bash +##============================================================================================== +## ## +## Script vaultwarden__Enable_Websocket-DSM_7.sh ## +## ## +## Source : https://gist.github.com/nstanke/3949ae1c4706854d8f166d1fb3dadc81 ## +## ## +##============================================================================================== +## ## +## Ce script pemet de router ce qui ne peut pas être fait avec le reverse-proxy ## +## de DSM (Synology) pour faire fonctionner les notifications Websocket ## +## Doc. vaultwarden : ## +## Route the /notifications/hub endpoint to the WebSocket server, by default ## +## at port 3012, making sure to pass the Connection and Upgrade headers. ## +## (Note the port can be changed with WEBSOCKET_PORT variable) ## +## https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications ## +## ## +##============================================================================================== +## ## +## Principe de Tâche planifier à créer ## +## ## +## Il faut lancer régulièrement le script car toutes modifications faites dans l'interface ## +## graphique du Reverse-Proxy de DSM va modifier le fichier de configuration. Il en va de ## +## même lorsque le NAS redémarre. ## +## ## +##============================================================================================== +## ## +## /!\ Il faut modifier l'adresse IP en ligne 47 par l'IP du NAS /!\ ## +## ## +##============================================================================================== +## ## +## Paramètres de lancement du script : ## +## bash /volume1/docker/bitwarden/enable_ws.sh vault.example.com 5555 5556 ## +## ## +## -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) ## +## -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM) ## +## -- 5556 = Port exposé WEBSOCKET_PORT par Docker ## +## ## +##============================================================================================== + +LOC_DIR="/etc/nginx" +part1=0 +part2=0 +MY_DOMAIN=$1 +PORT_ACCES=$2 +PORT_CONT=$3 +IP_NAS="192.168.2.200" + +echo -e "\n$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh pour activer les Notifications Websockets" + +f_affiche_parametre() { + echo " bash /volume1/docker/_Scripts-DOCKER/vaultwarden__Enable_Websocket.sh vault.example.com 5555 5556 " + echo " -- vault.example.com = Nom de domaine de vaultwarden (celui du Reverse Proxy de DSM) " + echo " -- 5555 = Port exposé ROCKET_PORT par Docker (Identique à celui du Reverse Proxy de DSM)" + echo " -- 5556 = Port exposé WEBSOCKET_PORT par Docker" +} + +if [ ! $# -eq 3 ]; then + if [ $# -eq 0 ]; then + # Aucun paramètre n'a été fourni. On va afficher la liste de ce qui peut être utilisé. + echo "$(date "+%R:%S - ") Aucun paramètre fourni ! Revoir l'appel du script :" + f_affiche_parametre + else + echo "$(date "+%R:%S - ") Le nombre de paramètres fournis n'est pas correct ! Revoir l'appel du script :" + f_affiche_parametre + fi + echo -e "$(date "+%R:%S - ") ECHEC de lancement du script !!!!!!!!!\n" + exit 1 +fi + +echo "$(date "+%R:%S - ") Exécution des commandes..." + + +############################################################################################################# +## Début de la partie de création/modification de fichiers +## +if [ -f $LOC_DIR/websocket.locations.vaultwarden ]; then + rm $LOC_DIR/websocket.locations.vaultwarden + part1=1 +fi +echo """ +location /notifications/hub { + proxy_pass http://$IP_NAS:$PORT_CONT; + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; +} + +location /notifications/hub/negotiate { + proxy_pass http://$IP_NAS:$PORT_ACCES; +} +""" >>$LOC_DIR/websocket.locations.vaultwarden + +# Note : avec DSM7, le chemin d'accès du fichier server.ReverseProxy.conf a changé +# DSM6.2 = /etc/nginx/app.d/server.ReverseProxy.conf +# DSM7 = /etc/nginx/sites-enabled/server.ReverseProxy.conf +if ! grep -q "websocket.locations.vaultwarden" /etc/nginx/sites-enabled/server.ReverseProxy.conf; then + + # Commandes fonctionnelles avec DSM6.2.x, mais plus avec DSM 7.0 (RC) + #sed -i "/$1;/ a\ include $LOC_DIR/websocket.locations.vaultwarden;" /etc/nginx/app.d/server.ReverseProxy.conf + #if nginx -t 2>/dev/null; then synoservicecfg --reload nginx; else exit 1; fi + + # Commande fonctionnelles avec DSM 7 (RC) + sed -r "s#^([[:blank:]]*server_name[[:blank:]]*${MY_DOMAIN}[[:blank:]]*;[[:blank:]]*)\$#\1\n\n\tinclude ${LOC_DIR}/websocket.locations.vaultwarden;#" /etc/nginx/sites-enabled/server.ReverseProxy.conf > /etc/nginx/sites-enabled/server.ReverseProxy.conf.new + mv /etc/nginx/sites-enabled/server.ReverseProxy.conf.new /etc/nginx/sites-enabled/server.ReverseProxy.conf + + if nginx -t 2>/dev/null; then synosystemctl reload nginx; else exit 1; fi + + part2=1 # Variable pour indiquer que cette partie a été exécutée + +fi +## +## Fin de la partie de création/modification de fichiers +############################################################################################################# + +if [ $part1 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/websocket.locations.vaultwarden existait déjà, il a été supprimé puis recréé." +else + echo "$(date "+%R:%S - ") -- Le fichier $LOC_DIR/websocket.locations.vaultwarden n'existait pas, il a été créé." +fi +if [ $part2 -eq 1 ]; then + echo "$(date "+%R:%S - ") -- !!!!!! ---> La modification dans le fichier /etc/nginx/sites-enabled/server.ReverseProxy.conf n'existait pas. Elle a été écrite." + echo "$(date "+%R:%S - ") -- !!!!!! ---> Le fichier /etc/nginx/sites-enabled/server.ReverseProxy.conf a du être réinitialisé après un reboot ou lors d'une modification du reverse-proxy dans DSM." +else + echo "$(date "+%R:%S - ") -- La modification du fichier /etc/nginx/sites-enabled/server.ReverseProxy.conf a déjà été effectuée lors d'une précédente exécution. Aucune modification n'est donc nécessaire." +fi + +echo "$(date "+%R:%S - ") Script vaultwarden__Enable_Websocket.sh terminé" + +exit \ No newline at end of file diff --git a/docker-compose/watchtower/docker-compose.yml b/docker-compose/watchtower/docker-compose.yml new file mode 100755 index 0000000..99e3012 --- /dev/null +++ b/docker-compose/watchtower/docker-compose.yml @@ -0,0 +1,29 @@ +## Discord Plex FR : https://discord.gg/ERpYMqS +## Version 2021-02-26 +version: "2.3" +services: + watchtower: + container_name: watchtower + image: containrrr/watchtower:amd64-latest + restart: unless-stopped + environment: + - TZ=Europe/Paris + - WATCHTOWER_SCHEDULE= 0 0 6 * * * #mise a jour des conteneurs tous les jours a 6:00 + - WATCHTOWER_LABEL_ENABLE=true + - WATCHTOWER_CLEANUP=true + - WATCHTOWER_REMOVE_VOLUMES=true + - WATCHTOWER_NOTIFICATIONS_LEVEL=debug +#Les 3 lignes dessous sont a utiliser pour être notifié par Gotify +# - WATCHTOWER_NOTIFICATIONS=gotify +# - WATCHTOWER_NOTIFICATION_GOTIFY_URL=https://gotify.ndd.fr +# - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN= + - WATCHTOWER_ROLLING_RESTART=true + - WATCHTOWER_LIFECYCLE_HOOKS=true +#Les 3 lignes dessous sont a utiliser pour être notifié par SLACK/DISCORD +# - WATCHTOWER_NOTIFICATIONS=slack #si discord laissé slack +# - WATCHTOWER_NOTIFICATION_SLACK_IDENTIFIER=Watchtower +# - WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL=URL-DU-TOKEN/slack #si discord laissé /slack + volumes: + - /var/run/docker.sock:/var/run/docker.sock +# Network conseillé de ne pas utiliser host (pas de redirection de port) ni default_bridge car limité a 16 ip + network_mode: 'watchtower_network' \ No newline at end of file diff --git a/wiki/activer_skip_intro.md b/wiki/activer_skip_intro.md new file mode 100644 index 0000000..5877d88 --- /dev/null +++ b/wiki/activer_skip_intro.md @@ -0,0 +1,33 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* + +*Version 2021-02-26* + +# Activer la fonction Skip Intro + +Disponible depuis la version 1.19.3.2793, cette fonction permet de passer les génériques d’intro des séries. +Les intros de moins de 20 secondes sont ignorées ainsi que celles situées à plus de la moitié de l’épisode. +Cette fonctionnalité va analyser chaque épisode de chaque série pour déterminer l’introduction, cela peut donc prendre du temps! +Attention, le Plex Pass est obligatoire pour l’utilisateur qui regarde du contenu, ainsi que le propriétaire du serveur Plex! +(Les utilisateurs gérés présents dans le PlexHOME ont également accès à cette fonction.) + +**Lecteurs compatibles :** +- Fire TV `v.8.0.1+` +- Android mobile `v.8.0.1+` +- Android TV `v.8.0.1+` +- Apple TV `v.2.18+` +- iOS `v.6.12+` +- macOS `v.1.11+` +- Roku `v.6.5.4+` +- Web `v.4.34+` +- Windows `v.1.11+` + +**Activer l’analyse automatique :** +• Sur Plex allez ici: `Paramètres → Bibliothèque` +• Repérez le réglage `Generate intro video markers` et mettez-le soit en `tâche planifiée`, soit `tâche planifiée et quand un média est ajouté` (Je vous conseille la 1ère option car l’analyse se fera uniquement durant la maintenance.) + +Si vous avez plusieurs bibliothèques telles que: Séries TV, Séries d’animation et Toutes les Séries. Vous devriez décocher l’option `enable intro detection` (`••• → Gérer la bibliothèque → Modifier → Avancé`) des bibliothèques Séries TV ainsi que Séries d’animation (car l’analyse sera effectuée sur la bibliothèque Toutes les Séries et cela évite au serveur de ré-analyser chaque fichier.) + +**Analyse manuelle :** +Pour analyser manuellement une bibliothèque (`••• → Gérer la bibliothèque → Analyser`), ou une série (`••• → Analyser`). + +*Écrit par Ymerix le 04/09/2020* diff --git a/wiki/installation_docker_portainer_raspbian.md b/wiki/installation_docker_portainer_raspbian.md new file mode 100755 index 0000000..5059e79 --- /dev/null +++ b/wiki/installation_docker_portainer_raspbian.md @@ -0,0 +1,51 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS Version 2021-03-08* + +### Installation de Docker, Docker-compose et Portainer sur raspbian + +## Sommaire +* [Pré-requis](#pré-requis) +* [Installation de Docker](#installation-de-docker) +* [Installation de Docker-compose](#installation-de-docker-compose) +* [Installation de Portainer](#installation-de-portainer) + +## Pré-requis : + +En 1er temps, on met a jour le raspberry : +`sudo apt update && sudo apt upgrade -y` + +## Installation de Docker : + +On install docker : +`curl -sSL https://get.docker.com | sh` + +On ajoute l'utilisateur pi au groupe docker : +`sudo usermod -aG docker pi` + +## Installation de Docker-compose : + +On install les dépendances nécessaires : +`sudo apt install libffi-dev libssl-dev python3 python3-pip` + +On install docker-compose +`sudo pip3 install docker-compose` + +On redémarre le Raspberry +`sudo reboot` + +## Installation de Portainer : + +On créer le volume portainer_data nécessaire au fonctionnement de Portainer +docker volume create portainer_data + +On créer le conteneur contenant Portainer, et on le lance : +`docker run -d -p 8000:8000 -p 9000:9000 --restart unless-stopped --name="Portainer" -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer` + +Maintenant nous pouvons accéder à l'interface de Portainer, via l'adresse : http://adresse_du_pi:9000/ +Exemple, si votre Pi est a l'adresse ip 192.168.1.210, l'interface de Portainer sera l'adresse : http://192.168.1.210:9000/ + +La 1ere chose a faire est de choisir un nom d'utilisateur et un mot de passe, ensuite, on choisi la méthode de connexion a docker, on choisi "Local" et on clique sur "Connect" + + +[Source 1](https://linuxhint.com/install_docker_on_raspbian_os/) | [Source 2](https://www.zuidwijk.com/installing-docker-and-docker-compose-on-a-raspberry-pi-4/) + +*Écrit par EVOTk le 04/09/2020* diff --git a/wiki/la_casa_de_papel.md b/wiki/la_casa_de_papel.md new file mode 100644 index 0000000..b762548 --- /dev/null +++ b/wiki/la_casa_de_papel.md @@ -0,0 +1,72 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* +*Version 2021-02-26* + +# Association La Casa De Papel + +Pour les détenteurs de la serie `La Casa de Papel` sur Plex, vous avez dû remarquer que l'association de la série est impossible car les episodes ne sont pas répertorié de la même manière sur TMDb, TheTVDB et Netflix, (TMDb & TheTVDB 2 saisons, Netflix 4 saisons) nous allons voir comment mettre en place les 4 saisons sur Plex comme sur Netflix avec les titres des épisodes, les cover, les fanart et la liste des acteurs ! + +Les épisodes doivent être rangés comme suit : +- Saison 1 : 13 épisodes +- Saison 2 : 9 épisodes +- Saison 3 : 8 épisodes +- Saison 4 : 8 épisodes + +C'est d'ailleurs dans ce format là que vous allez la trouver la plupart du temps, d'où l'intérêt de ce tutoriel 😉 + +**! Attention !** Si jamais vos épisodes ne sont pas répertorié de cette manière sur Plex, déplacer votre série complètement de votre dossier série, lancer un scan sur Plex pour que celle-ci n'apparaisse plus, réorganiser là de cette manière et remettez là dans votre dossier série, scannez à nouveau pour qu'elle apparaisse dans cet ordre là ! + +Plutôt que de tout editer manuellement il existe une façon plus simple de tout corriger avec l'outil `XBMCnfoTVimporter`. + +Il ajoute un nouvel agent à Plex lisant des fichiers nfo locaux. (Ça devrait être intégré sur Plex mais bon 🙄) + +***Télécharger le Plug-in Webtools ici :*** [WebTools](https://github.com/ukdtom/WebTools.bundle/releases/tag/3.0.0) + +Pour l'installer, placer le dossier WebTools.bundle dans votre dossier Plug-in Plex (vérifier bien que le nom du dossier soit webtools.bundle et pas autre chose !) + +Redémarrez votre serveur Plex, vous devrez le voir apparaître dans vos extensions dans la page de gestion de votre serveur Plex, `Paramètres > Réglages > Extension`. + +Maintenant rendez-vous sur la plage : http://ipduserveurPlex:33400 + +Logguer vous avec vos identifiants Plex. +Dans le menu sur la gauche, cliquer sur `UAS`. +Dans les catégories à droite > `Agent` + +Enfin, installer l'agent `XBMCnfoTVImporter`. + +Une fois l'installation terminée, redémarrer votre serveur Plex. + +Rendez-vous maintenant sur votre page d'administration Plex > `Paramètres > Agents > Séries > XBMCnfoTVImporter`. + +Cocher tout les agents et placez-les dans l'ordre suivant : +- Local Media Assets (TV) +- XBMCnfoTVImporter +- Plexe Theme Music +- OpenSubtitles.org + +Cliquer sur le logo Paramètres à côté de XBMCnfoTqvImporter puis cocher `disable agents artwork support` , et `SAUVEGARDER`. + +Ensuite, télécharger le pack de données de la série, j'ai fais un repack de plusieurs données que j'ai trouver sur le net, il contient les .nfo, les cover et les fanart, tout en français ! + +Télécharger ici : https://uptobox.com/8fajowr00h0w + +Maintenant, il faut extraire les fichiers dans votre dossier "La Casa de papel", l'arborescence est déjà faite, attention, le nom des fichier NFO et JPG doivent correpondre au nom de l'épisode en question ! S'ils ne sont pas nommé de la même manière chez vous pensez à les renommer pour qu'ils correspondent ! + +Ensuite, allez dans Plex, La Casa de Papel > "corriger l'association" (3 petits points sur la droite de la cover de la série) > Options de recherche (en haut en orange) et maintenant sélectionnez le nouveau XBMC... dans Agent de la liste déroulante et cliquer sur Rechercher. + +La Casa de Papel va maintenant apparaître, cliquer dessus. + +Actualisé les métadonnées et attendez la fin du téléchargement des métadonnées. + +Vous devez charger le fond des saisons manuellement, il correspond au fichier SeasonXX-fanart.jpg dans leur dossier saison respectif. + +Je vous ai aussi mis les synospys des saisons que vous devrez ajouter manuellement sur Plex en cliquant sut le petit crayon sur la cover de la saison. + +Voilà, vous avez maintenant la Casa de Papel correctement répertorié sur Plex 😊. + +Le seul problème restant, qui ne peux malheureusement pas être règlé, est pour les utilisateurs de Sonarr, la série ne sera jamais détecté comme complète car les saisons ne sont pas rangées comme sur TheTVDB. + +**Crédits :** +- NFO (BenMitnicK édité par Razor_AMG) +- Fanart (BenMitnicK) +- Cover a (XDM) +- Cover b (Razor_AMG) diff --git a/wiki/markdown.md b/wiki/markdown.md new file mode 100755 index 0000000..7c77113 --- /dev/null +++ b/wiki/markdown.md @@ -0,0 +1,43 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* *Version 2021-3-07* + +###Markdown + +**Styles :** +- Italique : *texte* ou _texte_ +- Gras : **texte** +- Souligné : __texte__ +- Barré : ~~texte~~ +- Italique souligné : __*texte*__ +- Gras souligné : __**texte**__ +- Gras italique : ***texte*** +- Gras italique souligné : __***texte***__ +- Gras italique souligné barré : ~~__***texte***__~~ +- Spoil : ||texte|| +*ce ne sont que des exemples, mais vous pouvez jongler entre les différents styles* +*note : Si un style italique souligné commence avec __*, il doit finir avec *__* + +**Blocs de code :** +- Simple : [Image](https://support.discord.com/hc/article_attachments/360058503112/1_code_block.png) +- Gros bloc : [Image](https://support.discord.com/hc/article_attachments/360058503132/2_multiple_line_code_blocks.png) +- Gros bloc avec couleur de code : [Image](https://support.discord.com/hc/article_attachments/360058666851/3_css.png) +*impossible de montrer autrement qu'avec des images pour ces 3 exemples* + +**Citations :** +Citation : > texte +Bloc +de +citation : >>> texte + +**Liens :** +[Text](link) +Voici un texte avec un lien vers [un site sur les réseaux de neurones](https://www.neural-networks.io) + +**Titres de section :** +# h1 Heading +## h2 Heading +### h3 Heading +#### h4 Heading +##### h5 Heading +###### h6 Heading + +*Écrit par Ymerix le 23/02/2021* diff --git a/wiki/nvidia_transcoding.md b/wiki/nvidia_transcoding.md new file mode 100755 index 0000000..2531076 --- /dev/null +++ b/wiki/nvidia_transcoding.md @@ -0,0 +1,9 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* *Version 2021-03-07* + +# nvidia transcoding + +Estimation du nombre de transcode de votre carte nvidia + +[Elpamsoft.com](https://www.elpamsoft.com/?p=Plex-Hardware-Transcoding) + +*Écrit par Zoz le 19/11/2020* diff --git a/wiki/passmark.md b/wiki/passmark.md new file mode 100644 index 0000000..e291244 --- /dev/null +++ b/wiki/passmark.md @@ -0,0 +1,27 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* +*Version 2021-02-26* + +# Passmark & Transcodage Software + +Le Passmark est un indice de puissance brute de calcul d'un processeur. Celui-ci est exprimé en **points**. +Plus le score est élevé, plus le processeur est "puissant". + +Pour connaitre le score de votre processeur, rendez-vous ici : https://www.cpubenchmark.net/ + +## Recommandations de Plex : + +Pour un seul transcodage complet d'une vidéo, les exigences de score PassMark suivantes sont une bonne indication : +- 4K HDR (50Mbps, 10-bit HEVC) file: 17000 PassMark score* +- 4K SDR (40Mbps, 8-bit HEVC) file: 12000 PassMark score* +- 1080p (10Mbps, H.264) file: 2000 PassMark score +- 720p (4Mbps, H.264) file: 1500 PassMark score + +**en transcodage vers une version 1080p 10Mbps* + + +## Exemple : +Si on prend exemple sur un [Intel J4125](https://www.cpubenchmark.net/cpu.php?cpu=Intel+Celeron+J4125+%40+2.00GHz&id=3667), celui possède 3108 points. + +En **transcodage software**, il sere donc capable de transcoder au maximum un flux 1080p. Mais bien incapable de transcoder un flux 4K ! + +**Source :** [Support Plex](https://support.plex.tv/articles/201774043-what-kind-of-cpu-do-i-need-for-my-server/) diff --git a/wiki/quel_serveur_acheter.md b/wiki/quel_serveur_acheter.md new file mode 100755 index 0000000..25cb7d5 --- /dev/null +++ b/wiki/quel_serveur_acheter.md @@ -0,0 +1,18 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* *Version 2021-03-07* + +# Quel serveur acheter + +- Combien de transcodages en simultanés ? +- Connexion locale et/ou distante ? +- Connexion internet actuelle ? +- Faire profiter mon entourage ? +- Nombre d'utilisateurs ? +- Quels disques pour les films/séries et où les mettre ? +- Quantité de stockage ? +- Serveur dédié à Plex ou pas ? +- Quel budget (hors disques durs) ? +- Solutions plutôt clés en main ou un Linux pourrait convenir ? + +__**Et répondez-y en-dessous pour que l'on puisse vous aider.**__ + +*Écrit par Ymerix le 04/09/2020* diff --git a/wiki/quicksync.md b/wiki/quicksync.md new file mode 100755 index 0000000..fad8eff --- /dev/null +++ b/wiki/quicksync.md @@ -0,0 +1,10 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* *Version 2021-03-07* + +# Quiksync + +Quicksync permet un nombre de transcodes énorme sans cartes graphique, c'est une solution a considéré si vous souhaitez un serveur capable de plus de 10 transcodes... + +[Serverbuilds](https://forums.serverbuilds.net/t/guide-hardware-transcoding-the-jdm-way-quicksync-and-nvenc/1408/3) + +*Écrit par Zoz le 19/11/2020* + diff --git a/wiki/transcoder_4k.md b/wiki/transcoder_4k.md new file mode 100755 index 0000000..d6c669b --- /dev/null +++ b/wiki/transcoder_4k.md @@ -0,0 +1,27 @@ +*Discord Plex FR : https://discord.gg/ERpYMqS* *Version 2021-03-08* + +# Transcoder 4k + +__**ON NE TRANSCODE PAS DE LA 4K !**__ + +░░░░░▄▄▄▄▀▀▀▀▀▀▀▀▄▄▄▄▄▄░░░░░░░ +░░░░░█░░░░▒▒▒▒▒▒▒▒▒▒▒▒░░▀▀▄░░░░ +░░░░█░░░▒▒▒▒▒▒░░░░░░░░▒▒▒░░█░░░ +░░░█░░░░░░▄██▀▄▄░░░░░▄▄▄░░░░█░░ +░▄▀▒▄▄▄▒░█▀▀▀▀▄▄█░░░██▄▄█░░░░█░ +█░▒█▒▄░▀▄▄▄▀░░░░░░░░█░░░▒▒▒▒▒░█ +█░▒█░█▀▄▄░░░░░█▀░░░░▀▄░░▄▀▀▀▄▒█ +░█░▀▄░█▄░█▀▄▄░▀░▀▀░▄▄▀░░░░█░░█░ +░░█░░░▀▄▀█▄▄░█▀▀▀▄▄▄▄▀▀█▀██░█░░ +░░░█░░░░██░░▀█▄▄▄█▄▄█▄████░█░░░ +░░░░█░░░░▀▀▄░█░░░█░█▀██████░█░░ +░░░░░▀▄░░░░░▀▀▄▄▄█▄█▄█▄█▄▀░░█░░ +░░░░░░░▀▄▄░▒▒▒▒░░░░░░░░░░▒░░░█░ +░░░░░░░░░░▀▀▄▄░▒▒▒▒▒▒▒▒▒▒░░░░█░ +░░░░░░░░░░░░░░▀▄▄▄▄▄░░░░░░░░█░░ + +__**ON NE TRANSCODE PAS DE LA 4K !**__ + +[Plus sérieusement la solution ici !](https://peertube.zoz-serv.org/videos/watch/506fbe5e-2973-43bc-9e96-a686e54b1c20) + +*Écrit par Ymerix le 04/09/2020, Maj Zoz le 07/03/2021*