From 8b975e7d54047023b652a3c0a146449618751fb0 Mon Sep 17 00:00:00 2001 From: m3tam3re Date: Fri, 11 Apr 2025 11:33:45 +0200 Subject: [PATCH] v0.1.0 --- configuration.nix | 1 + flake.lock | 103 +++++++++++++++++++++++++++++++++++++++++----- flake.nix | 9 ++-- install.sh | 72 ++++++++++++++++++++++++-------- update.sh | 101 ++++++++++++++++++++++++++++----------------- 5 files changed, 216 insertions(+), 70 deletions(-) diff --git a/configuration.nix b/configuration.nix index 9182872..08678b9 100644 --- a/configuration.nix +++ b/configuration.nix @@ -60,6 +60,7 @@ in { # Networking networking = { + hostName = jsonConfig.hostname; firewall = { enable = true; # Only allow necessary ports diff --git a/flake.lock b/flake.lock index c1682f5..60ae008 100644 --- a/flake.lock +++ b/flake.lock @@ -6,11 +6,11 @@ "nixpkgs-unstable": "nixpkgs-unstable" }, "locked": { - "lastModified": 1741872348, - "narHash": "sha256-4d0S59c/rR5lcfqeqw3z+k4FlDwyci6dwrwMPgKuO/g=", + "lastModified": 1744363797, + "narHash": "sha256-Zn8TIOonPBQojN5NZ9Q+y6hvwAKFvW+iLXiceGNQ40o=", "ref": "stable", - "rev": "50af8d01fb5d5d5616bd1d5c38ced9946f863ca4", - "revCount": 6, + "rev": "45622da8ac40d404e59fa1eff9f63e42b7b95e2b", + "revCount": 10, "type": "git", "url": "https://code.m3tam3re.com/m3tam3re/self-host-playbook-base" }, @@ -20,6 +20,26 @@ "url": "https://code.m3tam3re.com/m3tam3re/self-host-playbook-base" } }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs_2", + "utils": "utils" + }, + "locked": { + "lastModified": 1727447169, + "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, "disko": { "inputs": { "nixpkgs": [ @@ -27,11 +47,11 @@ ] }, "locked": { - "lastModified": 1741786315, - "narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=", + "lastModified": 1744145203, + "narHash": "sha256-I2oILRiJ6G+BOSjY+0dGrTPe080L3pbKpc+gCV3Nmyk=", "owner": "nix-community", "repo": "disko", - "rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de", + "rev": "76c0a6dba345490508f36c1aa3c7ba5b6b460989", "type": "github" }, "original": { @@ -40,6 +60,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1741600792, @@ -72,18 +108,65 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1702272962, + "narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "base-config": "base-config", - "deploy-rs": [ - "nixpkgs" - ], + "deploy-rs": "deploy-rs", "disko": "disko", "nixpkgs": [ "base-config", "nixpkgs" ] } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 2e1572b..c629c0e 100644 --- a/flake.nix +++ b/flake.nix @@ -16,7 +16,6 @@ }; deploy-rs = { url = "github:serokell/deploy-rs"; - follows = "nixpkgs"; }; }; @@ -29,7 +28,7 @@ } @ inputs: let jsonConfig = builtins.fromJSON (builtins.readFile ./config.json); in { - nixosConfigurations.server = nixpkgs.lib.nixosSystem { + nixosConfigurations.${jsonConfig.hostname} = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ (base-config.nixosModules.default { @@ -43,15 +42,15 @@ inherit self; }; }; - deploy.nodes.server = { - hostname = "self-host-playbook"; + deploy.nodes.${jsonConfig.hostname} = { + hostname = jsonConfig.hostname; profiles.system = { sshUser = jsonConfig.username; user = "root"; interactiveSudo = true; path = deploy-rs.lib.x86_64-linux.activate.nixos - self.nixosConfigurations.server; + self.nixosConfigurations.${jsonConfig.hostname}; }; }; }; diff --git a/install.sh b/install.sh index 2bfeb89..172ca07 100755 --- a/install.sh +++ b/install.sh @@ -65,6 +65,14 @@ setup_latest_version() { local target_version=$1 local dir_name=$2 + # Safety check: Ensure we're in the self-host-playbook directory + local current_dir=$(basename "$(pwd)") + if [ "$current_dir" != "self-host-playbook" ]; then + echo "❌ Error: Must be in 'self-host-playbook' directory to setup latest version" + echo "Current directory: $(pwd)" + return 1 + fi + echo "⬇️ Downloading version $target_version..." TEMP_DIR=$(mktemp -d) @@ -80,6 +88,12 @@ setup_latest_version() { return 1 fi + # Additional safety check before copying files + if [ ! -f "$CLONE_DIR/flake.nix" ]; then + echo "❌ Error: Downloaded content doesn't appear to be a valid self-host-playbook" + return 1 + fi + # Copy files from clone to target directory cp -r "$CLONE_DIR"/* "$dir_name/" @@ -88,12 +102,25 @@ setup_latest_version() { # Function to setup from template setup_from_template() { + # Ensure we're in the correct directory + local current_dir=$(basename "$(pwd)") + if [ "$current_dir" != "self-host-playbook" ]; then + echo "❌ Error: Must be in 'self-host-playbook' directory" + exit 1 + fi + # Create backup if directory is not empty if [ -n "$(ls -A)" ]; then local CURRENT_VERSION=$(date +%Y%m%d_%H%M%S) local backup_dir="backup_${CURRENT_VERSION}_$(date +%Y%m%d_%H%M%S)" echo "📑 Creating backup in $backup_dir..." mkdir -p "$backup_dir" + # Add safety check for backup creation + if [ ! -d "$backup_dir" ]; then + echo "❌ Error: Failed to create backup directory" + exit 1 + fi + find . -maxdepth 1 ! -name "." ! -name ".." ! -name "$backup_dir" -exec cp -r {} "$backup_dir/" \; echo "✅ Backup created successfully" @@ -112,7 +139,7 @@ setup_from_template() { generate_ssh_key() { local KEY_NAME="self-host-playbook" local KEY_PATH="$HOME/.ssh/${KEY_NAME}" -W + if [ ! -f "$KEY_PATH" ]; then mkdir -p "$HOME/.ssh" echo "🔑 Generating new SSH key pair..." >&2 @@ -195,6 +222,7 @@ get_device_name() { setup_ssh_config() { local username=$1 local ip_address=$2 + local hostname=$3 # Add hostname parameter local ssh_config_dir="$HOME/.ssh" local ssh_config_file="$ssh_config_dir/config" local ssh_key_file="$ssh_config_dir/self-host-playbook" @@ -203,19 +231,20 @@ setup_ssh_config() { mkdir -p "$ssh_config_dir" chmod 700 "$ssh_config_dir" - # Create or append to SSH config - local config_entry="Host self-host-playbook + # Create or append to SSH config using hostname as the Host name + local config_entry="Host $hostname HostName $ip_address User $username + Port 2222 IdentityFile $ssh_key_file" # Check if entry already exists - if ! grep -q "Host self-host-playbook" "$ssh_config_file" 2>/dev/null; then + if ! grep -q "Host $hostname" "$ssh_config_file" 2>/dev/null; then echo -e "\n$config_entry" >> "$ssh_config_file" echo "✅ Added SSH config entry" else # Update existing entry - sed -i.bak "/Host self-host-playbook/,/IdentityFile.*/{ + sed -i.bak "/Host $hostname/,/IdentityFile.*/{ s/HostName.*/HostName $ip_address/ s/User.*/User $username/ }" "$ssh_config_file" @@ -265,11 +294,11 @@ SSH_PUB_KEY=$(cat "${SSH_KEY_PATH}.pub") || { echo echo "🔑 Here is your public key:" echo -cat $SSH_KEY_PATH.pub +cat "$SSH_KEY_PATH.pub" echo "" echo "📁 You can also find the keyfile here:" echo -echo $SSH_KEY_PATH.pub +echo "$SSH_KEY_PATH.pub" echo read -p "Press ENTER to continue or CTRL + C to abort..." @@ -278,15 +307,23 @@ echo "" echo "📝 Please provide the following information:" echo "-------------------------------------------" read -p "1. Enter target server IP address: " IP_ADDRESS -read -p "2. Enter desired username for server access: " USERNAME -read -s -p "3. Enter desired password: " PASSWORD +read -p "2. Enter hostname for the server: " HOSTNAME + +# Validate hostname format +while ! [[ $HOSTNAME =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$ ]]; do + echo "❌ Invalid hostname format. Please use a valid hostname (e.g., my-server.example.com)" + read -p "Enter hostname for the server: " HOSTNAME +done + +read -p "3. Enter desired username for server access: " USERNAME +read -s -p "4. Enter desired password: " PASSWORD echo -echo "4. Enter domain names for services (must point to $IP_ADDRESS):" +echo "5. Enter domain names for services (must point to $IP_ADDRESS):" read -p " - Domain for Portainer: " PORTAINER_DOMAIN read -p " - Domain for n8n: " N8N_DOMAIN read -p " - Domain for Baserow: " BASEROW_DOMAIN echo -echo "5. How do you authentiate to the target machine?" +echo "6. How do you authenticate to the target machine?" echo "-------------------------------------------" echo " 1) Password" echo " 2) SSH Key" @@ -295,10 +332,10 @@ read -p "Enter your choice (1-2): " KEY_CHOICE case $KEY_CHOICE in 1) - INSTALL_COMMAND="nix run github:nix-community/nixos-anywhere -- --flake .#server root@$IP_ADDRESS" + INSTALL_COMMAND="nix run github:nix-community/nixos-anywhere -- --flake .#$HOSTNAME root@$IP_ADDRESS" ;; 2) - INSTALL_COMMAND="nix run github:nix-community/nixos-anywhere -- --flake .#server -i $SSH_KEY_PATH root@$IP_ADDRESS" + INSTALL_COMMAND="nix run github:nix-community/nixos-anywhere -- --flake .#$HOSTNAME -i $SSH_KEY_PATH root@$IP_ADDRESS" ;; *) echo "❌ Invalid choice" @@ -309,7 +346,7 @@ esac setup_from_template echo -echo "6. Select your cloud provider:" +echo "7. Select your cloud provider:" echo " 1) AWS (Newer instances with NVMe)" echo " 2) AWS (Older instances)" echo " 3) Google Cloud Platform" @@ -387,7 +424,8 @@ cat > config.json << EOF "baserow": "$BASEROW_DOMAIN" }, "rootDevice": "$DEVICE_NAME", - "ipAddress": "$IP_ADDRESS" + "ipAddress": "$IP_ADDRESS", + "hostname": "$HOSTNAME" } EOF @@ -416,7 +454,7 @@ echo "This process might take several minutes..." # Run nixos-anywhere installation $INSTALL_COMMAND && { echo "🔧 Setting up SSH configuration..." - setup_ssh_config "$USERNAME" "$IP_ADDRESS" + setup_ssh_config "$USERNAME" "$IP_ADDRESS" "$HOSTNAME" echo echo "🎉 Installation completed successfully!" echo "=====================================>" @@ -426,7 +464,7 @@ $INSTALL_COMMAND && { echo "- Baserow: https://$BASEROW_DOMAIN" echo echo "To connect to your server, use:" - echo "ssh self-host-playbook" + echo "ssh $HOSTNAME" echo install_deploy_rs echo diff --git a/update.sh b/update.sh index 926a66e..fa4f1c9 100644 --- a/update.sh +++ b/update.sh @@ -26,7 +26,7 @@ get_current_version() { } get_latest_version() { - local LATEST_VERSION + local latest_version latest_version=$(curl -s "https://code.m3tam3re.com/api/v1/repos/m3tam3re/self-host-playbook/tags" | jq -r '.[] | select(.name | startswith("v")) | .name' | sort -V | tail -n1) @@ -86,6 +86,13 @@ show_changelog() { perform_update() { local target_version=$1 local backup_dir=$2 + + # Verify essential files exist before proceeding + if [ ! -f "config.json" ] || [ ! -d "env" ]; then + echo "❌ Error: Essential files missing. Are you in the correct directory?" + return 1 + fi + echo "⬇️ Downloading version $target_version..." TEMP_DIR=$(mktemp -d) @@ -101,6 +108,12 @@ perform_update() { return 1 fi + # Verify downloaded content + if [ ! -f "$CLONE_DIR/flake.nix" ]; then + echo "❌ Error: Downloaded content appears invalid" + return 1 + fi + # Remove current directory contents except backup echo "🗑️ Cleaning current directory..." find . -maxdepth 1 ! -name "." ! -name ".." ! -name "$backup_dir" -exec rm -rf {} + @@ -109,11 +122,27 @@ perform_update() { echo "📋 Installing new version..." cp -r "$CLONE_DIR"/* . - # Restore configuration files from backup - echo "🔄 Restoring configuration files..." - cp -r "${backup_dir}/config.json" \ - "${backup_dir}/env" . 2>/dev/null || true + # Verify essential files were copied + if [ ! -f "flake.nix" ]; then + echo "❌ Error: Failed to copy new version files" + return 1 + fi + # Restore configuration files from backup with validation + echo "🔄 Restoring configuration files..." + if [ -f "${backup_dir}/config.json" ]; then + cp -r "${backup_dir}/config.json" . || { + echo "❌ Error: Failed to restore config.json" + return 1 + } + fi + + if [ -d "${backup_dir}/env" ]; then + cp -r "${backup_dir}/env" . || { + echo "❌ Error: Failed to restore env directory" + return 1 + } + fi return 0 } @@ -121,67 +150,60 @@ perform_update() { setup_ssh_config() { local username=$1 local ip_address=$2 + local hostname=$3 local ssh_config_dir="$HOME/.ssh" local ssh_config_file="$ssh_config_dir/config" local ssh_key_file="$ssh_config_dir/self-host-playbook" - # Create .ssh directory if it doesn't exist mkdir -p "$ssh_config_dir" chmod 700 "$ssh_config_dir" - # Create or append to SSH config - local config_entry="Host self-host-playbook + local config_entry="Host $hostname HostName $ip_address User $username + Port 2222 IdentityFile $ssh_key_file" - # Check if entry already exists - if ! grep -q "Host self-host-playbook" "$ssh_config_file" 2>/dev/null; then + if ! grep -q "Host $hostname" "$ssh_config_file" 2>/dev/null; then echo -e "\n$config_entry" >> "$ssh_config_file" echo "✅ Added SSH config entry" else - # Update existing entry - sed -i.bak "/Host self-host-playbook/,/IdentityFile.*/{ + sed -i.bak "/Host $hostname/,/IdentityFile.*/{ s/HostName.*/HostName $ip_address/ s/User.*/User $username/ }" "$ssh_config_file" echo "✅ Updated existing SSH config entry" fi - # Set appropriate permissions chmod 600 "$ssh_config_file" } -update_config_json() { - local ip_address=$1 +update_config_value() { + local key=$1 + local value=$2 local config_file="config.json" - # Read existing config local config config=$(cat "$config_file") - # Update or add ipAddress field - if jq -e '.ipAddress' "$config_file" >/dev/null 2>&1; then - config=$(echo "$config" | jq --arg ip "$ip_address" '.ipAddress = $ip') + if jq -e ".$key" "$config_file" >/dev/null 2>&1; then + config=$(echo "$config" | jq --arg key "$key" --arg value "$value" '.[$key] = $value') else - config=$(echo "$config" | jq --arg ip "$ip_address" '. + {ipAddress: $ip}') + config=$(echo "$config" | jq --arg key "$key" --arg value "$value" '. + {($key): $value}') fi - # Write back to file echo "$config" | jq '.' > "$config_file" - echo "✅ Updated IP address in config.json" + echo "✅ Updated $key in config.json" } install_deploy_rs() { echo "🔧 Installing deploy-rs to user environment..." - # Check if deploy is already installed if command -v deploy >/dev/null 2>&1; then echo "ℹ️ deploy-rs is already installed" return 0 fi - # Install deploy-rs using nix profile if nix profile install 'github:serokell/deploy-rs'; then echo "✅ deploy-rs installed successfully" else @@ -190,12 +212,10 @@ install_deploy_rs() { fi } - # Main script echo "🔄 Self-Host Playbook Update Assistant" echo "======================================" -# Check if we're in the right directory if [ ! -f "config.json" ]; then echo "❌ Error: config.json not found. Please run this script in your self-host-playbook directory." exit 1 @@ -203,25 +223,35 @@ fi USERNAME=$(jq -r '.username' config.json) IP_ADDRESS=$(jq -r '.ipAddress // empty' config.json) +HOSTNAME=$(jq -r '.hostname // empty' config.json) if [ -z "$USERNAME" ]; then echo "❌ Error: Could not read username from config.json" exit 1 fi -# If IP address is not in config.json, prompt for it if [ -z "$IP_ADDRESS" ]; then echo "ℹ️ No IP address found in config.json" read -p "Enter the IP address of your server: " IP_ADDRESS - # Validate IP address format if ! [[ $IP_ADDRESS =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "❌ Error: Invalid IP address format" exit 1 fi - # Update config.json with the new IP address - update_config_json "$IP_ADDRESS" + update_config_value "ipAddress" "$IP_ADDRESS" +fi + +if [ -z "$HOSTNAME" ]; then + echo "ℹ️ No hostname found in config.json" + read -p "Enter the hostname for your server: " HOSTNAME + + if ! [[ $HOSTNAME =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*$ ]]; then + echo "❌ Error: Invalid hostname format" + exit 1 + fi + + update_config_value "hostname" "$HOSTNAME" fi VERSION_FILE="version.json" @@ -248,26 +278,21 @@ read -p "Do you want to update to version $LATEST_VERSION? (y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then - # Create backup backup_dir="backup_${CURRENT_VERSION}_$(date +%Y%m%d_%H%M%S)" echo "📑 Creating backup in $backup_dir..." mkdir -p "$backup_dir" find . -maxdepth 1 ! -name "." ! -name ".." ! -name "$backup_dir" -exec cp -r {} "$backup_dir/" \; - - # Perform update if perform_update "$LATEST_VERSION" "$backup_dir"; then echo echo "✅ Update completed successfully!" - # Setup SSH configuration echo echo "🔧 Setting up SSH configuration..." - setup_ssh_config "$USERNAME" "$IP_ADDRESS" + setup_ssh_config "$USERNAME" "$IP_ADDRESS" "$HOSTNAME" echo install_deploy_rs - echo - echo "To apply the changes, run:" - echo "sudo nixos-rebuild switch" + echo "🚀 Applying the update to your system..." + deploy .#$HOSTNAME echo echo "If you encounter any issues, your backup is available in $backup_dir" else