Files
SneakyScan/docs/DEPLOYMENT.md
Phillip Tarrant 5e3a70f837 Fix schedule management and update documentation for database-backed configs
This commit addresses multiple issues with schedule management and updates
  documentation to reflect the transition from YAML-based to database-backed
  configuration system.

  **Documentation Updates:**
  - Update DEPLOYMENT.md to remove all references to YAML config files
  - Document that all configurations are now stored in SQLite database
  - Update API examples to use config IDs instead of YAML filenames
  - Remove configs directory from backup/restore procedures
  - Update volume management section to reflect database-only storage

  **Cron Expression Handling:**
  - Add comprehensive documentation for APScheduler cron format conversion
  - Document that from_crontab() accepts standard format (Sunday=0) and converts automatically
  - Add validate_cron_expression() helper method with detailed error messages
  - Include helpful hints for day-of-week field errors in validation
  - Fix all deprecated datetime.utcnow() calls, replace with datetime.now(timezone.utc)

  **Timezone-Aware DateTime Fixes:**
  - Fix "can't subtract offset-naive and offset-aware datetimes" error
  - Add timezone awareness to croniter.get_next() return values
  - Make _get_relative_time() defensive to handle both naive and aware datetimes
  - Ensure all datetime comparisons use timezone-aware objects

  **Schedule Edit UI Fixes:**
  - Fix JavaScript error "Cannot set properties of null (setting 'value')"
  - Change reference from non-existent 'config-id' to correct 'config-file' element
  - Add config_name field to schedule API responses for better UX
  - Eagerly load Schedule.config relationship using joinedload()
  - Fix AttributeError: use schedule.config.title instead of .name
  - Display config title and ID in schedule edit form

  **Technical Details:**
  - app/web/services/schedule_service.py: 6 datetime.utcnow() fixes, validation enhancements
  - app/web/services/scheduler_service.py: Documentation, validation, timezone fixes
  - app/web/templates/schedule_edit.html: JavaScript element reference fix
  - docs/DEPLOYMENT.md: Complete rewrite of config management sections

  Fixes scheduling for Sunday at midnight (cron: 0 0 * * 0)
  Fixes schedule edit page JavaScript errors
  Improves user experience with config title display
2025-11-24 12:53:06 -06:00

30 KiB

SneakyScanner Deployment Guide

Table of Contents

  1. Overview
  2. Prerequisites
  3. Quick Start
  4. Configuration
  5. First-Time Setup
  6. Running the Application
  7. Using the Web Interface
  8. Volume Management
  9. Health Monitoring
  10. Troubleshooting
  11. Security Considerations
  12. Upgrading
  13. Backup and Restore

Overview

SneakyScanner is deployed as a Docker container running a Flask web application with an integrated network scanner. The application requires privileged mode and host networking to perform network scans using masscan and nmap.

Architecture:

  • Web Application: Flask app on port 5000 with modern web UI
  • Database: SQLite (persisted to volume) - stores all configurations, scan results, and settings
  • Background Jobs: APScheduler for async scan execution
  • Scanner: masscan, nmap, sslyze, Playwright
  • Config Management: Database-backed configuration system managed entirely via web UI
  • Scheduling: Cron-based scheduled scans with dashboard management

Prerequisites

System Requirements

  • Operating System: Linux (Ubuntu 20.04+, Debian 11+, or similar)
  • Docker: Version 20.10+ or Docker Engine 24.0+
  • Docker Compose: Version 2.0+ (or docker-compose 1.29+)
  • Memory: Minimum 2GB RAM (4GB+ recommended)
  • Disk Space: Minimum 5GB free space
  • Permissions: Root/sudo access for Docker privileged mode

Network Requirements

  • Outbound internet access for Docker image downloads
  • Access to target networks for scanning
  • Port 5000 available on host (or configure alternative)

Install Docker and Docker Compose

Ubuntu/Debian:

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add your user to docker group
sudo usermod -aG docker $USER
newgrp docker

# Verify installation
docker --version
docker compose version

Other Linux distributions: See Docker installation guide


Quick Start

For users who want to get started immediately with the web application:

Option 1: Automated Setup (Recommended)

# 1. Clone the repository
git clone <repository-url>
cd SneakyScan

# 2. Run the setup script
./setup.sh

