Initial framework: reusable modules, lib, pkgs, overlays, scripts, sample environment
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Scripts
|
||||
|
||||
Utility scripts for infrastructure management.
|
||||
Covers deployment, LXC container creation and bootstrap,
|
||||
initial configuration of new NixOS machines, and age key generation.
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### `create-lxc-nixos.sh` — Create and deploy a NixOS LXC container
|
||||
|
||||
Creates a NixOS LXC container on a remote Proxmox VE hypervisor, then
|
||||
bootstraps it with the initial NixOS configuration and runs `deploy.sh`
|
||||
to apply the host-specific configuration.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./create-lxc-nixos.sh <short_name> [options]
|
||||
|
||||
# Example: create dns01 with static IPv4 and IPv6 token
|
||||
./create-lxc-nixos.sh dns01 \
|
||||
--ip 10.40.0.10/24 \
|
||||
--ip6 ::a:b:c:d \
|
||||
--pve-host pve01.prod.lagraula.fr
|
||||
|
||||
# Dry run to preview the commands
|
||||
./create-lxc-nixos.sh dns01 --dry-run
|
||||
```
|
||||
|
||||
**Bootstrap process:**
|
||||
1. `pct create` — create the container from the NixOS template
|
||||
2. `pct start <CT_ID>` — start the container
|
||||
3. Wait for the container to be ready (polling `pct exec`)
|
||||
4. `pct push initial-lxc-configuration.nix` → `/etc/nixos/configuration.nix`
|
||||
5. `pct push deploy.sh` → `/usr/local/bin/deploy-nixos`
|
||||
6. `pct exec nixos-rebuild switch` — apply initial config (SSH, git, curl)
|
||||
7. `pct exec deploy-nixos` — clone repo and apply host-specific config
|
||||
|
||||
### `deploy.sh` — Deploy NixOS configuration from Git repository
|
||||
|
||||
Clones or updates the nixos-infra repository, detects the hostname,
|
||||
finds the corresponding configuration file, and applies it with
|
||||
`nixos-rebuild switch`.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./deploy.sh [options]
|
||||
|
||||
# Options
|
||||
-u, --repo-url URL Git repository URL (default: https://gitea.lagraula.fr/...)
|
||||
-d, --repo-dir DIR Local directory (default: /etc/nixos-infra)
|
||||
-b, --branch BRANCH Git branch (default: main)
|
||||
-n, --dry-run Simulate without making changes
|
||||
```
|
||||
|
||||
**Configuration lookup order:**
|
||||
1. `hosts/servers/<hostname>/configuration.nix`
|
||||
2. `hosts/workstations/<hostname>/configuration.nix`
|
||||
|
||||
### `initial-lxc-configuration.nix` — Bootstrap NixOS configuration (LXC)
|
||||
|
||||
Minimal NixOS configuration pushed to a new LXC container during the
|
||||
bootstrap phase. Installs SSH, git, and curl so the container can
|
||||
clone the repository and apply its specific configuration.
|
||||
|
||||
**Pushed to `/etc/nixos/configuration.nix` by `create-lxc-nixos.sh`.**
|
||||
|
||||
### `gen-secrets-keys.sh` — Generate age public keys for agenix
|
||||
|
||||
Connects to each host in the infrastructure, retrieves its SSH host
|
||||
key via `ssh-keyscan`, converts it to an age public key with
|
||||
`ssh-to-age`, and stores it in `secrets/pubkeys/<hostname>.age`.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./gen-secrets-keys.sh
|
||||
|
||||
# Prerequisites
|
||||
# nix-shell -p ssh-to-age
|
||||
```
|
||||
|
||||
**After generating keys, encrypt secrets with:**
|
||||
```bash
|
||||
age -r $(cat secrets/pubkeys/<hostname>.age) -o secrets/<name>.age
|
||||
agenix -e secrets/<name>.age
|
||||
```
|
||||
|
||||
### `update-nixpkgs.sh` — Update the nixpkgs pin
|
||||
|
||||
Updates `pkgs/nixpkgs.json` with the latest commit from nixpkgs stable.
|
||||
|
||||
## Deployment workflow (LXC containers)
|
||||
|
||||
```
|
||||
create-lxc-nixos.sh # Step 1: Create + bootstrap
|
||||
└─ pct create
|
||||
└─ pct push initial-lxc-configuration.nix
|
||||
└─ pct push deploy.sh
|
||||
└─ pct exec nixos-rebuild switch
|
||||
└─ pct exec deploy.sh # Step 2: Clone repo + apply config
|
||||
└─ git clone
|
||||
└─ nixos-rebuild switch (host-specific)
|
||||
```
|
||||
|
||||
For subsequent updates on an already-deployed container:
|
||||
```bash
|
||||
ssh <hostname>
|
||||
sudo /usr/local/bin/deploy-nixos
|
||||
Executable
+325
@@ -0,0 +1,325 @@
|
||||
#!/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, bootstrap and deploy a NixOS LXC container on a remote Proxmox VE 9 server.
|
||||
|
||||
Usage:
|
||||
$0 <short_name> [options]
|
||||
$0 -h|--help
|
||||
|
||||
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 IPv4 address (e.g. 192.168.1.100/24).
|
||||
--ip6 TOKEN IPv6 token for SLAAC (e.g. ::1:2:3:4).
|
||||
-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-ssh-key KEY SSH key file for authentication.
|
||||
--initial-config FILE Initial NixOS configuration file to push
|
||||
[default: ./initial-lxc-configuration.nix].
|
||||
--repo-url URL Git repository URL for deploy.sh
|
||||
[default: (none, must be provided)].
|
||||
--branch BRANCH Git branch for deploy.sh [default: main].
|
||||
--environment ENV Environment name (production, dev, etc.)
|
||||
[default: (none, must be provided or set via config)].
|
||||
--skip-deploy Skip the post-creation bootstrap (push + nixos-rebuild).
|
||||
--dry-run Simulate container creation without execution.
|
||||
|
||||
Optional configuration files (loaded in order, later overrides earlier):
|
||||
/etc/nixos-infra/hosts/config
|
||||
\${XDG_CONFIG_HOME}/nixos-infra/hosts/config
|
||||
./config
|
||||
"
|
||||
|
||||
# --- Default Parameters (Environment Variables) ---
|
||||
# Proxmox Server
|
||||
PVE_HOST="${PVE_HOST:-}"
|
||||
PVE_USER="${PVE_USER:-admin}"
|
||||
PVE_PORT="${PVE_PORT:-22}"
|
||||
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:-}"
|
||||
UNPRIVILEGED="${UNPRIVILEGED:-0}"
|
||||
IP="${IP:-}"
|
||||
IP6="${IP6:-}"
|
||||
CMODE="${CMODE:-console}"
|
||||
TAGS="${TAGS:-}"
|
||||
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
||||
|
||||
# Bootstrap
|
||||
INITIAL_CONFIG="${INITIAL_CONFIG:-./initial-lxc-configuration.nix}"
|
||||
REPO_URL="${REPO_URL:-}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
||||
ENVIRONMENT="${ENVIRONMENT:-}"
|
||||
|
||||
# --- Parse Arguments with docopts (Highest priority) ---
|
||||
# set +e is to prevent set -e from eating the error message from docopts.
|
||||
# This code is up here to prevent useless error messages to be printed
|
||||
# in case the "-h" or "--help" argument is used.
|
||||
set +e
|
||||
args=$(docopts -h "$usage" : "$@")
|
||||
eval "$args"
|
||||
set -e
|
||||
|
||||
# --- Apply Configuration Files (by increasing priority) ---
|
||||
XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
|
||||
CONFIG_FILES=(\
|
||||
"/etc/nixos-infra/hosts/config" \
|
||||
"$XDG_CONFIG_HOME/nixos-infra/hosts/config" \
|
||||
"./config")
|
||||
for conffile in ${CONFIG_FILES[*]}; do
|
||||
if [ -f "$conffile" ]; then
|
||||
echo "📄 Applying parameters from $conffile..."
|
||||
set -a
|
||||
source "$conffile"
|
||||
set +a
|
||||
else
|
||||
echo "ℹ️ $conffile not found (optional)."
|
||||
fi
|
||||
done
|
||||
|
||||
# Override with CLI arguments (have priority over config files)
|
||||
PVE_HOST="${pve_host:-$PVE_HOST}"
|
||||
PVE_USER="${pve_user:-$PVE_USER}"
|
||||
PVE_PORT="${pve_port:-$PVE_PORT}"
|
||||
PVE_SSH_KEY="${pve_ssh_key:-$PVE_SSH_KEY}"
|
||||
DRY_RUN="${dry_run:-$DRY_RUN}"
|
||||
|
||||
TEMPLATE="${template:-$TEMPLATE}"
|
||||
ROOTFS_SIZE="${rootfs_size:-$ROOTFS_SIZE}"
|
||||
CORES="${cores:-$CORES}"
|
||||
MEMORY="${memory:-$MEMORY}"
|
||||
SWAP="${swap:-$SWAP}"
|
||||
PASSWORD="${password:-$PASSWORD}"
|
||||
BRIDGE="${bridge:-$BRIDGE}"
|
||||
VLAN="${vlan:-$VLAN}"
|
||||
DOMAIN="${domain:-$DOMAIN}"
|
||||
UNPRIVILEGED="${unprivileged:-$UNPRIVILEGED}"
|
||||
IP="${ip:-$IP}"
|
||||
IP6="${ip6:-$IP6}"
|
||||
CMODE="${cmode:-$CMODE}"
|
||||
TAGS="${tags:-$TAGS}"
|
||||
SSH_PUBLIC_KEYS="${ssh_public_keys:-$SSH_PUBLIC_KEYS}"
|
||||
|
||||
INITIAL_CONFIG="${initial_config:-$INITIAL_CONFIG}"
|
||||
REPO_URL="${repo_url:-$REPO_URL}"
|
||||
BRANCH="${branch:-$BRANCH}"
|
||||
SKIP_DEPLOY="${skip_deploy:-$SKIP_DEPLOY}"
|
||||
ENVIRONMENT="${environment:-$ENVIRONMENT}"
|
||||
|
||||
# --- SSH Key Default Logic ---
|
||||
if [ "$PVE_SSH_KEY" = "default" ]; then
|
||||
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
|
||||
fi
|
||||
|
||||
# --- Critical Parameters Validation ---
|
||||
mandatory_params=(
|
||||
"TEMPLATE"
|
||||
"ROOTFS_SIZE"
|
||||
"CORES"
|
||||
"MEMORY"
|
||||
"SWAP"
|
||||
"PASSWORD"
|
||||
"BRIDGE"
|
||||
"DOMAIN"
|
||||
"UNPRIVILEGED"
|
||||
"CMODE"
|
||||
"SSH_PUBLIC_KEYS"
|
||||
"PVE_HOST"
|
||||
"PVE_USER"
|
||||
"PVE_PORT"
|
||||
)
|
||||
missing_params=()
|
||||
for param in ${mandatory_params[*]}; do
|
||||
if [ -z "${!param}" ]; then missing_params+=("$param"); fi
|
||||
done
|
||||
if [ ${#missing_params[@]} -gt 0 ]; then
|
||||
echo "❌ Error: The following necessary parameters are missing: ${missing_params[*]}" >&2
|
||||
echo "❌ Error: Please provide them through a config file or the command line." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Authentication Validation
|
||||
if [ ! -f "$PVE_SSH_KEY" ]; then
|
||||
echo "❌ Error: SSH key file '$PVE_SSH_KEY' does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate initial-config.nix exists (unless --skip-deploy)
|
||||
if [ "$SKIP_DEPLOY" != "true" ] && [ ! -f "$INITIAL_CONFIG" ]; then
|
||||
echo "❌ Error: Initial NixOS configuration '$INITIAL_CONFIG' not found." >&2
|
||||
echo " Provide a valid path with --initial-config or use --skip-deploy." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate deploy.sh exists (unless --skip-deploy)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DEPLOY_SCRIPT="${SCRIPT_DIR}/deploy.sh"
|
||||
if [ "$SKIP_DEPLOY" != "true" ] && [ ! -f "$DEPLOY_SCRIPT" ]; then
|
||||
echo "❌ Error: deploy.sh not found at '$DEPLOY_SCRIPT'." >&2
|
||||
echo " The bootstrap phase requires deploy.sh to be present." >&2
|
||||
exit 1
|
||||
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 "
|
||||
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
|
||||
# IPv6: use SLAAC with a token if provided, otherwise DHCP
|
||||
if [ -n "$IP6" ]; then
|
||||
NET_OPTS="$NET_OPTS,ip6=auto,token6=${IP6}"
|
||||
else
|
||||
NET_OPTS="$NET_OPTS,ip6=dhcp"
|
||||
fi
|
||||
|
||||
# --- Container Creation ---
|
||||
echo "🚀 Creating LXC container $short_name on $PVE_HOST (domain: $DOMAIN)..."
|
||||
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 0 --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 mode:"
|
||||
echo " - Container creation skipped"
|
||||
echo " - Bootstrap phase skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
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)."
|
||||
|
||||
# --- Bootstrap Phase (unless --skip-deploy) ---
|
||||
if [ "$SKIP_DEPLOY" = "true" ]; then
|
||||
echo "⏭️ --skip-deploy set. Container created but not bootstrapped."
|
||||
echo " Start it manually with: pct start $LXC_ID"
|
||||
echo " Then apply a configuration manually."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🚀 Starting bootstrap phase for CT $LXC_ID..."
|
||||
|
||||
# 1. Start the container
|
||||
echo "▶️ Starting container $LXC_ID..."
|
||||
run_proxmox "pct start $LXC_ID" || {
|
||||
echo "❌ Error: Failed to start container $LXC_ID." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 2. Wait for the container to be ready (SSH or pct exec available)
|
||||
echo "⏳ Waiting for container to be ready..."
|
||||
for i in $(seq 1 30); do
|
||||
if run_proxmox "pct exec $LXC_ID -- true" 2>/dev/null; then
|
||||
echo "✅ Container $LXC_ID is ready."
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 30 ]; then
|
||||
echo "❌ Error: Container $LXC_ID did not become ready in time." >&2
|
||||
echo " You can retry bootstrap manually." >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 3. Push initial-lxc-configuration.nix
|
||||
echo "📄 Pushing initial NixOS configuration..."
|
||||
run_proxmox "pct push $LXC_ID '$INITIAL_CONFIG' /etc/nixos/configuration.nix" || {
|
||||
echo "❌ Error: Failed to push initial configuration." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 4. Push deploy.sh
|
||||
echo "📄 Pushing deploy script..."
|
||||
run_proxmox "pct push $LXC_ID '$DEPLOY_SCRIPT' /usr/local/bin/deploy-nixos" || {
|
||||
echo "❌ Error: Failed to push deploy script." >&2
|
||||
exit 1
|
||||
}
|
||||
run_proxmox "pct exec $LXC_ID -- chmod +x /usr/local/bin/deploy-nixos" || {
|
||||
echo "❌ Error: Failed to make deploy script executable." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 5. Apply initial configuration (nixos-rebuild switch)
|
||||
echo "⚙️ Applying initial NixOS configuration (this may take a while)..."
|
||||
if ! run_proxmox "pct exec $LXC_ID -- nixos-rebuild switch" 2>&1; then
|
||||
echo "⚠️ Warning: Initial nixos-rebuild may have issues." >&2
|
||||
echo " Check the container manually: pct exec $LXC_ID -- nixos-rebuild switch" >&2
|
||||
# Continue anyway — deploy.sh might still work
|
||||
fi
|
||||
echo "✅ Initial configuration applied."
|
||||
|
||||
# 6. Run deploy.sh to clone the repo and apply the specific configuration
|
||||
echo "🌐 Running deploy.sh to clone repo and apply specific configuration..."
|
||||
# Pass REPO_URL, BRANCH and ENVIRONMENT as env vars to deploy.sh inside the container
|
||||
DEPLOY_CMD="REPO_URL='$REPO_URL' BRANCH='$BRANCH' ENVIRONMENT='$ENVIRONMENT' /usr/local/bin/deploy-nixos"
|
||||
if ! run_proxmox "pct exec $LXC_ID -- bash -c '$DEPLOY_CMD'" 2>&1; then
|
||||
echo "⚠️ Warning: deploy.sh encountered issues." >&2
|
||||
echo " You can retry manually: pct exec $LXC_ID -- /usr/local/bin/deploy-nixos" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🎉 Container $short_name (CT $LXC_ID) successfully created and deployed!"
|
||||
echo " Connect with: ssh root@${IP%%/*} (or use pct exec $LXC_ID)"
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- Default values (can be overridden by environment variables) ---
|
||||
REPO_URL="${REPO_URL:-}"
|
||||
REPO_DIR="${REPO_DIR:-/etc/nixos-infra}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
DRY_RUN="${DRY_RUN:-false}"
|
||||
|
||||
# --- Usage ---
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Deploy NixOS configuration from the nixos-infra repository.
|
||||
|
||||
Usage:
|
||||
$0 [options]
|
||||
|
||||
Options:
|
||||
-u, --repo-url URL Git repository URL
|
||||
[default: ${REPO_URL}]
|
||||
-d, --repo-dir DIR Local directory for the repository
|
||||
[default: ${REPO_DIR}]
|
||||
-b, --branch BRANCH Git branch to deploy
|
||||
[default: ${BRANCH}]
|
||||
-n, --dry-run Simulate deployment without making changes.
|
||||
-h, --help Show this help message.
|
||||
|
||||
Environment variables:
|
||||
REPO_URL, REPO_DIR, BRANCH, DRY_RUN (same as options above).
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Parse arguments ---
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-u|--repo-url) REPO_URL="$2"; shift 2 ;;
|
||||
-d|--repo-dir) REPO_DIR="$2"; shift 2 ;;
|
||||
-b|--branch) BRANCH="$2"; shift 2 ;;
|
||||
-n|--dry-run) DRY_RUN="true"; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "❌ Unknown option: $1" >&2; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
HOSTNAME=$(hostname)
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "❌ This script must be run as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Dry run mode ---
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "🧪 Dry run mode:"
|
||||
echo " - Repository URL: $REPO_URL"
|
||||
echo " - Repository dir: $REPO_DIR"
|
||||
echo " - Branch: $BRANCH"
|
||||
echo " - Hostname: $HOSTNAME"
|
||||
echo " - Expected config: $REPO_DIR/environments/<env>/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
echo ""
|
||||
echo " Would execute:"
|
||||
echo " git clone --branch $BRANCH $REPO_URL $REPO_DIR"
|
||||
echo " nixos-rebuild switch -I nixos-config=...$HOSTNAME/configuration.nix"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Clone or update the repository ---
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
echo "🔄 Mise à jour du dépôt dans $REPO_DIR..."
|
||||
cd "$REPO_DIR"
|
||||
git fetch origin
|
||||
git checkout "$BRANCH"
|
||||
git pull origin "$BRANCH"
|
||||
else
|
||||
echo "📥 Clonage du dépôt dans $REPO_DIR..."
|
||||
mkdir -p "$REPO_DIR"
|
||||
git clone --branch "$BRANCH" "$REPO_URL" "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# --- Find the configuration for this machine ---
|
||||
ENVIRONMENT="${ENVIRONMENT:-}"
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
# Try common environment names
|
||||
for env in production prod staging stage dev development; do
|
||||
if [ -d "$REPO_DIR/environments/$env" ]; then
|
||||
ENVIRONMENT="$env"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$ENVIRONMENT" ]; then
|
||||
echo "❌ Error: No environment specified and none detected." >&2
|
||||
echo " Set ENVIRONMENT environment variable or use --environment flag." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CONFIG_PATH="$REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
CONFIG_PATH="$REPO_DIR/environments/$ENVIRONMENT/hosts/workstations/$HOSTNAME/configuration.nix"
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
echo "❌ Error : No configuration found for $HOSTNAME in environment '$ENVIRONMENT'" >&2
|
||||
echo " Checked paths :" >&2
|
||||
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
||||
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/workstations/$HOSTNAME/configuration.nix" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Apply the configuration ---
|
||||
echo "🚀 Deploying the configuration for $HOSTNAME..."
|
||||
nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
|
||||
|
||||
echo "✅ Deployment was successful !"
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- gen-secrets-keys.sh ---
|
||||
# Generate age public keys from SSH host keys for all known hosts.
|
||||
#
|
||||
# This script retrieves each host's SSH host key, converts it to an
|
||||
# age public key using ssh-to-age, and stores it in
|
||||
# secrets/pubkeys/<hostname>.age for use with agenix.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
PUBKEYS_DIR="${PROJECT_DIR}/secrets/pubkeys"
|
||||
|
||||
# Ensure ssh-to-age is available
|
||||
if ! command -v ssh-to-age &> /dev/null; then
|
||||
echo "❌ Error: 'ssh-to-age' is required."
|
||||
echo " Install it with: nix-shell -p ssh-to-age"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$PUBKEYS_DIR"
|
||||
|
||||
echo "🔑 Generating age public keys from SSH host keys..."
|
||||
echo " Output directory: $PUBKEYS_DIR"
|
||||
echo ""
|
||||
|
||||
# Known hosts (hostname, user@host, ssh port)
|
||||
# Add entries as hosts are deployed in the infrastructure
|
||||
HOSTS=(
|
||||
# Hypervisors
|
||||
# "pve01:root@pve01.prod.lagraula.fr:22"
|
||||
# "pve02:root@pve02.prod.lagraula.fr:22"
|
||||
# LXC containers (once deployed)
|
||||
# "dns01:root@dns01.lagraula.fr:22"
|
||||
# "gitea01:root@gitea01.lagraula.fr:22"
|
||||
# "vault01:root@vault01.lagraula.fr:22"
|
||||
# "rp01:root@rp01.lagraula.fr:22"
|
||||
# Workstations
|
||||
# "sting:root@sting.lagraula.fr:22"
|
||||
)
|
||||
|
||||
if [ ${#HOSTS[@]} -eq 0 ]; then
|
||||
echo "⚠️ No hosts configured. Edit the HOSTS array in this script first."
|
||||
echo ""
|
||||
echo "For a single host, you can also run manually:"
|
||||
echo " ssh-keyscan <host> 2>/dev/null | grep ed25519 | awk '{print \$3}' | ssh-to-age > $PUBKEYS_DIR/<hostname>.age"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for entry in "${HOSTS[@]}"; do
|
||||
IFS=':' read -r hostname ssh_user_port <<< "$entry"
|
||||
IFS='@' read -r ssh_user ssh_host <<< "$ssh_user_port"
|
||||
|
||||
echo "🖥️ Processing $hostname ($ssh_user@$ssh_host)..."
|
||||
|
||||
age_key=$(ssh-keyscan -t ed25519 "$ssh_host" 2>/dev/null | \
|
||||
grep "ed25519" | \
|
||||
awk '{print $3}' | \
|
||||
ssh-to-age 2>/dev/null || true)
|
||||
|
||||
if [ -z "$age_key" ]; then
|
||||
echo " ⚠️ Could not retrieve age key for $hostname. Skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "$age_key" > "$PUBKEYS_DIR/$hostname.age"
|
||||
echo " ✅ Saved age public key: $age_key"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "🎉 Done! Generated $(ls -1 "$PUBKEYS_DIR"/*.age 2>/dev/null | wc -l) key(s)."
|
||||
echo ""
|
||||
echo "To encrypt a secret for specific hosts:"
|
||||
echo " age -r \$(cat $PUBKEYS_DIR/<hostname>.age) -o secrets/<name>.age"
|
||||
echo ""
|
||||
echo "Or with agenix:"
|
||||
echo " agenix -e secrets/<name>.age"
|
||||
@@ -0,0 +1,27 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Install Git, curl, and other required tools
|
||||
environment.systemPackages = with pkgs; [ git curl ];
|
||||
|
||||
# Enable SSH for initial deployment
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
permitRootLogin = "yes";
|
||||
passwordAuthentication = true;
|
||||
};
|
||||
|
||||
# Clone the repository so deploy.sh can use it
|
||||
system.activationScripts.setup-deploy = ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Create the target directory
|
||||
mkdir -p /etc/nixos-infra
|
||||
|
||||
# The deploy script has already been pushed to /usr/local/bin/deploy-nixos
|
||||
# by create-lxc-nixos.sh; it will clone the repo and apply the config.
|
||||
'';
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Met à jour le commit de référence pour Nixpkgs
|
||||
|
||||
BRANCH="nixos-25.11"
|
||||
REPO="https://github.com/NixOS/nixpkgs"
|
||||
JSON_FILE="$(dirname "$0")/../pkgs/nixpkgs.json"
|
||||
|
||||
echo "Récupération du dernier commit sur $BRANCH..."
|
||||
REV=$(git ls-remote $REPO refs/heads/$BRANCH | cut -f1)
|
||||
|
||||
if [ -z "$REV" ]; then
|
||||
echo "Erreur : Impossible de récupérer le commit."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Calcul du hash (cela peut prendre un moment)..."
|
||||
SHA256=$(nix-prefetch-url --unpack "https://github.com/NixOS/nixpkgs/archive/$REV.tar.gz")
|
||||
|
||||
cat <<EOF > "$JSON_FILE"
|
||||
{
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/$REV.tar.gz",
|
||||
"rev": "$REV",
|
||||
"sha256": "$SHA256"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Succès ! Nixpkgs est maintenant épinglé au commit : $REV"
|
||||
Reference in New Issue
Block a user