diff --git a/ct/trek.sh b/ct/trek.sh index a11b3275..647dc533 100644 --- a/ct/trek.sh +++ b/ct/trek.sh @@ -24,7 +24,7 @@ function update_script() { check_container_storage check_container_resources - if [[ ! -f ~/.trek ]]; then + if [[ ! -d /opt/trek ]]; then msg_error "No ${APP} Installation Found!" exit fi @@ -53,13 +53,14 @@ function update_script() { msg_info "Installing Server Dependencies" cd /opt/trek/server - $STD npm ci --production + $STD npm ci msg_ok "Installed Server Dependencies" mv /opt/trek-data.bak /opt/trek/data mv /opt/trek-uploads.bak /opt/trek/uploads - ln -sf /opt/trek/data /opt/trek/server/data - ln -sf /opt/trek/uploads /opt/trek/server/uploads + rm -rf /opt/trek/server/data /opt/trek/server/uploads + ln -s /opt/trek/data /opt/trek/server/data + ln -s /opt/trek/uploads /opt/trek/server/uploads cp /opt/trek.env.bak /opt/trek/server/.env rm -f /opt/trek.env.bak diff --git a/install/trek-install.sh b/install/trek-install.sh index c3e7e18b..d8dc323f 100644 --- a/install/trek-install.sh +++ b/install/trek-install.sh @@ -17,7 +17,7 @@ msg_info "Installing Dependencies" $STD apt install -y build-essential msg_ok "Installed Dependencies" -NODE_VERSION="24" setup_nodejs +NODE_VERSION="22" setup_nodejs fetch_and_deploy_gh_release "trek" "mauriceboe/TREK" "tarball" @@ -34,19 +34,24 @@ mkdir -p /opt/trek/server/public cp -r /opt/trek/client/dist/* /opt/trek/server/public/ cp -r /opt/trek/client/public/fonts /opt/trek/server/public/fonts 2>/dev/null || true mkdir -p /opt/trek/{data/logs,uploads/{files,covers,avatars,photos}} -ln -sf /opt/trek/data /opt/trek/server/data -ln -sf /opt/trek/uploads /opt/trek/server/uploads +rm -rf /opt/trek/server/data /opt/trek/server/uploads +ln -s /opt/trek/data /opt/trek/server/data +ln -s /opt/trek/uploads /opt/trek/server/uploads ENCRYPTION_KEY=$(openssl rand -hex 32) +ADMIN_EMAIL="admin@trek.local" ADMIN_PASSWORD=$(openssl rand -base64 18 | tr -dc 'A-Za-z0-9' | head -c 16) cat </opt/trek/server/.env NODE_ENV=production PORT=3000 ENCRYPTION_KEY=${ENCRYPTION_KEY} +ADMIN_EMAIL=${ADMIN_EMAIL} +ADMIN_PASSWORD=${ADMIN_PASSWORD} COOKIE_SECURE=false FORCE_HTTPS=false LOG_LEVEL=info TZ=UTC EOF +chmod 600 /opt/trek/server/.env msg_ok "Set up Server" msg_info "Creating Service" @@ -77,24 +82,16 @@ for i in $(seq 1 30); do fi sleep 1 done -cd /opt/trek/server -$STD node -e " -const Database = require('better-sqlite3'); -const bcrypt = require('bcryptjs'); -const db = new Database('./data/travel.db'); -const hash = bcrypt.hashSync('${ADMIN_PASSWORD}', 12); -db.prepare('UPDATE users SET password_hash = ?, must_change_password = 0 WHERE email = ?').run(hash, 'admin@trek.local'); -db.close(); -" -{ - echo "" - echo "TREK Admin Credentials" - echo "Email: admin@trek.local" - echo "Password: ${ADMIN_PASSWORD}" - echo "" -} >>~/trek.creds +if ! curl -sf http://localhost:3000/api/health >/dev/null 2>&1; then + msg_error "TREK failed to initialize" + exit +fi +sed -i '/^ADMIN_EMAIL=/d;/^ADMIN_PASSWORD=/d' /opt/trek/server/.env msg_ok "TREK initialized" -msg_ok "Created Service" + +echo -e "${INFO}${YW} Default Admin Account:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}Email: ${ADMIN_EMAIL}${CL}" +echo -e "${TAB}${GATEWAY}${BGN}Password: ${ADMIN_PASSWORD}${CL}" motd_ssh customize diff --git a/json/trek.json b/json/trek.json index 2631a616..9255c1db 100644 --- a/json/trek.json +++ b/json/trek.json @@ -28,17 +28,21 @@ } ], "default_credentials": { - "username": null, + "username": "admin@trek.local", "password": null }, "notes": [ { - "text": "The first user to register becomes the admin.", + "text": "A default admin account is seeded during setup with the email admin@trek.local.", "type": "info" }, { - "text": "ENCRYPTION_KEY is auto-generated during setup. See `/opt/trek/server/.env`.", + "text": "ENCRYPTION_KEY is auto-generated during setup and stored in `/opt/trek/server/.env`.", + "type": "info" + }, + { + "text": "Set APP_URL in `/opt/trek/server/.env` if you plan to use OIDC or email-based features.", "type": "info" } ] -} +} \ No newline at end of file diff --git a/misc/k3s-argocd-bootstrap.sh b/misc/k3s-argocd-bootstrap.sh new file mode 100644 index 00000000..106c6fef --- /dev/null +++ b/misc/k3s-argocd-bootstrap.sh @@ -0,0 +1,103 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Quick homelab bootstrap for a single-node management VM +# - Installs K3s (if missing) +# - Installs Argo CD (optional) +# - Waits for core components to become ready +# +# Usage examples: +# sudo bash k3s-argocd-bootstrap.sh +# sudo INSTALL_ARGOCD=false bash k3s-argocd-bootstrap.sh +# sudo K3S_VERSION="v1.34.1+k3s1" bash k3s-argocd-bootstrap.sh + +K3S_VERSION="${K3S_VERSION:-v1.34.1+k3s1}" +INSTALL_ARGOCD="${INSTALL_ARGOCD:-true}" +ARGOCD_NAMESPACE="${ARGOCD_NAMESPACE:-argocd}" +ARGOCD_MANIFEST_URL="${ARGOCD_MANIFEST_URL:-https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml}" + +log() { + echo "[INFO] $*" +} + +ok() { + echo "[OK] $*" +} + +fail() { + echo "[ERROR] $*" >&2 + exit 1 +} + +require_root() { + if [[ "${EUID}" -ne 0 ]]; then + fail "Run as root (sudo)." + fi +} + +install_k3s_if_missing() { + if command -v k3s >/dev/null 2>&1; then + ok "K3s is already installed: $(k3s --version | head -n1)" + return + fi + + log "Installing K3s (${K3S_VERSION})" + curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="${K3S_VERSION}" sh - + ln -sf /usr/local/bin/k3s /usr/local/bin/kubectl + ok "K3s installed" +} + +wait_for_k3s() { + log "Waiting for K3s node readiness" + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + for _ in $(seq 1 90); do + if kubectl get nodes >/dev/null 2>&1; then + if kubectl get nodes --no-headers 2>/dev/null | grep -q " Ready "; then + ok "K3s node is Ready" + return + fi + fi + sleep 2 + done + fail "K3s did not become Ready in time" +} + +install_argocd() { + if [[ "${INSTALL_ARGOCD}" != "true" ]]; then + log "Skipping ArgoCD installation (INSTALL_ARGOCD=${INSTALL_ARGOCD})" + return + fi + + log "Installing ArgoCD into namespace ${ARGOCD_NAMESPACE}" + kubectl create namespace "${ARGOCD_NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f - + kubectl apply -n "${ARGOCD_NAMESPACE}" -f "${ARGOCD_MANIFEST_URL}" + + log "Waiting for ArgoCD server deployment" + kubectl -n "${ARGOCD_NAMESPACE}" rollout status deploy/argocd-server --timeout=10m + ok "ArgoCD installed" +} + +print_next_steps() { + echo + echo "---" + echo "KUBECONFIG path: /etc/rancher/k3s/k3s.yaml" + if [[ "${INSTALL_ARGOCD}" == "true" ]]; then + echo "ArgoCD initial admin secret:" + echo " kubectl -n ${ARGOCD_NAMESPACE} get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d; echo" + echo "Port-forward UI:" + echo " kubectl -n ${ARGOCD_NAMESPACE} port-forward svc/argocd-server 8080:443" + fi + echo "Cluster check:" + echo " kubectl get nodes -o wide" +} + +main() { + require_root + install_k3s_if_missing + wait_for_k3s + install_argocd + print_next_steps +} + +main "$@" diff --git a/tools/pve/lxc-prehook.sh b/tools/pve/lxc-prehook.sh index a4203114..9a6dfcf5 100644 --- a/tools/pve/lxc-prehook.sh +++ b/tools/pve/lxc-prehook.sh @@ -395,10 +395,12 @@ append_unique_line_in_ct() { local target_file="$1" local line="$2" - retry_pct_exec bash -c " - touch '$target_file' - grep -Fqx -- \"$line\" '$target_file' || echo \"$line\" >> '$target_file' - " + retry_pct_exec bash -c ' + target_file="$1" + line="$2" + touch "$target_file" + grep -Fqx -- "$line" "$target_file" || echo "$line" >> "$target_file" + ' _ "$target_file" "$line" } resolve_requested_packages() { diff --git a/vm/k3s-vm.sh b/vm/k3s-vm.sh index f5548b85..63b4e79e 100644 --- a/vm/k3s-vm.sh +++ b/vm/k3s-vm.sh @@ -23,6 +23,7 @@ METHOD="" NSAPP="Debian 12 VM" var_os="debian" var_version="12" +INSTALL_ARGOCD_BOOTSTRAP="${INSTALL_ARGOCD_BOOTSTRAP:-1}" THIN="discard=on,ssd=1," set -e @@ -380,6 +381,57 @@ virt-customize -q -a "${FILE}" \ msg_ok "Added in Image K3s, Helm & k9s" +if [[ "$INSTALL_ARGOCD_BOOTSTRAP" == "1" ]]; then + msg_info "Add in Image ArgoCD Bootstrap" + virt-customize -q -a "${FILE}" \ + --run-command 'mkdir -p /usr/local/sbin /etc/systemd/system /var/lib' \ + --run-command 'cat <<"EOF" >/usr/local/sbin/bootstrap-argocd.sh +#!/usr/bin/env bash +set -euo pipefail + +export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + +for _ in $(seq 1 120); do + if kubectl get nodes --no-headers 2>/dev/null | grep -q " Ready "; then + break + fi + sleep 2 +done + +if ! kubectl get nodes --no-headers 2>/dev/null | grep -q " Ready "; then + echo "K3s is not ready yet" + exit 1 +fi + +kubectl create namespace argocd --dry-run=client -o yaml | kubectl apply -f - +kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml +kubectl -n argocd rollout status deploy/argocd-server --timeout=10m + +touch /var/lib/argocd-bootstrap.done +EOF' \ + --run-command 'chmod +x /usr/local/sbin/bootstrap-argocd.sh' \ + --run-command 'cat <<"EOF" >/etc/systemd/system/argocd-bootstrap.service +[Unit] +Description=ArgoCD Bootstrap +After=network-online.target k3s.service +Wants=network-online.target +ConditionPathExists=!/var/lib/argocd-bootstrap.done + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/bootstrap-argocd.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target +EOF' \ + --run-command 'systemctl enable argocd-bootstrap.service' >/dev/null + + msg_ok "Added in Image ArgoCD Bootstrap" +else + msg_info "Skipping ArgoCD Bootstrap (INSTALL_ARGOCD_BOOTSTRAP=$INSTALL_ARGOCD_BOOTSTRAP)" +fi + msg_ok "Created a Debian 12 VM ${CL}${BL}(${HN})" if [ "$START_VM" == "yes" ]; then msg_info "Starting Debian 12 VM"