Implementasi platform perangkat lunak NAS yang aman


Dalam artikel sebelumnya , desain platform perangkat lunak NAS dijelaskan.
Sudah waktunya untuk mengimplementasikannya.


Periksa


Pastikan untuk memeriksa kesehatan kolam sebelum memulai:


zpool status -v 

Kolam dan semua disk di dalamnya harus ONLINE.


Lebih lanjut, saya berasumsi bahwa pada tahap sebelumnya semuanya dilakukan sesuai dengan instruksi , dan itu berhasil, atau Anda sendiri sangat mengerti apa yang Anda lakukan.


Fasilitas


Pertama-tama, ada baiknya mengurus manajemen yang nyaman jika Anda tidak melakukan ini sejak awal.
Itu akan diperlukan:


  • Server SSH: apt-get install openssh-server . Jika Anda tidak tahu cara mengkonfigurasi SSH, melakukan NAS di Linux terlalu dini Anda dapat membaca fitur penggunaannya dalam artikel ini , lalu menggunakan salah satu manual .
  • tmux atau layar : apt-get install tmux . Untuk menyimpan sesi saat masuk melalui SSH dan menggunakan beberapa jendela.

Setelah menginstal SSH, Anda perlu menambahkan pengguna agar tidak masuk melalui SSH sebagai root (input dinonaktifkan secara default dan Anda tidak perlu mengaktifkannya):


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

Untuk administrasi jarak jauh, ini adalah minimum yang cukup.


Meskipun demikian, Anda harus tetap menyambungkan keyboard dan monitor Anda juga perlu melakukan reboot ketika memperbarui kernel dan untuk memastikan bahwa semuanya berfungsi segera setelah memuat.


Alternatifnya adalah menggunakan Virtual KVM, yang menyediakan IME . Ada konsol di sana, meskipun dalam kasus saya ini diimplementasikan sebagai applet Java, yang sangat tidak nyaman.


Kustomisasi


Persiapan cache


Sejauh yang Anda ingat, dalam konfigurasi yang dijelaskan oleh saya ada SSD terpisah di bawah L2ARC, yang belum digunakan, tetapi diambil "untuk pertumbuhan".


Opsional, tetapi disarankan untuk mengisi SSD ini dengan data acak (dalam kasus Samsung EVO, masih akan diisi dengan nol setelah blkdiscard dijalankan, tetapi tidak pada semua SSD seperti ini):


 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 

Menonaktifkan Kompresi Log


Di ZFS, kompresi sudah digunakan, karena kompresi log melalui gzip jelas akan berlebihan.
Matikan:


 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 

Pembaruan sistem


Semuanya sederhana di sini:


 apt-get dist-upgrade --yes reboot 

Membuat snapshot untuk keadaan baru


Setelah mem-boot ulang, untuk memperbaiki kondisi kerja yang baru, Anda perlu menulis ulang snapshot pertama:


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

Organisasi sistem file


Partisi untuk SLOG


Hal pertama yang harus dilakukan untuk mencapai kinerja ZFS normal adalah meletakkan SLOG di SSD.
Biarkan saya mengingatkan Anda bahwa SLOG dalam konfigurasi yang digunakan digandakan pada dua SSD: untuk itu, perangkat pada LUKS-XTS akan dibuat di atas bagian ke-4 dari setiap 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 

Partisi untuk L2ARC dan Swap


Pertama, Anda perlu membuat partisi di bawah swap dan 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 

Partisi swap dan L2ARC akan dienkripsi pada kunci acak, seperti setelah reboot, mereka tidak diperlukan dan selalu memungkinkan untuk membuatnya kembali.
Oleh karena itu, dalam crypttab, sebuah baris ditulis untuk mengenkripsi / mendekripsi partisi dalam mode biasa:


 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 

Maka Anda perlu me-restart daemon dan mengaktifkan swap:


 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 

Karena swapiness tidak digunakan secara aktif pada SSD, parameter swapiness , yang secara default adalah 60, harus diatur ke 10.


L2ARC belum digunakan pada tahap ini, tetapi bagian untuk itu sudah siap:


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

Tangki renangn


Penciptaan kolam tank0 akan dijelaskan, tank1 dibuat dengan analogi.


Agar tidak membuat partisi yang sama secara manual dan menghindari kesalahan, saya menulis skrip untuk membuat partisi terenkripsi untuk kumpulan:


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 

