6 мая 2017

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

Настройка LinuxСистемное администрирование*nixВиртуализацияХранение данных


Астрологи объявили месяц статей о домашних 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.


После установки, не забудьте прописать pve-no-subscription для репозитория Proxmox, чтобы иметь возможность устанавливать из него пакеты.


cat /etc/apt/sources.list.d/pve-enterprise.list 
deb http://download.proxmox.com/debian jessie pve-no-subscription

Установка 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-essential

Скачаем исходники 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.
Также необходимо удалить требование версии для doxygen:


vim debian/control
# remove: watchdog
# remove version: doxygen (>= 1.8.9.1)

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


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.
Остальные строки подключают необходимые директории к файловой системе гостя.


Стоит обратить ваше внимание на то, что если внутри подключаемых в контейнер zfs-датасторов вы имеете другие, то их так же необходимо добавить в конфигурацию контейнера, иначе рискуете получить несколько неприятных багов. Приведу пример:


mp0: /tank/data,mp=/data
mp3: /tank/data/Music,mp=/data/Music
mp4: /tank/data/Pictures,mp=/data/Pictures

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


Docker


В директории /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.100.20:8096/;
        }
}

# pve.example.org
server {
        server_name pve.example.org;
        listen 80 ;
        location / {
                proxy_pass https://192.168.100.10:8006/;
        }
}

# nas.example.org
server {
        server_name nas.example.org;
        listen 80 ;
        location / {
                proxy_pass http://192.168.100.10:8080/;
        }
}

На этом все, теперь у вас есть NAS с виртуализацией и несколько отличных сервисов, защищенных SSL по последнему писку моды:


  • https://example.org
  • https://cloud.example.org
  • https://torrent.example.org
  • https://media.example.org
  • https://nas.example.org
  • https://pve.example.org

Спасибо за внимание и удачи в экспериментах :)

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
А у вас дома есть NAS? Какую систему используете?
2.05% FreeNAS 9 7
4.68% FreeNAS 10 16
19.88% OpenMediaVault 68
8.19% NAS4Free 28
12.28% Synology 42
4.09% QNAP 14
19.59% Обычный дистрибутив с вручную настроенными демонами 67
4.09% Другая / свободная 14
5.56% Другая / проприетарная 19
17.54% Нет 60
2.05% Любой дистрибутив и Docker 7
Проголосовали 342 пользователя. Воздержались 128 пользователей.
Теги:proxmoxopenmediavaultnasdockerdocker-composenginxproxmox 4proxmox veembydelugenextcloudunixlinuxхранилищеzfszfsonlinuxkvmlxcletsencryptfreenasfreenas 10; обзор софтаopen sourcesslssl сертификаты
Хабы: Настройка Linux Системное администрирование *nix Виртуализация Хранение данных
+18
55,2k 242
Комментарии 54
Лучшие публикации за сутки