Files
SneakyScan/docs/DEPLOYMENT.md

27 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)
  • Background Jobs: APScheduler for async scan execution
  • Scanner: masscan, nmap, sslyze, Playwright
  • Config Creator: Web-based CIDR-to-YAML configuration builder
  • 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:

# 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
nano .env

# 3. Build the Docker image
docker compose build

# 4. Initialize the database and set password
docker compose run --rm init-db --password "YourSecurePassword"

# 5. Start the application
docker compose up -d

# 6. 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.

Creating Your .env File

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

# Generate secure keys
python3 -c "import secrets; print('SECRET_KEY=' + secrets.token_hex(32))" >> .env
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
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 configs/ data/ output/ logs/

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

Step 2: Configure Scan Targets

You can create scan configurations in two ways:

Option A: Using the Web UI (Recommended - Phase 4 Feature)

  1. Navigate to Configs in the web interface
  2. Click "Create New Config"
  3. Use the CIDR-based config creator for quick setup:
    • Enter site name
    • Enter CIDR range (e.g., 192.168.1.0/24)
    • Select expected ports from dropdowns
    • Click "Generate Config"
  4. Or use the YAML Editor for advanced configurations
  5. Save and use immediately in scans or schedules

Option B: Manual YAML Files

Create YAML configuration files manually in the configs/ directory:

# Example configuration
cat > configs/my-network.yaml <<EOF
title: "My Network Infrastructure"
sites:
  - name: "Web Servers"
    cidr: "192.168.1.0/24"  # Scan entire subnet
    expected_ports:
      - port: 80
        protocol: tcp
        service: "http"
      - port: 443
        protocol: tcp
        service: "https"
      - port: 22
        protocol: tcp
        service: "ssh"
    ping_expected: true
EOF

Note: Phase 4 introduced a powerful config creator in the web UI that makes it easy to generate configs from CIDR ranges without manually editing YAML.

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

The database must be initialized before first use. The init-db service uses a profile, so you need to explicitly run it:

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

# The init-db command will:
# - Create database schema
# - Run all Alembic migrations
# - Set the application password (bcrypt hashed)
# - Create default settings with encryption

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

Password Requirements:

  • 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.

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 (Phase 4)

Creating Configs:

  1. Navigate to ConfigsCreate New Config
  2. CIDR Creator Mode:
    • Enter site name (e.g., "Production Servers")
    • Enter CIDR range (e.g., 192.168.1.0/24)
    • Select expected TCP/UDP ports from dropdowns
    • Click "Generate Config" to create YAML
  3. YAML Editor Mode:
    • Switch to editor tab for advanced configurations
    • Syntax highlighting with line numbers
    • Validate YAML before saving

Editing Configs:

  1. Navigate to Configs → Select config
  2. Click "Edit" button
  3. Make changes in YAML editor
  4. Save changes (validates YAML automatically)

Uploading Configs:

  1. Navigate to ConfigsUpload
  2. Select YAML file from your computer
  3. File is validated and saved to configs/ directory

Downloading Configs:

  • Click "Download" button next to any config
  • Saves YAML file to your local machine

Deleting Configs:

  • Click "Delete" button
  • Warning: Cannot delete configs used by active schedules

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?
./configs /app/configs Scan configuration files (managed via web UI) Yes
./data /app/data SQLite database (contains all scan history) Critical
./output /app/output Scan results (JSON, HTML, ZIP, screenshots) Yes
./logs /app/logs Application logs (rotating file handler) No

Note: As of Phase 4, the ./configs volume is read-write to support the web-based config creator and editor. The web UI can now create, edit, and delete configuration files directly.

Backing Up Data

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

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

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

# Backup configurations
tar -czf backups/$(date +%Y%m%d)/configs.tar.gz configs/

Restoring Data

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

# Restore database
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

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 (Phase 4)

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

# Get specific config
curl http://localhost:5000/api/configs/prod-network.yaml \
  -b cookies.txt

# Create new config
curl -X POST http://localhost:5000/api/configs \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "test-network.yaml",
    "content": "title: Test Network\nsites:\n  - name: Test\n    cidr: 10.0.0.0/24"
  }' \
  -b cookies.txt

# Update config
curl -X PUT http://localhost:5000/api/configs/test-network.yaml \
  -H "Content-Type: application/json" \
  -d '{
    "content": "title: Updated Test Network\nsites:\n  - name: Test Site\n    cidr: 10.0.0.0/24"
  }' \
  -b cookies.txt

# Download config
curl http://localhost:5000/api/configs/test-network.yaml/download \
  -b cookies.txt -o test-network.yaml

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

Scan Management

# Trigger a scan
curl -X POST http://localhost:5000/api/scans \
  -H "Content-Type: application/json" \
  -d '{"config_file": "/app/configs/prod-network.yaml"}' \
  -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
curl -X POST http://localhost:5000/api/schedules \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Daily Production Scan",
    "config_file": "/app/configs/prod-network.yaml",
    "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 -f docker-compose.yml logs web

# Common issues:
# 1. Database not initialized - run init-db first
# 2. Permission issues with volumes - check directory ownership
# 3. Port 5000 already in use - change FLASK_PORT or stop conflicting service

Database Initialization Fails

Problem: init_db.py fails with errors

# Check database directory permissions
ls -la data/

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

# Verify SQLite is accessible
sqlite3 data/sneakyscanner.db "SELECT 1;" 2>&1

# Remove corrupted database and reinitialize
rm data/sneakyscanner.db
docker compose -f docker-compose.yml run --rm init-db --password "YourPassword"

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

Config Files Not Appearing in Web UI

Problem: Manually created configs don't show up in web interface

# Check file permissions (must be readable by web container)
ls -la configs/

# Fix permissions if needed
sudo chown -R 1000:1000 configs/
chmod 644 configs/*.yaml

# Verify YAML syntax is valid
docker compose -f docker-compose.yml exec web python3 -c \
  "import yaml; yaml.safe_load(open('/app/configs/your-config.yaml'))"

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

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
chmod 600 data/sneakyscanner.db

# Configs should be read-only
chmod 444 configs/*.yaml

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
cp data/sneakyscanner.db "$BACKUP_DIR/"

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

# Backup configs
cp -r configs/ "$BACKUP_DIR/"

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

echo "Backup complete: $BACKUP_DIR"

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 files
cp backups/YYYYMMDD_HHMMSS/sneakyscanner.db data/
cp -r backups/YYYYMMDD_HHMMSS/configs/* configs/
cp -r backups/YYYYMMDD_HHMMSS/output/* output/

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

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) - Config Creator

  • CIDR-based Config Creator: Web UI for generating scan configs from CIDR ranges
  • YAML Editor: Built-in editor with syntax highlighting (CodeMirror)
  • Config Management UI: List, view, edit, download, and delete configs via web interface
  • Config Upload: Direct YAML file upload for advanced users
  • REST API: 7 new config management endpoints
  • Schedule Protection: Prevents deleting configs used by active schedules

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-17 Version: Phase 4 - Config Creator Complete