mirror of
https://github.com/andrey271192/Domain_web.git
synced 2026-09-21 14:51:57 +00:00
feat(deploy): full one-line install with search API
Bundle static site, FastAPI search, nginx proxy, and systemd unit so a fresh Ubuntu VPS can run curl install.sh and get /search working. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
133
install.sh
133
install.sh
@@ -1,13 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Domain Web — lightweight static site (nginx :80)
|
||||
# Domain Web — full deploy: static site + search API (nginx :80)
|
||||
# curl -fsSL https://raw.githubusercontent.com/andrey271192/Domain_web/main/install.sh | sudo bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="${DOMAIN_WEB_REPO_URL:-https://github.com/andrey271192/Domain_web.git}"
|
||||
BOT_REPO_URL="${DOMAIN_FINDER_REPO:-https://github.com/andrey271192/domain-finder-bot.git}"
|
||||
BRANCH="${DOMAIN_WEB_BRANCH:-main}"
|
||||
INSTALL_SRC="${DOMAIN_WEB_INSTALL_SRC:-/opt/domain-web-src}"
|
||||
WEB_ROOT="${DOMAIN_WEB_ROOT:-/var/www/domain-web}"
|
||||
API_DIR="${DOMAIN_WEB_API_DIR:-/opt/domain-web-api}"
|
||||
BOT_DIR="${DOMAIN_FINDER_BOT_DIR:-/opt/domain-finder-bot}"
|
||||
NGINX_SITE="domain-web"
|
||||
API_SERVICE="domain-web-api"
|
||||
LEGACY_SERVICES=("domain-scanner" "geoexport-site")
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
@@ -22,9 +26,19 @@ need_root() {
|
||||
}
|
||||
|
||||
install_packages() {
|
||||
log "Installing nginx, git, curl..."
|
||||
log "Installing system packages..."
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq nginx git curl ca-certificates rsync >/dev/null
|
||||
apt-get install -y -qq \
|
||||
nginx git curl ca-certificates rsync \
|
||||
python3 python3-venv python3-pip >/dev/null
|
||||
}
|
||||
|
||||
ensure_domainbot_user() {
|
||||
if ! id domainbot >/dev/null 2>&1; then
|
||||
log "Creating system user domainbot..."
|
||||
useradd --system --home "${BOT_DIR}" --shell /usr/sbin/nologin domainbot
|
||||
fi
|
||||
mkdir -p "${BOT_DIR}/data" "${API_DIR}"
|
||||
}
|
||||
|
||||
stop_legacy_scanner() {
|
||||
@@ -51,29 +65,78 @@ clone_repo() {
|
||||
fi
|
||||
}
|
||||
|
||||
clone_discovery_bot() {
|
||||
log "Fetching discovery modules (${BOT_REPO_URL})..."
|
||||
if [[ -d "${BOT_DIR}/.git" ]]; then
|
||||
git -C "${BOT_DIR}" fetch --depth 1 origin main 2>/dev/null || true
|
||||
git -C "${BOT_DIR}" reset --hard origin/main 2>/dev/null || \
|
||||
git -C "${BOT_DIR}" pull --ff-only 2>/dev/null || true
|
||||
else
|
||||
rm -rf "${BOT_DIR}"
|
||||
git clone --depth 1 "${BOT_REPO_URL}" "${BOT_DIR}"
|
||||
fi
|
||||
|
||||
if [[ ! -x "${BOT_DIR}/.venv/bin/python" ]]; then
|
||||
log "Creating domain-finder-bot venv (discovery deps)..."
|
||||
python3 -m venv "${BOT_DIR}/.venv"
|
||||
"${BOT_DIR}/.venv/bin/pip" install -q -U pip
|
||||
"${BOT_DIR}/.venv/bin/pip" install -q -r "${BOT_DIR}/requirements.txt"
|
||||
fi
|
||||
}
|
||||
|
||||
deploy_web() {
|
||||
log "Deploying static files to ${WEB_ROOT}..."
|
||||
mkdir -p "${WEB_ROOT}"
|
||||
log "Deploying static site to ${WEB_ROOT}..."
|
||||
mkdir -p "${WEB_ROOT}/data"
|
||||
rsync -a --delete "${INSTALL_SRC}/web/" "${WEB_ROOT}/"
|
||||
chown -R www-data:www-data "${WEB_ROOT}" 2>/dev/null || chown -R nginx:nginx "${WEB_ROOT}" 2>/dev/null || true
|
||||
|
||||
if [[ ! -f "${WEB_ROOT}/data/site-config.json" ]]; then
|
||||
cp "${INSTALL_SRC}/web/data/site-config.json.example" "${WEB_ROOT}/data/site-config.json"
|
||||
fi
|
||||
|
||||
chown -R www-data:www-data "${WEB_ROOT}" 2>/dev/null || \
|
||||
chown -R nginx:nginx "${WEB_ROOT}" 2>/dev/null || true
|
||||
}
|
||||
|
||||
deploy_api() {
|
||||
log "Deploying search API to ${API_DIR}..."
|
||||
mkdir -p "${API_DIR}"
|
||||
rsync -a --delete "${INSTALL_SRC}/api/" "${API_DIR}/"
|
||||
|
||||
if [[ ! -x "${API_DIR}/.venv/bin/python" ]]; then
|
||||
python3 -m venv "${API_DIR}/.venv"
|
||||
fi
|
||||
"${API_DIR}/.venv/bin/pip" install -q -U pip
|
||||
"${API_DIR}/.venv/bin/pip" install -q -r "${API_DIR}/requirements.txt"
|
||||
|
||||
chown -R domainbot:domainbot "${API_DIR}" "${BOT_DIR}"
|
||||
}
|
||||
|
||||
install_systemd() {
|
||||
log "Installing ${API_SERVICE}.service..."
|
||||
cp "${INSTALL_SRC}/systemd/domain-web-api.service" "/etc/systemd/system/${API_SERVICE}.service"
|
||||
systemctl daemon-reload
|
||||
systemctl enable "${API_SERVICE}.service"
|
||||
systemctl restart "${API_SERVICE}.service"
|
||||
}
|
||||
|
||||
configure_nginx() {
|
||||
log "Configuring nginx (HTTP :80)..."
|
||||
log "Configuring nginx (HTTP :80 only — port 443 untouched)..."
|
||||
local conf_src="${INSTALL_SRC}/nginx/domain-web.conf"
|
||||
if [[ ! -f "${conf_src}" ]]; then
|
||||
local snippet_src="${INSTALL_SRC}/nginx/domain-web-api.conf"
|
||||
|
||||
if [[ ! -f "${conf_src}" ]] || [[ ! -f "${snippet_src}" ]]; then
|
||||
echo "Missing nginx config in repo" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Backup existing default if it listens on 80 and is not ours
|
||||
if [[ -f /etc/nginx/sites-enabled/default ]] && ! grep -q "domain-web" /etc/nginx/sites-enabled/default 2>/dev/null; then
|
||||
if grep -q "listen 80" /etc/nginx/sites-enabled/default 2>/dev/null; then
|
||||
mv /etc/nginx/sites-enabled/default /etc/nginx/sites-enabled/default.bak.$(date +%s) 2>/dev/null || true
|
||||
mv /etc/nginx/sites-enabled/default "/etc/nginx/sites-enabled/default.bak.$(date +%s)" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
sed "s|/var/www/domain-web|${WEB_ROOT}|g" "${conf_src}" > "/etc/nginx/sites-available/${NGINX_SITE}"
|
||||
cp "${snippet_src}" /etc/nginx/snippets/domain-web-api.conf
|
||||
sed "s|WEB_ROOT|${WEB_ROOT}|g" "${conf_src}" > "/etc/nginx/sites-available/${NGINX_SITE}"
|
||||
ln -sf "/etc/nginx/sites-available/${NGINX_SITE}" "/etc/nginx/sites-enabled/${NGINX_SITE}"
|
||||
|
||||
nginx -t
|
||||
@@ -81,26 +144,66 @@ configure_nginx() {
|
||||
systemctl reload nginx
|
||||
}
|
||||
|
||||
allow_firewall() {
|
||||
if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q "Status: active"; then
|
||||
log "Allowing HTTP (80) in ufw..."
|
||||
ufw allow 80/tcp >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
verify() {
|
||||
log "Verifying deployment..."
|
||||
sleep 2
|
||||
|
||||
if ! systemctl is-active --quiet "${API_SERVICE}.service"; then
|
||||
journalctl -u "${API_SERVICE}.service" -n 30 --no-pager || true
|
||||
echo "ERROR: ${API_SERVICE} failed to start" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! curl -fsS "http://127.0.0.1:8081/api/health" | grep -q '"status"'; then
|
||||
echo "ERROR: API health check failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for path in / /search /connect.html /domains.html; do
|
||||
code="$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1${path}")"
|
||||
if [[ "${code}" != "200" && "${code}" != "301" && "${code}" != "302" ]]; then
|
||||
echo "WARNING: http://127.0.0.1${path} returned ${code}" >&2
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
print_done() {
|
||||
local ip
|
||||
ip="$(hostname -I 2>/dev/null | awk '{print $1}' || echo 'SERVER_IP')"
|
||||
log "Done."
|
||||
echo ""
|
||||
echo " Site root: ${WEB_ROOT}"
|
||||
echo " URL: http://${ip}/"
|
||||
echo " Pages: /connect.html /domains.html"
|
||||
echo " Site: http://${ip}/"
|
||||
echo " Search: http://${ip}/search"
|
||||
echo " Connect: http://${ip}/connect.html"
|
||||
echo " Domains: http://${ip}/domains.html"
|
||||
echo ""
|
||||
echo " Amnezia (443) and Docker containers were not stopped."
|
||||
echo " Telegram proxy config: ${WEB_ROOT}/data/site-config.json"
|
||||
echo " API service: systemctl status ${API_SERVICE}"
|
||||
echo ""
|
||||
echo " Port 443 / Docker / Amnezia were not modified."
|
||||
echo ""
|
||||
}
|
||||
|
||||
main() {
|
||||
need_root
|
||||
install_packages
|
||||
ensure_domainbot_user
|
||||
stop_legacy_scanner
|
||||
clone_repo
|
||||
clone_discovery_bot
|
||||
deploy_web
|
||||
deploy_api
|
||||
install_systemd
|
||||
configure_nginx
|
||||
allow_firewall
|
||||
verify
|
||||
print_done
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user