Тот же сайт на VPS или выделенном сервере

Выбрать тариф

Сайту из урока 4 нужно очень мало: несколько файлов PHP, одна база данных, почтовый ящик в другом месте. Двух виртуальных ядер, 2 ГБ памяти и 40 ГБ диска хватит ему и экспериментам, которые последуют. Меньше — и сборка PHP или импорт базы могут упереться в память в самый неподходящий момент.

Ищите в предложении четыре вещи. Резервные копии или хотя бы снимки, которые можно восстановить за минуту. Адрес IPv4 и адрес IPv6. Консоль или режим восстановления в панели — на тот день, когда SSH перестанет отвечать. И дата-центр недалеко от ваших посетителей. VPS хостинг показывает, как создать машину у одного провайдера, включая регион, образ и ключ SSH; шаги ниже начинаются, когда машина работает и у вас есть её IP-адрес.

Ключ SSH и первый вход

Пароль по SSH можно подобрать; ключ — нельзя. Если вы создали сервер с открытым ключом, как описано на странице VPS, для первого входа пароль не нужен. Если провайдер прислал пароль root, войдите с ним один раз и сразу переходите на ключи.

ssh root@203.0.113.10

The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established. ED25519 key fingerprint is SHA256:.... This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])?

Набирайте yes, только если отпечаток совпадает с тем, что провайдер показывает в панели. Это сравнение — единственная защита от машины, которая притворяется вашим новым сервером. Приглашение меняется на root@example:~#.

Пользователь с sudo и обновления

Работа от root всё время — это способ превратить опечатку в простой. Создайте обычного пользователя, дайте ему право на sudo и скопируйте ключ, чтобы входить под этим пользователем:

adduser example

usermod -aG sudo example

cp -r /root/.ssh /home/example/.ssh

chown -R example:example /home/example/.ssh

chmod 700 /home/example/.ssh

chmod 600 /home/example/.ssh/authorized_keys

Откройте второй терминал и войдите под новым пользователем, прежде чем закрыть первый. Если ключ скопирован неправильно, у root ещё есть рабочая сессия, и вы можете всё исправить:

ssh example@203.0.113.10

С этого момента каждая команда, которая меняет систему, начинается с sudo. Затем приведите систему в актуальное состояние:

sudo apt update

sudo apt upgrade -y

apt update обновляет список доступных пакетов, apt upgrade устанавливает более новые версии. На свежем сервере вторая команда может обновить и ядро; перезагрузка в конце — это нормально.

Файрвол

В Ubuntu инструмент — ufw, надстройка над iptables, которая в Ubuntu 24.04 работает на бэкенде nftables. Сначала разрешите SSH, затем веб-порты и только потом включайте файрвол. В обратном порядке вы сами закроете себе доступ к серверу:

sudo ufw allow OpenSSH

sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

sudo ufw enable

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup

sudo ufw status verbose

Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip To Action From -- ------ ---- OpenSSH ALLOW IN Anywhere 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere OpenSSH (v6) ALLOW IN Anywhere (v6) 80/tcp (v6) ALLOW IN Anywhere (v6) 443/tcp (v6) ALLOW IN Anywhere (v6)

Два правила открывают веб-порты для сервера, который ставится дальше. Политика по умолчанию отклоняет каждое входящее подключение, которое не разрешено правилом, и это то, что нужно: база данных и панель остаются невидимыми из интернета, даже если слушают. Правила одинаковы в любом дистрибутиве Linux; Файрвол в Linux рассказывает о них подробнее.

Nginx, PHP-FPM и MariaDB

Сайт запускают четыре пакета: веб-сервер, обработчик PHP, база данных и горсть расширений PHP, которые нужны большинству сайтов на PHP. Ubuntu 24.04 поставляет PHP 8.3, и это та версия, которую использует курс:

sudo apt install nginx mariadb-server php8.3-fpm php8.3-mysql php8.3-curl php8.3-xml php8.3-mbstring php8.3-zip php8.3-gd unzip

