NGINX + Apache + MariaDB (MySQL) + PHP + PHP-FPM (fastCGI) + FTP + PHPMyAdmin + Memcached + Postfix на Ubuntu

Обновлено Обновлено: Опубликовано Опубликовано:

Данная инструкция позволит настроить веб-сервер для решения большей части задач по размещению сайтов, порталов или веб-приложений. Она подходит для серверов на Ubuntu и других систем на основе deb-пакетов. Для RPM Linux читайте похожую инструкцию по настройке полноценного веб-сервера на CentOS.

Тематические термины: Linux, UbuntuNGINX, Apache, MySQL, MariaDBPHP-FPMFTPphpMyAdminMemcached, Postfix.

Содержание:

Настройка операционной системы

Обновляем Ubuntu:

apt-get update && apt-get upgrade

Настраиваем время:

apt-get install ntpdate

cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime

ntpdate ru.pool.ntp.org

* первая команда для установки пакета синхронизации времени; вторая задает часовой пояс по московскому времени; третья выполняет синхронизацию времени с сервером ru.pool.ntp.org.

Настраиваем cron для автоматической синхронизации времени:

crontab -e

И настраиваем запуск задания ежедневно в 00:00:

0 0 * * * /usr/sbin/ntpdate ru.pool.ntp.org

По умолчанию, в Ubuntu брандмауэр работает в режиме «разрешить все». Но если мы настроили защиту по максимуму, то для веб-сервера открываем следующие порты:

iptables -A INPUT -p tcp --match multiport --dports 20,21,25,80,443,465,587,8080,40900:40999 -j ACCEPT

* 80, 443 и 8080 порты для веб-сервера; 20, 21 порты нужны для работы FTP; 40900-40999 также необходимы для работы FTP (динамические порты для пассивного режима); 25, 465 и 587 порты нужны для работы почтового сервера по SMTP; Подробнее про настройку iptables.

Установка NGINX

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

apt-get install nginx

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

vi /etc/nginx/nginx.conf

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

* в данном примере мы сняли комментарий со строчки 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

* в процессе запуска мы можем увидим ошибку — возможно, в системе работает другой веб-сервер и занимает 80 порт. Как правило, это apache. Чтобы его выключить (на данном этапе он нам не нужен) вводим команду systemctl stop apache2.

Проверим работу веб-сервера. Открываем браузер и вводим в адресной строке http://<IP-адрес сервера>. В итоге мы должны увидеть заголовок «Welcome to nginx!»:

Заголовок Welcome to nginx!

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

systemctl status nginx

Установка PHP и PHP-FPM

Устанавливаем PHP и PHP-FPM:

apt-get install php php-fpm

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

systemctl enable php7.2-fpm

systemctl start php7.2-fpm

* обратите внимание, что мы запустили php-fpm версии 7.2. Но установлена может быть и другая версия — ее можно узнать по версии php командой php -v.

Настройка связки NGINX + PHP

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

vi /etc/nginx/sites-enabled/default

В секции location редактируем параметр index на следующее значение:

    location / {
        index index.php index.html index.htm;
    }

* в данном случае мы сказали серверу сначала искать индексный файл index.php, затем остальные по списку.

А внутри секции server добавим следующее:

        location ~ \.php$ {
            set $root_path /var/www/html;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
            include fastcgi_params;
            fastcgi_param DOCUMENT_ROOT $root_path;
        }

* где /var/www/html — корневой путь хранения скриптов; /run/php/php7.2-fpm.sock — путь до сокетного файла для взаимодействия с php-fpm. Обратите еще раз внимание, что если в нашей системе будет установлена другая версия php, необходимо внести соответствующую корректировку.

Пример файла default:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
    server_name _;

    location / {
        index index.php index.html index.htm;
    }

    location ~ \.php$ {
        set $root_path /var/www/html;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_param DOCUMENT_ROOT $root_path;
    }
}

Проверяем правильность настроек nginx:

nginx -t

И перезагружаем его:

systemctl restart nginx

Открываем конфигурационный файл PHP-FPM:

vi /etc/php/7.2/fpm/pool.d/www.conf

Проверяем, что путь до сокетного файла такой же, как мы задали в настройках NGINX:

listen = /run/php/php7.2-fpm.sock

В противном случае меняем его и перезапускаем сервис:

systemctl restart php7.2-fpm

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

cd /var/www/html

Создаем index.php со следующим содержимым:

vi index.php

<?php phpinfo(); ?>

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

