تنفيذ منصة برمجيات NAS آمنة


في مقال سابق ، تم وصف تصميم منصة برمجيات NAS.
حان الوقت لتنفيذه.


تحقق


تأكد من التحقق من صحة حمام السباحة قبل البدء:


zpool status -v 

يجب أن يكون التجمع وجميع الأقراص الموجودة فيه على الإنترنت.


علاوة على ذلك ، أفترض أنه في المرحلة السابقة تم عمل كل شيء وفقًا للتعليمات ، وأنه يعمل ، أو أنك تفهم جيدًا ما تفعله.


وسائل الراحة


بادئ ذي بدء ، يجدر الاعتناء بالإدارة المريحة إذا لم تقم بذلك منذ البداية.
ستكون مطلوبة:


  • خادم SSH: apt-get install openssh-server . إذا كنت لا تعرف كيفية تكوين SSH ، إجراء NAS على Linux مبكرًا جدًا يمكنك قراءة ميزات استخدامه في هذه المقالة ، ثم استخدم أحد الأدلة .
  • tmux أو الشاشة : apt-get install tmux . لحفظ الجلسة عند تسجيل الدخول عبر SSH واستخدام نوافذ متعددة.

بعد تثبيت SSH ، تحتاج إلى إضافة مستخدم حتى لا تسجل الدخول عبر SSH كجذر (يتم تعطيل الإدخال افتراضيًا ولا تحتاج إلى تمكينه):


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

بالنسبة للإدارة عن بعد ، هذا حد أدنى كاف.


ومع ذلك ، بينما تحتاج إلى إبقاء لوحة المفاتيح والشاشة متصلة ، مثل ستحتاج أيضًا إلى إعادة التشغيل عند تحديث النواة ومن أجل التأكد من أن كل شيء يعمل فورًا بعد التحميل.


البديل هو استخدام Virtual KVM ، الذي يوفر IME . هناك وحدة تحكم هناك ، على الرغم من أنها في حالتي يتم تنفيذها كبرنامج Java صغير ، وهو غير ملائم للغاية.


التخصيص


تحضير ذاكرة التخزين المؤقت


بقدر ما تتذكر ، في التكوين الذي وصفته ، هناك SSD منفصل تحت L2ARC ، لم يتم استخدامه بعد ، ولكن تم استخدامه "للنمو".


اختياري ، ولكن يُنصح بملء SSD ببيانات عشوائية (في حالة Samsung EVO ، سيتم ملؤه بالأصفار بعد blkdiscard ، ولكن ليس على جميع SSDs على أي حال):


 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 

تعطيل ضغط السجل


في ZFS ، يتم استخدام الضغط بالفعل ، لأن ضغط السجل من خلال gzip سيكون غير ضروري بشكل واضح.
إيقاف:


 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 

تحديث النظام


كل شيء بسيط هنا:


 apt-get dist-upgrade --yes reboot 

إنشاء لقطة لدولة جديدة


بعد إعادة التشغيل ، من أجل إصلاح حالة العمل الجديدة ، تحتاج إلى إعادة كتابة اللقطة الأولى:


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

تنظيم نظام الملفات


التقسيم ل SLOG


أول شيء يجب القيام به لتحقيق أداء ZFS العادي هو وضع SLOG على SSD.
دعني أذكرك أن SLOG في التكوين المستخدم مكرر على قرصين SSD: بالنسبة له ، سيتم إنشاء الأجهزة على LUKS-XTS أعلى القسم الرابع من كل 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 

التقسيم ل L2ARC والتبديل


تحتاج أولاً إلى إنشاء أقسام تحت المبادلة و 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 

سيتم تشفير قسم المبادلة و L2ARC على مفتاح عشوائي ، مثل بعد إعادة التشغيل ، لا تكون مطلوبة ويمكن دائمًا إعادة إنشائها.
لذلك ، في التشفير ، يتم كتابة سطر لتشفير / فك تشفير الأقسام في الوضع العادي:


 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 

ثم تحتاج إلى إعادة تشغيل الشياطين وتمكين المبادلة:


 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 

