Почта перестала быть просто почтой уже давно. Сегодня это центр деловой переписки, хранилище документов, канал уведомлений от десятков сервисов и одновременно сейф с личными данными. Привычные клиенты вроде Thunderbird или встроенного приложения в смартфоне отлично справляются со своей задачей, но у них есть одна особенность. Они привязаны к устройству. А что делать, если к почте нужен доступ с любого компьютера, из любого места, без установки лишнего софта? Ответ находится в категории веб-интерфейсов - и Rainloop здесь занимает особое место.
Почему Rainloop остаётся хорошим выбором для собственного почтового веб-интерфейса в 2024 году
Rainloop написан на PHP и работает как посредник между браузером пользователя и почтовыми серверами по протоколам IMAP и SMTP. Никаких собственных почтовых ящиков он не создаёт, никаких писем на сервере не хранит. Вся логика построена вокруг одной идеи - предоставить быстрый и красивый веб-интерфейс для уже существующих почтовых учёток. Это принципиально важный момент. Rainloop не конкурирует с Postfix или Dovecot, а дополняет их.
Вес у приложения смешной по меркам современного софта. Несколько десятков мегабайт и минимальные требования к ресурсам. На скромной виртуалке с одним ядром и гигабайтом оперативной памяти Rainloop чувствует себя уверенно и обслуживает десятки пользователей без задержек. Интерфейс отзывчивый, поддерживает горячие клавиши, умеет работать с несколькими учётными записями одновременно.
Ubuntu 22.04 Jammy Jellyfish в роли хостовой системы - решение логичное. LTS-релиз с поддержкой до 2027 года, свежие пакеты в репозиториях, устоявшаяся экосистема. Для почтового сервиса, который должен работать без сбоев, такой фундамент подходит идеально. Чего-то экзотического здесь не требуется, но внимания к деталям настройка потребует немало.
Подготовка сервера и настройка брандмауэра для защиты почтовых портов от посторонних
Любая серьёзная установка начинается с обновления системы. Банально, но без этого дальше двигаться нет смысла.
$ sudo apt update && sudo apt upgrade
Следом подтягиваются базовые утилиты, без которых пришлось бы скакать между пакетами. Возможно, часть уже установлена, но лишнего вреда от команды не будет.
$ sudo apt install wget curl nano unzip -y
Файрвол ufw в Ubuntu по умолчанию знает только про SSH. Для веб-интерфейса и почтовых соединений этого мало. Сначала смотрим текущее положение дел.
$ sudo ufw status
Ответ будет примерно таким.
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Теперь открываем HTTP и HTTPS - без них Rainloop работать не сможет.
$ sudo ufw allow http
$ sudo ufw allow https
Отдельно открываем порты для почтовых протоколов. 587 отвечает за отправку через SMTP с аутентификацией, 993 за безопасный IMAP, 465 за устаревший SMTPS, который до сих пор используется многими почтовыми провайдерами.
$ sudo ufw allow 587/tcp
$ sudo ufw allow 993/tcp
$ sudo ufw allow 465/tcp
Проверяем результат.
$ sudo ufw status
Установка свежей версии Nginx из официального репозитория и замена устаревшей сборки из стандартного дистрибутива
В Ubuntu 22.04 поставляется не самая новая версия Nginx. Для продакшена лучше подтянуть актуальный релиз из официального репозитория разработчика. Сначала добавляем ключ подписи.
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Прописываем сам репозиторий со стабильной веткой.
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
Обновляем списки пакетов.
$ sudo apt update
Ставим сам Nginx.
$ sudo apt install nginx
Проверяем, что установилась именно та версия, которая нужна.
$ nginx -v
Дальше начинается история с PHP. Rainloop капризничает с новыми версиями языка и требует именно PHP 8.0, хотя в Ubuntu 22.04 по умолчанию идёт 8.1. Спасает классический репозиторий Ondrej Sury, который держит в актуальном состоянии все живые ветки PHP.
$ sudo add-apt-repository ppa:ondrej/php
Ставим PHP 8.0 со всеми нужными расширениями. Курсор, обработка строк, работа с базой, XML - без них веб-клиент не заведётся.
$ sudo dnf install php8.0-fpm php8.0-curl php8.0-mbstring php8.0-mysql php8.0-xml php8.0-cli
Убеждаемся в корректной версии.
$ php --version
Проверяем, что сервис PHP-FPM живой.
$ sudo systemctl status php8.0-fpm
Тонкая настройка PHP-FPM под пересылку крупных вложений и смена пользователя на nginx
По умолчанию PHP разрешает загружать файлы размером до 2 мегабайт. Для электронной почты это катастрофически мало. Современные вложения легко переваливают за 10-15 мегабайт, а документы с картинками встречаются и тяжелее. Открываем основной конфиг.
$ sudo nano /etc/php/8.0/fpm/php.ini
Находим и меняем две строки. Значение 25 мегабайт - разумный компромисс между удобством и безопасностью.
upload_max_filesize = 25M
post_max_size = 25M
Теперь редактируем пул PHP-FPM, чтобы процессы запускались от пользователя nginx. Иначе веб-сервер не сможет читать сгенерированные файлы.
$ sudo nano /etc/php/8.0/fpm/pool.d/www.conf
Меняем пользователя и группу процесса.
...
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
; RPM: apache user chosen to provide access to the same directories as httpd
user = nginx
; RPM: Keep a group allowed to write in log dir.
group = nginx
...
И параметры сокета.
...
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions. The owner
; and group can be specified either by name or by their numeric IDs.
; Default Values: user and group are set as the running user
; mode is set to 0660
listen.owner = nginx
listen.group = nginx
...
Перезапускаем сервис.
$ sudo systemctl restart php8.0-fpm
Настройка базы данных MySQL и создание изолированного пользователя для работы Rainloop
MySQL в Ubuntu 22.04 идёт свежий и ставится одной командой.
$ sudo apt install mysql-server
Смотрим версию.
$ mysql --version
Для версий 8.0.28 и выше нужен небольшой хак. Заходим в консоль.
$ sudo mysql
Выставляем пароль для рута с использованием старого метода аутентификации. Это важно для корректной работы скрипта безопасной установки.
mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'YourPassword12!';
Выходим.
mysql> exit
Запускаем стандартный скрипт безопасности. Он задаст серию вопросов и поможет закрыть типовые дыры, через которые обычно проникают злоумышленники.
$ sudo mysql_secure_installation
При прохождении скрипта стоит согласиться с установкой компонента проверки паролей, выбрать уровень проверки 2 (самый строгий), отказаться от смены рутового пароля (его уже задали), убрать анонимных пользователей, запретить удалённый вход для рута, удалить тестовую базу и перезагрузить таблицы привилегий.
Теперь заходим снова с паролем.
$ sudo mysql -u root -p
Создаём базу под Rainloop.
mysql> CREATE DATABASE rainloop;
Отдельного пользователя для работы с этой базой. Принцип минимальных привилегий - один из краеугольных камней безопасности, и пренебрегать им не стоит.
mysql> CREATE USER 'rainuser'@'localhost' IDENTIFIED BY 'YourPassword23!';
Выдаём права только на одну базу.
mysql> GRANT ALL ON rainloop.* TO 'rainuser'@'localhost';
Применяем изменения и выходим.
mysql> FLUSH PRIVILEGES;
mysql> exit
Скачивание Rainloop распаковка файлов и выдача правильных прав на каталоги веб-приложения
Создаём каталог под веб-приложение.
$ sudo mkdir /var/www/html/rainloop -p
Скачиваем последнюю версию.
$ wget http://www.rainloop.net/repository/webmail/rainloop-community-latest.zip
Распаковываем архив прямо в нужный каталог.
$ sudo unzip rainloop-community-latest.zip -d /var/www/html/rainloop
Передаём владение веб-серверу.
$ sudo chown -R nginx:nginx /var/www/html/rainloop
Выставляем аккуратные права на директории и файлы. Такая схема - 755 для папок и 644 для файлов - считается безопасным стандартом для веб-приложений на PHP.
$ sudo find /var/www/html/rainloop -type d -exec chmod 755 {} \;
$ sudo find /var/www/html/rainloop -type f -exec chmod 644 {} \;
Получение сертификата Let's Encrypt и настройка виртуального хоста Nginx с современной криптографией
Работать с почтой по HTTP в 2024 году - моветон. Бесплатные сертификаты от Let's Encrypt решают вопрос шифрования без единой копейки затрат. Устанавливаем Snapd core.
$ sudo snap install core
Ставим Certbot.
$ sudo snap install --classic certbot
Создаём символическую ссылку.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Получаем сертификат для домена.
$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. -d rainloop.example.com
Генерируем параметры Диффи-Хеллмана на 4096 бит. Процесс не быстрый, на слабой виртуалке может занять несколько минут.
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
Чтобы обновление сертификата шло автоматически, добавляем хуки для остановки и запуска Nginx.
$ sudo nano /etc/letsencrypt/renewal/rainloop.example.com.conf
В конец файла вставляем.
pre_hook = systemctl stop nginx
post_hook = systemctl start nginx
Проверяем работоспособность обновления в режиме холостого запуска.
$ sudo certbot renew --dry-run
Теперь правим главный конфиг Nginx.
$ sudo nano /etc/nginx/nginx.conf
После строки include /etc/nginx/conf.d/*.conf добавляем параметр.
server_names_hash_bucket_size 64;
Создаём отдельный конфиг для Rainloop.
$ sudo nano /etc/nginx/conf.d/rainloop.conf
Внутри помещаем полноценную конфигурацию с редиректом на HTTPS, современными шифрами и OCSP stapling.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name rainloop.example.com;
root /var/www/html/rainloop;
index index.php;
client_max_body_size 25M;
access_log /var/log/nginx/rainloop.access.log;
error_log /var/log/nginx/rainloop.error.log;
ssl_certificate /etc/letsencrypt/live/rainloop.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/rainloop.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/rainloop.example.com/chain.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_keep_conn on;
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
location ^~ /data {
deny all;
}
}
# enforce HTTPS
server {
listen 80;
listen [::]:80;
server_name rainloop.example.com;
return 301 https://$host$request_uri;
}
Обращает на себя внимание блок с правилом deny all для каталога /data. Это критически важная деталь безопасности. В указанном каталоге Rainloop хранит конфигурационные файлы и данные пользователей, и прямой доступ к ним извне стал бы катастрофой. Проверяем синтаксис конфигурации.
$ sudo nginx -t
Перезапускаем веб-сервер.
$ sudo systemctl restart nginx
Первый вход в административную панель и подключение базы для хранения контактов
Административная панель открывается по специальному адресу. URL выглядит так.
https://rainloop.example.com/?admin
Дефолтные учётные данные для первого входа стандартные и нуждаются в немедленной замене.
- Логин admin
- Пароль 12345
- Переход в раздел Security
- Генерация нового длинного пароля
- Настройка раздела Contacts с выбором MySQL
- Ввод созданных ранее учётных данных базы
- Нажатие кнопки Test и проверка зелёной индикации подключения
После смены пароля можно переходить к настройке контактов. В разделе Contacts выбирается MySQL в выпадающем меню, вводятся данные созданного пользователя rainuser и пароль, затем проверяется соединение. Зелёная индикация кнопки Test говорит об успехе - таблицы создались, база готова принимать адресные записи.
Дальше остаётся добавить конкретные почтовые аккаунты. Rainloop умеет работать с любыми IMAP-серверами - от корпоративных решений до классических провайдеров. Достаточно знать адреса входящего и исходящего серверов, номера портов и реквизиты учётной записи.
Установка веб-клиента собственного размещения - история не только про удобство, но и про контроль. Кто владеет сервером, тот владеет данными. Никакие сторонние сервисы не читают заголовки писем, не показывают рекламу на основе содержимого переписки, не продают информацию рекламным сетям. Приватность в чистом виде, добытая собственными руками за час работы в терминале. А навык быстрого развёртывания таких сервисов - один из тех, что окупают себя многократно при любой смене места работы или запуске нового проекта.