Project Index

Crypto Evaluation & Readiness for Infrastructure Adaptation (Post-Quantum)

Overview

Post-Quantum Cryptography Scanner implementing Malaysia's NCII SCAD Framework.

Quick Links

Project Details

Key Features


Last Updated: 2026-07-10

Getting Started

Crypto Evaluation & Readiness for Infrastructure Adaptation (Post-Quantum)

1. First Time Setup (5 minutes)

# Install dependencies
pip install -e .

# Start the dashboard
ceria --verbose dashboard
# Server starts at http://localhost:8080

Once running, open your browser and go to http://localhost:8080/login:

01-login.png First time login screen - no users exist yet

Click "Register" to create your first admin user, then login:

02-login-filled.png Enter your admin credentials

After login, you'll see the main dashboard:

03-dashboard.png Dashboard ready for your first scan

2. Run Your First Scan (5 minutes)

Option A: CLI

# Scan your local network
ceria scan 192.168.1.0/24 --name "My First Scan"

# Or scan a specific subnet
ceria scan 10.0.0.0/24 --verbose

Option B: Web Dashboard (Recommended for First Time)

  1. Open http://localhost:8080/scan or click "New Scan" in the sidebar
  2. You'll see the scan configuration page:
04-scan-page.png Scan configuration with collectors and target settings
  1. Enter your target network (e.g., 192.168.1.0/24)
  2. Enable relevant collectors:
  1. Click "Start Scan"

The scan will run and you'll see progress updates in real-time.

3. View Results (2 minutes)

CLI

# View scan results as table
ceria report --session 1 --format table

# Export to CSV for spreadsheet analysis
ceria report --session 1 --format csv --output scan_results.csv

# Generate PDF report
ceria report --session 1 --format pdf --output scan_report.pdf

Web Dashboard

  1. Go to Scan Detail page (click on the scan from the dashboard)
  2. Expand devices to see findings:
topic-scan-results.png Scan results showing discovered devices and their crypto assets
  1. Click on any device to see detailed analysis:
05-inventory.png Device inventory with risk scores and PQC status
  1. View Reports for visual analytics:
08-report.png Risk heatmap and PQC readiness visualization Congratulations! You've completed your first PQC scan. Continue to the User Manual for detailed feature documentation.

Common Commands Cheat Sheet

TaskCommand
Start dashboardceria dashboard
Scan networkceria scan 192.168.1.0/24
View sessionspqcs sessions
Export CSVceria report --session 1 --format csv --output out.csv
Export PDFceria report --session 1 --format pdf --output out.pdf

Web Dashboard URLs

PageURL
Dashboard/
Start Scan/scan
Scan Results/scan/{id}
All Devices/inventory
Device Detail/inventory/{id}
Certificates/certificates
Settings/settings

→ See User Manual for complete documentation

Visual Overview

See the Screenshots Gallery for visual walkthrough of all pages.


Installation

Requirements

Local Installation

# Clone repository
git clone <repo-url>
cd pqc

# Install with pip
pip install -e .

# Or install development dependencies
pip install -e ".[dev]"

# Verify installation
ceria --version

Environment Setup

Create .env file:

# Required
SECRET_KEY=your-secure-secret-key-here
DATABASE_URL=sqlite:///pqcs.db

# Optional
DASHBOARD_HOST=0.0.0.0
DASHBOARD_PORT=8080
NCII_SECTOR=digital

# SSH Credentials (for remote collectors)
SSH_USERNAME=admin
SSH_PASSWORD=your-ssh-password
SSH_KEY_PATH=/path/to/private/key

# Database Scan Credentials
DB_SCAN_USERNAME=db_user
DB_SCAN_PASSWORD=db_password

NCII Sectors

Available sectors: defense, finance, healthcare, telecom, energy, transport, water, waste, gov, broadcast, digital


→ Next: Quick Start

Overview

What is CERIA?

CERIA discovers cryptographic assets across your network infrastructure and prioritizes them for Post-Quantum Cryptography (PQC) migration.

03-dashboard.png Main dashboard showing network-wide PQC readiness

Why PQC Migration?

Quantum computers will break current cryptographic algorithms:

The Threat Timeline

YearMilestone
2024-2029PQC standards finalized (NIST)
2030Malaysia NCII: Symmetric crypto migration deadline
2035Malaysia NCII: Asymmetric crypto migration deadline
2035+Cryptographically relevant quantum computer expected

Key Features

1. Automated Discovery

04-scan-page.png Configure network scans with multiple collectors

2. Risk-Based Prioritization

topic-risk-dashboard.png SCAD framework ranks devices by migration urgency

3. Certificate Management

topic-certificates-list.png Track all certificates with PQC readiness status

4. Compliance Reporting

Generate reports for:

Who Should Use CERIA?

Supported Platforms

PlatformStatus
Web Dashboard✅ Full support
CLI✅ Full support
Linux✅ Primary
macOS✅ Supported
Windows (WSL)✅ Supported
cPanel Hosting✅ Documented

Next: Architecture

Architecture

System Overview

architecture.png CERIA Architecture Diagram

Data Flow

1. Network Discovery

Target Range → nmap scan → Live hosts → Port detection → Device records

2. Cryptographic Collection

Device + Open Ports → Collector selection → Asset scanning → Crypto assets

3. Risk Analysis

Crypto assets → SCAD scoring → HNDL calculation → Priority ranking

4. Reporting

Prioritized assets → Visualization → Export (PDF/CSV/CBOM)

Collector Types

topic-device-assets.png Example: Device showing multiple crypto asset types
CollectorPortProtocolCredential Required
TLS/SSL443HTTPSNo
SSH22SSHOptional
VPN500/4500IKE/IPSecNo
Database5432/3306VariousYes
OS Crypto-SSHYes
App Config-SSHYes
Cert Store-SSHYes

Database Schema

Core Tables

Relationships

ScanSession (1) ──▶ (N) Device (1) ──▶ (N) CryptoAsset
                                    ──▶ (N) Certificate
                                     ──▶ (1) RiskScore

Next: Scanning Features

User Manual

Crypto Evaluation & Readiness for Infrastructure Adaptation (Post-Quantum)

Post-Quantum Cryptography Scanner — SCAD Framework Implementation

