Daemon Mode
Moat supports running as a daemon (background service) with proper privilege dropping and process management.
Features
- Background execution - Runs as a detached background process
- PID file management - Creates and manages PID files for process control
- Privilege dropping - Can drop privileges to a specified user and group after initialization
- Output redirection - Redirects stdout and stderr to configurable log files
- Working directory - Configurable working directory for the daemon
- Signal handling - Proper signal handling for graceful shutdown
Configuration
YAML Configuration
daemon:
enabled: false
pid_file: "/var/run/moat.pid"
working_directory: "/"
stdout: "/var/log/moat.out"
stderr: "/var/log/moat.err"
user: "nobody"
group: "daemon"
chown_pid_file: true
Command Line
moat --daemon \
--daemon-pid-file /var/run/moat.pid \
--daemon-working-dir / \
--daemon-stdout /var/log/moat.out \
--daemon-stderr /var/log/moat.err \
--daemon-user nobody \
--daemon-group daemon \
--iface eth0 --upstream "http://127.0.0.1:8081" --arxignis-api-key "your-key"
Environment Variables
export AX_DAEMON_ENABLED="true"
export AX_DAEMON_PID_FILE="/var/run/moat.pid"
export AX_DAEMON_WORKING_DIRECTORY="/"
export AX_DAEMON_STDOUT="/var/log/moat.out"
export AX_DAEMON_STDERR="/var/log/moat.err"
export AX_DAEMON_USER="nobody"
export AX_DAEMON_GROUP="daemon"
export AX_DAEMON_CHOWN_PID_FILE="true"
Process Management
Starting the Daemon
moat --daemon --config /etc/moat/config.yaml
Stopping the Daemon
# Using PID file
kill $(cat /var/run/moat.pid)
# Or send SIGTERM
kill -TERM $(cat /var/run/moat.pid)
# Graceful shutdown with SIGINT
kill -INT $(cat /var/run/moat.pid)
Checking Status
# Check if process is running
ps aux | grep moat
# Or check PID file
if [ -f /var/run/moat.pid ]; then
pid=$(cat /var/run/moat.pid)
if ps -p $pid > /dev/null; then
echo "Moat is running (PID: $pid)"
else
echo "Moat is not running (stale PID file)"
fi
else
echo "Moat is not running"
fi
Viewing Logs
In daemon mode, logs are split:
- stdout (
/var/log/moat.out) - Application logs (info, debug, warn, error) - stderr (
/var/log/moat.err) - Panic messages and system errors
# Tail application logs
tail -f /var/log/moat.out
# Tail error output
tail -f /var/log/moat.err
# View both logs simultaneously
tail -f /var/log/moat.out /var/log/moat.err
Security Considerations
Privilege Dropping
When running as daemon with a privileged user (e.g., root) to bind to ports < 1024 or attach XDP programs, it's recommended to drop privileges after initialization:
moat --daemon \
--daemon-user nobody \
--daemon-group daemon \
--iface eth0 --upstream "http://127.0.0.1:8081" --arxignis-api-key "your-key"
This will:
- Start as root (or privileged user)
- Bind to privileged ports (80, 443)
- Attach XDP programs to network interfaces
- Drop privileges to
nobody:daemon - Continue running as unprivileged user
File Permissions
Ensure proper permissions for daemon files:
# Create log directory
sudo mkdir -p /var/log/moat
sudo chown nobody:daemon /var/log/moat
sudo chmod 755 /var/log/moat
# Create PID directory
sudo mkdir -p /var/run
sudo chmod 755 /var/run
# Set up log files
sudo touch /var/log/moat.out /var/log/moat.err
sudo chown nobody:daemon /var/log/moat.out /var/log/moat.err
sudo chmod 644 /var/log/moat.out /var/log/moat.err
Systemd Integration
Create a systemd service file for easier management:
# /etc/systemd/system/moat.service
[Unit]
Description=Moat Reverse Proxy and Firewall
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/var/run/moat.pid
ExecStart=/usr/local/bin/moat --daemon --config /etc/moat/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
# Security settings
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/moat /var/run
[Install]
WantedBy=multi-user.target
Manage with systemd:
# Enable service
sudo systemctl enable moat
# Start service
sudo systemctl start moat
# Stop service
sudo systemctl stop moat
# Restart service
sudo systemctl restart moat
# View status
sudo systemctl status moat
# View logs
sudo journalctl -u moat -f
Troubleshooting
Daemon Won't Start
Check:
- Log files for errors:
cat /var/log/moat.err - Permissions on log directory and PID file location
- User/group exists:
id nobody - Configuration file is valid:
moat --config /etc/moat/config.yaml(without--daemon)
Permission Denied Errors
If you see permission errors:
- Ensure log directory is writable by daemon user
- Ensure PID file location is writable
- Check that user/group specified exists
- Verify file system permissions
Stale PID File
If daemon won't start due to existing PID file:
# Check if process is actually running
ps -p $(cat /var/run/moat.pid)
# If not running, remove stale PID file
sudo rm /var/run/moat.pid
# Then start daemon
moat --daemon --config /etc/moat/config.yaml
Usage Examples
Basic Daemon
moat --daemon --iface eth0 --upstream "http://127.0.0.1:8081" --arxignis-api-key "your-key"
Custom Settings
moat --daemon \
--daemon-pid-file /var/run/moat.pid \
--daemon-working-dir / \
--daemon-stdout /var/log/moat.out \
--daemon-stderr /var/log/moat.err \
--daemon-user nobody \
--daemon-group daemon \
--iface eth0 --upstream "http://127.0.0.1:8081" --arxignis-api-key "your-key"
With Configuration File
moat --config /path/to/config.yaml
Example config.yaml:
daemon:
enabled: true
pid_file: "/var/run/moat.pid"
working_directory: "/"
stdout: "/var/log/moat.out"
stderr: "/var/log/moat.err"
user: "nobody"
group: "daemon"
chown_pid_file: true
server:
upstream: "http://127.0.0.1:8081"
network:
iface: "eth0"
arxignis:
api_key: "your-key"
Next Steps
- Configuration Reference - Complete configuration options
- Test Your Setup - Validate your daemon setup