Русский
Русский
English
Статистика
Реклама

Nextcloud

Nextcloud отказоустойчивый деплой для средних компаний

30.11.2020 12:14:44 | Автор: admin


Есть очень крутой комбайн для совместного ведения проектов, LDAP-авторизацией, синхронизацией файлов с версионированием и чем-то вроде корпоративного мессенджера с видеоконференциями, которые прикрутили в последних версиях. Да, я про Nextcloud. С одной стороны, я сторонних Unix-way и четкого дробления приложений по отдельным функциям. С другой этот продукт более чем устойчив, работает много лет в нескольких проектах без особых проблем и дополнительные свистелки особо не мешают ему работать. Если очень хочется, то туда можно прикрутить практически любую дичь. Коммьюнити живое и вполне допиливает различные плагины, которые доступны как отдельные приложения.

Сегодня мы будем его разворачивать. Я не буду давать полной пошаговой инструкции, но постараюсь упомянуть про ключевые моменты архитектуры, на которые стоит обратить внимание. В частности, разберем балансировку нагрузки, репликацию БД и регламентное обслуживание без прерывания сервиса.
Деплоить будем в отказоустойчивом варианте для небольшой компании в 150-1000 пользователей, но для домашних пользователей тоже пригодится.

Что нужно компаниям?


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

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

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

  1. Киллер-фича с предоставлением доступа вовне в рамках федерации. Можно интегрироваться с аналогичным продуктом у коллег и другой компании.
  2. Предоставление доступов вовне по прямой ссылке. Очень помогает, если вы, например, работаете в полиграфии и надо обмениваться с клиентами большими объемами тяжелых данных.
  3. Редактор документов Collabora, который выполняется на стороне сервера и работает как фронтенд к LibreOffice.
  4. Чаты и видеозвонки. Немного спорная, не совсем стабильная функция, но она есть и работает. В последней версии ее уже стабилизировали.

Строим архитектуру


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


Типовой вариант для домашнего использования и единичных инсталляций.

Вариант все в одном неплох до тех пор, пока у вас немного пользователей, а вы можете себе позволить простой на время регламентных работ. Например, во время обновления. Также у монолитной схемы, с размещением на одной ноде есть проблемы с масштабированием. Поэтому, мы попробуем второй вариант.


Масштабируемый вариант деплоя, рекомендованный для более высоких нагрузок.

Основные компоненты системы:

  • 1 Балансировщик. Можете взять HAproxy или Nginx. Я рассмотрю вариант с Nginx.
  • 2-4 штуки Application server (web-server). Сама инсталляция Nextcloud с основным кодом на php.
  • 2 БД. В стандартной рекомендованной конфигурации это MariaDB.
  • NFS-хранилище.
  • Redis для кеширования запросов к БД

Балансировщик


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

Обратите внимание, что балансировщик также является точкой терминирования SSL/TLS для ваших клиентов, а общение с бэкендом может идти как по HTTP для доверенных внутренних сетей, так и с дополнительным HTTPS, если трафик до application-сервера идет по общим недоверенным каналам.

База данных


Типовое решение MySQL/MariaDB в кластерном исполнении в master-slave репликации. При этом у вас активна только одна БД, а вторая работает в режиме горячего резерва на случай аварийного отказа основной или при проведении плановых работ. Можно рассмотреть и вариант с балансировкой нагрузки, но она технически сложнее. При использовании MariaDB Galera Cluster с вариантом master-master репликации нужно использовать нечетное количество нод, но не менее трех. Таким образом минимизируется риск split-brain ситуаций, при рассечении связности между нодами.

Storage


Любое оптимальное для вас решение, которое предоставляет NFS-протокол. В случае высоких нагрузок можно рассмотреть IBM Elastic Storage или Ceph. Также возможно использование S3-совместимого объектного хранилища, но это скорее вариант для особо крупных инсталляций.

HDD или SSD


В принципе, для средних по размеру инсталляций вполне достаточно использования только HDD. Узким участком тут будут iops при чтении из БД, что сильно сказывается на отзывчивости системы, но, при наличии Redis, который кеширует все в RAM, это не будет особой проблемой. Так же часть кеша будет лежать в memcached на application-серверах. Тем не менее, я бы рекомендовал, по возможности, размещать application-сервера на SSD. Веб-интерфейс становится намного отзывчивее по ощущениям. При этом та же синхронизация файлов на десктопных клиентах будет работать примерно так же, как и при использовании HDD для этих узлов.

Скорость синхронизации и отдачи файлов будет определяться уже производительностью вашего NFS-хранилища.

Конфигурируем балансировщик


В качестве примера я приведу простой в базовой конфигурации и эффективный nginx. Да, различные дополнительные failover-плюшки у него доступны только в платной версии, но даже в базовом варианте он отлично выполняет свою задачу. Учтите, что балансировка типа round robin или random нам не подходит, так как application-сервера хранят кеши для конкретных клиентов.
К счастью, это решается использованием метода ip_hash. В таком случае сессии пользователя будут закреплены за конкретным бэкендом, к которому будут направляться все запросы со стороны пользователя. Этот момент описан в документации:
Задаёт для группы метод балансировки нагрузки, при котором запросы распределяются по серверам на основе IP-адресов клиентов. В качестве ключа для хэширования используются первые три октета IPv4-адреса клиента или IPv6-адрес клиента целиком. Метод гарантирует, что запросы одного и того же клиента будут всегда передаваться на один и тот же сервер. Если же этот сервер будет считаться недоступным, то запросы этого клиента будут передаваться на другой сервер. С большой долей вероятности это также будет один и тот же сервер.

К сожалению, при использовании этого метода могут быть проблемы с пользователями, которые находятся за динамическим IP и постоянно его меняют. Например, на клиентах с мобильным интернетом, которых может кидать по разным маршрутам при переключении между сотами. sticky cookie, который решает эту проблему доступен только в платной версии.

В конфигурационном файле nginx это описывается следующим образом:

upstream backend {    ip_hash;    server backend1_nextcloud.example.com;    server backend2_nextcloud.example.com;    server backend3_nextcloud.example.com;    server backend4_nextcloud.example.com;}

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

upstream backend {    ip_hash;    server backend1_nextcloud.example.com weight=3;    server backend2_nextcloud.example.com;    server backend3_nextcloud.example.com;}

В приведенном примере из 5 пришедших запросов 3 уйдут на backend1, 1 на backend2 и 1 на backend3.

В случае, если один из application-серверов откажет, nginx попробует переадресовать запрос следующему серверу из списка бэкендов.

Конфигурируем БД


Подробно Master-Slave конфигурацию можно посмотреть в основной документации.

Разберем несколько ключевых моментов. Для начала создаем пользователя для репликации данных:

create user 'replicant'@'%' identified by 'replicant_password';grant replication slave on *.* to replicant;flush privileges;

Затем правим конфиг мастера:

sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf 

В районе блока Logging and Replication вносим нужные правки:

[mysqld]log-bin         = /var/log/mysql/master-binlog-bin-index   = /var/log/mysql/master-bin.indexbinlog_format   = mixedserver-id       = 01replicate-do-db = nextcloudbind-address = 192.168.0.6

На Slave конфигурируем конфиг:

sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf 