Sekarang, menggunakan skrip ini, Anda perlu membuat kumpulan untuk menyimpan data:


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

Untuk catatan tentang parameter ashift=12 , lihat artikel dan komentar saya sebelumnya .


Setelah membuat kumpulan, saya mengeluarkan log-nya di SSD:


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

Di masa depan, dengan OMV diinstal dan dikonfigurasi, dimungkinkan untuk membuat kumpulan melalui GUI:


Pembuatan ZFS jatuh dalam OMV WEB GUI


Mengaktifkan kumpulan impor dan volume pemasangan otomatis saat boot


Untuk menjamin untuk mengaktifkan kumpulan pemasangan otomatis, jalankan perintah berikut:


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

Pada tahap ini, konfigurasi subsistem disk selesai.


Sistem operasi


Langkah pertama adalah menginstal dan mengkonfigurasi OMV untuk akhirnya mendapatkan semacam fondasi untuk NAS.


Instal OMV


OMV akan diinstal sebagai paket deb. Untuk melakukan ini, dimungkinkan untuk menggunakan instruksi resmi .


Skrip add_repo.sh menambahkan repositori OMV Arrakis ke /etc/apt/ sources.list.d sehingga sistem batch melihat repositori.


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 

Harap dicatat bahwa dibandingkan dengan aslinya, repositori mitra disertakan.


Untuk menginstal dan menginisialisasi, Anda harus menjalankan perintah di bawah ini.


Perintah untuk menginstal 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 diinstal. Ia menggunakan kernelnya sendiri, dan setelah instalasi reboot mungkin diperlukan.


Setelah reboot, antarmuka OpenMediaVault akan tersedia di port 80 (buka browser di NAS dengan alamat IP):



Nama pengguna / kata sandi default adalah admin/openmediavault .


Konfigurasikan OMV


Lebih lanjut, sebagian besar konfigurasi akan melalui WEB-GUI.


Buat koneksi yang aman


Sekarang Anda perlu mengubah kata sandi administrator WEB dan membuat sertifikat untuk NAS agar dapat bekerja pada HTTPS di masa mendatang.


Kata sandi diubah pada tab "Sistem-> Pengaturan Umum-> Kata Sandi Administrator Web" .
Untuk menghasilkan sertifikat pada tab "Sistem-> Sertifikat-> SSL", pilih "Tambah-> Buat" .


Sertifikat yang dibuat akan terlihat pada tab yang sama:


Sertifikat


Setelah membuat sertifikat, pada tab "Sistem-> Pengaturan Umum", aktifkan kotak centang "Aktifkan SSL / TLS" .


Sertifikat akan diperlukan sebelum konfigurasi selesai. Versi final akan menggunakan sertifikat yang ditandatangani untuk menghubungi OMV.


Sekarang Anda harus masuk ke OMV, ke port 443, atau cukup menetapkan https:// awalan ke IP di browser.


Jika Anda berhasil masuk, pada tab "System-> General Settings" Anda harus mengaktifkan kotak centang "Force SSL / TLS".


Ubah port 80 dan 443 menjadi 10080 dan 10443 .
Dan coba masuk ke alamat berikut: https://IP_NAS:10443 .
Mengubah port penting karena port 80 dan 443 akan menggunakan wadah buruh pelabuhan dengan nginx-reverse-proxy.


Pengaturan utama


Pengaturan minimum yang harus dilakukan terlebih dahulu:


  • Pada tab "Sistem-> Tanggal dan Waktu" periksa nilai zona waktu dan atur server NTP.
  • Pada tab "Sistem-> Pemantauan" memungkinkan pengumpulan statistik kinerja.
  • Pada tab "Sistem-> Manajemen Energi" mungkin perlu mematikan "Pemantauan" sehingga OMV tidak mencoba untuk mengendalikan kipas.

Jaringan


Jika antarmuka jaringan NAS kedua belum terhubung, sambungkan ke router.


Lalu:


  • Pada tab "System-> Network", atur nama host ke "nas" (atau apa pun yang Anda suka).
  • Atur ikatan untuk antarmuka seperti yang ditunjukkan pada gambar di bawah ini: "System-> Network-> Interfaces-> Add-> Bond" .
  • Tambahkan aturan firewall yang diperlukan pada tab "System-> Network-> Firewall" . Pertama, akses ke port 10443, 10080, 443, 80, 22 untuk SSH dan izin untuk menerima / mengirim ICMP sudah cukup.

