Skip to main content

In-process Nextflow Tower API shim — accumulate -with-tower trace events without a Seqera Platform subscription

Project description

Nextflow Turret

A self-hosted replacement for Seqera Platform (formerly Nextflow Tower). Run any Nextflow pipeline with -with-tower, track progress in real time, launch new runs from a web UI, and inspect logs — all without a cloud subscription.


Features

Feature Details
Tower trace receiver Accepts the full Nextflow -with-tower HTTP protocol
SQLite persistence Every run is immediately written to disk; survives restarts
Pipeline launcher Submit pipelines via web form or REST API; cancel running jobs
Web dashboard Live run list, per-run progress detail, failed-task drill-down
REST API JSON API for runs and launches (OpenAPI docs at /docs)
Embeddable library Use WorkflowRegistry + TowerRouter inside your own Python app

Installation

# Into an existing project
uv add "nextflow-turret @ git+https://github.com/msk-mind/nextflow-turret.git"

# Or with pip
pip install "nextflow-turret @ git+https://github.com/msk-mind/nextflow-turret.git"

Quick start — standalone server

# Start the server (default: http://0.0.0.0:8000, DB: turret.db)
turret

# Or with explicit options (always override config file)
turret --host 127.0.0.1 --port 9000 --db /data/turret.db --log-dir /data/logs

# Or via Python
python -m nextflow_turret.server --port 9000

Config file

Create a turret.toml in the working directory (or ~/.config/turret/config.toml for user-level defaults). CLI flags always win over config values.

[server]
host    = "0.0.0.0"
port    = 8000
db      = "/data/turret.db"
log_dir = "/data/turret-logs"

[launcher]
nextflow        = "/opt/nextflow/nextflow"
work_dir        = "/scratch/nf-work"
default_profile = "slurm"

A fully-commented template is at turret.toml.example.

Then point Nextflow at it:

nextflow run nf-core/rnaseq -with-tower http://localhost:8000 -name dispatcher_mybatch \
  -profile docker -r 3.14.0

Open http://localhost:8000 to see the live dashboard.


REST API

Interactive docs are available at /docs when the server is running.

Tower trace endpoints (called by Nextflow)

Method Path Purpose
GET /user-info Auth check on Nextflow startup
POST /trace/create Workflow registered → returns {workflowId}
PUT /trace/{id}/begin Workflow running
PUT /trace/{id}/progress Periodic task counts + per-task list
PUT /trace/{id}/heartbeat Keepalive (same payload as progress)
PUT /trace/{id}/complete Workflow finished

Runs API

Method Path Description
GET /api/runs List all runs (newest first)
GET /api/runs/{workflow_id} Single run detail with task counts, failures, resources

Launches API

Method Path Description
GET /api/launches List all launches (newest first)
POST /api/launches Submit a new pipeline launch
GET /api/launches/{id} Launch status and metadata
GET /api/launches/{id}/log?tail=N stdout/stderr log (optionally tailed)
DELETE /api/launches/{id} Cancel a running launch (SIGTERM)

Submit a launch via REST

curl -X POST http://localhost:8000/api/launches \
  -H "Content-Type: application/json" \
  -d '{
    "pipeline":  "nf-core/rnaseq",
    "revision":  "3.14.0",
    "profile":   "docker",
    "params":    {"input": "samplesheet.csv", "genome": "GRCh38"},
    "work_dir":  "/scratch/work"
  }'

run_name → batch_id mapping

Nextflow is launched with -name dispatcher_{batch_id}. The dispatcher_ prefix is stripped automatically to produce the batch_id that identifies the run.

To use a different prefix, create your own TowerRouter:

from nextflow_turret import TowerRouter, WorkflowRegistry

registry = WorkflowRegistry()
router   = TowerRouter(
    registry=registry,
    run_name_to_batch_id=lambda name: name.removeprefix("mypipeline_"),
)

Embedding in your own Python app

If you prefer to host the Tower receiver inside an existing service rather than running the standalone server, use the core library directly:

from nextflow_turret import TowerRouter, WorkflowRegistry

registry = WorkflowRegistry()
router   = TowerRouter(registry=registry)

# In your HTTP handler:
result = router.handle_get(path)          # GET /user-info
result = router.handle_post(path, body)   # POST /trace/create
result = router.handle_put(path, body)    # PUT  /trace/{id}/progress

