An open source Rails application for orchestrating cryptocurrency mining rigs. Manage multiple XMRig miners from a centralized web interface with real-time monitoring and configuration management.
- Multi-Rig Orchestration: Manage multiple mining rigs from a single dashboard
- Real-Time Monitoring: WebSocket-powered live updates via Action Cable
- XMRig Integration: Full support for CPU, GPU, and hybrid mining configurations
- Zero-Downtime Deployments: Kamal-based container deployments across multiple servers
- PWA-Ready: Progressive Web App support for mobile access
- Background Jobs: Solid Queue for reliable job processing
- Framework: Ruby on Rails 8.1
- Ruby Version: 3.4.5
- Database: SQLite3 (with Solid Cache, Solid Queue, Solid Cable)
- Frontend: Hotwire (Turbo + Stimulus)
- Asset Pipeline: Propshaft with Import Maps
- Deployment: Kamal with Docker
- Web Server: Puma with Thruster
- Error Tracking: Sentry (optional)
- Ruby 3.4.5
- SQLite3
- XMRig (for mining operations)
-
Clone the repository:
git clone https://github.com/yourusername/zen-miner.git cd zen-miner -
Install dependencies:
bundle install
-
Setup the database:
bin/rails db:setup
-
Start the development server:
bin/dev
-
Visit
http://localhost:3000
# Run all tests
bin/rails test
# Run system tests
bin/rails test:systemXMRig configuration files are stored in configs/:
| File | Purpose |
|---|---|
configs/cpu.json |
CPU-only mining |
configs/gpu.json |
GPU mining (OpenCL/CUDA) |
configs/hybrid.json |
Combined CPU+GPU mining |
Configure via Rails credentials or environment variables:
| Variable | Description |
|---|---|
RAILS_MASTER_KEY |
Rails encrypted credentials key |
MONERO_WALLET |
Destination wallet address |
Zen Miner uses Kamal for container deployments with a unique architecture where the Rails app runs in Docker containers while XMRig mining daemons run directly on the host machines.
Docker Host
├── Rails App (Docker container) → Web interface, API, job processing
│ └── SQLite DB @ /rails/storage → Shared via volume mount
├── XMRig (systemd service) → Mining process (runs on host)
├── Orchestrator (systemd daemon) → Command processor (runs on host)
└── /mnt/rails-storage → Shared volume for database
- Docker hosts configured with Kamal access
- Environment variables set:
RAILS_MASTER_KEY- Rails credentials encryption keyMONERO_WALLET- Monero wallet address for mining rewards
- Kamal 2.10.1+ installed locally
- SSH access to all host machines
# First-time setup
bin/kamal setup
# Deploy latest changes
bin/kamal deploy
# Verify deployment
bin/kamal logsThis deploys the Rails app with:
- SQLite database in
/rails/storage(mounted as Docker volume) - Puma web server with Thruster
- Solid Queue for background jobs
- Action Cable for real-time updates
CRITICAL: Host daemons must be installed AFTER Rails deployment to ensure database is available.
Prerequisites: Ruby and XMRig must be installed and available in PATH before running the installation script.
For each mining host, SSH in and run:
# SSH to host machine
ssh user@mining-host
# Verify prerequisites are installed
ruby --version # Should show Ruby 3.x or later
xmrig --version # Should show XMRig installation
# Clone repository (or copy host-daemon directory)
git clone https://github.com/yourusername/zen-miner.git
cd zen-miner/host-daemon
# ⚠️ SECURITY WARNING ⚠️
# NEVER commit wallet addresses to version control
# NEVER echo these values in scripts or logs
# Store wallet addresses securely (use environment variables or secrets manager)
# Set required environment variables
export MONERO_WALLET="your-monero-wallet-address" # ⚠️ Keep secret!
export WORKER_ID="unique-worker-id" # Unique identifier for this host
export POOL_URL="pool.hashvault.pro:443" # Optional
export CPU_MAX_THREADS_HINT="50" # Optional
# Run installation script as root
sudo ./install.shThe installation script ALWAYS executes all steps and restarts services on every run:
- ✅ Configuration files are ALWAYS overwritten with current environment variables
- ✅ Services are ALWAYS restarted after installation
- ✅ No idempotency checks - all steps run every time
⚠️ Manual config customizations will be lost (must be represented in environment variables)⚠️ Services experience brief downtime during installation/updates
This ensures:
- Configuration always matches current environment
- Services run with latest code after updates
- No edge cases from partial installations
The installation script will:
- Verify Ruby and XMRig are installed
- Install system dependencies (SQLite3, sudo)
- Create
xmrigandxmrig-orchestratorsystem users - Configure sudo permissions for orchestrator
- Generate XMRig configuration (ALWAYS overwrites
/etc/xmrig/config.json) - Install orchestrator daemon
- Set up systemd services (ALWAYS restarts services)
- Configure log rotation (7-day retention)
# Start the orchestrator daemon
sudo systemctl start xmrig-orchestrator
# Check status
sudo systemctl status xmrig-orchestrator
# View logs
sudo journalctl -u xmrig-orchestrator -fFrom Rails console or web interface:
# Start mining (uses WORKER_ID from environment)
Xmrig::CommandService.start_mining
# Stop mining
Xmrig::CommandService.stop_mining(reason: 'maintenance')
# Restart mining
Xmrig::CommandService.restart_mining(reason: 'config_change')After making changes to host-daemon/xmrig-orchestrator, update all hosts:
- Overwrite the orchestrator binary at
/usr/local/bin/xmrig-orchestrator - Restart the
xmrig-orchestratorservice (brief downtime expected) - Re-run all installation steps (no idempotency checks)
- Ensure all configuration files match current environment variables
For security, SSH host keys must be verified before deployment:
# Add all configured hosts to known_hosts (first time only)
bin/update-orchestrators-ssh --add-hosts
# Or list currently known hosts
bin/update-orchestrators-ssh --list-hosts~/.ssh/known_hosts (standard SSH location) to prevent MITM attacks. Each user must verify their own mining hosts before deployment.
# Update all hosts via SSH (with host key verification)
bin/update-orchestrators-ssh
# Update specific host
bin/update-orchestrators-ssh --host mini-1 --yes
# Dry run (show what would be executed)
bin/update-orchestrators-ssh --dry-run
# Show binary checksum (for verification)
bin/update-orchestrators-ssh --show-checksum
# Skip host key verification (INSECURE - only for testing)
bin/update-orchestrators-ssh --skip-host-verificationWhen to update orchestrators:
- After database migrations affecting
xmrig_commandsorxmrig_processestables - After changes to orchestrator code logic
- After bug fixes in the daemon
- If seeing "no such column" errors in orchestrator logs
Security Features:
- ✅ SSH host key verification prevents MITM attacks
- ✅ SHA256 checksum verification ensures binary integrity
- ✅ Parallel deployment with 10 concurrent workers
- ✅ 5-minute timeout per host prevents hanging
- ✅ Memory protection (output truncated at 100KB)
Binary Checksum Verification:
The deployment process automatically verifies file integrity using SHA256 checksums:
- Pre-deployment: Calculate SHA256 checksum of local
host-daemon/xmrig-orchestratorfile - Post-copy: Verify checksum on each remote host after file transfer
- Failure handling: Deployment aborts if checksum doesn't match
To view the checksum before deployment:
bin/update-orchestrators-ssh --show-checksumThis prevents:
- Corrupted file transfers
- Tampering during transit
- Deployment of unintended binaries
Note: The update script uses direct SSH (not container-based) for security. Rails containers never have write access to the host filesystem.
When deploying changes:
# 1. Deploy Rails application
bin/kamal deploy
# 2. Update orchestrators if daemon code changed
bin/update-orchestrators-ssh
# 3. Verify health
bin/kamal logs
ssh deploy@mini-1 'sudo systemctl status xmrig-orchestrator'The database is shared between Rails container and host daemons via volume mount:
# config/deploy.yml
volumes:
- "/mnt/rails-storage:/rails/storage"Important: Ensure /mnt/rails-storage exists on all hosts before deployment.
The orchestrator daemon monitors XMRig health every 10 seconds:
- Checks: Process status, HTTP API response, hashrate > 0
- Auto-restart: Immediate restart on any error (no backoff)
- Logging: Structured logs to
/var/log/xmrig/orchestrator.log
View health status:
# From host
curl http://127.0.0.1:8080/2/summary | jq
# From Rails console
XmrigProcess.find_by(hostname: 'host1')Issue: Orchestrator can't connect to database
# Check volume mount
ls -la /mnt/rails-storage/production.sqlite3
# Check database permissions
sudo -u xmrig-orchestrator sqlite3 /mnt/rails-storage/production.sqlite3 "SELECT 1"
# Check orchestrator logs
sudo journalctl -u xmrig-orchestrator -n 50Issue: XMRig won't start
# Check XMRig service
sudo systemctl status xmrig
# Check XMRig logs
sudo journalctl -u xmrig -n 50
# Validate config
cat /etc/xmrig/config.json | jqIssue: Commands not processing
# Check for pending commands in database
sudo sqlite3 /mnt/rails-storage/production.sqlite3 \
"SELECT * FROM xmrig_commands WHERE hostname='$(hostname)' AND status='pending'"
# Check orchestrator is running
sudo systemctl is-active xmrig-orchestrator- Orchestrator privileges: Runs as dedicated
xmrig-orchestratoruser (not root) - Sudo configuration: NOPASSWD only for specific systemctl commands
- XMRig sandboxing: systemd security directives (NoNewPrivileges, PrivateTmp, ProtectSystem)
- Database concurrency: SQLite WAL mode enabled for multi-process access
- Binary verification: SHA256 checksum validation for XMRig downloads
- Wallet validation: Monero address format validation before installation
Before deploying to production:
- Rails app deployed and database accessible
- Host daemons installed on all mining hosts
- Orchestrator services running and healthy
- XMRig configuration validated
- Database volume mount working
- Health monitoring operational
- Logs being collected and rotated
- Test mining commands working
- Firewall rules configured (if needed)
- Monitoring and alerting set up
See config/deploy.yml for full Kamal configuration.
zen-miner/
├── app/ # Application code
│ ├── controllers/ # Request handlers
│ ├── models/ # Database models
│ ├── views/ # HTML templates
│ ├── javascript/ # Stimulus controllers
│ └── jobs/ # Background jobs
├── config/ # Configuration
│ ├── deploy.yml # Kamal deployment
│ └── database.yml # Database settings
├── configs/ # XMRig mining configs
├── db/ # Database migrations
├── specs/ # Feature specifications
└── test/ # Test suite
The project uses:
- RuboCop with Rails Omakase style
- Brakeman for security scanning
- Bundler Audit for dependency vulnerabilities
Run all checks:
bin/rubocop
bin/brakeman
bundle exec bundler-audit- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source. See the LICENSE file for details.