Почтовый сервер nginx. Настройка NGINX для проксирования почты

This article will explain how to configure NGINX Plus or NGINX Open Source as a proxy for a mail server or an external mail service.

Introduction

NGINX can proxy IMAP, POP3 and SMTP protocols to one of the upstream mail servers that host mail accounts and thus can be used as a single endpoint for email clients. This may bring in a number of benefits, such as:

  • easy scaling the number of mail servers
  • choosing a mail server basing on different rules, for example, choosing the nearest server basing on a client’s IP address
  • distributing the load among mail servers
Prerequisites

    NGINX Plus (already includes the Mail modules necessary to proxy email traffic) or NGINX Open Source compiled the Mail modules using the --with-mail parameter for email proxy functionality and --with-mail_ssl_module parameter for SSL/TLS support:

    $ ./configure --with-mail --with-mail_ssl_module --with-openssl=[ DIR] /openssl-1.1.1

    IMAP, POP3 and/or SMTP mail servers or an external mail service

Configuring SMTP/IMAP/POP3 Mail Proxy Servers

In the NGINX configuration file:

mail { #... }

mail { server_name mail.example.com ; #... }

mail { server_name mail.example.com ; auth_http localhost : 9000 /cgi-bin/nginxauth.cgi ; #... }

Alternatively, specify whether to inform a user about errors from the authentication server by specifying the proxy_pass_error_message directive. This may be handy when a mailbox runs out of memory:

mail { server_name mail.example.com ; auth_http localhost : 9000 /cgi-bin/nginxauth.cgi ; proxy_pass_error_message on ; #... }

Configure each SMTP, IMAP, or POP3 server with the server blocks. For each server, specify:

  • the port number that correspond to the specified protocol with the listen directive
  • the protocol with the protocol directive (if not specified, will be automatically detected from the port specified in the listen directive)
  • permitted authentication methods with imap_auth , pop3_auth , and smtp_auth directives:

server { listen 25 ; protocol smtp ; smtp_auth login plain cram-md5 ; } server { listen 110 ; protocol pop3 ; pop3_auth plain apop cram-md5 ; } server { listen 143 ; protocol imap ; }

Setting up Authentication for a Mail Proxy

Each POP3/IMAP/SMTP request from the client will be first authenticated on an external HTTP authentication server or by an authentication script. Having an authentication server is obligatory for NGINX mail server proxy. The server can be created by yourself in accordance with the NGINX authentication protocol which is based on the HTTP protocol.

If authentication is successful, the authentication server will choose an upstream server and redirect the request. In this case, the response from the server will contain the following lines:

HTTP/1.0 200 OK Auth-Status: OK Auth-Server: # the server name or IP address of the upstream server that will used for mail processing Auth-Port: # the port of the upstream server

If authentication fails, the authentication server will return an error message. In this case, the response from the server will contain the following lines:

HTTP/1.0 200 OK Auth-Status: # an error message to be returned to the client, for example “Invalid login or password” Auth-Wait: # the number of remaining authentication attempts until the connection is closed

Note that in both cases the response will contain HTTP/1.0 200 OK which might be confusing.

For more examples of requests to and responses from the authentication server, see the ngx_mail_auth_http_module in NGINX Reference documentation .

Setting up SSL/TLS for a Mail Proxy

Using POP3/SMTP/IMAP over SSL/TLS you make sure that data passed between a client and a mail server are secured.

To enable SSL/TLS for the mail proxy:

Make sure your NGINX is configured with SSL/TLS support by typing-in the nginx -V command in the command line and then looking for the with --mail_ssl_module line in the output:

$ nginx -V configure arguments: ... with--mail_ssl_module

Make sure you have obtained server certificates and a private key and put them on the server. A certificate can be obtained from a trusted certificate authority (CA) or generated using an SSL library such as OpenSSL.

ssl on ;

starttls on ;

Add SSL certificates: specify the path to the certificates (which must be in the PEM format) with the ssl_certificate directive, and specify the path to the private key in the ssl_certificate_key directive:

mail { #... ssl_certificate /etc/ssl/certs/server.crt ; ssl_certificate_key /etc/ssl/certs/server.key ; }

You can use only strong versions and ciphers of SSL/TLS with the ssl_protocols and ssl_ciphers directives, or you can set your own preferable protocols and ciphers:

mail { #... ssl_protocols TLSv1 TLSv1.1 TLSv1.2 ; ssl_ciphers HIGH:!aNULL:!MD5 ; }

Optimizing SSL/TLS for Mail Proxy

These hints will help you make your NGINX mail proxy faster and more secure:

Set the number of worker processes equal to the number of processors with the worker_processes directive set on the same level as the mail context:

worker_processes auto ; mail { #... }

Enable the shared session cache and disable the built-in session cache with the auto ; mail { server_name mail.example.com ; auth_http localhost : 9000 /cgi-bin/nginxauth.cgi ; proxy_pass_error_message on ; ssl on ; ssl_certificate /etc/ssl/certs/server.crt ; ssl_certificate_key /etc/ssl/certs/server.key ; ssl_protocols TLSv1 TLSv1.1 TLSv1.2 ; ssl_ciphers HIGH:!aNULL:!MD5 ; ssl_session_cache shared:SSL:10m ; ssl_session_timeout 10m ; server { listen 25 ; protocol smtp ; smtp_auth login plain cram-md5 ; } server { listen 110 ; protocol pop3 ; pop3_auth plain apop cram-md5 ; } server { listen 143 ; protocol imap ; } }

In this example, there are three email proxy servers: SMTP, POP3 and IMAP. Each of the servers is configured with SSL and STARTTLS support. SSL session parameters will be cached.

The proxy server uses the HTTP authentication server – its configuration is beyond the scope of this article. All error messages from the server will be returned to clients.

Nginx - небольшой по размерам, очень быстрый, достаточно функциональный веб сервер и почтовый прокси-сервер, разработчик Игорь Сысоев (rambler.ru). Из-за очень маленького потребления ресурсов системы и скорости работы, а так-же гибкости конфигурирования, веб сервер Nginx часто используется в качестве фронтэнда к более тяжеловесным серверам, такими как Apache , в проектах с высокой нагрузкой. Классическим вариантом является связка, Nginx - Apache - FastCGI . Работая в такой схеме, сервер Nginx , принимает все запросы приходящие по HTTP, и в зависимости от конфигурации и собственно самого запроса, решает, обработать-ли запрос самому и отдать клиенту готовый ответ или отправить запрос на обработку, одному из бакэндов (Apache или FastCGI ).

Как известно, сервер Apache, каждый запрос обрабатывает в отдельном процессе (потоке), которые надо сказать, отжирают довольно НЕмаленькое количество системных ресурсов, если таких процессов 10-20, ерунда, а если их 100-500 и больше, системе становится не весело.

Попробуем представить подобную ситуацию. Предположим, на Apache приходит 300 HTTP запросов от клиентов, 150 клиентов сидят на быстрых выделенных линиях, а другие 150, на сравнительно медленных интернет каналах, пусть даже не на модемах. Что происходит в данной ситуации? А происходит следующее, веб сервер Apache, что-бы обработать эти 300 соединений, создает на каждое по процессу (потоку), контент он сгенерит быстро, и 150 быстрых клиентов тут-же заберут результат своих запросов, процессы их обслуживавшие будут убиты а ресурсы высвобождены, а 150 медленных, и забирать результаты своих запросов будут медленно, в силу неширокого интернет канала, в результате чего в системе будет висеть 150 процессов Apache , ожидающих, когда-же клиенты заберут сгенерированный веб сервером контент, пожирая массу системных ресурсов. Естественно ситуация гипотетическая, но суть думаю понятна. Исправить вышеописанную ситуацию и помогает связка . Прочитав весь запрос от клиента, он передает его на обработку Apache , который в свою очередь генерирует контент и максимально быстро возвращает готовый ответ в Nginx, после чего может со спокойной совестью прибить процесс и освободить занимаемые им системные ресурсы. веб сервер Nginx, получив результат запроса от Apache , записывает его в буфер или вообще в файл на диске и может сколь угодно долго отдавать его медленным клиентам, при этом его рабочие процессы едят так мало ресурсов что.. "об этом даже смешно говорить" ©. :) Такая схема, существенно экономит системные ресурсы, повторюсь, но рабочие процессы Nginx потребляют мизерное количество ресурсов, это тем-более актуально для больших проектов.

И это только малая часть того, что умеет сервер Nginx, не стоит забывать про возможности кэширования данных и работу с memcached . Приведу список основных функциональных возможностей веб сервера Nginx.

Функционал сервера Nginx в качестве HTTP сервера
  • Обработка статического контента, индексные файлы, листинг директорий, кэш дескрипторов открытых файлов;
  • Акселерированное проксирование с кэширование, распределение нагрузки и отказоустойчивостью;
  • Акселерированная поддержка FastCGI серверов с кэшированием, распределением нагрузки и отказоустойчивостью;
  • Модульная структура, поддержка различных фильтров (SSI, XSLT, GZIP, докачка, chunked ответы);
  • Поддержка SSL и расширения TLS SNI;
  • Ip-based или Name-based виртуальные сервера;
  • Работа с KeepAlive и pipelined соединениями;
  • Возможность конфигурирования любых таймаутов а так-же количества и размеров буферов, на уровне сервера Apache ;
  • Выполнение различных действий в зависимости от адреса клиента;
  • Изменение URI с помощью регулярных выражений;
  • Специальные страницы ошибок для 4хх и 5хх;
  • Ограничение доступа на основе адреса клиента или по паролю;
  • Настройка форматов лог-файлов, ротация логов;
  • Ограничение скорости ответа клиенту;
  • Ограничение количества одновременных подключений и запросов;
  • Поддержка методов PUT, DELETE, MKCOL, COPY и MOVE;
  • Изменение настроек и обновление сервера без остановки работы;
  • Встроенный Perl ;
Функционал сервера Nginx, в качестве почтового прокси-сервера
  • Форвардинг на IMAP/POP3 бакэнд, используя внешний HTTP сервер аутентификации;
  • Проверка SMTP пользователя на внешнем HTTP сервере аутентификации и форвардинг на внутренний SMTP сервер;
  • Поддержка следующих способов аутентификации:
    • POP3 - USER/PASS, APOP, AUTH LOGIN/PLAIN/CRAM-MD5;
    • IMAP - LOGIN, AUTH LOGIN/PLAIN/CRAM-MD5;
    • SMTP - AUTH LOGI/ PLAIN/CRAM-MD5;
  • Поддержка SSL;
  • поддержка STARTTLS и STLS;
Операционные системы и платформы, поддерживаемые веб сервером Nginx
  • FreeBSD, с 3 по 8 - платформы, i386 и amd64;
  • Linux, с 2.2 по 2.6 - платформа i386; Linux 2.6 - amd64;
  • Solaris 9 - платформы i386 и sun4u; Solaris 10 - платформы i386, amd64 и sun4v;
  • MacOS X платформы ppc, i386;
  • Windows XP, Windows Server 2003; (на данный момент в стадии бета-тестирования)
Архитектура и масштабируемость сервера Nginx
  • Основной (master) процесс, несколько (настраивается в файле конфигурации) рабочих процессов, работающих под непривилегированным пользователем;
  • Поддержка следующих методов обработки соединений:
    • select - стандартный метод. Соответствующий модуль Nginx собирается автоматически, если на данной платформе не найдено более эффективного метода. Можно принудительно включить или отключить сборку данного модуля с помощью параметров конфигурации --with-select_module или --without-select_module.
    • poll - стандартный метод. Соответствующий модуль Nginx собирается автоматически, если на данной платформе не найдено более эффективного метода. Можно принудительно включить или отключить сборку данного модуля с помощью параметров конфигурации --with-poll_module или --without-poll_module.
    • kqueue - эффективный метод, используемый в операционных системах FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 и MacOS X. При использовании на двухпроцессорных машинах с MacOS X может вызвать kernel panic.
    • epoll - эффективный метод, используемый в Linux 2.6+. В некоторых дистрибутивах, например SuSE 8.2, есть патчи для поддержки epoll ядром 2.4.
    • rtsig - real time signals , эффективный метод, используемый в Linux 2.2.19+. По-умолчанию в очереди для всей системы, не может находиться более 1024 сигналов. Этого мало для серверов с высокой нагрузкой, размер очереди нужно увеличить с помощью параметра ядра /proc/sys/kernel/rtsig-max. Однако, начиная с Linux 2.6.6-mm2, этот параметр отсутствует, вместо этого у каждого процесса существует отдельная очередь сигналов, размер которой определяется с помощью RLIMIT_SIGPENDING.
    • При переполнении очереди, сервер nginx сбрасывает её и обрабатывает соединения с помощью метода poll до тех пор, пока ситуация не придет в норму.
    • /dev/poll - эффективный метод, поддерживается в операционных системах Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ и Tru64 UNIX 5.1A+.
    • eventport - event ports , эффективный метод, используемый в Solaris 10. Перед использованием, необходимо установить патч, во избежания kernel panic.
  • Использование возможностей метода kqueue, таких как EV_CLEAR, EV_DISABLE (для временного выключения события), NOTE_LOWAT, EV_EOF, число доступных данных, коды ошибок;
  • Работа с sendfile (FreeBSD 3.1+, Linux 2.2.+, Mac OS X 10.5+), sendfile64 (Linux 2.4.21+) и sendfilev (Solaris 8 7/01+);
  • Поддержка accept-фильтров (FreeBSD 4.1+) и TCP_DEFER_ACCEPT (Linux 2.4+);
  • На 10 000 неактивных HTTP keep-alive соединений тратится примерно 2.5M памяти;
  • Минимальное количество операций копирования данных;

iRedMail - это готовая сборка почтового сервера с открытым исходным кодом. В основе сборки лежит SMTP-сервер Postfix (Mail Transfer Agent, сокращенно MTA). Так же в сборку входят: Dovecot, SpamAssassin, Greylist, ClamAV, SOGo Roundcube, NetData и NGINX.

Dovecot - IMAP/POP3 сервер.

Spamassassin - средство фильтрации спама.

Greylist - средство борьбы со спамом на основе серых списков.

ClamAV - антивирус.

Roundcube и SOGo - веб-клиенты для работы с электронной почтой.

NetData - программа мониторинга работы сервера в реальном времени.

Nginx - веб-сервер.

Поддерживает операционные системы: CentOS 7 , Debian 9 , Ubuntu 16.04/18.04 , FreeBSD 11/12 и OpenBSD 6.4 .

iRedMail имеет платную и бесплатную версии, которые отличаются друг от друга функционалом собственного веб-интерфейса почтовой сборки iRedAdmin. В бесплатной версии можно только создавать домены, почтовые ящики пользователей и администраторов. Если вам необходимо создать алиас, то сделать это в бесплатной версии через iRedAdmin уже не получится. К счастью есть бесплатное решение, которое называется PostfixAdmin, позволяющее это реализовать. PostfixAdmin легко встраивается в iRedMail и прекрасно с ним работает.

Установка

Для установки нам понадобится одна из перечисленных выше операционных систем. Я буду использовать Ubuntu Server 18.04. Так же у вас должно быть купленное доменное имя и настроенная DNS зона. Если вы используете DNS сервера вашего доменного регистратора, то необходимо в разделе управления доменной зоной сделать две записи: A и MX. Так же можно использовать свой собственный DNS, настроив делегирование в личном кабинете регистратора вашего доменного имени.

Настройка доменной зоны при использовании DNS регистратора

Обратите внимание! Время вступления настроек DNS в силу от нескольких часов до одной недели. Пока настройки не вступят в силу почтовый сервер не будет корректно работать.

Для установки скачиваем с сайта iRedMail актуальную версию. На текущий момент это 0.9.9.

# wget https://bitbucket.org/zhb/iredmail/downloads/iRedMail-0.9.9.tar.bz2

Затем распаковываем скачанный архив.

# tar xjf iRedMail-0.9.9.tar.bz2

Распаковка архива

И переходим в созданную папку.

# cd iRedMail-0.9.9

Папка с установщиком iRedMail

Проверяем содержимое папки

Содержимое папки

И запускаем скрипт установки iRedMail.

# bash iRedMail.sh

Запустится установка почтовой системы. В процессе установки нужно будет ответить на ряд вопросов. Соглашаемся начать установку.

Начало установки

Выбор директории установки

Теперь нужно выбрать веб-сервер. Выбор не велик, поэтому выбираем NGINX.

Выбор веб-сервера

Теперь необходимо выбрать сервер баз данных, который будет установлен и настроен на работу с почтовой системой. Выбираем MariaDB.

Выбор сервера баз данных

Задаем root пароль на базу.

Создание root пароля базы данных

Теперь указываем наш почтовый домен.

Создание почтового домена

Затем создаем пароль на ящик администратора postmaster@домен.ru.

Создание пароля почтового администратора

Выбор веб-компонентов

Подтверждаем заданные настройки.

Подтверждение настроек

Установка запущена.

Установка

По окончании установки подтверждаем создание правила iptables для SSH и перезапускаем firewall. iRedMail работает с iptables . В Ubuntu чаще всего используют утилиту управления firewall UFW . Если у вас по той или иной причине возникнет такая необходимость, то установите UFW (apt install ufw ) и добавьте правила что бы UFW (пример: ufw allow "Nginx Full" или ufw allow Postfix ) не блокировал работу почтового сервера. Посмотреть список доступных правил можно выполнив команду: ufw app list . Затем включите UFW : ufw enable .

Создание правила iptables

Перезапуск firewall

На этом установка iRedMail завершена. Система вывела нам адреса веб-интерфейсов и учетные данные для входа. Для включения всех компонентов почтовой системы необходимо выполнить перезагрузку сервера.

Окончание установки

Перезагружаемся.

# reboot

Настройка

Для начала нужно убедится, что все работает. Пробуем зайти в панель управления iReadAdmin по адресу https://домен/iredadmin . Логин postmaster@домен.ru , пароль создали при установке. Присутствует русскоязычный интерфейс.

Как видим все работает. При входе в iRedAdmin вы скорее всего получили ошибку безопасности, связанную с сертификатом. Это происходит потому, что iRedMail имеет вшитый самоподписной сертификат, на который и ругается браузер. Для устранения это проблемы необходимо установить действующий SSL сертификат. Если у вас есть купленный можете установить его. В примере я буду устанавливать бесплатный SSL от Let’s Encrypt.

Установка SSL сертификата Let’s Encrypt

Устанавливать сертификат мы будем при помощи утилиты certbot. Сначала добавим репозиторий.

# add-apt-repository ppa:certbot/certbot

Затем установим сам certboot с необходимыми компонентами.

# apt install python-certbot-nginx

Получаем сертификат.

# certbot --nginx -d домен.ru

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

Получение сертификата

Как видим сертификат успешно получен и система указала нам пути к самому сертификату и к ключу. Они то нам как раз и нужны. Вообще мы получили 4 файла, которые будут хранится в папке "/etc/letsencrypt/live/домен". Теперь необходимо сообщить веб-серверу о нашем сертификате, то есть заменить вшитый сертификат на тот, который мы только что получили. Для этого нам необходимо отредактировать всего лишь один файл.

# nano /etc/nginx/templates/ssl.tmpl

И изменяем в нем две последние строчки.

Заменяем SSL сертификат

Меняем пути в файле на пути, которые нам сообщила система при получении сертификата.

Замена SSL сертификата

И перезапускаем NGINX.

# service nginx restart

Теперь пробуем снова зайти в iRedAdmin .

Проверка SSL сертификата

Ошибки сертификата больше нет. Сертификат действителен. Можно кликнуть на замок и посмотреть его свойства. По окончании срока действия сертификата certboot должен обновить его в автоматическом режиме.

Теперь сообщим о сертификате Dovecot и Postfix. Для этого отредактируем два конфигурационных файла. Выполняем:

# nano /etc/dovecot/dovecot.conf

Находим блок:

#SSL: Global settings.

И меняем прописанный там сертификат на наш.

Замена сертификата для Dovecot

Так же обратите внимание на строчку "ssl_protocols". Ее значение должно быть "!SSLv3", иначе получите ошибку "Warning: SSLv2 not supported by OpenSSL. Please consider removing it from ssl_protocols" при перезапуске Dovecot.

# nano /etc/postfix/main.cf

Находим блок:

# SSL key, certificate, CA

И изменяем в нем пути на пути к файлам нашего сертификата.

Замена сертификата для Postfix

На этом установка сертификата закончена. Необходимо перезапустить Dovecot и Postfix, но лучше выполнить перезагрузку сервера.

# service dovecot restart

# reboot

Установка PHPMyAdmin

Этот пункт является необязательным, но я рекомендую выполнить его и установить PHPMyAdmin для удобства работы с базами данных.

# apt install phpmyadmin

Установщик спросит на работу с каким веб-сервером настраивать PHPMyAdmin, так как NGINX в этом списке нет, просто нажимаем TAB и идем дальше.

Установка PHPMyAdmin

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

# ln -s /usr/share/phpmyadmin /var/www/html

И пробуем зайти на https://домен/phpmyadmin/

PHPMyAdmin работает. Подключение защищено сертификатом, никаких ошибок нет. Идем дальше. Создадим администратора баз данных MySQL (MariaDB).

# mysql

И попадаем в консоль управления MariaDB. Далее поочередно делаем команды:

MariaDB > CREATE USER "admin"@"localhost" IDENTIFIED BY "пароль";
MariaDB > GRANT ALL PRIVILEGES ON *.* TO "admin"@"localhost" WITH GRANT OPTION;
MariaDB > FLUSH PRIVILEGES;

Создание пользователя MySQL

Все OK, вход выполнен. PHPMyAdmin готов к работе.

Установка PostfixAdmin

В принципе PostfixAdmin, как и PHPMyAdmin можно не устанавливать. Почтовый сервер прекрасно будет работать и без этих компонентов. Но тогда в вы не сможете создавать почтовые алиасы. Если вам этого и не надо, то смело можете пропустить эти разделы. Если же алиасы вам все таки нужны, то варианта у вас два: покупка платной версии iReaAdmin или установка PostfixAdmin. Конечно можно делать это и без дополнительного ПО, прописывая алиасы в базе данных в ручную, но это не всегда удобно и не для всех подходит. Я рекомендую использовать PostfixAdmin, его установку и интеграцию с iRedMail мы сейчас и рассмотрим. Запускаем установку:

# apt install postfixadmin

Соглашаемся и создаем пароль для системной базы программы.

Установка PostfixAdmin

Установка PostfixAdmin

Делаем симлинк по аналогии с установкой PHPMyAdmin.

# ln -s /usr/share/postfixadmin /var/www/html

Делаем пользователя, от имени которого запускается веб-сервер владельцем каталога. В нашем случае NGINX запускается от имени пользователя www-data.

# chown -R www-data /usr/share/postfixadmin

Теперь нам нужно отредактировать конфигурационный файл PostfixAdmin и внести в него информацию о базе данных, которую использует iRedAdmin. По умолчанию эта база называется vmail. Если зайти в PHPMyAdmin то можно ее там увидеть. И так, для того что бы PostfixAdmin мог вносить изменения в базу данных прописываем ее в конфигурации PostfixAdmin.

# nano /etc/postfixadmin/config.inc.php

Находим строки:

$CONF["database_type"] = $dbtype;
$CONF["database_host"] = $dbserver;
$CONF["database_user"] = $dbuser;
$CONF["database_password"] = $dbpass;
$CONF["database_name"] = $dbname;

И приводим к виду:

$CONF["database_type"] = "mysqli"; # Тип базы данных
$CONF["database_host"] = "localhost"; # Хост сервера баз данных
$CONF["database_user"] = "admin"; # Логин с правами на запись в базу vmail. Можно использовать созданный ранее admin
$CONF["database_password"] = "пароль"; # Пароль пользователя указанного выше
$CONF["database_name"] = "vmail"; # Название базы данных iRedMail

Внесение информации о базе данных

Если вы планируете использовать почтовый веб-клиент SOGo, то необходимо сделать еще одно дополнительное действие, а именно поменять шифрование PostfixAdmin в пункте $CONF["encrypt"] с "md5crypt" на "dovecot:SHA512-CRYPT" . Если вы это не сделаете, то при попытке авторизации в SOGo пользователем созданным в PostfixAdmin получите ошибку неверный логин или пароль.

Изменение типа шифрования

Теперь, что бы успешно завершить установку и не получить ошибок необходимо выполнить запрос к базе данных. Удобно это сделать через PHPMyAdmin. Выбираем базу vmail и переходим на вкладку SQL. В окне вводим:

DROP INDEX domain on mailbox;
DROP INDEX domain on alias;
ALTER TABLE alias ADD COLUMN `goto` text NOT NULL;

Запрос к базе данных

И нажимаем "Вперед". Теперь у нас все готово, можно переходить в веб-интерфейс PostfixAdmin и завершать установку. Для этого в браузере необходимо набрать: https://домен/postfixadmin/setup.php .

Должно появиться следующее:

Установка PostfixAdmin

Если все сделано по инструкции, то ошибок быть не должно. Если все же будут, то их предается устранить, иначе система не даст вам продолжить. Задаем пароль установки и жмем "Generate password hash ". Система сгенерирует хеш пароля, который необходимо вставить в параметр $CONF["setup_password"] .

Завершение установки PostfixAdmin

Изменение настроек файла конфигурации

Теперь вводим только что созданный пароль и создаем администратора PostfixAdmin. Администратора с логином postmaster лучше не создавать, поскольку могут быть проблемы со входом в панель администрирования iRedAdmin.

Создание администратора PostfixAdmin

Все, администратор создан. Можно выполнять вход.

Обратите внимание, что с точки зрения безопасности файл setup.php в директории postfixadmin лучше переименовать или удалить.

Переходим: https://домен/postfixadmin/ и вводим только что созданные учетные данные. В PostfixAdmin, так же как и в iRedAdmin, доступен русский язык. Его можно выбрать при авторизации.

Пробуем создать почтовый ящик пользователя.

Включение/Отключение модулей iRedMail

За управление модулями iRedMail отвечает iRedAPD. Он имеет конфигурационный файл, в котором прописаны работающие модули. Если тот или иной модуль вам не нужен, его можно удалить из файла конфигурации и он перестанет работать. Выполняем:

# nano /opt/iredapd/settings.py

Находим строчку "plugins " и удаляем из нее не нужные вам компоненты. Я уберу компонент "greylisting" . Он конечно достаточно эффективно защищает от спама, по при этом часто не доходят и нужные письма.

Greylist (серый список) - технология автоматической защиты от спама, основанная на анализе поведения сервера отправителя почты. При включенном "greylisting" сервер в первый раз отказывается принять письмо с неизвестного ему адреса, сообщая о временной ошибке. В таком случае сервер отправитель должен повторить отправку позже. Спамерские программы обычно такого не делают. Если письмо отправляется повторно, оно добавляется в список на 30 дней и уже обмен почтой происходит с первого раза. Использовать этот модуль или нет решайте сами.

Включение/Отключение модулей почты

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

# service iredapd restart

Тестирование почтового сервера

На этом настройка почтового сервера iRedMail закончена. Можно приступать к завершающему этапу - тестированию. Создадим два почтовых ящика. Для проверки один через iRedAdmin, второй через PostfixAdmin и отправим письмо с одного ящика на другой и наоборот. В iRedAdmin создадим ящик user1@домен.ru . В PostfixAdmin - user2@домен.ru

Создание пользователя в iRedAdmin

Создание пользователя в PostfixAdmin

Проверяем что пользователи создались.

Если вы обратить внимание на графу "Кому" в перечне ящиков PostfixAdmin, то можно заметить разницу между ящиками созданными в iRedAdmin и PostfixAdmin. Ящики созданные в iRedAdmin отмечены как "Forward only ", а созданные в PostfixAdmin как - "Mailbox ". Я сначала долго не мог понять почему так происходит и какая между ними разница, и наконец заметил одну вещь. Ящики в iRedAdmin создаются без алиасов, а ящики в PostfixAdmin с алиасом на самого себя.

И если эти алиасы удалить, то ящики станут отображаться как и созданные в iRedAdmin "Forward only ".

Удаление алиасов

Алиасы удалены. Проверяем PostfixAdmin.

Как видим все ящики стали "Forward only". Точно так же если создать в ящике созданном в iRedAdmin алиас сам на себя, то он станет "Mailbox". В принципе, на работоспособность почты это никак не влияет. Единственное вы не сможете создать алиас на ящике созданном в PostfixAdmin. Вместо создания алиаса, нужно будет отредактировать уже имеющийся. Кстати об алиасах, в новой версии iRedMail необходимо внести изменение в одну из карт Postfix, которая отвечает за алиасы. И если вы этого не сделаете, то созданные алиасы не будут работать. Для этого необходимо в файле /etc/postfix/mysql/virtual_alias_maps.cf исправить:

Выполняем:

# nano /etc/postfix/mysql/virtual_alias_maps.cf

И исправляем.

Настройка алиасов

Перезапускаем Postfix:

# service postfix restart

После этого все должно заработать.

И так, приступим к проверке почты. В ящик user1 мы зайдем через Roundcube, а в ящик user2 - через SOGo и отправим письмо с ящика user1 на user2 и обратно.

Отправка письмо с Roundcube

Получение письма в SOGo

Отправка письма в SOGo

Получение письма в Roundcube

Все работает без каких либо проблем. Доставка письма занимает от двух до пяти секунд. Точно так же письма прекрасно доставляются на сервера яндекса и mail.ru (проверено).

Теперь проверим алиасы. Создадим ящик user3 и сделаем алиас с ящика user1 на ящик user2 . И отправим письмо с ящика user3 на ящик user1 . При этом письмо должно будет прийти на ящик user2 .

Создание алиаса

Отправка письма с ящика user3 на ящик user1

Получение письма на ящике user2

С работой алиасов тоже все в порядке.

Протестируем работу почтового сервера через локальный почтовый клиент. В примере рассмотрим Mozilla Thunderbird. Создадим еще двух пользователей: client1 и client2 . Один ящик подключим по IMAP, другой по POP3 и отправим письмо с одного ящика на другой.

Подключение по IMAP

Подключение по POP3

Отправляем письмо с Клиент 1 на Клиент 2.

Отправка с Клиент 1

Получение на Клиент 2

И в обратном порядке.

Отправка с Клиент 2

Получение на Клиент 1

Все работает.

Если перейти по адресу: https://домен/netdata , то можно наблюдать графики состояния системы.

Заключение

На этом установка, настройка и тестирование почтовой системы iRedMail закончены. В итоге мы получили полностью бесплатный полноценный почтовый сервер с действующим SSL сертификатом, двумя разными почтовыми веб-клиентами, двумя панелями управления, а так же встроенными в почту антиспамом и антивирусом. По вашему желанию вместо почтовых веб-клиентов можно использовать локальные почтовые клиенты такие как Microsoft Outlook или Mozilla Thunderbird. Если не планируете использовать почтовые веб-клиенты их можно вообще не устанавливать, что бы не нагружать лишним сервер, или установить что-то одно, что вам нравится больше. Мне лично больше нравится SOGo, тем что его интерфейс оптимизирован под мобильные устройства, тем самым очень удобно просматривать электронную почту со смартфона. Тоже самое касается NetData и iRedAdmin, если не планируете пользоваться то лучше не устанавливать. Данная почтовая система не сильно требовательна к ресурсам. Все это работает на VPS сервере с 1024 Мб оперативной памяти и одним виртуальным процессором. Если у вас остались какие-либо вопросы по данной почтовой системе пишите в комментариях.

P.S. В ходе тестирования данного продукта на различных операционных системах с 1 Гб оперативной памяти (Ubuntu, Debian, CentOS) выяснилось, что 1 Гб мало для работы ClamAV. Почти во всех случаях при использовании 1 Гб памяти антивирус ссылался на ошибку связанную с базой данных. При это на операционных системах Debian и Ubuntu антивирус просто не сканировал проходящую через сервер почту, в остальном все работало нормально. На CentOS ситуация была несколько иной. Служба clamd полностью вешала систему, тем самым делая невозможным нормальную работу сервера. При попытке входа в веб-интерфейсы периодически NGINX выдавал 502 и 504 ошибки. Почта отправлялась тоже через раз. При этом если добавить оперативной памяти до 2 Гб, то во всех случаях никаких проблем с работой антивируса и сервера в целом не наблюдалось. ClamAV сканировал проходящую через почтовый сервер почту, о чем писал в логах. При попытке отправить вирус во вложении оправка блокировалась. Потребление памяти составляло примерно 1.2 - 1.7 Гб.

NGINX можно использовать не только в качестве веб-сервера или http-proxy, но и для проксирования почты по протоколам SMTP, IMAP, POP3. Это позволит настроить:

  • Единую точку входа для масштабируемой почтовой системы.
  • Балансировку нагрузки между всеми почтовыми серверами.

В данной статье установка выполняется на операционной системе Linux. В качестве почтового сервиса, на который передаются запросы можно использовать postfix, exim, dovecot, exchange, сборку iredmail и другое.

Принцип работы

NGINX принимает запросы и выполняет аутентификацию на веб-сервере. В зависимости от результата проверки логина и пароля, прокси вернет ответ с несколькими заголовками.

В случае успеха:

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

В случае неудачи:

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

Подготовка сервера

Внесем некоторые правки в настройки безопасности сервера.

SELinux

Отключаем SELinux, если используем CentOS или если используем данную систему безопасности на Ubuntu:

vi /etc/selinux/config

SELINUX=disabled

Брандмауэр

Если используем firewalld (по умолчанию в CentOS):

firewall-cmd --permanent --add-port=25/tcp --add-port=110/tcp --add-port=143/tcp

firewall-cmd --reload

Если используем iptables (по умолчанию в Ubuntu):

iptables -A INPUT -p tcp --dport 25 -j ACCEPT

iptables -A INPUT -p tcp --dport 110 -j ACCEPT

iptables -A INPUT -p tcp --dport 143 -j ACCEPT

apt-get install iptables-persistent

iptables-save > /etc/iptables/rules.v4

* в данном примере мы разрешили SMTP (25), POP3 (110), IMAP (143).

Установка NGINX

В зависимости от операционной системы, установка NGINX немного отличается.

или Linux Centos :

yum install nginx

или Linux Ubuntu :

apt install nginx

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

systemctl enable nginx

systemctl start nginx

Если в системе уже установлен NGINX, проверяем с какими модулями он работает:

Мы получим список опций, с которыми собран веб-сервер — среди них мы должны увидеть --with-mail . Если нужного модуля нет, нужно обновить nginx

Настройка NGINX

Открываем конфигурационный файл nginx и добавляем опцию mail :

vi /etc/nginx/nginx.conf

mail {

auth_http localhost:80/auth.php;

Server {
listen 25;
protocol smtp;
smtp_auth login plain cram-md5;
}

Server {
listen 110;
protocol pop3;

}

Server {
listen 143;
protocol imap;
}
}

* где:

  • server_name — имя почтового сервера, которое будет отображаться при SMTP-приветствии.
  • auth_http — веб-сервер и URL для запроса аутентификации.
  • proxy_pass_error_message — разрешает или запрещает показ сообщения при неудачной аутентификации.
  • listen — порт, на котором прослушиваются запросы.
  • protocol — протокол приложения, для которого прослушивается соответствующий порт.
  • smtp_auth — доступные методы аутентификации для SMTP.
  • pop3_auth — доступные методы аутентификации для POP3.

В секции http - server дописываем:

Server {
listen 80 default_server;
listen [::]:80 default_server;
...

Location ~ \.php$ {
set $root_path /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
include fastcgi_params;
fastcgi_param DOCUMENT_ROOT $root_path;
}
...

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

systemctl restart nginx

Установка и настройка PHP

Для выполнения аутентификации с помощью PHP, необходимо установить в систему следующие пакеты.

Если CentOS :

yum install php php-fpm

Если Ubuntu :

apt-get install php php-fpm

Запускаем PHP-FPM:

systemctl enable php-fpm

systemctl start php-fpm

Аутентификация

Проверка логина и пароля выполняется скриптом, путь до которого задается опцией auth_http. В нашем примере, это скрипт на PHP.

Пример официальной заготовки для скрипта проверки логина и пароля:

vi /usr/share/nginx/html/auth.php

* данный скрипт принимает любые логин и пароль и перенаправляет запросы на серверы 192.168.1.22 и 192.168.1.33 . Чтобы задать алгоритм аутентификации, редактируем строки 61 - 64. За возврат серверов, на которые идет перенаправление отвечают строки 73 - 77 — в данном примере если логин начинается на символы "a", "c", "f", "g", то перенаправление будет на сервер mailhost01 , иначе, на mailhost02 . Сопоставление имен серверов с IP-адресами можно задать на строках 31, 32, в противном случае, обращение будет идти по доменному имени.

Настройка почтового сервера

Обмен данными между NGINX прокси и почтовым сервером идут в открытом виде. Необходимо добавить в исключение возможность аутентификации по механизму PLAIN. Например, для настройки dovecot, делаем следующее:

vi /etc/dovecot/conf.d/10-auth.conf

Добавляем строки:

remote 192.168.1.11 {
disable_plaintext_auth = no
}

* в данном примере мы разрешили PLAIN-запросы на аутентификацию с сервера 192.168.1.11 .

Также проверяем:

* если ssl будет иметь значение required , проверка не будет работать, так как получится, что с одной стороны сервер разрешает запросы в открытом виде, но требует шифрование ssl.

Перезапускаем Dovecot сервис:

systemctl restart dovecot

Настройка клиента

Можно перейти к проверки настройки нашего прокси. Для этого в настройках клиента в качестве IMAP/POP2/SMTP указываем адрес или имя сервера nginx, например:

* в данном примере почтовый клиент настраивается для подключения к серверу 192.168.1.11 по открытым портам 143 (IMAP) и 25 (SMTP).

Шифрование

Теперь настроим SSL-подключение. Nginx должен быть собран с модулем mail_ssl_module — проверяем командой:

При отсутствии необходимого модуля, пересобираем nginx.

После редактируем наш конфигурационный файл:

vi /etc/nginx/nginx.conf

mail {
server_name mail.domain.local;
auth_http localhost/auth.php;

Proxy_pass_error_message on;

Ssl on;
ssl_certificate /etc/ssl/nginx/public.crt;
ssl_certificate_key /etc/ssl/nginx/private.key;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

Server {
listen 110;
protocol pop3;
pop3_auth plain apop cram-md5;
}

Server {
listen 143;
protocol imap;
}

Причина: срабатывает система безопасности SELinux.

Решение: отключить или настроить SELinux.

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

Почтовый прокси

Начнем с самого очевидного - со способности nginx выступать в роли почтового прокси. Эта функция есть в nginx изначально, а вот используется в продакшн она почему-то крайне редко, некоторые так и вообще не догадываются о ее существовании. Как бы там ни было, nginx поддерживает проксирование протоколов POP3, IMAP и SMTP с разными методами аутентификации, включая SSL и StartTLS, причем делает это очень быстро.

Зачем это нужно? Есть как минимум два применения данной функциональности. Первая: использовать nginx в качестве щита от назойливых спамеров, пытающихся отправить мусорные письма через наш SMTP-сервер. Обычно спамеры не создают много проблем, так как быстро отшибаются на этапе аутентификации, однако, когда их становится действительно много, nginx поможет сэкономить процессорные ресурсы. Вторая: использовать nginx для перенаправления пользователей на несколько почтовых POP3/IMAP-серверов. С этим, конечно, мог бы справиться и другой почтовый прокси, но зачем городить огород серверов, если на фронтенде уже установлен nginx для отдачи статики по HTTP, например?

Почтовый прокси-сервер в nginx сделан не совсем стандартно. Он использует дополнительный слой аутентификации, реализованный средствами HTTP, и, только если пользователь проходит этот барьер, он пропускается дальше. Обеспечивается такая функциональность путем создания страницы/скрипта, которой nginx отдает данные пользователя, а она/он возвращает ответ в виде стандартных OK или причины отказа (типа «Invalid login or password»). Скрипт запускается со следующими заголовками:

Входные данные скрипта аутентификации HTTP_AUTH_USER: юзер HTTP_AUTH_PASS: пароль HTTP_AUTH_PROTOCOL: почтовый протокол (IMAP, POP3 или SMTP)

А возвращает такие:

Выходные данные скрипта аутентификации HTTP_AUTH_STATUS: OK или причина отказа HTTP_AUTH_SERVER: реальный почтовый сервер для перенаправления HTTP_AUTH_PORT: порт сервера

Замечательная особенность такого подхода в том, что его можно использовать вовсе не для самой аутентификации, а чтобы раскидать пользователей по разным внутренним серверам, в зависимости от имени юзера, данных о текущих нагрузках на почтовые серверы либо вообще организовав простейшую балансировку нагрузки с помощью round-robin. Впрочем, если требуется всего лишь перекинуть пользователей на внутренний почтовый сервер, можно использовать вместо реального скрипта заглушку, реализованную самим nginx. Например, простейший SMTP- и IMAP-прокси в конфиге nginx будет выглядеть следующим образом:

# vi /etc/nginx/nginx.conf mail { # Адрес скрипта аутентификации auth_http localhost:8080/auth; # Отключаем команду XCLIENT, некоторые почтовые серверы ее не понимают xclient off; # IMAP-сервер server { listen 143; protocol imap; proxy on; } # SMTP-сервер server { listen 25; protocol smtp; proxy on; } }

# vi /etc/nginx/nginx.conf http { # Маппинг на нужный порт почтового сервера в зависимости от порта, отправленного в заголовке HTTP_AUTH_PROTOCOL map $http_auth_protocol $mailport { default 25; smtp 25; imap 143; } # Реализация «скрипта» аутентификации - всегда возвращает OK и перекидывает пользователя на внутренний почтовый сервер, выставляя нужный порт с помощью приведенного выше маппинга server { listen 8080; location /auth { add_header "Auth-Status" "OK"; add_header "Auth-Server" "192.168.0.1"; add_header "Auth-Port" $mailport; return 200; } } }

Это все. Такая конфигурация позволяет прозрачно перенаправлять пользователей на внутренний почтовый сервер, не создавая оверхеда в виде ненужного в данном случае скрипта. Применив скрипт, такую конфигурацию можно существенно расширить: настроить балансировку нагрузки, проверять пользователей по базе LDAP и выполнять другие операции. Написание скрипта выходит за рамки этой статьи, однако его очень легко реализовать, даже имея лишь поверхностные знания о PHP и Python.

Потоковое вещание видео

Поднять обычный видеохостинг на базе nginx легко. Достаточно только выложить перекодированное видео в доступный серверу каталог, прописать его в конфиг и настроить флеш- или HTML5-проигрыватель так, чтобы он брал видео из этого каталога. Однако, если требуется настроить непрерывное вещание видео из какого-то внешнего источника или веб-камеры, такая схема не сработает, и придется смотреть в сторону специальных потоковых протоколов.

Есть несколько протоколов, решающих эту задачу, наиболее эффективный и поддерживаемый из них RTMP. Беда только в том, что почти все реализации RTMP-сервера страдают от проблем. Официальный Adobe Flash Media Server платный. Red5 и Wowza написаны на Java, а потому не дают нужной производительности, еще одна реализация, Erlyvideo, написана на Erlang, что хорошо в случае настройки кластера, но не так эффективно для одиночного сервера.

Я же предлагаю другой подход - воспользоваться модулем RTMP для nginx. Он обладает превосходной производительностью и к тому же позволит использовать один сервер для отдачи как веб-интерфейса сайта, так и видеопотока. Проблема только в том, что модуль этот неофициальный, поэтому nginx с его поддержкой придется собрать самостоятельно. Благо сборка осуществляется стандартным способом:

$ sudo apt-get remove nginx $ cd /tmp $ wget http://bit.ly/VyK0lU -O nginx-rtmp.zip $ unzip nginx-rtmp.zip $ wget http://nginx.org/download/nginx-1.2.6.tar.gz $ tar -xzf nginx-1.2.6.tar.gz $ cd nginx-1.2.6 $ ./configure --add-module=/tmp/nginx-rtmp-module-master $ make $ sudo make install

Теперь модуль нужно настроить. Делается это, как обычно, через конфиг nginx:

Rtmp { # Активируем сервер вещания на порту 1935 по адресу сайт/rtmp server { listen 1935; application rtmp { live on; } } }

Модуль RTMP не умеет работать в многопоточной конфигурации, поэтому количество рабочих процессов nginx придется сократить до одного (позже я расскажу, как обойти эту проблему):

Worker_processes 1;

Теперь можно сохранить файл и заставить nginx перечитать конфигурацию. Настройка nginx завершена, но самого видеопотока у нас еще нет, поэтому его нужно где-то взять. Для примера пусть это будет файл video.avi из текущего каталога. Чтобы превратить его в поток и завернуть в наш RTMP-вещатель, воспользуемся старым добрым FFmpeg:

# ffmpeg -re -i ~/video.avi -c copy -f flv rtmp://localhost/rtmp/stream

В том случае, если видеофайл представлен не в формате H264, его следует перекодировать. Это можно сделать на лету с помощью все того же FFmpeg:

# ffmpeg -re -i ~/video.avi -c:v libx264 -c:a libfaac -ar 44100 -ac 2 -f flv rtmp://localhost/rtmp/stream

Поток также можно захватить прямо с веб-камеры:

# ffmpeg -f video4linux2 -i /dev/video0 -c:v libx264 -an -f flv rtmp://localhost/rtmp/stream

Чтобы просмотреть поток на клиентской стороне, можно воспользоваться любым проигрывателем с поддержкой RTMP, например mplayer:

$ mplayer rmtp://example.com/rtmp/stream

Или встроить проигрыватель прямо в веб-страницу, которая отдается тем же nginx (пример из официальной документации):

Простейший веб-проигрыватель RTMP

jwplayer("container").setup({ modes: [{ type: "flash", src: "/jwplayer/player.swf", config: { bufferlength: 1, file: "stream", streamer: "rtmp://localhost/rtmp", provider: "rtmp", } }] });

Важных строки тут всего две: «file: “stream”», указывающая на RTMP-поток, и «streamer: “rtmp://localhost/rtmp”», в которой указан адрес RTMP-стримера. Для большинства задач таких настроек будет вполне достаточно. По одному адресу можно пустить несколько разных потоков, а nginx будет эффективно их мультиплексировать между клиентами. Но это далеко не все, на что способен RTMP-модуль. С его помощью, например, можно организовать ретрансляцию видеопотока с другого сервера. Сервер FFmpeg для этого вообще не нужен, достаточно добавить следующие строки в конфиг:

# vi /etc/nginx/nginx.conf application rtmp { live on; pull rtmp://rtmp.example.com; }

Если требуется создать несколько потоков в разном качестве, можно вызвать перекодировщик FFmpeg прямо из nginx:

# vi /etc/nginx/nginx.conf application rtmp { live on; exec ffmpeg -i rtmp://localhost/rtmp/$name -c:v flv -c:a -s 320x240 -f flv rtmp://localhost/rtmp-320x240/$name; } application rtmp-320x240 { live on; }

С помощью такой конфигурации мы получим сразу два вещателя, один из которых будет доступен по адресу rtmp://сайт/rtmp, а второй, вещающий в качестве 320 x 240, - по адресу rtmp://сайт/rtmp–320x240. Далее на сайт можно повесить флеш-плеер и кнопки выбора качества, которые будут подсовывать плееру тот или иной адрес вещателя.

Ну и напоследок пример вещания музыки в сеть:

While true; do ffmpeg -re -i "`find /var/music -type f -name "*.mp3"|sort -R|head -n 1`" -vn -c:a libfaac -ar 44100 -ac 2 -f flv rtmp://localhost/rtmp/stream; done

Git-прокси

Система контроля версий Git способна обеспечивать доступ к репозиториям не только по протоколам Git и SSH, но и по HTTP. Когда-то реализация доступа по HTTP была примитивной и неспособной обеспечить полноценную работу с репозиторием. С версии 1.6.6 ситуация изменилась, и сегодня этот протокол можно использовать, чтобы, например, обойти ограничения брандмауэров как с той, так и с другой стороны соединения либо для создания собственного Git-хостинга с веб-интерфейсом.

К сожалению, официальная документация рассказывает только об организации доступа к Git средствами веб-сервера Apache, но, так как сама реализация представляет собой внешнее приложение со стандартным CGI-интерфейсом, ее можно прикрутить практически к любому другому серверу, включая lighttpd и, конечно же, nginx. Для этого не потребуется ничего, кроме самого сервера, установленного Git и небольшого FastCGI-сервера fcgiwrap, который нужен, потому что nginx не умеет работать с CGI напрямую, но умеет вызывать скрипты с помощью протокола FastCGI.

Вся схема работы будет выглядеть следующим образом. Сервер fcgiwrap будет висеть в фоне и ждать запроса на исполнение CGI-приложения. Nginx, в свою очередь, будет сконфигурирован на запрос исполнения CGI-бинарника git-http-backend через FastCGI-интерфейс каждый раз при обращении к указанному нами адресу. Получив запрос, fcgiwrap исполняет git-http-backend с указанными CGI-аргументами, переданными GIT-клиентом, и возвращает результат.

Чтобы реализовать такую схему, сначала установим fcgiwrap:

$ sudo apt-get install fcgiwrap

Настраивать его не нужно, все параметры передаются по протоколу FastCGI. Запущен он будет тоже автоматически. Поэтому остается только настроить nginx. Для этого создаем файл /etc/nginx/sites-enabled/git (если такого каталога нет, можно писать в основной конфиг) и пишем в него следующее:

# vi /etc/nginx/sites-enabled/git server { # Висим на порту 8080 listen 8080; # Адрес нашего сервера (не забудь добавить запись в DNS) server_name git.example.ru; # Логи access_log /var/log/nginx/git-http-backend.access.log; error_log /var/log/nginx/git-http-backend.error.log; # Основной адрес для анонимного доступа location / { # При попытке загрузки отправляем юзера на приватный адрес if ($arg_service ~* "git-receive-pack") { rewrite ^ /private$uri last; } include /etc/nginx/fastcgi_params; # Адрес нашего git-http-backend fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; # Адрес Git-репозитория fastcgi_param GIT_PROJECT_ROOT /srv/git; # Адрес файла fastcgi_param PATH_INFO $uri; # Адрес сервера fcgiwrap fastcgi_pass 127.0.0.1:9001; } # Адрес для доступа на запись location ~/private(/.*)$ { # Полномочия юзера auth_basic "git anonymous read-only, authenticated write"; # HTTP-аутентификация на основе htpasswd auth_basic_user_file /etc/nginx/htpasswd; # Настройки FastCGI include /etc/nginx/fastcgi_params; fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; fastcgi_param GIT_PROJECT_ROOT /srv/git; fastcgi_param PATH_INFO $1; fastcgi_pass 127.0.0.1:9001; } }

Этот конфиг предполагает три важные вещи:

  • Адресом репозитория будет /srv/git, поэтому выставляем соответствующие права доступа: $ sudo chown -R www-data:www-data /srv/git
  • Сам репозиторий должен быть открыт на чтение анонимусами и позволять аплоад по HTTP: $ cd /srv/git $ git config core.sharedrepository true $ git config http.receivepack true
  • Аутентификация осуществляется с помощью файла htpasswd, нужно его создать и добавить в него пользователей: $ sudo apt-get install apache2-utils $ htpasswd -c /etc/nginx/htpasswd user1 $ htpasswd /etc/nginx/htpasswd user2 ...
  • На этом все, перезагружаем nginx:

    Микрокеширование

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

    Есть несколько способов выйти из этой ситуации с наименьшими потерями, однако наиболее интересную идею предложил Фенн Бэйли (Fenn Bailey, fennb.com). Идея в том, чтобы просто поставить перед сервером nginx и заставить его кешировать весь передаваемый контент, но не просто кешировать, а всего на одну секунду. Изюминка здесь в том, что сотни и тысячи посетителей сайта в секунду, по сути, будут генерировать всего одно обращение к бэкенду, получая в большинстве своем кешированную страницу. При этом разницу вряд ли кто-то заметит, потому что даже на динамичном сайте одна секунда обычно ничего не значит.

    Конфиг с реализацией этой идеи будет выглядеть не так уж и сложно:

    # vi /etc/nginx/sites-enabled/cache-proxy # Настройка кеша proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:5m max_size=1000m; server { listen 80; server_name example.com; # Кешируемый адрес location / { # Кеш включен по умолчанию set $no_cache ""; # Отключаем кеш для всех методов, кроме GET и HEAD if ($request_method !~ ^(GET|HEAD)$) { set $no_cache "1"; } # В случае если клиент загружает контент на сайт (no_cache = 1), делаем так, чтобы отдаваемые ему данные не кешировались в течение двух секунд и он смог увидеть результат загрузки if ($no_cache = "1") { add_header Set-Cookie "_mcnc=1; Max-Age=2; Path=/"; add_header X-Microcachable "0"; } if ($http_cookie ~* "_mcnc") { set $no_cache "1"; } # Включаем/отключаем кеш в зависимости от состояния переменной no_cache proxy_no_cache $no_cache; proxy_cache_bypass $no_cache; # Проксируем запросы на реальный сервер proxy_pass http://appserver.example.ru; proxy_cache microcache; proxy_cache_key $scheme$host$request_method$request_uri; proxy_cache_valid 200 1s; # Защита от проблемы Thundering herd proxy_cache_use_stale updating; # Добавляем стандартные хидеры proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Не кешируем файлы размером больше 1 Мб proxy_max_temp_file_size 1M; } }

    Особое место в этом конфиге занимает строка «proxy_cache_use_stale updating;», без которой мы бы получили периодические всплески нагрузки на бэкенд-сервер из-за запросов, пришедших во время обновления кеша. В остальном все стандартно и должно быть понятно без лишних объяснений.

    Приближение прокси к ЦА

    Несмотря на повсеместное глобальное увеличение скоростей интернета, физическая удаленность сервера от целевой аудитории все равно продолжает играть свою роль. Это значит, что, если русский сайт крутится на сервере, расположенном где-нибудь в Америке, скорость доступа к нему будет априори медленнее, чем с российского сервера с такой же шириной канала (естественно, если закрыть глаза на все остальные факторы). Другое дело, что размещать серверы за рубежом зачастую выгоднее, в том числе и в плане обслуживания. Поэтому для получения профита, в виде более высоких скоростей отдачи, придется идти на хитрость.

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

    # vi /etc/nginx/sites-enabled/proxy # Храним кеш 30 дней в 100 Гб хранилище proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=static:32m inactive=30d max_size=100g; server { listen 80; server_name example.com; # Собственно, наш прокси location ~* .(jpg|jpeg|gif|png|ico|css|midi|wav|bmp|js|swf|flv|avi|djvu|mp3)$ { # Адрес бэкенда proxy_pass back.example.com:80; proxy_redirect off; 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_buffer_size 16k; proxy_buffers 32 16k; proxy_cache static; proxy_cache_valid 30d; proxy_ignore_headers "Cache-Control" "Expires"; proxy_cache_key "$uri$is_args$args"; proxy_cache_lock on; } }

    Выводы

    Сегодня с помощью nginx можно решить множество самых разных задач, многие из которых вообще не связаны с веб-сервером и протоколом HTTP. Почтовый прокси, сервер потокового вещания и интерфейс Git - это только часть таких задач.

    Интернет