# Example drop-in for the node's unit, which is where the pipe # setup lives. # # Copy to # /etc/systemd/system/.service.d/zzzz-metsuke.conf. The # name sorts last on purpose: an image shipping a host-wide # service.d drop-in that resets LoadCredential= would otherwise # apply after this one and clear the credential below. # # That directory is yours to make: `sudo mkdir -p` it. And bring: # the binary at /usr/local/bin/metsuke # the configuration at /etc/metsuke/config.toml # the signing key at /etc/metsuke/signing-key, owned by root, mode 0400 # # Take https://metsuke-leios.play.dev.cardano.org/files/config.pipe.toml as the configuration. # # Replace YOUR-NODE-COMMAND below with the command your node's unit # already runs, which `systemctl cat .service` prints. # The empty ExecStart= is what clears that command before this one # replaces it, and the shell is because systemd has no pipelines. # # Read that output for four directives before you use this, because # the shell is now what systemd supervises rather than your node: # # Type=notify nothing sends readiness, so the start times # out and systemd kills the node. Type=exec is # what a pipeline can be. # WatchdogSec= nothing pings, so the node is killed every # interval. Drop it, or move it to a unit that # still has a process of its own to watch. # ExecReload= $MAINPID is the shell, so a reload signals # that and not your node. # Restart= replaced, and so are RestartSec= and the # start limit in [Unit]. A pipeline exits 0 # however the node died, so on-failure would # never fire and the pool would leave the # network until somebody noticed. # # And two things about the command itself: it goes inside single # quotes below, so one containing `'` needs requoting, and systemd # expands `%` in it as a specifier, so one containing a literal `%` # needs it doubled to `%%`. # # The agent adds no group and reads no journal, and passes every # line through to its own stdout, so the node's output still # reaches the journal. What it costs instead, and the journald # setup does not: the agent is a process of the node's unit, so it # runs under that unit's user, sandbox and groups rather than the # ones metsuke.service sets, and LoadCredential= below is the node # unit's, so $CREDENTIALS_DIRECTORY/signing-key is readable by # every process that unit runs, cardano-node included. Use a Leios # key here: your pool id is a cold key's hash, so a compromised one # ends that pool rather than rotating. ADR 0010 prices both # sources. # # LoadCredential= and StateDirectory= add to the node's own rather # than replacing them, so a node unit that reads $STATE_DIRECTORY # sees two colon separated paths once this is in place. # # The three below are https://metsuke-leios.play.dev.cardano.org/files/cardano-node.service's own values, so # a node already on that unit is paced as it was. Reaching the # burst is deliberate: `failed` is a state a monitor can see, and # only a pipeline that fails at once gets there. # # None of that reaches the agent dying while the node lives. The # unit's process is the shell, which goes on waiting, so there is # no exit for Restart= to act on. A node that writes again may die # on the closed pipe and bring both back; a quiet one leaves the # unit active and collecting nothing. Under this source the agent's # liveness is yours to watch, and its startup line in # `journalctl -u ` is the signal. Supervising it is what # metsuke.service does for you under every other source. [Unit] StartLimitIntervalSec=600 StartLimitBurst=5 [Service] Restart=always RestartSec=60 LoadCredential=signing-key:/etc/metsuke/signing-key StateDirectory=metsuke ExecStart= ExecStart=/bin/sh -c 'YOUR-NODE-COMMAND | /usr/local/bin/metsuke --config /etc/metsuke/config.toml --signing-key %d/signing-key'