OpenRC is a lightweight, dependency-based init system that serves as an alternative to systemd and SysV init. Originally developed for Gentoo Linux, OpenRC has gained popularity across various distributions, particularly Alpine Linux, due to its simplicity, flexibility, and efficient resource usage.
What is OpenRC?
OpenRC stands for “Open Run Control” and represents a modern approach to system initialization and service management. Unlike traditional SysV init systems, OpenRC provides dependency-based service management, parallel service startup, and comprehensive logging capabilities while maintaining a smaller footprint than systemd.
Key Features of OpenRC
- Dependency-based service management: Services start based on their dependencies rather than fixed sequence numbers
- Parallel service startup: Independent services can start simultaneously, reducing boot times
- Cross-platform compatibility: Works on Linux, BSD, and other Unix-like systems
- Lightweight design: Minimal resource overhead compared to heavier init systems
- Flexible configuration: Easy-to-understand configuration files and service scripts
- Comprehensive logging: Detailed service startup and runtime logging
OpenRC Architecture and Components
OpenRC consists of several core components that work together to manage system initialization and services:
Core Components
- rc: The main init script that orchestrates the boot process
- runscript: The service management framework
- rc-status: Tool for monitoring service states
- rc-update: Service runlevel management utility
- rc-service: Service control interface
Directory Structure
/etc/init.d/ # Service scripts
/etc/runlevels/ # Runlevel directories
/etc/conf.d/ # Service configuration files
/var/lib/openrc/ # Runtime state information
/usr/share/openrc/ # OpenRC system files
Installation and Setup
Installing OpenRC on Different Distributions
On Alpine Linux (pre-installed):
# OpenRC comes pre-installed on Alpine Linux
apk info openrc
On Gentoo Linux:
# OpenRC is the default init system
emerge --ask sys-apps/openrc
On Debian/Ubuntu (alternative installation):
sudo apt update
sudo apt install openrc
Basic Configuration
After installation, configure OpenRC by editing the main configuration file:
# Edit the main OpenRC configuration
sudo nano /etc/rc.conf
Key configuration options include:
# Parallel startup (recommended)
rc_parallel="YES"
# Logging level
rc_logger="YES"
# Interactive mode for troubleshooting
rc_interactive="NO"
# Shell to use
rc_shell="/bin/sh"
Understanding Runlevels
OpenRC uses runlevels to organize services into different system states. The default runlevels include:
- sysinit: System initialization services
- boot: Basic system services required for operation
- default: Normal multi-user services
- shutdown: Services needed during system shutdown
Viewing Current Runlevel
# Check current runlevel
rc-status
# Example output:
Runlevel: default
acpid [ started ]
chronyd [ started ]
crond [ started ]
networking [ started ]
sshd [ started ]
syslog [ started ]
Managing Runlevels
# List all runlevels
ls /etc/runlevels/
# Switch to a different runlevel
sudo rc-update add service_name runlevel_name
sudo rc-update del service_name runlevel_name
Service Management with OpenRC
Basic Service Operations
OpenRC provides intuitive commands for managing services:
# Start a service
sudo rc-service nginx start
# Stop a service
sudo rc-service nginx stop
# Restart a service
sudo rc-service nginx restart
# Check service status
rc-service nginx status
# Reload service configuration
sudo rc-service nginx reload
Adding and Removing Services
# Add service to default runlevel
sudo rc-update add nginx default
# Remove service from runlevel
sudo rc-update del nginx default
# Show services in all runlevels
rc-update show
# Show services in specific runlevel
rc-update show default
Service Status Information
# Detailed status of all services
rc-status --all
# Status of specific runlevel
rc-status boot
# Show unused services
rc-status --unused
# Show services with dependencies
rc-status --list
Creating Custom OpenRC Services
Basic Service Script Structure
OpenRC service scripts are shell scripts with specific functions. Here’s a template for creating a custom service:
#!/sbin/openrc-run
# Service description
description="My Custom Application Service"
# Define the command to run
command="/usr/local/bin/myapp"
command_args="--daemon --config /etc/myapp/config.conf"
command_user="myapp:myapp"
pidfile="/var/run/myapp.pid"
# Dependencies
depend() {
need net
after logger
before nginx
}
# Pre-start function
start_pre() {
checkpath --directory --owner myapp:myapp --mode 0755 /var/run/myapp
checkpath --file --owner myapp:myapp --mode 0644 /var/log/myapp.log
}
# Post-start function
start_post() {
einfo "MyApp service started successfully"
}
# Pre-stop function
stop_pre() {
einfo "Stopping MyApp service gracefully"
}
Advanced Service Script Example
Here’s a more complex example for a web application service:
#!/sbin/openrc-run
description="Node.js Web Application"
command="/usr/bin/node"
command_args="/opt/webapp/app.js"
command_user="webapp:webapp"
command_background="yes"
pidfile="/var/run/webapp.pid"
start_stop_daemon_args="--stdout /var/log/webapp/stdout.log --stderr /var/log/webapp/stderr.log"
depend() {
need net localmount
after postgresql redis
before nginx
}
start_pre() {
# Create necessary directories
checkpath --directory --owner webapp:webapp --mode 0755 /var/run/webapp
checkpath --directory --owner webapp:webapp --mode 0755 /var/log/webapp
# Verify configuration
if [ ! -f /opt/webapp/config.json ]; then
eerror "Configuration file not found: /opt/webapp/config.json"
return 1
fi
# Check database connectivity
if ! su webapp -c "pg_isready -h localhost"; then
eerror "Database is not ready"
return 1
fi
}
start_post() {
# Wait for service to be ready
local timeout=30
local count=0
while [ $count -lt $timeout ]; do
if curl -s http://localhost:3000/health > /dev/null; then
einfo "WebApp is ready and responding"
return 0
fi
sleep 1
count=$((count + 1))
done
eerror "WebApp failed to start within $timeout seconds"
return 1
}
stop_post() {
# Cleanup temporary files
rm -f /tmp/webapp-*
einfo "WebApp cleanup completed"
}
reload() {
ebegin "Reloading WebApp configuration"
kill -HUP $(cat $pidfile)
eend $?
}
Dependency Management
Understanding Dependencies
OpenRC’s dependency system ensures services start in the correct order. The main dependency types are:
- need: Hard dependency – service cannot start without this
- use: Soft dependency – will use if available
- want: Optional dependency – starts if present
- after: Ordering dependency – start after this service
- before: Ordering dependency – start before this service
- provide: Virtual service provision
Example Dependency Configuration
depend() {
# Must have network and local filesystems
need net localmount
# Use DNS if available
use dns
# Start after system logger
after logger
# Start before web server
before apache2 nginx
# Provide database service
provide database
}
Viewing Service Dependencies
# Show dependency tree
rc-depend --tree
# Show dependencies for specific service
rc-depend --depend nginx
# Show what services depend on a service
rc-depend --rdepend postgresql
Advanced OpenRC Features
Service Configuration Files
Service-specific configurations are stored in /etc/conf.d/:
# /etc/conf.d/nginx
# Configuration for nginx service
# Additional command line arguments
NGINX_OPTS="-g 'daemon off;'"
# Configuration file location
NGINX_CONFIG="/etc/nginx/nginx.conf"
# User and group
NGINX_USER="nginx"
NGINX_GROUP="nginx"
# PID file location
NGINX_PIDFILE="/var/run/nginx.pid"
Service Monitoring and Supervision
OpenRC provides built-in supervision capabilities:
#!/sbin/openrc-run
description="Supervised Application"
command="/usr/local/bin/myapp"
supervisor="supervise-daemon"
supervise_daemon_args="--respawn-delay 5 --respawn-max 10"
command_user="myapp:myapp"
# Automatically restart on failure
respawn_delay=5
respawn_max=10
Service Hooks and Events
OpenRC supports hooks that execute at specific service lifecycle events:
# /etc/local.d/service-hook.start
#!/bin/sh
# This script runs when entering any runlevel
echo "System entering runlevel: $RC_RUNLEVEL" >> /var/log/runlevel.log
# Example: Start monitoring daemon
if [ "$RC_RUNLEVEL" = "default" ]; then
/usr/local/bin/start-monitoring
fi
Troubleshooting OpenRC
Common Issues and Solutions
Service fails to start:
# Check service status and logs
rc-service problematic_service status
tail -f /var/log/rc.log
# Run service in debug mode
RC_DEBUG=yes rc-service problematic_service start
Dependency issues:
# Check dependency tree
rc-depend --tree problematic_service
# Force start (bypass dependencies)
rc-service --nodeps problematic_service start
Boot issues:
# Enable interactive boot mode
# Add to kernel command line: rc_interactive=yes
# Or edit /etc/rc.conf
rc_interactive="YES"
Debugging Service Scripts
# Test service script syntax
sh -n /etc/init.d/service_name
# Run service with verbose output
RC_VERBOSE=yes rc-service service_name start
# Enable service debugging
# Add to service script:
# set -x # Enable debug output
Performance Optimization
Parallel Service Startup
Enable parallel startup for faster boot times:
# /etc/rc.conf
rc_parallel="YES"
# Set maximum parallel jobs
rc_max_jobs="4"
Service Optimization
# Optimize service dependencies
depend() {
# Use 'after' instead of 'need' where possible
after logger networking
# Use 'use' for optional dependencies
use dns
}
# Enable service caching
rc_cache_services="YES"
Migration and Compatibility
Migrating from systemd
When migrating from systemd to OpenRC, consider these mapping equivalents:
# systemd → OpenRC command equivalents
systemctl start service → rc-service service start
systemctl stop service → rc-service service stop
systemctl enable service → rc-update add service default
systemctl disable service → rc-update del service default
systemctl status service → rc-service service status
systemctl list-units → rc-status
Converting systemd Service Files
Basic conversion from systemd unit file to OpenRC script:
# systemd unit file
[Unit]
Description=My Service
After=network.target
[Service]
Type=simple
User=myuser
ExecStart=/usr/bin/myservice
Restart=always
[Install]
WantedBy=multi-user.target
Equivalent OpenRC script:
#!/sbin/openrc-run
description="My Service"
command="/usr/bin/myservice"
command_user="myuser"
command_background="yes"
pidfile="/var/run/myservice.pid"
supervisor="supervise-daemon"
depend() {
after net
}
Best Practices and Security
Security Considerations
- Run services with minimal privileges: Always specify appropriate user/group
- Secure file permissions: Use proper permissions for service scripts and configuration files
- Validate inputs: Check configuration files and dependencies before starting services
- Use proper PID file locations: Store PID files in appropriate directories with correct permissions
# Example security-focused service script
#!/sbin/openrc-run
description="Secure Web Service"
command="/usr/local/bin/webservice"
command_user="webservice:webservice"
pidfile="/var/run/webservice/webservice.pid"
# Security settings
umask=022
capabilities="cap_net_bind_service"
start_pre() {
# Create secure runtime directory
checkpath --directory --owner webservice:webservice --mode 0750 /var/run/webservice
# Validate configuration
if [ ! -f /etc/webservice/config.yml ]; then
eerror "Configuration file missing"
return 1
fi
# Check file permissions
if [ "$(stat -c %a /etc/webservice/config.yml)" != "640" ]; then
eerror "Configuration file has incorrect permissions"
return 1
fi
}
Monitoring and Logging
# Enable comprehensive logging
# /etc/rc.conf
rc_logger="YES"
rc_log_path="/var/log/rc.log"
# Service-specific logging
start_stop_daemon_args="--stdout-logger 'logger -t myservice' --stderr-logger 'logger -t myservice -p daemon.err'"
Conclusion
OpenRC provides a robust, lightweight alternative to heavier init systems while maintaining simplicity and flexibility. Its dependency-based approach, parallel service startup, and comprehensive service management capabilities make it an excellent choice for both desktop and server environments. Whether you’re managing a small Alpine Linux container or a complex Gentoo server, OpenRC offers the tools and flexibility needed for effective system initialization and service management.
By mastering OpenRC’s service management, dependency resolution, and advanced features, you can build efficient, reliable systems that start quickly and manage services effectively. The examples and best practices covered in this guide provide a solid foundation for implementing OpenRC in production environments.
- What is OpenRC?
- OpenRC Architecture and Components
- Installation and Setup
- Understanding Runlevels
- Service Management with OpenRC
- Creating Custom OpenRC Services
- Dependency Management
- Advanced OpenRC Features
- Troubleshooting OpenRC
- Performance Optimization
- Migration and Compatibility
- Best Practices and Security
- Conclusion







