Развёртывание статического на VPS вручную #
Допустим, что у вас уже есть:
- Виртуальная машина (VPS) с Debian GNU/Linux с известным IP адресом и доступом по SSH ключу
- Доменное имя, привязанное к IP адресу этой виртуальной машины
Разберём, как развернуть статический сайт с nginx на этой машине вручную.
Инструкция написана в предположении, что развёртывать сайт мы будем тоже из Linux.
Настройка Unix пользователей и доступов по ssh #
Настройка доступа под своим пользователем по ключу с sudo #
Скорее всего VPS позволяет подключится по SSH ключу из-под пользователя root, например так:
ssh root@ip-адрес-vps-сервера- Работать из-под root в Linux чревато проблемами — например, можно необдуманно выполнить опасную команду.
- Мы настроим подключение под обычным пользователем, и будем использовать
sudoдля запуска отдельных команд, требующих привилегий root.
Если на вашем компьютере тоже Linux, выясните имя пользователя командой: id -u -n
Допустим, мы получили имя ivan.ivanov.
Создать пользователя интерактивно (лучше указать привычный и надёжный пароль):
adduser --force-badname ivan.ivanovДобавить пользователя в группу sudo, чтобы он мог пользоваться sudo:
usermod -aG sudo ivan.ivanovОтредактировать файл /etc/sudoers.d/ivan_ivanov
- Мы позволим этому Unix пользователю использовать sudo без пароля
- Пустая строка в конце файла обязательна, иначе запуск sudo сломается для всех пользователей!
ivan.ivanov ALL=(ALL:ALL) NOPASSWD: ALLЗапустить сессию bash с новым пользователем и создать каталог ~/.ssh:
sudo -uivan.ivanov bash -l
mkdir -p ~/.sshОтредактировать файл ~/.ssh/authorized_keys, вставив туда свой публичный ключ (~/.ssh/id_rsa.pub или ~/.ssh/id_ed25519.pub).
Пример:
ssh-rsa AAAA...BHK ivan.ivanov@homeВсё! Теперь можно входить в систему по ключу и использовать sudo:
ssh ip-адрес-vps-сервера
sudo whoamiПодготовка конфигов nginx #
На своём компьютере создадим в проекте отдельную версию конфигов nginx для production:
- В проекте создайте подкаталог — например,
src/nginx-prod/ - Скопируйте в новый каталог конфиги nginx, используемые для локальной разработки — например, они могут быть в
src/nginx/ - Внесите изменения в конфиги для production
В конфигах для production стоит сделать несколько изменений:
- Поменять
user nginx;наuser www-data;— в Debian веб-сервер принято запускать под пользователем www-data - Пересмотреть
worker_processes 2;— возможно, вместо 2 поставить иное число или простоauto, чтобы число процессов nginx соответствовало числу ядер в системе - Поменять
error_log, чтобы писать логи в файл/var/log/nginx/error.logвместо stderr- в контекстах server можно вместо error.log указать иное имя файла — например,
atdd.ru.error.log
- в контекстах server можно вместо error.log указать иное имя файла — например,
- Поменять
access_log, чтобы писать логи в файл/var/log/nginx/access.logвместо stdout- в контекстах server можно вместо access.log указать иное имя файла — например,
atdd.ru.access.log
- в контекстах server можно вместо access.log указать иное имя файла — например,
- Явно определить
ssl_protocolsиssl_ciphers, чтобы поддержка TLS не зависела от версии nginx в дистрибутиве Linux, установленном на VPS - В контекстах
serverубрать локальные вариантыserver_name— например, убрать atdd.lan и localhost, но оставить atdd.ru - Поменяйте каталог в директиве
rootна/var/www/html/,/usr/local/www/atdd.ru/или любой иной каталог, куда вы планируете скопировать данные статического сайта
Пример изменений в nginx.conf:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024;
}
http {
# ... другие директивы ...
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
access_log /var/log/nginx/access.log;
}Пример изменений в конфиге хоста (контекст server):
server {
server_name atdd.ru;
access_log /var/log/nginx/atdd.ru.access.log;
error_log /var/log/nginx/atdd.ru.error.log warn;
root /usr/local/www/atdd.ru/;
# ... другие директивы ...
}Установка и настройка nginx на сервере #
Сначала зайдите на сервер: ssh ip-адрес-vps-сервера
Затем установите nginx:
sudo apt-get update
sudo apt-get install nginx
# Проверка версии nginx
sudo nginx -v
# Альтернативный способ - проверка версии пакета nginx
apt-cache policy nginxТеперь поменяйте основной конфиг nginx:
# Редактируем /etc/nginx/nginx.conf - скопируйте туда свою версию
sudo nano /etc/nginx/nginx.conf
# Проверяем корректность конфига nginx
sudo nginx -tУстановка последней версии nginx #
В дистрибутиве может быть устаревшая версия nginx, что помешает автоматизации работы с Let’s Encrypt.
- Например, в версиях nginx ниже 1.25.1 проявится проблема HTTP2 support in Nginx plugin
- Решение — установить последние версии nginx из официального репозитория nginx
Подробнее см. nginx: Linux packages, краткая версия ниже:
# Установка других необходимых пакетов
sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring
# Получение и проверка GPG-ключа репозитория
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
# Добавления репозитория APT
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/debian `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# Установка приоритета для пакетов из нового репозитория
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
# Установка новой версии nginx
sudo apt update
sudo apt install nginx
# Проверка версии nginx
sudo nginx -vПолучение сертификата Let’s Encrypt #
Временный конфиг nginx #
Добавим временный файл конфигурации на время получения сертификата Let’s Encrypt:
- Создайте конфиг своего сайта в каталоге
/etc/nginx/conf.d— например, используя редактор nano:sudo nano /etc/nginx/conf.d/atdd_ru.conf - Скопируйте конфигурацию ниже, поменяв atdd.ru на свой домен
- Обработка URL, начинающихся с
/.well-known, нужна для получения сертификата Let’s Encrypt
server {
listen 80;
listen [::]:80;
server_name atdd.ru;
root /usr/share/nginx/html;
location ~ /.well-known {
allow all;
}
location / {
index index.html;
}
}Установка и запуск Certbot #
Certbot — инструмент для автоматизации получения сертификатов Let’s Encrypt
- Сертификаты Let’s Encrypt выдаются на конкретный домен автоматизированно на 90 дней любому, кто докажет владение данным доменом
- Для выдачи сертификатов предусмотрен определённый протокол (ACME) и два способа доказательства владения доменом
- Мы применим один из способов доказательства владения доменом, реализованный в Certbot — отдача определённого файла с сервера, обслуживающего домен
Поддержка различных веб-серверов в Certbot реализована плагинами, и мы установим Certbot с плагином для nginx:
# Установка в Debian 12:
sudo apt install certbot python3-certbot-nginxДалее запускаем Certbot:
sudo certbot --nginxРезультат #
После запуска Certbot файл конфигурации nginx изменится.
- Обратите внимание на строки с суффиксом “# managed by Certbot”
- Эти строки не следует редактировать, т.к. их редактирует сам Certbot
- Однако их можно скопировать в локальную версию production конфигов в каталоге
src/nginx-prod/conf.d/
Вывести конфиг можно командой cat /etc/nginx/conf.d/<ваш-сайт>.conf. В моём случае он выглядит так:
server {
server_name atdd.ru;
root /usr/share/nginx/html;
location ~ /.well-known {
allow all;
}
location / {
index index.html;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/atdd.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/atdd.ru/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = atdd.ru) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name atdd.ru;
return 404; # managed by Certbot
}Применяем финальный конфиг #
В собственный конфиг nginx не забудьте внести правки от Let’s Encrypt:
- Скопировать все строки “# managed by Certbot”
- Добавить
обработку /.well-known
Пример:
server {
listen 80;
listen [::]:80;
server_name atdd.ru;
location ~ /.well-known {
root /usr/share/nginx/html;
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name atdd.ru;
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/atdd.ru/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/atdd.ru/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location ~ /.well-known {
allow all;
}
# ... другие параметры конфигурации
}Сохраним финальную версию и перезагрузим конфигурацию nginx
# Редактируем конфиг своего сайта - например, atdd.ru
sudo nano /etc/nginx/conf.d/atdd_ru.conf
# Проверяем корректность конфига nginx,
# затем выполняем чтение конфига сервисом nginx
sudo nginx -t && sudo systemctl reload nginxРазвёртываем статический сайт через rsync #
Утилита rsync предназначена для копирования файлов на сервер или между серверами при наличии SSH доступов. Для облачных платформ есть похожая утилита rclone, способная работать с S3-совместимыми хранилищами и с десятками других API облачных хранилищ.
Перед первым использованием нужно установить rsync как локально, так и на сервере:
sudo apt-get install rsyncДопустим, что мы хотим скопировать статический сайт с такими ограничениями:
- Локально статика находится в каталоге
public/проекта - На сервере nginx настроен на раздачу статики с каталога
/usr/local/www/atdd.ru/ - Пусть удалённый сервер доступен по домену
atdd.ruили по какому-то IP адресу - Мы не хотим копировать определённые файлы, например файл
.gitignore - Вход по SSH на сервере будет из-под root, но владельцем скопированных файлов будет www-data
Перед первым копированием на сервере надо создать каталог и поменять его владельца на www-data:
sudo mkdir -p /usr/local/www/atdd.ru
sudo chown www-data:www-data /usr/local/www/atdd.ruЗатем для каждого развёртывания можно использовать rsync:
# Проверка
rsync --dry-run --archive --progress --delete --exclude=.gitignore \
--chown=www-data:www-data \
public/ atdd.ru:/usr/local/www/atdd.ru/
# Выполнение
rsync --archive --progress --delete --exclude=.gitignore \
--chown=www-data:www-data \
public/ root@atdd.ru:/usr/local/www/atdd.ru/Объяснение флагов rsync:
| Флаг | Зачем он нужен |
|---|---|
| –archive | Архивный режим: копировать рекурсивно с сохранением владельца, группы, прав на файлы и времени изменения |
| –progress | Выводить прогресс |
| –delete | Удалять файлы в целевом каталоге, если их нет в источнике |
| –exclude=.gitignore | Исключить файлы по указанному шаблону |
| –chown=www-data:www-data | Поменять владельца и группу файлов на указанного |
Можно добавить в проект bash скрипт bin/deploy для копирования на сервер:
#!/usr/bin/env bash
set -o errexit
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
PROJECT_DIR=$(dirname "$SCRIPT_DIR")
rsync --archive --stats --delete --exclude=.gitignore \
--chown=www-data:www-data \
"$PROJECT_DIR/public/" \
root@atdd.ru:/usr/local/www/atdd.ru/