5 Quick Start
Ric Harvey edited this page 2025-12-03 20:24:07 +00:00

Quick Start Guide

This guide will help you set up Bovine Pages Server with Traefik to host static sites from your Forgejo or Gitea repositories.

Prerequisites

Before you begin, ensure you have:

  • Traefik v2.0+ installed and running (Installation Guide)
  • Forgejo or Gitea instance running and accessible
  • Docker (if using Docker setup) (Get Docker)
  • Domain name configured to point to your Traefik server
  • Redis or Valkey server for full functionality (see note below)
  • Basic understanding of Traefik configuration

Important: Redis/Valkey Requirement

⚠️ Redis (or Valkey) is strongly recommended for production deployments.

While Bovine Pages Server can run with in-memory caching only, you need Redis or Valkey to unlock these critical features:

  • Custom Domain HTTPS - Automatic SSL certificate generation for custom domains requires Redis provider in Traefik
  • Persistent Caching - High-performance caching that survives plugin restarts
  • Shared Cache - Multiple Traefik instances can share the same cache
  • Custom Domain Mappings - Persistent storage of domain-to-repository mappings

Without Redis/Valkey:

  • Custom domains won't get automatic HTTPS certificates
  • Cache is lost on every plugin restart
  • Performance will be significantly degraded
  • Custom domain mappings won't persist

Quick Setup:

# Docker
docker run -d --name redis -p 6379:6379 redis:7-alpine

# Or use Valkey (Redis fork)
docker run -d --name valkey -p 6379:6379 valkey/valkey:7-alpine

See the Docker Compose example below for a complete Redis setup with Traefik.

Architecture Overview

Bovine Pages Server works as a Traefik middleware plugin:

graph LR
    A[User Browser] -->|HTTPS Request| B[Traefik Reverse Proxy]
    B -->|Middleware| C[Bovine Pages Server Plugin]
    C -->|Fetch Content| D[Forgejo/Gitea API]
    D -->|Repository Data| C
    C -->|Cache| E[(Redis Cache)]
    C -->|Static Files| B
    B -->|HTTPS Response| A

    style B fill:#37a8db,stroke:#2980b9,stroke-width:2px,color:#fff
    style C fill:#9b59b6,stroke:#8e44ad,stroke-width:2px,color:#fff
    style D fill:#27ae60,stroke:#229954,stroke-width:2px,color:#fff
    style E fill:#e74c3c,stroke:#c0392b,stroke-width:2px,color:#fff

The plugin intercepts requests matching your pages domain pattern (e.g., *.pages.example.com), fetches content from Forgejo repositories via the API, optionally caches it in Redis for performance, and serves it as static websites through Traefik.

Setup Methods

Choose your setup method based on how you run Traefik:


Docker Compose Setup

Step 1: Configure Traefik Static Configuration

Create or update your traefik.yml static configuration file:

# traefik.yml
api:
  dashboard: true

entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

certificatesResolvers:
  letsencrypt-http:
    acme:
      email: your-email@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web

# Enable plugin support
experimental:
  plugins:
    pages-server:
      moduleName: code.squarecows.com/SquareCows/pages-server
      version: v0.0.8

providers:
  docker:
    exposedByDefault: false
  file:
    directory: /etc/traefik/dynamic
    watch: true
  redis:
    endpoints:
      - "redis:6379"
    rootKey: "traefik"
    # Optional: Add password if Redis requires authentication
    # password: "your-redis-password"

Important Configuration Notes:

  • experimental.plugins enables the Bovine Pages Server plugin
  • certificatesResolvers configures automatic HTTPS with Let's Encrypt
  • providers.file allows loading dynamic configuration from files
  • providers.redis enables dynamic router registration for custom domains (required for automatic SSL)
  • Redis provider allows Bovine Pages Server to dynamically register routers for custom domains
  • See Traefik Static Configuration for more options
  • See Traefik Redis Provider for Redis-specific configuration

Step 2: Configure Dynamic Configuration

Create a dynamic configuration file for the pages server middleware and routers:

File: dynamic/pages-config.yml

