
Предисловие
Если вам вдруг захотелось перестать пользоваться проприетарными мессенджерами типа Telegram, или просто просто посмотреть как это работает, то можете воспользоваться данной инструкцией.
По гайду можно настроить собственный сервер XMPP Prosody на Ubuntu 20.04, с веб-версией и закрытой регистрацией, аудио и видео вызовами.
Пароли, где они потребуются, ОБЯЗАТЕЛЬНО нужно записывать себе, чтобы их не забывать, лучше использовать менеджер паролей Keepass, а чтобы проще генерировать их, можно установить pwgen и запускать его командой:
pwgen -1 64 В интернете есть множество гайдов по настройке Prosody, но так как некоторые сайты постепенно или резко умирают - лишним не будет.
После настройки можно проверить свой сервер на https://compliance.conversations.im - результат должен быть 100%, то есть данная конфигурация сервера полностью соответствует современным видениям необходимых XEPов для работы с XMPP.
Железячная сторона вопроса - сервер кушает в районе 30-70мб ОЗУ на 30-100 пользоваталей, то есть для семьи и друзей вам хватит даже самой дешевой VPS или можете держать хост дома, если есть белый IP. Несмотря на высказывания про древность XMPP как технологии и перерерасход ресурсов, трафика это всё потребляет мало, работает стабильно даже в 2G сети, что в общем скорее хорошо, чем плохо.
Если у вас что-то не получилось, или нужны какие-нибудь пояснения - пишите в комментариях, обязательно отвечу.
Настройка домена у регистратора
Для начала нам нужно прописать DNS записи для домена у вашего регистратора домена
4 А-записи:
conference
proxy
pubsub
upload2 SRV записи:
_xmpp-client._tcp.example.com. example.com. 5 0 5222
_xmpp-server._tcp.example.com. example.com. 5 0 52692 TXT записи:
_xmppconnect "_xmpp-client-websocket=wss://example.com/xmpp-websocket"
_xmppconnect "_xmpp-client-xbosh=https://example.com/http-bind"NGINX+модули
Следом добавим репозиторий Prosody в систему, чтобы всегда иметь свежую версию серверной части:
определяем дистрибутив и добавляем репозиторий Prosody
echo deb http://packages.prosody.im/debian $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/prosody.list
sudo wget https://prosody.im/files/prosody-debian-packages.key -O/etc/apt/trusted.gpg.d/prosody.gpg
sudo apt updateи всё, теперь Prosody будет устанавливаться из репозитория разработчиков.
Установка NGINX и модуль загрузки файлов:
sudo apt install nginx libnginx-mod-http-perlСоздадим технические домены и заполним:
mkdir /var/www/tech
chown -R www-data:www-data /var/www/tech
sudo nano /etc/nginx/sites-enabled/example.com
---здесь и далее, после nano вставляем нижеидущий код
server {
server_name example.com;
location / {
root /var/www/tech;
#proxy_pass http://localhost:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_buffering off;
# proxy_protocol: on;
tcp_nodelay on;
}
}
location /http-bind {
proxy_pass http://localhost:5280/http-bind;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_buffering off;
tcp_nodelay on;
}
location /xmpp-websocket {
proxy_pass http://localhost:5280/xmpp-websocket;
proxy_http_version 1.1;
proxy_set_header Connection "Upgrade";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 900s;
}
location /register_web {
proxy_pass http://localhost:5280/register_web;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_buffering off;
tcp_nodelay on;
auth_basic "Private area";
auth_basic_user_file /var/www/protect/.htpasswd;
}
location /web {
proxy_pass http://localhost:5280/conversejs;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_buffering off;
tcp_nodelay on;
}
}Технические домены:
upload
sudo nano /etc/nginx/sites-enabled/upload.example.com
server {
listen 80;
server_name upload.example.com;
root /upload;
location / {
perl upload::handle;
}
}
pubsub
sudo nano /etc/nginx/sites-enabled/pubsub.example.com
server {
listen 80;
server_name pubsub.example.com;
root /var/www/tech;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}proxy
sudo nano /etc/nginx/sites-enabled/proxy.example.com
server {
listen 80;
server_name proxy.example.com;
root /var/www/tech;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}conference
sudo nano /etc/nginx/sites-enabled/conference.example.com
server {
listen 80;
server_name conference.example.com;
root /var/www/tech;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}Создаем пароль для закрытой регистрации пользователей:
perl -le 'print crypt("пароль_для_регистрации", "любые_символы_для_хэширования")'Далее записываем сгенерированный пароль и вписываем его в /var/www/protect/.htpasswd в формате login:password
mkdir /var/www/protect
sudo nano /var/www/protect/.htpasswd
login:passwordПодключаем модуль upload для NGINX:
mkdir /upload
chown -R www-data:www-data /upload/
mkdir -p /usr/local/lib/perl
wget -O /usr/local/lib/perl/upload.pm https://git.io/fNZgLДобавим модуль в конфиг:
sudo nano /etc/nginx/nginx.conf
perl_modules /usr/local/lib/perl;
perl_require upload.pm;
client_max_body_size 4096m;Впишем пароль в конфиг perl:
sudo nano /usr/local/lib/perl/upload.pm
CTRL+W пишем external_secret ENTER и вписываем пароль
$external_secret = 'ПАРОЛЬ'Перезапускаем NGINX и проверяем его работу:
sudo systemctl restart nginx.service
sudo systemctl status nginx.serviceЕсли стартанул без ошибок жмем CTRL+C и едем дальше
Сертификаты Let's Encrypt+БД
UPDATE: на сегодняшний день сертбот поставляется через snap, версия на питоне считается устаревшей, т.е вам нужно установить snap и certbot, далее получить сертификаты на 5 доменов, которые ниже по инструкции отсюда https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal
sudo apt install python3-certbot-nginx
certbot --nginx --rsa-key-size 4096 -d example.com
certbot --nginx --rsa-key-size 4096 -d upload.example.com
certbot --nginx --rsa-key-size 4096 -d conference.example.com
certbot --nginx --rsa-key-size 4096 -d proxy.example.com
certbot --nginx --rsa-key-size 4096 -d pubsub.example.comПосле этого можно зайти на домены и посмотреть, работают ли сертификаты
Далее устанавливаем базу данных и редактируем конфиг:
sudo apt install postgresql postgresql-contrib
sudo nano /etc/postgresql/14/main/postgresql.conf
и там вписываем listen_addresses = '127.0.0.1'(внимание, версия Postgesql может быть иная, от этого зависит расположение конфига в цифре, вместо 14 может быть например 10 или 16)
Перезапускаем БД:
sudo systemctl restart postgresql.serviceСоздаем пользователя БД:
su - postgres
createuser --pwprompt prosodyuserСоздаем саму БД:
psql
и вставляем это
CREATE DATABASE prosodyuser
OWNER prosodyuser;Выходим из БД \q
Установка Prosody
sudo apt install prosody lua-event lua-dbi-postgresqlУстанавливаем модули:
(в версии 12 модули вроде как ставятся по умолчанию, но я не разбирался в таких тонкостях)
cd /opt
sudo apt install mercurial
hg clone https://hg.prosody.im/prosody-modules/ prosody-modules
chown -R prosody:prosody /opt/prosody-modules
Создадим директорию для PID файла:
mkdir /var/run/prosody
chown -R prosody:prosody /var/run/prosodyСоздаем ключ Диффи-Хелмана:
cd /etc/prosody/certs/
openssl dhparam -out dh-2048.pem 2048
chown prosody:prosody dh-2048.pem
chmod u=rw,go= dh-2048.pemУстановим пакет для импорта сертификатов Prosody:
sudo apt install lua-secТеперь переходим к настройке конфига самого Prosody:
sudo nano /etc/prosody/prosody.cfg.luaИ туда вставляем следующий конфиг:
pidfile = "/var/run/prosody/prosody.pid";
---администраторы сервера---
admins = { "user@example.com" }
---Отключаем регистрацию через клиенты---
allow_registration = false
---Хранить всё в БД---
default_storage = "sql"
sql = {
driver = "PostgreSQL";
database = "prosodyuser";
host = "127.0.0.1";
port = 5432;
username = "prosodyuser";
password = "ПАРОЛЬ_ОТ_ПОЛЬЗОВАТЕЛЯ_БД";
}
sql_manage_tables = true
---Сертификаты---
certificates = "/etc/prosody/certs"
---http
http_host = "127.0.0.1"
http_ports = { 5280 }
https_ports = { }
http_interfaces = { "127.0.0.1" }
trusted_proxies = { "127.0.0.1" }
---Методы шифрования---
ssl = {
--key = "/etc/prosody/certs/example.com.key";
--certificate = "/etc/prosody/certs/example.com.crt";
options = { "no_sslv3", "no_sslv2", "no_ticket", "no_compression", "cipher_server_preference", "single_dh_use", "single_ecdh_use" };
ciphers="EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:AES256-GCM-SHA384";
protocol = "tlsv1_1+";
dhparam = "/etc/prosody/certs/dh-2048.pem";
}
---Обязательное шифрование Клиент сервер и Сервер и сервер
c2s_require_encryption = true;
s2s_require_encryption = true;
s2s_secure_auth = true;
---Модули---
plugin_paths = { "/opt/prosody-modules/" }
---Глобальные модули---
modules_enabled = {
-- Wichtige Module
"roster";
"saslauth";
"tls";
"dialback";
"disco";
-- Empfohlene Module
"private";
"profile";
"offline";
"admin_adhoc";
"admin_telnet";
--"http_files";
"legacyauth";
"version";
"uptime";
"time";
"ping";
"register";
"posix";
"bosh";
"announce";
-- "proxy65";
"pep";
"smacks";
"carbons";
"blocklist";
"csi";
"csi_battery_saver";
"mam";
"lastlog";
"list_inactive";
"cloud_notify";
"compat_dialback";
"throttle_presence";
"log_auth";
"server_contact_info";
"websocket";
"bookmarks";
"privacy_lists";
--"pubsub";
"filter_chatstates";
"vcard_legacy";
"pinger";
-- "turncredentials";
"http_upload_external";
"register_web";
"http_altconnect";
"conversejs";
"turn_external";
};
---Выключаем логи---
log = {
--debug = "/var/log/prosody/debug.log";
--info = "/var/log/prosody/info.log";
--warn = "/var/log/prosody/warn.log";
--error = "/var/log/prosody/error.log";
}
---Настройка архива сообщений, можно выставить в днях, или отключить вовсе---
default_archive_policy = true;
archive_expires_after = "1d";
---EXTERNAL HTTP UPLOAD---
http_upload_external_base_url = "https://upload.example.com/"
http_upload_external_secret = "ПАРОЛЬ_ОТ_UPLOAD"
http_upload_external_file_size_limit = 536870912 --4Gb
---шаблон для веб регистрации---
register_web_template = "/etc/prosody/register-templates/Prosody-Web-Registration-Theme"
---Websocket---
consider_websocket_secure = true;
--cross_domain_websocket = true;
---настройки веб клиента---
conversejs_options = {
debug = false;
view_mode = "fullscreen";
}
conversejs_tags = {
-- Load libsignal-protocol.js for OMEMO support (GPLv3; be aware of licence implications)
[[<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>]];
}
---cross_domain_bosh = true;
consider_bosh_secure = true;
---TURN STUN для звонков---
turn_external_host = "example.com"
turn_external_port = 3478
turn_external_secret = "ПАРОЛЬ"
contact_info = {
abuse = { "mailto:user@example.com", "xmpp:user@example.com" };
admin = { "mailto:user@example.com", "xmpp:user@example.com" };
feedback = { "mailto:user@example.com", "xmpp:user@example.com" };
sales = { "mailto:user@example.com", "xmpp:user@example.com" };
security = { "mailto:user@example.com", "xmpp:user@example.com" };
support = { "mailto:user@example.com", "xmpp:user@example.com" };
};
---domain---
c2s_direct_tls_ports = { 5223 }
c2s_direct_tls_ssl = {
certificate = "/etc/prosody/certs/example.com.crt";
key = "/etc/prosody/certs/example.com.key";
}
VirtualHost "example.com"
http_host = "example.com"
http_external_url = "https://example.com/"
authentication = "internal_hashed"
Component "conference.example.com" "muc"
name = "example.com chatrooms"
restrict_room_creation = "local"
muc_room_default_public = false
muc_room_default_members_only = true
muc_room_default_language = "ru"
max_history_messages = 500
modules_enabled = {
"muc_mam",
"vcard_muc",
"muc_cloud_notify";
}
muc_log_by_default = true
disco_items = {
{ "conference.example.com", "example.com MUC" };
}
Component "pubsub.example.com" "pubsub"
Component "proxy.example.com" "proxy65"
proxy65_acl = { "example.com" }
После изменения конфига перезапускаем Prosody:
sudo systemctl restart prosody.service
sudo systemctl status prosody.serviceИмпортируем сертификаты, которые создали с помощью Let's Encrypt:
sudo prosodyctl --root cert import /etc/letsencrypt/liveСоздаем веб интерфейс для регистрации:
mkdir /etc/prosody/register-templates/
cd /etc/prosody/register-templates
git clone https://gitlab.com/mimi89999/Prosody-Web-Registration-Theme.gitНастройка звонков
Установка Coturn для звонков через Conversation и Dino
sudo apt install coturnДалее правим конфиг:
sudo nano /etc/turnserver.conf
use-auth-secret
static-auth-secret=ПАРОЛЬ_ДЛЯ_КОТЮРНА
realm=example.com
# VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.
no-tcp-relay
# don't let the relay ever try to connect to private IP address ranges within your network (if any)
# given the turn server is likely behind your firewall, remember to include any privileged public IPs too.
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
# special case the turn server itself so that client->TURN->TURN->client flows work
allowed-peer-ip=10.0.0.1
# consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS.
user-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.
total-quota=1200И еще один:
sudo nano /etc/default/coturn
расскоментируйте строчку enable 1
и
sudo systemctl enable --now coturn
sudo systemctl restart coturn
sudo systemctl status coturnИмпорт сертификатов с помощью Cron:
sudo crontab -e
0 5 * * 1 /usr/bin/certbot renew --renew-hook "prosodyctl --root cert import /etc/letsencrypt/live" --quietВключаем файрволл:
sudo ufw allow 3478
sudo ufw allow 5222
sudo ufw allow 5000
sudo ufw allow 5269
sudo ufw allow ssh
sudo ufw allow 443
sudo ufw allow 80
sudo ufw enable
Удаление файлов пользователей
Так как автоочистки файлов нет, можно удалять их через Cron в зависимости от времени:
sudo nano /etc/cron.daily/deletefilesВставляем:
#!/bin/sh
find /upload/ -type f -mtime +30 -exec rm -v {} \;После этого скрипт будет проверять даты файлов и удалять все что старше 30 дней
Делаем файл исполняемым:
chmod +x deletefilesРегистрация пользователей происходит на странице https://example.com/register_web, если вы предварительно выслали им логин и пароль для захода
Веб клиент Converse.js находится тут https://example.com/web
Клиенты
Клиенты для смартфонов:
Conversations https://conversations.im/ Android
Blabber https://blabber.im/en.html Android
Monal https://monal.im/ iOS
Siskin https://siskin.im/ iOS
Клиенты для ПК:
Gajim https://gajim.org/ GNU/Linux и Windows
DINO https://dino.im/ GNU/Linux
Web клиент:
Статья распространяется под лицензией GNU FDL 1.3, полный текст лицензии доступен на https://www.gnu.org/licenses/fdl-1.3.html
Комментарии
17:11
20:06
10:25
17:49
18:11
18:16
18:17
18:28
21:03
08:18
09:36
12:21
16:54
...
:(
17:17
17:47
17:22
04:59
07:48
08:09
10:29
2) Не надо скрещивать в гибрид классические "в холодильнике мышь повесилась" с "за компанию и жид удавился".
3) С остальными тезисами полностью согласен.
:)
12:04
12:07
12:28
14:14
nginx: [emerg] unexpected end of file, expecting "}" in /etc/nginx/sites-enabled/testtest.ru:54
nginx: configuration file /etc/nginx/nginx.conf test failed
14:27
http {
##
# Basic Settings
##
perl_modules /usr/local/lib/perl;
perl_require upload.pm;
client_max_body_size 4096m;
19:18
07:38
05:41
02:37
17:22
19:56
17:21
15:24
20:51
10:39
02:22
Спасибо.
15:48
09:50
Модуль lua-dbi-sqlite3 установлен, в конфиге раскоментировал строку с сиквеллайтом, указал storage = sql, ничего не получается.
15:44
11:29
Couldn't write pidfile at /run/prosody/prosody.pid; /run/prosody/prosody.pid: No such file or directory
Error in SQL transaction: commit failed
База на sqlite, автоматом создается.
13:53
15:10
15:39
18:25
У самих разработчиков Prosody поддерживается дистрибутив на 11 Дебиане, но в Астре можно раскатить через репозиторий Дебиана 10 (на вики описано, я так и ставил Prosody).
Сейчас запустил с внутренней базой (не SQlite3) все работает, самоподписанные сертификаты подтянулись. Не понятно как общий список контактов (ростер) для всех сделать. Добавлял файл sharedgroups.txt как в мануале, прописывал модуль "groups" и строчку где брать текст с группами groups-file = "/etc/prosody/sharedgroups.txt" - не видят пользователи друг друга. В ежабере прямо в веб-админке можно ткнуть группу @all@, а как в Просодии прописать, чтобы она видела, не получается пока.
Спасибо за статью, я периодически к ней возвращаюсь чтобы почерпнуть разные части конфига, приходится листать разные сайты. Пока нужен конечно локальный чат, внутренний для предприятия, внутри сети.
16:36
А у вас работают голосовые звонки? Проверил Ejabberd и Prosody и ни в какую не могу заставить их обрабатывать звук.
11:51
23:59
Feb 28 20:23:32 prosody systemd[1]: Starting A high performance web server and a reverse proxy server...
Feb 28 20:23:32 prosody nginx[10047]: nginx: [emerg] "location" directive is not allowed here in /etc/nginx/sites-enabled/examle.com:14
Feb 28 20:23:32 prosody nginx[10047]: nginx: configuration file /etc/nginx/nginx.conf test failed
Feb 28 20:23:32 prosody systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Feb 28 20:23:32 prosody systemd[1]: nginx.service: Failed with result 'exit-code'.
Feb 28 20:23:32 prosody systemd[1]: Failed to start A high performance web server and a reverse proxy server.
Чего ему надо? Спасибо за помощь!
19:33
server {
server_name домен;
location / {
т.е там отступы)
UPD: парсер скушал форматирование в комментарии, в статье не скушал вроде - посмотрите внимательно на форматирование)
21:12
21:18
Если через TOR его можно отправить через torsocks/torify то научить понимать onion я его не смог.
08:29
12:17
19:25
19:55
20:34
23:02
Собственно внимательно изучаем данную часть.
https://www.consultant.ru/document/cons_doc_LAW_61798/9ab7abe2b9fe407f507610f7e6e14a951d575585/
01:00
https://its.1c.ru/db/stafft#content:35149:hdoc
Как только к нему будут подключены другие пользователи из интернета, тогда попадаете под действие 149-фз.
01:45
12:26
12:32
11:57
Я тоже когда-то пользовал джаббер . Теперь выкинув Телегу и,найдя замены без симок и регов ,опять вернулся .
Но я так - только со своими домочадцами общаюсь, чтоб без рекламы и посторонних.
Думал и сервак свой настроить ,но для этого надо ,чтоб какой-то комп работал постоянно. Передумал ))
00:13
13:21
11:35
Токс неработоспособен так же как и остальные "иже с ним" ))
Но делают для того ,чтоб база на месте оставалась , а не "где-то там"
Конечно,тут описано ,как терминале пальцы ломать ,чтоб установить.
Но сервер проще взять Openfire и настроить в 3 клика )
15:28
Я только начинаю осваивать шаманство с линукс и попытался настроить сервер по вашей статье и у меня возникло несколько затруднений. Надеюсь вы сможете мне помочь.
В данной части: "Создадим технические домены и заполним:"
Участок:
"server {
server_name example.com;
location / {
root /var/www/tech;
#proxy_pass http://localhost:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_buffering off;
# proxy_protocol: on;
tcp_nodelay on;
}
}
location /http-bind {
proxy_pass http://localhost:5280/http-bind"
Последняя скобка не лишняя? Потому что при попытке запуска nginx у меня выходила ошибка. Я ее убрал и статус стал норма.
В этом моменте у меня возник вопрос.
"Создаем пароль для закрытой регистрации пользователей:
perl -le 'print crypt("пароль_для_регистрации", "любые_символы_для_хэширования")'
Я придумал пароль и написал любые символы и при выполнении команды, не какого ответа нет, просто новая, пустая строка с приглашением #.
"Далее записываем сгенерированный пароль и вписываем его в /var/www/protect/.htpasswd в формате login:password" - в итоге что нужно сюда вписать за место password если не было "сгенерированный пароль"?
Далее. Использую свой домен, просто не указываю. Здесь https://example.com/register_web, при переходе на эту страницу, получаю запрос на логин и пароль. Подскажите, в какой части мы его указывали или еще не создали данного пользователя?
А по данному пути https://example.com/web получаю "404 Not Found" - и переход в адресной строке: https://example.com/conversejs/.
При попытке проверить сервер, ответ "Error 404 ¯\_(⊙︿⊙)_/¯ Credentials unavailable for"
Создал через терминал пользователя и зашел в приложении под ним. Значит все работает на половину и нужно чинить веб часть?
15:45
Создаем пользователя БД:
------------------------------------------------------
su - postgres
createuser --pwprompt prosodyuser
16:48
Создадим технические домены и заполним:
sudo nano /etc/nginx/sites-enabled/example.com
Я зашел на сервер по фтп, чтобы проверить, что создалось по данному пути и есть ли там что-то. Обнаружил файлы, которые имеют формат (Имя и Тип), и получилось, что они имеют Имя:example и Тип:com, Имя:upload.example и Тип:com и тд.
Это наталкивает меня на мысль, что у данных файлов\тех домены не верное расширение. Я ошибаюсь или так должно быть, какое должно быть расширение имен?
18:06
Заглянул я в файл nginx - error.log, а там и прояснилась ситуация.
[error] 4101#4101: *1 directory index of "/var/www/tech/" is forbidden
[error] 4101#4101: *1 "/var/www/tech/conversejs/index.html" is not found
[error] 2005#2005: *48 open() "/upload/favicon.ico" failed
[error] 2005#2005: *48 directory index of "/upload/" is forbidden
[error] 12301#12301: *29 open() "/var/www/tech/@vite/env" failed (2: No such file or directory)
[error] 12301#12301: *30 open() "/var/www/tech/actuator/env" failed (2: No such file or directory)
[error] 12301#12301: *31 open() "/var/www/tech/server" failed (2: No such file or directory)
[error] 12301#12301: *34 open() "/var/www/tech/.vscode/sftp.json" failed (2: No such file or directory)
[error] 12301#12301: *39 open() "/var/www/tech/about" failed (2: No such file or directory)
[error] 12301#12301: *43 open() "/var/www/tech/debug/default/view" failed (2: No such file or directory)
[error] 12301#12301: *45 open() "/var/www/tech/v2/_catalog" failed (2: No such file or directory)
[error] 12301#12301: *47 open() "/var/www/tech/ecp/Current/exporttool/microsoft.exchange.ediscovery.exporttool.application" failed (2: No such file or directory)
.......... И так далее.
Папка по пути "/var/www/tech/" пуста.
Следавал вашей инструкции, но похоже что-то упустил.
Прошу вашей помощи.