runit is a lightweight, cross-platform Unix init scheme with service supervision that provides a reliable alternative to traditional init systems. Developed by Gerrit Pape, runit offers a simple yet powerful approach to process supervision and system initialization, making it an excellent choice for embedded systems, containers, and servers requiring robust service management.
What is runit?
runit is a Unix init scheme that replaces the traditional SysV init system with a more reliable and simpler approach. It consists of three main stages and provides automatic service supervision, meaning it continuously monitors running services and automatically restarts them if they fail. This makes runit particularly valuable for mission-critical applications where uptime is essential.
The system is designed around the philosophy of “do one thing and do it well,” focusing specifically on process supervision and service management. Unlike systemd or other complex init systems, runit maintains simplicity while providing robust functionality.
Key Features of runit
- Automatic Service Supervision: Continuously monitors services and restarts failed processes
- Simple Configuration: Uses plain shell scripts for service definitions
- Fast Boot Times: Parallel service startup reduces boot time
- Reliable Logging: Built-in logging mechanism with svlogd
- Cross-Platform: Works on Linux, BSD, and other Unix-like systems
- Small Footprint: Minimal resource usage and dependencies
runit Architecture
runit operates through three distinct stages:
Stage 1: System Initialization
This stage handles one-time system initialization tasks such as mounting filesystems, configuring network interfaces, and setting up the basic system environment. It’s equivalent to the traditional /etc/rc.sysinit script.
Stage 2: Service Supervision
The core of runit, this stage starts the runsvdir program which supervises all services. It continuously monitors service directories and automatically starts, stops, and restarts services as needed.
Stage 3: System Shutdown
Handles graceful system shutdown, including stopping all supervised services, unmounting filesystems, and performing cleanup tasks.
Installing runit
runit installation varies depending on your Linux distribution:
Ubuntu/Debian:
sudo apt-get update
sudo apt-get install runit
CentOS/RHEL:
sudo yum install runit
# or for newer versions
sudo dnf install runit
Arch Linux:
sudo pacman -S runit
From Source:
wget http://smarden.org/runit/runit-2.1.2.tar.gz
tar xzf runit-2.1.2.tar.gz
cd runit-2.1.2
package/install
Basic runit Commands
runit provides several essential commands for service management:
sv – Service Control
The sv command is the primary tool for controlling services:
# Start a service
sv start service_name
# Stop a service
sv stop service_name
# Restart a service
sv restart service_name
# Check service status
sv status service_name
# Get service uptime
sv up service_name
Example Output:
$ sv status nginx
run: nginx: (pid 1234) 3600s
$ sv status down_service
down: down_service: 0s, normally up
runsvdir – Service Directory Monitor
Monitors service directories and starts runsv for each service:
runsvdir /etc/service
runsv – Single Service Supervisor
Supervises individual services:
runsv /etc/service/nginx
Creating runit Services
Creating services in runit involves setting up service directories with executable run scripts:
Basic Service Structure
/etc/sv/myservice/
├── run # Main service script (required)
├── finish # Cleanup script (optional)
├── down # Prevents auto-start (optional)
└── log/ # Logging service (optional)
└── run # Log service script
Creating a Simple Web Server Service
Let’s create a service for a simple Python HTTP server:
# Create service directory
sudo mkdir -p /etc/sv/webserver
# Create the run script
sudo tee /etc/sv/webserver/run << 'EOF'
#!/bin/sh
exec 2>&1
cd /var/www/html
exec python3 -m http.server 8080
EOF
# Make it executable
sudo chmod +x /etc/sv/webserver/run
# Enable the service
sudo ln -s /etc/sv/webserver /etc/service/
Service with Logging
# Create log directory
sudo mkdir -p /etc/sv/webserver/log
# Create log run script
sudo tee /etc/sv/webserver/log/run << 'EOF'
#!/bin/sh
exec svlogd -tt /var/log/webserver
EOF
# Make it executable
sudo chmod +x /etc/sv/webserver/log/run
# Create log directory
sudo mkdir -p /var/log/webserver
Advanced Service Configuration
Service with Environment Variables
# Create environment directory
sudo mkdir -p /etc/sv/myapp/env
# Set environment variables
echo "production" | sudo tee /etc/sv/myapp/env/NODE_ENV
echo "3000" | sudo tee /etc/sv/myapp/env/PORT
# Updated run script
sudo tee /etc/sv/myapp/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -e ./env -u appuser node /opt/myapp/server.js
EOF
Service with User Privileges
sudo tee /etc/sv/database/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -u postgres:postgres /usr/bin/postgres -D /var/lib/postgresql/data
EOF
Service Management Examples
Monitoring Service Status
# Check all services
sudo sv status /etc/service/*
# Example output:
run: apache2: (pid 1456) 7200s
run: nginx: (pid 1234) 3600s
down: mysql: 120s, normally up
run: ssh: (pid 892) 86400s
Interactive Service Control
# Start multiple services
for service in nginx mysql redis; do
sv start $service
echo "Started $service"
done
# Monitor service startup
watch 'sv status /etc/service/*'
Logging with svlogd
runit includes svlogd, a powerful logging daemon that provides automatic log rotation and filtering:
Basic Logging Configuration
# Log configuration file
sudo tee /var/log/myservice/config << 'EOF'
s1000000 # Maximum log file size (1MB)
n10 # Keep 10 log files
t # Add timestamps
EOF
Log Filtering
# Filter logs by pattern
sudo tee /var/log/myservice/config << 'EOF'
+*error* # Include lines containing 'error'
-*debug* # Exclude lines containing 'debug'
s10000000 # 10MB log files
n5 # Keep 5 files
EOF
Troubleshooting runit Services
Common Issues and Solutions
Service Won’t Start
# Check if run script is executable
ls -la /etc/sv/myservice/run
# Check for syntax errors
sh -n /etc/sv/myservice/run
# Check service logs
sudo tail -f /var/log/myservice/current
Service Keeps Restarting
# Check service status with details
sv status /etc/service/myservice
# Monitor service restarts
while true; do
sv status /etc/service/myservice
sleep 1
done
Debugging Service Scripts
# Add debug output to run script
#!/bin/sh
exec 2>&1
echo "Starting service at $(date)"
echo "Environment: $(env)"
echo "User: $(whoami)"
exec /path/to/program
Performance and Resource Management
Resource Limits
# Limit memory usage
sudo tee /etc/sv/myapp/run << 'EOF'
#!/bin/sh
exec 2>&1
exec chpst -m 100000000 -u appuser /opt/myapp/bin/myapp
EOF
CPU Limits
# Nice priority adjustment
exec chpst -n 10 -u appuser /opt/myapp/bin/myapp
Migration from Other Init Systems
From systemd
Converting a systemd service to runit:
# systemd service file
[Unit]
Description=My Web App
After=network.target
[Service]
Type=simple
User=webuser
WorkingDirectory=/opt/webapp
ExecStart=/opt/webapp/bin/server
Restart=always
[Install]
WantedBy=multi-user.target
Equivalent runit service:
# /etc/sv/webapp/run
#!/bin/sh
exec 2>&1
cd /opt/webapp
exec chpst -u webuser /opt/webapp/bin/server
Best Practices
Service Design Principles
- Keep run scripts simple: Avoid complex logic in run scripts
- Use exec: Replace the shell process with your program
- Redirect stderr: Use
exec 2>&1to combine output streams - Avoid daemonization: Run programs in foreground mode
- Set working directory: Use
cdbefore executing programs
Security Considerations
# Run service as non-root user
exec chpst -u serviceuser:servicegroup /path/to/program
# Set environment cleanly
exec chpst -e ./env -u serviceuser /path/to/program
# Limit resources
exec chpst -m 100000000 -o 1000 -u serviceuser /path/to/program
Monitoring and Alerting
Service Health Checks
#!/bin/bash
# health_check.sh
for service in $(ls /etc/service/); do
status=$(sv status "/etc/service/$service" 2>/dev/null)
if [[ $status == down* ]]; then
echo "ALERT: $service is down"
# Send notification
fi
done
Automated Service Recovery
# /etc/sv/myservice/finish
#!/bin/sh
# Cleanup script that runs when service exits
echo "Service $1 exited with code $2 at $(date)" >> /var/log/myservice/finish.log
# Conditional restart logic
if [ "$2" -eq "100" ]; then
# Exit code 100 means don't restart
touch ./down
fi
Conclusion
runit provides a robust, lightweight alternative to complex init systems while maintaining simplicity and reliability. Its service supervision capabilities, combined with straightforward configuration and excellent performance characteristics, make it an excellent choice for various deployment scenarios.
The system’s philosophy of simplicity doesn’t compromise functionality – from basic service management to advanced logging and resource control, runit offers all the tools necessary for effective system administration. Whether you’re managing a single server or a complex distributed system, runit’s reliable service supervision ensures your applications remain available and performant.
By following the practices and examples outlined in this guide, you’ll be well-equipped to implement runit in your infrastructure and take advantage of its powerful service supervision capabilities. The lightweight nature and cross-platform compatibility make it particularly valuable for modern containerized environments and embedded systems where resource efficiency is crucial.