This document describes the configuration options for LightNVR.
LightNVR supports two configuration file formats:
- INI format (recommended): A structured configuration format with sections and key-value pairs.
- Legacy key-value format: A simple key-value configuration format.
By default, LightNVR looks for a configuration file in the following locations (in order):
./lightnvr.ini(INI format in current directory)/etc/lightnvr/lightnvr.ini(INI format in system directory)./lightnvr.conf(legacy format in current directory)/etc/lightnvr/lightnvr.conf(legacy format in system directory)
You can specify a different configuration file using the -c option:
./lightnvr -c /path/to/config.confWhen saving configuration changes through the web interface, LightNVR will prefer to use the INI format.
The INI format is a structured configuration format that organizes settings into sections. Here's an example of the same configuration in INI format:
; LightNVR Configuration File (INI format)
[general]
pid_file = /var/run/lightnvr.pid
log_file = /var/log/lightnvr.log
log_level = 2 ; 0=ERROR, 1=WARN, 2=INFO, 3=DEBUG
syslog_enabled = false ; Enable logging to syslog
syslog_ident = lightnvr ; Syslog identifier
syslog_facility = LOG_USER ; Syslog facility
[storage]
path = /var/lib/lightnvr/data/recordings
max_size = 0 ; 0 means unlimited, otherwise bytes
retention_days = 30
auto_delete_oldest = true
; New recording format options
record_mp4_directly = false
mp4_path = /var/lib/lightnvr/data/recordings/mp4
mp4_directory_format = year_month_day
mp4_segment_duration = 900
mp4_retention_days = 30
[database]
path = /var/lib/lightnvr/data/database/lightnvr.db
[web]
port = 8080
bind_ip = 0.0.0.0
root = /var/lib/lightnvr/www
auth_enabled = true
username = admin
; Only read when the admin account is first created. Set it before the first start to
; avoid the default admin/admin ever being valid; afterwards manage users in the web UI.
; password =
auth_timeout_hours = 24 ; Session timeout in hours (default: 24)
audio_disabled = false ; Instance-wide audio compliance policy
; trusted_proxy_cidrs = 127.0.0.1/32,::1/128 ; Only trust X-Forwarded-For from these reverse proxies
web_thread_pool_size = 8
[streams]
max_streams = 32
; Note: Stream configurations are stored in the database
; and managed via the API/web UI
[models]
path = /var/lib/lightnvr/data/models
[api_detection]
url = http://localhost:9001/api/v1/detect
backend = onnx ; Detection backend: onnx (YOLOv8), tflite, or opencv
confidence_threshold = 0.35
filter_classes = car,motorcycle,truck,bus,bicycle ; Comma-separated class filter
[memory]
buffer_size = 1024 ; Buffer size in KB
use_swap = true
swap_file = /var/lib/lightnvr/data/swap
swap_size = 134217728 ; 128MB in bytes
[hardware]
hw_accel_enabled = false
hw_accel_device =
[go2rtc]
webrtc_enabled = true
webrtc_listen_port = 8555
stun_enabled = true
stun_server = stun.l.google.com:19302
; external_ip =
; ice_servers =
; proxy_max_inflight = 16
[mqtt]
enabled = false
broker_host = localhost
broker_port = 1883
; username =
; password =
client_id = lightnvr
topic_prefix = lightnvr
tls_enabled = false
keepalive = 60
qos = 1
retain = false
[onvif]
discovery_enabled = false
discovery_interval = 300
discovery_network = autoThe [storage] path remains the compatibility/default recording root. After the
database initializes, lightNVR registers the effective MP4 recording root as a
stable default target and attaches existing recording metadata by relative key;
it does not move footage.
Additional local or administrator-mounted NFS/SMB roots are managed under
Settings → Storage → Recording storage targets or through
/api/storage-targets. Each target has its own stable UUID, enabled state,
performance class, reserved headroom, watermarks, cached capacity, and health.
Enabled roots must already be mounted and writable. lightNVR does not mount
remote shares or store share credentials.
Storage pools and selector-driven lifecycle policies are managed on the same page. A pool can allocate by most-free, round-robin, or explicit priority. Policies may place new segments into a pool, require distinct verified copies, move footage to an archive target after an age threshold, and set minimum/desired/maximum retention. Lifecycle copies and moves are durable, restart-safe, bandwidth-limited, and constrained to each destination target's local-time archival window. The compliance panel uses the prior 30 days of observed bytes to forecast target pressure and expected policy retention.
The INI format offers several advantages:
- Simple and widely used format
- Easy to read and edit
- Organized into sections
- Support for comments
- Lightweight parsing
The configuration file is divided into several sections:
[general]
pid_file = /var/run/lightnvr.pid
log_file = /var/log/lightnvr.log
log_level = 2 ; 0=ERROR, 1=WARN, 2=INFO, 3=DEBUG
syslog_enabled = false ; Enable logging to syslog
syslog_ident = lightnvr ; Syslog identifier (application name)
syslog_facility = LOG_USER ; Syslog facilitypid_file: Path to the PID filelog_file: Path to the log filelog_level: Logging level (0=ERROR, 1=WARN, 2=INFO, 3=DEBUG)syslog_enabled: Enable logging to syslog for easier system integration and centralized log management (default: false)syslog_ident: Syslog identifier/application name used in syslog messages (default: "lightnvr")syslog_facility: Syslog facility for categorizing messages. Valid values:LOG_USER(default): User-level messagesLOG_DAEMON: System daemon messagesLOG_LOCAL0throughLOG_LOCAL7: Local use facilities for custom applications
When syslog_enabled is set to true, LightNVR will send log messages to the system's syslog daemon in addition to the regular log file and console output. This provides several benefits:
- Centralized Logging: Integrate with system-wide log management tools
- Remote Logging: Forward logs to remote syslog servers for centralized monitoring
- Log Rotation: Leverage system log rotation policies
- Integration with Monitoring Tools: Use tools like
journalctl,rsyslog, orsyslog-ng
Example syslog configuration for production use:
syslog_enabled = true
syslog_ident = lightnvr
syslog_facility = LOG_LOCAL0To view LightNVR logs via syslog on systemd-based systems:
# View all LightNVR logs
journalctl -t lightnvr
# Follow logs in real-time
journalctl -t lightnvr -f
# View logs from the last hour
journalctl -t lightnvr --since "1 hour ago"On traditional syslog systems, logs will appear in /var/log/syslog or /var/log/messages depending on your syslog configuration.
[storage]
path = /var/lib/lightnvr/data/recordings
max_size = 0 ; 0 means unlimited, otherwise bytes
retention_days = 30
auto_delete_oldest = true
record_mp4_directly = false
mp4_path = /var/lib/lightnvr/data/recordings/mp4
mp4_directory_format = year_month_day
mp4_segment_duration = 900
mp4_retention_days = 30path: Directory where recordings are storedmax_size: Maximum storage size in bytes (0 means unlimited)retention_days: Number of days to keep recordingsauto_delete_oldest: Whether to automatically delete the oldest recordings when storage is fullrecord_mp4_directly: Enable direct MP4 recording (instead of HLS-to-MP4 conversion)mp4_path: Directory for direct MP4 recordingsmp4_directory_format: Recording folder layout:flat,year_month(YYYY/MM), oryear_month_day(YYYY/MM/DD, default)mp4_segment_duration: Duration of each MP4 segment in secondsmp4_retention_days: Number of days to keep MP4 recordings
[database]
path = /var/lib/lightnvr/data/database/lightnvr.db
startup_check = off
backup_retention_count = 6path: Path to the SQLite database filestartup_check: Optional consistency check run against an existing database at boot (default:off).quickrunsPRAGMA quick_check, which validates page structure.fullrunsPRAGMA integrity_check, which additionally cross-checks every index against its table — its cost scales with total index size, so on a large database it can take minutes, and it runs before the HTTP listener is bound, so that time appears to clients as a gateway error.offskips the check. Corruption seen in practice (truncated writes, torn pages) is caught byquick. Both checks scan the database before the HTTP listener binds, so run them during a maintenance window rather than on every boot.backup_retention_count: Number of timestamped backups to retain (default: 6). Each backup is a full copy of the database, so this multiplies disk usage by the database size.
[web]
port = 8080
bind_ip = 0.0.0.0
root = /var/lib/lightnvr/www
auth_enabled = true
username = admin
; password = ; only read when the admin account is first created
auth_timeout_hours = 24
audio_disabled = false
; trusted_proxy_cidrs = 127.0.0.1/32,::1/128
web_thread_pool_size = 8port: Port for the web interfacebind_ip: IP address for the web interfaceroot: Directory containing web interface filesauth_enabled: Whether to enable authentication for the web interfaceusername: Username for web interface authenticationpassword: Password used only when the admin account is first created. If unset, the account is created asadmin/admin— see the warning below. Once the account exists this setting is ignored; passwords live in the database and are changed from Settings → Users.auth_timeout_hours: Session timeout in hours (default: 24)audio_disabled: Instance-wide compliance policy (default: false). When true, LightNVR prevents audio in new recordings, live listening, and two-way talk; the Live View audio controls are removed. Per-stream audio settings and custom go2rtc source/config overrides cannot bypass the policy. Existing recording files are not rewritten or deleted. Container deployments may set the equivalentLIGHTNVR_AUDIO_DISABLED=trueenvironment variable.trusted_proxy_cidrs: Comma- or newline-separated list of IPv4/IPv6 CIDRs allowed to setX-Forwarded-For/X-Real-IPheaders. Required when running behind a reverse proxy (nginx, Caddy, Traefik, Kubernetes ingress) — without it, the audit log, login allow-list, and rate limiter all see every request as coming from the proxy itself. See Reverse Proxy & HTTPS.web_thread_pool_size: Number of worker threads for the web server (default: 8)
⚠️ Default credentials areadmin/admin. Combined with the defaultbind_ip = 0.0.0.0, anyone who can reach port 8080 can reach your cameras and recordings if an attacker completes first login before you do. Either setpasswordbefore the very first start, or log in withadmin/adminand complete the mandatory password-change screen. Until the change succeeds, that password-authenticated session can only verify its state and change its own password; MFA is evaluated after the new password is set and the user signs in again.The requirement is added only when a new administrator is created with the fallback password. Existing users are not flagged on upgrade, and API-key authentication and demo mode are unaffected.
There is no password-reset flag. If you lose the admin password, stop LightNVR, delete the account row, and restart — it is recreated by the same first-run rules:
sqlite3 /var/lib/lightnvr/data/database/lightnvr.db "DELETE FROM users WHERE username = 'admin';"
[streams]
max_streams = 32max_streams: Runtime stream capacity for one LightNVR instance (default: 32, maximum: 1024). Changing it requires a restart. Higher values reserve more memory; the number of cameras a host can actively record, relay, or analyze still depends on its CPU, memory, storage, network, and enabled workloads.
Note: Stream configurations are stored in the SQLite database and managed via the API or web UI. They are no longer configured in the INI file.
[models]
path = /var/lib/lightnvr/data/modelspath: Directory where detection models are stored
[api_detection]
url = http://localhost:9001/api/v1/detect
backend = onnx
confidence_threshold = 0.35
filter_classes = car,motorcycle,truck,bus,bicycleurl: URL of the external detection APIbackend: Detection backend to use:onnx(YOLOv8 - best accuracy),tflite, oropencvconfidence_threshold: Minimum confidence threshold for detections (0.0-1.0)filter_classes: Comma-separated list of object classes to detect (empty = all classes)
[memory]
buffer_size = 1024 ; Buffer size in KB
use_swap = true
swap_file = /var/lib/lightnvr/data/swap
swap_size = 134217728 ; 128MB in bytesbuffer_size: Buffer size for video processing in KBuse_swap: Whether to use a swap file for additional memoryswap_file: Path to the swap fileswap_size: Size of the swap file in bytes
[hardware]
hw_accel_enabled = false
hw_accel_device =hw_accel_enabled: Whether to enable hardware accelerationhw_accel_device: Device to use for hardware acceleration
[go2rtc]
webrtc_enabled = true
webrtc_listen_port = 8555
stun_enabled = true
stun_server = stun.l.google.com:19302
; external_ip =
; ice_servers =
; proxy_max_inflight = 16webrtc_enabled: Enable WebRTC streaming (default: true)webrtc_listen_port: Port for WebRTC connections (default: 8555)stun_enabled: Enable STUN for NAT traversal (default: true)stun_server: Primary STUN server addressexternal_ip: External IP for complex NAT scenarios (leave empty for auto-detection)ice_servers: Custom ICE servers, comma-separated (format:stun:host:portorturn:host:port)proxy_max_inflight: Maximum concurrent HLS/snapshot proxy requests (default: 16, range: 1-128)
[mqtt]
enabled = false
broker_host = localhost
broker_port = 1883
; username =
; password =
client_id = lightnvr
topic_prefix = lightnvr
tls_enabled = false
keepalive = 60
qos = 1
retain = falseenabled: Enable MQTT publishing of detection events (default: false)broker_host: MQTT broker hostname or IP addressbroker_port: MQTT broker port (default: 1883, use 8883 for TLS)username: MQTT authentication username (optional)password: MQTT authentication password (optional)client_id: MQTT client ID (default: lightnvr)topic_prefix: Topic prefix for detection events. Events are published to{topic_prefix}/detections/{stream_name}tls_enabled: Enable TLS for MQTT connection (default: false)keepalive: MQTT keepalive interval in seconds (default: 60)qos: MQTT QoS level: 0 (at most once), 1 (at least once), 2 (exactly once)retain: Retain detection messages on the broker (default: false)
See MQTT_INTEGRATION.md for detailed MQTT documentation.
[onvif]
discovery_enabled = false
discovery_interval = 300
discovery_network = autodiscovery_enabled: Enable automatic ONVIF camera discovery (default: false)discovery_interval: Interval in seconds between discovery scans (30-3600, default: 300)discovery_network: Network to scan in CIDR notation, orautofor automatic detection. For Docker containers, setLIGHTNVR_ONVIF_NETWORKenvironment variable instead.
See config/lightnvr.ini in the repository for a complete, annotated example configuration file. The example includes all available sections and settings with descriptive comments.
LightNVR supports the following command line options:
-c, --config FILE: Use the specified configuration file-d, --daemon: Run as a daemon-h, --help: Show help message-v, --version: Show version information
The Ingenic A1 SoC has limited memory (256MB), so it's important to optimize memory usage:
-
Set appropriate buffer sizes:
[memory] buffer_size = 512 ; 512KB buffer size
-
Enable swap file for additional memory:
[memory] use_swap = true swap_file = /var/lib/lightnvr/data/swap swap_size = 134217728 ; 128MB in bytes
-
Limit the number of streams via
[streams]section and configure lower resolution/fps via the web UI. -
Use stream priorities (1-10, higher = more important) to ensure critical streams get resources when memory is constrained.
If you encounter issues with your configuration:
-
Check the log file for error messages:
tail -f /var/log/lightnvr/lightnvr.log -
Verify that all paths in the configuration file exist and have the correct permissions
-
Test stream URLs separately using a tool like VLC or ffmpeg:
ffplay rtsp://192.168.1.100:554/stream1 -
Monitor memory usage to ensure you're not exceeding the available memory:
top -p $(pgrep lightnvr)