diff --git a/configuration-files/numbus-backup-server.conf b/configuration-files/numbus-backup-server.conf deleted file mode 100644 index 2fa35de..0000000 --- a/configuration-files/numbus-backup-server.conf +++ /dev/null @@ -1,147 +0,0 @@ -### -----------------> ### -### MANDATORY SETTINGS ### - - - -## Live target settings -# The IP address of the machine to install NixOS on (must be reachable via SSH). -export LIVE_TARGET_IP="192.168.1.10" -# The password of the live installer environment (the one you set using 'passwd' on the live machine). -export LIVE_TARGET_PASSWD="example" - - -## Backup server settings -# The language/keyboard layout (e.g. FR, EN, DE). -export SERVER_LANGUAGE="FR" -# The system locale (e.g. fr_FR, en_US, de_DE). -export SERVER_LOCALE="fr_FR" -# The timezone (e.g. Europe/Paris, America/New_York, Europe/Berlin). -export SERVER_TIMEZONE="Europe/Paris" -# The name of the server owner. Used in mails and for identification (if you bought support or have multiple servers). -export SERVER_OWNER_NAME="yourName" -# The email address where services notifications and alerts will be sent. -export SERVER_USER_EMAIL="user@your-domain.com" -# The email address where system failure notifications and alerts will be sent. -export SERVER_ADMIN_EMAIL="admin@your-domain.com" -# A list of SSH public keys allowed to log in as the administrator. -export SERVER_AUTHORIZED_SSH_PUBKEYS=( "ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" ) - - -## Traefik settings -# Cloudflare API token with "Zone:DNS:Edit" permissions for automatic renewal of Let's Encrypt certificates. -export CLOUDFLARE_DNS_API_TOKEN="yourToken" - - -## Smtp settings -# The email account used by the server to send outgoing notifications. -export SMTP_SERVER_USERNAME="your-address@gmail.com" -# The password for the email account (use an App Password if using Gmail/2FA). -export SMTP_SERVER_PASSWORD="emrp raps vzoi vnoe" -export SMTP_SERVER_HOST="smtp.yourdomain.com" -export SMTP_SERVER_PORT="587" - - -## Network settings -# The local network subnet in CIDR notation (e.g. 192.168.1.0/24). -export NETWORK_SUBNET="192.168.1.0/24" -# The IP address of your internet router/gateway. -export NETWORK_ROUTER_IP="192.168.1.1" -# The static IP address to assign to this server (must be outside the router's DHCP range). -export HOME_SERVER_IP="192.168.1.5" - - -## Services settings -# The root domain name for your services (e.g. example.com). -export DOMAIN_NAME="yourdomain.com" - - -## Web applications -# All apps are open-source, fully local -export SELECTED_WEB_APPLICATIONS=( - # Minecraft server(s) manager. Supports Bedrock and Java, Dynmap. https://craftycontrol.com/ - "crafty" - # Network-Video-Recorder with advanced features such as person detection, face recognition. https://frigate.video/ - "frigate" - # Full-featured git platform. Replace GitHub with your own and stop AI bots from accessing your code. https://about.gitea.com/ - "gitea" - # Home automation platform. Every smart home devices in one place. Endless automation options. Integrates with Frigate to get notified when someone is detected. https://www.home-assistant.io/ - "home-assistant" - # A modern, secure, highly customizable application dashboard. https://gethomepage.dev/ - "homepage" - # Photos backup platform similar to Google Photos. Advanced features such as face and object recognition powered search. https://immich.app/ - "immich" - # A set of super useful tools when doing IT. https://it-tools.tech/ - "it-tools" - # The Free Software Media System. Stream to any device from your own server, with no strings attached. https://jellyfin.org/ - "jellyfin" - # Workflow automation for technical people. node-based workflow automation tool. https://n8n.io/ - "n8n" - # Network boot various operating system installers and utilities from one place. https://netboot.xyz/ - "netbootxyz" - # The most popular self-hosted collaboration platform. File sharing, productivity, and groupware. https://nextcloud.com/ - "nextcloud" - # Send push notifications to your phone or desktop via PUT/POST. https://ntfy.sh/ - "ntfy" - # Open Source ERP and CRM. https://www.odoo.com/ - "odoo" - # Open source password manager for teams. Security first, privacy focused. https://www.passbolt.com/ - "passbolt" - # A fancy self-hosted monitoring tool. https://uptimekuma.org/ - "uptime-kuma" - # Free/Libre Open Source Software Binaries of VS Code. Run VS Code in your browser. https://vscodium.com/ - "vscodium" -) - - -## System services -# All apps are open-source, fully local -export SELECTED_SYSTEM_SERVICES=( - # Backup your numbus-server using this client. - "backup-client" - # Anti-virus software. Will scan the system periodically. Will scan on-access the data stored in your services' data directories : for example, where your Nextcloud data is. https://www.clamav.net/ - "clamav" - # Virtualization host software. Uses Qemu/KVM. Run VMs with near-native performance and device passthrough capabilities. https://www.qemu.org/ - "virtualization" -) - - -### MANDATORY SETTINGS ### -### <----------------- ### - - - -### -----------------> ### -### OPTIONAL SETTINGS ### - - - -## Web applications subdomain -# Subdomains for each selected web application. -# āš ļø The order must strictly match the SELECTED_WEB_APPLICATIONS array above. The below example would be correct if you selected every service in the SELECTED_WEB_APPLICATIONS array. -export SELECTED_WEB_APPLICATIONS_SUBDOMAIN=( - "my-crafty-subdomain" - "my-frigate-subdomain" - "my-gitea-subdomain" - "my-home-assistant-subdomain" # Example : your Home-assistant URL will be ; https://my-home-assistant-subdomain.yourdomain.com/ - "my-homepage-subdomain" - "my-immich-subdomain" - "my-it-tools-subdomain" - "my-jellyfin-subdomain" # Example : your Jellyfin URL will be ; https://my-jellyfin-subdomain.yourdomain.com/ - "my-n8n-subdomain" - "my-netbootxyz-subdomain" - "my-nextcloud-subdomain" - "my-ntfy-subdomain" - "my-odoo-subdomain" - "my-passbolt-subdomain" - "my-uptime-kuma-subdomain" - "my-vscodium-subdomain" -) - - -## Script settings -# Enable verbose logging for debugging purposes. -export DEBUG="true" - - -### OPTIONAL SETTINGS ### -### <----------------- ### \ No newline at end of file diff --git a/configuration-files/numbus-computer.conf b/configuration-files/numbus-computer.conf deleted file mode 100644 index 8802a97..0000000 --- a/configuration-files/numbus-computer.conf +++ /dev/null @@ -1,22 +0,0 @@ -# --> -# MANDATORY SETTINGS -# <-- - -## Script settings -export DEBUG="true" - -## Live target settings -export LIVE_TARGET_IP="192.168.1.10" -export LIVE_TARGET_PASSWD="example" - -## Computer settings -export COMPUTER_LANGUAGE="FR" -export COMPUTER_LOCALE="fr_FR" -export COMPUTER_TIMEZONE="Europe/Paris" -export COMPUTER_OWNER_NAME="yourName" -export COMPUTER_AUTHORIZED_SSH_PUBKEYS=( "ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" ) - -## Network settings -export NETWORK_SUBNET="192.168.1.0/24" -export NETWORK_ROUTER_IP="192.168.1.1" -export HOME_SERVER_IP="192.168.1.5" \ No newline at end of file diff --git a/configuration-files/numbus-server.conf b/configuration-files/numbus-server.conf deleted file mode 100644 index 94ff582..0000000 --- a/configuration-files/numbus-server.conf +++ /dev/null @@ -1,101 +0,0 @@ -### MANDATORY SETTINGS ### - -## šŸ“¦ Live target settings -# See docs/numbus-server/configuration/live_target.md -LIVE_TARGET_IP="192.168.1.10" -LIVE_TARGET_PASSWD="example" - - -## āš™ļø Server settings -# See docs/numbus-server/configuration/server.md -SERVER_LANGUAGE="FR" -SERVER_LOCALE="fr_FR" -SERVER_TIMEZONE="Europe/Paris" -SERVER_OWNER_NAME="yourName" -SERVER_ADMIN_EMAIL="admin@your-domain.com" -SERVER_AUTHORIZED_SSH_PUBKEYS=( "ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" ) - - -## šŸ“¬ Mail settings -# See docs/numbus-server/configuration/mail.md -SMTP_SERVER_USERNAME="your-address@your-domain.com" -SMTP_SERVER_PASSWORD="emrp raps vzoi vnoe" -SMTP_SERVER_HOST="smtp.yourdomain.com" -SMTP_SERVER_PORT="587" - - -## šŸ›œ Network settings -# See docs/numbus-server/configuration/network.md -NETWORK_SUBNET="192.168.1.0/24" -NETWORK_ROUTER_IP="192.168.1.1" -HOME_SERVER_IP="192.168.1.5" - - -## šŸ› ļø Services settings -# See docs/numbus-server/configuration/services/index.md -DOMAIN_NAME="yourdomain.com" -SELECTED_DNS_SERVICE="pi-hole" # or SELECTED_DNS_SERVICE="adguard" -SELECTED_WEB_APPLICATIONS=( - "crafty" - "frigate" - "gitea" - "home-assistant" - "homepage" - "immich" - "it-tools" - "jellyfin" - "n8n" - "netbootxyz" - "nextcloud" - "ntfy" - "odoo" - "passbolt" - "uptime-kuma" - "vscodium" -) -SELECTED_SYSTEM_SERVICES=( - "clamav" - "virtualization" -) - - -## 🚦 Traefik settings -# See docs/numbus-server/configuration/services/automatic_ssl_certs.md -CLOUDFLARE_DNS_API_TOKEN="yourToken" - - - -### OPTIONAL SETTINGS ### - -## ā›ļø Crafty settings -# See docs/numbus-server/configuration/services/crafty.md -DYNMAP_ENABLED="false" -WANTED_NUMBER_OF_JAVA_MINECRAFT_SERVERS="1" -WANTED_NUMBER_OF_BEDROCK_MINECRAFT_SERVERS="0" - - -## šŸ“œ Script settings -# See docs/numbus-server/configuration/script.md -VERBOSE="true" - - -## šŸ—ŗ Custom subdomains -# See docs/numbus-server/configuration/services/custom_subdomain.md -PI_HOLE_SUBDOMAIN="pi-hole" -ADGUARD_SUBDOMAIN="adguard" -CRAFFY_SUBDOMAIN="crafty" -FRIGATE_SUBDOMAIN="frigate" -GITEA_SUBDOMAIN="gitea" -HOME_ASSISTANT_SUBDOMAIN="home-assistant" -HOMEPAGE_SUBDOMAIN="homepage" -IMMICH_SUBDOMAIN="immich" -IT_TOOLS_SUBDOMAIN="it-tools" -JELLYFIN_SUBDOMAIN="jellyfin" -N8N_SUBDOMAIN="n8n" -NETBOOTXYZ_SUBDOMAIN="netbootxyz" -NEXTCLOUD_SUBDOMAIN="nextcloud" -NTFY_SUBDOMAIN="ntfy" -ODOO_SUBDOMAIN="odoo" -PASSBOLT_SUBDOMAIN="passbolt" -UPTIME_KUMA_SUBDOMAIN="uptime-kuma" -VSCODIUM_SUBDOMAIN="vscodium" \ No newline at end of file diff --git a/configuration-files/numbus-tv.conf b/configuration-files/numbus-tv.conf deleted file mode 100644 index 8802a97..0000000 --- a/configuration-files/numbus-tv.conf +++ /dev/null @@ -1,22 +0,0 @@ -# --> -# MANDATORY SETTINGS -# <-- - -## Script settings -export DEBUG="true" - -## Live target settings -export LIVE_TARGET_IP="192.168.1.10" -export LIVE_TARGET_PASSWD="example" - -## Computer settings -export COMPUTER_LANGUAGE="FR" -export COMPUTER_LOCALE="fr_FR" -export COMPUTER_TIMEZONE="Europe/Paris" -export COMPUTER_OWNER_NAME="yourName" -export COMPUTER_AUTHORIZED_SSH_PUBKEYS=( "ssh-ed25519 AAAAoefzefpoipoeCEZJCPEACPAcjapjcpajepcjAPJECJPEJAPJAZ yours@yourdomain.com" ) - -## Network settings -export NETWORK_SUBNET="192.168.1.0/24" -export NETWORK_ROUTER_IP="192.168.1.1" -export HOME_SERVER_IP="192.168.1.5" \ No newline at end of file diff --git a/configurator/bridge.py b/configurator/bridge.py new file mode 100644 index 0000000..91d72db --- /dev/null +++ b/configurator/bridge.py @@ -0,0 +1,39 @@ +import http.server +import json +import osdf81ec3e7f29dfdb84a3a7eec1ea38348003b908 + +class BridgeHandler(http.server.SimpleHTTPRequestHandler): + def do_GET(self): + if self.path == '/logs': + self.send_response(200) + self.send_header('Content-type', 'text/plain') + self.send_header('Access-Control-Allow-Origin', '*') + self.end_headers() + if os.path.exists('deploy.log'): + with open('deploy.log', 'r') as f: + lines = f.readlines() + self.wfile.write("".join(lines[-20:]).encode()) + return + return http.server.SimpleHTTPRequestHandler.do_GET(self) + + def do_POST(self): + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + + if self.path == '/discovery': + with open("live_settings.json", "wb") as f: + f.write(post_data) + self.send_response(200) + self.end_headers() + # Signal Bash that discovery data is ready + with open(".discovery_ready", "w") as f: f.write("1") + + elif self.path == '/deploy': + with open("../numbus.yaml", "wb") as f: + f.write(post_data) + self.send_response(200) + self.end_headers() + with open(".deploy_signal", "w") as f: f.write("1") + +os.chdir("configurator") +http.server.HTTPServer(('localhost', 49151), BridgeHandler).serve_forever() \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index f9a8cd9..0ea3ed6 100644 --- a/deploy.sh +++ b/deploy.sh @@ -2,112 +2,64 @@ #!nix-shell -i bash -p bash nano coreutils gnused gum fastfetch xkcdpass sops ssh-to-age age sshpass envsubst pciutils usbutils mosquitto curl jq yq python3 launch_configurator() { - local PORT=8088 + local PORT=49151 local CONFIG_FILE="numbus.yaml" local BRIDGE_SCRIPT="configurator/bridge.py" - # Create a more robust Python Bridge - cat << EOF > "${BRIDGE_SCRIPT}" -import http.server -import json -import os - -class BridgeHandler(http.server.SimpleHTTPRequestHandler): - def do_GET(self): - if self.path == '/logs': - self.send_response(200) - self.send_header('Content-type', 'text/plain') - self.send_header('Access-Control-Allow-Origin', '*') - self.end_headers() - if os.path.exists('deploy.log'): - with open('deploy.log', 'r') as f: - lines = f.readlines() - self.wfile.write("".join(lines[-20:]).encode()) - return - return http.server.SimpleHTTPRequestHandler.do_GET(self) - - def do_POST(self): - content_length = int(self.headers['Content-Length']) - post_data = self.rfile.read(content_length) - - if self.path == '/discovery': - with open("live_settings.json", "wb") as f: - f.write(post_data) - self.send_response(200) - self.end_headers() - # Signal Bash that discovery data is ready - with open(".discovery_ready", "w") as f: f.write("1") - - elif self.path == '/deploy': - with open("${CONFIG_FILE}", "wb") as f: - f.write(post_data) - self.send_response(200) - self.end_headers() - with open(".deploy_signal", "w") as f: f.write("1") - -os.chdir("configurator") -http.server.HTTPServer(('localhost', ${PORT}), BridgeHandler).serve_forever() -EOF - # Cleanup old signals - rm -f configurator/.discovery_ready configurator/.deploy_signal configurator/live_settings.json configurator/hardware.json + rm -${FILES_RM_FLAGS} configurator/.discovery_ready configurator/.deploy_signal configurator/live_settings.json configurator/hardware.json - echo -e "šŸš€ Launching Numbus Configurator..." + echo -e "\n šŸš€ Launching Numbus Configurator..." python3 "${BRIDGE_SCRIPT}" > /dev/null 2>&1 & BRIDGE_PID=$! - echo -e "āž”ļø Open your browser at: $(gum style --foreground 212 "http://localhost:${PORT}")" + echo -e "\n āž”ļø Open your browser at: $(gum style --foreground 212 "http://localhost:${PORT}")" xdg-open "http://localhost:${PORT}" 2>/dev/null || open "http://localhost:${PORT}" 2>/dev/null || true } hierarchy_preparation() { - if [[ -e final-nix-config/etc/nixos/configuration.nix || -e final-nix-config/home/numbus-admin/.ssh/id_ed25519 ]]; then - gum confirm "It seems you have already run this script. Previously generated files need to be cleaned up. Proceed?" || { echo -e "\n\nāŒ Aborting."; exit 1; } - rm -rf final-nix-config/etc/nixos/* - rm -f final-nix-config/var/lib/sops-nix/* - rm -f final-nix-config/etc/secrets/disks/* - rm -f final-nix-config/var/lib/numbus-server/* - rm -f final-nix-config/home/numbus-admin/.ssh/* + if [[ -e configuration/etc/nixos/configuration.nix || -e configuration/home/numbus-admin/.ssh/id_ed25519 ]]; then + mkdir -${MKDIR_FLAGS} .trash/ + echo " āš ļø It seems you have already run this script. Previously generated files need to be cleaned up." + mv -${MV_FLAGS} configuration/{.,}* .trash/"$(date)_cleanup"/ + echo " āœ… Your files have been moved to the .trash directory. You can retrieve them there if needed." fi - mkdir -p final-nix-config/etc/ - mkdir -p final-nix-config/etc/nixos/ - mkdir -p final-nix-config/etc/secrets/ - mkdir -p final-nix-config/etc/secrets/disks/ - mkdir -p final-nix-config/etc/nixos/secrets/ - mkdir -p final-nix-config/var/ - mkdir -p final-nix-config/var/lib/ - mkdir -p final-nix-config/var/lib/sops-nix/ - mkdir -p final-nix-config/var/lib/numbus-server/ + mkdir -${MKDIR_FLAGS} configuration/home/numbus-admin/.ssh/ + mkdir -${MKDIR_FLAGS} configuration/etc/nixos/secrets/podman + mkdir -${MKDIR_FLAGS} configuration/etc/nixos/secrets/system + mkdir -${MKDIR_FLAGS} configuration/etc/nixos/secrets/disks + mkdir -${MKDIR_FLAGS} configuration/var/lib/sops-nix/ + mkdir -${MKDIR_FLAGS} configuration/var/lib/numbus-server/ - echo -e "\nāœ… Writing configuration..." - cp -${FILES_COPY_FLAGS} templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix - cp -${FILES_COPY_FLAGS} templates/nix-config/flake.nix final-nix-config/etc/nixos/flake.nix - export CONFIGURATION_PATH="final-nix-config/etc/nixos/configuration.nix" + mkdir -${MKDIR_FLAGS} to-keep-preciously/ } setup_ssh() { - mkdir -p final-nix-config/ - mkdir -p final-nix-config/home/ - mkdir -p final-nix-config/home/numbus-admin/ - mkdir -p final-nix-config/home/numbus-admin/.ssh/ + if [[ ${DEBUG} -eq 1 ]]; then + echo -e "\n āœ… Generating new SSH key for numbus-admin..." + fi - echo -e "\n\nāœ… Generating new SSH key for numbus-admin..." - chmod 700 final-nix-config/home/numbus-admin/.ssh/ - ssh-keygen -t "ed25519" -C "numbus-admin@numbus-server" -f "final-nix-config/home/numbus-admin/.ssh/id_ed25519" -N "" -q + chmod 700 configuration/home/numbus-admin/.ssh/ + ssh-keygen -t "ed25519" -C "numbus-admin@numbus-server" -f "configuration/home/numbus-admin/.ssh/id_ed25519" -N "" -q - echo -e "\n\nāž”ļø Copying SSH key to target host '${TARGET_USER}@${LIVE_TARGET_IP}'..." - if sshpass -p "${LIVE_TARGET_PASSWD}" ssh-copy-id -o StrictHostKeyChecking=no -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}"; then - echo -e "\nāœ… SSH key copied successfully" + if [[ ${DEBUG} -eq 1 ]]; then + echo -e "\n āž”ļø Copying SSH key to target host '${TARGET_USER}@${LIVE_TARGET_IP}'..." + fi + + if sshpass -p "${LIVE_TARGET_PASSWD}" ssh-copy-id -o StrictHostKeyChecking=no -i "configuration/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}"; then + if [[ ${DEBUG} -eq 1 ]]; then + echo -e "\n āœ… SSH key copied successfully" + fi else - echo -e "\nāŒ Failed to copy SSH key. Please check the host IP and password." + echo -e "\n āŒ Failed to copy SSH key. Please check the host IP and password." exit 1 fi } ssh_to_host() { local COMMAND="${1}" - ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" "${COMMAND}" + ssh -i "configuration/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" "${COMMAND}" } hardware_detection() { @@ -117,6 +69,7 @@ hardware_detection() { ssh_to_host 'bash -s' << SSHEND TARGET_GRAPHICS="false" TARGET_GRAPHICS_BRAND=() + for brand in Intel AMD NVIDIA; do if lspci -nn 2>/dev/null | grep -i "vga" | grep -iq "\${brand}"; then TARGET_GRAPHICS="true" @@ -162,7 +115,7 @@ for DISK in \$(lsblk -x SIZE -d -n -e 7,11 -o NAME); do fi # Disk health - if [[ \$(echo "$LIVE_TARGET_PASSWD" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then + if [[ \$(echo "${LIVE_TARGET_PASSWD}" | sudo -S smartctl -H /dev/\$DISK 2>/dev/null | grep 'self-assessment' | awk '{print \$6}') == "PASSED" ]]; then DISK_HEALTH+=("PASSED") else DISK_HEALTH+=("N/A") @@ -173,42 +126,34 @@ for DISK in \$(lsblk -x SIZE -d -n -e 7,11 -o NAME); do done -# Build organized JSON output for yq -cat << EOF > "\${TMPFILE}" -{ - "graphics": { - "enabled": \${TARGET_GRAPHICS}, - "brands": [ \$(printf '"%s",' "\${TARGET_GRAPHICS_BRAND[@]}" | sed 's/,\$//') ], - "renderer": \${TARGET_GRAPHICS_RENDERER} - }, - "tpu": { - "usb": \${TARGET_USB_CORAL}, - "pcie": \${TARGET_PCIE_CORAL} - }, - "tpm": { - "enabled": \${TARGET_TPM}, - "version": "\${TARGET_TPM_VERSION}" - }, - "zigbee": { - "device": "\${TARGET_ZIGBEE_DEVICE}" - }, - "network": { - "interface": "\${TARGET_INTERFACE}" - }, - "disks": [ -\$( - count=\${#DISK_NAME[@]} - for i in "\${!DISK_NAME[@]}"; do - echo " {\"name\": \"\${DISK_NAME[\$i]}\", \"path\": \"\${DISK_DEVPATH[\$i]}\", \"type\": \"\${DISK_TYPE[\$i]}\", \"health\": \"\${DISK_HEALTH[\$i]}\", \"id\": \"\${DISK_ID[\$i]}\", \"size\": \"\${DISK_SIZE[\$i]}\"}\$( [[ \$i -lt \$((count-1)) ]] && echo ',' )" - done -) - ] -} -EOF +disk_args=() +for i in "\${!DISK_NAME[@]}"; do + disk_args+=("\${DISK_NAME[\$i]}" "\${DISK_DEVPATH[\$i]}" "\${DISK_TYPE[\$i]}" "\${DISK_HEALTH[\$i]}" "\${DISK_ID[\$i]}" "\${DISK_SIZE[\$i]}") +done + +nix-shell -p jq --run "jq -n \\ + --argjson graphics_enabled \"\$TARGET_GRAPHICS\" \\ + --argjson graphics_brands \"\$(nix-shell -p jq --run \"jq -n '\\\$ARGS.positional' --args \\\"\${TARGET_GRAPHICS_BRAND[@]}\\\"\" jq)\" \\ + --argjson graphics_renderer \"\$TARGET_GRAPHICS_RENDERER\" \\ + --argjson tpu_usb \"\$TARGET_USB_CORAL\" \\ + --argjson tpu_pcie \"\$TARGET_PCIE_CORAL\" \\ + --argjson tpm_enabled \"\$TARGET_TPM\" \\ + --arg tpm_version \"\$TARGET_TPM_VERSION\" \\ + --arg zigbee_device \"\$TARGET_ZIGBEE_DEVICE\" \\ + --arg interface \"\$TARGET_INTERFACE\" \\ + --argjson disks \"\$(nix-shell -p jq --run \"jq -n '[range(\\\$ARGS.positional | length / 6) as \\\$i | {name: \\\$ARGS.positional[\\\$i*6], path: \\\$ARGS.positional[\\\$i*6+1], type: \\\$ARGS.positional[\\\$i*6+2], health: \\\$ARGS.positional[\\\$i*6+3], id: \\\$ARGS.positional[\\\$i*6+4], size: \\\$ARGS.positional[\\\$i*6+5]}]' --args \\\"\${disk_args[@]}\\\"\" jq)\" \\ + '{ + graphics: { enabled: \$graphics_enabled, brands: \$graphics_brands, renderer: \$graphics_renderer }, + tpu: { usb: \$tpu_usb, pcie: \$tpu_pcie }, + tpm: { enabled: \$tpm_enabled, version: \$tpm_version }, + zigbee: { device: \$zigbee_device }, + network: { interface: \$interface }, + disks: \$disks + }'" > "${TMPFILE}" SSHEND ### Get hardware information <-- - scp -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}":"${TMPFILE}" "hardware.json" &> /dev/null + scp -i "configuration/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}":"${TMPFILE}" "hardware.json" &> /dev/null # Create YAML for NixOS and JSON for the Configurator Website yq -P '.' hardware.json > hardware.yaml @@ -216,7 +161,7 @@ SSHEND rm hardware.json ### --> Generate hardware-configuration.nix - if ssh_to_host "sudo nixos-generate-config --no-filesystems --show-hardware-config" > final-nix-config/etc/nixos/hardware-configuration.nix; then + if ssh_to_host "sudo nixos-generate-config --no-filesystems --show-hardware-config" > configuration/etc/nixos/hardware-configuration.nix; then echo -e "\nāœ… Hardware configuration generated" else echo -e "\nāŒ Failed to generate hardware configuration" @@ -429,8 +374,8 @@ disk_config_generation() { keys_generation() { for i in $(seq 1 "${#BOOT_DISKS_ID_LIST[@]}"); do PASS="$(xkcdpass)" - echo -n "$PASS" > "final-nix-config/etc/secrets/disks/boot-${i}" - chmod 600 "final-nix-config/etc/secrets/disks/boot-${i}" + echo -n "$PASS" > "configuration/etc/secrets/disks/boot-${i}" + chmod 600 "configuration/etc/secrets/disks/boot-${i}" ssh_to_host 'bash -s' << EOF echo "$LIVE_TARGET_PASSWD" | sudo -S mkdir -p /etc/secrets/disks/ echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/boot-${i}" @@ -439,8 +384,8 @@ EOF done for i in $(seq 1 "$CONTENT_DISK_NUMBER"); do PASS="$(xkcdpass)" - echo -n "$PASS" > "final-nix-config/etc/secrets/disks/content-${i}" - chmod 600 "final-nix-config/etc/secrets/disks/content-${i}" + echo -n "$PASS" > "configuration/etc/secrets/disks/content-${i}" + chmod 600 "configuration/etc/secrets/disks/content-${i}" ssh_to_host 'bash -s' << EOF echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/content-${i}" echo "$LIVE_TARGET_PASSWD" | sudo -S chmod 600 /etc/secrets/disks/content-${i} @@ -448,8 +393,8 @@ EOF done for i in $(seq 1 "$PARITY_DISK_NUMBER"); do PASS="$(xkcdpass)" - echo -n "$PASS" > "final-nix-config/etc/secrets/disks/parity-${i}" - chmod 600 "final-nix-config/etc/secrets/disks/parity-${i}" + echo -n "$PASS" > "configuration/etc/secrets/disks/parity-${i}" + chmod 600 "configuration/etc/secrets/disks/parity-${i}" ssh_to_host 'bash -s' << EOF echo "$LIVE_TARGET_PASSWD" | sudo -S bash -c "printf '%s' '$PASS' > /etc/secrets/disks/parity-${i}" echo "$LIVE_TARGET_PASSWD" | sudo -S chmod 600 /etc/secrets/disks/parity-${i} @@ -467,18 +412,18 @@ EOF export SSH_KEYS_FORMATTED echo -e "\n āœ… Generating sops-nix keys..." - ssh-to-age -private-key -i final-nix-config/home/numbus-admin/.ssh/id_ed25519 > final-nix-config/var/lib/sops-nix/key.txt - export SOPS_PUBLIC_KEY=$(age-keygen -y final-nix-config/var/lib/sops-nix/key.txt) + ssh-to-age -private-key -i configuration/home/numbus-admin/.ssh/id_ed25519 > configuration/var/lib/sops-nix/key.txt + export SOPS_PUBLIC_KEY=$(age-keygen -y configuration/var/lib/sops-nix/key.txt) echo -e "\n āœ… Generating sops-nix configuration files..." - envsubst < templates/nix-config/sops-nix/.sops.yaml > final-nix-config/etc/nixos/.sops.yaml + envsubst < templates/nix-config/sops-nix/.sops.yaml > configuration/etc/nixos/.sops.yaml echo -e "\n āœ… Encrypting secrets in the correct file..." envsubst < "templates/nix-config/sops-nix/secrets.yaml" \ | sops encrypt --filename-override secrets.yaml \ --input-type yaml --output-type yaml \ --age $SOPS_PUBLIC_KEY \ - --output final-nix-config/etc/nixos/secrets/secrets.yaml + --output configuration/etc/nixos/secrets/secrets.yaml } sum_up() { @@ -538,18 +483,18 @@ Please save the following secrets to a secure place (i.e. your local password ma **Boot Disks (${#BOOT_DISKS_ID_LIST[@]}) :** -* **Disk 1 Secret Key :** \`$( cat final-nix-config/etc/secrets/disks/boot-1 )\` -$( [[ -n "${BOOT_DISKS_ID_LIST[1]:-}" ]] && echo "* **Disk 2 secret key :** \`$( cat final-nix-config/etc/secrets/disks/boot-2 )\`" ) +* **Disk 1 Secret Key :** \`$( cat configuration/etc/secrets/disks/boot-1 )\` +$( [[ -n "${BOOT_DISKS_ID_LIST[1]:-}" ]] && echo "* **Disk 2 secret key :** \`$( cat configuration/etc/secrets/disks/boot-2 )\`" ) **Data Disks ($CONTENT_DISK_NUMBER):** $( [[ $CONTENT_DISK_NUMBER -eq 0 ]] && echo "* *Not configured*" ) -$( [[ $CONTENT_DISK_NUMBER -gt 0 ]] && j=1 && for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do echo "* **Disk ${j} Secret Key :** \`$( cat final-nix-config/etc/secrets/disks/content-${j} )\`" && j=$((j + 1)); done ) +$( [[ $CONTENT_DISK_NUMBER -gt 0 ]] && j=1 && for i in $(seq 0 $(($CONTENT_DISK_NUMBER - 1))); do echo "* **Disk ${j} Secret Key :** \`$( cat configuration/etc/secrets/disks/content-${j} )\`" && j=$((j + 1)); done ) **Parity Disks ($PARITY_DISK_NUMBER):** $( [[ $PARITY_DISK_NUMBER -eq 0 ]] && echo "* *Not configured*" ) -$( [[ $PARITY_DISK_NUMBER -gt 0 ]] && j=1 && for i in $(seq $CONTENT_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do echo "* **Disk ${j} Secret Key :** \`$( cat final-nix-config/etc/secrets/disks/parity-${j} )\`" && j=$((j + 1)); done ) +$( [[ $PARITY_DISK_NUMBER -gt 0 ]] && j=1 && for i in $(seq $CONTENT_DISK_NUMBER $((${#DATA_DISKS_ID[@]} - 1))); do echo "* **Disk ${j} Secret Key :** \`$( cat configuration/etc/secrets/disks/parity-${j} )\`" && j=$((j + 1)); done ) EOF ) @@ -559,7 +504,7 @@ EOF gum confirm "āž”ļø Would you like to manually edit the configuration (āš ļø advanced users only)" || { echo -e "\n\nāœ… continuing with the installation..."; return 0; } - nano final-nix-config/etc/nixos/configuration.nix + nano configuration/etc/nixos/configuration.nix } cloudflare_dns_setup() { @@ -664,9 +609,9 @@ cloudflare_dns_setup() { } export_configuration() { - cp deploy.conf final-nix-config/var/lib/numbus-server/numbus-server.conf + cp -${FILES_CP_FLAGS} deploy.conf configuration/var/lib/numbus-server/numbus-server.conf - local CONFIG_EXPORT_DIR="final-nix-config/var/lib/numbus-server/" + local CONFIG_EXPORT_DIR="configuration/var/lib/numbus-server/" local CONFIG_EXPORT_FILE="${CONFIG_EXPORT_DIR}/numbus-server.conf" echo "export TARGET_INTERFACE=\"${TARGET_INTERFACE}\"" >> $CONFIG_EXPORT_FILE @@ -685,15 +630,15 @@ export_configuration() { } deploy() { - git -C . add -f "final-nix-config/" + git -C . add -f "configuration/" git -C . add -f "templates/" git -C . add -f "deploy.conf" echo -e "\n\nšŸ”„ Deploying to the remote server..." - nix flake update --flake ./final-nix-config/etc/nixos + nix flake update --flake ./configuration/etc/nixos nix run github:nix-community/nixos-anywhere -- \ - --flake ./final-nix-config/etc/nixos#numbus-server \ - --extra-files final-nix-config \ + --flake ./configuration/etc/nixos#numbus-server \ + --extra-files configuration \ --chown "/home/numbus-admin/" 1000:1000 \ --target-host ${TARGET_USER}@${LIVE_TARGET_IP} @@ -741,7 +686,7 @@ postrun_action() { Do you want to enable automatic disk decryption on boot ?" if gum confirm "āž”ļø I understand, 'yes' to proceed."; then - sshpass -p "${LIVE_TARGET_PASSWD}" ssh -i "final-nix-config/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" 'bash -s' << EOF + sshpass -p "${LIVE_TARGET_PASSWD}" ssh -i "configuration/home/numbus-admin/.ssh/id_ed25519" "${TARGET_USER}@${LIVE_TARGET_IP}" 'bash -s' << EOF echo "Enrolling boot disk key to TPM..." BOOT_DISKS_NAME=(${BOOT_DISKS_NAME[@]}) @@ -789,7 +734,7 @@ nix_update() { echo -e "\n\nšŸ”„ Updating NixOS on the remote server..." nixos-rebuild --target-host numbus-admin@${LIVE_TARGET_IP} \ - --use-remote-sudo switch --flake final-nix-config/etc/nixos#numbus-server + --use-remote-sudo switch --flake configuration/etc/nixos#numbus-server } set -euo pipefail @@ -820,28 +765,61 @@ sleep 1 # --- MAIN ORCHESTRATION LOOP --- +# 0. TESTING ONLY +DEBUG=1 + +if [[ ${DEBUG-0} -eq 1 ]]; then + FILES_CP_FLAGS="vau" + FILES_RM_FLAGS="vf" + DIR_RM_FLAGS="rvf" + MKDIR_FLAGS="pv" + MV_FLAGS="vu" +else + DEBUG=0 + FILES_CP_FLAGS="au" + FILES_RM_FLAGS="f" + DIR_RM_FLAGS="rf" + MKDIR_FLAGS="p" + MV_FLAGS="u" +fi + # 1. Initialize the UI and Bridge launch_configurator -# 2. Wait for Live Credentials from the Website -echo -ne "ā³ Waiting for device credentials from web UI..." +# 2. Prepare the directories +hierarchy_preparation + +# 3. Wait for Live Credentials from the Website +if [[ ${DEBUG} -eq 1 ]]; then + echo -e "\n ā³ Waiting for device credentials from web UI..." +fi + while [ ! -f configurator/.discovery_ready ]; do - sleep 1 + sleep 2 done -echo -e "\nāœ… Credentials received." + +if [[ ${DEBUG} -eq 1 ]]; then +echo -e "\n āœ… Credentials received." +fi # 3. Load Credentials and run Discovery +DEVICE_TYPE=$(jq -r '.device_type' configurator/live_settings.json) LIVE_TARGET_IP=$(jq -r '.live_ip' configurator/live_settings.json) LIVE_TARGET_PASSWD=$(jq -r '.live_password' configurator/live_settings.json) TARGET_USER="nixos" # Default for NixOS ISO setup_ssh -hierarchy_preparation hardware_detection -echo -e "āœ… Discovery complete. Hardware data sent to Configurator." + +if [[ ${DEBUG} -eq 1 ]]; then +echo -e "\n āœ… Discovery complete. Hardware data sent to Configurator." +fi # 4. Wait for Final Configuration Submission -echo -ne "ā³ Waiting for final configuration deployment signal..." +if [[ ${DEBUG} -eq 1 ]]; then +echo -e "\n ā³ Waiting for final configuration deployment signal..." +fi + while [ ! -f configurator/.deploy_signal ]; do sleep 1 done