# 3. Access the web interface
# Open browser to: http://localhost:5000
# Login with password from ./admin_password.txt or ./logs/admin_password.txt

The setup script automatically:

  • Generates secure random keys (SECRET_KEY, ENCRYPTION_KEY)
  • Prompts for password or generates a random one
  • Creates required directories
  • Builds Docker image
  • Starts the application
  • Auto-initializes database on first run

Option 2: Manual Setup

# 1. Clone the repository
git clone <repository-url>
cd SneakyScan

# 2. Create environment file
cp .env.example .env
# Edit .env and set SECRET_KEY and SNEAKYSCANNER_ENCRYPTION_KEY
# Optionally set INITIAL_PASSWORD (leave blank for auto-generation)
nano .env

# 3. Build and start (database auto-initializes on first run)
docker compose up --build -d

# 4. Check logs for auto-generated password (if not set in .env)
docker compose logs web | grep "Password"
# Or check: ./logs/admin_password.txt

# 5. Access the web interface
# Open browser to: http://localhost:5000

Alternative: Standalone CLI Scanner

For quick one-off scans without the web interface:

# Build and run with standalone compose file
docker compose -f docker-compose-standalone.yml build
docker compose -f docker-compose-standalone.yml up

# Results saved to ./output/ directory

Note: docker-compose.yml (web application) is now the default. Use docker-compose-standalone.yml for CLI-only scans.


Configuration

Environment Variables

SneakyScanner is configured via environment variables. The recommended approach is to use a .env file.

UDP Port Scanning

  • UDP Port scanning is disabled by default.
  • You can turn it on via the .env variable.
  • By Default, UDP port scanning only scans the top 20 ports, for convenience I have included the NMAP top 100 UDP ports as well.

Creating Your .env File

# Copy the example file
cp .env.example .env

# Generate secure keys
# SECRET_KEY: Flask session secret (64-character hex string)
python3 -c "import secrets; print('SECRET_KEY=' + secrets.token_hex(32))" >> .env

# SNEAKYSCANNER_ENCRYPTION_KEY: Fernet key for database encryption (32 url-safe base64 bytes)
python3 -c "from cryptography.fernet import Fernet; print('SNEAKYSCANNER_ENCRYPTION_KEY=' + Fernet.generate_key().decode())" >> .env

# Edit other settings as needed
nano .env

Key Configuration Options

Variable Description Default Required
FLASK_ENV Environment mode (production or development) production Yes
FLASK_DEBUG Enable debug mode (true or false) false Yes
SECRET_KEY Flask session secret (change in production!) dev-secret-key-change-in-production Yes
SNEAKYSCANNER_ENCRYPTION_KEY Encryption key for sensitive settings (empty) Yes
DATABASE_URL SQLite database path sqlite:////app/data/sneakyscanner.db Yes
INITIAL_PASSWORD Password for first-run initialization (leave empty to auto-generate) (empty) No
LOG_LEVEL Logging level (DEBUG, INFO, WARNING, ERROR) INFO No
SCHEDULER_EXECUTORS Number of concurrent scan threads 2 No
SCHEDULER_JOB_DEFAULTS_MAX_INSTANCES Max instances of same job 3 No
CORS_ORIGINS CORS allowed origins (comma-separated) * No

Important Security Note:

  • ALWAYS change SECRET_KEY and SNEAKYSCANNER_ENCRYPTION_KEY in production
  • Never commit .env file to version control
  • Use strong, randomly-generated keys

First-Time Setup

Step 1: Prepare Directories

The application needs these directories (created automatically by Docker):

# Verify directories exist
ls -la data/ output/ logs/

# If missing, create them
mkdir -p data output logs

Step 2: Configure Scan Targets

After starting the application, create scan configurations using the web UI:

Creating Configurations via Web UI

  1. Navigate to Configs in the web interface
  2. Click "Create New Config"
  3. Use the form-based config creator:
    • Enter site name
    • Enter CIDR range (e.g., 192.168.1.0/24)
    • Select expected TCP/UDP ports from dropdowns
    • Optionally enable ping checks
  4. Click "Save Configuration"
  5. Configuration is saved to database and immediately available for scans and schedules

Note: All configurations are stored in the database, not as files. This provides better reliability, easier backup, and seamless management through the web interface.

Step 3: Build Docker Image

# Build the image (takes 5-10 minutes on first run)
docker compose -f docker-compose.yml build

