All-In-One: Proxmox + OpenMediaVault или ещё одна идея для домашнего NAS

от автора

Астрологи объявили месяц статей о домашних NAS на хабре, так что поделюсь и своей историей успеха…

Не так давно я попробовал новый FreeNAS Coral. Понравилось мне в нем если не все, то очень многое: это и новый гипервизор bhyve, и повсеместное использование 9P для проброса файловой системы на гостя, а так же идея с docker и многое другое.
Кроме того я ещё больше влюбился в ZFS со всеми её плюшками, такими как дедупликация и сжатие на лету.

Но к сожалению не все было так гладко как хотелось бы и, к тому же, флешка с установленной системой приказала долго жить, так что настало время для новых экспериментов!
На этот раз я задумал реализовать что-то похожее, но только лучше и целиком на Linux.

В статье так же будет немного рассказано про Docker и автоматический прокси с автоматическим получением сертификатов Letsencrypt.

Для начала расскажу что же мне все таки не понравилось в FreeNAS Corral:

  • Не готов для production. (недавно этот релиз вообще отозвали)
  • Работа с docker удобна только в случае единичных контейнеров, в случае когда контейнеров много управление через веб-морду становится крайне неэффективным.
  • Контейнеры запускаются внутри виртуальных машин с Linux, а порты проксируются через хост, что в принципе не плохо, но подразумевает некий оверхед в сравнении если бы они запускались прямо на хосте.
  • Гипервизор bhyve пока не поддерживает live-snapshots.
  • Нет возможности создавать виртуальные машины не из шаблонов. (по крайней мере в GUI)
  • Система установленая на флешку ужасно тормозила.

В принципе со всем этим можно было бы жить, но как я говорил флешка с системой сдохла и теперь у меня есть новые идеи:

  • Систему нужно устанавливать на жёсткий диск, пусть даже самый простой, но на диск, а не на флешку.
    Идея с установленной системы отдельно от данных хороша, но сколько я флешек не перепробовал (включая USB 3.0) всё равно работает очень плохо и безбожно тормозит. Так что ставить будем на отдельный HDD.

  • ZFS в качестве основанной файловой системы. ZFS позволяет не думать как мне распределять ресурсы хранилища между файловыми системами и виртуальными машинами, она поддерживает моментальные снимки (снапшоты), дедупликацию и сжатие на лету, а также известный RAIDZ.

  • Proxmox в качестве системы управления виртуализацией. Здесь есть все что необходимо: это поддержка как полной так и контейнерный виртуализации, снапшоты, автоматические бекапы и многое другое, а главное ZFS тут предлагается по умолчанию и работает прямо из коробки.
    Proxmox целиком и полностью управляется через современный веб-интерфейс на ExtJS:

Proxmox так-же позволяет подключаться к консоли виртуальной машины через веб-интерфейс:

для этого используется HTML5 клиент noVNC

  • OpenMediaVault в качестве системы управления хранилищем.

При выборе хранилища основным критерием была поддержка ZFS и работа на linux, а не на FreeBSD т.к. его хотелось установить на хостовую систему вместе с Proxmox а не на отдельную виртуальную машину.

Я рассматривал несколько софтин на эту роль, пробовал даже openATTIC — к сожалению поддержка ZFS там оказалась довольно слаба и на данный момент многих опций там просто нет, хотя я уверен что с CEPH дело предстоит несколько иначе.

В поисках я наткнулся на замечательный плагин добавляющмй поддержку zfs для OpenMediaVault — он даёт полный контроль над ZFS. Вместе с самим OpenMediaVault он полностью реализует все те функции, чего я так долго хотел получить от хранилища.
OpenMediaVault, как и Proxmox, целиком и полностью управляется через современный веб-интерфейс на ExtJS:

Proxmox и OpenMediaVault будут составлять ядро нашей системы, в результате чего мы получим многофункциональный комбайн продвинутой системы хранилища и продвинутой системы виртуализации в одной коробке, все данные при этом, как и диски виртуальных машин будут храниться на ZFS.
В случае если понадобится развернуть какой то новый сервис, всегда можно создать отдельную
виртуальную машину или контейнер для этого. Об этом я раскскажу чуть позже.

