Custom Apps

How to Deploy a Python App on a VPS Without a Dockerfile

A requirements file and one start command. Or a uv lockfile, if you want the install pinned down to the hash.

A Python web service usually needs a container file that nobody wants to own. Impreza generates it: choose the strategy python_pip, give the platform a flat requirements.txt and the command that starts your server, and it builds Python 3.13 with a virtual environment and a non root user.

If your project already uses uv, you can pin the install instead, with pyproject.toml and uv.lock.

What you get

  • Python 3.13 in a virtual environment, built without a container file
  • Two dependency paths: a flat requirements.txt, or a locked uv project
  • Your own start command, run as a non root user
  • Port 8000 by default, with PORT and HOST supplied to the process
  • Health checked from inside the container, requiring 2xx with no redirect

Choose the dependency path

requirements.txt is the default and the simplest. It has to be a flat list of PyPI package names with optional extras and version specifiers, up to 32 KB. Options such as -r includes, --index-url lines, direct URLs, local paths, @ references and line continuations are all refused. That restriction is what lets the build run with no network access beyond public PyPI and no chance of a requirements file redirecting the install somewhere else.

uv is the pinned path. Set python_package_manager to [email protected] and supply pyproject.toml with uv.lock. The build runs a locked, non editable production install, so what lands in the image is exactly what the lockfile resolved. Custom uv sources, extra indexes, workspaces and resolution settings are refused; those need a Dockerfile.

What neither path can do

Neither installs system packages. A wheel that needs a compiler, a system library or a headless browser at build time is outside both recipes. Write a Dockerfile for those, which is a supported deployment mode, not a fallback.

Deploy it

Write the start command

This recipe has no default. Give it the exact production command, on one line, and bind to the supplied port:

gunicorn app:app --bind 0.0.0.0:$PORT

For an async framework, the equivalent is uvicorn main:app --host 0.0.0.0 --port $PORT. Never put a credential in this field.

Pick the folder

If the repository holds more than one project, set project_dir to the subfolder holding the dependency file. Hidden folders, parent segments and symlinked path components are rejected.

Analyze first

Send requirements.txt and the start command to the project analyzer, through the portal or your AI agent. It returns framework hints and the findings that would block the build, without fetching your repository or executing anything.

Create the deployment

Create a custom deployment with build strategy python_pip, your source, and the start command. Add python_package_manager only if you are using uv. Keep 8000 unless the app needs another port.

Set the health path

Point healthcheck_path at a route that returns 200 by itself. Add require_healthy_start so a release that never answers is treated as a failure instead of a success.

Django and Flask often answer the root path with a redirect

The probe requires a 2xx status and does not follow redirects. An app that sends / to /login or to a language prefix fails the check even though it is running perfectly. Add a small route that returns 200 with no side effects, and point the health path at it.

Migrations are a separate step, on purpose

The deploy never touches your database. Run migrations after the release is live, through app inspection and maintenance or as a scheduled task, and take a backup first. Release history can restore an image; it cannot restore a table you dropped.

After it is running

Read the runtime health of the containers, which the platform reports separately from the result of the last operation, and remember that an observation has a freshness window: a stale reading is reported as unknown rather than guessed. Reading current health needs agent 0.6.4 or newer.

When you redeploy, the start command, health path and startup policy are inherited, so later releases are one action. If a replacement fails, an eligible healthy previous release can be recovered while volumes are preserved. See recovering from a failed deploy.

Start now

Get an offshore VPS with the agent preselected, wire up automatic deploys on git push, or read the other recipes: Node, PHP and static sites.

My Apps + Impreza MCP

One platform. Two ways to start.

Deploy and manage supported apps from My Apps or a connected AI assistant. Choose an Impreza VPS, or connect a compatible server you already administer.

New infrastructure

A VPS from Impreza

From US$9 /month

1 vCPU · 1 GB RAM · 20 GB SSD
Monthly billing

  • Choose the location and resources for your project.
  • Select the optional Impreza Agent for supported app management and AI operations.
  • Connect up to 5 external servers in total while an Impreza VPS is active.

Entry size shown. Your app may need more capacity. Backup storage and other separately billed services are extra.

Configure your VPS

Keep your current host

Your existing server

First server free

One external-server connection
No Impreza VPS or account balance required

  • Connect a compatible Linux server you administer.
  • Deploy supported catalog apps or custom applications.
  • Use My Apps or an authorized AI assistant through MCP.

The connection slot is free. Your existing hosting bill, domains and backup storage are not included.

Connect your server

App management requires the Impreza Agent to be installed and online. You choose the permissions delegated to a compatible AI assistant. Review the selected configuration and final total before purchasing.