Как я поднял свой мессенджер: Nextcloud Talk на TrueNAS через свой домен

—

от автора

Я устал от ситуации с мессенджерами и настроил звонки через Nextcloud Talk для всей семьи. Потому что мама звонит в VK и не понимает, почему звонки не проходят — у меня iPhone, приложение VK удалено из стора. А значит, отозван токен для уведомлений и входящие вызовы проходят только если приложение открыто. А папа звонит в TG по старой привычке — пока включишь VPN, пока дождешься установления соединения…

Задача: дать возможность всей семье общаться через свой self-hosted сервер с Nextcloud Talk. В моём случае это TrueNAS, об этом писал ранее на Хабре. Для этого нужен домен с SSL-сертификатом и доступом к htaccess либо конфигам nginx. Схема выглядит так:

Блок-схема как поднять Nextcloud Talk на своём self-hosted TrueNAS-сервере

Блок-схема как поднять Nextcloud Talk на своём self-hosted TrueNAS-сервере

Шаг 1. Настройка хоста

Нам потребуется свой домен example.com. Допустим у него пописаны NS от хостера:

Я использую VPS с HestiaCP вместо виртуального хостинга, но данная схема будет работать с любой панелью. Работать будем дальше с ней. Далее в панели хостера создаём поддомен nextcloud.example.com (хотя можно и на основном домене делать) и меняем A-запись в настройках DNS на IP сервера с HestiaCP. Проверяем через терминал (PowerShell), что резолвится:

Мы должны увидеть IP сервера с HestiaCP. Выпускаем SSL от Let’s Encrypt — так SSL-сертификатом будет управлять HestiaCP и отвечать за его автоматический перевыпуск. DNS support для домена не нужен, т к DNS управлеятся хостером.

  • Enable SSL for this domain — вкл

  • Use Let’s Encrypt to obtain SSL certificate — вкл

  • Enable automatic HTTPS redirection — вкл

Настройки домена в HestiaCP

Настройки домена в HestiaCP

Шаг 2. Настройка Port Forwarding на домашнем роутере

Мне повезло, и провайдер выдал мне статичный IPv4 не за CGNAT, иначе потребовался бы DDNS. Сам Nextcloud у меня уже установлен на TrueNAS в домашней сети по адресу 192.168.0.17:30027 (порт 30027 — дефолтный для Nextcloud). Давайте сгенерируем рандомный порт и настроим Port Forwarding на роутере с этого порта на 30027.

На примере моего старенького роутера Asus RT-N12 — давайте настроим Port Forwarding c рандомного порта 56070 на 192.168.0.17:30027:

  • Service Name = Nextcloud # Называете как нравится

  • Source Target = IP вашего хостинга или VPS. Так доступ будет только у вашего VPS. Можно оставить пустым, но будет менее безопасно

  • Port Range = 56070

  • Local IP = 192.168.0.17 # локальный IP TrueNAS

  • Local Port = 30027

  • Protocol = TCP

Создаем сразу еще два правила — они понадобятся нам позже:

  • Service Name = Nextcloud coturn 3478 # Называете как нравится

  • Source Target = пусто # Если разрешаем подключения с любого IP

  • Port Range = 3478

  • Local IP = 192.168.0.17 # локальный IP TrueNAS

  • Local Port = 3478

  • Protocol = BOTH

И последнее:

  • Service Name = Nextcloud coturn  relay # Называете как нравится

  • Source Target = пусто # Если разрешаем подключения с любого IP

  • Port Range = 49160:49200

  • Local IP = 192.168.0.17 # локальный IP TrueNAS

  • Local Port = 49160

  • Protocol = UDP

Настройка Port Forwarding на роутере Asus RT-N12

Настройка Port Forwarding на роутере Asus RT-N12

Шаг 3. Настройка реверс-прокси на хостинге

Наша задача в том, чтобы при открытии https://nextcloud.example.com/ открывалась страница логина. Есть несколько вариантов: 

Вариант 1. Через htaccess (apache)

Создаем файл .htaccess в корне public_html сайта и прописываем туда 2 строчки:

# Проксирование всех запросов на домашний NextcloudRewriteEngine OnRewriteRule (.*) http://<ВНЕШНИЙ_IP_РОУТЕРА>:56070/$1 [P,L]

Эта история будет работать, если на хостинге включено 2 модуля:

  • proxy_module

  • proxy_http_module

Проверить можно подключившись к терминалу хостинга и ввести команду:

apachectl -M | grep proxy

Если этих 2х модулей не видно — то можно доустановить, например у меня не хватало одного модуля:

a2enmod proxy_httpsystemctl restart apache2

Я также попробовал данную схему с обычным виртуальным хостингом у одного из популярных хостеров в РФ — у него хоть и доступен терминал из браузера, но установить недостающие модули он не дал. Возможно стоит обратиться с вопросом к техподдержке.

Вариант 2. Через nginx

Создаем новый шаблон для Proxy Template и применяем его к nextcloud.example.com в HestiaCP. Признаюсь честно — код помогал писать Claude:

cat > /usr/local/hestia/data/templates/web/nginx/nextcloud_proxy.tpl << 'EOF'#=========================================================================## Nextcloud External Proxy Web Domain Template                            ## Custom template, proxies all requests including static assets           ## to an external backend, without local try_files fallback.               ##=========================================================================#server {        listen      %ip%:%proxy_port%;        server_name %domain_idn% %alias_idn%;        error_log   /var/log/%web_system%/domains/%domain%.error.log error;        include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;        location ~ /\.(?!well-known\/|file) {                deny all;                return 404;        }        location / {                proxy_pass http://<ВНЕШНИЙ_IP_РОУТЕРА>:56070;                proxy_http_version 1.1;                proxy_set_header Host $host;                proxy_set_header X-Real-IP $remote_addr;                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                proxy_set_header X-Forwarded-Proto $scheme;                proxy_set_header Upgrade $http_upgrade;                proxy_set_header Connection "upgrade";                proxy_read_timeout 3600s;                proxy_send_timeout 3600s;                client_max_body_size 10G;        }        location /error/ {                alias %home%/%user%/web/%domain%/document_errors/;        }        include %home%/%user%/conf/web/%domain%/nginx.conf_*;}EOF

И повторяем тоже самое для HTTPS (stpl):

cat > /usr/local/hestia/data/templates/web/nginx/nextcloud_proxy.stpl << 'EOF'#=========================================================================## Nextcloud External Proxy Web Domain Template (SSL)                      ## Custom template, proxies all requests including static assets           ## to an external backend, without local try_files fallback.               ##=========================================================================#server {        listen      %ip%:%proxy_ssl_port% ssl;        server_name %domain_idn% %alias_idn%;        error_log   /var/log/%web_system%/domains/%domain%.error.log error;        ssl_certificate     %ssl_pem%;        ssl_certificate_key %ssl_key%;        ssl_stapling        on;        ssl_stapling_verify on;        if ($anti_replay = 307) { return 307 https://$host$request\_uri; }        if ($anti_replay = 425) { return 425; }        include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;        location ~ /\.(?!well-known\/|file) {                deny all;                return 404;        }        location / {                proxy_pass http://<ВНЕШНИЙ_IP_РОУТЕРА>:56070;                proxy_http_version 1.1;                proxy_set_header Host $host;                proxy_set_header X-Real-IP $remote_addr;                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                proxy_set_header X-Forwarded-Proto $scheme;                proxy_set_header Upgrade $http_upgrade;                proxy_set_header Connection "upgrade";                proxy_read_timeout 3600s;                proxy_send_timeout 3600s;                client_max_body_size 10G;        }        location /error/ {                alias %home%/%user%/web/%domain%/document_errors/;        }        proxy_hide_header Upgrade;        include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;}EOF

Затем проверяем:

# должно быть без ошибок nginx -t# ребутаем nginxsystemctl reload nginx# проверяем, что статика грузится (должно быть 200)curl -I https://nextcloud.example.com/core/css/server.css

Вариант 3. Для тех, кто понимает что делает

Не повторяйте это дома!

  • A-запись nextcloud.example.com указывает прямо на домашний IP.

  • На роутере открыть порты 80 и 443 на TrueNAS.

  • В каталоге приложений TrueNAS ставится обратный прокси с Let’s Encrypt, например Nginx Proxy Manager, и проксирует домен на Nextcloud.

—

После выполнения одного из вариантов — уже можно попробовать открыть https://nextcloud.example.com/ в браузере и мы увидим заглушку от Nextcloud.

Шаг 4. Отключить DoS protection на роутере

Со включеным DoS protection роутер пропускает без задержек лишь несколько запросов, а всем последующим даёт таймаут и ставит в очередь. Выглядит это так, что вы открываете страницу логина в Nextcloud по адресу https://nextcloud.example.com/, а там простая текстовая заглушка и статика загружается несколько минут. В Dev Tools браузера видно, как во вкладке Network запросы к статике летят с большой задержкой друг за другом.

Отключение DoS protection на роутере Asus RT-N12

Отключение DoS protection на роутере Asus RT-N12
Проверяем, что статика ЛК Nextcloud грузится без задержек в Dev Tools

Проверяем, что статика ЛК Nextcloud грузится без задержек в Dev Tools

Шаг 5. Настройка разрешенных хостов в Nextcloud

Открываем Shell Nextcloud в Truenas и добавляем наш домен в список разрешенных:

php occ config:system:get trusted_domains

У меня показало 4 хоста:

