### Configure and Start TaskTrove Pro with Docker Compose Source: https://docs.tasktrove.io/pro-setup Define the service in docker-compose.yml and start the container. This setup includes volume mapping and environment configuration. ```yaml services: tasktrove-pro: image: ghcr.io/dohsimpson/tasktrove-pro ports: - "3000:3000" environment: - LICENSE_KEY=YOUR-LICENSE-KEY-HERE - AUTH_SECRET=YOUR-AUTH-SECRET-HERE volumes: - ./data:/app/data - /etc/machine-id:/etc/machine-id:ro restart: always ``` ```bash docker-compose up -d ``` -------------------------------- ### Restore Data on New Server Source: https://docs.tasktrove.io/backup Extracts the migration archive and starts the TaskTrove container on the new server. ```bash tar -xzf tasktrove-migration.tar.gz docker run -p 3000:3000 -v ./data:/app/data -v ./backups:/app/backups -d --restart=always --name tasktrove ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Set up TaskTrove with Docker Compose Source: https://docs.tasktrove.io/installation Clones the TaskTrove repository and starts the service with docker-compose up -d. For Pro, pass -f docker-compose-pro.yml and update AUTH_SECRET. ```bash # Download the setup files git clone https://github.com/dohsimpson/TaskTrove cd TaskTrove/selfhost # Start TaskTrove docker-compose up -d ``` -------------------------------- ### Start TaskTrove Pro with Docker Source: https://docs.tasktrove.io/pro-setup Run the TaskTrove Pro container using the docker run command with required environment variables and volume mounts. ```bash docker run -p 3000:3000 -v ./data:/app/data \ -e LICENSE_KEY="YOUR-LICENSE-KEY-HERE" \ -e AUTH_SECRET="YOUR-AUTH-SECRET-HERE" \ -v /etc/machine-id:/etc/machine-id:ro \ -d --restart=always --name tasktrove-pro \ ghcr.io/dohsimpson/tasktrove-pro ``` -------------------------------- ### Access TaskTrove in browser Source: https://docs.tasktrove.io/installation Open this URL in a web browser to access the TaskTrove interface after installation. ```text http://localhost:3000 ``` -------------------------------- ### Run TaskTrove with Docker Source: https://docs.tasktrove.io/installation Starts TaskTrove on port 3000 with a data volume and restart policy. For Pro, replace the image with ghcr.io/dohsimpson/tasktrove-pro. ```bash docker run -p 3000:3000 -v ./data:/app/data -d --restart=always --name tasktrove ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Upgrade TaskTrove with Docker Source: https://docs.tasktrove.io/upgrading Commands to pull the latest image, stop the existing container, and start a new container with the updated image. ```bash # Pull the latest image docker pull ghcr.io/dohsimpson/tasktrove # Stop and remove the current container docker stop tasktrove docker rm tasktrove # Start with the new image docker run -p 3000:3000 -v ./data:/app/data -d --restart=always --name tasktrove ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Docker Compose environment for SSO header auth Source: https://docs.tasktrove.io/sso-header-auth Example Docker Compose configuration for the tasktrove-pro container. Sets SSO_HEADER_AUTH_ENABLED to true, defines the username header as Remote-User, and provides the public AUTH_URL. The ellipsis indicates additional environment variables may be present. ```yaml services: tasktrove-pro: image: ghcr.io/dohsimpson/tasktrove-pro environment: - SSO_HEADER_AUTH_ENABLED=true - SSO_HEADER_AUTH_USERNAME_HEADER=Remote-User - AUTH_URL=https://tasktrove.example.com - ... ``` -------------------------------- ### Run TaskTrove with AUTH_SECRET via Docker Source: https://docs.tasktrove.io/installation Starts TaskTrove with password protection by setting the AUTH_SECRET environment variable. Use a random key generated with openssl rand -hex 32. ```bash # Docker docker run -p 3000:3000 -v ./data:/app/data \ -e AUTH_SECRET="random-long-encryption-key" \ -d --restart=always --name tasktrove \ ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Manual Backup via Tar Archive Source: https://docs.tasktrove.io/backup Create a compressed tar archive of the data directory and verify the contents. ```bash # Create a timestamped backup archive tar -czf tasktrove-backup-$(date +%Y%m%d-%H%M%S).tar.gz ./data # Verify the backup tar -tzf tasktrove-backup-*.tar.gz ``` -------------------------------- ### Get Host MAC Address for MACHINE_ID Source: https://docs.tasktrove.io/pro-setup Retrieve the host's primary MAC address to use as a MACHINE_ID if /etc/machine-id is unavailable. ```bash ip link show | grep -A 1 "link/ether" | head -2 ``` -------------------------------- ### Create Migration Backup Source: https://docs.tasktrove.io/backup Creates a tar archive of the current data directory for migration purposes. ```bash tar -czf tasktrove-migration.tar.gz ./data ``` -------------------------------- ### Create data directory Source: https://docs.tasktrove.io/troubleshooting Creates the host data directory that will be mounted to /app/data inside the container. Required before running TaskTrove to avoid permission errors. ```bash mkdir -p ./data ``` -------------------------------- ### Schedule Automated Backup with Cron Source: https://docs.tasktrove.io/backup Make the backup script executable and schedule it to run daily at 2 AM using crontab. ```bash chmod +x backup-tasktrove.sh # Add to crontab for daily backup at 2 AM 0 2 * * * /path/to/backup-tasktrove.sh ``` -------------------------------- ### Run TaskTrove with Docker Source: https://docs.tasktrove.io/backup Deploy TaskTrove using the docker run command with volume mappings for data and backups. ```bash docker run -p 3000:3000 \ -v ./data:/app/data \ -v ./backups:/app/backups \ -d --restart=always --name tasktrove \ ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Verify License Activation Logs Source: https://docs.tasktrove.io/pro-setup Check the container logs to confirm that the license validation was successful. ```text [License] Machine fingerprint: xxx-xxx-xxx [License] Validating license with Keygen... [License] Validation result: VALID ``` -------------------------------- ### Manual Backup via File Copy Source: https://docs.tasktrove.io/backup Stop the container, copy the data directory to a backup location, and restart the container. ```bash # Stop TaskTrove container (optional but recommended) docker stop tasktrove # Copy the data directory to your backup location cp -r ./data /path/to/your/backup/tasktrove-backup-$(date +%Y%m%d) # Restart TaskTrove docker start tasktrove ``` -------------------------------- ### Run convert.py to downgrade data.json Source: https://docs.tasktrove.io/downgrade-pro-to-base Run this command to convert your Pro data.json file to the base schema. The -o option writes the output directly to the same file, overriding it. Ensure you have backed up your data before running. ```bash convert.py path/to/data.json -o path/to/data.json ``` -------------------------------- ### Startup log showing machine fingerprint Source: https://docs.tasktrove.io/pro-setup Shows the format of the machine fingerprint log line that appears in the startup logs. Use this to check your server's Machine ID. ```plaintext [License] Machine fingerprint: xxx-xxx-xxx ``` -------------------------------- ### Stop, remove, and run TaskTrove with version tag Source: https://docs.tasktrove.io/upgrading Stops and removes the current container, optionally restores a pre-migration backup, and runs a new container pinned to version v0.2.0. The backup filename uses a placeholder [timestamp] that must be replaced with the actual backup timestamp. ```bash docker stop tasktrove docker rm tasktrove # Restore your data backup (if migrated) cp ./data/data.json.backup-[timestamp] ./data/data.json # Run with specific version tag docker run -p 3000:3000 -v ./data:/app/data -d --restart=always --name tasktrove ghcr.io/dohsimpson/tasktrove:v0.2.0 ``` -------------------------------- ### Upgrade TaskTrove with Docker Compose Source: https://docs.tasktrove.io/upgrading Commands to navigate to the directory, pull updated images, stop services, and restart them using Docker Compose. ```bash # Navigate to your TaskTrove directory cd TaskTrove/selfhost # Pull the latest images docker-compose pull # Stop current services docker-compose down # Start with updated images docker-compose up -d ``` -------------------------------- ### Rollback after failed migration Source: https://docs.tasktrove.io/troubleshooting List available backups and restore the data.json file from a specific backup timestamp, then restart the container. ```bash docker exec tasktrove ls -la /app/data/*.backup-* docker exec tasktrove cp /app/data/data.json.backup-1234567890 /app/data/data.json docker restart tasktrove ``` -------------------------------- ### Restore from Directory Copy Source: https://docs.tasktrove.io/backup Restores data by manually replacing the current data directory with a backup copy. ```bash # Stop TaskTrove docker stop tasktrove # Replace current data with backup rm -rf ./data cp -r /path/to/backup/data ./data # Start TaskTrove docker start tasktrove ``` -------------------------------- ### Deploy TaskTrove with Docker Compose Source: https://docs.tasktrove.io/backup Deploy TaskTrove using a docker-compose.yml file to define services and volumes. ```yaml version: "3.8" services: tasktrove: image: ghcr.io/dohsimpson/tasktrove ports: - "3000:3000" volumes: - ./data:/app/data - ./backups:/app/backups restart: always ``` -------------------------------- ### Automated Backup Script Source: https://docs.tasktrove.io/backup A shell script to automate backups with retention management. ```bash #!/bin/bash # backup-tasktrove.sh BACKUP_DIR="/path/to/backups" DATE=$(date +%Y%m%d-%H%M%S) BACKUP_NAME="tasktrove-backup-$DATE.tar.gz" # Create backup directory if it doesn't exist mkdir -p "$BACKUP_DIR" # Create backup tar -czf "$BACKUP_DIR/$BACKUP_NAME" ./data # Keep only last 7 backups (optional) cd "$BACKUP_DIR" && ls -t tasktrove-backup-*.tar.gz | tail -n +8 | xargs rm -f echo "Backup completed: $BACKUP_NAME" ``` -------------------------------- ### Transfer Migration Backup Source: https://docs.tasktrove.io/backup Transfers the migration archive to the new server using scp. ```bash scp tasktrove-migration.tar.gz user@newserver:/path/to/tasktrove/ ``` -------------------------------- ### Restore from Built-in Auto Backup Source: https://docs.tasktrove.io/backup Restores data from a ZIP backup file created by the built-in system. ```bash # Stop TaskTrove docker stop tasktrove # Navigate to backup directory cd backups # List available backups (newest first) ls -t backup-*.zip # Extract the desired backup (replace filename with your chosen backup) unzip backup-2024-01-15_02-00-00.zip -d ../ # This creates a 'data' folder with your backed up data # Start TaskTrove docker start tasktrove ``` -------------------------------- ### Verify Manual Tar Backup Source: https://docs.tasktrove.io/backup Tests the integrity of the manual tar.gz backup archive. ```bash tar -tzf tasktrove-backup-*.tar.gz >/dev/null && echo "Backup archive is valid" ``` -------------------------------- ### Stop and Remove Base Edition Container Source: https://docs.tasktrove.io/pro-setup Stop and remove the existing base edition container before migrating to the Pro edition. ```bash docker stop tasktrove docker rm tasktrove ``` -------------------------------- ### Fix insufficient permissions Source: https://docs.tasktrove.io/troubleshooting Adjust directory permissions and test write access to resolve permission-related errors. ```bash chmod 755 ./data docker exec tasktrove touch /app/data/test.txt ``` -------------------------------- ### Verify Auto Backup ZIP file Source: https://docs.tasktrove.io/backup Tests the integrity of the auto-generated ZIP backup file. ```bash unzip -t backups/backup-*.zip && echo "Auto backup ZIP is valid" ``` -------------------------------- ### Restart TaskTrove with AUTH_SECRET to enable authentication Source: https://docs.tasktrove.io/troubleshooting Restarts the TaskTrove container with the AUTH_SECRET environment variable to enable password protection after migration is complete. Replace 'your-secret-key' with a secure secret. ```bash docker stop tasktrove docker rm tasktrove docker run -p 3000:3000 -v ./data:/app/data -e AUTH_SECRET=your-secret-key -d --restart=always --name tasktrove ghcr.io/dohsimpson/tasktrove ``` -------------------------------- ### Restore from Tar Archive Source: https://docs.tasktrove.io/backup Restores data by extracting a tar.gz archive into the data directory. ```bash # Stop TaskTrove docker stop tasktrove # Remove current data and extract backup rm -rf ./data tar -xzf tasktrove-backup-*.tar.gz # Start TaskTrove docker start tasktrove ``` -------------------------------- ### TaskTrove Directory Structure Source: https://docs.tasktrove.io/backup The expected directory layout for TaskTrove data and backup files. ```text tasktrove/ ├── data/ # Your TaskTrove data files ├── backups/ # Auto-generated backup files (ZIP format) └── docker-compose.yml ``` -------------------------------- ### Set permissions for data directory Source: https://docs.tasktrove.io/troubleshooting Fixes permission issues when the data directory exists but TaskTrove cannot access it. chmod 755 sets read/write/execute permissions for the owner, and chown -R 1000:1000 matches the container user for persistent issues. ```bash # Set proper permissions chmod 755 ./data # For persistent permission issues, match container user sudo chown -R 1000:1000 ./data ``` -------------------------------- ### Validate data.json with python Source: https://docs.tasktrove.io/troubleshooting Use this command to verify if the data.json file inside the container is valid JSON. ```bash docker exec tasktrove cat /app/data/data.json | python -m json.tool ``` -------------------------------- ### Python script convert.py to downgrade Pro data.json to base Source: https://docs.tasktrove.io/downgrade-pro-to-base Run this script to convert a Pro data.json file to the base schema. It removes Pro-only fields such as ownerId, assignees, reward, reactions, members, and productivity settings. The script reads a JSON file, converts it, and writes to stdout or a specified output file. Requires Python 3 and the input file must be a JSON object. ```python #!/usr/bin/env python3 import argparse import json import sys from typing import Any, Dict, List def pick_user(user_field: Any) -> Dict[str, Any]: if isinstance(user_field, list): admins = [u for u in user_field if isinstance(u, dict) and u.get("role") == "admin"] if admins: return admins[0] return user_field[0] if user_field else {} if isinstance(user_field, dict): return user_field return {} def clean_user(user: Dict[str, Any]) -> Dict[str, Any]: user = dict(user) user.pop("role", None) user.pop("preferences", None) return user def clean_task(task: Dict[str, Any]) -> Dict[str, Any]: task = dict(task) task.pop("ownerId", None) task.pop("assignees", None) task.pop("reward", None) comments = task.get("comments") if isinstance(comments, list): cleaned_comments: List[Dict[str, Any]] = [] for comment in comments: if isinstance(comment, dict): comment = dict(comment) comment.pop("reactions", None) cleaned_comments.append(comment) else: cleaned_comments.append(comment) task["comments"] = cleaned_comments return task def clean_project(project: Dict[str, Any]) -> Dict[str, Any]: project = dict(project) project.pop("members", None) return project def clean_settings(settings: Dict[str, Any]) -> Dict[str, Any]: settings = dict(settings) general = settings.get("general") if isinstance(general, dict): general = dict(general) general.pop("newTaskOwnership", None) settings["general"] = general data = settings.get("data") if isinstance(data, dict): data = dict(data) data.pop("calendarSync", None) data.pop("calendarSyncSchedule", None) settings["data"] = data settings.pop("productivity", None) return settings def convert(data: Dict[str, Any]) -> Dict[str, Any]: tasks = data.get("tasks", []) projects = data.get("projects", []) labels = data.get("labels") project_groups = data.get("projectGroups") label_groups = data.get("labelGroups") settings = data.get("settings", {}) user = pick_user(data.get("user")) return { "tasks": [clean_task(t) if isinstance(t, dict) else t for t in tasks], "projects": [clean_project(p) if isinstance(p, dict) else p for p in projects], "labels": labels, "projectGroups": project_groups, "labelGroups": label_groups, "settings": clean_settings(settings) if isinstance(settings, dict) else settings, "user": clean_user(user) if isinstance(user, dict) else user, "version": data.get("version"), "edition": "base", } def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description=( "Convert a Pro TaskTrove data.json file to the base schema. " "Outputs to stdout unless --output is provided." ) ) parser.add_argument("input", help="Path to pro data.json") parser.add_argument("-o", "--output", help="Write output to file instead of stdout") return parser.parse_args() def main() -> int: args = parse_args() try: with open(args.input, "r", encoding="utf-8") as f: data = json.load(f) except FileNotFoundError: print(f"Input file not found: {args.input}", file=sys.stderr) return 1 except json.JSONDecodeError as exc: print(f"Invalid JSON in {args.input}: {exc}", file=sys.stderr) return 1 if not isinstance(data, dict): print("Input JSON must be an object at the top level.", file=sys.stderr) return 1 converted = convert(data) output = json.dumps(converted, indent=2, ensure_ascii=True) if args.output: with open(args.output, "w", encoding="utf-8") as f: f.write(output) f.write("\n") else: print(output) return 0 if __name__ == "__main__": raise SystemExit(main()) ``` -------------------------------- ### Update Docker Compose for Migration Source: https://docs.tasktrove.io/pro-setup Update the docker-compose.yml file to use the Pro image and include the necessary license configuration. ```yaml services: tasktrove-pro: image: ghcr.io/dohsimpson/tasktrove-pro # Changed from dohsimpson/tasktrove ports: - "3000:3000" environment: - LICENSE_KEY=YOUR-LICENSE-KEY-HERE - AUTH_SECRET=YOUR-AUTH-SECRET-HERE # Add if not already set volumes: - ./data:/app/data - /etc/machine-id:/etc/machine-id:ro restart: always ``` -------------------------------- ### Verify data directory access Source: https://docs.tasktrove.io/troubleshooting Checks that TaskTrove can access the data directory by viewing container logs and testing file access inside the container. The commands list the /app/data directory and display the data.json file. ```bash # View container logs docker logs tasktrove # Test data directory access docker exec tasktrove ls -la /app/data docker exec tasktrove cat /app/data/data.json ```