Базовая настройка сервера для 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

HTTPS configuration

Для проверки установки сертификата и его рейтинга воспользуемся сервисом SSL Server Test.

Более подробно настройки ssl-конфигурации и получение максимального рейтинга рассмотрим в отдельной статье.

Security configuration

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 configuration

Мы будем использовать версию PHP 7.2, которая устанавливается из официального репозитория.

Про установку и сборку различных версий PHP поговорим в отдельной статье.

Routing configuration

Routing configuration

Logging configuration

Logging configuration

Performance configuration

Performance configuration

Nginx configuration

Nginx configuration

Server 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+.

SSL Labs рейтинг 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
Автор :

Cookies and IP addresses allow us to deliver and improve our web content, resolve technical errors, and provide you with a personalized experience. Our website uses cookies and collects your IP address for these purposes.