# SneakyScanner Deployment Guide ## Table of Contents 1. [Overview](#overview) 2. [Prerequisites](#prerequisites) 3. [Quick Start](#quick-start) 4. [Configuration](#configuration) 5. [First-Time Setup](#first-time-setup) 6. [Running the Application](#running-the-application) 7. [Using the Web Interface](#using-the-web-interface) 8. [Volume Management](#volume-management) 9. [Health Monitoring](#health-monitoring) 10. [Troubleshooting](#troubleshooting) 11. [Security Considerations](#security-considerations) 12. [Upgrading](#upgrading) 13. [Backup and Restore](#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:** ```bash # 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](https://docs.docker.com/engine/install/) --- ## Quick Start For users who want to get started immediately with the web application: ```bash # 1. Clone the repository git clone 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: ```bash # 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 ```bash # 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): ```bash # 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: ```bash # Example configuration cat > configs/my-network.yaml <&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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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" ```bash # 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:** ```bash # 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:** ```nginx 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 ```bash # 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 ```bash # 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: ```bash # 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 # 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`: ```bash #!/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: ```bash 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 ```bash # 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