nf-core/configs: Queen’s University Belfast Kelvin2 HPC Configuration

nf-core pipelines have been configured for use on Queen’s University Belfast’s Kelvin2 HPC cluster. To use this profile, run a pipeline with -profile kelvin2, which loads the pre-configured kelvin2.config.

This profile was tested with Nextflow 26.04.4 and the nf-core/rnaseq pipeline 3.26.0.

Set up Nextflow and Apptainer

Kelvin2 provides Nextflow and Apptainer as modules:

module load nextflow/24.07.27/java-22.0.2
module load apps/apptainer/1.3.4

To run a newer Nextflow release without replacing the module launcher, set NXF_VER (the launcher downloads and caches that version under $NXF_HOME):

NXF_VER=26.04.4 nextflow info

Option 2: Up-to-date Nextflow binary + module Apptainer

If you need a newer Nextflow than the module provides, install the Nextflow launcher onto scratch and keep using the system Apptainer module:

# Install Nextflow to a directory on scratch (example path)
mkdir -p /mnt/scratch2/users/$USER/bin
curl -fsSL https://get.nextflow.io -o /mnt/scratch2/users/$USER/bin/nextflow
chmod +x /mnt/scratch2/users/$USER/bin/nextflow
export PATH="/mnt/scratch2/users/$USER/bin:$PATH"

module load apps/apptainer/1.3.4

Option 3: Conda or Mamba

Conda/Mamba environments are also fine on Kelvin2:

conda create --name nextflow --channel bioconda --channel conda-forge nextflow apptainer
conda activate nextflow

Confirm the install

After any of these options, confirm both tools are available:

nextflow info
apptainer --version

Run a pipeline

Launch a pipeline with the kelvin2 profile:

nextflow run nf-core/<PIPELINE> -profile kelvin2 --outdir <RESULTS> [other arguments]

The Nextflow driver process must keep running for the whole pipeline. Use a terminal multiplexer such as tmux or screen so it survives an SSH disconnect. Note which login node you are on so you can reconnect to the same one:

tmux new -s nextflow        # detach: Ctrl-b then d; reattach: tmux attach -t nextflow

Once Apptainer images are cached, the driver is light enough to run on a login node inside tmux. The first run of a pipeline (or any run that pulls many new images) can be CPU-heavy on the login node while container images are fetched. For those cases, start the driver on a compute node via srun inside tmux, or submit a hands-free batch job:

#!/usr/bin/env bash
#SBATCH --job-name=nextflow_pipeline
#SBATCH --output=nextflow_pipeline_%j.log
#SBATCH --partition=k2-medpri
#SBATCH --time=24:00:00
#SBATCH --cpus-per-task=2
#SBATCH --mem-per-cpu=4G

module load nextflow/24.07.27/java-22.0.2
module load apps/apptainer/1.3.4

nextflow run nf-core/<PIPELINE> -profile kelvin2 --outdir <RESULTS> [other arguments]

Save that as e.g. run_nextflow.sh and submit with sbatch run_nextflow.sh.

Cluster specifications

  • Scheduler: SLURM
  • Container engine: Apptainer
  • Maximum CPUs: 128 per job
  • Maximum memory: 786 GB on general-access nodes, up to 2 TB on high-memory (k2-himem) nodes
  • Maximum time: 720 hours (30 days)

Partition selection

The SLURM partition is chosen automatically from each task’s requested resources, so you never need to set one:

Task requirementsPartitions used
≤ 3 hours walltimek2-hipri, k2-medpri, k2-lowpri
≤ 24 hours walltimek2-medpri, k2-lowpri
> 24 hours walltimek2-lowpri
> 786 GB memoryk2-himem only (2 TB, 3-day limit)
> 12 GB per corealso offered k2-himem

Notes

  • Resuming runs: The work/ directory is retained on completion (cleanup is left at its default). To reclaim scratch space, set cleanup = true in your own config, or run nextflow clean afterwards.
  • Container cache: Apptainer images are cached under /mnt/scratch2/users/$USER/apptainer_cache, so each image is pulled once and reused across runs. To cache elsewhere - for example a shared group directory - set NXF_APPTAINER_CACHEDIR to override this.

Support

For questions about this configuration profile, contact the maintainer listed in config_profile_contact. For general Kelvin2 cluster support, see the Kelvin2 documentation or contact the NI-HPC team.

Config file

See config file on GitHub

conf/kelvin2
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Nextflow config for QUB's Kelvin2 HPC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Author: William McCann
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
params {
config_profile_name = 'kelvin2'
config_profile_description = "Queen's University Belfast Kelvin2 HPC cluster profile provided by nf-core/configs."
config_profile_contact = 'William McCann (@wmsci)'
config_profile_url = 'https://ni-hpc.github.io/nihpc-documentation/'
// Legacy resource ceilings. Only read by older nf-core pipelines (pre-v3.0 template
// or Nextflow < 24.04). Modern pipelines use `process.resourceLimits` below instead.
max_cpus = 128
max_memory = 2.TB
max_time = 720.h
}
process {
// Modern resource ceilings, used by current Nextflow and nf-core pipelines.
// Mirrors params.max_* above so both old and new pipelines are covered.
resourceLimits = [
cpus : params.max_cpus,
memory: params.max_memory,
time : params.max_time,
]
executor = 'slurm'
maxRetries = 2
// Timestamp-tolerant caching
cache = 'lenient'
// Dynamic partition (queue) selection. Nextflow sets the SLURM partition (-p) from the
// return value and the walltime (-t) from task.time.
// - Jobs above the 786 GB general-node ceiling go only to k2-himem.
// - Other CPU tasks are placed by walltime; high memory-per-core jobs are additionally offered k2-himem.
queue = {
// General nodes top out at 786 GB; only k2-himem (2 TB, 3-day limit) can take more.
if (task.memory && task.memory > 786.GB) {
return 'k2-himem'
}
// Offer eligible partitions from highest to lowest priority: k2-hipri (≤ 3 h) and
// k2-medpri (≤ 24 h) only within their walltime limits, then k2-lowpri as a catch-all.
def partitions = []
if (task.time <= 3.h) { partitions.add('k2-hipri') }
if (task.time <= 24.h) { partitions.add('k2-medpri') }
partitions.add('k2-lowpri')
// High memory-per-core ratio (> 12 GB/core): also offer k2-himem, since general
// nodes fit these jobs poorly even when total RAM is within the 786 GB ceiling.
if (task.memory && task.cpus && task.memory.toGiga() / task.cpus > 12) {
partitions.add('k2-himem')
}
return partitions.join(',')
}
}
executor {
queueSize = 200
submitRateLimit = '10/sec'
jobName = { "${task.process.split(':').last()}" }
}
apptainer {
enabled = true
autoMounts = true
pullTimeout = 3.h
// Per-user image cache on scratch, so images are pulled once and reused across runs.
cacheDir = "/mnt/scratch2/users/${System.getenv('USER') ?: 'nxf'}/apptainer_cache"
}
// Allow anonymous access to AWS S3 (e.g. for nf-core test data and iGenomes).
aws {
client {
anonymous = true
}
}