feat(ufw): auto-open firewall ports after app installation
- cloudpanel: allow ftp, smtp, dns, http, https, smtps, imaps, pop3s, and admin panel ports - coolify: allow http, https, and dashboard port after install - pterodactyl: allow http, https, wings daemon (8080), and sftp (2022) ports - uptime-kuma: allow app port on install - proxmox: add open_firewall_ports() with ufw guard checks and new menu option [9]
This commit is contained in:
@@ -284,6 +284,19 @@ install_cloudpanel() {
|
|||||||
|
|
||||||
echo -e "${GREEN}[✓] Installation completed${NC}"
|
echo -e "${GREEN}[✓] Installation completed${NC}"
|
||||||
|
|
||||||
|
ufw_allow 20/tcp "CloudPanel FTP data"
|
||||||
|
ufw_allow 21/tcp "CloudPanel FTP"
|
||||||
|
ufw_allow 25/tcp "CloudPanel SMTP"
|
||||||
|
ufw_allow 53/tcp "CloudPanel DNS (TCP)"
|
||||||
|
ufw_allow 53/udp "CloudPanel DNS (UDP)"
|
||||||
|
ufw_allow 80/tcp "CloudPanel HTTP"
|
||||||
|
ufw_allow 443/tcp "CloudPanel HTTPS"
|
||||||
|
ufw_allow 465/tcp "CloudPanel SMTPS"
|
||||||
|
ufw_allow 587/tcp "CloudPanel submission"
|
||||||
|
ufw_allow 993/tcp "CloudPanel IMAPS"
|
||||||
|
ufw_allow 995/tcp "CloudPanel POP3S"
|
||||||
|
ufw_allow "${PANEL_PORT}/tcp" "CloudPanel admin"
|
||||||
|
|
||||||
# Configure Basic Auth
|
# Configure Basic Auth
|
||||||
configure_cloudpanel_basic_auth
|
configure_cloudpanel_basic_auth
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,10 @@ install_coolify() {
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
|
ufw_allow 80/tcp "Coolify HTTP"
|
||||||
|
ufw_allow 443/tcp "Coolify HTTPS"
|
||||||
|
ufw_allow "${PORT}/tcp" "Coolify dashboard"
|
||||||
|
|
||||||
local duration=$(( $(date +%s) - start_time ))
|
local duration=$(( $(date +%s) - start_time ))
|
||||||
local minutes=$((duration / 60))
|
local minutes=$((duration / 60))
|
||||||
local seconds=$((duration % 60))
|
local seconds=$((duration % 60))
|
||||||
|
|||||||
+31
-1
@@ -306,6 +306,34 @@ show_network_info() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
# Firewall
|
||||||
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
open_firewall_ports() {
|
||||||
|
echo -e "${WHITE}${BOLD}OPEN PROXMOX FIREWALL PORTS${NC}\n"
|
||||||
|
|
||||||
|
check_proxmox || return 1
|
||||||
|
|
||||||
|
if ! command -v ufw >/dev/null 2>&1; then
|
||||||
|
echo -e "${YELLOW}[!] UFW is not installed on this host. Nothing to do.${NC}"
|
||||||
|
echo -e "${GRAY} Proxmox uses its own pve-firewall; UFW is optional.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if ! ufw status 2>/dev/null | grep -q "Status: active"; then
|
||||||
|
echo -e "${YELLOW}[!] UFW is installed but inactive. Enable it first.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ufw_allow "${PANEL_PORT}/tcp" "Proxmox web UI"
|
||||||
|
ufw_allow 5900:5999/tcp "Proxmox VNC console"
|
||||||
|
ufw_allow 3128/tcp "Proxmox SPICE proxy"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${GRAY}[i] For clustered nodes, also open: 5404-5405/udp (corosync), 60000-60050/tcp (live migration).${NC}"
|
||||||
|
echo -e "${GRAY}[i] If using NFS storage: 111/tcp+udp and 2049/tcp.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
# Main Menu
|
# Main Menu
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
@@ -321,9 +349,10 @@ show_menu() {
|
|||||||
echo -e " ${CYAN}[6]${NC} View Network Info"
|
echo -e " ${CYAN}[6]${NC} View Network Info"
|
||||||
echo -e " ${PURPLE}[7]${NC} Update Proxmox VE"
|
echo -e " ${PURPLE}[7]${NC} Update Proxmox VE"
|
||||||
echo -e " ${PURPLE}[8]${NC} Clear Cache"
|
echo -e " ${PURPLE}[8]${NC} Clear Cache"
|
||||||
|
echo -e " ${PURPLE}[9]${NC} Open Firewall Ports (UFW)"
|
||||||
echo -e " ${RED}[0]${NC} Back to main menu"
|
echo -e " ${RED}[0]${NC} Back to main menu"
|
||||||
echo ""
|
echo ""
|
||||||
echo -n "Choice [0-8]: "
|
echo -n "Choice [0-9]: "
|
||||||
}
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
@@ -341,6 +370,7 @@ main() {
|
|||||||
6) show_network_info ;;
|
6) show_network_info ;;
|
||||||
7) update_proxmox ;;
|
7) update_proxmox ;;
|
||||||
8) clear_cache ;;
|
8) clear_cache ;;
|
||||||
|
9) open_firewall_ports ;;
|
||||||
0) return 0 ;;
|
0) return 0 ;;
|
||||||
*) echo -e "${RED}Invalid option${NC}" ;;
|
*) echo -e "${RED}Invalid option${NC}" ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@@ -264,6 +264,11 @@ install_pterodactyl() {
|
|||||||
|
|
||||||
[ -s /etc/pterodactyl/config.yml ] && systemctl enable --now wings
|
[ -s /etc/pterodactyl/config.yml ] && systemctl enable --now wings
|
||||||
|
|
||||||
|
ufw_allow 80/tcp "Pterodactyl HTTP"
|
||||||
|
ufw_allow 443/tcp "Pterodactyl HTTPS"
|
||||||
|
ufw_allow 8080/tcp "Pterodactyl Wings daemon"
|
||||||
|
ufw_allow 2022/tcp "Pterodactyl Wings SFTP"
|
||||||
|
|
||||||
local duration=$(( $(date +%s) - start_time ))
|
local duration=$(( $(date +%s) - start_time ))
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
+7
-1
@@ -138,6 +138,8 @@ EOF
|
|||||||
echo -e "${CYAN}Access URL: ${BOLD}http://$server_ip:$PORT${NC}"
|
echo -e "${CYAN}Access URL: ${BOLD}http://$server_ip:$PORT${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
ufw_allow "${PORT}/tcp" "Uptime Kuma"
|
||||||
|
|
||||||
# Optional domain configuration
|
# Optional domain configuration
|
||||||
echo -e "${WHITE}Configure domain with SSL? (y/n)${NC}"
|
echo -e "${WHITE}Configure domain with SSL? (y/n)${NC}"
|
||||||
read -n 1 -r
|
read -n 1 -r
|
||||||
@@ -148,7 +150,11 @@ EOF
|
|||||||
read -p "Email for SSL: " EMAIL
|
read -p "Email for SSL: " EMAIL
|
||||||
echo ""
|
echo ""
|
||||||
configure_domain_ssl "$DOMAIN_NAME" "$EMAIL"
|
configure_domain_ssl "$DOMAIN_NAME" "$EMAIL"
|
||||||
[ $? -eq 0 ] && echo -e "${GREEN}[✓] Domain configured: ${BOLD}https://$DOMAIN_NAME${NC}"
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}[✓] Domain configured: ${BOLD}https://$DOMAIN_NAME${NC}"
|
||||||
|
ufw_allow 80/tcp "Uptime Kuma HTTP (nginx)"
|
||||||
|
ufw_allow 443/tcp "Uptime Kuma HTTPS (nginx)"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -122,6 +122,25 @@ apt_noninteractive() {
|
|||||||
echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections 2>/dev/null || true
|
echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add a UFW allow rule, but only if UFW is installed AND active. No-op
|
||||||
|
# otherwise — so app installers can declare the ports they need without
|
||||||
|
# forcing UFW on hosts that don't use it.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ufw_allow 8000/tcp "Coolify dashboard"
|
||||||
|
# ufw_allow 80/tcp
|
||||||
|
ufw_allow() {
|
||||||
|
command -v ufw >/dev/null 2>&1 || return 0
|
||||||
|
ufw status 2>/dev/null | grep -q "Status: active" || return 0
|
||||||
|
local rule=$1 comment=${2:-}
|
||||||
|
if [ -n "$comment" ]; then
|
||||||
|
ufw allow "$rule" comment "$comment" >/dev/null
|
||||||
|
else
|
||||||
|
ufw allow "$rule" >/dev/null
|
||||||
|
fi
|
||||||
|
ok "UFW: allowed ${rule}${comment:+ (${comment})}"
|
||||||
|
}
|
||||||
|
|
||||||
# Wait for other apt/dpkg processes to release their locks. Up to 120s.
|
# Wait for other apt/dpkg processes to release their locks. Up to 120s.
|
||||||
wait_for_apt() {
|
wait_for_apt() {
|
||||||
command -v apt >/dev/null 2>&1 || return 0
|
command -v apt >/dev/null 2>&1 || return 0
|
||||||
|
|||||||
@@ -425,8 +425,6 @@ main_menu() {
|
|||||||
echo ""
|
echo ""
|
||||||
echo -e " ${GREEN}[1]${NC} Applications"
|
echo -e " ${GREEN}[1]${NC} Applications"
|
||||||
echo -e " ${CYAN}[2]${NC} System Tools"
|
echo -e " ${CYAN}[2]${NC} System Tools"
|
||||||
echo -e " ${PURPLE}[3]${NC} Server Benchmark"
|
|
||||||
echo -e " ${YELLOW}[4]${NC} Harden Server"
|
|
||||||
echo -e " ${GRAY}[u]${NC} Update lxs"
|
echo -e " ${GRAY}[u]${NC} Update lxs"
|
||||||
echo -e " ${RED}[0]${NC} Exit"
|
echo -e " ${RED}[0]${NC} Exit"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -436,8 +434,6 @@ main_menu() {
|
|||||||
case $choice in
|
case $choice in
|
||||||
1) menu_install_apps ;;
|
1) menu_install_apps ;;
|
||||||
2) download_and_run "tools/system-tools.sh" ;;
|
2) download_and_run "tools/system-tools.sh" ;;
|
||||||
3) download_and_run "tools/server-benchmark.sh" ;;
|
|
||||||
4) download_and_run "tools/harden.sh" ;;
|
|
||||||
u|U) cmd_update ;;
|
u|U) cmd_update ;;
|
||||||
0)
|
0)
|
||||||
clear
|
clear
|
||||||
|
|||||||
+48
-2
@@ -12,6 +12,44 @@ eval "$_lib"
|
|||||||
unset _lib
|
unset _lib
|
||||||
export LXS_LOG_FILE="/tmp/lxs_system_tools.log"
|
export LXS_LOG_FILE="/tmp/lxs_system_tools.log"
|
||||||
|
|
||||||
|
# Run a sibling tool script. Prefers a file next to this script (installed
|
||||||
|
# layout); falls back to downloading from LXS_RAW_BASE.
|
||||||
|
run_sibling() {
|
||||||
|
local script_path=$1
|
||||||
|
shift
|
||||||
|
local script_name self_dir resolved src="${BASH_SOURCE[0]}"
|
||||||
|
script_name=$(basename "$script_path")
|
||||||
|
|
||||||
|
if [ -n "$src" ]; then
|
||||||
|
resolved=$(readlink -f "$src" 2>/dev/null) \
|
||||||
|
|| resolved=$(realpath "$src" 2>/dev/null) \
|
||||||
|
|| resolved="$src"
|
||||||
|
self_dir=$(dirname "$resolved")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$self_dir" ] && [ -f "${self_dir}/${script_name}" ]; then
|
||||||
|
chmod +x "${self_dir}/${script_name}" 2>/dev/null || true
|
||||||
|
"${self_dir}/${script_name}" "$@"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
local temp_file exit_code
|
||||||
|
temp_file=$(mktemp "/tmp/lxs.${script_name%.*}.XXXXXX.sh")
|
||||||
|
echo -e "${PURPLE}[*] Downloading ${BOLD}${script_name}${NC}${PURPLE}...${NC}"
|
||||||
|
if curl -fsSL -H "Cache-Control: no-cache" -o "${temp_file}" "${LXS_RAW_BASE}/${script_path}"; then
|
||||||
|
echo -e "${GREEN}[✓] Downloaded${NC}"
|
||||||
|
chmod +x "${temp_file}"
|
||||||
|
"${temp_file}" "$@"
|
||||||
|
exit_code=$?
|
||||||
|
rm -f "${temp_file}"
|
||||||
|
return $exit_code
|
||||||
|
else
|
||||||
|
echo -e "${RED}[✗] Failed to download ${script_path}${NC}"
|
||||||
|
rm -f "${temp_file}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Menu: System Tools
|
# Menu: System Tools
|
||||||
menu_system_tools() {
|
menu_system_tools() {
|
||||||
while true; do
|
while true; do
|
||||||
@@ -28,9 +66,11 @@ menu_system_tools() {
|
|||||||
echo -e " ${CYAN}[6]${NC} View system logs (last 50 lines)"
|
echo -e " ${CYAN}[6]${NC} View system logs (last 50 lines)"
|
||||||
echo -e " ${CYAN}[7]${NC} Show top resource-consuming processes"
|
echo -e " ${CYAN}[7]${NC} Show top resource-consuming processes"
|
||||||
echo -e " ${CYAN}[8]${NC} Check disk health (SMART)"
|
echo -e " ${CYAN}[8]${NC} Check disk health (SMART)"
|
||||||
|
echo -e " ${PURPLE}[9]${NC} Server Benchmark"
|
||||||
|
echo -e " ${YELLOW}[10]${NC} Harden Server"
|
||||||
echo -e " ${RED}[0]${NC} Exit"
|
echo -e " ${RED}[0]${NC} Exit"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e -n "${BOLD}Choice [0-8]: ${NC}"
|
echo -e -n "${BOLD}Choice [0-10]: ${NC}"
|
||||||
read -r choice
|
read -r choice
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
@@ -266,11 +306,17 @@ menu_system_tools() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
9)
|
||||||
|
run_sibling "tools/server-benchmark.sh"
|
||||||
|
;;
|
||||||
|
10)
|
||||||
|
run_sibling "tools/harden.sh"
|
||||||
|
;;
|
||||||
0)
|
0)
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo -e "${RED}[✗] Invalid option. Please select 0-8.${NC}"
|
echo -e "${RED}[✗] Invalid option. Please select 0-10.${NC}"
|
||||||
sleep 2
|
sleep 2
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
|
|||||||
Reference in New Issue
Block a user