DinD HostingManual
Overview/Manual/Start here
CHAPTER 01

Core concepts

Eleven nouns explain the whole platform. Learn them once and every other chapter reads quickly.

The vocabulary#

Term What it is
User A person (or agent identity) with an email, a password and a role: admin or user. Admins create users — there is no self-registration.
Alias A short, unique handle of 2–15 characters [a-z0-9] that every user has. It appears in daemon names and site names (<slug>.<alias>.<base_domain>).
Project The unit you deploy: a slug, a display name and a base domain. A project owns one web app, its databases, domains, variables and backups.
Slug The project's short name, 2–40 characters [a-z0-9-], unique per user.
App The running web application of a project — one container, built from your source. One app per project in this version.
Deployment One build-and-run attempt. Numbered per project, with a status, a build log and the manifest that was resolved.
Runtime How your source is built and started: static, node, python or php. Auto-detected, or set in platform.yaml.
Daemon (DinD) A Docker daemon running inside a container. Every user gets their own for apps; databases live in a shared one. Your code never shares a daemon with another user.
Database A PostgreSQL or MySQL container attached to a project, with generated credentials and an SQL console.
Bucket Your personal S3 bucket (<alias>-files) on the built-in MinIO, with your own access keys.
Token A long-lived dt_… API token for agents and CI, created on the tokens page.

How the pieces nest#

Everything the platform runs lives inside one privileged container, dind-hosting. Inside it, services and per-user daemons share a private network, and every user's apps run in a daemon of their own.

outside Browsers*.alex.example.com REST clients · CIBearer JWT / dt_ token AI agentsClaude Code · MCP Host ingress reverse proxy ornftables on the hostyour decision → 10.10.10.10 dind-hostingmain DinD · privileged · bridge “hosting” · 10.10.10.10 · no published host ports platform-net · 172.28.0.0/16 · static IPs Traefik:80 :443 · ACME172.28.0.3 management:8900 UI·API·MCP172.28.0.2 platform-pgstate · metrics172.28.0.4 MinIOS3 · backups172.28.0.5 projects-alex172.28.0.64 blogstatic:10000 shopnode 24:10001 dbshared DB daemon172.28.0.10 postgresshop-main:20000 mysqlblog-wp:20001 projects-bob172.28.0.65 apipython 3.12:10000 sitephp 8.5:10001 db-aliceoptional · dedicated postgresanalytics:20000 /platform-data/sockets/ main.sock · db.sock · projects-alex.sock · … data/ on the host bind-mounted into the main DinD: main-docker · platform/{db,minio,deploys, traefik,secrets,sockets} · dind/ legend HTTP route chosen by Host Docker API over unix sockets user daemon (apps) database daemon the one host-level container
The whole platform. One host-level container holds the platform services and one app daemon per user. Databases live in a shared daemon, or in a dedicated one when an admin switches that on for a user.

Three things are worth noticing:

  1. One address toward the host. The platform is reached at 10.10.10.10 on a host bridge network. It publishes no host ports; what is forwarded from the Internet is your ingress decision.
  2. A daemon per user. Your apps are built and run by a daemon only you use. That is the isolation boundary between tenants.
  3. Everything is reconciled. A management container re-asserts the desired state of all of this on every boot — a reboot or crash brings the whole stack back without help.

Who owns what#

usersapp daemons (one per user)shared servicesalexrole: useralias: alexbobrole: useralias: bobprojects-alex172.28.0.64blogstatic · nginx:10000shopnode 24:10001projects-bob172.28.0.65apipython 3.12 · :10000ownsownsdbshared database daemonpostgresshop-mainmysqlblog-wppostgresapi-mainMinIOone IAM user + bucket eachalex-filesIAM user alexbob-filesIAM user bobApps get DB_MAIN_HOST/PORT/USER/PASSWORD/NAME and S3_* as environment variables.Teal = database access over platform-net · green dashed = S3 with the user’s own scoped keys.
Tenancy. Each user owns an app daemon with their projects; databases and object storage are shared services scoped per user.

The platform enforces ownership in the service layer, so the web console, the REST API and the MCP tools behave identically:

  • A user sees and changes only their own projects, databases, backups and tokens. A foreign object answers not found — never forbidden — so existence is not leaked.
  • An admin also sees every project and can create and disable users, switch a user's dedicated database daemon on or off, read platform-wide metrics and change platform settings.

Three doors, one set of rules#

Web consoleReact SPA · browserlogin → JWT (8 h)REST API/api/v1 · JSON · SSEJWT or dt_… tokenMCP server/mcp/ · stdiodt_… token for agentsmanagement · service layerRBAC + ownershipa user sees only their own objectsbusiness logicdeploy · databases · domains · backupsaudit trailaudit_log · query_log for every changeidentical ruleson every doorDocker daemonsunix sockets only · docker-pyPlatform databaseusers · projects · deployments · logsMinIO · Traefik filesS3 admin via mc · dynamic route files
The console, the REST API and the MCP server are thin wrappers over the same service layer: same authorisation, same limits, same audit trail.

Anything you can click you can also script (curl) or hand to an agent (deploy_app, run_query, …). The API tokens, REST & MCP chapter covers authentication.

What lives where#

Data Stored in Survives a redeploy?
Users, projects, deployments, settings, audit rows, metrics Platform PostgreSQL (platform-pg) Yes
Your source archives data/platform/deploys on the host Until retention prunes them
Build logs Live buffer while building, then MinIO Yes
Built images and app volumes Your app daemon projects-<alias> Images are rebuilt; volumes persist
Database files A named volume inside the database daemon Yes
Backups and dumps MinIO bucket platform Per retention policy
Your own files MinIO bucket <alias>-files Yes
Generated secrets (JWT key, passwords, Fernet key) data/platform/secrets (mode 0600) Yes

Container filesystems are disposable

A deploy replaces the app container. Anything your app writes outside a declared volume (see platform.yaml) or outside S3 is gone after the next deploy or recreate.

Statuses you will meet#

Object Values
Deployment queued fetching building running failed
App container running stopped missing
Domain pre-check pending passed dns_failed routing_failed
Certificate none pending issued error

Limits at a glance#

1 appper project
2–40characters in a slug
512 MiBlargest archive upload
100project variables per project
1 000 rowsor 1 MiB per SQL result
14 days · 5default backup retention per scope