rs_maps/README.md
2026-08-03 09:42:13 +01:00

114 lines
3.7 KiB
Markdown

<!-- README.md -->
# Waymark — build and deploy
Single Rust binary + one rootless Postgres container. See `DESIGN.md` for the reasoning.
> **This code has not been compiled.** It was written without a Rust toolchain available,
> so treat the first `cargo build` as the real review. Expect to fix a handful of import
> paths and trait-bound details, not the structure.
## 1. Refresh dependency versions
`Cargo.toml` has plausible versions, but pin them properly:
```bash
cargo add axum -F multipart,macros
cargo add tokio -F full
cargo add sqlx --no-default-features -F runtime-tokio,tls-rustls,postgres,uuid,time,macros,migrate
cargo add tower-sessions
cargo add tower-sessions-sqlx-store -F postgres
cargo add lettre --no-default-features -F tokio1-rustls,smtp-transport,builder,pool
cargo add rust-embed -F debug-embed
cargo build
```
Two version-sensitive spots to check first if it doesn't compile:
- **`tower-sessions` / `tower-sessions-sqlx-store` must be a matching pair.** The store crate
tracks the main crate's version and they break in lockstep. Check the store's own README for
which `tower-sessions` it expects.
- **axum 0.8 changed path params from `:id` to `{id}`.** This code uses `{id}`. If you end up on
0.7 for some reason, they all need changing back.
## 2. Database
```bash
podman secret create mapserver-db-password - # type the password, then Ctrl-D
mkdir -p ~/.config/containers/systemd
cp deploy/postgres.container ~/.config/containers/systemd/
systemctl --user daemon-reload
systemctl --user start postgres
```
Migrations run automatically on startup — both `./migrations` and the session store's own.
## 3. Config
```bash
mkdir -p ~/.config/mapserver ~/gpx
cp .env.example ~/.config/mapserver/.env
chmod 600 ~/.config/mapserver/.env
$EDITOR ~/.config/mapserver/.env
```
Must change: `DATABASE_URL`, `REG_TOKEN`, `PUBLIC_URL`, `BASE_PATH`, `GPX_DIR`.
Leave `SMTP_HOST` empty for now — reset links get logged instead of emailed, and the whole flow
is testable without a provider.
## 4. Run
```bash
cargo build --release
mkdir -p ~/.local/bin && cp target/release/mapserver ~/.local/bin/
cp deploy/mapserver.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now mapserver
loginctl enable-linger "$USER" # or nothing starts at boot
journalctl --user -u mapserver -f
```
## 5. nginx
Merge `deploy/nginx-snippet.conf` into your existing TLS server block, then
`nginx -t && systemctl reload nginx`.
## 6. First account
Visit `https://your-domain/maps/`, choose "Create an account", and enter the `REG_TOKEN` from
`.env`.
---
## Testing the reset flow with real mail
`mailpit` gives you a local SMTP server and a web inbox with no signup:
```
SMTP_HOST=127.0.0.1
SMTP_PORT=1025
SMTP_TLS=none
SMTP_USERNAME=
SMTP_PASSWORD=
```
When you move to a real provider: use an app-specific password (any account with 2FA will reject
the normal one over SMTP), check SMTP isn't disabled by default on the account, and make sure
`SMTP_FROM` is an address that account may send as.
## Things worth checking by hand after the first deploy
- `curl -i https://your-domain/maps/api/gpx/file/../../etc/passwd` → 400 or 404, never a file
- Live location works (needs HTTPS; it silently fails on plain HTTP)
- Session survives `systemctl --user restart mapserver`
- Upload a >2 MB GPX — catches both the axum and nginx body limits at once
- Upload the same filename twice — second one should come back as `name-1.gpx`
- Reboot the server, confirm both units come back (this is what `enable-linger` is for)
## Unit tests
cargo test
No database needed — every test is pure: base-path normalisation, bbox parsing,
GPX filename safety, and the rate-limiter window.