# dynamic/pages-config.yml
http:
  middlewares:
    pages-server:
      plugin:
        pages-server:
          # Required settings
          pagesDomain: pages.example.com
          forgejoHost: https://git.example.com

          # Optional: Authentication for private repos
          # forgejoToken: your-api-token-here

          # Optional: Redis caching for better performance
          # enableRedisCache: true
          # redisAddress: redis:6379
          # redisPassword: your-redis-password

          # Optional: Password protection settings
          # authSecretKey: your-secret-key-here
          # authCookieDuration: 3600

          # Optional: Custom domains
          # enableCustomDomains: true
          # customDomainCacheTTL: 600

          # Optional: Traefik Redis provider integration
          # traefikRedisRouterEnabled: true
          # traefikRedisCertResolver: letsencrypt-http

  routers:
    # HTTPS router for pages domain
    pages-https:
      rule: "HostRegexp(`{subdomain:[a-z0-9-]+}.pages.example.com`)"
      entryPoints:
        - websecure
      middlewares:
        - pages-server
      service: noop@internal
      tls:
        certResolver: letsencrypt-http

    # HTTPS router for custom domains (if enabled)
    pages-custom-domains-https:
      rule: "HostRegexp(`{domain:.+}`)"
      entryPoints:
        - websecure
      middlewares:
        - pages-server
      service: noop@internal
      priority: 1
      tls:
        certResolver: letsencrypt-http

    # HTTP router (handles ACME challenges and redirects to HTTPS)
    pages-http:
      rule: "HostRegexp(`{subdomain:[a-z0-9-]+}.pages.example.com`) || HostRegexp(`{domain:.+}`)"
      entryPoints:
        - web
      middlewares:
        - pages-server
      service: noop@internal
      priority: 1

