Co-authored-by: Cursor <cursoragent@cursor.com>
9.5 KiB
Shop
Интернет-магазин на Node.js с локальной базой SQLite.
Возможности
- Каталог товаров с категориями и поиском
- Корзина и оформление заказа
- Регистрация и вход пользователей
- История заказов в личном кабинете
Требования
- Node.js 18+
- npm
- На Linux для сборки
better-sqlite3:build-essential,python3
Быстрый развёртывание на Ubuntu
Скопируйте блок целиком на чистый сервер Ubuntu 22.04 / 24.04 (от root или через sudo):
# 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):
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)
Чтобы магазин работал после перезагрузки сервера:
cp /opt/shop/deploy/shop.service /etc/systemd/system/shop.service
# Код обновляйте от root; НЕ делайте chown -R на весь /opt/shop (ломает git pull)
cd /opt/shop
git config --global --add safe.directory /opt/shop
git pull
npm install --omit=dev
# Запись только в data/ — для пользователя службы www-data
mkdir -p /opt/shop/data
chown -R www-data:www-data /opt/shop/data
chmod +x /opt/shop/scripts/diagnose-502.sh 2>/dev/null || true
systemctl daemon-reload
systemctl enable shop
systemctl start shop
systemctl status shop
# Backend должен ответить:
curl -s http://127.0.0.1:3000/health
# {"ok":true,"service":"shop"}
Логи: journalctl -u shop -f
Caddy — SSL и reverse proxy (рекомендуется)
Caddy автоматически выпускает и продлевает сертификаты Let's Encrypt.
Перед установкой:
- Домен указывает на IP сервера (A-запись).
- Открыты порты 80 и 443 в файрволе.
- Служба
shopзапущена и слушает127.0.0.1:3000.
Установка Caddy на Ubuntu
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.
# Замените shop.example.com и email на свои
cp /opt/shop/caddy/Caddyfile.example /etc/caddy/Caddyfile
nano /etc/caddy/Caddyfile
Пример /etc/caddy/Caddyfile:
{
email admin@example.com
}
shop.example.com {
encode gzip zstd
reverse_proxy 127.0.0.1:3000
}
Проверка и перезапуск:
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)
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
Порт 3000 наружу не открывайте — к приложению ходят только через Caddy.
Порядок запуска после перезагрузки
shop(Node.js на127.0.0.1:3000)caddy(прокси + HTTPS)
HTTP 502 при рабочем SSL
SSL есть, 502 — значит Caddy жив, а Node на 127.0.0.1:3000 не отвечает.
На сервере выполните:
bash /opt/shop/scripts/diagnose-502.sh
journalctl -u shop -n 50 --no-pager
curl -v http://127.0.0.1:3000/health
Частые причины и исправление:
| Причина | Что сделать |
|---|---|
Служба shop не запущена или падает |
systemctl restart shop, смотрите логи journalctl -u shop -f |
Нет npm install / сломан better-sqlite3 |
cd /opt/shop && npm install --omit=dev (нужны build-essential, python3) |
Нет прав на data/ у www-data |
mkdir -p /opt/shop/data && chown -R www-data:www-data /opt/shop/data |
dubious ownership / нет git pull |
chown -R root:root /opt/shop + safe.directory (см. выше) |
В .env нет HOST/PORT |
HOST=127.0.0.1, PORT=3000, затем systemctl restart shop |
Неверный путь к node в systemd |
which node → подставьте в ExecStart в /etc/systemd/system/shop.service |
| Caddy стартовал раньше shop | cp deploy/caddy-after-shop.conf /etc/systemd/system/caddy.service.d/shop.conf и daemon-reload |
Быстрое восстановление:
cd /opt/shop
git config --global --add safe.directory /opt/shop
git pull
npm install --omit=dev
mkdir -p data
chown -R www-data:www-data /opt/shop/data
systemctl restart shop
curl -s http://127.0.0.1:3000/health # должен быть {"ok":true,...}
systemctl reload caddy
Ошибка dubious ownership при git pull:
Вы сделали chown -R www-data на весь каталог. Верните владельца репозиторию root и оставьте data/ за www-data:
chown -R root:root /opt/shop
chown -R www-data:www-data /opt/shop/data
git config --global --add safe.directory /opt/shop
git pull
Пока curl http://127.0.0.1:3000/health не возвращает OK — HTTPS через Caddy будет отдавать 502.
Другие проблемы
| Симптом | Решение |
|---|---|
| Нет сертификата | DNS, порты 80/443, верный домен в Caddyfile |
| Редирект-цикл / нет cookies | В .env: TRUST_PROXY=1, NODE_ENV=production |
Обновление с Git
cd /opt/shop
systemctl stop shop
git pull
npm install --omit=dev
systemctl start shop
# Caddy перезагружать не нужно, если Caddyfile не менялся
Локальная разработка
npm install
cp .env.example .env
npm run dev
Сайт: 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). Делайте резервные копии:
cp -a data/shop.db data/shop.db.bak
Структура проекта
caddy/
Caddyfile.example — пример reverse proxy + SSL
deploy/
shop.service — unit для systemd
scripts/
diagnose-502.sh — проверка при 502
src/
server.js — точка входа
db.js — схема SQLite
seed.js — демо-данные
routes/ — маршруты
views/ — шаблоны EJS
public/css/ — стили
Репозиторий
git clone https://git.evilfox.cc/test/shop10.git