chore: v0.2.2 — user-friendly README, one-line deploy, auto-install deps
This commit is contained in:
parent
c19944bc27
commit
0f78666bf3
4 changed files with 257 additions and 41 deletions
|
|
@ -2,6 +2,13 @@
|
|||
|
||||
All notable changes to NextNVR will be documented in this file.
|
||||
|
||||
## [0.2.2] — 2026-08-05
|
||||
### Added
|
||||
- User-friendly README.md with one-line install command
|
||||
- Auto-install dependencies in setup.sh (ffmpeg, git, Go 1.24.5)
|
||||
- Colored terminal output during deployment
|
||||
- Preserves existing config.yaml on re-deployment
|
||||
|
||||
## [0.2.1] — 2026-08-05
|
||||
### Changed
|
||||
- **Flat recording directory**: `/mnt/recordings/{cam-name}/{YYYY-MM-DD-HH-MM}.mp4`
|
||||
|
|
|
|||
110
README.md
110
README.md
|
|
@ -1 +1,111 @@
|
|||
# NextNVR
|
||||
|
||||
A lightweight, self-hosted video recorder for IP cameras. Records 8 RTSP streams into 5-minute MP4 clips with near-zero CPU usage. Built for the **Casa Alba Mindelo** guesthouse.
|
||||
|
||||
---
|
||||
|
||||
## Quick Install
|
||||
|
||||
Copy and paste this single line into your terminal:
|
||||
|
||||
```bash
|
||||
curl -sSL https://git.lohmar.co.uk/cclohmar/NextNVR/raw/branch/main/setup.sh | bash
|
||||
```
|
||||
|
||||
That's it. The script installs everything needed and starts NextNVR automatically.
|
||||
|
||||
Once done, open **[http://192.168.1.10:8080](http://192.168.1.10:8080)** in your browser.
|
||||
|
||||
---
|
||||
|
||||
## What It Does
|
||||
|
||||
| Feature | Detail |
|
||||
|---|---|
|
||||
| 📹 **Recording** | 8 cameras simultaneously, 5-minute MP4 clips |
|
||||
| 💾 **Storage** | Saves to `/mnt/recordings/` — keeps 18 days, auto-deletes older |
|
||||
| 🖥️ **Live Wall** | 4×2 grid showing all cameras at once. Click one to enlarge. |
|
||||
| 🔍 **Playback** | Browse recordings by camera and date with presets (Today, Yesterday, Last 7 Days) |
|
||||
| ⚙️ **Setup Wizard** | Scans your network for cameras and helps you name them |
|
||||
| 🔒 **Local Only** | Everything runs on your own hardware. No cloud, no subscriptions. |
|
||||
|
||||
---
|
||||
|
||||
## Server
|
||||
|
||||
| What | Detail |
|
||||
|---|---|
|
||||
| Address | `http://192.168.1.10:8080` |
|
||||
| Config file | `/opt/nextnvr/config.yaml` |
|
||||
| Recordings | `/mnt/recordings/` |
|
||||
| Logs | `sudo journalctl -u nextnvr -f` |
|
||||
|
||||
### Useful Commands
|
||||
|
||||
```bash
|
||||
sudo systemctl status nextnvr # is it running?
|
||||
sudo systemctl restart nextnvr # restart after changing config
|
||||
sudo systemctl stop nextnvr # stop recording
|
||||
sudo journalctl -u nextnvr -f # watch live logs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## How It Works
|
||||
|
||||
```
|
||||
IP Cameras NextNVR Your Browser
|
||||
─────────── ────────── ─────────────
|
||||
192.168.1.201 ─┐
|
||||
192.168.1.202 ─┤ RTSP FFmpeg -c copy .mp4 http://192.168.1.10:8080
|
||||
192.168.1.203 ─┼──────────► (no re-encoding) ────────► Live Wall + Playback
|
||||
... ┤ 5 min segments Settings + Setup
|
||||
192.168.1.209 ─┘ auto-delete >18d
|
||||
```
|
||||
|
||||
- **Zero transcoding** — FFmpeg copies the video stream directly. CPU stays under 5%.
|
||||
- **Crash-proof** — if a camera disconnects, it auto-reconnects after 5 seconds.
|
||||
- **Atomic files** — recording in progress uses `.part.mp4`. Only renamed to `.mp4` when complete. No corrupted files.
|
||||
|
||||
---
|
||||
|
||||
## Adding or Changing Cameras
|
||||
|
||||
1. Open **http://192.168.1.10:8080**
|
||||
2. Click the **Settings** tab
|
||||
3. Click **🔍 Scan Network** to find your cameras
|
||||
4. Give each camera a name and description
|
||||
5. Click **💾 Save Configuration**
|
||||
6. Restart: `sudo systemctl restart nextnvr`
|
||||
|
||||
Or edit the config file directly:
|
||||
|
||||
```bash
|
||||
sudo nano /opt/nextnvr/config.yaml
|
||||
sudo systemctl restart nextnvr
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Updating
|
||||
|
||||
```bash
|
||||
curl -sSL https://git.lohmar.co.uk/cclohmar/NextNVR/raw/branch/main/setup.sh | bash
|
||||
```
|
||||
|
||||
The script pulls the latest version and restarts the service automatically.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Check |
|
||||
|---|---|
|
||||
| Can't open the web page | Is NextNVR running? `sudo systemctl status nextnvr` |
|
||||
| No cameras showing | Check `config.yaml` — are camera IPs and passwords correct? |
|
||||
| Recordings not saving | Does `/mnt/recordings/` exist? Is the disk mounted? (`df -h`) |
|
||||
| Disk full | Recordings older than 18 days are auto-deleted. Check `df -h /mnt/recordings` |
|
||||
|
||||
---
|
||||
|
||||
Built with ❤️ in Mindelo, Portugal. 🇵🇹
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
0.2.1
|
||||
0.2.2
|
||||
|
|
|
|||
179
setup.sh
179
setup.sh
|
|
@ -1,89 +1,188 @@
|
|||
#!/bin/bash
|
||||
# NextNVR v0.1.0 — Deployment Script
|
||||
# Clones the repository and deploys to /opt/nextnvr
|
||||
# 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_BIN="/home/master/.local/go/bin/go"
|
||||
FFMPEG_BIN="ffmpeg"
|
||||
GO_VERSION="1.24.5"
|
||||
GO_OS="linux"
|
||||
GO_ARCH="amd64"
|
||||
|
||||
echo "=== NextNVR Deployment ==="
|
||||
echo "Target: ${DEPLOY_DIR}"
|
||||
echo "Git: ${GIT_URL}"
|
||||
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..."
|
||||
|
||||
# 1. Install system dependencies if missing.
|
||||
if ! command -v ffmpeg &>/dev/null; then
|
||||
echo "Installing ffmpeg..."
|
||||
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
|
||||
|
||||
# 2. Clone or pull repository.
|
||||
if [ -d "${DEPLOY_DIR}" ]; then
|
||||
echo "Repository exists, pulling latest..."
|
||||
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
|
||||
|
||||
# ── 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
|
||||
echo "Cloning repository..."
|
||||
info "Cloning repository..."
|
||||
sudo mkdir -p "${DEPLOY_DIR}"
|
||||
sudo chown master:master "${DEPLOY_DIR}"
|
||||
sudo chown "$(whoami):$(whoami)" "${DEPLOY_DIR}"
|
||||
git clone "${GIT_URL}" "${DEPLOY_DIR}"
|
||||
cd "${DEPLOY_DIR}"
|
||||
log "Source cloned."
|
||||
fi
|
||||
|
||||
# 3. Build the Go binary with embedded static files.
|
||||
echo "Building NextNVR binary..."
|
||||
export PATH=$HOME/.local/go/bin:$PATH
|
||||
export GOPATH=$HOME/go
|
||||
# ── 4. Build ──
|
||||
log "Step 4/6: Building NextNVR binary..."
|
||||
|
||||
cd "${DEPLOY_DIR}"
|
||||
go mod tidy
|
||||
CGO_ENABLED=0 go build -ldflags="-s -w -X main.Version=$(cat VERSION) -X main.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" -o nextnvr .
|
||||
|
||||
# 4. Copy config if not present.
|
||||
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"
|
||||
echo "Default config.yaml created."
|
||||
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
|
||||
|
||||
# 5. Set permissions.
|
||||
sudo chown -R master:master "${DEPLOY_DIR}"
|
||||
chmod +x "${DEPLOY_DIR}/nextnvr"
|
||||
# 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..."
|
||||
|
||||
# 6. Install systemd service.
|
||||
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
|
||||
if [ ! -f "${SERVICE_FILE}" ]; then
|
||||
echo "Creating systemd service..."
|
||||
sudo tee "${SERVICE_FILE}" > /dev/null <<EOF
|
||||
sudo tee "${SERVICE_FILE}" > /dev/null <<EOF
|
||||
[Unit]
|
||||
Description=NextNVR — IP Camera Recorder
|
||||
After=network.target
|
||||
Wants=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=master
|
||||
User=$(whoami)
|
||||
WorkingDirectory=${DEPLOY_DIR}
|
||||
ExecStart=${DEPLOY_DIR}/nextnvr --config ${DEPLOY_DIR}/config.yaml
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
LimitNOFILE=65536
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable "${SERVICE_NAME}"
|
||||
fi
|
||||
|
||||
# 7. Restart service.
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable "${SERVICE_NAME}"
|
||||
sudo systemctl restart "${SERVICE_NAME}"
|
||||
sleep 2
|
||||
sudo systemctl status "${SERVICE_NAME}" --no-pager
|
||||
|
||||
sleep 2
|
||||
|
||||
# ── Done ──
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo -e " ${GREEN}NextNVR deployment complete!${NC}"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
info " Web UI: http://192.168.1.10:8080"
|
||||
info " Config: ${DEPLOY_DIR}/config.yaml"
|
||||
info " Storage: /mnt/recordings/"
|
||||
echo ""
|
||||
echo " Service commands:"
|
||||
echo " sudo systemctl status ${SERVICE_NAME}"
|
||||
echo " sudo systemctl restart ${SERVICE_NAME}"
|
||||
echo " sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
echo ""
|
||||
|
||||
# Show service status.
|
||||
sudo systemctl status "${SERVICE_NAME}" --no-pager --lines=5 2>/dev/null || true
|
||||
echo ""
|
||||
echo "=== Deployment Complete ==="
|
||||
echo "NextNVR running on http://127.0.0.1:8080"
|
||||
echo "Service: sudo systemctl [start|stop|restart|status] ${SERVICE_NAME}"
|
||||
echo "Logs: sudo journalctl -u ${SERVICE_NAME} -f"
|
||||
echo "Config: ${DEPLOY_DIR}/config.yaml"
|
||||
|
|
|
|||
Loading…
Reference in a new issue