Skip to content

Deploy Python with uv

Overview

uv is a modern package and project manager for Python, built in Rust. Clever Cloud provides native uv deployment support as an alternative to the legacy WSGI-based deployment (uWSGI/Gunicorn + Nginx). With uv, your application manages its own HTTP server.

Activation

Native uv deployment activates when both conditions are met:

  • A uv.lock file exists at the root of your project
  • The CC_PYTHON_UV_RUN_COMMAND environment variable is set to a valid command

If either condition is missing, the application deploys with the legacy Python backend.

Build phase

During the build phase, dependencies are installed with:

uv sync --locked --no-progress --no-dev

To install development dependencies, set ENVIRONMENT=development. The --no-dev flag is then removed.

The uv cache (~/.cache/uv) is included in the build cache to speed up subsequent deployments.

Run phase

The application starts with the command defined in CC_PYTHON_UV_RUN_COMMAND. It must start an HTTP server listening on 0.0.0.0:$PORT. Clever Cloud sets PORT to 8080 by default. Set it to 9000 when you enable at least one Request Flow middleware.

CC_RUN_COMMAND takes precedence over CC_PYTHON_UV_RUN_COMMAND if both are set.

NameDescriptionRequiredDefault
CC_PYTHON_UV_RUN_COMMANDCommand to start the application (e.g. uv run python app.py)Yes-
CC_RUN_COMMANDOverrides CC_PYTHON_UV_RUN_COMMAND if setNo-
ENVIRONMENTSet to development to include dev dependencies during buildNoproduction
PORTPort used by your HTTP serverNo8080

Differences with legacy Python deployment

With native uv deployment:

Enable health check during deployment

The healthcheck allows you to limit downtimes. Indeed, you can provide Clever Cloud with paths to check. If these paths return something other than 200, the deployment will fail.

Add one (or several) environment variable as such:

CC_HEALTH_CHECK_PATH=/my/awesome/path

Or

CC_HEALTH_CHECK_PATH_0=/my/awesome/path
CC_HEALTH_CHECK_PATH_1=/my/other/path

The deployment process checks all paths. All of them must reply with a 200 OK response code.

By default, when no environment variable (for ex: APP_HOME) is defined, the monitoring checks your repository root path /.

Example

Using the path listed above, below are the expected logs:

Response from GET /my/awesome/path is 200
Response from GET /my/other/path is 500
Health check failed:
- GET /my/other/path returned 500.
If the deployment fails after this message, please update your configuration and redeploy.

In this example, the first path is OK, but the second one failed. This gives you a hint on what failed in your application.

Best practice for healthcheck endpoints

To make the most of a healthcheck endpoint, have it check your critical dependencies. For example:

  • execute SELECT 1 + 1; on your database
  • retrieve a specific Cellar file
  • ping a specific IP through a VPN

Request Flow: Varnish, Redirection.io, OAuth2 Proxy, custom proxy

Request Flow automatically chains reverse proxies between port 8080 (public) and your application, allocating middleware ports automatically. Some services are detected from your configuration, while others must be listed explicitly in CC_REQUEST_FLOW:

  • Otoroshi Challenge: set OTOROSHI_CHALLENGE_SECRET
  • Varnish: add a clevercloud/varnish.vcl file or set CC_VARNISH_FILE
  • Redirection.io: set CC_REDIRECTIONIO_PROJECT_KEY
  • OAuth2 Proxy: set CC_REQUEST_FLOW=oauth2-proxy and its OAUTH2_PROXY_* settings

Multiple services can run simultaneously. Setting CC_REQUEST_FLOW replaces automatic detection, so list every service you need in order (e.g. oauth2-proxy,varnish). To add a custom middleware, include custom in the chain and define CC_REQUEST_FLOW_CUSTOM with @@LISTEN_PORT@@ and @@FORWARD_PORT@@ placeholders. To block public access, set CC_REQUEST_FLOW=block.

If your application manages its own HTTP server, configure it to listen on port 9000 instead of 8080 when at least one middleware is active. Clever Cloud handles this automatically for runtimes with a managed web server.

Last updated on

Did this documentation help you ?