- Add deploy.resources sections to all services based on service type - Lightweight services: 0.25 CPU, 128M RAM (Traefik, Authelia, Pi-hole) - Web services: 0.50 CPU, 256M RAM (Dashboards, simple web apps) - Media services: 2.0 CPU, 2G RAM (Jellyfin, transcoding) - Database services: 1.0 CPU, 1G RAM (PostgreSQL, caching) - Heavy apps: 1.5 CPU, 1G RAM (Nextcloud, Home Assistant) - Monitoring: 0.75 CPU, 512M RAM (Prometheus, Grafana) - Include CPU, memory, and process limits with reservations - Create comprehensive resource limits template documentation
202 lines
6.9 KiB
Bash
Executable File
202 lines
6.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# AI-Homelab Resource Limits Application Script
|
|
# Applies researched resource limits to all Docker Compose stacks
|
|
# Run as: sudo ./apply-resource-limits.sh
|
|
|
|
set -e
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
# Check if running as root
|
|
if [ "$EUID" -ne 0 ]; then
|
|
log_error "Please run as root (sudo ./apply-resource-limits.sh)"
|
|
exit 1
|
|
fi
|
|
|
|
# Get actual user
|
|
ACTUAL_USER="${SUDO_USER:-$USER}"
|
|
|
|
log_info "Applying researched resource limits to all stacks..."
|
|
echo ""
|
|
|
|
# Function to add resource limits to a service in docker-compose.yml
|
|
add_resource_limits() {
|
|
local compose_file="$1"
|
|
local service_name="$2"
|
|
local template="$3"
|
|
|
|
# Define resource limits based on template
|
|
case $template in
|
|
"lightweight")
|
|
limits="cpus: '0.25'\n memory: 128M\n pids: 256"
|
|
reservations="cpus: '0.10'\n memory: 64M"
|
|
;;
|
|
"web")
|
|
limits="cpus: '0.50'\n memory: 256M\n pids: 512"
|
|
reservations="cpus: '0.25'\n memory: 128M"
|
|
;;
|
|
"database")
|
|
limits="cpus: '1.0'\n memory: 1G\n pids: 1024"
|
|
reservations="cpus: '0.50'\n memory: 512M"
|
|
;;
|
|
"media")
|
|
limits="cpus: '2.0'\n memory: 2G\n pids: 2048"
|
|
reservations="cpus: '1.0'\n memory: 1G"
|
|
;;
|
|
"downloader")
|
|
limits="cpus: '1.0'\n memory: 512M\n pids: 1024"
|
|
reservations="cpus: '0.50'\n memory: 256M"
|
|
;;
|
|
"heavy")
|
|
limits="cpus: '1.5'\n memory: 1G\n pids: 2048"
|
|
reservations="cpus: '0.75'\n memory: 512M"
|
|
;;
|
|
"monitoring")
|
|
limits="cpus: '0.75'\n memory: 512M\n pids: 1024"
|
|
reservations="cpus: '0.25'\n memory: 256M"
|
|
;;
|
|
*)
|
|
log_warning "Unknown template: $template for $service_name"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# Check if service already has deploy.resources
|
|
if grep -A 10 " $service_name:" "$compose_file" | grep -q "deploy:"; then
|
|
log_warning "$service_name in $compose_file already has deploy section - skipping"
|
|
return
|
|
fi
|
|
|
|
# Find the service definition and add deploy.resources after the image line
|
|
if grep -q "^ $service_name:" "$compose_file"; then
|
|
# Create a temporary file with the deploy section
|
|
local deploy_section=" deploy:
|
|
resources:
|
|
limits:
|
|
$limits
|
|
reservations:
|
|
$reservations"
|
|
|
|
# Use awk to insert the deploy section after the image line
|
|
awk -v service="$service_name" -v deploy="$deploy_section" '
|
|
/^ '"$service_name"':/ { in_service=1 }
|
|
in_service && /^ image:/ {
|
|
print $0
|
|
print deploy
|
|
in_service=0
|
|
next
|
|
}
|
|
{ print }
|
|
' "$compose_file" > "${compose_file}.tmp" && mv "${compose_file}.tmp" "$compose_file"
|
|
|
|
log_success "Added $template limits to $service_name in $(basename "$compose_file")"
|
|
else
|
|
log_warning "Service $service_name not found in $compose_file"
|
|
fi
|
|
}
|
|
|
|
# Process each stack
|
|
STACKS_DIR="/opt/stacks"
|
|
|
|
# Core stack (already has some limits)
|
|
log_info "Processing core stack..."
|
|
if [ -f "$STACKS_DIR/core/docker-compose.yml" ]; then
|
|
# DuckDNS is already done, check if others need limits
|
|
if ! grep -A 5 " authelia:" "$STACKS_DIR/core/docker-compose.yml" | grep -q "deploy:"; then
|
|
add_resource_limits "$STACKS_DIR/core/docker-compose.yml" "authelia" "lightweight"
|
|
fi
|
|
fi
|
|
|
|
# Infrastructure stack
|
|
log_info "Processing infrastructure stack..."
|
|
if [ -f "$STACKS_DIR/infrastructure/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/infrastructure/docker-compose.yml" "pihole" "lightweight"
|
|
add_resource_limits "$STACKS_DIR/infrastructure/docker-compose.yml" "dockge" "web"
|
|
add_resource_limits "$STACKS_DIR/infrastructure/docker-compose.yml" "glances" "web"
|
|
fi
|
|
|
|
# Dashboard stack
|
|
log_info "Processing dashboard stack..."
|
|
if [ -f "$STACKS_DIR/dashboards/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/dashboards/docker-compose.yml" "homepage" "web"
|
|
add_resource_limits "$STACKS_DIR/dashboards/docker-compose.yml" "homarr" "web"
|
|
fi
|
|
|
|
# Media stack
|
|
log_info "Processing media stack..."
|
|
if [ -f "$STACKS_DIR/media/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/media/docker-compose.yml" "jellyfin" "media"
|
|
add_resource_limits "$STACKS_DIR/media/docker-compose.yml" "calibre-web" "web"
|
|
fi
|
|
|
|
# Downloaders stack
|
|
log_info "Processing downloaders stack..."
|
|
if [ -f "$STACKS_DIR/downloaders/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/downloaders/docker-compose.yml" "qbittorrent" "downloader"
|
|
fi
|
|
|
|
# Home Assistant stack
|
|
log_info "Processing home assistant stack..."
|
|
if [ -f "$STACKS_DIR/homeassistant/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/homeassistant/docker-compose.yml" "homeassistant" "heavy"
|
|
add_resource_limits "$STACKS_DIR/homeassistant/docker-compose.yml" "esphome" "web"
|
|
add_resource_limits "$STACKS_DIR/homeassistant/docker-compose.yml" "nodered" "web"
|
|
fi
|
|
|
|
# Productivity stack
|
|
log_info "Processing productivity stack..."
|
|
if [ -f "$STACKS_DIR/productivity/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/productivity/docker-compose.yml" "nextcloud" "heavy"
|
|
add_resource_limits "$STACKS_DIR/productivity/docker-compose.yml" "gitea" "web"
|
|
fi
|
|
|
|
# Monitoring stack
|
|
log_info "Processing monitoring stack..."
|
|
if [ -f "$STACKS_DIR/monitoring/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/monitoring/docker-compose.yml" "prometheus" "monitoring"
|
|
add_resource_limits "$STACKS_DIR/monitoring/docker-compose.yml" "grafana" "web"
|
|
add_resource_limits "$STACKS_DIR/monitoring/docker-compose.yml" "loki" "monitoring"
|
|
add_resource_limits "$STACKS_DIR/monitoring/docker-compose.yml" "uptime-kuma" "web"
|
|
fi
|
|
|
|
# Development stack
|
|
log_info "Processing development stack..."
|
|
if [ -f "$STACKS_DIR/development/docker-compose.yml" ]; then
|
|
add_resource_limits "$STACKS_DIR/development/docker-compose.yml" "code-server" "heavy"
|
|
fi
|
|
|
|
# Fix ownership
|
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$STACKS_DIR"
|
|
|
|
echo ""
|
|
log_success "Resource limits application complete!"
|
|
echo ""
|
|
log_info "Next steps:"
|
|
echo " 1. Review the applied limits: docker compose config"
|
|
echo " 2. Deploy updated stacks: docker compose up -d"
|
|
echo " 3. Monitor usage: docker stats"
|
|
echo " 4. Adjust limits as needed based on real usage"
|
|
echo ""
|
|
log_info "Note: These are conservative defaults based on typical usage patterns."
|
|
log_info "Monitor actual resource usage and adjust limits accordingly." |