Ваше приложение работает на localhost. Теперь вы хотите открыть его по настоящему домену, не оставляя включённым свой ноутбук. Не хватает нескольких элементов: VPS, управляемого процесса приложения, DNS и reverse proxy с HTTPS.
В этом руководстве показан такой путь на примере небольшого Node.js-приложения. Claude Code может помочь изучить проект и подготовить конфигурацию для проверки, но ответственность за изменения на сервере остаётся за вами. Модель на VPS не устанавливается, а доступ к Claude и его оплата не связаны с хостингом.
Анимированное пошаговое руководство. Дашборд вымышленный, это демонстрация, а не мониторинг реальной инфраструктуры.
Посмотрите обзор развёртывания
Смотреть обзор развёртывания (видео на английском языке).
Что мы действительно проверили: настоящий дашборд, изначально созданный Claude Code, был развёрнут нашим оператором на временном Linux VPS. Мы проверили публичный DNS, доверенный HTTPS, перенаправление с HTTP на HTTPS, работу приложения и прокси без root-прав, а также доступность после перезапуска сервиса приложения. Нового автономного развёртывания силами Claude не проводилось. Приведённый ниже пример запроса носит обучающий характер и не является записанным ответом.
Прежде чем начать
- Linux VPS с systemd и SSH-аккаунт с правами sudo. Сначала используйте тестовый VPS; не перезаписывайте сервисы и веб-конфигурацию существующего сайта.
- Поддерживаемая LTS-версия Node.js, установленная для всего сервера, и Caddy, установленный как системный сервис. Установите эти компоненты до выполнения шагов развёртывания.
- Домен или поддомен, DNS-записи которого вы можете редактировать.
- Небольшое самодостаточное приложение. Наш пример отдаёт
index.htmlс помощьюserver.mjs, без пакетных зависимостей и базы данных.
Приложениям на фреймворках нужны собственные команды сборки и запуска, зависимости и план хранения данных. Не считайте, что проект на Next.js, Python или с базой данных можно использовать с этим примером из двух файлов без изменений.
1. Попросите Claude Code изучить проект, прежде чем что-либо менять
Начните в локальной директории проекта. Хороший первый запрос:
Inspect this project without changing files. Identify its runtime,
build and start commands, configuration and secrets. Propose a Linux
VPS deployment using a non-root systemd service and Caddy HTTPS.
Bind the app to 127.0.0.1:3000. Explain each proposed file and
verification step. Do not connect to a server or edit DNS.
Описанные в документации рабочие процессы Claude Code включают планирование перед правками. Проверяйте предлагаемые изменения, а не принимайте команды развёртывания вслепую. Не включайте в запросы и репозитории API-ключи, учётные данные production и приватные SSH-ключи; доступ только на чтение не делает конфиденциальные файлы закрытыми.
2. Подготовьте и перенесите приложение
Для этого минимального примера сохраните свой HTML как index.html и используйте следующий сервер. По умолчанию он привязан к loopback и не раскрывает произвольные файлы проекта:
import {createServer} from 'node:http';
import {readFileSync} from 'node:fs';
import {fileURLToPath} from 'node:url';
const page=readFileSync(new URL('./index.html',import.meta.url));
export function createAppServer(){
return createServer((req,res)=>{
const pathname=new URL(req.url,'http://localhost').pathname;
if(pathname!=='/' && pathname!=='/index.html'){
res.writeHead(404,{'Content-Type':'text/plain; charset=utf-8'});res.end('Not found');return;
}
res.writeHead(200,{'Content-Type':'text/html; charset=utf-8','X-Content-Type-Options':'nosniff'});res.end(page);
});
}
if(process.argv[1]===fileURLToPath(import.meta.url)){
const host=process.env.HOST||'127.0.0.1';const port=Number(process.env.PORT||3000);
const server=createAppServer();server.listen(port,host,()=>console.log(`Demo app listening on ${host}:${port}`));
process.on('SIGTERM',()=>server.close(()=>process.exit(0)));
}
Запустите его локально командой node server.mjs, откройте http://127.0.0.1:3000, затем остановите его, прежде чем продолжить. Если на VPS порт 3000 уже занят, выберите другой приватный порт и используйте его одинаково в сервисе и в прокси.
Из локальной директории проекта выполните команды, заменив deploy и VPS_IP на ваш SSH-аккаунт и реальный адрес сервера:
ssh deploy@VPS_IP 'mkdir -p ~/my-app'
scp index.html server.mjs deploy@VPS_IP:~/my-app/
На сервере установите эти два несекретных файла в доступную для чтения директорию приложения:
sudo install -d -m 0755 /opt/my-app
sudo install -m 0644 ~/my-app/index.html ~/my-app/server.mjs /opt/my-app/
command -v node
Запишите абсолютный путь к исполняемому файлу Node. Он должен быть доступен вне вашей login-оболочки и домашней директории. Установка через менеджер версий, доступная только пользователю в /home, не подходит для описанного ниже усиленного сервиса. Никогда не копируйте файл .env из среды разработки, приватные ключи или дампы базы данных в публичную веб-директорию.
3. Запустите приложение как systemd-сервис без root
Выполните sudoedit /etc/systemd/system/my-app.service. Замените /ABSOLUTE/PATH/TO/node на реальный общий для сервера путь к исполняемому файлу, который вы только что проверили:
[Unit]
Description=My Node web app
After=network.target
[Service]
Type=simple
DynamicUser=true
WorkingDirectory=/opt/my-app
ExecStart=/ABSOLUTE/PATH/TO/node /opt/my-app/server.mjs
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=3000
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
Механизмы контроля выполнения в systemd описывают динамические учётные записи и параметры усиления защиты. Этот профиль подходит для нашего приложения, работающего только на чтение; приложениям, которые записывают загрузки или базы данных, нужно осознанно настроить постоянное хранилище и права доступа.
sudo systemctl daemon-reload
sudo systemctl enable --now my-app.service
sudo systemctl status my-app.service --no-pager
curl -fsS http://127.0.0.1:3000/
Устраните ошибки приложения, прежде чем трогать DNS. Включённый сервис настроен на запуск при загрузке, но это не доказательство того, что перезагрузка была проверена.
4. Направьте поддомен на VPS
Создайте A-запись для выбранного имени хоста, например app.example.com, указывающую на публичный IPv4-адрес вашего VPS. В Cloudflare в нашей демонстрации с прямым подключением к серверу использовался режим DNS only и автоматический TTL. Не копируйте IP-адрес из нашей демонстрации в записи своего сайта.
Проверьте публичный ответ командой dig +short A app.example.com. Проверьте также dig +short AAAA app.example.com: если существует запись IPv6, она должна вести на то же работающее развёртывание по IPv6. DNS лишь сопоставляет адрес: он не запускает приложение и не настраивает HTTPS.
5. Поставьте Caddy перед приватным приложением
Оставьте сервис Node на 127.0.0.1:3000. Откройте публичные веб-порты 80 и 443 в firewall провайдера и в firewall хоста, не закрывая себе SSH-доступ. Не открывайте порт 3000 в интернет.
Добавьте этот блок сайта в конфигурацию установленного сервиса Caddy, заменив имя хоста из примера. Сохраните остальные блоки сайтов:
app.example.com {
encode zstd gzip
reverse_proxy 127.0.0.1:3000
}
Директива reverse_proxy перенаправляет публичные запросы на приватное приложение. При подходящем публичном имени хоста и выполнении условий проверки сертификата автоматический HTTPS в Caddy получает и продлевает сертификаты и перенаправляет HTTP на HTTPS.
Для стандартного системного сервиса Caddy и стандартного пути конфигурации:
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
sudo systemctl reload caddy
Наш VPS для съёмок использовал отдельный сервис Caddy и изолированные пути конфигурации, а не стандартный общий сервис, показанный выше. Принцип маршрутизации тот же; приведённые для читателя пути и названия сервисов — адаптация, а не дословная запись установки.
6. Проверьте публичный результат и перезапуск сервиса
curl -I http://app.example.com/
curl -I https://app.example.com/
sudo systemctl restart my-app.service
curl --retry 5 --retry-delay 1 --retry-connrefused -I https://app.example.com/
Убедитесь, что есть перенаправление HTTP на HTTPS, успешный ответ по HTTPS и действительный сертификат в браузере. Не используйте curl -k, чтобы скрыть ошибки доверия. Откройте страницу из другой сети, а не только изнутри VPS.
Если проверка после перезапуска не прошла, нужно разобраться: изучите journalctl -u my-app.service -n 50 --no-pager и логи сервиса Caddy. Ошибки DNS, неверный IPv6, остановленное приложение, неправильный порт upstream и заблокированная проверка сертификата — это разные проблемы.
Мы проверили перезапуск сервиса приложения, а не перезагрузку VPS и не конфигурацию с высокой доступностью. Прежде чем размещать реальное бизнес-приложение, продумайте также обновления, резервные копии, мониторинг, управление секретами и постоянные данные.
От локального проекта до публичного адреса
Весь путь прост: подготовьте проект, перенесите его на VPS, запустите как управляемый сервис без root, направьте DNS на сервер и завершайте публичный HTTPS на reverse proxy. Claude Code может помочь подготовить и объяснить эти элементы, но проверка и эксплуатационный контроль по-прежнему важны.
Ознакомьтесь с тарифами Linux VPS от SharpHeberg, когда будете готовы вывести локальный проект в сеть. Хостинг предоставляет серверное окружение, но не включает подписку на Claude и не размещает модель Claude локально.