Всем привет! Часто требуется поднять свой проект на VPS/VDS. Именно это я и покажу в данной статье.

Что нам понадобится

  1. VPS (Ubuntu 22.04, Ubuntu 24.04 - самый доступный вариант).

  2. Домен (для примера будет использоваться test.ru) и доступ к DNS-записям домена.

  3. Приложение (код вашего проекта), которое мы будем деплоить.

В конце я покажу альтернативный способ, который не потребует настройки NGINX, SSL, покупки домена и других вещей, а именно использование "движка приложений" Amvera с развертыванием через простой git push, где вся настройка произойдет автоматически.

От теории к практике: что мы будем делать?

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

Что мы будем делать (очень кратко):

  1. Запустим приложение "в коробке" - в Docker: приложение будет работать на сервере, но не торчать в интернет напрямую. То есть оно будет доступно только локально, например по 127.0.0.1:8000.

  2. Поставим reverse-proxy с помощью Nginx: Nginx будет единственным, кто торчит наружу на портах 80 и 443 (для ssl).

NGINX будет делать две вещи:

  1. Принимать запросы на test.ru;

  2. Перенаправлять их внутрь Docker-контейнера (127.0.0.1:8000).

  3. Сделаем нормальный HTTPS (SSL-сертификат) чтобы браузер показывал замочек и не ругался.

Сертификат используем бесплатный от Let's Encrypt. Cтавится он через certbot, плюс сам обновляется автоматически (если открыт 80 порт).

Практика и настройка VPS/VDS

Ниже я покажу “минимально правильный” путь: безопасный вход на сервер, установка Docker, загрузка проекта на VPS, запуск контейнера, подключение домена через Nginx и включение HTTPS.

Шаг 0: Подключаемся к серверу и обновляем систему

ssh root@IP-сервера
# Например: ssh root@1.2.3.4
# Команда ниже обновляет все пакеты и список доступных пакетов в системе
apt update && apt -y upgrade

Шаг 1. Создаем безопасного пользователя и настраиваем доступ по SSH-ключу

Работать под root - не лучшая идея. Мы будем делать правильно:

adduser deploy
usermod -aG sudo deploy

Теперь на своем ПК создаем ключ:

ssh-keygen -t ed25519

И копируем его на сервер (чтобы сервер мог нас корректно авторизовать):

ssh-copy-id deploy@IP-сервера

Проверяем вход:

ssh deploy@IP-сервера

Дальше по пути: отключаем root-логин и вход по паролю (чтобы мы могли войти только по ключу):

sudo nano /etc/ssh/sshd_config

Установим:

PermitRootLogin no
# !!! Не устанавливай PasswordAuthentication no, если еще не проверил вход по ключу !!!
PasswordAuthentication no

И применяем:

sudo systemctl restart ssh

Шаг 2. Включаем фаервол (UFW)

Оставляем наружу только SSH/HTTP/HTTPS:

sudo apt -y install ufw
# Запрещаем все входящее
sudo ufw default deny incoming
# Разрешаем все исходящее
sudo ufw default allow outgoing

sudo ufw allow OpenSSH
# HTTP
sudo ufw allow 80/tcp
# HTTPS
sudo ufw allow 443/tcp

sudo ufw enable
sudo ufw status

Шаг 3. Устанавливаем Docker

Вы можете просто скопировать следующий скрипт для установки Docker:

sudo apt update

sudo apt install ca-certificates curl gnupg

sudo install -m 0755 -d /etc/apt/keyrings    
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg    
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \      "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

или установить Docker по официальной инструкции.

И добавим себя в группу Docker:

sudo usermod -aG docker $USER
newgrp docker
docker version

Шаг 4. Загружаем файлы проекта на VPS

Рассмотрим два нормальных способа.

Способ A. через Git (самый удобный)

Если проект есть в Github/Gitlab:

sudo mkdir -p /opt/myapp # <- Здесь будет лежать наше приложение
sudo chown -R $USER:$USER /opt/myapp
cd /opt/myapp

git clone <ССЫЛКА_НА_РЕПОЗИТОРИЙ> .

Способ Б: загрузка файлов с ПК на сервер (scp/rsync)

Если репозитория нет или проще загрузить файлы:
scp:

scp -r ./myapp deploy@IP_СЕРВЕРА:/opt/

или rsync (лучше, если много файлов):

rsync -av --progress ./myapp/ deploy@IP_СЕРВЕРА:/opt/myapp/

Шаг 5. Создание Dockerfile и запуск приложения

Здесь все чуть более индивидуально, но шаблон один и тот же: в Dockerfile мы описываем, как собрать и запустить контейнер.

Что вообще такое Dockerfile:

Dockerfile - это простой текстовый файл, который содержит в себе понятную для Docker инструкцию к сборке и запуску образа (image) вашего приложения.

Я покажу два самых популярных кейса: Python FastAPI и Node.js.

5.1 Dockerfile - пример для Python FastAPI

FROM python:3.12-slim

WORKDIR /app

# Предполагается, что у нас есть файл requirements.txt со всеми зависимостями проекта
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host=0.0.0.0", "--port=8000"]

5.2 Dockerfile - пример для Node.js

FROM node:20-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --omit=dev

COPY . .

EXPOSE 3000
CMD ["npm", "start"]

5.3 Сборка образа и запуск контейнера

После того, как Dockerfile готов, остается 2 шага:

  1. Собрать image

  2. Запустить контейнер из образа

Перейдем в папку проекта:

cd /opt/myapp

Собираем образ (пусть будет myapp:latest):

# Предполагается, что Dockerfile расположен в той же папке, где работает терминал (/opt/myapp)
docker build -t myapp:latest .

Проверяем, появился ли образ:

docker images | grep myapp

Запускаем контейнер

Для примера с Python FastAPI:

docker run -d \
  --name myapp \
  --restart unless-stopped \
  -p 127.0.0.1:8000:8000 \
  myapp:latest

Проверяем, работает ли контейнер:

docker ps
docker logs -f --tail=200 myapp

5.4 Обновление приложения

Когда меняем код и хотим обновить контейнер, логика простая:

  1. Остановить и удалить старый контейнер.

  2. Собрать новый образ.

  3. Запустить новый контейнер.

cd /opt/myapp

docker stop myapp
docker rm myapp

docker build -t myapp:latest .

docker run -d \
  --name myapp \
  --restart unless-stopped \
  -p 127.0.0.1:8000:8000 \
  myapp:latest

Шаг 6. Настраиваем Nginx как reverse-proxy

Ставим nginx:

sudo apt -y install nginx
sudo systemctl enable --now nginx

Отключаем дефолтный сайт:

sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

Создаем конфиг сайта:

sudo nano /etc/nginx/sites-available/myapp

Заменим домен test.ru на собственный:

server {
    listen 80;
    server_name test.ru www.test.ru;

    client_max_body_size 25m;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_read_timeout 60s;
    }
}

Активируем сайт:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo nginx -t
sudo systemctl reload nginx

6.1 Установка A-записи на домене

Это необходимо для того, чтобы домен понимал, к какому IP он привязан.

В значении A записи (это такая DNS-запись, обычно настраивается на сайте регистратора в настройках домена) нужно прописать IP машины (VPS/VDS).

Шаг 7. HTTPS через Let's Encrypt (certbot)

Ставим certbot (версия для nginx):

sudo apt -y install certbot python3-certbot-nginx

Выписываем сертификат и автоматически правим конфиг Nginx:

sudo certbot --nginx -d test.ru -d www.test.ru

Проверяем автообновление (необязательно):

sudo certbot renew --dry-run

Шаг 8. Проверка и правки

Если контейнер запущен, A-запись раскатилась по DNS-серверам и test.ru открывается - все готово. Однако иногда бывает, что сайт отдает ошибку 502.

502 Bad Gateway

Обычно говорит о том, что Nginx не достучался до приложения.

docker ps
docker logs --tail=200 myapp
ss -lntp | grep 8000
sudo tail -n 200 /var/log/nginx/error.log

Альтернатива: запуск на Amvera за 3 минуты без настройки инфраструктуры

С VPS-путем выше все честно: он дает полный контроль, но требует времени и внимания - обновления ОС, UFW, конфиги Nginx, SSL, перезапуски, логи.

Если задача быстро развернуть проект и не заниматься обслуживанием сервера, проще использовать специализированный движек приложений, такой как Amvera.

Что такое Amvera

