First attempt at LXC container deployment chain.
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
options.secrets = {
|
||||
enable = lib.mkEnableOption "agenix secret management";
|
||||
|
||||
identity = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/etc/ssh/ssh_host_ed25519_key";
|
||||
description = "Path to the SSH host private key used for age decryption.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.secrets.enable {
|
||||
age = {
|
||||
identityPaths = [ config.secrets.identity ];
|
||||
secrets = { };
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [ agenix ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
self: super: {
|
||||
# Custom packages and overrides for nixos-infra
|
||||
# agenix is already available in nixpkgs — no custom overlay needed.
|
||||
}
|
||||
@@ -1,4 +1,107 @@
|
||||
# Scripts
|
||||
|
||||
Utility scripts for infrastructure management.
|
||||
Covers deployment, LXC container creation, and
|
||||
initial bootstrap of new NixOS machines.
|
||||
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-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-configuration.nix` — Bootstrap NixOS configuration
|
||||
|
||||
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 unstable.
|
||||
|
||||
## Deployment workflow (LXC containers)
|
||||
|
||||
```
|
||||
create-lxc-nixos.sh # Step 1: Create + bootstrap
|
||||
└─ pct create
|
||||
└─ pct push initial-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
|
||||
@@ -10,35 +10,42 @@ if ! command -v docopts &> /dev/null; then
|
||||
fi
|
||||
|
||||
# --- Usage and Documentation ---
|
||||
usage="Create and configure an LXC container on a remote Proxmox VE 9 server.
|
||||
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 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-ssh-key KEY SSH key file for authentication.
|
||||
--dry-run Simulate container creation without execution.
|
||||
-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-configuration.nix].
|
||||
--repo-url URL Git repository URL for deploy.sh
|
||||
[default: https://gitea.lagraula.fr/xavier/nixos-infra.git].
|
||||
--branch BRANCH Git branch for deploy.sh [default: main].
|
||||
--skip-deploy Skip the post-creation bootstrap (push + nixos-rebuild).
|
||||
--dry-run Simulate container creation without execution.
|
||||
|
||||
Optional configuration files:
|
||||
Optional configuration files (loaded in order, later overrides earlier):
|
||||
/etc/nixos-infra/hosts/config
|
||||
\${XDG_CONFIG_HOME}/nixos-infra/hosts/config
|
||||
./config
|
||||
@@ -64,10 +71,17 @@ VLAN="${VLAN:-}"
|
||||
DOMAIN="${DOMAIN:-lagraula.fr}"
|
||||
UNPRIVILEGED="${UNPRIVILEGED:-0}"
|
||||
IP="${IP:-}"
|
||||
IP6="${IP6:-}"
|
||||
CMODE="${CMODE:-console}"
|
||||
TAGS="${TAGS:-}"
|
||||
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
||||
|
||||
# Bootstrap
|
||||
INITIAL_CONFIG="${INITIAL_CONFIG:-./initial-configuration.nix}"
|
||||
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
||||
|
||||
# --- 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
|
||||
@@ -90,18 +104,17 @@ for conffile in ${CONFIG_FILES[*]}; do
|
||||
source "$conffile"
|
||||
set +a
|
||||
else
|
||||
echo "❌ $conffile not found."
|
||||
echo "ℹ️ $conffile not found (optional)."
|
||||
fi
|
||||
done
|
||||
|
||||
# Proxmox Server
|
||||
# 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}"
|
||||
|
||||
# LXC Container
|
||||
TEMPLATE="${template:-$TEMPLATE}"
|
||||
ROOTFS_SIZE="${rootfs_size:-$ROOTFS_SIZE}"
|
||||
CORES="${cores:-$CORES}"
|
||||
@@ -113,10 +126,16 @@ 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}"
|
||||
|
||||
# --- SSH Key Default Logic ---
|
||||
if [ "$PVE_SSH_KEY" = "default" ]; then
|
||||
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
|
||||
@@ -124,19 +143,19 @@ fi
|
||||
|
||||
# --- Critical Parameters Validation ---
|
||||
mandatory_params=(
|
||||
"TEMPLATE" \
|
||||
"ROOTFS_SIZE" \
|
||||
"CORES" \
|
||||
"MEMORY" \
|
||||
"SWAP" \
|
||||
"PASSWORD" \
|
||||
"BRIDGE" \
|
||||
"DOMAIN" \
|
||||
"UNPRIVILEGED" \
|
||||
"CMODE" \
|
||||
"SSH_PUBLIC_KEYS" \
|
||||
"PVE_HOST" \
|
||||
"PVE_USER" \
|
||||
"TEMPLATE"
|
||||
"ROOTFS_SIZE"
|
||||
"CORES"
|
||||
"MEMORY"
|
||||
"SWAP"
|
||||
"PASSWORD"
|
||||
"BRIDGE"
|
||||
"DOMAIN"
|
||||
"UNPRIVILEGED"
|
||||
"CMODE"
|
||||
"SSH_PUBLIC_KEYS"
|
||||
"PVE_HOST"
|
||||
"PVE_USER"
|
||||
"PVE_PORT"
|
||||
)
|
||||
missing_params=()
|
||||
@@ -145,7 +164,7 @@ for param in ${mandatory_params[*]}; do
|
||||
done
|
||||
if [ ${#missing_params[@]} -gt 0 ]; then
|
||||
echo "❌ Error: The following necessary parameters are missing: ${missing_params[*]}" >&2
|
||||
echo "❌ Error: Plesase provide them through one the proposed config file or the command line." >&2
|
||||
echo "❌ Error: Please provide them through a config file or the command line." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -155,6 +174,22 @@ if [ ! -f "$PVE_SSH_KEY" ]; then
|
||||
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"
|
||||
@@ -174,9 +209,15 @@ fi
|
||||
if [ -n "$IP" ]; then
|
||||
NET_OPTS="$NET_OPTS,ip=$IP"
|
||||
fi
|
||||
set -x
|
||||
# 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..."
|
||||
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 \
|
||||
@@ -192,12 +233,89 @@ 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
|
||||
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
|
||||
echo "✅ LXC container $short_name created successfully (ID: $LXC_ID)."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 3. Push initial-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 and BRANCH as environment variables to deploy.sh inside the container
|
||||
DEPLOY_CMD="REPO_URL='$REPO_URL' BRANCH='$BRANCH' /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)"
|
||||
@@ -1,42 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="https://gitea.lagraula.fr/xavier/nixos-infra.git"
|
||||
REPO_DIR="/etc/nixos-infra"
|
||||
BRANCH="main"
|
||||
# --- Default values (can be overridden by environment variables) ---
|
||||
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
||||
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 "Ce script doit être exécuté en tant que root." >&2
|
||||
echo "❌ This script must be run as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cloner ou mettre à jour le dépôt
|
||||
# --- 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/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..."
|
||||
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..."
|
||||
echo "📥 Clonage du dépôt dans $REPO_DIR..."
|
||||
mkdir -p "$REPO_DIR"
|
||||
git clone --branch "$BRANCH" "$REPO_URL" "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# Trouver la configuration pour cette machine
|
||||
# --- Find the configuration for this machine ---
|
||||
CONFIG_PATH="$REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
CONFIG_PATH="$REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix"
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
echo "Erreur : Aucune configuration trouvée pour $HOSTNAME dans $REPO_DIR" >&2
|
||||
echo "❌ Error : No configuration found for $HOSTNAME in $REPO_DIR" >&2
|
||||
echo " Checked paths :" >&2
|
||||
echo " - $REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
||||
echo " - $REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Appliquer la configuration
|
||||
echo "Déploiement de la configuration pour $HOSTNAME..."
|
||||
# --- Apply the configuration ---
|
||||
echo "🚀 Deploying the configuration for $HOSTNAME..."
|
||||
nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
|
||||
|
||||
echo "Déploiement terminé avec succès !"
|
||||
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"
|
||||
@@ -4,29 +4,24 @@
|
||||
# Install Git, curl, and other required tools
|
||||
environment.systemPackages = with pkgs; [ git curl ];
|
||||
|
||||
# Enable unsecured SSH for initial deployment
|
||||
# Enable SSH for initial deployment
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
permitRootLogin = "yes";
|
||||
passwordAuthentication = true;
|
||||
};
|
||||
|
||||
# Deployment script
|
||||
# Clone the repository so deploy.sh can use it
|
||||
system.activationScripts.setup-deploy = ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Télécharger le script de déploiement depuis Gitea
|
||||
curl -o /usr/local/bin/deploy-nixos https://gitea.lagraula.fr/xavier/nixos-infra/raw/main/scripts/deploy.sh
|
||||
chmod +x /usr/local/bin/deploy-nixos
|
||||
|
||||
# Cloner le dépôt (si ce n'est pas déjà fait)
|
||||
# Create the target directory
|
||||
mkdir -p /etc/nixos-infra
|
||||
if [ ! -d "/etc/nixos-infra/.git" ]; then
|
||||
git clone https://gitea.lagraula.fr/xavier/nixos-infra.git /etc/nixos-infra
|
||||
fi
|
||||
|
||||
# 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";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Ignore all age-encrypted secret files
|
||||
*.age
|
||||
|
||||
# But keep the pubkeys directory (for tracked .age pubkey files)
|
||||
!pubkeys/
|
||||
Reference in New Issue
Block a user