First attempt at LXC container deployment chain.

This commit is contained in:
2026-05-06 21:19:13 +02:00
parent 7fd43cf252
commit bf96cfbee0
9 changed files with 455 additions and 73 deletions
+22
View File
@@ -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 ];
};
}
+4
View File
@@ -0,0 +1,4 @@
self: super: {
# Custom packages and overrides for nixos-infra
# agenix is already available in nixpkgs — no custom overlay needed.
}
+105 -2
View File
@@ -1,4 +1,107 @@
# Scripts # Scripts
Utility scripts for infrastructure management. Utility scripts for infrastructure management.
Covers deployment, LXC container creation, and Covers deployment, LXC container creation and bootstrap,
initial bootstrap of new NixOS machines. 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
+146 -28
View File
@@ -10,7 +10,7 @@ if ! command -v docopts &> /dev/null; then
fi fi
# --- Usage and Documentation --- # --- 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: Usage:
$0 <short_name> [options] $0 <short_name> [options]
@@ -28,7 +28,8 @@ Options:
-v, --vlan VLAN VLAN tag (e.g. tag=10). -v, --vlan VLAN VLAN tag (e.g. tag=10).
-d, --domain DOMAIN DNS domain. -d, --domain DOMAIN DNS domain.
-u, --unprivileged UNPRIV Unprivileged container (0 or 1). -u, --unprivileged UNPRIV Unprivileged container (0 or 1).
-i, --ip IP Static IP (e.g. 192.168.1.100/24). -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. -C, --cmode CMODE Console mode (console or tty). Default: console.
-T, --tags TAGS Tags for the container (optional). -T, --tags TAGS Tags for the container (optional).
-k, --ssh-public-keys KEYS SSH public keys for the container. -k, --ssh-public-keys KEYS SSH public keys for the container.
@@ -36,9 +37,15 @@ Options:
--pve-user USER Proxmox user (default: admin). --pve-user USER Proxmox user (default: admin).
--pve-port PORT SSH port for Proxmox (default: 22). --pve-port PORT SSH port for Proxmox (default: 22).
--pve-ssh-key KEY SSH key file for authentication. --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. --dry-run Simulate container creation without execution.
Optional configuration files: Optional configuration files (loaded in order, later overrides earlier):
/etc/nixos-infra/hosts/config /etc/nixos-infra/hosts/config
\${XDG_CONFIG_HOME}/nixos-infra/hosts/config \${XDG_CONFIG_HOME}/nixos-infra/hosts/config
./config ./config
@@ -64,10 +71,17 @@ VLAN="${VLAN:-}"
DOMAIN="${DOMAIN:-lagraula.fr}" DOMAIN="${DOMAIN:-lagraula.fr}"
UNPRIVILEGED="${UNPRIVILEGED:-0}" UNPRIVILEGED="${UNPRIVILEGED:-0}"
IP="${IP:-}" IP="${IP:-}"
IP6="${IP6:-}"
CMODE="${CMODE:-console}" CMODE="${CMODE:-console}"
TAGS="${TAGS:-}" TAGS="${TAGS:-}"
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}" 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) --- # --- Parse Arguments with docopts (Highest priority) ---
# set +e is to prevent set -e from eating the error message from docopts. # 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 # 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" source "$conffile"
set +a set +a
else else
echo " $conffile not found." echo " $conffile not found (optional)."
fi fi
done done
# Proxmox Server # Override with CLI arguments (have priority over config files)
PVE_HOST="${pve_host:-$PVE_HOST}" PVE_HOST="${pve_host:-$PVE_HOST}"
PVE_USER="${pve_user:-$PVE_USER}" PVE_USER="${pve_user:-$PVE_USER}"
PVE_PORT="${pve_port:-$PVE_PORT}" PVE_PORT="${pve_port:-$PVE_PORT}"
PVE_SSH_KEY="${pve_ssh_key:-$PVE_SSH_KEY}" PVE_SSH_KEY="${pve_ssh_key:-$PVE_SSH_KEY}"
DRY_RUN="${dry_run:-$DRY_RUN}" DRY_RUN="${dry_run:-$DRY_RUN}"
# LXC Container
TEMPLATE="${template:-$TEMPLATE}" TEMPLATE="${template:-$TEMPLATE}"
ROOTFS_SIZE="${rootfs_size:-$ROOTFS_SIZE}" ROOTFS_SIZE="${rootfs_size:-$ROOTFS_SIZE}"
CORES="${cores:-$CORES}" CORES="${cores:-$CORES}"
@@ -113,10 +126,16 @@ VLAN="${vlan:-$VLAN}"
DOMAIN="${domain:-$DOMAIN}" DOMAIN="${domain:-$DOMAIN}"
UNPRIVILEGED="${unprivileged:-$UNPRIVILEGED}" UNPRIVILEGED="${unprivileged:-$UNPRIVILEGED}"
IP="${ip:-$IP}" IP="${ip:-$IP}"
IP6="${ip6:-$IP6}"
CMODE="${cmode:-$CMODE}" CMODE="${cmode:-$CMODE}"
TAGS="${tags:-$TAGS}" TAGS="${tags:-$TAGS}"
SSH_PUBLIC_KEYS="${ssh_public_keys:-$SSH_PUBLIC_KEYS}" 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 --- # --- SSH Key Default Logic ---
if [ "$PVE_SSH_KEY" = "default" ]; then if [ "$PVE_SSH_KEY" = "default" ]; then
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}" PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
@@ -124,19 +143,19 @@ fi
# --- Critical Parameters Validation --- # --- Critical Parameters Validation ---
mandatory_params=( mandatory_params=(
"TEMPLATE" \ "TEMPLATE"
"ROOTFS_SIZE" \ "ROOTFS_SIZE"
"CORES" \ "CORES"
"MEMORY" \ "MEMORY"
"SWAP" \ "SWAP"
"PASSWORD" \ "PASSWORD"
"BRIDGE" \ "BRIDGE"
"DOMAIN" \ "DOMAIN"
"UNPRIVILEGED" \ "UNPRIVILEGED"
"CMODE" \ "CMODE"
"SSH_PUBLIC_KEYS" \ "SSH_PUBLIC_KEYS"
"PVE_HOST" \ "PVE_HOST"
"PVE_USER" \ "PVE_USER"
"PVE_PORT" "PVE_PORT"
) )
missing_params=() missing_params=()
@@ -145,7 +164,7 @@ for param in ${mandatory_params[*]}; do
done done
if [ ${#missing_params[@]} -gt 0 ]; then if [ ${#missing_params[@]} -gt 0 ]; then
echo "❌ Error: The following necessary parameters are missing: ${missing_params[*]}" >&2 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 exit 1
fi fi
@@ -155,6 +174,22 @@ if [ ! -f "$PVE_SSH_KEY" ]; then
exit 1 exit 1
fi 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 --- # --- SSH Connection to Proxmox Server ---
run_proxmox() { run_proxmox() {
local ssh_cmd="ssh -p $PVE_PORT" local ssh_cmd="ssh -p $PVE_PORT"
@@ -174,9 +209,15 @@ fi
if [ -n "$IP" ]; then if [ -n "$IP" ]; then
NET_OPTS="$NET_OPTS,ip=$IP" NET_OPTS="$NET_OPTS,ip=$IP"
fi 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 --- # --- 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 \ CREATE_CMD="pct create $ROOTFS_SIZE $TEMPLATE --cores $CORES \
--memory $MEMORY --swap $SWAP --hostname $short_name.$DOMAIN \ --memory $MEMORY --swap $SWAP --hostname $short_name.$DOMAIN \
--password $PASSWORD --unprivileged $UNPRIVILEGED --net0 $NET_OPTS \ --password $PASSWORD --unprivileged $UNPRIVILEGED --net0 $NET_OPTS \
@@ -192,12 +233,89 @@ echo "🔧 Command to execute on $PVE_HOST: $DISPLAY_CMD"
# Execute or simulate # Execute or simulate
if [ "$DRY_RUN" = "true" ]; then if [ "$DRY_RUN" = "true" ]; then
echo "🧪 Dry run: Skipping actual execution." echo "🧪 Dry run mode:"
else echo " - Container creation skipped"
LXC_ID=$(run_proxmox "$CREATE_CMD" | grep -oP '\d+') echo " - Bootstrap phase skipped"
if [ -z "$LXC_ID" ]; then 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 echo "❌ Error: Failed to create the container." >&2
exit 1 exit 1
fi
echo "✅ LXC container $short_name created successfully (ID: $LXC_ID)."
fi 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-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)"
+69 -12
View File
@@ -1,42 +1,99 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
REPO_URL="https://gitea.lagraula.fr/xavier/nixos-infra.git" # --- Default values (can be overridden by environment variables) ---
REPO_DIR="/etc/nixos-infra" REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
BRANCH="main" 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) HOSTNAME=$(hostname)
if [ "$(id -u)" -ne 0 ]; then 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 exit 1
fi 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 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" cd "$REPO_DIR"
git fetch origin git fetch origin
git checkout "$BRANCH" git checkout "$BRANCH"
git pull origin "$BRANCH" git pull origin "$BRANCH"
else else
echo "Clonage du dépôt dans $REPO_DIR..." echo "📥 Clonage du dépôt dans $REPO_DIR..."
mkdir -p "$REPO_DIR" mkdir -p "$REPO_DIR"
git clone --branch "$BRANCH" "$REPO_URL" "$REPO_DIR" git clone --branch "$BRANCH" "$REPO_URL" "$REPO_DIR"
fi fi
# Trouver la configuration pour cette machine # --- Find the configuration for this machine ---
CONFIG_PATH="$REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix" CONFIG_PATH="$REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix"
if [ ! -f "$CONFIG_PATH" ]; then if [ ! -f "$CONFIG_PATH" ]; then
CONFIG_PATH="$REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix" CONFIG_PATH="$REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix"
fi fi
if [ ! -f "$CONFIG_PATH" ]; then 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 exit 1
fi fi
# Appliquer la configuration # --- Apply the configuration ---
echo "Déploiement de la configuration pour $HOSTNAME..." echo "🚀 Deploying the configuration for $HOSTNAME..."
nixos-rebuild switch -I nixos-config="$CONFIG_PATH" nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
echo "ploiement terminé avec succès !" echo "✅ Deployment was successful !"
+78
View File
@@ -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"
+6 -11
View File
@@ -4,29 +4,24 @@
# Install Git, curl, and other required tools # Install Git, curl, and other required tools
environment.systemPackages = with pkgs; [ git curl ]; environment.systemPackages = with pkgs; [ git curl ];
# Enable unsecured SSH for initial deployment # Enable SSH for initial deployment
services.openssh = { services.openssh = {
enable = true; enable = true;
permitRootLogin = "yes"; permitRootLogin = "yes";
passwordAuthentication = true; passwordAuthentication = true;
}; };
# Deployment script # Clone the repository so deploy.sh can use it
system.activationScripts.setup-deploy = '' system.activationScripts.setup-deploy = ''
#!${pkgs.bash}/bin/bash #!${pkgs.bash}/bin/bash
set -euo pipefail set -euo pipefail
# Télécharger le script de déploiement depuis Gitea # Create the target directory
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)
mkdir -p /etc/nixos-infra 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 # The deploy script has already been pushed to /usr/local/bin/deploy-nixos
fi # by create-lxc-nixos.sh; it will clone the repo and apply the config.
''; '';
system.stateVersion = "25.11"; system.stateVersion = "25.11";
} }
+5
View File
@@ -0,0 +1,5 @@
# Ignore all age-encrypted secret files
*.age
# But keep the pubkeys directory (for tracked .age pubkey files)
!pubkeys/