22.07.10 Apache2(frontend) + Nginx(backend) на Gentoo(генту) с заточкой под liteовый highload (массхостинг)

0.250 Предисловие

Данная статья есть логическое продолжение статьи от 31.05.2010 ProFTPd+MySQL+Quota+WebAdmin на Gentoo, все попутные сервисы настроил, решил перевести сервак с чистого Апача на связку Апач+ЕнжинИкс, причем как водится везде апач у нас совместно с PHP5 будет отдавать весь динамический контент а быстрый ЕнжинИкс(Nginx) всю статику.

Итак, продолжаем...

0.500 Имею

Сервак с предустановленной и настроенной ОС Генту(Gentoo) и грамотно настроенным под наши нужды файрволлом(IPTables).


0.750 Хочу

[shadowbox=/images/newspost_images/nginx_x_accel_redirect_2.png|::||]/images/newspost_images/thumb_nginx_x_accel_redirect_2.png[/shadowbox]


Упрощенно эти шаги можно описать следующим образом:

  • Пакет от клиента приходит на некоторый IP-адрес и 80-й порт сервера;
  • Далее, если клиент запрашивает статический контент мы отдаем ему статику через ЕнжинИкс;
  • Если не статику, то далее работает бэкенд связка Апача и ПХП на 8080 порту;


1. Установка и настройка ЕнжинИкс(nginx)+Апач(Apache).

Первым делом делаем синхронизацию портежей(Portages)

# emerge-webrsync


Далее разбираемся с USE-флагами:

Я ставил Nginx из нестабильной ветки, т.к. мне показалось, что это будет гораздо лучше чем использовать морально устаревший пакет, для этого внес в /etc/make.conf следующую строку:

ACCEPT_KEYWORDS="~amd64"


# emerge -pv apache nginx

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R   ] www-servers/apache-2.2.15  USE="ldap ssl -debug -doc (-selinux) -static -suexec -threads" APACHE2_MODULES="actions alias asis auth_basic auth_digest authn_alias authn_anon authn_dbd authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cern_meta charset_lite dav dav_fs dav_lock dbd deflate dir disk_cache dumpio env expires ext_filter file_cache filter headers ident imagemap include info log_config log_forensic logio mem_cache mime mime_magic negotiation proxy proxy_ajp proxy_balancer proxy_connect proxy_ftp proxy_http rewrite setenvif speling status substitute unique_id userdir usertrack version vhost_alias" APACHE2_MPMS="-event -itk -peruser -prefork -worker" 0 kB
[ebuild   R   ] www-servers/nginx-0.8.38  USE="http http-cache ipv6 pcre ssl -aio -debug -libatomic -vim-syntax" NGINX_MODULES_HTTP="access addition auth_basic autoindex charset empty_gif flv gzip gzip_static image_filter perl proxy realip rewrite secure_link ssi stub_status sub -browser -dav -degradation -fastcgi -geo -geoip -headers_more -limit_req -limit_zone -map -memcached -passenger -push -random_index -referer -split_clients -upstream_ip_hash -userid -uwsgi -xslt" NGINX_MODULES_MAIL="-imap -pop3 -smtp" RUBY_TARGETS="ruby18" 0 kB


Вот то, что осело у меня в /etc/make.conf

APACHE2_MODULES="actions alias auth_basic authn_alias authn_anon authn_dbm authn_default authn_file authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache dav dav_fs dav_lock deflate dir disk_cache env expires ext_filter file_cache filter headers include info log_config logio mem_cache mime mime_magic negotiation rewrite setenvif speling status unique_id userdir usertrack vhost_alias asis auth_digest authn_dbd cern_meta charset_lite dbd dumpio ident imagemap log_forensic proxy proxy_ajp proxy_balancer proxy_connect proxy_ftp proxy_http substitute version"
NGINX_MODULES_HTTP="proxy access auth_basic autoindex charset empty_gif gzip gzip_static image_filter perl rewrite secure_link ssi stub_status addition flv realip static-gzip sub webdav"


Всё нравится? - Устанавливаем!

# emerge nginx apache


2. Настройка ЕнжинИкс(Nginx) как фронтэнд(FrontEnd) для Apache на Генту(Gentoo).

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

Много было прочитано всяческой информации с разных авторитетных и не очень изданий, много шлака было отобрано, отсеяно и выжато, результатом моих стараний считаю данный конфиг:

# cat /etc/nginx/nginx.conf


// Далее по коду будут внесены небольшие изменения, поскольку конфиг был взят с рабочей телеги и не хотелось бы палить домены

#user  nobody;
worker_processes  1;

# Количество процессов - не будет хватать - можно добавить...

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

# Куда класть логи?

#pid        logs/nginx.pid;

# Pid - если используете нестандартный инит-файл или управляете из ВебМорды

events {
    worker_connections  1024;
# Количество соединений на 1 воркер процесс
}