# Read progress at any time:
state = registry.get_by_batch("mybatch")
print(state["pct"], "% complete")
print(state["task_counts"])   # {"succeeded": 42, "running": 3, ...}
print(state["failures"])      # [{"taskId": 7, "process": "ALIGN", "exit": 1}, ...]

Module-level singleton

For quick scripts, a global registry is available:

import nextflow_turret as turret

turret.register_workflow(workflow_id, batch_id, run_name)
turret.update_progress(workflow_id, progress_dict, tasks_list)
turret.mark_complete(workflow_id)

state = turret.get_progress(batch_id)   # → dict or None

Utilities

from nextflow_turret import tower_process_to_slurm_name

# Convert a Tower process name to a SLURM job name prefix
tower_process_to_slurm_name("MUSSEL:EXTRACT_FEATURES:TESSELLATE_FEATURIZE_BATCH")
# → "MUSSEL_EXTRACT_FEATURES_TESSELLATE_FEATURIZE_BATCH"

Architecture

nextflow_turret/
├── state.py            # WorkflowRegistry, WorkflowState — core in-memory model
├── handlers.py         # TowerRouter — parses Tower HTTP payloads
├── db/
│   └── store.py        # RunStore — SQLite persistence (runs + launches)
├── launcher/
│   └── launcher.py     # Launcher — subprocess management for pipeline runs
└── server/
    ├── app.py          # FastAPI application factory (create_app)
    ├── registry.py     # PersistentWorkflowRegistry — DB-backed registry
    ├── __main__.py     # CLI entry point (turret / python -m nextflow_turret.server)
    └── templates/      # Jinja2 HTML templates (dashboard, detail, launch form)

Key design decisions:

  • Write-through persistence — every Tower trace event is committed to SQLite before the HTTP response is sent.
  • Restart recovery — on startup, PersistentWorkflowRegistry re-hydrates all rows from the DB so in-progress runs can continue receiving trace events.
  • No external dependencies for the core library — only fastapi, uvicorn, and jinja2 are needed for the server extras.

Development

git clone https://github.com/msk-mind/nextflow-turret.git
cd nextflow-turret

# Run tests (uv installs deps automatically)
uv run pytest

# Or sync into a venv and work interactively
uv sync --extra server
source .venv/bin/activate
pytest --tb=short -q

Test layout

File Tests Coverage
tests/test_turret.py 39 Core library (WorkflowRegistry, WorkflowState, TowerRouter)
tests/test_server.py 44 Server layer (RunStore, PersistentWorkflowRegistry, all endpoints)
tests/test_integration.py 32 Cross-layer: Tower→SQLite, restart recovery, concurrency, API/DB/UI consistency
tests/test_e2e.py 34 Full scenarios: NF trace lifecycle, failed tasks, multi-run dashboard, launch UI journey, error paths

License

Nextflow Turret is released under the GNU Affero General Public License v3.0 (AGPL-3.0-or-later).

This means:

  • Free to use, modify, and self-host for any purpose.
  • If you modify Nextflow Turret and run it as a network service, you must make your modified source code available to users of that service.

See LICENSE for the full terms.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nextflow_turret-0.1.0.tar.gz (74.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nextflow_turret-0.1.0-py3-none-any.whl (59.5 kB view details)

Uploaded Python 3

File details

Details for the file nextflow_turret-0.1.0.tar.gz.

File metadata

  • Download URL: nextflow_turret-0.1.0.tar.gz
  • Upload date:
  • Size: 74.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nextflow_turret-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bdfbe11619210a4a23b9651ef0b9728dd2f6a94c3d59bc4d4c0fd7a1bc593858
MD5 57886f071214f1083b4de291f560a8eb
BLAKE2b-256 a4810df4c8fda5a2a65d7985d5bb5d73188998e00721daa66adc8e718cbf27cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for nextflow_turret-0.1.0.tar.gz:

Publisher: publish.yml on msk-mind/nextflow-turret

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nextflow_turret-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for nextflow_turret-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5a166d370c1b174afe466a5125f91e967cef3aae9782357ec57a532bbdee8d3
MD5 ece1e988bd662e7fa41798294814a27f
BLAKE2b-256 85e2cdd4f136cd00990046ce1f945f646cab43f92aea239a3b83ca9cc77109ec

See more details on using hashes here.

Provenance

The following attestation bundles were made for nextflow_turret-0.1.0-py3-none-any.whl:

Publisher: publish.yml on msk-mind/nextflow-turret

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page