204 lines
7.0 KiB
Bash
204 lines
7.0 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Этап A: первичная настройка свежего Debian/Ubuntu (LXC/VM) под Craftshop.
|
|
# Запускать НА СЕРВЕРЕ от root один раз:
|
|
# curl -fsSL … | bash или scp + bash server-bootstrap.sh
|
|
#
|
|
# По умолчанию: ставит Node 22.x (NodeSource), nginx, пользователя deploy, каталоги
|
|
# /opt/craftshop/server и /opt/craftshop/www, systemd craftshop-api, сайт nginx.
|
|
#
|
|
# После выполнения:
|
|
# 1) Положите .env в /opt/craftshop/server/ (DATABASE_URL, JWT_SECRET, ADMIN_EMAIL, CORS_ORIGIN, PORT=3333)
|
|
# 2) DEPLOY_RESTART_CMD при SSH от root: «systemctl restart craftshop-api» (без sudo)
|
|
# 3) Запустите deploy-ssh.sh с вашей машины (по умолчанию пользователь SSH — root, см. scripts/deploy.env.example)
|
|
#
|
|
set -euo pipefail
|
|
|
|
if [[ "$(id -u)" != "0" ]]; then
|
|
echo "Запускайте от root: sudo $0" >&2
|
|
exit 1
|
|
fi
|
|
|
|
CRAFTSHOP_ROOT="${CRAFTSHOP_ROOT:-/opt/craftshop}"
|
|
CRAFTSHOP_USER="${CRAFTSHOP_USER:-deploy}"
|
|
CRAFTSHOP_SERVER_NAME="${CRAFTSHOP_SERVER_NAME:-_}"
|
|
CRAFTSHOP_NODE_MAJOR="${CRAFTSHOP_NODE_MAJOR:-22}"
|
|
SKIP_NODE_INSTALL="${SKIP_NODE_INSTALL:-0}"
|
|
SKIP_NGINX="${SKIP_NGINX:-0}"
|
|
SKIP_SYSTEMD="${SKIP_SYSTEMD:-0}"
|
|
|
|
if [[ -f /etc/craftshop-bootstrap.env ]]; then
|
|
set -a
|
|
# shellcheck source=/dev/null
|
|
source /etc/craftshop-bootstrap.env
|
|
set +a
|
|
fi
|
|
|
|
detect_os() {
|
|
if [[ -f /etc/os-release ]]; then
|
|
# shellcheck source=/dev/null
|
|
source /etc/os-release
|
|
echo "${ID:-unknown}"
|
|
return 0
|
|
fi
|
|
echo unknown
|
|
}
|
|
|
|
OS="$(detect_os)"
|
|
if [[ "$OS" != "debian" && "$OS" != "ubuntu" ]]; then
|
|
echo "Ожидался Debian или Ubuntu (получено: $OS). Прервите выполнение, если образ другой." >&2
|
|
fi
|
|
|
|
echo ">>> apt-get update"
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update -y
|
|
|
|
echo ">>> Базовые пакеты"
|
|
apt-get install -y ca-certificates curl gnupg
|
|
|
|
if [[ "$SKIP_NODE_INSTALL" != "1" ]]; then
|
|
if command -v node >/dev/null 2>&1; then
|
|
ver="$(node -p "parseInt(process.versions.node,10)" 2>/dev/null || echo 0)"
|
|
if [[ "${ver:-0}" -ge 20 ]]; then
|
|
echo ">>> Node уже есть (версия $(node --version)), пропуск NodeSource"
|
|
else
|
|
echo ">>> Node слишком старый, ставим ${CRAFTSHOP_NODE_MAJOR}.x через NodeSource"
|
|
curl -fsSL "https://deb.nodesource.com/setup_${CRAFTSHOP_NODE_MAJOR}.x" | bash -
|
|
apt-get install -y nodejs
|
|
fi
|
|
else
|
|
echo ">>> Установка Node.js ${CRAFTSHOP_NODE_MAJOR}.x через NodeSource"
|
|
curl -fsSL "https://deb.nodesource.com/setup_${CRAFTSHOP_NODE_MAJOR}.x" | bash -
|
|
apt-get install -y nodejs
|
|
fi
|
|
else
|
|
echo ">>> SKIP_NODE_INSTALL=1 — убедитесь, что node >= 20.6 есть в системе"
|
|
command -v node >/dev/null 2>&1 || {
|
|
echo "node не найден" >&2
|
|
exit 1
|
|
}
|
|
fi
|
|
|
|
echo ">>> Пользователь $CRAFTSHOP_USER"
|
|
if ! id -u "$CRAFTSHOP_USER" >/dev/null 2>&1; then
|
|
useradd --create-home --shell /bin/bash "$CRAFTSHOP_USER"
|
|
fi
|
|
|
|
echo ">>> Каталоги $CRAFTSHOP_ROOT/{server,www,uploads}"
|
|
mkdir -p "$CRAFTSHOP_ROOT/server/uploads" "$CRAFTSHOP_ROOT/www"
|
|
chown -R "$CRAFTSHOP_USER:$CRAFTSHOP_USER" "$CRAFTSHOP_ROOT"
|
|
chmod 755 "$CRAFTSHOP_ROOT" "$CRAFTSHOP_ROOT/server" "$CRAFTSHOP_ROOT/www"
|
|
|
|
if [[ "$SKIP_SYSTEMD" != "1" ]]; then
|
|
echo ">>> systemd craftshop-api"
|
|
cat >/etc/systemd/system/craftshop-api.service <<EOF
|
|
[Unit]
|
|
Description=Craftshop API (Fastify)
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=$CRAFTSHOP_USER
|
|
Group=$CRAFTSHOP_USER
|
|
WorkingDirectory=$CRAFTSHOP_ROOT/server
|
|
EnvironmentFile=-$CRAFTSHOP_ROOT/server/.env
|
|
ExecStart=/usr/bin/node src/index.js
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
LimitNOFILE=65535
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
systemctl daemon-reload
|
|
systemctl enable craftshop-api.service
|
|
echo "(сервис не запущен, пока не появится код и \$CRAFTSHOP_ROOT/server/.env)"
|
|
fi
|
|
|
|
if [[ "$SKIP_NGINX" != "1" ]]; then
|
|
apt-get install -y nginx
|
|
|
|
NGINX_SITE="/etc/nginx/sites-available/craftshop"
|
|
|
|
cat >"$NGINX_SITE" <<NGX
|
|
# Craftshop: статика SPA + proxy /api и /uploads на Node (:3333)
|
|
server {
|
|
listen 80 default_server;
|
|
listen [::]:80 default_server;
|
|
|
|
server_name $CRAFTSHOP_SERVER_NAME;
|
|
|
|
root $CRAFTSHOP_ROOT/www;
|
|
index index.html;
|
|
|
|
location /api/ {
|
|
client_max_body_size 250m;
|
|
proxy_pass http://127.0.0.1:3333;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
}
|
|
|
|
location /uploads/ {
|
|
proxy_pass http://127.0.0.1:3333;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
}
|
|
|
|
location / {
|
|
try_files \$uri \$uri/ /index.html;
|
|
}
|
|
}
|
|
NGX
|
|
|
|
if [[ -f /etc/nginx/sites-enabled/default ]]; then
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
fi
|
|
ln -sf "$NGINX_SITE" /etc/nginx/sites-enabled/craftshop
|
|
|
|
nginx -t
|
|
systemctl reload nginx || systemctl restart nginx
|
|
|
|
echo ">>> nginx включён на порту 80 (server_name=$CRAFTSHOP_SERVER_NAME)"
|
|
fi
|
|
|
|
cat >"$CRAFTSHOP_ROOT/server/README-PLACE-ENV.txt" <<TXT
|
|
Создайте файл .env в этом каталоге (права только для $CRAFTSHOP_USER).
|
|
Минимум:
|
|
DATABASE_URL="file:./prod.db"
|
|
PORT=3333
|
|
JWT_SECRET=<длинная случайная строка>
|
|
ADMIN_EMAIL=<ваш email админа>
|
|
CORS_ORIGIN=http://<IP_или_домен_фронта>
|
|
IS_DEFAULT_CODE_ENABLED=false
|
|
|
|
Базу и код вы зальёте скриптом deploy-ssh.sh с машины разработчика:
|
|
первый запуск после деплоя: systemctl start craftshop-api (от root; иначе sudo)
|
|
TXT
|
|
chown "$CRAFTSHOP_USER:$CRAFTSHOP_USER" "$CRAFTSHOP_ROOT/server/README-PLACE-ENV.txt"
|
|
|
|
if [[ -n "${CRAFTSHOP_AUTHORIZED_KEY:-}" ]]; then
|
|
uhome="$(getent passwd "$CRAFTSHOP_USER" | cut -d: -f6)"
|
|
install -d -m 700 -o "$CRAFTSHOP_USER" -g "$CRAFTSHOP_USER" "$uhome/.ssh"
|
|
afile="$uhome/.ssh/authorized_keys"
|
|
if [[ ! -f "$afile" ]]; then
|
|
install -m 600 -o "$CRAFTSHOP_USER" -g "$CRAFTSHOP_USER" /dev/null "$afile"
|
|
fi
|
|
if ! grep -qFx "$CRAFTSHOP_AUTHORIZED_KEY" "$afile" 2>/dev/null; then
|
|
printf '%s\n' "$CRAFTSHOP_AUTHORIZED_KEY" >>"$afile"
|
|
fi
|
|
echo ">>> Добавлен SSH-ключ в $afile"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Готово Этап A."
|
|
echo "- Каталог: $CRAFTSHOP_ROOT"
|
|
echo "- Пользователь: $CRAFTSHOP_USER"
|
|
echo "- Положите $CRAFTSHOP_ROOT/server/.env и выполните деплой кода (--backend-only), затем: systemctl start craftshop-api"
|