(feat): drastic improvements to automation of LXC configuration with scaffolding in place for automating VM and LXC build downloads

This commit is contained in:
root 2024-12-10 04:13:10 -08:00
parent 98a055da3e
commit e071937cf1
17 changed files with 385 additions and 186 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
repo-to*
build/

View File

@ -0,0 +1,16 @@
# Details: https://github.com/kirill-markin/repo-to-text
# Syntax: gitignore rules
# Ignore files and directories for all sections from gitignore file
# Default: True
gitignore-import-and-ignore: True
# Ignore files and directories for tree
# and "Contents of ..." sections
ignore-tree-and-content:
- ".repo-to-text-settings.yaml"
# Ignore files and directories for "Contents of ..." section
ignore-content:
- "README.md"
- "LICENSE"

View File

@ -1,122 +0,0 @@
#!/bin/bash
set -e
# Function to display usage
usage() {
echo "Usage: $0 <container_id> --ssh-key <ssh_key> --ip <ip_address> --gateway <gateway> --user <username>"
echo " <container_id>: ID of the container (100-999)"
echo " --ssh-key: SSH public key for the user"
echo " --ip: IP address for the container"
echo " --gateway: Gateway IP address"
echo " --user: Username for the admin user (default: admin)"
exit 1
}
# Function to validate IP address format
validate_ip() {
if [[ $1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
return 0
fi
return 1
}
# Parse command-line arguments
CTID=$1
shift
while [[ $# -gt 0 ]]; do
case $1 in
--ssh-key) SSH_KEY="$2"; shift 2 ;;
--ip) IP_ADDRESS="$2"; shift 2 ;;
--gateway) GATEWAY="$2"; shift 2 ;;
--user) USERNAME="$2"; shift 2 ;;
*) echo "Unknown option: $1"; usage ;;
esac
done
# Validate inputs
[[ ! $CTID =~ ^[1-9][0-9]{2}$ ]] && { echo "Error: Invalid container ID"; usage; }
[[ -z $SSH_KEY ]] && { echo "Error: SSH key is required"; usage; }
[[ -z $IP_ADDRESS ]] && { echo "Error: IP address is required"; usage; }
[[ -z $GATEWAY ]] && { echo "Error: Gateway is required"; usage; }
validate_ip "$IP_ADDRESS" || { echo "Error: Invalid IP address"; usage; }
validate_ip "$GATEWAY" || { echo "Error: Invalid gateway"; usage; }
USERNAME=${USERNAME:-admin}
# Function to generate NixOS configuration
generate_nixos_config() {
cat << EOF
{ modulesPath, config, pkgs, ... }:
{
imports = [ "\${modulesPath}/virtualisation/lxc-container.nix" ];
boot.isContainer = true;
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
environment.systemPackages = with pkgs; [ openssh binutils man git ];
users.users.${USERNAME} = {
isNormalUser = true;
extraGroups = [ "wheel" ];
openssh.authorizedKeys.keys = [ "${SSH_KEY}" ];
};
security.sudo.wheelNeedsPassword = false;
programs.nix-ld.enable = true;
services.openssh = {
enable = true;
settings = {
AllowUsers = ["${USERNAME}"];
PasswordAuthentication = false;
PermitRootLogin = "no";
};
};
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
defaultGateway = "${GATEWAY}";
nameservers = [ "8.8.8.8" "8.8.4.4" ];
interfaces.eth0.ipv4.addresses = [{
address = "${IP_ADDRESS}";
prefixLength = 24;
}];
};
system.stateVersion = "24.05";
}
EOF
}
# Main execution
if ! pct status "$CTID" >/dev/null 2>&1; then
echo "Error: Container $CTID does not exist"
exit 1
fi
CONFIG_CONTENT=$(generate_nixos_config)
pct start ${CTID}
sleep 10
pct enter ${CTID} << EOF
/run/current-system/sw/bin/bash << 'INNEREOF'
export PATH=/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/run/current-system/sw/bin:\$PATH
source /etc/profile
mkdir -p /etc/nixos
cat > /etc/nixos/configuration.nix << 'CONFIGEOF'
${CONFIG_CONTENT}
CONFIGEOF
nixos-rebuild switch
INNEREOF
EOF
echo "Configuration applied successfully!"

