Cache Management
The Bovine Pages Server utilizes Redis or Valkey for caching to enhance performance and facilitate advanced features. The cache stores file content, custom domain mappings, password hashes, directory listings, and Traefik router configurations.
Cache Key Structure
File Content Cache
username:repository:filepath
Examples:
squarecows:bovine-website:public/index.html
john:my-blog:public/assets/style.css
alice:docs:public/api/v1/reference.html
Custom Domain Mappings
Forward Mapping:
custom_domain:bovine.squarecows.com
custom_domain:www.example.com
Reverse Mapping:
squarecows:bovine-website
john:personal-site
Password Hash Cache
password_hash:username:repository
Examples:
password_hash:squarecows:private-docs
password_hash:alice:team-wiki
Traefik Router Configurations
traefik/http/routers/{sanitized-domain}/{property}
Examples:
traefik/http/routers/custom-bovine-squarecows-com/entrypoints
traefik/http/routers/custom-bovine-squarecows-com/rule
traefik/http/routers/custom-bovine-squarecows-com/service
traefik/http/routers/custom-bovine-squarecows-com/middlewares
traefik/http/routers/custom-bovine-squarecows-com/tls/certresolver
traefik/http/routers/custom-bovine-squarecows-com/priority
Accessing Redis/Valkey CLI
Docker/Podman Setup
# List all containers
docker ps
# Find Redis/Valkey container
docker ps | grep -E "redis|valkey"
Connection Methods
Method 1: Direct Command Execution
# Redis
docker exec <container-name> redis-cli <command>
# Valkey
docker exec <container-name> valkey-cli <command>
Method 2: Interactive Shell
# Redis
docker exec -it <container-name> redis-cli
# Valkey
docker exec -it <container-name> valkey-cli
Method 3: Container Shell + CLI
# Enter container
docker exec -it <container-name> sh
# Then run CLI commands
redis-cli
# or
valkey-cli
With Password Authentication
# Add -a flag
docker exec <container-name> redis-cli -a your-password <command>
# Or in interactive mode, authenticate after connecting
docker exec -it <container-name> redis-cli
127.0.0.1:6379> AUTH your-password
OK
Inspecting Cache Contents
View All Keys
# Redis
docker exec redis redis-cli KEYS "*"
# Valkey
docker exec valkey valkey-cli KEYS "*"
Scan Keys (Recommended for Production)
# Scan all keys (safer than KEYS)
docker exec redis redis-cli --scan
# Scan with pattern
docker exec redis redis-cli --scan --pattern "*bovine*"
# Count total keys
docker exec redis redis-cli DBSIZE
View Specific Key Value
# Get a single key
docker exec redis redis-cli GET "custom_domain:bovine.squarecows.com"
# Example output: squarecows:bovine-website
Check Key Type and TTL
# Check key type
docker exec redis redis-cli TYPE "custom_domain:bovine.squarecows.com"
# Check time-to-live (-1 = no expiration, -2 = doesn't exist)
docker exec redis redis-cli TTL "custom_domain:bovine.squarecows.com"
# Check if key exists
docker exec redis redis-cli EXISTS "custom_domain:bovine.squarecows.com"
Search for Keys by Pattern
# Find all keys for a specific user
docker exec redis redis-cli --scan --pattern "squarecows:*"
# Find all custom domains
docker exec redis redis-cli --scan --pattern "custom_domain:*"
# Find all password hashes
docker exec redis redis-cli --scan --pattern "password_hash:*"
# Find all Traefik router configs
docker exec redis redis-cli --scan --pattern "traefik/http/routers/*"
Flushing Cache
Flush Cache for Specific Website
Custom Domain Site (e.g., bovine.squarecows.com)
Step 1: Find what repository the domain maps to
docker exec redis redis-cli GET custom_domain:bovine.squarecows.com
# Output: squarecows:bovine-website
Step 2: Delete all cached content
# Redis
docker exec redis sh -c "redis-cli --scan --pattern 'squarecows:bovine-website:*' | xargs -r redis-cli DEL"
# Valkey
docker exec valkey sh -c "valkey-cli --scan --pattern 'squarecows:bovine-website:*' | xargs -r valkey-cli DEL"
Step 3: Delete custom domain mappings
# Redis
docker exec redis redis-cli DEL custom_domain:bovine.squarecows.com
docker exec redis redis-cli DEL squarecows:bovine-website
# Valkey
docker exec valkey valkey-cli DEL custom_domain:bovine.squarecows.com
docker exec valkey valkey-cli DEL squarecows:bovine-website
Step 4: Delete Traefik router configurations
# Redis (sanitized domain: bovine.squarecows.com → bovine-squarecows-com)
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/entrypoints
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/rule
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/service
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/middlewares
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/tls/certresolver
docker exec redis redis-cli DEL traefik/http/routers/custom-bovine-squarecows-com/priority
# Valkey (same commands, just replace redis-cli with valkey-cli)
Quick Method: Delete Everything Related to Domain
# Redis
docker exec redis sh -c "redis-cli --scan --pattern '*bovine.squarecows.com*' | xargs -r redis-cli DEL"
docker exec redis sh -c "redis-cli --scan --pattern '*bovine-squarecows-com*' | xargs -r redis-cli DEL"
# Valkey
docker exec valkey sh -c "valkey-cli --scan --pattern '*bovine.squarecows.com*' | xargs -r valkey-cli DEL"
docker exec valkey sh -c "valkey-cli --scan --pattern '*bovine-squarecows-com*' | xargs -r valkey-cli DEL"
Pages Domain Site (e.g., john.pages.example.com/blog)
Flush all cached content for a repository:
# Redis
docker exec redis sh -c "redis-cli --scan --pattern 'john:blog:*' | xargs -r redis-cli DEL"
# Valkey
docker exec valkey sh -c "valkey-cli --scan --pattern 'john:blog:*' | xargs -r valkey-cli DEL"
Delete password hash (if password protected):
# Redis
docker exec redis redis-cli DEL password_hash:john:blog
# Valkey
docker exec valkey valkey-cli DEL password_hash:john:blog
Flush Cache for Specific User
# Redis
docker exec redis sh -c "redis-cli --scan --pattern 'john:*' | xargs -r redis-cli DEL"
# Valkey
docker exec valkey sh -c "valkey-cli --scan --pattern 'john:*' | xargs -r valkey-cli DEL"
Flush Entire Cache
# Redis
docker exec redis redis-cli FLUSHDB
# Valkey
docker exec valkey valkey-cli FLUSHDB
# Flush all databases (if using multiple)
docker exec redis redis-cli FLUSHALL
Common Cache Management Tasks
Invalidate Cache After Content Update
# Delete all cached files for the repository
docker exec redis sh -c "redis-cli --scan --pattern 'username:repository:*' | xargs -r redis-cli DEL"
# The next request will fetch fresh content from Forgejo
Remove Stale Custom Domain Mapping
# 1. Find current mapping
docker exec redis redis-cli GET custom_domain:old-domain.com
# 2. Delete forward mapping
docker exec redis redis-cli DEL custom_domain:old-domain.com
# 3. Delete reverse mapping (using output from step 1)
docker exec redis redis-cli DEL username:repository
# 4. Delete Traefik router configs
docker exec redis sh -c "redis-cli --scan --pattern 'traefik/http/routers/custom-old-domain-com/*' | xargs -r redis-cli DEL"
Clear Password Cache
# Redis
docker exec redis redis-cli DEL password_hash:username:repository
# Valkey
docker exec valkey valkey-cli DEL password_hash:username:repository
Monitor Cache Activity
# Watch commands in real-time
docker exec redis redis-cli MONITOR
# Get cache statistics
docker exec redis redis-cli INFO stats
# Check memory usage
docker exec redis redis-cli INFO memory
Automated Cache Management
Using the Cache Reaper Script
cd reaper/
python3 reaper.py --forgejo-host https://git.example.com \
--redis-host localhost \
--redis-port 6379 \
--dry-run
Scheduled Cache Cleanup
# Edit crontab
crontab -e
# Run reaper daily at 2 AM
0 2 * * * cd /path/to/reaper && python3 reaper.py --forgejo-host https://git.example.com --redis-host localhost
Troubleshooting
Cache Not Working
Check if Redis/Valkey is running:
docker ps | grep -E "redis|valkey"
docker exec redis redis-cli PING
# Expected: PONG
Check Traefik can connect to Redis:
# Check Traefik logs for Redis connection errors
docker logs traefik | grep -i redis
Verify cache configuration in middleware:
- Check
enableRedisCache: truein Traefik middleware config - Verify
redisAddresspoints to correct container/host - Test Redis connectivity:
docker exec traefik ping redis
Custom Domain Not Working
Check if domain mapping exists:
docker exec redis redis-cli GET custom_domain:yourdomain.com
# Should return: username:repository
Check if Traefik router exists:
docker exec redis redis-cli --scan --pattern "traefik/http/routers/custom-yourdomain-com/*"
# Should return 6 keys
Re-register domain:
- Delete existing mappings (see above)
- Visit the pages URL:
https://username.pages.example.com/repository/ - Check cache again - mappings should be recreated
High Memory Usage
Check cache size:
docker exec redis redis-cli INFO memory | grep used_memory_human
docker exec redis redis-cli DBSIZE
Find largest keys:
docker exec redis redis-cli --bigkeys
# Or use redis-cli memory doctor
docker exec redis redis-cli --memkeys
Reduce cache size:
- Lower cache TTL in middleware configuration
- Run cache reaper more frequently
- Flush unused cached content
- Consider increasing
maxmemoryand enabling eviction policy
Authentication Issues
Test authentication:
# Without password
docker exec redis redis-cli PING
# Error: NOAUTH Authentication required
# With password
docker exec redis redis-cli -a your-password PING
# PONG
Update Traefik middleware configuration:
redisPassword: your-redis-password
Best Practices
Production Recommendations
- Enable Redis/Valkey - Don’t rely on in-memory cache in production
- Set Appropriate TTLs - Balance freshness vs performance (default 300s is good)
- Monitor Memory - Set up alerts for high memory usage
- Regular Cleanup - Run cache reaper script daily or weekly
- Backup Strategy - Redis persistence (RDB/AOF) for critical mappings
- Security - Use password authentication for Redis/Valkey
Cache Invalidation Strategy
When to manually invalidate:
- After repository content changes
- After
.pagesfile modifications - After password changes
- When custom domain configuration changes
Automatic invalidation:
- File cache expires after TTL (default 300s)
- Directory listings expire after 60s
- Password hashes expire after 60s
Performance Tuning
Optimize cache hit rate:
- Increase TTL for rarely-changing content
- Pre-warm cache for popular pages
- Monitor cache hit/miss ratio
Optimize memory usage:
- Set
maxmemorylimit in Redis - Enable eviction policy (e.g.,
allkeys-lru) - Compress large cached values
Reference Commands
Quick Reference Card
# === INSPECTION ===
# List all keys
docker exec redis redis-cli KEYS "*"
# Scan keys (production-safe)
docker exec redis redis-cli --scan
# Get key value
docker exec redis redis-cli GET key-name
# Check if key exists
docker exec redis redis-cli EXISTS key-name
# === DELETION ===
# Delete single key
docker exec redis redis-cli DEL key-name
# Delete by pattern
docker exec redis sh -c "redis-cli --scan --pattern 'pattern:*' | xargs -r redis-cli DEL"
# Flush entire cache
docker exec redis redis-cli FLUSHDB
# === MONITORING ===
# Real-time monitoring
docker exec redis redis-cli MONITOR
# Cache statistics
docker exec redis redis-cli INFO stats
# Memory usage
docker exec redis redis-cli INFO memory
# === MAINTENANCE ===
# Count keys
docker exec redis redis-cli DBSIZE
# Find large keys
docker exec redis redis-cli --bigkeys
# Test connection
docker exec redis redis-cli PING
Additional Resources
- Cache Reaper - Automated cache cleanup
- Custom Domains - Custom domain configuration
- Password Protection - Password authentication