NextWks/deploy.sh
cclohmar b069cab1e3 fix(deploy): default server port to 80 (reverse proxy standard)
- Change config template in deploy.sh from port 8080 to port 80
- A reverse proxy must listen on port 80 for public HTTP traffic
- CAP_NET_BIND_SERVICE allows non-root binding to low ports
2026-07-06 08:54:58 +01:00

216 lines
6.6 KiB
Bash
Executable file

#!/bin/bash
# ============================================================
# NextWks — Production Deploy Script
# Idempotent: safe for first-time setup and subsequent updates.
# Run: sudo bash deploy.sh
# ============================================================
set -euo pipefail
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m'
info() { echo -e "${BLUE}[+]${NC} $1"; }
ok() { echo -e "${GREEN}[✓]${NC} $1"; }
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
die() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
header(){ echo -e "\n${BOLD}${CYAN}── $1 ──${NC}"; }
# ============================================================
# CONFIG
# ============================================================
INSTALL_DIR="/opt/nextworkspace"
SRC_DIR="${INSTALL_DIR}/src/core"
CONFIG_DIR="${INSTALL_DIR}/config/nextworkspace"
DATA_DIR="${INSTALL_DIR}/data/core"
CERTS_DIR="${INSTALL_DIR}/data/certs"
LOGS_DIR="${INSTALL_DIR}/logs"
STATIC_DIR="${INSTALL_DIR}/static"
BIN_PATH="${INSTALL_DIR}/core"
CONFIG_PATH="${CONFIG_DIR}/config.yaml"
SERVICE_FILE="/etc/systemd/system/nextwks.service"
SVC_USER="nextwks"
REPO_URL="https://git.lohmar.co.uk/lexton-it/NextWks.git"
# Must be root
[ "${EUID:-$(id -u)}" -ne 0 ] && die "Run as root: sudo bash deploy.sh"
# ============================================================
# PHASE 1: DIRECTORY SCAFFOLD + SERVICE USER
# ============================================================
header "Phase 1: Directory Structure"
if ! id "$SVC_USER" &>/dev/null; then
useradd -r -s /usr/sbin/nologin -d /nonexistent "$SVC_USER"
ok "Created service user: $SVC_USER"
else
info "Service user exists: $SVC_USER"
fi
mkdir -p "$SRC_DIR" "$CONFIG_DIR/apps.d" "$DATA_DIR" "$CERTS_DIR" "$LOGS_DIR" "$STATIC_DIR"
chown -R "$SVC_USER:$SVC_USER" "$DATA_DIR" "$CERTS_DIR" "$LOGS_DIR" "$STATIC_DIR"
ok "Directory tree created at $INSTALL_DIR/"
# ============================================================
# PHASE 2: FETCH + BUILD
# ============================================================
header "Phase 2: Build"
if [ -d "$SRC_DIR/.git" ]; then
info "Pulling latest from origin..."
cd "$SRC_DIR"
git fetch origin main --quiet
git reset --hard origin/main --quiet
ok "Repo updated"
else
info "Cloning repository..."
git clone --depth 1 "$REPO_URL" "$SRC_DIR" --quiet
cd "$SRC_DIR"
ok "Repo cloned"
fi
VERSION=$(cat "$SRC_DIR/VERSION" 2>/dev/null || echo "dev")
COMMIT_SHA=$(cd "$SRC_DIR" && git rev-parse --short HEAD)
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if ! command -v go &>/dev/null; then
die "Go is not installed. Run: apt install golang-go"
fi
info "Building v${VERSION} (${COMMIT_SHA})..."
cd "$SRC_DIR/src"
go build -ldflags="-s -w \
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.Version=${VERSION} \
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.BuildTime=${BUILD_TIME} \
-X git.lohmar.co.uk/lexton-it/NextWks/core/version.CommitSHA=${COMMIT_SHA}" \
-o "$BIN_PATH" .
chmod 755 "$BIN_PATH"
chown "$SVC_USER:$SVC_USER" "$BIN_PATH"
ok "Binary: $BIN_PATH"
# ============================================================
# PHASE 3: CONFIG + ASSETS
# ============================================================
header "Phase 3: Configuration"
if [ ! -f "$CONFIG_PATH" ]; then
ADMIN_TOKEN=$(openssl rand -hex 32 2>/dev/null || head -c32 /dev/urandom | xxd -p -c32)
SESSION_SECRET=$(openssl rand -hex 32 2>/dev/null || head -c32 /dev/urandom | xxd -p -c32)
cat > "$CONFIG_PATH" << CONFIGEOF
# NextWks — Production Configuration
# Generated: $(date)
server:
host: "0.0.0.0"
port: 80
admin:
secret_token: "${ADMIN_TOKEN}"
database:
type: "sqlite"
path: "${DATA_DIR}/nextwks.db"
authelia:
host: "http://127.0.0.1:9091"
config_path: "/opt/authelia/configuration.yml"
users_db_path: "/opt/authelia/users_database.yml"
oidc:
issuer_url: "https://app.nextwks.eu/auth"
client_id: "nextwks"
client_secret: ""
redirect_url: "https://app.nextwks.eu/access"
smtp:
host: ""
port: 587
username: ""
password: ""
from: "noreply@nextwks.local"
session:
secret: "${SESSION_SECRET}"
expiry_minutes: 60
tls:
enabled: false
domain: ""
email: ""
storage_path: "${CERTS_DIR}"
staging: false
CONFIGEOF
chmod 600 "$CONFIG_PATH"
chown "$SVC_USER:$SVC_USER" "$CONFIG_PATH"
ok "Config: $CONFIG_PATH"
warn "IMPORTANT: Edit $CONFIG_PATH with your domain, email, and SMTP settings!"
else
ok "Config exists (not overwritten): $CONFIG_PATH"
fi
if [ -d "$SRC_DIR/app/static" ]; then
cp -r "$SRC_DIR/app/static/"* "$STATIC_DIR/" 2>/dev/null || true
chown -R "$SVC_USER:$SVC_USER" "$STATIC_DIR"
ok "Static assets copied"
fi
# ============================================================
# PHASE 4: SYSTEMD
# ============================================================
header "Phase 4: Systemd"
cat > "$SERVICE_FILE" << SERVICEEOF
[Unit]
Description=Next Workspace (NextWks) Core
Documentation=https://git.lohmar.co.uk/lexton-it/NextWks
After=network-online.target authelia.service
Wants=network-online.target authelia.service
[Service]
Type=simple
User=${SVC_USER}
Group=${SVC_USER}
WorkingDirectory=${INSTALL_DIR}
ExecStart=${BIN_PATH} -config ${CONFIG_PATH}
Restart=on-failure
RestartSec=5
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=${DATA_DIR} ${LOGS_DIR} ${CERTS_DIR}
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
SERVICEEOF
systemctl daemon-reload
systemctl enable nextwks 2>/dev/null || true
systemctl restart nextwks
ok "Systemd unit installed and service restarted"
# ============================================================
# PHASE 5: HEALTH CHECK
# ============================================================
header "Phase 5: Health Check"
sleep 2
if curl -s --max-time 5 http://localhost:8080/api/health 2>/dev/null | grep -q '"status":"ok"'; then
ok "Health check passed — NextWks v${VERSION} (${COMMIT_SHA}) is running"
else
warn "Health check failed — check logs: journalctl -u nextwks -n 30"
fi
echo ""
echo -e "${GREEN}════════════════════════════════════════${NC}"
echo -e "${GREEN} NextWks v${VERSION} deployed${NC}"
echo -e "${GREEN}════════════════════════════════════════${NC}"
echo ""
info " Binary: ${BIN_PATH}"
info " Config: ${CONFIG_PATH}"
info " Data: ${DATA_DIR}"
info " Logs: journalctl -u nextwks -f"
info " Version: ${VERSION} (${COMMIT_SHA})"
echo ""