# Verify image was created
docker images | grep sneakyscanner

Step 4: Initialize Database

Automatic Initialization (Recommended)

As of Phase 5, the database is automatically initialized on first run:

# Just start the application
docker compose up -d

# On first run, the entrypoint script will:
# - Detect no existing database
# - Generate a random password (if INITIAL_PASSWORD not set in .env)
# - Save password to ./logs/admin_password.txt
# - Initialize database schema
# - Create default settings and alert rules
# - Start the Flask application

# Check logs to see the auto-generated password
docker compose logs web | grep "Password"

# Or view the password file
cat logs/admin_password.txt

Manual Initialization (Advanced)

You can still manually initialize the database if needed:

# Initialize database and set application password
docker compose run --rm init-db --password "YourSecurePassword" --force

# The init-db command will:
# - Create database schema
# - Set the application password (bcrypt hashed)
# - Create default settings with encryption
# - Create default alert rules

# Verify database was created
ls -lh data/sneakyscanner.db

Password Management:

  • Leave INITIAL_PASSWORD blank in .env for auto-generation
  • Auto-generated passwords are saved to ./logs/admin_password.txt
  • For custom password, set INITIAL_PASSWORD in .env
  • Minimum 8 characters recommended
  • Use a strong, unique password
  • Store securely (password manager)

Note: The init-db service is defined with profiles: [tools] in docker-compose.yml, which means it won't start automatically with docker compose up. However, the web service now handles initialization automatically via the entrypoint script.

Step 5: Verify Configuration

# Check database file was created
ls -lh data/sneakyscanner.db

# Verify Docker Compose configuration
docker compose -f docker-compose.yml config

Running the Application

Starting the Application

# Start in detached mode (background)
docker compose -f docker-compose.yml up -d

# View logs during startup
docker compose -f docker-compose.yml logs -f web

# Expected output:
# web_1  | INFO:werkzeug: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

Accessing the Web Interface

  1. Open browser to: http://localhost:5000
  2. Login with the password you set during database initialization (username is not required - single-user mode)
  3. Dashboard will display:
    • Recent scans with status indicators
    • Summary statistics (total scans, IPs, ports, services)
    • Trend charts showing infrastructure changes over time
    • Quick actions (run scan, create config, view schedules)

Stopping the Application

# Stop containers (preserves data)
docker compose -f docker-compose.yml down

# Stop and remove volumes (WARNING: deletes all data!)
docker compose -f docker-compose.yml down -v

Restarting the Application

# Restart all services
docker compose -f docker-compose.yml restart

# Restart only the web service
docker compose -f docker-compose.yml restart web

Viewing Logs

# View all logs
docker compose -f docker-compose.yml logs

# Follow logs in real-time
docker compose -f docker-compose.yml logs -f

# View last 100 lines
docker compose -f docker-compose.yml logs --tail=100

# View logs for specific service
docker compose -f docker-compose.yml logs web

Using the Web Interface

Dashboard Overview

The dashboard provides a central view of your scanning activity:

Key Sections:

  • Summary Statistics: Total scans, IPs discovered, open ports, services detected
  • Recent Scans: Last 10 scans with status, timestamp, and quick actions
  • Trend Charts: Port count trends over time using Chart.js
  • Quick Actions: Buttons to run scans, create configs, manage schedules

Managing Scan Configurations

All scan configurations are stored in the database and managed entirely through the web interface.

Creating Configs:

  1. Navigate to ConfigsCreate New Config
  2. Fill in the configuration form:
    • Enter site name (e.g., "Production Servers")
    • Enter CIDR range (e.g., 192.168.1.0/24)
    • Select expected TCP/UDP ports from dropdowns
    • Enable/disable ping checks
  3. Click "Save Configuration"
  4. Configuration is immediately stored in database and available for use

Editing Configs:

  1. Navigate to Configs → Select config from list
  2. Click "Edit" button
  3. Modify any fields in the configuration form
  4. Click "Save Changes" to update database

Viewing Configs:

  • Navigate to Configs page to see all saved configurations
  • Each config shows site name, CIDR range, and expected ports
  • Click on any config to view full details

Deleting Configs:

  • Click "Delete" button next to any config
  • Warning: Cannot delete configs used by active schedules
  • Deletion removes the configuration from the database permanently

