Web-сервер Nginx - пошагово

В этой инструкции пошагово разберём установку и настройку LEMP - стека для организации web-сервера на системе CentOS 7.

Будет сделано:

  • первоначальная настройка CentOS
  • установка и конфигурирование Nginx + php-fpm
  • установка и настройка MariaDB
  • установка PHP
  • создание двух тестовых сайтов, установка WordPress
  • автоматический Backup баз данных
  • поддержка HTTPS с помощью Let's Encrypt

Итак, мы находимся в только что установленном CentOS:


Выполняем обновление системы:

sudo yum clean all
sudo yum update
sudo yum autoremove

Устанавливаем текстовый редактор nano, файловый менеджер mc и инструменты для работы с сетью, программу для скачивания:

sudo yum install mc nano net-tools wget -y

Назначение имени компа:

sudo nano /etc/sysconfig/network
1
HOSTNAME=_имя_компьютера_
sudo hostnamectl set-hostname _имя_компьютера_

Назначение статического IP:

с помощью программулины:
 sudo nmtui
либо в рукопашку:
sudo nano /etc/sysconfig/network-scripts/ifcfg-eth0
1
2
3
4
5
6
7
8
9
BOOTPROTO="none"
IPADDR="192.168.2.203"
GATEWAY="192.168.2.254"
DNS1="192.168.2.254"
DNS2="8.8.8.8"
# Disable ipv6 #
IPV6INIT="no"
# Subnet #
PREFIX=24
Перезапуск сети:
sudo systemctl restart network

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

Написано здесь


Редактируем правила фаервола:

Смотрим работает ли фаервол:

firewall-cmd --state

Смотрим правила:

firewall-cmd --permanent --list-all

Убираем dhcpv6-client:

firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client

Разрешаем http:

firewall-cmd --permanent --zone=public --add-service=http

Перезагружаем правила:

firewall-cmd --reload

 

Ещё про фаервол: здесь


Установка Nginx:

Добавляем CentOS 7 EPEL репозиторий:

sudo yum install epel-release

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

sudo yum install nginx

Запускаем его:

sudo systemctl start nginx

Добавляем его в автозагрузку:

sudo systemctl enable nginx

Можно смотреть в браузер


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

Запускаем и добавляем в автозагрузку:

sudo yum install mariadb mariadb-server -y
sudo systemctl start mariadb
sudo systemctl enable mariadb

Проверяем порт 3306:

netstat -tulpn

Проведем начальную настройку MySQL, на все вопросы скрипта ответьте «Y» и придумайте пароль суперпользователя:

mysql_secure_installation

Делаем отдельную базу данных для будущего сайта и отдельного пользователя для этой базы:

mysql -u root -p

create database tst105db;

Создаем пользователя для локального подключения:

CREATE USER 'tst105dbuser'@'localhost' IDENTIFIED BY 'mypassword';

Дать полные права на базу tst105db пользователю tst105dbuser:

grant all on tst105db.* to 'tst105dbuser'@'localhost';

Если нужно, разрешаем удаленное подключение к БД:

Добавляем правило в фаерволл:

firewall-cmd --permanent --zone=public --add-port=3306/tcp
firewall-cmd --reload

Разрешаем подключения извне:

mysql -u root -p

Показать пользователей БД:

SELECT Host, User, plugin FROM mysql.user;

создать сетевого пользователя:

CREATE USER 'remoteuser'@'%' IDENTIFIED BY 'mypassword';

Дать полные права на базу tst105db пользователю remoteuser:

grant all on tst105db.* to 'remoteuser'@'%';
exit;

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

установим PHP7.2 из репозитория REMI:

yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum-utils -y

yum-config-manager --enable remi-php72

yum install php php-common php-opcache php-mcrypt php-cli php-gd php-curl php-mysqlnd -y

Проверяем:

php -v

--------------------------------------
Конфигурирование PHP 7.x для работы с Nginx:

