A community based topic aggregation platform built on atproto

build(aggregators): add Docker deployment for Reddit Highlights aggregator

Add containerized deployment configuration:
- Dockerfile: Python 3.11-slim with cron support
- docker-compose.yml: Service definition with volume mounts
- docker-entrypoint.sh: Cron setup and environment handling
- crontab: 10-minute polling schedule
- .env.example: Environment variable template

Deployment uses the same pattern as the Kagi News aggregator.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

+173
+19
aggregators/reddit-highlights/.env.example
··· 1 + # Reddit Highlights Aggregator Environment Variables 2 + # 3 + # Copy this file to .env and fill in the values. 4 + 5 + # Coves API Key (required) 6 + # Get this from your Coves aggregator registration 7 + COVES_API_KEY=ckapi_your_api_key_here 8 + 9 + # Optional: Override Coves API URL from config.yaml 10 + # COVES_API_URL=https://coves.social 11 + 12 + # Optional: Override config file path 13 + # CONFIG_PATH=config.yaml 14 + 15 + # Optional: Override state file path 16 + # STATE_FILE=data/state.json 17 + 18 + # Optional: Skip anti-detection jitter (for testing only) 19 + # SKIP_JITTER=false
+54
aggregators/reddit-highlights/Dockerfile
··· 1 + # Reddit Highlights Aggregator 2 + # Production-ready Docker image with cron scheduler 3 + 4 + FROM python:3.11-slim 5 + 6 + # Install cron and other utilities 7 + RUN apt-get update && apt-get install -y \ 8 + cron \ 9 + curl \ 10 + procps \ 11 + && rm -rf /var/lib/apt/lists/* 12 + 13 + # Set working directory 14 + WORKDIR /app 15 + 16 + # Copy requirements first for better caching 17 + COPY requirements.txt . 18 + 19 + # Install Python dependencies (production only) 20 + RUN pip install --no-cache-dir \ 21 + feedparser==6.0.11 \ 22 + requests==2.31.0 \ 23 + pyyaml==6.0.1 24 + 25 + # Copy application code 26 + COPY src/ ./src/ 27 + COPY config.yaml ./ 28 + 29 + # Create data directory for state persistence 30 + RUN mkdir -p /app/data 31 + 32 + # Copy crontab file 33 + COPY crontab /etc/cron.d/reddit-aggregator 34 + 35 + # Give execution rights on the cron job and apply it 36 + RUN chmod 0644 /etc/cron.d/reddit-aggregator && \ 37 + crontab /etc/cron.d/reddit-aggregator 38 + 39 + # Create log file to be able to run tail 40 + RUN touch /var/log/cron.log 41 + 42 + # Copy entrypoint script 43 + COPY docker-entrypoint.sh /usr/local/bin/ 44 + RUN chmod +x /usr/local/bin/docker-entrypoint.sh 45 + 46 + # Health check - verify cron is running 47 + HEALTHCHECK --interval=60s --timeout=10s --start-period=10s --retries=3 \ 48 + CMD pgrep cron || exit 1 49 + 50 + # Run the entrypoint script 51 + ENTRYPOINT ["docker-entrypoint.sh"] 52 + 53 + # Default command: tail the cron log 54 + CMD ["tail", "-f", "/var/log/cron.log"]
+8
aggregators/reddit-highlights/crontab
··· 1 + # Run Reddit Highlights aggregator every 30 minutes 2 + # The Python script adds 0-10 min random jitter for anti-detection 3 + # Effective polling interval: 30-40 minutes (varies each run) 4 + # Source environment variables exported by docker-entrypoint.sh 5 + */30 * * * * . /etc/environment; cd /app && /usr/local/bin/python -m src.main >> /var/log/cron.log 2>&1 6 + 7 + # Blank line required at end of crontab 8 +
+45
aggregators/reddit-highlights/docker-compose.yml
··· 1 + services: 2 + reddit-aggregator: 3 + build: 4 + context: . 5 + dockerfile: Dockerfile 6 + container_name: reddit-highlights-aggregator 7 + restart: unless-stopped 8 + 9 + # Environment variables 10 + environment: 11 + # Required: Coves API Key 12 + - COVES_API_KEY=${COVES_API_KEY} 13 + 14 + # Optional: Override Coves API URL 15 + - COVES_API_URL=${COVES_API_URL:-https://coves.social} 16 + 17 + # Optional: Run immediately on startup (useful for testing) 18 + - RUN_ON_STARTUP=${RUN_ON_STARTUP:-false} 19 + 20 + # Optional: Skip jitter (for testing only) 21 + - SKIP_JITTER=${SKIP_JITTER:-false} 22 + 23 + # Mount config file and state directory 24 + volumes: 25 + - ./config.yaml:/app/config.yaml:ro 26 + - ./data:/app/data # State persistence for deduplication 27 + 28 + # Load credentials from .env 29 + env_file: 30 + - .env 31 + 32 + # Logging configuration 33 + logging: 34 + driver: "json-file" 35 + options: 36 + max-size: "10m" 37 + max-file: "3" 38 + 39 + # Health check 40 + healthcheck: 41 + test: ["CMD", "pgrep", "cron"] 42 + interval: 60s 43 + timeout: 10s 44 + retries: 3 45 + start_period: 10s
+47
aggregators/reddit-highlights/docker-entrypoint.sh
··· 1 + #!/bin/bash 2 + set -e 3 + 4 + echo "Starting Reddit Highlights Aggregator..." 5 + echo "=========================================" 6 + 7 + # Load environment variables if .env file exists 8 + if [ -f /app/.env ]; then 9 + echo "Loading environment variables from .env" 10 + export $(grep -v '^#' /app/.env | xargs) 11 + fi 12 + 13 + # Validate required environment variables 14 + if [ -z "$COVES_API_KEY" ]; then 15 + echo "ERROR: Missing required environment variable!" 16 + echo "Please set COVES_API_KEY (format: ckapi_...)" 17 + exit 1 18 + fi 19 + 20 + echo "API Key prefix: ${COVES_API_KEY:0:12}..." 21 + echo "Cron schedule: Every 30 minutes (with 0-10 min jitter)" 22 + 23 + # Export environment variables for cron 24 + # Cron runs in a separate environment and doesn't inherit container env vars 25 + echo "Exporting environment variables for cron..." 26 + printenv | grep -E '^(COVES_|SKIP_|PATH=)' > /etc/environment 27 + 28 + # Start cron in the background 29 + echo "Starting cron daemon..." 30 + cron 31 + 32 + # Optional: Run aggregator immediately on startup (for testing) 33 + if [ "$RUN_ON_STARTUP" = "true" ]; then 34 + echo "Running aggregator immediately (RUN_ON_STARTUP=true)..." 35 + # Skip jitter for immediate run 36 + cd /app && SKIP_JITTER=true python -m src.main 37 + fi 38 + 39 + echo "=========================================" 40 + echo "Reddit Highlights Aggregator is running!" 41 + echo "Polling r/nba for streamable links" 42 + echo "Logs will appear below:" 43 + echo "=========================================" 44 + echo "" 45 + 46 + # Execute the command passed to docker run (defaults to tail -f /var/log/cron.log) 47 + exec "$@"