Обе системы поставляются и работают на Debian, что с одной стороны должно существенно упростить задачу, но с другой стороны обе системы несут в себе огромное количество пакетов и зависимостей, которые периодически могут пересекаться и конфликтовать между ссобой.
И специально для вас я написал небольшую инструкцию о том как сделать это.

Как установить OpenMediaVault на Proxmox

Установка Proxmox

Вам понадобится установочный диск, взять его можно на официальном сайте:

Установка проста и интуитивно понятна, так что думаю, не вызовет у вас лишних вопросов.
Скажу только что желательно иметь отдельный физический диск под систему, чтобы в случае чего её всегда можно было бы безболезненно переустановить, не затрагивая при этом диски с данными.

При установке Proxmox можно так же выбрать файловую систему ZFS или даже настроить програмный RAID.

Установка OpenMediaVault

Установим репозитроий OpenMediaVault 3.0 Erasmus:

echo "deb http://packages.openmediavault.org/public erasmus main" > /etc/apt/sources.list.d/openmediavault.list 

Как я говорил ранее, пакет openmediavault имеет некоторые неразрешимые зависимости с компонентами Proxmox, в часности это качается пакета watchdog, который в Proxmox начиная с версии 4.0 является fencing-демоном по умолчанию. В нашем случае он установлен по умолчанию как зависимость от proxmox-ve, но мы его не используем т.к. не используем кластеризацию.

В любом случае эти зависимости нам нужно как-то разрешить, и поэтому мы пересоберем deb-пакет для openmediavault.

Подготовим окружение для сборки:

apt install build-essentials

Скачаем исходники OpenMediaVault 3.0 Erasmus, и перейдем в директорию для сборки:

wget https://github.com/openmediavault/openmediavault/archive/3.x.tar.gz -O - | tar xzvf - cd openmediavault-3.x/deb/openmediavault

Эта команда покажет нам необходимые зависимости, которые мы должны установить в системе перед сборкой пакета:

dpkg-checkbuilddeps

Исходя из вывода предыдущей команды установим необходимые пакеты:

apt install debhelper fakeroot gettext dh-systemd doxygen

Теперь нам нужно удалить watchdog из зависимостей, для этого отредактируем debian/control и удалим оттуда watchdog:

vim debian/control # remove: watchdog

Проверим зависимости для сборки еще раз:

dpkg-checkbuilddeps

И запустим саму сборку:

dpkg-buildpackage -us -uc 

После сборки вы получите готовый deb-пакет, который мы и установим в систему:

cd .. dpkg -i openmediavault_*.deb

Теперь установим остальные зависимости, для этого запустим:

aptitude -f install

Теперь можно запустить скрипт для начальной конфигурации, поменять пароль администратора / порт веб-сервера и что-нибудь еще:

omv-firstaid

Установка плагина ZFS:

Плагин openmediavault-zfs устанавливается отдельно от OpenMediaVault и так как он тоже имеет неразрешимые зависимости мы тоже соберем его вручную:

Скачаем исходники, и перейдем в директорию для сборки:

wget https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-zfs/archive/master.tar.gz -O - | tar xzvf -  cd openmediavault-zfs-master

Подправим зависимости, удалим zfs-dkms так-как в Proxmox начиная с версии 4.0, ZFS уже идет в комплекте с ядром, до кучи за ненадобностью удалим так же linux-headers-* / pve-headers :

vim debian/control # remove: zfs-dkms # remove: linux-headers-amd64 | pve-headers | linux-headers-3.16.0-4-all

Проверим зависимости для сборки:

dpkg-checkbuilddeps

Запустим сборку:

dpkg-buildpackage -us -uc 

После сборки установим полученный пакет и зависимости для него:

cd .. dpkg -i openmediavault-zfs_*.deb aptitude -f install

Если возникнут трудности со сброкой пакетов, в документации Debian есть неплохая статья на русском языке:

На этом пожалуй все, теперь вы имеете Proxmox и OpenMediaVault установленные на одной системе, самое время перейти в GUI создать и настроить пулы ZFS и подключить их в Proxmox.
Как это сделать я описывать не буду, об этом и так полно информации в интернете.

Что дальше?

