Skip to main content

Python

A Python application serving its own HTTP, through Gunicorn or Uvicorn

A Python application serving its own HTTP, through a WSGI or ASGI server — Gunicorn, Uvicorn. Like Node and Go it is the web server as well as the application, and it replaces PHP-FPM and Nginx rather than joining them. In front of it is the platform's proxy, which terminates TLS and routes the hostname.

The image is the official Python image on Debian, slim, with uv, a compiler and the MySQL and PostgreSQL client headers added, so a package that builds from source — mysqlclient does — builds. Choose the version with runtime.python in vallic.yaml:

version: 1
type: python

runtime:
  python: '3.14'

build:
  steps:
    - uv sync --locked --no-dev --no-editable
  cache:
    - .venv

start: python -m gunicorn app:app
port: 8000

Run everything as python -m … — the server, workers, cron and deploy steps. The build installs into .venv in the checkout, and the release is that checkout moved: python is the release's own wherever it runs, while a script such as bin/gunicorn still names the build's path inside it. For the same reason, install without --editable.

With no start, the image runs python -m gunicorn, which reads the application from gunicorn.conf.py (wsgi_app = "app:app"). Gunicorn listens on PORT — 8000 unless port says otherwise — on every address, and starts WEB_CONCURRENCY workers, 2 unless you set it on the service (see Service settings). uv's and pip's download caches are kept between builds for you, and so is .venv when the build names it.

The image's Python is the one used, whatever a .python-version file asks for: the version is runtime.python.

Uploads and anything else written at runtime go under /mnt/files (VALLIC_PRIVATE_DIR), which outlives the release. See Python for a fuller example, and Django for Django.

Versions

Version Status
3.15 Supported
3.14 Supported, and the default
3.13 Supported
3.12 Supported

Pin the version, not the build: name 3.14 and the platform matches it to the current build, so a security rebuild reaches you without anybody editing a repository.

What you can change

In vallic.yaml — what each one does is on Service settings:

services:
  - python:
      version: '3.14'
      environment:
        WEB_CONCURRENCY: …

Anything not on this list refuses the deploy, naming the variable — rather than being accepted and quietly ignored.