chore: restructure repo to /root/lexton-it/NextWks/ with src/ + app/ layout and install.sh
This commit is contained in:
parent
ed68a8c51a
commit
e3fbe0f9d9
5 changed files with 255 additions and 16 deletions
17
.gitignore
vendored
17
.gitignore
vendored
|
|
@ -1,8 +1,9 @@
|
||||||
# Binaries
|
# Binaries
|
||||||
/bin/
|
app/core
|
||||||
/data/*.db
|
app/core.exe
|
||||||
/data/*.db-wal
|
app/data/*.db
|
||||||
/data/*.db-shm
|
app/data/*.db-wal
|
||||||
|
app/data/*.db-shm
|
||||||
|
|
||||||
# OS files
|
# OS files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
@ -18,8 +19,6 @@ Thumbs.db
|
||||||
.env
|
.env
|
||||||
.env.local
|
.env.local
|
||||||
|
|
||||||
# Setup check binary
|
# Generated binaries (development build)
|
||||||
src/setupcheck
|
src/core/setupcheck
|
||||||
src/setupcheck.exe
|
src/core/setupcheck.exe
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
# Next Workspace (NextWks) Configuration
|
# Next Workspace (NextWks) - Development Configuration
|
||||||
# Path: /opt/nextwks/config.yaml
|
# Path: ./config.yaml (relative to binary)
|
||||||
|
# For production, install.sh deploys to /opt/nextwks/config.yaml
|
||||||
|
|
||||||
server:
|
server:
|
||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
port: 8080
|
port: 8080
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
secret_token: "CHANGE_ME_ADMIN_SECRET_TOKEN"
|
secret_token: "dev-admin-secret-token"
|
||||||
|
|
||||||
database:
|
database:
|
||||||
type: "sqlite"
|
type: "sqlite"
|
||||||
path: "/opt/nextwks/data/nextwks.db"
|
path: "./data/nextwks.db"
|
||||||
|
|
||||||
authelia:
|
authelia:
|
||||||
host: "http://127.0.0.1:9091"
|
host: "http://127.0.0.1:9091"
|
||||||
|
|
@ -25,5 +26,5 @@ smtp:
|
||||||
from: "noreply@nextwks.local"
|
from: "noreply@nextwks.local"
|
||||||
|
|
||||||
session:
|
session:
|
||||||
secret: "CHANGE_ME_SESSION_SECRET"
|
secret: "dev-session-secret"
|
||||||
expiry_minutes: 60
|
expiry_minutes: 60
|
||||||
206
install.sh
Executable file
206
install.sh
Executable file
|
|
@ -0,0 +1,206 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Next Workspace (NextWks) - Bare-Metal Installer
|
||||||
|
# Deploys compiled binaries to /opt/nextwks/ for production use
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./install.sh # Build and install
|
||||||
|
# ./install.sh --skip-build # Install existing binaries only
|
||||||
|
# ./install.sh --config-only # Generate config only
|
||||||
|
# ./install.sh --uninstall # Remove installation
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
error() { echo -e "${RED}Error:${NC} $1" >&2; }
|
||||||
|
success() { echo -e "${GREEN}$1${NC}"; }
|
||||||
|
info() { echo -e "${BLUE}$1${NC}"; }
|
||||||
|
warn() { echo -e "${YELLOW}Warning:${NC} $1"; }
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
INSTALL_DIR="/opt/nextwks"
|
||||||
|
BIN_DIR="${INSTALL_DIR}/bin"
|
||||||
|
DATA_DIR="${INSTALL_DIR}/data"
|
||||||
|
MODULES_DIR="${INSTALL_DIR}/modules"
|
||||||
|
CONFIG_FILE="${INSTALL_DIR}/config.yaml"
|
||||||
|
SERVICE_FILE="/etc/systemd/system/nextwks.service"
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
SKIP_BUILD=false
|
||||||
|
CONFIG_ONLY=false
|
||||||
|
UNINSTALL=false
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--skip-build) SKIP_BUILD=true ;;
|
||||||
|
--config-only) CONFIG_ONLY=true ;;
|
||||||
|
--uninstall) UNINSTALL=true ;;
|
||||||
|
*) error "Unknown argument: $arg"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Uninstall ---
|
||||||
|
if [ "$UNINSTALL" = true ]; then
|
||||||
|
info "Uninstalling Next Workspace..."
|
||||||
|
|
||||||
|
if [ -f "$SERVICE_FILE" ]; then
|
||||||
|
systemctl stop nextwks 2>/dev/null || true
|
||||||
|
systemctl disable nextwks 2>/dev/null || true
|
||||||
|
rm -f "$SERVICE_FILE"
|
||||||
|
systemctl daemon-reload
|
||||||
|
info "Removed systemd service"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -d "$INSTALL_DIR" ]; then
|
||||||
|
rm -rf "$INSTALL_DIR"
|
||||||
|
success "Removed $INSTALL_DIR"
|
||||||
|
else
|
||||||
|
info "No installation found at $INSTALL_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "Uninstall complete"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Build ---
|
||||||
|
if [ "$SKIP_BUILD" = false ] && [ "$CONFIG_ONLY" = false ]; then
|
||||||
|
info "Building Next Workspace core..."
|
||||||
|
|
||||||
|
if ! command -v go &>/dev/null; then
|
||||||
|
error "Go is not installed. Install Go 1.22+ first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$REPO_DIR/src"
|
||||||
|
|
||||||
|
# Build the core binary
|
||||||
|
go build -o "$REPO_DIR/app/core" -ldflags="-s -w" .
|
||||||
|
success "Core binary built: app/core"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Install ---
|
||||||
|
if [ "$CONFIG_ONLY" = false ]; then
|
||||||
|
info "Installing to $INSTALL_DIR..."
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
mkdir -p "$BIN_DIR" "$DATA_DIR" "$MODULES_DIR"
|
||||||
|
|
||||||
|
# Copy binary
|
||||||
|
if [ -f "$REPO_DIR/app/core" ]; then
|
||||||
|
cp "$REPO_DIR/app/core" "$BIN_DIR/core"
|
||||||
|
chmod 755 "$BIN_DIR/core"
|
||||||
|
success "Installed binary to $BIN_DIR/core"
|
||||||
|
else
|
||||||
|
error "Binary not found. Run without --skip-build or build manually."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy modules if any exist
|
||||||
|
if [ -d "$REPO_DIR/app/modules" ] && [ "$(ls -A "$REPO_DIR/app/modules" 2>/dev/null)" ]; then
|
||||||
|
cp -r "$REPO_DIR/app/modules"/* "$MODULES_DIR/"
|
||||||
|
success "Installed modules"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
info "Generating configuration..."
|
||||||
|
|
||||||
|
if [ ! -f "$CONFIG_FILE" ]; then
|
||||||
|
# Generate unique secrets
|
||||||
|
ADMIN_SECRET=$(openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | xxd -p -c 32)
|
||||||
|
SESSION_SECRET=$(openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | xxd -p -c 32)
|
||||||
|
|
||||||
|
cat > "$CONFIG_FILE" << CONFIGEOF
|
||||||
|
# Next Workspace (NextWks) - Production Configuration
|
||||||
|
# Auto-generated by install.sh on $(date)
|
||||||
|
|
||||||
|
server:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
admin:
|
||||||
|
secret_token: "${ADMIN_SECRET}"
|
||||||
|
|
||||||
|
database:
|
||||||
|
type: "sqlite"
|
||||||
|
path: "${DATA_DIR}/nextwks.db"
|
||||||
|
|
||||||
|
authelia:
|
||||||
|
host: "http://127.0.0.1:9091"
|
||||||
|
config_path: "/opt/authelia/config/configuration.yml"
|
||||||
|
users_db_path: "/opt/authelia/data/users_database.yml"
|
||||||
|
|
||||||
|
smtp:
|
||||||
|
host: ""
|
||||||
|
port: 587
|
||||||
|
username: ""
|
||||||
|
password: ""
|
||||||
|
from: "noreply@nextwks.local"
|
||||||
|
|
||||||
|
session:
|
||||||
|
secret: "${SESSION_SECRET}"
|
||||||
|
expiry_minutes: 60
|
||||||
|
CONFIGEOF
|
||||||
|
|
||||||
|
chmod 600 "$CONFIG_FILE"
|
||||||
|
success "Configuration generated: $CONFIG_FILE"
|
||||||
|
warn "Admin secret token: ${ADMIN_SECRET}"
|
||||||
|
warn "Save this token! You need it for admin API access."
|
||||||
|
else
|
||||||
|
info "Configuration already exists at $CONFIG_FILE (not overwritten)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Systemd Service ---
|
||||||
|
if [ "$CONFIG_ONLY" = false ]; then
|
||||||
|
info "Setting up systemd service..."
|
||||||
|
|
||||||
|
cat > "$SERVICE_FILE" << SERVICEEOF
|
||||||
|
[Unit]
|
||||||
|
Description=Next Workspace (NextWks) Core
|
||||||
|
After=network.target authelia.service
|
||||||
|
Wants=authelia.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
WorkingDirectory=${INSTALL_DIR}
|
||||||
|
ExecStart=${BIN_DIR}/core -config ${CONFIG_FILE}
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
SERVICEEOF
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
success "Systemd service created: $SERVICE_FILE"
|
||||||
|
info "Enable with: systemctl enable --now nextwks"
|
||||||
|
info "Start with: systemctl start nextwks"
|
||||||
|
info "Status with: systemctl status nextwks"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Summary ---
|
||||||
|
echo ""
|
||||||
|
success "═══════════════════════════════════════════"
|
||||||
|
success " Next Workspace (NextWks) installed!"
|
||||||
|
success "═══════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
info " Binary: ${BIN_DIR}/core"
|
||||||
|
info " Config: ${CONFIG_FILE}"
|
||||||
|
info " Data: ${DATA_DIR}/"
|
||||||
|
info " Service: nextwks"
|
||||||
|
echo ""
|
||||||
|
info " Admin UI: http://localhost:8080/admin"
|
||||||
|
info " Health API: http://localhost:8080/api/health"
|
||||||
|
echo ""
|
||||||
|
info " Start with: systemctl start nextwks"
|
||||||
|
info " Logs: journalctl -u nextwks -f"
|
||||||
|
echo ""
|
||||||
10
src/main.go
10
src/main.go
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -15,10 +16,15 @@ import (
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
||||||
logger.Info("starting Next Workspace (NextWks)")
|
|
||||||
|
// Config path: default to ./config.yaml for dev, override with -config for production
|
||||||
|
configPath := flag.String("config", "./config.yaml", "path to configuration file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
logger.Info("starting Next Workspace (NextWks)", "config", *configPath)
|
||||||
|
|
||||||
// Load configuration
|
// Load configuration
|
||||||
cfg, err := config.Load("/opt/nextwks/config.yaml")
|
cfg, err := config.Load(*configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("failed to load config", "error", err)
|
logger.Error("failed to load config", "error", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
||||||
27
testdata/authelia/configuration.yml
vendored
Normal file
27
testdata/authelia/configuration.yml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Authelia Configuration (Development Mock)
|
||||||
|
# Path: used for testing config parsing
|
||||||
|
|
||||||
|
host: 0.0.0.0
|
||||||
|
port: 9091
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: debug
|
||||||
|
|
||||||
|
jwt_secret: dev-jwt-secret-change-in-production
|
||||||
|
|
||||||
|
session:
|
||||||
|
name: authelia_session
|
||||||
|
secret: dev-authelia-session-secret-please-change
|
||||||
|
expiration: 1h
|
||||||
|
inactivity: 5m
|
||||||
|
|
||||||
|
storage:
|
||||||
|
local:
|
||||||
|
path: /opt/authelia/data/db.sqlite
|
||||||
|
|
||||||
|
access_control:
|
||||||
|
default_policy: deny
|
||||||
|
|
||||||
|
authentication_backend:
|
||||||
|
file:
|
||||||
|
path: /opt/authelia/data/users_database.yml
|
||||||
Loading…
Reference in a new issue