Sign inSign up

hoholabs/rotato

By hoholabs

•Updated 7 months ago

A deterministic, self-healing project staging system that manages libraries and targets.

Image
Content management system
0

1.5K

hoholabs/rotato repository overview

⁠Rotato

Self-hosted Docker app that syncs projects from libraries to storage-limited target devices (e.g. a Steam Deck or mini PC). It copies files from your source libraries to a target, enforcing a configurable storage limit with automatic LRU eviction.

⁠Quick Start

Create a docker-compose.yml:

services:
  rotato:
    image: hoholabs/rotato:latest
    container_name: rotato
    ports:
      - "7777:7777"
    volumes:
      - rotato_data:/data
      - /path/to/your/library:/mnt/my_library
      - /path/to/your/target:/mnt/my_target
    restart: unless-stopped

volumes:
  rotato_data:

Then run:

docker compose up -d

Open http://localhost:7777⁠ in your browser.

⁠Volume Mounts

MountPurpose
/dataPersistent database — always use a named volume here
/mnt/*Mount your library folders and target devices here — name them whatever you like

You can add as many libraries and targets as you need — just add more volume entries and register them in the UI.

⁠Target Availability (Sentinel File)

Rotato checks whether a target device is online before syncing to it. When you add a target in the UI, Rotato tries to create the sentinel file automatically — so if the device is already mounted and writable, it just works.

If you need to create it manually (e.g. for a device added before v0.2.0, or one that was offline when registered), place an empty file called .rotato_available at the root of the target mount:

touch /path/to/your/target/.rotato_available

If this file is missing, Rotato will show the target as OFFLINE and skip it. This lets it gracefully handle devices that are off or disconnected.

⁠Unraid Setup

  1. Go to Docker → Add Container
  2. Set Repository to hoholabs/rotato:latest
  3. Add port mapping: 7777 → 7777
  4. Add a path for the database: Host path /mnt/user/appdata/rotato, Container path /data
  5. Add paths for your libraries and targets (host path → any /mnt/... container path you choose)
  6. Start the container and open http://your-unraid-ip:7777
  7. Register your libraries and targets in the UI using the container paths you mapped

⁠Project Covers

To set a cover image for a project, place an image file named __cover (any extension) in the root folder of the project:

My Project/
  __cover.jpg   ← cover image
  game.exe
  ...

Rotato will use this image as the project's tile artwork in the UI.

⁠How It Works

  • Libraries are read-only sources (e.g. a NAS share with your game collection)
  • Targets are storage-limited destinations (e.g. a Steam Deck's SD card)
  • Projects (top-level folders in a library) can be queued to a target via the UI
  • The worker copies queued projects in the background, evicting the oldest unpinned projects when the target is full
  • Pinned projects are never evicted

⁠Managing the Queue

Click a project tile to queue it. Queued and in-progress items appear in the queue popover (click the worker status chip in the top bar).

From the queue popover you can:

  • ▶ Run Now — force-start a queued item immediately, without waiting for the worker's next cycle
  • ⏸ Pause / ▶ Resume — pause a specific queued item so the worker skips it; other items in the queue continue normally
  • ✕ Cancel — cancel an active copy while it's in progress; the partial staging data is cleaned up automatically

If a copy is interrupted (container restart, network hiccup, etc.), Rotato resumes from where it left off on the next worker pass — it doesn't restart from scratch.

⁠Pinning Projects

Click the ❤ pin icon on any project that's already on the target to pin it. Pinned projects:

  • Are never evicted, even when the target runs low on space
  • Sort to the front of the grid so they're easy to find
  • Cannot be removed while pinned — click the pin to unpin first

⁠Offline Handling

Rotato tracks whether libraries and targets are reachable:

  • If a library mount goes offline, its projects are preserved in the database and shown in the UI — they just can't be queued until the mount comes back. The library is marked OFFLINE in the dropdown and manage modal.
  • If a target mount goes offline (sentinel file missing), the worker skips it entirely. The target is marked OFFLINE in the status bar, dropdown, and manage modal.

⁠Navigating the UI

  • Tab key — cycles through your registered targets
  • Default target — in the Target Manager, click a target's folder icon to set it as the default. The default target is selected automatically when you open the app.
  • Hover / long-press a project tile — shows a tooltip with the project's size, library, state, and the date it was added to the target (on-target projects only)
  • Inline rename — in the Target or Library Manager, click a name to rename it directly

⁠Changelog

⁠v0.2.0
  • Copies are now chunked and resumable — interrupted transfers pick up where they left off
  • Per-item pause, resume, run-now, and cancel controls added to the queue popover
  • Offline state is now shown for libraries and targets throughout the UI
  • Added project tile tooltips, inline renaming, Tab key target switching, and default target setting
  • Sentinel file is auto-created when a new target is registered
⁠v0.1.1
  • Initial public release with library/target management, LRU eviction, pinning, project covers, and Docker Hub publishing

Tag summary

Content type

Image

Digest

sha256:bf2aba642…

Size

84.1 MB

Last updated

7 months ago

docker pull hoholabs/rotato