Deployment
Almasix is an ASGI application. In production you run Uvicorn (or another
ASGI server) behind a reverse proxy, keep APP_DEBUG off, migrate before
traffic hits new code, and run queue workers as separate processes.
This page is about deploying your app. A short section at the end covers how the Almasix framework itself is published to PyPI, for open-source consumers who want that picture.
Server requirements
Section titled “Server requirements”- Python 3.11+
- An ASGI server — Uvicorn is what
smith serveuses - A reverse proxy (nginx, Caddy, Traefik, a cloud load balancer) that terminates TLS and forwards to the app
- Whatever databases, Redis, or mail services your
config/*.pypoints at
Environment and secrets
Section titled “Environment and secrets”Never commit .env. On the host or in the orchestrator, set at least:
| Variable | Production expectation |
|---|---|
APP_ENV |
production |
APP_DEBUG |
false — debug pages and Vite comments must not ship |
APP_KEY |
A long random secret (smith key:generate once, then inject) |
APP_URL |
The public origin, including scheme |
Database, Redis, mail, and queue credentials come from the same env file or from your platform’s secret store. Prefer injecting secrets at runtime over baking them into images.
Serving the application
Section titled “Serving the application”From the application root:
smith serve --host 0.0.0.0 --port 8000 --workers 4 --no-reload --proxy-headers| Flag | Role |
|---|---|
--workers |
Uvicorn worker processes (reload turns off automatically when > 1) |
--no-reload |
Required for production even with one worker |
--proxy-headers |
Honour X-Forwarded-* from the reverse proxy |
--forwarded-allow-ips |
Which proxy IPs may set those headers (default *) |
Point the ASGI import at bootstrap.app:asgi (the scaffold default). Equivalent
bare Uvicorn:
uvicorn bootstrap.app:asgi --host 0.0.0.0 --port 8000 --workers 4 --proxy-headersTrusted proxies inside the app
Section titled “Trusted proxies inside the app”smith serve --proxy-headers tells Uvicorn to trust forwarded headers. For
request IP / scheme helpers inside Almasix middleware, also trust proxies in
bootstrap/app.py:
from almasix.http import HEADER_X_FORWARDED_ALL
def configure_middleware(middleware: Middleware) -> None: middleware.trust_proxies(at="*", headers=HEADER_X_FORWARDED_ALL) middleware.trust_hosts(at=["example.com", "*.example.com"])See Middleware.
Static assets
Section titled “Static assets”Vite writes into public/build/. The HTTP kernel mounts public/{css,js,images,fonts,build}
when those folders exist. Build assets in CI or in the image:
npm ci && npm run buildA CDN or the reverse proxy can still front /build if you prefer.
Health checks
Section titled “Health checks”Every application created with Application.configure(...).create() registers
GET /up by default — an empty 200 outside the Almasix middleware stacks,
so smith down does not take the probe offline. Point your load balancer at it.
application = ( Application.configure(BASE_PATH) .with_middleware(configure_middleware) .with_health("/up") # default; pass None to disable .create())Optimize before traffic
Section titled “Optimize before traffic”smith optimizeThat compile-checks every Prism template (view:cache). Config, routes, and
event listeners are not written to disk caches: an ASGI process boots once
and serves for its lifetime, so those caches would save almost nothing and risk
serving stale values. See Smith Console.
Migrations and queue workers
Section titled “Migrations and queue workers”On each deploy, before or as the new workers start:
smith migrate --forcesmith optimizeRun queue consumers as separate long-lived processes (not inside the web workers):
smith queue:work --tries=3Schedule smith schedule:work (or cron * * * * * smith schedule:run) the same
way. See Queues and Task Scheduling.
Configure channels in config/logging.py. In containers, prefer stderr (or a
stack that includes it) so the platform collects logs. The exception Handler
reports through the logger — see Logging and Error Handling.
Bare metal
Section titled “Bare metal”- Install Python 3.11+, create a venv,
pip install -r requirements.txt(or pinalmasixand your app deps). - Place
.envwith production values;APP_DEBUG=false. smith migrate --force && smith optimize.- Run under systemd (or supervisord): one unit for
smith serve --host 127.0.0.1 --port 8000 --workers 4 --no-reload --proxy-headers, plus units forqueue:workand the scheduler. - Terminate TLS at nginx/Caddy; proxy to
127.0.0.1:8000; health-check/up.
Container
Section titled “Container”Build from the application root (the directory with bootstrap/ and
smith), not from the framework repo:
FROM python:3.13-slim
WORKDIR /appENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ APP_ENV=production \ APP_DEBUG=false
COPY pyproject.toml README.md ./COPY . .RUN pip install --no-cache-dir .
EXPOSE 8000CMD ["smith", "serve", "--host", "0.0.0.0", "--port", "8000", \ "--workers", "2", "--no-reload", "--proxy-headers"]examples/deploy/
adds a compose sketch (web + queue:work + Postgres) with an /up healthcheck.
Run migrations as a release job or an entrypoint step before workers accept traffic — do not rely on web processes to migrate.
How Almasix is published (framework)
Section titled “How Almasix is published (framework)”The framework is on PyPI. Releases use
GitHub Actions Trusted Publishing (OIDC) — see .github/workflows/publish.yml.
No API tokens are stored in the repo.
To cut a release (maintainers):
- Confirm
project.versioninpyproject.tomlandalmasix.__version__match (CI refuses a tag that disagrees with the packaged version). - Merge to
main. - Optional rehearsal: Actions → Publish → Run workflow → target
testpypi. - Create an annotated tag (for example
v0.9.0) and a GitHub Release on that tag. Publishing the Release triggers the PyPI job.
Install the global project generator with a tool installer (not system pip —
PEP 668 blocks that on many machines):
pipx install almasix# or: uv tool install almasix# pin: pipx install almasix==0.9.0Inside an application’s virtualenv, Almasix is a normal dependency
(pip install -e . / your lockfile) — that is what production images install.
Related
Section titled “Related”- Installation
- Middleware (trusted proxies / hosts)
- Security headers & CORS
- Smith Console (
optimize,serve,down/up) - Queues