147 lines
6.0 KiB
Bash
Executable File
147 lines
6.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# ─── Configuration ───────────────────────────────────────────────────────────
|
|
K3S_VERSION="v1.31.4+k3s1"
|
|
LONGHORN_VERSION="1.7.2"
|
|
LONGHORN_REPO="https://charts.longhorn.io"
|
|
|
|
# ─── Helper ──────────────────────────────────────────────────────────────────
|
|
info() { printf '\033[1;34m[INFO]\033[0m %s\n' "$*"; }
|
|
warn() { printf '\033[1;33m[WARN]\033[0m %s\n' "$*"; }
|
|
error() { printf '\033[1;31m[ERROR]\033[0m %s\n' "$*" >&2; exit 1; }
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $(basename "$0") <command>
|
|
|
|
Commands:
|
|
server Install k3s server (manager node)
|
|
agent Install k3s agent (worker node)
|
|
longhorn Install Longhorn via Helm
|
|
sops-keygen Generate an age keypair for SOPS
|
|
apply-secrets Decrypt and apply SOPS secrets to the cluster
|
|
deploy Helm-install all charts
|
|
all Run: server → longhorn → sops-keygen → apply-secrets → deploy
|
|
EOF
|
|
}
|
|
|
|
# ─── k3s server ──────────────────────────────────────────────────────────────
|
|
cmd_server() {
|
|
info "Installing k3s server ${K3S_VERSION} …"
|
|
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="${K3S_VERSION}" sh -s - server \
|
|
--write-kubeconfig-mode 644
|
|
|
|
info "Waiting for node to be Ready …"
|
|
until kubectl get node "$(hostname)" -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null | grep -q True; do
|
|
sleep 2
|
|
done
|
|
info "Server node is Ready."
|
|
|
|
local token
|
|
token=$(cat /var/lib/rancher/k3s/server/node-token)
|
|
local ip
|
|
ip=$(hostname -I | awk '{print $1}')
|
|
info "Worker join command:"
|
|
echo " curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=\"${K3S_VERSION}\" K3S_URL=\"https://${ip}:6443\" K3S_TOKEN=\"${token}\" sh -"
|
|
}
|
|
|
|
# ─── k3s agent ───────────────────────────────────────────────────────────────
|
|
cmd_agent() {
|
|
if [[ -z "${K3S_URL:-}" || -z "${K3S_TOKEN:-}" ]]; then
|
|
error "Set K3S_URL and K3S_TOKEN environment variables first.\n K3S_URL=https://<manager-ip>:6443 K3S_TOKEN=<token> $0 agent"
|
|
fi
|
|
info "Installing k3s agent ${K3S_VERSION} …"
|
|
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="${K3S_VERSION}" K3S_URL="${K3S_URL}" K3S_TOKEN="${K3S_TOKEN}" sh -
|
|
info "Agent installed. It will appear as a node shortly."
|
|
}
|
|
|
|
# ─── Longhorn ────────────────────────────────────────────────────────────────
|
|
cmd_longhorn() {
|
|
info "Installing Longhorn ${LONGHORN_VERSION} via Helm …"
|
|
helm repo add longhorn "${LONGHORN_REPO}" 2>/dev/null || true
|
|
helm repo update longhorn
|
|
kubectl create namespace longhorn-system 2>/dev/null || true
|
|
helm upgrade --install longhorn longhorn/longhorn \
|
|
--namespace longhorn-system \
|
|
--version "${LONGHORN_VERSION}" \
|
|
--set defaultSettings.defaultReplicaCount=2 \
|
|
--wait
|
|
info "Longhorn installed."
|
|
}
|
|
|
|
# ─── SOPS / age ─────────────────────────────────────────────────────────────
|
|
cmd_sops_keygen() {
|
|
local keydir="/etc/sops/age"
|
|
local keyfile="${keydir}/keys.txt"
|
|
if [[ -f "${keyfile}" ]]; then
|
|
warn "Age key already exists at ${keyfile} — skipping generation."
|
|
else
|
|
info "Generating age keypair …"
|
|
sudo mkdir -p "${keydir}"
|
|
age-keygen -o "${keyfile}" 2>&1
|
|
sudo chmod 600 "${keyfile}"
|
|
info "Key written to ${keyfile}"
|
|
fi
|
|
info "Public key (put this in .sops.yaml):"
|
|
grep 'public key' "${keyfile}" | awk '{print $NF}'
|
|
}
|
|
|
|
cmd_apply_secrets() {
|
|
local secrets_dir
|
|
secrets_dir="$(cd "$(dirname "$0")/.." && pwd)/secrets"
|
|
info "Decrypting and applying secrets …"
|
|
local decrypted
|
|
decrypted="$(sops -d "${secrets_dir}/secrets.enc.yaml")"
|
|
|
|
local ns
|
|
for ns in $(printf '%s\n' "${decrypted}" | grep '^\s*namespace:' | awk '{print $2}' | sort -u); do
|
|
kubectl create namespace "${ns}" 2>/dev/null || true
|
|
done
|
|
|
|
printf '%s\n' "${decrypted}" | kubectl apply -f -
|
|
info "Secrets applied."
|
|
}
|
|
|
|
# ─── Deploy all charts ──────────────────────────────────────────────────────
|
|
cmd_deploy() {
|
|
local charts_dir
|
|
charts_dir="$(cd "$(dirname "$0")/.." && pwd)/charts"
|
|
|
|
local -a chart_order=(traefik-config media paperless mealie dashboards utils headlamp gitea)
|
|
local -A chart_ns=(
|
|
[traefik-config]=kube-system
|
|
[media]=media
|
|
[paperless]=apps
|
|
[mealie]=apps
|
|
[dashboards]=apps
|
|
[utils]=apps
|
|
[headlamp]=apps
|
|
[gitea]=apps
|
|
)
|
|
|
|
for chart in "${chart_order[@]}"; do
|
|
local ns="${chart_ns[$chart]}"
|
|
info "Deploying ${chart} → namespace ${ns} …"
|
|
kubectl create namespace "${ns}" 2>/dev/null || true
|
|
helm upgrade --install "${chart}" "${charts_dir}/${chart}" \
|
|
--namespace "${ns}" \
|
|
--wait --timeout 5m
|
|
done
|
|
info "All charts deployed."
|
|
}
|
|
|
|
# ─── Main ────────────────────────────────────────────────────────────────────
|
|
[[ $# -lt 1 ]] && { usage; exit 1; }
|
|
|
|
case "$1" in
|
|
server) cmd_server ;;
|
|
agent) cmd_agent ;;
|
|
longhorn) cmd_longhorn ;;
|
|
sops-keygen) cmd_sops_keygen ;;
|
|
apply-secrets) cmd_apply_secrets ;;
|
|
deploy) cmd_deploy ;;
|
|
all) cmd_server; cmd_longhorn; cmd_sops_keygen; cmd_apply_secrets; cmd_deploy ;;
|
|
*) usage; exit 1 ;;
|
|
esac
|