This guide covers how to self-host the Jules Task Queue system using Docker or manual deployment.
The easiest way to self-host is using the provided Docker Compose setup:
- Docker and Docker Compose installed
- GitHub App credentials (see GitHub App Setup Guide)
git clone https://github.com/ihildy/jules-task-queue.git
cd jules-task-queueCreate a .env file in the project root:
cp .env.example .envImportant: We recommend .env over .env.local because Prisma is picky about environment file locations.
Edit the .env file with your specific configuration. See .env.example for all available options and their descriptions.
Key variables you need to configure:
DATABASE_URL: PostgreSQL connection stringGITHUB_APP_ID: Your GitHub App IDNEXT_PUBLIC_GITHUB_APP_NAME: Your GitHub App name (for display)GITHUB_APP_PRIVATE_KEY: Your GitHub App private keyGITHUB_APP_WEBHOOK_SECRET: Webhook verification secretGITHUB_APP_CLIENT_ID&GITHUB_APP_CLIENT_SECRET: For OAuth (optional)
Note: For GITHUB_APP_PRIVATE_KEY, you can either:
- Base64 encode your private key:
cat private-key.pem | base64 - Or use the raw PEM format with
\nescaped as\\n
# Start all services including PostgreSQL database and cron
docker-compose -f docker-compose.selfhost.yml up -d
# Check status
docker-compose -f docker-compose.selfhost.yml ps
# View logs
docker-compose -f docker-compose.selfhost.yml logs -f app
docker-compose -f docker-compose.selfhost.yml logs -f cronIf you're using Coolify or another platform that provides managed databases and cron jobs:
# Use the standard docker-compose file
docker-compose up -d
# Check status
docker-compose ps
# View logs
docker-compose logs -f appThe self-hosting Docker Compose setup (docker-compose.selfhost.yml) includes:
- app: The Next.js application (port 3000)
- db: PostgreSQL database (port 5432)
- cron: Automated retry job runner (runs every 30 minutes)
The platform hosting setup (docker-compose.yml) includes:
- app: The Next.js application only (expects external database and cron)
If you prefer not to use Docker:
- Node.js 18+
- PostgreSQL database
- pnpm package manager
Create a PostgreSQL database and update your .env file:
DATABASE_URL=postgresql://username:password@localhost:5432/jules_queue# Install dependencies
pnpm install
# Generate Prisma client
pnpm db:generate
# Run database migrations
pnpm db:migrate
# Build the application
pnpm build
# Start production server
pnpm startSince you're not using Docker, you need to manually set up the cron job:
Add to your crontab (crontab -e):
# Run Jules retry job every 30 minutes
*/30 * * * * cd /path/to/your/jules-task-queue && pnpm cron:run >> /var/log/jules-cron.log 2>&1In your platform's scheduled tasks:
- Command:
pnpm cron:run - Schedule:
*/30 * * * *(every 30 minutes)
| Variable | Build Variable | Description |
|---|---|---|
DATABASE_URL |
No | PostgreSQL connection string |
NEXT_PUBLIC_GITHUB_APP_ID |
Yes | GitHub App ID from your app settings |
NEXT_PUBLIC_GITHUB_APP_NAME |
Yes | GitHub App name (for client-side display) |
GITHUB_APP_PRIVATE_KEY |
No | GitHub App private key (base64 encoded or with \n) |
GITHUB_APP_WEBHOOK_SECRET |
No | Secret used to verify GitHub App webhook signatures |
GITHUB_APP_CLIENT_ID |
No | GitHub App client ID (for OAuth user access tokens) |
GITHUB_APP_CLIENT_SECRET |
No | GitHub App client secret (for OAuth user access tokens) |
GITHUB_APP_CALLBACK_URL |
No | Callback URL for GitHub App OAuth flow |
CRON_SECRET |
No | Secret for authenticating cron job requests |
NODE_ENV |
No | Set to production for production deployments |
Note: Webhooks are automatically configured when users install your GitHub App on their repositories.
- Create your GitHub App following the GitHub App Setup Guide
- Configure your GitHub App webhook URL to:
https://your-domain.com/api/webhooks/github-app - Users can install your app on their repositories for automatic webhook setup
Coolify provides managed services for databases and cron jobs. For Coolify deployment:
- Use the standard
docker-compose.yml(not the selfhost version) - Set environment variables in Coolify's interface
- Mark build variables: Ensure
NEXT_PUBLIC_GITHUB_APP_NAMEis marked as "Is Build Variable?" in Coolify - Use managed database: Set
DATABASE_URLto point to your Coolify-managed database - Configure scheduled tasks: Use Coolify's scheduled tasks feature instead of the cron container
Note: Vercel only allows once per day cron jobs for free accounts.
These platforms handle the build and deployment automatically:
- Connect your GitHub repository
- Set environment variables in the platform's dashboard
- The platform will build and deploy automatically
The system provides several health check endpoints:
# Application health
curl https://your-domain.com/api/health
# Example healthy response:
# {"status":"healthy","timestamp":"2025-07-16T21:27:07.286Z","version":"0.1.0","uptime":323.494783647,"environment":"production","checks":{"database":"ok","githubApp":"ok","webhook":"ok"}}# Application logs (full self-hosting)
docker-compose -f docker-compose.selfhost.yml logs -f app
# Cron job logs (full self-hosting)
docker-compose -f docker-compose.selfhost.yml logs -f cron
# Database logs (full self-hosting)
docker-compose -f docker-compose.selfhost.yml logs -f db
# Application logs (platform hosting)
docker-compose logs -f appdocker-compose -f docker-compose.selfhost.yml downdocker-compose -f docker-compose.selfhost.yml restartCheck your application logs and cron job logs in the locations you specified.
Clean up old completed tasks periodically:
# Using tRPC API
curl -X POST "https://your-domain.com/api/trpc/admin.cleanup" \
-H "Content-Type: application/json" \
-d '{"olderThanDays": 30}'
# Or using the database directly
psql $DATABASE_URL -c "DELETE FROM \"JulesTask\" WHERE \"createdAt\" < NOW() - INTERVAL '30 days' AND \"flaggedForRetry\" = false;"Error: "Invalid environment variables" or client-side variables not available
Solution:
- For Coolify: Ensure
NEXT_PUBLIC_GITHUB_APP_NAMEis marked as "Is Build Variable?" - For self-hosting: Make sure all required variables are set in your
.envfile - For GitHub App private key: Ensure it's properly formatted (base64 encoded or escaped newlines)
Error: "Invalid keyData" or "Failed to read private key"
Solution: Format your private key correctly. You can either:
# Option 1: Base64 encode the entire key
cat your-private-key.pem | base64 > private-key-base64.txt
# Then set GITHUB_APP_PRIVATE_KEY to the base64 string
# Option 2: Escape newlines manually
# Replace all \n with \\n in your private key string- Docker: Check if cron container is running:
docker-compose -f docker-compose.selfhost.yml ps - Manual: Verify crontab is correctly configured:
crontab -l - Logs: Check cron execution logs for errors
- Coolify: Use the platform's scheduled tasks feature instead
- Secret: Verify
GITHUB_APP_WEBHOOK_SECRETmatches GitHub configuration - URL: Ensure webhook URL is accessible from GitHub
- Events: Confirm "Issues" events are selected in GitHub webhook settings
- URL: Verify
DATABASE_URLis correct - Network: Ensure database is accessible from application
- Migrations: Run
pnpm db:migrateif using manual installation
This usually indicates container/service conflicts:
- Coolify: Make sure you're using
docker-compose.yml(notdocker-compose.selfhost.yml) - Self-hosting: Make sure you're using
docker-compose.selfhost.yml - Port conflicts: Ensure no other services are using ports 3000 or 5432
Enable debug logging:
# Set environment variable
DEBUG=jules:*
# Or check application logs for detailed information
docker-compose -f docker-compose.selfhost.yml logs -f app | grep -E "(ERROR|WARN|cron)"- Database: Use strong passwords and limit network access
- API Keys: Store in secure environment variables, not in code
- HTTPS: Always use HTTPS in production
- Firewall: Limit access to necessary ports only
- Updates: Keep Docker images and dependencies updated
# Database backup (self-hosting)
docker-compose -f docker-compose.selfhost.yml exec db pg_dump -U jules jules_queue > backup.sql
# Restore from backup
docker-compose -f docker-compose.selfhost.yml exec -T db psql -U jules jules_queue < backup.sql- API Documentation: See
API_DOCUMENTATION.mdfor tRPC endpoint details - Issues: Create GitHub issues for bugs or questions
- Health Check: Always verify
/api/healthreturns{"status":"healthy"}after deployment