Skip to content

Yangseok/ondol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

331 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔥 Ondol

A warm, batteries-included CMS in Rust — boards, shop, wiki, blog & an AI authoring studio, all under one roof.

English · 日本語 · 한국어

License: MIT Rust PostgreSQL After pushing to GitHub, enable the CI badge: CI

Ondol (온돌) is the traditional Korean underfloor heating that keeps a home warm — the idea behind this project: a single, cozy place where your whole community lives. Inspired by Korea's Gnuboard, rebuilt in Rust.

Most Rust "CMS" projects are single-purpose (a static-site generator, a forum, a blog). Ondol fills the empty niche: a full, dynamic, WordPress/Gnuboard-class CMS in a single binary — memory-safe, fast, and self-hostable.


Screenshots

Board Admin dashboard AI authoring studio
Board Admin AI Studio

Features

  • 📋 Boards — categories, nested comments, per-board permission levels, points, secret posts, notices, tags, attachments, full-text search
  • 👥 Members & RBAC — level system, role groups, auto-promotion, dormant/withdrawal flows, multi-admin per board
  • 🛒 Shop — products & options, cart, orders, inventory, shipping fees, tracking, reviews, points (Gnuboard Youngcart-class)
  • 📚 Wiki & Blog — versioned wiki with access control; blog skin reusing the board engine
  • 🤖 AI authoring studio — long-form book generation (outline → draft → review → publish) + admin writing assist, with a provider abstraction (local Ollama or cloud) and encrypted API keys
  • 🛡️ Security — CSRF, in-process WAF (bot/scanner blocking), RBAC, OAuth2 (PKCE, refresh, webhooks, OpenAPI), SSRF guards, AES-256-GCM secret encryption, bcrypt isolated on a blocking pool
  • 🔎 SEO — OpenGraph/Twitter, JSON-LD (Article/Product/Breadcrumb), sitemap & robots, per-page noindex
  • Modern SSR — Tera server-rendering + htmx islands (list search / pagination / comments update without full reloads)
  • 🧩 Skeleton for derived sites — build new services on top via SiteHooks + template overlay, keeping the core untouched
  • 🧰 Ops-ready — versioned schema migrations (auto-applied on boot), structured logging (tracing), i18n scaffold, polls · FAQ · 1:1 inquiry · messages · notifications · mail templates · visitor stats

Tech stack

Area Choice
Language / runtime Rust + Tokio
Web framework Axum 0.8
Data access SeaORM (simple) + sqlx (joins/aggregates)
Database PostgreSQL 16 (+ pgvector, optional)
Templates Tera (SSR) + htmx
Sessions tower-sessions (PostgreSQL store)

Quick start

# 1. Config
cp .env.example .env          # edit DB, port, upload size, SMTP, APP_SECRET …

# 2. Dev database (PostgreSQL 16)
docker compose up -d

# 3. Run
cargo run                     # http://127.0.0.1:3000

The admin account is admin; the initial password is printed once to the console on first boot (or set ADMIN_INITIAL_PASSWORD in .env). On a fresh install the browser opens a setup wizard (/setup) — authenticate with the console password, then choose your site name and a new admin password. The schema is created/migrated automatically on startup.

Documentation

Derived sites (portfolio starters, D-111)

Ten in-repo starters, each shipped as track A (server-rendered Tera theme) + track B (headless Next.js) on one backend — 10 types × 2 tracks = 20 running sites. Details: docs/DERIVED-CATALOG.md · per-site notes in sites/<id>/docs/SITE.md.

Ports & landing URLs

id Type · benchmark Track A (server-rendered) Track B (headless)
community Gallery community · DCInside http://127.0.0.1:3001/board/gd http://127.0.0.1:3101
forum Threaded Q&A · Discourse http://127.0.0.1:3002/board/ask http://127.0.0.1:3102
blog Editorial blog · Ghost/Medium http://127.0.0.1:3003/board/log http://127.0.0.1:3103
magazine Multi-author · NYT/Verge http://127.0.0.1:3004/board/feature http://127.0.0.1:3104
wiki Docs · Notion/Nextra http://127.0.0.1:3005/wiki http://127.0.0.1:3105
shop Commerce · Shopify/Apple http://127.0.0.1:3006/shop http://127.0.0.1:3106
jobs Job board · JobKorea/Wanted http://127.0.0.1:3007/board/jobs http://127.0.0.1:3107
realestate Listings · Zigbang/Dabang http://127.0.0.1:3008/board/listings http://127.0.0.1:3108
reserve Booking · Interpark/Airbnb http://127.0.0.1:3009/reserve http://127.0.0.1:3110
studio Book reader · Substack/Ridi http://127.0.0.1:3010/books http://127.0.0.1:3111

Backends use ports 3001–3010, fronts 3101–3111 (reserve front is 3110). Track A URLs above point at the content screen; track B home is /. Every site has a KO/EN/JA language switcher in the header.

Run one site

A track B front talks to its own track A backend, so start the backend first.

# Track A (server-rendered) — backend on 3001–3010, DB ondol_<id> (auto-created)
scripts/catalog.sh reserve
#   On the very FIRST boot it prints a one-time admin password to the console (D-027):
#     "최초 관리자 계정 생성: admin / <random>"  — log in with that, or preset it:
#     ADMIN_INITIAL_PASSWORD=admin123 scripts/catalog.sh reserve

# Track B (headless) — Next.js dev server on 3101–3111 (needs the backend above running)
cd fronts && pnpm install          # first time only
pnpm --filter reserve-front dev    # or: cd fronts/reserve && pnpm dev

Run all 20 at once

scripts/portfolio-e2e.sh orchestrates every backend + front together. It uses throwaway ondol_<id>_e2e databases (your ondol_<id> demo DBs stay untouched) and fixes the admin login to admin / admin123.

scripts/portfolio-e2e.sh up       # build + recreate DBs + start 20 servers (~1–2 min)
scripts/portfolio-e2e.sh status   # 200 = ready
scripts/portfolio-e2e.sh down     # stop everything

scripts/portfolio-e2e.sh up start # serve production builds instead of dev (needs: cd fronts && <id> build)

Prerequisites for either path: docker compose up -d (PostgreSQL + Redis) and, for track B, pnpm install inside fronts/. A one-page index of all 20 links lives at docs/PORTFOLIO.html.

Payments (shop): bank transfer works out of the box; card PGs (TossPayments, PortOne) are enabled per-gateway in /admin/payments after entering sandbox keys — see docs/PAYMENTS.md.

Contributing

Issues and PRs welcome. Run the test suite before submitting:

docker compose up -d
cargo test --workspace

License

MIT © Yangseok

Bundled third-party: htmx (0BSD) · TOAST UI Editor (MIT)

About

A warm, batteries-included CMS in Rust — boards, shop, wiki, blog & an AI authoring studio.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages