diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7781be6 --- /dev/null +++ b/.env.example @@ -0,0 +1,54 @@ +# TaskPlaner Environment Configuration +# Copy to .env and customize for your deployment + +# ============================================ +# Server Configuration +# ============================================ + +# Port the server listens on (inside container) +# Map to host port via docker-compose ports setting +PORT=3000 + +# ============================================ +# Data Storage +# ============================================ + +# Directory for database and uploads +# Docker: /app/data (must match volume mount) +# Local development: ./data +TASKPLANER_DATA_DIR=/app/data + +# ============================================ +# Production URL (REQUIRED for production) +# ============================================ + +# The full URL where users access the app +# Used for CSRF validation and generating absolute URLs +# Example: https://tasks.example.com +ORIGIN=http://localhost:3000 + +# ============================================ +# Request Limits +# ============================================ + +# Maximum request body size +# Supports K, M, G suffixes +# Default: 512kb, recommended for images: 10M +BODY_SIZE_LIMIT=10M + +# ============================================ +# Reverse Proxy Configuration +# Uncomment when running behind nginx/traefik/etc +# ============================================ + +# Header containing original protocol (http/https) +# PROTOCOL_HEADER=x-forwarded-proto + +# Header containing original host +# HOST_HEADER=x-forwarded-host + +# Header containing original client IP +# ADDRESS_HEADER=x-forwarded-for + +# Number of trusted proxies in front of app +# XFF_DEPTH=1 diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..124eb46 --- /dev/null +++ b/backup.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# TaskPlaner Data Backup Script +# Creates a timestamped backup of the Docker volume + +set -e + +# Configuration (override via environment) +BACKUP_DIR="${BACKUP_DIR:-./backups}" +VOLUME_NAME="${VOLUME_NAME:-taskplaner_taskplaner_data}" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_FILE="${BACKUP_DIR}/taskplaner_backup_${TIMESTAMP}.tar.gz" + +# Create backup directory if needed +mkdir -p "$BACKUP_DIR" + +echo "=========================================" +echo "TaskPlaner Backup" +echo "=========================================" +echo "Volume: $VOLUME_NAME" +echo "Output: $BACKUP_FILE" +echo "" + +# Check if volume exists +if ! docker volume inspect "$VOLUME_NAME" > /dev/null 2>&1; then + echo "Error: Volume '$VOLUME_NAME' not found" + echo "" + echo "Available volumes:" + docker volume ls --format ' - {{.Name}}' | grep -i taskplaner || echo " (none with 'taskplaner' in name)" + echo "" + echo "Tip: Set VOLUME_NAME environment variable to use a different volume" + exit 1 +fi + +# Create backup using temporary Alpine container +echo "Creating backup..." +docker run --rm \ + -v "${VOLUME_NAME}:/data:ro" \ + -v "$(cd "$BACKUP_DIR" && pwd):/backup" \ + alpine:latest \ + tar czf "/backup/taskplaner_backup_${TIMESTAMP}.tar.gz" -C /data . + +echo "" +echo "Backup complete!" +echo "File: $BACKUP_FILE" +echo "Size: $(du -h "$BACKUP_FILE" | cut -f1)" +echo "" +echo "To restore: docker run --rm -v ${VOLUME_NAME}:/data -v \$(pwd)/${BACKUP_DIR}:/backup alpine tar xzf /backup/taskplaner_backup_${TIMESTAMP}.tar.gz -C /data"