View File

@ -1,64 +0,0 @@
{ modulesPath, config, pkgs, ... }:
{
imports =
[
# Default path for lxc/lxd configuration
"${modulesPath}/virtualisation/lxc-container.nix"
];
boot.isContainer = true;
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
# Essential packages
environment.systemPackages = with pkgs; [
openssh
binutils
man
git
];
# Administrative sudo user
users.users.admin = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # wheel group is sudo access
};
security.sudo.wheelNeedsPassword = true;
# Facilitates access via VS Code Remote Explorer
programs.nix-ld.enable = true;
# Enable password-based SSH login for admin user
services.openssh = {
enable = true;
settings = {
AllowUsers = ["admin"]; # everyone
PasswordAuthentication = true;
PermitRootLogin = "no";
};
};
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-eth0" = {
matchConfig.Name = "eth0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
system.stateVersion = "24.05"; # Did you read the comment?
}

View File

@ -0,0 +1,42 @@
{ modulesPath, config, pkgs, ... }:
{
imports = [
./lxc.nix
./users.nix
./network.nix
];
# Nix settings
nix = {
settings = {
auto-optimise-store = true;
experimental-features = [ "nix-command" "flakes" ];
allowed-users = [ "@wheel" ];
};
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
};
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Set NIX_PATH
nix.nixPath = [
"nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos"
"nixos-config=/etc/nixos/configuration.nix"
"/nix/var/nix/profiles/per-user/root/channels"
];
# Auto upgrades
system.autoUpgrade = {
enable = true;
dates = "04:00";
randomizedDelaySec = "45min";
persistent = true;
};
system.stateVersion = "24.05";
}

23
nix-config/lxc.nix Normal file
View File

@ -0,0 +1,23 @@
{ modulesPath, config, pkgs, ... }:
{
imports = [
"${modulesPath}/virtualisation/lxc-container.nix"
];
boot.isContainer = true;
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
environment.systemPackages = with pkgs; [
openssh
binutils
man
git
];
programs.nix-ld.enable = true;
}

20
nix-config/network.nix Normal file
View File

@ -0,0 +1,20 @@
{ config, pkgs, ... }:
{
networking = {
dhcpcd.enable = false;
useDHCP = false;
useHostResolvConf = false;
};
systemd.network = {
enable = true;
networks."50-eth0" = {
matchConfig.Name = "eth0";
networkConfig = {
DHCP = "ipv4";
IPv6AcceptRA = true;
};
linkConfig.RequiredForOnline = "routable";
};
};
}

View File

@ -0,0 +1,20 @@
{ modulesPath, config, pkgs, ... }:
{
# Administrative sudo user
users.users.admin = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # wheel group is sudo access
};
# Enable password-based SSH login for admin user
services.openssh = {
enable = true;
settings = {
AllowUsers = ["admin"]; # everyone
PasswordAuthentication = true;
PermitRootLogin = "no";
};
};
}

18
nix-config/users.nix Normal file
View File

@ -0,0 +1,18 @@
{ config, pkgs, ... }:
{
users.users.nixos = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
security.sudo.wheelNeedsPassword = true;
services.openssh = {
enable = true;
settings = {
AllowUsers = ["nixos"];
PasswordAuthentication = true;
PermitRootLogin = "no";
};
};
}

2
scripts/create.sh Normal file
View File

@ -0,0 +1,2 @@
TODO: Deploy lxc using user defined variables
TODO: Deploy vm using user defined variables

25
scripts/get-latest.sh Normal file
View File

