The Marreq backend is split into three Rust crates that live as
directories inside the Marreq root repository (a single Cargo
workspace, no git submodules):
| Crate | Kind | Purpose |
|---|---|---|
marreq-core |
library | Shared domain, persistence (Diesel), Rocket primitives, auth, services, routes, fairings. Used by both deployment binaries. |
marreq-server |
binary | Self-hosted deployment. Admin-managed users; no public registration. |
marreq-cloud |
binary | Hosted / SaaS deployment. Self-registration, email verification, password reset, single bootstrap site administrator. |
The root Marreq repo is a virtual Cargo workspace — it contains no Rust
source of its own. It hosts the frontend, Docker files, documentation,
mcp-server, and developer tooling. A single top-level Cargo.lock keeps
dependency versions consistent across all three crates.
Deployment mode is selected at compile time by choosing which binary to
build, rather than by flipping a Cargo feature flag. No --features server/--features cloud flag exists any more.
Marreq/ ← root repo (virtual workspace)
├── Cargo.toml ← workspace: ["marreq-core","marreq-server","marreq-cloud"]
├── Cargo.lock ← single lock-file for the whole workspace
├── Makefile ← convenience targets (see below)
├── marreq-core/ ← in-tree crate (library)
│ ├── Cargo.toml ← [lib] marreq-core
│ ├── src/ ← shared library source
│ ├── migrations/ ← Diesel migrations (schema source of truth)
│ ├── diesel.toml
│ └── scripts/ ← dev tooling & DB helpers (formerly backend/scripts/)
│ ├── db_setup.sh
│ ├── db_seed.sh
│ ├── db_migrate.sh
│ ├── db_reset.sh
│ ├── db_backup.sh
│ ├── run_checks.sh
│ ├── run_tests.sh
│ ├── run_ci.sh
│ └── init_complete.sql
├── marreq-server/ ← in-tree crate (binary)
│ ├── Cargo.toml ← [[bin]] marreq-server; depends on marreq-core
│ └── src/
│ ├── main.rs ← Rocket launch, wires Server deployment mode
│ ├── deployment.rs ← impl DeploymentMode for Server
│ ├── api/ ← server-only routes (admin user management)
│ └── routes.rs ← pub fn routes() → server-only route vec
├── marreq-cloud/ ← in-tree crate (binary)
│ ├── Cargo.toml ← [[bin]] marreq-cloud; depends on marreq-core
│ └── src/
│ ├── main.rs ← Rocket launch, wires Cloud deployment mode
│ ├── deployment.rs ← impl DeploymentMode for Cloud
│ ├── api/auth_public.rs ← register, verify-email, forgot/reset-password
│ ├── services/ ← registration_service.rs (cloud-only)
│ ├── fairings/ ← cloud_admin_bootstrap.rs
│ └── routes.rs ← pub fn routes() → cloud-only route vec
├── frontend/ ← React 19 + Vite SPA
├── docker/ ← Dockerfile, docker-compose.yml, nginx config
├── docs/ ← documentation (you are here)
└── mcp-server/ ← optional Node/TypeScript MCP server for AI assistants
[workspace]
resolver = "2"
members = ["marreq-core", "marreq-server", "marreq-cloud"]
[workspace.package]
edition = "2021"
license = "AGPL-3.0-or-later"Each deployment crate declares its library dependency as:
[dependencies]
marreq-core = { path = "../marreq-core" }git clone git@github.com:MarreqSW/Marreq.git
cd Marreqcargo build --workspace# Self-hosted mode (default for most dev work)
cargo run -p marreq-server
# SaaS / hosted mode
cargo run -p marreq-cloudA top-level Makefile wraps the most common commands:
| Target | Command |
|---|---|
make server |
cargo run -p marreq-server |
make cloud |
cargo run -p marreq-cloud |
make build |
cargo build --workspace --release |
make test |
cargo test --workspace |
make fmt |
cargo fmt --all |
make lint |
cargo clippy --workspace --all-targets -- -D warnings |
make docker-server |
Build Docker image for marreq-server |
make docker-cloud |
Build Docker image for marreq-cloud |
make frontend |
cd frontend && npm run dev |
Run make help to list all targets with descriptions.
Deployment mode is chosen at compile time by selecting the binary crate — no runtime flags or Cargo features need to be toggled:
| Behaviour | marreq-server |
marreq-cloud |
|---|---|---|
| User creation | Admin-only (POST /api/users) |
Public self-registration |
| Email verification | Not required | Required on sign-up |
| Password reset | Admin resets via API | Self-service via email link |
| Site admin bootstrap | N/A | MARREQ_SITE_ADMIN_EMAIL env var |
| Public auth routes | Not mounted | /api/auth/register, /api/auth/forgot-password, etc. |
GET /api/meta/deployment |
{ "mode": "server" } |
{ "mode": "cloud" } |
| Variable | Purpose |
|---|---|
MARREQ_PUBLIC_BASE_URL |
Public SPA origin for email links. Default for direct local runs: http://localhost:8000; Docker cloud compose defaults it to http://localhost:8082. |
MARREQ_SITE_ADMIN_EMAIL |
Email of the Cloud site admin. Existing users are promoted and verified. |
MARREQ_SITE_ADMIN_BOOTSTRAP_PASSWORD |
Initial password used only when the Cloud admin does not yet exist. |
SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM_ADDRESS |
SMTP settings for Cloud auth emails and notifications. |
The SPA reads GET /api/meta/deployment to decide whether to show the
self-service registration and password-reset UI.
- Add source under
marreq-core/src/<module>/. - Expose it in
marreq-core/src/lib.rs(pub mod <module>;orpub use <module>::…). - Both deployment binaries gain access immediately via
marreq_core::<module>::…. - If the module needs dependencies not yet in
marreq-core/Cargo.toml, add them there. New shared deps go into the root[workspace.dependencies]block first; member crates reference them viadep = { workspace = true }. - If
marreq_core::deployment::current()is read from the new module, remember that every binary must register a mode at startup viaapp::build_with. There is no fallbackdefault_mode()any more — tests usemarreq_core::deployment::install_test_server_mode()from thetest-helpersfeature. - Commit the change normally — all three crates live in the same repo.
- Add source under
marreq-server/src/(e.g.src/api/my_feature.rs). - Register routes or fairings in
marreq-server/src/routes.rs(pub fn routes()) or the fairing list inmain.rs. - Commit normally — all three crates live in the same repo.
- Add source under
marreq-cloud/src/(e.g.src/api/my_feature.rs). - Register in
marreq-cloud/src/routes.rsor the fairing list inmain.rs. - Commit normally — all three crates live in the same repo.
The DeploymentMode trait lives in marreq-core::deployment. Each binary
has its own impl DeploymentMode in src/deployment.rs. Extend the trait
there if you need core to call back into deployment-specific logic.
- GitHub Actions: workflows in
.github/workflows/build and test all three crates and run the frontend test suite. The CI matrix covers bothmarreq-serverandmarreq-cloudbinaries. - Docker: see
docker/README.md. The defaultdocker/docker-compose.ymlbuilds and runsmarreq-server. A separatedocker/Dockerfile.cloudtarget produces themarreq-cloudimage. Thedocker-entrypoint.shapplies Diesel migrations before launch.
Migrations and dev-helper scripts live inside the marreq-core crate:
- Schema migrations:
marreq-core/migrations/*/up.sql(Diesel, shared by both binaries). - Diesel config:
marreq-core/diesel.toml. - Helper scripts:
marreq-core/scripts/—db_setup.sh,db_seed.sh,db_migrate.sh,db_reset.sh,db_backup.sh,run_checks.sh,run_tests.sh,run_ci.sh,init_complete.sql.
See the setup guide for the end-to-end local flows, and the database setup guide for full schema/setup details.
The legacy backend/ single-crate layout was retired on 2026-04-27 as
part of the 3-crate workspace restructure. The old tree is still reachable
in the git history of the root repository. Cargo features --features server and --features cloud no longer exist; choose the binary
(-p marreq-server or -p marreq-cloud) instead.
Follow-up cleanup landed shortly after retirement:
marreq_core::app::build()andmarreq_core::deployment::default_mode()(the legacy fallbacks kept alive whilebackend/was being torn down) were removed. Each binary must callmarreq_core::app::build_with(mode, routes, fairings)at startup; tests usemarreq_core::deployment::install_test_server_mode()(gated on thetest-helpersCargo feature).- All shared dependencies now live in the root
[workspace.dependencies]block; the three memberCargo.tomlfiles reference them viadep = { workspace = true }. - The Docker
backendcompose service was renamed tomarreq-server, and a siblingmarreq-cloudservice is available behind thecloudprofile (docker compose --profile cloud up -d marreq-cloud).