LEMP стек c PHP 7 на CentOS 7 + Let’s Encrypt в Google Cloud для развертывания приложения Symfony 4

от автора

Добрый день, уважаемый Хабр!
Скажу сразу, что я — разработчик, и, думаю многие коллеги меня поддержат, в наших проектах часто не хватает системных администраторов, где-то сначала, где-то всегда. Нам приходится изучать новые для себя материалы в данной области, а делиться друг с другом накопленным опытом, по-моему, правильно. Данная статья не претендует на лавры завершенного руководства по настройке CentOS, и да, в ней отключается SELinux, и не создаются дополнительные пользователи MySQL, она описывает лишь то, что сказано в заголовке при чем в минимальной рабочей конфигурации. В конфигурации, которую затем всегда может дополнить специалист, но которая позволит развернуть требуемый проект за максимально короткое время. Я буду благодарен гуру за их советы и замечания, всегда за конструктивную критику, на основании которой буду вносить правки, если потребуется. Для остальных же хочу процитировать AntonShevchuk: «Если Вы не согласны с автором статьи — опишите свою точку зрения, зачем же злорадно понижать ему карму?». Спасибо, поехали…

В данном посте я приведу конкретные шаги по установке и настройке связки Nginx + MySQL + PHP7 на CentOS 7. Стоит отметить, что в данной статье будет рассказано про настройку системы для одного домена. В качестве площадки будет использоваться инстанс на Google Cloud Platform, с создания которого и начну:

Создание экземпляра в Google Cloud с генерацией SSH-ключей

Выберем в главном меню выбираем «Compute Engine» и нажимаем «Создать экземпляр». В зависимости от предполагаемой нагрузки выбираем тип машины, но не ниже g1-small, так как Composer для Symfony 4 требователен к оперативной памяти и на f1-micro загрузить зависимости не сможет.

Предлагаемый образ загрузочного диска изменяем на CentOS 7, минимальный объем диска в 10Гб вполне подойдет для развертывания системы, всех необходимых библиотек и зависимостей.

Для доступа к создаваемому серверу по SSH необходимо сгенерировать соответствующий ключ, у пользователей MacOS X или Linux для этого существует команда

ssh-keygen -t rsa -f __FILE__ -C __USER__

где __FILE__ — путь к сохраняемому ключу с именем файла, а __USER__ — имя пользователя под которым вы будете логинититься в систему. При выполнения данной команды система запросит вас указать ключевую фразу, которая будет служить паролем при использовании данного ключа, ее ввод необязателен, для пропуска ничего не вводите и нажмите Enter, далее подтвердите предыдущее действие. После выполнения данной команды система создаст указанный в __FILE__ приватный ключ, а рядом с ним — открытый с именем __FILE__.pub
Последнее, что остается сделать с ключом пользователям MacOS X и Linux — это запретить доступ на запись для всех, кроме владельца ключа, делается это командой

chmod 400 __FILE__ 

Пользователи Windows могут вопользоваться программой PuTTYgen. Откройте программу, нажмите Generate и следуйте инструкциям, установленные по-умолчанию параметры подходит для большинства случаев, однако Google настаивает на 2048-битных ключах, не забудьте установить данный параметр. Поле «Key comment» служит для задания имени пользователя, а для задания ключевой фразы — «Key passphrase». После завершения генерации программа отобразит публичный ключ. Чтобы сохранить приватный ключ с расширением .ppk нажмите «Save private key».

Скопируйте содержимое открытого ключа (из файла __FILE__.pub для MacOS X / Linux или из окна PuTTYgen для Windows) и вставьте его в соответствующее поле на вкладке «Безопасность»:

Не забываем разрешить трафик HTTP и HTTPS, поставив галочки в соответствующих полях. На данном этапе все готово, нажимаем «Создать».

После создания система отобразит присвоенный экземпляру внешний IP-адрес, подключимся к нему по SSH используя приватный ключ:

ssh -i __FILE__ __USER__@__IP__

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

export USER_NAME=__ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__ export DOMAIN_NAME=__ВАШЕ_ДОМЕННОЕ_ИМЯ__

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

Обновляем систему и удаляем «осиротевшие» пакеты:

yum clean all yum update yum autoremove

Добавляем поддержку репозиториев Fedora, установим текстовый редактор nano и утилиту wget для возможности получения файлов с удаленных серверов. Для развертывания приложений на Symfony (и не только), я использую клонирование git-репозитория, для реализации данного метода установим поддержку git, также Symfony необходима поддержка zip (опция -y означает автоматический ответ «Y» на все возникающие у инсталлятора вопросы):

yum install epel-release nano wget git-core zip unzip -y

Нужно указать корректное имя хоста, для этого отредактируем конфигурационный файл сети:

cat << EOF > /etc/sysconfig/network HOSTNAME=${DOMAIN_NAME} EOF

Сохраняем файл и устанавливаем его же с помощью утилиты hostnamectl:

hostnamectl set-hostname ${DOMAIN_NAME}

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

yum install nginx -y

Запускаем nginx:

systemctl start nginx

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

systemctl enable nginx

Устанавливаем MySQL, запускаем и добавляем в автозагрузку:

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

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

mysql_secure_installation

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

yum install certbot -y

Так как к моменту написания данной статьи PHP 7 нет ни в репозиториях CentOS, ни в Fedora, его мы установим из репозитория REMI:

yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm yum-utils -y  yum-config-manager --enable remi-php72  yum --enablerepo=remi,remi-php72 install php-fpm php-common php-opcache php-cli php-pear php-pdo php-mysqlnd php-gd php-mcrypt php-xml php-zip -y