لأن لا يتم استخدام swapiness بنشاط على SSD ؛ يجب swapiness معلمة swapiness ، وهي 60 افتراضيًا ، على 10.


لم يتم استخدام L2ARC بعد في هذه المرحلة ، ولكن القسم الخاص به جاهز بالفعل:


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

خزانات برك


سيتم وصف إنشاء تجمع tank1 ، يتم إنشاء tank1 عن طريق القياس.


لكي لا أقوم بإنشاء نفس الأقسام يدويًا وتجنب الأخطاء ، قمت بكتابة برنامج نصي لإنشاء أقسام مشفرة للمجمعات:


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 

الآن ، باستخدام هذا البرنامج النصي ، تحتاج إلى إنشاء تجمع لتخزين البيانات:


 ./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* 

للحصول على ملاحظات حول ashift=12 ، راجع مقالاتي السابقة وتعليقاتي عليها.


بعد إنشاء التجمع ، وضعت سجله على SSD:


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

في المستقبل ، مع تثبيت وتهيئة OMV ، سيكون من الممكن إنشاء تجمعات من خلال واجهة المستخدم الرسومية:


ويمكن إنشاء ZFS في OMV WEB GUI


تمكين استيراد التجمع والتثبيت التلقائي عند التمهيد


لضمان تمكين تجمعات التثبيت التلقائي ، قم بتشغيل الأوامر التالية:


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

في هذه المرحلة ، اكتمل تكوين النظام الفرعي للقرص.


نظام تشغيل


الخطوة الأولى هي تثبيت وتكوين OMV من أجل الحصول على نوع من الأساس لـ NAS.


قم بتثبيت OMV


سيتم تثبيت OMV كحزمة deb. للقيام بذلك ، من الممكن استخدام التعليمات الرسمية .


يضيف البرنامج النصي add_repo.sh مستودع OMV Arrakis إلى /etc/apt/ sources.list.d بحيث يرى نظام الدُفعات المستودع.


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 

يرجى ملاحظة أنه بالمقارنة مع الأصل ، يتم تضمين مستودع الشريك.


للتثبيت والتهيئة ، يجب تشغيل الأوامر أدناه.


أوامر تثبيت 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. يستخدم نواة خاصة به ، وبعد التثبيت قد يلزم إعادة تشغيل الكمبيوتر.


بعد إعادة التشغيل ، ستتوفر واجهة OpenMediaVault على المنفذ 80 (انتقل إلى المتصفح على NAS بواسطة عنوان IP):



اسم المستخدم / كلمة المرور الافتراضية هي admin/openmediavault .


تكوين OMV


علاوة على ذلك ، سيتم تمرير معظم التكوين عبر WEB-GUI.


قم بإنشاء اتصال آمن


تحتاج الآن إلى تغيير كلمة مرور مسؤول WEB وإنشاء شهادة لـ NAS من أجل العمل على HTTPS في المستقبل.


يتم تغيير كلمة المرور في علامة التبويب "النظام-> الإعدادات العامة-> كلمة مرور مسؤول الويب" .
لإنشاء شهادة في علامة التبويب "النظام-> الشهادات-> SSL" ، حدد "إضافة-> إنشاء" .


ستكون الشهادة التي تم إنشاؤها مرئية في علامة التبويب نفسها:


الشهادة


بعد إنشاء الشهادة ، في علامة التبويب "النظام-> إعدادات عامة" ، قم بتمكين مربع الاختيار "تمكين SSL / TLS" .


ستطلب شهادة قبل اكتمال التكوين. ستستخدم النسخة النهائية شهادة موقعة للاتصال بـ OMV.


تحتاج الآن إلى تسجيل الدخول إلى OMV ، على المنفذ 443 ، أو ببساطة تعيين البادئة https:// إلى IP في المستعرض.


إذا تمكنت من تسجيل الدخول ، في علامة التبويب "System-> General Settings" ، فأنت بحاجة إلى تمكين مربع الاختيار "Force SSL / TLS".


تغيير المنافذ 80 و 443 إلى 10080 و 10443 .
وحاول تسجيل الدخول إلى العنوان التالي: https://IP_NAS:10443 .
تغيير المنافذ مهم لأن المنفذين 80 و 443 سيستخدمان حاوية عامل الميناء مع الوكيل nginx-reverse-proxy.


الإعدادات الأساسية


الحد الأدنى من الإعدادات التي يجب القيام بها أولاً:


  • في علامة التبويب "النظام-> التاريخ والوقت" ، تحقق من قيمة المنطقة الزمنية وقم بتعيين خادم NTP.
  • على علامة التبويب "النظام-> المراقبة" تمكن من جمع إحصاءات الأداء.
  • في علامة التبويب "النظام-> إدارة الطاقة" ، من المحتمل إيقاف تشغيل "المراقبة" حتى لا تحاول OMV التحكم في المراوح.

شبكة


إذا لم يتم توصيل واجهة شبكة NAS الثانية بعد ، فقم بتوصيلها بالموجه.


ثم:


  • في علامة التبويب "النظام-> الشبكة" ، عيّن اسم المضيف على "nas" (أو أي شيء تريده).
  • قم بإعداد الترابط للواجهات كما هو موضح في الشكل أدناه: "System-> Network-> Interfaces-> Add-> Bond" .
  • أضف قواعد جدار الحماية الضرورية في علامة التبويب "النظام-> الشبكة-> جدار الحماية" . أولاً ، الوصول إلى المنافذ 10443 و 10080 و 443 و 80 و 22 لـ SSH والإذن بتلقي / إرسال ICMP كافٍ.

إعداد الربط


ونتيجة لذلك ، يجب أن تظهر الواجهات في الترابط ، والتي سيراها الموجه كواجهة واحدة وتعيين عنوان IP واحد لها:


واجهات الترابط


إذا رغبت في ذلك ، فمن الممكن أيضًا تكوين SSH من WEB GUI:


إعداد SSH


المستودعات والوحدات


في علامة التبويب "System-> Update Management-> Settings" ، شغّل "التحديثات التي يدعمها المجتمع" .


أولاً ، قم بإضافة مستودعات OMV الإضافية .
يمكن القيام بذلك ببساطة عن طريق تثبيت المكون الإضافي أو الحزمة ، كما هو موضح في المنتدى .


في صفحة "System-> Plugins" ، تحتاج إلى العثور على المكوّن الإضافي "openmediavault-omvextrasorg" وتثبيته.


ونتيجة لذلك ، سيظهر رمز "OMV-Extras" في قائمة النظام (يمكن رؤيته في لقطات الشاشة).


اذهب إلى هناك وقم بتمكين المستودعات التالية:


  • OMV-Extras.org. مستودع مستقر يحتوي على العديد من الإضافات.
  • اختبار OMV-Extras.org. بعض الإضافات من هذا المستودع ليست في المستودع المستقر.
  • عامل الميناء CE. في الواقع ، دوكر.

في علامة التبويب "System-> OMV Extras-> Kernel" يمكنك تحديد النواة التي تحتاجها ، بما في ذلك النواة من Proxmox (لم أقم بتثبيتها بنفسي ، لأنني لست بحاجة إليها بعد ، لذلك لا أوصي بها):



قم بتثبيت الملحقات الإضافية الضرورية ( بخط عريض للغاية ، بخط مائل - اختياري ، لم أقم بتثبيته):


