docs: Server-Operations — универсальное развёртывание без привязки к домену

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
shop
2026-05-17 13:34:25 +03:00
parent d31a63829c
commit 561fbd22e0
11 changed files with 336 additions and 402 deletions
+18 -14
View File
@@ -1,4 +1,4 @@
# Shop — документация v0.20.0
# Shop — документация
Интернет-магазин на **Node.js** и **PostgreSQL 17**.
@@ -7,7 +7,8 @@
| Способ | Когда использовать |
|--------|-------------------|
| **[Установка через Docker](Install-Docker)** | Быстрый старт, тест, изолированное окружение |
| **[Установка без Docker](Install-Native)** | Production на Ubuntu, systemd, свой Caddy |
| **[Установка без Docker](Install-Native)** | Production на Ubuntu, systemd, Caddy |
| **[Сервер: установка и обновление](Server-Operations)** | Обновления, systemd, типичные ошибки |
## Требования
@@ -17,31 +18,35 @@
## Быстрый старт
### Docker (3 команды)
### Docker
```bash
git clone https://git.evilfox.cc/test/shop10.git && cd shop10
git checkout v0.10.0
cp .env.docker.example .env && docker compose up -d --build
git clone <URL-вашего-репозитория> shop
cd shop
cp .env.docker.example .env
docker compose up -d --build
```
Сайт: http://localhost:3000
### Без Docker
### Без Docker (сервер)
```bash
git clone https://git.evilfox.cc/test/shop10.git /opt/shop/shop10
cd /opt/shop/shop10
export SHOP_ROOT=/opt/shop
export GIT_REPO_URL='<URL-вашего-репозитория>'
git clone "$GIT_REPO_URL" "$SHOP_ROOT"
cd "$SHOP_ROOT"
sudo bash scripts/quick-deploy-ubuntu.sh
```
Обновление на работающем сервере:
Обновление:
```bash
bash /opt/shop/shop10/scripts/server-update.sh
bash "$SHOP_ROOT/scripts/server-update.sh"
```
## Проверка работы
## Проверка
```bash
curl -s http://127.0.0.1:3000/health
@@ -51,6 +56,5 @@ curl -s http://127.0.0.1:3000/health
## Ссылки
- [Репозиторий](https://git.evilfox.cc/test/shop10)
- [Releases](https://git.evilfox.cc/test/shop10/releases)
- [Решение проблем](Troubleshooting)
- [Сервер: установка и обновление](Server-Operations)
+41 -160
View File
@@ -1,225 +1,106 @@
# Установка без Docker (Ubuntu)
Production-развёртывание на **Ubuntu 22.04 / 24.04**: Node.js 20, PostgreSQL 17, systemd, опционально Caddy.
Production: Node.js 20, PostgreSQL 17, systemd, опционально Caddy.
**Полное руководство по ошибкам и обновлениям:** [Server-Operations](Server-Operations).
Задайте каталог клона:
```bash
export SHOP_ROOT=/opt/shop
```
---
## 1. Требования
- Сервер Ubuntu 22.04 или 24.04 (root или sudo)
- Минимум 1 GB RAM, 10 GB диск
- Открыты порты **22**, **80**, **443** (если используете Caddy)
- Порт **3000** наружу не открывать — только localhost
- Ubuntu 22.04 или 24.04
- Порты 22, 80, 443 (для Caddy)
- Порт 3000 только localhost
## 2. Установка системных пакетов
## 2. Системные пакеты
```bash
apt update
apt install -y git curl ca-certificates
```
### Node.js 20 LTS
### Node.js 20
```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
node -v # v20.x
apt install -y nodejs git curl
```
### PostgreSQL 17
Не используйте `apt install postgresql-17` без PGDG — пакет не найдётся. Скрипт подключает PGDG автоматически:
Не используйте `apt install postgresql-17` без PGDG:
```bash
sudo bash /opt/shop/shop10/scripts/install-postgresql-ubuntu.sh
sudo bash "$SHOP_ROOT/scripts/install-postgresql-ubuntu.sh"
```
## 3. Клонирование проекта
## 3. Клонирование
```bash
git clone https://git.evilfox.cc/test/shop10.git /opt/shop/shop10
cd /opt/shop/shop10/shop10
git checkout v0.20.0
export GIT_REPO_URL='<URL-вашего-репозитория>'
git clone "$GIT_REPO_URL" "$SHOP_ROOT"
cd "$SHOP_ROOT"
```
Или быстрая установка всего стека: `sudo bash scripts/quick-deploy-ubuntu.sh`
Или: `sudo SHOP_GIT_URL="$GIT_REPO_URL" bash scripts/quick-deploy-ubuntu.sh`
## 4. База данных PostgreSQL
## 4. База данных
```bash
cd /opt/shop/shop10/shop10
cd "$SHOP_ROOT"
bash scripts/setup-postgres-ubuntu.sh
```
Скрипт:
- запускает PostgreSQL;
- создаёт пользователя и БД `shop` (по умолчанию пароль `shop`**смените в production**);
- выводит строку `DATABASE_URL`.
Проверка:
```bash
psql "postgresql://shop:shop@127.0.0.1:5432/shop" -c "SELECT 1"
```
## 5. Файл окружения `.env`
## 5. `.env`
```bash
cp .env.example .env
nano .env
```
Обязательные параметры:
`SESSION_SECRET`, `DATABASE_URL`, `SITE_URL` (ваш публичный URL без привязки к конкретному домену в коде).
```env
PORT=3000
HOST=127.0.0.1
NODE_ENV=production
TRUST_PROXY=1
SESSION_SECRET=сгенерируйте_длинную_строку
DATABASE_URL=postgresql://shop:ВАШ_ПАРОЛЬ@127.0.0.1:5432/shop
```
Секрет сессии:
## 6. Зависимости
```bash
openssl rand -hex 32
```
`HOST=127.0.0.1` — приложение доступно только локально; снаружи — через Caddy.
## 6. Установка зависимостей Node.js
```bash
cd /opt/shop/shop10
npm install --omit=dev
```
При первом запуске приложение создаст таблицы и демо-товары (если каталог пуст).
## 7. Служба systemd
## 7. systemd
```bash
cp /opt/shop/shop10/deploy/shop.service /etc/systemd/system/shop.service
systemctl daemon-reload
systemctl enable shop
systemctl start shop
systemctl status shop
sudo bash scripts/install-shop-service.sh
```
Unit ждёт PostgreSQL (`ExecStartPre` + `pg_isready`) и запускает Node от пользователя `www-data`.
`WorkingDirectory` в unit = `$SHOP_ROOT`. Не делайте `chown -R www-data` на весь репозиторий.
**Важно:** не выполняйте `chown -R www-data /opt/shop` — это ломает `git pull`. Права на запись нужны только для каталога `data/` (если используется); с PostgreSQL каталог `data/` не обязателен.
## 8. Caddy
Логи:
После `curl http://127.0.0.1:3000/health` → OK:
```bash
journalctl -u shop -f
```
## 8. Проверка backend
```bash
curl -s http://127.0.0.1:3000/health
ss -tlnp | grep 3000
```
В логах должно быть: `Магазин: http://127.0.0.1:3000 (PostgreSQL)`
## 9. Caddy — HTTPS и reverse proxy
Установка Caddy:
```bash
apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
```
Конфигурация:
```bash
cp /opt/shop/shop10/caddy/Caddyfile.example /etc/caddy/Caddyfile
nano /etc/caddy/Caddyfile
```
Пример (замените домен и email):
```caddyfile
{
email admin@example.com
}
shop.example.com {
encode gzip zstd
reverse_proxy 127.0.0.1:3000
}
```
```bash
caddy validate --config /etc/caddy/Caddyfile
systemctl enable caddy
cp "$SHOP_ROOT/caddy/Caddyfile.example" /etc/caddy/Caddyfile
# укажите ваш домен в Caddyfile
systemctl reload caddy
```
Файрвол:
## 9. Обновление
```bash
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
bash "$SHOP_ROOT/scripts/server-update.sh"
```
Зависимость Caddy от shop (опционально):
```bash
mkdir -p /etc/systemd/system/caddy.service.d
cp /opt/shop/deploy/caddy-after-shop.conf /etc/systemd/system/caddy.service.d/shop.conf
systemctl daemon-reload
```
## 10. Обновление
```bash
cd /opt/shop/shop10/shop10
git config --global --add safe.directory "$(pwd)"
bash scripts/server-update.sh
```
Если клон в `/opt/shop` без подкаталога — используйте `/opt/shop`. Скрипт ищет `package.json` автоматически; можно запустить так:
```bash
bash /opt/shop/shop10/scripts/server-update.sh
```
Или вручную:
```bash
git pull
npm install --omit=dev
systemctl restart shop
curl -s http://127.0.0.1:3000/health
systemctl reload caddy
```
## 11. Архитектура
## 10. Архитектура
```
Интернет → Caddy :443 → 127.0.0.1:3000 (Node.js shop)
Интернет → Caddy :443 → 127.0.0.1:3000 (Node.js)
PostgreSQL 127.0.0.1:5432
```
## 12. Резервное копирование БД
## 11. Резервное копирование
```bash
sudo -u postgres pg_dump shop > shop_backup_$(date +%F).sql
```
Восстановление:
```bash
sudo -u postgres psql shop < shop_backup_2026-05-17.sql
```
+179
View File
@@ -0,0 +1,179 @@
# Сервер: установка и обновление
Инструкция **без привязки к конкретному домену или хостингу**. Подставьте свои значения:
| Переменная | Что это | Пример |
|------------|---------|--------|
| `SHOP_ROOT` | Каталог клона, где лежат `package.json` и `scripts/` | `/opt/shop` |
| `GIT_REPO_URL` | URL вашего git-репозитория | `https://forge.example.com/user/shop.git` |
| `SITE_URL` | Публичный URL магазина (для писем и passkey) | `https://shop.example.com` |
Проверка каталога:
```bash
export SHOP_ROOT=/opt/shop
test -f "$SHOP_ROOT/package.json" && echo OK || echo "Неверный SHOP_ROOT"
```
---
## Первая установка (Ubuntu, без Docker)
```bash
export SHOP_ROOT=/opt/shop
export GIT_REPO_URL='https://ВАШ-FORGE/путь/к/shop.git'
apt update && apt install -y git curl
git clone "$GIT_REPO_URL" "$SHOP_ROOT"
cd "$SHOP_ROOT"
sudo SHOP_INSTALL_DIR="$SHOP_ROOT" SHOP_GIT_URL="$GIT_REPO_URL" \
bash scripts/quick-deploy-ubuntu.sh
```
Скрипт: Node.js (если нет), PostgreSQL (PGDG), `.env`, `npm install`, служба **shop** (systemd).
---
## Обновление кода (сайт уже работает)
```bash
cd "$SHOP_ROOT"
bash scripts/git-sync.sh
bash scripts/server-update.sh
```
Или одной строкой (путь к скриптам в вашем клоне):
```bash
bash "$SHOP_ROOT/scripts/server-update.sh"
```
---
## Скрипты в `scripts/`
| Скрипт | Назначение |
|--------|------------|
| `quick-deploy-ubuntu.sh` | Первая установка / полный цикл |
| `server-update.sh` | `git pull`, `npm install`, перезапуск shop |
| `git-sync.sh` | Исправить detached HEAD, синхронизация с `main` |
| `install-postgresql-ubuntu.sh` | PostgreSQL 17 через PGDG |
| `setup-postgres-ubuntu.sh` | Пользователь и БД `shop` |
| `install-shop-service.sh` | Установка systemd unit |
| `free-port-3000.sh` | Освободить порт (старый `npm start`) |
| `fix-db-connection.sh` | ECONNREFUSED :5432 |
| `diagnose-502.sh` | HTTP 502, Caddy |
| `diagnose-shop-service.sh` | Падение shop.service |
Все скрипты сами ищут `SHOP_ROOT` (каталог, откуда вызван `scripts/`, или переменная окружения).
---
## Частые ошибки
### `Unable to locate package postgresql-17`
В стандартном Ubuntu нет пакета 17. Не копируйте `apt install postgresql-17` из старых заметок.
```bash
sudo bash "$SHOP_ROOT/scripts/install-postgresql-ubuntu.sh"
bash "$SHOP_ROOT/scripts/setup-postgres-ubuntu.sh"
```
### `URL_РЕПОЗИТОРИЯ: No such file` или placeholder в команде
В документации иногда указан **шаблон**, а не команда. Клонируйте так:
```bash
git clone 'https://ВАШ-FORGE/shop.git' "$SHOP_ROOT"
```
### `package.json` ENOENT в `/opt/shop`
Вы в **родительской** папке, а клон в подкаталоге (или наоборот).
```bash
find /opt -name package.json 2>/dev/null
export SHOP_ROOT=/путь/где/найден
cd "$SHOP_ROOT"
```
### `You are not currently on a branch`
После `git checkout v0.x.x` репозиторий в detached HEAD.
```bash
cd "$SHOP_ROOT"
bash scripts/git-sync.sh
```
### `scripts/...: No such file or directory`
Запуск не из клона. Используйте полный путь:
```bash
bash "$SHOP_ROOT/scripts/server-update.sh"
```
### `Служба shop не установлена` / `Unit shop.service could not be found`
```bash
cd "$SHOP_ROOT"
sudo bash scripts/install-shop-service.sh
```
В `/etc/systemd/system/shop.service` поля `WorkingDirectory` и `EnvironmentFile` должны указывать на **`$SHOP_ROOT`**.
### `shop.service: status=1/FAILURE`, `activating (auto-restart)`
1. **Порт 3000 занят** (старый ручной Node) — health отвечает, systemd падает:
```bash
sudo bash "$SHOP_ROOT/scripts/free-port-3000.sh"
sudo systemctl restart shop
systemctl status shop
```
2. **PostgreSQL** — смотрите лог:
```bash
journalctl -u shop -n 40 --no-pager
bash "$SHOP_ROOT/scripts/diagnose-shop-service.sh"
```
3. **`.env` не в `SHOP_ROOT`** — скопируйте с прежнего места:
```bash
cp /старый/путь/.env "$SHOP_ROOT/.env"
sudo bash "$SHOP_ROOT/scripts/install-shop-service.sh"
```
### Изменения в git не видны на сайте
Обновление делали не в том каталоге или служба смотрит на другой путь:
```bash
cd "$SHOP_ROOT" && git log -1 --oneline
grep WorkingDirectory /etc/systemd/system/shop.service
bash scripts/server-update.sh
```
---
## Проверка
```bash
systemctl status shop
curl -s http://127.0.0.1:3000/health
```
Ожидается: `{"ok":true,"service":"shop","database":"postgresql"}` и **`Active: active (running)`**.
---
## Caddy / HTTPS
Пока `curl http://127.0.0.1:3000/health` не OK, reverse proxy будет отдавать **502**. Сначала backend, потом Caddy.
См. также: [Решение проблем](Troubleshooting), [Установка без Docker](Install-Native).
+38 -165
View File
@@ -1,190 +1,56 @@
# Решение проблем
## Диагностика одной командой
Полное руководство по развёртыванию: **[Сервер: установка и обновление](Server-Operations)**.
Перед любыми командами задайте каталог клона:
```bash
bash /opt/shop/shop10/scripts/diagnose-502.sh
export SHOP_ROOT=/opt/shop # замените на свой путь (где есть package.json)
cd "$SHOP_ROOT"
```
(замените путь на каталог вашего клона — где есть `package.json`)
---
## Ошибки при «быстром развёртывании»
| Ошибка | Причина | Решение |
|--------|---------|---------|
| `Unable to locate package postgresql-17` | В Ubuntu нет PG 17 без PGDG | `sudo bash /opt/shop/shop10/scripts/install-postgresql-ubuntu.sh` |
| `URL_РЕПОЗИТОРИЯ: No such file` | Скопирован placeholder из README | Используйте реальный URL: `git clone https://git.evilfox.cc/test/shop10.git /opt/shop/shop10` |
| `package.json` в `/opt/shop` | Неверный каталог | Репозиторий в `/opt/shop/shop10` |
| Изменения не применились | `git pull` не в том каталоге | `bash /opt/shop/shop10/scripts/server-update.sh` |
Полное развёртывание / обновление:
## Диагностика
```bash
cd /opt/shop/shop10 && git pull
sudo bash scripts/quick-deploy-ubuntu.sh
```
Только обновление кода (сайт уже работает):
```bash
bash /opt/shop/shop10/scripts/server-update.sh
```
## git: You are not currently on a branch / not a git repository
Клон на теге (detached HEAD) или обновление из `/opt/shop` вместо `/opt/shop/shop10`:
```bash
cd /opt/shop/shop10
git status
bash scripts/git-sync.sh
bash scripts/server-update.sh
```
Если `fatal: not a git repository` в `/opt/shop/shop10`:
```bash
ls -la /opt/shop/shop10/.git
# нет .git — заново:
mv /opt/shop/shop10 /opt/shop/shop10.bak.$(date +%s)
git clone https://git.evilfox.cc/test/shop10.git /opt/shop/shop10
cp /opt/shop/shop10.bak.*/.env /opt/shop/shop10/.env 2>/dev/null || cp /opt/shop/shop10/.env.example /opt/shop/shop10/.env
bash /opt/shop/shop10/scripts/server-update.sh
```
## shop.service: exit-code / activating (auto-restart)
**Health ответил OK, но systemd падает** — часто порт 3000 занят старым `npm start`:
```bash
cd /opt/shop/shop10
git pull
sudo bash scripts/free-port-3000.sh
sudo systemctl restart shop
systemctl status shop
```
Лог:
```bash
journalctl -u shop -n 30 --no-pager
# EADDRINUSE → free-port-3000.sh
# MODULE_NOT_FOUND → npm install --omit=dev
```
## Job for shop.service failed (control process exited)
Чаще всего не запущен PostgreSQL или не прошёл `ExecStartPre`:
```bash
cd /opt/shop/shop10
git pull
sudo bash scripts/install-postgresql-ubuntu.sh
bash scripts/setup-postgres-ubuntu.sh
sudo bash scripts/install-shop-service.sh
```
Диагностика:
```bash
bash /opt/shop/shop10/scripts/diagnose-shop-service.sh
bash "$SHOP_ROOT/scripts/diagnose-502.sh"
bash "$SHOP_ROOT/scripts/diagnose-shop-service.sh"
journalctl -u shop -n 50 --no-pager
```
Скопировать старый `.env`:
---
```bash
cp /opt/shop/.env /opt/shop/shop10/.env
sudo bash /opt/shop/shop10/scripts/install-shop-service.sh
```
## Краткая таблица ошибок
## Служба shop не установлена
| Симптом | Что делать |
|---------|------------|
| `postgresql-17` not found | `sudo bash scripts/install-postgresql-ubuntu.sh` |
| Placeholder / `URL_РЕПОЗИТОРИЯ` | `git clone <ваш-url> "$SHOP_ROOT"` — не копировать шаблоны как команды |
| Нет `package.json` | `find /opt -name package.json`; `cd` в найденный каталог |
| detached HEAD | `bash scripts/git-sync.sh` |
| Нет `scripts/...` | `bash "$SHOP_ROOT/scripts/server-update.sh"` |
| Unit shop not found | `sudo bash scripts/install-shop-service.sh` |
| shop exit-code / auto-restart | `sudo bash scripts/free-port-3000.sh`; `systemctl restart shop` |
| 502 в браузере | `curl http://127.0.0.1:3000/health` — сначала backend |
| ECONNREFUSED :5432 | `bash scripts/fix-db-connection.sh` |
Код обновился, но systemd unit не настроен:
```bash
cd /opt/shop/shop10
sudo bash scripts/install-shop-service.sh
```
Проверка:
```bash
systemctl status shop
curl -s http://127.0.0.1:3000/health
```
## scripts/server-update.sh: No such file or directory
Вы не в каталоге репозитория или клон в подпапке (например `/opt/shop/shop10`):
```bash
ls /opt/shop/shop10/package.json
bash /opt/shop/shop10/scripts/server-update.sh
```
В `deploy/shop.service` укажите тот же путь в `WorkingDirectory` и `EnvironmentFile`.
Подробности — в [Server-Operations](Server-Operations).
---
## HTTP 502 (Caddy / браузер)
**SSL работает, страница 502** — Caddy жив, backend (Node) не отвечает.
```bash
curl -s http://127.0.0.1:3000/health
systemctl status shop
journalctl -u shop -n 30 --no-pager
```
Пока `/health` не OK — Caddy будет отдавать 502.
---
## ECONNREFUSED 127.0.0.1:5432
PostgreSQL не запущен или не установлен.
```bash
bash /opt/shop/shop10/scripts/fix-db-connection.sh
```
Или вручную:
```bash
systemctl start postgresql
pg_isready -h 127.0.0.1 -p 5432
bash scripts/setup-postgres-ubuntu.sh
```
Проверьте `DATABASE_URL` в `/opt/shop/shop10/.env`.
---
## Служба shop сразу останавливается
В логе только «База уже содержит товары» без строки `Магазин: http://...`:
```bash
bash /opt/shop/shop10/scripts/server-update.sh
systemctl restart shop
```
---
## dubious ownership (git pull)
Не делайте `chown -R www-data /opt/shop`.
```bash
chown -R root:root /opt/shop
git config --global --add safe.directory /opt/shop
git pull
```
---
## Docker: контейнер app unhealthy
## Docker
```bash
docker compose logs app
@@ -192,16 +58,23 @@ docker compose logs postgres
docker compose up -d --build
```
---
## Docker: нет связи с БД
Проверьте, что `DATABASE_URL` в compose указывает на хост `postgres`, а не `127.0.0.1` (внутри контейнера app).
`DATABASE_URL` в compose должен указывать на сервис `postgres`, не на `127.0.0.1` внутри контейнера app.
---
## Полезные ссылки
## git pull / dubious ownership
Не делайте `chown -R www-data` на весь каталог репозитория.
```bash
git config --global --add safe.directory "$SHOP_ROOT"
cd "$SHOP_ROOT" && git pull
```
---
## Ссылки
- [Сервер: установка и обновление](Server-Operations)
- [Установка Docker](Install-Docker)
- [Установка без Docker](Install-Native)
- [Репозиторий](https://git.evilfox.cc/test/shop10)