Установщик запускает Nginx и MariaDB. PHP-FPM работает отдельной службой; Nginx использует его, когда блок сервера передаёт запросы .php в его сокет, что и делает блок ниже. Проверьте через systemctl, что все три службы работают:

systemctl is-active nginx mariadb php8.3-fpm

active active active

Откройте адрес сервера в браузере: отвечает приветственная страница Nginx, и это доказывает, что файрвол и веб-сервер согласны друг с другом. Если видите ошибку браузера, проверьте ufw status и systemctl status nginx. Полная установка, включая подробности о сайте по умолчанию, — в статье Установка Nginx на Ubuntu.

MariaDB нужна одна команда, чтобы быть в безопасности на свежей установке. Она задаёт пароль root для базы данных, удаляет анонимных пользователей и тестовые базы данных и задаёт несколько вопросов; отвечайте да на все:

sudo mariadb-secure-installation

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

Блок сервера

Папка для файлов, файл настройки для Nginx, символическая ссылка, которая его включает. Папка принадлежит пользователю сайта, а её группа — группа веб-сервера. Пока урок 8 не даст сайту собственный пул, PHP работает под www-data, поэтому папке загрузок понадобится запись для группы; команды после копирования её добавляют:

sudo mkdir -p /var/www/example.com/html

sudo chown -R example:www-data /var/www/example.com

sudo vi /etc/nginx/sites-available/example.com

server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/html; index index.php index.html; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.3-fpm.sock; } location ~ /\.ht { deny all; } }

Блок location / пробует запрошенный файл, затем папку, затем отвечает 404. Это правильное правило для небольшого сайта из курса. Фронт-контроллер, к которому прибегает фреймворк или CMS, отправляет каждый запрос в один файл, с try_files $uri $uri/ /index.php?$query_string;. Блок PHP отправляет каждый запрос .php в сокет PHP-FPM по умолчанию; отдельный пул на сайт заменяет его в уроке 8. Последний блок отказывает в любом запросе к скрытому файлу .htaccess.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

sudo nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

sudo systemctl reload nginx

Домену пока не обязательно указывать сюда. Nginx выбирает сайт по заголовку Host, поэтому curl может притвориться доменом, и запрос дойдёт до вашего нового блока. Папка пока пустая, поэтому запрос ответил бы 403; сначала напишите тестовую страницу от пользователя сайта:

sudo -u example sh -c 'echo "<h1>example.com</h1>" > /var/www/example.com/html/index.html'

curl -H "Host: example.com" http://203.0.113.10/

<h1>example.com</h1>

Шаг с rsync ниже заменит этот тестовый файл настоящим сайтом.

Скопировать сайт через rsync

Со своего компьютера, из папки с файлами сайта, скопируйте всё на сервер. -a сохраняет права и время, -v перечисляет файлы, -z сжимает передачу, а --delete удаляет на сервере файлы, которых больше нет локально:

rsync -avz --delete ~/site/ example@203.0.113.10:/var/www/example.com/

sending incremental file list ./ config.php html/ html/index.php html/uploads/ ...

Назначение — папка сайта, а не html/: config.php попадает на уровень выше веб-корня, точно как на виртуальном хостинге.

Будьте осторожны с --delete в первый раз: он приводит сервер в точное соответствие с вашей папкой. Если папка загрузок есть только на сервере, её удалят. Скопируйте один раз без этой опции, сравните, затем добавьте её для регулярных обновлений.

PHP работает под www-data, пока урок 8 не создаст пул для сайта, а файлы, скопированные rsync, принадлежат example с группой example, поэтому сайт пока не может писать свои загрузки. Создайте папку, если копирование её не принесло, и дайте веб-серверу запись для группы только на эту папку:

sudo -u example mkdir -p /var/www/example.com/html/uploads

sudo chgrp -R www-data /var/www/example.com/html/uploads

sudo chmod -R g+w /var/www/example.com/html/uploads

Урок 8 заменит это пулом PHP-FPM, который работает под example, и тогда папку можно вернуть группе сайта.

