Skip to content

Deploying Bluecherry

Bluecherry is a sophisticated, open-source Linux video surveillance system designed for network (IP) cameras with a minimal resource footprint. Built with efficiency in mind, Bluecherry delivers professional-grade video surveillance capabilities while maintaining low memory usage and CPU overhead, making it ideal for deployment on cloud infrastructure. Whether you’re securing a single property, managing multiple locations, or building an enterprise surveillance network, Bluecherry provides a powerful, flexible, and free solution with complete control over your security infrastructure.

Why Bluecherry?

Bluecherry stands out as the premier choice for professional video surveillance with exceptional features:

  • Completely Open Source: Free and donation-supported under GPL license with no licensing restrictions
  • Unlimited Cameras: Add unlimited network cameras to your surveillance system
  • ONVIF Support: Full compatibility with ONVIF standard cameras with automatic detection
  • Web-Based Interface: User-friendly web interface for configuration and live viewing
  • Low Resource Usage: Minimal memory footprint and efficient CPU usage for cost-effective deployment
  • Live Streaming: Real-time video streaming with multiple quality options
  • Cross-Platform Clients: Desktop clients available for Linux, Windows, and macOS
  • Mobile Apps: Native iOS and Android applications for mobile surveillance
  • User Roles and Access: Granular role-based access control for multiple users
  • Email Notifications: Automated email alerts for motion detection and events
  • Webhook Support: Integration with external systems via webhooks
  • Event Recording: Automated video recording with motion detection
  • Video Playback: Search and review recorded video with timeline navigation
  • Multi-Site Management: Manage multiple surveillance systems from one interface
  • Cloud Connectivity: Connect to your surveillance system securely from anywhere
  • Database Support: Integrated database for events and metadata
  • Easy Installation: Docker-based installation for quick deployment
  • Seamless Upgrades: Simple upgrade process without complex dependencies
  • Virtual Machine Ready: Works perfectly in virtualized environments
  • Active Community: Vibrant community support via forums and Discord

Bluecherry is ideal for small businesses needing professional surveillance, property managers monitoring multiple locations, security professionals deploying enterprise systems, home users requiring local surveillance control, and organizations prioritizing open-source security solutions. With persistent storage on Klutch.sh, your surveillance system is always available and secure.

Prerequisites

Before deploying Bluecherry, ensure you have:

  • A Klutch.sh account
  • A GitHub repository with your Bluecherry deployment configuration
  • Basic familiarity with Docker and Git
  • IP cameras with ONVIF support (or compatible network cameras)
  • Sufficient storage for video recordings (typically 100GB-1TB+ depending on retention policy)
  • Stable internet connection with adequate bandwidth for video streams
  • Understanding of network configuration and port management

Important Considerations

