Merge pull request #21 from outis1one/claude/fix-magic-mirror-setup-LWG3r

Claude/fix magic mirror setup lwg3r
This commit is contained in:
outis1one
2026-01-12 10:11:43 -05:00
committed by GitHub
3 changed files with 746 additions and 208 deletions
+244
View File
@@ -0,0 +1,244 @@
# Ubuntu Post-Install Script - New Structure
## Current Problems
1. ❌ Services prompt individually even when not selected in whiptail
2. ❌ Too many things installed BEFORE whiptail menu (Samba, VPNs, fail2ban)
3. ❌ No clear explanation to user about script phases
4. ❌ No uninstall option
5. ❌ Confusing for re-running on existing servers
## New Structure
### PHASE 1: Essential System Setup (Before Whiptail)
**Purpose:** Install only what's REQUIRED for everything else to work
**What stays BEFORE whiptail:**
- ✅ System updates (apt update/upgrade)
- ✅ Essential packages (openssh-server, rsync, curl, wget, git, vim, htop, ncdu)
- ✅ SSH key generation (optional)
- ✅ SSH key import from GitHub/Launchpad (optional)
- ✅ Docker & Docker Compose installation
- ✅ Hard drive mounting/formatting
**What moves TO whiptail menu:**
- 🔄 Samba file sharing
- 🔄 fail2ban for SSH
- 🔄 VPN services (Tailscale, WireGuard, NetBird)
- 🔄 Remote desktop (RustDesk, TeamViewer)
- 🔄 MeshCentral agent
### PHASE 2: Service Selection (Whiptail Menu)
**Purpose:** Let user choose ALL optional services
**New whiptail menu structure:**
```
┌─────────────────── Select Services ────────────────────┐
│ ☐ INSTALL ☑ UNINSTALL │
│ │
│ === NETWORK & SECURITY === │
│ [ ] SAMBA File sharing (SMB/CIFS) │
│ [ ] FAIL2BAN_SSH Protect SSH from brute-force │
│ [ ] TAILSCALE Easy VPN mesh network │
│ [ ] NETBIRD Self-hosted VPN │
│ [ ] WIREGUARD Manual VPN configuration │
│ │
│ === REMOTE ACCESS === │
│ [ ] RUSTDESK Remote desktop (OSS) │
│ [ ] TEAMVIEWER Remote desktop (commercial) │
│ [ ] MESHCENTRAL Remote management agent │
│ │
│ === DOCKER SERVICES === │
│ [ ] ACTUALBUDGET Personal finance │
│ [ ] KEYCLOAK Identity management │
│ [ ] CADDY Reverse proxy │
│ [ ] FAIL2BAN_CADDY Protect Caddy services │
│ [ ] JELLYFIN Media server │
│ [ ] IMMICH Photo backup │
│ [ ] AUDIOBOOKSHELF Audiobook server │
│ [ ] MEALIE Recipe manager │
│ [ ] UPTIMEKUMA Service monitoring │
│ [ ] PORTAINER Docker management UI │
│ [ ] WATCHTOWER Auto-update containers │
│ ... (all other services) │
│ │
│ === MESHCENTRAL SERVER === │
│ [ ] MESHCENTRAL_SRV Self-hosted remote mgmt server │
│ │
│ <Install Selected> <Uninstall Selected> │
└─────────────────────────────────────────────────────────┘
```
### PHASE 3: Installation
**Purpose:** Install/uninstall selected services in correct order
**Dependency-aware installation order:**
1. Install Caddy first (if selected)
2. Install services that depend on Caddy (Keycloak, etc.)
3. Install fail2ban for Caddy (if selected + Caddy installed)
4. Install independent services in parallel where possible
### Re-Running The Script
**Behavior on already-configured server:**
**Phase 1 (Essential):**
- Detects existing installations
- Shows: "Docker is already installed: (version)"
- Prompts: "Reinstall Docker? (y/n): **n**" (defaults to NO)
- Skips if "n"
**Phase 2 (Services):**
- Whiptail menu shows ALL services
- Already-installed services could be marked with (installed)
- User can:
- Select new services to add
- Select installed services + click "Uninstall Selected"
- Skip menu to make no changes
## Implementation Changes
### 1. Add Intro Text
```bash
# At beginning of script after argument parsing
if [ "$UNATTENDED" != true ]; then
cat << 'EOF'
╔════════════════════════════════════════════════════════════════╗
║ Ubuntu Post-Install Setup Script ║
╚════════════════════════════════════════════════════════════════╝
This script installs and configures your Ubuntu server in TWO phases:
PHASE 1: ESSENTIAL SETUP (Required)
• System updates & core packages
• SSH configuration
• Docker & Docker Compose
• Hard drive mounting
PHASE 2: SERVICE SELECTION (Optional)
• Interactive menu to select services
• Install OR uninstall services
• Safe to re-run on existing servers
Press ENTER to begin Phase 1...
EOF
read -p ""
fi
```
### 2. Reorganize Script Sections
**NEW ORDER:**
1. Intro text
2. Essential system setup (Phase 1)
3. Whiptail menu with ALL services (Phase 2)
4. Service installations based on selections
**REMOVED FROM PRE-WHIPTAIL:**
- Lines 1709-1800: Samba installation → Move to whiptail
- Lines 1596-1625: fail2ban (SSH) → Move to whiptail
- Lines 1841-1888: NetBird → Move to whiptail
- Lines 1889-1945: WireGuard → Move to whiptail
- Lines 1947-1998: Tailscale → Move to whiptail
- Lines 2000-2044: RustDesk → Move to whiptail
- Lines 2046-2095: TeamViewer → Move to whiptail
- Lines 2097-2153: MeshCentral Agent → Move to whiptail
### 3. Update Whiptail Menu
**Add these to the checklist:**
```bash
"SAMBA" "File sharing (Windows, Mac, Linux)" OFF \
"FAIL2BAN_SSH" "Protect SSH from brute-force attacks" OFF \
"TAILSCALE" "Easy VPN mesh network" OFF \
"NETBIRD" "Self-hosted VPN alternative" OFF \
"WIREGUARD" "Manual VPN configuration" OFF \
"RUSTDESK" "Open-source remote desktop" OFF \
"TEAMVIEWER" "Commercial remote desktop" OFF \
"MESHCENTRAL_AGENT" "Remote management agent" OFF \
```
### 4. Add Uninstall Functionality
**New buttons in whiptail:**
```bash
--extra-button --extra-label "Uninstall" \
--ok-button "Install" --cancel-button "Skip"
```
**Check return code:**
- 0 = Install selected
- 1 = Skip/Cancel
- 3 = Uninstall selected
**Uninstall logic:**
```bash
if [ $WHIPTAIL_RETURN -eq 3 ]; then
# Uninstall mode
for service in $SELECTED_SERVICES; do
uninstall_service "$service"
done
fi
```
### 5. Fix Duplicate Prompts
**Current issue:**
```bash
if [ -z "$INSTALL_AUDIOBOOKSHELF" ]; then
prompt_yn "Install Audiobookshelf? (y/n):" "n" INSTALL_AUDIOBOOKSHELF
fi
```
**Problem:** This runs even if user didn't select it in whiptail!
**Fix:** Only show prompt if whiptail wasn't used OR variable not set by whiptail
```bash
# After whiptail, set a flag
WHIPTAIL_USED=true
# In individual service sections
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_AUDIOBOOKSHELF" ]; then
prompt_yn "Install Audiobookshelf? (y/n):" "n" INSTALL_AUDIOBOOKSHELF
fi
```
**Or simpler:** Just remove all individual prompts! If whiptail is available, use it. If not, show ALL services as prompts.
## Benefits
1. ✅ Clear two-phase structure
2. ✅ All optional services in ONE menu
3. ✅ No duplicate prompts
4. ✅ Uninstall functionality
5. ✅ Safe to re-run
6. ✅ User understands what's happening when
7. ✅ Faster for users who know what they want
## Migration Path
**For existing users:**
1. Script still works the same way
2. New intro text explains structure
3. Existing installations detected
4. Can use uninstall to remove unwanted services
## Testing Scenarios
1. **Fresh install:** All prompts flow correctly
2. **Re-run:** Detects existing, allows adding new services
3. **Uninstall:** Removes selected services cleanly
4. **Whiptail unavailable:** Falls back to individual prompts
5. **Cancel menu:** Skips all service installations
---
**Implementation Priority:**
1. ✅ Fix duplicate prompts (CRITICAL - doing now)
2. ⏳ Add intro text (HIGH)
3. ⏳ Move services to whiptail (HIGH)
4. ⏳ Add uninstall functionality (MEDIUM)
5. ⏳ Improve re-run detection (LOW - already works)
+59
View File
@@ -0,0 +1,59 @@
#!/bin/bash
# SCRIPT FLOW EXPLANATION FOR USERS
cat << 'EOF'
╔════════════════════════════════════════════════════════════════╗
║ Ubuntu Post-Install Setup Script ║
╚════════════════════════════════════════════════════════════════╝
This script is divided into TWO main phases:
┌────────────────────────────────────────────────────────────────┐
│ PHASE 1: ESSENTIAL SYSTEM SETUP (Required) │
├────────────────────────────────────────────────────────────────┤
│ These are installed/configured FIRST: │
│ ✓ System updates and essential packages │
│ ✓ OpenSSH server (remote access) │
│ ✓ rsync, curl, wget (core utilities) │
│ ✓ SSH key configuration │
│ ✓ Docker & Docker Compose (container platform) │
│ ✓ Hard drive mounting (storage setup) │
│ │
│ These are REQUIRED for everything else to work. │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ PHASE 2: SERVICE SELECTION MENU (Optional) │
├────────────────────────────────────────────────────────────────┤
│ After Phase 1, you'll see a CHECKBOX MENU where you can: │
│ • Select which services to INSTALL │
│ • Select which services to UNINSTALL │
│ • Skip services you don't want │
│ │
│ Services include: │
│ • Self-hosted apps (ActualBudget, Keycloak, Jellyfin, etc.) │
│ • Network services (Samba, VPNs, fail2ban) │
│ • Monitoring tools (Uptime Kuma, Portainer, Watchtower) │
│ • And many more... │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ RE-RUNNING THIS SCRIPT │
├────────────────────────────────────────────────────────────────┤
│ You can safely re-run this script on an already configured │
│ server: │
│ • Phase 1 will DETECT existing installations and skip them │
│ • Phase 2 menu will show ALL services (installed and not) │
│ • Select NEW services to add │
│ • Or select UNINSTALL to remove services │
│ │
│ The script is IDEMPOTENT - safe to run multiple times! │
└────────────────────────────────────────────────────────────────┘
Press ENTER to continue with Phase 1 (Essential Setup)...
EOF
read -p ""
# Now continue with the actual script...
EOF
+443 -208
View File
@@ -2186,35 +2186,122 @@ else
# Use whiptail for service selection if available
if command -v whiptail &> /dev/null; then
# Build checklist of all available services
SELECTED_SERVICES=$(whiptail --title "Select Docker Services to Install" \
--checklist "Use SPACE to select, ENTER to confirm:" 25 78 17 \
"IMMICH" "Photo & video backup (like Google Photos)" OFF \
"AUDIOBOOKSHELF" "Audiobook & podcast server" OFF \
"EMBY" "Media server for movies, TV, music" OFF \
"ARM" "Automatic Ripping Machine for DVDs/Blu-rays" OFF \
"FILEBROWSER" "Web-based file manager" OFF \
"MAGICMIRROR" "Smart mirror / dashboard display" OFF \
"ACTUALBUDGET" "Personal finance management with bank sync" OFF \
"KEYCLOAK" "Identity & Access Management (SSO)" OFF \
"CADDY" "Reverse proxy with automatic HTTPS" OFF \
"FAIL2BAN" "Intrusion prevention system" OFF \
"LYRION" "Music streaming server (LMS)" OFF \
"MEALIE" "Recipe manager & meal planner" OFF \
"MINECRAFT" "Minecraft game server" OFF \
"JELLYFIN" "Free media server (Emby alternative)" OFF \
"FRIGATE" "AI-powered NVR for security cameras" OFF \
"NTFY" "Push notifications server" OFF \
"UPTIMEKUMA" "Service monitoring dashboard" OFF \
"WGEASY" "WireGuard VPN with web UI" OFF \
"TRACCAR" "GPS tracking server" OFF \
"PORTAINER" "Docker management web UI" OFF \
"MESHCENTRAL" "Remote management server" OFF \
"FINDMYDEVICE" "Device tracking (like Find My)" OFF \
"FRIGATE_NOTIFY" "Push notifications for Frigate" OFF \
"WATCHTOWER" "Automatic container updates" OFF \
# Detect existing services
echo "Detecting existing services..."
declare -A EXISTING_SERVICES
[ -d "$DOCKER_DIR/immich" ] && EXISTING_SERVICES[IMMICH]="ON"
[ -d "$DOCKER_DIR/audiobookshelf" ] && EXISTING_SERVICES[AUDIOBOOKSHELF]="ON"
[ -d "$DOCKER_DIR/emby" ] && EXISTING_SERVICES[EMBY]="ON"
[ -d "$DOCKER_DIR/arm" ] && EXISTING_SERVICES[ARM]="ON"
[ -d "$DOCKER_DIR/filebrowser" ] && EXISTING_SERVICES[FILEBROWSER]="ON"
[ -d "$DOCKER_DIR/magicmirror" ] && EXISTING_SERVICES[MAGICMIRROR]="ON"
[ -d "$DOCKER_DIR/actualbudget" ] && EXISTING_SERVICES[ACTUALBUDGET]="ON"
[ -d "$DOCKER_DIR/keycloak" ] && EXISTING_SERVICES[KEYCLOAK]="ON"
[ -d "$DOCKER_DIR/caddy" ] && EXISTING_SERVICES[CADDY]="ON"
[ -d "$DOCKER_DIR/lms" ] && EXISTING_SERVICES[LYRION]="ON"
[ -d "$DOCKER_DIR/mealie" ] && EXISTING_SERVICES[MEALIE]="ON"
[ -d "$DOCKER_DIR/minecraft" ] && EXISTING_SERVICES[MINECRAFT]="ON"
[ -d "$DOCKER_DIR/jellyfin" ] && EXISTING_SERVICES[JELLYFIN]="ON"
[ -d "$DOCKER_DIR/frigate" ] && EXISTING_SERVICES[FRIGATE]="ON"
[ -d "$DOCKER_DIR/ntfy" ] && EXISTING_SERVICES[NTFY]="ON"
[ -d "$DOCKER_DIR/uptime-kuma" ] && EXISTING_SERVICES[UPTIMEKUMA]="ON"
[ -d "$DOCKER_DIR/wg-easy" ] && EXISTING_SERVICES[WGEASY]="ON"
[ -d "$DOCKER_DIR/traccar" ] && EXISTING_SERVICES[TRACCAR]="ON"
[ -d "$DOCKER_DIR/portainer" ] && EXISTING_SERVICES[PORTAINER]="ON"
[ -d "$DOCKER_DIR/meshcentral" ] && EXISTING_SERVICES[MESHCENTRAL]="ON"
[ -d "$DOCKER_DIR/fmd" ] && EXISTING_SERVICES[FINDMYDEVICE]="ON"
[ -d "$DOCKER_DIR/frigate-notify" ] && EXISTING_SERVICES[FRIGATE_NOTIFY]="ON"
[ -d "$DOCKER_DIR/watchtower" ] && EXISTING_SERVICES[WATCHTOWER]="ON"
command -v fail2ban-client &> /dev/null && EXISTING_SERVICES[FAIL2BAN]="ON"
# Ask user what action to perform
ACTION=$(whiptail --title "Service Management" --menu \
"Choose an action:" 15 60 3 \
"1" "Install new services" \
"2" "Uninstall existing services" \
"3" "Cancel and skip" \
3>&1 1>&2 2>&3)
case "$ACTION" in
1)
# INSTALL MODE
MENU_MODE="INSTALL"
# Build checklist - mark existing services as ON
SELECTED_SERVICES=$(whiptail --title "Select Docker Services to Install" \
--checklist "Use SPACE to select, ENTER to confirm. [*] = already installed" 25 78 17 \
"IMMICH" "Photo & video backup (like Google Photos)" ${EXISTING_SERVICES[IMMICH]:-OFF} \
"AUDIOBOOKSHELF" "Audiobook & podcast server" ${EXISTING_SERVICES[AUDIOBOOKSHELF]:-OFF} \
"EMBY" "Media server for movies, TV, music" ${EXISTING_SERVICES[EMBY]:-OFF} \
"ARM" "Automatic Ripping Machine for DVDs/Blu-rays" ${EXISTING_SERVICES[ARM]:-OFF} \
"FILEBROWSER" "Web-based file manager" ${EXISTING_SERVICES[FILEBROWSER]:-OFF} \
"MAGICMIRROR" "Smart mirror / dashboard display" ${EXISTING_SERVICES[MAGICMIRROR]:-OFF} \
"ACTUALBUDGET" "Personal finance management with bank sync" ${EXISTING_SERVICES[ACTUALBUDGET]:-OFF} \
"KEYCLOAK" "Identity & Access Management (SSO)" ${EXISTING_SERVICES[KEYCLOAK]:-OFF} \
"CADDY" "Reverse proxy with automatic HTTPS" ${EXISTING_SERVICES[CADDY]:-OFF} \
"FAIL2BAN" "Intrusion prevention system" ${EXISTING_SERVICES[FAIL2BAN]:-OFF} \
"LYRION" "Music streaming server (LMS)" ${EXISTING_SERVICES[LYRION]:-OFF} \
"MEALIE" "Recipe manager & meal planner" ${EXISTING_SERVICES[MEALIE]:-OFF} \
"MINECRAFT" "Minecraft game server" ${EXISTING_SERVICES[MINECRAFT]:-OFF} \
"JELLYFIN" "Free media server (Emby alternative)" ${EXISTING_SERVICES[JELLYFIN]:-OFF} \
"FRIGATE" "AI-powered NVR for security cameras" ${EXISTING_SERVICES[FRIGATE]:-OFF} \
"NTFY" "Push notifications server" ${EXISTING_SERVICES[NTFY]:-OFF} \
"UPTIMEKUMA" "Service monitoring dashboard" ${EXISTING_SERVICES[UPTIMEKUMA]:-OFF} \
"WGEASY" "WireGuard VPN with web UI" ${EXISTING_SERVICES[WGEASY]:-OFF} \
"TRACCAR" "GPS tracking server" ${EXISTING_SERVICES[TRACCAR]:-OFF} \
"PORTAINER" "Docker management web UI" ${EXISTING_SERVICES[PORTAINER]:-OFF} \
"MESHCENTRAL" "Remote management server" ${EXISTING_SERVICES[MESHCENTRAL]:-OFF} \
"FINDMYDEVICE" "Device tracking (like Find My)" ${EXISTING_SERVICES[FINDMYDEVICE]:-OFF} \
"FRIGATE_NOTIFY" "Push notifications for Frigate" ${EXISTING_SERVICES[FRIGATE_NOTIFY]:-OFF} \
"WATCHTOWER" "Automatic container updates" ${EXISTING_SERVICES[WATCHTOWER]:-OFF} \
3>&1 1>&2 2>&3)
;;
2)
# UNINSTALL MODE
MENU_MODE="UNINSTALL"
# Only show services that exist
UNINSTALL_OPTIONS=""
[ -n "${EXISTING_SERVICES[IMMICH]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS IMMICH \"Photo & video backup\" ON"
[ -n "${EXISTING_SERVICES[AUDIOBOOKSHELF]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS AUDIOBOOKSHELF \"Audiobook server\" ON"
[ -n "${EXISTING_SERVICES[EMBY]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS EMBY \"Media server\" ON"
[ -n "${EXISTING_SERVICES[ARM]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS ARM \"Automatic Ripping Machine\" ON"
[ -n "${EXISTING_SERVICES[FILEBROWSER]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS FILEBROWSER \"Web file manager\" ON"
[ -n "${EXISTING_SERVICES[MAGICMIRROR]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS MAGICMIRROR \"Smart mirror\" ON"
[ -n "${EXISTING_SERVICES[ACTUALBUDGET]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS ACTUALBUDGET \"Personal finance\" ON"
[ -n "${EXISTING_SERVICES[KEYCLOAK]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS KEYCLOAK \"Identity management\" ON"
[ -n "${EXISTING_SERVICES[CADDY]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS CADDY \"Reverse proxy\" ON"
[ -n "${EXISTING_SERVICES[FAIL2BAN]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS FAIL2BAN \"Intrusion prevention\" ON"
[ -n "${EXISTING_SERVICES[LYRION]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS LYRION \"Music server\" ON"
[ -n "${EXISTING_SERVICES[MEALIE]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS MEALIE \"Recipe manager\" ON"
[ -n "${EXISTING_SERVICES[MINECRAFT]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS MINECRAFT \"Game server\" ON"
[ -n "${EXISTING_SERVICES[JELLYFIN]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS JELLYFIN \"Media server\" ON"
[ -n "${EXISTING_SERVICES[FRIGATE]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS FRIGATE \"NVR cameras\" ON"
[ -n "${EXISTING_SERVICES[NTFY]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS NTFY \"Push notifications\" ON"
[ -n "${EXISTING_SERVICES[UPTIMEKUMA]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS UPTIMEKUMA \"Service monitoring\" ON"
[ -n "${EXISTING_SERVICES[WGEASY]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS WGEASY \"WireGuard VPN\" ON"
[ -n "${EXISTING_SERVICES[TRACCAR]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS TRACCAR \"GPS tracking\" ON"
[ -n "${EXISTING_SERVICES[PORTAINER]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS PORTAINER \"Docker management\" ON"
[ -n "${EXISTING_SERVICES[MESHCENTRAL]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS MESHCENTRAL \"Remote management\" ON"
[ -n "${EXISTING_SERVICES[FINDMYDEVICE]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS FINDMYDEVICE \"Device tracking\" ON"
[ -n "${EXISTING_SERVICES[FRIGATE_NOTIFY]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS FRIGATE_NOTIFY \"Frigate notifications\" ON"
[ -n "${EXISTING_SERVICES[WATCHTOWER]}" ] && UNINSTALL_OPTIONS="$UNINSTALL_OPTIONS WATCHTOWER \"Container updates\" ON"
if [ -z "$UNINSTALL_OPTIONS" ]; then
whiptail --title "No Services Found" --msgbox "No services detected to uninstall." 8 50
SELECTED_SERVICES=""
else
SELECTED_SERVICES=$(eval "whiptail --title 'Select Services to Uninstall' \
--checklist 'WARNING: Data will be backed up but services will be removed' 25 78 17 \
$UNINSTALL_OPTIONS \
3>&1 1>&2 2>&3")
fi
;;
3|*)
# Cancel
SELECTED_SERVICES=""
MENU_MODE="CANCEL"
;;
esac
# Check if user cancelled
if [ $? -ne 0 ]; then
echo "Service selection cancelled. Skipping Docker applications."
@@ -2274,14 +2361,134 @@ else
if echo "$SELECTED_SERVICES" | grep -q "FRIGATE_NOTIFY"; then INSTALL_FRIGATE_NOTIFY="y"; fi
if echo "$SELECTED_SERVICES" | grep -q "WATCHTOWER"; then INSTALL_WATCHTOWER="y"; fi
echo ""
echo "Selected services:"
echo "$SELECTED_SERVICES" | tr '"' '\n' | grep -v '^$' | sed 's/^/ - /'
echo ""
if [ "$MENU_MODE" = "UNINSTALL" ]; then
echo ""
echo "Services selected for uninstallation:"
echo "$SELECTED_SERVICES" | tr '"' '\n' | grep -v '^$' | sed 's/^/ - /'
echo ""
# Process uninstalls
if [ -n "$SELECTED_SERVICES" ]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " UNINSTALLING SERVICES"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Define uninstall function
uninstall_service() {
local SERVICE_NAME=$1
local SERVICE_DIR=$2
local CONTAINER_NAME=$3
echo "Uninstalling $SERVICE_NAME..."
if [ -d "$SERVICE_DIR" ]; then
cd "$SERVICE_DIR" 2>/dev/null || return
# Stop and remove containers
if [ -f "docker-compose.yml" ]; then
echo " Stopping containers..."
docker compose down 2>/dev/null || docker-compose down 2>/dev/null || true
fi
# Backup data
BACKUP_DIR="$DOCKER_DIR/backups/$(date +%Y%m%d-%H%M%S)-$SERVICE_NAME"
mkdir -p "$BACKUP_DIR"
echo " Backing up to $BACKUP_DIR..."
cp -r "$SERVICE_DIR" "$BACKUP_DIR/" 2>/dev/null || true
# Remove service directory
echo " Removing $SERVICE_DIR..."
rm -rf "$SERVICE_DIR"
echo "$SERVICE_NAME uninstalled (backup: $BACKUP_DIR)"
else
echo "$SERVICE_NAME directory not found, skipping"
fi
echo ""
}
# Uninstall selected services
if echo "$SELECTED_SERVICES" | grep -q "IMMICH"; then uninstall_service "Immich" "$DOCKER_DIR/immich" "immich"; fi
if echo "$SELECTED_SERVICES" | grep -q "AUDIOBOOKSHELF"; then uninstall_service "AudioBookshelf" "$DOCKER_DIR/audiobookshelf" "audiobookshelf"; fi
if echo "$SELECTED_SERVICES" | grep -q "EMBY"; then uninstall_service "Emby" "$DOCKER_DIR/emby" "emby"; fi
if echo "$SELECTED_SERVICES" | grep -q "ARM"; then uninstall_service "ARM" "$DOCKER_DIR/arm" "arm"; fi
if echo "$SELECTED_SERVICES" | grep -q "FILEBROWSER"; then uninstall_service "FileBrowser" "$DOCKER_DIR/filebrowser" "filebrowser"; fi
if echo "$SELECTED_SERVICES" | grep -q "MAGICMIRROR"; then uninstall_service "MagicMirror" "$DOCKER_DIR/magicmirror" "magicmirror"; fi
if echo "$SELECTED_SERVICES" | grep -q "ACTUALBUDGET"; then uninstall_service "ActualBudget" "$DOCKER_DIR/actualbudget" "actualbudget"; fi
if echo "$SELECTED_SERVICES" | grep -q "KEYCLOAK"; then uninstall_service "Keycloak" "$DOCKER_DIR/keycloak" "keycloak"; fi
if echo "$SELECTED_SERVICES" | grep -q "CADDY"; then uninstall_service "Caddy" "$DOCKER_DIR/caddy" "caddy"; fi
if echo "$SELECTED_SERVICES" | grep -q "LYRION"; then uninstall_service "Lyrion" "$DOCKER_DIR/lms" "lms"; fi
if echo "$SELECTED_SERVICES" | grep -q "MEALIE"; then uninstall_service "Mealie" "$DOCKER_DIR/mealie" "mealie"; fi
if echo "$SELECTED_SERVICES" | grep -q "MINECRAFT"; then uninstall_service "Minecraft" "$DOCKER_DIR/minecraft" "minecraft"; fi
if echo "$SELECTED_SERVICES" | grep -q "JELLYFIN"; then uninstall_service "Jellyfin" "$DOCKER_DIR/jellyfin" "jellyfin"; fi
if echo "$SELECTED_SERVICES" | grep -q "FRIGATE\""; then uninstall_service "Frigate" "$DOCKER_DIR/frigate" "frigate"; fi
if echo "$SELECTED_SERVICES" | grep -q "NTFY"; then uninstall_service "ntfy" "$DOCKER_DIR/ntfy" "ntfy"; fi
if echo "$SELECTED_SERVICES" | grep -q "UPTIMEKUMA"; then uninstall_service "Uptime Kuma" "$DOCKER_DIR/uptime-kuma" "uptime-kuma"; fi
if echo "$SELECTED_SERVICES" | grep -q "WGEASY"; then uninstall_service "wg-easy" "$DOCKER_DIR/wg-easy" "wg-easy"; fi
if echo "$SELECTED_SERVICES" | grep -q "TRACCAR"; then uninstall_service "Traccar" "$DOCKER_DIR/traccar" "traccar"; fi
if echo "$SELECTED_SERVICES" | grep -q "PORTAINER"; then uninstall_service "Portainer" "$DOCKER_DIR/portainer" "portainer"; fi
if echo "$SELECTED_SERVICES" | grep -q "MESHCENTRAL"; then uninstall_service "MeshCentral" "$DOCKER_DIR/meshcentral" "meshcentral"; fi
if echo "$SELECTED_SERVICES" | grep -q "FINDMYDEVICE"; then uninstall_service "FindMyDevice" "$DOCKER_DIR/fmd" "fmd"; fi
if echo "$SELECTED_SERVICES" | grep -q "FRIGATE_NOTIFY"; then uninstall_service "Frigate-Notify" "$DOCKER_DIR/frigate-notify" "frigate-notify"; fi
if echo "$SELECTED_SERVICES" | grep -q "WATCHTOWER"; then uninstall_service "Watchtower" "$DOCKER_DIR/watchtower" "watchtower"; fi
# Special handling for fail2ban (system package)
if echo "$SELECTED_SERVICES" | grep -q "FAIL2BAN"; then
echo "Uninstalling fail2ban..."
echo " Stopping fail2ban service..."
systemctl stop fail2ban 2>/dev/null || true
systemctl disable fail2ban 2>/dev/null || true
echo " Removing fail2ban package..."
apt-get remove --purge -y fail2ban 2>/dev/null || true
echo " ✓ fail2ban uninstalled"
echo ""
fi
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo " Uninstallation complete!"
echo " Backups saved to: $DOCKER_DIR/backups/"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
fi
# After uninstall, exit the Docker apps section
WHIPTAIL_USED=true
elif [ "$MENU_MODE" = "INSTALL" ]; then
echo ""
echo "Selected services:"
echo "$SELECTED_SERVICES" | tr '"' '\n' | grep -v '^$' | sed 's/^/ - /'
echo ""
# Mark that whiptail was used - skip all individual prompts
WHIPTAIL_USED=true
else
# Cancel or other mode
WHIPTAIL_USED=false
fi
else
# Whiptail not available - will use individual prompts
WHIPTAIL_USED=false
MENU_MODE="INSTALL"
fi
# ---- IMMICH ----
if [ -z "$INSTALL_IMMICH" ]; then
# Skip installation section if we just did uninstalls
if [ "$MENU_MODE" = "UNINSTALL" ]; then
echo "Skipping installation section (uninstall mode was selected)."
# Jump to end of Docker section by setting a flag
SKIP_DOCKER_INSTALLS=true
else
SKIP_DOCKER_INSTALLS=false
fi
# ============================================================================
# DOCKER SERVICE INSTALLATIONS
# ============================================================================
if [ "$SKIP_DOCKER_INSTALLS" != true ]; then
# ---- IMMICH ----
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_IMMICH" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ IMMICH - Self-hosted photo & video backup │"
@@ -2491,13 +2698,15 @@ IMMICH_ENV
fi
# ---- AUDIOBOOKSHELF ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ AUDIOBOOKSHELF - Audiobook & podcast server │"
echo "│ Stream audiobooks with progress sync across devices. │"
echo "│ Port: 13378 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Audiobookshelf? (y/n):" "n" INSTALL_AUDIOBOOKSHELF
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_AUDIOBOOKSHELF" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ AUDIOBOOKSHELF - Audiobook & podcast server │"
echo "│ Stream audiobooks with progress sync across devices. │"
echo "│ Port: 13378 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Audiobookshelf? (y/n):" "n" INSTALL_AUDIOBOOKSHELF
fi
if [ "$INSTALL_AUDIOBOOKSHELF" = "y" ] || [ "$INSTALL_AUDIOBOOKSHELF" = "Y" ]; then
echo "Installing Audiobookshelf..."
@@ -2553,14 +2762,14 @@ ABS_ENV
fi
# ---- EMBY ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ EMBY - Media server for movies, TV, music │"
echo "│ Stream your media library to any device. │"
echo "│ Port: 8096 (web), 8920 (https) │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_EMBY" ]; then
prompt_yn "Install Emby? (y/n):" "n" INSTALL_EMBY
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_EMBY" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ EMBY - Media server for movies, TV, music │"
echo "│ Stream your media library to any device. │"
echo "│ Port: 8096 (web), 8920 (https) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Emby? (y/n):" "n" INSTALL_EMBY
fi
if [ "$INSTALL_EMBY" = "y" ] || [ "$INSTALL_EMBY" = "Y" ]; then
@@ -2620,14 +2829,14 @@ EMBY_ENV
fi
# ---- A.R.M. (Automatic Ripping Machine) ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ A.R.M. - Automatic Ripping Machine │"
echo "│ Automatically rip DVDs, Blu-rays, and CDs. │"
echo "│ Port: 8080 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_ARM" ]; then
prompt_yn "Install A.R.M.? (y/n):" "n" INSTALL_ARM
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_ARM" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ A.R.M. - Automatic Ripping Machine │"
echo "│ Automatically rip DVDs, Blu-rays, and CDs. │"
echo "│ Port: 8080 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install A.R.M.? (y/n):" "n" INSTALL_ARM
fi
if [ "$INSTALL_ARM" = "y" ] || [ "$INSTALL_ARM" = "Y" ]; then
@@ -2704,14 +2913,14 @@ ARM_ENV
fi
# ---- FILEBROWSER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FILEBROWSER - Web-based file manager │"
echo "│ Browse, upload, download files via web interface. │"
echo "│ Port: 8085 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_FILEBROWSER" ]; then
prompt_yn "Install Filebrowser? (y/n):" "n" INSTALL_FILEBROWSER
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_FILEBROWSER" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FILEBROWSER - Web-based file manager │"
echo "│ Browse, upload, download files via web interface. │"
echo "│ Port: 8085 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Filebrowser? (y/n):" "n" INSTALL_FILEBROWSER
fi
if [ "$INSTALL_FILEBROWSER" = "y" ] || [ "$INSTALL_FILEBROWSER" = "Y" ]; then
@@ -2781,14 +2990,14 @@ FB_SETTINGS
fi
# ---- MAGIC MIRROR ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MAGIC MIRROR - Smart mirror / dashboard display │"
echo "│ Modular smart mirror platform. Run up to 3 instances. │"
echo "│ Ports: 8081, 8082, 8083 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_MAGICMIRROR" ]; then
prompt_yn "Install Magic Mirror? (y/n):" "n" INSTALL_MAGICMIRROR
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_MAGICMIRROR" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MAGIC MIRROR - Smart mirror / dashboard display │"
echo "│ Modular smart mirror platform. Run up to 3 instances. │"
echo "│ Ports: 8081, 8082, 8083 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Magic Mirror? (y/n):" "n" INSTALL_MAGICMIRROR
fi
if [ "$INSTALL_MAGICMIRROR" = "y" ] || [ "$INSTALL_MAGICMIRROR" = "Y" ]; then
@@ -3014,13 +3223,13 @@ MM_CONFIG
fi
# ---- ACTUALBUDGET ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ ACTUALBUDGET - Open-source Personal Finance Management │"
echo "│ Budget tracking with bank account synchronization via SimpleFIN│"
echo "│ Port: 5006 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_ACTUALBUDGET" ]; then
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_ACTUALBUDGET" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ ACTUALBUDGET - Open-source Personal Finance Management │"
echo "│ Budget tracking with bank account synchronization via SimpleFIN│"
echo "│ Port: 5006 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install ActualBudget? (y/n):" "n" INSTALL_ACTUALBUDGET
fi
@@ -3069,13 +3278,13 @@ AB_COMPOSE
fi
# ---- KEYCLOAK ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ KEYCLOAK - Identity and Access Management (IAM) │"
echo "│ SSO, OAuth2, SAML, User Management, MFA │"
echo "│ Port: 8180 (HTTP) - Use reverse proxy for HTTPS │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_KEYCLOAK" ]; then
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_KEYCLOAK" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ KEYCLOAK - Identity and Access Management (IAM) │"
echo "│ SSO, OAuth2, SAML, User Management, MFA │"
echo "│ Port: 8180 (HTTP) - Use reverse proxy for HTTPS │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Keycloak? (y/n):" "n" INSTALL_KEYCLOAK
fi
@@ -3587,13 +3796,13 @@ EOF
fi
# ---- CADDY WEB SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ CADDY - Modern Web Server & Reverse Proxy │"
echo "│ Automatic HTTPS, reverse proxy for all your services │"
echo "│ Port: 80 (HTTP), 443 (HTTPS) │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_CADDY" ]; then
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_CADDY" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ CADDY - Modern Web Server & Reverse Proxy │"
echo "│ Automatic HTTPS, reverse proxy for all your services │"
echo "│ Port: 80 (HTTP), 443 (HTTPS) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Caddy reverse proxy? (y/n):" "n" INSTALL_CADDY
fi
@@ -3727,13 +3936,13 @@ CADDYFILE
fi
# ---- FAIL2BAN ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FAIL2BAN - Intrusion Prevention System │"
echo "│ Automatically ban IPs with failed auth attempts │"
echo "│ Protects SSH, Caddy, and other services │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_FAIL2BAN" ]; then
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_FAIL2BAN" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FAIL2BAN - Intrusion Prevention System │"
echo "│ Automatically ban IPs with failed auth attempts │"
echo "│ Protects SSH, Caddy, and other services │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install and configure fail2ban? (y/n):" "n" INSTALL_FAIL2BAN
fi
@@ -3859,14 +4068,14 @@ backend = auto"
fi
# ---- LYRION MUSIC SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ LYRION MUSIC SERVER (LMS) - Music streaming server │"
echo "│ Stream music to Squeezebox devices, apps, and Chromecast. │"
echo "│ Port: 9000 (web), 9090 (CLI), 3483 (players) │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_LMS" ]; then
prompt_yn "Install Lyrion Music Server? (y/n):" "n" INSTALL_LMS
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_LMS" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ LYRION MUSIC SERVER (LMS) - Music streaming server │"
echo "│ Stream music to Squeezebox devices, apps, and Chromecast. │"
echo "│ Port: 9000 (web), 9090 (CLI), 3483 (players) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Lyrion Music Server? (y/n):" "n" INSTALL_LMS
fi
if [ "$INSTALL_LMS" = "y" ] || [ "$INSTALL_LMS" = "Y" ]; then
@@ -3925,14 +4134,14 @@ LMS_ENV
fi
# ---- MEALIE ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MEALIE - Recipe manager & meal planner │"
echo "│ Save recipes, plan meals, generate shopping lists. │"
echo "│ Port: 9925 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_MEALIE" ]; then
prompt_yn "Install Mealie? (y/n):" "n" INSTALL_MEALIE
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_MEALIE" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MEALIE - Recipe manager & meal planner │"
echo "│ Save recipes, plan meals, generate shopping lists. │"
echo "│ Port: 9925 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Mealie? (y/n):" "n" INSTALL_MEALIE
fi
if [ "$INSTALL_MEALIE" = "y" ] || [ "$INSTALL_MEALIE" = "Y" ]; then
@@ -3986,14 +4195,14 @@ MEALIE_COMPOSE
fi
# ---- MINECRAFT SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MINECRAFT SERVER - Game server with RAM limit │"
echo "│ Fabric server with configurable memory allocation. │"
echo "│ Port: 25565 │"
echo "└─────────────────────────────────────────────────────────────────┘"
if [ -z "$INSTALL_MINECRAFT" ]; then
prompt_yn "Install Minecraft Server? (y/n):" "n" INSTALL_MINECRAFT
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_MINECRAFT" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MINECRAFT SERVER - Game server with RAM limit │"
echo "│ Fabric server with configurable memory allocation. │"
echo "│ Port: 25565 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Minecraft Server? (y/n):" "n" INSTALL_MINECRAFT
fi
if [ "$INSTALL_MINECRAFT" = "y" ] || [ "$INSTALL_MINECRAFT" = "Y" ]; then
@@ -4144,13 +4353,15 @@ MC_ENV
fi
# ---- JELLYFIN (Alternative to Emby) ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ JELLYFIN - Free media server (alternative to Emby) │"
echo "│ Stream movies, TV, music. No premium features locked. │"
echo "│ Port: 8096 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Jellyfin? (y/n):" "n" INSTALL_JELLYFIN
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_JELLYFIN" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ JELLYFIN - Free media server (alternative to Emby) │"
echo "│ Stream movies, TV, music. No premium features locked. │"
echo "│ Port: 8096 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Jellyfin? (y/n):" "n" INSTALL_JELLYFIN
fi
if [ "$INSTALL_JELLYFIN" = "y" ] || [ "$INSTALL_JELLYFIN" = "Y" ]; then
echo "Installing Jellyfin..."
@@ -4214,13 +4425,15 @@ JELLYFIN_ENV
fi
# ---- FRIGATE NVR ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FRIGATE - AI-powered NVR for security cameras │"
echo "│ Object detection, recordings, 24/7 monitoring. │"
echo "│ Port: 5000 (web), 8554 (RTSP), 8555 (WebRTC) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Frigate? (y/n):" "n" INSTALL_FRIGATE
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_FRIGATE" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FRIGATE - AI-powered NVR for security cameras │"
echo "│ Object detection, recordings, 24/7 monitoring. │"
echo "│ Port: 5000 (web), 8554 (RTSP), 8555 (WebRTC) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Frigate? (y/n):" "n" INSTALL_FRIGATE
fi
if [ "$INSTALL_FRIGATE" = "y" ] || [ "$INSTALL_FRIGATE" = "Y" ]; then
echo "Installing Frigate..."
@@ -4536,13 +4749,15 @@ CADDY_FILE
fi
# ---- DDCLIENT DYNAMIC DNS ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ DDCLIENT - Dynamic DNS updater │"
echo "│ Keep your domain pointing to your home IP. │"
echo "│ Supports: Cloudflare, DuckDNS, No-IP, and more. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install ddclient? (y/n):" "n" INSTALL_DDCLIENT
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_DDCLIENT" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ DDCLIENT - Dynamic DNS updater │"
echo "│ Keep your domain pointing to your home IP. │"
echo "│ Supports: Cloudflare, DuckDNS, No-IP, and more. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install ddclient? (y/n):" "n" INSTALL_DDCLIENT
fi
if [ "$INSTALL_DDCLIENT" = "y" ] || [ "$INSTALL_DDCLIENT" = "Y" ]; then
echo "Installing ddclient..."
@@ -4622,13 +4837,15 @@ DDCLIENT_CONF
fi
# ---- NTFY NOTIFICATIONS ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ NTFY - Push notifications server │"
echo "│ Send notifications from scripts to your phone. │"
echo "│ Port: 8090 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install ntfy? (y/n):" "n" INSTALL_NTFY
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_NTFY" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ NTFY - Push notifications server │"
echo "│ Send notifications from scripts to your phone. │"
echo "│ Port: 8090 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install ntfy? (y/n):" "n" INSTALL_NTFY
fi
if [ "$INSTALL_NTFY" = "y" ] || [ "$INSTALL_NTFY" = "Y" ]; then
echo "Installing ntfy..."
@@ -4683,13 +4900,15 @@ NTFY_ENV
fi
# ---- UPTIME KUMA ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ UPTIME KUMA - Service monitoring dashboard │"
echo "│ Monitor websites, servers, Docker containers. │"
echo "│ Port: 3001 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Uptime Kuma? (y/n):" "n" INSTALL_UPTIMEKUMA
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_UPTIMEKUMA" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ UPTIME KUMA - Service monitoring dashboard │"
echo "│ Monitor websites, servers, Docker containers. │"
echo "│ Port: 3001 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Uptime Kuma? (y/n):" "n" INSTALL_UPTIMEKUMA
fi
if [ "$INSTALL_UPTIMEKUMA" = "y" ] || [ "$INSTALL_UPTIMEKUMA" = "Y" ]; then
echo "Installing Uptime Kuma..."
@@ -4734,13 +4953,15 @@ UPTIME_COMPOSE
fi
# ---- WG-EASY (WireGuard with Web UI) ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ WG-EASY - WireGuard VPN with web management │"
echo "│ Easy WireGuard setup with QR codes for clients. │"
echo "│ Port: 51821 (web), 51820 (VPN) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install wg-easy? (y/n):" "n" INSTALL_WGEASY
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_WGEASY" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ WG-EASY - WireGuard VPN with web management │"
echo "│ Easy WireGuard setup with QR codes for clients. │"
echo "│ Port: 51821 (web), 51820 (VPN) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install wg-easy? (y/n):" "n" INSTALL_WGEASY
fi
if [ "$INSTALL_WGEASY" = "y" ] || [ "$INSTALL_WGEASY" = "Y" ]; then
echo "Installing wg-easy..."
@@ -4808,13 +5029,15 @@ WGEASY_ENV
fi
# ---- TRACCAR GPS TRACKING ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ TRACCAR - GPS tracking server │"
echo "│ Track phones, vehicles, assets with OwnTracks/Traccar apps. │"
echo "│ Port: 8082 (web), 5055 (OsmAnd), 5000+ (devices) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Traccar? (y/n):" "n" INSTALL_TRACCAR
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_TRACCAR" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ TRACCAR - GPS tracking server │"
echo "│ Track phones, vehicles, assets with OwnTracks/Traccar apps. │"
echo "│ Port: 8082 (web), 5055 (OsmAnd), 5000+ (devices) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Traccar? (y/n):" "n" INSTALL_TRACCAR
fi
if [ "$INSTALL_TRACCAR" = "y" ] || [ "$INSTALL_TRACCAR" = "Y" ]; then
echo "Installing Traccar..."
@@ -4879,13 +5102,15 @@ TRACCAR_XML
fi
# ---- PORTAINER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ PORTAINER - Docker management web UI │"
echo "│ Manage containers, images, volumes via browser. │"
echo "│ Port: 9443 (https), 9000 (http) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Portainer? (y/n):" "n" INSTALL_PORTAINER
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_PORTAINER" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ PORTAINER - Docker management web UI │"
echo "│ Manage containers, images, volumes via browser. │"
echo "│ Port: 9443 (https), 9000 (http) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Portainer? (y/n):" "n" INSTALL_PORTAINER
fi
if [ "$INSTALL_PORTAINER" = "y" ] || [ "$INSTALL_PORTAINER" = "Y" ]; then
echo "Installing Portainer..."
@@ -4932,13 +5157,15 @@ PORTAINER_COMPOSE
fi
# ---- MESHCENTRAL SERVER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MESHCENTRAL SERVER - Self-hosted remote management │"
echo "│ Full MeshCentral server (not just agent). Manage all devices. │"
echo "│ Port: 4430 (https), 4433 (agent) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install MeshCentral Server? (y/n):" "n" INSTALL_MESHCENTRAL_SERVER
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_MESHCENTRAL_SERVER" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ MESHCENTRAL SERVER - Self-hosted remote management │"
echo "│ Full MeshCentral server (not just agent). Manage all devices. │"
echo "│ Port: 4430 (https), 4433 (agent) │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install MeshCentral Server? (y/n):" "n" INSTALL_MESHCENTRAL_SERVER
fi
if [ "$INSTALL_MESHCENTRAL_SERVER" = "y" ] || [ "$INSTALL_MESHCENTRAL_SERVER" = "Y" ]; then
echo "Installing MeshCentral Server..."
@@ -5010,13 +5237,15 @@ MC_ENV
fi
# ---- FINDMYDEVICE (FMD) ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FINDMYDEVICE - Self-hosted device tracking │"
echo "│ Track and locate Android devices. Alternative to Google Find. │"
echo "│ Port: 8084 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install FindMyDevice server? (y/n):" "n" INSTALL_FMD
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_FMD" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FINDMYDEVICE - Self-hosted device tracking │"
echo "│ Track and locate Android devices. Alternative to Google Find. │"
echo "│ Port: 8084 │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install FindMyDevice server? (y/n):" "n" INSTALL_FMD
fi
if [ "$INSTALL_FMD" = "y" ] || [ "$INSTALL_FMD" = "Y" ]; then
echo "Installing FindMyDevice..."
@@ -5073,13 +5302,15 @@ FMD_ENV
fi
# ---- FRIGATE-NOTIFY ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FRIGATE-NOTIFY - Push notifications for Frigate events │"
echo "│ Get alerts when Frigate detects people, cars, etc. │"
echo "│ Sends to: ntfy, Pushover, Discord, Gotify, and more. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Frigate-Notify? (y/n):" "n" INSTALL_FRIGATE_NOTIFY
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_FRIGATE_NOTIFY" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ FRIGATE-NOTIFY - Push notifications for Frigate events │"
echo "│ Get alerts when Frigate detects people, cars, etc. │"
echo "│ Sends to: ntfy, Pushover, Discord, Gotify, and more. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Frigate-Notify? (y/n):" "n" INSTALL_FRIGATE_NOTIFY
fi
if [ "$INSTALL_FRIGATE_NOTIFY" = "y" ] || [ "$INSTALL_FRIGATE_NOTIFY" = "Y" ]; then
echo "Installing Frigate-Notify..."
@@ -5176,13 +5407,15 @@ FN_CONFIG
fi
# ---- WATCHTOWER ----
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ WATCHTOWER - Container update monitoring │"
echo "│ Monitor containers for updates. NOTIFY ONLY by default. │"
echo "│ Why notify-only? Apps like Immich have breaking DB migrations. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Watchtower? (y/n):" "n" INSTALL_WATCHTOWER
if [ "$WHIPTAIL_USED" != true ] && [ -z "$INSTALL_WATCHTOWER" ]; then
echo ""
echo "┌─────────────────────────────────────────────────────────────────┐"
echo "│ WATCHTOWER - Container update monitoring │"
echo "│ Monitor containers for updates. NOTIFY ONLY by default. │"
echo "│ Why notify-only? Apps like Immich have breaking DB migrations. │"
echo "└─────────────────────────────────────────────────────────────────┘"
prompt_yn "Install Watchtower? (y/n):" "n" INSTALL_WATCHTOWER
fi
if [ "$INSTALL_WATCHTOWER" = "y" ] || [ "$INSTALL_WATCHTOWER" = "Y" ]; then
echo "Installing Watchtower..."
@@ -5301,6 +5534,8 @@ WT_ENV
fi
fi
fi # End SKIP_DOCKER_INSTALLS check
# ============================================================================
# KOPIA BACKUP FOR DOCKER CONTAINERS
# ============================================================================