Импорт базы данных

Файлы — только половина сайта; таблица pages и её строки живут в базе данных. Экспортируйте её на старом хосте, перенесите дамп и импортируйте на новом сервере. На старом хосте:

mysqldump -u example_user -p example_db > site.sql

scp site.sql example@203.0.113.10:~/

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

sudo mariadb -e "CREATE DATABASE example_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

sudo mariadb -e "CREATE USER 'example_user'@'localhost' IDENTIFIED BY 'a-long-random-password';"

sudo mariadb -e "GRANT ALL ON example_db.* TO 'example_user'@'localhost';"

sudo mariadb example_db < ~/site.sql

Дамп большого сайта занимает время и ничего не печатает, когда всё удалось. Проверьте результат внутри базы данных: в списке таблиц должна быть pages:

sudo mariadb -e "SHOW TABLES FROM example_db;"

+---------------------+ | Tables_in_example_db | +---------------------+ | pages | +---------------------+

Если старый хост использовал другого пользователя или пароль базы, отредактируйте config.php на новом сервере под то, что вы только что создали. Тогда сайт загружается по временному IP с заголовком Host из проверки выше, до любого изменения DNS.

Если ваш сайт на WordPress, дополнительные шаги перечислены в отдельной статье: Отдельная статья: WordPress (необязательно).

Снизить TTL и переключить DNS

Делайте это в два шага с разницей в день, и переезд займёт минуты, а не часы. Сначала, за день до переключения, снизьте TTL записей A и AAAA до 300 секунд. Тогда старый ответ быстро истечёт, когда вы его измените:

example.com. 300 IN A 198.51.100.20

Во-вторых, когда новый сайт правильно отвечает в проверке с заголовком Host, смените запись A на новый сервер, 203.0.113.10, и дождитесь, пока пройдёт старый TTL. Следите за ответом публичного резолвера: он ближе к тому, что видят посетители, чем ваш собственный:

dig +short @1.1.1.1 example.com

203.0.113.10

Оставьте старый сервер работать, а его файлы — неизменными хотя бы сутки после переключения. Некоторые посетители и некоторые почтовые серверы будут ещё пользоваться старым адресом, пока не истекут их кэши. Когда всё выглядит правильно, верните TTL к 3600 и отмените старый тариф.

Certbot и продление

Сертификат от Let's Encrypt бесплатен, и для него нужны две команды. Certbot читает настройку Nginx, доказывает контроль над каждым именем по HTTP, устанавливает сертификат и с --redirect пишет перенаправление с http на https. Первый запуск ещё спрашивает адрес почты для уведомлений об окончании срока и согласие с условиями обслуживания:

sudo apt install certbot python3-certbot-nginx

sudo certbot --nginx --redirect -d example.com -d www.example.com

Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem This certificate expires on 2027-02-04. Deploying certificate Successfully deployed certificate for example.com to /etc/nginx/sites-enabled/example.com Congratulations! You have successfully enabled HTTPS on https://example.com

Проверьте, что перенаправление на месте:

curl -I http://example.com/

HTTP/1.1 301 Moved Permanently Location: https://example.com/

Certbot также ставит таймер systemd, который продлевает сертификат дважды в день, когда срок подходит к концу. Проверьте, что таймер есть и что продление прошло бы успешно, не дожидаясь настоящей даты:

systemctl list-timers | grep certbot

Fri 2026-11-06 15:22:00 UTC 9h left certbot.timer certbot.service

sudo certbot renew --dry-run

Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/example.com/fullchain.pem (success)

Пробный запуск — та проверка, которую повторяют после любого изменения настройки. О самом сертификате рассказывает статья об HTTPS и сертификатах простыми словами, а о службе, которая его выпускает, — letsencrypt.org.

Журналы

Когда сайт ведёт себя странно, три места отвечают на большинство вопросов. Nginx пишет строку на каждый запрос в журнал доступа, а причины сбоев — в журнал ошибок:

sudo tail -n 5 /var/log/nginx/access.log

