2026-04-07 02:04:22 +05:30
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
# YakPanel (YakPanel-server) — native Linux installer (systemd + Nginx + Redis).
|
|
|
|
|
#
|
|
|
|
|
# One-liners (run as root):
|
|
|
|
|
# curl -fsSL https://www.yakpanel.com/YakPanel-server/install.sh | bash
|
|
|
|
|
# wget -qO- https://www.yakpanel.com/YakPanel-server/install.sh | bash
|
|
|
|
|
#
|
|
|
|
|
# Preserve environment through sudo:
|
|
|
|
|
# sudo -E bash install.sh
|
|
|
|
|
#
|
|
|
|
|
# Environment (optional):
|
2026-04-07 02:42:07 +05:30
|
|
|
# REPO_URL Git URL (default: https://source.yakpanel.com/admin/yakpanel-core.git)
|
2026-04-07 02:04:22 +05:30
|
|
|
# YAKPANEL_BRANCH Branch/tag for shallow clone (default: default branch)
|
|
|
|
|
# GIT_REF Alias for YAKPANEL_BRANCH
|
|
|
|
|
# INSTALL_PATH Install dir (default: /www/server/YakPanel-server)
|
|
|
|
|
# PANEL_PORT Nginx listen port (default: 8888)
|
|
|
|
|
# BACKEND_PORT Uvicorn port (default: 8889)
|
|
|
|
|
# YAKPANEL_SOURCE_DIR If set, skip git: must contain backend/ and frontend/ (air-gap / local tree)
|
|
|
|
|
#
|
|
|
|
|
# From an already-cloned YakPanel-server repo:
|
|
|
|
|
# sudo YAKPANEL_SOURCE_DIR="$(pwd)" bash install.sh
|
|
|
|
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
2026-04-07 02:42:07 +05:30
|
|
|
REPO_URL="${REPO_URL:-https://source.yakpanel.com/admin/yakpanel-core.git}"
|
2026-04-07 02:04:22 +05:30
|
|
|
INSTALL_PATH="${INSTALL_PATH:-/www/server/YakPanel-server}"
|
|
|
|
|
PANEL_PORT="${PANEL_PORT:-8888}"
|
|
|
|
|
BACKEND_PORT="${BACKEND_PORT:-8889}"
|
|
|
|
|
YAKPANEL_BRANCH="${YAKPANEL_BRANCH:-${GIT_REF:-}}"
|
|
|
|
|
SYSTEMD_UNIT="YakPanel-server"
|
|
|
|
|
|
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
|
case "$1" in
|
|
|
|
|
--repo-url)
|
|
|
|
|
REPO_URL="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--install-path)
|
|
|
|
|
INSTALL_PATH="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--branch|--ref)
|
|
|
|
|
YAKPANEL_BRANCH="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--source-dir)
|
|
|
|
|
YAKPANEL_SOURCE_DIR="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--panel-port)
|
|
|
|
|
PANEL_PORT="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
--backend-port)
|
|
|
|
|
BACKEND_PORT="$2"
|
|
|
|
|
shift 2
|
|
|
|
|
;;
|
|
|
|
|
-h|--help)
|
|
|
|
|
grep '^#' "$0" | grep -v '^#!/' | sed 's/^# \{0,1\}//'
|
|
|
|
|
exit 0
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
echo "Unknown option: $1 (use --help)"
|
|
|
|
|
exit 1
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo "=========================================="
|
|
|
|
|
echo " YakPanel Installer (YakPanel-server)"
|
|
|
|
|
echo "=========================================="
|
|
|
|
|
|
|
|
|
|
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
|
|
|
|
|
echo "Run as root, e.g.: sudo -E bash $0"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
detect_pkg_manager() {
|
|
|
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
|
|
|
echo "apt"
|
|
|
|
|
elif command -v dnf >/dev/null 2>&1; then
|
|
|
|
|
echo "dnf"
|
|
|
|
|
elif command -v yum >/dev/null 2>&1; then
|
|
|
|
|
echo "yum"
|
|
|
|
|
else
|
|
|
|
|
echo ""
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PKG=$(detect_pkg_manager)
|
|
|
|
|
if [ -z "$PKG" ]; then
|
|
|
|
|
echo "No supported package manager (apt-get, dnf, or yum). Use Docker instead; see README.md."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
install_base_packages() {
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[1/6] Installing system dependencies ($PKG)..."
|
|
|
|
|
case "$PKG" in
|
|
|
|
|
apt)
|
|
|
|
|
apt-get update -qq
|
|
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y \
|
2026-04-07 04:11:59 +05:30
|
|
|
git python3 python3-venv python3-pip python3-dev build-essential \
|
|
|
|
|
redis-server nginx curl ca-certificates
|
2026-04-07 02:04:22 +05:30
|
|
|
;;
|
|
|
|
|
dnf|yum)
|
|
|
|
|
if [ "$PKG" = dnf ]; then
|
|
|
|
|
$PKG install -y dnf-plugins-core 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
if [ "$PKG" = dnf ] && [ -f /etc/almalinux-release ]; then
|
|
|
|
|
dnf config-manager --set-enabled crb 2>/dev/null || dnf config-manager --set-enabled powertools 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
if [ "$PKG" = dnf ] && [ -f /etc/rocky-release ]; then
|
|
|
|
|
dnf config-manager --set-enabled crb 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
$PKG install -y git python3 python3-pip nginx redis curl ca-certificates \
|
|
|
|
|
gcc-c++ make python3-devel openssl-devel || \
|
|
|
|
|
$PKG install -y git python3 python3-pip nginx redis curl ca-certificates gcc-c++ make
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-07 04:11:59 +05:30
|
|
|
# Default dist Python (3.10+ on Ubuntu 22.04) is enough; otherwise install 3.11 from apt.
|
|
|
|
|
ensure_python_for_backend() {
|
|
|
|
|
if [ -n "${PYTHON_CMD:-}" ]; then
|
|
|
|
|
return 0
|
2026-04-07 02:04:22 +05:30
|
|
|
fi
|
2026-04-07 04:11:59 +05:30
|
|
|
if python3 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)' 2>/dev/null; then
|
2026-04-07 02:04:22 +05:30
|
|
|
PYTHON_CMD=python3
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
2026-04-07 04:11:59 +05:30
|
|
|
if command -v python3.11 >/dev/null 2>&1 && python3.11 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 10) else 1)' 2>/dev/null; then
|
|
|
|
|
PYTHON_CMD=python3.11
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
2026-04-07 02:04:22 +05:30
|
|
|
if [ "$PKG" = apt ]; then
|
2026-04-07 04:11:59 +05:30
|
|
|
echo "Python 3.10+ required for the backend; installing python3.11 from apt..."
|
2026-04-07 02:04:22 +05:30
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y python3.11 python3.11-venv python3.11-dev || {
|
2026-04-07 04:11:59 +05:30
|
|
|
echo "Could not install python3.11. Enable universe or install Python 3.10+ manually."
|
2026-04-07 02:04:22 +05:30
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
PYTHON_CMD=python3.11
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
2026-04-07 04:11:59 +05:30
|
|
|
echo "Python 3.10+ required. Current: $(python3 -V 2>/dev/null || echo 'python3 missing')"
|
2026-04-07 02:04:22 +05:30
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ensure_node_18_plus() {
|
|
|
|
|
local major
|
|
|
|
|
if command -v node >/dev/null 2>&1; then
|
|
|
|
|
major="$(node -v | sed 's/^v//' | cut -d. -f1)"
|
|
|
|
|
if [ "${major:-0}" -ge 18 ] 2>/dev/null; then
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
echo "Installing Node.js 20 (NodeSource)..."
|
|
|
|
|
case "$PKG" in
|
|
|
|
|
apt)
|
|
|
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
|
|
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs
|
|
|
|
|
;;
|
|
|
|
|
dnf|yum)
|
|
|
|
|
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
|
|
|
|
|
$PKG install -y nodejs
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
find_yakpanel_root_in_tree() {
|
|
|
|
|
local root="$1"
|
|
|
|
|
if [ -d "$root/YakPanel-server/backend" ] && [ -d "$root/YakPanel-server/frontend" ]; then
|
|
|
|
|
echo "$root/YakPanel-server"
|
|
|
|
|
elif [ -d "$root/YakPanel-master/YakPanel-server/backend" ] && [ -d "$root/YakPanel-master/YakPanel-server/frontend" ]; then
|
|
|
|
|
echo "$root/YakPanel-master/YakPanel-server"
|
|
|
|
|
elif [ -d "$root/yakpanel-server/backend" ] && [ -d "$root/yakpanel-server/frontend" ]; then
|
|
|
|
|
echo "$root/yakpanel-server"
|
|
|
|
|
elif [ -d "$root/YakPanel-master/yakpanel-server/backend" ] && [ -d "$root/YakPanel-master/yakpanel-server/frontend" ]; then
|
|
|
|
|
echo "$root/YakPanel-master/yakpanel-server"
|
|
|
|
|
elif [ -d "$root/backend" ] && [ -d "$root/frontend" ]; then
|
|
|
|
|
echo "$root"
|
|
|
|
|
else
|
|
|
|
|
echo ""
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage_source_to_install_path() {
|
|
|
|
|
local src="$1"
|
|
|
|
|
mkdir -p "$(dirname "$INSTALL_PATH")"
|
|
|
|
|
rm -rf "$INSTALL_PATH"
|
|
|
|
|
cp -a "$src" "$INSTALL_PATH"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
install_base_packages
|
2026-04-07 04:11:59 +05:30
|
|
|
ensure_python_for_backend
|
2026-04-07 02:04:22 +05:30
|
|
|
ensure_node_18_plus
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[2/6] Obtaining YakPanel source..."
|
|
|
|
|
if [ -n "${YAKPANEL_SOURCE_DIR:-}" ]; then
|
|
|
|
|
if [ ! -d "$YAKPANEL_SOURCE_DIR/backend" ] || [ ! -d "$YAKPANEL_SOURCE_DIR/frontend" ]; then
|
|
|
|
|
echo "YAKPANEL_SOURCE_DIR must contain backend/ and frontend/: $YAKPANEL_SOURCE_DIR"
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
stage_source_to_install_path "$YAKPANEL_SOURCE_DIR"
|
|
|
|
|
else
|
|
|
|
|
TMP_DIR="$(mktemp -d)"
|
|
|
|
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
2026-04-07 02:30:14 +05:30
|
|
|
export GIT_TERMINAL_PROMPT=0
|
2026-04-07 02:32:11 +05:30
|
|
|
# Disable credential helpers for this clone so anonymous HTTPS public repos work
|
|
|
|
|
# from curl|bash (no TTY); USER:TOKEN in REPO_URL is still used if present.
|
|
|
|
|
CLONE_ARGS=(git -c credential.helper= clone --depth 1)
|
2026-04-07 02:04:22 +05:30
|
|
|
if [ -n "$YAKPANEL_BRANCH" ]; then
|
|
|
|
|
CLONE_ARGS+=(--branch "$YAKPANEL_BRANCH")
|
|
|
|
|
fi
|
|
|
|
|
CLONE_ARGS+=("$REPO_URL" "$TMP_DIR/repo")
|
|
|
|
|
if ! "${CLONE_ARGS[@]}"; then
|
|
|
|
|
echo "Git clone failed. Check REPO_URL=$REPO_URL, DNS, and outbound HTTPS."
|
2026-04-07 02:35:38 +05:30
|
|
|
echo "If the server requires sign-in: allow anonymous clone for HTTP(S), or use a token in the URL, e.g."
|
2026-04-07 02:42:07 +05:30
|
|
|
echo " REPO_URL=https://USER:TOKEN@source.yakpanel.com/admin/yakpanel-core.git"
|
2026-04-07 02:35:38 +05:30
|
|
|
echo "Or override: REPO_URL=https://your.other.git/mirror.git"
|
2026-04-07 02:04:22 +05:30
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
SRC_DIR="$(find_yakpanel_root_in_tree "$TMP_DIR/repo")"
|
|
|
|
|
if [ -z "$SRC_DIR" ]; then
|
|
|
|
|
echo "Could not find YakPanel-server layout (backend/ + frontend/) under cloned repo."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
stage_source_to_install_path "$SRC_DIR"
|
|
|
|
|
trap - EXIT
|
|
|
|
|
rm -rf "$TMP_DIR"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[3/6] Setting up backend..."
|
|
|
|
|
cd "$INSTALL_PATH/backend"
|
|
|
|
|
"$PYTHON_CMD" -m venv venv
|
|
|
|
|
# shellcheck source=/dev/null
|
|
|
|
|
source venv/bin/activate
|
|
|
|
|
pip install -q -r requirements.txt
|
2026-04-07 04:11:59 +05:30
|
|
|
./venv/bin/python -c "import app.main" || {
|
|
|
|
|
echo "ERROR: Backend failed to import (see traceback above). Check Python version and requirements."
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
2026-04-07 02:04:22 +05:30
|
|
|
python scripts/seed_admin.py
|
|
|
|
|
deactivate
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[4/6] Building frontend..."
|
|
|
|
|
cd "$INSTALL_PATH/frontend"
|
|
|
|
|
npm install --silent
|
|
|
|
|
npm run build
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[5/6] Configuring systemd..."
|
|
|
|
|
REDIS_AFTER="redis.target"
|
2026-04-07 04:03:46 +05:30
|
|
|
REDIS_WANTS=""
|
|
|
|
|
case "$PKG" in
|
|
|
|
|
apt)
|
|
|
|
|
REDIS_AFTER="redis-server.service"
|
|
|
|
|
REDIS_WANTS="Wants=redis-server.service"
|
|
|
|
|
;;
|
|
|
|
|
dnf|yum)
|
|
|
|
|
REDIS_AFTER="redis.service"
|
|
|
|
|
REDIS_WANTS="Wants=redis.service"
|
|
|
|
|
;;
|
|
|
|
|
esac
|
2026-04-07 02:04:22 +05:30
|
|
|
|
2026-04-07 04:03:46 +05:30
|
|
|
# Redis must be up before Uvicorn; starting it after the panel caused 502 (nginx OK, API down).
|
2026-04-07 02:04:22 +05:30
|
|
|
case "$PKG" in
|
|
|
|
|
apt)
|
|
|
|
|
systemctl enable redis-server 2>/dev/null || true
|
|
|
|
|
systemctl start redis-server 2>/dev/null || true
|
|
|
|
|
;;
|
|
|
|
|
dnf|yum)
|
|
|
|
|
systemctl enable redis 2>/dev/null || true
|
|
|
|
|
systemctl start redis 2>/dev/null || true
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
|
2026-04-07 04:03:46 +05:30
|
|
|
cat > "/etc/systemd/system/${SYSTEMD_UNIT}.service" << EOF
|
|
|
|
|
[Unit]
|
|
|
|
|
Description=YakPanel Backend
|
|
|
|
|
After=network.target $REDIS_AFTER
|
|
|
|
|
$REDIS_WANTS
|
|
|
|
|
|
|
|
|
|
[Service]
|
|
|
|
|
Type=simple
|
|
|
|
|
User=root
|
|
|
|
|
WorkingDirectory=$INSTALL_PATH/backend
|
2026-04-07 04:28:40 +05:30
|
|
|
# Include system paths: systemd does not expand \$PATH reliably; venv-only PATH breaks dnf/apt from the API.
|
|
|
|
|
Environment="PATH=$INSTALL_PATH/backend/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
2026-04-07 04:11:59 +05:30
|
|
|
Environment=PYTHONUNBUFFERED=1
|
2026-04-07 04:03:46 +05:30
|
|
|
ExecStart=$INSTALL_PATH/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port $BACKEND_PORT
|
|
|
|
|
Restart=always
|
|
|
|
|
RestartSec=3
|
|
|
|
|
|
|
|
|
|
[Install]
|
|
|
|
|
WantedBy=multi-user.target
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
systemctl daemon-reload
|
|
|
|
|
systemctl enable "$SYSTEMD_UNIT"
|
|
|
|
|
systemctl restart "$SYSTEMD_UNIT" || systemctl start "$SYSTEMD_UNIT"
|
|
|
|
|
|
|
|
|
|
backend_ok=0
|
2026-04-07 04:11:59 +05:30
|
|
|
for _ in {1..120}; do
|
2026-04-07 04:03:46 +05:30
|
|
|
if curl -sfS --max-time 2 "http://127.0.0.1:${BACKEND_PORT}/api/health" >/dev/null 2>&1; then
|
|
|
|
|
backend_ok=1
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
sleep 0.5
|
|
|
|
|
done
|
|
|
|
|
if [ "$backend_ok" -ne 1 ]; then
|
|
|
|
|
echo ""
|
|
|
|
|
echo "WARNING: Backend did not respond on http://127.0.0.1:${BACKEND_PORT}/api/health (login will show 502 via Nginx)."
|
|
|
|
|
echo "Check: systemctl status $SYSTEMD_UNIT --no-pager"
|
|
|
|
|
echo "Logs: journalctl -u $SYSTEMD_UNIT -n 80 --no-pager"
|
|
|
|
|
echo "If SELinux is Enforcing: setsebool -P httpd_can_network_connect 1"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
write_nginx_site() {
|
|
|
|
|
local target="$1"
|
|
|
|
|
cat > "$target" << NGINXEOF
|
|
|
|
|
server {
|
|
|
|
|
listen $PANEL_PORT;
|
|
|
|
|
server_name _;
|
|
|
|
|
root $INSTALL_PATH/frontend/dist;
|
|
|
|
|
index index.html;
|
|
|
|
|
location / {
|
|
|
|
|
try_files \$uri \$uri/ /index.html;
|
|
|
|
|
}
|
|
|
|
|
location /api {
|
|
|
|
|
proxy_pass http://127.0.0.1:$BACKEND_PORT;
|
|
|
|
|
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;
|
|
|
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
2026-04-07 04:03:46 +05:30
|
|
|
proxy_connect_timeout 60s;
|
|
|
|
|
proxy_send_timeout 60s;
|
|
|
|
|
proxy_read_timeout 60s;
|
2026-04-07 02:04:22 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
NGINXEOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "[6/6] Configuring Nginx..."
|
|
|
|
|
if [ -d /etc/nginx/sites-available ] && [ -d /etc/nginx/sites-enabled ]; then
|
|
|
|
|
write_nginx_site /etc/nginx/sites-available/YakPanel-server
|
|
|
|
|
ln -sf /etc/nginx/sites-available/YakPanel-server /etc/nginx/sites-enabled/YakPanel-server
|
|
|
|
|
else
|
|
|
|
|
write_nginx_site /etc/nginx/conf.d/YakPanel-server.conf
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
systemctl enable nginx 2>/dev/null || true
|
|
|
|
|
systemctl start nginx 2>/dev/null || true
|
|
|
|
|
nginx -t
|
|
|
|
|
systemctl reload nginx 2>/dev/null || systemctl restart nginx
|
|
|
|
|
|
2026-04-07 04:03:46 +05:30
|
|
|
# Nginx -> upstream (e.g. 127.0.0.1:$BACKEND_PORT) is blocked by default on EL + SELinux => 502.
|
|
|
|
|
if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce 2>/dev/null)" = "Enforcing" ]; then
|
|
|
|
|
if command -v setsebool >/dev/null 2>&1; then
|
|
|
|
|
setsebool -P httpd_can_network_connect 1 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
if systemctl is-active --quiet firewalld 2>/dev/null; then
|
|
|
|
|
firewall-cmd --permanent --add-port="${PANEL_PORT}/tcp" >/dev/null 2>&1 || true
|
|
|
|
|
firewall-cmd --reload >/dev/null 2>&1 || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if command -v ufw >/dev/null 2>&1; then
|
|
|
|
|
ufw allow "${PANEL_PORT}/tcp" 2>/dev/null || true
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
echo "=========================================="
|
|
|
|
|
echo " YakPanel installed successfully!"
|
|
|
|
|
echo "=========================================="
|
|
|
|
|
echo ""
|
|
|
|
|
echo " Access: http://YOUR_SERVER_IP:$PANEL_PORT"
|
|
|
|
|
echo " Login: admin / admin"
|
|
|
|
|
echo ""
|
|
|
|
|
echo " Change your password after first login."
|
2026-04-07 04:03:46 +05:30
|
|
|
echo " UI works but login shows 502? Backend down or SELinux: systemctl status $SYSTEMD_UNIT; journalctl -u $SYSTEMD_UNIT -n 50"
|
|
|
|
|
echo " SELinux: installer calls setsebool httpd_can_network_connect if Enforcing; see README for 403 on static files."
|
2026-04-07 02:04:22 +05:30
|
|
|
echo "=========================================="
|