Note: All configurations are database-backed, providing automatic backups when you backup the database file.

Running Scans

Manual Scans:

  1. Navigate to Dashboard or Scans
  2. Click "Run Scan Now"
  3. Select configuration file from dropdown
  4. Click "Start Scan"
  5. Scan executes in background (APScheduler)
  6. Monitor progress on Scans page

Scheduled Scans:

  1. Navigate to SchedulesCreate Schedule
  2. Enter schedule name (e.g., "Daily production scan")
  3. Select config file
  4. Enter cron expression (e.g., 0 2 * * * for 2 AM daily)
  5. Enable schedule
  6. Scans run automatically in background

Cron Expression Examples:

  • 0 2 * * * - Daily at 2 AM
  • 0 */6 * * * - Every 6 hours
  • 0 0 * * 0 - Weekly on Sunday at midnight
  • 0 0 1 * * - Monthly on 1st at midnight

Viewing Scan Results

Scan List:

  • Navigate to Scans page
  • View all historical scans with filters
  • Click scan ID to view details

Scan Details:

  • Full scan results organized by site
  • Discovered IPs, ports, services
  • SSL/TLS certificate information
  • TLS version support and cipher suites
  • Service version detection
  • Screenshots of web services
  • Download buttons (JSON, HTML, ZIP)

Trend Analysis:

  • Charts showing port count changes over time
  • Identify infrastructure drift
  • Track service version updates

Volume Management

Understanding Volumes

SneakyScanner uses several mounted volumes for data persistence:

Volume Container Path Purpose Important?
./data /app/data SQLite database (contains configurations, scan history, settings) Critical
./output /app/output Scan results (JSON, HTML, ZIP, screenshots) Yes
./logs /app/logs Application logs (rotating file handler) No

Note: All scan configurations are stored in the SQLite database (./data/sneakyscanner.db). There is no separate configs directory or YAML files. Backing up the database file ensures all your configurations are preserved.

Backing Up Data

# Create backup directory
mkdir -p backups/$(date +%Y%m%d)

# Backup database (includes all configurations)
cp data/sneakyscanner.db backups/$(date +%Y%m%d)/

# Backup scan outputs
tar -czf backups/$(date +%Y%m%d)/output.tar.gz output/

Important: The database backup includes all scan configurations, settings, schedules, and scan history. No separate configuration file backup is needed.

Restoring Data

# Stop application
docker compose -f docker-compose.yml down

# Restore database (includes all configurations)
cp backups/YYYYMMDD/sneakyscanner.db data/

# Restore outputs
tar -xzf backups/YYYYMMDD/output.tar.gz

# Restart application
docker compose -f docker-compose.yml up -d

Note: Restoring the database file restores all configurations, settings, schedules, and scan history.

Cleaning Up Old Scan Results

Option A: Using the Web UI (Recommended)

  1. Navigate to Scans page
  2. Select scans you want to delete
  3. Click "Delete" button
  4. Confirm deletion (removes database records and all associated files)

Option B: Manual Cleanup

# Find old scan results (older than 30 days)
find output/ -type f -name "scan_report_*.json" -mtime +30

# Delete old scan results and screenshots
find output/ -type f -mtime +30 -delete
find output/ -type d -empty -delete

# Note: Manual deletion doesn't remove database records
# Use the web UI or API for complete cleanup

Option C: Using the API

# Delete a specific scan (removes DB records + files)
curl -X DELETE http://localhost:5000/api/scans/{scan_id} \
  -b cookies.txt

API Usage Examples

SneakyScanner provides a comprehensive REST API for automation and integration. All API endpoints require authentication via session cookies.

Authentication

# Login and save session cookie
curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"password": "YourPassword"}' \
  -c cookies.txt

# Logout
curl -X POST http://localhost:5000/api/auth/logout \
  -b cookies.txt

Config Management

# List all configs
curl http://localhost:5000/api/configs \
  -b cookies.txt

# Get specific config by ID
curl http://localhost:5000/api/configs/1 \
  -b cookies.txt

# Create new config
curl -X POST http://localhost:5000/api/configs \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Network",
    "cidr": "10.0.0.0/24",
    "expected_ports": [
      {"port": 80, "protocol": "tcp", "service": "http"},
      {"port": 443, "protocol": "tcp", "service": "https"}
    ],
    "ping_expected": true
  }' \
  -b cookies.txt