Amvera - сервис, заточенный на быстрый и легкий деплой IT-приложений, предоставляющий бонусом:

  • Автоматизацию развертывания. Достаточно просто сделать push в привязанный git (или перетянуть файлы в интерфейсе) и сервис сам все настроит и запустит.

  • Бесплатный внешний домен с HTTPS;

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

  • Бесплатные 111 рублей на баланс для тестов;

Когда это особенно удобно:

  • нужно быстро показать MVP/демо приложения

  • нет желания админить VPS

  • проект не один, и хочется повторяемости деплоя

А VPS-вариант выше остается отличным способом разобраться “как оно устроено внутри” и получить полный контроль.

Практика: деплой Amvera

Шаг 0. Регистрация пользователя

Тут все просто: регистрируемся по ссылке и сразу получаем бесплатные 111 рублей для тестов.

Шаг 1. Выбор типа приложения

Amvera предлагает запуск сразу нескольких типов приложения:

  1. Обычное приложение. Конфигурация, файлы проекта - все от вас.

  2. Преднастроенный сервис. Это сервис, который был заранее настроен и который можно развернуть менее, чем за 5 минут (это n8n, pgadmin, wordpress и др.).

  3. Cron-сервис. То же обычное приложение, но с возможностью запуска по расписанию.

Для нас актуален первый тип - Приложение.

Шаг 2. Создание проекта

Открываем главную страницу проектов и жмём кнопку "Создать проект"

Создаем проект
Создаем проект
  1. В открывшемся окне выбираем тип сервиса: "Приложение". Жмем далее.

  2. Далее выбираем произвольное название проекта и тариф.

  3. Обязательно жмем "Далее". После этого, дальнейшие этапы настройки приложения можно пропустить.

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

Открываем его.

Шаг 3. Базовая навигация и загрузка файлов

Тут нам важны все вкладки, но кратко я расскажу только про некоторые:

  • Репозиторий: тут собраны все файлы проекта:

  • Code: Git-репозиторий, содержащий все файлы для сборки запускаемого образа. Именно туда мы загрузим файлы.

  • Data: постоянное хранилище /data. Именно сюда ОБЯЗАТЕЛЬНО нужно сохранять все изменяемые в процессе работы приложения файлы. Это может быть как SQLite-БД, так и простой изменяемый JSON.

  • Конфигурация: встроенный конфигуратор и генератор amvera.yml (так называется файл конфигурации). К нему мы обратимся чуть позже.

  • Логи: наверное, самая важная вкладка для уже собранного приложения. В ней собраны:

    • Логи сборки проекта,

    • Логи приложения проекта,

    • Логи системы,

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

  • Домены: здесь вы можете подключить как собственный домен с HTTP/HTTPS, так и бесплатный домен от Amvera (ничего доплачивать не нужно).

Итак, загрузим файлы проекта.

Для этого переходим во вкладку Репозиторий -> Code и грузим файлы либо через интерфейс перетягиваем, либо подключаем GitLab, GitHub или BitBukket репозиторий, либо грузим вручную через git.

Шаг 4. Настройка конфигурации

Тут все как с Dockerfile - все индивидуально под каждый проект. Мы можем лишь показать примеры некоторых конфигураций.

Если у вас возникнут трудности с созданием конфигурации, обращайтесь к документации: https://docs.amvera.ru/applications/supported-env.html.

Пример для Python (запускаем main.py):

Задание конфигурации для Python
Задание конфигурации для Python

Шаг 5. Сборка и запуск приложения

Когда ваша конфигурация готова, вы можете попробовать собрать проект. Делается это во вкладке "Конфигурация" кнопкой "Собрать".

Во время сборки рекомендуется следить за логами и статусом проекта. Не всегда получается запустить проект с первого раза - это нормально.

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

Итог настройки VDS для деплоя

Мы развернули код на VDS, используя такие технологии как Docker, настроили Nginx и HTTPS (Let’s Encrypt). Открыли только нужные порты для безопасности и активировали наш код на удаленном сервере.

Если нужен тот же результат быстрее и без обслуживания сервера, можно задеплоить на Amvera за 3 минуты, сделав push в привязанный git и заполнив пару полей конфигурации.

Комментарии (1)


  1. Dok_DD
    07.12.2025 11:23

    еще один 100600 хауту, написанный под копирку.

    и root можно смело оставлять, если включить мозг и почитать man sshd_config на предмет Match хотя бы.

    и от туда же узнать что without-password давно уже deprecated