From 284213cecfb4b5516eda67ca7be4d31a66a5e3e9 Mon Sep 17 00:00:00 2001 From: blobcode Date: Fri, 16 Oct 2026 20:03:09 -0400 Subject: [PATCH] add nix dev env --- .envrc | 1 + .gitignore | 1 + flake.lock | 25 +++++ flake.nix | 24 +++++ go.work.sum | 15 +++ scripts/dev.sh | 248 +++++++++++++++++++++++++++++++++++++++++++++++++ shell.nix | 11 +++ 7 files changed, 325 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 go.work.sum create mode 100755 scripts/dev.sh create mode 100644 shell.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 91c1095..2a79687 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__/ *.py[cod] auth-service/node_modules/ auth-service/data/ +.direnv/ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..30761b0 --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1791956154, + "narHash": "sha256-gJX2+xcImvxBCI3bp7zXKLUX2AwsdTxMgJ1UX/5Hm/o=", + "rev": "55bfb4d7437bd4e09ab7cba58a43bd68eb310044", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1092090.55bfb4d7437b/nixexprs.tar.zst" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..0693bd1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,24 @@ +{ + inputs.nixpkgs.url = "nixpkgs/nixos-unstable"; + + outputs = inputs: + let + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + forEachSupportedSystem = f: inputs.nixpkgs.lib.genAttrs supportedSystems (system: f { + pkgs = import inputs.nixpkgs { inherit system; }; + }); + in + { + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell { + packages = with pkgs; [ + go + nodejs + python3 + k3s + kubectl + ]; + }; + }); + }; +} diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000..7f72567 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,15 @@ +cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= +github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= diff --git a/scripts/dev.sh b/scripts/dev.sh new file mode 100755 index 0000000..422e94c --- /dev/null +++ b/scripts/dev.sh @@ -0,0 +1,248 @@ +#!/usr/bin/env bash +# +# scripts/dev.sh - Bring up local development environment for Mist +# +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT_DIR" + +# Text styles +BOLD='\033[1m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}[INFO]${NC} $*"; } +log_ok() { echo -e "${GREEN}[OK]${NC} $*"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } + +usage() { + echo -e "${BOLD}Usage:${NC} $0 [options] + +${BOLD}Options:${NC} + --frontend-only Run only the web interface dev server (Vite) + --port-forward Forward Kubernetes mist-api service to localhost:3000 and run frontend + --full-stack Start local Auth service, Backend API, and Frontend dev server + --k3s Start a local k3s server instance + --port Frontend dev server port (default: 3001) + --api-proxy Set backend API proxy URL (default: http://127.0.0.1:3000) + --help, -h Show this help message + +${BOLD}Examples:${NC} + $0 Auto-detect cluster and start local dev environment + $0 --port-forward Forward deployed cluster API (port 3000) & start frontend (port 3001) + $0 --api-proxy http://100.73.139.66:8088/api" + exit 0 +} + +# Parse options +MODE="auto" +FRONTEND_PORT="3001" +API_PROXY="${MIST_API_PROXY:-http://127.0.0.1:3000}" +START_K3S=false + +while [[ $# -gt 0 ]]; do + case "$1" in + --frontend-only) + MODE="frontend" + shift + ;; + --port-forward) + MODE="port-forward" + shift + ;; + --full-stack) + MODE="full-stack" + shift + ;; + --k3s) + START_K3S=true + shift + ;; + --port) + FRONTEND_PORT="$2" + shift 2 + ;; + --api-proxy) + API_PROXY="$2" + shift 2 + ;; + --help|-h) + usage + ;; + *) + log_error "Unknown option: $1" + usage + ;; + esac +done + +# Track background PIDs for cleanup +PIDS=() +cleanup() { + if [ ${#PIDS[@]} -gt 0 ]; then + log_info "Stopping background services..." + for pid in "${PIDS[@]}"; do + if kill -0 "$pid" 2>/dev/null; then + kill "$pid" 2>/dev/null || true + fi + done + wait 2>/dev/null || true + fi + log_ok "All services stopped." +} +trap cleanup EXIT INT TERM + +# Ensure dependencies exist +check_command() { + if ! command -v "$1" >/dev/null 2>&1; then + log_error "Command '$1' not found. Please activate the dev environment using 'direnv' or 'nix develop'." + exit 1 + fi +} + +check_command node +check_command npm +check_command go + +# Discover KUBECONFIG if not set +find_kubeconfig() { + if [ -n "${KUBECONFIG:-}" ] && [ -f "$KUBECONFIG" ]; then + return 0 + fi + for path in \ + "/home/utmist/.kube/config" \ + "$HOME/.kube/config" \ + "/etc/rancher/k3s/k3s.yaml" \ + "$HOME/.config/rancher/k3s/k3s.yaml"; do + if [ -r "$path" ]; then + export KUBECONFIG="$path" + log_info "Found Kubeconfig at: $KUBECONFIG" + return 0 + fi + done + return 1 +} + +# Check cluster reachability +cluster_reachable() { + if command -v kubectl >/dev/null 2>&1; then + kubectl cluster-info >/dev/null 2>&1 && return 0 + fi + if command -v k3s >/dev/null 2>&1; then + k3s kubectl cluster-info >/dev/null 2>&1 && return 0 + fi + return 1 +} + +KUBECTL_CMD="kubectl" +if ! command -v kubectl >/dev/null 2>&1 && command -v k3s >/dev/null 2>&1; then + KUBECTL_CMD="k3s kubectl" +fi + +# Start local k3s if requested +if [ "$START_K3S" = true ]; then + log_info "Starting local k3s server..." + check_command k3s + K3S_DATA_DIR="$ROOT_DIR/.k3s-dev" + mkdir -p "$K3S_DATA_DIR" + + if [ "$(id -u)" -eq 0 ]; then + k3s server --data-dir "$K3S_DATA_DIR" & + else + log_info "Running k3s in rootless mode..." + k3s server --rootless --data-dir "$K3S_DATA_DIR" & + fi + PIDS+=($!) + + export KUBECONFIG="$HOME/.kube/k3s.yaml" + log_info "Waiting for k3s cluster to be ready..." + for _ in $(seq 1 30); do + if cluster_reachable; then + log_ok "Local k3s cluster is ready!" + break + fi + sleep 2 + done +fi + +# Auto-detect mode if "auto" +if [ "$MODE" = "auto" ]; then + find_kubeconfig || true + if cluster_reachable; then + # Check if mist-api service exists in mist-system + if $KUBECTL_CMD -n mist-system get service/mist-api >/dev/null 2>&1; then + log_info "Detected active cluster with service/mist-api in mist-system." + MODE="port-forward" + else + log_info "Detected Kubernetes cluster. Will use local full-stack mode with cluster connectivity." + MODE="full-stack" + fi + else + log_info "No reachable Kubernetes cluster found. Starting frontend with API proxy: $API_PROXY" + MODE="frontend" + fi +fi + +# Setup web-interface dependencies +if [ ! -d "web-interface/node_modules" ]; then + log_info "Installing web-interface dependencies..." + npm --prefix web-interface ci +fi + +# Execute according to mode +case "$MODE" in + port-forward) + log_info "Starting port-forward for service/mist-api on 127.0.0.1:3000..." + $KUBECTL_CMD -n mist-system port-forward service/mist-api 3000:3000 --address 127.0.0.1 & + PIDS+=($!) + sleep 2 + + log_info "Starting Vite frontend at http://127.0.0.1:${FRONTEND_PORT} (proxying to http://127.0.0.1:3000)..." + export MIST_API_PROXY="http://127.0.0.1:3000" + npm --prefix web-interface run dev -- --host 127.0.0.1 --port "$FRONTEND_PORT" --strictPort + ;; + + full-stack) + # 1. Start auth-service if dependencies are present + if [ ! -d "auth-service/node_modules" ]; then + log_info "Installing auth-service dependencies..." + npm --prefix auth-service ci + fi + + log_info "Starting Auth service on 127.0.0.1:3002..." + export BETTER_AUTH_SECRET="${BETTER_AUTH_SECRET:-mist-local-dev-secret-key-32-chars-long}" + export MIST_ADMIN_EMAIL="${MIST_ADMIN_EMAIL:-admin@mist.local}" + export MIST_ADMIN_PASSWORD="${MIST_ADMIN_PASSWORD:-mistadmin12345}" + export PORT=3002 + export HOST=127.0.0.1 + node auth-service/server.mjs & + PIDS+=($!) + sleep 2 + + # 2. Build and start API + log_info "Building mist-api..." + go -C src build -o ../bin/mist-api . + log_info "Starting mist-api on 127.0.0.1:3000..." + export MIST_HTTP_ADDR="127.0.0.1:3000" + export MIST_AUTH_URL="http://127.0.0.1:3002" + bin/mist-api & + PIDS+=($!) + sleep 2 + + # 3. Start Frontend + log_info "Starting Vite frontend at http://127.0.0.1:${FRONTEND_PORT}..." + export MIST_API_PROXY="http://127.0.0.1:3000" + npm --prefix web-interface run dev -- --host 127.0.0.1 --port "$FRONTEND_PORT" --strictPort + ;; + + frontend) + log_info "Starting Vite frontend at http://127.0.0.1:${FRONTEND_PORT} (proxying to ${API_PROXY})..." + export MIST_API_PROXY="$API_PROXY" + npm --prefix web-interface run dev -- --host 127.0.0.1 --port "$FRONTEND_PORT" --strictPort + ;; +esac diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..9896b5e --- /dev/null +++ b/shell.nix @@ -0,0 +1,11 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + packages = with pkgs; [ + go + nodejs + python3 + k3s + kubectl + ]; +}