<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Callisto Labs</title>
    <subtitle>Self-hosted observability and hands-on support for Nextflow on on-premise HPC clusters.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://www.callistolabs.eu/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://www.callistolabs.eu"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-08-20T00:00:00+00:00</updated>
    <id>https://www.callistolabs.eu/atom.xml</id>
    <entry xml:lang="en">
        <title>Where did my task go? Monitoring Nextflow on Slurm without Tower</title>
        <published>2026-08-20T00:00:00+00:00</published>
        <updated>2026-08-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://www.callistolabs.eu/blog/monitoring-nextflow-on-slurm-without-tower/"/>
        <id>https://www.callistolabs.eu/blog/monitoring-nextflow-on-slurm-without-tower/</id>
        
        <content type="html" xml:base="https://www.callistolabs.eu/blog/monitoring-nextflow-on-slurm-without-tower/">&lt;p&gt;If you run Nextflow pipelines on a university HPC cluster, your monitoring
stack probably looks like mine did: one terminal tailing &lt;code&gt;.nextflow.log&lt;&#x2F;code&gt;,
another running &lt;code&gt;squeue&lt;&#x2F;code&gt; every thirty seconds, and a growing suspicion that
somewhere between &quot;submitted&quot; and &quot;completed&quot; your tasks are spending a lot
of time doing nothing at all.&lt;&#x2F;p&gt;
&lt;p&gt;The frustrating part is that the information exists. Nextflow knows when it
submitted each task and when Slurm actually started it. It knows how much
memory you requested and how much the process actually used. It just doesn&#x27;t
show you any of this while the run is going — and by the time you&#x27;re staring
at the trace file after a failed 14-hour run, aggregating submit-to-start
deltas per process with &lt;code&gt;awk&lt;&#x2F;code&gt; is nobody&#x27;s idea of observability.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-options-as-of-2026&quot;&gt;The options, as of 2026&lt;&#x2F;h2&gt;
&lt;p&gt;The obvious answer is Seqera Platform (formerly Tower), and if your lab runs
in the cloud with a budget, it&#x27;s a good one. On a shared on-premise cluster
the picture is different:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Seqera Cloud&#x27;s free tier&lt;&#x2F;strong&gt; is sized for trying things out — a handful
of users and concurrent runs, limited run history. Fine for one person;
not for a core facility with dozens of users.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Self-hosting Seqera Platform&lt;&#x2F;strong&gt; is an Enterprise license conversation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The open-source nf-tower&lt;&#x2F;strong&gt; was archived in January 2025 and is
unmaintained.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-with-weblog&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; gives you a firehose of JSON events and a &quot;build the
rest yourself&quot; exercise.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Meanwhile, every HPC cluster I&#x27;ve touched already runs a Prometheus and
Grafana stack somewhere — the sysadmins use it for node health. What&#x27;s
missing is the bridge between Nextflow&#x27;s head job and that stack.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-awkward-thing-about-head-jobs&quot;&gt;The awkward thing about head jobs&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s what makes the bridge less trivial than &quot;expose an HTTP endpoint&quot;:
on a well-run cluster your Nextflow head job isn&#x27;t on the login node — it&#x27;s
a batch job itself, running on a compute node behind a firewall, with an IP
your Prometheus server has never heard of and no inbound connectivity at
all. Classic pull-based scraping simply doesn&#x27;t reach it. On air-gapped
clusters, nothing does.&lt;&#x2F;p&gt;
&lt;p&gt;But there is one thing every HPC node can always do: &lt;strong&gt;write a file to the
shared filesystem&lt;&#x2F;strong&gt;. And it turns out Prometheus grew an idiom for exactly
this situation years ago — the node_exporter &lt;em&gt;textfile collector&lt;&#x2F;em&gt;, built
for batch jobs and cron scripts. Write your metrics to a &lt;code&gt;.prom&lt;&#x2F;code&gt; file
atomically, point a node_exporter at the directory, done. No network, no
credentials, no agent on the cluster.&lt;&#x2F;p&gt;
&lt;p&gt;That observation became &lt;a href=&quot;&#x2F;nf-prometheus&#x2F;&quot;&gt;nf-prometheus&lt;&#x2F;a&gt;: a small
(zero-dependency, Apache 2.0) Nextflow plugin that listens to workflow
events and exports them in Prometheus format, textfile-first. A Pushgateway
mode covers live updates during the run, and a classic HTTP &lt;code&gt;&#x2F;metrics&lt;&#x2F;code&gt;
endpoint exists for the cases where the head node is actually reachable.&lt;&#x2F;p&gt;
&lt;p&gt;The metric I built it for is &lt;strong&gt;per-process scheduler queue wait&lt;&#x2F;strong&gt; — the
submit-to-start time your &lt;code&gt;squeue&lt;&#x2F;code&gt; never aggregates for you. On the
dashboard it sits next to requested-vs-used CPUs and peak RSS, which
together answer the two questions every cluster admin eventually asks a
pipeline user: &lt;em&gt;why are you queued so long&lt;&#x2F;em&gt; and &lt;em&gt;why did you request 32 GB
for a process that peaks at 4&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;img&#x2F;nf-prometheus-dashboard.png&quot; alt=&quot;The nf-prometheus Grafana dashboard showing a demo run: status tiles, per-process queue wait, wall time, CPUs and peak RSS&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Setup genuinely takes about five minutes: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mcallisto&#x2F;nf-prometheus&#x2F;blob&#x2F;main&#x2F;docs&#x2F;5-minute-setup.md&quot;&gt;the walkthrough is in the
repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;three-things-the-test-cluster-taught-me&quot;&gt;Three things the test cluster taught me&lt;&#x2F;h2&gt;
&lt;p&gt;I developed the plugin against a single-node Slurm cluster in a container
(Rocky 9, Slurm from EPEL — the setup ships in the repo under &lt;code&gt;dev&#x2F;slurm&#x2F;&lt;&#x2F;code&gt;).
Even a toy cluster manages to reproduce the greatest hits of real HPC
operations:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;1. The node that drains itself.&lt;&#x2F;strong&gt; After every container restart, and
occasionally after successfully finishing jobs, slurmctld would put the node
in &lt;code&gt;drain&lt;&#x2F;code&gt; — reason: &lt;code&gt;Kill task failed&lt;&#x2F;code&gt;. With &lt;code&gt;proctrack&#x2F;pgid&lt;&#x2F;code&gt; (no cgroups
in a container), slurmd is slow to reap task process groups and drains the
node out of caution. Jobs sit in &lt;code&gt;PD&lt;&#x2F;code&gt; forever and nothing in Nextflow&#x27;s
output tells you why. &lt;code&gt;sinfo&lt;&#x2F;code&gt; first, always. (&lt;code&gt;UnkillableStepTimeout&lt;&#x2F;code&gt; and an
auto-resume watchdog fixed the dev environment.)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. The metrics that were silently empty.&lt;&#x2F;strong&gt; My first dashboard had a
beautiful peak-RSS panel showing nothing. Nextflow only collects per-task
resource metrics if an observer explicitly asks for them by returning
&lt;code&gt;true&lt;&#x2F;code&gt; from &lt;code&gt;enableMetrics()&lt;&#x2F;code&gt; — which the plugin template doesn&#x27;t mention.
One overridden method later, a task that allocated 60 MB dutifully reported
a 73 MB peak. An empty dashboard panel is an integration test, if you let
it be one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. cgroups v2 without systemd.&lt;&#x2F;strong&gt; Slurm&#x27;s cgroup plugin wants to create
its scope via dbus, which doesn&#x27;t exist in a container. &lt;code&gt;IgnoreSystemd=yes&lt;&#x2F;code&gt;
in &lt;code&gt;cgroup.conf&lt;&#x2F;code&gt; is the documented escape hatch, and one more entry in the
&quot;things that are obvious after you know them&quot; file that HPC runs on.&lt;&#x2F;p&gt;
&lt;p&gt;None of these are exotic. They&#x27;re Tuesday on a real cluster — which is
rather the point of having a dashboard that shows you &lt;em&gt;where&lt;&#x2F;em&gt; the time
went instead of a log that shows you everything except that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;What&#x27;s next&lt;&#x2F;h2&gt;
&lt;p&gt;The plugin does one thing right now: run-level observability. The obvious
next layer — and the reason the metrics carry the labels they do — is
&lt;strong&gt;showback&lt;&#x2F;strong&gt;: CPU-hours per pipeline, per user, per PI, the number a core
facility needs at the end of the quarter. That&#x27;s where this is headed.&lt;&#x2F;p&gt;
&lt;p&gt;If you run Nextflow on Slurm (or PBS, or LSF) and this scratches an itch —
or conspicuously fails to — I&#x27;d genuinely like to hear about it:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mcallisto&#x2F;nf-prometheus&#x2F;issues&quot;&gt;issues and feature requests welcome&lt;&#x2F;a&gt;,
or find me on nf-core Slack.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