Весь необходимый софт установлен, перейдем к его настройке, первоначально отредактируем конфигурационный файл php-fpm:

nano /etc/php-fpm.d/www.conf

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

user = __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__ group = __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__ listen.owner = __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__ listen.group = __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__

Далее, укажем сокет — необходимо под строкой listen = 127.0.0.1:9000 добавить следующее:
listen = /var/run/php-fpm/php-fpm.sock

Сохраните изменения, затем запустите и добавьте php-fpm в автозагрузку:

systemctl start php-fpm systemctl enable php-fpm

Отключим SELINUX:

setenforce 0

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

nano /etc/selinux/config

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

Сохраните изменения и выйдете из режима суперпользователя. Далее мы создадим директорию для проекта в домашней директории и поместим туда индексный файл — заглушку для проверки работоспособности создаваемого стека:

cd mkdir -p ${DOMAIN_NAME}/public cd ${DOMAIN_NAME}/public nano index.php

Пусть содержимое файла будет следующим (замените __YOUR_ROOT_PASSWORD__ на пароль суперпользователя MySQL, указанный при его настройке):

<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>

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

nano /etc/nginx/nginx.conf

Изменим имя пользователя подобно конфигурации php-fpm:
user __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__;

Конфигурацию директивы server, созданную по-уполчанию, измените следующим образом:

server {     set $USER_NAME __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__;      server_name $hostname www.$hostname;      root /home/$USER_NAME/$hostname/public;      location / {         # try to serve file directly, fallback to index.php         try_files $uri /index.php$is_args$args;     }      location ~ ^/index\.php(/|$) {         fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;         fastcgi_split_path_info ^(.+\.php)(/.*)$;         include fastcgi_params;          fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;         fastcgi_param DOCUMENT_ROOT $realpath_root;          internal;     }      location ~ \.php$ {         return 404;     }      error_log /var/log/nginx/$hostname.error.log;     access_log /var/log/nginx/$hostname.access.log; }

Сохраните изменения и дайте команду nginx перечитать конфигурацию:

nginx -s reload

По доменному имени __ВАШЕ_ДОМЕННОЕ_ИМЯ__ должна открываться созданная нами страница — заглушка.

Приступим к созданию сертификата:

openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048  certbot certonly --webroot -w /home/${USER_NAME}/${DOMAIN_NAME}/public -d ${DOMAIN_NAME}  certbot certonly --webroot -w /home/${USER_NAME}/${DOMAIN_NAME}/public -d www.${DOMAIN_NAME}

После генерации ключей, изменим конфигурацию nginx для поддержки HTTPS, в данной конфигурации «главным» идет домен без www и настроено перенаправление на защищенное соединение. И так:

nano /etc/nginx/nginx.conf

Меняем созданную нами 2 шага назад директиву server на следующие:

server {        set $USER_NAME __ИМЯ_ПОЛЬЗОВАТЕЛЯ_СИСТЕМЫ__;        listen 443 ssl;        server_name $hostname;         ssl_certificate /etc/letsencrypt/live/__ВАШЕ_ДОМЕННОЕ_ИМЯ__/fullchain.pem;        ssl_certificate_key /etc/letsencrypt/live/__ВАШЕ_ДОМЕННОЕ_ИМЯ__/privkey.pem;         ssl_protocols TLSv1 TLSv1.1 TLSv1.2;        ssl_prefer_server_ciphers on;        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";        ssl_ecdh_curve secp384r1;        ssl_session_cache shared:SSL:10m;        ssl_session_tickets off;        ssl_stapling on;        ssl_stapling_verify on;        resolver 8.8.8.8 8.8.4.4 valid=300s;        resolver_timeout 5s;        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";        add_header X-Frame-Options DENY;        add_header X-Content-Type-Options nosniff;         ssl_dhparam /etc/ssl/certs/dhparam.pem;         root /home/$USER_NAME/$hostname/public;         location / {            # try to serve file directly, fallback to index.php            try_files $uri /index.php$is_args$args;        }         location ~ ^/index\.php(/|$) {            fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;            fastcgi_split_path_info ^(.+\.php)(/.*)$;            include fastcgi_params;             fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;            fastcgi_param DOCUMENT_ROOT $realpath_root;             internal;        }         location ~ \.php$ {            return 404;        }         error_log /var/log/nginx/$hostname.error.log;        access_log /var/log/nginx/$hostname.access.log;    }     server {        listen 443 ssl;        server_name www.$hostname;         ssl_certificate /etc/letsencrypt/live/www.__ВАШЕ_ДОМЕННОЕ_ИМЯ__/fullchain.pem;        ssl_certificate_key /etc/letsencrypt/live/www.__ВАШЕ_ДОМЕННОЕ_ИМЯ__/privkey.pem;        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;         return 301 https://$hostname$request_uri;    }     server {        server_name $hostname www.$hostname;        return 301 https://$hostname$request_uri;    }

Сохраняем результат и говорим nginx перечитать конфигурацию:

nginx -s reload

Так как Let’s Encrypt необходимо обновлять раз в три месяца, настроим автоматическое продление в планировщике, к примеру так, в ночь на понедельник

crontab -e

15 4 * * 1 /usr/bin/certbot renew —quiet
18 4 * * 1 /usr/bin/systemctl reload nginx

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

chown -R ${USER_NAME}:${USER_NAME} /var/lib/nginx chown -R ${USER_NAME}:${USER_NAME} /var/lib/php/session/

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

UPD:
По совету Amet13 в командах используются переменные + объединение пакетов в последовательную «бесшумную» установку


ссылка на оригинал статьи https://habr.com/post/419121/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *