TaskServer is an always-on Node.js server for running and scheduling scripts with a web-based dashboard. It provides an easy way to manage long-running processes and scheduled cron jobs without the need for a database.
- Forever Scripts: Run long-running scripts that automatically restart on failure
- Cron Jobs: Schedule scripts to run at specific intervals
- Web Dashboard: Monitor and manage all your scripts from a beautiful web interface
- Log Management: View, download, and automatically clean up old logs
- Cloudflare Tunnel: Securely access your dashboard from anywhere online
- Configuration via YAML: Simple configuration file for all settings
- No Database Required: Lightweight and easy to deploy
- PM2 Integration: Reliable process management using PM2
- Modern UI: Clean and responsive web interface
- Installation
- Quick Start
- Configuration
- Script Types
- Web Dashboard
- Cloudflare Tunnel Setup
- Log Management
- API Endpoints
- Usage Examples
- Troubleshooting
- Node.js >= 14.0.0
- npm or yarn
- Python 3.x (if you plan to run Python scripts)
- Clone the repository:
git clone https://github.com/raylin01/TaskServer.git
cd TaskServer- Install dependencies:
npm install- Create your configuration file:
cp config.example.yaml config.yaml- Edit
config.yamlto add your scripts and configure settings:
nano config.yaml # or use your preferred editor- Configure your scripts in
config.yaml:
scripts:
- name: myForeverScript
path: ./scripts/myScript.js
type: forever
args: []
env: {}- Start the server:
npm start- Open the dashboard:
Navigate to http://localhost:3000 in your browser.
TaskServer supports self-updates via GitSync!
To enable this:
- Install PM2:
npm install -g pm2(or usenpx pm2). - Run with PM2: You MUST start TaskServer using PM2 with the name
taskserver.pm2 start server.js --name taskserver
- Configure GitSync: Add TaskServer to your GitSync config (see GitSync docs).
When updated, GitSync will call the restart API. TaskServer detects it is restarting itself and performs a graceful pm2 restart instead of a full stop/start cycle.
All configuration is done in the config.yaml file.
# Log Management Settings
logManagement:
autoDelete: true # Enable automatic deletion of old logs
retentionDays: 7 # Keep logs for 7 days
checkInterval: 3600000 # Check every hour (in milliseconds)
# Server Settings (Optional)
server:
port: 3000 # Web interface port (default: 3000)
logsDir: "./logs" # Directory to store logs (default: ./logs)
# PM2 Settings (Optional)
pm2:
maxRestarts: 10000 # Max restarts before giving up (default: 10000)
autoRestart: true # Auto restart on crash (default: true)
# Cloudflare Tunnel Settings (Optional)
cloudflare:
enabled: false # Set to true to enable Cloudflare Tunnel
tunnelToken: "" # Your Cloudflare Tunnel token
# Scripts Configuration
scripts:
- name: exampleForever
path: ./scripts/exampleForever.js
type: forever
args: []
env: {}
- name: exampleCron
path: ./scripts/exampleCron.py
type: cron
schedule: '0 * * * *' # Run every hour (cron syntax)
count: 5 # Optional: limit number of runs
args: ["--foo", "bar"]
env: {FOO: "bar"}TaskServer uses PM2 under the hood, which automatically detects and runs scripts based on their file extension:
| Extension | Interpreter | Example |
|---|---|---|
.js, .mjs, .cjs, .ts |
Node.js | myScript.js |
.py |
Python | myScript.py |
.sh |
Bash | myScript.sh |
.rb |
Ruby | myScript.rb |
| Any executable | Direct execution | myBinary |
Note: Make sure the required interpreter (Python, Ruby, etc.) is installed on your system and available in PATH.
Forever scripts are long-running processes that will automatically restart if they crash.
scripts:
- name: myService
path: ./scripts/service.js
type: forever
args: ["--port", "8080"]
env:
NODE_ENV: production
API_KEY: your-api-keyUse cases:
- Web servers
- Background workers
- Message queue consumers
- Real-time data processors
Cron scripts run on a schedule using cron syntax.
scripts:
- name: dailyBackup
path: ./scripts/backup.sh
type: cron
schedule: '0 2 * * *' # Run at 2 AM daily
count: 100 # Optional: stop after 100 runs
args: ["--destination", "/backups"]
env:
BACKUP_PATH: /dataYou can run shell commands directly without needing a script file. Use command instead of path:
scripts:
# Run a webhook every 5 minutes
- name: apiWebhook
command: curl -X POST https://api.example.com/webhook -H "Content-Type: application/json"
type: cron
schedule: '*/5 * * * *'
env:
API_KEY: your-key
# Monitor a service continuously
- name: healthCheck
command: ping -c 1 google.com && echo "Service is up"
type: foreverCommon use cases:
- API webhooks and HTTP requests (
curl,wget) - System commands (
echo,date,uptime) - Database backups (
mysqldump,pg_dump) - File operations (
rsync,cp,mv) - Chained commands using
&&or||
Cron Syntax:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 7) (Sunday = 0 or 7)
│ │ │ │ │
* * * * *
Common patterns:
* * * * *- Every minute0 * * * *- Every hour0 0 * * *- Daily at midnight0 0 * * 0- Weekly on Sunday0 0 1 * *- Monthly on the 1st
The web dashboard provides a comprehensive interface to manage your scripts.
- View all configured scripts
- See real-time status (running, stopped, scheduled)
- Start, stop, or restart scripts
- View last run time for cron jobs
- Quick access to logs
- View logs for any script
- Auto-refresh capability
- Download individual log files
- Delete old log files
- View log statistics (total size, file count)
- Syntax highlighting for better readability
- Add new scripts through the web interface
- Configure all script parameters
- Choose between forever and cron types
- Modify existing script configurations
- Update schedules, arguments, and environment variables
- Configure log management settings
- Set up Cloudflare Tunnel
- Adjust retention policies
Access your TaskServer dashboard from anywhere on the internet using Cloudflare Tunnel.
- Go to Cloudflare Zero Trust Dashboard
- Navigate to Access → Tunnels
- Click Create a tunnel
- Choose Cloudflared and follow the setup
- Copy your tunnel token
cloudflare:
enabled: true
tunnelToken: "your-cloudflare-tunnel-token-here"npm startThe console will display your public URL:
TaskServer running at http://localhost:3000
Starting Cloudflare Tunnel...
Cloudflare Tunnel URL: https://xxx-xxx-xxx.trycloudflare.com
Dashboard accessible online at: https://xxx-xxx-xxx.trycloudflare.com
- Secure Access: No need to expose ports or configure firewall rules
- HTTPS by Default: Automatic SSL/TLS encryption
- No Static IP Required: Works from anywhere, even behind NAT
- Free: Cloudflare Tunnel is free to use
You can also run cloudflared as a TaskServer forever script to expose other services (like GitSync webhooks) to the internet:
scripts:
# Expose a service on port 4000 (e.g., GitSync webhook server)
- name: my-tunnel
command: cloudflared tunnel --url http://localhost:4000
type: forever
# Or use a named tunnel with a token for a permanent URL
- name: my-named-tunnel
command: cloudflared tunnel run --token YOUR_TUNNEL_TOKEN
type: foreverQuick tunnel (auto-generated URL):
cloudflared tunnel --url http://localhost:4000
# Outputs: https://xxx-xxx-xxx.trycloudflare.comNamed tunnel (permanent custom domain):
- Create a tunnel in Cloudflare Zero Trust Dashboard
- Configure routing to your local service
- Use the token in TaskServer config above
Tip: Running cloudflared via TaskServer gives you auto-restart on failure, log management, and unified control over all your tunnels.
TaskServer automatically manages logs for all your scripts.
Configure automatic deletion of old logs:
logManagement:
autoDelete: true # Enable automatic cleanup
retentionDays: 7 # Keep logs for 7 days
checkInterval: 3600000 # Check every hour (1 hour = 3600000ms)Logs are stored in the logs/ directory with the following naming convention:
- Forever scripts:
{scriptName}-out-{timestamp}.logand{scriptName}-error-{timestamp}.log - Cron scripts:
{scriptName}-out-{timestamp}.logand{scriptName}-error-{timestamp}.log
- Web Dashboard: Navigate to
/logs/:scriptName - Direct File Access: Check the
logs/directory
- Download: Click the download button in the logs viewer
- Delete: Click the delete button for individual log files
- Auto-refresh: Enable live log viewing in the dashboard
TaskServer provides REST API endpoints for programmatic access.
GET /scripts- List all scripts with statusGET /add-script- Show add script formPOST /add-script- Add a new scriptGET /edit-script/:scriptName- Show edit formPOST /edit-script/:scriptName- Update a scriptPOST /delete-script/:scriptName- Delete a script
These endpoints return JSON and support optional API key authentication:
GET /api/scripts- List all scripts with status as JSONPOST /api/restart-script/:scriptName- Restart a forever scriptPOST /api/stop-script/:scriptName- Stop a forever scriptPOST /api/start-script/:scriptName- Start a forever script
Authentication (optional):
Enable in config.yaml:
api:
authEnabled: true
apiKey: "your-secret-key"Include the API key in requests:
# Via header
curl -X POST http://localhost:3000/api/restart-script/myScript \
-H "X-API-Key: your-secret-key"
# Via query parameter
curl -X POST "http://localhost:3000/api/restart-script/myScript?apiKey=your-secret-key"GET /logs/:scriptName- View logs pageGET /api/logs/:scriptName- Get logs as JSONGET /api/logs/:scriptName/download?file=filename- Download log fileDELETE /api/logs/:scriptName/delete?file=filename- Delete log file
GET /settings- View settings pagePOST /settings- Update settings
Script: scripts/webServer.js
const express = require('express');
const app = express();
const port = process.env.PORT || 8080;
app.get('/', (req, res) => {
res.send('Hello from TaskServer!');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`);
});Configuration:
scripts:
- name: webServer
path: ./scripts/webServer.js
type: forever
args: []
env:
PORT: 8080
NODE_ENV: productionScript: scripts/dataSync.py
#!/usr/bin/env python3
import sys
import datetime
def main():
print(f"Running data sync at {datetime.datetime.now()}")
# Your sync logic here
print("Data sync completed!")
if __name__ == "__main__":
main()Configuration:
scripts:
- name: dataSync
path: ./scripts/dataSync.py
type: cron
schedule: '0 */6 * * *' # Every 6 hours
args: []
env: {}Script: scripts/backup.sh
#!/bin/bash
SOURCE=$1
DEST=$2
echo "Backing up from $SOURCE to $DEST"
tar -czf "$DEST/backup-$(date +%Y%m%d).tar.gz" "$SOURCE"
echo "Backup completed!"Configuration:
scripts:
- name: backup
path: ./scripts/backup.sh
type: cron
schedule: '0 3 * * *' # Daily at 3 AM
args: ["/data", "/backups"]
env:
BACKUP_RETENTION: "30"- Check script path: Ensure the path is correct and relative to the TaskServer root
- Check permissions: Make sure scripts are executable (
chmod +x script.sh) - Check logs: View logs in the dashboard for error messages
- Verify dependencies: Ensure all required packages are installed
- Token not working: Verify you copied the complete token from Cloudflare
- Tunnel not starting: Check that
enabled: truein config.yaml - URL not showing: Wait up to 15 seconds for the tunnel to establish
- Enable automatic log cleanup:
logManagement: autoDelete: true retentionDays: 3
- Manually delete logs from the dashboard
- Implement log rotation in your scripts
- Restart the server:
npm start - Clear PM2 processes:
pm2 killthen restart - Check PM2 logs:
pm2 logs
TaskServer/
├── server.js # Main server entry point
├── config.yaml # Configuration file
├── package.json # Dependencies
├── logs/ # Log files directory
├── public/ # Static assets
│ └── styles.css # Dashboard styles
├── routes/ # Express routes
│ └── scripts.js # Script management routes
├── scripts/ # Your scripts go here
│ ├── exampleForever.js
│ └── exampleCron.py
├── utils/ # Utility modules
│ ├── configHandler.js # Config loading/saving
│ ├── logViewer.js # Log management
│ ├── logCleanup.js # Automatic log cleanup
│ └── cloudflareTunnel.js # Cloudflare Tunnel integration
└── views/ # EJS templates
├── layout.ejs
├── scripts.ejs
├── logs.ejs
├── add-script.ejs
├── edit-script.ejs
└── settings.ejs
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.
- Built with Express.js
- Process management by PM2
- Scheduling with node-cron
- Cloudflare Tunnel support via cloudflared
If you encounter any issues or have questions, please open an issue on GitHub.