# Systemd Service for Mihomo + YACD Two approaches: **system-level** (recommended for always-on servers) and **user-level**. --- ## Option A: System-Level Services (recommended for servers) System-level services run as root, survive logout without extra config, and start early in boot. ### Create service files **Pitfall**: The Hermes security scanner blocks `sudo tee /etc/systemd/system/` and `sudo cp` into system paths. Workaround: write to `/tmp` first using `write_file`, then ask the user to manually run `sudo cp` + `sudo systemctl`. ```bash # Step 1: Agent writes to /tmp (allowed by write_file tool) # /tmp/mihomo.service: [Unit] Description=Mihomo (Clash Meta) Proxy After=network-online.target Wants=network-online.target [Service] Type=simple WorkingDirectory=/home/openclaw/clash ExecStart=/home/openclaw/clash/mihomo -d /home/openclaw/clash/config Restart=on-failure RestartSec=5 LimitNOFILE=65535 StandardOutput=append:/tmp/mihomo.log StandardError=append:/tmp/mihomo.log [Install] WantedBy=multi-user.target # /tmp/yacd.service: [Unit] Description=YACD - Clash Dashboard After=network-online.target mihomo.service Wants=network-online.target Requires=mihomo.service [Service] Type=simple WorkingDirectory=/home/openclaw/clash/yacd ExecStart=/usr/bin/python3 -m http.server 9091 --bind 0.0.0.0 Restart=on-failure RestartSec=3 StandardOutput=append:/tmp/yacd.log StandardError=append:/tmp/yacd.log [Install] WantedBy=multi-user.target ``` ### Step 2: User manually runs ```bash sudo cp /tmp/mihomo.service /etc/systemd/system/ sudo cp /tmp/yacd.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable mihomo yacd sudo systemctl start mihomo yacd sudo systemctl status mihomo yacd ``` ### Key design choices - `Requires=mihomo.service` on yacd: yacd won't start if mihomo fails - `After=network-online.target`: wait for network before starting - `Restart=on-failure`: auto-restart on crash - `LimitNOFILE=65535`: mihomo handles many connections - Logs to `/tmp/` via `append:` (matches startup.sh convention) ### Migration from startup.sh Once systemd manages the services, **disable** the startup.sh service definitions to prevent conflicts: ```bash # Disable (don't delete — keep as backup) mv ~/startup/services/mihomo.sh ~/startup/services/mihomo.sh.disabled mv ~/startup/services/yacd.sh ~/startup/services/yacd.sh.disabled # if applicable # Verify startup.sh no longer manages these bash ~/startup/startup.sh status # should not show mihomo/yacd # Use systemd exclusively systemctl --user start|stop|restart|status mihomo # user-level # or: sudo systemctl start|stop|restart|status mihomo # system-level ``` **Why disable instead of delete**: If systemd service has issues, you can quickly re-enable by renaming back. Also keeps the service definition as documentation. **Pitfall**: If you forget to disable startup.sh definitions AND the watchdog still calls `startup.sh restart`, the two managers fight over PIDs. Always migrate atomically: create systemd service → enable → disable startup.sh definition → update watchdog. --- ## Option B: User-Level Services (for non-root setups) User services run as the logged-in user, no root needed for service files. ```bash mkdir -p ~/.config/systemd/user cat > ~/.config/systemd/user/mihomo.service << 'EOF' [Unit] Description=Mihomo (Clash Meta) Proxy After=network.target [Service] Type=simple WorkingDirectory=%h/clash ExecStart=%h/clash/mihomo -d %h/clash/config Restart=on-failure RestartSec=5 [Install] WantedBy=default.target EOF cat > ~/.config/systemd/user/yacd-dashboard.service << 'EOF' [Unit] Description=YACD Dashboard (static HTTP) After=network.target mihomo.service [Service] Type=simple WorkingDirectory=%h/clash/yacd ExecStart=/usr/bin/python3 -m http.server 9091 --bind 0.0.0.0 --directory %h/clash/yacd Restart=on-failure RestartSec=5 [Install] WantedBy=default.target EOF systemctl --user daemon-reload systemctl --user enable mihomo yacd-dashboard systemctl --user start mihomo yacd-dashboard ``` **Critical**: Without linger, user services die on logout: ```bash sudo loginctl enable-linger $USER ``` --- ## Verify (both options) ```bash # System-level sudo systemctl status mihomo yacd # User-level systemctl --user status mihomo yacd-dashboard curl -s http://127.0.0.1:9090/version curl -s http://127.0.0.1:9091/ | head -3 ```