Дальше самое интересное, теперь можно приступить к настройке дополнительных сервисов.
Из них я хочу показать как настроить:

  • WordPress — это один из самых простых и распространненых движков для построения сайтов.
  • Nextcloud — ваше личное облако и интерфейс для доступа к файлам.
  • Deluge — на мой взгляд лучшая торрентокачалка.
  • Emby — свободный медиа сервер, позволяет стримить мультимедиа прямо в браузере или через DLNA.
  • nginx-proxy — который будет автоматически генерировать конфиг и все эти сервисы проксировать.
  • nginx-proxy-companion — будет получать и обновлять сертификаты в автоматическом порядке.

Каждый из этих сервисов будет доступен на субдомене и защищен SSL, с валидным сертификатом от Letsencrypt. На помощь нам придет Docker, думаю что это гораздо проще чем вы могли бы себе это представить.

Я полагаю вы уже настроили хранилище ZFS и подключили его в интерфейс Proxmox.

В моем конкретном случае есть два пула:

  • rpool — это тот что создал proxmox при установке
  • tank — это RAIDZ пул из трех дисков с данными

Также я создал четыре основных датастора:

  • tank/pve — для виртуальных машин Proxmox
  • tank/docker — здесь будут храниться данные сервисов запущенных в docker
  • tank/cloud — для данных nextcloud
  • tank/data — основная файлопосойка, внутри есть еще несколько датасторов, таких как Music, Photos, Movies, каждый со своими настройками, например для Music и Photos включена дедупликация, так как у меня большое количество повторяющихся файлов, которые я неизвсестно когда разгребу…

Теперь я хочу создать отдельную виртуальную машину в Proxmox, а точнее контейнер и запускать все в нем, что бы больше не издеваться над основной системой, и по возможности изолировать эти сервисы от нее.
В конфигурацию контейнера я добавил следующий строки:

lxc.aa_profile: unconfined lxc.cap.drop: mp0: /tank/data,mp=/data mp1: /tank/cloud,mp=/cloud mp2: /tank/docker,mp=/docker

Первые две выдают контейнеру больше прав, так что становится возможным запустить другие конейнеры внутри него, это необходимо для функционирования docker.
Остальные строки подключают необходимые директории к файловой системе гостя.

Внутри контейнера нам необходимо установить docker и docker-compose, а после этого я покажу как у меня все организованно.

В директории /docker у меня созданы директории для каждого отдельного сервиса:

# ls /docker/ deluge  emby nextcloud  nginx-proxy wordpress

В каждой директории лежит отдельный docker-compose.yml файл и данные каждого отдельного контейнера.

К примеру так выглядит docker-compose.yml:

для nginx-proxy и nginx-proxy-companion

nginx-proxy:   restart: on-failure:5   image: jwilder/nginx-proxy:alpine   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   labels:     - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"  nginx-proxy-companion:   restart: on-failure:5   image: jrcs/letsencrypt-nginx-proxy-companion   volumes:     - ./certs:/etc/nginx/certs:rw     - /var/run/docker.sock:/var/run/docker.sock:ro   volumes_from:     - nginx-proxy

Вы можете зайти в директорию с nginx-proxy и выполнив docker-compose up вы проучите готовый запущенный сервис, это очень удобно!

  • Контейнер nginx-proxy в двух словах работает следующим образом, он запускается слушает docker.sock и в случае если обраружит запущенный контейнер с переменной VIRTUAL_HOST, то сгенерирует конфиг для этого виртуального хоста, с проксированием на виртуальный ip контейра.
  • Контейнер nginx-proxy-companion работает схожим образом, если обнаруживает запущенный контейнер с переменной LETSENCRYPT_HOST он автоматически получает для него сертификат.

Для более подробной информации совертую обратиться к официальной страничке проектов:

  • nginx-proxy — который будет автоматически генерировать конфиг и все эти сервисы проксировать.
  • nginx-proxy-companion — будет получать и обновлять сертификаты в автоматическом порядке.

Сразу должен предупредить, nginx-proxy не работает с Compose file version 2, т.к. требует чтобы между контейнерами была одна общая сеть.
Так что необходимо использлвать только Compose file version 1, либо держать все сервисы в одном конфиге.

Теперь сами конфиги:

для WordPress:

