ccebf0d26d
Co-authored-by: Cursor <cursoragent@cursor.com>
261 lines
7.1 KiB
Markdown
261 lines
7.1 KiB
Markdown
# Shop
|
||
|
||
Интернет-магазин на **Node.js** с локальной базой **SQLite**.
|
||
|
||
## Возможности
|
||
|
||
- Каталог товаров с категориями и поиском
|
||
- Корзина и оформление заказа
|
||
- Регистрация и вход пользователей
|
||
- История заказов в личном кабинете
|
||
|
||
## Требования
|
||
|
||
- Node.js 18+
|
||
- npm
|
||
- На Linux для сборки `better-sqlite3`: `build-essential`, `python3`
|
||
|
||
---
|
||
|
||
## Быстрый развёртывание на Ubuntu
|
||
|
||
Скопируйте блок целиком на чистый сервер Ubuntu 22.04 / 24.04 (от root или через `sudo`):
|
||
|
||
```bash
|
||
# 1. Зависимости системы
|
||
apt update
|
||
apt install -y git curl build-essential python3
|
||
|
||
# 2. Node.js 20 LTS
|
||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||
apt install -y nodejs
|
||
|
||
# 3. Клонирование (замените URL при необходимости)
|
||
cd /opt
|
||
git clone https://git.evilfox.cc/test/shop10.git shop
|
||
cd shop
|
||
|
||
# 4. Настройка окружения
|
||
cp .env.example .env
|
||
# Сгенерируйте секрет сессии:
|
||
sed -i "s/change-me-to-a-long-random-string/$(openssl rand -hex 32)/" .env
|
||
|
||
# 5. Установка приложения
|
||
npm install --omit=dev
|
||
|
||
# 6. Caddy (HTTPS + прокси) — см. раздел ниже; для проверки без домена:
|
||
npm start
|
||
```
|
||
|
||
Без Caddy сайт на **http://IP:3000**. С Caddy и доменом — **https://ваш-домен**.
|
||
|
||
В `.env` для production задайте (уже есть в `.env.example`):
|
||
|
||
```env
|
||
PORT=3000
|
||
HOST=127.0.0.1
|
||
NODE_ENV=production
|
||
TRUST_PROXY=1
|
||
SESSION_SECRET=ваш-длинный-секрет
|
||
```
|
||
|
||
`HOST=127.0.0.1` — Node слушает только localhost; снаружи доступ через Caddy.
|
||
|
||
При первом запуске создаются `data/shop.db`, `data/sessions.db` и демо-товары.
|
||
|
||
---
|
||
|
||
## Запуск как служба (systemd)
|
||
|
||
Чтобы магазин работал после перезагрузки сервера:
|
||
|
||
```bash
|
||
cat > /etc/systemd/system/shop.service << 'EOF'
|
||
[Unit]
|
||
Description=Shop Node.js
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=www-data
|
||
WorkingDirectory=/opt/shop
|
||
EnvironmentFile=/opt/shop/.env
|
||
ExecStart=/usr/bin/node src/server.js
|
||
Restart=on-failure
|
||
RestartSec=5
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
# Права на каталог (если клонировали в /opt/shop)
|
||
chown -R www-data:www-data /opt/shop
|
||
|
||
systemctl daemon-reload
|
||
systemctl enable shop
|
||
systemctl start shop
|
||
systemctl status shop
|
||
```
|
||
|
||
Логи: `journalctl -u shop -f`
|
||
|
||
---
|
||
|
||
## Caddy — SSL и reverse proxy (рекомендуется)
|
||
|
||
[Caddy](https://caddyserver.com/) автоматически выпускает и продлевает сертификаты Let's Encrypt.
|
||
|
||
**Перед установкой:**
|
||
|
||
1. Домен указывает на IP сервера (A-запись).
|
||
2. Открыты порты **80** и **443** в файрволе.
|
||
3. Служба `shop` запущена и слушает `127.0.0.1:3000`.
|
||
|
||
### Установка Caddy на Ubuntu
|
||
|
||
```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
|
||
```
|
||
|
||
### Конфигурация
|
||
|
||
В репозитории лежит пример: `caddy/Caddyfile.example`.
|
||
|
||
```bash
|
||
# Замените shop.example.com и email на свои
|
||
cp /opt/shop/caddy/Caddyfile.example /etc/caddy/Caddyfile
|
||
nano /etc/caddy/Caddyfile
|
||
```
|
||
|
||
Пример `/etc/caddy/Caddyfile`:
|
||
|
||
```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
|
||
systemctl reload caddy
|
||
systemctl status caddy
|
||
```
|
||
|
||
Сайт: **https://shop.example.com**
|
||
|
||
Логи Caddy: `journalctl -u caddy -f`
|
||
|
||
### Файрвол (ufw)
|
||
|
||
```bash
|
||
ufw allow 22/tcp
|
||
ufw allow 80/tcp
|
||
ufw allow 443/tcp
|
||
ufw enable
|
||
```
|
||
|
||
Порт **3000** наружу не открывайте — к приложению ходят только через Caddy.
|
||
|
||
### Порядок запуска после перезагрузки
|
||
|
||
1. `shop` (Node.js на `127.0.0.1:3000`)
|
||
2. `caddy` (прокси + HTTPS)
|
||
|
||
### Типичные проблемы
|
||
|
||
| Симптом | Решение |
|
||
|--------|---------|
|
||
| 502 Bad Gateway | `systemctl status shop`, проверьте `curl http://127.0.0.1:3000` |
|
||
| Нет сертификата | DNS, порты 80/443, верный домен в `Caddyfile` |
|
||
| Редирект-цикл / нет cookies | В `.env`: `TRUST_PROXY=1`, `NODE_ENV=production` |
|
||
|
||
---
|
||
|
||
## Обновление с Git
|
||
|
||
```bash
|
||
cd /opt/shop
|
||
systemctl stop shop
|
||
git pull
|
||
npm install --omit=dev
|
||
systemctl start shop
|
||
# Caddy перезагружать не нужно, если Caddyfile не менялся
|
||
```
|
||
|
||
---
|
||
|
||
## Локальная разработка
|
||
|
||
```bash
|
||
npm install
|
||
cp .env.example .env
|
||
npm run dev
|
||
```
|
||
|
||
Сайт: [http://localhost:3000](http://localhost:3000)
|
||
|
||
## Переменные окружения
|
||
|
||
| Переменная | Описание | По умолчанию |
|
||
|------------------|---------------------------|----------------|
|
||
| `PORT` | Порт HTTP-сервера | `3000` |
|
||
| `HOST` | Адрес привязки | `0.0.0.0` (dev), `127.0.0.1` (prod) |
|
||
| `NODE_ENV` | Режим (`production` — secure cookies) | — |
|
||
| `TRUST_PROXY` | Доверять заголовкам Caddy (`1`) | — |
|
||
| `SESSION_SECRET` | Секрет для сессий | dev-значение |
|
||
|
||
## Скрипты npm
|
||
|
||
| Команда | Описание |
|
||
|----------------|----------------------------------|
|
||
| `npm start` | Запуск сервера (production) |
|
||
| `npm run dev` | Запуск с автоперезагрузкой |
|
||
| `npm run seed` | Заполнение каталога, если пуст |
|
||
|
||
## База данных
|
||
|
||
Локально в каталоге `data/`:
|
||
|
||
- `shop.db` — товары, пользователи, заказы
|
||
- `sessions.db` — сессии
|
||
|
||
Каталог `data/` в git не попадает (см. `.gitignore`). Делайте резервные копии:
|
||
|
||
```bash
|
||
cp -a data/shop.db data/shop.db.bak
|
||
```
|
||
|
||
## Структура проекта
|
||
|
||
```
|
||
caddy/
|
||
Caddyfile.example — пример reverse proxy + SSL
|
||
src/
|
||
server.js — точка входа
|
||
db.js — схема SQLite
|
||
seed.js — демо-данные
|
||
routes/ — маршруты
|
||
views/ — шаблоны EJS
|
||
public/css/ — стили
|
||
```
|
||
|
||
## Репозиторий
|
||
|
||
```bash
|
||
git clone https://git.evilfox.cc/test/shop10.git
|
||
```
|