Deploy
Publish the dashboard with Cloudflare Tunnel
The cloudflared service in docker-compose.yml runs a named Cloudflare tunnel. The tunnel proxies a public hostname to port 8000 on the fantasy-bot container. It reads its config from ~/.cloudflared on the Docker host. The cloudflared/ folder in this project is a reference copy only.
Set up the tunnel once per host:
Install
cloudflaredon the host.Authenticate
cloudflaredto your Cloudflare account:cloudflared tunnel loginCreate the tunnel:
cloudflared tunnel create fantasy-botRoute a hostname to the tunnel:
cloudflared tunnel route dns fantasy-bot fantasy.yourdomain.comWrite
~/.cloudflared/config.ymlon the host, using the tunnel ID from step 3:tunnel: <tunnel-id> credentials-file: /etc/cloudflared/<tunnel-id>.json ingress: - hostname: fantasy.yourdomain.com service: http://fantasy-bot:8000 - service: http_status:404In
docker-compose.yml, setDASHBOARD_URLto the hostname from step 4.Start the stack:
docker-compose up -d
Tunnel credentials belong to the tunnel, not to the machine. To move the stack to another host, copy ~/.cloudflared/config.yml and the matching <tunnel-id>.json file across. Create a second tunnel only when you want to repoint DNS to a new one.
Run the tunnel from one host at a time. The fantasy-bot container also runs the scheduler, so two running copies post every report twice.
To test without a Cloudflare account or a domain, run a quick tunnel. It prints a random trycloudflare.com URL that changes on every restart:
cloudflared tunnel --url http://localhost:8000Deploy to a remote host
The container behaves the same on any host. A move takes a file transfer and the tunnel setup on the new host. These steps assume an Ubuntu VPS.
Provision a Linux VPS and set up SSH key access.
Install Docker and the Compose plugin on the VPS:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc echo "deb [signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \ > /etc/apt/sources.list.d/docker.list apt-get update && apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-pluginCopy the project to the VPS. Skip
data/andlogs/, which the host creates fresh:scp -r gamedaybot setup.py requirements.txt Dockerfile docker-compose.yml \ .dockerignore config.env root@<vps-ip>:/opt/fantasy-football/Set up the tunnel on the VPS, so
~/.cloudflaredexists there. See Publish the dashboard with Cloudflare Tunnel.Create
data/andlogs/, then give them to the container’s non-root user:mkdir -p /opt/fantasy-football/{data,logs} chown -R 1000:1000 /opt/fantasy-football/{data,logs}Docker creates a missing bind-mount directory as root. The container runs as uid
1000, so it then fails to open the database.Build and start the stack:
cd /opt/fantasy-football docker-compose up -d --build
If another machine already runs the stack, stop it there with docker-compose down before you start the new copy. Two schedulers post every report twice.
Publish this documentation site
The site is a static Quarto website, so Cloudflare Pages can build and host it.
Render it locally first:
quarto render docsThe output lands in docs/_site.
Then create a Cloudflare Pages project connected to this repository and set:
| Setting | Value |
|---|---|
| Build command | quarto render docs |
| Build output directory | docs/_site |
| Root directory | repository root |
Cloudflare’s build image does not ship Quarto, so install it in the build command. Use this instead of the plain render:
curl -sL -o quarto.tar.gz https://github.com/quarto-dev/quarto-cli/releases/download/v1.10.18/quarto-1.10.18-linux-amd64.tar.gz && tar -xzf quarto.tar.gz && ./quarto-1.10.18/bin/quarto render docsTo publish pre-rendered output instead, commit docs/_site, leave the build command empty, and point the output directory at docs/_site. Every Pages deployment gets a *.pages.dev URL; add a custom domain in the project’s settings.