Quickstart
Let's discover Caddy Snake in less than 5 minutes.
Caddy Snake is a Caddy plugin that lets you run Python web apps directly inside Caddy — no reverse proxy needed. The plugin spawns Python worker subprocesses and forwards requests over a Unix domain socket (loopback TCP on Windows), so you do not need a separate Gunicorn or Uvicorn process.
Works with Flask, Django, FastAPI, and any other WSGI/ASGI framework.
Option 1: Install from PyPI
The fastest way to get started. Install with pip and you're ready to go:
pip install caddysnake
This installs the caddysnake command, which is a thin wrapper around a pre-compiled Caddy binary with the caddy-snake plugin. No C compiler or manual build step required — workers use the Python interpreter from your environment.
Available on PyPI for Python 3.12 through 3.14 on Linux and macOS (x86_64 and ARM64).
Usage
# Start a WSGI server
caddysnake --server-type wsgi --app main:app
# Start an ASGI server
caddysnake --server-type asgi --app main:app
# Start an ESGI server
caddysnake --server-type esgi --app main:application
This starts a server on port 9080 serving your app. See caddysnake --help for all available options. Python-handler flags match the Caddyfile python block; see the configuration reference for the full list.
| Flag | Description | Default |
|---|---|---|
--server-type wsgi|asgi|esgi | Required. Type of Python app | — |
--app <module:var> | Required. Python module and app variable (e.g. main:app) | — |
--domain <example.com> | Enable HTTPS with automatic certificates | — |
--listen <addr> | Custom listen address | :9080 |
--workers <count> | Number of worker processes | CPU count |
--venv <path> | Path to a Python virtual environment | — |
--working-dir <path> | Working directory for the Python app | — |
--env-file <path> | Dotenv file for worker env (repeatable) | — |
--env-var NAME=VALUE | Inline worker env var (repeatable) | — |
--start-timeout=<dur|-1|forever> | Worker readiness wait (=-1 or forever for indefinite) | 120s |
--runtime <name> | Worker runtime (see runtime) | per interface |
--lifespan on|off | ASGI lifespan events | off |
--static-path <path> | Serve a static files directory | — |
--static-route <route> | Route prefix for static files | /static |
--debug | Enable debug logging | false |
--access-logs | Enable access logs | false |
--autoreload | Watch .py files and reload on changes | false |
Example
pip install caddysnake fastapi
caddysnake \
--server-type asgi \
--app main:app \
--workers 4 \
--static-path ./static \
--access-logs
The caddysnake PyPI package bundles a Caddy binary built with the caddy-snake plugin using maturin. Under the hood it runs caddy python-server with the same flags. See how the CLI works for more details.
Option 2: Download a pre-built binary
Download a self-contained Caddy binary with Python embedded from the latest release. No system Python required — everything is bundled into a single executable.
# Download and extract
tar -xzf caddy-standalone-3.13-x86_64_v2-unknown-linux-gnu.tar.gz
# Start a server
./caddy python-server --server-type wsgi --app main:app
Pre-built binaries are available for Python 3.12 through 3.14 (including 3.13-nogil and 3.14-nogil) on Linux and macOS (x86_64 and ARM64). See the Pre-built Binaries page for details on how they work.
Option 3: Build from source
CGO_ENABLED=0 xcaddy build --with github.com/mliezun/caddy-snake
Requirements
- Python >= 3.12 (runtime — used by worker subprocesses)
- Go >= 1.26 and xcaddy
Install on Ubuntu 24.04:
sudo apt-get install python3 golang
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
Example usage: FastAPI
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello-world")
def hello():
return "Hello world!"
Caddyfile
http://localhost:9080 {
python /* {
module_asgi "main:app"
lifespan on
}
}
Run:
pip install fastapi
./caddy run --config Caddyfile
curl http://localhost:9080/hello-world
# Hello world!
It's possible to enable/disable lifespan events by adding the lifespan on|off directive to your Caddy configuration. In the above case the lifespan events are enabled. Omitting the directive disables them by default.
Example usage: Flask
main.py
from flask import Flask
app = Flask(__name__)
@app.route("/hello-world")
def hello():
return "Hello world!"
Caddyfile
http://localhost:9080 {
python /* {
module_wsgi "main:app"
}
}
Run:
pip install Flask
./caddy run --config Caddyfile
curl http://localhost:9080/hello-world
# Hello world!
Option 4: Use a Docker image
Docker images are available with Python 3.12, 3.13, and 3.14:
FROM mliezun/caddy-snake:latest-py3.13
WORKDIR /app
COPY . /app
CMD ["caddy", "run", "--config", "/app/Caddyfile"]
Images are published to both registries:
Build with Docker
There's a template file in the project: builder.Dockerfile. It supports build arguments to configure which Python or Go version to use.
# Build the Docker image
docker build -f builder.Dockerfile --build-arg PY_VERSION=3.13 -t caddy-snake-builder .
# Extract the caddy binary to your current directory
docker run --rm -v $(pwd):/output caddy-snake-builder
Make sure to match the Python version with your target environment.
Virtual environments
You can point Caddy Snake to a Python virtual environment using the venv directive:
python {
module_wsgi "main:app"
venv "./venv"
}
Behind the scenes, this appends venv/lib/python3.x/site-packages to sys.path so installed packages are available to your app.
The venv packages are added to the global sys.path, which means all Python apps served by Caddy share the same packages.
Per-app environment variables
Use env_file and env_var inside a python block to configure worker environment variables without setting them globally on the Caddy process. Inline env_var entries override values from env_file when both set the same name.
python {
module_wsgi "main:app"
working_dir "/var/www/myapp"
env_file "/var/www/myapp/.env"
env_var DEBUG "1"
}
See the configuration reference for precedence, dynamic placeholders, and reserved variable names.
Platform support
| Platform | Notes |
|---|---|
| Linux (x86_64) | Primary platform |
| Linux (arm64) | Full support |
| macOS | Full support |
Python versions: 3.12, 3.13, 3.13-nogil (free-threaded), 3.14, 3.14-nogil (free-threaded)
What's next?
- Learn about Installation & Distribution — PyPI, pre-built binaries, and how they work
- Learn about all Configuration Options
- See more Examples with Flask, Django, FastAPI, Socket.IO, and more
- Understand the Architecture and how it all works
- Check out the Benchmarks comparing Caddy Snake to traditional reverse proxy setups