Skip to content

valkyoth/aetherheim

Repository files navigation

Aetherheim

Aetherheim is a secure Rust CMS foundation using Axum, SurrealDB, and Fluxheim. The roadmap tracks later Leptos admin UI and Wasmtime plugin runtime milestones.

Local Infrastructure

The development stack runs SurrealDB and Fluxheim in rootless Podman while the Rust app runs locally on the host.

cp .env.podman.example .env.podman
podman compose --env-file .env.podman -f deploy/podman/podman-compose.yml up -d

Expected local endpoints:

  • Fluxheim: http://127.0.0.1:8080
  • SurrealDB: http://127.0.0.1:8000
  • Rust app upstream expected by Fluxheim: http://127.0.0.1:3000

When running behind the local Fluxheim container, bind the Rust app to 0.0.0.0:3000; Fluxheim proxies to it through host.containers.internal.

Run the full local checks:

scripts/checks.sh

This gate runs formatting, clippy, tests, cargo deny, cargo audit, cargo license, and scripts/check_latest_crates.sh so direct crate versions stay aligned with crates.io.

Run checks plus the local app, Fluxheim, and SurrealDB smoke test:

AETHERHEIM_RUN_SMOKE=1 scripts/checks.sh

The smoke gate covers the Fluxheim reverse proxy path and a compact direct manual installer path against the Rust app without a reverse proxy.

Deployment notes for manual operation, Fluxheim reverse proxy operation, and rootless Podman/Wolfi operation are tracked in docs/DEPLOYMENT.md.

The smoke test enables AETHERHEIM_ALLOW_INSECURE_INSTALLER_PASSKEY_FIXTURE=1 for deterministic API testing. Do not set that variable outside local smoke runs; it is rejected unless AETHERHEIM_ALLOW_INSECURE_LOCAL_DATABASE_PASSWORD=1 is also set. Normal installer admin creation expects a browser WebAuthn registration response.

The smoke test does not enable the insecure administrator bypass. It creates a short-lived smoke session directly in the disposable SurrealDB test database after installer completion, then exercises privileged APIs through the normal session middleware.

For a real first launch, Aetherheim creates a high-entropy installer token file with 0600 permissions and stores only the keyed token hash in SurrealDB. By default the file is written to AETHERHEIM_STORAGE_DIR/installer-token; set AETHERHEIM_INSTALLER_TOKEN_FILE to use an explicit operator-owned path. Aetherheim attempts to remove the token file after the first administrator is created and the installer is locked. The installer and site settings also support public URL aliases, entered as absolute origins such as https://example.eu, so one single-site install can serve the same public site from multiple configured domains without enabling multi-site routing or expanding administrator/passkey origins. Behind Fluxheim or another reverse proxy, configure each alias domain as a host for the same upstream and forward the original host; Aetherheim only trusts X-Forwarded-Host when forwarded headers are enabled.

Set AETHERHEIM_STORAGE_DIR to the local asset storage directory. Uploaded asset bytes are written below that root with generated uploads/ keys; public metadata responses never expose storage keys or checksums. Set AETHERHEIM_INSTANCE_ID_FILE to a persistent operator-owned path when you want the instance identity outside the storage directory; otherwise Aetherheim creates AETHERHEIM_STORAGE_DIR/instance-id on first boot.

Administrator Auth

The first-run installer creates the first administrator with a passkey, returns one-time recovery codes that the operator must store before leaving the page, and then locks itself automatically. Normal administrator login uses:

  • POST /_aetherheim/auth/passkey/options to create a short-lived discoverable WebAuthn challenge.
  • POST /_aetherheim/auth/passkey/finish to verify the assertion, update passkey state, and issue an HttpOnly, SameSite=Strict, Secure aetherheim_admin_session cookie scoped to /_aetherheim.
  • GET /_aetherheim/auth/session to check the current administrator session.
  • POST /_aetherheim/auth/logout to revoke the database-backed session and clear the browser cookie.

Session tokens are never stored in plaintext. Aetherheim stores only keyed token hashes, verifies active/non-expired sessions in SurrealDB, and requires route-specific capabilities for privileged APIs. system.admin remains the superuser override. Authorization re-loads the current user and role capabilities on each privileged request, so disabling a user or changing roles takes effect without waiting for the session to expire. User and commenter email addresses are also stored as keyed, normalized hashes instead of raw addresses or unsalted digests. Authentication routes are rate-limited and failed passkey/recovery attempts trigger a temporary client lockout using the configured security policy.

Administrator recovery codes are one-time, high-entropy fallback credentials. The installer creates the first set for the initial administrator. Plaintext codes are returned only in the creation response; Aetherheim stores only keyed hashes and short prefixes for operator identification. Recovery login consumes a matching active code for the requested username before issuing an admin session, and replayed codes are rejected. Operators can revoke unused recovery codes; revocation returns only safe metadata and records an audit event.

Roadmap

The release roadmap is tracked in docs/ROADMAP.md. The 1.0 scope includes a secure first-run installer with one-time setup token, passkey-first administrator creation, environment/proxy validation, safe site defaults, and automatic installer lockout after setup.

Licensing notes are tracked in docs/LICENSING.md. The current core license is EUPL-1.2; a future plugin/theme exception is planned for the stable Wasm extension runtime so independently developed extensions can use their own licenses through the documented API boundary.

About

Rust CMS using SurrealDB

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

  •  

Packages

 
 
 

Contributors