- Rust 46.9%
- Vue 26.5%
- TypeScript 24.8%
- CSS 0.7%
- JavaScript 0.6%
- Other 0.4%
| .config | ||
| .github/workflows | ||
| app | ||
| crates | ||
| migrations | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.sample | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| compose.dev.yml | ||
| config.cfg | ||
| Dockerfile | ||
| Dockerfile.rust.build | ||
| Dockerfile.web.build | ||
| Makefile | ||
| README.md | ||
| rust-toolchain.toml | ||
| rustfmt.toml | ||
Overview
Agir P.U.R.R is a full‑stack Rust + Vue 3 application:
- Backend Axum / SQLx (Postgres) – served from
/api - Frontend Vue 3 + Vite - static build served from
/by the same binary
Prerequisites
| Tool | Version (tested) | Notes |
|---|---|---|
| Rust | stable 1.88 | rustup toolchain install stable |
| pnpm | 10.x | deterministic JS installs ([pnpm.io][1]) |
| Node | 24 LTS | for the Vue build |
| Postgres | = 15 | running locally on localhost:5432 |
Local development
# 1. Clone
git clone ssh://git@git.asso-purr.eu.org:2222/ljahier/agir-purr.git
cd agir-purr
# 2. Build Rust deps (creates target/)
cargo build # dev profile
# 3. JS deps + Vite dev server
# create a `.env` file in `app/` directory with `VITE_API_URL=http://localhost:3000/api` value
cd app
pnpm install # installs dependencies
pnpm dev # http://localhost:5173
# 4. Init DB (from repo/migrations)
cd ..
cargo run -- upgrade # wraps `sqlx migrate run` under the hood
# 5. Configure encryption key (required)
cargo run -- keys add --public-key age1... --label local-dev
# 6. Run backend
cargo run -- server start --user # user API/UI runtime
# or
cargo run -- server start --admin # admin API/UI runtime
Edit: configuration is provided via environment variables (see Production config below).
Production build (Docker)
Builds happen inside Docker and export artifacts to dist/ only.
make prod x86_64-unknown-linux-gnu
Outputs:
dist/bin/agirddist/admin.zipdist/users.zip
For ARM:
make prod aarch64-unknown-linux-gnu
Note: make prod relies on Docker BuildKit for --output. Docker Desktop enables this by default.
Production run (systemd + Caddy)
- Unzip the static apps and serve them with Caddy:
unzip -q dist/admin.zip -d /var/www/agir-admin
unzip -q dist/users.zip -d /var/www/agir-users
- Run database migrations:
dist/bin/agird upgrade
- Add at least one age encryption key (required before server startup):
dist/bin/agird keys add --public-key age1... --label primary
- Run two daemons using the same binary but different env vars:
dist/bin/agird server start --admin
dist/bin/agird server start --user
Use systemd EnvironmentFile= for shared config and Environment= to override per daemon (e.g. UNIX_SOCKS_PATH and CORS_ORIGIN).
Production config (env vars)
Required:
DATABASE_URLLISTEN_ADDRUPLOADS_DIRCORS_ORIGINTOTP_ISSUERTOTP_ENCRYPTION_KEY(64 hex chars)SESSION_TTL_SECONDSDOCUMENSO_API_URLDOCUMENSO_APP_URLDOCUMENSO_API_KEYDOCUMENSO_TEMPLATE_IDDOCUMENSO_WEBHOOK_SECRET
Optional:
UNIX_SOCKS_PATH(if set, binds a Unix domain socket instead ofLISTEN_ADDR)COOKIE_SECURE(defaults totrue)CSP(if set, sent asContent-Security-Policy)RUST_LOG(standard Rust log filter, e.g.info,agird=debug)
The binary reads .env at startup (via dotenvy) if present, but in production it is typical to set env vars via systemd.
Encryption keys
Age public keys are now stored in Postgres (encryption_keys table), not in env vars.
The server refuses to start when no key is configured.
New mandat files are encrypted for all configured public keys.
# list configured keys
agird keys list
# add a key
agird keys add --public-key age1... --label primary
# remove by UUID or label (cannot remove the last remaining key)
agird keys remove <id-or-label>
# re-encrypt existing .age files using current DB public keys
# --identity points to an age identity file containing private key(s)
agird keys regenerate --identity /path/to/identities.txt
Generate TypeScript SDK
cargo run --features openapi -- export-openapi -o app/openapi-admin.json --admin
cargo run --features openapi -- export-openapi -o app/openapi-admin.json
cd app && npm run generate-client
Output in sdk/agir-user/src/ with typed API client.