mysql:   restart: on-failure:5   image: mariadb:10.0   hostname: mysql   volumes:     - /etc/localtime:/etc/localtime:ro     - ./mysql:/var/lib/mysql   environment:     - MYSQL_ROOT_PASSWORD=seekac7aexoh2eithut6sie1eYaeNgei     - MYSQL_DATABASE=example_org     - MYSQL_USER=example_org     - MYSQL_PASSWORD=imieth7iev4dah6eeraik6Ohz6oiVup7  wordpress:   restart: on-failure:5   image: wordpress   hostname: example.org   volumes:     - /etc/localtime:/etc/localtime:ro     - ./wordpress:/var/www/html   links:     - mysql:mysql   environment:     - "VIRTUAL_HOST=example.org,www.example.org"     - "LETSENCRYPT_HOST=example.org,www.example.org"     - "LETSENCRYPT_EMAIL=admin@example.org"

для Nextcloud:

nextcloud:   restart: on-failure:5   image: nextcloud   hostname: cloud   domainname: example.org   volumes:     - /etc/localtime:/etc/localtime:ro     - ./nextcloud:/var/www/html     - /cloud:/cloud     - /data:/data   links:      - mysql:mysql     - redis:redis   environment:     - "VIRTUAL_HOST=cloud.example.org"     - "LETSENCRYPT_HOST=cloud.example.org"     - "LETSENCRYPT_EMAIL=admin@example.org"  redis:   restart: on-failure:5   image: redis   hostname: redis   volumes:     - /etc/localtime:/etc/localtime:ro  mysql:   restart: on-failure:5   image: mariadb:10.0   hostname: mysql   volumes:     - /etc/localtime:/etc/localtime:ro     - ./mysql:/var/lib/mysql   environment:     - MYSQL_ROOT_PASSWORD=ei8aiWaeDaeDoo8aida0woaNaiy8deer     - MYSQL_DATABASE=nextcloud     - MYSQL_USER=nextcloud     - MYSQL_PASSWORD=rahGhied8lei6ogh2keitie1chaiheex

для Deluge:

deluge:   restart: on-failure:5   image: linuxserver/deluge   hostname: torrent   domainname: example.org   volumes:     - /etc/localtime:/etc/localtime:ro     - ./config:/config     - /data:/data   ports:      - 53160:53160     - 53160:53160/udp     - 8112:8112     - 58846:58846     - 6881:6881   expose:     - 8112   environment:     - PUID=33     - PGID=33     - "VIRTUAL_HOST=torrent.example.org"     - "VIRTUAL_PORT=8112"     - "LETSENCRYPT_HOST=torrent.example.org"     - "LETSENCRYPT_EMAIL=admin@example.org"

для Emby:

emby:   restart: on-failure:5   image: emby/embyserver   volumes:     - /etc/localtime:/etc/localtime:ro     - ./config:/config     - /data:/data   environment:     - APP_UID=33     - APP_GID=33   net: host

Для emby я использлвал net: host — это означает что контейнер будет использовать хостовую сеть вместо виртуальной сети для docker. Этот шаг необходим для работы DLNA-сервера. По той же причине не указанны VIRTUAL_HOST и LETSENCRYPT_HOST переменные.

Но стойте, как же быть? — как добавить такой контейнер к nginx-proxy?
А как быть если я хочу иметь доступ к веб-интерфейсам Proxmox и OpenMediaVault снаружи? — а они запущены вообще не в docker и даже не на этом хосте.

Решение не заставило себя долго искать, для подключений такого типа можно создать еще один отдельный прокси контейнер:

docker-compose.yml

nginx-local:   restart: on-failure:5   image: nginx   expose:     - 80   environment:     - "VIRTUAL_HOST=media.example.org,pve.example.org,nas.example.org"     - "LETSENCRYPT_HOST=media.example.org,pve.example.org,nas.example.org"     - "LETSENCRYPT_EMAIL=admin@example.org"   volumes:     - ./local-config:/etc/nginx/conf.d

С таким конфигом:

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 off; # 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; }  # media.example.org server {         server_name media.example.org;         listen 80 ;         location / {                 proxy_pass http://192.168.225.20:8096/;         } }  # pve.example.org server {         server_name pve.example.org;         listen 80 ;         location / {                 proxy_pass https://192.168.225.10:8006/;         } }  # nas.example.org server {         server_name nas.example.org;         listen 80 ;         location / {                 proxy_pass http://192.168.225.10:8080/;         } }

На этом все, спасибо за внимание и удачи в экспериментах 🙂

ссылка на оригинал статьи https://habrahabr.ru/post/328048/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *