diff --git a/mermaids.sh b/mermaids.sh index 0483f49..434fe2b 100644 --- a/mermaids.sh +++ b/mermaids.sh @@ -1,6 +1,4 @@ #!/bin/bash -# ct/mermaidjs.sh - Create and configure a self-hosted Mermaid.js editor LXC - set -euo pipefail RED='\033[0;31m' @@ -13,15 +11,13 @@ log() { echo -e "${GREEN}[$(date +%H:%M:%S)]${NC} $1"; } warn() { echo -e "${YELLOW}[$(date +%H:%M:%S)]${NC} $1"; } die() { echo -e "${RED}[$(date +%H:%M:%S)]${NC} $1"; exit 1; } -# Ensure root on Proxmox -if [[ $EUID -ne 0 ]]; then +if [[ $EUID -ne 0 ]] || [[ ! -f /etc/pve/nodes ]]; then die "This script must be run as root on a Proxmox VE host" fi -# Defaults LXC_HOSTNAME="mermaid" LXC_ID="" -LXC_MEMORY=512 +LXC_MEMORY=256 LXC_CORES=1 LXC_DISK="local-lvm" LXC_TEMPLATE="local:vztmpl/debian-12-standard_12.12-1_amd64.tar.zst" @@ -31,48 +27,35 @@ LXC_NETMASK="24" LXC_GATEWAY="" LXC_BRIDGE="vmbr0" -# Auto-increment VMID get_next_id() { local max=0 - for id in $(pct list | awk 'NR>1 {print $1}'); do - ((id > max)) && max=$id - done + for id in $(pct list | awk 'NR>1 {print $1}'); do ((id > max)) && max=$id; done echo $((max + 1)) } -log "=== Mermaid.js Interactive Editor LXC Setup ===" -log "This creates a self-hosted Mermaid editor with OFFLINE support." - +log "=== Mermaid Editor LXC Setup (Alpine + Caddy) ===" read -rp "Hostname (default: mermaid): " HOSTNAME_INPUT [[ -n "$HOSTNAME_INPUT" ]] && LXC_HOSTNAME="$HOSTNAME_INPUT" - read -rp "Container ID (default: $(get_next_id)): " ID_INPUT LXC_ID=${ID_INPUT:-$(get_next_id)} - -read -rp "Memory (MB, default: 512): " MEM_INPUT -LXC_MEMORY=${MEM_INPUT:-512} - +read -rp "Memory (MB, default: 256): " MEM_INPUT +LXC_MEMORY=${MEM_INPUT:-256} read -rp "CPU Cores (default: 1): " CORES_INPUT LXC_CORES=${CORES_INPUT:-1} - read -rp "Root Password (default: mermaid): " PASS_INPUT LXC_ROOT_PASSWORD=${PASS_INPUT:-mermaid} - -read -rp "Disk Storage Pool (default: local-lvm): " DISK_INPUT +read -rp "Disk Pool (default: local-lvm): " DISK_INPUT LXC_DISK=${DISK_INPUT:-local-lvm} - -read -rp "Network Bridge (default: vmbr0): " BRIDGE_INPUT +read -rp "Bridge (default: vmbr0): " BRIDGE_INPUT LXC_BRIDGE=${BRIDGE_INPUT:-vmbr0} - -read -rp "IP Address (e.g., 192.168.1.60; leave blank for DHCP): " IP_INPUT +read -rp "IP (blank for DHCP): " IP_INPUT LXC_IP="$IP_INPUT" - -if [[ -n "$LXC_IP" ]]; then +[[ -n "$LXC_IP" ]] && { read -rp "Netmask (default: 24): " NETMASK_INPUT LXC_NETMASK=${NETMASK_INPUT:-24} - read -rp "Gateway (blank for none): " GW_INPUT + read -rp "Gateway (blank): " GW_INPUT LXC_GATEWAY="$GW_INPUT" -fi +} NET0_ARGS="name=eth0,bridge=$LXC_BRIDGE" if [[ -n "$LXC_IP" ]]; then @@ -84,168 +67,115 @@ fi pvesm status | grep -q "$LXC_DISK" || die "Storage pool '$LXC_BRIDGE' not found" ip link show "$LXC_BRIDGE" >/dev/null 2>&1 || die "Bridge '$LXC_BRIDGE' not found" -# === 1. Create LXC Container === log "Creating LXC container $LXC_ID ($LXC_HOSTNAME)..." -pct create $LXC_ID $LXC_TEMPLATE \ - -hostname $LXC_HOSTNAME \ - -memory $LXC_MEMORY \ - -cores $LXC_CORES \ - -net0 $NET0_ARGS \ - -rootfs $LXC_DISK:1 \ +pct create "$LXC_ID" "$LXC_TEMPLATE" \ + -hostname "$LXC_HOSTNAME" \ + -memory "$LXC_MEMORY" \ + -cores "$LXC_CORES" \ + -net0 "$NET0_ARGS" \ + -rootfs "$LXC_DISK:1" \ -ostype debian \ - -password $LXC_ROOT_PASSWORD \ + -password "$LXC_ROOT_PASSWORD" \ -onboot 1 -# === 2. Start & wait for boot === log "Starting container..." -pct start $LXC_ID +pct start "$LXC_ID" log "Waiting for container to be reachable..." for i in {1..40}; do - if pct exec $LXC_ID -- sh -c "ping -c1 127.0.0.1 >/dev/null 2>&1"; then - break - fi + pct exec "$LXC_ID" -- sh -c "ping -c1 127.0.0.1 >/dev/null 2>&1" && break sleep 1 done -# === 3. Prepare install script (bundled offline Mermaid) === -log "Deploying Mermaid editor + Caddy..." +log "Deploying Mermaid editor (offline + interactive UI)..." +pct exec "$LXC_ID" -- sh -c " + set -euo pipefail + GREEN='\033[0;32m'; NC='\033[0m' + log() { echo -e \"\${GREEN}[\$(date +%H:%M:%S)]\${NC} \$1\"; } -# Generate the install script dynamically (with bundled mermaid.min.js) -pct push $LXC_ID - <<'EOF' /root/mermaid-install.sh -#!/bin/bash -set -euo pipefail + # 1. Update + install deps + log 'Updating system...' + apk update >/dev/null 2>&1 + apk add caddy curl >/dev/null 2>&1 -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' + # 2. Download Mermaid (offline) + log 'Downloading Mermaid v10.6.1...' + mkdir -p /var/www/mermaid + wget -q -O /var/www/mermaid/mermaid.min.js \ + https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js -log() { echo -e "${GREEN}[$(date +%H:%M:%S)]${NC} $1"; } - -# 1. Update & install Caddy & deps -log "Updating system..." -apt-get update -qq -apt-get install -y -qq curl wget - -# 2. Download Mermaid.min.js (offline bundled) -log "Downloading Mermaid v10.6.1 (offline)..." -mkdir -p /var/www/mermaid -wget -q https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js -O /var/www/mermaid/mermaid.min.js - -# 3. Create the editor HTML (self-contained: editor + preview + Mermaid JS) -log "Creating Mermaid editor interface..." -cat > /var/www/mermaid/index.html <<'HTML' + # 3. Create editor HTML (split editor + preview) + log 'Creating interactive editor interface...' + cat > /var/www/mermaid/index.html <<'HTMLEOF' - + Self-hosted Mermaid Editor - + - -
+ +
-HTML +HTMLEOF -# 4. Caddy config (HTTP only — easy; HTTPS in comment) -cat > /etc/caddy/Caddyfile <<'CADDY' + # 4. Caddy config (HTTP) + log 'Configuring Caddy...' + cat > /etc/caddy/Caddyfile <<'CADDYEOF' :80 { - root * /var/www/mermaid - file_server - log { - output file /var/log/caddy/access.log - } + root * /var/www/mermaid + file_server + log { output file /var/log/caddy/access.log } } -# Uncomment below for Let's Encrypt HTTPS -# mermaid.yourdomain.com { -# root * /var/www/mermaid -# file_server -# } -CADDY +CADDYEOF -# 5. Start & enable Caddy -rc-service caddy start -rc-update add caddy + # 5. Start Caddy + rc-service caddy start >/dev/null 2>&1 + rc-update add caddy >/dev/null 2>&1 + sleep 3 -# 6. Check if Caddy started -sleep 5 -if curl -sf http://localhost >/dev/null; then - log "✅ Mermaid Editor is live!" -else - warn "Caddy failed — check 'rc-service caddy status' and 'journalctl -u caddy'" - exit 1 -fi + if curl -sf http://localhost >/dev/null; then + log 'Mermaid Editor is live!' + else + log 'Caddy may still be starting — check rc-service caddy status' + fi -# 7. Summary -IP=$(hostname -I 2>/dev/null | cut -d' ' -f1) -if [[ -z "$IP" ]]; then - IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') -fi -log "URL: ${BLUE}http://${IP}${NC}" -log "Root password: ${YELLOW}$LXC_ROOT_PASSWORD${NC}" -log "SSH: ssh root@${IP}" -EOF + # 6. Summary + IP=$(hostname -I 2>/dev/null | cut -d' ' -f1) + [[ -z \"$IP\" ]] && IP=$(ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') + log \"URL: ${BLUE}http://${IP}${NC}\" + log \"Root password: ${YELLOW}$LXC_ROOT_PASSWORD${NC}\" +" -# Push & run the install script inside LXC -log "Installing Mermaid editor..." -pct exec $LXC_ID -- bash /root/mermaid-install.sh +IP=$(pct exec "$LXC_ID" -- sh -c 'hostname -I 2>/dev/null | cut -d" " -f1') +[[ -z "$IP" ]] && IP=$(pct exec "$LXC_ID" -- sh -c "ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'") -# === 4. Final summary === -IP=$(pct exec $LXC_ID -- hostname -I 2>/dev/null | cut -d' ' -f1) -[[ -z "$IP" ]] && IP=$(pct exec $LXC_ID -- ip -4 addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}') - -log "✅ Mermaid Editor LXC ($LXC_ID) ready!" +log "Mermaid Editor LXC ($LXC_ID) ready!" log "URL: ${BLUE}http://${IP}${NC}" log "Root password: ${YELLOW}$LXC_ROOT_PASSWORD${NC}" \ No newline at end of file