#!/bin/bash # NextNVR — One-Line Deployment Script # Usage: curl -sSL https://git.lohmar.co.uk/cclohmar/NextNVR/raw/branch/main/setup.sh | bash set -e GIT_URL="https://git.lohmar.co.uk/cclohmar/NextNVR.git" DEPLOY_DIR="/opt/nextnvr" SERVICE_NAME="nextnvr" GO_VERSION="1.24.5" GO_OS="linux" GO_ARCH="amd64" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color log() { echo -e "${GREEN}[NextNVR]${NC} $1"; } warn() { echo -e "${YELLOW}[NextNVR]${NC} $1"; } err() { echo -e "${RED}[NextNVR]${NC} $1"; } info() { echo -e "${CYAN}[NextNVR]${NC} $1"; } echo "" echo "============================================" echo " NextNVR — IP Camera Recorder" echo " One-Line Deployment" echo "============================================" echo "" # ── Check for sudo ── if ! command -v sudo &>/dev/null; then err "sudo is required but not installed. Please install sudo first." exit 1 fi # ── 1. Install system dependencies ── log "Step 1/6: Installing system dependencies..." if ! command -v ffmpeg &>/dev/null; then info "Installing ffmpeg..." sudo apt-get update -qq sudo apt-get install -y -qq ffmpeg log "ffmpeg installed." else log "ffmpeg already installed: $(ffmpeg -version 2>&1 | head -1)" fi if ! command -v git &>/dev/null; then info "Installing git..." sudo apt-get install -y -qq git log "git installed." fi if ! command -v curl &>/dev/null; then sudo apt-get install -y -qq curl fi # ── 1b. Verify time synchronization (critical for NVR timestamps) ── log "Checking time sync..." if systemctl is-active --quiet systemd-timesyncd 2>/dev/null; then log "systemd-timesyncd is active." elif ! timedatectl status 2>/dev/null | grep -q "System clock synchronized: yes"; then warn "Time sync is NOT active. Enabling systemd-timesyncd..." sudo systemctl enable --now systemd-timesyncd 2>/dev/null || true sudo timedatectl set-ntp true 2>/dev/null || true log "Time sync enabled." else log "Time sync is active." fi # Verify timezone is sensible. TZ=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "unknown") log "Timezone: ${TZ}" log "Local time: $(date)" # ── 2. Install Go (user-local, no sudo needed after download) ── log "Step 2/6: Setting up Go ${GO_VERSION}..." GO_TAR="go${GO_VERSION}.${GO_OS}-${GO_ARCH}.tar.gz" GO_URL="https://go.dev/dl/${GO_TAR}" GO_HOME="$HOME/.local/go" if [ -f "${GO_HOME}/bin/go" ]; then CURRENT_GO=$(${GO_HOME}/bin/go version 2>/dev/null | grep -oP 'go\K[0-9.]+' || echo "0") if [ "$CURRENT_GO" = "$GO_VERSION" ]; then log "Go ${GO_VERSION} already installed." else warn "Go ${CURRENT_GO} found, upgrading to ${GO_VERSION}..." rm -rf "${GO_HOME}" curl -sSL "${GO_URL}" -o /tmp/${GO_TAR} mkdir -p "${GO_HOME}" tar -C "$HOME/.local" -xzf /tmp/${GO_TAR} rm /tmp/${GO_TAR} log "Go ${GO_VERSION} installed." fi else info "Downloading Go ${GO_VERSION}..." curl -sSL "${GO_URL}" -o /tmp/${GO_TAR} mkdir -p "${GO_HOME}" tar -C "$HOME/.local" -xzf /tmp/${GO_TAR} rm /tmp/${GO_TAR} log "Go ${GO_VERSION} installed." fi export PATH="${GO_HOME}/bin:$PATH" export GOPATH="$HOME/go" # ── 3. Clone or update repository ── log "Step 3/6: Fetching NextNVR source..." if [ -d "${DEPLOY_DIR}/.git" ]; then info "Repository exists, pulling latest..." cd "${DEPLOY_DIR}" git pull origin main log "Source updated." else info "Cloning repository..." sudo mkdir -p "${DEPLOY_DIR}" sudo chown "$(whoami):$(whoami)" "${DEPLOY_DIR}" git clone "${GIT_URL}" "${DEPLOY_DIR}" cd "${DEPLOY_DIR}" log "Source cloned." fi # ── 4. Build ── log "Step 4/6: Building NextNVR binary..." cd "${DEPLOY_DIR}" go mod tidy VERSION=$(cat VERSION 2>/dev/null || echo "unknown") BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) CGO_ENABLED=0 go build \ -ldflags="-s -w -X main.Version=${VERSION} -X main.BuildTime=${BUILD_TIME}" \ -o nextnvr . chmod +x nextnvr log "Binary built: nextnvr v${VERSION} ($(du -h nextnvr | cut -f1))" # ── 5. Create default config if missing ── log "Step 5/6: Checking configuration..." if [ ! -f "${DEPLOY_DIR}/config.yaml" ]; then cp config.yaml "${DEPLOY_DIR}/config.yaml" log "Default config.yaml created. Edit it to add your cameras:" info " sudo nano ${DEPLOY_DIR}/config.yaml" else log "config.yaml already exists — preserved." fi # Ensure recordings directory exists. sudo mkdir -p /mnt/recordings sudo chown "$(whoami):$(whoami)" /mnt/recordings 2>/dev/null || true # ── 6. Install systemd service ── log "Step 6/6: Installing systemd service..." SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" sudo tee "${SERVICE_FILE}" > /dev/null </dev/null || true echo ""