Table of Contents

  1. Overview - What is CERIA and why use it
  2. Architecture - System design and data flow
  3. CLI Usage - Command-line interface
  4. Web Dashboard - Web UI walkthrough
  5. Scanning Features - Network discovery and scanning
  6. Cryptographic Collectors - 7 collector types
  7. Risk Scoring - SCAD framework (7 criteria)
  8. HNDL Calculator - Mosca's Inequality risk
  9. Certificate Management - Certificate analysis
  10. Compliance - MySEAL and NCII
  11. Migration Planning - Step-by-step migration

Overview

CERIA discovers cryptographic assets across your network and prioritizes them for Post-Quantum Cryptography (PQC) migration based on the 7-criterion SCAD Framework.

03-dashboard.png Main dashboard showing network-wide PQC readiness

Quick Start

New user? Start with the Quick Start Guide for a 5-minute introduction.

Key Features

Cryptographic Discovery

7 Collectors discover cryptographic assets across your network:
CollectorDiscoversScreenshot
TLS/SSLHTTPS certificates, cipher suitestopic-scan-results.png
SSHHost keys, algorithms, bannertopic-device-assets.png
VPNIPsec, SSL-VPN configurations06-settings.png
DatabaseCrypto protocols for DB connectionstopic-scan-results.png
OS CryptoOperating system crypto librariestopic-device-assets.png
App ConfigApplication-specific settings06-settings.png
Certificate StoresX.509 certificates with chain analysistopic-certificates-list.png

SCAD Risk Scoring

7-criterion framework with adjustable weights:

topic-settings-weights.png Configure risk scoring weights in Settings

View risk assessment per device:

topic-hndl-device.png Device detail showing HNDL risk and score breakdown

HNDL Risk Calculator

Mosca's Inequality visualization:

07-hndl.png Harvest Now Decrypt Later risk calculator

MySEAL/MyKriptografi Compliance

Malaysia NCII compliance reporting with vendor readiness tracking.

Web Dashboard Features

topic-risk-dashboard.png Priority risk cards and device summary topic-reports.png Advanced visualization and analytics

CLI Interface

Full command-line access for automation and scripting:

topic-cli-dashboard.png CLI dashboard for scripted operations

Technology Stack

Visual Guide

See Screenshots Gallery for visual documentation of all features.


Last Updated: 2026-07-10

Web Dashboard

Access

http://localhost:8080 (local)
https://pqcs.dysfunktion.tech (deployed)

Pages

Public Pages

PageURLDescriptionScreenshot
Login/loginJWT authentication01-login.png

Protected Pages

PageURLDescription
Dashboard/Summary, device table, charts, topology
Scan Control/scanConfigure and run network scans
Scan Detail/scan/{id}Full scan results with expandable devices
Inventory/inventoryAll devices with filters and sorting
Device Detail/inventory/{id}Device tiering, migration tracking, HNDL
Certificates/certificatesCertificate store with PQC assessment
HNDL Detail/hndlHarvest Now Decrypt Later risk analysis
Report/reportVisualization: heatmap, timeline, expiry charts
Settings/settingsCredentials, ports, scoring weights, scheduling
Profile/profileUser management, password change

Dashboard Overview

The main dashboard provides a comprehensive view of your network's PQC readiness:

03-dashboard.png Main dashboard with device summary, risk distribution, and PQC readiness gauge

Scan Configuration

Configure and start network scans from the Scan Control page:

04-scan-page.png Scan configuration - select collectors, set target range, and start scanning

Device Management

View all discovered devices in the Inventory:

05-inventory.png Device inventory with filtering, sorting, and risk scores

Device Detail View

Deep dive into individual device analysis:

topic-hndl-device.png Device detail showing HNDL risk, crypto assets, and score breakdown topic-device-assets.png Individual cryptographic assets per device

Certificate Management

Browse discovered certificates with PQC status:

topic-certificates-list.png Certificate store with PQC assessment and expiry tracking

Reports & Visualization

View risk heatmaps and compliance reports:

08-report.png Risk heatmap, certificate expiry timeline, and PQC readiness charts topic-reports.png Detailed analytics and reporting visualizations

HNDL Risk Analysis

Access Mosca's Inequality calculator:

07-hndl.png Harvest Now Decrypt Later risk analysis dashboard

Settings & Configuration

Configure scanning parameters and scoring weights:

06-settings.png Application settings with SSH credentials, custom ports, and auto-scan scheduling topic-settings-weights.png SCAD risk scoring weights configuration

Risk Priority Dashboard

Monitor critical devices requiring immediate attention:

topic-risk-dashboard.png Risk priority cards highlighting CRITICAL and HIGH priority devices

Navigation

Use the sidebar menu to navigate between pages. The dashboard shows:


Screenshots

See detailed screenshots in Screenshots Gallery

Quick preview:


CLI Usage

Global Options

pqcs [OPTIONS] COMMAND [ARGS]...

Options:
  --db-url TEXT       Database URL (env: DATABASE_URL)
  --verbose, -v       Enable debug logging
  --version           Show version
  --help              Show help

Commands

topic-cli-dashboard.png CLI dashboard view when running ceria dashboard

1. Scan Network

# Basic scan
ceria scan 192.168.1.0/24

# Named scan
ceria scan 192.168.1.0/24 --name "Production Network Scan"

# Specific collectors only
ceria scan 192.168.1.0/24 --collectors tls,ssh,vpn

# All available collectors
ceria scan 192.168.1.0/24 --collectors tls,ssh,vpn,db,os_crypto,app_config,cert_store
Available Collectors:

Sample scan output in terminal:

[2026-07-10 10:00:01] INFO: Starting scan: My First Scan
[2026-07-10 10:00:05] INFO: Port scan: Found 24 hosts
[2026-07-10 10:00:12] INFO: TLS collector: 15 certificates collected
[2026-07-10 10:00:18] INFO: SSH collector: 8 SSH servers found
[2026-07-10 10:00:25] INFO: Cert collector: 22 certificates discovered
[2026-07-10 10:00:30] INFO: Scan completed in 29.4s

2. Network Discovery

# Discover hosts without full crypto scan
pqcs discover 192.168.1.0/24 --ports 22,443,8443

3. Generate Reports

# Table format (console)
ceria report --session 1 --format table

# Filter by priority
ceria report --session 1 --priority CRITICAL --format table

# Export to CSV
ceria report --session 1 --format csv --output report.csv

# Export to JSON
ceria report --session 1 --format json --output report.json

# Export to PDF
ceria report --session 1 --format pdf --output report.pdf

# Export CBOM (CycloneDX)
ceria report --session 1 --format cbom --output cbom.json

Sample table output:

