Astro на Ubuntu 24.04: пошаговая установка
Если сайт на Next.js или Nuxt грузит браузер мегабайтами клиентского JS ради простой лендинговой страницы, знакомая история. Astro устроен иначе: он собирает страницы в статический HTML и подключает JavaScript только там, где он реально нужен — «острова» интерактивности вроде формы или карусели, а не весь фреймворк целиком. Ниже — рабочий процесс установки Astro на чистый сервер с Ubuntu 24.04: от Node.js и первой сборки до продакшен-раздачи через Nginx, HTTPS и автодеплоя при обновлении контента.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Astro и когда есть смысл ставить его на свой VPS
Astro — генератор сайтов с «островной» архитектурой (islands architecture): по умолчанию каждая страница рендерится в чистый HTML/CSS без JS, а фреймворк-компоненты (React, Vue, Svelte, Solid — можно даже смешивать в одном проекте) гидрируются на клиенте только там, где вы явно это указали директивой client:load, client:visible и т.п. Итог — значительно меньше JS на клиенте по сравнению с типичным SPA-фреймворком, и как следствие обычно лучше метрики Core Web Vitals, особенно на мобильных.
У Astro три режима вывода:
- static (по умолчанию) — все страницы собираются в HTML на этапе сборки, сайт — набор статических файлов;
- server — приложение рендерит страницы на каждый запрос через Node-адаптер (SSR), нужен постоянно работающий процесс;
- гибридный подход — часть страниц пререндерится в static-режиме, часть помечается
export const prerender = falseи рендерится динамически (в Astro 5+ это делается внутри режимаserver, а не отдельным флагомhybrid, как было в более ранних версиях — если у вас старый проект, сверьтесь с документацией под вашу версию Astro).
Собственный VPS вместо Netlify/Vercel имеет смысл, когда: вам нужен SSR с доступом к внутренней сети (например, к своей БД без публичного API), вы хотите держать несколько сайтов на одном сервере без лимитов бесплатных тарифов, или экономика важнее — аренда VPS с оплатой из России картой или криптой часто выходит дешевле подписок на зарубежные PaaS, особенно на нескольких проектах.
Подготовка сервера: Node.js и системные зависимости
Понадобится чистый VPS на Ubuntu 24.04 с пользователем, у которого есть sudo (если сервер только что развёрнут и вы ещё не разграничили root-доступ и базовую защиту, сначала пройдите первичную настройку Ubuntu 24.04 — обновления, firewall, SSH-ключи).
Обновите систему и поставьте базовые пакеты сборки:
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl build-essential
Astro требует Node.js версии не ниже 18.20.8 (актуальные релизы Astro ориентируются на LTS-ветки Node). На конец августа 2026 актуальна LTS-ветка Node.js 22.x — но проверьте на nodejs.org, какая LTS-версия текущая на момент, когда вы читаете это, версии обновляются. Ставим через официальный репозиторий NodeSource — так node попадёт в /usr/bin, что удобно для systemd-юнитов позже:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v
Альтернатива — nvm, если на сервере несколько проектов с разными версиями Node. Тогда учитывайте, что бинарник Node будет лежать в домашней директории пользователя (~/.nvm/versions/node/vX.Y.Z/bin/node), и в systemd-юните нужно указывать полный путь, а не просто node.
Создайте отдельного системного пользователя для деплоя, если ещё не сделали — не работайте от root:
sudo adduser --disabled-password --gecos "" deploy
sudo usermod -aG sudo deploy
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверСоздание проекта и выбор режима вывода
Заходим под пользователем деплоя и создаём проект стандартным CLI:
su - deploy
mkdir -p /var/www && cd /var/www
npm create astro@latest myastroapp
CLI спросит про шаблон (пустой, blog, portfolio и т.д.), TypeScript (strict/strictest/relaxed), установку зависимостей и инициализацию git-репозитория — на сервере обычно достаточно --no-git, если проект уже держите в своём репозитории и будете клонировать его сюда, а не создавать заново.
Структура типового проекта:
myastroapp/
├── src/
│ ├── pages/ # файловая маршрутизация
│ ├── components/ # .astro и фреймворк-компоненты
│ └── layouts/
├── public/ # статика без обработки
├── astro.config.mjs
└── package.json
Проверьте сборку сразу:
cd myastroapp
npm run build
Для static-режима результат появится в dist/ — это обычный набор HTML/CSS/JS файлов, никакого рантайма не нужно. Для server-режима понадобится адаптер (см. ниже), и dist/ будет содержать серверный вход плюс клиентские ассеты.
Локально (или через npm run preview на сервере, слушает по умолчанию порт 4321) стоит проверить сборку перед тем, как выставлять её наружу.
Static-режим: сборка и раздача через Nginx
Это самый простой и самый дешёвый по ресурсам вариант — сервер просто отдаёт файлы, никакого Node-процесса в проде не требуется.
Убедитесь, что в astro.config.mjs output не переопределён (или явно output: 'static'):
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://example.com',
output: 'static',
});
Соберите проект и скопируйте dist/ туда, откуда его будет отдавать Nginx:
npm run build
sudo mkdir -p /var/www/myastroapp/dist
sudo rsync -a --delete dist/ /var/www/myastroapp/dist/
sudo chown -R www-data:www-data /var/www/myastroapp/dist
Если Nginx ещё не установлен и вы не настраивали его как реверс-прокси или раздачу статики раньше, у нас есть отдельный разбор — Nginx как реверс-прокси на VPS пригодится и для чисто статической раздачи, логика конфига похожая.
Конфиг сайта:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/myastroapp/dist;
index index.html;
location / {
try_files $uri $uri.html $uri/ =404;
}
location /_astro/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
}
Папка _astro/ содержит бандлы с хэшем в имени файла — их можно кэшировать агрессивно (immutable), а HTML-страницы кэшировать так же не стоит, иначе после деплоя пользователи будут получать старую версию из кэша браузера.
Активируйте конфиг и перезапустите Nginx:
sudo ln -s /etc/nginx/sites-available/myastroapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
SSR-режим: Node-адаптер и systemd-сервис
Если нужен server-рендеринг (персонализация, работа с сессиями, прямые запросы к БД на каждый рендер), добавьте официальный Node-адаптер:
npx astro add node
Команда сама пропишет адаптер в astro.config.mjs и спросит про режим — выбирайте standalone, он поднимает встроенный HTTP-сервер без внешнего Express:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
});
Соберите проект — точка входа окажется в dist/server/entry.mjs:
npm run build
Заведите systemd-юнит, чтобы процесс поднимался автоматически и перезапускался при падении:
# /etc/systemd/system/myastroapp.service
[Unit]
Description=Astro SSR приложение
After=network.target
[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/myastroapp
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=4321
ExecStart=/usr/bin/node ./dist/server/entry.mjs
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now myastroapp
sudo systemctl status myastroapp
Слушайте на 127.0.0.1, а наружу пускайте через Nginx-реверс-прокси — не выставляйте Node-процесс в интернет напрямую:
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:4321;
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;
}
}
Если предпочитаете process manager вместо systemd — pm2 start dist/server/entry.mjs --name myastroapp тоже рабочий вариант, особенно если на сервере уже крутятся другие Node-приложения под pm2 и вам удобнее единый интерфейс pm2 list / pm2 logs вместо systemctl под каждое.
Домен, HTTPS и автодеплой при обновлении
Направьте A-запись домена на IP сервера. Если ещё не настраивали DNS для сервера с нуля, у нас есть отдельная инструкция — настройка домена и DNS на Ubuntu 24.04.
Сертификат Let's Encrypt через certbot ставится одинаково что для static, что для SSR-варианта, разница только в том, что проксирует Nginx:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
Certbot сам пропишет listen 443 ssl и редирект с 80 порта, а автопродление уже включено таймером systemd (certbot.timer) — проверить можно командой sudo certbot renew --dry-run. Если хотите разобраться в механике подробнее — есть отдельная статья про настройку Let's Encrypt SSL.
Для автодеплоя при пуше в git самый простой вариант без внешних CI — небольшой скрипт на сервере, который дергается через webhook или по SSH из GitHub Actions:
#!/bin/bash
# /var/www/myastroapp/deploy.sh
set -e
cd /var/www/myastroapp
git pull origin main
npm ci
npm run build
# для static:
rsync -a --delete dist/ /var/www/myastroapp/public_dist/
# для SSR — перезапуск сервиса:
sudo systemctl restart myastroapp
Более полный разбор вариантов автодеплоя (GitHub Actions по SSH, webhook, простой git-hook) — в статье автодеплой из git на VPS. Для небольших проектов обычно хватает git pull + npm run build по SSH из CI, разворачивать полноценный CI/CD раннер ради лендинга или блога избыточно.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько оперативной памяти нужно для сборки Astro-проекта?
Для небольших сайтов (до пары сотен страниц) хватает 1 ГБ, npm run build укладывается в него. Для крупных контент-проектов с сотнями markdown-файлов и обработкой изображений разумнее закладывать 2 ГБ и больше — сборка может упираться в память, а не в CPU.
Можно ли раздавать static-сборку без Nginx, прямо через astro preview?
Технически да, но astro preview — это инструмент для локальной проверки сборки перед деплоем, не production-сервер: там нет ни нормального управления кэшированием, ни устойчивости к нагрузке. Для прода — Nginx или другой полноценный веб-сервер.
Чем SSR-режим Astro отличается по нагрузке от static?
В static-режиме сервер отдаёт готовые файлы — нагрузка минимальна, справится и бюджетный тариф. SSR держит постоянный Node-процесс и рендерит страницы на каждый запрос, так что при заметном трафике стоит закладывать больше CPU и памяти, чем для чисто статического сайта.
Нужен ли отдельный процесс для API-роутов Astro?
Нет, если вы используете встроенные API-роуты Astro (src/pages/api/*.ts) в server-режиме — они обслуживаются тем же Node-процессом, что и страницы, отдельный сервер не нужен.
Что делать, если после деплоя браузер показывает старую версию сайта?
Чаще всего дело в кэше HTML на стороне Nginx или браузера. Для static-режима не ставьте долгий Cache-Control на HTML-файлы (только на хэшированные ассеты в _astro/), а после деплоя можно принудительно сбросить кэш Nginx через proxy_cache_purge, если он у вас настроен, либо просто дождаться истечения TTL.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →