Who This Article Is For Primary Audience: DevOps Engineers, System Administrators, SRE Teams, Backend Developers managing Linux infrastructure Primary Audience: Prerequisites: Prerequisites: Basic Linux command-line experience Understanding of SSH and remote server management Familiarity with systemd services Basic knowledge of TLS/SSL certificates (helpful but not required) Basic Linux command-line experience Understanding of SSH and remote server management Familiarity with systemd services systemd Basic knowledge of TLS/SSL certificates (helpful but not required) What is Joblet? Joblet is a lightweight process isolation platform that lets you run commands and scripts in secure, resource-controlled environments. Think of it as a simpler alternative to Docker for process execution - no containers needed, just a single binary that provides: Secure isolation using Linux namespaces Resource limits for CPU, memory, and I/O Real-time Process monitoring and log streaming gRPC API with authentication Simple CLI for easy interaction Secure isolation using Linux namespaces Secure isolation Resource limits for CPU, memory, and I/O Resource limits Real-time Process monitoring and log streaming Real-time Process monitoring gRPC API with authentication gRPC API Simple CLI for easy interaction Simple CLI Whether you're building a CI/CD system, running user code safely, or need isolated task execution, Joblet provides a clean, production-ready solution. Why Use Joblet? Before vs After Scenarios Let's see how Joblet transforms common development and operations challenges with real examples: 🔍 System Call Isolation in Action 🔍 System Call Isolation in Action ❌ Without Joblet: Direct Host Execution (Dangerous) # Running ps aux directly on the host shows ALL system processes $ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.3 167744 13132 ? Ss Jun26 0:11 /sbin/init root 2 0.0 0.0 0 0 ? S Jun26 0:00 [kthreadd] systemd+ 564 0.0 0.2 90096 5392 ? Ss Jun26 0:00 /lib/systemd/systemd-resolved messagebus 565 0.0 0.1 8808 3840 ? Ss Jun26 0:02 /usr/bin/dbus-daemon --system joblet 1234 0.1 0.5 123456 10240 ? Sl Jun26 1:23 /opt/joblet/joblet postgres 2345 0.0 1.2 456789 25600 ? S Jun26 0:45 postgres: main process mysql 3456 0.2 2.1 789012 43520 ? Sl Jun26 2:10 mysqld --datadir=/var/lib/mysql apache2 4567 0.0 0.8 234567 16384 ? S Jun26 0:30 /usr/sbin/apache2 -DFOREGROUND ... user 9999 0.0 0.0 10072 1608 pts/2 R+ 17:37 0:00 ps aux # Running ps aux directly on the host shows ALL system processes $ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.3 167744 13132 ? Ss Jun26 0:11 /sbin/init root 2 0.0 0.0 0 0 ? S Jun26 0:00 [kthreadd] systemd+ 564 0.0 0.2 90096 5392 ? Ss Jun26 0:00 /lib/systemd/systemd-resolved messagebus 565 0.0 0.1 8808 3840 ? Ss Jun26 0:02 /usr/bin/dbus-daemon --system joblet 1234 0.1 0.5 123456 10240 ? Sl Jun26 1:23 /opt/joblet/joblet postgres 2345 0.0 1.2 456789 25600 ? S Jun26 0:45 postgres: main process mysql 3456 0.2 2.1 789012 43520 ? Sl Jun26 2:10 mysqld --datadir=/var/lib/mysql apache2 4567 0.0 0.8 234567 16384 ? S Jun26 0:30 /usr/sbin/apache2 -DFOREGROUND ... user 9999 0.0 0.0 10072 1608 pts/2 R+ 17:37 0:00 ps aux Security Issues: Security Issues: Process can see ALL system processes (including sensitive services) Has access to process details, PIDs, and resource usage Can potentially interact with or signal other processes No isolation from host system resources Process can see ALL system processes (including sensitive services) Has access to process details, PIDs, and resource usage Can potentially interact with or signal other processes No isolation from host system resources ✅ With Joblet ✅ With Joblet # Running the same command through Joblet shows ONLY the job's process $ rnx run ps aux Job started: ID: 120 Command: ps aux Status: RUNNING StartTime: 2025-01-15T17:34:33Z $ rnx log 120 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 0 1 0.0 0.0 10044 1580 ? R 17:34 0:00 ps aux # Running the same command through Joblet shows ONLY the job's process $ rnx run ps aux Job started: ID: 120 Command: ps aux Status: RUNNING StartTime: 2025-01-15T17:34:33Z $ rnx log 120 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND 0 1 0.0 0.0 10044 1580 ? R 17:34 0:00 ps aux Security Benefits: Security Benefits: Job sees ONLY its own process (PID 1 in isolated namespace) Cannot discover or interact with host processes Complete process isolation from host system Protected from interference by other jobs Job sees ONLY its own process (PID 1 in isolated namespace) Cannot discover or interact with host processes Complete process isolation from host system Protected from interference by other jobs Quick Start: Your First Job (Process) Installation # Download the latest release wget $(curl -s https://api.github.com/repos/ehsaniara/joblet/releases/latest | grep "browser_download_url.*_amd64\.deb" | cut -d '"' -f 4) # Interactive installation (recommended - prompts for server IP) sudo dpkg -i joblet_*_amd64.deb # Start the service sudo systemctl start joblet sudo systemctl enable joblet # test locally rnx --config=/opt/joblet/config/rnx-config.yml list # Download the latest release wget $(curl -s https://api.github.com/repos/ehsaniara/joblet/releases/latest | grep "browser_download_url.*_amd64\.deb" | cut -d '"' -f 4) # Interactive installation (recommended - prompts for server IP) sudo dpkg -i joblet_*_amd64.deb # Start the service sudo systemctl start joblet sudo systemctl enable joblet # test locally rnx --config=/opt/joblet/config/rnx-config.yml list That's it! Joblet is now running as a system service with auto-generated SSL certificates. Your First Process # Run a simple command rnx run echo "Hello from Joblet!" # Output: # Job started: # ID: 1 # Command: echo Hello from Joblet! # Status: RUNNING # StartTime: 2024-01-15T10:30:45Z # Network: host (shared with system) # Run a simple command rnx run echo "Hello from Joblet!" # Output: # Job started: # ID: 1 # Command: echo Hello from Joblet! # Status: RUNNING # StartTime: 2024-01-15T10:30:45Z # Network: host (shared with system) Congratulations! You just ran your first isolated job. Essential Commands Running Jobs The rnx run command is your main interface for job execution: rnx run # Basic command rnx run ls -la # Python script rnx run python3 -c "print('Hello from Python!')" # With resource limits rnx run --max-cpu=50 --max-memory=256 stress-ng --cpu 1 --timeout 30s # Complex shell commands rnx run bash -c "for i in {1..5}; do echo 'Iteration $i'; sleep 1; done" # Basic command rnx run ls -la # Python script rnx run python3 -c "print('Hello from Python!')" # With resource limits rnx run --max-cpu=50 --max-memory=256 stress-ng --cpu 1 --timeout 30s # Complex shell commands rnx run bash -c "for i in {1..5}; do echo 'Iteration $i'; sleep 1; done" Resource Limits Explained: Resource Limits Explained: --max-cpu=N - CPU percentage (50 = 50% of one core) --max-memory=N - Memory limit in MB --max-iobps=N - I/O operations per second limit --max-cpu=N - CPU percentage (50 = 50% of one core) --max-cpu=N --max-memory=N - Memory limit in MB --max-memory=N --max-iobps=N - I/O operations per second limit --max-iobps=N Monitoring Jobs # List all jobs rnx list # Output: # 1 COMPLETED StartTime: 2024-01-15T10:30:45Z Command: echo Hello from Joblet! # 2 RUNNING StartTime: 2024-01-15T10:31:20Z Command: sleep 60 # 3 FAILED StartTime: 2024-01-15T10:32:10Z Command: invalid-command # Get detailed job status rnx status 2 # Output: # Id: 2 # Command: sleep 60 # ExitCode: 0 # Started At: 2024-01-15T10:31:20Z # Ended At: # Status: RUNNING # MaxCPU: 100 # MaxMemory: 512 # MaxIOBPS: 0 # List all jobs rnx list # Output: # 1 COMPLETED StartTime: 2024-01-15T10:30:45Z Command: echo Hello from Joblet! # 2 RUNNING StartTime: 2024-01-15T10:31:20Z Command: sleep 60 # 3 FAILED StartTime: 2024-01-15T10:32:10Z Command: invalid-command # Get detailed job status rnx status 2 # Output: # Id: 2 # Command: sleep 60 # ExitCode: 0 # Started At: 2024-01-15T10:31:20Z # Ended At: # Status: RUNNING # MaxCPU: 100 # MaxMemory: 512 # MaxIOBPS: 0 Real-time Log Streaming One of Joblet's killer features is real-time log streaming: # Stream logs from a running job rnx log 2 # Output streams in real-time: # Logs for job 2 (Press Ctrl+C to exit if streaming): # Starting process... # Processing data... # Step 1 complete # Step 2 complete # ... # Stream logs from a running job rnx log 2 # Output streams in real-time: # Logs for job 2 (Press Ctrl+C to exit if streaming): # Starting process... # Processing data... # Step 1 complete # Step 2 complete # ... The log command automatically follows the output until the job completes or you press Ctrl+C. Configuration and Customization Server Configuration Joblet's behavior can be customized via configuration file at /opt/joblet/config/joblet-config.yml: /opt/joblet/config/joblet-config.yml server: address: "0.0.0.0" port: 50051 joblet: defaultCpuLimit: 100 # Default CPU limit (100%) defaultMemoryLimit: 512 # Default memory limit (512MB) defaultIoLimit: 0 # No I/O limit by default maxConcurrentJobs: 50 # Max simultaneous jobs jobTimeout: "1h" # Job timeout validateCommands: true # Enable command validation security: # Certificates embedded here automatically serverCert: | -----BEGIN CERTIFICATE----- ... serverKey: | -----BEGIN PRIVATE KEY----- ... caCert: | -----BEGIN CERTIFICATE----- ... logging: level: "INFO" # DEBUG, INFO, WARN, ERROR format: "text" # text or json output: "stdout" # stdout or file path server: address: "0.0.0.0" port: 50051 joblet: defaultCpuLimit: 100 # Default CPU limit (100%) defaultMemoryLimit: 512 # Default memory limit (512MB) defaultIoLimit: 0 # No I/O limit by default maxConcurrentJobs: 50 # Max simultaneous jobs jobTimeout: "1h" # Job timeout validateCommands: true # Enable command validation security: # Certificates embedded here automatically serverCert: | -----BEGIN CERTIFICATE----- ... serverKey: | -----BEGIN PRIVATE KEY----- ... caCert: | -----BEGIN CERTIFICATE----- ... logging: level: "INFO" # DEBUG, INFO, WARN, ERROR format: "text" # text or json output: "stdout" # stdout or file path After changing configuration: sudo systemctl restart joblet sudo systemctl restart joblet Client Configuration Point the CLI to a different server: # Connect to remote Joblet instance rnx --server 192.168.1.100:50051 run echo "Hello from remote!" # Or set it as default export JOBLET_SERVER=192.168.1.100:50051 rnx run echo "Using environment variable" # Connect to remote Joblet instance rnx --server 192.168.1.100:50051 run echo "Hello from remote!" # Or set it as default export JOBLET_SERVER=192.168.1.100:50051 rnx run echo "Using environment variable" Security and Authentication Certificate Management Joblet uses mTLS for security. Certificates are auto-generated during installation, but you can regenerate them: # Regenerate all certificates sudo /usr/local/bin/certs_gen.sh # This creates: # - CA certificate # - Server certificate # - Admin client certificate (full access) # - Viewer client certificate (read-only access) # Regenerate all certificates sudo /usr/local/bin/certs_gen.sh # This creates: # - CA certificate # - Server certificate # - Admin client certificate (full access) # - Viewer client certificate (read-only access) Role-Based Access Joblet supports two roles via certificate organizational units: Admin Role (full access): Admin Role Run jobs Stop jobs View job status and logs List all jobs Run jobs Stop jobs View job status and logs List all jobs Viewer Role (read-only): Viewer Role View job status and logs List all jobs Cannot run or stop jobs View job status and logs List all jobs Cannot run or stop jobs The role is determined by the OU field in the client certificate. OU Monitoring and Troubleshooting Service Status # Check Joblet service status sudo systemctl status joblet # View service logs sudo journalctl -u joblet -f # Check resource usage sudo systemctl show joblet --property=CPUUsageNSec,MemoryCurrent # Check Joblet service status sudo systemctl status joblet # View service logs sudo journalctl -u joblet -f # Check resource usage sudo systemctl show joblet --property=CPUUsageNSec,MemoryCurrent Job Debugging # Check job output for failed jobs rnx status <job-id> rnx log <job-id> # List recent jobs with status rnx list | head -10 # Monitor active jobs watch -n 2 'rnx list | grep RUNNING' # Check job output for failed jobs rnx status <job-id> rnx log <job-id> # List recent jobs with status rnx list | head -10 # Monitor active jobs watch -n 2 'rnx list | grep RUNNING' Performance Tips Resource Limits: Always set appropriate limits to prevent runaway jobs Concurrent Jobs: Monitor system resources when running many parallel jobs Log Management: Long-running jobs can generate large logs - consider log rotation Cleanup: Joblet automatically cleans up completed jobs, but monitor disk space Resource Limits: Always set appropriate limits to prevent runaway jobs Resource Limits Concurrent Jobs: Monitor system resources when running many parallel jobs Concurrent Jobs Log Management: Long-running jobs can generate large logs - consider log rotation Log Management Cleanup: Joblet automatically cleans up completed jobs, but monitor disk space Cleanup Comparison with Alternatives Feature Joblet Docker Systemd Setup Complexity Simple Moderate Complex Resource Isolation ✅ ✅ Limited Network Isolation Optional ✅ ❌ Filesystem Isolation ✅ ✅ ❌ Real-time Logs ✅ Manual Manual Job API ✅ Manual ❌ Single Binary ✅ ❌ ❌ Feature Joblet Docker Systemd Setup Complexity Simple Moderate Complex Resource Isolation ✅ ✅ Limited Network Isolation Optional ✅ ❌ Filesystem Isolation ✅ ✅ ❌ Real-time Logs ✅ Manual Manual Job API ✅ Manual ❌ Single Binary ✅ ❌ ❌ Feature Joblet Docker Systemd Feature Feature Joblet Joblet Docker Docker Systemd Systemd Setup Complexity Simple Moderate Complex Setup Complexity Setup Complexity Simple Simple Moderate Moderate Complex Complex Resource Isolation ✅ ✅ Limited Resource Isolation Resource Isolation ✅ ✅ ✅ ✅ Limited Limited Network Isolation Optional ✅ ❌ Network Isolation Network Isolation Optional Optional ✅ ✅ ❌ ❌ Filesystem Isolation ✅ ✅ ❌ Filesystem Isolation Filesystem Isolation ✅ ✅ ✅ ✅ ❌ ❌ Real-time Logs ✅ Manual Manual Real-time Logs Real-time Logs ✅ ✅ Manual Manual Manual Manual Job API ✅ Manual ❌ Job API Job API ✅ ✅ Manual Manual ❌ ❌ Single Binary ✅ ❌ ❌ Single Binary Single Binary ✅ ✅ ❌ ❌ ❌ ❌ Getting Help Documentation: Check the GitHub repository Issues: Report bugs and feature requests on GitHub Logs: Always check sudo journalctl -u joblet for service issues Community: Join discussions in the project's GitHub issues Documentation: Check the GitHub repository Documentation GitHub repository Issues: Report bugs and feature requests on GitHub Issues Logs: Always check sudo journalctl -u joblet for service issues Logs sudo journalctl -u joblet Community: Join discussions in the project's GitHub issues Community Conclusion Joblet provides a clean, simple way to run isolated jobs without the complexity of container orchestration. Whether you're processing data, running tests, or executing user code, Joblet's combination of security, simplicity, and real-time monitoring makes it an excellent choice for job execution. Key takeaways: Installation is simple: One package, automatic configuration Usage is intuitive: Familiar command-line interface Security is built-in: Namespace isolation and mTLS authentication Monitoring is real-time: Stream logs and monitor resource usage Integration is straightforward: gRPC API for programmatic access Installation is simple: One package, automatic configuration Installation is simple Usage is intuitive: Familiar command-line interface Usage is intuitive Security is built-in: Namespace isolation and mTLS authentication Security is built-in Monitoring is real-time: Stream logs and monitor resource usage Monitoring is real-time Integration is straightforward: gRPC API for programmatic access Integration is straightforward Start with simple commands, experiment with resource limits, and gradually integrate Joblet into your workflows. The platform is designed to grow with your needs while maintaining simplicity and security. GitHub https://github.com/ehsaniara/joblet?embedable=true https://github.com/ehsaniara/joblet?embedable=true