قائمة الإضافات.
  • openmediavault-apttool. الحد الأدنى من واجهة المستخدم الرسومية للعمل مع نظام دفعي. يضيف "خدمات-> Apttool" .
  • openmediavault-anacron. يضيف القدرة على العمل من واجهة المستخدم الرسومية مع جدولة غير متزامنة. يضيف "System-> Anacron" .
  • openmediavault- النسخ الاحتياطي. يوفر نظام النسخ الاحتياطي في التخزين. يضيف صفحة "النظام> النسخ الاحتياطي" .
  • openmediavault- الأقراص. مطلوب لجمع إحصائيات حول أداء القرص.
  • openmediavault-dnsmasq . يتيح لك رفع خادم DNS و DHCP على NAS. لأنني أقوم بذلك على جهاز توجيه ، لا أحتاج إليه.
  • openmediavault-docker-gui . واجهة إدارة حاوية Docker. يضيف "الخدمات-> عامل الميناء" .
  • openmediavault-ldap . دعم المصادقة من خلال LDAP. يضيف "إدارة الحقوق -> خدمة الدليل" .
  • openmediavault-letencrypt . دعم Let's Encrypt from GUI. ليست هناك حاجة إليها ، لأنها تستخدم التضمين في حاوية nginx-reverse-proxy.
  • openmediavault-luksencryption . دعم تشفير LUKS. من الضروري أن تكون الأقراص المشفرة مرئية في واجهة OMV. يضيف "التخزين-> التشفير" .
  • openmediavault الجوز . دعم UPS. يضيف "خدمات-> UPS" .
  • openmediavault-omvextrasorg . يجب تثبيت إضافات OMV بالفعل.
  • openmediavault-resetperms. يسمح لك بإعادة تعيين الأذونات وإعادة تعيين قوائم التحكم في الوصول في الدلائل المشتركة. يضيف "التحكم في الوصول -> الدلائل العامة -> إعادة تعيين الأذونات" .
  • طريق openmediavault. البرنامج المساعد مفيد لإدارة التوجيه. يضيف "System-> Network-> Static Route" .
  • openmediavault- الارتباطات. يوفر القدرة على إنشاء روابط رمزية. يضيف الصفحة "الخدمات-> الروابط" .
  • أنظمة openmediavault-unionfiles. دعم UnionFS. قد يكون مفيدًا في المستقبل ، على الرغم من أن عامل الميناء يستخدم ZFS كخلفية. يضيف "التخزين-> أنظمة ملفات الاتحاد" .
  • openmediavault- virtualbox . يمكن استخدامه لتضمين قدرات إدارة الجهاز الظاهري في واجهة المستخدم الرسومية.
  • openmediavault-zfs . يضيف المكون الإضافي دعم ZFS إلى OpenMediaVault. بعد التثبيت ، ستظهر صفحة "التخزين-> ZFS" .

الأقراص


يجب أن تكون كافة الأقراص الموجودة في النظام مرئية OMV. تأكد من ذلك من خلال النظر إلى علامة التبويب "التخزين-> الأقراص" . إذا لم تكن جميع الأقراص مرئية ، فقم بإجراء فحص.


أقراص في النظام


هناك ، على جميع محركات الأقراص الصلبة ، يجب تمكين التخزين المؤقت للكتابة (بالنقر على قرص من القائمة والنقر فوق الزر "تحرير").


تأكد من أن جميع الأقسام المشفرة مرئية في علامة التبويب "التخزين-> التشفير" :


أقسام مشفرة


حان الوقت الآن لتكوين SMART ، المشار إليه كوسيلة لزيادة الموثوقية:


  • انتقل إلى علامة التبويب "التخزين-> SMART-> الإعدادات" . قم بتشغيل SMART.
  • في نفس المكان ، حدد قيم مستويات درجة حرارة الأقراص (حرجة ، عادة 60 درجة مئوية ، ونظام درجة الحرارة الأمثل للقرص 15-45 درجة مئوية).
  • انتقل إلى علامة التبويب "التخزين-> SMART-> الأجهزة" . قم بتشغيل المراقبة لكل محرك أقراص.
  • انتقل إلى علامة التبويب "التخزين-> SMART-> الاختبارات المجدولة" . قم بإضافة اختبار ذاتي قصير مرة واحدة يوميًا لكل قرص واختبار ذاتي طويل مرة كل شهر. علاوة على ذلك ، حتى لا تتداخل فترات الاختبار الذاتي.

على هذا ، يمكن اعتبار تكوين القرص مكتملاً.


أنظمة الملفات والدلائل المشتركة