203.0.113.55 - - [06/Nov/2026:10:00:00 +0000] "GET / HTTP/1.1" 200 5123 "-" "Mozilla/5.0" 203.0.113.55 - - [06/Nov/2026:10:00:01 +0000] "GET /wp-login.php HTTP/1.1" 404 162 "-" "Mozilla/5.0"

sudo tail -n 5 /var/log/nginx/error.log

2026/11/06 09:59:12 [error] 1234#1234: *56 FastCGI sent in stderr: "PHP message: PHP Fatal error: Allowed memory size exhausted" while reading response header from upstream

Третье место — журнал systemd, который хранит вывод самих служб. Здесь видно падение PHP-FPM или перезапуск Nginx:

sudo journalctl -u php8.3-fpm -n 20 --no-pager

Читайте журналы снизу вверх и отметьте время первой ошибки. Первая строка — причина; сто строк после неё — следствия.

Что меняется на выделенном сервере

Всё вышеперечисленное работает на выделенном сервере так же: это тоже машина с Ubuntu, где вы root. Различия физические.

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

Тест

1 Зачем создавать обычного пользователя с sudo вместо работы от root?

  1. Root не может запускать веб-сервер
  2. Так сервер работает быстрее
  3. Команда с опечаткой гораздо менее разрушительна, а в журнале видно, кто что сделал
  4. SSH по умолчанию отказывает root во входе
Ответ

c) Root может удалить что угодно одной командой. Обычному пользователю нужен sudo на каждое изменение, и это заставляет на миг подумать и оставляет след для аудита.

2 В каком порядке настраивают файрвол на новом сервере?

  1. Сначала включить, потом разрешить SSH
  2. Разрешить SSH и веб-порты, потом включить
  3. Включить и ничего не разрешать
  4. Включить после того, как сайт выйдет в сеть
Ответ

b) При политике запрета по умолчанию и без правила для SSH вы сами закроете себе доступ. Разрешите нужные порты, затем включайте файрвол.

3 Какая директива заставляет Nginx отправлять запросы .php в PHP-FPM?

  1. root
  2. try_files
  3. server_name
  4. fastcgi_pass
Ответ

d) fastcgi_pass указывает сокет или адрес пула PHP-FPM. root только говорит, где лежат файлы.

4 Зачем снижать TTL за день до переноса сайта на другой сервер?

  1. Так новый сервер работает быстрее
  2. Старые закэшированные ответы быстро истекают, и посетители раньше попадают на новый адрес
  3. Так шифруются запросы DNS
  4. Так уменьшается размер сертификата
Ответ

b) TTL решает, как долго резолверы держат старый адрес. Снижайте его до изменения, а не после, чтобы само изменение разошлось за минуты.

5 Файлы на новом сервере, база данных импортирована, но сайт показывает старое содержимое. Какова наиболее вероятная причина?

  1. Файрвол блокирует порт 443
  2. Домен всё ещё разрешается в старый сервер или кэш ещё держит старый адрес
  3. PHP не установлен
  4. В базе данных нет таблиц
Ответ

b) До новой машины не добраться, пока DNS не укажет на неё и старые ответы не истекут. Проверьте заголовком Host против нового IP, чтобы разделить две проблемы.

6 Как узнать, что продление сертификата будет работать и дальше?

  1. Сегодня браузер показывает замок
  2. Файл сертификата существует
  3. certbot renew --dry-run завершается успешно, а таймер есть в списке
  4. Домен зарегистрирован
Ответ

c) Пробный запуск повторяет настоящее продление, ничего не меняя. Замок сегодня ничего не говорит о том, что будет через 60 дней.

7 Какая задача появляется только на выделенном сервере, но не на VPS?

  1. Установка Nginx
  2. Наблюдение за массивом RAID и замена отказавшего диска через провайдера
  3. Создание пользователя с sudo
  4. Выпуск сертификата
Ответ

b) Провайдер VPS скрывает оборудование. На выделенной машине диски, массив и удалённая консоль становятся частью вашей работы.

Автор статьи: Arthur Isaev