Skip to content

Projects

Three systems with full engineering notes, then smaller tools. Every figure comes from the project’s own records and links to the source.

Featured projects

Nerkhbaan

In production

نرخبان · 2026 — Present

A price platform for gold, currencies, and crypto with history, alerts, and web, admin, and desktop apps. Every quote names its source and time and carries an explicit expiry, so an outdated price is never shown as current.

Role
Founder & sole engineer
Category
Backend · DevOps · Product engineering
Status
Live at nerkhbaan.ir (release 2.8.1)
Evidence
nerkhbaan.ir (opens in a new tab)Source code (opens in a new tab)

Key facts

Live release
2.8.1
API paths (OpenAPI)
117
CI jobs passed
15/15
p95 in a 30-min load test
323 ms

From the project’s status record and CI, October 2026. The load test ran on an isolated copy of the stack.

My part

  • Built the whole product: FastAPI API, TimescaleDB and Redis data layer, React web and admin apps, an Electron desktop app, and a Go feed sidecar.
  • Run it in production on Docker Compose: two API replicas behind Nginx, migrations gated by readiness, and scheduled backups with a tested restore.
  • Every release passes 15 CI jobs, including integration tests on real TimescaleDB and Redis, Playwright browser tests, and Trivy scans of seven images.

Stack

  • FastAPI
  • TimescaleDB
  • Redis
  • Go
  • React
  • Electron
  • Docker Compose
  • Nginx
  • GitHub Actions
  • Prometheus
  • Trivy
Read the case study

Architecture

  1. Feed job

    A scheduled GitHub Actions job fetches public market APIs every 5 minutes, checks ranges and age, and publishes one JSON feed.

  2. Go sidecar

    Pulls the feed every 60 s, re-validates it, and pushes quotes to the API with an HMAC-SHA256 signature. It holds no database or admin credentials.

  3. FastAPI × 2

    Verifies signatures and replays, refreshes each instrument under a Redis lease, flags anomalies, and assigns stale and expiry times.

  4. TimescaleDB + Redis

    TimescaleDB keeps price history. Redis holds leases, the quote cache, live-update pub/sub, and a persistence outbox.

  5. Nginx

    TLS, rate limits, REST and WebSocket routing to the API replicas.

  6. Clients

    React web app (PWA), React admin panel, and Electron desktop app. Live prices over WebSocket, with polling as fallback.

How a price travels from public market APIs to users.

Engineering case study

Problem and constraints
  • Show prices where every number states its instrument, unit, source, and time, and never present an outdated price as current.
  • Units and purities are never converted or estimated: a missing direct gold price stays unavailable.
  • Runs on a single server in Iran, where some foreign data providers are not reachable.
Data freshness
  • Each quote stores when it was observed plus explicit stale and expiry times; its status moves from live to stale to expired against the clock.
  • Stale, suspicious, expired, or unpersisted quotes are never shown as current.
  • Disagreeing sources are flagged by volatility-adjusted anomaly checks, and confirmation requires an independent source.
Fault handling
  • Only one replica refreshes a given instrument at a time, using Redis leases with owner-checked release.
  • Provider calls have request budgets, retries, and a circuit breaker; a stale primary source falls back to a fresh secondary.
  • If a database write fails, the quote is queued in a Redis stream outbox and marked unpersisted until it is flushed.
  • If Redis is down, refresh pauses, stored values keep serving, and WebSocket clients fall back to polling.
  • Readiness returns 200 only when the database is reachable and migrations are current; Redis and refresh health are reported alongside.
CI/CD and deployment
  • 15 CI jobs: locked Node builds, Python unit tests, the Go sidecar, Compose and monitoring config checks, Playwright browser tests, dependency and secret scans, and Trivy scans of seven images that fail on any HIGH or CRITICAL finding.
  • Integration tests run on real TimescaleDB and Redis, apply migrations twice to prove they are idempotent, verify migration checksums, and run a restore drill.
  • Production is Docker Compose on one host with two API replicas. Release 2.8.1 was rolled out by scaling to three replicas and removing the old ones one at a time.
Observability and security
  • Eight Prometheus alert rules cover API down, unavailable or expired prices, stalled refresh, provider failure rate, dead letters, persistence backlog, and Redis memory; CI validates them with promtool.
  • The admin panel uses separate session cookies, CSRF protection, permission checks, re-authentication, and required TOTP MFA.
  • Containers drop all capabilities with no-new-privileges, the API port is internal only, and Python dependencies are hash-pinned and checked with pip-audit.
Verified outcomes
  • Release 2.8.1 went live on nerkhbaan.ir in October 2026 after all 15 CI jobs passed and the final API image showed no HIGH or CRITICAL findings.
  • Load test on an isolated copy of the stack: 27,000 of 27,000 requests succeeded over 30 minutes at about 15 requests per second, p95 323 ms, with 200 WebSocket clients connected and no errors.
  • Fault tests on the same copy: all 200 WebSocket clients recovered from an API shutdown in 3.7 s and resynchronized after a Redis outage in 4.5 s.
  • A full database restore matched every table and row count.