В отличае от Apache, Nginx не имеет встроенной поддержки PHP файлов, поэтому нам нужно установить PHP FPM пакет:

sudo yum install php-fpm

По-умолчанию PHP FPM запускается под пользователем apache на порту 9000. Мы изменим пользователя на nginx:

sudo cp /etc/php-fpm.d/www.conf /etc/php-fpm.d/www.conf-original
sudo nano /etc/php-fpm.d/www.conf
1
2
3
4
5
6
7
...
user = nginx
...
group = nginx
...
listen.owner = nginx
listen.group = nginx

К тому же под строкой listen = 127.0.0.1:9000 нужно добавить следующее:

1
listen = /var/run/php-fpm/php-fpm.sock

Убедитесь что папка /var/lib/php имеет необходимые права доступа (ls -l):

sudo chown -R root:nginx /var/lib/php

Запускаем и добавляем в автозагрузку PHP FPM сервис:

sudo systemctl start php-fpm
sudo systemctl enable php-fpm

Для того чтобы Nginx мог обрабатывать PHP файлы:

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf-original
sudo nano /etc/nginx/nginx.conf
1
2
3
4
5
6
7
8
9
10
server {
# . . . other code
location ~ \.php$ {
#fastcgi_pass localhost:9000;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME
$document_root$fastcgi_script_name;
include fastcgi_params;
}
}

Перечитываем конфиг:

sudo nginx -t
sudo nginx -s reload

Кстати, вот команда для полного перезапуска Nginx (если вдруг понадобится):

sudo systemctl restart nginx

Сейчас по http отдается страница из /usr/share/nginx/html,
что в директиве root файла /etc/nginx/nginx.conf

Можно проверить работает ли php, создав рядом файл test.php со следующим содержимым:

<?php
 phpinfo();
 ?>

Для этого выполните команду

sudo nano /usr/share/nginx/html/test.php

Откройте его в браузере (не заабудьте сделать DNS-перенаправление имени домена на IP вашего сервера, например, с помощью файла hosts)

Проверяем работает ли php + mariadb:

sudo nano /usr/share/nginx/html/index2.php

Вставляем, заменяя пароль от рута базы данных:

<html>
<head>
    <h2>LEMP test</h2>
</head>
    <body>
    <?php echo '<p>Hello!</p>';

    $host = "localhost";
    $username = "root";
    $password = "__YOUR_ROOT_PASSWORD__";

    $connection = mysqli_connect($host, $username, $password);

    if (!$connection) 
        print '<p>DB connect failed with error: ' .  mysqli_connect_error() . '</p>';
    else
        print '<p>DB connection established</p>';
    ?>
</body>
</html>

Открываем в браузере http://.../index2.php


Создаём свои сайты. Создавать их будем в папке /var/www

cd /var/www
sudo mkdir tst104.1gb.ru
cd tst104.1gb.ru
sudo nano index.html

Итак, я создал 2 сайта:

/var/www/tst104.1gb.ru/public_html/index.html

/var/www/tst105.1gb.ru/public_html/index.php

Директивы server в файле файла /etc/nginx/nginx.conf я оставил такие:

#Если открывается tst104.1gb.ru или www.tst104.1gb.ru
server{
        listen 80;
        server_name     tst104.1gb.ru   www.tst104.1gb.ru;
        root /var/www/tst104.1gb.ru/public_html;

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

        location ~* \.(gif|jpg|png)$ {
            expires 30d;
        }

        location ~ \.php$ {
            fastcgi_pass  localhost:9000;
            fastcgi_param SCRIPT_FILENAME
                          $document_root$fastcgi_script_name;
            include       fastcgi_params;
        }

    }

