-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathinstall.sh
More file actions
162 lines (145 loc) · 6.03 KB
/
Copy pathinstall.sh
File metadata and controls
162 lines (145 loc) · 6.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/bin/bash
# VortexPanel Universal Installer
# Supports: Ubuntu 20.04+, Debian 11+, Fedora 38+, RHEL/AlmaLinux/Rocky 8+
set -e
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
log() { echo -e "${GREEN}[VortexPanel]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
err() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
# Detect OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID="${ID,,}"
OS_VER="${VERSION_ID}"
OS_FAMILY="unknown"
PKG_MGR="apt"
case "$OS_ID" in
ubuntu|debian|linuxmint|pop) OS_FAMILY="debian"; PKG_MGR="apt" ;;
fedora) OS_FAMILY="fedora"; PKG_MGR="dnf" ;;
rhel|centos|almalinux|rocky|ol|cloudlinux) OS_FAMILY="rhel"; PKG_MGR="dnf" ;;
*) warn "Unknown OS: $OS_ID, assuming Debian-like" ; OS_FAMILY="debian"; PKG_MGR="apt" ;;
esac
else
err "Cannot detect OS"
fi
log "Detected: $NAME $VERSION_ID ($OS_FAMILY/$PKG_MGR)"
# Install dependencies
log "Installing dependencies..."
PYTHON_BIN="python3"
if [ "$PKG_MGR" = "apt" ]; then
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq || true
apt-get install -y python3 python3-pip python3-venv curl git wget unzip sudo
elif [ "$PKG_MGR" = "dnf" ]; then
dnf install -y python3 python3-pip curl git wget unzip sudo
# Enable EPEL for extra packages
if [[ "$OS_ID" =~ ^(rhel|almalinux|rocky|ol|centos|cloudlinux)$ ]]; then
dnf install -y epel-release 2>/dev/null || true
fi
# RHEL8-family ships Python 3.6 by default, which is too old for
# Flask 3.x / boto3 / flask-sock. Use python3.11 if available.
PYMAJOR=$(python3 -c 'import sys; print(sys.version_info[0])' 2>/dev/null || echo 0)
PYMINOR=$(python3 -c 'import sys; print(sys.version_info[1])' 2>/dev/null || echo 0)
if [ "$PYMAJOR" -lt 3 ] || { [ "$PYMAJOR" -eq 3 ] && [ "$PYMINOR" -lt 8 ]; }; then
warn "System python3 is $PYMAJOR.$PYMINOR (too old), installing python3.11"
dnf install -y python3.11 2>/dev/null || dnf install -y python3.11 python3.11-pip
fi
fi
# Use python3.11 for the venv if the system default is too old (RHEL8-family)
if command -v python3.11 &>/dev/null; then
V=$(python3 -c 'import sys; print(sys.version_info[1])' 2>/dev/null || echo 0)
if [ "$V" -lt 8 ] 2>/dev/null; then PYTHON_BIN="python3.11"; fi
fi
# Install VortexPanel
INSTALL_DIR="/opt/vortexpanel"
log "Installing VortexPanel to $INSTALL_DIR..."
mkdir -p "$INSTALL_DIR"
# Clone or copy — always end up with a PERMANENT, git-connected source at
# /root/Vortexpanel, never a /tmp path (which gets wiped on reboot and silently
# breaks future `git pull` + deploy.sh workflows with no way to trace it back).
SRC_DIR="/root/Vortexpanel"
if [ -d "$SRC_DIR/.git" ]; then
log "Using existing git checkout at $SRC_DIR"
elif [ -e "$SRC_DIR" ]; then
# Something is there but it's not a valid git repo (e.g. leftover files
# from a previous manual copy) — move it aside rather than fail or silently
# clone into a messy directory.
warn "$SRC_DIR exists but isn't a git repo — moving it to ${SRC_DIR}.bak"
mv "$SRC_DIR" "${SRC_DIR}.bak.$(date +%s)"
git clone https://github.com/BrowserlessAPI/VortexPanel.git "$SRC_DIR"
else
git clone https://github.com/BrowserlessAPI/VortexPanel.git "$SRC_DIR"
fi
cp -r "$SRC_DIR/panel" "$SRC_DIR/web" "$SRC_DIR/app.py" "$INSTALL_DIR/"
# Create virtualenv
log "Setting up Python environment..."
"$PYTHON_BIN" -m venv "$INSTALL_DIR/venv"
"$INSTALL_DIR/venv/bin/pip" install --upgrade pip -q
if [ -f "$SRC_DIR/requirements.txt" ]; then
"$INSTALL_DIR/venv/bin/pip" install -r "$SRC_DIR/requirements.txt" -q
else
"$INSTALL_DIR/venv/bin/pip" install flask flask-session flask-sock requests gunicorn boto3 -q
fi
# Create directories
mkdir -p /opt/vortexpanel/{backups,logs,sessions}
mkdir -p /var/log/vortexpanel
mkdir -p /etc/nginx/vortex 2>/dev/null || true
# Create credentials
if [ ! -f "$INSTALL_DIR/credentials.json" ]; then
PASS=$(openssl rand -base64 12)
HASH=$(python3 -c "import hashlib; print(hashlib.sha256('$PASS'.encode()).hexdigest())")
cat > "$INSTALL_DIR/credentials.json" << EOF
{
"username": "admin",
"password_hash": "$HASH",
"email": "admin@vortexpanel.local"
}
EOF
log "Generated admin password: $PASS"
echo "$PASS" > "$INSTALL_DIR/admin_password.txt"
fi
# Create systemd service
cat > /etc/systemd/system/vortexpanel.service << EOF
[Unit]
Description=VortexPanel Control Panel
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$INSTALL_DIR
ExecStart=$INSTALL_DIR/venv/bin/gunicorn --workers 4 --threads 4 --worker-class gthread --bind 0.0.0.0:8888 --timeout 120 --access-logfile /var/log/vortexpanel/access.log --error-logfile /var/log/vortexpanel/error.log app:app
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable vortexpanel
systemctl restart vortexpanel
# Generate deploy.sh — always points at the SAME $SRC_DIR resolved above,
# so it can never drift out of sync with wherever the source actually lives.
cat > /root/deploy.sh << EOF
#!/bin/bash
cp -r $SRC_DIR/panel/ $SRC_DIR/web/ $INSTALL_DIR/
cp $SRC_DIR/app.py $INSTALL_DIR/
find $INSTALL_DIR -name "__pycache__" -exec rm -rf {} + 2>/dev/null
systemctl restart vortexpanel && sleep 2
curl -s -o /dev/null -w "Panel: %{http_code}\n" http://127.0.0.1:8888/
echo "✓ Deployed"
EOF
chmod +x /root/deploy.sh
log "Created /root/deploy.sh (source: $SRC_DIR -> install: $INSTALL_DIR)"
# Firewall rules
if command -v ufw &>/dev/null; then
ufw allow 8888/tcp 2>/dev/null || true
elif command -v firewall-cmd &>/dev/null; then
firewall-cmd --permanent --add-port=8888/tcp 2>/dev/null || true
firewall-cmd --reload 2>/dev/null || true
fi
IP=$(curl -s https://api.ipify.org 2>/dev/null || hostname -I | awk '{print $1}')
log "============================================"
log "VortexPanel installed successfully!"
log "URL: http://$IP:8888"
log "Username: admin"
log "Password: $(cat $INSTALL_DIR/admin_password.txt 2>/dev/null || echo 'See credentials.json')"
log "============================================"