Pengaturan ikatan


Akibatnya, antarmuka dalam ikatan akan muncul, yang akan dilihat router sebagai satu antarmuka dan menetapkan satu alamat IP:


Ikatan antarmuka


Jika diinginkan, dimungkinkan untuk mengkonfigurasi SSH tambahan dari WEB GUI:


Pengaturan ssh


Repositori dan modul


Pada tab "Sistem-> Perbarui Manajemen-> Pengaturan" nyalakan "Pembaruan yang didukung oleh komunitas . "


Pertama, tambahkan repositori tambahan OMV .
Ini dapat dilakukan hanya dengan menginstal plugin atau paket, seperti yang ditunjukkan di forum .


Pada halaman "System-> Plugins" Anda perlu menemukan plugin "openmediavault-omvextrasorg" dan menginstalnya.


Hasilnya, ikon "OMV-Extras" akan muncul di menu sistem (dapat dilihat di tangkapan layar).


Pergi ke sana dan aktifkan repositori berikut:


  • OMV-Extras.org. Repositori stabil yang berisi banyak plugin.
  • Pengujian OMV-Extras.org. Beberapa plugin dari repositori ini tidak ada dalam repositori stable.
  • Docker CE. Sebenarnya, Docker.

Pada tab "System-> OMV Extras-> Kernel" Anda dapat memilih kernel yang Anda butuhkan, termasuk kernel dari Proxmox (saya tidak menginstalnya sendiri, karena saya belum membutuhkannya, oleh karena itu saya tidak merekomendasikannya):



Instal plugin yang diperlukan ( cetak tebal mutlak, cetak miring - opsional, yang tidak saya instal):


Daftar plugin.
  • openmediavault-apttool. GUI minimum untuk bekerja dengan sistem batch. Menambahkan "Layanan-> Apttool" .
  • openmediavault-anacron. Menambahkan kemampuan untuk bekerja dari GUI dengan penjadwal asinkron. Menambahkan "System-> Anacron" .
  • openmediavault-backup. Menyediakan sistem cadangan dalam penyimpanan. Menambahkan halaman "System-> Backup" .
  • openmediavault-diskstats. Diperlukan untuk mengumpulkan statistik tentang kinerja disk.
  • openmediavault-dnsmasq . Memungkinkan Anda menaikkan server DNS dan DHCP di NAS. Karena saya melakukan ini di router, saya tidak membutuhkannya.
  • openmediavault-docker-gui . Antarmuka manajemen wadah Docker. Menambahkan "Layanan-> Docker" .
  • openmediavault-ldap . Dukungan untuk otentikasi melalui LDAP. Menambahkan "Manajemen Hak -> Layanan Direktori" .
  • openmediavault-letsencrypt . Dukungan untuk Let's Encrypt dari GUI. Ini tidak diperlukan, karena menggunakan embedding dalam wadah nginx-reverse-proxy.
  • openmediavault-luksencryption . Dukungan enkripsi LUKS. Diperlukan bahwa disk terenkripsi terlihat di antarmuka OMV. Menambahkan "Storage-> Enkripsi" .
  • openmediavault-nut . Dukungan UPS. Menambahkan "Layanan-> UPS" .
  • openmediavault-omvextrasorg . OMV Extras seharusnya sudah diinstal.
  • openmediavault-resetperms. Memungkinkan Anda mengatur ulang izin dan mengatur ulang daftar kontrol akses di direktori bersama. Menambahkan "Kontrol Akses -> Direktori Umum -> Atur Ulang Izin" .
  • openmediavault-rute. Plugin yang berguna untuk manajemen perutean. Menambahkan "System-> Network-> Static Route" .
  • openmediavault-symlinks. Memberikan kemampuan untuk membuat tautan simbolik. Menambahkan halaman "Layanan-> Simbol" .
  • openmediavault-unionfilesystems. Dukungan UnionFS. Ini mungkin berguna di masa depan, meskipun buruh pelabuhan menggunakan ZFS sebagai backend. Menambahkan "Storage-> Union Filesystems" .
  • openmediavault-virtualbox . Ini dapat digunakan untuk menanamkan kemampuan manajemen mesin virtual di GUI.
  • openmediavault-zfs . Plugin menambahkan dukungan ZFS ke OpenMediaVault. Setelah instalasi, halaman "Storage-> ZFS" akan muncul.