IP Address    | Hostname    | Priority  | Algorithms
--------------+-------------+-----------+------------------
192.168.1.10  | web-server  | CRITICAL  | RSA-1024 
192.168.1.20  | mail-server | HIGH      | RSA-2048, SHA-1
192.168.1.30  | db-server   | MEDIUM    | RSA-2048

4. List Sessions

pqcs sessions

Output:

ID  | Name                    | Status     | Devices | Started
----+-------------------------+------------+---------+-------------------
1   | My First Scan           | completed  | 24      | 2026-07-10 10:00
2   | Production Network Scan | running    | 12      | 2026-07-10 11:30

5. Launch Dashboard

# Default port 8080
ceria dashboard

# Custom port
ceria dashboard --port 3000 --host 127.0.0.1

Opens web interface at http://localhost:8080 (or your specified port).


Scanning Features

Network Discovery

CERIA uses nmap for initial host discovery:

Discovery Methods

Port Scanning

Default ports include:

Custom Ports

Add custom ports in Settings:

Format: ports or ranges
Example: 9000,9001,9002-9010,10000

06-settings.png Configure custom ports in Settings

Scanning Modes

Quick Scan

Deep Scan

Credential-Based Scan

Requires SSH credentials for: topic-scan-results.png Scan results showing discovered devices

Scan Scheduling

Automated Re-scans

  1. Go to Settings
  2. Enable Automatic Re-scan
  3. Select frequency:

Drift Detection

Compares scan results over time:

Alerts for significant changes.

Scan Performance

Network Size Recommendations

Network SizeTimeoutConcurrent Hosts
/24 (254)5 min50
/23 (510)10 min50
/22 (1,022)20 min50
/16 (65k)60 min25

Tune via Settings page.


See also: Cryptographic Collectors

Risk Scoring

The SCAD (System Cryptographic Asset Demand) Framework uses 7 criteria with adjustable weights (must sum to 100%).

Dashboard View

topic-risk-dashboard.png Risk priority distribution on main dashboard

Configuring Weights

topic-settings-weights.png Adjust SCAD framework weights in Settings page

Criteria Descriptions

CriterionWeightDescription
Algorithm Vulnerability25%Known vulnerabilities in current algorithms
Data Lifespan20%How long data must remain confidential
Key Size15%RSA key size or ECC curve strength
System Criticality15%Importance to business operations
Legacy Status10%End-of-life systems harder to migrate
Third Party Dependency10%External dependencies affecting migration
NCII Sector5%Malaysia NCII sector classification

Priority Levels

Score RangePriorityAction
80-100CRITICALImmediate migration required
60-79HIGHPlan migration within 6 months
40-59MEDIUMPlan migration within 12 months
20-39LOWPlan migration within 24 months
0-19MINIMALTrack for future migration

Adjusting Weights

  1. Go to Settings page
  2. Modify criterion weights (must sum to 100%)
  3. Click Save
  4. Re-run scan to apply new weights

Industry-Specific Configurations

Financial Services

Algorithm Vulnerability: 30%
Data Lifespan: 25%
System Criticality: 20%
Key Size: 10%
Legacy Status: 5%
Third Party: 5%
NCII Sector: 5%

Healthcare

Data Lifespan: 35%
Algorithm Vulnerability: 25%
System Criticality: 15%
Key Size: 10%
Legacy Status: 5%
Third Party: 5%
NCII Sector: 5%

See Screenshots Gallery for more views.


HNDL Calculator

HNDL Overview Dashboard

07-hndl.png Harvest Now Decrypt Later summary on dashboard

Mosca's Inequality

Implements Mosca's Inequality: X + Y > Z

Where:

Device-Level HNDL Analysis

topic-hndl-device.png Mosca's Inequality calculation per device with X+Y vs Z breakdown

Risk Levels

X+Y vs ZRisk LevelRecommended Action
X+Y >> ZCRITICALImmediate migration
X+Y > ZHIGHBegin migration now
X+Y ≈ ZMODERATEPlan within 6 months
X+Y < ZLOWPlan within 12 months
X+Y << ZMINIMALTrack and monitor

Setting Data Retention

  1. Go to Inventory → Select Device
  2. Click Edit on tiering section
  3. Set Data Retention (Years)
  4. Save changes

HNDL risk auto-recalculates when you update the value.

Examples

Critical Risk Example

Data Retention: 15 years (medical records)
Migration Time: 2 years
Quantum Timeline: 10 years (2035 estimate)

X + Y = 17 > Z = 10
Result: CRITICAL - Data needs protection beyond quantum capability

Low Risk Example

Data Retention: 1 year (temporary cache)
Migration Time: 2 years
Quantum Timeline: 10 years

X + Y = 3 < Z = 10
Result: MINIMAL - Data expires before quantum threat

See Screenshots Gallery for more visuals.


Certificate Management

Certificate Discovery

Automatically extracts and stores X.509 certificates from:

topic-certificates-list.png Certificate inventory with PQC status

Certificate Analysis

For each certificate, CERIA analyzes:

Basic Properties

Algorithm Assessment

AlgorithmPQC Status
RSA-2048+⚠️ Vulnerable
ECDSA P-256⚠️ Vulnerable
ECDSA P-384⚠️ Vulnerable
Ed25519✅ PQC Ready
Ed448✅ PQC Ready
ML-DSA✅ PQC Ready
ML-KEM✅ PQC Ready

Signature Analysis

Chain Analysis

Root CA (ISRG Root X1)
  └── Intermediate (R3)
       └── Leaf (example.com)

Each level assessed for:

06-settings.png Certificate chain detail view

CA Roadmap Database

Tracks vendor PQC transition plans:

CA VendorCurrent StatusPQC ETA
DigiCertTransitioning2025
Let's EncryptTransitioning2025
SectigoTransitioning2025
GlobalSignPlanning2026
AWS ACMReadyAvailable
Azure KVReadyAvailable

Certificate Actions

Download

Expiry Alerts

Automatic warnings for certificates expiring within:

PQC Assessment Report

Generates report showing:
See Screenshots Gallery for certificate views

Compliance

MySEAL Compliance

MySEAL (Malaysia Security Evaluation and Assurance Lab) approved algorithms for government and critical infrastructure.

MySEAL Approved Algorithms

Encryption

Digital Signatures

Key Exchange

MySEAL Compliance Check

CERIA checks devices against MySEAL approved algorithms and flags non-compliant crypto.

MyKriptografi NCII Framework

Malaysia's National Critical Information Infrastructure (NCII) requirements for Post-Quantum Cryptography.

PQC Transition Timeline

