osu!somtum is an osu! private server from Thailand. Services communicate via a shared MySQL database and Redis cache, all hosted on OVH and fronted by Cloudflare.
Website: somtum.fun
flowchart TB
subgraph Clients["External Clients"]
osu(["osu! Game Client"])
web(["Web Browser"])
dclient(["Discord"])
end
subgraph CF["Cloudflare (DNS · CDN · DDoS · SSL)"]
cf{{"Proxy & Cache"}}
end
subgraph OVH["OVH VPS — Podman Containers"]
ng{{"Caddy — Reverse Proxy & Rate Limiting"}}
subgraph Public["Public Services"]
bancho["bancho.py<br/>(Python/FastAPI) :10000"]
gukarkka["gukarkka<br/>(Next.js 14) :3000"]
payments["payments-service<br/>(Python/FastAPI) :8001"]
end
subgraph Internal["Internal Services"]
circlecore["Circlecore-somtum<br/>(Python/FastAPI) :8555"]
end
subgraph Bots["Bots"]
bot["Discord-Bot-Somtum<br/>(discord.py)"]
end
subgraph Data["Data Stores"]
mysql[("MySQL 9.4<br/>Shared Database")]
redis[("Redis 8.2<br/>Cache & Sessions")]
files[("Static Files<br/>Avatars & Replays")]
end
end
subgraph ExternalAPIs["External APIs"]
osuapi["osu! API v1/v2"]
discordwh["Discord Webhooks"]
truemoney["TrueMoney / PromptPay"]
stripe["Stripe"]
end
%% Client connections
osu -->|"c.somtum.fun"| cf
web --> cf --> ng
dclient <--> bot
%% Caddy routing
ng -->|"somtum.fun"| gukarkka
ng -->|"session / api .somtum.fun"| bancho
ng -->|"a.somtum.fun"| files
%% Inter-service HTTP
gukarkka -->|"player & session data"| bancho
gukarkka -->|"donations"| payments
bancho -->|"replay analysis"| circlecore
payments -->|"grant_donator"| bancho
bot -->|"player actions"| bancho
bot -->|"replay checks"| circlecore
%% External APIs
bancho --> osuapi
bancho --> discordwh
circlecore --> discordwh
payments --> truemoney
payments --> stripe
bot --> discordwh
%% Data stores
bancho --> mysql & redis
gukarkka --> redis
payments & bot --> mysql
%% Styling
classDef client fill:#e1f5fe,stroke:#01579b,color:#01579b
classDef proxy fill:#fff3e0,stroke:#e65100,color:#e65100
classDef public fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20
classDef internal fill:#f3e5f5,stroke:#7b1fa2,color:#4a148c
classDef data fill:#fce4ec,stroke:#c2185b,color:#880e4f
classDef external fill:#eceff1,stroke:#546e7a,color:#37474f
classDef bot fill:#e3f2fd,stroke:#1565c0,color:#1565c0
class osu,web,dclient client
class cf,ng proxy
class bancho,gukarkka,payments public
class circlecore internal
class mysql,redis,files data
class osuapi,discordwh,truemoney,stripe external
class bot bot
| Service | Language | Purpose |
|---|---|---|
| bancho.py | Python/FastAPI | Core game server (osu! protocol, scoring, multiplayer) |
| gukarkka | Next.js 14/TypeScript | Web frontend — profiles, leaderboards, beatmap browser & uploads |
| Discord-Bot-Somtum | Python/discord.py | Community bot — stats, moderation, beatmap workflow |
| Circlecore-somtum | Python/FastAPI | Anti-cheat — replay analysis & similarity detection |
| payments-service | Python/FastAPI | Donation processing (TrueMoney, PromptPay, Stripe) |
- Shared Database: bancho.py, Discord bot, and payments-service all connect to the same MySQL instance
- Redis: bancho.py for sessions and cache; gukarkka for caching
- HTTP REST: All inter-service communication
| Caller | Target | Purpose |
|---|---|---|
| gukarkka | bancho.py | Player sessions, scores, leaderboards |
| gukarkka | payments-service | Donation redeem, PromptPay, Stripe checkout, admin approve/reject |
| bancho.py | Circlecore-somtum | Queue replay for analysis after score submit |
| payments-service | bancho.py | POST /internal/grant_donator — sync donator status |
| Discord-Bot-Somtum | bancho.py | Player management (restrict, whitelist, etc.) |
| Discord-Bot-Somtum | Circlecore-somtum | On-demand replay checks from staff commands |
- Client
POSTs encrypted score data to bancho.py viac.somtum.fun - bancho.py decrypts and validates the score
- Score and stats written to MySQL
- Replay queued to Circlecore-somtum for async analysis
- Circlecore fires Discord webhook alert if suspicious
- First-place announcements sent via Discord webhook
osu!somtum lets players host their own beatmaps (a custom feature not in vanilla bancho.py). Uploads are supported both in-game (via the standard osu-osz2-bmsubmit endpoints on osu.somtum.fun) and through the web frontend:
- Player uploads an
.oszto bancho.py - bancho.py validates the session, parses the zip, and SHA-256-dedups each difficulty against existing maps
- Each diff is cross-checked against the osu! API v1 to reject maps already submitted to osu!
- A fresh somtum set ID is allocated;
BeatmapID/BeatmapSetIDlines are rewritten and the map is persisted to disk mapsets/mapsrows are inserted assomtum_onlywith statusPending, awaiting nomination- Upload is audited via Discord webhook
| Category | Technologies |
|---|---|
| Languages | Python, TypeScript, SQL |
| Web Frameworks | FastAPI, Next.js 14, React 18 |
| Databases | MySQL 9.4, Redis 8.2 |
| Styling | Tailwind CSS, shadcn/ui |
| Discord | discord.py 2.4+ |
| Anti-cheat | circleguard 5.4.3 |
| Containers | Podman / Podman Compose |
| Reverse Proxy | Caddy |
| External APIs | osu! API v1/v2, Discord, TrueMoney, PromptPay, Stripe |
| Provider | Purpose |
|---|---|
| OVH | VPS — hosts all services |
| Cloudflare | DNS, CDN, DDoS protection, SSL certificates |
| Caddy | Reverse proxy, automatic HTTPS, rate limiting |
| Podman | Container runtime & orchestration |
| Domain | Service | Notes |
|---|---|---|
somtum.fun |
gukarkka :3000 | Web frontend |
c / ce / c4 / osu / b / api / session .somtum.fun |
bancho.py :10000 | osu! client + API endpoints (rate-limited on c/ce/c4/osu) |
payment.somtum.fun |
payments-service :8001 | Donation processing |
a.somtum.fun |
Static files | Avatars |
assets.somtum.fun / assets1.somtum.fun |
Static files | Banners, clan assets, replays |
All subdomains sit behind the Cloudflare proxy; Caddy handles routing and automatic HTTPS at the OVH VPS.