127.0.0.1192.168.0.17localhostnextcloud

Значит добавляем новый хост с индексом 4:

php occ config:system:set trusted_domains 4 --value=nextcloud.example.com

Дальше добавляем:

php occ config:system:set overwrite.cli.url --value="https://nextcloud.example.com"php occ config:system:set overwriteprotocol --value="https"php occ config:system:set overwritehost --value="nextcloud.example.com"

Перезагружаем приложение Nextcloud в TrueNAS. Теперь при запросе https://nextcloud.example.com/ должен происходить редирект на /login и открываться страница логина в Nextcloud. Проверяем статику в Dev Tools, если открылась почти пустая заглушка. Если все сделано верно — мы сможем авторизоваться.

Теперь уже можно попробовать создать пару тестовых учеток и обменяться сообщениями. Но для звонков надо сделать еще кое-что.

Шаг 6. Поднимаем coturn-сервер

Далее надо поднять свой Turn (coturn) сервер. Без него работают только сообщения, со звонками нормально работать не будет. К сожалению в каталоге приложений TrueNAS нет готового решения, как в случае с RustDesk Relay например. Для этого:

Создаём датасет на TrueNAS: main_pool/coturn (Owner = root)

Через Shell (или SSH) кладём файл конфига:

mkdir -p /mnt/main_pool/coturn/conf nano /mnt/main_pool/coturn/conf/turnserver.conf

Вставляем конфиг, меняем пароль:

listening-port=3478tls-listening-port=5349listening-ip=192.168.0.17external-ip=<ВНЕШНИЙ_IP_РОУТЕРА>relay-ip=192.168.0.17min-port=49160max-port=49200verbosefingerprintlt-cred-mechuser=talkuser:<СЛОЖНЫЙ_ПАРОЛЬ>realm=example.comno-tlsv1no-tlsv1_1

Выставляем права:

chown -R root:root /mnt/main_pool/coturn

Создаем кастомное приложение в TrueNAS: Apps — Discover Apps — Custom App с таким конфигом:

Application Name* = coturnRepository* = coturn/coturnPull Policy* = Pull the image if it is not already present on the host.Command  turnserver  -c  /etc/coturn/turnserver.confRestart Policy* = Unless Stopped - Restarts the container irrespective of the exit code but stops restarting when the service is stopped or removed.Host Network = OnMount Path* = /etc/coturn/turnserver.confHost Path* = /mnt/main_pool/coturn/conf/turnserver.conf

Деплоим приложение и запускаем.

Шаг 7. Финальная настройка Nextcloud

Открываем с ПК Nextcloud — Administration settings — Talk — TURN servers, добавить сервер с префиксом turn:, адресом <ВНЕШНИЙ_IP_РОУТЕРА>:3478, секретом и протоколом UDP and TCP. Без этого шага звонки не смогут использовать ваш TURN. Там же стоит оставить стандартный STUN stun.nextcloud.com:443.

Дальше делаем тестовый звонок вне домашней сети. Всё должно работать.

Потом была проблема с тем, что нет уведомления о входящем звонке на айфоне (call kit не заработал) — перелогинился, выкинул приложение из памяти и всё заработало. Проверить доставку пуш-уведомлений можно командой (вводить в Shell приложения Nextcloud):

php occ notification:test-push --talk <USER>

Чем порадовал Nextcloud как мессенджер

  • Есть Screen Sharing для iPhone. Очень удобно объяснять родителям куда и что нажимать. 

  • Есть подключение по ссылке к миту для рандомных гостей.

  • Есть отдельное приложение Talk без лишних функций облака, кроссплатформенное (любая ОС, на ПК сделано на базе Electron).

  • Уведомелния приходят на Apple Watch.

  • Есть реакции на сообщения, редактирование отправленных, онлайн-статусы, избранное, видео-звонки. Что еще надо для счастья?

Ну и конечно же приложение есть во всех сторах (работают уведомления), не страшны случайные блокировки РКН. 

Вместо вывода

Теперь можно со спокойной душой отключить все уведомления в Telegram, чтобы не отвлекали от работы. А близкие достанут тебя через Nextcloud. Плюсом у вас появится возможность шарить файлы наружу из основного приложения Nextcloud — теперь он будет иметь основной адрес вашего хоста вместо IP.

Можно еще поработать над дополнительной безопасностью — у нас остался незащищенный участок между доменом и домашним роутером, а также стоит подумать над защитой нашего домена от посторонних глаз. Первое, что приходит на ум — посмотреть основные Request Headers от браузера и клиента Nextcloud и сделать их минимальную проверку в htaccess, остальным отдавать 403 код ответа.

Мой канал в Telegram — @barbolin, там я делюсь своими открытиями во всём, что касается работы.

ссылка на оригинал статьи https://habr.com/ru/articles/1101832/