PhaseDeadlineRequirements
Phase 12030Symmetric crypto migration
Phase 22035Asymmetric crypto migration

NCII Sectors

Priority weighting based on sector:

SectorWeight
DefenseCritical
FinanceCritical
HealthcareCritical
TelecomHigh
EnergyHigh
GovernmentHigh
Digital ServicesMedium

Compliance Report

Generated report includes:

topic-reports.png Compliance visualization in Reports

NACSA Alignment

National Cyber Security Agency (NACSA) guidelines:

  1. Crypto Inventory ✅ - Automated discovery
  2. Risk Assessment ✅ - SCAD scoring
  3. Migration Plan ✅ - Priority-based roadmap
  4. Progress Tracking ✅ - Scheduled re-scans

Export Formats

CBOM (CycloneDX)

Cryptographic Bill of Materials in standard format for:

NACSA XML (Future)

Direct NACSA reporting format support planned.
See also: Risk Scoring for compliance weighting

Migration Planning

Migration Advisor

CERIA analyzes crypto patterns and generates step-by-step migration plans.

Detected Patterns

Common cryptographic configurations requiring migration:

PatternCurrent StateTarget State
rsa-2048-tlsRSA-2048 TLSML-KEM/ML-DSA or X25519/Ed25519
rsa-4096-tlsRSA-4096 TLSPQC algorithms
ecdsa-p256-tlsECDSA P-256ML-DSA-65 or Ed25519
ssh-rsa-deprecatedssh-rsarsa-sha2-512 or Ed25519
ssh-ecdsaECDSA host keysEd25519 host keys
vpn-ikev2-rsaIKEv2 with RSAIKEv2 with ECDSA or PQC
topic-device-assets.png Device showing detected crypto patterns

Migration Plan Structure

Each migration plan includes:

1. Current State

2. Target State

3. Migration Steps

Numbered procedures:
1. Generate new key pair
2. Create CSR with new algorithm
3. Obtain PQC-ready certificate
4. Configure service to use new cert
5. Test connectivity
6. Schedule cutover

4. Caveats & Risks

Known issues:

5. Rollback Procedure

How to revert if issues occur.

6. Resources

Dependency Graph

Visualize migration dependencies:

Root CA must migrate first
  → Intermediate CAs
    → Leaf certificates
      → Device configurations
topic-reports.png Migration critical path visualization

Critical Path Analysis

Identifies the order in which to migrate:

  1. Root CAs (blocks everything)
  2. Intermediate CAs (blocks leaf certs)
  3. High-risk devices (SCAD priority)
  4. Remaining devices (by tier)

Migration Tracking

Per-device migration status:

StatusMeaning
Not StartedNo action taken
In PlanningMigration designed
TestingIn test environment
ScheduledProduction date set
CompleteMigrated to PQC
BlockedDependency pending

Update status in device detail page.

Migration Timeline

Recommended timeline based on HNDL risk:

HNDL RiskMigration Window
CRITICALImmediate - 3 months
HIGH3 - 6 months
MEDIUM6 - 12 months
LOW12 - 24 months
MINIMALTrack only

See HNDL Calculator for risk assessment

API Reference

Authentication

Login

POST /api/v1/auth/login
Content-Type: application/json

{
  "username": "string",
  "password": "string"
}
Response:
{
  "status": "ok",
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": {
    "id": 1,
    "username": "admin",
    "role": "admin"
  }
}

All API endpoints require a JWT token except /auth/login and /auth/register.

Endpoints Overview

Scans

Devices

Certificates

Analytics

Exports

Python Example

import requests

BASE_URL = "https://pqcs.dysfunktion.tech/api/v1"

# Login
resp = requests.post(f"{BASE_URL}/auth/login", json={
    "username": "admin",
    "password": "password"
})
token = resp.json()["token"]
headers = {"Authorization": f"Bearer {token}"}

# Start scan
resp = requests.post(
    f"{BASE_URL}/scans/start",
    headers=headers,
    json={"target_range": "10.0.0.0/24"}
)
session_id = resp.json()["session_id"]

# Export PDF
pdf = requests.get(
    f"{BASE_URL}/export/{session_id}?format=pdf",
    headers=headers
)
open("report.pdf", "wb").write(pdf.content)

Error Codes

CodeMeaning
400Bad Request
401Unauthorized
403Forbidden
404Not Found
409Conflict
422Unprocessable Entity
429Rate Limited
500Server Error

Administration Guide

Complete guide for administering CERIA in production environments.


User Management

User Roles

06-settings.png User configuration and settings access
RolePermissions
adminFull access: scans, reports, settings, user management
userCan run scans, view reports, modify device data
viewerRead-only: view scans, reports, cannot modify data

Creating Users

Via Web Interface

  1. Login as admin
  2. Go to ProfileUser Management
  3. Click Add User
  4. Fill in:
  1. Save

Via CLI Script

import bcrypt
from pqcs.db import init_db, User
from pqcs.config import AppConfig

config = AppConfig()
db = init_db(config.database.url)

# Create user
pw_hash = bcrypt.hashpw(b"newpassword", bcrypt.gensalt())
user = User(
    username="newuser",
    password_hash=pw_hash.decode(),
    role="user",
    is_active=True
)
db.add(user)
db.commit()
print(f"Created: {user.username}")

Disabling Users

  1. Go to ProfileUser Management
  2. Find the user
  3. Toggle Active switch to OFF
  4. User immediately loses access

Password Reset

# Reset via Python
python << 'EOF'
import bcrypt
from pqcs.db import init_db, User
from pqcs.config import AppConfig

config = AppConfig()
db = init_db(config.database.url)

user = db.query(User).filter_by(username="user_to_reset").first()
if user:
    new_pw = bcrypt.hashpw(b"temppassword123", bcrypt.gensalt())
    user.password_hash = new_pw.decode()
    db.commit()
    print("Password reset. User must change on next login.")
EOF

Scan Management

Scheduling Automated Scans

06-settings.png Settings page with scan configuration
  1. Go to Settings page
  2. Under Automatic Re-scan section:
  1. Save settings

Managing Running Scans

Check Scan Status

# Via CLI
pqcs sessions

# Via API
curl http://localhost:8080/api/v1/scans/1/status \
  -H "Authorization: Bearer <token>"
topic-scan-results.png Scan results showing completed devices

Stop a Running Scan

  1. Go to Scan Detail page
  2. Click Stop Scan button
  3. Or via API:
curl -X POST http://localhost:8080/api/v1/scans/1/stop \
  -H "Authorization: Bearer <token>"

Delete Old Scans

# Delete scans older than 90 days
from pqcs.db import init_db, ScanSession
from pqcs.config import AppConfig
from datetime import datetime, timedelta

config = AppConfig()
db = init_db(config.database.url)

cutoff = datetime.utcnow() - timedelta(days=90)
old_scans = db.query(ScanSession).filter(
    ScanSession.finished_at < cutoff
).all()

for scan in old_scans:
    print(f"Deleting: {scan.name}")
    db.delete(scan)

db.commit()
print(f"Deleted {len(old_scans)} scans")

Scan Optimization

06-settings.png Configure scan timeouts and rate limits

Custom Ports

Add custom ports in Settings:

Format: individual ports or ranges
Example: 9000,9001,9002-9010,10000

Scan Timeouts by Network Size

Network SizeRecommended Timeout
/24 (254 hosts)300 seconds (5 min)
/23 (510 hosts)600 seconds (10 min)
/22 (1022 hosts)1200 seconds (20 min)
/16 (65534 hosts)3600 seconds (60 min)

Database Administration

Database Location

Default SQLite database paths:

Direct Database Access

# Connect via SQLite CLI
sqlite3 /home2/yusricom/db/pqcs.db

# Common queries
.tables
.schema devices
SELECT COUNT(*) FROM devices;
SELECT * FROM scan_sessions ORDER BY started_at DESC LIMIT 5;
.quit

Database Maintenance

topic-scan-results.png Monitor database growth with regular maintenance

Vacuum (Reclaim Space)

# Removes deleted data and shrinks file
sqlite3 /home2/yusricom/db/pqcs.db "VACUUM;"

Analyze (Performance)

# Update query planner statistics
sqlite3 /home2/yusricom/db/pqcs.db "ANALYZE;"

Check Integrity

# Verify database is not corrupted
sqlite3 /home2/yusricom/db/pqcs.db "PRAGMA integrity_check;"

PostgreSQL Migration (Advanced)

# Install PostgreSQL adapter
pip install psycopg2-binary

# Export SQLite
sqlite3 pqcs.db .dump > dump.sql

# Import to PostgreSQL
psql -U postgres -d pqcs < dump.sql

# Update connection string
export DATABASE_URL="postgresql://user:pass@localhost/pqcs"

Configuration Management

Settings Storage

Settings stored in database table settings:

{
    "scan_rate_limit": "5",
    "default_scan_timeout": "300",
    "nmap_args": "-sV -O -sS",
    "ssh_username": "",
    "custom_ports": "",
}

Updating Settings

Via API

# Update single setting
curl -X PUT http://localhost:8080/api/v1/settings/scan_rate_limit \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"value": "10"}'

# Get all settings
curl http://localhost:8080/api/v1/settings \
  -H "Authorization: Bearer <token>"

Via Environment Variables

Priority order (highest first):

  1. Environment variables (.env)
  2. Database settings
  3. Default values


Risk Scoring Configuration

topic-settings-weights.png Adjust SCAD framework criterion weights

Understanding SCAD Weights

Default configuration (must sum to 100%):

CriterionDefaultWhen to Increase
Algorithm Vulnerability25%Known CVEs, weak algorithms
Data Lifespan20%Long-term sensitive data
Key Size15%Large RSA keys (>2048)
System Criticality15%Business-critical systems
Legacy Status10%EOL systems
Third Party Dependency10%Vendor-managed crypto
NCII Sector5%Regulated industries

Recalculating Scores

After changing weights, rescore existing devices:

from pqcs.scoring.engine import ScoringEngine
from pqcs.db import init_db, Device
from pqcs.config import AppConfig

config = AppConfig()
db = init_db(config.database.url)
scoring = ScoringEngine(config.scoring, config.ncii_sector)

devices = db.query(Device).all()
for device in devices:
    score = scoring.calculate(device, device.assets)
    # Update in database
    print(f"{device.ip_address}: {score.overall_score}")

db.commit()

Monitoring & Alerts

Health Check Endpoint

# Basic health check
curl http://localhost:8080/health

# Expected response:
{
  "status": "ok",
  "timestamp": "2026-07-10T12:00:00",
  "version": "0.1.0",
  "database": "connected"
}
topic-risk-dashboard.png Monitor overall system health via dashboard

Log Monitoring

PatternMeaningAction
scan completedNormalNone
collector errorScan issueCheck collector config
database errorDB issueCheck connectivity
authentication failedLogin attemptReview if suspicious
rate limit exceededToo many scansAdjust thresholds

Log Rotation

Add to /etc/logrotate.d/pqcs:

/opt/pqcs/logs/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 pqcs pqcs
}


Maintenance Tasks

Daily Tasks

Weekly Tasks

topic-certificates-list.png Review certificate expiry weekly

Monthly Tasks

Quarterly Tasks


Backup & Recovery

Automated Daily Backup

#!/bin/bash
# /opt/pqcs/backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/pqcs"
SOURCE_DB="/home2/yusricom/db/pqcs.db"

# Create backup dir
mkdir -p $BACKUP_DIR

# Backup database
cp $SOURCE_DB "$BACKUP_DIR/pqcs_$DATE.db"

# Compress
gzip "$BACKUP_DIR/pqcs_$DATE.db"

# Backup configuration
tar czf "$BACKUP_DIR/config_$DATE.tar.gz" \
  /opt/pqcs/.env

# Upload to S3 (optional)
# aws s3 cp "$BACKUP_DIR/pqcs_$DATE.db.gz" s3://pqcs-backups/

# Keep only last 30 days
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete

echo "Backup completed: pqcs_$DATE.db.gz"

Crontab entry:

0 2 * * * /opt/pqcs/backup.sh >> /var/log/pqcs/backup.log 2>&1

Recovery Procedures

Scenario 1: Database Corruption

# Stop application
sudo systemctl stop pqcs

# Restore from backup
sudo cp /backups/pqcs/pqcs_20260701_020000.db \
  /home2/yusricom/db/pqcs.db
sudo chown yusricom:yusricom /home2/yusricom/db/pqcs.db

# Restart
sudo systemctl start pqcs

Scenario 2: Complete Server Failure

# On new server

# 1. Install CERIA
pip install -e .

# 2. Restore database
mkdir -p /home2/yusricom/db
cp /backups/pqcs/pqcs_latest.db /home2/yusricom/db/pqcs.db

# 3. Restore config
cp /backups/pqcs/.env /opt/pqcs/.env

# 4. Set permissions
chown -R pqcs:pqcs /home2/yusricom/db /opt/pqcs

# 5. Start service
systemctl start pqcs

Troubleshooting

Database Locked

# Find and kill blocking process
fuser /home2/yusricom/db/pqcs.db

# Or wait for timeout

Scan Stuck

# Check if nmap is running
ps aux | grep nmap

# Kill hanging nmap
sudo pkill -9 nmap

High Memory Usage

# Limit concurrent hosts
export MAX_CONCURRENT_HOSTS=25

# Or use smaller subnets
ceria scan 192.168.1.0/25  # instead of /24

Cannot Access Dashboard

SymptomSolution
403 ForbiddenCheck file permissions
500 ErrorCheck Passenger/Application logs
Not loadingVerify firewall/port settings
Cookie errorClear browser cache

Related Documentation


Last Updated: 2026-07-10

Deployment Guide

Complete guide for deploying CERIA in production environments.


cPanel Shared Hosting (Production) ⭐

This is the current deployment method for https://pqcs.dysfunktion.tech.

Prerequisites

Files Required

FilePurpose
passenger_wsgi.pyWSGI entry point for Passenger
requirements.txtPython dependencies
pqcs/Application code directory
.htaccessApache configuration

Step 1: Upload Files

Upload project files to:

/home/username/public_html/pqcs.example.com/

Directory structure:
pqcs.example.com/
├── passenger_wsgi.py
├── requirements.txt
├── .htaccess
└── pqcs/
    ├── __init__.py
    ├── web/
    ├── scanner/
    └── ...

Step 2: Configure .htaccess

Create .htaccess in application root:

PassengerPython /home/username/virtualenv/pqcs/3.11/bin/python
PassengerAppRoot /home/username/public_html/pqcs.example.com
PassengerAppType wsgi
PassengerStartupFile passenger_wsgi.py

Step 3: Setup Python App in cPanel

  1. Login to cPanel
  2. Go to Setup Python App (usually under Software section)
  3. Click Create Application
topic-cli-dashboard.png The cPanel interface for creating a Python application
  1. Configure the following settings:
  1. Click Create

Your app should now show in cPanel as "Running":

03-dashboard.png Successfully deployed application running on cPanel

Step 4: Install Dependencies

SSH into server:

cd /home/username/public_html/pqcs.example.com

# Activate virtual environment
source /home/username/virtualenv/pqcs/3.11/bin/activate

# Install dependencies
pip install -r requirements.txt

# Create database directory outside web root
mkdir -p /home/username/db
chmod 755 /home/username/db

Step 5: Initialize Database

# Run in virtual environment
python << 'EOF'
import sys
sys.path.insert(0, '/home/username/public_html/pqcs.example.com')
from pqcs.db import init_db
init_db('sqlite:////home/username/db/pqcs.db')
print("Database initialized")
EOF

Step 6: Environment Variables

In cPanel > Setup Python App > Environment Variables, add:

VariableValueDescription
SECRET_KEYopenssl rand -hex 32JWT signing key
DATABASE_URLsqlite:////home/username/db/pqcs.dbDatabase path

Step 7: Restart Application

cd /home/username/public_html/pqcs.example.com
mkdir -p tmp
touch tmp/restart.txt

Step 8: Verify Deployment

Visit https://pqcs.example.com and you should see:

01-login.png Login page - confirmation that the app is successfully deployed

Login with your admin credentials (default: admin/admin on first run):

02-login-filled.png Enter credentials to access the dashboard

After login, verify the dashboard loads correctly:

03-dashboard.png Dashboard shows device summary and risk distribution

Test the Settings page to ensure database is working:

06-settings.png Settings page confirms database connection is active

Check the Inventory page shows device management:

05-inventory.png Device inventory loads successfully

If all pages load without errors, your deployment is complete! 🎉

Troubleshooting cPanel

If you encounter issues during deployment, check the following:

IssueSolutionVisual Indicator
403 ForbiddenCheck permissions: chmod 644 .htaccess passenger_wsgi.pyBrowser shows "403 Forbidden"
500 Internal ErrorCheck Passenger log in cPanel > LogsBrowser shows "500 Internal Server Error"
Application not foundVerify passenger_wsgi.py exists and application variable is setcPanel shows app as "Stopped"
Database not foundUse absolute path in DATABASE_URL"OperationalError: unable to open database file" in logs
Import errorsRun pip install in correct virtualenv"ModuleNotFoundError" in Passenger log

Common Deployment Errors

Error: "Incomplete response received from application" Error: "unable to open database file"
# Create database directory outside web root
mkdir -p /home/username/db
chmod 755 /home/username/db
# Update DATABASE_URL to:
# sqlite:////home/username/db/pqcs.db
Error: Login fails with 422 WSGI Issues If you see "Application object is not a WSGI callable": Restart After Changes
# Always restart the app after modifying Python files
cd /home/username/public_html/pqcs.example.com
touch tmp/restart.txt

If problems persist, check the detailed logs in cPanel under Logs > Error Logs.

passenger_wsgi.py Template

#!/usr/bin/env python3
import os
import sys

APP_ROOT = "/home/username/public_html/pqcs.example.com"
sys.path.insert(0, APP_ROOT)
os.chdir(APP_ROOT)

# Use database outside web root
DB_PATH = "/home/username/db/pqcs.db"
os.environ['DATABASE_URL'] = f'sqlite:///{DB_PATH}'

from pqcs.web.app import create_app
from pqcs.config import AppConfig

config = AppConfig()
config.database.url = f'sqlite:///{DB_PATH}'

asgi_app = create_app(config)

# WSGI wrapper for FastAPI
import asyncio

