Настраиваем веб-сервер — nginx и apache на одном сервере

Вострокнутов Михаил
Вострокнутов Михаил
29.12.19

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

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

    Устанавливаем NGINX:

    apt-get update

    apt-get install nginx

    Внесем изменение в файл nginx.conf:

    vi /etc/nginx/nginx.conf

    Снимаем комментарий со строки:

    http {
      ....
      server_names_hash_bucket_size 64;
      ....
    }
    

    Так на практике, может встретиться ошибка could not build server_names_hash, you should increase server_names_hash_bucket_size: 32.

    Она возникает при большом количестве виртуальных серверов или если один из них будет иметь длинное название. Данная строка в конфиге исправит ситуацию.

    Запускаем nginx:

    systemctl enable nginx

    systemctl start nginx

    Проверим работу веб-сервера. Открываем браузер и вводим в адресной строке http://<IP-адрес сервера>.

    В итоге мы должны увидеть заголовок «Welcome to nginx!».

    Если стартовая страница не загружается, проверяем состояние сервиса и исправляем причину:

    systemctl status nginx

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

    Для поддержки файла .htaccess, который используется многими сайтами, необходимо установить и настроить веб-сервер Apache.

    Устанавливаем apache и модуль для php:

    apt-get install apache2 libapache2-mod-php php php-xml php-intl php-gd php-curl php-zip php-mbstring

    Заходим в настройки портов:

    vi /etc/apache2/ports.conf

    И редактируем следующее:

    Listen 127.0.0.1:8080
    
    #<IfModule ssl_module>
    #    Listen 443
    #</IfModule>
    
    #<IfModule mod_gnutls.c>
    #    Listen 443
    #</IfModule>
    

    *мы настроили прослушивание на порту 8080, так как на 80 уже работает NGINX. Также мы закомментировали прослушивание по 443, так как и он будет слушаться NGINX.

    Запрещаем mpm_event:

    a2dismod mpm_event

    по умолчанию, apache2 может быть установлен с модулем мультипроцессовой обработки mpm_event. Данный модуль не поддерживает php 7 и выше.

    Разрешаем модуль мультипроцессовой обработки mpm_prefork:

    a2enmod mpm_prefork

    Разрешаем модуль php:

    a2enmod php7.3

    Разрешаем модуль rewrite:

    a2enmod rewrite

    *в данном примере установлен php версии 7.3.

    Разрешаем модуль setenvif:

    a2enmod setenvif

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

    systemctl enable apache2

    systemctl start apache2

    Открываем браузер и вводим в адресную строку http://<IP-адрес сервера>:8080. Мы должны увидеть привычную страницу.

    *в разделе Server API мы должны увидеть Apache.

    NGINX и Apache одновременно

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

    vi /etc/nginx/sites-enabled/default

    ...
    location / {
    	location ~ [^/]\.ph(p\d*|tml)$ {
    		try_files /does_not_exists @fallback;
    	}
    	location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {
    		try_files $uri $uri/ @fallback;
    	}
    	location / {
    		try_files /does_not_exists @fallback;
    	}
    }
    location @fallback {
    	proxy_pass http://127.0.0.1:8080;
    	proxy_redirect http://127.0.0.1:8080 /;
    	proxy_set_header Host $host;
    	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    	proxy_set_header X-Forwarded-Proto $scheme;
    	access_log off;
    }
    ...
    

    Проверяем nginx:

    nginx -t

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

    systemctl restart nginx

    Пробуем открыть в браузере http://<IP-адрес сервера> — должна открыться та же страница, что при проверке Apache (с добавлением 8080).

    Apache Real IP

    Запросы на apache приходят от NGINX, и они воспринимаются первым как от IP-адреса 127.0.0.1. На практике, это может привести к проблемам, так как некоторым сайтам необходимы реальные адреса посетителей. Для решения проблемы будем использовать модуль remoteip.

    Создаем конфигурационный файл со следующим содержимым:

    vi /etc/apache2/mods-available/remoteip.conf

    Записываем:

    <IfModule remoteip_module>
      RemoteIPHeader X-Forwarded-For
      RemoteIPTrustedProxy 127.0.0.1/8
    </IfModule>
    

    Активируем модуль:

    a2enmod remoteip

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

    systemctl restart apache2

    Для проверки настройки открываем браузер и вводим в адресную строку http://<IP-адрес сервера>, где откроется наша страница phpinfo.

    В разделе Apache Environment мы должны увидеть внешний адрес компьютера, с которого обращаемся к серверу в опции REMOTE_ADDR.

    Установка СУБД MariaDB

    В данной статье мы установим MariaDB. Установка выполняется следующей командой:

    apt-get install mariadb-server

    Разрешаем автозапуск и запускаем СУБД:

    systemctl enable mariadb

    systemctl start mariadb

    Зададим пароль для учетной записи mysql-root:

    mysqladmin -u root password

    Для возможности подключаться к базе данных скриптами PHP, необходимо установить следующие модули:

    apt-get install php-mysql php-mysqli

    После перезагружаем apache2:

    systemctl restart apache2

    mysql -uroot -p
    
    mysql> GRANT ALL PRIVILEGES ON *.* TO 'dbuser'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
    
    # ALL PRIVILEGES: предоставляет полные права на использование данных.
    # *.* : права предоставляются на все базы и все таблицы.
    # dbuser: имя учетной записи.
    # localhost: доступ для учетной записи будет предоставлен только с локального компьютера.
    # password: пароль, который будет задан пользователю.
    # WITH GRANT OPTION: будут предоставлены дополнительные права на изменение структуры баз и таблиц.
    
    > quit
    

    И открываем наш сайт в браузере. В phpinfo появится новая секция MySQL.

    Настраивает возможность входа в adminer.php

    > use mysql;
    
    > update user set plugin='' where User='root';
    
    > flush privileges;
    
    > exit
    

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

    sudo systemctl restart mariadb.service

    Настройка пользователя

    Создаем пользователя

    adduser dev

    Добавляем пользователя в группу www-data

    adduser dev www-data

    Даем права sudo пользователю

    usermod -aG sudo dev

    NGINX

    Открываем и редактируем следующий файл:

    vi /etc/nginx/nginx.conf

    И внутри секции http добавляем:

    client_max_body_size 512M;

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

    systemctl restart nginx

    Установка Memcached

    Memcached — Программное обеспечение, реализующее сервис кэширования данных в оперативной памяти на основе хеш-таблицы.

    Для начала, выполняем установку пакетов:

    apt-get install memcached php-memcached

    После разрешаем автозапуск и запускаем сервис кэширования:

    systemctl enable memcached

    systemctl start memcached

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

    systemctl restart apache2

    Для проверки, что модуль memcached появился в PHP, открываем наш сайт в браузере — в phpinfo должна появиться новая секция Memcached.

    Создание первого сайта

    Создаем новый файл виртуального домена NGINX:

    vi /etc/nginx/sites-available/site.altopromo.com.conf

    Обязательно на конце должен быть *.conf, так как только такие файлы веб-сервер подгружает в конфигурацию.

    И добавляем следующее содержимое.

    Для HTTP

    # Устанавливается только на главный домен, чтобы шел редирект с ip на главный домен.
    server {
      listen 80;
      server_name Ваш_ip;
      return 301 http://site.altopromo.com$request_uri;
    }
    
    server {
      listen       80;
      server_name  site.altopromo.com www.site.altopromo.com;
      set $root_path /var/www/site.altopromo.com/www;
    
      access_log /var/www/site.altopromo.com/log/nginx/access_log;
      error_log /var/www/site.altopromo.com/log/nginx/error_log;
      gzip  on;
      gzip_disable "msie6";
      gzip_min_length 1000;
      gzip_vary on;
      gzip_proxied    expired no-cache no-store private auth;
      gzip_types      text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss
    
      root   $root_path;
    
      location / {
    		location ~ [^/]\.ph(p\d*|tml)$ {
    			try_files /does_not_exists @fallback;
    		}
    		location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {
    			try_files $uri $uri/ @fallback;
    		}
    		location / {
    			try_files /does_not_exists @fallback;
    		}
        }
        location @fallback {
    		proxy_pass http://127.0.0.1:8080;
    		proxy_redirect http://127.0.0.1:8080 /;
    		proxy_set_header Host $host;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header X-Forwarded-Proto $scheme;
    		access_log off;
    	}
    }
    

    Создаем ярлык:

    ln -s /etc/nginx/sites-available/site.altopromo.com.conf /etc/nginx/sites-enabled/site.altopromo.com

    Где site.altopromo.com — домен, для которого создается виртуальный домен;

    /var/www/site.altopromo.com — каталог, в котором будет размещаться сайт.

    Все запросы будут переводиться на локальный сервер на порт 8080, на котором работает apache, кроме обращений к статическим файлам (jpg, png, css и так далее).

    Для HTTPS

    Существующий Сертификат

    # Устанавливается только на главный домен, чтобы шел редирект с ip на главный домен.
    server {
      listen 80;
      server_name Ваш_ip;
      return 301 https://site.altopromo.com$request_uri;
    }
    
    server {
      listen       443 ssl;
      ssl on;
      ssl_certificate /etc/nginx/ssl/cert.pem;
      ssl_certificate_key /etc/nginx/ssl/cert.key;
    
      server_name site.altopromo.com www.site.altopromo.com;
      set $root_path /var/www/site.altopromo.com/www;
    
      access_log /var/www/site.altopromo.com/log/nginx/access_log;
      error_log /var/www/site.altopromo.com/log/nginx/error_log;
      gzip  on;
      gzip_disable "msie6";
      gzip_min_length 1000;
      gzip_vary on;
      gzip_proxied    expired no-cache no-store private auth;
      gzip_types      text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss
    
      root   $root_path;
    
      location / {
    		location ~ [^/]\.ph(p\d*|tml)$ {
    			try_files /does_not_exists @fallback;
    		}
    		location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {
    			try_files $uri $uri/ @fallback;
    		}
    		location / {
    			try_files /does_not_exists @fallback;
    		}
        }
        location @fallback {
    		proxy_pass http://127.0.0.1:8080;
    		proxy_redirect http://127.0.0.1:8080 /;
    		proxy_set_header Host $host;
    		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    		proxy_set_header X-Forwarded-Proto $scheme;
    		access_log off;
    	}
    }
    

    Создаем ярлык:

    ln -s /etc/nginx/sites-available/site.altopromo.com.conf /etc/nginx/sites-enabled/site.altopromo.com

    В первой секции server мы перенаправляем все запросы по незащищенному http на https.

    ssl_certificate и ssl_certificate_key — пути к публичному и приватному ключам соответственно.

    /etc/nginx/ssl/cert.pem - в cert.pem вставляем публичный сертификат
    /etc/nginx/ssl/cert.key - в cert.key вставляем приватный сертификат

    nginx -t

    nginx -s reload

    Получение бесплатного SSL сертификата Let's Encrypt

    Установил certbot:

    sudo apt install certbot

    Отредактировал конфиг etc/letsencrypt/cli.ini добавив:

    authenticator = webroot
    webroot-path = /var/www/site.altopromo.com
    post-hook = service nginx reload
    text = True
    

    Создал произвольный файл:

    mkdir -p /var/www/site.altopromo.com/.well-known/acme-challenge

    echo Success > /var/www/site.altopromo.com/.well-known/acme-challenge/example.html

    Зарегистрировался в Let's Encrypt:

    certbot register --email me@example.com

    Добавил в конфиг nginx:

    location /.well-known {
      root /var/www/site.altopromo.com;
    }
    

    Файл example.html что мы создали должен быть доступен, для проверки, выполним:

    curl -L http://site.altopromo.com/.well-known/acme-challenge/example.html

    Если все хорошо ответ будет Success.

    После проверки файл удалим:

    rm /var/www/site.altopromo.com/.well-known/acme-challenge/example.html

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

    Прежде чем получить сертификат рекомендуется провести тест:

    certbot certonly --dry-run -d example.com

    Если все ок получаем сертификат:

    certbot certonly -d example.com -d www.example.com

    Далее получим список сертификатов (find /etc/letsencrypt/live/ -type l) и зададим настройки для nginx:

    server_name site.altopromo.com;
    listen site.altopromo.com:443 ssl;
    access_log off;
    
    ssl_certificate /etc/letsencrypt/live/site.altopromo.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/site.altopromo.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/site.altopromo.com/chain.pem;
    
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 127.0.0.1 8.8.8.8;
    
    expires off;
    

    *не забыть в админке включить SSL и принудительное перенаправление.

    Теперь создаем виртуальный домен в Apache:

    vi /etc/apache2/sites-available/site.altopromo.com.conf

    <VirtualHost 127.0.0.1:8080>
      Define root_domain site.altopromo.com
      Define root_path /var/www/site.altopromo.com
    
      ServerName ${root_domain}
      ServerAlias www.${root_domain}
      DocumentRoot ${root_path}/www
    
      ErrorLog ${root_path}/log/apache/error_log
      TransferLog  ${root_path}/log/apache/access_log
    
      <IfModule mod_dir.c>
          DirectoryIndex index.php index.html index.htm
      </IfModule> 
    
      <Directory /var/www/site.altopromo.com/www>
          AllowOverride All
          Options Indexes ExecCGI FollowSymLinks
          Require all granted
      </Directory> 
    
      <IfModule setenvif_module>
          SetEnvIf X-Forwarded-Proto https HTTPS=on
      </IfModule> 
    
      <IfModule php7_module>
          php_admin_value upload_tmp_dir ${root_path}/tmp
          php_admin_value doc_root ${root_path}
          php_value open_basedir    ${root_path}:/usr/local/share/smarty:/usr/local/share/pear
          php_value post_max_size 512M
          php_value upload_max_filesize 512M 
          php_flag short_open_tag On 
      </IfModule>
    </VirtualHost>
    
    #  где post_max_size — максимальный объем отправляемых на сервер данных;
    
    #  где upload_max_filesize — максимально допустимый размер одного загружаемог;
    
    #  где short_open_tag — разрешение использования короткого способа открытия php (<?).
    
    

    Создаем ярлык:

    ln -s /etc/apache2/sites-available/site.altopromo.com.conf /etc/apache2/sites-enabled/site.altopromo.com.conf

    Создаем каталоги для сайта:

    mkdir -p /var/www/site.altopromo.com/{www,tmp}

    mkdir -p /var/www/site.altopromo.com/log/{nginx,apache}

    Создаем индексный файл со следующим содержимым:

    vi /var/www/site.altopromo.com/www/index.php

    <?php echo "<h1>Hello world!</h1>"; ?>

    Задаем права на папки:

    chown -R www-data:www-data /var/www/site.altopromo.com

    chmod -R 775 /var/www/site.altopromo.com

    Проверяем корректность настроек конфигурационных файлов:

    nginx -t

    apachectl configtest

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

    systemctl reload nginx

    systemctl reload apache2

    Открываем сайт в браузере по нашему домену site.altopromo.com (он должен быть прописан в DNS или можно его задать в локальном файле hosts того компьютера, с которого мы открываем сайт в браузере).

    Мы должны увидеть фразу «Hello world!».