A Rust (Axum) incident management app connected to PostgreSQL, built for Clever Cloud's native Rust runtime (no Docker image, no Dockerfile). Demonstrates async Rust web development with automatic database migrations — dressed with the Clever Brand Kit and putting the Clever Cloud certification front and center.
- Fork this repository
- In the Clever Cloud console, create a new Rust application — connect your forked repo
- Before the first deploy, in the app's Scalability tab:
- enable the dedicated build instance (size M) — it is disabled by default. Without it,
cargo buildruns on the small app instance, pins its CPU at 100 % and the deployment stalls; - enable auto-scalability: size nano → XS, 1 → 2 instances.
- enable the dedicated build instance (size M) — it is disabled by default. Without it,
- Add a PostgreSQL add-on on the XXS Small Space plan (
xxs_sml, the smallest dedicated plan) with encryption at rest enabled, and link it to your app. Encryption can only be chosen when the add-on is created; the shared DEV plan offers neither encryption nor more than 5 connections. The app readsPOSTGRESQL_ADDON_URIdirectly, do not copy it intoDATABASE_URL. - Recommended environment variables (console or
clever env set):DB_POOL_MAX=2— pool size; keepDB_POOL_MAX × instancesbelow the add-on's connection limit (xxs_sml= 45: 2 instances, doubled during a redeploy, × 2 = 8)RUST_LOG=incident_tracker=info,tower_http=info(already the built-in default)CC_HEALTH_CHECK_PATH=/health— the platform validates the deployment against PostgreSQLCC_RUST_VERSION=1.94— pins the toolchain used by the build (minimum declared: 1.85)
- Push → Clever Cloud builds with
cargo build --release --lockedand deploys automatically
clever create --type rust demo-rust-postgresql
clever scale --build-flavor M
clever scale --flavor nano
clever scale --min-flavor nano --max-flavor XS --min-instances 1 --max-instances 2
clever addon create postgresql-addon demo-rust-db --plan xxs_sml --option encryption=true --link demo-rust-postgresql --yes
clever env set CC_HEALTH_CHECK_PATH /health
clever env set DB_POOL_MAX 2
clever env set CC_RUST_VERSION 1.94
clever deployclever create leaves the dedicated build disabled too: run clever scale --build-flavor M before clever deploy, and check that clever status shows Dedicated build: M. The build instance is only billed while a build runs. Set the fixed nano size before the auto-scalability range: --min-flavor alone does not shrink an instance that already runs at XS. After the deploy, clever status should show running (1*nano), Scalers: 1 to 2, Sizes: nano to XS. An app created this way deploys from its Clever Cloud git remote: redeploy with clever deploy, a push to GitHub does not trigger it.
To move an existing app from a DEV database to an encrypted one: create the xxs_sml add-on with --option encryption=true, unlink the DEV add-on (clever service unlink-addon <id>), link the new one (clever service link-addon <id>), then clever restart — the migrations recreate the schema at startup (data is not copied).
Build time: ~1–2 minutes on the dedicated M build instance (measured: 1 min 16 s for a first build). Subsequent deploys reuse the build cache.
| Layer | Technology |
|---|---|
| Language | Rust (edition 2021) |
| Web framework | Axum 0.8 |
| Async runtime | Tokio |
| Database | PostgreSQL |
| DB access | SQLx 0.8 |
| Templates | Askama 0.12 |
| Design | Clever Brand Kit (Plus Jakarta Sans, navy #13172e, dégradé Clever) |
- List, create, and update incidents
- Filter by status: open / investigating / resolved (
?status=) - Severity levels: low / medium / high / critical
- Automatic database migrations at startup (
sqlx::migrate!()) /healthendpoint — 200 when PostgreSQL answersSELECT 1, 503 otherwise- Server-side validation: title ≤ 255, service ≤ 100, description ≤ 10 000 characters (form error, never a 500)
- Security headers on every response (
X-Content-Type-Options,Referrer-Policy,X-Frame-Options,Content-Security-Policy) — TLS/HSTS stay on the Clever Cloud proxy - Graceful shutdown on SIGTERM/Ctrl+C (in-flight requests drained, pool closed)
/statspage with incident counts- « Vu depuis Clever Cloud » panel: shows the variables the platform injects (
CC_APP_NAME,APP_ID,INSTANCE_NUMBER,INSTANCE_TYPE,CC_PRETTY_INSTANCE_NAME,CC_COMMIT_ID,CC_DEPLOYMENT_ID) — displays « Local · hors Clever Cloud » when running outside the platform
The UI uses the shared Clever Brand Kit: a single stylesheet (static/cc-brand.css, tokens --cc-*, Plus Jakarta Sans + JetBrains Mono via Google Fonts with system fallbacks), the official Clever Cloud logo and the certification badge inlined as Askama partials (templates/partials/). No dependency was added: the CSS is embedded in the binary with include_str! and served on /cc-brand.css.
Page structure (identical to the kit's reference page): sticky topbar → hero → certification block → demo content + platform panel → « Ce que Clever Cloud fait » → footer. App-specific styles live in a short <style> block in templates/base.html; cc-brand.css is never edited.
Spec: docs/superpowers/specs/2026-09-06-clever-brand-design.md.
The home page puts the Clever Cloud Academy certification right under the hero: the two official tracks (Cloud Computing Fundamentals, Advanced Deployment) and a call to action. Every page carries a « Se certifier ↗ » link in the topbar.
→ academy.clever.cloud — digital badges are issued automatically once a track is validated.
- Rust (stable, 1.85+ —
rust-versioninCargo.toml) - PostgreSQL running locally
git clone https://github.com/Vitiosum/demo-rust-postgresql
cd demo-rust-postgresql
cp .env.example .env
# Edit .env: set DATABASE_URL to your local PostgreSQL connection string
cargo run
# → http://localhost:8080One-liner without .env:
DATABASE_URL=postgres://localhost/demo_rust PORT=8082 cargo run| Variable | Required | Description |
|---|---|---|
POSTGRESQL_ADDON_URI |
✅ (Clever) | Injected by the linked PostgreSQL add-on; read when DATABASE_URL is absent |
DATABASE_URL |
✅ (local) | PostgreSQL connection string for local runs (takes precedence if set) |
PORT |
auto | Injected by Clever Cloud (default: 8080) |
DB_POOL_MAX |
— | Max pool connections (default: 2). Rule: DB_POOL_MAX × instances ≤ add-on limit (xxs_sml = 45, DEV = 5) |
RUST_LOG |
— | Log filter (default: incident_tracker=info,tower_http=info) |
CC_HEALTH_CHECK_PATH |
— (Clever) | Set to /health so the platform checks PostgreSQL before routing traffic |
CC_RUST_VERSION |
— (Clever) | Pins the Rust toolchain used by the build (e.g. 1.94) |
CC_APP_NAME, APP_ID, INSTANCE_NUMBER, INSTANCE_TYPE, CC_PRETTY_INSTANCE_NAME, CC_COMMIT_ID, CC_DEPLOYMENT_ID |
auto | Injected by Clever Cloud, read-only, displayed in the platform panel |
| Method | Path | Description |
|---|---|---|
| GET | / |
List incidents (?status= filter) |
| GET | /incidents/new |
Create form |
| POST | /incidents |
Create incident |
| GET | /incidents/{id} |
Incident detail |
| POST | /incidents/{id}/status |
Update status |
| GET | /stats |
Statistics |
| GET | /health |
Health check (200 if PostgreSQL answers, 503 otherwise) |
| GET | /cc-brand.css |
Clever Brand Kit stylesheet (embedded) |
Axum 0.8 note: path parameters use the
{id}syntax. The former:idsyntax makes Axum 0.8 panic at startup (Path segments must not start with ':') — this was fixed in this repository.
- The PostgreSQL add-on must be linked before the first deploy (
POSTGRESQL_ADDON_URI) — the app exits at startup without it - Database:
xxs_smlplan with encryption at rest (daily backups, 7 retained); encryption is chosen at creation only and the DEV plan does not offer it - Pool sizing:
DB_POOL_MAX(default 2) × number of instances must stay below the add-on's connection limit — a redeploy briefly doubles the instances (up to 4 with a 2-instance max: 4 × 2 = 8 ≤ 45) clevercloud/rust.jsonis picked up by the platform at build time (build log:Configuration file detected: …/clevercloud/rust.json); the Rust runtime itself is configured through environment variables — nothing indicates that itsappIsToBeBuiltkey changes the runtime's behaviour- Migrations are applied automatically at startup via
sqlx::migrate!()— no manual migration step needed - The binary listens on
0.0.0.0:$PORTas required by Clever Cloud - The dedicated build instance (M) must be enabled before the first deploy — it is disabled by default, and building on the nano/XS app instance stalls the deployment
- Auto-scalability: nano → XS, 1 → 2 instances — enough for a demo, the Rust binary idles well within a nano instance
- First build takes ~1–2 min on the dedicated M build instance — Clever Cloud caches compiled artifacts for subsequent deploys