fix(install): lite deploy for small VPS disks

Run Postgres/Redis in Docker and build Next.js on host to avoid
image build exhausting 10GB root volumes.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Андрей Бобырев
2026-05-24 22:22:55 +03:00
parent ab5c0084b2
commit 9c7bd392e9

View File

@@ -1,10 +1,11 @@
#!/usr/bin/env bash
# Domain Scanner — one-command VPS install (Docker Compose + nginx)
# Domain Scanner — VPS install (Postgres/Redis in Docker, Next.js on host)
# Full `docker compose up` (web image) needs ~4GB free disk; this script uses the lite path.
set -euo pipefail
REPO_URL="${DOMAIN_SCANNER_REPO_URL:-https://github.com/andrey271192/Domain_web.git}"
BRANCH="${DOMAIN_SCANNER_BRANCH:-main}"
INSTALL_DIR="${DOMAIN_SCANNER_INSTALL_DIR:-/opt/domain_web}"
INSTALL_DIR="${DOMAIN_SCANNER_INSTALL_DIR:-/opt/domain-scanner}"
SERVICE_NAME="domain-scanner"
NGINX_SITE="domain-scanner"
APP_PORT="${DOMAIN_SCANNER_PORT:-3000}"
@@ -27,16 +28,26 @@ install_packages() {
apt-get install -y -qq curl ca-certificates git nginx openssl >/dev/null
}
install_node() {
if command -v node >/dev/null 2>&1 && [[ "$(node -p 'process.versions.node.split(".")[0]')" -ge 20 ]]; then
log "Node $(node -v) already installed"
return
fi
log "Installing Node.js 22..."
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y -qq nodejs >/dev/null
}
install_docker() {
if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
log "Docker already installed"
return
else
log "Installing Docker..."
curl -fsSL https://get.docker.com | sh
fi
log "Installing Docker..."
curl -fsSL https://get.docker.com | sh
systemctl enable docker.socket docker.service
systemctl start docker.socket
systemctl start docker.service
systemctl enable docker.socket docker.service 2>/dev/null || true
systemctl start docker.socket 2>/dev/null || true
systemctl start docker.service 2>/dev/null || true
}
stop_legacy() {
@@ -46,6 +57,7 @@ stop_legacy() {
rm -f "/etc/systemd/system/${LEGACY_SERVICE}.service"
rm -f "/etc/nginx/sites-enabled/${LEGACY_NGINX}"
rm -f "/etc/nginx/sites-available/${LEGACY_NGINX}"
rm -rf /opt/domain_web 2>/dev/null || true
systemctl daemon-reload 2>/dev/null || true
}
@@ -73,35 +85,64 @@ setup_env() {
sed -i "s|^NEXTAUTH_SECRET=.*|NEXTAUTH_SECRET=${secret}|" .env
sed -i "s|^NEXTAUTH_URL=.*|NEXTAUTH_URL=http://${ip}|" .env
sed -i "s|^NEXT_PUBLIC_APP_URL=.*|NEXT_PUBLIC_APP_URL=http://${ip}|" .env
export PORT="${APP_PORT}"
sed -i "s|^DATABASE_URL=.*|DATABASE_URL=postgresql://scanner:scanner@127.0.0.1:5432/domain_scanner?schema=public|" .env
sed -i "s|^REDIS_URL=.*|REDIS_URL=redis://127.0.0.1:6379|" .env
}
deploy_compose() {
deploy_data_services() {
log "Starting Postgres and Redis (Docker)..."
cd "${INSTALL_DIR}"
export PORT="${APP_PORT}"
AVAIL_KB=$(df -k "${INSTALL_DIR}" | awk 'NR==2 {print $4}')
if [[ "${AVAIL_KB:-0}" -lt 2500000 ]]; then
log "Low disk — Node-native deploy..."
bash "${INSTALL_DIR}/scripts/install-node.sh"
return
fi
log "Building Docker stack..."
if docker compose version >/dev/null 2>&1; then
if ! docker compose build 2>&1; then
log "Docker build failed — Node-native deploy..."
bash "${INSTALL_DIR}/scripts/install-node.sh"
return
docker compose up -d postgres redis
for i in $(seq 1 30); do
if docker compose exec -T postgres pg_isready -U scanner -d domain_scanner >/dev/null 2>&1; then
break
fi
docker compose up -d
docker compose exec -T web npx prisma db push
else
if ! docker-compose build 2>&1; then
bash "${INSTALL_DIR}/scripts/install-node.sh"
return
fi
docker-compose up -d
docker-compose exec -T web npx prisma db push
fi
sleep 2
done
}
build_app() {
log "Building Next.js app on host..."
cd "${INSTALL_DIR}"
export NODE_ENV=production
npm ci
npx prisma generate
npx prisma db push
npm run build
rm -rf node_modules
npm ci --omit=dev
npx prisma generate
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
journalctl --vacuum-size=80M 2>/dev/null || true
apt-get clean 2>/dev/null || true
}
install_systemd() {
log "Installing systemd unit (${SERVICE_NAME})..."
cat >"/etc/systemd/system/${SERVICE_NAME}.service" <<EOF
[Unit]
Description=Domain Scanner (Next.js)
After=network.target docker.service
Wants=docker.service
[Service]
Type=simple
WorkingDirectory=${INSTALL_DIR}/.next/standalone
EnvironmentFile=${INSTALL_DIR}/.env
Environment=HOSTNAME=0.0.0.0
Environment=PORT=${APP_PORT}
Environment=NODE_ENV=production
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "${SERVICE_NAME}.service"
systemctl restart "${SERVICE_NAME}.service"
}
install_nginx() {
@@ -138,10 +179,14 @@ EOF
verify() {
log "Verifying deployment..."
sleep 5
sleep 4
if ! systemctl is-active --quiet "${SERVICE_NAME}.service"; then
systemctl status "${SERVICE_NAME}.service" --no-pager || true
journalctl -u "${SERVICE_NAME}.service" -n 30 --no-pager || true
exit 1
fi
if ! curl -fsS -o /dev/null "http://127.0.0.1:${APP_PORT}/api/health"; then
echo "App health check failed on port ${APP_PORT}" >&2
cd "${INSTALL_DIR}" && docker compose logs --tail=40 web 2>/dev/null || true
echo "Health check failed on port ${APP_PORT}" >&2
exit 1
fi
local title
@@ -150,22 +195,21 @@ verify() {
echo "ERROR: GeoExport mirror still served — aborting" >&2
exit 1
fi
if ! curl -fsS -o /dev/null "http://127.0.0.1/"; then
echo "nginx not serving on :80" >&2
exit 1
fi
local ip
ip="$(hostname -I | awk '{print $1}')"
log "Done. Domain Scanner: http://${ip}/"
log "Title check: ${title:-ok}"
log "Title: ${title:-Domain Scanner}"
}
need_root
install_packages
install_node
install_docker
stop_legacy
clone_or_update
setup_env
deploy_compose
deploy_data_services
build_app
install_systemd
install_nginx
verify