added rust server
This commit is contained in:
1 parent
a2aa714a83
commit
b32eabcd12
21 files changed
+5199
-143
No files matched your search
@@ -23,9 +23,9 @@ Android ───────────┘
|
||||
|
||||
## Исходный код
|
||||
|
||||
Текущая кодовая база содержит 9 Go-файлов.
|
||||
Production runtime — один Rust-процесс: `src/main.rs`, `runtime.rs`, `config.rs`, `database.rs`, `auth.rs`, `sync.rs`, `server.rs`, `go_json.rs`. SQLite bundled через rusqlite; HTTP обслуживается axum/hyper. `runtime.rs` сохраняет socket deadlines Go (header 5s, read 15s, write 30s, idle 60s) и ограничивает graceful shutdown десятью секундами. `go_json.rs` сохраняет особенности encoding/json и исходные payload bytes. Статические файлы из `internal/httpapi/web` встроены при компиляции. Go-код сохранён как эталон совместимости и вариант rollback.
|
||||
|
||||
Пути:
|
||||
Пути сохранённой Go-реализации:
|
||||
|
||||
```text
|
||||
- internal/auth
|
||||
|
||||
@@ -1,108 +1,85 @@
|
||||
# Deployment
|
||||
|
||||
## Компоненты
|
||||
## Runtime and configuration
|
||||
|
||||
```text
|
||||
Internet
|
||||
│
|
||||
HTTPS
|
||||
│
|
||||
▼
|
||||
Reverse proxy / Load Balancer
|
||||
│
|
||||
▼
|
||||
BalanceServer
|
||||
│
|
||||
▼
|
||||
Database
|
||||
```
|
||||
The production executable is the Rust server, built with `cargo build --locked
|
||||
--release`. SQLite is bundled into the executable. The Go implementation remains
|
||||
in `cmd/balance-server` and `internal/` as a compatibility reference and rollback
|
||||
option; build it with `go build -o balance-server-go ./cmd/balance-server`.
|
||||
|
||||
## Configuration
|
||||
The Dockerfile uses a Rust 1.90 Debian Bookworm builder and a Debian Bookworm slim
|
||||
runtime, running as the unprivileged `balance` user. The image embeds the existing
|
||||
web client and uses no separate frontend process. Build dependencies and SQLite
|
||||
are compiled at image build time.
|
||||
The numeric identity remains UID 100 / GID 101, matching the original Alpine Go
|
||||
image, so existing volume permissions are preserved across the switch.
|
||||
|
||||
Все environment variables и flags должны задаваться через deployment environment, а не hard-code в Go.
|
||||
`docker compose up -d --build` publishes **http://localhost:8123** (host 8123,
|
||||
container 8080). `GET /health` is the liveness endpoint. Direct binary execution
|
||||
uses `:8080` by default. Place a TLS reverse proxy in front of the published port
|
||||
for remote access; pass `X-Forwarded-Proto: https` to enable Secure session cookies.
|
||||
|
||||
Перед production deployment составьте список переменных, которые реально читает текущий код:
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `BALANCE_ADDR` | `:8080` | HTTP listen address |
|
||||
| `BALANCE_DB_PATH` | `./data/balance.db` | SQLite file; Docker uses `/data/balance.db` |
|
||||
| `BALANCE_JWT_SECRET` | required | At least 32 characters; retain across migration |
|
||||
| `BALANCE_ACCESS_TTL` | `15m` | Go-style duration for access tokens |
|
||||
| `BALANCE_REFRESH_TTL` | `720h` | Go-style duration for refresh tokens |
|
||||
| `BALANCE_ALLOW_REGISTRATION` | `true` | Enable creation of accounts |
|
||||
| `BALANCE_CORS_ORIGINS` | empty | Comma-separated allowed browser origins |
|
||||
|
||||
```text
|
||||
- docker-compose.yml
|
||||
- docker-compose.yml
|
||||
- docker-compose.yml
|
||||
- go.mod
|
||||
- README.md
|
||||
- README.md
|
||||
- README.md
|
||||
- Dockerfile
|
||||
- Dockerfile
|
||||
- Dockerfile
|
||||
- internal/database/database.go
|
||||
- internal/database/database.go
|
||||
- internal/database/database.go
|
||||
- internal/config/config.go
|
||||
- internal/config/config.go
|
||||
- internal/config/config.go
|
||||
- internal/auth/tokens.go
|
||||
- internal/auth/tokens.go
|
||||
- internal/auth/tokens.go
|
||||
- internal/auth/password.go
|
||||
```
|
||||
Inject secrets through the deployment environment or `.env`; never put them in
|
||||
images or source control. Compose preserves the existing named `balance-data`
|
||||
volume mounted at `/data`. Keep that volume and its project name when upgrading.
|
||||
|
||||
## Docker
|
||||
## Go to Rust migration
|
||||
|
||||
Если репозиторий содержит Dockerfile/compose, используйте их как canonical deployment recipe.
|
||||
1. Build and validate the Rust binary/image before stopping production. Retain the
|
||||
previous Go executable/image and exact environment for rollback.
|
||||
2. Stop the Go service and confirm no other process writes its SQLite database.
|
||||
3. Back up the entire database directory, including `balance.db` and any
|
||||
`balance.db-wal`/`balance.db-shm` files. Protect the backup as financial data.
|
||||
Record the existing environment securely, especially `BALANCE_JWT_SECRET`.
|
||||
4. Start Rust with the **same database path/volume and JWT secret**. The schema is
|
||||
unchanged: startup creates missing tables and indexes without rewriting
|
||||
existing accounts, records, change sequences or refresh-token hashes.
|
||||
5. Check `/health`, login with an existing account, refresh an existing session,
|
||||
and sync a device with its saved cursor. Verify another device receives edits
|
||||
and tombstones. Inspect error rates without logging credentials or tokens.
|
||||
|
||||
Не включайте secrets в Docker image.
|
||||
The existing Argon2id password hashes, HS256 JWT claims, hashed refresh tokens,
|
||||
RFC3339 timestamps, entity versions and global change sequences are shared with
|
||||
Go. No export/import, cursor reset, account recreation or forced sign-out is
|
||||
required. Do not start both implementations against the same database at once.
|
||||
|
||||
## Health/readiness
|
||||
## Rollback
|
||||
|
||||
Если проект предоставляет health endpoint, load balancer должен использовать его для readiness.
|
||||
Stop Rust first. Start the retained Go executable/image with the same current
|
||||
database directory and secret. Rust-written accounts, password hashes, refresh
|
||||
sessions, records, tombstones and cursors remain readable by Go. Check health,
|
||||
login, refresh and sync again. The compatibility suite exercises both directions,
|
||||
including a second takeover back to the original implementation.
|
||||
|
||||
Database connectivity желательно проверять отдельно от liveness.
|
||||
For database corruption or an unrelated failed migration, stop all writers before
|
||||
restoring the complete backup directory. Restoring an older backup discards
|
||||
changes after that backup and may require clients to resynchronize; prefer normal
|
||||
binary rollback against the current database when it is healthy. Never overwrite
|
||||
an active database or delete a Compose volume as part of an upgrade.
|
||||
|
||||
## Database migrations
|
||||
## Validation and operations
|
||||
|
||||
Migration должна выполняться контролируемо:
|
||||
Before release run `cargo test --locked`, `cargo build --locked --release`,
|
||||
`python3 tools/compatibility.py --rust-binary target/release/balance-server`, and
|
||||
the retained reference checks `go test ./...`, `go vet ./...`, `go build ./...`.
|
||||
The differential suite uses temporary databases and loopback listeners, compares
|
||||
API/errors/security headers/assets, tests browser cookies, pagination, LWW,
|
||||
tombstones, concurrent pushes, token expiration, refresh rotation, rate limiting,
|
||||
and shared-database takeover/rollback in both directions.
|
||||
|
||||
```text
|
||||
backup
|
||||
↓
|
||||
migration
|
||||
↓
|
||||
health check
|
||||
↓
|
||||
application rollout
|
||||
```
|
||||
|
||||
Не запускайте destructive migration автоматически без backup/rollback plan.
|
||||
|
||||
## Backups
|
||||
|
||||
Финансовые данные — пользовательские данные высокой ценности.
|
||||
|
||||
Минимум:
|
||||
- регулярные DB backups;
|
||||
- retention policy;
|
||||
- периодическая проверка restore;
|
||||
- encrypted backup storage.
|
||||
|
||||
## Observability
|
||||
|
||||
Рекомендуется мониторить:
|
||||
- HTTP 5xx;
|
||||
- auth failures;
|
||||
- sync failures;
|
||||
- latency;
|
||||
- DB latency/errors;
|
||||
- active users/devices;
|
||||
- size/lag of sync change log;
|
||||
- disk/storage usage.
|
||||
|
||||
## Release checklist
|
||||
|
||||
- [ ] Tests green.
|
||||
- [ ] Database migrations проверены.
|
||||
- [ ] Backup создан.
|
||||
- [ ] Secrets injected через secure mechanism.
|
||||
- [ ] HTTPS включён.
|
||||
- [ ] Health checks работают.
|
||||
- [ ] Sync tested with both mobile clients.
|
||||
- [ ] Rollback plan готов.
|
||||
Keep regular encrypted backups with retention and restore drills. Monitor HTTP
|
||||
5xx, sync errors, authentication failures, latency, database/change-log growth
|
||||
and free disk space. The in-memory limiter allows 30 registration/login/refresh
|
||||
attempts per remote IP per minute and resets on restart; use proxy controls when
|
||||
operating a public service. Application logs must never include passwords,
|
||||
Authorization headers or tokens.
|
||||
@@ -2,29 +2,36 @@
|
||||
|
||||
## Требования
|
||||
|
||||
Проект использует Go 1.25.0.
|
||||
Production-сервер использует Rust 1.90+ и bundled SQLite. Go 1.25+ нужен для сохранённой эталонной реализации и differential-проверок. Python 3 используется без сторонних пакетов.
|
||||
|
||||
Проверить локальную версию:
|
||||
|
||||
```bash
|
||||
rustc --version
|
||||
cargo --version
|
||||
go version
|
||||
```
|
||||
|
||||
## Установка зависимостей
|
||||
|
||||
```bash
|
||||
cargo fetch --locked
|
||||
go mod download
|
||||
```
|
||||
|
||||
## Сборка
|
||||
|
||||
```bash
|
||||
cargo build --locked
|
||||
go build ./...
|
||||
```
|
||||
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
cargo test --locked
|
||||
cargo build --locked
|
||||
python3 tools/compatibility.py
|
||||
go test ./...
|
||||
```
|
||||
|
||||
@@ -37,6 +44,8 @@ go test -race ./...
|
||||
## Static checks
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo clippy --locked --all-targets -- -D warnings
|
||||
go vet ./...
|
||||
```
|
||||
|
||||
@@ -48,24 +57,24 @@ go vet ./...
|
||||
|
||||
Не коммитьте реальные credentials.
|
||||
|
||||
Пример общего workflow:
|
||||
Собрать и запустить Rust-сервер:
|
||||
|
||||
```bash
|
||||
go mod download
|
||||
go test ./...
|
||||
go build ./...
|
||||
./<server-binary>
|
||||
cargo build --locked --release
|
||||
export BALANCE_JWT_SECRET="replace-with-a-long-random-secret"
|
||||
export BALANCE_DB_PATH="./data/balance.db"
|
||||
./target/release/balance-server
|
||||
```
|
||||
|
||||
Имя binary и обязательные env vars определяются текущей entrypoint/config реализацией.
|
||||
По умолчанию сервер слушает `:8080`. Файл `.env` читает Docker Compose; при
|
||||
прямом запуске переменные нужно передать процессу через окружение.
|
||||
|
||||
## Database
|
||||
|
||||
Перед первым запуском:
|
||||
1. поднять требуемую БД;
|
||||
2. применить migrations, если проект их использует;
|
||||
3. задать connection settings;
|
||||
4. проверить health/startup logs.
|
||||
SQLite встроен в executable. При первом запуске сервер создаёт каталог,
|
||||
таблицы и индексы автоматически. Отдельный процесс БД не нужен. При переходе
|
||||
с Go сохраните существующий файл БД и `BALANCE_JWT_SECRET`; подробная
|
||||
процедура и откат описаны в [DEPLOYMENT.md](DEPLOYMENT.md).
|
||||
|
||||
## Production
|
||||
|
||||
@@ -74,11 +83,13 @@ go build ./...
|
||||
```text
|
||||
source
|
||||
↓
|
||||
go test ./...
|
||||
cargo fmt --check && cargo test --locked
|
||||
↓
|
||||
go vet ./...
|
||||
cargo clippy --locked --all-targets -- -D warnings
|
||||
↓
|
||||
go build ./...
|
||||
cargo build --locked --release
|
||||
↓
|
||||
python3 tools/compatibility.py --rust-binary target/release/balance-server
|
||||
↓
|
||||
container/package
|
||||
↓
|
||||
@@ -105,3 +116,5 @@ health check
|
||||
- concurrent sync с двух устройств;
|
||||
- login/refresh после истечения access token;
|
||||
- delete → pull на другом устройстве.
|
||||
|
||||
Production build: `cargo build --locked --release`. Прямой запуск: `BALANCE_JWT_SECRET=<secret> target/release/balance-server`, порт 8080. Docker Compose публикует порт 8123 и сохраняет прежний volume `/data`. Процедура миграции Go → Rust и rollback: [DEPLOYMENT.md](DEPLOYMENT.md).
|
||||
Reference in new issue
Block a user