يجب عليك إنشاء أنظمة ملفات للأدلة المحددة مسبقًا.
يمكن القيام بذلك من وحدة التحكم ، أو من واجهة OMV WEB ( التخزين-> ZFS-> حدد خزان التجمع 0-> زر الإضافة -> نظام الملفات ).


أوامر لإنشاء 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 

يجب أن تكون النتيجة بنية الدليل التالية:



بعد ذلك ، أضف ملفات FS التي تم إنشاؤها كدلائل مشتركة في صفحة "إدارة حقوق الوصول-> الدلائل العامة- > إضافة" .
يرجى ملاحظة أن معلمة "الجهاز" تساوي المسار إلى نظام الملفات الذي تم إنشاؤه في ZFS ، وأن معلمة "المسار" لجميع الدلائل هي "/".



النسخ الاحتياطي


يتم النسخ الاحتياطي بواسطة أداتين:



إذا كنت تستخدم المكون الإضافي ، فمن المحتمل أن تحصل على خطأ:


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

من أجل إصلاحه ، كما لاحظ مطورو OMV في هذا "التكوين غير القياسي للغاية" ، سيكون من الممكن رفض المكون الإضافي واستخدام أدوات ZFS في شكل zfs send/receive .
أو ، حدد بشكل صريح المعلمة "جهاز الجذر" في شكل جهاز فعلي يتم إجراء التنزيل منه.
من الأنسب بالنسبة لي استخدام المكون الإضافي وعمل نسخة احتياطية من نظام التشغيل من الواجهة ، بدلاً من تخبط شيء ما مع إرسال zfs ، لذلك أفضل الخيار الثاني.


إعداد النسخ الاحتياطي


لإجراء النسخ الاحتياطي ، قم أولاً بإنشاء نظام tank0/apps/backup خلال ZFS ، ثم في قائمة "النظام-> النسخ الاحتياطي" ، انقر فوق "+" في حقل معلمة "المجلد العام" وأضف الجهاز الذي تم إنشاؤه كهدف وحقل "المسار" تم الضبط على "/".


هناك مشكلات في zfs-auto-snapshot أيضًا. إذا لم يتم تكوينها ، فسوف تلتقط الصور كل ساعة وكل يوم وكل أسبوع وكل شهر لمدة عام.
والنتيجة هي ما في لقطة الشاشة:


الكثير من الرسائل غير المرغوب فيها من zfs-auto-snapshot


إذا كنت قد صادفت هذا بالفعل ، فقم بتشغيل التعليمات البرمجية التالية لإزالة اللقطات التلقائية:


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

ثم قم بتكوين لقطة zfs-auto-snapshot لتعمل في cron.
للبدء ، ما عليك سوى حذف /etc/cron.hourly/zfs-auto-snapshot إذا لم تكن بحاجة إلى التقاط الصور كل ساعة.


إخطارات البريد الإلكتروني


وقد أشير إلى الإشعار عبر البريد الإلكتروني باعتباره إحدى الوسائل لتحقيق الموثوقية.
لذلك ، تحتاج الآن إلى تكوين إعلامات البريد الإلكتروني.
للقيام بذلك ، قم بتسجيل مربع على أحد الخوادم العامة (حسنًا ، أو قم بتكوين خادم SMTP بنفسك ، إذا كان لديك بالفعل أسباب للقيام بذلك).


ثم تحتاج للذهاب إلى صفحة "النظام-> الإخطار" وإدخال:


  • عنوان خادم SMTP.
  • منفذ خادم SMTP.
  • اسم المستخدم
  • عنوان المرسل (عادة ما يتطابق المكون الأول من العنوان مع الاسم).
  • كلمة مرور المستخدم
  • في حقل "المستلم" ، عنوانك المعتاد الذي سترسل إليه NAS إشعارات.

يُنصح بشدة بتمكين SSL / TLS.


يظهر مثال على إعداد Yandex في لقطة الشاشة:


إخطارات البريد الإلكتروني


إعداد الشبكة خارج NAS


عنوان IP


