Nomploy Nomad Packs

← All packs

tududi v0.1.0

Productivity

Tududi — a self-hosted task and project manager with areas, projects, tasks, notes and tags, plus recurring tasks and a calendar view. Deployed as a single host-networked Nomad service (SQLite).

nomad-pack run tududi --registry nomploy
…or one line (add registry + run)
curl -fsSL https://packs.nomploy.com/install.sh | sh -s -- tududi

Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.

2 tasks http 3002 3 volumes image chrisvel/tududi:latest tracks :latest image bumped today
Variables 15
values.hcl

Save as values.hcl, edit, then run:

nomad-pack run tududi -f values.hcl --registry nomploy
# The name of the Nomad job.
job_name = "tududi"

# The Nomad namespace to deploy into.
namespace = "default"

# The datacenters to deploy to.
datacenters = ["*"]

# The Tududi container image. Pin a tag in production.
image = "chrisvel/tududi:latest"

# Host port for the Tududi web UI.
port = 3002

# Email of the admin account seeded on first start.
admin_email = "admin@example.com"

# Password of the admin account seeded on first start. CHANGE THIS.
admin_password = "tududi_change_me"

# Secret used to sign sessions (openssl rand -hex 64). CHANGE THIS.
session_secret = "change_me_to_a_long_random_session_secret_0000"

# Comma-separated origins allowed to reach the API. Set to your public URL.
allowed_origins = "http://localhost:3002"

# Set true when running behind a reverse proxy (e.g. Traefik) so secure cookies work.
trust_proxy = "true"

# Named volume for the SQLite database (/app/db).
db_volume = "tududi_db"

# Named volume for uploaded files (/app/uploads).
uploads_volume = "tududi_uploads"

# Named volume for backups (/app/backups).
backups_volume = "tududi_backups"

# Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []

# The task resources.
resources = {
    cpu    = 500
    memory = 768
  }
NameTypeDefaultDescription
job_name string
"tududi"
The name of the Nomad job.
namespace string
"default"
The Nomad namespace to deploy into.
datacenters list
["*"]
The datacenters to deploy to.
image string
"chrisvel/tududi:latest"
The Tududi container image. Pin a tag in production.
port number
3002
Host port for the Tududi web UI.
admin_email set me string
"admin@example.com"
Email of the admin account seeded on first start.
admin_password set me string
"tududi_change_me"
Password of the admin account seeded on first start. CHANGE THIS.
session_secret set me string
"change_me_to_a_long_random_session_secret_0000"
Secret used to sign sessions (openssl rand -hex 64). CHANGE THIS.
allowed_origins string
"http://localhost:3002"
Comma-separated origins allowed to reach the API. Set to your public URL.
trust_proxy string
"true"
Set true when running behind a reverse proxy (e.g. Traefik) so secure cookies work.
db_volume string
"tududi_db"
Named volume for the SQLite database (/app/db).
uploads_volume string
"tududi_uploads"
Named volume for uploaded files (/app/uploads).
backups_volume string
"tududi_backups"
Named volume for backups (/app/backups).
constraints list
[]
Placement constraints. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
resources object
{
    cpu    = 500
    memory = 768
  }
The task resources.
Back up this pack

This pack stores data in 3 Docker named volumes: tududi_dbtududi_uploadstududi_backups

restic

# Run on the node hosting this pack. Point restic at your repo first:
#   export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>"
#   export RESTIC_PASSWORD="<repo-password>"
#   export AWS_ACCESS_KEY_ID=<key>  AWS_SECRET_ACCESS_KEY=<secret>
restic backup \
  /var/lib/docker/volumes/tududi_db/_data \
  /var/lib/docker/volumes/tududi_uploads/_data \
  /var/lib/docker/volumes/tududi_backups/_data

rclone (sync to S3/R2)

rclone sync /var/lib/docker/volumes/tududi_db/_data backup:<bucket>/tududi_db
rclone sync /var/lib/docker/volumes/tududi_uploads/_data backup:<bucket>/tududi_uploads
rclone sync /var/lib/docker/volumes/tududi_backups/_data backup:<bucket>/tududi_backups

Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.

Readme

tududi

Tududi is a self-hosted task and project management app. It organises work into areas → projects → tasks, with notes, tags, recurring tasks, due dates, a today/calendar view and multi-user sharing — a clean, keyboard-friendly alternative to Todoist or Things that runs on your own server.

This pack runs Tududi as a single host-networked Nomad service backed by SQLite.

Deploy

nomad-pack run tududi --registry=nomploy \
  --var admin_email=you@example.com \
  --var admin_password=$(openssl rand -hex 12) \
  --var session_secret=$(openssl rand -hex 64) \
  --var allowed_origins=https://tasks.example.com

Open http://<node-ip>:3002 and sign in with your admin email/password.

Configuration

Variable Default Description
image chrisvel/tududi:latest Container image (pin a tag in production).
port 3002 Host port for the web UI.
admin_email admin@example.com Seeded admin email.
admin_password tududi_change_me Seeded admin password — change this.
session_secret placeholder Session signing secret — change this.
allowed_origins http://localhost:3002 Public URL(s) allowed to call the API.
trust_proxy true Trust X-Forwarded-* (behind Traefik).
db_volume tududi_db Volume for the SQLite database (/app/db).
resources 300 MHz / 384 MB CPU and memory for the task.

A prestart init task makes the volumes writable by the app user. The database, uploads and backups persist across restarts. Set allowed_origins to the exact URL you serve Tududi from, or the browser's requests will be rejected.