@ -0,0 +1,25 @@
#!/bin/bash
IMAGE_TYPE="$1"
BASE_URL="https://hydra.nixos.org/job/nixos/release-24.11/nixos"
DOWNLOAD_DIR="./build"
if [ "$IMAGE_TYPE" = "VM" ]; then
DOWNLOAD_URL="${BASE_URL}.proxmoxImage.x86_64-linux/latest/download/1"
OUTPUT_FILE="${DOWNLOAD_DIR}/nixos_proxmox_vm.vma.zst"
elif [ "$IMAGE_TYPE" = "LXC" ]; then
DOWNLOAD_URL="${BASE_URL}.proxmoxLXC.x86_64-linux/latest/download/1"
OUTPUT_FILE="${DOWNLOAD_DIR}/nixos_proxmox_lxc.tar.xz"
else
echo "Error: Invalid image type. Must be 'VM' or 'LXC'" >&2
exit 1
fi
wget -q --show-progress -O "$OUTPUT_FILE" "$DOWNLOAD_URL"
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "Error: Download failed" >&2
rm -f "$OUTPUT_FILE"
exit $EXIT_CODE
fi

49
scripts/list-lxcs.sh Normal file
View File

@ -0,0 +1,49 @@
#!/bin/bash
# ANSI color codes
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'
# Array to store valid CTIDs
declare -a valid_ctids
echo -e "${BLUE}Available NixOS Containers:${NC}"
printf "%-8s %s\n" "VMID" "Name"
echo "----------------"
# Populate the list and store valid CTIDs
for conf in /etc/pve/lxc/*.conf; do
if grep -q "^ostype: nixos" "$conf"; then
vmid=$(basename "$conf" .conf)
name=$(grep "^hostname:" "$conf" | cut -d' ' -f2)
printf "%-8s %s\n" "$vmid" "$name"
valid_ctids+=("$vmid")
fi
done
if [ ${#valid_ctids[@]} -eq 0 ]; then
echo -e "${RED}No NixOS containers found!${NC}" >&2
exit 1
fi
# Ask for user input
echo -e "\nEnter the CTID of the container you want to configure:"
read -r selected_ctid
# Validate input
valid=0
for ctid in "${valid_ctids[@]}"; do
if [ "$ctid" = "$selected_ctid" ]; then
valid=1
break
fi
done
if [ $valid -eq 0 ]; then
echo -e "${RED}Error: Invalid CTID selected!${NC}" >&2
exit 1
fi
# Output the selected CTID for use in other scripts
echo "$selected_ctid"

View File

@ -0,0 +1,39 @@
#!/bin/bash
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <container_id>"
exit 1
fi
CTID="$1"
CONFIG_FILE="/etc/pve/lxc/${CTID}.conf"
MOUNT_POINT="/root/nixos-config-${CTID}"
NIX_CONFIG_DIR="./nix-config"
if [ ! -d "$NIX_CONFIG_DIR" ]; then
echo "Error: nix-config directory not found"
exit 1
fi
# Parse container config and mount
echo "Parsing container configuration..."
ROOTFS_LINE=$(grep "^rootfs:" "$CONFIG_FILE")
VOLUME_NAME=$(echo "$ROOTFS_LINE" | sed 's/rootfs: local-lvm:\([^,]*\).*/\1/')
DEVICE_PATH="/dev/pve/${VOLUME_NAME}"
echo "Creating mount point..."
mkdir -p "$MOUNT_POINT"
echo "Mounting container filesystem..."
mount "$DEVICE_PATH" "$MOUNT_POINT"
echo "Copying NixOS configuration..."
mkdir -p "${MOUNT_POINT}/etc/nixos"
cp -r ${NIX_CONFIG_DIR}/* "${MOUNT_POINT}/etc/nixos/"
echo "Unmounting container filesystem..."
umount "$MOUNT_POINT"
rmdir "$MOUNT_POINT"
echo "Configuration files copied successfully"

10
scripts/post-deploy.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
# ANSI color codes
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# Get primary IP address (excluding docker/vm interfaces)
IP_ADDRESS=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '^127\.' | head -n 1)
echo -e "${HOSTNAME} is now deployed at ${GREEN}${IP_ADDRESS}${NC}"

17
scripts/rebuild-nixos.sh Normal file
View File

@ -0,0 +1,17 @@
#!/bin/bash
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <container_id>"
exit 1
fi
CTID="$1"
echo "Updating channels..."
pct exec ${CTID} -- nix-channel --update
echo "Rebuilding NixOS configuration..."
pct exec ${CTID} -- nixos-rebuild switch -I nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos -I nixos-config=/etc/nixos/configuration.nix
echo "NixOS rebuild completed successfully"

View File

@ -0,0 +1,37 @@
#!/bin/bash
set -e
if [ -z "$1" ]; then
echo "Usage: $0 <container_id>"
exit 1
fi
CTID="$1"
# Function to add or update line in config file
update_config_line() {
local file="$1"
local search="$2"
local replace="$3"
if [ -f "$file" ]; then
if ! grep -q "^${search}" "$file"; then
echo "${replace}" >> "$file"
else
sed -i "s|^${search}.*|${replace}|" "$file"
fi
fi
}
# Update Proxmox LXC config
PVE_CONFIG="/etc/pve/lxc/${CTID}.conf"
update_config_line "$PVE_CONFIG" "lxc.init_cmd:" "lxc.init_cmd: /run/current-system/sw/bin/bash"
update_config_line "$PVE_CONFIG" "cmode:" "cmode: shell"
# Update LXC system config
LXC_CONFIG="/var/lib/lxc/${CTID}/config"
update_config_line "$LXC_CONFIG" "lxc.init.cmd" "lxc.init.cmd = /run/current-system/sw/bin/bash"
update_config_line "$LXC_CONFIG" "lxc.environment = TERM" "lxc.environment = TERM=linux"
update_config_line "$LXC_CONFIG" "lxc.environment = PATH" "lxc.environment = PATH=/run/current-system/sw/bin"
echo "LXC terminal configuration updated successfully"

65
setup.sh Executable file
View File

@ -0,0 +1,65 @@
#!/bin/bash
set -e
# ANSI color codes
BLUE='\033[0;34m'
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'
# Check if running as root
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}This script must be run as root${NC}"
exit 1
fi
# Check and install git if needed
if ! command -v git >/dev/null 2>&1; then
echo "Installing git..."
nix-env -i git
fi
REPO_DIR="/root/.nixos-utils"
# Clone or update repository
if [ -d "$REPO_DIR" ]; then
echo "Updating existing repository..."
cd "$REPO_DIR"
git pull
else
echo "Cloning repository..."
git clone https://git.jeirslab.xyz/jeirmeister/NixOS-PVE-LXC.git "$REPO_DIR"
cd "$REPO_DIR"
fi
# Make scripts executable
echo "Making scripts executable..."
find ./scripts -name "*.sh" -execdir chmod u+x {} +
# Get CTID from list-lxcs.sh
echo -e "${BLUE}Detecting NixOS containers...${NC}"
CTID=$(./scripts/list-lxcs.sh)
if [ -z "$CTID" ]; then
echo -e "${RED}No container ID was selected${NC}"
exit 1
fi
echo -e "${GREEN}Selected container: $CTID${NC}"
# Execute configuration steps in sequence
echo -e "\nConfiguring NixOS container $CTID..."
echo "Step 1: Setting up LXC terminal..."
./scripts/setup-lxc-terminal.sh "$CTID"
echo "Step 2: Mounting and copying NixOS configuration..."
./scripts/mount-nixos-config.sh "$CTID"
echo "Step 3: Rebuilding NixOS configuration..."
./scripts/rebuild-nixos.sh "$CTID"
echo "Step 4: Running post-deployment tasks..."
./scripts/post-deploy.sh
echo -e "${GREEN}NixOS container $CTID has been configured successfully!${NC}"