diff --git a/README.md b/README.md index a64aa9c..c6ab528 100644 --- a/README.md +++ b/README.md @@ -170,21 +170,14 @@ DATABASE_URL=postgresql://shop:shop@127.0.0.1:5432/shop ## Запуск как служба (systemd) ```bash -cp /opt/shop/shop10/deploy/shop.service /etc/systemd/system/shop.service - cd /opt/shop/shop10 -cp .env.example .env # при первой установке -# Заполните SESSION_SECRET и DATABASE_URL - -npm install --omit=dev - -# Не делайте chown -R www-data на весь /opt/shop (ломает git pull) -systemctl daemon-reload -systemctl enable shop -systemctl start shop +cp .env.example .env # при первой установке — SESSION_SECRET, DATABASE_URL +sudo bash scripts/install-shop-service.sh journalctl -u shop -f ``` +Не делайте `chown -R www-data` на весь каталог репозитория (ломает `git pull`). + `EnvironmentFile=/opt/shop/shop10/.env` должен содержать `DATABASE_URL`. --- diff --git a/scripts/install-shop-service.sh b/scripts/install-shop-service.sh new file mode 100644 index 0000000..c2e761e --- /dev/null +++ b/scripts/install-shop-service.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Установка systemd-службы shop (после git clone и .env) +# sudo bash scripts/install-shop-service.sh +set -euo pipefail + +if [ "$(id -u)" -ne 0 ]; then + echo "Запустите от root: sudo bash scripts/install-shop-service.sh" + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/shop-root.sh" + +echo "=== Установка службы shop ===" +echo "Каталог: $SHOP_ROOT" + +if [ ! -f "$SHOP_ROOT/package.json" ]; then + echo "Ошибка: нет package.json в $SHOP_ROOT" + exit 1 +fi + +if [ ! -f "$SHOP_ROOT/.env" ]; then + if [ -f "$SHOP_ROOT/.env.example" ]; then + cp "$SHOP_ROOT/.env.example" "$SHOP_ROOT/.env" + echo "Создан .env из .env.example — отредактируйте SESSION_SECRET и DATABASE_URL" + else + echo "Ошибка: нет .env — создайте из .env.example" + exit 1 + fi +fi + +if ! grep -q '^DATABASE_URL=' "$SHOP_ROOT/.env"; then + echo "ВНИМАНИЕ: в .env нет DATABASE_URL" +fi + +if ! command -v node >/dev/null; then + echo "Ошибка: node не найден" + exit 1 +fi + +NODE_BIN=$(command -v node) +echo "Node: $NODE_BIN ($($NODE_BIN -v))" + +npm install --omit=dev --prefix "$SHOP_ROOT" + +cp -f "$SHOP_ROOT/deploy/shop.service" /etc/systemd/system/shop.service +sed -i "s|WorkingDirectory=.*|WorkingDirectory=${SHOP_ROOT}|" /etc/systemd/system/shop.service +sed -i "s|EnvironmentFile=.*|EnvironmentFile=${SHOP_ROOT}/.env|" /etc/systemd/system/shop.service +sed -i "s|ExecStart=.*|ExecStart=${NODE_BIN} src/server.js|" /etc/systemd/system/shop.service + +# www-data должен читать код (не меняем владельца всего дерева — только доступ на чтение) +chmod -R a+rX "$SHOP_ROOT" 2>/dev/null || true +if ! sudo -u www-data test -r "$SHOP_ROOT/package.json"; then + echo "Предупреждение: www-data не читает $SHOP_ROOT — проверьте права каталога" +fi + +if command -v pg_isready >/dev/null; then + systemctl enable postgresql 2>/dev/null || true + systemctl start postgresql 2>/dev/null || true +fi + +systemctl daemon-reload +systemctl enable shop +systemctl restart shop + +sleep 2 +if curl -sf http://127.0.0.1:3000/health; then + echo "" + echo "OK — служба shop запущена" + systemctl status shop --no-pager -l | head -12 + systemctl reload caddy 2>/dev/null || true +else + echo "shop не отвечает на :3000" + journalctl -u shop -n 25 --no-pager + exit 1 +fi diff --git a/scripts/server-update.sh b/scripts/server-update.sh index 6153907..3183515 100644 --- a/scripts/server-update.sh +++ b/scripts/server-update.sh @@ -33,16 +33,24 @@ if command -v pg_isready >/dev/null; then } fi -if systemctl is-active --quiet shop 2>/dev/null; then +if [ -f /etc/systemd/system/shop.service ]; then + systemctl daemon-reload systemctl restart shop - sleep 1 - curl -sf http://127.0.0.1:3000/health && echo || { - echo "shop не отвечает — смотрите: journalctl -u shop -n 30" + sleep 2 + if curl -sf http://127.0.0.1:3000/health; then + echo "" + echo "OK" + systemctl reload caddy 2>/dev/null || true + else + echo "shop не отвечает — journalctl -u shop -n 30" exit 1 - } - systemctl reload caddy 2>/dev/null || true - echo "OK" + fi +elif [ "$(id -u)" -eq 0 ]; then + echo "Служба shop не установлена — устанавливаем..." + bash "$SCRIPT_DIR/install-shop-service.sh" else - echo "Служба shop не установлена. См. deploy/shop.service" - echo "WorkingDirectory в unit должен совпадать с: $SHOP_ROOT" + echo "Служба shop не установлена. Выполните от root:" + echo " sudo bash $SHOP_ROOT/scripts/install-shop-service.sh" + echo "WorkingDirectory: $SHOP_ROOT" + exit 1 fi diff --git a/wiki/Troubleshooting.md b/wiki/Troubleshooting.md index ec5c77a..b59f085 100644 --- a/wiki/Troubleshooting.md +++ b/wiki/Troubleshooting.md @@ -52,6 +52,22 @@ cp /opt/shop/shop10.bak.*/.env /opt/shop/shop10/.env 2>/dev/null || cp /opt/shop bash /opt/shop/shop10/scripts/server-update.sh ``` +## Служба shop не установлена + +Код обновился, но 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`):