أستخدم عنوان IP ثابتًا أبيض ، والذي يكلف بالإضافة إلى 100 روبل شهريًا. إذا لم تكن هناك رغبة في الدفع وكان عنوانك ديناميكيًا ، ولكن ليس لـ NAT ، فمن الممكن ضبط سجلات DNS الخارجية من خلال واجهة برمجة التطبيقات للخدمة المحددة.
ومع ذلك ، يجب أن يوضع في الاعتبار أن عنوانًا غير NAT يمكن أن يصبح فجأة عنوان NAT: كقاعدة عامة ، لا يمنح مقدمو الخدمة أي ضمانات.


جهاز التوجيه


كجهاز توجيه ، لدي لوحة Mikrotik RouterBoard ، مشابهة لتلك الموجودة في الصورة أدناه.


جهاز التوجيه Mikrotik


هناك ثلاثة أشياء مطلوبة على جهاز التوجيه:


  • تكوين عناوين ثابتة لـ NAS. في حالتي ، يتم إصدار العناوين عبر DHCP ، وأحتاج إلى التأكد من أن المحولات التي تحمل عنوان MAC محددًا تحصل دائمًا على نفس عنوان IP. في RouterOS ، يتم ذلك في علامة التبويب "IP-> DHCP Server" باستخدام الزر "جعل ثابت" .
  • قم بتكوين خادم DNS بحيث يعطي الاسم IP اسم "nas" ، وكذلك الأسماء التي تنتهي بـ ".nas" و ". NAS.cloudns.cc" (حيث تكون "NAS" هي المنطقة في ClouDNS أو خدمة مماثلة). يظهر مكان القيام بذلك في RouterOS في لقطة الشاشة أدناه. في حالتي ، يتم تنفيذ ذلك عن طريق مطابقة الاسم مع تعبير عادي: " ^.*\.nas$|^nas$|^.*\.NAS.cloudns.cc$ "
  • تكوين إعادة توجيه المنفذ. في RouterOS ، يتم ذلك في علامة التبويب "IP-> Firewall" ، ولن أتطرق إلى هذا الأمر أكثر من ذلك.

تكوين DNS في RouterOS


ClouDNS


CLouDNS بسيطة. إنشاء حساب ، تأكيد. سيتم تسجيل سجلات NS معك بالفعل. بعد ذلك ، مطلوب الحد الأدنى من الإعداد.


أولاً ، تحتاج إلى إنشاء المناطق اللازمة (المنطقة التي تحمل الاسم NAS المميزة باللون الأحمر في لقطة الشاشة هي ما يجب عليك إنشاؤه باسم مختلف ، بالطبع).


إنشاء منطقة في ClouDNS


ثانيًا ، في هذه المنطقة يجب عليك تسجيل سجلات A التالية:


  • nas ، www ، omv ، control واسم فارغ . للوصول إلى واجهة OMV.
  • ldap . واجهة PhpLdapAdmin
  • ssp . واجهة لتغيير كلمات مرور المستخدم.
  • اختبار . خادم الاختبار.

ستتم إضافة أسماء النطاقات المتبقية عند إضافة الخدمات.
انقر فوق المنطقة ، ثم "إضافة سجل جديد" ، حدد نوع A ، أدخل اسم المنطقة وعنوان IP لجهاز التوجيه الذي يوجد خلفه NAS.


تمت إضافة سجلات A


ثانيًا ، تحتاج إلى الوصول إلى واجهة برمجة التطبيقات. يتم دفعها في ClouDNS ، لذلك يجب عليك أولاً دفع ثمنها. في خدمات أخرى ، إنه مجاني. إذا كنت تعرف أيهما أفضل ، وهذا مدعوم من Lexicon ، فيرجى كتابة التعليقات.


بعد الوصول إلى API ، تحتاج إلى إضافة مستخدم API جديد هناك.


إضافة مستخدم ClouDNS API


"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" 

:


أطلقت 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 .


:


تكوين OMV للعمل مع 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 

" " " ".
, :


إعداد UPS


. , .
.


الخلاصة


. , , , , .
— .


-, OMV .


WEB-, , :



Docker WEB-:



, OMV .


:



:



CPU:


CPU




.
!


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


All Articles