diff --git a/bin/wild-init b/bin/wild-init index 76e79d3..df4b436 100755 --- a/bin/wild-init +++ b/bin/wild-init @@ -51,68 +51,358 @@ if [ ! -d "${SCAFFOLD_DIR}" ]; then exit 1 fi -# Check if current directory is empty (unless --update is used) -if [ "${UPDATE}" = false ]; then - # Check if directory has any files (including hidden files, excluding . and ..) - if [ -n "$(find . -maxdepth 1 -name ".*" -o -name "*" | grep -v "^\.$" | head -1)" ]; then - echo "Error: Current directory is not empty" - echo "Use --update flag to overwrite existing scaffold files while preserving other files" - exit 1 +# Check if scaffolding already exists +if [ -d ".wildcloud" ]; then + echo "Wild-Cloud project scaffolding already exists." + echo "" + read -p "Do you want to update scaffold files? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + UPDATE=true + echo "Updating scaffold files..." + else + echo "Skipping scaffold update." + echo "" fi -fi - -echo "Initializing Wild-Cloud project in $(pwd)" - -if [ "${UPDATE}" = true ]; then - echo "Updating scaffold files (preserving existing non-scaffold files)" else - echo "Copying scaffold files to empty directory" + # Check if current directory is empty for new scaffolding + if [ "${UPDATE}" = false ]; then + # Check if directory has any files (including hidden files, excluding . and ..) + if [ -n "$(find . -maxdepth 1 -name ".*" -o -name "*" | grep -v "^\.$" | head -1)" ]; then + echo "Error: Current directory is not empty" + echo "Use --update flag to overwrite existing scaffold files while preserving other files" + exit 1 + fi + fi + + echo "Initializing Wild-Cloud project in $(pwd)" + UPDATE=false fi -# Function to copy files and directories -copy_scaffold() { - local src_dir="$1" - local dest_dir="$2" - - # Create destination directory if it doesn't exist - mkdir -p "${dest_dir}" - - # Copy directory structure - find "${src_dir}" -type d | while read -r src_subdir; do - rel_path="${src_subdir#${src_dir}}" - rel_path="${rel_path#/}" # Remove leading slash if present - if [ -n "${rel_path}" ]; then - mkdir -p "${dest_dir}/${rel_path}" - fi - done - - # Copy files - find "${src_dir}" -type f | while read -r src_file; do - rel_path="${src_file#${src_dir}}" - rel_path="${rel_path#/}" # Remove leading slash if present - dest_file="${dest_dir}/${rel_path}" +# Do scaffolding if needed +if [ ! -d ".wildcloud" ] || [ "${UPDATE}" = true ]; then + if [ "${UPDATE}" = true ]; then + echo "Updating scaffold files (preserving existing non-scaffold files)" + else + echo "Copying scaffold files to empty directory" + fi + + # Function to copy files and directories + copy_scaffold() { + local src_dir="$1" + local dest_dir="$2" - # Ensure destination directory exists - dest_file_dir=$(dirname "${dest_file}") - mkdir -p "${dest_file_dir}" + # Create destination directory if it doesn't exist + mkdir -p "${dest_dir}" - if [ "${UPDATE}" = true ] && [ -f "${dest_file}" ]; then - echo "Updating: ${rel_path}" - else - echo "Creating: ${rel_path}" - fi + # Copy directory structure + find "${src_dir}" -type d | while read -r src_subdir; do + rel_path="${src_subdir#${src_dir}}" + rel_path="${rel_path#/}" # Remove leading slash if present + if [ -n "${rel_path}" ]; then + mkdir -p "${dest_dir}/${rel_path}" + fi + done - cp "${src_file}" "${dest_file}" - done + # Copy files + find "${src_dir}" -type f | while read -r src_file; do + rel_path="${src_file#${src_dir}}" + rel_path="${rel_path#/}" # Remove leading slash if present + dest_file="${dest_dir}/${rel_path}" + + # Ensure destination directory exists + dest_file_dir=$(dirname "${dest_file}") + mkdir -p "${dest_file_dir}" + + if [ "${UPDATE}" = true ] && [ -f "${dest_file}" ]; then + echo "Updating: ${rel_path}" + else + echo "Creating: ${rel_path}" + fi + + cp "${src_file}" "${dest_file}" + done + } + + # Copy scaffold files to current directory + copy_scaffold "${SCAFFOLD_DIR}" "." + + echo "" + echo "Wild-Cloud project initialized successfully!" + echo "" +fi + +# Configuration setup (integrated from wild-setup-config) +echo "Starting configuration setup..." +echo "" + +# Include all the configuration logic from wild-setup-config +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Helper functions +print_header() { + echo -e "\n${BLUE}=== $1 ===${NC}\n" } -# Copy scaffold files to current directory -copy_scaffold "${SCAFFOLD_DIR}" "." +print_info() { + echo -e "${BLUE}INFO:${NC} $1" +} +print_warning() { + echo -e "${YELLOW}WARNING:${NC} $1" +} + +print_success() { + echo -e "${GREEN}SUCCESS:${NC} $1" +} + +print_error() { + echo -e "${RED}ERROR:${NC} $1" +} + +# Function to prompt for input with default value +prompt_with_default() { + local prompt="$1" + local default="$2" + local current_value="$3" + local result + + if [ -n "${current_value}" ] && [ "${current_value}" != "null" ]; then + printf "%s [current: %s]: " "${prompt}" "${current_value}" >&2 + read -r result + if [ -z "${result}" ]; then + result="${current_value}" + fi + elif [ -n "${default}" ]; then + printf "%s [default: %s]: " "${prompt}" "${default}" >&2 + read -r result + if [ -z "${result}" ]; then + result="${default}" + fi + else + printf "%s: " "${prompt}" >&2 + read -r result + while [ -z "${result}" ]; do + printf "This value is required. Please enter a value: " >&2 + read -r result + done + fi + + echo "${result}" +} + +# Function to get current config value safely +get_current_config() { + local key="$1" + if [ -f "${WC_HOME}/config.yaml" ]; then + set +e + result=$(wild-config "${key}" 2>/dev/null) + set -e + echo "${result}" + else + echo "" + fi +} + +# Function to get current secret value safely +get_current_secret() { + local key="$1" + if [ -f "${WC_HOME}/secrets.yaml" ]; then + set +e + result=$(wild-secret "${key}" 2>/dev/null) + set -e + echo "${result}" + else + echo "" + fi +} + +# Set and export WC_HOME +if [ -z "${WC_HOME:-}" ]; then + WC_HOME="$(pwd)" +fi +export WC_HOME + +# Detect current network subnet and gateway for IP suggestions +CURRENT_IP=$(ip route get 8.8.8.8 | awk '{print $7; exit}' 2>/dev/null || echo "192.168.1.100") +GATEWAY_IP=$(ip route | grep default | awk '{print $3; exit}' 2>/dev/null || echo "192.168.1.1") +SUBNET_PREFIX=$(echo "${CURRENT_IP}" | cut -d. -f1-3) +print_info "Detected network: ${SUBNET_PREFIX}.x (gateway: ${GATEWAY_IP})" + +print_header "Wild-Cloud Configuration Setup" +echo "This will help you configure your wild-cloud deployment." +echo "You can press Enter to keep current values or defaults." echo "" -echo "Wild-Cloud project initialized successfully!" + +# Basic Information +print_header "Basic Information" + +current_email=$(get_current_config "operator.email") +email=$(prompt_with_default "Your email address (for Let's Encrypt certificates)" "" "${current_email}") +wild-config-set "operator.email" "${email}" + +# Domain Configuration +print_header "Domain Configuration" + +current_base_domain=$(get_current_config "cloud.baseDomain") +base_domain=$(prompt_with_default "Your base domain name (e.g., example.com)" "" "${current_base_domain}") +wild-config-set "cloud.baseDomain" "${base_domain}" + +current_domain=$(get_current_config "cloud.domain") +domain=$(prompt_with_default "Your public cloud domain" "cloud.${base_domain}" "${current_domain}") +wild-config-set "cloud.domain" "${domain}" + +current_internal_domain=$(get_current_config "cloud.internalDomain") +internal_domain=$(prompt_with_default "Your internal cloud domain" "internal.${domain}" "${current_internal_domain}") +wild-config-set "cloud.internalDomain" "${internal_domain}" + +# Derive cluster name from domain (remove dots and make lowercase) +cluster_name=$(echo "${domain}" | tr '.' '-' | tr '[:upper:]' '[:lower:]') +wild-config-set "cluster.name" "${cluster_name}" +print_info "Set cluster name to: ${cluster_name}" + +# Cloudflare Configuration +print_header "Cloudflare Configuration" +echo "For automatic SSL certificates and DNS management, we use Cloudflare." echo "" -echo "Next steps:" -echo "1. Review and customize the configuration files" -echo "2. Set up your .wildcloud/config.yaml with your Wild-Cloud repository path" -echo "3. Start using wild-app-* commands to manage your applications" \ No newline at end of file + +current_cf_domain=$(get_current_config "cluster.certManager.cloudflare.domain") +if [ -z "${current_cf_domain}" ]; then + cf_domain="${domain}" +else + cf_domain="${current_cf_domain}" +fi + +echo "Is your domain '${base_domain}' registered and managed through Cloudflare? (y/n)" +read -r use_cloudflare + +if [[ "${use_cloudflare}" =~ ^[Yy]$ ]]; then + wild-config-set "cluster.certManager.cloudflare.domain" "${cf_domain}" + + current_cf_token=$(get_current_secret "cloudflare.token") + if [ -z "${current_cf_token}" ]; then + echo "" + print_info "You'll need a Cloudflare API token with the following permissions:" + echo " - Zone:Zone:Read" + echo " - Zone:DNS:Edit" + echo " - Include:All zones" + echo "" + echo "Create one at: https://dash.cloudflare.com/profile/api-tokens" + echo "" + fi + + cf_token=$(prompt_with_default "Cloudflare API token" "" "${current_cf_token}") + wild-secret-set "cloudflare.token" "${cf_token}" +else + print_warning "You'll need to configure DNS and SSL certificates manually." + print_info "Consider transferring your domain to Cloudflare for easier management." +fi + +# Network Configuration +print_header "Network Configuration" + +current_router_ip=$(get_current_config "cloud.router.ip") +router_ip=$(prompt_with_default "Router/Gateway IP" "${GATEWAY_IP}" "${current_router_ip}") +wild-config-set "cloud.router.ip" "${router_ip}" + +current_dns_ip=$(get_current_config "cloud.dns.ip") +dns_ip=$(prompt_with_default "DNS server IP (dnsmasq machine)" "${SUBNET_PREFIX}.50" "${current_dns_ip}") +wild-config-set "cloud.dns.ip" "${dns_ip}" + +current_dhcp_range=$(get_current_config "cloud.dhcpRange") +dhcp_range=$(prompt_with_default "DHCP range for dnsmasq" "${SUBNET_PREFIX}.100,${SUBNET_PREFIX}.200" "${current_dhcp_range}") +wild-config-set "cloud.dhcpRange" "${dhcp_range}" + +current_interface=$(get_current_config "cloud.dnsmasq.interface") +interface=$(prompt_with_default "Network interface for dnsmasq" "eth0" "${current_interface}") +wild-config-set "cloud.dnsmasq.interface" "${interface}" + +current_external_resolver=$(get_current_config "cloud.dns.externalResolver") +external_resolver=$(prompt_with_default "External DNS resolver" "1.1.1.1" "${current_external_resolver}") +wild-config-set "cloud.dns.externalResolver" "${external_resolver}" + +# Cluster Configuration +print_header "Kubernetes Cluster Configuration" + +current_talos_version=$(get_current_config "cluster.nodes.talos.version") +talos_version=$(prompt_with_default "Talos version" "v1.6.1" "${current_talos_version}") +wild-config-set "cluster.nodes.talos.version" "${talos_version}" + +current_ip_pool=$(get_current_config "cluster.ipAddressPool") +ip_pool=$(prompt_with_default "MetalLB IP address pool" "${SUBNET_PREFIX}.80-${SUBNET_PREFIX}.89" "${current_ip_pool}") +wild-config-set "cluster.ipAddressPool" "${ip_pool}" + +# Automatically set load balancer IP to first address in the pool +lb_ip=$(echo "${ip_pool}" | cut -d'-' -f1) +wild-config-set "cluster.loadBalancerIp" "${lb_ip}" +print_info "Set load balancer IP to: ${lb_ip} (first IP in MetalLB pool)" + +# Control plane nodes +echo "" +print_info "Configure control plane nodes (you need at least 3 for HA):" + +current_vip=$(get_current_config "cluster.nodes.control.vip") +vip=$(prompt_with_default "Control plane virtual IP" "${SUBNET_PREFIX}.90" "${current_vip}") +wild-config-set "cluster.nodes.control.vip" "${vip}" + +for i in 1 2 3; do + current_node_ip=$(get_current_config "cluster.nodes.control.node${i}.ip") + node_ip=$(prompt_with_default "Control plane node ${i} IP address" "${SUBNET_PREFIX}.$(( 90 + i ))" "${current_node_ip}") + wild-config-set "cluster.nodes.control.node${i}.ip" "${node_ip}" +done + +# Talos Configuration +echo "" + +current_schematic_id=$(get_current_config "cluster.nodes.talos.schematicId") +echo "" +print_info "Get your Talos schematic ID from: https://factory.talos.dev/" +print_info "This customizes Talos with the drivers needed for your hardware." +schematic_id=$(prompt_with_default "Talos schematic ID" "" "${current_schematic_id}") +wild-config-set "cluster.nodes.talos.schematicId" "${schematic_id}" + +# External DNS +current_owner_id=$(get_current_config "cluster.externalDns.ownerId") +owner_id=$(prompt_with_default "External DNS owner ID" "external-dns-${cluster_name}" "${current_owner_id}") +wild-config-set "cluster.externalDns.ownerId" "${owner_id}" + +# Storage Configuration +print_header "Storage Configuration" + +current_nfs_host=$(get_current_config "cloud.nfs.host") +nfs_host=$(prompt_with_default "NFS server host" "${dns_ip}" "${current_nfs_host}") +wild-config-set "cloud.nfs.host" "${nfs_host}" + +current_media_path=$(get_current_config "cloud.nfs.mediaPath") +media_path=$(prompt_with_default "NFS media path" "/mnt/storage/media" "${current_media_path}") +wild-config-set "cloud.nfs.mediaPath" "${media_path}" + +current_storage_capacity=$(get_current_config "cloud.nfs.storageCapacity") +storage_capacity=$(prompt_with_default "Storage capacity for NFS PV" "1Ti" "${current_storage_capacity}") +wild-config-set "cloud.nfs.storageCapacity" "${storage_capacity}" + +# Docker Registry +print_header "Docker Registry Configuration" + +current_registry_host=$(get_current_config "cloud.dockerRegistryHost") +registry_host=$(prompt_with_default "Docker registry hostname" "registry.${internal_domain}" "${current_registry_host}") +wild-config-set "cloud.dockerRegistryHost" "${registry_host}" + +# Summary +print_header "Configuration Complete" +print_success "Your wild-cloud configuration has been saved!" +echo "" +print_info "Configuration files:" +echo " - ${WC_HOME}/config.yaml" +echo " - ${WC_HOME}/secrets.yaml" +echo "" +print_info "Next steps:" +echo " 1. Review your configuration files" +echo " 2. Run 'wild-setup' to generate setup files" +echo " 3. Follow the setup instructions in docs/SETUP_FULL.md" +echo "" \ No newline at end of file diff --git a/bin/wild-setup-config b/bin/wild-setup-config deleted file mode 100755 index bdd111e..0000000 --- a/bin/wild-setup-config +++ /dev/null @@ -1,277 +0,0 @@ -#!/bin/bash - -set -e -set -o pipefail - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Helper functions -print_header() { - echo -e "\n${BLUE}=== $1 ===${NC}\n" -} - -print_info() { - echo -e "${BLUE}INFO:${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}WARNING:${NC} $1" -} - -print_success() { - echo -e "${GREEN}SUCCESS:${NC} $1" -} - -print_error() { - echo -e "${RED}ERROR:${NC} $1" -} - -# Function to prompt for input with default value -prompt_with_default() { - local prompt="$1" - local default="$2" - local current_value="$3" - local result - - if [ -n "${current_value}" ] && [ "${current_value}" != "null" ]; then - printf "%s [current: %s]: " "${prompt}" "${current_value}" >&2 - read -r result - if [ -z "${result}" ]; then - result="${current_value}" - fi - elif [ -n "${default}" ]; then - printf "%s [default: %s]: " "${prompt}" "${default}" >&2 - read -r result - if [ -z "${result}" ]; then - result="${default}" - fi - else - printf "%s: " "${prompt}" >&2 - read -r result - while [ -z "${result}" ]; do - printf "This value is required. Please enter a value: " >&2 - read -r result - done - fi - - echo "${result}" -} - -# Function to get current config value safely -get_current_config() { - local key="$1" - if [ -f "${WC_HOME}/config.yaml" ]; then - set +e - result=$(wild-config "${key}" 2>/dev/null) - set -e - echo "${result}" - else - echo "" - fi -} - -# Function to get current secret value safely -get_current_secret() { - local key="$1" - if [ -f "${WC_HOME}/secrets.yaml" ]; then - set +e - result=$(wild-secret "${key}" 2>/dev/null) - set -e - echo "${result}" - else - echo "" - fi -} - -# Check if we're in a wild-cloud directory -if [ ! -d ".wildcloud" ]; then - print_error "You must run this script from a wild-cloud directory" - exit 1 -fi - -# Set and export WC_HOME -if [ -z "${WC_HOME:-}" ]; then - WC_HOME="$(pwd)" -fi -export WC_HOME - -# Detect current network subnet and gateway for IP suggestions -CURRENT_IP=$(ip route get 8.8.8.8 | awk '{print $7; exit}' 2>/dev/null || echo "192.168.1.100") -GATEWAY_IP=$(ip route | grep default | awk '{print $3; exit}' 2>/dev/null || echo "192.168.1.1") -SUBNET_PREFIX=$(echo "${CURRENT_IP}" | cut -d. -f1-3) -print_info "Detected network: ${SUBNET_PREFIX}.x (gateway: ${GATEWAY_IP})" - -print_header "Wild-Cloud Configuration Setup" -echo "This script will help you configure your wild-cloud deployment." -echo "You can press Enter to keep current values or defaults." -echo "" - -# Basic Information -print_header "Basic Information" - -current_email=$(get_current_config "operator.email") -email=$(prompt_with_default "Your email address (for Let's Encrypt certificates)" "" "${current_email}") -wild-config-set "operator.email" "${email}" - -# Domain Configuration -print_header "Domain Configuration" - -current_base_domain=$(get_current_config "cloud.baseDomain") -base_domain=$(prompt_with_default "Your base domain name (e.g., example.com)" "" "${current_base_domain}") -wild-config-set "cloud.baseDomain" "${base_domain}" - -current_domain=$(get_current_config "cloud.domain") -domain=$(prompt_with_default "Your public cloud domain" "cloud.${base_domain}" "${current_domain}") -wild-config-set "cloud.domain" "${domain}" - -current_internal_domain=$(get_current_config "cloud.internalDomain") -internal_domain=$(prompt_with_default "Your internal cloud domain" "internal.${domain}" "${current_internal_domain}") -wild-config-set "cloud.internalDomain" "${internal_domain}" - -# Derive cluster name from domain (remove dots and make lowercase) -cluster_name=$(echo "${domain}" | tr '.' '-' | tr '[:upper:]' '[:lower:]') -wild-config-set "cluster.name" "${cluster_name}" - -# Cloudflare Configuration -print_header "Cloudflare Configuration" -echo "For automatic SSL certificates and DNS management, we use Cloudflare." -echo "" - -current_cf_domain=$(get_current_config "cluster.certManager.cloudflare.domain") -if [ -z "${current_cf_domain}" ]; then - cf_domain="${domain}" -else - cf_domain="${current_cf_domain}" -fi - -echo "Is your domain '${base_domain}' registered and managed through Cloudflare? (y/n)" -read -r use_cloudflare - -if [[ "${use_cloudflare}" =~ ^[Yy]$ ]]; then - wild-config-set "cluster.certManager.cloudflare.domain" "${cf_domain}" - - current_cf_token=$(get_current_secret "cloudflare.token") - if [ -z "${current_cf_token}" ]; then - echo "" - print_info "You'll need a Cloudflare API token with the following permissions:" - echo " - Zone:Zone:Read" - echo " - Zone:DNS:Edit" - echo " - Include:All zones" - echo "" - echo "Create one at: https://dash.cloudflare.com/profile/api-tokens" - echo "" - fi - - cf_token=$(prompt_with_default "Cloudflare API token" "" "${current_cf_token}") - wild-secret-set "cloudflare.token" "${cf_token}" -else - print_warning "You'll need to configure DNS and SSL certificates manually." - print_info "Consider transferring your domain to Cloudflare for easier management." -fi - -# Network Configuration -print_header "Network Configuration" - -current_router_ip=$(get_current_config "cloud.router.ip") -router_ip=$(prompt_with_default "Router/Gateway IP" "${GATEWAY_IP}" "${current_router_ip}") -wild-config-set "cloud.router.ip" "${router_ip}" - -current_dns_ip=$(get_current_config "cloud.dns.ip") -dns_ip=$(prompt_with_default "DNS server IP (dnsmasq machine)" "${SUBNET_PREFIX}.50" "${current_dns_ip}") -wild-config-set "cloud.dns.ip" "${dns_ip}" - -current_dhcp_range=$(get_current_config "cloud.dhcpRange") -dhcp_range=$(prompt_with_default "DHCP range for dnsmasq" "${SUBNET_PREFIX}.100,${SUBNET_PREFIX}.200" "${current_dhcp_range}") -wild-config-set "cloud.dhcpRange" "${dhcp_range}" - -current_interface=$(get_current_config "cloud.dnsmasq.interface") -interface=$(prompt_with_default "Network interface for dnsmasq" "eth0" "${current_interface}") -wild-config-set "cloud.dnsmasq.interface" "${interface}" - -current_external_resolver=$(get_current_config "cloud.dns.externalResolver") -external_resolver=$(prompt_with_default "External DNS resolver" "1.1.1.1" "${current_external_resolver}") -wild-config-set "cloud.dns.externalResolver" "${external_resolver}" - -# Cluster Configuration -print_header "Kubernetes Cluster Configuration" - -current_talos_version=$(get_current_config "cluster.nodes.talos.version") -talos_version=$(prompt_with_default "Talos version" "v1.6.1" "${current_talos_version}") -wild-config-set "cluster.nodes.talos.version" "${talos_version}" - -current_ip_pool=$(get_current_config "cluster.ipAddressPool") -ip_pool=$(prompt_with_default "MetalLB IP address pool" "${SUBNET_PREFIX}.80-${SUBNET_PREFIX}.89" "${current_ip_pool}") -wild-config-set "cluster.ipAddressPool" "${ip_pool}" - -# Automatically set load balancer IP to first address in the pool -lb_ip=$(echo "${ip_pool}" | cut -d'-' -f1) -wild-config-set "cluster.loadBalancerIp" "${lb_ip}" - -# Control plane nodes -echo "" - -current_vip=$(get_current_config "cluster.nodes.control.vip") -vip=$(prompt_with_default "Control plane virtual IP" "${SUBNET_PREFIX}.90" "${current_vip}") -wild-config-set "cluster.nodes.control.vip" "${vip}" - -for i in 1 2 3; do - current_node_ip=$(get_current_config "cluster.nodes.control.node${i}.ip") - node_ip=$(prompt_with_default "Control plane node ${i} IP address" "${SUBNET_PREFIX}.$(( 90 + i ))" "${current_node_ip}") - wild-config-set "cluster.nodes.control.node${i}.ip" "${node_ip}" -done - -# Talos Configuration -echo "" - -current_schematic_id=$(get_current_config "cluster.nodes.talos.schematicId") -echo "" -print_info "Get your Talos schematic ID from: https://factory.talos.dev/" -print_info "This customizes Talos with the drivers needed for your hardware." -schematic_id=$(prompt_with_default "Talos schematic ID" "" "${current_schematic_id}") -wild-config-set "cluster.nodes.talos.schematicId" "${schematic_id}" - -# External DNS -current_owner_id=$(get_current_config "cluster.externalDns.ownerId") -owner_id=$(prompt_with_default "External DNS owner ID" "external-dns-${cluster_name}" "${current_owner_id}") -wild-config-set "cluster.externalDns.ownerId" "${owner_id}" - -# Storage Configuration -print_header "Storage Configuration" - -current_nfs_host=$(get_current_config "cloud.nfs.host") -nfs_host=$(prompt_with_default "NFS server host" "${dns_ip}" "${current_nfs_host}") -wild-config-set "cloud.nfs.host" "${nfs_host}" - -current_media_path=$(get_current_config "cloud.nfs.mediaPath") -media_path=$(prompt_with_default "NFS media path" "/mnt/storage/media" "${current_media_path}") -wild-config-set "cloud.nfs.mediaPath" "${media_path}" - -current_storage_capacity=$(get_current_config "cloud.nfs.storageCapacity") -storage_capacity=$(prompt_with_default "Storage capacity for NFS PV" "1Ti" "${current_storage_capacity}") -wild-config-set "cloud.nfs.storageCapacity" "${storage_capacity}" - -# Docker Registry -print_header "Docker Registry Configuration" - -current_registry_host=$(get_current_config "cloud.dockerRegistryHost") -registry_host=$(prompt_with_default "Docker registry hostname" "registry.${internal_domain}" "${current_registry_host}") -wild-config-set "cloud.dockerRegistryHost" "${registry_host}" - -# Summary -print_header "Configuration Complete" -print_success "Your wild-cloud configuration has been saved!" -echo "" -print_info "Configuration files:" -echo " - ${WC_HOME}/config.yaml" -echo " - ${WC_HOME}/secrets.yaml" -echo "" -print_info "Next steps:" -echo " 1. Review your configuration files" -echo " 2. Run 'wild-setup' to generate setup files" -echo " 3. Follow the setup instructions in docs/SETUP_FULL.md" -echo "" \ No newline at end of file diff --git a/docs/SETUP_FULL.md b/docs/SETUP_FULL.md index 79fc9da..b4022e9 100644 --- a/docs/SETUP_FULL.md +++ b/docs/SETUP_FULL.md @@ -1,5 +1,21 @@ # Wild-cloud Setup +## Hardware prerequisites + +Procure the following before setup: + +- Any machine for running setup and managing your cloud. +- One small machine for dnsmasq (running Ubuntu linux) +- Three machines for control nodes (2GB memory, 100GB hard drive). +- Any number of worker node machines. +- A network switch connecting all these machines to your router. +- A network router (e.g. Fluke 2) connected to the Internet. +- A domain of your choice registerd (or managed) on Cloudflare. + +## Setup + +Clone this repo (you probably already did this). + ```bash source env.sh ``` @@ -10,80 +26,17 @@ Initialize a personal wild-cloud in any empty directory, for example: cd ~ mkdir ~/my-wild-cloud cd my-wild-cloud + wild-init ``` -## Cloud configuration - -```bash -cp config.example.yaml config.yaml -cp secrets.example.yaml secrets.yaml -``` - -```md -Core Variables: - -- wildcloud.root - Used by wild-config wildcloud.root command -- cluster.name - Cluster name - -DNS/Network Variables: - -- cloud.dns.ip - DNS server IP for dnsmasq -- cloud.domain - Main public domain -- cloud.internalDomain - Internal/private domain -- cloud.dhcpRange - DHCP range for dnsmasq -- cloud.router.ip - Gateway/router IP -- cloud.dnsmasq.interface - Network interface for dnsmasq -- cloud.dns.externalResolver - External DNS resolver - -Cluster Variables: - -- cluster.loadBalancerIp - Load balancer IP for services -- cluster.ipAddressPool - MetalLB IP address pool -- cluster.nodes.control.vip - Virtual IP for control plane -- cluster.nodes.control.node1/2/3.ip - Control plane node IPs -- cluster.nodes.control.node1/2/3.interface - Network interfaces -- cluster.nodes.control.node1/2/3.disk - Installation disks -- cluster.nodes.talos.version - Talos version -- cluster.nodes.talos.schematicId - Talos schematic ID - -Certificate/DNS Variables: - -- operator.email - Email for Let's Encrypt certificates -- cluster.certManager.cloudflare.domain - Domain for Cloudflare DNS challenge -- cluster.externalDns.ownerId - Unique identifier for ExternalDNS - -Storage Variables: - -- cloud.nfs.host - NFS server host -- cloud.nfs.mediaPath - NFS media path -- cloud.nfs.storageCapacity - Storage capacity for NFS PV - -Registry Variables: - -- cloud.dockerRegistryHost - Docker registry hostname -``` - -Copy setup files. - -```bash -wild-setup -``` - ## Dnsmasq - Install a Linux machine on your LAN. Record it's IP address in your `config:cloud.dns.ip`. - Ensure it is accessible with ssh. -- From your wild-cloud directory, run `wild-central-generate-setup`. -- Run `cluster/dnsmasq/bin/create-setup-bundle.sh` -- Run `cluster/dnsmasq/bin/transfer-setup-bundle.sh` - -Now ssh into your dnsmasq machine and do the following: ```bash -sudo -i -cd /root/dnsmasq-setup -./setup.sh +wild-dnsmasq-install ``` ## Cluster Setup diff --git a/my-scaffold/config.example.yaml b/my-scaffold/config.example.yaml deleted file mode 100644 index d8c62e1..0000000 --- a/my-scaffold/config.example.yaml +++ /dev/null @@ -1,63 +0,0 @@ -wildcloud: - repository: /home/adam/wildcloud -operator: - email: adam@adam.tld -cloud: - domain: cloud.adam.tld - internalDomain: internal.cloud.adam.tld - dockerRegistryHost: docker-registry.internal.cloud.adam.tld - tz: America/Los_Angeles - router: - dynamicDns: # Some routers provide this. - ip: 192.168.8.1 - nfs: - host: box-01 - mediaPath: /data/media - storageCapacity: 250Gi - dns: - ip: 192.168.8.218 - externalResolver: 1.1.1.1 - dhcpRange: 192.168.8.100,192.168.8.239 - dnsmasq: - interface: enp5s0 - username: adam -cluster: - nodes: - talos: - version: v1.10.3 - schematic: - customization: - extraKernelArgs: - - -talos.halt_if_installed - systemExtensions: - officialExtensions: - - siderolabs/gvisor - - siderolabs/intel-ucode - - siderolabs/iscsi-tools - - siderolabs/util-linux-tools - schematicId: TBD - control: - vip: 192.168.8.30 - node1: - ip: 192.168.8.31 - node2: - ip: 192.168.8.32 - node3: - ip: 192.168.8.33 - name: adam-cluster - ipaddressPool: 192.168.8.20-192.168.8.29 - loadBalancerIp: 192.168.8.20 - kubernetes: - config: /home/adam/.kube/config - context: default - dashboard: - adminUsername: admin - certManager: - namespace: cert-manager - cloudflare: - domain: adam.tld - ownerId: cloud-adam-cluster - externalDns: - ownerId: cloud-adam-cluster - dockerRegistry: - storage: 10Gi diff --git a/my-scaffold/secrets.example.yaml b/my-scaffold/secrets.example.yaml deleted file mode 100644 index dd9cd95..0000000 --- a/my-scaffold/secrets.example.yaml +++ /dev/null @@ -1,4 +0,0 @@ -cluster: - certManager: - cloudflare: - apiToken: