diff --git a/examples/virt/hetzner/.gitignore b/examples/virt/hetzner/.gitignore index f2fe8d3d..5d83f941 100644 --- a/examples/virt/hetzner/.gitignore +++ b/examples/virt/hetzner/.gitignore @@ -1,2 +1,4 @@ hetzner_kristof1 hetzner_kristof2 +hetzner_kristof3 +hetzner_test1 diff --git a/examples/virt/hetzner/hetzner_example.hero b/examples/virt/hetzner/hetzner_example.hero index f8a74950..ac23e1a7 100755 --- a/examples/virt/hetzner/hetzner_example.hero +++ b/examples/virt/hetzner/hetzner_example.hero @@ -1,4 +1,4 @@ -#!/usr/bin/env hero +#!/usr/bin/env hero // !!hetznermanager.configure @@ -33,5 +33,3 @@ server_name: 'kristof2' wait: true hero_install: true // Install Herolib on the new OS - - diff --git a/examples/virt/hetzner/hetzner_kristof1.vsh b/examples/virt/hetzner/hetzner_kristof1.vsh index 57dda8de..ca82ab2a 100755 --- a/examples/virt/hetzner/hetzner_kristof1.vsh +++ b/examples/virt/hetzner/hetzner_kristof1.vsh @@ -22,7 +22,7 @@ passwd := os.environ()['HETZNER_PASSWORD'] or { hs := ' !!hetznermanager.configure user:"${user}" - whitelist:"2521602,2555487" + whitelist:"2521602,2555487,2573047" password:"${passwd}" sshkey:"kristof" ' @@ -42,28 +42,28 @@ mut cl := hetznermanager.get()! println(cl.servers_list()!) -mut serverinfo := cl.server_info_get(name: 'kristof1')! +mut serverinfo := cl.server_info_get(name: name)! println(serverinfo) // cl.server_reset(name: 'kristof2', wait: true)! -// cl.server_rescue(name: 'kristof1', wait: true, hero_install: true)! +// cl.server_rescue(name: name, wait: true, hero_install: true)! // mut ks := cl.keys_get()! // println(ks) // console.print_header('SSH login') -// mut b := builder.new()! -// mut n := b.node_new(ipaddr: serverinfo.server_ip)! - -// this will put hero in debug mode on the system -// n.hero_install(compile: true)! - -// n.shell('')! cl.ubuntu_install(name: name, wait: true, hero_install: true)! // cl.ubuntu_install(name: 'kristof20', wait: true, hero_install: true)! // cl.ubuntu_install(id:2550378, name: 'kristof21', wait: true, hero_install: true)! // cl.ubuntu_install(id:2550508, name: 'kristof22', wait: true, hero_install: true)! // cl.ubuntu_install(id: 2550253, name: 'kristof23', wait: true, hero_install: true)! + +// this will put hero in debug mode on the system +mut b := builder.new()! +mut n := b.node_new(ipaddr: serverinfo.server_ip)! +n.hero_install(compile: true)! + +n.shell('')! diff --git a/examples/virt/hetzner/hetzner_kristof3.vsh b/examples/virt/hetzner/hetzner_kristof3.vsh new file mode 100755 index 00000000..4ecd44ef --- /dev/null +++ b/examples/virt/hetzner/hetzner_kristof3.vsh @@ -0,0 +1,69 @@ +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run + +import incubaid.herolib.virt.hetznermanager +import incubaid.herolib.ui.console +import incubaid.herolib.core.base +import incubaid.herolib.builder +import time +import os +import incubaid.herolib.core.playcmds + +name := 'kristof3' + +user := os.environ()['HETZNER_USER'] or { + println('HETZNER_USER not set') + exit(1) +} +passwd := os.environ()['HETZNER_PASSWORD'] or { + println('HETZNER_PASSWORD not set') + exit(1) +} + +hs := ' +!!hetznermanager.configure + user:"${user}" + whitelist:"2521602,2555487,2573047" + password:"${passwd}" + sshkey:"kristof" +' + +println(hs) + +playcmds.run(heroscript: hs)! + +console.print_header('Hetzner Test.') + +mut cl := hetznermanager.get()! +// println(cl) + +// for i in 0 .. 5 { +// println('test cache, first time slow then fast') +// } + +println(cl.servers_list()!) + +mut serverinfo := cl.server_info_get(name: name)! + +println(serverinfo) + +// cl.server_reset(name: 'kristof2', wait: true)! + +// cl.server_rescue(name: name, wait: true, hero_install: true)! + +// mut ks := cl.keys_get()! +// println(ks) + +// console.print_header('SSH login') + +cl.ubuntu_install(name: name, wait: true, hero_install: true)! +// cl.ubuntu_install(name: 'kristof20', wait: true, hero_install: true)! +// cl.ubuntu_install(id:2550378, name: 'kristof21', wait: true, hero_install: true)! +// cl.ubuntu_install(id:2550508, name: 'kristof22', wait: true, hero_install: true)! +// cl.ubuntu_install(id: 2550253, name: 'kristof23', wait: true, hero_install: true)! + +// this will put hero in debug mode on the system +mut b := builder.new()! +mut n := b.node_new(ipaddr: serverinfo.server_ip)! +n.hero_install(compile: true)! + +n.shell('')! diff --git a/examples/virt/hetzner/hetzner_test1.vsh b/examples/virt/hetzner/hetzner_test1.vsh new file mode 100755 index 00000000..880ac755 --- /dev/null +++ b/examples/virt/hetzner/hetzner_test1.vsh @@ -0,0 +1,69 @@ +#!/usr/bin/env -S v -n -w -cg -gc none -cc tcc -d use_openssl -enable-globals run + +import incubaid.herolib.virt.hetznermanager +import incubaid.herolib.ui.console +import incubaid.herolib.core.base +import incubaid.herolib.builder +import time +import os +import incubaid.herolib.core.playcmds + +name := 'test1' + +user := os.environ()['HETZNER_USER'] or { + println('HETZNER_USER not set') + exit(1) +} +passwd := os.environ()['HETZNER_PASSWORD'] or { + println('HETZNER_PASSWORD not set') + exit(1) +} + +hs := ' +!!hetznermanager.configure + user:"${user}" + whitelist:"2575034" + password:"${passwd}" + sshkey:"kristof" +' + +println(hs) + +playcmds.run(heroscript: hs)! + +console.print_header('Hetzner Test.') + +mut cl := hetznermanager.get()! +// println(cl) + +// for i in 0 .. 5 { +// println('test cache, first time slow then fast') +// } + +println(cl.servers_list()!) + +mut serverinfo := cl.server_info_get(name: name)! + +println(serverinfo) + +// cl.server_reset(name: 'kristof2', wait: true)! + +// cl.server_rescue(name: name, wait: true, hero_install: true)! + +// mut ks := cl.keys_get()! +// println(ks) + +// console.print_header('SSH login') + +cl.ubuntu_install(name: name, wait: true, hero_install: true)! +// cl.ubuntu_install(name: 'kristof20', wait: true, hero_install: true)! +// cl.ubuntu_install(id:2550378, name: 'kristof21', wait: true, hero_install: true)! +// cl.ubuntu_install(id:2550508, name: 'kristof22', wait: true, hero_install: true)! +// cl.ubuntu_install(id: 2550253, name: 'kristof23', wait: true, hero_install: true)! + +// this will put hero in debug mode on the system +mut b := builder.new()! +mut n := b.node_new(ipaddr: serverinfo.server_ip)! +n.hero_install(compile: true)! + +n.shell('')! diff --git a/examples/virt/hetzner/readme.md b/examples/virt/hetzner/readme.md index 05d4b418..f762c142 100644 --- a/examples/virt/hetzner/readme.md +++ b/examples/virt/hetzner/readme.md @@ -8,12 +8,20 @@ hero git pull https://git.threefold.info/despiegk/hero_secrets source ~/code/git.ourworld.tf/despiegk/hero_secrets/mysecrets.sh ``` -## to e.g. install kristof 1 +## to e.g. install test1 ``` -~/code/github/incubaid/herolib/examples/virt/hetzner/hetzner_kristof1.vsh +~/code/github/incubaid/herolib/examples/virt/hetzner/hetzner_test1.vsh ``` +keys available: + +- hossnys (RSA 2048) +- Jan De Landtsheer (ED25519 256) +- mahmoud (ED25519 256) +- kristof (ED25519 256) +- maxime (ED25519 256) + ## hetzner info get the login passwd from: diff --git a/lib/installers/virt/kubernetes_installer/instructions.md b/lib/installers/virt/kubernetes_installer/instructions.md new file mode 100644 index 00000000..a1de2ad7 --- /dev/null +++ b/lib/installers/virt/kubernetes_installer/instructions.md @@ -0,0 +1,217 @@ + + +need to install following + + +#!/bin/bash + +set -euo pipefail + +EXTRA_ARGS="" + +log_info() { + echo '[INFO] ' "$@" +} + +log_fatal() { + echo '[ERROR] ' "$@" >&2 + exit 1 +} + +source_env_file() { + local env_file="${1:-}" + + if [ ! -f "$env_file" ]; then + log_fatal "Environment file not found: $env_file" + fi + + set -a + source "$env_file" + set +a +} + +check_root() { + if [ "$EUID" -ne 0 ]; then + log_fatal "This script must be run as root" + fi +} + +install_deps() { + log_info "Updating package lists..." + if ! apt-get update -qq > /dev/null 2>&1; then + log_fatal "Failed to update package lists" + fi + + if ! command -v curl &> /dev/null; then + log_info "Installing curl..." + apt-get install -y -qq curl > /dev/null 2>&1 || log_fatal "Failed to install curl" + fi + + if ! command -v ip &> /dev/null; then + log_info "Installing iproute2 for ip command..." + apt-get install -y -qq iproute2 > /dev/null 2>&1 || log_fatal "Failed to install iproute2" + fi + + if ! command -v k3s &> /dev/null; then + log_info "Installing k3s..." + if ! curl -fsSL -o /usr/local/bin/k3s https://github.com/k3s-io/k3s/releases/download/v1.33.1+k3s1/k3s 2>/dev/null; then + log_fatal "Failed to download k3s" + fi + chmod +x /usr/local/bin/k3s + fi + + if ! command -v kubectl &> /dev/null; then + log_info "Installing kubectl..." + if ! curl -fsSL -o /usr/local/bin/kubectl https://dl.k8s.io/release/v1.33.1/bin/linux/amd64/kubectl 2>/dev/null; then + log_fatal "Failed to download kubectl" + fi + chmod +x /usr/local/bin/kubectl + fi +} + +get_iface_ipv6() { + local iface="$1" + + # Step 1: Find the next-hop for 400::/7 + local route_line + route_line=$(ip -6 route | grep "^400::/7.*dev ${iface}" || true) + if [ -z "$route_line" ]; then + log_fatal "No 400::/7 route found via interface ${iface}" + fi + + # Extract next-hop IPv6 + local nexthop + nexthop=$(echo "$route_line" | awk '{for(i=1;i<=NF;i++) if ($i=="via") print $(i+1)}') + local prefix + prefix=$(echo "$nexthop" | cut -d':' -f1-4) + + # Step 3: Get global IPv6 addresses and match subnet + local ipv6_list + ipv6_list=$(ip -6 addr show dev "$iface" scope global | awk '/inet6/ {print $2}' | cut -d'/' -f1) + + local ip ip_prefix + for ip in $ipv6_list; do + ip_prefix=$(echo "$ip" | cut -d':' -f1-4) + if [ "$ip_prefix" = "$prefix" ]; then + echo "$ip" + return 0 + fi + done + + log_fatal "No global IPv6 address found on ${iface} matching prefix ${prefix}" +} + +prepare_args() { + log_info "Preparing k3s arguments..." + + if [ -z "${K3S_FLANNEL_IFACE:-}" ]; then + log_fatal "K3S_FLANNEL_IFACE not set, it should be your mycelium interface" + else + local ipv6 + ipv6=$(get_iface_ipv6 "$K3S_FLANNEL_IFACE") + EXTRA_ARGS="$EXTRA_ARGS --node-ip=$ipv6" + fi + + if [ -n "${K3S_DATA_DIR:-}" ]; then + log_info "k3s data-dir set to: $K3S_DATA_DIR" + if [ -d "/var/lib/rancher/k3s" ] && [ -n "$(ls -A /var/lib/rancher/k3s 2>/dev/null)" ]; then + cp -r /var/lib/rancher/k3s/* $K3S_DATA_DIR && rm -rf /var/lib/rancher/k3s + fi + EXTRA_ARGS="$EXTRA_ARGS --data-dir $K3S_DATA_DIR --kubelet-arg=root-dir=$K3S_DATA_DIR/kubelet" + fi + + if [[ "${MASTER:-}" = "true" ]]; then + EXTRA_ARGS="$EXTRA_ARGS --cluster-cidr=2001:cafe:42::/56" + EXTRA_ARGS="$EXTRA_ARGS --service-cidr=2001:cafe:43::/112" + EXTRA_ARGS="$EXTRA_ARGS --flannel-ipv6-masq" + fi + + if [ -z "${K3S_URL:-}" ]; then + # Add additional SANs for planetary network IP, public IPv4, and public IPv6 + # https://github.com/threefoldtech/tf-images/issues/98 + local ifaces=( "tun0" "eth1" "eth2" ) + + for iface in "${ifaces[@]}" + do + # Check if interface exists before querying + if ! ip addr show "$iface" &>/dev/null; then + continue + fi + + local addrs + addrs=$(ip addr show "$iface" 2>/dev/null | grep -E "inet |inet6 " | grep "global" | cut -d '/' -f1 | awk '{print $2}' || true) + + local addr + for addr in $addrs + do + # Validate the IP address by trying to route to it + if ip route get "$addr" &>/dev/null; then + EXTRA_ARGS="$EXTRA_ARGS --tls-san $addr" + fi + done + done + + if [ "${HA:-}" = "true" ]; then + EXTRA_ARGS="$EXTRA_ARGS --cluster-init" + fi + else + if [ -z "${K3S_TOKEN:-}" ]; then + log_fatal "K3S_TOKEN must be set when K3S_URL is specified (joining a cluster)" + fi + fi +} + +patch_manifests() { + log_info "Patching manifests..." + + dir="${K3S_DATA_DIR:-/var/lib/rancher/k3s}" + manifest="$dir/server/manifests/tfgw-crd.yaml" + + # If K3S_URL found, remove manifest and exit. it is an agent node + if [[ -n "${K3S_URL:-}" ]]; then + rm -f "$manifest" + log_info "Agent node detected, removed manifest: $manifest" + exit 0 + fi + + # If K3S_URL not found, patch the manifest. it is a server node + [[ ! -f "$manifest" ]] && echo "Manifest not found: $manifest" >&2 && exit 1 + + sed -i \ + -e "s|\${MNEMONIC}|${MNEMONIC:-}|g" \ + -e "s|\${NETWORK}|${NETWORK:-}|g" \ + -e "s|\${TOKEN}|${TOKEN:-}|g" \ + "$manifest" +} + +run_node() { + if [ -z "${K3S_URL:-}" ]; then + log_info "Starting k3s server (initializing new cluster)..." + log_info "Command: k3s server --flannel-iface $K3S_FLANNEL_IFACE $EXTRA_ARGS" + exec k3s server --flannel-iface "$K3S_FLANNEL_IFACE" $EXTRA_ARGS 2>&1 + elif [ "${MASTER:-}" = "true" ]; then + log_info "Starting k3s server (joining existing cluster as master)..." + log_info "Command: k3s server --server $K3S_URL --flannel-iface $K3S_FLANNEL_IFACE $EXTRA_ARGS" + exec k3s server --server "$K3S_URL" --flannel-iface "$K3S_FLANNEL_IFACE" $EXTRA_ARGS 2>&1 + else + log_info "Starting k3s agent (joining existing cluster as worker)..." + log_info "Command: k3s agent --server $K3S_URL --flannel-iface $K3S_FLANNEL_IFACE $EXTRA_ARGS" + exec k3s agent --server "$K3S_URL" --flannel-iface "$K3S_FLANNEL_IFACE" $EXTRA_ARGS 2>&1 + fi +} + + +main() { + source_env_file "${1:-}" + check_root + install_deps + prepare_args + patch_manifests + run_node +} + +main "$@" + + + +INSTRUCTIONS: USE HEROLIB AS MUCH AS POSSIBLE e.g. SAL diff --git a/lib/installers/virt/kubernetes_installer/moreinfo.md b/lib/installers/virt/kubernetes_installer/moreinfo.md new file mode 100644 index 00000000..fbb2b9c7 --- /dev/null +++ b/lib/installers/virt/kubernetes_installer/moreinfo.md @@ -0,0 +1,3 @@ +https://github.com/codescalers/kubecloud/blob/master/k3s/native_guide/k3s_killall.sh + +still need to implement this diff --git a/lib/virt/hetznermanager/rescue.v b/lib/virt/hetznermanager/rescue.v index a1b15ba8..ae8a0a0a 100644 --- a/lib/virt/hetznermanager/rescue.v +++ b/lib/virt/hetznermanager/rescue.v @@ -193,7 +193,7 @@ pub fn (mut h HetznerManager) ubuntu_install(args ServerInstallArgs) !&builder.N console.print_debug('server ${serverinfo.server_name} is reacheable over ssh, lets now install hero if asked for.') if args.hero_install { - n.exec_silent('apt update && apt install -y mc redis')! + n.exec_silent('apt update && apt install -y mc redis libpq5 libpq-dev')! n.hero_install(compile: args.hero_install_compile)! } diff --git a/manual/serve_wiki.sh b/manual/serve_wiki.sh deleted file mode 100755 index 4ec00925..00000000 --- a/manual/serve_wiki.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -# Exit on error -set -e - -echo "Starting HeroLib Manual Wiki Server..." - -# Get the directory of this script (manual directory) -MANUAL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -# Get the directory of this script (manual directory) -CONFIG_FILE="$MANUAL_DIR/config.json" - -# Path to the wiki package -WIKI_DIR="/Users/timurgordon/code/github/incubaid/herolauncher/pkg/ui/wiki" - -# Path to the herolib directory -HEROLIB_DIR="/Users/timurgordon/code/github/incubaid/herolib" - -cd "$WIKI_DIR" - -# Run the wiki server on port 3004 -go run . "$MANUAL_DIR" "$CONFIG_FILE" 3004 - -# The script will not reach this point unless the server is stopped -echo "Wiki server stopped."