No description
  • Go 75%
  • JavaScript 10.3%
  • Just 6.2%
  • CSS 5.2%
  • Dockerfile 2%
  • Other 1.3%
Find a file
Sophie Quinn-Graham 46ca0f3005
All checks were successful
Build Docker Image / build (push) Successful in 1m13s
push a main image too
2026-09-06 17:13:29 +10:00
.forgejo/workflows push a main image too 2026-09-06 17:13:29 +10:00
config add a web interface + justfile 2026-09-06 16:26:06 +10:00
deploy add a web interface + justfile 2026-09-06 16:26:06 +10:00
example-jobs add a web interface + justfile 2026-09-06 16:26:06 +10:00
rclone rclone.conf needs to come from whoever runs this 2026-09-06 16:07:03 +10:00
runner Prevent duplicate job dispatch and improve TUI progress display 2026-04-09 21:44:50 +10:00
scheduler add a web interface + justfile 2026-09-06 16:26:06 +10:00
ui Prevent duplicate job dispatch and improve TUI progress display 2026-04-09 21:44:50 +10:00
web add a web interface + justfile 2026-09-06 16:26:06 +10:00
.dockerignore build docker container(s) 2026-09-06 15:35:55 +10:00
.gitignore add a web interface + justfile 2026-09-06 16:26:06 +10:00
AGENTS.md add a web interface + justfile 2026-09-06 16:26:06 +10:00
Dockerfile add a web interface + justfile 2026-09-06 16:26:06 +10:00
go.mod first version 2026-04-09 21:18:33 +10:00
go.sum first version 2026-04-09 21:18:33 +10:00
justfile add a web interface + justfile 2026-09-06 16:26:06 +10:00
main.go add a web interface + justfile 2026-09-06 16:26:06 +10:00
README.md add a web interface + justfile 2026-09-06 16:26:06 +10:00
renovate.json chore(deps): add renovate.json 2026-08-08 01:06:26 +00:00

rclone-manager

Scheduling and monitoring for rclone sync jobs. Define jobs as YAML files and rclone-manager will run them on a schedule, showing live status either as a terminal UI or as a web dashboard.

Requirements

  • Go 1.21+
  • rclone installed and available on $PATH

Usage

rclone-manager --jobs <path-to-jobs-dir> [--poll <interval>] [--ui tui|web]
Flag Default Description
--jobs (required) Path to directory containing job YAML files
--poll 5m How often to check for due jobs
--rclone-config $RCLONE_CONFIG Path to rclone.conf. Empty leaves rclone to its own default discovery (~/.config/rclone/rclone.conf, RCLONE_CONFIG_<REMOTE>_* env vars, ...)
--ui tui (or $RCLONE_MANAGER_UI) Interface to run: tui (terminal) or web (HTTP)
--web-addr :8080 (or $RCLONE_MANAGER_WEB_ADDR) Listen address for the web interface

Interfaces

Both modes run the same scheduler and runner; they only differ in how you watch them.

--ui tui (default) renders a live dashboard in the terminal. Press q to quit.

--ui web serves the same information over HTTP and needs no TTY, which makes it the right choice under Kubernetes, Docker without -it, or anywhere you would rather point a browser than attach to a process.

rclone-manager --jobs ./my-jobs --ui web --web-addr :8080
Endpoint Description
GET / Dashboard: current job with live progress, upcoming schedule, run history
GET /api/state The same data as JSON — handy for scripting or testing
POST /api/jobs/{name}/run Run a job immediately, ignoring its schedule. 404 if unknown, 409 if already running
GET /healthz, GET /readyz Liveness and readiness. Both are cheap and never touch rclone, so a long sync will not fail a probe

The page polls /api/state once a second (backing off to every 15s while the tab is hidden). All assets are embedded in the binary — nothing is fetched from a CDN.

Job format

Each .yaml / .yml file in the jobs directory defines one sync job:

name: my-backup
source: /path/to/source
destination: /path/to/destination
operation: sync          # sync, copy, or bisync
schedule: 1h             # Go duration (e.g. 30m, 6h) or cron expression (e.g. "0 2 * * *")
flags:                   # optional rclone flags
  checksum: true

Fields

Field Required Description
name yes Human-readable job name
source yes Source path or rclone remote
destination yes Destination path or rclone remote
operation yes sync, copy, or bisync
schedule yes Interval (Go duration) or 5-field cron expression
flags no Extra flags passed to rclone

Docker

The image never contains an rclone.conf — supply it at run time:

docker build -t rclone-manager .
docker run --rm -it \
  -v ~/.config/rclone/rclone.conf:/config/rclone.conf:ro \
  -v ./my-jobs:/jobs:ro \
  rclone-manager

Without a TTY, run the web interface instead:

docker run --rm -p 8080:8080 \
  -v ~/.config/rclone/rclone.conf:/config/rclone.conf:ro \
  -v ./my-jobs:/jobs:ro \
  rclone-manager --jobs /jobs --ui web

The image sets RCLONE_CONFIG=/config/rclone.conf, so mounting the file there is all that is needed. Point it elsewhere by overriding that env var or passing --rclone-config <path>; pass --rclone-config "" to define remotes purely through RCLONE_CONFIG_<REMOTE>_* env vars instead. If the configured path does not exist, startup fails with an explicit error rather than silently running with no remotes.

Read-only config mounts

Kubernetes secrets and :ro bind mounts are not writable, but rclone rewrites its config file whenever it refreshes an OAuth token. When the config is not writable, rclone-manager copies it to a private 0600 file under $TMPDIR at startup and points rclone at the copy. Refreshed tokens therefore last for the lifetime of the process and are re-derived from the refresh token after a restart. $TMPDIR must be writable — with a read-only root filesystem, mount an emptyDir at /tmp.

Kubernetes

deploy/kubernetes.yaml is a working example: the config arrives as a Secret mounted at /config/rclone.conf, and jobs as a ConfigMap at /jobs.

kubectl create secret generic rclone-config \
  --from-file=rclone.conf=$HOME/.config/rclone/rclone.conf
kubectl apply -f deploy/kubernetes.yaml

The example runs --ui web, so no TTY is needed: the container exposes port 8080, both probes point at it, and a Service fronts it. Open the dashboard with:

kubectl port-forward svc/rclone-manager 8080:80

then browse to http://localhost:8080. To run the TUI under Kubernetes instead, drop the --ui web args and set tty: true and stdin: true on the container, then attach with kubectl attach -it deploy/rclone-manager (detach with Ctrl-P Ctrl-Q).

Building

go build -o rclone-manager .

Local development

A justfile wraps the common tasks. Everything runs through Docker, so no local Go toolchain is needed — only just, docker, curl and jq.

just copy     # build the image, start the web interface, run the example copy job

example-jobs/ holds two jobs that copy between directories inside the container, so they exercise the scheduler, runner and rclone daemon end to end without needing a configured remote. just seeds the source tree under .local/data/ (git-ignored), which is also where you can inspect what was copied.

Recipe Description
just build Build the Docker image
just run Build and start the web interface on http://localhost:8080
just copy run, then trigger the example copy job and print its result
just trigger <job> Trigger any job by name and wait for it to finish
just state Print /api/state as JSON
just logs Follow the container logs
just tui Run the terminal UI against the same example jobs
just stop / just clean Stop the container / also delete the seeded data