В районе блока Logging and Replication вносим нужные правки:

    [mysqld]    server-id       = 02    relay-log-index = /var/log/mysql/slave-relay-bin.index    relay-log       = /var/log/mysql/slave-relay-bin    replicate-do-db = nextcloud    read-only = 1    bind-address    = 192.168.0.7

Перезапускаем оба сервера:

sudo systemctl restart mariadb

Далее надо будет скопировать БД на Slave.
На Master выполняем для начала выполняем блокировку таблиц:

flush tables with read lock;

А затем смотрим статус:

    MariaDB [(none)]> show master status;    +-------------------+----------+--------------+------------------+    | File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |    +-------------------+----------+--------------+------------------+    | master-bin.000001 |      772 |              |                  |    +-------------------+----------+--------------+------------------+    1 row in set (0.000 sec)

Не выходим из консоли БД, иначе блокировки снимутся!
Нам понадобится отсюда master_log_file и master_log_pos для конфигурации Slave.
Делаем дамп и снимаем блокировки:

sudo mysqldump -u root nextcloud > nextcloud.sql

    > unlock tables;    > exit;

Затем на Slave импортируем дамп и рестартуем демон:

sudo mysqldump -u root nextcloud < nextcloud.sqlsudo systemctl restart mariadb

После этого в консоли настраиваем репликацию:

    MariaDB [(none)]> change master 'master01' to         master_host='192.168.0.6',         master_user='replicant',         master_password='replicant_password',         master_port=3306,         master_log_file='master-bin.000001',         master_log_pos=772,         master_connect_retry=10,         master_use_gtid=slave_pos;

Запускаем и проверяем:

> start slave 'master01';show slave 'master01' status\G;

В ответе не должно быть ошибок и два пункта укажут на успешность процедуры:

Slave_IO_Running: YesSlave_SQL_Running: Yes

Деплоим Application ноды


Есть несколько вариантов деплоя:

  1. snap
  2. docker-image
  3. ручное обновление

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

Да, там есть каналы подписки, а мажорные релизы, по идее он не должен переключать, но все же подумайте. Я бы рекомендовал полный контроль за процессом обновления, тем более, что нередко он сопровождается изменением структуры данных в БД.

Docker-image хороший вариант, особенно, если у вас часть инфраструктуры крутится уже на Kubernetes. Та же нода Redis, скорее всего уедет в кластер следом за application-серверами.

Если у вас нет инфраструктуры для этого, то ручное обновление и развертывание из tar.gz вполне удобно и контролируемо.

Не забудьте, что на application-сервера вам потребуется установить веб-сервер для обработки входящих запросов. Я бы рекомендовал связку из nginx + php-fpm7.4. С последними версиями php-fmp ощутимо выросло быстродействие и отзывчивость.

онфигурирование SSL/TLS


Однозначно стоит рассчитывать на TLS 1.3, если вы делаете новую инсталляцию и нет проблем с пакетами nginx, которые зависят от свежести системного openssl. В частности, 0-RTT и другие плюшки позволяют временами ощутимо ускорить повторное подключение клиентов за счет кеширования. Безопасность также выше за счет выпиливания устаревших протоколов.

