Shinobi is a free and open-source CCTV/NVR (Network Video Recorder) solution written in Node.js. It serves as a modern FOSS alternative to proprietary video surveillance systems like Blue Iris, Milestone XProtect, Genetec Security Center, or commercial NVR solutions from Hikvision, Dahua, and others. Shinobi supports RTSP, ONVIF, and various IP camera protocols with features including motion detection, object detection, and multi-user support.
1. Prerequisites
Hardware Requirements
Software Requirements
Network Requirements
2. Supported Operating Systems
Shinobi officially supports:
3. Installation
RHEL/CentOS/Rocky Linux/AlmaLinux
# Enable EPEL and PowerTools/CRB repositories
sudo dnf install -y epel-release
sudo dnf config-manager --set-enabled powertools # CentOS Stream 8
sudo dnf config-manager --set-enabled crb # RHEL/Rocky/Alma 9
# Install dependencies
sudo dnf install -y ffmpeg ffmpeg-devel x264 x265 x264-devel x265-devel \
git curl gnupg2 gcc-c++ make cairo-devel jpeg-devel \
giflib-devel pango-devel python3 python3-pip
# Install Node.js 18.x
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
sudo dnf install -y nodejs
# Install MariaDB
sudo dnf install -y mariadb mariadb-server
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
# Create Shinobi database and user
sudo mysql -e "CREATE DATABASE ccio;"
sudo mysql -e "CREATE USER 'ccio'@'localhost' IDENTIFIED BY 'your_secure_password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON ccio.* TO 'ccio'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Clone and install Shinobi
cd /opt
sudo git clone https://gitlab.com/Shinobi-Systems/Shinobi.git shinobi
sudo chown -R $USER:$USER /opt/shinobi
cd /opt/shinobi
# Install Node.js dependencies
npm install --unsafe-perm
npm install pm2 -g
# Configure Shinobi
cp conf.sample.json conf.json
cp super.sample.json super.json
# Initialize database
node /opt/shinobi/sql/framework.js
# Create systemd service (see Service Management section)
Debian/Ubuntu
# Update package lists
sudo apt update
# Install FFmpeg and multimedia libraries
sudo apt install -y ffmpeg x264 x265 git curl gnupg2 \
build-essential python3 python3-pip libcairo2-dev \
libjpeg-dev libgif-dev libpango1.0-dev
# Install Node.js 18.x
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# Install MariaDB
sudo apt install -y mariadb-server mariadb-client
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
# Create Shinobi database and user
sudo mysql -e "CREATE DATABASE ccio;"
sudo mysql -e "CREATE USER 'ccio'@'localhost' IDENTIFIED BY 'your_secure_password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON ccio.* TO 'ccio'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Clone and install Shinobi
cd /opt
sudo git clone https://gitlab.com/Shinobi-Systems/Shinobi.git shinobi
sudo chown -R $USER:$USER /opt/shinobi
cd /opt/shinobi
# Install dependencies
npm install --unsafe-perm
sudo npm install pm2 -g
# Configure Shinobi
cp conf.sample.json conf.json
cp super.sample.json super.json
# Initialize database
node /opt/shinobi/sql/framework.js
Arch Linux
# Update system
sudo pacman -Syu
# Install dependencies
sudo pacman -S ffmpeg x264 x265 git curl gnupg nodejs npm \
python python-pip base-devel cairo libjpeg-turbo \
libpng pango giflib mariadb
# Enable and start MariaDB
sudo systemctl enable --now mariadb
sudo mysql_secure_installation
# Create Shinobi database and user
sudo mysql -e "CREATE DATABASE ccio;"
sudo mysql -e "CREATE USER 'ccio'@'localhost' IDENTIFIED BY 'your_secure_password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON ccio.* TO 'ccio'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Clone and install Shinobi
cd /opt
sudo git clone https://gitlab.com/Shinobi-Systems/Shinobi.git shinobi
sudo chown -R $USER:$USER /opt/shinobi
cd /opt/shinobi
# Install dependencies
npm install --unsafe-perm
sudo npm install pm2 -g
# Configure Shinobi
cp conf.sample.json conf.json
cp super.sample.json super.json
# Initialize database
node /opt/shinobi/sql/framework.js
Alpine Linux
# Update package index
sudo apk update
# Install dependencies
sudo apk add --no-cache ffmpeg x264 x265 git curl gnupg \
nodejs npm python3 py3-pip build-base cairo-dev \
jpeg-dev libpng-dev pango-dev giflib-dev mariadb \
mariadb-client mariadb-dev
# Initialize MariaDB
sudo mysql_install_db --user=mysql --datadir=/var/lib/mysql
sudo rc-service mariadb start
sudo rc-update add mariadb default
sudo mysql_secure_installation
# Create Shinobi database and user
sudo mysql -e "CREATE DATABASE ccio;"
sudo mysql -e "CREATE USER 'ccio'@'localhost' IDENTIFIED BY 'your_secure_password';"
sudo mysql -e "GRANT ALL PRIVILEGES ON ccio.* TO 'ccio'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Clone and install Shinobi
cd /opt
sudo git clone https://gitlab.com/Shinobi-Systems/Shinobi.git shinobi
sudo chown -R $USER:$USER /opt/shinobi
cd /opt/shinobi
# Install dependencies
npm install --unsafe-perm
sudo npm install pm2 -g
# Configure Shinobi
cp conf.sample.json conf.json
cp super.sample.json super.json
# Initialize database
node /opt/shinobi/sql/framework.js
4. Configuration
Database Configuration
Edit /opt/shinobi/conf.json
:
{
"port": 8080,
"addStorage": [
{
"name": "second",
"path": "/opt/shinobi/videos2"
}
],
"ssl": {
"key": "/path/to/private.key",
"cert": "/path/to/certificate.crt",
"enabled": false,
"port": 8443
},
"db": {
"host": "127.0.0.1",
"user": "ccio",
"password": "your_secure_password",
"database": "ccio",
"port": 3306
},
"mail": {
"auth": {
"user": "your_email@example.com",
"pass": "your_app_password"
},
"host": "smtp.gmail.com",
"port": 587,
"secure": false
},
"cron": {
"deleteOld": "0 * * * *"
}
}
Super User Configuration
Edit /opt/shinobi/super.json
:
{
"port": 8080,
"bindip": "0.0.0.0",
"ssl": {
"key": "",
"cert": "",
"enabled": false,
"port": 8443
},
"db": {
"host": "127.0.0.1",
"user": "ccio",
"password": "your_secure_password",
"database": "ccio",
"port": 3306
},
"mail": {
"auth": {
"user": "your_email@example.com",
"pass": "your_app_password"
},
"host": "smtp.gmail.com",
"port": 587,
"secure": false
}
}
Creating Storage Directories
# Create video storage directories
sudo mkdir -p /opt/shinobi/videos
sudo mkdir -p /var/shinobi/recordings
sudo chown -R shinobi:shinobi /opt/shinobi/videos
sudo chown -R shinobi:shinobi /var/shinobi/recordings
# Set proper permissions
sudo chmod 755 /opt/shinobi/videos
sudo chmod 755 /var/shinobi/recordings
5. Service Management
Create Shinobi User
# Create dedicated user
sudo useradd -r -s /bin/false -d /opt/shinobi shinobi
sudo chown -R shinobi:shinobi /opt/shinobi
systemd Service (RHEL, Debian, Arch, SUSE)
Create /etc/systemd/system/shinobi.service
:
[Unit]
Description=Shinobi CCTV System
After=network.target mariadb.service
Wants=mariadb.service
[Service]
Type=forking
User=shinobi
Group=shinobi
WorkingDirectory=/opt/shinobi
ExecStart=/usr/bin/pm2 start ecosystem.config.js --env production
ExecReload=/usr/bin/pm2 reload ecosystem.config.js --env production
ExecStop=/usr/bin/pm2 stop ecosystem.config.js
PIDFile=/opt/shinobi/.pm2/pm2.pid
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Create /opt/shinobi/ecosystem.config.js
:
module.exports = {
apps: [
{
name: 'camera',
script: 'camera.js',
cwd: '/opt/shinobi',
instances: 1,
exec_mode: 'fork',
env: {
NODE_ENV: 'production'
}
},
{
name: 'cron',
script: 'cron.js',
cwd: '/opt/shinobi',
instances: 1,
exec_mode: 'fork',
env: {
NODE_ENV: 'production'
}
}
]
};
# Enable and start services
sudo systemctl daemon-reload
sudo systemctl enable --now shinobi
sudo systemctl status shinobi
OpenRC Service (Alpine Linux)
Create /etc/init.d/shinobi
:
#!/sbin/openrc-run
description="Shinobi CCTV System"
command="/usr/bin/pm2"
command_args="start /opt/shinobi/ecosystem.config.js --env production"
command_user="shinobi"
pidfile="/run/shinobi.pid"
depend() {
need net mariadb
after mariadb
}
start_pre() {
checkpath --directory --owner shinobi:shinobi --mode 0755 /run/shinobi
}
# Make executable and enable
sudo chmod +x /etc/init.d/shinobi
sudo rc-update add shinobi default
sudo rc-service shinobi start
6. Troubleshooting
Common Issues
1. Shinobi won't start:
# Check logs
sudo journalctl -u shinobi -f
# Check PM2 status
sudo -u shinobi pm2 status
sudo -u shinobi pm2 logs
# Check database connection
mysql -u ccio -p ccio -e "SHOW TABLES;"
2. Cameras not connecting:
# Test RTSP stream manually
ffmpeg -rtsp_transport tcp -i rtsp://username:password@camera_ip:554/stream -t 10 test.mp4
# Check network connectivity
ping camera_ip
telnet camera_ip 554
3. High CPU usage:
# Check encoding settings in monitor configuration
# Reduce video quality or frame rate
# Enable hardware acceleration if available
4. Storage issues:
# Check disk space
df -h /opt/shinobi/videos
# Check permissions
ls -la /opt/shinobi/videos
# Check cron job for cleanup
sudo -u shinobi crontab -l
7. Security Considerations
SSL/TLS Configuration
# Generate self-signed certificate
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/shinobi/ssl/shinobi.key \
-out /opt/shinobi/ssl/shinobi.crt
# Set permissions
sudo chown shinobi:shinobi /opt/shinobi/ssl/*
sudo chmod 600 /opt/shinobi/ssl/shinobi.key
sudo chmod 644 /opt/shinobi/ssl/shinobi.crt
Update /opt/shinobi/conf.json
:
{
"ssl": {
"key": "/opt/shinobi/ssl/shinobi.key",
"cert": "/opt/shinobi/ssl/shinobi.crt",
"enabled": true,
"port": 8443
}
}
Firewall Configuration
#### firewalld (RHEL/CentOS)
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --permanent --add-port=8443/tcp
sudo firewall-cmd --reload
#### ufw (Ubuntu/Debian)
sudo ufw allow 8080/tcp
sudo ufw allow 8443/tcp
sudo ufw enable
#### iptables
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 8443 -j ACCEPT
sudo iptables-save | sudo tee /etc/iptables/rules.v4
User Authentication
1. Change default admin password:
2. Create limited users:
3. API Key Security:
# Generate secure API keys
openssl rand -hex 32
# Rotate keys regularly via web interface
8. Performance Tuning
Hardware Acceleration
Enable GPU acceleration in /opt/shinobi/conf.json
:
{
"accelerator": {
"enabled": true,
"hwaccel": "vaapi",
"hwaccel_device": "/dev/dri/renderD128"
}
}
CPU Optimization
# Set CPU governor to performance
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
# Adjust process priorities
sudo systemctl edit shinobi
Add to override file:
[Service]
Nice=-10
IOSchedulingClass=1
IOSchedulingPriority=4
Memory Optimization
# Increase shared memory for large installations
echo 'kernel.shmmax = 268435456' | sudo tee -a /etc/sysctl.conf
echo 'kernel.shmall = 2097152' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Storage Optimization
# Use SSD for database and temporary files
sudo mkdir -p /var/lib/mysql-ssd
sudo mount /dev/nvme0n1p1 /var/lib/mysql-ssd
sudo chown mysql:mysql /var/lib/mysql-ssd
# Configure log rotation
sudo nano /etc/logrotate.d/shinobi
Add:
/opt/shinobi/logs/*.log {
daily
missingok
rotate 7
compress
delaycompress
copytruncate
}
9. Backup and Restore
Database Backup
#!/bin/bash
# /opt/shinobi/scripts/backup-db.sh
BACKUP_DIR="/var/backups/shinobi"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="ccio"
DB_PASS="your_secure_password"
DB_NAME="ccio"
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup database
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/shinobi_db_$DATE.sql
# Compress backup
gzip $BACKUP_DIR/shinobi_db_$DATE.sql
# Remove backups older than 30 days
find $BACKUP_DIR -name "shinobi_db_*.sql.gz" -mtime +30 -delete
echo "Database backup completed: $BACKUP_DIR/shinobi_db_$DATE.sql.gz"
Configuration Backup
#!/bin/bash
# /opt/shinobi/scripts/backup-config.sh
BACKUP_DIR="/var/backups/shinobi"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup directory
mkdir -p $BACKUP_DIR
# Backup configuration files
tar -czf $BACKUP_DIR/shinobi_config_$DATE.tar.gz \
/opt/shinobi/conf.json \
/opt/shinobi/super.json \
/opt/shinobi/ssl/ \
/etc/systemd/system/shinobi.service
echo "Configuration backup completed: $BACKUP_DIR/shinobi_config_$DATE.tar.gz"
Automated Backup Setup
# Add to crontab
sudo crontab -e
# Daily database backup at 2 AM
0 2 * * * /opt/shinobi/scripts/backup-db.sh
# Weekly configuration backup
0 3 * * 0 /opt/shinobi/scripts/backup-config.sh
Restore Procedures
# Restore database
gunzip -c /var/backups/shinobi/shinobi_db_YYYYMMDD_HHMMSS.sql.gz | \
mysql -u ccio -p ccio
# Restore configuration
tar -xzf /var/backups/shinobi/shinobi_config_YYYYMMDD_HHMMSS.tar.gz -C /
# Restart services
sudo systemctl restart mariadb
sudo systemctl restart shinobi
10. System Requirements
Minimum Requirements
Recommended Requirements
Scaling Guidelines
11. Support
Official Resources
Troubleshooting Resources
12. Contributing
How to Contribute
1. Fork the repository on GitLab
2. Create a feature branch
3. Submit merge request
4. Follow coding standards
5. Include tests and documentation
Development Setup
# Clone development version
git clone https://gitlab.com/Shinobi-Systems/Shinobi.git
cd Shinobi
# Install development dependencies
npm install --dev
# Run in development mode
npm run dev
13. License
Shinobi is licensed under the GNU General Public License v3.0 (GPLv3).
Key points:
14. Acknowledgments
Credits
15. Version History
Current Releases
Major Features by Version
16. Appendices
A. Camera Configuration Examples
#### Generic RTSP Camera
{
"name": "Front Door",
"type": "rtsp",
"path": "rtsp://username:password@192.168.1.100:554/stream1",
"port": 554,
"host": "192.168.1.100",
"username": "admin",
"password": "camera_password"
}
#### Hikvision Camera
{
"name": "Hikvision Cam",
"type": "rtsp",
"path": "rtsp://admin:password@192.168.1.101:554/Streaming/Channels/101",
"port": 554,
"host": "192.168.1.101"
}
#### Dahua Camera
{
"name": "Dahua Cam",
"type": "rtsp",
"path": "rtsp://admin:password@192.168.1.102:554/cam/realmonitor?channel=1&subtype=0",
"port": 554,
"host": "192.168.1.102"
}
B. API Examples
#### Get Monitor List
curl -X GET "http://localhost:8080/api/monitor/list" \
-H "Content-Type: application/json" \
-d '{"ke":"your_api_key","uid":"your_user_id"}'
#### Start Recording
curl -X POST "http://localhost:8080/api/monitor/record/start" \
-H "Content-Type: application/json" \
-d '{"ke":"your_api_key","uid":"your_user_id","mid":"monitor_id"}'
C. Performance Monitoring
#!/bin/bash
# Monitor Shinobi performance
echo "=== CPU Usage ==="
top -bn1 | grep shinobi
echo "=== Memory Usage ==="
ps aux | grep shinobi | awk '{sum+=$6} END {print "Total Memory: " sum/1024 " MB"}'
echo "=== Disk Usage ==="
df -h /opt/shinobi/videos
echo "=== Active Connections ==="
netstat -an | grep :8080 | wc -l
echo "=== Database Size ==="
mysql -u ccio -p ccio -e "SELECT table_schema AS 'Database',
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'MB'
FROM information_schema.tables WHERE table_schema='ccio';"
---
For more information and updates, visit https://github.com/howtomgr/shinobi