class WSGIWrapper:
    def __init__(self, asgi_app):
        self.asgi_app = asgi_app

    def __call__(self, environ, start_response):
        scope = {
            'type': 'http',
            'asgi': {'version': '3.0'},
            'method': environ.get('REQUEST_METHOD', 'GET'),
            'scheme': environ.get('wsgi.url_scheme', 'https'),
            'path': environ.get('PATH_INFO', '/'),
            'query_string': environ.get('QUERY_STRING', '').encode(),
            'headers': [],
            'server': (environ.get('SERVER_NAME', 'localhost'), 
                      int(environ.get('SERVER_PORT', 443))),
            'client': (environ.get('REMOTE_ADDR', '127.0.0.1'), 
                      int(environ.get('REMOTE_PORT', 0) or 0)),
        }
        
        body = b''
        if 'wsgi.input' in environ:
            cl = environ.get('CONTENT_LENGTH')
            if cl:
                try:
                    body = environ['wsgi.input'].read(int(cl))
                except:
                    pass
        
        messages = []
        
        async def receive():
            return {'type': 'http.request', 'body': body, 'more_body': False}
        
        async def send(message):
            messages.append(message)
        
        loop = asyncio.new_event_loop()
        try:
            asyncio.set_event_loop(loop)
            loop.run_until_complete(self.asgi_app(scope, receive, send))
            
            start_msg = next(m for m in messages if m['type'] == 'http.response.start')
            status = f"{start_msg['status']}"
            headers = [(k.decode() if isinstance(k, bytes) else k,
                       v.decode() if isinstance(v, bytes) else v) 
                      for k, v in start_msg.get('headers', [])]
            start_response(status, headers)
            
            body_parts = [m.get('body', b'') for m in messages 
                         if m['type'] == 'http.response.body']
            return body_parts if body_parts else [b'']
        finally:
            loop.close()

application = WSGIWrapper(asgi_app)

Docker Deployment

Dockerfile

FROM python:3.11-slim

# Install system dependencies
RUN apt-get update && apt-get install -y \
    nmap libpq-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
RUN pip install -e .

RUN mkdir -p /data /logs

ENV DATABASE_URL=sqlite:////data/pqcs.db
ENV DASHBOARD_HOST=0.0.0.0
ENV DASHBOARD_PORT=8080
ENV PYTHONUNBUFFERED=1

EXPOSE 8080

CMD ["pqcs", "dashboard", "--host", "0.0.0.0", "--port", "8080"]

docker-compose.yml

version: '3.8'

services:
  pqcs:
    build: .
    container_name: pqcs
    ports:
      - "8080:8080"
    volumes:
      - ./data:/data
      - ./logs:/logs
    environment:
      - SECRET_KEY=${SECRET_KEY}
      - DATABASE_URL=sqlite:////data/pqcs.db
    restart: unless-stopped

Build and Run

# Generate a secure secret key
export SECRET_KEY=$(openssl rand -hex 32)

# Create directories for persistent data
mkdir -p data logs

# Build and start the container
docker-compose up -d --build

# Verify the container is running
docker ps | grep pqcs

# View application logs
docker-compose logs -f pqcs

Expected output after successful startup:

[INFO] Starting CERIA Web Dashboard
[INFO] Database initialized
[INFO] Uvicorn running on http://0.0.0.0:8080

Access the application at http://localhost:8080. You should see the login page similar to the production deployment:

Note: The Docker deployment uses the same codebase as cPanel, so all features (dashboard, scans, reports) work identically.

Stopping the Container

docker-compose down

# To also remove volumes (WARNING: deletes all data)
docker-compose down -v

Ubuntu Server Deployment

System Requirements

Installation

# Install system dependencies
sudo apt-get update
sudo apt-get install -y python3 python3-pip python3-venv nmap openssl

# Create dedicated user for security
sudo useradd -r -s /bin/false pqcs

# Create directory structure
sudo mkdir -p /opt/pqcs /var/lib/pqcs /var/log/pqcs
sudo chown -R pqcs:pqcs /opt/pqcs /var/lib/pqcs /var/log/pqcs

# Clone and setup application
# Option A: Clone from repository
sudo -u pqcs git clone https://github.com/yourusername/pqcs.git /opt/pqcs

# Option B: Upload files via SCP/FTP
# scp -r /local/pqcs/* pqcs@server:/opt/pqcs/

# Setup Python virtual environment
cd /opt/pqcs
sudo -u pqcs python3 -m venv venv
sudo -u pqcs venv/bin/pip install --upgrade pip
sudo -u pqcs venv/bin/pip install -e .

# Create environment configuration
sudo -u pqcs tee /opt/pqcs/.env << 'EOF'
SECRET_KEY=$(openssl rand -hex 32)
DATABASE_URL=sqlite:////var/lib/pqcs/pqcs.db
DASHBOARD_HOST=0.0.0.0
DASHBOARD_PORT=8080
EOF

# Initialize the database
sudo -u pqcs /opt/pqcs/venv/bin/python -c "
import sys
sys.path.insert(0, '/opt/pqcs')
from pqcs.db import init_db
from pqcs.config import AppConfig
config = AppConfig()
init_db(config.database.url)
print('Database initialized successfully')
"

# Set proper permissions
chmod 600 /opt/pqcs/.env
chmod 750 /var/lib/pqcs
chmod 644 /var/lib/pqcs/pqcs.db 2>/dev/null || true

Create systemd service file:

sudo tee /etc/systemd/system/pqcs.service << 'EOF'
[Unit]
Description=CERIA Dashboard
After=network.target

[Service]
Type=simple
User=pqcs
Group=pqcs
WorkingDirectory=/opt/pqcs
Environment="PATH=/opt/pqcs/venv/bin"
EnvironmentFile=-/opt/pqcs/.env
ExecStart=/opt/pqcs/venv/bin/uvicorn pqcs.web.app:create_app --host 0.0.0.0 --port 8080
Restart=always
RestartSec=10
StandardOutput=append:/var/log/pqcs/app.log
StandardError=append:/var/log/pqcs/error.log

[Install]
WantedBy=multi-user.target
EOF

Enable and start the service:

# Reload systemd to recognize new service
sudo systemctl daemon-reload

# Enable service to start on boot
sudo systemctl enable pqcs

# Start the service
sudo systemctl start pqcs

# Check status
sudo systemctl status pqcs

You should see output like:

● pqcs.service - CERIA Dashboard
     Loaded: loaded (/etc/systemd/system/pqcs.service; enabled)
     Active: active (running) since Fri 2026-07-10 10:00:00 UTC
     Main PID: 12345 (uvicorn)

Systemd Service

Create /etc/systemd/system/pqcs.service:

[Unit]
Description=CERIA Dashboard
After=network.target

[Service]
Type=simple
User=pqcs
Group=pqcs
WorkingDirectory=/opt/pqcs
Environment="PATH=/opt/pqcs/venv/bin"
EnvironmentFile=/opt/pqcs/.env
ExecStart=/opt/pqcs/venv/bin/uvicorn pqcs.web.app:create_app --host 0.0.0.0 --port 8080
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Start service:

sudo systemctl daemon-reload
sudo systemctl enable pqcs
sudo systemctl start pqcs

Nginx Reverse Proxy

