From 874d88410c03ca4cf7d3a59d40bae932cbbee38c Mon Sep 17 00:00:00 2001 From: Florian <52180080+florianjs@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:28:39 +0100 Subject: [PATCH] Release v0.3.2 --- .env.example | 132 +++++++++++++++++++++++++ doc/guide/configuration.md | 70 ++++++++------ doc/guide/getting-started.md | 38 +++++--- package.json | 2 +- scripts/setup.sh | 182 +++++++++++++++++++++++++++++++++++ 5 files changed, 384 insertions(+), 40 deletions(-) create mode 100644 .env.example create mode 100755 scripts/setup.sh diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..40327e5 --- /dev/null +++ b/.env.example @@ -0,0 +1,132 @@ +# ============================================================================= +# OpenTracker Environment Configuration +# ============================================================================= +# This file works for both development and production. +# Copy to .env and adjust values as needed. +# +# DEVELOPMENT: Use defaults as-is with `docker compose up -d` +# PRODUCTION: Use docker-compose.prod.yml and generate all secrets below + +# ----------------------------------------------------------------------------- +# Environment Mode +# ----------------------------------------------------------------------------- +NODE_ENV=development + +# ----------------------------------------------------------------------------- +# Domain Configuration (Production only) +# ----------------------------------------------------------------------------- +# DOMAIN=your-tracker.com +# TRACKER_DOMAIN=tracker.your-tracker.com +# MONITORING_DOMAIN=monitoring.your-tracker.com +# ACME_EMAIL=admin@your-tracker.com + +# ----------------------------------------------------------------------------- +# Database (PostgreSQL) +# ----------------------------------------------------------------------------- +# Development (SSL disabled) +DATABASE_URL=postgres://tracker:tracker@localhost:5432/opentracker + +# Production (SSL enforced - sslmode=require automatically added in nuxt.config.ts) +# DATABASE_URL=postgres://tracker:STRONG_PASSWORD@pgbouncer:6432/opentracker + +# Production database settings +DB_USER=tracker +# ⚠️ PRODUCTION: Generate with: openssl rand -base64 32 +DB_PASSWORD=tracker +DB_NAME=opentracker +DB_PORT=5432 + +# Database connection pool +DB_POOL_MAX=20 + +# SSL/TLS for database connections +# Development: SSL disabled for local testing +# Production: SSL automatically enforced (see documentation/ssl-setup.md) +# Generate certificates with: ./scripts/generate-ssl-certs.sh + +# Debug mode (never enable in production) +DB_DEBUG=false + +# ----------------------------------------------------------------------------- +# Redis +# ----------------------------------------------------------------------------- +REDIS_URL=redis://localhost:6379 + +# Redis authentication (REQUIRED for production) +REDIS_PASSWORD= + +# Redis key prefix (namespace isolation) +REDIS_KEY_PREFIX=ot: + +# Redis port (for docker-compose) +REDIS_PORT=6379 + +# SSL/TLS for Redis connections +REDIS_TLS=false +REDIS_TLS_REJECT_UNAUTHORIZED=true +# REDIS_TLS_CA=/path/to/ca-certificate.crt + +# ----------------------------------------------------------------------------- +# Tracker Ports +# ----------------------------------------------------------------------------- +TRACKER_PORT=8000 +TRACKER_HTTP_PORT=8080 +TRACKER_UDP_PORT=8081 +TRACKER_WS_PORT=8082 + +# Debug mode for verbose tracker logging (logs raw announce params) +TRACKER_DEBUG=false + +# Tracker announce URLs (displayed in admin dashboard for .torrent files) +# ⚠️ PRODUCTION: Configure these with your actual domain +TRACKER_HTTP_URL=https://tracker.your-domain.com/announce +TRACKER_UDP_URL=udp://tracker.your-domain.com:8081/announce +TRACKER_WS_URL=wss://tracker.your-domain.com/ws + +# ----------------------------------------------------------------------------- +# Security +# ----------------------------------------------------------------------------- + +# Session encryption (REQUIRED for production - generate with: openssl rand -hex 32) +NUXT_SESSION_SECRET= + +# Admin API key (REQUIRED for production - generate with: openssl rand -hex 32) +ADMIN_API_KEY= + +# IP hashing secret (REQUIRED for production - generate with: openssl rand -hex 32) +IP_HASH_SECRET=opentracker-default-secret-change-me + +# ----------------------------------------------------------------------------- +# Monitoring (Production only - Grafana) +# ----------------------------------------------------------------------------- +# GRAFANA_ADMIN_USER=admin +# GRAFANA_ADMIN_PASSWORD=CHANGE_THIS_SECURE_PASSWORD + +# Monitoring Basic Auth (generate hash with: caddy hash-password) +# MONITORING_USER=admin +# MONITORING_PASSWORD_HASH= + +# ----------------------------------------------------------------------------- +# Quick Start +# ----------------------------------------------------------------------------- +# +# DEVELOPMENT: +# cp .env.example .env +# docker compose up -d +# npm run dev +# +# PRODUCTION: +# cp .env.example .env +# # Generate all secrets: +# echo "NODE_ENV=production" >> .env +# echo "NUXT_SESSION_SECRET=$(openssl rand -hex 32)" >> .env +# echo "ADMIN_API_KEY=$(openssl rand -hex 32)" >> .env +# echo "IP_HASH_SECRET=$(openssl rand -hex 32)" >> .env +# echo "DB_PASSWORD=$(openssl rand -base64 24)" >> .env +# echo "REDIS_PASSWORD=$(openssl rand -base64 24)" >> .env +# echo "GRAFANA_ADMIN_PASSWORD=$(openssl rand -base64 16)" >> .env +# # Configure domains +# echo "DOMAIN=your-tracker.com" >> .env +# # Start +# docker compose -f docker-compose.prod.yml up -d + diff --git a/doc/guide/configuration.md b/doc/guide/configuration.md index c016d4a..dbbf045 100644 --- a/doc/guide/configuration.md +++ b/doc/guide/configuration.md @@ -6,43 +6,59 @@ OpenTracker is configured primarily through environment variables. This page cov ### Core Settings -| Variable | Description | Default | -|----------|-------------|---------| -| `NUXT_PUBLIC_SITE_NAME` | Your tracker's display name | `OpenTracker` | -| `NUXT_PUBLIC_SITE_URL` | Public URL of your tracker | — | -| `NUXT_SESSION_PASSWORD` | Session encryption key (32+ chars) | — | +| Variable | Description | Default | +| ----------------------- | ---------------------------------- | ------------- | +| `NUXT_PUBLIC_SITE_NAME` | Your tracker's display name | `OpenTracker` | +| `NUXT_PUBLIC_SITE_URL` | Public URL of your tracker | — | +| `NUXT_SESSION_PASSWORD` | Session encryption key (32+ chars) | — | ### Database -| Variable | Description | Default | -|----------|-------------|---------| -| `DATABASE_URL` | PostgreSQL connection string | — | -| `POSTGRES_USER` | Database username | `opentracker` | -| `POSTGRES_PASSWORD` | Database password | — | -| `POSTGRES_DB` | Database name | `opentracker` | +| Variable | Description | Default | +| ------------------- | ---------------------------- | ------------- | +| `DATABASE_URL` | PostgreSQL connection string | — | +| `POSTGRES_USER` | Database username | `opentracker` | +| `POSTGRES_PASSWORD` | Database password | — | +| `POSTGRES_DB` | Database name | `opentracker` | ### Redis -| Variable | Description | Default | -|----------|-------------|---------| -| `REDIS_URL` | Redis connection string | `redis://localhost:6379` | -| `REDIS_PASSWORD` | Redis password | — | +| Variable | Description | Default | +| ---------------- | ----------------------- | ------------------------ | +| `REDIS_URL` | Redis connection string | `redis://localhost:6379` | +| `REDIS_PASSWORD` | Redis password | — | ### Tracker -| Variable | Description | Default | -|----------|-------------|---------| -| `TRACKER_SECRET` | Secret for generating passkeys | — | -| `IP_HASH_SECRET` | Secret for hashing peer IPs | — | -| `NUXT_PUBLIC_ANNOUNCE_URL` | Public announce URL | — | +| Variable | Description | Default | +| ------------------ | ------------------------------------------- | -------------------------------- | +| `TRACKER_SECRET` | Secret for generating passkeys | — | +| `IP_HASH_SECRET` | Secret for hashing peer IPs | — | +| `TRACKER_HTTP_URL` | HTTP announce URL (shown in .torrent files) | `http://localhost:8080/announce` | +| `TRACKER_UDP_URL` | UDP announce URL | `udp://localhost:8081/announce` | +| `TRACKER_WS_URL` | WebSocket URL | `ws://localhost:8082` | +| `TRACKER_DEBUG` | Enable verbose tracker logging | `false` | + +::: tip Configuring Tracker URLs +These URLs are embedded in `.torrent` files and displayed in the admin dashboard. Configure them with your actual domain: + +```bash +# In your .env file +TRACKER_HTTP_URL=https://tracker.your-domain.com/announce +TRACKER_UDP_URL=udp://tracker.your-domain.com:8081/announce +TRACKER_WS_URL=wss://tracker.your-domain.com/ws +``` + +Replace `your-domain.com` with your actual tracker domain. +::: ### Security -| Variable | Description | Default | -|----------|-------------|---------| -| `POW_DIFFICULTY` | Proof of Work difficulty (1-10) | `5` | -| `RATE_LIMIT_WINDOW` | Rate limit window in seconds | `60` | -| `RATE_LIMIT_MAX` | Max requests per window | `100` | +| Variable | Description | Default | +| ------------------- | ------------------------------- | ------- | +| `POW_DIFFICULTY` | Proof of Work difficulty (1-10) | `5` | +| `RATE_LIMIT_WINDOW` | Rate limit window in seconds | `60` | +| `RATE_LIMIT_MAX` | Max requests per window | `100` | ## Docker Compose Configuration @@ -66,7 +82,7 @@ services: app: build: . ports: - - "3000:3000" + - '3000:3000' environment: - DATABASE_URL=postgresql://opentracker:opentracker@db:5432/opentracker - REDIS_URL=redis://redis:6379 @@ -121,7 +137,7 @@ Always use the `install.sh` script for production deployments. It handles: - Configuring TLS for all connections - Setting up firewall rules - Network isolation for databases -::: + ::: For manual deployments, ensure: diff --git a/doc/guide/getting-started.md b/doc/guide/getting-started.md index 55cdca1..4de6d6c 100644 --- a/doc/guide/getting-started.md +++ b/doc/guide/getting-started.md @@ -18,11 +18,11 @@ You must configure your DNS records to point to your VPS IP address before runni Create the following **A records** pointing to your server's IP: -| Subdomain | Record Type | Value | -|-----------|-------------|-------| -| `tracker.your-domain.com` | A | Your VPS IP | -| `announce.your-domain.com` | A | Your VPS IP | -| `monitoring.your-domain.com` | A | Your VPS IP | +| Subdomain | Record Type | Value | +| ---------------------------- | ----------- | ----------- | +| `tracker.your-domain.com` | A | Your VPS IP | +| `announce.your-domain.com` | A | Your VPS IP | +| `monitoring.your-domain.com` | A | Your VPS IP | ::: tip DNS propagation usually completes within a few minutes, but can take up to 24-48 hours. The installer will fail to obtain SSL certificates if DNS is not properly configured. @@ -53,23 +53,37 @@ The installer will automatically: After installation, Grafana is accessible at `https://monitoring.your-domain.com/grafana` with default credentials `admin` / `admin`. -### Option 2: Development with Docker +### Option 2: Docker Setup (Interactive) -For local development and testing: +For local development or manual production deployment: ```bash # Clone repository git clone https://github.com/florianjs/opentracker.git && cd opentracker -cp .env.example .env -# Start all services (app + postgres + redis) +# Run interactive setup +./scripts/setup.sh +``` + +The setup script will: + +- Ask if you want **development** or **production** mode +- For production: prompt for domain names and email +- Generate all cryptographic secrets automatically +- Configure tracker announce URLs +- Create a ready-to-use `.env` file + +Then start the services: + +```bash +# Development docker compose up -d -# View logs -docker compose logs -f app +# Production (with SSL, Caddy, monitoring) +docker compose -f docker-compose.prod.yml up -d --build ``` -Open [http://localhost:3000](http://localhost:3000) to access your tracker. +Open [http://localhost:3000](http://localhost:3000) (dev) or `https://your-domain.com` (prod) to access your tracker. ## First Steps After Installation diff --git a/package.json b/package.json index 663df9d..8bd7c28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "opentracker", - "version": "0.3.1", + "version": "0.3.2", "type": "module", "private": true, "scripts": { diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..3fe647f --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,182 @@ +#!/bin/bash +# ============================================================================= +# OpenTracker - Quick Docker Setup +# ============================================================================= +# Interactive setup for Docker deployments. +# Creates .env file with proper configuration for development or production. +# +# Usage: ./scripts/setup.sh +# ============================================================================= + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +BOLD='\033[1m' +NC='\033[0m' + +log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } +log_success() { echo -e "${GREEN}✓${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; } + +# Get script directory +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +echo "" +echo -e "${CYAN}${BOLD}╔══════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}${BOLD}║ OpenTracker - Docker Setup ║${NC}" +echo -e "${CYAN}${BOLD}╚══════════════════════════════════════════════════════════╝${NC}" +echo "" + +# Check if .env.example exists +if [[ ! -f "$PROJECT_DIR/.env.example" ]]; then + log_error ".env.example not found. Are you in the OpenTracker directory?" +fi + +# Check if .env already exists +if [[ -f "$PROJECT_DIR/.env" ]]; then + echo -e "${YELLOW}A .env file already exists.${NC}" + read -p "Overwrite it? (y/N): " OVERWRITE + if [[ ! $OVERWRITE =~ ^[Yy]$ ]]; then + echo "Setup cancelled." + exit 0 + fi +fi + +# Ask for environment type +echo "" +echo -e "${BOLD}Select environment:${NC}" +echo " 1) Development (local testing, no SSL)" +echo " 2) Production (Docker on VPS with SSL)" +echo "" +read -p "Choice [1-2]: " ENV_CHOICE + +case $ENV_CHOICE in + 1) ENV_TYPE="development" ;; + 2) ENV_TYPE="production" ;; + *) log_error "Invalid choice" ;; +esac + +# Copy base config +cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env" +log_success "Created .env from .env.example" + +if [[ "$ENV_TYPE" == "development" ]]; then + # Development: just use defaults + echo "" + log_success "Development setup complete!" + echo "" + echo -e "${BOLD}Next steps:${NC}" + echo " docker compose up -d" + echo " Open http://localhost:3000" + echo "" + exit 0 +fi + +# ============================================================================= +# PRODUCTION SETUP +# ============================================================================= +echo "" +echo -e "${BOLD}Production Configuration${NC}" +echo "" + +# Domain configuration +read -p "Main domain (e.g., tracker.example.com): " DOMAIN +if [[ -z "$DOMAIN" ]]; then + log_error "Domain is required for production" +fi + +read -p "Tracker subdomain [tracker.$DOMAIN]: " TRACKER_DOMAIN +TRACKER_DOMAIN="${TRACKER_DOMAIN:-tracker.$DOMAIN}" + +read -p "Monitoring subdomain [monitoring.$DOMAIN]: " MONITORING_DOMAIN +MONITORING_DOMAIN="${MONITORING_DOMAIN:-monitoring.$DOMAIN}" + +read -p "Email for SSL certificates: " ACME_EMAIL +if [[ -z "$ACME_EMAIL" ]]; then + log_error "Email is required for Let's Encrypt SSL" +fi + +# Generate secrets +log_info "Generating cryptographic secrets..." +NUXT_SESSION_SECRET=$(openssl rand -hex 32) +ADMIN_API_KEY=$(openssl rand -hex 32) +IP_HASH_SECRET=$(openssl rand -hex 32) +DB_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=') +REDIS_PASSWORD=$(openssl rand -base64 24 | tr -d '/+=') +GRAFANA_PASSWORD=$(openssl rand -base64 16 | tr -d '/+=') + +# Update .env file +log_info "Updating .env file..." + +# Use sed to update values (compatible with both Linux and macOS) +sed_inplace() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + +# Environment +sed_inplace "s/^NODE_ENV=.*/NODE_ENV=production/" "$PROJECT_DIR/.env" + +# Domains +sed_inplace "s|^# DOMAIN=.*|DOMAIN=$DOMAIN|" "$PROJECT_DIR/.env" +sed_inplace "s|^# TRACKER_DOMAIN=.*|TRACKER_DOMAIN=$TRACKER_DOMAIN|" "$PROJECT_DIR/.env" +sed_inplace "s|^# MONITORING_DOMAIN=.*|MONITORING_DOMAIN=$MONITORING_DOMAIN|" "$PROJECT_DIR/.env" +sed_inplace "s|^# ACME_EMAIL=.*|ACME_EMAIL=$ACME_EMAIL|" "$PROJECT_DIR/.env" + +# Database +sed_inplace "s|^DATABASE_URL=.*|DATABASE_URL=postgres://tracker:$DB_PASSWORD@pgbouncer:6432/opentracker|" "$PROJECT_DIR/.env" +sed_inplace "s/^DB_PASSWORD=.*/DB_PASSWORD=$DB_PASSWORD/" "$PROJECT_DIR/.env" + +# Redis +sed_inplace "s|^REDIS_URL=.*|REDIS_URL=redis://redis:6379|" "$PROJECT_DIR/.env" +sed_inplace "s/^REDIS_PASSWORD=.*/REDIS_PASSWORD=$REDIS_PASSWORD/" "$PROJECT_DIR/.env" + +# Security +sed_inplace "s/^NUXT_SESSION_SECRET=.*/NUXT_SESSION_SECRET=$NUXT_SESSION_SECRET/" "$PROJECT_DIR/.env" +sed_inplace "s/^ADMIN_API_KEY=.*/ADMIN_API_KEY=$ADMIN_API_KEY/" "$PROJECT_DIR/.env" +sed_inplace "s/^IP_HASH_SECRET=.*/IP_HASH_SECRET=$IP_HASH_SECRET/" "$PROJECT_DIR/.env" + +# Tracker URLs +sed_inplace "s|^TRACKER_HTTP_URL=.*|TRACKER_HTTP_URL=https://$TRACKER_DOMAIN/announce|" "$PROJECT_DIR/.env" +sed_inplace "s|^TRACKER_UDP_URL=.*|TRACKER_UDP_URL=udp://$TRACKER_DOMAIN:8081/announce|" "$PROJECT_DIR/.env" +sed_inplace "s|^TRACKER_WS_URL=.*|TRACKER_WS_URL=wss://$TRACKER_DOMAIN/ws|" "$PROJECT_DIR/.env" + +# Monitoring +sed_inplace "s|^# GRAFANA_ADMIN_USER=.*|GRAFANA_ADMIN_USER=admin|" "$PROJECT_DIR/.env" +sed_inplace "s|^# GRAFANA_ADMIN_PASSWORD=.*|GRAFANA_ADMIN_PASSWORD=$GRAFANA_PASSWORD|" "$PROJECT_DIR/.env" + +echo "" +log_success "Production setup complete!" +echo "" +echo -e "${BOLD}Generated credentials (save these!):${NC}" +echo -e " Database password: ${CYAN}$DB_PASSWORD${NC}" +echo -e " Redis password: ${CYAN}$REDIS_PASSWORD${NC}" +echo -e " Grafana password: ${CYAN}$GRAFANA_PASSWORD${NC}" +echo "" +echo -e "${BOLD}Configured domains:${NC}" +echo -e " Main: https://$DOMAIN" +echo -e " Tracker: https://$TRACKER_DOMAIN" +echo -e " Monitoring: https://$MONITORING_DOMAIN/grafana" +echo "" +echo -e "${BOLD}Next steps:${NC}" +echo " 1. Ensure DNS A records point to your server IP:" +echo " - $DOMAIN" +echo " - $TRACKER_DOMAIN" +echo " - $MONITORING_DOMAIN" +echo "" +echo " 2. Start the production stack:" +echo " docker compose -f docker-compose.prod.yml up -d --build" +echo "" +echo " 3. View logs:" +echo " docker compose -f docker-compose.prod.yml logs -f app" +echo ""