Known limitations

  • Single host, with no disaster-recovery site.
  • Zero downtime is not claimed: the 2.8.1 rollout recorded two short readiness timeouts.
  • Load figures cover anonymous price reads and live streams, not authenticated admin traffic.
  • The scheduled feed job depends on GitHub’s cron, which has delayed runs by hours.

Dolphin CRM

In development

دلفین · 2026 — Present

A Persian-first CRM/ERP for sales, quotations and invoicing, payments, inventory, telephony, and after-sales. One codebase is deployed separately for each customer, and each installation runs as its own isolated Docker Compose stack.

Role
Co-founder & lead engineer
Category
Backend · Security · Production operations
Status
Release 2.40.55 (October 2026)
Evidence
Source code (opens in a new tab)

Key facts

Feature flags
46
Automated tests
3,641
Tagged releases
56
Non-superuser DB roles
3

From the repository as of 15 October 2026. Tests run on SQLite and PostgreSQL 16, plus 23 browser tests.

My part

  • Lead the engineering of the Django and PostgreSQL application: 46 feature flags, a right-to-left interface, and server-sent live updates.
  • Designed the deployment model: an isolated stack per installation, a signed feature manifest that fails closed, and non-superuser database roles with per-table grants.
  • Built the operations tooling: scripted deploy and rollback, a maintenance write-stop, and backups that are verified by restoring them.

Stack

  • Django
  • Python
  • PostgreSQL
  • Docker Compose
  • Nginx
  • Gunicorn
  • Asterisk
  • Selenium
  • GNU Bash
Read the case study

Architecture

  1. Browser

    Server-rendered RTL panel with ES modules; no build step at deploy time.

  2. Nginx

    TLS, static files, and a reversible write-stop that rejects POST, PUT, PATCH, and DELETE during maintenance.

  3. Django (Gunicorn)

    Every request is checked against the feature manifest, the user’s role permissions, and record-level scope.

  4. PostgreSQL 17

    Accessed with a non-superuser role and exact per-table grants; no DELETE on financial tables, insert-only audit tables.

  5. Side services

    Realtime (LISTEN/NOTIFY → server-sent events), an integrations worker (outbox, webhooks, Asterisk, SMS), and a backup scheduler.

Request path and the services around it in one installation.

Engineering case study

Problem and requirements
  • One codebase deployed separately for each customer, with no customer-specific code branches.
  • Feature availability, role permissions, and record-level scope are independent controls, and turning a feature off never deletes data.
  • Installations may be offline: images are transferred to servers that cannot reach package registries.
Architecture
  • Django 5.2 and Django REST Framework on Python 3.13, Gunicorn, Nginx, and PostgreSQL 17. There is no Redis or Celery; background work runs in dedicated worker containers.
  • Live updates use PostgreSQL LISTEN/NOTIFY and server-sent events. Events carry no data, so the browser re-fetches through the permission-checked API.
Installation isolation
  • Each installation is its own Compose project with its own database, backup volume, secrets, feature manifest, and hostname.
  • The deploy script refuses to run if two stacks share a database volume, a rule added after a real catalog-corruption incident.
Feature configuration
  • 46 feature flags (22 on by default) are declared with their dependencies.
  • In production, enabled features come from an Ed25519-signed manifest, and the application refuses to start if it is missing, altered, or signed by an unknown key.
Database privilege separation
  • A superuser account is used only by one-shot setup jobs: db-bootstrap → migrate → db-finalize must finish before the web service starts.
  • Migrations, the running application, and backups each use a separate non-superuser role with per-table grants.
Deployment and rollback
  • deploy.sh runs preflight checks, records the previous image, provisions roles, takes a backup, migrates, applies grants, starts services, and reloads Nginx.
  • --rollback redeploys the previous image; migrations are additive, so rolling back the code does not require reversing the schema.
Backup restoration
  • Backups are pg_dump archives with SHA-256 checksums. A verification job restores them in a container with networking disabled.
  • A weekly restore drill runs automatically, and off-host copies are encrypted and verified after transfer.
Verified development outcomes
  • Release 2.40.55 on 15 October 2026; about 3,640 automated tests pass on both SQLite and PostgreSQL 16, plus 23 browser tests.
  • 56 tagged releases in the 2.40 line, each with a changelog entry.
  • Application and job containers run read-only, with all capabilities dropped and no-new-privileges.

Known limitations

  • The signed manifest makes feature changes fail closed and detectable, but its trusted public keys are read from the host’s environment file. Someone with full control of the host could add their own key, so it protects against accidental or casual changes, not against the host owner.
  • Python source inside the image is readable, and there is no licence expiry or online activation by design.
  • No point-in-time recovery: the recovery point is the backup interval, six hours by default.
  • Telephony (Asterisk/FreePBX) and SMS integrations are implemented and tested against simulated systems; live validation is pending.

Stackplore

In development

2026 — Present

A self-hosted workspace that brings Docker and Kubernetes inventory, health, topology, logs, metrics, and events into one versioned API and an English/Persian interface. It is read-only by default and built for troubleshooting, not as a control plane.

Role
Author & sole engineer
Category
Platform engineering · DevOps tooling
Status
Pre-1.0: 0.7.0 in progress, latest tag v0.6.0
Evidence
Source code (opens in a new tab)

Key facts

OpenAPI paths
47
Forward-only migrations
14
CI jobs
6
Latest tag
v0.6.0

From the repository as of 17 October 2026.

My part

  • Designed and built the Go API, PostgreSQL schema, provider adapters, and the React interface from one OpenAPI contract.
  • Kept access least-privilege: Docker through a read-only mTLS proxy, Kubernetes through get/list RBAC in the namespaces you choose.
  • CI exercises the providers against a real Docker Engine and a kind cluster, not only fixtures.

Stack

  • Go
  • PostgreSQL
  • Kubernetes
  • Docker
  • Helm
  • OpenAPI
  • React
  • TypeScript
Read the case study

Architecture

  1. Browser

    React interface in English and Persian, using a client generated from the OpenAPI contract.

  2. Go application

    Serves the embedded UI and the /api/v1 API with local accounts, CSRF checks, and server-sent event streams.

  3. Collection workers

    Bounded in-process workers poll providers on a schedule. Requests read stored data and never trigger collection.

  4. Providers

    Docker through an mTLS proxy that allows only fixed read endpoints; Kubernetes through client-go with get/list RBAC; a deterministic demo source.

  5. PostgreSQL

    Normalized observations, alerts, notification outbox, and audit log, under 14 forward-only migrations.

One Go application with the interface embedded, reading from providers into PostgreSQL.

Engineering case study

Implemented and tested
  • Inventory, health, topology, logs, current and historical metrics, and events for Docker, Kubernetes, and a demo source.
  • Local accounts with Argon2id hashing, opaque sessions, CSRF checks, and re-authentication for high-risk actions.
  • Alerts with in-app notifications and opt-in webhook and Matrix delivery.
  • Guarded restart and scale actions, all off by default.
In progress (0.7.0)
  • A single non-root image that serves both the interface and the API.
  • CI checks for a fresh Compose install and a Helm install on kind with TLS to PostgreSQL; results are not recorded yet.
Planned before 1.0
  • Backup, restore, upgrade, and rollback drills on a real production target.
  • Published images with an SBOM, vulnerability scans, and signing.
  • A full accessibility and performance review.
Security
  • Direct Docker socket access is allowed only in local development; production uses the restricted proxy.
  • The Helm chart grants get/list only in the listed namespaces and never reads Secrets or ConfigMaps.
  • The container runs as UID 10001 with a read-only root filesystem and all capabilities dropped.
Testing
  • CI runs the Go tests with the race detector against PostgreSQL 17, the web tests, Compose and Helm checks, and provider tests against a real Docker Engine and a kind cluster.

Known limitations

  • Not production-ready: 1.0 requires the production-target drills listed above.
  • Runs as a single replica; images are built from source and not yet published.

More projects

  • Prometheus & Jira → Matrix bridges

    n8n workflows · Monitoring · 2025

    Two n8n workflows that bring Prometheus alerts and Jira updates into the team’s Matrix chat.

    • Alertmanager webhooks become colour-coded firing/resolved messages with a link to the Prometheus graph.
    • Jira assignments and @mentions reach the right person’s Matrix direct messages.
    • Tokens are validated and renewed automatically; delivery retries with backoff and jitter.
  • Matrix User Manager

    Bash TUI · Automation & ops · 2025

    A terminal menu for managing users on a Synapse homeserver running in Docker.

    • Finds the Synapse containers and reads homeserver.yaml on its own.
    • Works with PostgreSQL or SQLite, with a safe stop/start around SQLite writes.
    • Includes database backups.
  • LinSecGuard

    Bash CLI · Security · 2025

    An interactive hardening check for Linux servers.

    • Checks SSH root login and port, UFW rules, and running services.
    • Finds insecure file permissions and open ports.
    • Reports failed logins and pending security updates.
  • SysTrack

    Bash · cron · Monitoring · 2025

    A cron-scheduled resource monitor for Linux hosts.

    • Tracks CPU, memory, disk, and network usage.
    • Emails an alert when a threshold is crossed.
    • Rotates its own logs.
  • Automated Backup Script

    Bash CLI · Automation & ops · 2025

    Interactive, scheduled backups of directories.

    • Creates tar or zip archives on a cron schedule.
    • Logs its runs and removes backups older than seven days.
  • EasyCert

    Bash CLI · Security · 2025

    An interactive OpenSSL wrapper for a local certificate authority.

    • Creates a local CA and wildcard or subdomain certificates.
    • Restarts the Nginx or Traefik container to load them.
  • CipherCert

    Desktop app · Security · 2026

    A desktop analyzer for TLS certificates.

    • Electron/React interface over a FastAPI engine.
    • Inspects certificate chains and expiry, and grades domains.
    • Keeps scan history in SQLite.