Mise en place d'une plateforme logicielle NAS sécurisée


Dans un article précédent , la conception de la plate-forme logicielle NAS a été décrite.
Il est temps de le mettre en œuvre.


Vérifier


Assurez-vous de vérifier la santé de la piscine avant de commencer:


zpool status -v 

Le pool et tous les disques qu'il contient doivent ĂŞtre EN LIGNE.


De plus, je suppose qu'à l'étape précédente, tout a été fait selon les instructions , et cela fonctionne, ou vous-même comprenez bien ce que vous faites.


Commodités


Tout d'abord, cela vaut la peine de prendre soin d'une gestion pratique si vous ne l'avez pas fait dès le début.
Il faudra:


  • Serveur SSH: apt-get install openssh-server . Si vous ne savez pas comment configurer SSH, faire NAS sur Linux est trop tĂ´t Vous pouvez lire les caractĂ©ristiques de son utilisation dans cet article , puis utiliser l' un des manuels .
  • tmux ou Ă©cran : apt-get install tmux . Pour enregistrer la session lors de la connexion via SSH et utiliser plusieurs fenĂŞtres.

Après avoir installé SSH, vous devez ajouter un utilisateur afin de ne pas vous connecter via SSH en tant que root (l'entrée est désactivée par défaut et vous n'avez pas besoin de l'activer):


 zfs create rpool/home/user adduser user cp -a /etc/skel/.[!.]* /home/user chown -R user:user /home/user 

Pour l'administration Ă  distance, c'est un minimum suffisant.


Néanmoins, alors que vous devez garder le clavier et le moniteur connectés, comme vous devrez également redémarrer lors de la mise à jour du noyau et afin de vous assurer que tout fonctionne immédiatement après le chargement.


Une alternative consiste à utiliser Virtual KVM, qui fournit IME . Il y a une console là-bas, bien que dans mon cas, elle soit implémentée comme une applet Java, ce qui n'est pas très pratique.


Personnalisation


Préparation du cache


Pour autant que vous vous en souvenez, dans la configuration décrite par moi, il y a un SSD séparé sous L2ARC, qui n'est pas encore utilisé, mais pris "pour la croissance".


Facultatif, mais il est conseillé de remplir ce SSD avec des données aléatoires (dans le cas de Samsung EVO, il sera toujours rempli de zéros après l'exécution de blkdiscard, mais pas sur tous les SSD comme celui-ci):


 dd if=/dev/urandom of=/dev/disk/by-id/ata-Samsung_SSD_850_EVO bs=4M && blkdiscard /dev/disk/by-id/ata-Samsung_SSD_850_EVO 

Désactiver la compression des journaux


Sur ZFS, la compression est déjà utilisée, car la compression des journaux via gzip sera clairement superflue.
Désactiver:


 for file in /etc/logrotate.d/* ; do if grep -Eq "(^|[^#y])compress" "$file" ; then sed -i -r "s/(^|[^#y])(compress)/\1#\2/" "$file" fi done 

Mise à jour du système


Ici, tout est simple:


 apt-get dist-upgrade --yes reboot 

Création d'un instantané pour un nouvel état


Après le redémarrage, afin de corriger le nouvel état de fonctionnement, vous devez réécrire le premier instantané:


 zfs destroy rpool/ROOT/debian@install zfs snapshot rpool/ROOT/debian@install 

Organisation du système de fichiers


Partitionnement pour SLOG


La première chose à faire pour obtenir des performances ZFS normales est de mettre SLOG sur le SSD.
Permettez-moi de vous rappeler que SLOG dans la configuration utilisée est dupliqué sur deux SSD: pour cela, les périphériques sur LUKS-XTS seront créés en haut de la 4ème section de chaque SSD:


 dd if=/dev/urandom of=/etc/keys/slog.key bs=1 count=4096 cryptsetup --verbose --cipher "aes-xts-plain64:sha512" --key-size 512 --key-file /etc/keys/slog.key luksFormat /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part4 cryptsetup --verbose --cipher "aes-xts-plain64:sha512" --key-size 512 --key-file /etc/keys/slog.key luksFormat /dev/disk/by-id/ata-Micron_1100-part4 echo "slog0_crypt1 /dev/disk/by-id/ata-Samsung_SSD_850_PRO-part4 /etc/keys/slog.key luks,discard" >> /etc/crypttab echo "slog0_crypt2 /dev/disk/by-id/ata-Micron_1100-part4 /etc/keys/slog.key luks,discard" >> /etc/crypttab 

Partitionnement pour L2ARC et Swap


Vous devez d'abord créer des partitions sous swap et l2arc:


 sgdisk -n1:0:48G -t1:8200 -c1:part_swap -n2::196G -t2:8200 -c2:part_l2arc /dev/disk/by-id/ata-Samsung_SSD_850_EVO 

La partition de swap et L2ARC seront chiffrés sur une clé aléatoire, comme après un redémarrage, ils ne sont pas nécessaires et il est toujours possible de les recréer.
Par conséquent, dans crypttab, une ligne est écrite pour chiffrer / déchiffrer les partitions en mode clair:


 echo swap_crypt /dev/disk/by-id/ata-Samsung_SSD_850_EVO-part1 /dev/urandom swap,cipher=aes-xts-plain64:sha512,size=512 >> /etc/crypttab echo l2arc_crypt /dev/disk/by-id/ata-Samsung_SSD_850_EVO-part2 /dev/urandom cipher=aes-xts-plain64:sha512,size=512 >> /etc/crypttab 

Ensuite, vous devez redémarrer les démons et activer l'échange:


 echo 'vm.swappiness = 10' >> /etc/sysctl.conf sysctl vm.swappiness=10 systemctl daemon-reload systemctl start systemd-cryptsetup@swap_crypt.service echo /dev/mapper/swap_crypt none swap sw,discard 0 0 >> /etc/fstab swapon -av 

Parce que swapiness n'est pas activement utilisé sur le SSD; le paramètre swapiness , qui est 60 par défaut, doit être défini sur 10.


L2ARC n'est pas encore utilisé à ce stade, mais la section correspondante est déjà prête:


 $ ls /dev/mapper/ control l2arc_crypt root_crypt1 root_crypt2 slog0_crypt1 slog0_crypt2 swap_crypt tank0_crypt0 tank0_crypt1 tank0_crypt2 tank0_crypt3 

Réservoir de piscinesN


La création du pool tank0 sera décrite, tank1 est créé par analogie.


Afin de ne pas créer manuellement les mêmes partitions et d'éviter les erreurs, j'ai écrit un script pour créer des partitions chiffrées pour les pools:


create_crypt_pool.sh
 #!/bin/bash KEY_SIZE=512 POOL_NAME="$1" KEY_FILE="/etc/keys/${POOL_NAME}.key" LUKS_PARAMS="--verbose --cipher aes-xts-plain64:sha${KEY_SIZE} --key-size $KEY_SIZE" [ -z "$1" ] && { echo "Error: pool name empty!" ; exit 1; } shift [ -z "$*" ] && { echo "Error: devices list empty!" ; exit 1; } echo "Devices: $*" read -p "Is it ok? " a [ "$a" != "y" ] && { echo "Bye"; exit 1; } dd if=/dev/urandom of=$KEY_FILE bs=1 count=4096 phrase="?" read -s -p "Password: " phrase echo read -s -p "Repeat password: " phrase1 echo [ "$phrase" != "$phrase1" ] && { echo "Error: passwords is not equal!" ; exit 1; } echo "### $POOL_NAME" >> /etc/crypttab index=0 for i in $*; do echo "$phrase"|cryptsetup $LUKS_PARAMS luksFormat "$i" || exit 1 echo "$phrase"|cryptsetup luksAddKey "$i" $KEY_FILE || exit 1 dev_name="${POOL_NAME}_crypt${index}" echo "${dev_name} $i $KEY_FILE luks" >> /etc/crypttab cryptsetup luksOpen --key-file $KEY_FILE "$i" "$dev_name" || exit 1 index=$((index + 1)) done echo "###" >> /etc/crypttab phrase="=====================================================" phrase1="=================================================" unset phrase unset phrase1 

Maintenant, en utilisant ce script, vous devez créer un pool pour stocker des données:


 ./create_crypt_pool.sh zpool create -o ashift=12 -O atime=off -O compression=lz4 -O normalization=formD tank0 raidz1 /dev/disk/by-id/dm-name-tank0_crypt* 

Pour des notes sur le paramètre ashift=12 , voir mes articles précédents et commentaires à leur sujet.


Après avoir créé le pool, j'ai mis son journal sur le SSD:


 zpool add tank0 log mirror /dev/disk/by-id/dm-name-slog0_crypt1 /dev/disk/by-id/dm-name-slog0_crypt2 

À l'avenir, avec OMV installé et configuré, il sera possible de créer des pools via l'interface graphique:


La création de ZFS est tombée dans l'interface graphique Web OMV


Activation de l'importation de pool et des volumes de montage automatique au démarrage


Afin de garantir l'activation des pools de montage automatique, exécutez les commandes suivantes:


 rm /etc/zfs/zpool.cache systemctl enable zfs-import-scan.service systemctl enable zfs-mount.service systemctl enable zfs-import-cache.service 

À ce stade, la configuration du sous-système de disque est terminée.


Système d'exploitation


La première étape consiste à installer et configurer OMV afin d'obtenir enfin une sorte de fondation pour le NAS.


Installer OMV


OMV sera installé en tant que package deb. Pour ce faire, il est possible d'utiliser les instructions officielles .


Le script add_repo.sh ajoute le référentiel OMV Arrakis à /etc/apt/ sources.list.d afin que le système de traitement par lots voit le référentiel.


add_repo.sh
 cat <<EOF >> /etc/apt/sources.list.d/openmediavault.list deb http://packages.openmediavault.org/public arrakis main # deb http://downloads.sourceforge.net/project/openmediavault/packages arrakis main ## Uncomment the following line to add software from the proposed repository. # deb http://packages.openmediavault.org/public arrakis-proposed main # deb http://downloads.sourceforge.net/project/openmediavault/packages arrakis-proposed main ## This software is not part of OpenMediaVault, but is offered by third-party ## developers as a service to OpenMediaVault users. deb http://packages.openmediavault.org/public arrakis partner # deb http://downloads.sourceforge.net/project/openmediavault/packages arrakis partner EOF 

Veuillez noter que par rapport à l'original, le référentiel partenaire est inclus.


Pour installer et initialiser, vous devez exécuter les commandes ci-dessous.


Commandes d'installation d'OMV.
 ./add_repo.sh export LANG=C export DEBIAN_FRONTEND=noninteractive export APT_LISTCHANGES_FRONTEND=none apt-get update apt-get --allow-unauthenticated install openmediavault-keyring apt-get update apt-get --yes --auto-remove --show-upgraded \ --allow-downgrades --allow-change-held-packages \ --no-install-recommends \ --option Dpkg::Options::="--force-confdef" \ --option DPkg::Options::="--force-confold" \ install postfix openmediavault # Initialize the system and database. omv-initsystem 

OMV installé. Il utilise son propre noyau, et après l'installation, un redémarrage peut être nécessaire.


Après le redémarrage, l'interface OpenMediaVault sera disponible sur le port 80 (accédez au navigateur du NAS par adresse IP):



Le nom d'utilisateur / mot de passe par défaut est admin/openmediavault .


Configurer OMV


De plus, la majeure partie de la configuration passera par l'interface Web.


Établir une connexion sécurisée


Vous devez maintenant changer le mot de passe de l'administrateur WEB et générer un certificat pour le NAS afin de travailler sur HTTPS à l'avenir.


Le mot de passe est modifié dans l'onglet "Système-> Paramètres généraux-> Mot de passe administrateur Web" .
Pour générer un certificat sur l'onglet "Système-> Certificats-> SSL", sélectionnez "Ajouter-> Créer" .


Le certificat créé sera visible sur le même onglet:


Attestation


Après avoir créé le certificat, dans l' onglet "Système-> Paramètres généraux", cochez la case "Activer SSL / TLS" .


Un certificat sera requis avant la fin de la configuration. La version finale utilisera un certificat signé pour contacter OMV.


Vous devez maintenant vous connecter à OMV, au port 443, ou simplement attribuer le préfixe https:// à IP dans le navigateur.


Si vous avez réussi à vous connecter, dans l'onglet "Système-> Paramètres généraux", vous devez activer la case à cocher "Forcer SSL / TLS".


Modifiez les ports 80 et 443 en 10080 et 10443 .
Et essayez de vous connecter Ă  l'adresse suivante: https://IP_NAS:10443 .
La modification des ports est importante car les ports 80 et 443 utiliseront le conteneur Docker avec nginx-reverse-proxy.


Paramètres principaux


Les paramètres minimum qui doivent être effectués en premier:


  • Dans l'onglet "Système-> Date et heure", vĂ©rifiez la valeur du fuseau horaire et dĂ©finissez le serveur NTP.
  • Dans l'onglet "Système-> Surveillance", activez la collecte des statistiques de performances.
  • Sur l'onglet "Système-> Gestion de l'Ă©nergie", il vaut probablement la peine de dĂ©sactiver la "Surveillance" pour qu'OMV n'essaye pas de contrĂ´ler les ventilateurs.

Réseau


Si la deuxième interface réseau NAS n'est pas encore connectée, connectez-la au routeur.


Ensuite:


  • Dans l' onglet "Système-> RĂ©seau", dĂ©finissez le nom d'hĂ´te sur "nas" (ou ce que vous voulez).
  • Configurez la liaison pour les interfaces comme indiquĂ© dans la figure ci-dessous: "Système-> RĂ©seau-> Interfaces-> Ajouter-> Lien" .
  • Ajoutez les règles de pare-feu nĂ©cessaires sur l'onglet "Système-> RĂ©seau-> Pare-feu" . Tout d'abord, l'accès aux ports 10443, 10080, 443, 80, 22 pour SSH et l'autorisation de recevoir / envoyer ICMP sont suffisants.

Configuration de liaison


En conséquence, les interfaces de liaison devraient apparaître, que le routeur verra comme une interface et lui attribuera une adresse IP:


Interfaces de liaison


Si vous le souhaitez, il est possible de configurer en plus SSH Ă  partir de l'interface graphique Web:


Configuration ssh


Référentiels et modules


Dans l'onglet "Système-> Gestion des mises à jour-> Paramètres", activez "Mises à jour prises en charge par la communauté" .


Tout d'abord, ajoutez des référentiels OMV extras .
Cela peut être fait simplement en installant le plugin ou le package, comme indiqué sur le forum .


Sur la page "Système-> Plugins" vous devez trouver le plugin "openmediavault-omvextrasorg" et l'installer.


En conséquence, l'icône "OMV-Extras" apparaîtra dans le menu système (elle peut être vue dans les captures d'écran).


Allez-y et activez les référentiels suivants:


  • OMV-Extras.org. Un rĂ©fĂ©rentiel stable contenant de nombreux plugins.
  • Tests OMV-Extras.org. Certains plugins de ce rĂ©fĂ©rentiel ne sont pas dans le rĂ©fĂ©rentiel stable.
  • Docker CE. En fait, Docker.

Dans l'onglet "System-> OMV Extras-> Kernel", vous pouvez sélectionner le noyau dont vous avez besoin, y compris le noyau de Proxmox (je ne l'ai pas installé moi-même, car je n'en ai pas encore besoin, donc je ne le recommande pas):



Installez les plugins nécessaires ( gras absolument nécessaire, en italique - facultatif, que je n'ai pas installé):


Liste des plugins.
  • openmediavault-apttool. GUI minimum pour travailler avec un système batch. Ajoute "Services-> Apttool" .
  • openmediavault-anacron. Ajoute la possibilitĂ© de travailler Ă  partir de l'interface graphique avec un planificateur asynchrone. Ajoute "Système-> Anacron" .
  • openmediavault-backup. Fournit un système de sauvegarde dans le stockage. Ajoute une page "Système-> Sauvegarde" .
  • openmediavault-diskstats. NĂ©cessaire pour collecter des statistiques sur les performances du disque.
  • openmediavault-dnsmasq . Vous permet d'augmenter le serveur DNS et DHCP sur le NAS. Parce que je le fais sur un routeur, je n'en ai pas besoin.
  • openmediavault-docker-gui . Interface de gestion des conteneurs Docker. Ajoute "Services-> Docker" .
  • openmediavault-ldap . Prise en charge de l'authentification via LDAP. Ajoute "Gestion des droits -> Service d'annuaire" .
  • openmediavault-letsencrypt . Prise en charge de Let's Encrypt Ă  partir de l'interface graphique. Il n'est pas nĂ©cessaire, car il utilise l'incorporation dans le conteneur nginx-reverse-proxy.
  • openmediavault-luksencryption . Prise en charge du cryptage LUKS. Il est nĂ©cessaire que les disques chiffrĂ©s soient visibles dans l'interface OMV. Ajoute "Stockage-> Cryptage" .
  • Ă©crou openmediavault . Prise en charge UPS. Ajoute "Services-> UPS" .
  • openmediavault-omvextrasorg . OMV Extras doit dĂ©jĂ  ĂŞtre installĂ©.
  • openmediavault-resetperms. Vous permet de rĂ©initialiser les autorisations et de rĂ©initialiser les listes de contrĂ´le d'accès sur les rĂ©pertoires partagĂ©s. Ajoute "ContrĂ´le d'accès -> RĂ©pertoires gĂ©nĂ©raux -> RĂ©initialiser les autorisations" .
  • openmediavault-route. Plugin utile pour la gestion du routage. Ajoute "Système-> RĂ©seau-> Route statique" .
  • openmediavault-symlinks. Offre la possibilitĂ© de crĂ©er des liens symboliques. Ajoute la page "Services-> Liens symboliques" .
  • openmediavault-unionfilesystems. Prise en charge d'UnionFS. Cela peut ĂŞtre utile Ă  l'avenir, bien que le docker utilise ZFS comme backend. Ajoute "Storage-> Union Filesystems" .
  • openmediavault-virtualbox . Il peut ĂŞtre utilisĂ© pour intĂ©grer des capacitĂ©s de gestion de machine virtuelle dans l'interface graphique.
  • openmediavault-zfs . Le plugin ajoute le support ZFS Ă  OpenMediaVault. Après l'installation, la page "Stockage-> ZFS" apparaĂ®tra.

Disques


Tous les disques qui sont dans le système doivent être visibles OMV. Assurez-vous de cela en regardant l' onglet "Stockage-> Disques" . Si tous les disques ne sont pas visibles, lancez une analyse.


Disques dans le système


Là, sur tous les disques durs, la mise en cache d'écriture doit être activée (en cliquant sur un disque dans la liste et en cliquant sur le bouton "Modifier").


Assurez-vous que toutes les sections chiffrées sont visibles sur l' onglet "Stockage-> Chiffrement" :


Cloisons chiffrées


Il est maintenant temps de configurer SMART, indiqué comme un moyen d'augmenter la fiabilité:


  • AccĂ©dez Ă  l' onglet "Stockage-> SMART-> Paramètres" . Allumez SMART.
  • Au mĂŞme endroit, sĂ©lectionnez les valeurs des niveaux de tempĂ©rature des disques (critiques, gĂ©nĂ©ralement 60 C, et le rĂ©gime de tempĂ©rature optimal du disque 15-45 C).
  • AccĂ©dez Ă  l' onglet "Stockage-> SMART-> Appareils" . Activez la surveillance pour chaque lecteur.
  • AccĂ©dez Ă  l' onglet "Stockage-> SMART-> Tests planifiĂ©s" . Ajoutez un court auto-test une fois par jour pour chaque disque et un long auto-test une fois par mois. De plus, afin que les pĂ©riodes d'auto-test ne se chevauchent pas.

Sur ce point, la configuration du disque peut être considérée comme terminée.


Systèmes de fichiers et répertoires partagés


Vous devez créer des systèmes de fichiers pour des répertoires prédéfinis.
Cela peut être fait depuis la console ou depuis l'interface WEB OMV ( Stockage-> ZFS-> Sélectionner le réservoir de la piscine0-> Bouton Ajouter -> Système de fichiers ).


Commandes de création de FS.
 zfs create -o utf8only=on -o normalization=formD -p tank0/user_data/books zfs create -o utf8only=on -o normalization=formD -p tank0/user_data/music zfs create -o utf8only=on -o normalization=formD -p tank0/user_data/pictures zfs create -o utf8only=on -o normalization=formD -p tank0/user_data/downloads zfs create -o compression=off -o utf8only=on -o normalization=formD -p tank0/user_data/videos 

Le résultat doit être la structure de répertoires suivante:



Après cela, ajoutez les FS créés en tant que répertoires partagés sur la page "Gestion des droits d'accès-> Répertoires généraux-> Ajouter" .
Veuillez noter que le paramètre "Device" est égal au chemin d'accès au système de fichiers créé dans ZFS, et le paramètre "Path" pour tous les répertoires est "/".



Sauvegarde


La sauvegarde se fait par deux outils:



Si vous utilisez le plugin, vous obtenez très probablement une erreur:


 lsblk: /dev/block/0:22: not a block device 

Pour y remédier, comme l'ont noté les développeurs OMV dans cette "configuration très non standard", il serait possible de refuser le plugin et d'utiliser les outils ZFS sous forme d' zfs send/receive .
Ou, spécifiez explicitement le paramètre «périphérique racine» sous la forme d'un périphérique physique à partir duquel le téléchargement est effectué.
Il est plus pratique pour moi d'utiliser le plugin et de sauvegarder le système d'exploitation à partir de l'interface, au lieu de cadrer quelque chose de moi-même avec zfs send, donc je préfère la deuxième option.


Configuration de sauvegarde


Pour que la sauvegarde fonctionne, créez d'abord le système de fichiers tank0/apps/backup via ZFS, puis dans le menu "Système-> Sauvegarde", cliquez sur "+" dans le champ de paramètre "Dossier public" et ajoutez le périphérique créé comme cible et le champ "Chemin" réglé sur "/".


Il y a aussi des problèmes avec zfs-auto-snapshot. Si elle n'est pas configurée, elle prendra des photos toutes les heures, tous les jours, toutes les semaines, tous les mois pendant un an.
Le résultat est ce qui est dans la capture d'écran:


Beaucoup de spam provenant de zfs-auto-snapshot


Si vous l'avez déjà rencontré, exécutez le code suivant pour supprimer les instantanés automatiques:


 zfs list -t snapshot -o name -S creation | grep "@zfs-auto-snap" | tail -n +1500 | xargs -n 1 zfs destroy -vr 

Configurez ensuite zfs-auto-snapshot pour qu'il s'exécute dans cron.
Pour commencer, supprimez simplement /etc/cron.hourly/zfs-auto-snapshot si vous n'avez pas besoin de prendre des photos toutes les heures.


Notifications par e-mail


La notification par e-mail a été indiquée comme l'un des moyens d'assurer la fiabilité.
Par conséquent, vous devez maintenant configurer la notification par e-mail.
Pour ce faire, enregistrez une boîte sur l'un des serveurs publics (enfin, ou configurez le serveur SMTP vous-même, si vous avez vraiment des raisons de le faire).


Ensuite, vous devez vous rendre sur la page "Système-> Notification" et saisir:


  • Adresse du serveur SMTP.
  • Port du serveur SMTP.
  • Identifiant
  • Adresse de l'expĂ©diteur (gĂ©nĂ©ralement, le premier composant de l'adresse correspond au nom).
  • Mot de passe utilisateur
  • Dans le champ "Destinataire", votre adresse habituelle Ă  laquelle le NAS enverra des notifications.

Il est fortement conseillé d'activer SSL / TLS.


Un exemple de configuration pour Yandex est illustré dans la capture d'écran:


Notifications par e-mail


Configuration du réseau en dehors du NAS


Adresse IP


J'utilise une adresse IP statique blanche, qui coûte plus 100 roubles par mois. Si vous ne souhaitez pas payer et que votre adresse est dynamique, mais pas pour NAT, il est possible d'ajuster les enregistrements DNS externes via l'API du service sélectionné.
Néanmoins, il convient de garder à l'esprit qu'une adresse non NAT peut soudainement devenir une adresse NAT: en règle générale, les fournisseurs ne donnent aucune garantie.


Routeur


En tant que routeur, j'ai un Mikrotik RouterBoard , similaire Ă  celui de l'image ci-dessous.


Carte mère Mikrotik


Trois choses sont requises sur le routeur:


  • Configurez des adresses statiques pour le NAS. Dans mon cas, les adresses sont Ă©mises via DHCP, et je dois m'assurer que les adaptateurs avec une adresse MAC spĂ©cifique obtiennent toujours la mĂŞme adresse IP. Dans RouterOS, cela se fait sur l' onglet "IP-> Serveur DHCP" avec le bouton "Rendre statique" .
  • Configurez le serveur DNS afin que pour le nom "nas", ainsi que les noms se terminant par ".nas" et ".NAS.cloudns.cc" (oĂą "NAS" est la zone sur ClouDNS ou un service similaire), il donne le système IP. OĂą faire cela dans RouterOS est indiquĂ© dans la capture d'Ă©cran ci-dessous. Dans mon cas, cela est implĂ©mentĂ© en faisant correspondre le nom avec une expression rĂ©gulière: " ^.*\.nas$|^nas$|^.*\.NAS.cloudns.cc$ "
  • Configurez la redirection de port. Dans RouterOS, cela se fait sur l' onglet "IP-> Pare-feu" , je ne m'attarderai pas lĂ -dessus.

Configurateur DNS dans RouterOS


ClouDNS


CLouDNS est simple. Créez un compte, confirmez. Les enregistrements NS seront déjà enregistrés auprès de vous. Ensuite, une configuration minimale est requise.


Tout d'abord, vous devez créer les zones nécessaires (la zone portant le nom NAS surlignée en rouge dans la capture d'écran est ce que vous devez créer avec un nom différent, bien sûr).


Création d'une zone dans ClouDNS


Deuxièmement, dans cette zone, vous devez enregistrer les enregistrements A suivants:


  • nas , www , omv , control et un nom vide . Pour accĂ©der Ă  l'interface OMV.
  • ldap . Interface PhpLdapAdmin
  • ssp . Interface pour changer les mots de passe des utilisateurs.
  • test . Serveur de test.

Les noms de domaine restants seront ajoutés à mesure que les services seront ajoutés.
Cliquez sur la zone, puis sur "Ajouter un nouvel enregistrement" , sélectionnez le type A, entrez le nom de la zone et l'adresse IP du routeur derrière lequel se trouve le NAS.


Ajout des enregistrements a


Deuxièmement, vous devez accéder à l'API. Dans ClouDNS, il est payé, vous devez donc d'abord le payer. Dans d'autres services, c'est gratuit. Si vous savez ce qui est le mieux et que cela est pris en charge par Lexicon , veuillez écrire dans les commentaires.


Après avoir accédé à l'API, vous devez y ajouter un nouvel utilisateur d'API.


Ajout d'un utilisateur API ClouDNS


"IP address" IP : , API. , , API, auth-id auth-password . Lexicon, .



ClouDNS .



Docker


openmediavault-docker-gui, docker-ce .


, docker-compose , :


 apt-get install docker-compose 

:


 zfs create -p /tank0/docker/services 

, /var/lib/docker . ( , SSD), , , .


..,
. .



, .
, GUI , : , .. , .


/var/lib :


 service docker stop zfs create -o com.sun:auto-snapshot=false -p /tank0/docker/lib rm -rf /var/lib/docker ln -s /tank0/docker/lib /var/lib/docker service docker start 

:


 $ ls -l /var/lib/docker lrwxrwxrwx 1 root root 17 Apr 7 12:35 /var/lib/docker -> /tank0/docker/lib 

:


 docker network create docker0 

Docker .


nginx-reverse-proxy


Docker , .


, .


: nginx-proxy letsencrypt-dns .


, OMV 10080 10443, 80 443.


/tank0/docker/services/nginx-proxy/docker-compose.yml
 version: '2' networks: docker0: external: name: docker0 services: nginx-proxy: networks: - docker0 restart: always image: jwilder/nginx-proxy ports: - "80:80" - "443:443" volumes: - ./certs:/etc/nginx/certs:ro - ./vhost.d:/etc/nginx/vhost.d - ./html:/usr/share/nginx/html - /var/run/docker.sock:/tmp/docker.sock:ro - ./local-config:/etc/nginx/conf.d - ./nginx.tmpl:/app/nginx.tmpl labels: - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true" letsencrypt-dns: image: adferrand/letsencrypt-dns volumes: - ./certs/letsencrypt:/etc/letsencrypt environment: - "LETSENCRYPT_USER_MAIL=MAIL@MAIL.COM" - "LEXICON_PROVIDER=cloudns" - "LEXICON_OPTIONS=--delegated NAS.cloudns.cc" - "LEXICON_PROVIDER_OPTIONS=--auth-id=CLOUDNS_ID --auth-password=CLOUDNS_PASSWORD" 

:


  • nginx-reverse-proxy — c .
  • letsencrypt-dns — ACME Let's Encrypt.

nginx-reverse-proxy jwilder/nginx-proxy .


docker0 — , , docker-compose.
nginx-proxy — , . docker0. , 80 443 ports (, , docker0, ).
restart: always , .


:


  • certs /etc/nginx/certs — , , Let's Encrypt. ACME .
  • ./vhost.d:/etc/nginx/vhost.d — . .
  • ./html:/usr/share/nginx/html — . .
  • /var/run/docker.sock , /tmp/docker.sock — Docker . docker-gen .
  • ./local-config , /etc/nginx/conf.d — nginx. , .
  • ./nginx.tmpl , /app/nginx.tmpl — nginx, docker-gen .

letsencrypt-dns adferrand/letsencrypt-dns . ACME Lexicon, DNS .


certs/letsencrypt /etc/letsencrypt .


, :


  • LETSENCRYPT_USER_MAIL=MAIL@MAIL.COM — Let's Encrypt. , .
  • LEXICON_PROVIDER=cloudns — Lexicon. — cloudns .
  • LEXICON_PROVIDER_OPTIONS=--auth-id=CLOUDNS_ID --auth-password=CLOUDNS_PASSWORD --delegated=NAS.cloudns.cc — CLOUDNS_ID ClouDNS . CLOUDNS_PASSWORD — , API. NAS.cloudns.cc, NAS — DNS . cloudns , (cloudns.cc), ClouDNS API .

: .
, , , , Let's encrypt:


 $ ls ./certs/letsencrypt/ accounts archive csr domains.conf keys live renewal renewal-hooks 

, , .


/tank0/docker/services/nginx-proxy/nginx.tmpl
 {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }} {{ define "upstream" }} {{ if .Address }} {{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}} {{ if and .Container.Node.ID .Address.HostPort }} # {{ .Container.Node.Name }}/{{ .Container.Name }} server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }}; {{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}} {{ else if .Network }} # {{ .Container.Name }} server {{ .Network.IP }}:{{ .Address.Port }}; {{ end }} {{ else if .Network }} # {{ .Container.Name }} {{ if .Network.IP }} server {{ .Network.IP }} down; {{ else }} server 127.0.0.1 down; {{ end }} {{ end }} {{ end }} # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the # scheme used to connect to this server map $http_x_forwarded_proto $proxy_x_forwarded_proto { default $http_x_forwarded_proto; '' $scheme; } # If we receive X-Forwarded-Port, pass it through; otherwise, pass along the # server port the client connected to map $http_x_forwarded_port $proxy_x_forwarded_port { default $http_x_forwarded_port; '' $server_port; } # If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any # Connection header that may have been passed to this server map $http_upgrade $proxy_connection { default upgrade; '' close; } # Apply fix for very long server names server_names_hash_bucket_size 128; # Default dhparam {{ if (exists "/etc/nginx/dhparam/dhparam.pem") }} ssl_dhparam /etc/nginx/dhparam/dhparam.pem; {{ end }} # Set appropriate X-Forwarded-Ssl header map $scheme $proxy_x_forwarded_ssl { default off; https on; } gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; log_format vhost '$host $remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; access_log off; {{ if $.Env.RESOLVERS }} resolver {{ $.Env.RESOLVERS }}; {{ end }} {{ if (exists "/etc/nginx/proxy.conf") }} include /etc/nginx/proxy.conf; {{ else }} # HTTP 1.1 support proxy_http_version 1.1; proxy_buffering off; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $proxy_connection; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; # Mitigate httpoxy attack (see README for details) proxy_set_header Proxy ""; {{ end }} {{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }} server { server_name _; # This is just an invalid value which will never trigger on a real hostname. listen 80; {{ if $enable_ipv6 }} listen [::]:80; {{ end }} access_log /var/log/nginx/access.log vhost; return 503; } {{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }} server { server_name _; # This is just an invalid value which will never trigger on a real hostname. listen 443 ssl http2; {{ if $enable_ipv6 }} listen [::]:443 ssl http2; {{ end }} access_log /var/log/nginx/access.log vhost; return 503; ssl_session_tickets off; ssl_certificate /etc/nginx/certs/default.crt; ssl_certificate_key /etc/nginx/certs/default.key; } {{ end }} {{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }} {{ $host := trim $host }} {{ $is_regexp := hasPrefix "~" $host }} {{ $upstream_name := when $is_regexp (sha1 $host) $host }} # {{ $host }} upstream {{ $upstream_name }} { {{ range $container := $containers }} {{ $addrLen := len $container.Addresses }} {{ range $knownNetwork := $CurrentContainer.Networks }} {{ range $containerNetwork := $container.Networks }} {{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }} ## Can be connected with "{{ $containerNetwork.Name }}" network {{/* If only 1 port exposed, use that */}} {{ if eq $addrLen 1 }} {{ $address := index $container.Addresses 0 }} {{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }} {{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}} {{ else }} {{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }} {{ $address := where $container.Addresses "Port" $port | first }} {{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }} {{ end }} {{ else }} # Cannot connect to network of this container server 127.0.0.1 down; {{ end }} {{ end }} {{ end }} {{ end }} } {{ $default_host := or ($.Env.DEFAULT_HOST) "" }} {{ $default_server := index (dict $host "" $default_host "default_server") $host }} {{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}} {{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }} {{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}} {{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }} {{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}} {{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }} {{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to "Mozilla-Intermediate" */}} {{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "Mozilla-Intermediate" }} {{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}} {{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }} {{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}} {{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }} {{/* Get the first cert name defined by containers w/ the same vhost */}} {{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }} {{/* Get the best matching cert by name for the vhost. */}} {{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}} {{/* vhostCert is actually a filename so remove any suffixes since they are added later */}} {{ $vhostCert := trimSuffix ".crt" $vhostCert }} {{ $vhostCert := trimSuffix ".key" $vhostCert }} {{/* Use the cert specified on the container or fallback to the best vhost match */}} {{ $cert := (coalesce $certName $vhostCert) }} {{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (or (and (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/fullchain.pem" $cert)) (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/privkey.pem" $cert))) (and (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert)))) ) }} {{ if $is_https }} {{ if eq $https_method "redirect" }} server { server_name {{ $host }}; listen 80 {{ $default_server }}; {{ if $enable_ipv6 }} listen [::]:80 {{ $default_server }}; {{ end }} access_log /var/log/nginx/access.log vhost; return 301 https://$host$request_uri; } {{ end }} server { server_name {{ $host }}; listen 443 ssl http2 {{ $default_server }}; {{ if $enable_ipv6 }} listen [::]:443 ssl http2 {{ $default_server }}; {{ end }} access_log /var/log/nginx/access.log vhost; {{ if eq $network_tag "internal" }} # Only allow traffic from internal clients include /etc/nginx/network_internal.conf; {{ end }} {{ if eq $ssl_policy "Mozilla-Modern" }} ssl_protocols TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; {{ else if eq $ssl_policy "Mozilla-Intermediate" }} ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:!DSS'; {{ else if eq $ssl_policy "Mozilla-Old" }} ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:DES-CBC3-SHA:HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP'; {{ else if eq $ssl_policy "AWS-TLS-1-2-2017-01" }} ssl_protocols TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256'; {{ else if eq $ssl_policy "AWS-TLS-1-1-2017-01" }} ssl_protocols TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA'; {{ else if eq $ssl_policy "AWS-2016-08" }} ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA'; {{ else if eq $ssl_policy "AWS-2015-05" }} ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA'; {{ else if eq $ssl_policy "AWS-2015-03" }} ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA'; {{ else if eq $ssl_policy "AWS-2015-02" }} ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA'; {{ end }} ssl_prefer_server_ciphers on; ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; {{ if (and (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/fullchain.pem" $cert)) (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/privkey.pem" $cert))) }} ssl_certificate /etc/nginx/certs/letsencrypt/live/{{ (printf "%s/fullchain.pem" $cert) }}; ssl_certificate_key /etc/nginx/certs/letsencrypt/live/{{ (printf "%s/privkey.pem" $cert) }}; {{ else if (and (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }} ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }}; ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }}; {{ end }} {{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }} ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }}; {{ end }} {{ if (exists (printf "/etc/nginx/certs/%s.chain.pem" $cert)) }} ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }}; {{ end }} {{ if (and (ne $https_method "noredirect") (ne $hsts "off")) }} add_header Strict-Transport-Security "{{ trim $hsts }}" always; {{ end }} {{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }} include {{ printf "/etc/nginx/vhost.d/%s" $host }}; {{ else if (exists "/etc/nginx/vhost.d/default") }} include /etc/nginx/vhost.d/default; {{ end }} location / { {{ if eq $proto "uwsgi" }} include uwsgi_params; uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ else if eq $proto "fastcgi" }} root {{ trim $vhost_root }}; include fastcgi.conf; fastcgi_pass {{ trim $upstream_name }}; {{ else }} proxy_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ end }} {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} auth_basic "Restricted {{ $host }}"; auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }}; {{ end }} {{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }} include {{ printf "/etc/nginx/vhost.d/%s_location" $host}}; {{ else if (exists "/etc/nginx/vhost.d/default_location") }} include /etc/nginx/vhost.d/default_location; {{ end }} } } {{ end }} {{ if or (not $is_https) (eq $https_method "noredirect") }} server { server_name {{ $host }}; listen 80 {{ $default_server }}; {{ if $enable_ipv6 }} listen [::]:80 {{ $default_server }}; {{ end }} access_log /var/log/nginx/access.log vhost; {{ if eq $network_tag "internal" }} # Only allow traffic from internal clients include /etc/nginx/network_internal.conf; {{ end }} {{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }} include {{ printf "/etc/nginx/vhost.d/%s" $host }}; {{ else if (exists "/etc/nginx/vhost.d/default") }} include /etc/nginx/vhost.d/default; {{ end }} location / { {{ if eq $proto "uwsgi" }} include uwsgi_params; uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ else if eq $proto "fastcgi" }} root {{ trim $vhost_root }}; include fastcgi.conf; fastcgi_pass {{ trim $upstream_name }}; {{ else }} proxy_pass {{ trim $proto }}://{{ trim $upstream_name }}; {{ end }} {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} auth_basic "Restricted {{ $host }}"; auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }}; {{ end }} {{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }} include {{ printf "/etc/nginx/vhost.d/%s_location" $host}}; {{ else if (exists "/etc/nginx/vhost.d/default_location") }} include /etc/nginx/vhost.d/default_location; {{ end }} } } {{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }} server { server_name {{ $host }}; listen 443 ssl http2 {{ $default_server }}; {{ if $enable_ipv6 }} listen [::]:443 ssl http2 {{ $default_server }}; {{ end }} access_log /var/log/nginx/access.log vhost; return 500; ssl_certificate /etc/nginx/certs/default.crt; ssl_certificate_key /etc/nginx/certs/default.key; } {{ end }} {{ end }} {{ end }} 

