Merge branch 'main' of ssh://gitea.prod.lagraula.fr:2222/xavier/nixos-infra

This commit is contained in:
2026-04-30 23:00:45 +02:00
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env bash
set -euo pipefail
# --- Dependencies ---
# Check if docopts is installed (for Bash)
if ! command -v docopts &> /dev/null; then
echo "❌ Error: 'docopts' is required for Bash." >&2
echo "See https://github.com/docopt/docopts to install it." >&2
exit 1
fi
# --- Usage and Documentation ---
usage="Create and configure an LXC container on a remote Proxmox VE 9 server.
Usage:
$0 <short_name> [options]
Options:
-h, --help Show this message.
-t, --template TEMPLATE LXC template (e.g. local:vztmpl/nixos-unstable).
-r, --rootfs-size SIZE Root filesystem size (e.g. 8G).
-c, --cores CORES Number of CPU cores.
-m, --memory MEMORY RAM in MiB.
-s, --swap SWAP Swap in MiB.
-p, --password PASSWORD Root password for the container.
-b, --bridge BRIDGE Network bridge (e.g. vmbr0).
-v, --vlan VLAN VLAN tag (e.g. tag=10).
-d, --domain DOMAIN DNS domain.
-u, --unprivileged UNPRIV Unprivileged container (0 or 1).
-i, --ip IP Static IP (e.g. 192.168.1.100/24).
-C, --cmode CMODE Console mode (console or tty). Default: console.
-T, --tags TAGS Tags for the container (optional).
-k, --ssh-public-keys KEYS SSH public keys for the container.
--pve-host HOST Proxmox host (e.g. pve).
--pve-user USER Proxmox user (default: admin).
--pve-port PORT SSH port for Proxmox (default: 22).
--pve-password PASSWORD Password for SSH authentication on Proxmox.
--pve-ssh-key KEY SSH key file for authentication.
--dry-run Simulate container creation without execution.
"
# --- Default Parameters (Environment Variables) ---
# Proxmox Server
PVE_HOST="${PVE_HOST:-}"
PVE_USER="${PVE_USER:-admin}"
PVE_PORT="${PVE_PORT:-22}"
PVE_PASSWORD="${PVE_PASSWORD:-}"
PVE_SSH_KEY="${PVE_SSH_KEY:-}"
DRY_RUN="${DRY_RUN:-false}"
# LXC Container
TEMPLATE="${TEMPLATE:-local:vztmpl/nixos-unstable-amd64-default_20260428}"
ROOTFS_SIZE="${ROOTFS_SIZE:-8G}"
CORES="${CORES:-2}"
MEMORY="${MEMORY:-2048}"
SWAP="${SWAP:-1024}"
PASSWORD="${PASSWORD:-changeme}"
BRIDGE="${BRIDGE:-vmbr0}"
VLAN="${VLAN:-}"
DOMAIN="${DOMAIN:-lagraula.fr}"
UNPRIVILEGED="${UNPRIVILEGED:-0}"
IP="${IP:-}"
CMODE="${CMODE:-console}"
TAGS="${TAGS:-}"
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
# --- Parse Arguments with docopts (Lowest Priority) ---
args=$(docopts -h "$usage" : "$@")
eval "$args"
# Short name of the machine (mandatory parameter)
SHORT_NAME="${argv[0]:-}"
if [ -z "$SHORT_NAME" ]; then
echo "❌ Error: The short name of the machine is required." >&2
echo "$usage" >&2
exit 1
fi
# --- Override with /etc/nixos-infra/hosts/<short_name> (Medium Priority)
if [ -f "/etc/nixos-infra/hosts/$SHORT_NAME" ]; then
echo "📄 Applying parameters from /etc/nixos-infra/hosts/$SHORT_NAME..."
set -a
source "/etc/nixos-infra/hosts/$SHORT_NAME"
set +a
fi
# --- Override with ./<short_name> (Medium Priority) ---
if [ -f "./$SHORT_NAME" ]; then
echo "📄 Applying parameters from ./$SHORT_NAME..."
set -a
source "./$SHORT_NAME"
set +a
fi
# --- Apply Command-Line Arguments (Highest Priority) ---
eval "$args"
# --- SSH Key Default Logic ---
if [ "$PVE_SSH_KEY" = "default" ]; then
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
elif [ -z "$PVE_SSH_KEY" ] && [ -z "$PVE_PASSWORD" ]; then
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
fi
# --- Critical Parameters Validation ---
if [ -z "$TEMPLATE" ] || [ -z "$ROOTFS_SIZE" ] || [ -z "$CORES" ] || \
[ -z "$MEMORY" ] || [ -z "$SWAP" ] || [ -z "$PASSWORD" ] || \
[ -z "$BRIDGE" ] || [ -z "$DOMAIN" ] || [ -z "$UNPRIVILEGED" ] || \
[ -z "$CMODE" ] || [ -z "$SSH_PUBLIC_KEYS" ] || \
[ -z "$PVE_HOST" ] || [ -z "$PVE_USER" ] || [ -z "$PVE_PORT" ]; then
echo "❌ Error: One or more critical parameters are missing." >&2
exit 1
fi
# Authentication Validation
if [ -z "$PVE_PASSWORD" ]; then
if [ -z "$PVE_SSH_KEY" ]; then
echo "❌ Error: No authentication parameter is defined." >&2
exit 1
elif [ ! -f "$PVE_SSH_KEY" ]; then
echo "❌ Error: SSH key file '$PVE_SSH_KEY' does not exist." >&2
exit 1
fi
fi
# --- SSH Connection to Proxmox Server ---
run_proxmox() {
local ssh_cmd="ssh -p $PVE_PORT"
if [ -n "$PVE_SSH_KEY" ] && [ -f "$PVE_SSH_KEY" ]; then
ssh_cmd="$ssh_cmd -i $PVE_SSH_KEY"
else
ssh_cmd="$ssh_cmd -o PreferredAuthentications=password \
-o StrictHostKeyChecking=no"
fi
$ssh_cmd "$PVE_USER@$PVE_HOST" "$1"
}
# --- Network Options Construction ---
NET_OPTS="name=eth0,bridge=$BRIDGE"
if [ -n "$VLAN" ]; then
NET_OPTS="$NET_OPTS,$VLAN"
fi
if [ -n "$IP" ]; then
NET_OPTS="$NET_OPTS,ip=$IP"
fi
# --- Container Creation ---
echo "🚀 Creating LXC container $SHORT_NAME on $PVE_HOST..."
CREATE_CMD="pct create $ROOTFS_SIZE $TEMPLATE --cores $CORES \
--memory $MEMORY --swap $SWAP --hostname $SHORT_NAME.$DOMAIN \
--password $PASSWORD --unprivileged $UNPRIVILEGED --net0 $NET_OPTS \
--onboot 1 --cmode $CMODE --ssh-public-keys $SSH_PUBLIC_KEYS"
if [ -n "$TAGS" ]; then
CREATE_CMD="$CREATE_CMD --tags $TAGS"
fi
# Display the command (with password masked)
DISPLAY_CMD=$(echo "$CREATE_CMD" |
sed "s/--password [^ ]*/--password \*\*\*\*\*/g")
echo "🔧 Command to execute on $PVE_HOST: $DISPLAY_CMD"
# Execute or simulate
if [ "$DRY_RUN" = "true" ]; then
echo "🧪 Dry run: Skipping actual execution."
else
LXC_ID=$(run_proxmox "$CREATE_CMD" | grep -oP '\d+')
if [ -z "$LXC_ID" ]; then
echo "❌ Error: Failed to create the container." >&2
exit 1
fi
echo "✅ LXC container $SHORT_NAME created successfully (ID: $LXC_ID)."
fi