systemd Service Setup
This guide covers running mik as a systemd service for production Linux deployments.
Prerequisites
Section titled “Prerequisites”- Linux system with systemd
- mik binary installed to
/usr/local/bin/mik - WASM modules deployed to
/var/lib/mik/
Basic Service
Section titled “Basic Service”Create /etc/systemd/system/mik.service:
[Unit]Description=mik WASI HTTP RuntimeDocumentation=https://github.com/dufeutech/mikAfter=network.target
[Service]Type=simpleUser=mikGroup=mikWorkingDirectory=/var/lib/mikExecStart=/usr/local/bin/mik run --port 3000 /var/lib/mik/app.wasmRestart=alwaysRestartSec=5
# Security hardeningNoNewPrivileges=yesProtectSystem=strictProtectHome=yesPrivateTmp=yesReadWritePaths=/var/lib/mik
# EnvironmentEnvironment=RUST_LOG=infoEnvironmentFile=-/etc/mik/mik.env
# Resource limitsLimitNOFILE=65535MemoryMax=2G
[Install]WantedBy=multi-user.targetUser Setup
Section titled “User Setup”Create a dedicated service user:
# Create system user (no login shell, no home)sudo useradd -r -s /usr/sbin/nologin mik
# Create directoriessudo mkdir -p /var/lib/mik/modulessudo mkdir -p /var/lib/mik/datasudo mkdir -p /etc/mik
# Set ownershipsudo chown -R mik:mik /var/lib/miksudo chmod 700 /var/lib/mikEnvironment File
Section titled “Environment File”Create /etc/mik/mik.env for sensitive configuration:
# API key for daemon endpointsMIK_API_KEY=your-secret-key-here
# Log levelRUST_LOG=info
# Optional: custom portPORT=3000Secure the file:
sudo chmod 600 /etc/mik/mik.envsudo chown root:mik /etc/mik/mik.envManagement Commands
Section titled “Management Commands”# Reload systemd after creating/modifying servicesudo systemctl daemon-reload
# Enable service to start on bootsudo systemctl enable mik
# Start the servicesudo systemctl start mik
# View statussudo systemctl status mik
# View logssudo journalctl -u mik -f
# Restart after config changessudo systemctl restart mik
# Stop the servicesudo systemctl stop mikMulti-Instance Setup
Section titled “Multi-Instance Setup”Run multiple mik instances on different ports:
Service Template
Section titled “Service Template”Create /etc/systemd/system/mik@.service:
[Unit]Description=mik WASI HTTP Runtime - %iAfter=network.target
[Service]Type=simpleUser=mikGroup=mikWorkingDirectory=/var/lib/mik/%iExecStart=/usr/local/bin/mik run --port %i /var/lib/mik/%i/app.wasmRestart=alwaysRestartSec=5
NoNewPrivileges=yesProtectSystem=strictProtectHome=yesPrivateTmp=yesReadWritePaths=/var/lib/mik/%i
Environment=RUST_LOG=infoEnvironmentFile=-/etc/mik/%i.env
[Install]WantedBy=multi-user.targetUsing the Template
Section titled “Using the Template”# Create instance directoriessudo mkdir -p /var/lib/mik/3001sudo mkdir -p /var/lib/mik/3002
# Deploy modulessudo cp app1.wasm /var/lib/mik/3001/app.wasmsudo cp app2.wasm /var/lib/mik/3002/app.wasm
# Start instancessudo systemctl enable --now mik@3001sudo systemctl enable --now mik@3002
# Check statussudo systemctl status 'mik@*'Daemon Mode Service
Section titled “Daemon Mode Service”For applications needing embedded services (KV, SQL, Storage):
Create /etc/systemd/system/mik-daemon.service:
[Unit]Description=mik DaemonAfter=network.target
[Service]Type=simpleUser=mikGroup=mikWorkingDirectory=/var/lib/mikExecStart=/usr/local/bin/mik daemonRestart=alwaysRestartSec=5
NoNewPrivileges=yesProtectSystem=strictProtectHome=yesPrivateTmp=yesReadWritePaths=/var/lib/mik
Environment=RUST_LOG=infoEnvironmentFile=-/etc/mik/daemon.env
[Install]WantedBy=multi-user.targetThen run instances that connect to the daemon:
# Start daemonsudo systemctl start mik-daemon
# Start instances (they'll use daemon services)mik run --detach --name api --port 3000Socket Activation
Section titled “Socket Activation”For on-demand startup, use socket activation:
Socket Unit
Section titled “Socket Unit”Create /etc/systemd/system/mik.socket:
[Unit]Description=mik Socket
[Socket]ListenStream=3000Accept=noNoDelay=yes
[Install]WantedBy=sockets.targetModified Service
Section titled “Modified Service”Update /etc/systemd/system/mik.service:
[Unit]Description=mik WASI HTTP RuntimeRequires=mik.socketAfter=mik.socket
[Service]Type=simpleUser=mikGroup=mikWorkingDirectory=/var/lib/mikExecStart=/usr/local/bin/mik run /var/lib/mik/app.wasmStandardInput=socket
NoNewPrivileges=yesProtectSystem=strictProtectHome=yesPrivateTmp=yesReadWritePaths=/var/lib/mik
Environment=RUST_LOG=info
[Install]WantedBy=multi-user.targetEnable Socket
Section titled “Enable Socket”# Enable socket (not service directly)sudo systemctl enable --now mik.socket
# Check socket statussudo systemctl status mik.socket
# First request will start the servicecurl http://localhost:3000/healthSecurity Hardening
Section titled “Security Hardening”Full Hardening Options
Section titled “Full Hardening Options”[Service]# Process isolationNoNewPrivileges=yesPrivateTmp=yesPrivateDevices=yesProtectSystem=strictProtectHome=yesProtectKernelTunables=yesProtectKernelModules=yesProtectControlGroups=yes
# FilesystemReadWritePaths=/var/lib/mikReadOnlyPaths=/etc/mik
# NetworkRestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# System callsSystemCallFilter=@system-serviceSystemCallErrorNumber=EPERM
# CapabilitiesCapabilityBoundingSet=AmbientCapabilities=
# MiscLockPersonality=yesMemoryDenyWriteExecute=yesRestrictRealtime=yesRestrictSUIDSGID=yesVerify Security
Section titled “Verify Security”# Check security scoresudo systemd-analyze security mik.serviceResource Limits
Section titled “Resource Limits”[Service]# Memory limitsMemoryMax=2GMemoryHigh=1.5G
# CPU limitsCPUQuota=200%CPUWeight=100
# File descriptorsLimitNOFILE=65535
# Process limitsLimitNPROC=4096
# Core dumps (disable in production)LimitCORE=0Health Monitoring
Section titled “Health Monitoring”Watchdog
Section titled “Watchdog”Add watchdog support:
[Service]WatchdogSec=30mik will send periodic keepalive signals. If it stops responding, systemd will restart it.
Health Check Service
Section titled “Health Check Service”Create /etc/systemd/system/mik-healthcheck.service:
[Unit]Description=mik Health Check
[Service]Type=oneshotExecStart=/usr/bin/curl -sf http://localhost:3000/healthCreate /etc/systemd/system/mik-healthcheck.timer:
[Unit]Description=mik Health Check Timer
[Timer]OnBootSec=1minOnUnitActiveSec=1min
[Install]WantedBy=timers.targetEnable:
sudo systemctl enable --now mik-healthcheck.timerLog Configuration
Section titled “Log Configuration”Journal Settings
Section titled “Journal Settings”View logs with different verbosity:
# Follow logsjournalctl -u mik -f
# Last 100 linesjournalctl -u mik -n 100
# Since bootjournalctl -u mik -b
# Time rangejournalctl -u mik --since "2025-01-01 00:00:00" --until "2025-01-01 12:00:00"
# JSON outputjournalctl -u mik -o jsonPersistent Logs
Section titled “Persistent Logs”By default, journald may not persist logs across reboots. Enable persistence:
sudo mkdir -p /var/log/journalsudo systemctl restart systemd-journaldTroubleshooting
Section titled “Troubleshooting”Service Won’t Start
Section titled “Service Won’t Start”# Check detailed statussystemctl status mik -l
# Check full logsjournalctl -u mik -e
# Verify binary existsls -la /usr/local/bin/mik
# Verify permissionsls -la /var/lib/mik/Permission Denied
Section titled “Permission Denied”# Check user can access filessudo -u mik ls /var/lib/mik/
# Reset permissionssudo chown -R mik:mik /var/lib/miksudo chmod 700 /var/lib/miksudo chmod 644 /var/lib/mik/modules/*.wasmPort Already in Use
Section titled “Port Already in Use”# Find what's using the portsudo ss -tlnp | grep 3000
# Kill the process or change mik's portMemory Issues
Section titled “Memory Issues”# Check resource usagesystemctl status mikcat /sys/fs/cgroup/system.slice/mik.service/memory.current
# Check limitssystemctl show mik -p MemoryMaxComplete Example
Section titled “Complete Example”Directory Structure
Section titled “Directory Structure”/var/lib/mik/├── modules/│ ├── api.wasm│ └── auth.wasm├── data/│ ├── state.redb│ └── sqlite.db└── mik.toml
/etc/mik/├── mik.env└── daemon.toml
/etc/systemd/system/└── mik.serviceConfiguration Files
Section titled “Configuration Files”/var/lib/mik/mik.toml:
[project]name = "production-api"
[server]port = 3000modules = "modules/"cache_size = 100max_cache_mb = 512/etc/mik/mik.env:
MIK_API_KEY=your-production-keyRUST_LOG=infoNext Steps
Section titled “Next Steps”- Production Deployment - Full production guide
- Monitoring & Observability - Metrics and logging
- Operations Runbook - Troubleshooting guide