Configuration Highlights:

  • Replace pages.example.com with your actual pages domain
  • Replace git.example.com with your Forgejo/Gitea instance URL
  • The middleware automatically handles HTTPS redirects (except for ACME challenges)
  • Uses noop@internal service (Traefik's built-in no-op service)
  • See Configuration Guide for all available options

Step 3: Docker Compose File

Create or update your docker-compose.yml:

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard (optional, secure in production)
    volumes:
      # Mount Traefik configuration
      - ./traefik.yml:/etc/traefik/traefik.yml:ro
      - ./dynamic:/etc/traefik/dynamic:ro

      # Mount Docker socket for Docker provider
      - /var/run/docker.sock:/var/run/docker.sock:ro

      # Mount Let's Encrypt storage
      - ./letsencrypt:/letsencrypt
    environment:
      - TZ=UTC
    networks:
      - web

  # Optional: Redis for caching
  redis:
    image: redis:7-alpine
    container_name: redis
    restart: unless-stopped
    command: redis-server --requirepass your-redis-password
    volumes:
      - redis-data:/data
    networks:
      - web

networks:
  web:
    external: true

volumes:
  redis-data:

Docker Setup Notes:

  • Create the web network first: docker network create web
  • Traefik dashboard accessible at http://localhost:8080 (secure in production!)
  • Let's Encrypt certificates stored in ./letsencrypt/acme.json
  • See Traefik Docker Documentation for more details

Step 4: Start Services

# Create Docker network
docker network create web

# Create required directories
mkdir -p dynamic letsencrypt

# Set proper permissions for Let's Encrypt storage
touch letsencrypt/acme.json
chmod 600 letsencrypt/acme.json

# Start Traefik
docker-compose up -d

# Check logs
docker-compose logs -f traefik

Standalone Traefik Setup

If you're running Traefik without Docker, follow these steps:

Step 1: Add Plugin and Redis Provider to Traefik Configuration

Edit your traefik.yml static configuration:

# Enable plugin support
experimental:
  plugins:
    pages-server:
      moduleName: code.squarecows.com/SquareCows/pages-server
      version: v0.0.8

# Add Redis provider for dynamic router registration
providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true
  redis:
    endpoints:
      - "localhost:6379"  # Update if Redis is on different host
    rootKey: "traefik"
    # Optional: Add password if Redis requires authentication
    # password: "your-redis-password"

Note: Redis provider is required for custom domain support with automatic SSL certificates.

Step 2: Create Middleware Configuration

Create a dynamic configuration file (e.g., /etc/traefik/dynamic/pages.yml):

http:
  middlewares:
    pages-server:
      plugin:
        pages-server:
          pagesDomain: pages.example.com
          forgejoHost: https://git.example.com

Step 3: Configure Routers

Add routers to your dynamic configuration:

http:
  routers:
    pages-https:
      rule: "HostRegexp(`{subdomain:[a-z0-9-]+}.pages.example.com`)"
      entryPoints:
        - websecure
      middlewares:
        - pages-server
      service: noop@internal
      tls:
        certResolver: letsencrypt-http

Step 4: Restart Traefik

# Systemd
sudo systemctl restart traefik

# Or if running manually
traefik --configFile=/etc/traefik/traefik.yml

Setup Your First Repository

Now that Traefik is configured, let's create your first static site:

Step 1: Create Repository Structure

In your Forgejo/Gitea repository, create this structure:

your-repository/
├── .pages              # Configuration file
└── public/             # Static files directory
    ├── index.html      # Your homepage
    ├── about.html
    └── assets/
        ├── style.css
        └── logo.png

Step 2: Create .pages File

In your repository root, create a .pages file:

enabled: true

Optional Settings:

enabled: true
directory_index: true           # Enable directory listings
custom_domain: www.example.com  # Use a custom domain
password: sha256-hash-here      # Password protect your site

See Configuration Guide for all options.

Step 3: Add Your Static Files

Create a simple public/index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Static Site</title>
</head>
<body>
    <h1>Welcome to My Static Site!</h1>
    <p>Hosted with Bovine Pages Server</p>
</body>
</html>

Step 4: Commit and Push

git add .
git commit -m "Initial pages setup"
git push origin main

Step 5: Access Your Site

Your site is now live at:

https://username.pages.example.com/repository/

Replace:

  • username with your Forgejo/Gitea username
  • pages.example.com with your configured pages domain
  • repository with your repository name

Verification Steps

1. Check Traefik Dashboard

Access the Traefik dashboard (if enabled) to verify:

  • Plugin loaded successfully
  • Middleware configured
  • Routers active

2. Test Basic Functionality

# Test pages domain
curl -I https://username.pages.example.com/repository/

# Should return 200 OK and show your content

3. Check Logs

# Docker setup
docker-compose logs -f traefik

# Systemd setup
journalctl -u traefik -f

Look for:

  • Plugin initialization messages
  • No error messages about missing configuration
  • Successful requests being served

Troubleshooting

Plugin Not Loading

Problem: Traefik doesn't load the plugin

Solutions:

  1. Verify experimental.plugins section in static config
  2. Check Traefik version (requires v2.0+)
  3. Ensure internet connectivity to download plugin
  4. Check logs: docker-compose logs traefik

404 Errors

Problem: Getting 404 when accessing pages URL

Checklist:

  1. Repository has public/ folder with content
  2. Repository has .pages file with enabled: true
  3. Router rules match your domain pattern
  4. DNS points to Traefik server
  5. forgejoHost is correct in middleware config

SSL Certificate Issues

Problem: HTTPS not working or certificate errors

Solutions:

  1. Check Let's Encrypt rate limits
  2. Verify port 80 is accessible (required for HTTP challenge)
  3. Check acme.json permissions: chmod 600 acme.json
  4. Review certificate resolver configuration
  5. See Traefik ACME Documentation

Redis Connection Errors

Problem: Redis caching not working

Solutions:

  1. Verify Redis is running: docker-compose ps redis
  2. Check Redis address in middleware config
  3. Verify Redis password matches
  4. Plugin will fall back to in-memory cache if Redis unavailable

Next Steps

Now that you have Bovine Pages Server running:

  1. 📖 Read the Configuration Guide - Learn about all available options
  2. 🔒 Setup Password Protection - Secure private sites
  3. 🌐 Configure Custom Domains - Use your own domains
  4. 📁 Enable Directory Listings - Browse files without index.html
  5. 🧹 Setup Cache Reaper - Automated cleanup for production

Additional Resources

Traefik Documentation

Docker Resources

Bovine Pages Server


Support