ScanOps is an internal authorized-use network/security operations platform built with Django MVT, HTML templates, and HTMX.
- Django 4.2 (MVT)
- HTMX + server-rendered templates
- Gunicorn in Docker
- PostgreSQL in Docker (default runtime database)
- Ensure Docker Engine + Docker Compose plugin are installed.
- Create runtime env file once:
cp .env.example .env-
Update at least:
JTRO_SECRET_KEYSCANOPS_DB_PASSWORDJTRO_ALLOWED_HOSTS(for VPS/public hostnames)
-
Deploy:
./scripts/deploy_and_run.sh upAccess:
http://127.0.0.1:8008/login/http://0.0.0.0:8008/login/
./scripts/deploy_and_run.sh ps
./scripts/deploy_and_run.sh logs
./scripts/deploy_and_run.sh restart
./scripts/deploy_and_run.sh downCreate a backup from your currently configured local DB (.env):
./scripts/deploy_and_run.sh backup-local-dbRestore a SQL backup into Docker PostgreSQL:
./scripts/deploy_and_run.sh restore-db --backup-file dbbackup/migration/<your-backup>.sqlYou can also restore automatically during startup:
./scripts/deploy_and_run.sh up --restore-db --backup-file dbbackup/migration/<your-backup>.sqlYou can still run Django directly:
python manage.py migrate
python manage.py runserver 0.0.0.0:8008- Docker workflow:
DOCKER_README.md - Backup scheduler and restore notes:
BACKUP_README.md
ScanOps includes full account self-service authentication flows:
- Register:
/register/ - Register success:
/register/success/ - Forgot password:
/password-reset/ - Password reset email sent:
/password-reset/done/ - Password reset confirm:
/reset/<uidb64>/<token>/ - Password reset complete:
/reset/done/ - Change password (logged-in):
/password-change/ - Password change done:
/password-change/done/
Registration behavior is environment-driven:
SCANOPS_SELF_REGISTRATION_ENABLED(default:True)SCANOPS_SELF_REGISTRATION_REQUIRES_APPROVAL(default:False)SCANOPS_SELF_REGISTRATION_DEFAULT_ROLE(default:viewer)
By default, new users are created with least-privilege role viewer.
Password reset uses Django's secure token flow and sends emails using environment variables:
EMAIL_BACKENDEMAIL_HOSTEMAIL_PORTEMAIL_USE_TLSEMAIL_USE_SSLEMAIL_HOST_USEREMAIL_HOST_PASSWORDDEFAULT_FROM_EMAIL
For local development, use:
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
With console backend, reset links are printed in app logs/terminal output.
ScanOps includes a public product documentation page:
- URL:
/documentation/ - Public access: available without login from the login page via Read Documentation
- In-app access: available from the sidebar for authenticated users via Read Documentation
The page documents core modules and safe operational workflow without exposing sensitive runtime data.
ScanOps includes two feedback intake routes for users and visitors:
- Suggestions:
/feedback/suggestions/ - Issues:
/feedback/issues/
Suggestions capture improvement ideas. Issues capture operational defects and can include optional evidence attachments (jpg, jpeg, png, webp, mp4, webm, mov, max 25MB).
The New Scan page (/scans/new/) is accessible in two modes:
- Visitors (not logged in): can open the page in public-safe preview mode only. Submission is blocked and they are prompted to sign in/register.
- Authenticated users (all roles): can create scan requests using user-scoped targets and profiles.
The backend enforces ownership filtering on target/profile selection and blocks anonymous POST submission.
ScanOps enforces backend ownership filtering for operational data.
- Scoped roles (
analyst,operator,viewer) can only access their own records. - Global roles (
super_admin,security_admin) can access all operational records. - Isolation is applied across list views, detail views, POST actions, HTMX partial endpoints, and form dropdown querysets.
Ownership is evaluated through centralized visibility helpers in:
apps/ops/services/data_visibility_service.py
The schedule module supports public-safe access:
- Visitors (not logged in): can browse public schedules only (
is_public=True) in read-only mode. - Authenticated users: can create/manage only their own schedules, and can view public schedules.
- Super Admin / Security Admin: can view and manage all schedules.
Sensitive schedule details are restricted in public mode (target/profile details are hidden).
If legacy rows are missing ownership references, run:
./.venv/bin/python manage.py backfill_user_ownershipOptional dry run:
./.venv/bin/python manage.py backfill_user_ownership --dry-runScanOps is intended for internal authorized-use operations only. Do not use this project to scan unauthorized systems or networks.
This project is licensed under the MIT License - see the LICENSE file for details.