Initial YakPanel commit
This commit is contained in:
337
YakPanel-server/install.sh
Normal file
337
YakPanel-server/install.sh
Normal file
@@ -0,0 +1,337 @@
|
||||
#!/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):
|
||||
# REPO_URL Git URL (default: public GitHub; use source.yakpanel.com when mirror is live)
|
||||
# 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
|
||||
|
||||
REPO_URL="${REPO_URL:-https://github.com/YakPanel/YakPanel.git}"
|
||||
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 \
|
||||
git python3 python3-venv python3-pip redis-server nginx curl ca-certificates
|
||||
;;
|
||||
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
|
||||
}
|
||||
|
||||
ensure_python_min_311() {
|
||||
if command -v python3.11 >/dev/null 2>&1; then
|
||||
if python3.11 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)' 2>/dev/null; then
|
||||
PYTHON_CMD=python3.11
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
if python3 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else 1)' 2>/dev/null; then
|
||||
PYTHON_CMD=python3
|
||||
return 0
|
||||
fi
|
||||
if [ "$PKG" = apt ]; then
|
||||
echo "Python 3.11+ required for the backend; installing python3.11 from apt..."
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y python3.11 python3.11-venv python3.11-dev || {
|
||||
echo "Could not install python3.11. Use Ubuntu 24.04+, enable universe, or install Python 3.11+ manually."
|
||||
exit 1
|
||||
}
|
||||
PYTHON_CMD=python3.11
|
||||
return 0
|
||||
fi
|
||||
echo "Python 3.11+ required. Current: $(python3 -V 2>/dev/null || echo 'python3 missing')"
|
||||
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
|
||||
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
|
||||
CLONE_ARGS=(git clone --depth 1)
|
||||
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."
|
||||
echo "Try: sudo -E env REPO_URL=https://github.com/YakPanel/YakPanel.git bash install.sh"
|
||||
echo "Own mirror: REPO_URL=https://source.yakpanel.com/yakpanel.git (requires bare repo published; see HOSTING.txt)."
|
||||
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
|
||||
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"
|
||||
if [ "$PKG" = apt ]; then
|
||||
REDIS_AFTER="redis-server.service"
|
||||
fi
|
||||
|
||||
cat > "/etc/systemd/system/${SYSTEMD_UNIT}.service" << EOF
|
||||
[Unit]
|
||||
Description=YakPanel Backend
|
||||
After=network.target $REDIS_AFTER
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=$INSTALL_PATH/backend
|
||||
Environment="PATH=$INSTALL_PATH/backend/venv/bin:\$PATH"
|
||||
ExecStart=$INSTALL_PATH/backend/venv/bin/uvicorn app.main:app --host 127.0.0.1 --port $BACKEND_PORT
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl enable "$SYSTEMD_UNIT"
|
||||
systemctl restart "$SYSTEMD_UNIT" || systemctl start "$SYSTEMD_UNIT"
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
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."
|
||||
echo " SELinux: if Nginx returns 403, see README (labels or temporary permissive)."
|
||||
echo "=========================================="
|
||||
Reference in New Issue
Block a user