Fraisier - Deployment orchestrator for the FraiseQL ecosystem. Any language, any database, any deployment target.
Project description
Fraisier
Atomic deploy + migrate with automatic rollback.
Deploy your PostgreSQL application to bare metal or Docker, with database
migrations that actually work. Preflight check, migrate up, restart, health
check — and confiture migrate down if anything fails.
preflight → migrate up → restart → health check → done
│ │
│ failure │ failure
▼ ▼
(no changes) migrate down → git rollback
Why Fraisier?
Every deployment tool treats database migrations as an afterthought:
| Tool | Migration story |
|---|---|
| Kamal | Piggybacks on Rails entrypoint — no locking, no rollback |
| Dokku | Manual dokku run <app> rake db:migrate |
| CI scripts | Brittle ssh && migrate && restart — breaks at the worst moment |
| Migration tools | Run migrations with zero awareness of deployment state |
Nobody coordinates preflight → migrate → deploy → health check → rollback as a single atomic workflow. Fraisier does.
Who is this for?
Teams running PostgreSQL applications using confiture for migrations on bare metal or Docker Compose. You've been burned by:
- A migration that locked a table during deploy
- A deploy that went live before the migration finished
- A failed migration with no way to roll back the schema
- A rollback that reverted the app but left the schema inconsistent
When NOT to use Fraisier
- Kubernetes: Use Helm, ArgoCD, or Flux. Fraisier manages systemd services and Docker Compose, not pods.
- Multiple databases: Fraisier is PostgreSQL-only via confiture. MySQL, MongoDB, etc. are not supported.
- Large fleets (10+ servers): Fraisier targets 1-3 servers. For larger fleets, use Ansible, Terraform, or a proper orchestrator.
- No database migrations: If your app doesn't have a database or doesn't use confiture, fraisier's main value proposition doesn't apply.
Compared to
| Tool | Strength | Fraisier's difference |
|---|---|---|
| Kamal | Zero-config Docker deploy | No migration awareness, no atomic rollback |
| Dokku | Heroku-like git push | Migrations are manual, no preflight checks |
| Coolify | Web UI, broad language support | Fraisier is CLI-first, PostgreSQL-deep |
| Ansible | Infrastructure automation | Fraisier is deploy-only, not infra management |
Quickstart
1. Install
pip install fraisier
# or
uv add fraisier
2. Initialize
fraisier init
This creates a fraises.yaml with sensible defaults.
3. Preview
fraisier deploy my_api production --dry-run
╭──────── DRY RUN ────────╮
│ Target my_api -> production
│ Strategy migrate
│ Preflight check reversibility + duplicates
│ Migration confiture migrate up
│ Restart gunicorn-myapi.service
│ Health http://localhost:8000/health (timeout: 30s)
│ Rollback confiture migrate down (if health check fails)
╰─────────────────────────╯
4. Deploy
fraisier deploy my_api production
5. Ship (bump + commit + push + deploy)
fraisier ship patch # 1.0.0 -> 1.0.1, commit, push, deploy
fraisier ship patch --no-deploy # Skip deploy after push
How It Works
Deployment strategies
Three database-aware strategies, configured per environment:
| Strategy | Environment | What it does |
|---|---|---|
rebuild |
development | Drop DB, rebuild schema from scratch via confiture migrate rebuild |
restore_migrate |
staging | Restore production backup, then confiture migrate up |
migrate |
production | Preflight → confiture migrate up → restart → health check. Rollback via confiture migrate down on failure |
Rollback
When a health check fails after migration, Fraisier:
- Calls
confiture migrate down --steps=Nto reverse exactly the migrations applied - Checks out the previous git commit
- Restarts the service
Use --no-rollback to deploy irreversible migrations (those without down files).
Configuration
Fraisier reads fraises.yaml. A fraise is a deployable service (API, worker, ETL, scheduled job).
fraises:
my_api:
type: api
environments:
production:
branch: main
app_path: /var/www/my-api
systemd_service: gunicorn-myapi.service
database:
name: myapp_production
strategy: migrate
confiture_config: confiture.yaml
health_check:
url: http://localhost:8000/health
timeout: 30
branch_mapping:
main:
fraise: my_api
environment: production
CLI Reference
Core
fraisier init Scaffold fraises.yaml
fraisier deploy <fraise> <env> [--dry-run] Deploy a fraise
fraisier deploy <fraise> <env> --no-rollback Allow irreversible migrations
fraisier ship patch|minor|major [--dry-run] Bump, commit, push, deploy
fraisier ship patch --no-deploy Ship without deploying
fraisier list [--flat] List all fraises
fraisier status <fraise> <env> Check fraise status
fraisier rollback <fraise> <env> Roll back to previous version
fraisier health [--json] Check all service health
Database
fraisier db migrate <fraise> -e <env> Run database migrations
fraisier db reset <fraise> -e <env> Reset from template (dev)
fraisier backup <fraise> -e <env> Database backup
Infrastructure
fraisier scaffold [--dry-run] Generate systemd, nginx, CI files
fraisier providers List deployment providers
fraisier provider-test <type> Run provider pre-flight checks
Versioning
fraisier version show Show version.json
fraisier version bump patch|minor|major Bump version atomically
Deployment Providers
| Provider | Description |
|---|---|
bare_metal |
SSH + systemd — the default for VPS deployments |
docker_compose |
Docker Compose stacks with container exec for migrations |
Git Providers
Auto-detected from webhook headers. Supports per-fraise overrides.
| Provider | Self-hosted |
|---|---|
| GitHub / GitHub Enterprise | Yes |
| GitLab / self-hosted GitLab | Yes |
| Gitea / Forgejo | Yes |
| Bitbucket Cloud / Server | Yes |
Webhook Server
Event-driven deploys triggered by git push:
fraisier-webhook # starts on port 8080
Configure your Git server to send push events to https://your-server/webhook.
The webhook auto-detects the Git provider from request headers.
Part of the FraiseQL Ecosystem
| Tool | Purpose |
|---|---|
| confiture | PostgreSQL schema migrations |
| pgGit | Database version control |
| fraiseql | Compiled GraphQL engine (Rust runtime) |
| pg_tviews | Incremental materialized views |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fraisier-0.3.8.tar.gz.
File metadata
- Download URL: fraisier-0.3.8.tar.gz
- Upload date:
- Size: 436.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b76d97e21cd3e361aa4d7e200558e2ca9e38b09e6fffd5b2a3d7d511f278c37
|
|
| MD5 |
25b905aa2c49f66a8c001adacc99b8c4
|
|
| BLAKE2b-256 |
5a889a6c9c3c0ae558e0bbf719b373daf813b96d3f7e473f8e531bfe24461611
|
File details
Details for the file fraisier-0.3.8-py3-none-any.whl.
File metadata
- Download URL: fraisier-0.3.8-py3-none-any.whl
- Upload date:
- Size: 192.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5c3fcf8b293cee477e10fa4d4febfcf371c3eb2a8dd8ce1320b40207a48c809
|
|
| MD5 |
95e11bad6e1c4c6c957c1dacc59e524b
|
|
| BLAKE2b-256 |
5645a194b4bf85a9e9eebce109c8f4b53f0cc6c5f411e36609c0ba1d3a634a2b
|