Skip to main content
The recommended way to run tuliprox in production is with Docker. Pre-built Alpine images are published to the GitHub Container Registry. Available image: ghcr.io/euzu/tuliprox-alpine:latest

Quick start with Docker Compose

1

Create a docker-compose.yml

Create a docker-compose.yml file in your working directory:
docker-compose.yml
services:
  tuliprox:
    container_name: tuliprox
    image: ghcr.io/euzu/tuliprox-alpine:latest
    working_dir: /app
    volumes:
      - /home/tuliprox/tuliprox:/app/tuliprox
      - /home/tuliprox/config:/app/config
      - /home/tuliprox/data:/app/data
      - /home/tuliprox/cache:/app/cache
    environment:
      - TZ=Europe/Paris
    ports:
      - "8901:8901"
    restart: unless-stopped
2

Start the container

docker compose up -d
3

Open the Web UI

Navigate to http://localhost:8901 in your browser and complete the initial configuration.

Volume mounts

MountPurpose
/app/tuliproxBinary and runtime files
/app/configConfiguration files (config.yml, source.yml, etc.)
/app/dataPersistent data, backups, and downloads
/app/cacheCache directory for playlist and metadata caching
Map these volumes to host directories you control. All paths inside the container are relative to /app.

Environment variables

VariableExampleDescription
TZEurope/ParisContainer timezone. Affects log timestamps and scheduled tasks.

Port mapping

tuliprox listens on port 8901 by default. The compose snippet "8901:8901" publishes it on the same host port.

Restart policies

Use restart: unless-stopped for most setups. For tighter control, use restart: on-failure.

Healthcheck

tuliprox supports a built-in healthcheck command:
tuliprox --healthcheck
Wire this into Docker’s healthcheck:
healthcheck:
  test: ["CMD", "/app/tuliprox", "-p", "/app/config", "--healthcheck"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 10s

Running with docker run

For a quick test without Compose:
docker run -d \
  --name tuliprox \
  -p 8901:8901 \
  -v /home/tuliprox/config:/app/config \
  -v /home/tuliprox/data:/app/data \
  -v /home/tuliprox/cache:/app/cache \
  -e TZ=Europe/Paris \
  --restart unless-stopped \
  ghcr.io/euzu/tuliprox-alpine:latest

Building the image from source

To build a local image from the repository root:
docker build --rm -f docker/Dockerfile -t tuliprox .
You can target specific architectures or final stages:
# scratch-based minimal image (x86_64)
docker build --rm -f docker/Dockerfile -t tuliprox \
  --target scratch-final \
  --build-arg RUST_TARGET=x86_64-unknown-linux-musl .

# Alpine-based image (aarch64)
docker build --rm -f docker/Dockerfile -t tuliprox \
  --target alpine-final \
  --build-arg RUST_TARGET=aarch64-unknown-linux-musl .
Available RUST_TARGET values: x86_64-unknown-linux-musl, aarch64-unknown-linux-musl, armv7-unknown-linux-musleabihf. After building, update your compose file to reference your local image:
image: tuliprox

Container templates

The repository ships ready-to-use Docker Compose templates for common production stacks under docker/container-templates/.
TemplateFolderPurpose
Traefikcontainer-templates/traefik/Reverse proxy with TLS (ACME/DNS), dashboard, security middlewares
Gluetuncontainer-templates/gluetun/VPN egress via WireGuard with SOCKS5, HTTP, and Shadowsocks sidecars
CrowdSeccontainer-templates/crowdsec/Intrusion detection with Traefik and firewall bouncers
tuliproxcontainer-templates/tuliprox/tuliprox wired for Traefik reverse proxying on port 8901

Setting up the full stack

1

Create shared Docker networks

docker network create proxy-net
docker network create crowdsec-net
2

Start Traefik

cd container-templates/traefik
touch config/acme.json && chmod 600 config/acme.json
echo "<your-dns-api-token>" > cf-token && chmod 600 cf-token
Edit .env to set TZ, TRAEFIK_DASHBOARD_CREDENTIALS, CF_API_EMAIL, and CF_DNS_API_TOKEN_FILE. Then start:
docker compose up -d
docker logs -f traefik
3

Start Gluetun (optional VPN egress)

Edit container-templates/gluetun/gluetun-02/.env.wg-02 with your WireGuard credentials, then:
docker compose -f container-templates/gluetun/gluetun-02/docker-compose.yml up -d
4

Start tuliprox

docker compose -f container-templates/tuliprox/docker-compose.yml up -d
docker logs -f tuliprox
5

Start CrowdSec (optional)

docker compose -f container-templates/crowdsec/docker-compose.yml up -d

Traefik labels for tuliprox

The tuliprox template includes Traefik labels. Adjust the hostnames and middlewares for your domain:
labels:
  - "traefik.enable=true"

  # HTTP
  - "traefik.http.routers.tuliprox.entrypoints=web"
  - "traefik.http.routers.tuliprox.rule=Host(`cdn.example.com`)"
  - "traefik.http.routers.tuliprox.middlewares=redirect-to-https@file"

  # HTTPS
  - "traefik.http.routers.tuliprox-secure.entrypoints=websecure"
  - "traefik.http.routers.tuliprox-secure.rule=Host(`cdn.example.com`)"
  - "traefik.http.routers.tuliprox-secure.tls=true"
  - "traefik.http.routers.tuliprox-secure.tls.certresolver=cloudflare"
  - "traefik.http.routers.tuliprox-secure.middlewares=default-security-headers@file"

  # Service port
  - "traefik.http.services.tuliprox.loadbalancer.server.port=8901"
Replace cdn.example.com and all other placeholder hostnames with your actual domain. The templates ship with example domains like cdn.tuliprox.io that are not functional.

Build docs developers (and LLMs) love