Я устал от ситуации с мессенджерами и настроил звонки через 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 строчки:

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

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

  • proxy_module

  • proxy_http_module

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

apachectl -M | grep proxy

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

a2enmod proxy_http
systemctl 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

# ребутаем nginx
systemctl 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.1
192.168.0.17
localhost
nextcloud

Значит добавляем новый хост с индексом 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=3478
tls-listening-port=5349
listening-ip=192.168.0.17
external-ip=<ВНЕШНИЙ_IP_РОУТЕРА>
relay-ip=192.168.0.17
min-port=49160
max-port=49200
verbose
fingerprint
lt-cred-mech
user=talkuser:<СЛОЖНЫЙ_ПАРОЛЬ>
realm=example.com
no-tlsv1
no-tlsv1_1

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

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

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

Application Name* = coturn
Repository* = coturn/coturn
Pull Policy* = Pull the image if it is not already present on the host.
Command
  turnserver
  -c
  /etc/coturn/turnserver.conf
Restart Policy* = Unless Stopped - Restarts the container irrespective of the exit code but stops restarting when the service is stopped or removed.
Host Network = On
Mount Path* = /etc/coturn/turnserver.conf
Host 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, там я делюсь своими открытиями во всём, что касается работы.

Комментарии (1)


  1. warlinx
    30.10.2026 18:16

    айти которое мы заслужили - мамы папы школьные пет проекты в сми