Приведу актуальный конфиг для nginx application-сервера, который находится общается с балансировщиком по TLS:
Конфиг nginx
upstream php-handler { server unix:/var/run/php/php7.4-fpm.sock;}server {    listen 80;    server_name backend1_nextcloud.example.com;    # enforce https    root /var/www/nextcloud/;    return 301 https://$server_name$request_uri;}server {    listen 443 ssl http2;    ssl_early_data on;#    listen [::]:443 ssl http2;    server_name backend1_nextcloud.example.com;    # Path to the root of your installation    root /var/www/nextcloud/;    # Log path    access_log /var/log/nginx/nextcloud.nginx-access.log;    error_log /var/log/nginx/nextcloud.nginx-error.log;    ### SSL CONFIGURATION ###        ssl_certificate /etc/letsencrypt/live/backend1_nextcloud.example.com/fullchain.pem;        ssl_certificate_key /etc/letsencrypt/live/backend1_nextcloud.example.com/privkey.pem;        ssl_trusted_certificate /etc/letsencrypt/live/backend1_nextcloud.example.com/fullchain.pem;        ssl_dhparam /etc/ssl/certs/dhparam.pem;        ssl_protocols TLSv1.2 TLSv1.3;        ssl_prefer_server_ciphers on;        #ssl_ciphers "EECDH+AESGCM:EECDH+CHACHA20:EECDH+AES256:!AES128";        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POL>        ssl_session_cache shared:SSL:50m;        ssl_session_timeout 5m;        ssl_stapling on;        ssl_stapling_verify on;        resolver 8.8.4.4 8.8.8.8;        add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains; preload' always;### КОНЕЦ КОНФИГУРАЦИИ SSL ###    # Add headers to serve security related headers    # Before enabling Strict-Transport-Security headers please read into this    # topic first.    # add_header Strict-Transport-Security "max-age=15768000;    # includeSubDomains; preload;";    #    # WARNING: Only add the preload option once you read about    # the consequences in https://hstspreload.org/. This option    # will add the domain to a hardcoded list that is shipped    # in all major browsers and getting removed from this list    # could take several months.    add_header Referrer-Policy "no-referrer" always;    add_header X-Content-Type-Options "nosniff" always;    add_header X-Download-Options "noopen" always;    add_header X-Frame-Options "SAMEORIGIN" always;    add_header X-Permitted-Cross-Domain-Policies "none" always;    add_header X-Robots-Tag "none" always;    add_header X-XSS-Protection "1; mode=block" always;    # Remove X-Powered-By, which is an information leak    fastcgi_hide_header X-Powered-By;    location = /robots.txt {        allow all;        log_not_found off;        access_log off;    }    # The following 2 rules are only needed for the user_webfinger app.    # Uncomment it if you're planning to use this app.    #rewrite ^/.well-known/host-meta /public.php?service=host-meta last;    #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json    # last;    location = /.well-known/carddav {      return 301 $scheme://$host/remote.php/dav;    }    location = /.well-known/caldav {      return 301 $scheme://$host/remote.php/dav;    }    # set max upload size    client_max_body_size 512M;    fastcgi_buffers 64 4K;    # Enable gzip but do not remove ETag headers    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-fon>    # Uncomment if your server is build with the ngx_pagespeed module    # This module is currently not supported.    #pagespeed off;    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)(\/.*|)$;        set $path_info $fastcgi_path_info;        try_files $fastcgi_script_name =404;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;        fastcgi_param PATH_INFO $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;    }    # Adding the cache control header for js, css and map files    # Make sure it is BELOW the PHP block    location ~ \.(?:css|js|woff2?|svg|gif|map)$ {        try_files $uri /index.php$request_uri;        add_header Cache-Control "public, max-age=15778463";        # Add headers to serve security related headers (It is intended to        # have those duplicated to the ones above)        # Before enabling Strict-Transport-Security headers please read into        # this topic first.        #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;        #        # WARNING: Only add the preload option once you read about        # the consequences in https://hstspreload.org/. This option        # will add the domain to a hardcoded list that is shipped        # in all major browsers and getting removed from this list        # could take several months.        add_header Referrer-Policy "no-referrer" always;        add_header X-Content-Type-Options "nosniff" always;        add_header X-Download-Options "noopen" always;        add_header X-Frame-Options "SAMEORIGIN" always;        add_header X-Permitted-Cross-Domain-Policies "none" always;        add_header X-Robots-Tag "none" always;        add_header X-XSS-Protection "1; mode=block" always;        # Optional: Don't log access to assets        access_log off;    }    location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {        try_files $uri /index.php$request_uri;        # Optional: Don't log access to other assets        access_log off;    }}

Регламентное обслуживание


Не забудьте, что в промышленном окружении требуется обеспечить минимальный и нулевой простой сервиса при обновлении или тем более резервном копировании. Ключевая сложность тут зависимость состояния метаданных в БД и самих файлов, которые доступны через NFS или объектное хранилище.
При обновлении application-серверов на новую минорную версию особых проблем не возникает. Но кластер все равно надо переводить в mainenance mode для обновления структуры БД.
Выключаем балансировщик в момент наименьшей нагрузки и приступаем к обновлению.

После этого выполняем на нем процесс ручного обновления из скачанного tar.gz, с сохранением конфигурационного файла config.php. Обновление через веб на крупных инсталляциях очень плохая идея!
Выполняем обновление через командную строку:

sudo -u www-data php /var/www/nextcloud/occ upgrade

После этого включаем балансировщик и подаем трафик на обновленный сервер. Для этого выводим все необновленные application-сервера из балансировки:

upstream backend {    ip_hash;    server backend1_nextcloud.example.com;    server backend2_nextcloud.example.com down;    server backend3_nextcloud.example.com down;    server backend4_nextcloud.example.com down;}

Остальные ноды постепенно обновляем и вводим в строй. При этом occ upgrade уже выполнять не нужно! Нужно только заменить php-файлы и сохранить конфигурацию.

При резервном копировании нужно останавливать репликацию на Slave и выполнять одновременный дамп метаданных из БД одновременно с созданием снапшота файлов в хранилище. Хранить их нужно попарно. Восстановление аналогично должно происходить из дампа БД и файлов за один и тот же период. В противном случае возможны потери данных, так как файл может лежать в хранилище, но не иметь метаданных в БД.



Подробнее..

Radxa sata hat для raspberry pi 4 домашний сервер с НАС, облаком и торрентокачалкой через впн в докере

06.01.2021 18:12:51 | Автор: admin
Подходил к концу календарный год, к праздникам правительство ужесточило локдаун и ввело комендантский час. Впереди было дней 10 выходных, и я решил, что наступает самое то время, чтобы занять себя настройкой домашнего сервера, идею которого я вынашивал уже некоторое время.

Часть 1. Выбор ЭВМ и компонентов


Основные требования к домашнему серверу были компактность и низкое энергопотребление. В качестве ЭВМ я рассматривал разные одноплатники, даже раздумывал насчёт одноплатников на х64 архитектуре. Основными критериями поиска были избыточное ОЗУ от 8 Гб, современные порты: усб3.0 и гигабитный лан. Идея была заколхозить всё это на болтах в какой-нибудь коробке типа миниАТХ, используя усб-сата интерфейсы для жёстких дисков. Мне такая реализация совершенно не импонировала эстетически, и я не торопился её воплощать. Как вдруг я наткнулся на НАС кит для 4ой малины от китайцев из Радха.

Как я понял, сам сата хэт уже был представлен некоторое время назад и даже весьма быстро распродан ограниченным тиражом. Но в этот раз китайцы предлагали в том числе и коробку. Вся конструкция выглядела весьма компактно и настолько симпатично, насколько бы мои не очень ровные руки никогда не смогли бы это сами сделать. Я погуглил эту коробку, нашёл один проплаченный обзор на ютубе и меня это, в принципе, устроило. Решил долго не думать, потому что, скорее всего партию быстро распродадут, да и по акции блок питания давали бесплатно. Коробка с сата хэтом с экспресс доставкой из Шэньчжэня мне обошлась в 125.23 на момент покупки. Выбор коробки автоматически сузил выбор ЭВМ до 4ой малины, которую я приобрёл на амазоне за 79,97 за модель с 8 Гб ОЗУ. Так же на амазоне были приобретены 2 жёстких диска ВД 2,5 2 ТБ по 63,81 за каждый, и сд карточка Самсунг ЭВО 120 за 15,25 на алиэкспрессе. Итого 348,07, я подумал, что читателю будет интересен финансовый вопрос.

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

  • корпус сделан из цельного куска металла, покрашенного снаружи белой краской;
  • днище с отверстиями для вентиляции тоже металлическое;
  • крепёжные винтики и гаечки: металл (не металлическая только верхняя пластиковая полупрозрачная крышка с отверстиями для большого вентилятора);
  • сата хэт следующей ревизии, а не той, что была у влоггера на ютубе, и имеет разъём для подключения батарейки;
  • маленький олед экран выводит инфу о состоянии системы;
  • большой вентилятор и олед экранчик работают посредством установки софта от Радха, который представляет собой питоньи скрипты, и устанавливается вводом одной команды в терминале.

image

Верхний вентилятор по умолчанию имеет 4 режима работы в зависимости от температуры процессора, которые отличаются разной интенсивностью вращения и издаваемого шума: на уровне 1 почти не слышно, уровень 2 слышно, 3-4 слышно слишком хорошо. За это, собственно, и отвечают питоньи скрипты.



В целом я оказался доволен данным девайсом, но у меня появилось одно замечание. В комплекте используется ходовой олед экранчик, который можно легко заказать на алишечке, но экранчик припаян к плате, китайцам ничего не стоило использовать FPC/FCC коннектор на плате. Это бы сильно упростило замену олед экранчика в случае его выгорания, например.

Часть 2. Питоньи скрипты от Радха


Что ж, всё собрано, приступим к настройке софта. Я не буду флудить копипасту, поэтому общие моменты будут представлены ссылками на хауту из поисковой строки, некоторые пропущу, а вот на подводных камешках можно остановиться подробнее.

Я выбрал ОС ubuntu server 20.04.1, прекрасный гайд по установке написали сами Каноникл. Следом устанавливаем софт от Радха по их ману. Тут возник подводный камешек номер 1. Дело в том, что для определённых торрентокачательных нужд мне нужно было использовать ВПН, но мой впн провайдер не поддерживает ИПв6. Когда я настроил опенвпн под мой провайдер, я обнаружил, что моя анонимность, скажем так, протекает именно через ИПв6. Ну ладно, на системном уровне ИПв6 в убунту отключается весьма просто.

Как именно
Нужно поправить конфиг утилиты sysctl
$ sudo nano /etc/sysctl.conf

и добавить туда следующее
net.ipv6.conf.all.disable_ipv6=1net.ipv6.conf.default.disable_ipv6=1net.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 restartexit 0

Далее файлу даются нужные права и всё:
$ sudo chmod 755 /etc/rc.local


Но тут случилось непредвиденное, большой вентилятор из коробки перестал работать вообще. Исключив возможность хардварной поломки, я стал искать причину софтверную. Вывод состояния сервиса rockpi-sata показывал ошибки относящиеся к питоньему скрипту fan.py
ubuntu@ubuntu:~$ sudo service rockpi-sata status rockpi-sata.service - Rockpi SATA HatLoaded: loaded (/lib/systemd/system/rockpi-sata.service; enabled; vendor preset: enabled)Active: active (running) since Fri 2020-12-25 17:16:07 CET; 11min agoMain PID: 1879 (python3)Tasks: 4 (limit: 9252)CGroup: /system.slice/rockpi-sata.service1879 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on2896 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on2897 /usr/bin/python3 /usr/bin/rockpi-sata/main.py on2898 /usr/bin/python3 /usr/bin/rockpi-sata/main.py onDec 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 runningDec 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_dcDec 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_PWMDec 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_extDec 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 Гб.
image

А вот это пример загрузки одного крупного файла.
image

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

Второй подводный камешек не относится к сата хэту, а, собственно, к линукс серверу, как объекту материальной культуры. Задача состояла в том, что сервер используется для разных задач: там будут стоять веб-сервер (облако), на который я буду стучаться снаружи,
и невозбранный качатель битового потока через впн. Проблема оказалась в том, что трафик мне нужно было как-то разделить, чтобы всё работало параллельно. Моя первая мысль была настроить фаервол. Я использовал следующие правила:
$ 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

Если всё прошло успешно, вывод должен быть вот таким:
image

Тем не менее такой тест малополезен для успокоения сильно раскачанной паранойи, поэтому я воспользовался шаркой и смотрел соединения в процессе загрузки торрента с каким-нибудь популярным линукс-дистрибутивом, скажем, убунтой. Исключив из выдачи не относящиеся к делу соединения с устройствами в локальной сети, впн сервером, а также некоторые автоматические бродкасты, за время загрузки образа убунты не произошло ничего подозрительного:
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"

image

Но что будет если опенвпн потеряет соединение или сервис внезапно остановится? Внутри контейнера работает утилита top, её вывод выглядит примерно так:
image
Убьём процесс опенвпн:
$ kill -9 6

После этого контейнер перезапустился. Я потом где-то вычитал на форумах, что контейнер настроен таким образом, что если теряется соединение с опенвпн или этот процесс завершается, то контейнер просто перезапускается. Такой вот килсвич. Я остался доволен.

Часть 4. Облако


Я выбрал облако Некстклауд и устанавливал его по одному гайду. Основное отличие моей установки в том, что я использовал другие репы для апача и пхп:
$ sudo add-apt-repository ppa:ondrej/apache2$ sudo add-apt-repository ppa:ondrej/php

После конфигурации некстклауда рекомендую проверить в админке предупреждения и пофиксить их.
image

Фиксы
В моём случае нужно было исправить отсутствующие индексы. Что это за индексы и где они отсутствуют читатель при желании мог бы объяснить автору в комментариях. Лечится это предупреждение вызовом одной команды
$ 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 0unixsocket /var/run/redis/redis.sockunixsocketperm 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=1opcache.enable_cli=1opcache.interned_strings_buffer=8opcache.max_accelerated_files=10000opcache.memory_consumption=128opcache.save_comments=1opcache.revalidate_freq=1

И перезапустить апач:
$ sudo systemctl restart apache2


Облако теоретически можно подключить как сетевой диск по ВебДАВ, но почему-то не в виндовс 10. С использованием утилиты Cyberduck я протестировал работу облака в локальной сети. Как видно на скриншотах ниже, скорости на загрузку в облако достигают приемлимых 12 МБ/с, а загрузки из облака приличных 35 МБ/с. Данные скорости получены при включённом шифровании в облаке с ключом рса4096.

image

image

Часть 5. Энергопотребление


Изначально я хотел дать этому серверу поработать недельку, чтобы с использованием счётчика мощности привести статистику. Но, к сожалению, я не разобрался, как правильно настроить этот счётчик мощности, поэтому я приведу изображение с данными с индикатора. Как видно, в режиме простоя система потребляет 8.5 Вт энергии, а в моменты активной синхронизации с облаком (папка с личными данными размером около 200 Гб) до 16.88 Вт. Подробная статистика позволила бы рассчитать среднее значение потребляемой мощности в день, но за её отсутствием и из расчёта, что большую часть времени сервер простаивает, я на вскидку принимаю 10 Вт за усреднённое значение потребляемой мощности, что в месяц даёт:

$10 Вт * 24 ч * 30 = 7,2 кВт*ч$

При текущих ценах в 0,31 за 1 кВт*ч, сумма расходов на содержание сервера в месяц составит около 2,23, что не должно сильно отразиться на моём среднем потреблении энергии.

image

Коль с потреблением и расходами разобрались, то я предлагаю провести небольшую оценку финансовых вложений и сравнить с предложениями виртуальных серверов на рынке. К сожалению, равнозначного сравнения у меня не вышло, потому что, как я понял, рынок виртуальных серверов предлагает либо производительные серверы, либо серверы для хранения данных. Предположим, что полученный домашний сервер по производительности сравним с серверами для хранения данных и проанализируем текущие цены. Как видно по ссылке, аренда сервера с 2 Тб дискового пространства будет стоить 100 в год. Годовой счёт за электричество моего домашнего мини-сервера на 4ой малине должен обойтись примерно в 27,16. При потраченных 348,07, получается что окупаемость домашнего сервера займёт:

$348,07 / (100/год - 27,16/год) = 4,78 лет$

Что долго, и читатель в принципе будет прав решив, что оно того не стоит.

Давайте рассмотрим ещё один вариант с апгрейдом до 4 Тб дискового пространства. В случае домашнего сервера я бы прикупил дополнительные 2 диска по 2 Тб, что в текущих ценах на амазоне составит дополнительные 127,62. Потребление сервера должно будет вырасти и, предположим, в среднем составит 18 Вт. Это даст годовой счёт электроэнергии уже в 48,88. Теперь сравним со стоимостью сервера хранения на 4 Тб (340 в год) и оценим окупаемость:

$475,69 / (340/год - 48,88/год) = 1,63 года$

Что недолго, и уже не выглядит противоречивым вложением средств.

Заключение


В данном посте мы узнали про замечательный сата хэт для 4ой малины и про симпатичный кит на его основе для домашнего сервера. Мы посмотрели производительность этой системы на примере копирования файлов по сети, а также производительность запущенного на этом сервере облака Некстклауд. Вопросы энергопотребления, стоимости и расходов на данный сервер так же не оставлены в стороне. Благодарю за прочтение этого материала. Критические замечания по поводу представленных решений приветствуются.

В частности я бы хотел попросить читателя поделиться опытом в следующих вопросах:

  1. ZFS?
  2. Просадки скорости копирования по сети, что с этим делать?
  3. Апач или всё таки нгинкс?
  4. Какой упс выбрать?
  5. Почему докер обходит правила впн?
Подробнее..

Из песочницы NextCloud в качестве сервиса по созданию защищенных ссылок

04.08.2020 14:20:22 | Автор: admin
Привет, Хабр! Хочу поделиться немного нетривиальным кейсом по настройке NextCloud в качестве сервиса по созданию защищенных ссылок, для прямого скачивания данных с подключенного сетевого smb\cifs-диска. Опишу решения нюансов, с которыми столкнулся во время настройки.

Зачем это надо?


Удобная доставка контента конечному пользователю, минуя возню с FTP и невозможность (из-за NDA) воспользоваться публичными сервисами и облаками для передачи файлов (BTsync, Google-\Mail-\Yandex-Disk\Dropbox\etc).





Предисловие


Наш офис имеет определенную инфраструктуру, в неё входит в том числе и ActiveDirectory, в которой у нас находятся сотрудники, состоящие в группах.

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

Обычно, для отдачи данных во внешний мир поднимается, либо отдельный FTP, либо данные выгружаются на уже имеющийся. Признаюсь, это далеко не всегда удобно как минимум, создание и управление временными логинами и паролями (например, когда партнёрам нужно отдать готовый контент), контроль места на FTP-сервере, ручная выгрузка на FTP-сервер перед отправкой.

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

На такую идею нас натолкнули одни из партнеров, так как у них имелся внутренний сервис, но там он был самописным.

Готовых вариантов с ходу в поисковике не нашлось (если у вас есть оные на примете отпишитесь, пожалуйста в комментариях), а тратить потенциально много человеко-часов на разработку с нуля, тестирование и поддержку не было желания и ресурсов ни у кого. Да и зачем изобретать велосипед, если зачастую все уже придумано до. Так на ум и пришел сервис NextCloud, который умеет подключать к себе внешние ресурсы.

Речь пойдет о последней стабильной, на данный момент версии 19, но наш метод настройки подойдет и для более ранних версий мы изначально реализовали это на 16 версии и потом постепенно обновлялись. Недавно я как раз поднимал его с нуля на последней (19), и опираясь на неё пишу статью.

Что мы хотим получить в конечном итоге:


  • Только сотрудники могут заходить в наш сервис и только через ActiveDirectoty\LDAP, точно так же как заходят на офисный пк, в Jira, Confluence, Nexus и пр.
  • После авторизации в веб интерфейсе NextCloud, сотруднику должен быть подключен наш сетевой диск, с точно такими-же правами, как это происходит при заходе с рабочего компьютера.
  • При первом входе в NextCloud у каждой учетной записи создаются файлы-примеры в домашнем каталоге, которые занимают места на диске. По хорошему, от этого надо избавиться.
  • Сотрудник не должен иметь возможность загружать что либо, как на подключенный диск, так и в аккаунт NextCloud .*Это просто наша хотелка, на самом деле она не обязательная.
  • Сотрудник может создавать временные ссылки, защищенные паролем на любые доступные ему ресурсы будь то папка или отдельный файл. А также управлять ими (ссылками) отзывать, менять срок жизни и прочее.
  • Конечному пользователю, кому отправлена защищенная ссылка, достаточно её открыть и ввести пароль, чтобы получить возможность скачать расшаренные ему данные.



Развёртка и настройка зависимостей


Для начала, нам надо иметь отдельную виртуалку или сервер, где можно установить операционную систему, и после NextCloud.

На Хабре есть не одна статья, посвященная развёртке системы и сервиса.

AlexanderS достаточно хорошо и подробно описал процесс от установки системы до самой настройки облака (включая актуализацию статей по годам). Не вижу смысла в очередной раз это всё повторять.

1. Так как мы подключаем в NextCloud сетевой диск, то нам понадобятся пакеты в систему: smbclient, libsmbclient , php-ldap, и php-smbclient.

Ремарка, на случай использования Docker
Если вы тоже используете докер, то напомню официальный образ не имеет на борту пакетов для работы с samba и вам лучше создать форк, установив их в своем DockerFile. И, согласно документации, установка пакета php-smbclient внутри их образа немного отличается от классического apt install package.

Пример DockerFile
FROM nextcloud:latestRUN apt update -y &&  apt install -y --allow-unauthenticated smbclient libsmbclient libsmbclient-devRUN pecl install smbclientRUN docker-php-ext-enable smbclient



2. Из-за особенностей настроек нашего сервера samba (отключена поддержка smb1), на машине с nextcloud, в файлах /etc/samba/smb.conf и /usr/share/samba/smb.conf пришлось поменять строки, отвечающие за протокол:

[global] client min protocol = SMB2client max protocol = SMB3

Продолжение примера DockerFile
RUN rm -frv /etc/samba/smb.conf /usr/share/samba/smb.confADD smb.conf /etc/samba/ADD smb.conf /usr/share/samba/


В ином случае, nextcloud так и не смог подключиться к диску.



Настройка nextcloud


Итак, Nextcloud уже установлен, зависимости поставлены, а в сервисе заведен один внутренний юзер, который создался во время установки.

Шаг первый. Подготовка шаблона аккаунтов сотрудников.


Поскольку у нас будет не один сотрудник в системе, а постепенно их количество будет меняться если заранее не настроить шаблон создаваемого пользователя у каждого будет в домашней папке несколько файлов-примеров. Хорошо что по этому поводу у nextcloud есть отдельная настройка skeleton files, которая настраивается в config.php.

  'skeletondirectory' => '/var/www/html/data/donotdeletme',

То есть, можно создать пустую папку и указать в конфиге полный путь к ней.

Шаг Второй. Делаем пользователей read-only


Достаточно указать квоту в 1 B (1 байт) в разделе настроек пользователей (http(s)://nextcloud.domain.tld/settings/users).

Шаг третий заранее чиним ZipStreamer


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



Как это работает
Если вы перейдя по шареной ссылке, нажали кнопку "Dowload All Files"/"Скачать все файлы", то вы заметите, что вам не показывается в браузере (или в менеджере загрузок) конечный вес архива, а полоса загрузки будет неопределенной.



Это связано с тем, что по этой кнопке система в режиме реального времени создает и отдает вам на скачивание архив (в большинстве случаев .zip, в редких кейсах .tar)

Кстати, в силу особенности этой технологии, возобновление приостановленных загрузок в этом случае невозможно.

Похожее поведение есть у и аналогичных сервисов: Google Drive, Яндекс.Диск, и т.д.

Проблема кроется в том, что по неизвестным причинам, заложенная в NextCloud логика сбоит, и при случае, если в папке больше 65536 файлов, и\или их общий вес будет превышать 4гб скорее всего вы столкнетесь с проблемой, что скачанный файл будет либо побит, либо загрузка будет прерываться после скачанных 4гб.

Данной проблеме выделяли достаточное время, на GitHub даже есть, и не один, закрытый тикет (#1755, #15871, #8798), но несмотря на то, что якобы проблема решена у нас она так и осталась, и с переменным успехом воспроизводилась, очень мешая работе. Пришлось решать её более радикально.

Решение
Поскольку у нас 100% 64хбитная система, то мы принудительно говорим библиотеке использовать 64х-битный режим. Решение в лоб.

<папка, где установлен nextcloud>/lib/private/Streamer.php:
- $this->streamerInstance = new ZipStreamer(['zip64' => false]);+ $this->streamerInstance = new ZipStreamer(['zip64' => true]);

Ремарка, на случай использования Docker
В официальном образе происходит при каждом запуске контейнера некий Integrity Check и из одного места в другое распаковываются оригинальные файлы поверх установленных( из /usr/src/nextcloud/* в /var/www/html/*).

Поэтому просто в лоб замапить файл в условном /var/www не получится при запуске файл либо перетрется оригиналом, либо контейнер запустится и упадет сразу с ошибкой.

Так что мы подменяем патченым файлом исходный в папке /usr/src/nextcloud/lib/private/ еще при сборке в CI нашего форкнутого образа. Получается, наш поправленный файл будет гарантированно всегда использоваться.

Продолжение примера DockerFile
RUN rm -frv /usr/src/nextcloud/lib/private/Streamer.phpADD Streamer.php /usr/src/nextcloud/lib/private/RUN chown nobody:nogroup /usr/src/nextcloud/lib/private/Streamer.php

Эти манипуляции, по крайней мере при использовании докер-образа, в Панели Администрирования точно завалят вам встроенную проверку на подлинность, имейте это ввиду.




Но лично нас пока это устроило.

Шаг четвертый настраиваем параметры ссылок


В параметрах публикации настраиваем правила так, как будет удобно. Например, делаем обязательную защиту паролем и ставим обязательный срок жизни.

Шаг пятый подключаем сетевой диск


  1. Переходим в настройку внешних хранилищ. (http(s)://nextcloud.domain.tld/settings/admin/externalstorages)
  2. Выбираем добавление CMB \ CIFS хранилища.
  3. Заполняем поля имени, домена, папки и тд.
  4. Выбираем Учетные данные, хранить в базе данных именно этот пункт позволяет при заходе пользователя по его связке логина и пароля подключать диск к его учетной записи в NextCloud. (Пункт хранение логина и пароля во время сессии не взлетел).
  5. Не забываем в меню <...> отметить чекбоксами Только чтение и разрешение предоставление общего доступа.

Шаг шестой запускаем пользователей через LDAP


Теперь, когда мы все подготовили ставим из маркетплейса плагин, и сразу после подключаем LDAP. В нашей системе, мы давали доступ сотрудникам, которые находятся в группе NextcloudAccess. Можете сделать аналогично.



Заключение


Всё, после всех этих нехитрых, но местами не самых очевидных манипуляций сервис работает, диск подключен, сотрудники добавлены, а пользователи качают и довольны.

Полный пример нашего DockerFile
FROM nextcloud:latestENV DEBIAN_FRONTEND noninteractive#installing smbclientRUN apt update -y &&  apt install -y --allow-unauthenticated smbclient libsmbclient libsmbclient-devRUN pecl install smbclientRUN docker-php-ext-enable smbclient#fix of ZipStreammerRUN rm -frv /usr/src/nextcloud/lib/private/Streamer.phpADD Streamer.php /usr/src/nextcloud/lib/private/RUN chown nobody:nogroup /usr/src/nextcloud/lib/private/Streamer.php#fix of smb configRUN rm -frv /etc/samba/smb.conf /usr/share/samba/smb.confADD smb.conf /etc/samba/ADD smb.conf /usr/share/samba/




Нагрузочное тестирование


Как дела с нагрузкой? спросите вы напоследок.

Замеры в час пик




Наш инстанс сервиса крутится на ~ 6Gb Ram + 6CPU в виртуальной машине среди других VM.

При пике нагрузки на сеть оперативной памяти использовалось чуть более 2.5Gb, процессор забит не был, а отдача в среднем была около 5Gbit/s (рекорд доходило и до 8Gbit/s).

Единственное, что заметили при отдаче сверх 6Gbit/s во внешний мир, у нас периодически отваливается web-интерфейс, но сами загрузки у пользователей продолжают идти.



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



Проверено на: nextcloud 16, 17, 18, 19Дата написания: 26.07.2020Дата правок: 02.08.2020Что поправлено: Сделал кликабельные скриншотыВерсия: 1.0.0.5
Подробнее..

Быстрый запуск Nextcloud и Onlyoffice на Ubuntu SSL от Letsencrypt

20.06.2021 18:15:44 | Автор: admin

Мало того, что многие не доверяют общедоступным облакам, так они еще и предлагают непозволительно малые объемы дискового пространства.

Однажды мне понадобилось 1Tb облачного хранилища и выбор пал на Nextcloud, который и было решено развернуть на собственном домашнем сервере

В данной статье я опишу как быстро и безболезненно установить и настроить облако Nextcloud и облачный редактор Onlyoffice

Статья предполагает, что у вас уже установлен и настроен Ubuntu.

Все действия были проверены на Ubuntu Server 20.04

Что будем делать:
1. Установим Nginx, PHP и MariaDB
2. Добавим бесплатный SSL-сертификат Let's Encrypt
3. Развернем NextCloud
4. Произведем тонкие настройки сервера
5. Установим Onlyoffice

Бесплатные доменные имена в домене .tk можно получить на www.freenom.com

Первым делом, устанавливаем вспомогательные утилиты

sudo apt-get install nano mc zip -y

Этот пункт можно пропустить, если настраиваете облако на локальный диск, а не на отдельную машину с доступом по nfs, мне понадобилось сделать это именно на nfs

# Ставим nfs-clientsudo apt install nfs-common -y# -------------------# Монтируем папку nfs# Ставим nginxsudo mkdir -p /nfs/ncsudo mount your_host_ip:/папка_шары_nfs/ /nfs/ncsudo ls -l /nfs/nc/sudo df -hsudo du -sh /nfs/nc/# -------------------# Монтируем nfs при загрузкеsudo nano /etc/fstab# Добавим такую строку в конец файлаyour_host_ip:/папка_шары_nfs/  /nfs/nc  nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0

Ставим nginx

sudo apt install nginx -ysudo nginx -Vsudo systemctl enable nginxsudo systemctl start nginx

Ставим php 7.4

sudo apt install php7.4-fpm php7.4-mysql php7.4 php7.4-curl php7.4-gd php7.4-json php7.4-mbstring php7.4-common php7.4-xml php7.4-zip php7.4-opcache php-apcu php-imagick -y

Настраиваем php 7.4

sudo nano /etc/php/7.4/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

# Настраиваем php.ini:

sudo nano /etc/php/7.4/fpm/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

Разрешаем автозапуск php-fpm и перезапускаем его:

sudo systemctl enable php7.4-fpmsudo systemctl restart php7.4-fpm

Устанавливаем MariaDB:

sudo apt install mariadb-serversudo systemctl enable mariadbsudo systemctl start mariadb

Запуск сценария безопасности (здесь можно поменять пароль рута, убрать ненужные разрешения):

sudo mysql_secure_installation

Создаем базу данных для Nextcloud (в примере указан пароль nextcloud, его лучше заменить на свой) :

sudo mysql -u root -p

Вводим пароль рута для MariaDB

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

Теперь надо создать файл конфигурации Nginx для Nextcloud

sudo nano /etc/nginx/sites-enable/nextcloud.conf

И вставляем в него следующий текст, естественно, заменив nc.myhost.com на свои сервера

server {    listen 80;    server_name nc.myhost.com;    return 301 https://$server_name$request_uri;}server {    listen 443 ssl;    server_name nc.myhost.com;    ssl_certificate /etc/nginx/ssl/cert.pem;    ssl_certificate_key /etc/nginx/ssl/cert.key;    root /var/www/nextcloud;    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;    client_max_body_size 10G;    fastcgi_buffers 64 4K;    rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;    rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;    rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;    index index.php;    error_page 403 = /core/templates/403.php;    error_page 404 = /core/templates/404.php;    location = /robots.txt {      allow all;      log_not_found off;      access_log off;    }    location ~ ^/(data|config|\.ht|db_structure\.xml|README) {        deny all;    }    location / {        rewrite ^/.well-known/host-meta /public.php?service=host-meta last;        rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;        rewrite ^/.well-known/carddav /remote.php/carddav/ redirect;        rewrite ^/.well-known/caldav /remote.php/caldav/ redirect;        rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;        try_files $uri $uri/ index.php;    }    location ~ ^(.+?\.php)(/.*)?$ {        try_files $1 = 404;        include fastcgi_params;        fastcgi_param SCRIPT_FILENAME $document_root$1;        fastcgi_param PATH_INFO $2;        fastcgi_param HTTPS on;        fastcgi_pass unix:/run/php/php7.4-fpm.sock;    }    location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {        expires modified +30d;        access_log off;    }}

Теперь необходимо получить сертификаты для ssl

Устанавливаем Certbot и его плагин для Nginx:

sudo apt install certbot python3-certbot-nginx

Получаем сертификаты для всего (я получал для всех поддоменов, которые прописал на freenom, в т.ч. для почты, заббикса, и т.п., у вас могут быть и должны быть свои)

Сначала с ключом --dry-run проверяем все ли в порядке

sudo certbot certonly --agree-tos --email you@mail -d nc.myhost.com-d www.myhost.com -d zabbix.myhost.com --nginx --dry-run --d

Если все хорошо, то получаем сертификаты

sudo certbot certonly --agree-tos --email почта@администратора -d myhost.com-d nc.myhost.com-d cloud.myhost.com-d zabbix.myhost.com-d www.myhost.com-d mail.myhost.com sudo certbot certonly --agree-tos --email your@mail -d nc.myhost.com-d www.33rus.com -d zabbix.33rus.com --nginx n 

Сертификаты появятся в папке /etc/letsencrypt/live/myhost.com cert.pem chain.pem fullchain.pem privkey.pem

Подключаем сертификаты к сайту

sudo nano /etc/nginx/sites-available/nextcloud.conf

ssl_certificate /etc/letsencrypt/live/myhost.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myhost.com/privkey.pem;

Устанавливаем Nextcloud:

Скачиваем последнюю версию с сайте Nextcloud:

cd /tmp/sudo wget https://download.nextcloud.com/server/releases/nextcloud-21.0.0.zipsudo unzip nextcloud-21.0.0.zipsudo cp -R nextcloud /var/www/nextcloud/cd /var/www/sudo chown -R www-data:www-data nextcloud/sudo chown -R www-data:www-data /nfs/nc

Обратите внимание, в данном случае я использую папку на nfs, вам необходимо использовать папку в соответствии с вашими настройками

Почти все. Заходим на https://nc.myhost.com
Создаем пользователя, пароль, прописываем доступ к каталогу /nfs/nc/
Прописываем созданную ранее базу данных и пароль к ней.

Теперь тонкая настройка Nextcloud и установка Onlyoffice

Ставим Redis и APCu

sudo apt install memcached php-memcached -ysudo apt install php-apcu redis-server php-redis -ysudo nano /var/www/nextcloud/config/config.php

И добавляем следующие строки перед закрывающей скобкой )

'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Redis',
'redis' =>
array (
'host' => '127.0.0.1',
'port' => 6379,
),
'memcache.locking' => '\OC\Memcache\Redis',

Переиндексация файлов (если вдруг вы скопировали файлы в папку nexcloud не через интерфейсы nextcloud, то их надо переиндексировать)

sudo -u www-data php /var/www/nextcloud/occ files:scan --all

Устанавливаем OnlyOffice DocumentServer

Первым делом устанавливаем версию PostgreSQL, включенную в вашу версию Ubuntu:

sudo apt install postgresql -y

После установки PostgreSQL создайте базу данных и пользователя PostgreSQL:

Пользователем и паролем для созданной базы данных должны быть onlyoffice.

sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice;"sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH password 'onlyoffice';"sudo -i -u postgres psql -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;"

Установка rabbitmq и nginx-extras:

sudo apt install rabbitmq-server -ysudo apt install nginx-extras -y

Установка ONLYOFFICE Docs

Добавьте GPG-ключ:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys CB2DE8E5

Добавьте репозиторий ONLYOFFICE Docs:

sudo echo "deb https://download.onlyoffice.com/repo/debian squeeze main" | sudo tee /etc/apt/sources.list.d/onlyoffice.list sudo apt update

Устанавливаем mariadb-client!

sudo apt install mariadb-client -y

Устанавливаем ONLYOFFICE Docs. Не ошибитесь с вводом пароля. Это должен быть onlyoffice

sudo apt install onlyoffice-documentserver -y

Переводим onlyoffice на https

sudo cp -f /etc/onlyoffice/documentserver/nginx/ds-ssl.conf.tmpl /etc/onlyoffice/documentserver/nginx/ds.confsudo nano /etc/onlyoffice/documentserver/nginx/ds.conf 

Меняем порт ssl не забыв пробросить его в роутере

listen 0.0.0.0:7443 ssl;
listen [::]:7443 ssl default_server;

Перезапускаем nginx

sudo service nginx restart

Настраиваем cron

sudo crontab -u www-data -e

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

*/5 * * * * php -f /var/www/nextcloud/cron.php

Ну, вот и все, останется через веб-интерфейс установить плагин ONLYOFFICE в вашем Nextcloud и прописать сервер https://myhost.com:7443

Подробнее..

Вебинар DataLine Безопасное хранение корпоративных документов и совместная онлайн-работа 14 апреля

02.04.2021 12:23:26 | Автор: admin

Разберем доступные на рынке решения для организации хранения документов и расскажем о возможностях сервисов на базе open-source решения Nextcloud. Вебинар будет интересен тем, кто ищет безопасное для компании и удобное для сотрудников решение для хранения корпоративных файлов и совместной работы над документами.

В программе:

  • Удобно, но небезопасно, и наоборот: сетевой диск, публичные облачные хранилища и диски.

  • Open-source решение Nextcloud.

  • Разворачиваем Nextcloud самостоятельно.

  • Сервис DataLine на базе Nextcloud: возможности, которые сложно получить в варианте on-premise.

  • Не просто хранилище: платформа для совместной работы на базе Nextcloud.

  • Кейсы и демонстрация основных модулей решения Nextcloud.

Начало вебинара в 11.00. Продолжительность 1 час. Участие бесплатное, но нужно зарегистрироваться.

Подробнее..

Nextcloud на VirtualBox с хранилищем в общей папке

17.01.2021 18:05:05 | Автор: admin

Идея иметь собственное домашнее облако у меня была давно. Рассматривал варианты NAS на основе бесплатных дистрибутивов типа FreeNAS, NAS4Free, OpenMediaVault и пр. Но хотелось, чтобы был мобильный клиент, простой и красивый webUI. Раньше как-то баловался с разными решениями и понравился проект ownCloud. Но на текущий момент у него платное мобильное приложение. Сейчас стоит около 30 рублей, но хотелось иметь что-то более бесплатное. Вспомнил про хороший форк ownCloud Nextcloud. Мобильное приложение бесплатное (+ для есть и дополнительные приложения) и есть декстопные клиенты (Win, Mac, Linux). Сам Nextcloud имеет множество настроек, интеграций, а также возможность установки расширений (приложений).

Распространяется Nextcloud несколькими вариантами:

  1. Архив серверного приложения для web-сервера;

  2. Web-инсталлер;

  3. Образами для VirtualBox, Docker и Snap-пакет.

Я решил реализовать схему на VirtualBox, с подключением общей папки, как хранилища.

Предусловие: На сервере должен быть установлен VirtualBox (далее VB) и VirtualBox Extension Pack (далее VBEP).

Импорт виртуальной машины

1. Скачиваем образ виртуальной машины Nextcloud-VM.ova.

Другие варианты образов представлены на сайте Hansson IT.

2. Двойным кликом запускаем скаченный образ, после чего откроется импорт VirtualBox.

В настройках можно указать для создаваемой виртуальной машины (далее ВМ) Имя, Описание и Папку. Характеристики железа уменьшать не стоит, иначе при установке Nextcloud могут появиться ошибки о недостаточности ресурсов. Все настройки ВМ, в т.ч. общие папки, лучше настраивать после завершения установки Nextcloud.

3. После нажимаем Импорт и ждём завершения создания нашей ВМ.

4. После успешного импорта, ВМ отобразиться в списке ВМ VB.

Первоначальная настройка Nextcloud

Образ ВМ основан на Ubuntu Server 20.04.1 LTS в котором предустановлены скрипты разворачивания Nextcloud.

1. Запускаем ВМ.

2. После запуска ВМ появляется приглашение авторизации. По умолчанию пользователь (админ) сервера ncadmin, с паролем nextcloud.

Смена пароля будет предложена после завершения конфигурации Nextcloud.

3. Авторизовываемся на сервере.

4. После авторизации появляется приветственное сообщение первого запуска с прделожением запустить скрипт установки. Для запуска необходимо ввести пароль пользователя ncadmin.

Вводим пароль, нажимаем Enter и запускается процесс установки Nextcloud.

5. После проверки конфигурации ВМ будет отображено сообщение о выборе варианта хранения данных. В образе ВМ подключено 2 жестких диска (динамические по 40 Гб):

  • disk1 диск с ОС, файловая система ext4.

  • disk2 диск с файловой системой ZFS.

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

Ознакомившись с сообщением, нажимаем Ок.

6. Открывается окно выбора жесткого диска для хранения.

Стрелками встаем на позицию 1 Disk, активируем её пробелом.

Клавишей Tab переходим к блоку кнопок, выбираем Ok и нажимаем Enter.

7. На следующем шаге открывается окно выбора DNS сервера:

  • Quad9

  • Cloudflare

  • Local локальный сервер (по DHCP)

Я предпочитаю использовать Cloudflare. Выбираю его и нажимаю Ok.

8. Следующее окно сообщение о выборе зеркала обновлений.

Ознакомившись с сообщением, нажимаем Ок.

9. Следующее сообщение информирует о текущем сервере обновлений http://archive.ubuntu.com/ubuntu.

Ознакомившись с сообщением, нажимаем Ок.

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

Я решил остаться на стандартном, хотя по тестам есть зеркала и получше (выше скорость, меньше пинг, шире канал). Поэтому на этом шаге выбираю No и нажимаю Enter.

После чего начнется установка Nextcloud (+PostgreSQL, PHP, Apache).

11. По завершению установки будет предложено изменить пароль ncadmin

Нажимаем любую клавишу. Вводим новый пароль, нажимаем Enter, подтверждаем новый пароль ещё раз и нажимаем Enter.

12. После смены пароля появляется сообщение что текущий админ в Nextcloud ncadmin. И его нужно заменить на нашего.

Нажимаем любую клавишу. Вводим имя пользователя, нажимаем Enter, вводим пароль, нажимаем Enter, подтверждаем пароль ещё раз и нажимаем Enter.

13. Далее появляется окно с выбором местоположения

Выбираем Europe, и нажимаем Ok.

14. В следующем окне необходимо выбрать город. Выбираем необходимый и нажимаем Ok.

15. Может появиться следующее сообщение о том, что существует обновленная версия файла '/etc/sysemd/resolved.conf' и нужно принять решение что делать:

Y или I установить обновленную (основную действующую) версию;

N или O оставить текущую установленную версию;

D показать изменения между версиями;

Z запустить shell

Я решил установить обновленную версию: ввожу Y и нажимаю Enter.

После обновления файла ВМ будет перезагружена.

16. После перезагрузки ВМ необходимо авторизоваться (на этом этапе можно пользоваться PuTTY). После авторизации будет приветственное окно, которое сообщит, что мы все установили и это окно можно отключить удалив файл /home/ncadmin/welcome.sh (иначе оно будет постоянно появляться).

Нажимаем Ok. Nextcloud установлен.

Настройка ВМ

Для работы расширений VB установим соответствующий пакет sudo apt install virtualbox-guest-utils

После установки выключим ВМ для её настройки sudo shutdown -h now

После того, как ВМ будет выключена, в VB зайдем в настройки.

1. Можно включить двунаправленный буфер обмена (но лучше пользоваться PuTTY)

2. Я уменьшил оперативную память до 1024 Гб и отключил гибкий диск

3. Установил использование одного ядра процессора

4. Создал общую папку (folder): указал путь и включил авто-подключение

Сохраняем настройки и запускаем ВМ.

Изменение папки хранения данных

Основной гайд для этого блока взял отсюда https://enk2x.ru/2019/09/21/datanew/

После запуска ВМ, авторизуемся.

1. Проверяем наличие общей папки

cd /media

ls

Должно отобразиться наименование sf_folder (на гостевой машине у общей папки префикс sf_), где folder имя общей папки на хост машине.

2. Включаем в группу vboxsf (группа-владелец общей папки) пользователей ncadmin и www-data (пользователь Apache).

sudo usermod -aG vboxsf ncadmin

sudo usermod -aG vboxsf www-data

После включения в группу перезагружаем ВМ

sudo shutdown -r now

3. После перезагрузки авторизуемся и переводим приложение nextcloud в режим обслуживания

sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --on

Папка nextcloud расположена в корне папки www, а не внутри html

4. Копируем файлы настроек и пользовательские файлы в общую папку

sudo cp -R /mnt/ncdata /media/sf_folder

5. Убеждаемся что всё скопировано

cd /media/sf_folder/ncdata

ls

Так же можно проверить на хост машине в общей папке

6. Изменяем путь к папке данных в конфиг-файле

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

Откроется файл config.php, где для параметра 'datadirectory' необходимо изменить значение '/mnt/ncdata' на '/media/sf_folder/ncdata' (где folder имя общей папки)

После внесения изменений нажимаем Ctrl+X, на вопрос о сохранении изменений вводим y и нажимаем Enter.

7. Выключаем режим обслуживания

sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off

Результат

Проверим работоспособность.

1. Авторизуемся на сервере Nextcloud через web-интерфейс под пользователей admin и добавим картинку в папку Photos

2. Проверим наличие файла в общей папке на хост-машине

3. Проверим наличие файла в мобильном приложении.

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

4. Обратный порядок копирования

Если мы сначала вручную закидываем файлы в общую папку (без использования приложения), то в приложении они не будут видны. Для того, чтобы они отобразились, нужно пересканировать папки командой

sudo -u www-data php /var/www/nwxtcloud/occ files:scan all

После сканирования, добавленный файлы отобразятся в приложении.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru