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:

  1. Install cloudflared on the host.

  2. Authenticate cloudflared to your Cloudflare account:

    cloudflared tunnel login
  3. Create the tunnel:

    cloudflared tunnel create fantasy-bot
  4. Route a hostname to the tunnel:

    cloudflared tunnel route dns fantasy-bot fantasy.yourdomain.com
  5. Write ~/.cloudflared/config.yml on 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:404
  6. In docker-compose.yml, set DASHBOARD_URL to the hostname from step 4.

  7. 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:8000

Deploy 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.

  1. Provision a Linux VPS and set up SSH key access.

  2. 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-plugin
  3. Copy the project to the VPS. Skip data/ and logs/, 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/
  4. Set up the tunnel on the VPS, so ~/.cloudflared exists there. See Publish the dashboard with Cloudflare Tunnel.

  5. Create data/ and logs/, 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.

  6. 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 docs

The 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 docs

To 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.