From 89095f3d5d3dd6c2a23a224404ddab3a3f363808 Mon Sep 17 00:00:00 2001 From: "CanbiZ (MickLesk)" <47820557+MickLesk@users.noreply.github.com> Date: Fri, 24 Apr 2026 09:52:03 +0200 Subject: [PATCH] trek: seed default admin, fix install and hooks Seed a default admin account and harden the installer; update symlink behavior and LXC hook argument handling. - Install: downgrade Node setup to 22, write ADMIN_EMAIL/ADMIN_PASSWORD into /opt/trek/server/.env for initial boot, chmod the file, wait for app health, then remove plaintext creds from the env and print the default admin credentials. Remove previous DB patching script and credentials file generation. Add health-check failure handling. - ct/trek.sh: check for /opt/trek instead of ~/.trek, run npm ci without --production, and recreate server data/uploads by removing any existing dirs and creating explicit symlinks. - Installer: mirror symlink strategy used in the container (rm then ln -s) and ensure generated ENCRYPTION_KEY note; add ADMIN_EMAIL default. - json: set default username to admin@trek.local, update notes about seeded admin, ENCRYPTION_KEY storage, and APP_URL recommendation. - tools/pve/lxc-prehook.sh: fix append_unique_line_in_ct to pass positional arguments into the bash -c snippet safely (avoid parent-shell expansion). These changes ensure a reproducible default admin creation flow without leaving plaintext credentials, improve symlink handling, and fix a bug in the LXC prehook. --- ct/trek.sh | 9 +-- install/trek-install.sh | 37 ++++++------- json/trek.json | 12 ++-- misc/k3s-argocd-bootstrap.sh | 103 +++++++++++++++++++++++++++++++++++ tools/pve/lxc-prehook.sh | 10 ++-- vm/k3s-vm.sh | 52 ++++++++++++++++++ 6 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 misc/k3s-argocd-bootstrap.sh 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"