#!/bin/bash set -e BASE_DIR="$HOME/homelab" DASHBOARD_DIR="$BASE_DIR/dashboard" TEMPLATES_DIR="$DASHBOARD_DIR/templates" DOCKER_COMPOSE_FILE="$BASE_DIR/docker-compose.yml" echo "Creating dashboard directory structure..." mkdir -p "$TEMPLATES_DIR" echo "Writing app.py..." cat > "$DASHBOARD_DIR/app.py" << 'EOF' from flask import Flask, render_template, jsonify, request import subprocess import requests app = Flask(__name__) DEVICES = { "desktop": "AA:BB:CC:DD:EE:FF", # Replace with real MAC } DEVICE_IPS = { "desktop": "192.168.1.10", # Replace with real IP } WOL_API_URL = "https://wol.zea.lt" def ping_host(ip): try: subprocess.check_output(['ping', '-c', '1', '-W', '1', ip]) return True except subprocess.CalledProcessError: return False @app.route('/') def dashboard(): status = {dev: ping_host(ip) for dev, ip in DEVICE_IPS.items()} return render_template('dashboard.html', devices=DEVICES, status=status) @app.route('/wake/', methods=['POST']) def wake_device(device): if device not in DEVICES: return jsonify({"error": "Device not found"}), 404 try: r = requests.post(f"{WOL_API_URL}/wake/{device}") if r.ok: return jsonify({"message": f"Wake command sent to {device}"}) else: return jsonify({"error": f"Failed to send wake command: {r.text}"}), r.status_code except Exception as e: return jsonify({"error": str(e)}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=8080) EOF echo "Writing dashboard.html template..." cat > "$TEMPLATES_DIR/dashboard.html" << 'EOF' HomeLab Dashboard

HomeLab Dashboard

Services

Devices

{% for device, mac in devices.items() %} {% endfor %}
Device Status Action
{{ device }} {% if status[device] %} Online {% else %} Offline {% endif %}
EOF echo "Writing Dockerfile..." cat > "$DASHBOARD_DIR/Dockerfile" << 'EOF' FROM python:3.11-slim WORKDIR /app COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . EXPOSE 8080 CMD ["python", "app.py"] EOF echo "Writing requirements.txt..." cat > "$DASHBOARD_DIR/requirements.txt" << 'EOF' Flask==2.3.2 requests==2.31.0 EOF # Backup docker-compose.yml just in case cp "$DOCKER_COMPOSE_FILE" "$DOCKER_COMPOSE_FILE.bak" echo "Updating docker-compose.yml to add dashboard service..." # Append dashboard service before the last line if it ends with '...' or just at end # If docker-compose.yml uses version 3+ it should be fine cat >> "$DOCKER_COMPOSE_FILE" << 'EOF' dashboard: build: ./dashboard container_name: dashboard restart: always labels: - "traefik.enable=true" - "traefik.http.routers.dashboard.rule=Host(`dashboard.zea.lt`)" - "traefik.http.routers.dashboard.entrypoints=websecure" - "traefik.http.routers.dashboard.tls.certresolver=leresolver" EOF echo "Setup complete! You can now run:" echo "cd $BASE_DIR && docker-compose build dashboard && docker-compose up -d dashboard"