#Если открывается tst105.1gb.ru или www.tst105.1gb.ru
server{
        listen 80;
        server_name     tst105.1gb.ru   www.tst105.1gb.ru;
        root /var/www/tst105.1gb.ru/public_html;

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

        location ~* \.(gif|jpg|png)$ {
            expires 30d;
        }

        location ~ \.php$ {
            fastcgi_pass  localhost:9000;
            fastcgi_param SCRIPT_FILENAME
                          $document_root$fastcgi_script_name;
            include       fastcgi_params;
        }

    }
    
#Если открывается без разницы какой сайт, кроме тех двух
server {
        listen       80 default_server;
        server_name _;
        root         /usr/share/nginx/html;

        location / {
        }
        
        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

Не забываем перечитать конфиг:

sudo nginx -t
sudo nginx -s reload

Теперь при открытии соответствующих сайтов (при условии наличия соответствующих DNS направлений) в первом случае откроется html файл, во втором - php. В любом другом случае - страница nginx.

Про настройки этого файла можно почитать в официальной русской документации здесь: http://nginx.org/ru/docs/http/request_processing.html


Ставим вордпресс:

Если установить Вордпресс Вам что-то мешает, то вот хардкордный рецепт:
Используйте это если у Вас появились проблемы с установкой:

Отключим SELINUX:

setenforce 0

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

nano /etc/selinux/config

где указать SELINUX=disabled

reboot

Качаем zip с официального сайта и распаковываем все его файлы в папку с нашим сайтом.

Переходим в папку сайта

cd /var/www/tst105.1gb.ru/public_html

Качаем (возьмите последнюю версию отсюда: https://ru.wordpress.org/download/):

sudo wget https://ru.wordpress.org/latest-ru_RU.tar.gz

Распаковываем:

sudo tar -xzvf latest-ru_RU.tar.gz

Удаляем файл:

sudo rm latest-ru_RU.tar.gz

Переносим всё содержимое папки public_html/wordpress в public_html:

cd ..
sudo mv -v public_html/wordpress/* public_html/

Удаляем папку wordpress:

sudo rmdir public_html/wordpress

Проверяем, что владелец всех файлов сайта - nginx и у группы есть права на запись (ls -l), если это не так, делаем

chown -R nginx:nginx tst104.1gb.ru
chmod -R 775 tst104.1gb.ru

Чтобы добавить пользователя в группу, выполните команду:

Добавляем пользователя admin2 в группу nginx

sudo usermod -a -G nginx admin2

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

id admin2

Открываем браузер и делаем первый запуск Вордпресса с указанием доступа к БД.

Если wordpress постоянно просит логин и пароль для FTP, то у Вас проблемы с правами на папку с сайтом. Проверьте чтобы пользователь из конфига nginx мог писать туда файлы.

Вообще говоря, у WordPress есть мануал насчёт Nginx'а: https://codex.wordpress.org/Nginx, где предлагается несколько иное содержимое файла nginx.conf


Настроим архивация MySQL с помощью automysqlbackup:

Заходим на сайт https://sourceforge.net/projects/automysqlbackup/files/AutoMySQLBackup/ и берём ссылку на свежую версию, заменяя пробелы на %20.

Подготавливаем папку:

sudo mkdir /opt/automysqlbackup
cd /opt/automysqlbackup

Скачиваем:

sudo wget http://downloads.sourceforge.net/project/automysqlbackup/AutoMySQLBackup/AutoMySQLBackup%20VER%203.0/automysqlbackup-v3.0_rc6.tar.gz

Распаковываем:

sudo tar zxvf automysqlbackup-v3.0_rc6.tar.gz

Удаляем файл архива:

sudo rm automysqlbackup-v3.0_rc6.tar.gz

Запускаем скрипт установки (global configuration directory и directory for the executable не меняем):

sudo ./install.sh

Редактируем конфиг:

sudo nano /etc/automysqlbackup/automysqlbackup.conf

Расскоментируйте и установите следующие директивы конфигурации

CONFIG_mysql_dump_username='_пользовательБД_'
CONFIG_mysql_dump_password='_пароль_пользователя_'
CONFIG_mysql_dump_host='localhost'
CONFIG_backup_dir='/var/www/backups/db'
CONFIG_do_monthly="01"
CONFIG_do_weekly="5"
CONFIG_rotation_daily=6
CONFIG_rotation_weekly=35
CONFIG_rotation_monthly=150
CONFIG_mysql_dump_port=3306
CONFIG_mysql_dump_compression='gzip'
CONFIG_db_exclude=( 'information_schema' 'performance_schema' )

Создаем папку для бакапов:

sudo mkdir /var/www/backups
sudo mkdir /var/www/backups/db

Можете проверить архивацию, выполнив:

sudo /usr/local/bin/automysqlbackup

Добавим задание в Cron:

sudo nano /etc/crontab
0 2 * * * root /usr/local/bin/automysqlbackup

Вызов automysqlbackup будет производиться каждый день в 2 часа ночи

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

Логи Cron находятся здесь: /var/log/cron

UPD:

Теперь сделаем архивацию файлов

В папке /var/www/backups создадим файл do_backup_now.sh:

cd /var/www/backupssudo nano do_backup_now.sh

И поместим примерно следующее содержимое:

#!/bin/sh
cd /var/www

#File naming
DATE=`date +"%Y-%m-%d_%Hh%Mm"`

#Creating list of site dirrectories on this pattern .*\.\w{1,4} (must ends with .abcd)
LIST=`ls | grep -E ".*\.\w{1,4}"`

#Create directory if not exists
test ! -d /var/www/backups/files_of_sites/`date +%Y`/`date +%m` && { mkdir -p /var/www/backups/files_of_sites/`date +%Y`/`date +%m` ; }

#Cicle of site dirrectories
for ELEMENT in $LIST
 do

 tar -zcvpf /var/www/backups/files_of_sites/`date +%Y`/`date +%m`/$ELEMENT-$DATE.tar.gz /var/www/$ELEMENT --exclude=backup --exclude=managed_cache --exclude=stats --exclude=resize_cache >> /dev/null 2> /var/www/backups/start_backup_files.sh.errors.log

 done
 
#Run mysql backup:
/usr/local/bin/automysqlbackup

exit 0

Дадим на него права:

sudo chmod 770 do_backup_now.sh

Теперь при вызове

sudo ./do_backup_now.sh

будет создататься архив файлов + архив баз в /var/www/backups

Теперь в Cron'е вместо

0 2 * * * root /usr/local/bin/automysqlbackup

укажем

0 2 * * * root /var/www/backups/do_backup_now.sh

Можно не использовать automysqlbackup, а прописать все в файле. Например, так:

 #!/bin/sh
cd /var/www

#File naming
DATE=`date +"%Y-%m-%d_%Hh%Mm"`

#Creating list of site dirrectories on this pattern .*\.\w{1,4} (must ends with .abcd)
LIST=`ls | grep -E ".*\.\w{1,4}"`

#Create directory if not exists
test ! -d /var/www/backups/files_of_sites/`date +%Y`/`date +%m` && { mkdir -p /var/www/backups/files_of_sites/`date +%Y`/`date +%m` ; }

#Cicle of site dirrectories
for ELEMENT in $LIST
 do

 tar -zcvpf /var/www/backups/files_of_sites/`date +%Y`/`date +%m`/$ELEMENT-$DATE.tar.gz /var/www/$ELEMENT --exclude=backup --exclude=managed_cache --exclude=stats --exclude=resize_cache >> /dev/null 2> /var/www/$

 done

#Run mysql backup:
#/usr/local/bin/automysqlbackup

USER="логин пользователя, имеющего доступ ко всем базам данных"
PASSWORD="пароль пользователя, имеющего доступ ко всем базам данных"
OUTPUT="/var/www/backups/db_of_sites/`date +%Y`/`date +%m`" #директория для хранения резервных копий

#Create directory if not exists
test ! -d $OUTPUT && { mkdir -p $OUTPUT ; }


databases=`mysql --user="$USER" --password="$PASSWORD" -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`

for db in $databases; do
    if [[ "$db" != "information_schema" ]] && [[ "$db" != "performance_schema" ]] && [[ "$db" != "mysql" ]] && [[ "$db" != "sys" ]]  ; then
        #echo "Dumping database: $db"
        mysqldump --force --opt --user="$USER" --password="$PASSWORD" --databases $db > $OUTPUT/$db-$DATE.sql
        gzip $OUTPUT/$db-$DATE.sql
    fi
done

exit 0

Настройка HTTPS:

Instructions:

https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/

Добавим поддержку Let's Encrypt:

yum install certbot -y

Важное отступление в том, что к этому моменту в вас должен быть доменное имя ссылающееся на данный сайт на сервере. Иначе сертификат не получится получить

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

certbot certonly --webroot -w /var/www/tst104.1gb.ru -d tst104.1gb.ru

certbot certonly --webroot -w /var/www/tst104.1gb.ru -d www.tst104.1gb.ru

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

Если у вас возникает ошибка типа

http://tst104.1gb.ru/.well-known/acme-challenge/eqPo2nLyj7GXUVOuZwGZfDIduAsUrOlMU_j0:
 "<!doctype html>\n<html lang=\"ru-RU\">\n<head>\n<meta
 charset=\"UTF-8\">\n<meta name=\"viewport\"
 content=\"width=device-width, initial-sca"

, проверьте правильность вот этого пути: certbot certonly --webroot -w /var/www/tst104.1gb.ru -d tst104.1gb.ru. В своё время я целый день потерял меняя насторйки nginx, создавая перенаправления на .well-known/acme-challenge, но оказалось нужно было просто дописать /public_html 🙂

Меняем настройки nginx для поддержки HTTPS:

sudo nano /etc/nginx/nginx.conf

В соответствующем server - вместо

listen 80;

пишем (будем использовать путь без www):

listen 443 ssl;    
ssl_certificate /etc/letsencrypt/live/tst104.1gb.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tst104.1gb.ru/privkey.pem;

А также заменяем

server_name     tst104.1gb.ru   www.tst104.1gb.ru;

на

server_name     tst104.1gb.ru;

Потому что сертификат годен только для него.

Сохраняем и проверяем конфигурацию:

sudo nginx -t

Если всё ок, то

sudo nginx -s reload

Проверяем прослушку 443 порта:

netstat -tulpn

Пробуем открыть в браузере https://tst104.1gb.ru и о чудо :)) работает!

Однако останось несколько неразрешенных моментов:

https://www.tst104.1gb.ru
http://tst104.1gb.ru
http://www.tst104.1gb.ru
Итак, по порядку:
Добавляем другие сертификаты + перенаправление с https://www.tst104.1gb.ru на  https://tst104.1gb.ru:

server {
       listen 443 ssl;
       server_name www.tst104.1gb.ru;

       ssl_certificate /etc/letsencrypt/live/www.tst104.1gb.ru/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/www.tst104.1gb.ru/privkey.pem;

       return 301 https://tst104.1gb.ru$request_uri;
   }

Перенаправление с HTTP на HTTPS для www и без него:

server {
       server_name tst104.1gb.ru www.tst104.1gb.ru;
       return 301 https://tst104.1gb.ru$request_uri;
   }

Сертификаты годны 90 дней, поэтому добавляем задачу в Cron на автообновление:

 sudo nano /etc/crontab
0 0 1 * * root /usr/bin/certbot renew --quiet
1 0 1 * * root systemctl restart nginx

Задача будет запускаться каждое 1 число месяца в 0 часов ночи. Команда проверяет, истекает ли сертификат на сервере в течение следующих 30 дней, и обновляет его, если это так. Директива --quiet просит certbot не генерировать output.

Через минуту после этого вызывается перезапуск nginx, т.к. новые сертификаты без этого не подцепятся. (Возможно, есть более красивый способ подцепления сертификатов, напишите в комментариях 🙂

Полезные статьи:


Настройка функции mail() на php

За основу взял статью https://hd.zp.ua/nastrojka-msmtp-dlya-otpravki-pisem-php-mail-cherez-servisy-gmail-i-yandex/ с некоторыми уточнениями и важным замечанием

Итак, мы не будем поднимать postfix и т.д. Мы будем слать почту через SMTP с помощью msmtp.

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

sudo yum install msmtp -y

Правим конфиг:

sudo nano /etc/msmtprc

Вносим данные только что зарегистрированной почты на Яндексе:

account yandex
logfile /var/log/msmtp.log
host smtp.yandex.ru
port 587
from YOUR_LOGIN@yandex.ru
keepbcc on
auth on
user YOUR_LOGIN@yandex.ru
password YOUR_PASSWORD
tls on
tls_starttls on
tls_certcheck off

Создадим файл для логов:

sudo touch /var/log/msmtp.log
sudo chown root:nginx /var/log/msmtp.log
sudo chmod 770 /var/log/msmtp.log

Проверяем.

Создаем дирректорию для тестов (в последствии можете её удалить):

sudo mkdir /var/www/msmtp
sudo chmod 777 /var/www/msmtp

cd /var/www/msmtp

Создаем тестовое письмо

echo -e "From: YOUR_LOGIN@yandex.ru \n\
To: YOUR_OWN_EMAIL@mail.ru \n\
Subject: Hello World \n\
\n\
This email was sent using MSMTP" >> sample_email.txt

В поле From укажите зарегистрированную на Яндексе почту (хотя, можете указать совершенно лефую и письмо придет якобы я неё 🙂 )

В поле To укажите почту куда будете слать письмо.

Делаем отправку из консоли:

Дебаг, но улетит в спам и будет пустое

sudo cat sample_email.txt | msmtp --debug -a yandex YOUR_OWN_EMAIL@mail.ru

Без дебага, но всё будет как надо
sudo cat sample_email.txt | msmtp  -a yandex YOUR_OWN_EMAIL@mail.ru

Теперь вы можете создать файл 1.php в корне вашего сайта с таким содержанием:

<?php
   if (mail("YOUR_OWN_EMAIL@mail.ru", "theme", "message", "From: YOUR_LOGIN@yandex.ru")){
      echo "success";
   }else{
      echo "error";
   } 
?>

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

sudo php /var/www/YOUR_SITE/1.php

будет. Здесь проблема в правах. И тут мы подошли к моменту, который немного вынес мне мозг:

Внимание! Очень важно чтобы владелец файла /etc/msmtprc был пользователь, под которым запущен web-сервер (у меня это nginx)
Особенно важно чтобы права на файл /etc/msmtprc были Чтение/Запись только для владельца! Не больше, не меньше! Иначе Вы не сможете отправлять письма и сломаете голову почему! Ещё раз повторю, что даже большие права на этот файл не дадут отправляться письмам. Права должны быть 600, а владелец - пользователь, под которым стартует web-сервер!

ls -l /etc/msmtprc

sudo chmod 600 /etc/msmtprc
sudo chown nginx /etc/msmtprc
sudo chgrp nginx /etc/msmtprc

ls -l /etc/msmtprc

Нужно сказать php через что слать письма:

sudo cp /etc/php.ini /etc/php.ini.original
sudo nano /etc/php.ini

Параметру sendmail_path присваиваем значение:

sendmail_path = "/usr/bin/msmtp -C /etc/msmtprc --logfile /var/log/msmtp.log -a yandex -t"

Перезагружаем php-fpm:

sudo systemctl reload php-fpm

Теперь письма полетят с помощью функции mail() - php как надо.

 

(Просмотрено 1 383 раз, 1 раз за сегодня)
Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий