CARACAL Fleet

Digital signage management · self-hosted

Every screen in the building, from one tab.

CARACAL Fleet runs your Raspberry Pi and PC signage screens from one place: what they show, when they show it, and whether they are still alive. New screens install themselves from an SD card. One docker compose up on your own server.

  • Latest4.21.0
  • ServerDocker · amd64, arm64
  • ScreensRaspberry Pi 4/5 · PC
  • InterfaceEN · CS · SK · DE · PL
  • LicenseGPL-3.0
caracal-fleet · overview
CARACAL Fleet in action: sign-in, the overview, devices and a week of one screen, the screen wall, a global playlist with weather and news widgets, approvals, what plays when, proof of play, the media library and an emergency message
Overview, the screen wall, a global playlist with weather and news widgets, approvals, what plays when, proof of play and an emergency message.

What it does

Built for the person who looks after twenty TVs in reception, meeting rooms and the shop floor, and gets the call when one of them shows a browser error.

Watch every screen

  • Live state of each screen: online, CPU, RAM, disk, temperature, and what it is playing right now.
  • Needs attention list with the reason for each problem, and a timeline of outages per device.
  • Alerts after a delay you choose, grouped into one message, with a "resolved" message too.
  • Screen wall of what every screen shows, a map of locations and a monthly PDF report.
  • Proof of play: what each screen showed and for how long, with a CSV export.

Put content on them

  • Playlists of web pages, Grafana dashboards, images, videos and IP cameras, up to 9 in a grid.
  • Widgets drawn by the screen: clock, weather, RSS, a table from Google Sheets, a calendar, a meeting room, a QR code, a ticker.
  • PDF and PowerPoint become one picture per page.
  • Screen layout with a side panel and a bottom bar next to the playlist.
  • Emergency message on all screens or chosen locations in one click.

Run the whole fleet

  • Global playlists deployed to many screens, with 50 kept versions and a preview of what changes.
  • Schedules by hour and weekday, screen hours with HDMI-CEC off and on, and a day view of what plays when.
  • Approvals for content before it goes on the screens.
  • Media library with Replace everywhere.
  • Customers: agencies give each client its own locations, users and content.

Install and update

  • Zero-touch SD cards for Raspberry Pi and USB sticks for PCs, or one command on any Debian, Ubuntu or Alpine.
  • Staged updates to pilot screens first, then in batches; automatic rollback if a screen doesn't come back.
  • Offline screens: Fleet can be the only download source, apt and Docker included.
  • Fleet updates itself from the web interface, with rollback.
  • SSH console to any screen right in the browser.

Zero-touch installation

From a blank SD card to a playing screen

No keyboard on the TV, no SSH. The card carries Wi-Fi or a static IP, the time zone, the download source and a template with the playlist, so the screen is ready the moment it connects.

The enrollment token on the card is removed on the first boot.

  1. Add device → Prepare SD cardPick Wi-Fi, address, location and a template in Fleet.
  2. Write Raspberry Pi OS Lite or DietPiWith Raspberry Pi Imager, then copy the downloaded files to the boot partition.
  3. Power the Pi onIt installs Docker, the display, CARACAL and the agent by itself.
  4. It appears in FleetAs prefix-xxxxxx after 10 to 30 minutes, already playing its playlist.

How it fits together

The agent on each screen opens every connection itself, so screens can sit behind NAT or in another network. Logins of websites travel only to the screen.

Works with what you have

Alerts

  • E-mail (SMTP)
  • Microsoft Teams
  • Slack
  • Discord
  • Telegram
  • ntfy
  • Webhook

Backups off the server

  • Amazon S3
  • Backblaze B2
  • Cloudflare R2
  • MinIO
  • Nextcloud (WebDAV)
  • SFTP
  • SMB
  • NFS
  • rclone

Sign-in

  • Microsoft Entra ID
  • Google
  • Keycloak
  • Authentik
  • TOTP two-factor

Content sources

  • Grafana
  • Open-Meteo
  • RSS / Atom
  • Google Sheets / CSV
  • Microsoft 365 / Google calendars
  • RTSP / ONVIF cameras

Notification API · REST · webhooks

Let your other systems talk to the screens

Grafana, Alertmanager and Uptime Kuma webhooks work as they are. A token reaches all screens or only chosen groups and locations, with its own rate limit.

API tokens with a role and scope can drive the whole REST API, and signed webhooks report device.offline, takeover.started, content.expiring and more.

A notification on every screen
$ curl -X POST https://fleet.example/api/notify \
    -H "Authorization: Bearer cft_..." -H "Content-Type: application/json" \
    -d '{"title":"Backup finished","message":"DB01","level":"success"}'
Emergency message for 30 minutes
$ curl -X POST https://fleet.example/api/takeovers \
    -H "Authorization: Bearer cfa_..." -H "Content-Type: application/json" \
    -d '{"title":"Evacuate the building","level":"critical","minutes":30,"targets":{"all":true}}'

Permissions

The reception can change its own screens

Thirteen permissions in built-in or custom roles, each for a scope: all devices or chosen locations, groups and devices. User groups give roles too, and nobody can grant more than they have.

RoleCan
viewersee state, playlists, schedules and screens
operator+ control playback and change content
manager+ all device permissions, installation, notification API, audit
admineverything, users and settings included

Security

Whoever controls the hub controls the screens, so the hub is built to be hard to take over.

  • Passwords with PBKDF2-SHA256, HMAC-signed sessions ended by a password change.
  • Rate-limited sign-in per address and per account, with failures in the audit log.
  • Strict headers: CSP without inline scripts, HSTS, X-Frame-Options: DENY.
  • Per-device tokens for agents; the enrollment token can be rotated at any time.
  • SSH host keys pinned on first use, credentials never stored, idle consoles closed.
  • Secrets travel only to the screen and are removed from the command once delivered.
  • Known limits, stated plainly: the hub container runs as root, and backups kept on the hub itself are not encrypted. Copies sent off the server can be, with AES-256-GCM.

Run it on any Docker host

A Linux server, a NAS or a spare Raspberry Pi. Open http://server:8090 and claim it with the one-time setup code from the log. Add Caddy for HTTPS with one more flag.

Quick start
$ mkdir caracal-fleet && cd caracal-fleet
$ curl -fsSLO https://raw.githubusercontent.com/Gelluithor/Caracal-Fleet/main/compose.yml
$ docker compose up -d
$ docker compose logs hub | grep "SETUP CODE"