Risuko
Guides

Headless Server

Run Risuko as a headless download server without a GUI.

Risuko can run as a headless download server, accepting commands over JSON-RPC. This is useful for servers, NAS devices, Docker containers, or any environment without a display.

Starting the Server

Via CLI

risuko serve --rpc-port 16800

serve runs in the foreground until it receives Ctrl+C or an RPC risuko.shutdown request. --rpc-port defaults to 16800; pass -v/--verbose for debug logging. There is no --rpc-secret flag — the server reads its secret from config (see Remote Access).

Via Node.js

// @risuko/risuko-js is a CommonJS native addon, so import the default
// export and read methods off it — named imports are not available
import risuko from "@risuko/risuko-js";

await risuko.startEngine({
  rpcPort: 16800,
  enableRpc: true,
});

// Engine is now running and accepting RPC commands
// Keep the process alive
process.on("SIGINT", async () => {
  await risuko.stopEngine();
  process.exit(0);
});

Controlling the Server

Once the server is running, use any of these methods to control it:

From the CLI

# Add a download
risuko download https://example.com/file.zip --rpc-port 16800

# Check status
risuko status --rpc-port 16800

# Shut down
risuko shutdown --rpc-port 16800

From curl

curl -X POST http://localhost:16800/jsonrpc \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":"1","method":"risuko.addUri","params":[["https://example.com/file.zip"]]}'

From Node.js (RPC client)

You can also write a custom JSON-RPC client to talk to a remote server. The RPC Protocol page documents all available methods.

Remote Access

The RPC server binds to 127.0.0.1 by default and only accepts local connections. To accept connections from other machines, set rpc-host:

risuko config set rpc-host 0.0.0.0

Once the server is reachable from the network, set an authentication secret. The engine reads rpc-secret from system.json in the config directory — risuko config set writes to user.json, which the engine ignores for this key, so edit the file directly:

{ "rpc-secret": "choose-a-secret" }

CLI clients then pass --rpc-secret <secret>; raw JSON-RPC clients prepend "token:<secret>" to the params array (see RPC Protocol).

Running as a systemd Service

[Unit]
Description=Risuko Download Engine
After=network.target

[Service]
Type=simple
User=risuko
ExecStart=/usr/local/bin/risuko serve --rpc-port 16800
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl enable risuko
sudo systemctl start risuko

Docker

FROM debian:bookworm-slim

COPY risuko /usr/local/bin/risuko
RUN chmod +x /usr/local/bin/risuko && mkdir -p /downloads

ENV XDG_CONFIG_HOME=/config
EXPOSE 16800
VOLUME ["/downloads", "/config"]

CMD ["risuko", "serve", "--rpc-port", "16800"]

XDG_CONFIG_HOME=/config places the config directory at /config/dev.risuko.app. Create system.json there before starting the container: rpc-host must be 0.0.0.0 (the default 127.0.0.1 binds the container's loopback, so the published port would never reach the server) and dir points downloads at the volume. Missing keys are filled from defaults.

mkdir -p /path/to/config/dev.risuko.app
cat > /path/to/config/dev.risuko.app/system.json <<'EOF'
{
  "dir": "/downloads",
  "rpc-host": "0.0.0.0",
  "rpc-secret": "choose-a-secret"
}
EOF

docker run -d \
  -p 16800:16800 \
  -v /path/to/downloads:/downloads \
  -v /path/to/config:/config \
  risuko

Session Persistence

The engine automatically saves session state every 30 seconds and on shutdown. When restarted:

  • Completed downloads are remembered
  • Active downloads resume from where they left off
  • Configuration persists in the config directory

The default config directory depends on the deployment method:

  • CLI: ~/.config/dev.risuko.app (Linux), ~/Library/Application Support/dev.risuko.app (macOS)
  • Node.js API: configurable via EngineConfig.configDir

On this page