Информация о php (phpinfo)

* в данном примере используется php версии 7.2.

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

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

apt-get install mariadb-server

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

systemctl enable mariadb

systemctl start mariadb

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

mysqladmin -u root password

PHP + MariaDB

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

apt-get install php-mysql php-mysqli

После перезагружаем php-fpm:

systemctl restart php7.2-fpm

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

В phpinfo появилась информация о поддержке MySQL

* несмотря на то, что мы установили mariadb, в заголовке мы видим mysql. Так и должно быть.

Установка phpMyAdmin

Для установки phpMyAdmin вводим следующую команду:

apt-get install phpmyadmin

* в процессе установки система может потребовать ввод пароля для пользователя phpmyadmin. Его нужно ввести дважды.

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

vi /etc/nginx/sites-enabled/phpmyadmin.conf

И добавим в него следующее содержимое:

server {
        listen       80;
        server_name  phpmyadmin.dmosk.local;
        set $root_path /usr/share/phpmyadmin;

        root $root_path;

        location / {
                index index.php;
        }

        location ~ \.php$ {
                fastcgi_pass unix:/run/php/php7.2-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
                include fastcgi_params;
                fastcgi_param DOCUMENT_ROOT $root_path;
        }
}

* где phpmyadmin.dmosk.local — адрес для виртуального домена, именно этот адрес должен быть введен в адресную строку браузера, чтобы открылся нужный сайт. Поэтому есть нет возможность зарегистрировать домен и имя узла в DNS, можно воспользоваться локальным файлом hosts. /usr/share/phpmyadmin — это каталог, в который по умолчанию устанавливается phpMyAdmin.

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

systemctl reload nginx

И открываем в браузере наш домен, в данном примере, http://phpmyadmin.dmosk.local. Откроется форма для авторизации — вводим логин phpmyadmin и пароль, который мы указали при установке.

Установка Memcached

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

apt-get install memcached php-memcached

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

systemctl enable memcached

systemctl start memcached

Перезапускаем php-fpm:

systemctl restart php7.2-fpm

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

В phpinfo появилась информация о поддержке Memcached

Установка и настройка FTP-сервера

Мы настроим ProFTPd, так как он позволит использовать виртуальных пользователей с uid пользователя www-data.

Для его установки вводим следующую команду:

apt-get install proftpd

Смотрим uid пользователя www-data:

id www-data

* в Ubuntu это, как правило, 33.

Создаем виртуального пользователя:

ftpasswd --passwd --file=/etc/proftpd/ftpd.passwd --name=ftpwww --uid=33 --gid=33 --home=/var/www --shell=/usr/sbin/nologin

* где /etc/proftpd/ftpd.passwd — путь до файла, в котором хранятся пользователи; ftpwww — имя пользователя (логин); uid и gid — идентификаторы пользователя и группы системной учетной записи (www-data); /var/www — домашний каталог пользователя; /usr/sbin/nologin — оболочка, запрещающая локальный вход пользователя в систему.

Открываем основной конфигурационный файл:

vi /etc/proftpd/proftpd.conf

Снимаем комментарий или редактируем опцию:

DefaultRoot                     ~

* данная опция говорит о том, что корневой директорией для пользователя будет домашняя директория. Это нужно, чтобы FTP-пользователи не могли выйти за пределы дозволенного и видеть на сервере сайты друг друга.

Создаем дополнительный конфигурационный файл для proftpd:

vi /etc/proftpd/conf.d/custom.conf

Со следующим содержимым:

UseIPv6 off
IdentLookups off
PassivePorts 40900 40999

RequireValidShell off
AuthUserFile /etc/proftpd/ftpd.passwd
AuthPAM off
LoadModule mod_auth_file.c
AuthOrder mod_auth_file.c

* где 40900 - 40999 — диапазон динамических портов для пассивного режима.

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

systemctl enable proftpd

systemctl start proftpd

Пробуем подключиться к серверу, использую любые FTP-клиенты, например, FileZilla, Total Commander или тот же браузер.

Apache

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

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

apt-get install apache2 libapache2-mod-php

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

vi /etc/apache2/ports.conf

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

Listen 8080

#<IfModule ssl_module>
#       Listen 443
#</IfModule>

#<IfModule mod_gnutls.c>
#       Listen 443
#</IfModule>

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

Теперь открываем настройку следующего модуля:

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

И добавляем впереди индексных файлов index.php:

<IfModule dir_module>
    DirectoryIndex index.php index.html ...
</IfModule>