, nginx /etc/nginx/certs/%s.crt /etc/nginx/certs/%s.pem , %s — ( — , ).


/etc/nginx/certs/letsencrypt/live/%s/{fullchain.pem, privkey.pem} , :


 {{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (or (and (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/fullchain.pem" $cert)) (exists (printf "/etc/nginx/certs/letsencrypt/live/%s/privkey.pem" $cert)) ) (and (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert)) ) ) ) }} 

, domains.conf .


/tank0/docker/services/nginx-proxy/certs/letsencrypt/domains.conf
 *.NAS.cloudns.cc NAS.cloudns.cc 

. , , , client_max_body_size 20, .


/tank0/docker/services/nginx-proxy/local-config/max_upload_size.conf
 client_max_body_size 20G; 

, :


 docker-compose up 

( ), Ctrl+C :


 docker-compose up -d 


— nginx, . , , .
, NAS.


.


docker-compose :


/tank0/docker/services/test_nginx/docker-compose.yml
 version: '2' networks: docker0: external: name: docker0 services: nginx-local: restart: always image: nginx:alpine expose: - 80 - 443 environment: - "VIRTUAL_HOST=test.NAS.cloudns.cc" - "VIRTUAL_PROTO=http" - "VIRTUAL_PORT=80" - CERT_NAME=NAS.cloudns.cc networks: - docker0 

:


  • docker0 — . .
  • expose — , . , 80 HTTP 443 HTTPS.
  • VIRTUAL_HOST=test.NAS.cloudns.cc — , nginx-reverse-proxy .
  • VIRTUAL_PROTO=http — nginx-reverse-proxy . , HTTP.
  • VIRTUAL_PORT=80 — nginx-reverse-proxy.
  • CERT_NAME=NAS.cloudns.cc — . , , . NAS — DNS .
  • networks — , nginx-reverse-proxy docker0 .

, . docker-compose up , test.NAS.cloudns.cc .


:


 $ docker-compose up Creating testnginx_nginx-local_1 Attaching to testnginx_nginx-local_1 nginx-local_1 | 172.22.0.5 - - [29/Jul/2018:15:32:02 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537 (KHTML, like Gecko) Chrome/67.0 Safari/537" "192.168.2.3" nginx-local_1 | 2018/07/29 15:32:02 [error] 8#8: *2 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.22.0.5, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "test.NAS.cloudns.cc", referrer: "https://test.NAS.cloudns.cc/" nginx-local_1 | 172.22.0.5 - - [29/Jul/2018:15:32:02 +0000] "GET /favicon.ico HTTP/1.1" 404 572 "https://test.NAS.cloudns.cc/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537 (KHTML, like Gecko) Chrome/67.0 Safari/537" "192.168.2.3" 

:


Lancé Nginx


, , , , : .


, Ctrl+C, docker-compose down .


local-rpoxy


, nginx-default , nas, omv 10080 10443 .


.


/tank0/docker/services/nginx-local/docker-compose.yml
 version: '2' networks: docker0: external: name: docker0 services: nginx-local: restart: always image: nginx:alpine expose: - 80 - 443 environment: - "VIRTUAL_HOST=NAS.cloudns.cc,nas,nas.*,www.*,omv.*,nas-controller.nas" - "VIRTUAL_PROTO=http" - "VIRTUAL_PORT=80" - CERT_NAME=NAS.cloudns.cc volumes: - ./local-config:/etc/nginx/conf.d networks: - docker0 

docker-compose , .
, , , NAS.cloudns.cc . , NAS DNS , .


/tank0/docker/services/nginx-local/local-config/default.conf
 # If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the # scheme used to connect to this server map $http_x_forwarded_proto $proxy_x_forwarded_proto { default $http_x_forwarded_proto; '' $scheme; } # If we receive X-Forwarded-Port, pass it through; otherwise, pass along the # server port the client connected to map $http_x_forwarded_port $proxy_x_forwarded_port { default $http_x_forwarded_port; '' $server_port; } # Set appropriate X-Forwarded-Ssl header map $scheme $proxy_x_forwarded_ssl { default off; https on; } access_log on; error_log on; # HTTP 1.1 support proxy_http_version 1.1; proxy_buffering off; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; # Mitigate httpoxy attack (see README for details) proxy_set_header Proxy ""; server { server_name _; # This is just an invalid value which will never trigger on a real hostname. listen 80; return 503; } server { server_name www.* nas.* omv.* ""; listen 80; location / { proxy_pass https://172.21.0.1:10443/; } } # nas-controller server { server_name nas-controller.nas; listen 80 ; location / { proxy_pass https://nas-controller/; } } 

  • 172.21.0.1 — . 443, OMV HTTPS. .
  • https://nas-controller/ — -, IPMI, nas, nas-controller.nas, nas-controller. .

LDAP


LDAP-


LDAP- — .
Docker . , , .


LDIF- .


/tank0/docker/services/ldap/docker-compose.yml
 version: "2" networks: ldap: docker0: external: name: docker0 services: open-ldap: image: "osixia/openldap:1.2.0" hostname: "open-ldap" restart: always environment: - "LDAP_ORGANISATION=NAS" - "LDAP_DOMAIN=nas.nas" - "LDAP_ADMIN_PASSWORD=ADMIN_PASSWORD" - "LDAP_CONFIG_PASSWORD=CONFIG_PASSWORD" - "LDAP_TLS=true" - "LDAP_TLS_ENFORCE=false" - "LDAP_TLS_CRT_FILENAME=ldap_server.crt" - "LDAP_TLS_KEY_FILENAME=ldap_server.key" - "LDAP_TLS_CA_CRT_FILENAME=ldap_server.crt" volumes: - ./certs:/container/service/slapd/assets/certs - ./ldap_data/var/lib:/var/lib/ldap - ./ldap_data/etc/ldap/slapd.d:/etc/ldap/slapd.d networks: - ldap ports: - 172.21.0.1:389:389 - 172.21.0.1::636:636 phpldapadmin: image: "osixia/phpldapadmin:0.7.1" hostname: "nas.nas" restart: always networks: - ldap - docker0 expose: - 443 links: - open-ldap:open-ldap-server volumes: - ./certs:/container/service/phpldapadmin/assets/apache2/certs environment: - VIRTUAL_HOST=ldap.* - VIRTUAL_PORT=443 - VIRTUAL_PROTO=https - CERT_NAME=NAS.cloudns.cc - "PHPLDAPADMIN_LDAP_HOSTS=open-ldap-server" #- "PHPLDAPADMIN_HTTPS=false" - "PHPLDAPADMIN_HTTPS_CRT_FILENAME=certs/ldap_server.crt" - "PHPLDAPADMIN_HTTPS_KEY_FILENAME=private/ldap_server.key" - "PHPLDAPADMIN_HTTPS_CA_CRT_FILENAME=certs/ldap_server.crt" - "PHPLDAPADMIN_LDAP_CLIENT_TLS_REQCERT=allow" ldap-ssp: image: openfrontier/ldap-ssp:https volumes: #- ./ssp/mods-enabled/ssl.conf:/etc/apache2/mods-enabled/ssl.conf - /etc/ssl/certs/ssl-cert-snakeoil.pem:/etc/ssl/certs/ssl-cert-snakeoil.pem - /etc/ssl/private/ssl-cert-snakeoil.key:/etc/ssl/private/ssl-cert-snakeoil.key restart: always networks: - ldap - docker0 expose: - 80 links: - open-ldap:open-ldap-server environment: - VIRTUAL_HOST=ssp.* - VIRTUAL_PORT=80 - VIRTUAL_PROTO=http - CERT_NAME=NAS.cloudns.cc - "LDAP_URL=ldap://open-ldap-server:389" - "LDAP_BINDDN=cn=admin,dc=nas,dc=nas" - "LDAP_BINDPW=ADMIN_PASSWORD" - "LDAP_BASE=ou=users,dc=nas,dc=nas" - "MAIL_FROM=admin@nas.nas" - "PWD_MIN_LENGTH=8" - "PWD_MIN_LOWER=3" - "PWD_MIN_DIGIT=2" - "SMTP_HOST=" - "SMTP_USER=" - "SMTP_PASS=" 

:



LDAP- , :


  • LDAP_ORGANISATION=NAS — . .
  • LDAP_DOMAIN=nas.nas — . . , .
  • LDAP_ADMIN_PASSWORD=ADMIN_PASSWORD — .
  • LDAP_CONFIG_PASSWORD=CONFIG_PASSWORD — .

-, " ", .


:


  • /container/service/slapd/assets/certs certs — . .
  • ./ldap_data/ — , . LDAP .

ldap , 389 ( LDAP) 636 (LDAP SSL, ) .


PhpLdapAdmin : LDAP ldap 443 docker0 , , nginx-reverse-proxy.


:


  • VIRTUAL_HOST=ldap.* — , nginx-reverse-proxy .
  • VIRTUAL_PORT=443 — nginx-reverse-proxy.
  • VIRTUAL_PROTO=https — nginx-reverse-proxy.
  • CERT_NAME=NAS.cloudns.cc — , .

SSL .


SSP HTTP .
, , .


— LDAP.


  • LDAP_URL=ldap://open-ldap-server:389 — LDAP (. links ).
  • LDAP_BINDDN=cn=admin,dc=nas,dc=nas — .
  • LDAP_BINDPW=ADMIN_PASSWORD — , , open-ldap.
  • LDAP_BASE=ou=users,dc=nas,dc=nas — , .

LDAP LDAP :


 apt-get install ldap-utils ldapadd -x -H ldap://172.21.0.1 -D "cn=admin,dc=nas,dc=nas" -W -f ldifs/inititialize_ldap.ldif ldapadd -x -H ldap://172.21.0.1 -D "cn=admin,dc=nas,dc=nas" -W -f ldifs/base.ldif ldapadd -x -H ldap://172.21.0.1 -D "cn=admin,cn=config" -W -f ldifs/gitlab_attr.ldif 

gitlab_attr.ldif , Gitlab ( ) .
.


LDAP
 $ ldapsearch -x -H ldap://172.21.0.1 -b dc=nas,dc=nas -D "cn=admin,dc=nas,dc=nas" -W Enter LDAP Password: # extended LDIF # # LDAPv3 # base <dc=nas,dc=nas> with scope subtree # filter: (objectclass=*) # requesting: ALL # # nas.nas dn: dc=nas,dc=nas objectClass: top objectClass: dcObject objectClass: organization o: NAS dc: nas # admin, nas.nas dn: cn=admin,dc=nas,dc=nas objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator ... # ldap_users, groups, nas.nas dn: cn=ldap_users,ou=groups,dc=nas,dc=nas cn: ldap_users gidNumber: 500 objectClass: posixGroup objectClass: top # search result search: 2 result: 0 Success # numResponses: 12 # numEntries: 11 

LDAP . WEB-.


OMV LDAP


LDAP , OMV : , , , , — .


LDAP .


:


Configurer OMV pour travailler avec LDAP



, , NAS USB.
.
NUT GUI OMV.
"->" , , , , "eaton".


" " :


 driver = usbhid-ups port = auto desc = "Eaton 9130 700 VA" vendorid = 0463 pollinterval = 10 

  • driver = usbhid-ups — USB, USB HID.
  • vendorid — , lsusb .
  • pollinterval — c.

.


lsusb , :


 # lsusb Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub --> Bus 001 Device 003: ID 0463:ffff MGE UPS Systems UPS Bus 001 Device 004: ID 046b:ff10 American Megatrends, Inc. Virtual Keyboard and Mouse Bus 001 Device 002: ID 046b:ff01 American Megatrends, Inc. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 

" " " ".
, :


Configuration de l'onduleur


. , .
.


Conclusion


. , , , , .
— .


-, OMV .


WEB-, , :



Docker WEB-:



, OMV .


:


Calendrier d'utilisation du réseau


:


Graphique d'utilisation de la mémoire


CPU:


Graphique d'utilisation du processeur




.
!


Source: https://habr.com/ru/post/fr415779/


All Articles