# Update config
curl -X PUT http://localhost:5000/api/configs/1 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Updated Test Network",
    "cidr": "10.0.1.0/24"
  }' \
  -b cookies.txt

# Delete config
curl -X DELETE http://localhost:5000/api/configs/1 \
  -b cookies.txt

Scan Management

# Trigger a scan (using config ID from database)
curl -X POST http://localhost:5000/api/scans \
  -H "Content-Type: application/json" \
  -d '{"config_id": 1}' \
  -b cookies.txt

# List all scans
curl http://localhost:5000/api/scans?page=1&per_page=20 \
  -b cookies.txt

# Get scan details
curl http://localhost:5000/api/scans/123 \
  -b cookies.txt

# Check scan status
curl http://localhost:5000/api/scans/123/status \
  -b cookies.txt

# Delete scan
curl -X DELETE http://localhost:5000/api/scans/123 \
  -b cookies.txt

Schedule Management

# List schedules
curl http://localhost:5000/api/schedules \
  -b cookies.txt

# Create schedule (using config ID from database)
curl -X POST http://localhost:5000/api/schedules \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily Production Scan",
    "config_id": 1,
    "cron_expression": "0 2 * * *",
    "enabled": true
  }' \
  -b cookies.txt

# Update schedule
curl -X PUT http://localhost:5000/api/schedules/1 \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}' \
  -b cookies.txt

# Manually trigger scheduled scan
curl -X POST http://localhost:5000/api/schedules/1/trigger \
  -b cookies.txt

# Delete schedule
curl -X DELETE http://localhost:5000/api/schedules/1 \
  -b cookies.txt

Settings Management

# Get all settings (sanitized - passwords hidden)
curl http://localhost:5000/api/settings \
  -b cookies.txt

# Update settings
curl -X PUT http://localhost:5000/api/settings \
  -H "Content-Type: application/json" \
  -d '{
    "retention_days": 90,
    "smtp_server": "smtp.gmail.com"
  }' \
  -b cookies.txt

# Test email configuration
curl -X POST http://localhost:5000/api/settings/test-email \
  -b cookies.txt

# Health check (no auth required)
curl http://localhost:5000/api/settings/health

Statistics

# Get dashboard summary
curl http://localhost:5000/api/stats/summary \
  -b cookies.txt

# Get trend data
curl http://localhost:5000/api/stats/trends?days=30&metric=port_count \
  -b cookies.txt

# Get certificate expiry overview
curl http://localhost:5000/api/stats/certificates \
  -b cookies.txt

For complete API documentation, see docs/API_REFERENCE.md.


Health Monitoring

Health Check Endpoint

SneakyScanner includes a built-in health check endpoint used by Docker's healthcheck:

# Check application health
curl http://localhost:5000/api/settings/health

# Expected response (200 OK):
# {"status": "healthy"}

# This endpoint is also used by Docker Compose healthcheck
# Defined in docker-compose.yml:
# - Interval: 60s (check every minute)
# - Timeout: 10s
# - Retries: 3
# - Start period: 40s (grace period for app startup)

Docker Health Status

# Check container health status
docker ps | grep sneakyscanner-web

# View health check logs
docker inspect sneakyscanner-web | grep -A 10 Health

Monitoring Logs

# Watch for errors in logs
docker compose -f docker-compose.yml logs -f | grep ERROR

# Check application log file
tail -f logs/sneakyscanner.log

Troubleshooting

Container Won't Start

Problem: Container exits immediately after starting

# Check logs for errors
docker compose logs web

# Common issues:
# 1. Permission issues with volumes - check directory ownership
# 2. Port 5000 already in use - change FLASK_PORT or stop conflicting service
# 3. Database initialization failed - check logs for specific error

# Check if database initialization is stuck
docker compose logs web | grep -A 20 "First Run Detected"

# If initialization failed, clean up and retry
docker compose down
rm -rf data/.db_initialized  # Remove marker file
docker compose up -d

Database Initialization Fails

Problem: Automatic database initialization fails on first run

# Check database directory permissions
ls -la data/

# Fix permissions if needed
sudo chown -R $USER:$USER data/

# View initialization logs
docker compose logs web | grep -A 50 "Initializing database"

# Clean up and retry initialization
docker compose down
rm -rf data/sneakyscanner.db data/.db_initialized
docker compose up -d

# Or manually initialize with specific password
docker compose down
rm -rf data/sneakyscanner.db data/.db_initialized
docker compose run --rm init-db --password "YourPassword" --force
docker compose up -d

Can't Find Password File

Problem: Password file not created or can't be found

# Check both possible locations
cat admin_password.txt      # Created by setup.sh
cat logs/admin_password.txt  # Created by Docker entrypoint

# Check container logs for password
docker compose logs web | grep -i password

# If password file is missing, manually set one
docker compose down
docker compose run --rm init-db --password "YourNewPassword" --force
docker compose up -d

Scans Fail with "Permission Denied"

Problem: Scanner cannot run masscan/nmap

# Verify container is running in privileged mode
docker inspect sneakyscanner-web | grep Privileged
# Should show: "Privileged": true

# Verify network mode is host
docker inspect sneakyscanner-web | grep NetworkMode
# Should show: "NetworkMode": "host"

# If not, verify docker-compose.yml has:
# privileged: true
# network_mode: host

Can't Access Web Interface

Problem: Browser can't connect to http://localhost:5000

# Verify container is running
docker ps | grep sneakyscanner-web

# Check if Flask is listening
docker compose -f docker-compose.yml exec web netstat -tlnp | grep 5000

# Check firewall rules
sudo ufw status | grep 5000

# Try from container host
curl http://localhost:5000/api/settings/health

# Check logs for binding errors
docker compose -f docker-compose.yml logs web | grep -i bind

Background Scans Not Running

Problem: Scans stay in "running" status forever

# Check scheduler is initialized
docker compose -f docker-compose.yml logs web | grep -i scheduler

# Check for job execution errors
docker compose -f docker-compose.yml logs web | grep -i "execute_scan"

# Verify APScheduler environment variables
docker compose -f docker-compose.yml exec web env | grep SCHEDULER

# Check for scan job errors
docker compose -f docker-compose.yml logs web | grep -E "(ERROR|Exception|Traceback)"

# Verify scanner executables are available
docker compose -f docker-compose.yml exec web which masscan nmap

Configs Not Appearing in Web UI

Problem: Created configs don't show up in web interface

# Check database connectivity
docker compose -f docker-compose.yml logs web | grep -i "database"

# Verify database file exists and is readable
ls -lh data/sneakyscanner.db

# Check for errors when creating configs
docker compose -f docker-compose.yml logs web | grep -i "config"

# Try accessing configs via API
curl http://localhost:5000/api/configs -b cookies.txt

# If database is corrupted, check integrity
docker compose -f docker-compose.yml exec web sqlite3 /app/data/sneakyscanner.db "PRAGMA integrity_check;"

Health Check Failing

Problem: Docker health check shows "unhealthy"

# Run health check manually
docker compose -f docker-compose.yml exec web \
  python3 -c "import urllib.request; print(urllib.request.urlopen('http://localhost:5000/api/settings/health').read())"

# Check if health endpoint exists
curl -v http://localhost:5000/api/settings/health

# Common causes:
# 1. Application crashed - check logs
# 2. Database locked - check for long-running scans
# 3. Flask not fully started - wait 40s (start_period)

Security Considerations

Production Deployment Checklist

  • Changed SECRET_KEY to random value (64+ character hex string)
  • Changed SNEAKYSCANNER_ENCRYPTION_KEY to random Fernet key
  • Set strong application password via init-db
  • Set FLASK_ENV=production
  • Set FLASK_DEBUG=false
  • Configured proper CORS_ORIGINS (not *)
  • Using HTTPS/TLS (reverse proxy recommended)
  • Restricted network access (firewall rules)
  • Regular backups configured (database + configs)
  • Log monitoring enabled
  • Scheduled scans configured with appropriate frequency
  • Alert rules configured (Phase 5 - coming soon)
  • Webhook/email notifications configured (Phase 5 - coming soon)

Network Security

Privileged Mode Considerations:

  • Container runs with --privileged flag for raw socket access (masscan/nmap)
  • This grants extensive host capabilities - only run on trusted networks
  • Restrict Docker host access with firewall rules
  • Consider running on dedicated scan server

Recommendations:

# Restrict access to port 5000 with firewall
sudo ufw allow from 192.168.1.0/24 to any port 5000
sudo ufw enable

# Or use reverse proxy (nginx, Apache) with authentication

HTTPS/TLS Setup

SneakyScanner does not include built-in TLS. For production, use a reverse proxy:

Example nginx configuration:

server {
    listen 443 ssl http2;
    server_name scanner.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

File Permissions

# Ensure proper ownership of data directories
sudo chown -R $USER:$USER data/ output/ logs/

# Restrict database file permissions (contains configurations and sensitive data)
chmod 600 data/sneakyscanner.db

# Ensure database directory is writable
chmod 700 data/

Upgrading

Upgrading to New Version

# 1. Stop the application
docker compose -f docker-compose.yml down

# 2. Backup database
cp data/sneakyscanner.db data/sneakyscanner.db.backup

# 3. Pull latest code
git pull origin master

# 4. Rebuild Docker image
docker compose -f docker-compose.yml build

# 5. Run database migrations
docker compose -f docker-compose.yml run --rm web alembic upgrade head

# 6. Start application
docker compose -f docker-compose.yml up -d

# 7. Verify upgrade
docker compose -f docker-compose.yml logs -f
curl http://localhost:5000/api/settings/health

Rolling Back

If upgrade fails:

# Stop new version
docker compose -f docker-compose.yml down

# Restore database backup
cp data/sneakyscanner.db.backup data/sneakyscanner.db

# Checkout previous version
git checkout <previous-version-tag>

# Rebuild and start
docker compose -f docker-compose.yml build
docker compose -f docker-compose.yml up -d

Backup and Restore

Automated Backup Script

Create backup.sh:

#!/bin/bash
BACKUP_DIR="backups/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"

# Stop application for consistent backup
docker compose -f docker-compose.yml stop web

# Backup database (includes all configurations)
cp data/sneakyscanner.db "$BACKUP_DIR/"

# Backup outputs (last 30 days only)
find output/ -type f -mtime -30 -exec cp --parents {} "$BACKUP_DIR/" \;

# Restart application
docker compose -f docker-compose.yml start web

echo "Backup complete: $BACKUP_DIR"
echo "Database backup includes all configurations, settings, and scan history"

Make executable and schedule with cron:

chmod +x backup.sh

# Add to crontab (daily at 2 AM)
crontab -e
# Add line:
0 2 * * * /path/to/SneakyScan/backup.sh

Restore from Backup

# Stop application
docker compose -f docker-compose.yml down

# Restore database (includes all configurations)
cp backups/YYYYMMDD_HHMMSS/sneakyscanner.db data/

# Restore output files
cp -r backups/YYYYMMDD_HHMMSS/output/* output/

# Start application
docker compose -f docker-compose.yml up -d

Note: Restoring the database file will restore all configurations, settings, schedules, and scan history from the backup.


Support and Further Reading

  • Project README: README.md - General project information
  • API Documentation: docs/API_REFERENCE.md - Complete REST API reference
  • Roadmap: docs/ROADMAP.md - Project roadmap, feature plans, and architecture
  • Issue Tracker: File bugs and feature requests on GitHub

What's New

Phase 4+ (2025-11-17) - Database-Backed Configuration System

  • Database-Backed Configs: All configurations stored in SQLite database (no YAML files)
  • Web-Based Config Creator: Form-based UI for creating scan configs from CIDR ranges
  • Config Management UI: List, view, edit, and delete configs via web interface
  • REST API: Full config management via RESTful API with database storage
  • Schedule Protection: Prevents deleting configs used by active schedules
  • Automatic Backups: Configurations included in database backups

Phase 3 (2025-11-14) - Dashboard & Scheduling

  • Dashboard: Summary stats, recent scans, trend charts
  • Scheduled Scans: Cron-based scheduling with web UI management
  • Scan History: Detailed scan results with full data display
  • Chart.js Integration: Port count trends over time

Phase 2 (2025-11-14) - Web Application Core

  • REST API: Complete API for scan management
  • Background Jobs: APScheduler-based async execution
  • Authentication: Session-based login system
  • Database Integration: SQLite with SQLAlchemy ORM

Coming Soon: Phase 5 - Email, Webhooks & Comparisons

  • Email notifications for infrastructure changes
  • Webhook integrations (Slack, PagerDuty, custom)
  • Scan comparison reports
  • Alert rule configuration

Last Updated: 2025-11-24 Version: Phase 4+ - Database-Backed Configuration System