Deploying Bluecherry

  1. Create a New Project

    Log in to your Klutch.sh dashboard and create a new project for your Bluecherry surveillance system.

  2. Prepare Your Repository

    Create a GitHub repository with the following structure for your Bluecherry deployment:

    bluecherry-deploy/
    ├─ Dockerfile
    ├─ .env.example
    ├─ docker-entrypoint.sh
    ├─ .gitignore
    └─ README.md

    Here’s a Dockerfile for Bluecherry:

    FROM ubuntu:22.04
    ENV DEBIAN_FRONTEND=noninteractive
    # Install system dependencies
    RUN apt-get update && apt-get install -y \
    curl \
    wget \
    git \
    build-essential \
    autoconf \
    automake \
    libtool \
    pkg-config \
    php-fpm \
    php-cli \
    php-common \
    php-json \
    php-xml \
    php-curl \
    php-mysql \
    php-sqlite3 \
    nginx \
    mysql-server \
    sqlite3 \
    ffmpeg \
    libav-tools \
    vlc \
    vlc-plugin-base \
    vlc-plugin-core \
    libvlc-dev \
    libx264-dev \
    libx265-dev \
    libfdk-aac-dev \
    libmp3lame-dev \
    libopus-dev \
    libvpx-dev \
    libfreetype6-dev \
    libwebp-dev \
    python3 \
    python3-pip \
    sudo \
    systemctl \
    && rm -rf /var/lib/apt/lists/*
    # Install Bluecherry
    RUN curl -fsSL https://install.bluecherrydvr.com/docker | bash
    # Create necessary directories
    RUN mkdir -p /var/bluecherry/data \
    /var/bluecherry/recordings \
    /var/bluecherry/logs \
    /var/bluecherry/database \
    && chmod -R 755 /var/bluecherry
    # Copy entrypoint script
    COPY docker-entrypoint.sh /
    RUN chmod +x /docker-entrypoint.sh
    # Expose ports
    EXPOSE 7001 7002 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010
    # Health check
    HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:7001/ || exit 1
    # Run entrypoint
    ENTRYPOINT ["/docker-entrypoint.sh"]
    CMD ["/bin/bash"]

    Create a docker-entrypoint.sh file:

    #!/bin/bash
    set -e
    # Create necessary directories
    mkdir -p /var/bluecherry/data \
    /var/bluecherry/recordings \
    /var/bluecherry/logs \
    /var/bluecherry/database
    # Set proper permissions
    chmod -R 755 /var/bluecherry
    chown -R www-data:www-data /var/bluecherry
    # Initialize database if needed
    if [ ! -f /var/bluecherry/database/bluecherry.db ]; then
    echo "Initializing Bluecherry database..."
    sqlite3 /var/bluecherry/database/bluecherry.db < /usr/share/bluecherry/sql/bluecherry.sql || true
    chmod 755 /var/bluecherry/database/bluecherry.db
    chown www-data:www-data /var/bluecherry/database/bluecherry.db
    fi
    # Start PHP-FPM
    echo "Starting PHP-FPM..."
    service php-fpm start
    # Start Nginx
    echo "Starting Nginx..."
    service nginx start
    # Start Bluecherry services
    echo "Starting Bluecherry services..."
    service bluecherry start || true
    # Keep container running
    echo "Bluecherry surveillance system is running..."
    tail -f /var/log/bluecherry/*.log &
    wait

    Create a .env.example file:

    Terminal window
    # Bluecherry Configuration
    BLUECHERRY_HOST=0.0.0.0
    BLUECHERRY_PORT=7001
    BLUECHERRY_SECURE_PORT=7002
    # Admin User
    ADMIN_USER=admin
    ADMIN_PASSWORD=bluecherry
    ADMIN_EMAIL=admin@yourdomain.com
    # Database Configuration
    DB_TYPE=sqlite
    DB_PATH=/var/bluecherry/database/bluecherry.db
    # For MySQL:
    # DB_TYPE=mysql
    # DB_HOST=localhost
    # DB_NAME=bluecherry
    # DB_USER=bluecherry
    # DB_PASSWORD=secure_password
    # Storage Configuration
    RECORDINGS_PATH=/var/bluecherry/recordings
    DATA_PATH=/var/bluecherry/data
    LOG_PATH=/var/bluecherry/logs
    # Surveillance Settings
    ENABLE_EMAIL_ALERTS=true
    ALERT_EMAIL=admin@yourdomain.com
    RETENTION_DAYS=30
    # Network Configuration
    ALLOW_REMOTE_ACCESS=true
    ENABLE_HTTPS=true
    ENABLE_WEBHOOKS=true
    # Performance Tuning
    MAX_RECORDING_THREADS=4
    STREAMING_BUFFER_SIZE=2048
    DATABASE_CACHE_SIZE=512
    # Logging
    LOG_LEVEL=info

    Create a .gitignore file:

    .env
    recordings/
    database/
    logs/
    *.db
    *.log
    node_modules/
    .DS_Store

    Commit and push to your GitHub repository:

    Terminal window
    git init
    git add .
    git commit -m "Initial Bluecherry deployment"
    git remote add origin https://github.com/yourusername/bluecherry-deploy.git
    git push -u origin main
  3. Create a New App

    In the Klutch.sh dashboard:

    • Click “Create New App”
    • Select your GitHub repository containing the Dockerfile
    • Choose the branch (typically main or master)
    • Klutch.sh will automatically detect the Dockerfile in the root directory
  4. Configure Environment Variables

    Set up these essential environment variables in your Klutch.sh dashboard:

    VariableDescriptionExample
    BLUECHERRY_HOSTServer bind address0.0.0.0
    BLUECHERRY_PORTHTTP port7001
    BLUECHERRY_SECURE_PORTHTTPS port7002
    ADMIN_USERAdmin usernameadmin
    ADMIN_PASSWORDAdmin passwordbluecherry
    ADMIN_EMAILAdmin email addressadmin@yourdomain.com
    DB_TYPEDatabase type (sqlite/mysql)sqlite
    DB_PATHSQLite database path/var/bluecherry/database/bluecherry.db
    RECORDINGS_PATHVideo recordings directory/var/bluecherry/recordings
    DATA_PATHApplication data directory/var/bluecherry/data
    LOG_PATHLog files directory/var/bluecherry/logs
    ENABLE_EMAIL_ALERTSEnable motion detection alertstrue
    ALERT_EMAILAlert destination emailadmin@yourdomain.com
    RETENTION_DAYSVideo retention period30
    ALLOW_REMOTE_ACCESSEnable remote connectionstrue
    ENABLE_HTTPSEnable HTTPS accesstrue
    MAX_RECORDING_THREADSRecording threads4
    LOG_LEVELLogging verbosityinfo
  5. Configure Persistent Storage

    Bluecherry requires persistent storage for video recordings and database files. Add persistent volumes:

    Mount PathDescriptionRecommended Size
    /var/bluecherry/recordingsVideo recordings500GB-2TB
    /var/bluecherry/databaseDatabase files10GB
    /var/bluecherry/dataApplication data50GB
    /var/bluecherry/logsLog files20GB

    In the Klutch.sh dashboard:

    • Navigate to your app settings
    • Go to the “Volumes” section
    • Click “Add Volume” for each mount path
    • Set mount paths and sizes as specified above
    • Ensure recordings volume is sized for your retention policy and camera count
  6. Set Network Configuration

    Configure your app’s network settings:

    • Select traffic type: HTTP
    • Recommended internal port: 7001 (Bluecherry default web interface port)
    • Klutch.sh will handle HTTPS termination via reverse proxy
    • Additional ports (7002, 5000-5010) used for streaming and protocols
  7. Configure Custom Domain

    Bluecherry benefits from a custom domain for professional surveillance access:

    • Navigate to your app’s “Domains” section in Klutch.sh
    • Click “Add Custom Domain”
    • Enter your domain (e.g., surveillance.yourdomain.com or cctv.yourdomain.com)
    • Configure DNS with a CNAME record pointing to your Klutch.sh app
    • Update BLUECHERRY_HOST environment variable if needed
    • Klutch.sh will automatically provision SSL certificates
    • Access your surveillance system at https://surveillance.yourdomain.com
  8. Deploy Your App

    • Review all settings and environment variables
    • Verify all persistent volumes are properly configured with adequate sizes
    • Verify recordings volume is sized appropriately for your cameras and retention policy
    • Click “Deploy”
    • Klutch.sh will build the Docker image and start your Bluecherry instance
    • Wait for the deployment to complete (typically 10-15 minutes)
    • Access your Bluecherry instance at your configured domain
    • Log in with admin credentials to begin adding cameras

Initial Setup and Configuration

After deployment completes, access your Bluecherry instance to complete surveillance system setup.

Accessing Bluecherry

Navigate to your domain: https://surveillance.yourdomain.com

Log in to the admin panel using admin credentials you configured.

Admin Panel Access

Access administration features:

  1. Open https://surveillance.yourdomain.com in web browser
  2. Enter admin username and password (default: admin/bluecherry)
  3. You’re now in the Bluecherry admin dashboard
  4. Change default admin password immediately
  5. Configure system settings and add cameras

Adding IP Cameras

Set up your network cameras for surveillance:

Automatic Camera Discovery

  1. Ensure cameras are on the same network as Bluecherry
  2. Go to “Cameras” → “Add Cameras”
  3. Click “Network Scan” or “Auto-Discover”
  4. Bluecherry scans for ONVIF-compatible cameras
  5. Select cameras to add from discovery results
  6. Click “Add Selected Cameras”
  7. Enter camera credentials if required

Manual Camera Addition

  1. Navigate to “Cameras” → “Add Camera”
  2. Enter camera details:
    • Camera name/location
    • IP address or hostname
    • RTSP stream URL (if known)
    • Username and password
    • Stream resolution and codec
  3. Click “Test Connection” to verify
  4. Save camera configuration
  5. Monitor live stream to confirm connection

Configuring Camera Settings

Customize individual camera parameters:

  1. Select camera from camera list
  2. Go to “Settings” for the camera
  3. Configure:
    • Resolution and frame rate
    • Bitrate and quality settings
    • Recording settings (continuous/motion-triggered)
    • Event triggers
    • Retention policy
  4. Save settings and verify live stream

Setting Up Motion Detection

Enable automated recording based on motion:

  1. Navigate to “Cameras” → Select camera
  2. Go to “Motion Detection” settings
  3. Configure:
    • Enable/disable motion detection
    • Sensitivity level (adjust for false positives)
    • Detection areas (draw zones on preview)
    • Pre-recording buffer (seconds before motion)
    • Post-recording buffer (seconds after motion)
  4. Save configuration
  5. Test motion detection with camera movement

Configuring Recording Options

Set up video recording for your cameras:

  1. Go to “Cameras” → Select camera → “Recording”
  2. Configure:
    • Recording schedule (24/7, business hours, etc.)
    • Recording type (continuous/motion/manual)
    • Video quality and bitrate
    • Retention period (days to keep recordings)
  3. Adjust for your storage capacity
  4. Enable scheduled cleanup of old recordings
  5. Monitor storage usage in dashboard

Creating User Accounts and Roles

Set up multiple users with different access levels:

  1. Navigate to “Users” → “Add User”
  2. Enter user information:
    • Username and password
    • Email address
    • Display name
  3. Assign user role:
    • Admin: Full system access
    • Manager: Camera management and viewing
    • Viewer: View-only access to cameras
  4. Select cameras user can access
  5. Set user permissions
  6. Save user account
  7. User can log in and view assigned cameras

Setting Up Email Alerts

Configure notifications for motion detection and events:

  1. Go to “Settings” → “Email Notifications”
  2. Configure email server:
    • SMTP server address
    • SMTP port
    • Username and password
    • From email address
  3. Set alert rules:
    • Select cameras for alerts
    • Choose trigger events (motion, disconnect, etc.)
    • Set notification recipients
  4. Configure alert frequency to prevent spam
  5. Send test email to verify configuration

Viewing Live Streams

Access real-time camera feeds:

  1. Log in to Bluecherry web interface
  2. Click “Live View” or camera thumbnail
  3. Select camera from list
  4. View live stream (multiple stream quality options)
  5. Use playback controls for live stream
  6. Switch between cameras seamlessly
  7. Multi-camera view available in dashboard

Reviewing Recorded Video

Search and playback recorded surveillance footage:

  1. Navigate to “Playback” or “History”
  2. Select camera from dropdown
  3. Use calendar to select date
  4. Choose time range for viewing
  5. Click “Play” to start playback
  6. Use playback controls:
    • Play/Pause
    • Speed adjustment (1x, 2x, 4x)
    • Frame-by-frame navigation
    • Download video clip
  7. Search by motion detection events

Environment Variable Examples

Basic Configuration

Terminal window
BLUECHERRY_HOST=0.0.0.0
BLUECHERRY_PORT=7001
ADMIN_USER=admin
ADMIN_PASSWORD=securepassword
ADMIN_EMAIL=admin@yourdomain.com
DB_TYPE=sqlite
DB_PATH=/var/bluecherry/database/bluecherry.db
RECORDINGS_PATH=/var/bluecherry/recordings

Complete Production Configuration

Terminal window
# Server Configuration
BLUECHERRY_HOST=0.0.0.0
BLUECHERRY_PORT=7001
BLUECHERRY_SECURE_PORT=7002
# Admin Account
ADMIN_USER=admin
ADMIN_PASSWORD=very_secure_password_32_characters
ADMIN_EMAIL=admin@yourdomain.com
# Database Configuration
DB_TYPE=sqlite
DB_PATH=/var/bluecherry/database/bluecherry.db
# For MySQL:
# DB_TYPE=mysql
# DB_HOST=db.internal
# DB_NAME=bluecherry
# DB_USER=bluecherry
# DB_PASSWORD=secure_db_password
# Storage Configuration
RECORDINGS_PATH=/var/bluecherry/recordings
DATA_PATH=/var/bluecherry/data
LOG_PATH=/var/bluecherry/logs
# Surveillance Settings
ENABLE_EMAIL_ALERTS=true
ALERT_EMAIL=alerts@yourdomain.com
RETENTION_DAYS=30
AUTO_DELETE_OLD_RECORDINGS=true
# Network Configuration
ALLOW_REMOTE_ACCESS=true
ENABLE_HTTPS=true
ENABLE_WEBHOOKS=true
WEBHOOK_URL=https://webhook.yourdomain.com/bluecherry
# Performance Tuning
MAX_RECORDING_THREADS=8
STREAMING_BUFFER_SIZE=4096
DATABASE_CACHE_SIZE=1024
MAX_CONCURRENT_STREAMS=32
# Email Configuration
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=alerts@yourdomain.com
SMTP_PASSWORD=smtp_app_password
SMTP_FROM=Bluecherry Alerts <alerts@yourdomain.com>
SMTP_USE_TLS=true
# Logging
LOG_LEVEL=info
LOG_TO_FILE=true
LOG_ROTATION_ENABLED=true
LOG_RETENTION_DAYS=7

Sample Code and Getting Started

PHP - Camera Management Integration

<?php
// Bluecherry Camera Management Integration
class BluecherryManager {
private $apiUrl;
private $apiKey;
private $sessionId;
public function __construct($apiUrl, $username, $password) {
$this->apiUrl = $apiUrl;
$this->authenticate($username, $password);
}
private function authenticate($username, $password) {
// Authenticate with Bluecherry API
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/auth/login');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'username' => $username,
'password' => $password
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($response && isset($response['sessionId'])) {
$this->sessionId = $response['sessionId'];
}
}
public function getCameras() {
// Get list of all cameras
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/cameras');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->sessionId,
'Content-Type: application/json'
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response['cameras'] ?? [];
}
public function addCamera($name, $rtspUrl, $username, $password) {
// Add new camera to system
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/cameras');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'name' => $name,
'url' => $rtspUrl,
'username' => $username,
'password' => $password
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->sessionId,
'Content-Type: application/json'
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response;
}
public function enableMotionDetection($cameraId, $sensitivity) {
// Enable motion detection for camera
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/cameras/' . $cameraId . '/motion');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'enabled' => true,
'sensitivity' => $sensitivity
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->sessionId,
'Content-Type: application/json'
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response;
}
public function getRecordings($cameraId, $startTime, $endTime) {
// Get recordings for camera in time range
$ch = curl_init();
$query = http_build_query([
'start' => $startTime,
'end' => $endTime
]);
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/cameras/' . $cameraId . '/recordings?' . $query);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->sessionId,
'Content-Type: application/json'
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response['recordings'] ?? [];
}
public function setRecordingSchedule($cameraId, $schedule) {
// Set recording schedule for camera
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->apiUrl . '/api/v1/cameras/' . $cameraId . '/recording');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($schedule));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $this->sessionId,
'Content-Type: application/json'
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
return $response;
}
}
// Usage example
$bluecherry = new BluecherryManager(
'https://surveillance.yourdomain.com',
'admin',
'password'
);
$cameras = $bluecherry->getCameras();
foreach ($cameras as $camera) {
echo "Camera: " . $camera['name'] . " - " . $camera['status'] . "\n";
}

JavaScript - Live Stream Viewer

// Bluecherry Live Stream Viewer
class BluecherryViewer {
constructor(containerId, apiUrl, sessionToken) {
this.container = document.getElementById(containerId);
this.apiUrl = apiUrl;
this.sessionToken = sessionToken;
this.currentCamera = null;
this.videoElement = null;
this.init();
}
async init() {
this.setupUI();
this.loadCameras();
}
setupUI() {
// Create viewer HTML
this.container.innerHTML = `
<div class="bluecherry-viewer">
<div class="camera-selector">
<select id="cameraSelect" class="camera-dropdown">
<option value="">Select a camera...</option>
</select>
</div>
<div class="video-container">
<video id="liveStream" width="100%" height="auto" controls>
Your browser does not support the video tag.
</video>
</div>
<div class="camera-info">
<p id="cameraStatus">Disconnected</p>
<p id="cameraFPS">FPS: --</p>
<p id="cameraBitrate">Bitrate: -- Mbps</p>
</div>
<div class="controls">
<button id="snapshotBtn" class="btn">Snapshot</button>
<button id="recordBtn" class="btn">Record</button>
<button id="fullscreenBtn" class="btn">Fullscreen</button>
</div>
</div>
`;
this.videoElement = document.getElementById('liveStream');
this.setupEventListeners();
}
async loadCameras() {
try {
const response = await fetch(this.apiUrl + '/api/v1/cameras', {
headers: {
'Authorization': 'Bearer ' + this.sessionToken
}
});
const data = await response.json();
const select = document.getElementById('cameraSelect');
data.cameras.forEach(camera => {
const option = document.createElement('option');
option.value = camera.id;
option.textContent = camera.name;
select.appendChild(option);
});
} catch (error) {
console.error('Failed to load cameras:', error);
}
}
setupEventListeners() {
document.getElementById('cameraSelect').addEventListener('change', (e) => {
this.selectCamera(e.target.value);
});
document.getElementById('snapshotBtn').addEventListener('click', () => {
this.takeSnapshot();
});
document.getElementById('recordBtn').addEventListener('click', () => {
this.toggleRecording();
});
document.getElementById('fullscreenBtn').addEventListener('click', () => {
this.enterFullscreen();
});
}
async selectCamera(cameraId) {
if (!cameraId) return;
try {
const response = await fetch(
this.apiUrl + '/api/v1/cameras/' + cameraId + '/stream',
{
headers: {
'Authorization': 'Bearer ' + this.sessionToken
}
}
);
const data = await response.json();
this.videoElement.src = data.streamUrl;
this.currentCamera = cameraId;
this.updateCameraStatus('Connected');
} catch (error) {
console.error('Failed to select camera:', error);
this.updateCameraStatus('Connection Failed');
}
}
takeSnapshot() {
if (!this.currentCamera) {
alert('Please select a camera first');
return;
}
// Create canvas from video frame
const canvas = document.createElement('canvas');
canvas.width = this.videoElement.videoWidth;
canvas.height = this.videoElement.videoHeight;
canvas.getContext('2d').drawImage(this.videoElement, 0, 0);
// Download snapshot
const link = document.createElement('a');
link.href = canvas.toDataURL('image/jpeg');
link.download = 'snapshot-' + new Date().getTime() + '.jpg';
link.click();
}
toggleRecording() {
// Toggle local recording via MediaRecorder API
if (!this.mediaRecorder) {
const stream = this.videoElement.captureStream(30);
this.mediaRecorder = new MediaRecorder(stream);
this.recordedChunks = [];
this.mediaRecorder.ondataavailable = (e) => {
this.recordedChunks.push(e.data);
};
this.mediaRecorder.onstop = () => {
const blob = new Blob(this.recordedChunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'recording-' + new Date().getTime() + '.webm';
a.click();
this.recordedChunks = [];
};
this.mediaRecorder.start();
document.getElementById('recordBtn').textContent = 'Stop Recording';
} else {
this.mediaRecorder.stop();
this.mediaRecorder = null;
document.getElementById('recordBtn').textContent = 'Record';
}
}
enterFullscreen() {
if (this.videoElement.requestFullscreen) {
this.videoElement.requestFullscreen();
}
}
updateCameraStatus(status) {
document.getElementById('cameraStatus').textContent = status;
}
}
// Initialize viewer
document.addEventListener('DOMContentLoaded', () => {
new BluecherryViewer('viewer', 'https://surveillance.yourdomain.com', 'SESSION_TOKEN');
});

Bash - Automated Backup Script

#!/bin/bash
# Bluecherry Backup Script
BACKUP_DIR="/backups/bluecherry"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
# Create backup directory
mkdir -p $BACKUP_DIR
echo "Starting Bluecherry backup..."
# Backup database
echo "Backing up Bluecherry database..."
if [ -f /var/bluecherry/database/bluecherry.db ]; then
tar -czf $BACKUP_DIR/bluecherry_db_$TIMESTAMP.tar.gz \
/var/bluecherry/database/bluecherry.db
fi
# Backup application data
echo "Backing up application data..."
tar -czf $BACKUP_DIR/bluecherry_data_$TIMESTAMP.tar.gz \
/var/bluecherry/data \
--exclude='/var/bluecherry/data/recordings'
# Backup logs
echo "Backing up logs..."
tar -czf $BACKUP_DIR/bluecherry_logs_$TIMESTAMP.tar.gz \
/var/bluecherry/logs
# Backup configuration
echo "Backing up configuration..."
tar -czf $BACKUP_DIR/bluecherry_config_$TIMESTAMP.tar.gz \
/etc/bluecherry \
/etc/nginx/sites-enabled \
/etc/php-fpm.d
# Cleanup old backups
echo "Cleaning up old backups..."
find $BACKUP_DIR -name "bluecherry_*" -mtime +$RETENTION_DAYS -delete
# Calculate backup size
TOTAL_SIZE=$(du -sh $BACKUP_DIR | awk '{print $1}')
echo "Backup completed: $TIMESTAMP"
echo "Total backup size: $TOTAL_SIZE"
echo "Backup location: $BACKUP_DIR"
# List recent backups
echo ""
echo "Recent backups:"
ls -lh $BACKUP_DIR | tail -10
# Optional: Upload to cloud storage
# aws s3 sync $BACKUP_DIR s3://your-bucket/bluecherry-backups/ --delete
# Optional: Send backup notification
# curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
# -d "{\"text\":\"Bluecherry backup completed: $TIMESTAMP\"}"

cURL - API Integration Examples

Terminal window
# Bluecherry API Examples
# Authenticate and get session token
curl -X POST https://surveillance.yourdomain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "password"
}'
# Get all cameras
curl -X GET https://surveillance.yourdomain.com/api/v1/cameras \
-H "Authorization: Bearer SESSION_TOKEN"
# Get specific camera details
curl -X GET https://surveillance.yourdomain.com/api/v1/cameras/1 \
-H "Authorization: Bearer SESSION_TOKEN"
# Add new camera
curl -X POST https://surveillance.yourdomain.com/api/v1/cameras \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SESSION_TOKEN" \
-d '{
"name": "Front Door",
"url": "rtsp://192.168.1.100:554/stream",
"username": "camera_user",
"password": "camera_password",
"resolution": "1920x1080",
"fps": 30
}'
# Enable motion detection on camera
curl -X POST https://surveillance.yourdomain.com/api/v1/cameras/1/motion \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SESSION_TOKEN" \
-d '{
"enabled": true,
"sensitivity": 75,
"threshold": 100
}'
# Get recordings for camera
curl -X GET "https://surveillance.yourdomain.com/api/v1/cameras/1/recordings?start=2024-01-01&end=2024-01-02" \
-H "Authorization: Bearer SESSION_TOKEN"
# Download recording
curl -X GET "https://surveillance.yourdomain.com/api/v1/recordings/12345/download" \
-H "Authorization: Bearer SESSION_TOKEN" \
-o recording.mp4
# Get system status
curl -X GET https://surveillance.yourdomain.com/api/v1/system/status \
-H "Authorization: Bearer SESSION_TOKEN"
# Get storage information
curl -X GET https://surveillance.yourdomain.com/api/v1/system/storage \
-H "Authorization: Bearer SESSION_TOKEN"
# Update camera settings
curl -X PUT https://surveillance.yourdomain.com/api/v1/cameras/1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SESSION_TOKEN" \
-d '{
"name": "Front Door - Updated",
"resolution": "2560x1920",
"fps": 30,
"bitrate": 5000
}'
# Delete camera
curl -X DELETE https://surveillance.yourdomain.com/api/v1/cameras/1 \
-H "Authorization: Bearer SESSION_TOKEN"
# Create event alert rule
curl -X POST https://surveillance.yourdomain.com/api/v1/alerts \
-H "Content-Type: application/json" \
-H "Authorization: Bearer SESSION_TOKEN" \
-d '{
"name": "Motion Alert",
"camera_id": 1,
"trigger": "motion",
"action": "email",
"recipient": "admin@yourdomain.com"
}'

Surveillance System Management

Monitoring System Performance

Monitor your surveillance system health:

  1. Check CPU Usage: Monitor CPU load in dashboard
  2. Memory Monitoring: Verify RAM availability for streams
  3. Storage Monitoring: Track disk usage and retention
  4. Network Bandwidth: Monitor bandwidth utilization
  5. Recording Status: Verify cameras are recording
  6. Connection Status: Ensure cameras are connected

Managing Storage and Retention

Optimize storage usage:

  1. Set retention policy based on available storage
  2. Regular cleanup of old recordings
  3. Monitor disk space usage
  4. Implement tiered storage if needed
  5. Archive important recordings separately
  6. Adjust camera quality to reduce file sizes

User Access Management

Control who can access your surveillance system:

  1. Create appropriate user accounts
  2. Assign role-based permissions
  3. Restrict camera access by user
  4. Monitor user login activity
  5. Disable inactive accounts
  6. Require strong passwords
  7. Enable two-factor authentication if available

Event Logging and Alerts

Monitor system events:

  1. Review system logs for errors
  2. Monitor motion detection events
  3. Track camera connection changes
  4. Review user login/logout history
  5. Monitor failed authentication attempts
  6. Set up email alerts for critical events
  7. Archive important events

Troubleshooting

Common Issues and Solutions

Issue: Cameras not connecting

Solutions:

  • Verify camera IP addresses and network accessibility
  • Check camera credentials and RTSP URLs
  • Ensure cameras support ONVIF or compatible protocols
  • Verify network connectivity between Bluecherry and cameras
  • Check firewall rules and port forwarding
  • Review Bluecherry logs for connection errors

Issue: Recording not working

Troubleshooting:

  • Verify recording is enabled for camera
  • Check disk space availability
  • Verify permissions on recordings directory
  • Ensure motion detection is configured if using motion-triggered recording
  • Check CPU and memory usage
  • Review error logs for database issues

Issue: High CPU or memory usage

Solutions:

  • Reduce number of concurrent streams
  • Lower camera resolution and frame rates
  • Reduce video quality settings
  • Limit number of recording threads
  • Close unused connections
  • Monitor for stuck processes in logs

Issue: Cannot access web interface

Troubleshooting:

  • Verify Klutch.sh app is running
  • Check network connectivity
  • Verify domain DNS resolution
  • Clear browser cache and cookies
  • Check firewall rules
  • Review access logs for blocked connections

Issue: Email alerts not sending

Solutions:

  • Verify SMTP server configuration
  • Check SMTP credentials
  • Verify from email address is valid
  • Check firewall rules for SMTP port access
  • Review mail logs for errors
  • Test SMTP connection with telnet

Updating Bluecherry

To update Bluecherry to a newer version:

  1. Read the release notes and changelog
  2. Backup your database and recordings
  3. Update your Dockerfile:
    RUN curl -fsSL https://install.bluecherrydvr.com/docker | bash
  4. Commit and push to GitHub
  5. Klutch.sh will automatically rebuild
  6. Test camera connections after upgrade
  7. Verify recording functionality
  8. Monitor logs for any issues

Use Cases

Small Business Security

  • Monitor retail store or office
  • Motion detection for break-ins
  • Email alerts for suspicious activity

Property Management

  • Monitor multiple properties
  • Record activity for liability
  • Multi-site centralized management

Home Security

  • Protect residential property
  • Monitor entry points
  • Local storage and control

Event Venues

  • Monitor public spaces
  • Record events
  • Real-time security monitoring

Vehicle Tracking

  • Monitor parking areas
  • License plate recognition
  • Access control verification

Additional Resources

Conclusion

Deploying Bluecherry on Klutch.sh provides you with a professional, open-source video surveillance system that maintains complete control over your security infrastructure. With unlimited camera support, ONVIF compatibility, efficient resource usage, comprehensive recording capabilities, granular access control, and powerful event management, Bluecherry enables you to build a surveillance system tailored to your specific needs. Klutch.sh’s managed infrastructure ensures your surveillance system is always available, secure, and performant, allowing you to focus on monitoring and protecting what matters most.

Start securing your property or business today by deploying Bluecherry on Klutch.sh and experience professional-grade surveillance with the freedom and flexibility of open-source software.