Files
proxmox-lxc-shell-commands/proxmox-lxc-nodered.sh
claude-proxmox-sandbox f976ce1b5a Add Grist, Node-RED, Huginn scripts and update Windmill
- Add proxmox-lxc-grist.sh: Grist with Keycloak SSO and Mailpit
- Add proxmox-lxc-nodered.sh: Node-RED flow-based programming
- Add proxmox-lxc-huginn.sh: Huginn agent automation with Docker
- Update proxmox-lxc-windmill.sh: Add MariaDB, PostgreSQL, auto account setup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 02:24:43 +09:00

339 lines
10 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# Node-RED LXC Installation Script
# Description: Install Node-RED - Flow-based programming tool for IoT
# OS: Debian 12 (Bookworm)
# Ports: Web UI: 1880
# Repository: https://github.com/jeonghanyun/proxmox-lxc-shell-commands
# Last Updated: 2025-12
set -euo pipefail
#################################################################
# Configuration Variables
#################################################################
# Container Configuration
CT_ID=${CT_ID:-26003}
CT_HOSTNAME=${CT_HOSTNAME:-"nodered"}
CT_CORES=${CT_CORES:-2}
CT_MEMORY=${CT_MEMORY:-1024}
CT_SWAP=${CT_SWAP:-512}
CT_DISK_SIZE=${CT_DISK_SIZE:-8}
# Network Configuration
CT_IP=${CT_IP:-"dhcp"}
CT_GATEWAY=${CT_GATEWAY:-""}
CT_BRIDGE=${CT_BRIDGE:-"vmbr0"}
CT_NAMESERVER=${CT_NAMESERVER:-"8.8.8.8"}
# Storage Configuration
CT_STORAGE=${CT_STORAGE:-"local-lvm"}
TEMPLATE_STORAGE=${TEMPLATE_STORAGE:-"local"}
# Debian Template
DEBIAN_VERSION="12"
TEMPLATE_NAME=""
# Node-RED Configuration
NODERED_PORT=${NODERED_PORT:-1880}
# Container Options
CT_ONBOOT=${CT_ONBOOT:-1}
CT_UNPRIVILEGED=${CT_UNPRIVILEGED:-1}
CT_FEATURES="keyctl=1,nesting=1"
#################################################################
# Color Output Functions
#################################################################
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
#################################################################
# Validation Functions
#################################################################
check_root() {
if [[ $EUID -ne 0 ]]; then
error "This script must be run as root"
exit 1
fi
}
check_proxmox() {
if ! command -v pct &> /dev/null; then
error "This script must be run on a Proxmox VE host"
exit 1
fi
}
check_container_exists() {
if pct status "$CT_ID" &> /dev/null; then
error "Container ID $CT_ID already exists"
exit 1
fi
}
detect_and_download_template() {
info "Updating template database..."
pveam update 2>&1 | grep -q "update successful\|already up to date" || true
info "Detecting available Debian ${DEBIAN_VERSION} template..."
local available_template
available_template=$(pveam available --section system 2>/dev/null | grep "debian-${DEBIAN_VERSION}" | grep "standard" | tail -1 | awk '{print $2}')
if [[ -z "$available_template" ]]; then
error "No Debian ${DEBIAN_VERSION} template found"
exit 1
fi
TEMPLATE_NAME="$available_template"
info "Found template: $TEMPLATE_NAME"
if pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE_NAME"; then
success "Template already downloaded"
return 0
fi
warn "Downloading Debian template..."
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE_NAME" 2>&1
success "Template downloaded successfully"
}
#################################################################
# Container Creation Functions
#################################################################
create_container() {
info "Creating LXC container $CT_ID ($CT_HOSTNAME)..."
local net_config="name=eth0,bridge=${CT_BRIDGE},ip=${CT_IP}"
if [[ "$CT_IP" != "dhcp" ]] && [[ -n "$CT_GATEWAY" ]]; then
net_config="${net_config},gw=${CT_GATEWAY}"
fi
pct create "$CT_ID" \
"${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE_NAME}" \
--hostname "$CT_HOSTNAME" \
--cores "$CT_CORES" \
--memory "$CT_MEMORY" \
--swap "$CT_SWAP" \
--rootfs "${CT_STORAGE}:${CT_DISK_SIZE}" \
--net0 "$net_config" \
--nameserver "$CT_NAMESERVER" \
--onboot "$CT_ONBOOT" \
--unprivileged "$CT_UNPRIVILEGED" \
--features "$CT_FEATURES" \
--ostype debian || {
error "Failed to create container"
exit 1
}
success "Container $CT_ID created successfully"
}
start_container() {
info "Starting container $CT_ID..."
pct start "$CT_ID" || {
error "Failed to start container"
exit 1
}
info "Waiting for container to boot..."
sleep 5
success "Container started successfully"
}
configure_autologin() {
info "Configuring automatic console login..."
pct exec "$CT_ID" -- bash -c "mkdir -p /etc/systemd/system/container-getty@1.service.d"
pct exec "$CT_ID" -- bash -c 'cat > /etc/systemd/system/container-getty@1.service.d/override.conf << EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
EOF'
pct exec "$CT_ID" -- bash -c "systemctl daemon-reload"
pct exec "$CT_ID" -- bash -c "systemctl restart container-getty@1.service" 2>/dev/null || true
success "Automatic console login configured"
}
#################################################################
# Node-RED Installation Functions
#################################################################
install_nodejs() {
info "Installing Node.js..."
pct exec "$CT_ID" -- bash -c "apt-get update -qq"
pct exec "$CT_ID" -- bash -c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq curl ca-certificates gnupg"
# Install Node.js 20 LTS
pct exec "$CT_ID" -- bash -c '
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq nodejs
'
success "Node.js installed successfully"
}
install_nodered() {
info "Installing Node-RED..."
pct exec "$CT_ID" -- bash -c "npm install -g --unsafe-perm node-red"
success "Node-RED installed successfully"
}
configure_service() {
info "Configuring Node-RED service..."
pct exec "$CT_ID" -- bash -c 'cat > /etc/systemd/system/nodered.service << "EOF"
[Unit]
Description=Node-RED
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/root
ExecStart=/usr/bin/node-red
Restart=on-failure
RestartSec=5s
Environment=NODE_RED_HOME=/root/.node-red
[Install]
WantedBy=multi-user.target
EOF'
pct exec "$CT_ID" -- bash -c "systemctl daemon-reload"
pct exec "$CT_ID" -- bash -c "systemctl enable nodered"
pct exec "$CT_ID" -- bash -c "systemctl start nodered"
sleep 3
if pct exec "$CT_ID" -- bash -c "systemctl is-active --quiet nodered"; then
success "Node-RED service configured and started"
else
error "Node-RED service failed to start"
pct exec "$CT_ID" -- bash -c "systemctl status nodered"
exit 1
fi
}
add_container_notes() {
info "Adding container notes..."
local container_ip
if [[ "$CT_IP" == "dhcp" ]]; then
sleep 3
container_ip=$(pct exec "$CT_ID" -- hostname -I 2>/dev/null | awk '{print $1}')
if [[ -z "$container_ip" ]]; then
container_ip="[DHCP - check after boot]"
fi
else
container_ip="${CT_IP%/*}"
fi
local notes="Node-RED - Flow-Based Programming
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📋 CONTAINER DETAILS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Container ID: ${CT_ID}
Hostname: ${CT_HOSTNAME}
IP Address: ${container_ip}
CPU Cores: ${CT_CORES}
Memory: ${CT_MEMORY}MB
Disk Size: ${CT_DISK_SIZE}GB
🌐 APPLICATION ACCESS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Web UI: http://${container_ip}:${NODERED_PORT}
🔧 SERVICE MANAGEMENT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Status: pct exec ${CT_ID} -- systemctl status nodered
Start: pct exec ${CT_ID} -- systemctl start nodered
Stop: pct exec ${CT_ID} -- systemctl stop nodered
Restart: pct exec ${CT_ID} -- systemctl restart nodered
Logs: pct exec ${CT_ID} -- journalctl -u nodered -f
📦 CONTAINER MANAGEMENT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Enter: pct enter ${CT_ID}
Start: pct start ${CT_ID}
Stop: pct stop ${CT_ID}
Delete: pct destroy ${CT_ID}
AUTO-GENERATED BY: github.com/jeonghanyun/proxmox-lxc-shell-commands"
pct set "$CT_ID" -description "$notes" 2>/dev/null || true
success "Container notes added"
}
display_info() {
local container_ip
if [[ "$CT_IP" == "dhcp" ]]; then
container_ip=$(pct exec "$CT_ID" -- hostname -I | awk '{print $1}')
else
container_ip="${CT_IP%/*}"
fi
echo ""
echo "================================================================="
success "Node-RED LXC Container Setup Complete!"
echo "================================================================="
echo ""
info "All access information has been saved to container Notes"
echo ""
echo "Container Details:"
echo " • Container ID: $CT_ID"
echo " • Hostname: $CT_HOSTNAME"
echo " • IP Address: $container_ip"
echo ""
echo "Application Access:"
echo " • Web UI: http://${container_ip}:${NODERED_PORT}"
echo ""
echo "Service Management:"
echo " • Status: pct exec $CT_ID -- systemctl status nodered"
echo " • Logs: pct exec $CT_ID -- journalctl -u nodered -f"
echo " • Restart: pct exec $CT_ID -- systemctl restart nodered"
echo ""
echo "================================================================="
}
#################################################################
# Main Execution
#################################################################
main() {
info "Starting Node-RED LXC container creation..."
echo ""
check_root
check_proxmox
check_container_exists
detect_and_download_template
create_container
start_container
configure_autologin
install_nodejs
install_nodered
configure_service
add_container_notes
display_info
}
main "$@"