Architecture

How Weborn is built and how it works

Tech Stack

Backend
Python 3.13
Framework
FastAPI + Uvicorn
Frontend
Tailwind CSS
Terminal
xterm.js
Auth
JWT + CSRF
Database
SQLite
Process
systemd
Platform
Debian/Ubuntu

Request Flow

Every request follows this path from browser to application:

Browser → Nginx :80/:443 → Gunicorn/Uvicorn → App (Flask/FastAPI/Django)

For the Panel Itself

Browser :2025 → Uvicorn → FastAPI + Jinja2 → SQLite

Directory Structure

weborn/
    main.py              # FastAPI app + lifespan + mounts
    config.py            # Paths, VERSION, settings
    db.py                # SQLite schema, queries, settings
    auth.py              # JWT encode/decode, PAM, idle lock
    csrf.py              # CSRF token middleware (ASGI)
    ratelimit.py         # Token bucket rate limiter
    icons.py             # 57+ Heroicons v2 outline icons
    ui.py                # Jinja2 env, icon() global
    weborn.py            # CLI entry point (argparse)
    executors/
        __init__.py      # LocalExecutor, DryRunExecutor, WSLExecutor
    managers/
        apps.py          # AppManager (create/delete/start/stop)
        nginx.py         # NginxManager (sites, SSL, cache)
        apache.py        # ApacheManager (ports, virtual hosts)
        db.py            # DBManager (MariaDB, PostgreSQL)
        email.py         # EmailManager (Postfix, Dovecot, Rspamd)
        security.py      # SecurityManager (UFW, Fail2Ban, ClamAV)
    routers/
        dashboard.py     # Dashboard overview
        apps.py          # App CRUD, monitor, process config
        addons.py        # Addon store (39 addons)
        domains.py       # Domain & DNS management
        email.py         # Email stack management
        security.py      # Firewall, Fail2Ban, ClamAV
        ...              # 20+ route modules
    templates/           # Jinja2 HTML templates
    static/              # CSS, JS, icons
    addons/              # 39 addon manifests (.json)

Executor Modes

ModeDescriptionUsed When
localDirect subprocess execution with sudoRunning on Linux server (production)
wslExecutes commands via WSL distroDevelopment on Windows
dry-runSimulates commands, returns mock outputWindows dev without WSL

Authentication Flow

Login Request
    |
    +--> Check panel DB (PBKDF2-SHA256 hash)
    |       |
    |       +--> Match? --> Create JWT --> Set cookie --> Redirect
    |       |
    |       +--> No match?
    |               |
    |               +--> PAM fallback (su -c "password" user)
    |                       |
    |                       +--> Success? --> Create shadow user --> JWT --> Redirect
    |                       |
    |                       +--> Fail --> "Username atau password salah"

Security Layers

Database Schema

TablePurpose
usersPanel admin accounts (PBKDF2 hashes)
sessionsActive JWT sessions
appsDeployed applications (type, command, status)
domainsDomain configurations + SSL status
proxiesReverse proxy configurations
dns_recordsDNS record configurations
cronsScheduled tasks
settingsPanel settings + secret key
login_logsAudit trail (IP, timestamp, success/fail)
login_attemptsRate limiting counter per IP