remove obsolete maintenance scripts (moved into fastapi)

This commit is contained in:
2025-11-14 16:45:34 +01:00
parent 894f74fefb
commit 2c360e39a5
9 changed files with 0 additions and 5868 deletions
File diff suppressed because it is too large Load Diff
-60
View File
@@ -1,60 +0,0 @@
#!/bin/bash
# GPU Passthrough Verification Script
# Checks GPU accessibility in Docker and in GPU-enabled containers
set -e
echo "=== GPU Passthrough Check ==="
echo ""
# Check if nvidia-smi is available on host
echo "[1/4] Checking NVIDIA driver on host..."
if command -v nvidia-smi &> /dev/null; then
nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader
echo "✅ NVIDIA driver detected"
else
echo "❌ nvidia-smi not found on host"
exit 1
fi
echo ""
# Check if NVIDIA Container Toolkit is installed
echo "[2/4] Checking NVIDIA Container Toolkit..."
if docker run --rm --gpus all nvidia/cuda:11.4.0-base-ubuntu20.04 nvidia-smi &> /dev/null; then
echo "✅ NVIDIA Container Toolkit working"
else
echo "❌ NVIDIA Container Toolkit not working"
echo " Install with: sudo apt install nvidia-container-toolkit"
exit 1
fi
echo ""
# Check GPU in Ollama container (if running)
echo "[3/4] Checking GPU in Ollama container..."
if docker ps --format '{{.Names}}' | grep -q "^ollama$"; then
if docker exec ollama nvidia-smi &> /dev/null; then
echo "✅ Ollama has GPU access"
docker exec ollama nvidia-smi --query-gpu=name,utilization.gpu,memory.used --format=csv,noheader
else
echo "⚠️ Ollama running but no GPU access"
fi
else
echo "⚠️ Ollama container not running"
fi
echo ""
# Check GPU in Jellyfin container (if running)
echo "[4/4] Checking GPU in Jellyfin container..."
if docker ps --format '{{.Names}}' | grep -q "^jellyfin$"; then
if docker exec jellyfin nvidia-smi &> /dev/null; then
echo "✅ Jellyfin has GPU access"
docker exec jellyfin nvidia-smi --query-gpu=name,utilization.gpu,memory.used --format=csv,noheader
else
echo "⚠️ Jellyfin running but no GPU access"
fi
else
echo "⚠️ Jellyfin container not running"
fi
echo ""
echo "=== GPU Check Complete ==="
-197
View File
@@ -1,197 +0,0 @@
#!/bin/bash
# GPU Docker Passthrough - Clean Slate Fix Script
# Removes messy configs and installs working nvidia-container-toolkit version
set -e
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ GPU Docker Passthrough - Clean Slate Fix ║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}✗ Please run as root (use sudo)${NC}"
exit 1
fi
echo -e "${BLUE}==> Phase 1: Cleanup${NC}"
echo ""
# Remove all our backup files
echo "Removing config backups..."
rm -f /etc/nvidia-container-runtime/config.toml.backup*
rm -f /etc/docker/daemon.json.backup*
echo -e "${GREEN}✓ Removed config backups${NC}"
# Remove our test scripts (keep the final ones)
echo "Cleaning up test scripts..."
rm -f /home/jpmschweitzer/Projects/tower-of-joy/scripts/fix-gpu-docker.py
rm -f /home/jpmschweitzer/Projects/tower-of-joy/scripts/diagnose-gpu-error.py
rm -f /home/jpmschweitzer/Projects/tower-of-joy/scripts/fix-gpu-csv-mode.py
rm -f /home/jpmschweitzer/Projects/tower-of-joy/scripts/try-nvidia-docker2.sh
echo -e "${GREEN}✓ Cleaned up test scripts${NC}"
echo ""
echo -e "${BLUE}==> Phase 2: Check Available Versions${NC}"
echo ""
# Check what versions are available
echo "Checking available nvidia-container-toolkit versions..."
apt-cache policy nvidia-container-toolkit
echo ""
read -p "Do you see version 1.17.x or 1.16.x in the list above? (y/n) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo ""
echo -e "${BLUE}==> Phase 3: Downgrade to Compatible Version${NC}"
echo ""
# Get the version from user
echo "Available versions from list above:"
apt-cache madison nvidia-container-toolkit | head -5
echo ""
read -p "Enter the version to install (e.g., 1.17.2-1): " VERSION
echo ""
echo "Removing nvidia-container-toolkit 1.18..."
apt-get remove -y nvidia-container-toolkit || true
echo ""
echo "Installing nvidia-container-toolkit version $VERSION..."
apt-get install -y nvidia-container-toolkit=$VERSION
echo ""
echo "Holding package to prevent auto-upgrade..."
apt-mark hold nvidia-container-toolkit
echo -e "${GREEN}✓ Installed nvidia-container-toolkit $VERSION${NC}"
else
echo ""
echo -e "${YELLOW}⚠ Version 1.17/1.16 not available. Configuring 1.18 for legacy mode...${NC}"
echo ""
# Configure 1.18 properly for legacy mode
CONFIG_FILE="/etc/nvidia-container-runtime/config.toml"
# Backup original
cp $CONFIG_FILE ${CONFIG_FILE}.original
# Update config for legacy mode with proper settings
cat > $CONFIG_FILE << 'EOF'
disable-require = false
supported-driver-capabilities = "compat32,compute,display,graphics,ngx,utility,video"
[nvidia-container-cli]
environment = []
ldcache = "/etc/ld.so.cache"
ldconfig = "@/sbin/ldconfig.real"
load-kmods = true
[nvidia-container-runtime]
log-level = "info"
mode = "legacy"
runtimes = ["runc", "crun"]
[nvidia-container-runtime.modes.legacy]
cuda-compat-mode = "ldconfig"
[nvidia-container-runtime-hook]
path = "nvidia-container-runtime-hook"
skip-mode-detection = false
[nvidia-ctk]
path = "nvidia-ctk"
EOF
echo -e "${GREEN}✓ Configured nvidia-container-runtime for legacy mode${NC}"
fi
echo ""
echo -e "${BLUE}==> Phase 4: Configure Docker${NC}"
echo ""
# Create minimal Docker daemon.json
DAEMON_JSON="/etc/docker/daemon.json"
cp $DAEMON_JSON ${DAEMON_JSON}.original 2>/dev/null || true
cat > $DAEMON_JSON << 'EOF'
{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"args": []
}
}
}
EOF
echo -e "${GREEN}✓ Updated Docker daemon.json${NC}"
# Run nvidia-ctk configure
echo ""
echo "Running nvidia-ctk runtime configure..."
nvidia-ctk runtime configure --runtime=docker --config=$DAEMON_JSON
# Rebuild library cache
echo ""
echo "Rebuilding library cache..."
ldconfig
echo -e "${GREEN}✓ Configuration complete${NC}"
echo ""
echo -e "${BLUE}==> Phase 5: Restart Docker${NC}"
echo ""
systemctl restart docker
sleep 3
echo -e "${GREEN}✓ Docker restarted${NC}"
echo ""
echo -e "${BLUE}==> Phase 6: Test GPU Access${NC}"
echo ""
echo "Testing GPU access in Docker container..."
echo ""
if docker run --rm --gpus all nvidia/cuda:11.8.0-runtime-ubuntu20.04 nvidia-smi; then
echo ""
echo -e "${GREEN}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ SUCCESS! ║${NC}"
echo -e "${GREEN}║ GPU is now accessible in Docker! ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Configuration saved to:"
echo " - /etc/docker/daemon.json"
echo " - /etc/nvidia-container-runtime/config.toml"
echo ""
echo "Originals backed up to:"
echo " - /etc/docker/daemon.json.original"
echo " - /etc/nvidia-container-runtime/config.toml.original"
echo ""
exit 0
else
echo ""
echo -e "${RED}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ FAILED ║${NC}"
echo -e "${RED}║ GPU test still failing ║${NC}"
echo -e "${RED}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Troubleshooting:"
echo "1. Check Docker logs: sudo journalctl -u docker -n 50"
echo "2. Verify nvidia-container-cli: sudo nvidia-container-cli info"
echo "3. Check driver version: nvidia-smi"
echo ""
exit 1
fi
-86
View File
@@ -1,86 +0,0 @@
#!/bin/bash
# Complete downgrade of all nvidia-container packages to 1.17.9-1
set -e
GREEN='\033[0;32m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Downgrade All NVIDIA Container Packages ║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}✗ Please run as root (use sudo)${NC}"
exit 1
fi
VERSION="1.17.9-1"
echo -e "${BLUE}==> Step 1: Remove all nvidia-container packages${NC}"
apt-get remove -y nvidia-container-toolkit nvidia-container-toolkit-base libnvidia-container-tools libnvidia-container1 || true
echo -e "${GREEN}✓ Removed packages${NC}"
echo ""
echo -e "${BLUE}==> Step 2: Clean up${NC}"
apt-get autoremove -y
echo -e "${GREEN}✓ Cleaned up${NC}"
echo ""
echo -e "${BLUE}==> Step 3: Install all packages at version $VERSION${NC}"
apt-get install -y \
nvidia-container-toolkit=$VERSION \
nvidia-container-toolkit-base=$VERSION \
libnvidia-container-tools=$VERSION \
libnvidia-container1=$VERSION
echo -e "${GREEN}✓ Installed all packages at $VERSION${NC}"
echo ""
echo -e "${BLUE}==> Step 4: Hold packages to prevent auto-upgrade${NC}"
apt-mark hold nvidia-container-toolkit nvidia-container-toolkit-base libnvidia-container-tools libnvidia-container1
echo -e "${GREEN}✓ Packages held${NC}"
echo ""
echo -e "${BLUE}==> Step 5: Configure Docker${NC}"
nvidia-ctk runtime configure --runtime=docker --config=/etc/docker/daemon.json
echo -e "${GREEN}✓ Docker configured${NC}"
echo ""
echo -e "${BLUE}==> Step 6: Rebuild library cache${NC}"
ldconfig
echo -e "${GREEN}✓ Library cache rebuilt${NC}"
echo ""
echo -e "${BLUE}==> Step 7: Restart Docker${NC}"
systemctl restart docker
sleep 3
echo -e "${GREEN}✓ Docker restarted${NC}"
echo ""
echo -e "${BLUE}==> Step 8: Test GPU access${NC}"
echo ""
if docker run --rm --gpus all nvidia/cuda:11.8.0-runtime-ubuntu20.04 nvidia-smi; then
echo ""
echo -e "${GREEN}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ SUCCESS! ║${NC}"
echo -e "${GREEN}║ GPU is now accessible in Docker! ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
echo "Installed versions:"
dpkg -l | grep nvidia-container
echo ""
exit 0
else
echo ""
echo -e "${RED}╔═══════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ FAILED ║${NC}"
echo -e "${RED}║ GPU test still failing ║${NC}"
echo -e "${RED}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
exit 1
fi
-247
View File
@@ -1,247 +0,0 @@
#!/usr/bin/env python3
"""
Automated Uptime Kuma Monitor Setup for tower-of-joy Infrastructure
This script automatically creates monitors for all infrastructure services in Uptime Kuma.
It is idempotent - safe to run multiple times without creating duplicates.
Usage:
source .venv/bin/activate
python3 scripts/setup-kuma-monitors.py
Environment Variables:
KUMA_URL: Uptime Kuma URL (default: http://192.168.86.149:3001)
KUMA_USERNAME: Uptime Kuma admin username (will prompt if not set)
KUMA_PASSWORD: Uptime Kuma admin password (will prompt if not set)
"""
import os
import sys
from getpass import getpass
try:
from uptime_kuma_api import UptimeKumaApi, MonitorType
except ImportError:
print("\033[0;31mError: uptime-kuma-api package not installed\033[0m")
print("\nInstall dependencies:")
print(" source .venv/bin/activate")
print(" pip install -r requirements.txt")
sys.exit(1)
# Configuration
KUMA_URL = os.getenv("KUMA_URL", "http://192.168.86.149:3001")
# Service definitions
MONITORS = [
{
"name": "Portainer",
"url": "http://192.168.86.149:8001",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Container management interface"
},
{
"name": "Nginx Proxy Manager",
"url": "http://192.168.86.149:81",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Reverse proxy admin interface"
},
{
"name": "Ollama API",
"url": "http://192.168.86.149:11434",
"interval": 60,
"type": MonitorType.HTTP,
"description": "ML model API endpoint"
},
{
"name": "Headscale",
"url": "http://192.168.86.149:8085/health",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Mesh VPN control server"
},
{
"name": "Uptime Kuma",
"url": "http://192.168.86.149:3001",
"interval": 120,
"type": MonitorType.HTTP,
"description": "Service monitoring (self-check)"
},
{
"name": "Netdata",
"url": "http://192.168.86.149:19999",
"interval": 60,
"type": MonitorType.HTTP,
"description": "System metrics dashboard"
},
{
"name": "Heimdall",
"url": "http://192.168.86.149:8888",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Application dashboard"
},
{
"name": "Organizr",
"url": "http://192.168.86.149:9999",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Unified dashboard"
},
{
"name": "Jellyfin",
"url": "http://192.168.86.149:8096",
"interval": 60,
"type": MonitorType.HTTP,
"description": "Media streaming server"
},
]
def print_color(text, color="reset"):
"""Print colored text"""
colors = {
"red": "\033[0;31m",
"green": "\033[0;32m",
"yellow": "\033[1;33m",
"blue": "\033[0;34m",
"cyan": "\033[0;36m",
"reset": "\033[0m"
}
print(f"{colors.get(color, '')}{text}{colors['reset']}")
def get_credentials():
"""Get credentials from environment or prompt user"""
username = os.getenv("KUMA_USERNAME")
password = os.getenv("KUMA_PASSWORD")
if not username:
print_color("\nUptime Kuma credentials required", "yellow")
username = input("Username: ").strip()
if not password:
password = getpass("Password: ").strip()
return username, password
def setup_monitors():
"""Configure all monitors in Uptime Kuma"""
print_color("╔════════════════════════════════════════════╗", "blue")
print_color("║ Uptime Kuma Automated Monitor Setup ║", "blue")
print_color("╚════════════════════════════════════════════╝", "blue")
print()
print(f"Target: {KUMA_URL}")
print(f"Monitors to configure: {len(MONITORS)}")
print()
# Get credentials
username, password = get_credentials()
# Connect to Uptime Kuma
print_color("\nConnecting to Uptime Kuma...", "blue")
try:
api = UptimeKumaApi(KUMA_URL)
api.login(username, password)
print_color("✓ Connected successfully", "green")
except Exception as e:
print_color(f"✗ Connection failed: {e}", "red")
print()
print("Troubleshooting:")
print(" 1. Verify Uptime Kuma is running: docker ps | grep uptime-kuma")
print(f" 2. Check URL is correct: {KUMA_URL}")
print(" 3. Verify credentials are correct")
sys.exit(1)
print()
# Get existing monitors
print_color("Fetching existing monitors...", "blue")
existing_monitors = api.get_monitors()
existing_names = {m["name"] for m in existing_monitors}
print(f"Found {len(existing_monitors)} existing monitor(s)")
print()
# Configure each monitor
print_color("Configuring monitors...", "blue")
print()
created = 0
skipped = 0
failed = 0
for monitor_def in MONITORS:
name = monitor_def["name"]
if name in existing_names:
print(f"{name} - Already exists (skipping)")
skipped += 1
continue
try:
# Create the monitor
api.add_monitor(
type=monitor_def["type"],
name=name,
url=monitor_def["url"],
interval=monitor_def["interval"],
description=monitor_def.get("description", ""),
retryInterval=60,
resendInterval=0,
maxretries=1,
upsideDown=False,
notificationIDList=[],
httpBodyEncoding="utf8",
method="GET",
maxredirects=10,
accepted_statuscodes=["200-299"]
)
print_color(f"{name} - Created", "green")
print(f" URL: {monitor_def['url']}")
print(f" Interval: {monitor_def['interval']}s")
created += 1
except Exception as e:
print_color(f"{name} - Failed: {e}", "red")
failed += 1
print()
# Disconnect
api.disconnect()
# Summary
print_color("═══════════════════════════════════════════", "blue")
print_color("Summary:", "green")
print_color("═══════════════════════════════════════════", "blue")
print(f"Created: {created}")
print(f"Skipped (already exist): {skipped}")
print(f"Failed: {failed}")
print()
if created > 0:
print_color("✓ Setup complete! Monitors are now active.", "green")
print()
print("View monitors at:", KUMA_URL)
print("Refresh Organizr to see status widgets update")
elif skipped == len(MONITORS):
print_color("✓ All monitors already configured", "green")
else:
print_color("⚠ Some monitors could not be created", "yellow")
sys.exit(1)
if __name__ == "__main__":
try:
setup_monitors()
except KeyboardInterrupt:
print()
print_color("Setup cancelled by user", "yellow")
sys.exit(130)
except Exception as e:
print()
print_color(f"Unexpected error: {e}", "red")
import traceback
traceback.print_exc()
sys.exit(1)
-133
View File
@@ -1,133 +0,0 @@
#!/bin/bash
# Setup Uptime Kuma Monitors for tower-of-joy Infrastructure
#
# This script provides instructions and data for configuring monitoring
# for all infrastructure services in Uptime Kuma.
#
# Usage: ./scripts/setup-kuma-monitors.sh
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Configuration
KUMA_URL="http://192.168.86.149:3001"
# Service definitions
declare -a MONITORS=(
"Portainer|http://192.168.86.149:8001|60|Container management interface"
"Nginx Proxy Manager|http://192.168.86.149:81|60|Reverse proxy admin interface"
"Ollama API|http://192.168.86.149:11434|60|ML model API endpoint"
"Headscale|http://192.168.86.149:8085/health|60|Mesh VPN control server"
"Uptime Kuma|http://192.168.86.149:3001|120|Service monitoring (self-check)"
"Netdata|http://192.168.86.149:19999|60|System metrics dashboard"
"Heimdall|http://192.168.86.149:8888|60|Application dashboard"
"Organizr|http://192.168.86.149:9999|60|Unified dashboard"
"Jellyfin|http://192.168.86.149:8096|60|Media streaming server"
)
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Uptime Kuma Monitor Setup Guide ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${CYAN}Target:${NC} $KUMA_URL"
echo -e "${CYAN}Monitors to configure:${NC} ${#MONITORS[@]}"
echo ""
# Check if Uptime Kuma is accessible
echo -n "Checking Uptime Kuma availability... "
if curl -s -o /dev/null -w "%{http_code}" "$KUMA_URL" | grep -q "200\|301\|302"; then
echo -e "${GREEN}${NC}"
else
echo -e "${RED}${NC}"
echo -e "${RED}Error: Cannot reach Uptime Kuma at $KUMA_URL${NC}"
echo "Make sure Uptime Kuma is running: docker ps | grep uptime-kuma"
exit 1
fi
echo ""
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo -e "${GREEN}Monitors to Configure:${NC}"
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo ""
counter=1
for monitor_def in "${MONITORS[@]}"; do
IFS='|' read -r name url interval desc <<< "$monitor_def"
echo -e "${YELLOW}[$counter/${#MONITORS[@]}] $name${NC}"
echo -e " ${CYAN}URL:${NC} $url"
echo -e " ${CYAN}Interval:${NC} ${interval}s"
echo -e " ${CYAN}Description:${NC} $desc"
echo ""
((counter++))
done
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo -e "${GREEN}Setup Instructions:${NC}"
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo ""
echo "1. Open Uptime Kuma in your browser:"
echo -e " ${CYAN}${KUMA_URL}${NC}"
echo ""
echo "2. Log in with your Uptime Kuma credentials"
echo ""
echo "3. For each monitor listed above, click ${GREEN}'Add New Monitor'${NC} and enter:"
echo ""
echo " ${CYAN}Monitor Settings:${NC}"
echo " • Monitor Type: ${GREEN}HTTP(s)${NC}"
echo " • Friendly Name: ${GREEN}[Name from list above]${NC}"
echo " • URL: ${GREEN}[URL from list above]${NC}"
echo " • Heartbeat Interval: ${GREEN}[Interval from list]${NC} seconds"
echo " • Retries: ${GREEN}1${NC}"
echo " • Retry Interval: ${GREEN}60${NC} seconds"
echo " • HTTP Method: ${GREEN}GET${NC}"
echo " • Expected Status Code: ${GREEN}200${NC}"
echo ""
echo "4. Click ${GREEN}'Save'${NC} for each monitor"
echo ""
echo "5. After adding all monitors, verify they appear in:"
echo " • Uptime Kuma dashboard"
echo " • Organizr homepage (Service Status widget)"
echo ""
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo -e "${GREEN}Quick Copy-Paste Data:${NC}"
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo ""
for monitor_def in "${MONITORS[@]}"; do
IFS='|' read -r name url interval desc <<< "$monitor_def"
echo -e "${YELLOW}$name${NC}"
echo "$url"
echo ""
done
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo -e "${GREEN}Post-Setup Verification:${NC}"
echo -e "${BLUE}═══════════════════════════════════════════${NC}"
echo ""
echo "After adding all monitors:"
echo ""
echo "1. Check Uptime Kuma dashboard shows all services as 'Up'"
echo "2. Refresh Organizr (${CYAN}http://192.168.86.149:9999${NC})"
echo "3. Verify 'Service Status' widget shows all monitors"
echo "4. Test by stopping a container and watching status change:"
echo -e " ${CYAN}docker stop heimdall${NC}"
echo " (Monitor should show as Down within 60s)"
echo -e " ${CYAN}docker start heimdall${NC}"
echo " (Monitor should recover)"
echo ""
echo -e "${GREEN}✓ Setup guide complete!${NC}"
echo ""
echo -e "${YELLOW}Tip:${NC} For automated setup in the future, consider:"
echo " • Uptime Kuma API (requires authentication)"
echo " • Backup/restore Uptime Kuma configuration"
echo " • Export configuration: Settings → Backup"
echo ""
-105
View File
@@ -1,105 +0,0 @@
#!/bin/bash
# NVIDIA Driver Upgrade Script: 470 -> 535
# Upgrades NVIDIA driver for CUDA 12 support (required by Ollama)
set -e
echo "=== NVIDIA Driver Upgrade: 470 -> 535 ==="
echo ""
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "❌ This script must be run as root (use sudo)"
exit 1
fi
# Backup current state
echo "[1/9] Backing up current container state..."
docker ps > /tmp/nvidia-upgrade-containers-backup.txt
echo "✅ Container list saved to /tmp/nvidia-upgrade-containers-backup.txt"
echo ""
# Stop GPU containers
echo "[2/9] Stopping GPU-using containers..."
docker stop ollama 2>/dev/null || true
docker stop jellyfin 2>/dev/null || true
echo "✅ GPU containers stopped"
echo ""
# Unhold NVIDIA Container Toolkit packages
echo "[3/9] Unholding NVIDIA Container Toolkit packages..."
echo "libnvidia-container-tools install" | dpkg --set-selections
echo "libnvidia-container1 install" | dpkg --set-selections
echo "nvidia-container-toolkit install" | dpkg --set-selections
echo "nvidia-container-toolkit-base install" | dpkg --set-selections
echo "✅ Packages unheld"
echo ""
# Remove ALL driver 470 packages
echo "[4/9] Removing ALL NVIDIA driver 470 packages..."
apt-get purge -y 'libnvidia-*-470' 'nvidia-*-470' '*nvidia*470*' 2>&1 | grep -E "Removing|Purging|^$" || true
apt-get purge -y nvidia-settings 2>&1 | grep -E "Removing|Purging|^$" || true
apt-get autoremove -y > /dev/null 2>&1
echo "✅ All driver 470 packages removed"
echo ""
# Clean up package database
echo "[5/9] Cleaning package database..."
apt-get clean
apt-get autoclean
dpkg --configure -a
apt-get install -f -y
echo "✅ Package database cleaned"
echo ""
# Update package lists
echo "[6/9] Updating package lists..."
apt-get update > /dev/null 2>&1
echo "✅ Package lists updated"
echo ""
# Install driver 535 with all dependencies
echo "[7/9] Installing NVIDIA driver 535..."
apt-get install -y --no-install-recommends \
libnvidia-common-535 \
libnvidia-gl-535 \
libnvidia-compute-535 \
libnvidia-decode-535 \
libnvidia-encode-535 \
nvidia-utils-535 \
xserver-xorg-video-nvidia-535 \
libnvidia-cfg1-535 \
libnvidia-fbc1-535 \
nvidia-kernel-common-535 \
nvidia-dkms-535 \
nvidia-driver-535 \
nvidia-settings
echo "✅ Driver 535 installed"
echo ""
# Update NVIDIA Container Toolkit
echo "[8/9] Updating NVIDIA Container Toolkit..."
apt-get install --reinstall -y nvidia-container-toolkit > /dev/null 2>&1
nvidia-ctk runtime configure --runtime=docker > /dev/null 2>&1
echo "✅ Container toolkit updated"
echo ""
# Restart Docker
echo "[9/9] Restarting Docker daemon..."
systemctl restart docker
sleep 3
echo "✅ Docker restarted"
echo ""
echo "=== Upgrade Complete ==="
echo ""
echo "⚠️ REBOOT REQUIRED NOW"
echo ""
echo "Run: sudo reboot"
echo ""
echo "After reboot:"
echo " 1. Verify: nvidia-smi"
echo " 2. Restart: cd ~/Projects/portainer-core/stacks && docker compose -f ollama.yml up -d"
echo " 3. Test GPU: docker exec ollama ollama ps"
echo ""
-105
View File
@@ -1,105 +0,0 @@
#!/bin/bash
set -euo pipefail
#############################################################################
# Portainer Stack Creator
#
# Creates new Portainer stacks via REST API using local YAML files.
#
# Usage:
# ./create-stack.sh <stack-name.yml>
#
# Example:
# ./create-stack.sh gitea.yml
#############################################################################
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/.env"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Load credentials
if [ ! -f "$ENV_FILE" ]; then
log_error ".env file not found"
exit 1
fi
source "$ENV_FILE"
PORTAINER_URL="${PORTAINER_URL:-http://localhost:8001}"
# Validate arguments
if [ $# -ne 1 ]; then
log_error "Usage: $0 <stack-file.yml>"
exit 1
fi
YAML_FILE="$1"
STACK_NAME=$(basename "$YAML_FILE" .yml)
if [ ! -f "$YAML_FILE" ]; then
log_error "File not found: $YAML_FILE"
exit 1
fi
log_info "Creating stack: $STACK_NAME"
# Authenticate
log_info "Authenticating with Portainer..."
TOKEN=$(curl -s -X POST "$PORTAINER_URL/api/auth" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$PORTAINER_USERNAME\",\"password\":\"$PORTAINER_PASSWORD\"}" \
| python3 -c "import sys, json; print(json.load(sys.stdin)['jwt'])" 2>/dev/null)
if [ -z "$TOKEN" ]; then
log_error "Authentication failed"
exit 1
fi
log_success "Authenticated"
# Get endpoint ID
ENDPOINT_ID=$(curl -s -X GET "$PORTAINER_URL/api/endpoints" \
-H "Authorization: Bearer $TOKEN" \
| python3 -c "import sys, json; print(json.load(sys.stdin)[0]['Id'])" 2>/dev/null)
if [ -z "$ENDPOINT_ID" ]; then
log_error "Failed to get endpoint ID"
exit 1
fi
log_info "Endpoint ID: $ENDPOINT_ID"
# Read YAML content
YAML_CONTENT=$(cat "$YAML_FILE")
# Create stack
log_info "Creating stack in Portainer..."
RESPONSE=$(curl -s -X POST "$PORTAINER_URL/api/stacks/create/standalone/string?endpointId=$ENDPOINT_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"name": "$STACK_NAME",
"stackFileContent": $(echo "$YAML_CONTENT" | python3 -c "import sys, json; print(json.dumps(sys.stdin.read()))")
}
EOF
)
# Check for errors
if echo "$RESPONSE" | grep -q '"message"' && echo "$RESPONSE" | grep -q '"err"'; then
log_error "Failed to create stack: $RESPONSE"
exit 1
fi
log_success "✓ Stack '$STACK_NAME' created successfully!"
echo "$RESPONSE" | python3 -c "import sys, json; data=json.load(sys.stdin); print(f\"Stack ID: {data.get('Id', 'N/A')}\")" 2>/dev/null || true
-252
View File
@@ -1,252 +0,0 @@
#!/bin/bash
set -euo pipefail
#############################################################################
# Portainer Stack Updater (Automation-Only)
#
# Updates Portainer stacks via REST API using local YAML files.
# Credentials stored in .env file (gitignored).
#
# Usage:
# ./update-stack.sh <stack-name.yml>
#
# Example:
# ./update-stack.sh open-webui.yml
#############################################################################
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TOKEN_FILE="$SCRIPT_DIR/.portainer-token"
ENV_FILE="$SCRIPT_DIR/.env"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Load credentials from .env
if [ ! -f "$ENV_FILE" ]; then
log_error ".env file not found at $ENV_FILE"
exit 1
fi
source "$ENV_FILE"
if [ -z "${PORTAINER_USERNAME:-}" ] || [ -z "${PORTAINER_PASSWORD:-}" ]; then
log_error "PORTAINER_USERNAME and PORTAINER_PASSWORD must be set in .env file"
exit 1
fi
PORTAINER_URL="${PORTAINER_URL:-http://localhost:8080}"
#############################################################################
# Authentication
#############################################################################
authenticate() {
log_info "Authenticating with Portainer..."
local response
response=$(curl -s -X POST "$PORTAINER_URL/api/auth" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$PORTAINER_USERNAME\",\"password\":\"$PORTAINER_PASSWORD\"}" \
2>&1)
if [ $? -ne 0 ]; then
log_error "Failed to connect to Portainer at $PORTAINER_URL"
exit 1
fi
# Extract token
local token
token=$(echo "$response" | python3 -c "import sys, json; print(json.load(sys.stdin)['jwt'])" 2>/dev/null)
if [ -z "$token" ]; then
log_error "Failed to authenticate. Check credentials in .env file."
exit 1
fi
# Save token
echo "$token" > "$TOKEN_FILE"
chmod 600 "$TOKEN_FILE"
log_success "Authentication successful"
echo "$token"
}
get_token() {
if [ -f "$TOKEN_FILE" ]; then
cat "$TOKEN_FILE"
else
authenticate
fi
}
#############################################################################
# Stack Operations
#############################################################################
get_endpoint_id() {
local token="$1"
local response
response=$(curl -s -X GET "$PORTAINER_URL/api/endpoints" \
-H "Authorization: Bearer $token" 2>&1)
if [ $? -ne 0 ]; then
log_error "Failed to get endpoints"
return 1
fi
# Get first endpoint (local docker)
local endpoint_id
endpoint_id=$(echo "$response" | python3 -c "import sys, json; print(json.load(sys.stdin)[0]['Id'])" 2>/dev/null)
if [ -z "$endpoint_id" ]; then
log_error "No endpoints found"
return 1
fi
echo "$endpoint_id"
}
get_stack_id() {
local token="$1"
local stack_name="$2"
local response
response=$(curl -s -X GET "$PORTAINER_URL/api/stacks" \
-H "Authorization: Bearer $token" 2>&1)
if [ $? -ne 0 ]; then
log_error "Failed to get stacks"
return 1
fi
# Find stack by name
local stack_id
stack_id=$(echo "$response" | python3 -c "
import sys, json
stacks = json.load(sys.stdin)
for stack in stacks:
if stack['Name'] == '$stack_name':
print(stack['Id'])
break
" 2>/dev/null)
echo "$stack_id"
}
update_stack() {
local token="$1"
local stack_id="$2"
local endpoint_id="$3"
local yaml_content="$4"
log_info "Updating stack ID $stack_id..."
# Create JSON payload
local payload
payload=$(python3 -c "
import json, sys
data = {
'stackFileContent': '''$yaml_content''',
'prune': False,
'pullImage': False
}
print(json.dumps(data))
")
local response
response=$(curl -s -X PUT "$PORTAINER_URL/api/stacks/$stack_id?endpointId=$endpoint_id" \
-H "Authorization: Bearer $token" \
-H "Content-Type: application/json" \
-d "$payload" 2>&1)
if [ $? -ne 0 ]; then
log_error "Failed to update stack"
return 1
fi
# Check if response contains error
if echo "$response" | grep -q '"message"'; then
log_error "Stack update failed: $response"
return 1
fi
log_success "Stack updated successfully"
return 0
}
#############################################################################
# Main
#############################################################################
main() {
# Validate arguments
if [ $# -ne 1 ]; then
log_error "Usage: $0 <stack-file.yml>"
log_error "Example: $0 open-webui.yml"
exit 1
fi
local yaml_file="$1"
local yaml_path
# Support both relative and absolute paths
if [ -f "$yaml_file" ]; then
yaml_path="$yaml_file"
elif [ -f "$SCRIPT_DIR/$yaml_file" ]; then
yaml_path="$SCRIPT_DIR/$yaml_file"
else
log_error "Stack file not found: $yaml_file"
exit 1
fi
# Extract stack name from filename (remove .yml extension)
local stack_name
stack_name=$(basename "$yaml_file" .yml)
log_info "Updating stack: $stack_name"
# Read YAML content
local yaml_content
yaml_content=$(cat "$yaml_path")
# Get or create API token
local token
token=$(get_token)
# Get endpoint ID (local Docker)
local endpoint_id
endpoint_id=$(get_endpoint_id "$token")
if [ -z "$endpoint_id" ]; then
log_error "Failed to get endpoint ID"
exit 1
fi
# Get stack ID
local stack_id
stack_id=$(get_stack_id "$token" "$stack_name")
if [ -z "$stack_id" ]; then
log_error "Stack '$stack_name' not found in Portainer"
exit 1
fi
# Update stack
if update_stack "$token" "$stack_id" "$endpoint_id" "$yaml_content"; then
log_success "✓ Stack '$stack_name' updated successfully"
exit 0
else
log_error "Failed to update stack"
exit 1
fi
}
main "$@"