/etc/kuro/api.toml. Secrets (database URL, encryption key) are in
/etc/kuro/api.env, readable by the kuro user only. Everything else is set in the panel:
Settings.
Every key can be overridden by an environment variable KURO_API_<SECTION>__<KEY>, for example
KURO_API_HTTP__BIND=127.0.0.1:9000.
Sections
After a change:
sudo systemctl restart kuro-api.
On a node
The daemon reads/etc/kuro/daemon.toml, written at enrollment. Environment variables:
KURO_DAEMON_<SECTION>__<KEY>.
disk_measure_interval_secs (60 by default, 15 to 3600): seconds between two measurements of
server disk usage, for quotas. Each measurement walks every file: on a node with very large
worlds, raise it. A write (file, backup, install) triggers its own measurement anyway, and
over-quota refusals stay current.
After a change: sudo systemctl restart kuro-daemon.
Server outbound traffic
Each server has its own Docker network, isolated from other servers. From that network, however, a game can reach everything the host reaches: its private network, and on a cloud the instance metadata (169.254.169.254). The daemon does not filter this traffic, since that belongs in the
host firewall. On a Linux node with rootful Docker, these rules in the DOCKER-USER chain
reject traffic from Docker bridges to private ranges, without affecting the Internet, services
of the same server, or published ports:
Make the rules persistent with your distribution’s tool (
iptables-persistent, nftables).
They apply to every Docker network on the host, not just Kuro’s. With rootless Docker, the host
firewall does not see container traffic: these rules belong in the user’s network namespace,
which is beyond this guide.What the panel configures
- Settings › Project: server resource defaults and caps, audit log retention, opening the MCP server.
- Settings › DNS: DNS provider zone and token (see DNS).
- Access: admin accounts and roles.
Multiple API instances
Severalkuro-api can run on the same PostgreSQL database, behind a load balancer: zero-downtime
deploys, surviving the loss of a machine. Nothing to configure, each instance registers in the
database at startup. Good to know:
- Each instance keeps a dedicated connection for cross-instance notifications:
database.max_connectionsmust allow for it (10 by default). - Rate limits (
http.rate_limit_per_minute) are counted per instance. - A server’s live console and stats are only available from the instance its node is connected to; from another, opening the console is refused with a clear message. Commands, files and backups work from any instance.
Probes and request log
GET /api/health: liveness, answers200as soon as the process runs.GET /api/ready: readiness,200when the database answers and the daemon listener accepts connections,503otherwise with details (database,daemon_listener). This is the probe a load balancer or monitoring should query.
request log line: method, path without parameters, status,
duration, client address, x-request-id and authenticated actor. The id is also the audit log’s:
it links a technical error to the action that caused it. Probes and panel files are only logged
at debug (log.filter = "info,kuro_api::http::trace=debug" to see them).
