Skip to main content

Caddy web server with Tailscale plugin, packaged for pip installation

Project description

caddytail

Caddy web server with the Tailscale plugin, packaged for pip installation. Run any Flask or FastAPI app on your tailnet with one command.

Installation

pip install caddytail[flask]    # or caddytail[fastapi]

Quick Start

Write a normal Flask app — no CaddyTail-specific setup needed:

# app.py
from flask import Flask
from caddytail import get_user

app = Flask(__name__)

@app.get("/")
def index():
    user = get_user()
    return f"Hello, {user.name}!"

Run it on your tailnet:

caddytail run myapp app:app

That's it. Your app is now available at https://myapp.<tailnet>.ts.net with Tailscale authentication.

CLI

Hostname is always the first positional argument:

# Development — foreground, Ctrl-C kills everything
caddytail run <hostname> <app_ref> [--debug]

# Production — install as systemd service + tail logs
caddytail install <hostname> <app_ref> [--no-start] [--env K=V]

# Service management
caddytail status <hostname>
caddytail logs <hostname> [-n LINES] [-f]
caddytail restart <hostname>
caddytail uninstall <hostname>

# List all installed services
caddytail list

# Raw Caddy pass-through
caddytail caddy [args...]

The <app_ref> format is module:variable (like uvicorn), defaulting the variable to app:

  • app:app — import app from app.py
  • myproject.main:application — import application from myproject/main.py
  • app — shorthand for app:app

Behavior

  • run — starts Caddy + your app in the foreground. Ctrl-C kills everything.
  • install — writes a systemd unit file (ExecStart = caddytail run ...), enables, starts. If stdout is a tty, automatically tails logs. Ctrl-C stops tailing but leaves the service running.
  • uninstall — stops, disables, and removes the unit file.
  • caddy — passes all remaining args to the bundled Caddy binary.

Python API

get_user()

Returns a TailscaleUser with .name, .login, .profile_pic:

from caddytail import get_user

# Flask — no arguments needed
user = get_user()

# FastAPI — pass the Request object
user = get_user(request)

if user:
    print(user.name)        # "John Doe"
    print(user.login)       # "john@example.com"
    print(user.profile_pic) # "https://..."

login_required

Works as both a Flask decorator and a FastAPI Depends() target:

from caddytail import login_required

# Flask
@app.get("/secret")
@login_required
def secret():
    user = get_user()
    return f"Hello, {user.name}!"

# FastAPI
@app.get("/secret")
async def secret(user=Depends(login_required)):
    return {"message": f"Hello, {user.name}!"}

static()

Register static file paths to be served directly by Caddy:

from caddytail import static

static(app, "/assets/*", "./static")
static(app, "/uploads/*", "/var/www/uploads")

The runner picks these up automatically when starting Caddy.

CaddyTail class

For programmatic use (most users should use the CLI runner instead):

from caddytail import CaddyTail

caddy = CaddyTail(app, "myapp", debug=True)
caddy.run()

All ports are auto-allocated. No conflicts when running multiple apps.

FastAPI Example

from fastapi import FastAPI, Request, Depends
from caddytail import get_user, login_required

app = FastAPI()

@app.get("/")
async def index(request: Request):
    user = get_user(request)
    return {"message": f"Hello, {user.name}!"}

@app.get("/protected")
async def protected(user=Depends(login_required)):
    return {"message": f"Hello, {user.name}!"}
caddytail run myapp myproject:app

Supported Platforms

Pre-built wheels are available for:

Platform Architecture
Linux (glibc) x86_64, aarch64
macOS x86_64 (Intel), arm64 (Apple Silicon)
Windows x86_64

Building from Source

git clone https://github.com/jpc/caddytail
cd caddytail

# Install Go and xcaddy
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# Build caddy with the tailscale plugin
xcaddy build --with github.com/tailscale/caddy-tailscale --output src/caddytail/bin/caddy

# Build the wheel
pip install build
python -m build --wheel

License

This project packages Caddy (Apache 2.0 License) with the Tailscale plugin (BSD 3-Clause License).

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

caddytail-0.3.0.tar.gz (18.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

caddytail-0.3.0-py3-none-win_amd64.whl (21.4 MB view details)

Uploaded Python 3Windows x86-64

caddytail-0.3.0-py3-none-manylinux2014_x86_64.whl (21.2 MB view details)

Uploaded Python 3

caddytail-0.3.0-py3-none-manylinux2014_aarch64.whl (19.3 MB view details)

Uploaded Python 3

caddytail-0.3.0-py3-none-macosx_11_0_arm64.whl (19.9 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

caddytail-0.3.0-py3-none-macosx_10_15_x86_64.whl (21.4 MB view details)

Uploaded Python 3macOS 10.15+ x86-64

File details

Details for the file caddytail-0.3.0.tar.gz.

File metadata

  • Download URL: caddytail-0.3.0.tar.gz
  • Upload date:
  • Size: 18.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for caddytail-0.3.0.tar.gz
Algorithm Hash digest
SHA256 82621d796985b0f95ebc8901ce6efc2947cf9a70848cf1c9df3da9655cb0c5d7
MD5 aba3ab7a8f008e40f55475a247e261c6
BLAKE2b-256 11a56f3f97aed3a51a88ffc2b8495bac219dd367a8bdb4e3b44917eb7edbb17a

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0.tar.gz:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddytail-0.3.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: caddytail-0.3.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 21.4 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for caddytail-0.3.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 23a6eabf52d5ee0555e05e1b31ab5c00a18e79ef3e881fcd196cca382138fb1b
MD5 521c3932a9fd2493cf1db7998ff8b635
BLAKE2b-256 5b6d03cfcbea9d6320e1fba9894b0c4b5886666db12877945c947e83b5bd1c28

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0-py3-none-win_amd64.whl:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddytail-0.3.0-py3-none-manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for caddytail-0.3.0-py3-none-manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ac295a83ed98126126ab33d84e16d44f876393e02a7b62631f4c0dd16b1057ff
MD5 be1ff959df5e4b692798b079011c1053
BLAKE2b-256 b784447682601544e833301cd0e06aa1cd1d79b42190ef07df35aea1a7240b7c

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0-py3-none-manylinux2014_x86_64.whl:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddytail-0.3.0-py3-none-manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for caddytail-0.3.0-py3-none-manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 53204e042491789f78047ac76fc161edc593e2dac4f0f0dd30545caa2097a3d9
MD5 06de8fffa018bf7540fb27ca185a5639
BLAKE2b-256 5e0c844c4afad865d6425347e0f2b8717fa89eeb2a1f59f75b0188edf0e46455

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0-py3-none-manylinux2014_aarch64.whl:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddytail-0.3.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for caddytail-0.3.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3338ba203c0f253368c5c912dc79473c69d87ad38577c04093bb687a667ffb9d
MD5 4a735300d5d4f66edde97c88735cd1dd
BLAKE2b-256 010a5443d3e248e92aa1c9e0387a1f23e4d9d63ded7321902a12a51192bdd6d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0-py3-none-macosx_11_0_arm64.whl:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file caddytail-0.3.0-py3-none-macosx_10_15_x86_64.whl.

File metadata

File hashes

Hashes for caddytail-0.3.0-py3-none-macosx_10_15_x86_64.whl
Algorithm Hash digest
SHA256 a61f869c1102aaa96f4c3e1520296cae9163b3ad3b85146c423d0251ed484f6f
MD5 3ad164c7e745c2bb318d2dfdd502048c
BLAKE2b-256 c144765a443ecb644777ec7e3190720518968059d7093fd7213ca47bde8e6984

See more details on using hashes here.

Provenance

The following attestation bundles were made for caddytail-0.3.0-py3-none-macosx_10_15_x86_64.whl:

Publisher: build.yml on jpc/caddytail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page