Базовая настройка сервера для LEMP-стека
Table of contents
Introduction
В данной статье рассматривается базовая настройка сервера для разработки.
Установка и настройка будет производиться на сервере Ubuntu 18.04.2 LTS (Bionic Beaver)
.
В качестве хостинга используется EC2
инстанс на AWS.
В процессе развертывания будет установлено и настроено следующее ПО:
На выходе будет получен сервер с настроенным web-сервером NGINX
, поддержкой SSL
-сертификатов,
PHP-FPM
, MySQL
-сервером баз данных и установленными менеджерами пакетов npm
и Composer
.
Node будет установлен через NVM
, т.е. с возможностью переключения между версиями.
Также будет рассмотрено расширенное управление правами через ACL.
Server connection
Первым делом нам необходимо подключиться к серверу для дальнейшей настройки.
Для этого зайдем под выданными доступами (root
) на наш сервер, используя программное обеспечение:
Пользователь может отличаться от root, но он должен обязательно иметь право использовать привилегии суперпользователя sudo. Например, у AWS инстанса доступы выдаются от пользователя ubuntu.
Add new user
После того, как, соединились с сервером под пользователем root
, мы создадим нового пользователя и добавим его в новую группу пользователей, которую также создадим.
Создаем группу пользователей:
sudo groupadd developers
Список групп пользователей можно увидеть в файле /etc/group
, откроем его через редактор nano
:
nano /etc/group
В нем появилась новая запись:
developers:x:1001:
Теперь добавим нового пользователя developer
, занесем его в группу
developers
, sudo
и www-data
, а также дадим доступ к консоли bash
:
sudo useradd developer -g developers -m
sudo usermod -G sudo,developers,www-data developer
sudo usermod -s /bin/bash developer
Список пользователей можно увидеть в файле /etc/passwd
, откроем его через редактор nano
:
nano /etc/passwd
В нем появилась новая запись:
developer:x:1001:1001::/home/developer:/bin/bash
А в файле /etc/group
изменились записи:
sudo:x:27:ubuntu,developer
www-data:x:33:developer
Теперь осталось только задать пароль для нового пользователя. Для этого выполним команду passwd
и введем 2 раза пароль:
sudo passwd developer
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Перелогинимся на нового пользователя командой (или по новым доступам зайдем через PuTTY
):
sudo su developer
Теперь мы имеем нового пользователя, который включен в группу sudo
и
может выполнять команды из-под пользователя root
.
Сгенерируем ключи для доступа по ssh
:
ssh-keygen -t rsa -b 4096
Добавим сгенеренные ключи в список разрешенных для авторизации:
sudo cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Теперь мы можем соединиться с сервером используя ключи.
Удалить пользователя developer
можно следующей командой:
sudo deluser --remove-home developer
BASH color configuration
Как можно было заметить, в консоли все выводится одним цветом без разделения.
Чтобы улучшить ситуацию, мы применим цветовую схему к консоли в файле конфигурации, который находится в домашнем каталоге пользователя.
Перейдем в домашний каталог:
cd ~
~ обозначает домашнюю директорию.
Выведем список файлов:
ls -la
Откроем файл .bashrc
, используя редактор nano
:
sudo nano .bashrc
Найдем строку #force_color_prompt =yes
и раскомментируем ее, для этого уберем #
в начале строки.
После этого сохраним файл сочетанием клавиш Ctrl+O
и перезапустим сеанс PuTTY
для обновления конфигурации BASH
или просто перелогинимся под тем же пользователем:
sudo su developer
Server update
Теперь необходимо выполнить обновление сервера.
Обновление индекса пакетов:
sudo apt-get update
Индекс пакетов APT по существу база данных доступных пакетов из репозиториев, определенных в файле
/etc/apt/sources.list
и каталоге/etc/apt/sources.list.d
Обновление пакетов:
sudo apt-get upgrade
sudo apt-get dist-upgrade
После установки пакетов, возможно, понадобится перезагрузка. Выполним ее следующей командой:
sudo reboot
Server information
Пришло время узнать о сервере из консоли.
Выполним команду:
uname -a
uname - консольная UNIX-утилита, выводящая информацию о системе.
Выполним команду:
who
who - консольная UNIX-утилита, которая показывает текущих пользователей в системе.
Выполним команду:
date
date - консольная UNIX-утилита для работы с системными часами.
Installing NGINX
В качестве основного web
-сервера мы будем использовать NGINX
.
Для его установки выполним команду:
sudo apt-get install nginx
После выполнения установки перейдем в каталог установленного сервера:
cd /etc/nginx
Сразу создадим директорию (корневая директория сайта):
sudo mkdir -p /var/www/example.com/public
example.com - домен, который будет использоваться для примера.
В директории /var/www/example.com/public
создадим файл index.php
:
sudo touch /var/www/example.com/public/index.php
sudo nano /var/www/example.com/public/index.php
И выведем в нем phpinfo()
:
<?php
phpinfo();
Для конфигурирования воспользуемся сайтом: nginxconfig.io
HTTPS configuration
Для проверки установки сертификата и его рейтинга воспользуемся сервисом SSL Server Test.
Более подробно настройки ssl-конфигурации и получение максимального рейтинга рассмотрим в отдельной статье.
Security configuration
Referrer-Policy
: no-referrer-when-downgrade
- HTTP
-заголовок Referer
не будет отправлен при понижении уровня защищенности.
Подробнее: https://www.w3.org/TR/referrer-policy/#referrer-policy-no-referrer-when-downgrade
Content-Security-Policy
: default-src 'self' http: https: data: blob: 'unsafe-inline'
Подробнее: https://developer.mozilla.org/ru/docs/Web/HTTP/CSP
PHP configuration
Мы будем использовать версию PHP 7.2
, которая устанавливается из официального репозитория.
Про установку и сборку различных версий PHP поговорим в отдельной статье.
Routing configuration
Logging configuration
Performance configuration
Nginx configuration
Server configuration
После произведенной конфигурации сохраняем файлы, как указано ниже, но с некоторыми изменениями, показанными далее.
Мы находимся в директории /etc/nginx
, создадим тут файлы конфигурации.
Изменим конфигурацию сервера в файле nginx.conf
на ту, что получилась в процессе конфигурирования:
sudo nano nginx.conf
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 65535;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
types_hash_max_size 2048;
client_max_body_size 16M;
# MIME
include mime.types;
default_type application/octet-stream;
# logging
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn;
# SSL
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites
ssl_dhparam /etc/nginx/dhparam.pem;
# Mozilla Intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
resolver_timeout 2s;
# load configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Создадим директорию configs
:
sudo mkdir configs
Создадим файл с общей конфигурацией general.conf
и отредактируем его, добавив конфигурацию ниже:
sudo touch ./configs/general.conf
sudo nano ./configs/general.conf
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
}
# assets, media
location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ {
expires 7d;
access_log off;
}
# svg, fonts
location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ {
add_header Access-Control-Allow-Origin "*";
expires 7d;
access_log off;
}
# gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
Создадим файл с конфигурацией сертификатов letsencrypt letsencrypt.conf
и отредактируем его, добавив конфигурацию ниже:
sudo touch ./configs/letsencrypt.conf
sudo nano ./configs/letsencrypt.conf
# ACME-challenge
location ^~ /.well-known/acme-challenge/ {
root /var/www/_letsencrypt;
}
Создадим файл с конфигурацией параметров безопасности security.conf
и отредактируем его, добавив конфигурацию ниже:
sudo touch ./configs/security.conf
sudo nano ./configs/security.conf
# security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# . files
location ~ /\.(?!well-known) {
deny all;
}
Создадим директорию configs/php
:
sudo mkdir ./configs/php
В данной директории будем хранить конфигурации сокетов php-fpm
.
Создадим файл с конфигурацией php php7.2_fastcgi.conf
и отредактируем его, добавив конфигурацию ниже:
sudo touch ./configs/php/php7.2_fastcgi.conf
sudo nano ./configs/php/php7.2_fastcgi.conf
# 404
try_files $fastcgi_script_name =404;
# default fastcgi_params
include fastcgi_params;
# fastcgi settings
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_index index.php;
fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;
# fastcgi params
fastcgi_param DOCUMENT_ROOT $realpath_root;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param PHP_ADMIN_VALUE "open_basedir=$base/:/usr/lib/php/:/tmp/";
Создадим файл с конфигурацией сайта example.com
/etc/nginx/sites-available/example.com.conf
и отредактируем его, добавив конфигурацию ниже:
sudo touch ./sites-available/example.com.conf
sudo nano ./sites-available/example.com.conf
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
set $base /var/www/example.com;
root $base/public;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# security
include configs/security.conf;
# logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log warn;
# index.php
index index.php;
# index.php fallback
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# handle .php
location ~ \.php$ {
include configs/php/php7.2_fastcgi.conf;
}
# additional config
include configs/general.conf;
}
# subdomains redirect
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name *.example.com;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
return 301 https://example.com$request_uri;
}
# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name .example.com;
include configs/letsencrypt.conf;
location / {
return 301 https://example.com$request_uri;
}
}
Site activation
После создания всех файлов конфигурации нам необходимо активировать сайт, для этого выполним команду:
sudo ln -s /etc/nginx/sites-available/rdevelab.ru.conf /etc/nginx/sites-enabled
Мы просто создаем символьную ссылку на конфигурацию.
Теперь протестируем созданную конфигурацию:
sudo nginx -t
Мы получим ошибку, т.к. сертификаты еще не созданы, поэтому закомментируем подключение сертификатов в 2-х местах:
sudo nano /etc/nginx/sites-available/example.com
# SSL
#ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/rdelelab.ruexample.com/privkey.pem;
#ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
Теперь протестируем созданную конфигурацию еще раз и тест пройдет без ошибок:
sudo nginx -t
SSL configuration
Для начала сгенерируем ключи Diffie-Hellman
:
sudo openssl dhparam -dsaparam -out /etc/nginx/dhparam.pem 4096
Для настройки получения ssl
-сертификатов мы будем использовать certbot
, для этого добавим его репозиторий:
sudo add-apt-repository ppa:certbot/certbot
Далее выполним установку certbot
для nginx
:
sudo apt-get install python-certbot-nginx
Перезагрузим nginx:
sudo service nginx reload
Получим сертификат с использованием плагина nginx
для certbot
:
sudo certbot --nginx -d example.com -d www.example.com --rsa-key-size 4096
Т.к. получение сертификата идет в первый раз, то нас попросят ввести адрес email и принять условия использования.
Для проверки настройки обновления certbot
выполним сухой прогон и если нет ошибок, то все настроено корректно:
sudo certbot renew --dry-run
Открыв в браузере сайт example.com
, мы должны увидеть ошибку 502
, т.к. еще не настроили PHP-FPM
.
Протестировав сайт сервисом https://www.ssllabs.com/ssltest/, получим рейтинг A+
.
Installing PHP
Установим пакеты PHP
:
sudo apt-get install php7.2-cli php7.2-fpm php7.2-curl php7.2-gd php7.2-mysql php7.2-mbstring php7.2-xml
Теперь перезагрузим nginx
:
sudo service nginx reload
Открыв в браузере сайт example.com
, мы должны увидеть результат выполнения команды phpinfo()
.
На данный момент установка PHP-FPM завершена.
Об установке нескольких версий PHP можно прочитать в статье: Установка нескольких версий PHP на Ubuntu 18.04.3 LTS
Installing Git
Для установки системы контроля версий Git выполним следующую команду:
sudo apt-get install git
Проверим версию установленного git:
git --version
Installing NODE
Для установки Node.js
будем использовать nvm
, это позволит переключаться между различными версиями node
.
Сначала установим curl
для скачивания скрипта установки:
sudo apt-get install curl
Nvm
будем устанавливать из репозитория:
https://github.com/creationix/nvm
Установим последнюю версию, для этого нужно открыть файл: https://github.com/creationix/nvm/blob/master/install.sh
И в branches/tags
переключиться на последний tag
.
Нам нужна его сырая версия, поэтому нажимаем кнопку Raw и откроется файл по ссылке:
https://raw.githubusercontent.com/creationix/nvm/<VERSION>/install.sh
<VERSION>
- tag, который мы выбрали
Его-то мы и скачиваем через curl
:
curl -sL https://raw.githubusercontent.com/creationix/nvm/<VERSION>/install.sh -o install_nvm.sh
И дальше мы его запускаем:
bash install_nvm.sh
Далее можно либо перелогиниться, либо подгрузить изменения командой:
source ~/.profile
Теперь NVM
установлен и мы можем установить нужную версию node
:
nvm ls-remote
Вывелся длинный список версий node
, мы же выберем последнюю, у которой есть приписка LTS
. Установим ее командой:
nvm install VERSION
И проверим ее версию:
node -v
Если мы установили несколько node
, то переключиться, можно командой:
nvm use VERSION
Просмотреть список установленных node можно командой:
nvm ls
Installing Composer
Для установки composer
перейдем в раздел: https://getcomposer.org/download/
и выполним команды:
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
После того, как, мы скачали composer, установим его глобально:
sudo mv composer.phar /usr/local/bin/composer
Installing MySQL
Установим сервер баз данных MySQL
:
sudo apt-get install mysql-server
Теперь запустим скрипт безопасности:
sudo mysql_secure_installation
Сначала нам предложат установить плагин валидации паролей (Validate Password Plugin
), который позволяет тестировать надёжность паролей MySQL
.
Далее предложат задать пароль для пользователя root
.
Зададим уровень сложности: 2.
И, после того, как, установили пароль пользователя root
, отвечаем на все вопросы: y
.
Проверим работу MySQL
:
sudo mysql
Добавим нового пользователя и разрешим MySQL
принимать удаленные соединения.
Откроем файл настроек:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
И закомментируем строку:
#bind-address=127.0.0.1
Сохраним файл и перезагрузим сервер MySQL
:
sudo service mysql restart
Зайдем в MySQL
и добавим нового пользователя и базу данных:
sudo mysql
CREATE DATABASE `example`;
SHOW DATABASES;
Добавим пользователя и разрешим ему доступ удаленно, а также дадим доступ ко всем таблицам базы данных:
CREATE USER 'developer'@'%' IDENTIFIED BY 'PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'developer'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
Вместо PASSWORD введите сложный пароль, иначе вы получите ошибку: ERROR 1819 (HY000): Your password does not satisfy the current policy requirements.
Теперь база данных доступна удаленно.
Дата редактирования : 2021-01-06 16:22:55
Автор : Rosko