server {
    listen 80;
    server_name pqcs.example.com;
    return 301 https://$server_name$request_uri;
}

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

    ssl_certificate /etc/letsencrypt/live/pqcs.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pqcs.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        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;
    }

    location /static {
        alias /opt/pqcs/pqcs/web/static;
    }
}

Enable:

sudo ln -s /etc/nginx/sites-available/pqcs /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx


SSL/TLS Setup

Let's Encrypt (certbot)

# Install certbot
sudo apt-get install certbot python3-certbot-nginx

# Obtain certificate
sudo certbot --nginx -d pqcs.example.com

# Auto-renewal test
sudo certbot renew --dry-run

Security Hardening

File Permissions

# Database
chmod 600 /var/lib/pqcs/pqcs.db
chown pqcs:pqcs /var/lib/pqcs/pqcs.db

# Application
chmod 755 /opt/pqcs
chmod 644 /opt/pqcs/.env
chown -R pqcs:pqcs /opt/pqcs

Firewall Rules

# Allow only HTTPS
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 443/tcp
sudo ufw enable

Current Deployment

Current Deployment Reference

The official CERIA instance is deployed at:

Live URL: https://pqcs.dysfunktion.tech

Deployment Specifications

ComponentConfiguration
PlatformcPanel Shared Hosting
Python Version3.11
DatabaseSQLite at /home2/yusricom/db/pqcs.db
WSGI HandlerCustom FastAPI-to-WSGI wrapper
Web ServerApache with Passenger
SSLLet's Encrypt (AutoSSL)
Status✅ Production Ready

Live Application Screenshots

Login Screen

01-login.png Production login page at pqcs.dysfunktion.tech

Main Dashboard

03-dashboard.png Dashboard showing device summary, risk distribution, and priority devices

Scan Configuration

04-scan-page.png Scan configuration page for setting target ranges and collectors

Device Inventory

05-inventory.png Device inventory with filtering and risk score display

System Settings

06-settings.png Settings page for SSH credentials, ports, and scanning parameters

Risk Analysis

07-hndl.png Harvest Now Decrypt Later (HNDL) risk calculator

Reports

08-report.png Reports and visualization page with risk heatmaps

Deployment Validation Checklist

Use this checklist to verify your deployment is working correctly:

FeatureExpected ResultScreenshot
Login page loadsNo errors, form visible01-login.png
Authentication worksRedirects to dashboard02-login-filled.png
Dashboard displaysStats visible, no errors03-dashboard.png
Settings accessibleForm loads, values save06-settings.png
Inventory shows devicesDevice list loads05-inventory.png

If all checks pass, your deployment matches the production instance! 🎉

Related Documentation


Last Updated: 2026-07-10

Cryptographic Collectors

1. TLS/SSL Collector

Scans for: Visual output in scan results: topic-scan-results.png TLS collector finds certificates and cipher suites on HTTPS services Tools: sslyze, nmap scripts Confidence: 0.95 Default Ports: 443, 8443, 9443 Example findings in device detail: topic-device-assets.png Detail view of TLS assets including certificates and cipher suites

2. SSH Collector

Scans for: Tools: ssh-audit, paramiko Confidence: 0.90

3. VPN Collector

Scans for: Tools: ike-scan

4. Database Collector

Scans for: Requires: Database credentials

5. OS Crypto Collector

Scans for: Requires: SSH credentials

6. App Config Collector

Scans for: Requires: SSH credentials

7. Certificate Store Collector

Scans for: Requires: SSH credentials

Default Ports

SSH

TLS/HTTPS

VPN

Database

Mail

LDAP/Kerberos

RDP/VNC

SMB

Custom Ports

Add custom ports in Settings:

Format: comma-separated or ranges
Example: 9000,9001,9002-9010,10000



Troubleshooting

Common Issues

403 Forbidden (cPanel)

Symptom: Browser shows "403 Forbidden" error Visual indicator: 01-login.png Expected: This login page should appear. If you see 403 instead, check permissions. Solution:
# Fix file permissions via SSH
cd /home/username/public_html/pqcs.example.com
chmod 644 .htaccess passenger_wsgi.py
chmod 755 pqcs/

500 Internal Server Error

Symptom: "500 Internal Server Error" page Solution:
  1. Check cPanel > Logs > Error Log
  2. Verify Python dependencies:
  3. source /home/username/virtualenv/pqcs/3.11/bin/activate
    pip install -r requirements.txt
    
  1. Check passenger_wsgi.py syntax:
  2. python -m py_compile passenger_wsgi.py
    

Database Connection Issues

Symptom: "OperationalError: unable to open database file" Solution:
# Create database directory outside web root
mkdir -p /home/username/db
chmod 755 /home/username/db
chmod 666 /home/username/db/pqcs.db  # or 644 after creation

# Update DATABASE_URL environment variable:
# sqlite:////home/username/db/pqcs.db

Login Failures (422 Error)

Symptom: "Failed to load resource: the server responded with a status of 422" 02-login-filled.png If login fails after entering correct credentials: Solution:
  1. Ensure SECRET_KEY environment variable is set in cPanel
  2. Check bcrypt and pyjwt are installed:
  3. pip list | grep -E 'bcrypt|PyJWT'
    
  1. Reset password via CLI if needed:
  2. python << 'EOF'
    import bcrypt
    from pqcs.db import init_db, User
    from pqcs.config import AppConfig
    
    config = AppConfig()
    db = init_db(config.database.url)
    
    user = db.query(User).filter_by(username="admin").first()
    if user:
        new_pw = bcrypt.hashpw(b"admin", bcrypt.gensalt())
        user.password_hash = new_pw.decode()
        db.commit()
        print("Password reset to: admin")
    EOF
    

SSH Connection Failures

06-settings.png Configure SSH credentials in Settings page

Application Won't Start

cPanel specific:
  1. Check app shows as "Running" in cPanel Python App
  2. Verify passenger_wsgi.py exists and exposes application
  3. Restart the app:
  4. cd /home/username/public_html/pqcs.example.com
    mkdir -p tmp && touch tmp/restart.txt
    

Debug Mode

# Enable debug logging
ceria --verbose dashboard

# Or set environment variable
export LOG_LEVEL=DEBUG
ceria dashboard

Log Locations

PlatformLocation
LocalConsole (--verbose)
cPanel/home2/yusricom/logs/passenger.log
systemdjournalctl -u pqcs

Getting Help

  1. Check this troubleshooting guide
  2. Review relevant section in User Manual
  3. Check application logs
  4. Open issue in repository