* если не указан конкретный скрипт, сначала веб-сервер пытается найти и запустить index.php, затем index.html и так далее.

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

vi /etc/apache2/apache2.conf

Рядом с опциями Directory дописываем:

<Directory /var/www/*/www>
    AllowOverride All
    Options Indexes ExecCGI FollowSymLinks
    Require all granted
</Directory>

* где Directory указывает на путь, для которого мы хотим задать настройки; AllowOverride — позволит переопределить все настройки с помощью файла .htaccess; Options задает некоторые настройки: Indexes разрешает списки каталогов, ExecCGI разрешает запуск cgi скриптов, Require all granted — предоставляет всем доступ к сайтам в данном каталоге.

Ниже допишем:

<IfModule setenvif_module>
    SetEnvIf X-Forwarded-Proto https HTTPS=on
</IfModule>

* этой настройкой мы при получении заголовка X-Forwarded-Proto со значением https задаем переменную $_SERVER['HTTPS'] равную on. Данная настройки критична для функционирования некоторых CMS.

Запрещаем mpm_event:

a2dismod mpm_event

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

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

a2enmod mpm_prefork

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

a2enmod php7.2

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

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

a2enmod setenvif

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

systemctl enable apache2

systemctl start apache2

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

Проверка работоспособности Apache с помощью phpinfo

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

NGINX + Apache

Ранее мы настроили связку nginx + php-fpm. Теперь настроим nginx + apache. Открываем конфигурационный файл nginx для сайта по умолчанию:

vi /etc/nginx/sites-enabled/default

Находим наш настроенный location для php-fpm:

...
        location ~ \.php$ {
            set $root_path /var/www/html;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $root_path$fastcgi_script_name;
            include fastcgi_params;
            fastcgi_param DOCUMENT_ROOT $root_path;
        }
...

и меняем на:

...
        location ~ \.php$ {
            proxy_pass http://127.0.0.1:8080;
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        }
...

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

nginx -t

systemctl restart nginx

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

Проверка работоспособности Apache + NGINX

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.

Postfix

В качестве агента MTA мы будем использовать удобный в настройке и надежный Postfix.

Установка, настройка и запуск

Устанавливаем пакет postfix:

apt-get install postfix

Вносим некоторые изменения в настройки:

vi /etc/postfix/main.cf

myorigin = $mydomain
smtp_generic_maps = hash:/etc/postfix/generic_map

* mydomain — домен сервера; myorigin — имя домена, которое будет подставляться всем отправляемым сообщениям без явного указания оного; smtp_generic_maps указывает на карту с общими правилами пересылки.

Открываем карту пересылки:

vi /etc/postfix/generic_map

И добавляем:

@dmosk.local    no-reply@dmosk.local

* данной настройкой мы будем подставлять всем отправляемым письмам без поля FROM адрес no-reply@dmosk.local.

Создаем карту:

postmap /etc/postfix/generic_map

Включаем автозапуск почтового сервера и запускаем его службу:

systemctl enable postfix

systemctl start postfix

Корректная отправка

Для того, чтобы сервер мог отправлять сообщения на внешние ящики, необходимо корректно настроить в DNS, как минимум, записи A и PTR.

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

Для создания PTR-записи необходимо написать письмо Интернет-провайдеру, к которому подключен наш сервер. Если наш сервер арендуется у хостинговой компании, необходимо либо написать данное письмо данной хостинговой компании, либо данная возможность может быть предоставлена в панели управления хостинговыми услугами.

Тюнинг веб-сервера

PHP

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

vi /etc/php/7.2/apache2/php.ini

И правим следующее:

post_max_size = 1G
...
upload_max_filesize = 512M
...
short_open_tag = On
...
date.timezone = "Europe/Moscow"

* где post_max_size — максимальный объем отправляемых на сервер данных; upload_max_filesize — максимально допустимый размер одного загружаемого файла; short_open_tag — разрешение использования короткого способа открытия php (<?); date.timezone — временная зона, которая будет использоваться веб-сервером, если ее не переопределить настройками в коде php или в файле .htaccess.

Теже настройки применяем для php-fpm:

vi /etc/php/7.2/fpm/php.ini

post_max_size = 1G
...
upload_max_filesize = 512M
...
short_open_tag = On
...
date.timezone = "Europe/Moscow"

Перезапускаем php-fpm и apache:

systemctl restart php7.2-fpm

systemctl restart apache2

NGINX

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

vi /etc/nginx/nginx.conf

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

client_max_body_size 512M;

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

systemctl restart nginx

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

Настало время проверить наш сервер на реальном примере. Задаем переменную, значение которой будет домен сайта:

TMP_SITE=site1.local

* где site1.local заменить на имя домена, для которого создаем первый сайт. Нам будет намного удобнее копировать и вставлять команды с переменной (не придется править после копипасты).

1. Добавление виртуального домена

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

vi /etc/nginx/sites-enabled/$TMP_SITE.conf

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

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

Для HTTP:

server {
    listen       80;
    server_name  site1.local www.site1.local;
    set $root_path /var/www/site1.local/www;

    access_log /var/www/site1.local/log/nginx/access_log;
    error_log /var/www/site1.local/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 text/javascript application/javascript;

    root   $root_path;

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
    
    location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {
            expires modified +1w;
    }
}

* где site1.local — домен, для которого создается виртуальный домен; /var/www/site1 — каталог, в котором будет размещаться сайт.
** все запросы будут переводиться на локальный сервер, порт 8080, на котором работает apache, кроме обращений к статическим файла (jpg, png, css и так далее).
*** обратите внимание на выделения полужирным — здесь нужно подставить свои данные.

Для HTTPS:

server {
    listen 80;
    server_name site1.local www.site1.local;
    return 301 https://$host$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  site1.local www.site1.local;
    set $root_path /var/www/site1.local/www;

    access_log /var/www/site1.local/log/nginx/access_log;
    error_log /var/www/site1.local/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 text/javascript application/javascript;

    root   $root_path;

    location / {
        proxy_pass http://127.0.0.1:8080/;
        proxy_redirect     off;
        proxy_set_header   Host             $host:$server_port;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
    
    location ~* ^.+\.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|docx|xls|xlsx|exe|pdf|ppt|tar|wav|bmp|rtf|js)$ {
            expires modified +1w;
    }
}

* в первой секции server мы перенаправляем все запросы по незащищенному http на https.
** ssl_certificate и ssl_certificate_key — пути к публичному и приватному ключам соответственно.
*** для получения бесплатного сертификата читайте статью Получение бесплатного SSL сертификата Let's Encrypt.

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

vi /etc/apache2/sites-enabled/$TMP_SITE.conf

<VirtualHost *:8080>
    Define root_domain site1.local
    Define root_path /var/www/site1.local

    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

    php_admin_value upload_tmp_dir ${root_path}/tmp
    php_admin_value doc_root ${root_path}
    php_admin_value open_basedir    ${root_path}:/usr/local/share/smarty:/usr/local/share/pear
    php_admin_value session.save_path 0;0660;${root_path}/tmp
</VirtualHost>

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

mkdir -p /var/www/$TMP_SITE/{www,tmp}

mkdir -p /var/www/$TMP_SITE/log/{nginx,apache}

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

vi /var/www/$TMP_SITE/www/index.php

<?php echo "<h1>Hello from site1</h1>"; ?>

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

chown -R www-data:www-data /var/www/$TMP_SITE

chmod -R 775 /var/www/$TMP_SITE

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

nginx -t

apachectl configtest

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

systemctl reload nginx

systemctl reload apache2

Открываем сайт в браузере по нашему домену site1.local (он должен быть прописан в DNS или можно его задать в локальном файле hosts того компьютера, с которого мы открываем сайт в браузере). Мы должны увидит фразу «Hello from site1».

2. Создание базы данных

Создаем базу данных для сайта командами:

mysql -uroot -p

> CREATE DATABASE site1 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

> GRANT ALL PRIVILEGES ON site1.* TO dbuser@localhost IDENTIFIED BY 'password' WITH GRANT OPTION;

> quit

* данными sql-командами мы создаем базу данных site1 и предоставляем к ней доступ для учетной записи dbuser с паролем password. При желании сделать соединение более безопасным, можно убрать WITH GRANT OPTION.

3. Создание пользователя FTP

Для возможности подключения к сайту по FTP, создаем отдельного пользователя:

ftpasswd --passwd --file=/etc/proftpd/ftpd.passwd --name=site1.local --uid=33 --gid=33 --home=/var/www/$TMP_SITE --shell=/usr/sbin/nologin

* тут мы создадим пользователя site1.local, который будет иметь доступ к каталогу /var/www/$TMP_SITE.

# Серверы # Интернет # Ubuntu # NGINX # MySQL # Linux
Дмитрий Моск — частный мастер
Была ли полезна вам эта инструкция?

Да            Нет