Часть 1. Выбор ЭВМ и компонентов
Основные требования к домашнему серверу были компактность и низкое энергопотребление. В качестве ЭВМ я рассматривал разные одноплатники, даже раздумывал насчёт одноплатников на х64 архитектуре. Основными критериями поиска были избыточное ОЗУ от 8 Гб, современные порты: усб3.0 и гигабитный лан. Идея была заколхозить всё это на болтах в какой-нибудь коробке типа миниАТХ, используя усб-сата интерфейсы для жёстких дисков. Мне такая реализация совершенно не импонировала эстетически, и я не торопился её воплощать. Как вдруг я наткнулся на НАС кит для 4ой малины от китайцев из Радха.
Как я понял, сам сата хэт уже был представлен некоторое время назад и даже весьма быстро распродан ограниченным тиражом. Но в этот раз китайцы предлагали в том числе и коробку. Вся конструкция выглядела весьма компактно и настолько симпатично, насколько бы мои не очень ровные руки никогда не смогли бы это сами сделать. Я погуглил эту коробку, нашёл один проплаченный обзор на ютубе и меня это, в принципе, устроило. Решил долго не думать, потому что, скорее всего партию быстро распродадут, да и по акции блок питания давали бесплатно. Коробка с сата хэтом с экспресс доставкой из Шэньчжэня мне обошлась в €125.23 на момент покупки. Выбор коробки автоматически сузил выбор ЭВМ до 4ой малины, которую я приобрёл на амазоне за €79,97 за модель с 8 Гб ОЗУ. Так же на амазоне были приобретены 2 жёстких диска ВД 2,5” 2 ТБ по €63,81 за каждый, и сд карточка Самсунг ЭВО 120 за €15,25 на алиэкспрессе. Итого €348,07, я подумал, что читателю будет интересен финансовый вопрос.
Всё это добро собирается очень просто, дорогие китайские товарищи обо всём позаботились, пример можно видеть на представленном ниже изображении. Также я записал пару коротких видео собранного девайса. Из приятных моментов, о которых я был не в курсе на момент заказа девайса:
- корпус сделан из цельного куска металла, покрашенного снаружи белой краской;
- днище с отверстиями для вентиляции тоже металлическое;
- крепёжные винтики и гаечки: металл (не металлическая только верхняя пластиковая полупрозрачная крышка с отверстиями для большого вентилятора);
- сата хэт следующей ревизии, а не той, что была у влоггера на ютубе, и имеет разъём для подключения батарейки;
- маленький олед экран выводит инфу о состоянии системы;
- большой вентилятор и олед экранчик работают посредством установки софта от Радха, который представляет собой питоньи скрипты, и устанавливается вводом одной команды в терминале.
Верхний вентилятор по умолчанию имеет 4 режима работы в зависимости от температуры процессора, которые отличаются разной интенсивностью вращения и издаваемого шума: на уровне 1 почти не слышно, уровень 2 слышно, 3-4 – слышно слишком хорошо. За это, собственно, и отвечают питоньи скрипты.
В целом я оказался доволен данным девайсом, но у меня появилось одно замечание. В комплекте используется ходовой олед экранчик, который можно легко заказать на алишечке, но экранчик припаян к плате, китайцам ничего не стоило использовать FPC/FCC коннектор на плате. Это бы сильно упростило замену олед экранчика в случае его выгорания, например.
Часть 2. Питоньи скрипты от Радха
Что ж, всё собрано, приступим к настройке софта. Я не буду флудить копипасту, поэтому общие моменты будут представлены ссылками на хауту из поисковой строки, некоторые пропущу, а вот на подводных камешках можно остановиться подробнее.
Я выбрал ОС ubuntu server 20.04.1, прекрасный гайд по установке написали сами Каноникл. Следом устанавливаем софт от Радха по их ману. Тут возник подводный камешек номер 1. Дело в том, что для определённых торрентокачательных нужд мне нужно было использовать ВПН, но мой впн провайдер не поддерживает ИПв6. Когда я настроил опенвпн под мой провайдер, я обнаружил, что моя анонимность, скажем так, протекает именно через ИПв6. Ну ладно, на системном уровне ИПв6 в убунту отключается весьма просто.
$ sudo nano /etc/sysctl.conf
и добавить туда следующее
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1
Применить эти настройки:
$ sudo sysctl -p
А затем сделать так, чтобы после перезагрузки ипв6 не работал, для чего создаётся файл:
$ sudo nano /etc/rc.local
Который заполняется следующим содержимым:
#!/bin/bash
# /etc/rc.local
/etc/sysctl.d
/etc/init.d/procps restart
exit 0
Далее файлу даются нужные права и всё:
$ sudo chmod 755 /etc/rc.local
Но тут случилось непредвиденное, большой вентилятор из коробки перестал работать вообще.
Исключив возможность хардварной поломки, я стал искать причину софтверную. Вывод состояния сервиса rockpi-sata показывал ошибки относящиеся к питоньему скрипту fan.py:
ubuntu@ubuntu:~$ sudo service rockpi-sata status
? rockpi-sata.service - Rockpi SATA Hat
Loaded: loaded (/lib/systemd/system/rockpi-sata.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2020-12-25 17:16:07 CET; 11min ago
Main PID: 1879 (python3)
Tasks: 4 (limit: 9252)
CGroup: /system.slice/rockpi-sata.service
+-1879 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on
+-2896 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on
+-2897 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on
L-2898 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on
Dec 25 17:16:57 ubuntu python3[2899]: self._target(*self._args, **self._kwargs)
Dec 25 17:16:57 ubuntu python3[2899]: File “/usr/bin/rockpi-sata/fan.py”, line 81, in running
Dec 25 17:16:57 ubuntu python3[2899]: change_dc(get_dc())
Dec 25 17:16:57 ubuntu python3[2899]: File “/usr/bin/rockpi-sata/fan.py”, line 75, in change_dc
Dec 25 17:16:57 ubuntu python3[2899]: gpio.hardware_PWM(12, 25000, dc * 10000)
Dec 25 17:16:57 ubuntu python3[2899]: File “/usr/local/lib/python3.8/dist-packages/pigpio.py”, line 2044, in hardware_PWM
Dec 25 17:16:57 ubuntu python3[2899]: return _u2i(_pigpio_command_ext(
Dec 25 17:16:57 ubuntu python3[2899]: File “/usr/local/lib/python3.8/dist-packages/pigpio.py”, line 1062, in _pigpio_command_ext
Dec 25 17:16:57 ubuntu python3[2899]: sl.s.sendall(ext)
Dec 25 17:16:57 ubuntu python3[2899]: AttributeError: ‘NoneType’ object has no attribute ‘sendall’
Который не представляет из себя ничего интересного за исключением метода инициализации GPIO. Для этого там написан целый класс:
class MockPigpio:
@classmethod
def pi(cls):
try:
host = misc.check_output("netstat -l | grep -o '\S*:8888' | tr -d ':8888'")
gpio = pigpio.pi(host=host)
except Exception:
gpio = cls()
return gpio
def __init__(self):
syslog.syslog('PWM of pigpio is not available. Use on/off to control the fan.')
syslog.syslog('If you use pre-release kernel, please go back to stable release.')
def hardware_PWM(self, pin, _, dc):
misc.set_mode(pin, bool(dc))
gpio = MockPigpio.pi()
Меня заинтересовало, что же это за значение, используемое для инициализации хоста, которое выводит команда netstat -l | grep -o '\S*:8888' | tr -d ':8888'?
ipv6-localhost
Если ИПв6 отключен, то команда выводит пустую строку, и скрипт не работает. Признаться, я сначала пошёл долгим путём. Я заглянул в питоний модуль pigpio.py, в котором инициализация хоста была подробно описана, узнал, что, в принципе, методу pigpio.pi() не нужен никакой аргумент. Безуспешно попробовав варианты вызова этого метода без аргумента, с аргументом lcoalhost и ещё вариантами, которых я уже не помню, внутри скрипта fan.py, я понял, что я таки не умнее авторов, и пошёл лёгким путём. Дело в том, что модуль PIGPIO можно вызывать в ИПв4 режиме для этого нужно только отредактировать один файлик:
$ sudo nano /lib/systemd/system/pigpiod.service
И исправить параметр ExecStart на следующее значение
ExecStart=/usr/local/bin/pigpiod -l -m -n 127.0.0.1 -p 8888
Теперь команда netstat -l | grep -o '\S*:8888' | tr -d ':8888' выводит:
localhost
и вентилятор работает!
Часть 3. Разделяем трафики
Далее были настроены рейд типа 1, самба, опенвпн, трансмишн демон и килсвич на уфв. Описание этих процедур, я думаю рядовой читатель способен выгуглить самостоятельно.
Производительность полученного устройства в принципе норм. Хоть я и не понимаю откуда просадки скорости при копировании. Вот пример копирования папочки содержащей 39 эпизодов анимэ общим размером около 40 Гб.
А вот это пример загрузки одного крупного файла.
Видно, что система может использовать ресурс гигабитной сети полностью, когда захочет. С просадками в скорости копирования я пока что не разбирался.
Второй подводный камешек не относится к сата хэту, а, собственно, к линукс серверу, как объекту материальной культуры. Задача состояла в том, что сервер используется для разных задач: там будут стоять веб-сервер (облако), на который я буду стучаться снаружи, и невозбранный качатель битового потока через впн. Проблема оказалась в том, что трафик мне нужно было как-то разделить, чтобы всё работало параллельно. Моя первая мысль была настроить фаервол. Я использовал следующие правила:
$ sudo ufw default deny incoming
$ sudo ufw default deny outgoing
$ sudo ufw allow in on eth0 from 192.168.178.1
$ sudo ufw allow out on eth0 to 192.168.178.1
$ sudo ufw allow in on eth0 from 192.168.178.20
$ sudo ufw allow out on eth0 to 192.168.178.20
$ sudo ufw allow in on eth0 from any to any port 22,443 proto tcp
$ sudo ufw allow out on eth0 from any to any port 22,443 proto tcp
$ sudo ufw allow in on eth0 from any to any port 1194 proto udp
$ sudo ufw allow out on eth0 from any to any port 1194 proto udp
$ sudo ufw allow out on tun0 from any to any
$ sudo ufw allow in on tun0 from any to any
Наивно полагая, что всё будет прекрасно работать. Задумка была, что, может, файервол заредиректит все соединения через тун0, кроме некоторых через эз0, которые я использую в локальной сети, и пары портов, которые мне нужны чтобы стучаться на сервер снаружи. Данный конфиг работает прекрасно в локальной сети или если впн выключен: никакие соединения кроме разрешённых не проходят. При включённом впн установить соединение снаружи невозможно. Пакеты приходят, но ответы не редиректятся через эз0, а всё равно прут через тун0. Я потратил 2 дня но так и не разобрался, как это починить, и тогда я решил попробовать докер, благо нужный мне контейнер уже имеется.
Это был мой первый опыт работы с докером. Мне было сложно, я не понимал с чего начать, в чём разница между docker и docker-compose, что из себя представляет содержимое гита из ссылки, что такое образ, что такое контейнер, я до сих пор не понимаю как мне удалось сбилдить этот контейнер локально и что докер-композ выкачивал из интернета, но эта штука заработала.
После распаковки репозитория нужно отредактировать файлик docker-compose.yml. И изменить его содержание на:
version: '2'
services:
transmission:
image: haugene/transmission-openvpn
container_name: vpntrans
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun
restart: always
ports:
- "9092:9091"
dns:
- 8.8.8.8
- 8.8.4.4
# sysctls:
- net.ipv6.conf.all.disable_ipv6=1
volumes:
- /etc/localtime:/etc/localtime:ro
- /mnt/raid0/downloads/:/data
environment:
- OPENVPN_PROVIDER=SURFSHARK
- OPENVPN_CONFIG=mk-skp_udp
- OPENVPN_USERNAME=*your username*
- OPENVPN_PASSWORD=*your password*
- OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60
- LOCAL_NETWORK=192.168.178.0/24
# proxy:
- WEBPROXY_ENABLED=false
- TRANSMISSION_PORT_FORWARDING_ENABLED=true
- TRANSMISSION_PEER_PORT=51413
- PUID=1000
- PGID=100
В данном конфиге, если вы захотите его использовать для своих нужд, вам придётся обратить внимание на значения внешнего (для контейнера) порта, путь к вашему тому, в который трансмишн демон будет сохранять данные, и где можно будет отредактировать его настройки, ввести параметры вашей локальной сети. Так же вам надо будет настроить ваш впн провайдер из списка. Я использую сёрфшарк, значение параметра OPENVPN_CONFIG определяет выбор конфигурационного (собственно, это значение и есть имя нужного конфиг файла) *.ovpn файла конкретного сервера, к которому вы хотите подключаться. В этом примере выбран сервер в Республике Северная Македония.
Далее билдим и запускаем контейнер с нашими настройками:
$ sudo docker-compose up
Если всё пройдёт штатно, вы увидите в конце лог клиента опенвпн об успешном установлении соединения. Ну или нет, мало ли вы пользуетесь другим впн провайдером, который требует дополнительных человекочасов. Но если всё норм, можно нажать кнтрл-с и запустить контейнер как процесс в фоне. К слову, контейнер уже умеет сам стартовать при запуске системы и перезапускаться в случае ошибки.
$ sudo docker start vpntrans
Чтобы унять параною можно зайти в консоль внутри контейнера:
$ sudo docker exec -ti vpntrans /bin/bash
И проверить публичный ип-адрес:
$ curl ifconfig.co/json
Если всё прошло успешно, вывод должен быть вот таким:
Тем не менее такой тест малополезен для успокоения сильно раскачанной паранойи, поэтому я воспользовался шаркой и смотрел соединения в процессе загрузки торрента с каким-нибудь популярным линукс-дистрибутивом, скажем, убунтой. Исключив из выдачи не относящиеся к делу соединения с устройствами в локальной сети, впн сервером, а также некоторые автоматические бродкасты, за время загрузки образа убунты не произошло ничего подозрительного:
sudo tshark -i eth0 | grep -v "192.168.178.1" | grep -v "192.168.178.20" | grep -v "185.225.28.109" | grep -v "AVMAudio" | grep -v "SSDP" | grep -v "MDNS" | grep -v "LLMNR"
Но что будет если опенвпн потеряет соединение или сервис внезапно остановится? Внутри контейнера работает утилита top, её вывод выглядит примерно так:
Убьём процесс опенвпн:
$ kill -9 6
После этого контейнер перезапустился. Я потом где-то вычитал на форумах, что контейнер настроен таким образом, что если теряется соединение с опенвпн или этот процесс завершается, то контейнер просто перезапускается. Такой вот килсвич. Я остался доволен.
Часть 4. Облако
Я выбрал облако Некстклауд и устанавливал его по одному гайду. Основное отличие моей установки в том, что я использовал другие репы для апача и пхп:
$ sudo add-apt-repository ppa:ondrej/apache2
$ sudo add-apt-repository ppa:ondrej/php
После конфигурации некстклауда рекомендую проверить в админке предупреждения и пофиксить их.
$ cd /var/www/nextcloud/
$ sudo -u www-data php occ db:add-missing-indices
Так же у меня отсутствовала пара модулей пхп:
$ sudo apt install php-bcmath php-imagick
А затем система предлагала включить кэш, который улучшает производительность системы. Я где-то на форумах нашёл последовательность действий, но ссылочку не сохранил, поэтому приведу краткое описание данной процедуры. Для кэша нужно установить несколько утилит:
$ sudo apt install redis-server php-memcached memcached php-apcu -y
Запустить несколько сервисов:
$ sudo systemctl start redis-server
$ sudo systemctl enable redis-server
$ sudo systemctl start memcached
$ sudo systemctl enable memcached
Настроить систему редис в паре конфигов:
$ sudo nano /etc/redis/redis.conf
и исправить там следующие значения:
port 0
unixsocket /var/run/redis/redis.sock
unixsocketperm 700
Дать нужные права:
$ sudo usermod -aG redis www-data
Подправить конфиг некстклауда, чтобы он пользовался редисом:
$ sudo nano /var/www/nextcloud/config/config.php
Вставить следующее содержимое перед последними символами );
'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' =>
array (
'host' => '/var/run/redis/redis.sock',
'port' => 0,
'timeout' => 0,
'password' => '',
'dbindex' => 0,
),
Исправить следующие параметры в конфиге апача:
$ sudo nano /etc/php/7.4/apache2/php.ini
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1
И перезапустить апач:
$ sudo systemctl restart apache2
Облако теоретически можно подключить как сетевой диск по ВебДАВ, но почему-то не в виндовс 10. С использованием утилиты Cyberduck я протестировал работу облака в локальной сети. Как видно на скриншотах ниже, скорости на загрузку в облако достигают приемлимых 12 МБ/с, а загрузки из облака приличных 35 МБ/с. Данные скорости получены при включённом шифровании в облаке с ключом рса4096.
Часть 5. Энергопотребление
Изначально я хотел дать этому серверу поработать недельку, чтобы с использованием счётчика мощности привести статистику. Но, к сожалению, я не разобрался, как правильно настроить этот счётчик мощности, поэтому я приведу изображение с данными с индикатора. Как видно, в режиме простоя система потребляет 8.5 Вт энергии, а в моменты активной синхронизации с облаком (папка с личными данными размером около 200 Гб) до 16.88 Вт. Подробная статистика позволила бы рассчитать среднее значение потребляемой мощности в день, но за её отсутствием и из расчёта, что большую часть времени сервер простаивает, я на вскидку принимаю 10 Вт за усреднённое значение потребляемой мощности, что в месяц даёт:
При текущих ценах в €0,31 за 1 кВт*ч, сумма расходов на содержание сервера в месяц составит около €2,23, что не должно сильно отразиться на моём среднем потреблении энергии.
Коль с потреблением и расходами разобрались, то я предлагаю провести небольшую оценку финансовых вложений и сравнить с предложениями виртуальных серверов на рынке. К сожалению, равнозначного сравнения у меня не вышло, потому что, как я понял, рынок виртуальных серверов предлагает либо производительные серверы, либо серверы для хранения данных. Предположим, что полученный домашний сервер по производительности сравним с серверами для хранения данных и проанализируем текущие цены. Как видно по ссылке, аренда сервера с 2 Тб дискового пространства будет стоить €100 в год. Годовой счёт за электричество моего домашнего мини-сервера на 4ой малине должен обойтись примерно в €27,16. При потраченных €348,07, получается что окупаемость домашнего сервера займёт:
Что долго, и читатель в принципе будет прав решив, что оно того не стоит.
Давайте рассмотрим ещё один вариант с апгрейдом до 4 Тб дискового пространства. В случае домашнего сервера я бы прикупил дополнительные 2 диска по 2 Тб, что в текущих ценах на амазоне составит дополнительные €127,62. Потребление сервера должно будет вырасти и, предположим, в среднем составит 18 Вт. Это даст годовой счёт электроэнергии уже в €48,88. Теперь сравним со стоимостью сервера хранения на 4 Тб (€340 в год) и оценим окупаемость:
Что недолго, и уже не выглядит противоречивым вложением средств.
Заключение
В данном посте мы узнали про замечательный сата хэт для 4ой малины и про симпатичный кит на его основе для домашнего сервера. Мы посмотрели производительность этой системы на примере копирования файлов по сети, а также производительность запущенного на этом сервере облака Некстклауд. Вопросы энергопотребления, стоимости и расходов на данный сервер так же не оставлены в стороне. Благодарю за прочтение этого материала. Критические замечания по поводу представленных решений приветствуются.
В частности я бы хотел попросить читателя поделиться опытом в следующих вопросах:
- ZFS?
- Просадки скорости копирования по сети, что с этим делать?
- Апач или всё таки нгинкс?
- Какой упс выбрать?
- Почему докер обходит правила впн?
DustCn
Вентилятор с зависимостью от TCP/IP стека — это пять. Жалко что не доковырял…