Disk


Semua disk yang ada dalam sistem harus terlihat OMV. Pastikan ini dengan melihat tab "Storage-> Disks" . Jika tidak semua disk terlihat, jalankan pemindaian.


Disk dalam sistem


Di sana, di semua HDD, caching tulis harus diaktifkan (dengan mengklik pada disk dari daftar dan mengklik tombol "Edit").


Pastikan bahwa semua bagian terenkripsi terlihat pada tab "Storage-> Enkripsi" :


Partisi terenkripsi


Sekarang saatnya mengkonfigurasi SMART, yang diindikasikan sebagai cara untuk meningkatkan keandalan:


  • Pergi ke tab "Storage-> SMART-> Settings" . Nyalakan SMART.
  • Di tempat yang sama, pilih nilai level suhu disk (kritis, biasanya 60 C, dan rezim suhu optimal disk 15-45 C).
  • Pergi ke tab "Storage-> SMART-> Devices" . Aktifkan pemantauan untuk setiap drive.
  • Buka tab "Penyimpanan-> SMART-> Tes Terjadwal" . Tambahkan swa-uji singkat sehari sekali untuk setiap disk dan swa-uji panjang sebulan sekali. Apalagi, agar periode swa-uji tidak tumpang tindih.

Pada ini, konfigurasi disk dapat dianggap selesai.


Sistem File dan Direktori Bersama


Anda harus membuat sistem file untuk direktori yang telah ditentukan.
Ini dapat dilakukan dari konsol, atau dari antarmuka WEB OMV ( Storage-> ZFS-> Select pool tank0-> Add button -> Filesystem ).


Perintah untuk membuat 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 

Hasilnya harus struktur direktori berikut:



Setelah itu, tambahkan FS yang dibuat sebagai direktori bersama di halaman "Mengelola Hak Akses-> Direktori Umum-> Tambah" .
Harap dicatat bahwa parameter "Device" sama dengan path ke sistem file yang dibuat di ZFS, dan parameter "Path" untuk semua direktori adalah "/".



Cadangkan


Pencadangan dilakukan oleh dua alat:



Jika Anda menggunakan plugin, kemungkinan besar Anda mendapatkan kesalahan:


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

Untuk memperbaikinya, sebagaimana dicatat oleh pengembang OMV dalam "konfigurasi yang sangat tidak standar" ini, akan mungkin untuk menolak plugin dan menggunakan alat ZFS dalam bentuk zfs send/receive .
Atau, tentukan secara spesifik parameter "Root device" dalam bentuk perangkat fisik dari mana unduhan dilakukan.
Lebih nyaman bagi saya untuk menggunakan plugin dan mencadangkan OS dari antarmuka, daripada membingkai sesuatu milik saya sendiri dengan zfs send, jadi saya lebih suka opsi kedua.


Penyiapan cadangan


Untuk membuat cadangan berfungsi, pertama buat sistem file tank0/apps/backup melalui ZFS, kemudian di menu "System-> Backup" klik "+" di bidang parameter "Folder publik" dan tambahkan perangkat yang dibuat sebagai target dan bidang "Path" setel ke "/".


Ada masalah dengan zfs-auto-snapshot juga. Jika tidak dikonfigurasi, dia akan mengambil gambar setiap jam, setiap hari, setiap minggu, setiap bulan selama satu tahun.
Hasilnya adalah apa yang ada di tangkapan layar:


Banyak spam dari zfs-auto-snapshot


Jika Anda telah menemukan ini, jalankan kode berikut untuk menghapus snapshot otomatis:


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

Kemudian konfigurasikan zfs-auto-snapshot untuk berjalan di cron.
Untuk memulai, cukup hapus /etc/cron.hourly/zfs-auto-snapshot jika Anda tidak perlu mengambil gambar setiap jam.


Pemberitahuan Email


Pemberitahuan melalui email telah diindikasikan sebagai salah satu cara untuk mencapai keandalan.
Karenanya, sekarang Anda perlu mengonfigurasi notifikasi email.
Untuk melakukan ini, daftarkan sebuah kotak di salah satu server publik (baik, atau konfigurasikan sendiri server SMTP, jika Anda benar-benar memiliki alasan untuk melakukan ini).


Maka Anda harus pergi ke halaman "System-> Notification" dan masukkan:


  • Alamat server SMTP.
  • Port server SMTP.
  • Nama pengguna
  • Alamat pengirim (biasanya komponen pertama dari alamat tersebut sesuai dengan namanya).
  • Kata sandi pengguna
  • Di bidang "Penerima", alamat Anda yang biasa digunakan NAS untuk mengirimkan pemberitahuan.

Sangat disarankan untuk mengaktifkan SSL / TLS.


Contoh pengaturan untuk Yandex ditunjukkan pada tangkapan layar:


Permintaan Email


Pengaturan jaringan di luar NAS


Alamat IP


Saya menggunakan alamat IP statis putih, yang biayanya ditambah 100 rubel per bulan. Jika tidak ada keinginan untuk membayar dan alamat Anda dinamis, tetapi tidak untuk NAT, dimungkinkan untuk menyesuaikan catatan DNS eksternal melalui API layanan yang dipilih.
Namun demikian, harus diingat bahwa alamat non-NAT tiba-tiba dapat menjadi alamat NAT: sebagai suatu peraturan, penyedia tidak memberikan jaminan apa pun.


Router


Sebagai router, saya memiliki Mikrotik RouterBoard , mirip dengan yang ada di gambar di bawah ini.


Routerboard mikrotik


Tiga hal diperlukan pada router:


  • Konfigurasikan alamat statis untuk NAS. Dalam kasus saya, alamat dikeluarkan melalui DHCP, dan saya perlu memastikan bahwa adaptor dengan alamat MAC tertentu selalu mendapatkan alamat IP yang sama. Di RouterOS, ini dilakukan pada tab "IP-> DHCP Server" dengan tombol "Make static" .
  • Konfigurasikan server DNS sehingga untuk nama "nas", serta nama yang berakhiran ".nas" dan ".NAS.cloudns.cc" (di mana "NAS" adalah zona pada ClouDNS atau layanan serupa) itu memberikan sistem IP. Di mana melakukan ini di RouterOS ditunjukkan pada gambar di bawah. Dalam kasus saya, ini diterapkan dengan mencocokkan nama dengan ekspresi reguler: " ^.*\.nas$|^nas$|^.*\.NAS.cloudns.cc$ "
  • Konfigurasikan penerusan port. Di RouterOS, ini dilakukan pada tab "IP-> Firewall" , saya tidak akan membahas hal ini lebih lanjut.

Konfigurasikan DNS di RouterOS


ClouDNS


CLouDNS sederhana. Buat akun, konfirmasi. Catatan NS sudah akan terdaftar pada Anda. Selanjutnya, pengaturan minimal diperlukan.


Pertama, Anda perlu membuat zona yang diperlukan (zona dengan nama NAS yang disorot merah di tangkapan layar adalah apa yang harus Anda buat dengan nama yang berbeda, tentu saja).


Membuat zona di ClouDNS


Kedua, di zona ini Anda harus mendaftarkan A-record berikut:


  • nas , www , omv , control dan nama kosong . Untuk mengakses antarmuka OMV.
  • lap . Antarmuka PhpLdapAdmin
  • ssp . Antarmuka untuk mengubah kata sandi pengguna.
  • tes . Server uji.

Nama domain yang tersisa akan ditambahkan saat layanan ditambahkan.
Klik pada zona, lalu "Tambahkan catatan baru" , pilih tipe-A, masukkan nama zona dan alamat IP router di belakang NAS.


Ingat suatu catatan


Kedua, Anda perlu mengakses API. Di ClouDNS dibayar, jadi Anda harus membayarnya terlebih dahulu. Di layanan lain, ini gratis. Jika Anda tahu mana yang lebih baik, dan ini didukung oleh Lexicon , silakan tulis di komentar.


Setelah mendapatkan akses ke API, Anda perlu menambahkan pengguna API baru di sana.


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

:


Meluncurkan 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 .


:


Konfigurasikan OMV untuk bekerja dengan 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 

" " " ".
, :


Pengaturan UPS


. , .
.


Kesimpulan


. , , , , .
— .


-, OMV .


WEB-, , :



Docker WEB-:



, OMV .


:


Jadwal Penggunaan Jaringan


:


Grafik penggunaan memori


CPU:


Grafik penggunaan CPU




.
!


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


All Articles