diff --git a/nixos-infra/scripts/create-lxc-nixos.sh b/nixos-infra/scripts/create-lxc-nixos.sh index e69de29..2dcd517 100644 --- a/nixos-infra/scripts/create-lxc-nixos.sh +++ b/nixos-infra/scripts/create-lxc-nixos.sh @@ -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 [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/ (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 ./ (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 \ No newline at end of file