EmDash по умолчанию ориентирован на Cloudflare Workers, но запускается и на обычном сервере с Node.js. Для российских проектов это часто основной вариант: данные лежат в России, нет зависимости от доступности Cloudflare, а хостинг стоит несколько сотен рублей в месяц. По этой схеме работает nesmachny.ru и этот сайт.
Что понадобится
- VPS с Ubuntu 22.04 или 24.04, от 2 ГБ памяти. Сборка Astro требует памяти, поэтому добавьте swap на 2–4 ГБ.
- Node.js 22 и pnpm (через corepack).
- nginx и certbot для HTTPS.
- Домен, A-запись которого указывает на IP сервера.
1. Создайте проект
На своём компьютере выполните команду и выберите шаблон, например blog:
npm create emdash@latest2. Переключите проект на Node.js и SQLite
В astro.config.mjs укажите адаптер Node, базу SQLite и хранение медиа в локальной папке:
import node from "@astrojs/node";
import react from "@astrojs/react";
import { defineConfig } from "astro/config";
import emdash, { local } from "emdash/astro";
import { sqlite } from "emdash/db";
export default defineConfig({
site: "https://example.ru",
output: "server",
outDir: process.env.ASTRO_OUT_DIR || "dist",
adapter: node({ mode: "standalone" }),
integrations: [
react(),
emdash({
database: sqlite({ url: "file:./data.db" }),
storage: local({ directory: "./uploads", baseUrl: "/_emdash/api/media/file" }),
}),
],
});Строка outDir понадобится для сборки без простоя, о ней ниже.
3. Подготовьте файл .env на сервере
HOST=127.0.0.1
PORT=3013
NODE_ENV=production
SITE_URL=https://example.ru
EMDASH_SITE_URL=https://example.ru
EMDASH_ENCRYPTION_KEY=длинная-случайная-строкаНе пропускайте SITE_URL и EMDASH_SITE_URL. Без них EmDash строит адреса картинок с http://, и на HTTPS-сайте браузер блокирует их как смешанный контент. EMDASH_ENCRYPTION_KEY сгенерируйте один раз (например, openssl rand -base64 32) и не меняйте: им зашифрованы данные в базе.
4. Соберите и запустите
Скопируйте проект на сервер без node_modules, data.db и uploads, затем:
cd /var/www/example.ru
corepack pnpm install --frozen-lockfile
nice -n 19 corepack pnpm exec astro build
pm2 start dist/server/entry.mjs --name example --node-args="--env-file=.env"
pm2 saveПри первом запуске EmDash создаст data.db и применит миграции.
5. Настройте nginx
upstream example_site {
server 127.0.0.1:3013;
keepalive 32;
}
server {
listen 80;
server_name example.ru www.example.ru;
client_max_body_size 50m;
location / {
proxy_pass http://example_site;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Затем включите сайт и выпустите сертификат:
ln -s /etc/nginx/sites-available/example.ru /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d example.ru -d www.example.ru6. Создайте администратора
Откройте https://example.ru/_emdash/admin и пройдите мастер первичной настройки. Сразу добавьте вход по ключу доступа (passkey): пока на сервере не настроена отправка почты, ссылки для входа по email приходить не будут.
Обновления без простоя
Если собирать проект прямо в dist, живой сайт несколько десятков секунд отдаёт ошибки. Собирайте в отдельную папку и подменяйте её одной командой:
ASTRO_OUT_DIR=dist.new nice -n 19 corepack pnpm exec astro build
rm -rf dist.old && mv dist dist.old && mv dist.new dist
pm2 restart example && rm -rf dist.oldРезервные копии
Весь контент хранится в двух местах: в файле data.db и в папке uploads. Копируйте базу командой SQLite, а не простым копированием файла, иначе можно потерять последние изменения из журнала:
sqlite3 /var/www/example.ru/data.db ".backup /var/backups/example/data-$(date +%F).db"
tar czf /var/backups/example/uploads-$(date +%F).tgz -C /var/www/example.ru uploadsПоставьте эти команды в cron раз в сутки. И никогда не удаляйте файл data.db-wal, пока сайт запущен: в нём лежат изменения, которые ещё не попали в основную базу.
Что дальше
Следующий шаг — перенос контента со старого сайта. Если не хотите заниматься этим сами, посмотрите миграцию под ключ.