Свое облако на одноплатном компьютере Banana pi W2 (Nextcloud+Nginx+mdadm)

Мой первый пост, прошу сильно не пинать =)

Предыстория

Когда-то в мои руки попал старенький HP Microserver N36L, и я не придумал ничего лучше, как запилить туда Nextcloud c ONLYOFFICE в связке через docker. Раз корзина большая — добавил торрентокачалку и PLEX

микросервер имеет всего 2 вентиля (один 120 мм на выдув горячего воздуха от дисков и один махонький в блоке питания) но все равно донимал тем, что в комнате, где он стоит — спать невозможно. Да и энергии он все же поджирал, что заставляло задуматься о его целеообразности, если учесть цены на терабайт облачного хранилища в 2018 году. Правда после того, как известный надоедливый желтый поисковик заблокировал мне учетку с диском, деньгами и прочим и требовал фотку паспорта в обмен на данные — я понял, что личное облако все же необходимо.

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

В тот момент я уже слышал о малинке и об аналогах, но меня смущала скорость работы данных устройств в качестве хранилища.

Хотелось устройство с пассивным охлаждением, малым потреблением, наличием emmc, в идеале двух sata, ну или на край usb 3.0. гигабитную сетку, чтобы все быстро летало по локалке

Ежемесячно сканируя список аналогов малинки я наткнулся на основу для своего будущего минисервера — Bananapi W2

Свое облако на одноплатном компьютере Banana pi W2 (Nextcloud+Nginx+mdadm) Nextcloud, Arm, Banana Pi, Одноплатный компьютер, Длиннопост

Краткие характеристики:

Realtek RTD1296, Quad-core ARM Cortex-A53

2G DDR4 SDRAM

8G eMMC flash

2 port 10/100/1000 Mb Ethernet port

support 2 SATA III interface

M.2 KEY B

Бинго! - подумал я, и отключив мозг сразу же заказал в известном китайском магазине.

Сразу же заказал еще 2 удлинителя для sata

Спустя месяц комплект пришел ко мне и я сразу же начал с ним ковыряться. И началось….

Недостатки решения одноплатника

Сразу опишу те минусы, с которыми мне пришлось столкнуться:

1. Отсутствие корпуса. Сначала плата жила просто в родной коробке, в которой были вырезаны отверстия для вентиляции и под разъемы, сейчас плата в франкенкорпусе из металлических пластин с резиновыми проставками для гашения вибраций дисков

2. Отсутствие поддержки производителя — сопровождения нет, мертвый продукт без выпуска новых систем. Обидно, но для меня не смертельно. Потратил много времени и сил. Что и сподвигло на написание данной статьи, может кому то поможет. В итоге, по данной инструкции  все сделать можно очень быстро, о чем ниже

3. Как следствие от предыдущего — отсутствие аксессуаров (того же корпуса — 1 вид и все)

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

Проблему с охлаждением это решило, радиатор был просто положен сверху на процессор, что уменьшило температуру в простое до 56 градусов, термопрокладка еще едет

В качестве питания изначально использовал блок 12 V/2А, позже пришлось заменить на 12v/5A, чтобы запитать 2 жестких диска 3.5

Дальше стандартными методами был развернут оригинальный образ с сайта производителя на флешку, флешка вставлена в плату и началось знакомство. Первым делом при установке докера падал apt. просто все зависало на настройке docker-ce и все, больше ничего сделать нельзя. Перепробовал все linux-образы — одна фигня. Пока искал решение — наткнулся на следующую проблему — mdadm тоже не работает!

Ответ я нашел на сайте 4pda – в ядре просто нет поддержки рейда и даже дано объяснение, как собрать свое собственное ядро.

Долго ковырялся, в итоге все сделал и пишу теперь этот сумбурный мануал.

Итого, как запилить Nextcloud на Banana pi W2

1. Готовим образ

2. Собираем RAID 1

3. Ставим Nginx+Mysql+php-fpm

4. Ставим Nextcloud

5. Покупаем домен и ставим сертификат SSL

6. Немного напильника

Выглядит немного жутковато, но на деле займет минут 20, учитывая, что первый шаг можно пропустить.

1. Подготовка образа

(Для тех, кто торопится или просто не хочет во все это вникать — собранный образ внизу пункта)

Для сборки образа нам потребуется отдельный пк с линуксом, или виртуальная машина. В моем случае это был отдельный системник с ubuntu 18.04

Некоторые команды потребуют sudo, но раз вы не пролистали в конец пункта за готовым образом — то вы, наверное, уже знаете, что такое sudo. Я, как чайник, ввел sudo -s и дальше выполнял все от рута

Чтобы в процессе сборки ядра не возникали ошибки — необходимо подготовить систему (может не понадобится, но на ubuntu 18.04 возникали ошибки)

apt install build-essential
apt install libncurses5-dev libncursesw5-dev

Далее ставим необходимые для сборки программы

apt-get install git pv bc

После

git clone git://github.com/BPI-SINOVOIP/BPI-W2-bsp
cd BPI-W2-bsp
./build.sh

Появляется меню, тут выбираем пункт 4

Свое облако на одноплатном компьютере Banana pi W2 (Nextcloud+Nginx+mdadm) Nextcloud, Arm, Banana Pi, Одноплатный компьютер, Длиннопост
Свое облако на одноплатном компьютере Banana pi W2 (Nextcloud+Nginx+mdadm) Nextcloud, Arm, Banana Pi, Одноплатный компьютер, Длиннопост

Появляется подобное меню

Нажимаем «/» для поиска, набираем RAID, смотрим результат. Видим, что нужный нам пункт находится по пути Device Drivers – Multiple devices driver support

Нажимаем Exit, проходим по данному пути

Убеждаемся, что RAID Support стоит звездочка. Если нет — на данном пункте нажимаем пробел, пока не появится *

Убираем звездочку с пункта Autodetect RAID arrays during kernel boot – с ней возникают проблемы, работает криво и требует создания массива с метадата 0.90, а текущая версия 1.2. Обойдемся без нее.

Дальше стрелкой вправо перемещаемся на exit и выходим из меню конфигурации, соглашаясь на сохранение конфигурации. Снова запускаем ./build.sh, и выбираем пункт 1

Идем пить чай, минут 10 у вас есть, в зависимости от мощности используемого пк.

После окончания в папке пользователя появляется папка SD, содержимое которой нам и требуется.

Берем SD флешку на 8 гб, заливаем туда образ ubuntu 16.04 с офсайта

Далее подключаем через карт-ридер к компу, где у нас лежит готовая папка SD

Из подпапок BPI-BOOT и BPI-ROOT все файлы перекидываем на нашу SD флешку в те же папки.

SD-карта готова к использованию.

Но в дальнейшем лучше этот образ загнать в emmc, тогда работать будет гораздо быстрее

Пока вставляем карту в плату, запускаем и убеждаемся, что все работает

логин pi, пароль bananapi

делаем sudo apt update && sudo apt upgrade -y

Запросит пароль — bananapi

ждем, пока система обновится

После вытаскиваем карточку, возвращаем в картридер. С помощью lsblk смотрим, как называется устройство с нашей SD картой. В моем случае это /dev/mmcblk0

Вводим команду dd if=/dev/mmcblk0 of=ubuntu_16.04_with_raid.img

Идем пить чай, команда выполняется долго и прогресс свой никак не показывает

После выполнения команды в текущей папке появляется файл ubuntu_16.04_with_raid.img, который мы копируем на какую-нибудь usb, его мы теперь будем раскатывать в память emmc и в будущем он нам может еще пригодиться.

Для тех, кому не хочется все это делать, может связаться со мной и я поделюсь

2. Собираем RAID 1

apt-get install mdadm -y
mdadm --zero-superblock /dev/sataa /dev/satab -f
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sataa1 /dev/satab1
mdadm --detail --scan | tee -a /etc/mdadm/mdadm.conf

смотрим uuid массива, он нам пригодится в будущем

cat /etc/mdadm/mdadm.conf

В самом низу находим UUID= и копируем все, что за ним

создаем файловую систему

mkfs.ext4 /dev/md0

Далее создаем папку, в которую будет монтироваться массив, например /datacloud

mkdir /datacloud

и монтируем массив в данную папку

mount /dev/mdo /datacloud

А пока добавляю в файл /etc/rc.local две строки непосредственно перед exit 0:

mdadm --assemble /dev/md0 --uuid <uuid>

mount /dev/md0 /datacloud

вместо <uuid> вставляем то, что скопировали ранее из mdadm.conf

Перезагружаемся и проверяем, что наш массив смонтировался

Ставим Nginx+Mysql+php-fpm

apt install nginx
systemctl enable nginx
systemctl start nginx

Далее устанавливаем PHP-FPM и остальные необходимые модули - в репозиториях ubuntu только версия 7.2, актуальная версия 7.3:

add-apt-repository ppa:ondrej/php
apt update
apt install php7.3-fpm
apt install php7.3-mysql php7.3 php7.3-curl php7.3-gd php7.3-json php7.3-mbstring php7.3-common php7.3-xml php7.3-zip php7.3-opcache php-apcu php-imagick php7.3-intl

Устанавливаем Mysql

apt install mysql-server

mysql_secure_installation

отказываемся от проверки паролей, задаем пароль root пользователя, отвечаем "Y", два раза вводим пароль, на остальные вопросы отвечаем "Y".

Set root password? [Y/n] y
New password:
... Success!
Remove anonymous users? [Y/n] y
... Success!
Disallow root login remotely? [Y/n] y
... Success!
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y
... Success!

Создаем базу данных для Nextcloud:

mysql -u root -p

Вводим пароль, который только что создали

Вводим данные ниже, не забываем ‘nextclouduser’ 'password' - сменить на свои данные и не забываем их, они нам понадобятся.

CREATE DATABASE nextcloud;
CREATE USER 'nextclouduser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON nextcloud.* TO 'nextclouduser'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

Ставим Nextcloud

Идем в папку, куда будем качать nextcloud

cd /var/www/html/

Скачиваем Nextcloud c официального сайта, копируем адрес ссылки на zip архив:

wget https://download.nextcloud.com/server/releases/nextcloud-18....

распаковываем архив

unzip nextcloud-18.0.4.zip (если не срабатывает — ставим zip - apt install zip и повторяем)
меняем владельца папки
chown -R www-data:www-data nextcloud/

Не забываем удалить архив

rm nextcloud-18.0.4.zip

Покупаем домен и ставим сертификат SSL

Сначала мы отредактируем файл nginx.conf

nano nginx.conf
#Пользователь, от которого будет работать php-fpm
user www-data;
#Число ядер процессора
worker_processes 2;
worker_cpu_affinity auto;
include /etc/nginx/modules-enabled/*.conf;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Следом необходимо приобрести доменное имя. Инструкций об этом полно в интернете, как и регистраторов, поэтому тут я заострять внимания не буду. Так же можно сделать бесплатный домен 3 уровня, для поиграться, но настоятельно рекомендую купить свой, благо домен в зоне .ru стоит 200 рублей в год

Предположим, что у вас есть домен cloud.mydomain.ru, и он уже направлен на ваш ip

создаем конфиг для Nextcloud:

nano /etc/nginx/sites-avaiable/nextcloud.conf

cloud.mydomain.ru необходимо заменить на свои значения

upstream php-handler {
server 127.0.0.1:9000;
# server unix:/var/run/php/php7.3-fpm.sock;
}
server {
listen 80;
listen [::]:80;
server_name cloud.mydomain.ru;
# принудительное использование https
return 301 https://$server_name:443$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name cloud.mydomain.ru;
# ПРИМЕЧАНИЕ: некоторые настройки ниже могут быть избыточными
# Удалить X-Powered-By, который является утечкой информации
fastcgi_hide_header X-Powered-By;
# Путь к корню вашей инсталляции
root /var/www/html/nextcloud;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Следующие 2 правила нужны только для приложения user_webfinger.
# Раскомментируйте, если вы планируете использовать это приложение.
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
# Следующее правило необходимо только для приложения Social.
# Раскомментируйте, если вы планируете использовать это приложение.
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
location = /.well-known/carddav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
# установить максимальный размер загрузки
client_max_body_size 512M;
fastcgi_buffers 64 4K;
# Включите gzip, но не удаляйте заголовки ETag
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json
application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json
application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard
text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
location / {
rewrite ^ /index.php;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS on;
# Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass php-handler;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
# Добавление заголовка управления кэшем для JS, CSS и карта файлов
# Убедитесь , что это НИЖЕ PHP блок
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
# Необязательно: не регистрировать доступ к ресурсам
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg)$ {
try_files $uri /index.php$request_uri;
# Необязательно: не регистрировать доступ к другим ресурсам
access_log off;
}
}

Сохраняем (ctrl+o) и выходим (ctrl+x)

Включаем наш хост

ln -s /etc/nginx/sites-available/nextcloud.conf /etc/nginx/sites-enabled/nextcloud.conf

Делаем сертификат через Let’s Encrypt

Устанавливаем certbot

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx

теперь делаем сертификат

sudo certbot --nginx

Сертификат готов!

Немного напильника

Понадобится отредактировать так же конфигурацию PHP-FPM:

nano /etc/php/7.3/fpm/pool.d/www.conf

Закомментируем строку :

;listen = /run/php/php7.3-fpm.sock

Добавим вместо нее:

listen = 127.0.0.1:9000

Проверяем строки:

listen.owner = www-data
listen.group = www-data

проверяем конфигурацию

nginx -t

Если все хорошо — перезапускаем nginx

service nginx restart

Переходим по адресу нашей бананки, там нас уже приветствует Nextcloud

Заполняем логин администратора и пароль. Я лично этой учетной записью пользуюсь только для настройки, а постоянно использую другую учетную запись

Указываем, где будут храниться данные

/datacloud

Ниже указываем данные. Которые указывали, когда ставили Mysql

nextclouduser

password

nextcloud

localhost

Нажимаем «Завершить настройку»

Переходим в настройки и проверяем ошибки

1. Исправление ошибки php-fpm getenv("PATH")

nano /etc/php/7.3/fpm/pool.d/www.conf

Необходимо раскомментировать строки:

env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
systemctl restart php7.3-fpm

2. Разрешённое PHP максимальное значение использования памяти ниже рекомендуемого значения в 512 МБ

nano /etc/php/7.3/fpm/php.ini
upload_max_filesize = 3500M
memory_limit = 512M

systemctl restart php7.3-fpm

3. Не настроена система кеширования. Для увеличения производительности сервера, по возможности, настройте memcache. Более подробная информация доступна в документации.

nano /var/www/html/nextcloud/config/config.php

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

'memcache.local' => '\\OC\\Memcache\\APCu',
);
systemctl restart nginx

Далее потребуется настроить планировщик заданий

crontab -e -u www-data
no crontab for www-data - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/mcedit
4. /usr/bin/vim.tiny
5. /bin/ed
Choose 1-5 [1]: 1

Добавляем строку

*/15 * * * * php -f /var/www/html/nextcloud/cron.php

в Веб интерфейсе облака переходим в пункт "Основные параметры"В разделе "Фоновые задания" - жмем "Cron"

Создадим задание в планировщике, предложит выбрать редактор, укажите цифру: 1

Радуемся, наше облако готово к работе!

В конце рекомендую создать своего нового пользователя, а пользователя pi отключить

Итоги

Изучив рынок, уже после, хлебнув со всей силы, я понял, что выбора-то особо и нет. В качестве альтернативы Odroid H2 и Gigabyte GA-SBCAP3450

Обе платы х86, что конечно расширяет возможности, но кушают они явно больше, и стоимость в 2 раза выше (я покупал бананку за 6000+ 2 кабеля вышли в 250 рублей) блок питания у меня был, но новый стоит около 400 рублей.

Для х86 плат нужна еще оперативная память и ssd под систему, стоимость все же выйдет гораздо выше. Тут же плата себя и свои деньги отрабатывает