http {
    include       mime.types;
    default_type  application/octet-stream;

# Тут все понятно...

    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

# Пришлось отключить гзип, т.к. Яндекс начал выплёвывать все страницы из индекса...

    #gzip  on;

    # another virtual host using mix of IP-, name-, and port-based configuration
    #
    #server {
    #    listen       8000;
    #    listen       somename:8080;
    #    server_name  somename  alias  another.alias;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}


    # HTTPS server
    #
    #server {
    #    listen       443;
    #    server_name  localhost;

    #    ssl                  on;
    #    ssl_certificate      cert.pem;
    #    ssl_certificate_key  cert.key;

    #    ssl_session_timeout  5m;

    #    ssl_protocols  SSLv2 SSLv3 TLSv1;
    #    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    #    ssl_prefer_server_ciphers   on;

    #    location / {
    #        root   html;
    #        index  index.html index.htm;
    #    }
    #}

# HTTPS использовать не будем, поэтому комментим все нафиг.

	client_max_body_size 100m;
# Делее идет перечисление доменов, которые обслуживает Ваш сервер, их может быть сколько угодно, у меня в примере - парочка
	server {
		listen 11.22.33.44:80;
		server_name gnu.su www.gnu.su *.gnu.su;
		rewrite	^(/manager/.*)$	https://$host$1	permanent;
		location ~* ^/(webstat/|awstats|webmail/|myadmin/|manimg/) {
			proxy_pass http://11.22.33.44:8080;
			proxy_redirect http://gnu.su:8080/ /;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
		location / {
			proxy_pass http://11.22.33.44:8080;
			proxy_redirect http://gnu.su:8080/ /;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
		location /e107_admin/ {
			allow HH.OO.MM.EE/32;
			deny all;
			proxy_pass http://11.22.33.44:8080;
			proxy_redirect http://gnu.su:8080/e107_admin/ /e107_admin/;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
                }
		location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {

			access_log /home/httpd-logs/gnu.su.access.log;
			error_page 404 = @fallback;
			set $proot "/home/gnu.su/data/www/gnu.su";
			if ( $host = "gnu.su" ) {
				break;
			}
			if ( $host = "www.gnu.su" ) {
				break;
			}
			if ( $host ~* ^((.*).gnu.su)$ ) {
				set $proot /home/gnu.su/data/www/$1;
				break;
			}
			root $proot;
		}
		location @fallback {
			proxy_pass http://11.22.33.44:8080;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
	}

# Аналогично первому домену идет описание всех последующих...

	server {
		listen 55.66.77.88:80;
		server_name www.gnu.ru gnu.ru;
		rewrite ^(/manager/.*)$	https://$host$1	permanent;

		location ~* ^/(webstat/|awstats|webmail/|myadmin/|manimg/) {
			proxy_pass http://55.66.77.88:8080;
			proxy_redirect http://gnu.ru:8080/ /;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
		location / {
			proxy_pass http://55.66.77.88:8080;
			proxy_redirect http://gnu.ru:8080/ /;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
		location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
			root /home/gnuru/data/www/gnu.ru;
			access_log /home/httpd-logs/gnu.ru.access.log;
			error_page 404 = @fallback;
		}
		location @fallback {
			proxy_pass http://55.66.77.88:8080;
			proxy_set_header Host $host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Real-IP $remote_addr;
		}
	}
	server_names_hash_max_size 2048;
}


3. Настройка Апаче(Apache) как бэкэнда(BackEnd) для Nginx на Генту(Gentoo).

Единственный комментарий который хотелось бы дать, так это то, что я не стал заморачиваться с виртуал хостами в разных файликах, а положил описание всех доменов /etc/apache2/vhosts.d/vhosts.conf. Так проще прикрутить в последствии этот конфиг к какой-нибудь хостинговой панельке(типа ISP Manager, как и было сделано в последствии). Стандартный конфиг /etc/apache2/httpd.conf оставляем без изменений.

# cat /etc/apache2/vhosts.d/vhosts.conf


Listen 8080
NameVirtualHost 11.22.33.44:8080
NameVirtualHost 55.66.77.88:8080
	ServerName gnu.su
	DocumentRoot /home/gnu.su/data/www/gnu.su
	SuexecUserGroup gnu gnu 
	CustomLog /home/httpd-logs/gnu.su.access.log combined
	ErrorLog /home/httpd-logs/gnu.su.error.log
	ServerAlias www.gnu.su
	ServerAdmin root@gnu.su
                    Options -Indexes FollowSymLinks
            AllowOverride All
            Allow from all
        	php_admin_value open_basedir "/home/gnu.su/data:."
	php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f root@gnu.su"
	php_admin_value upload_tmp_dir "/home/gnu.su/data/mod-tmp"
	php_admin_value session.save_path "/home/gnu.su/data/mod-tmp"
	AddType application/x-httpd-php .php .php3 .php4 .php5 .phtml
	AddType application/x-httpd-php-source .phps
#	VirtualDocumentRoot /home/gnu.su/data/www/%0
# Так же перечисляем все остальные виртуальные хосты

	ServerName gnu.ru
...


Если на сервере 1 внешний айпи адрес(IP-address) или вы хотите чтобы сайт был доступен и по внутреннему интерфейсу, то вместо 11.22.33.44:8080 пишем *:8080.

3. Установка mod_rpaf

Редактируем стартовые параметры Apache2 в /etc/conf.d/apache2. В частности добавляем запуск модулей PHP5 и RPAF. Модуль RPAF используется для того чтобы в журналах регистрировался адрес клиента, вместо адреса шлюза nginx.

# nano /etc/conf.d/apache2

APACHE2_OPTS="-D INFO -D LANGUAGE -D PHP5 -D RPAF"

Файл конфигурации:

# emerge -pv mod_rpaf

# cat /etc/apache2/modules.d/10_mod_rpaf.conf

    LoadModule rpaf_module modules/mod_rpaf.so
    RPAFenable on
    RPAFsethostname On
    RPAFproxy_ips 11.22.33.44 55.66.77.88
    RPAFheader X-Forwarded-For


4. Ставим все сервисы в автозагрузку

# rc-update add apache2 default 
# rc-update add nginx default


p.s.: Есть Варианты с установкой eAccelerator, но е107 cms нормально с ними не работает...