{% extends "base.html" %} {% block title %}User guide · LibreSignage{% endblock %} {% block meta_description %}Install the LibreSignage server and screen client, then learn how to manage content, schedules, layouts, and displays.{% endblock %} {% block head %} {% endblock %} {% block content %}
Public documentation

LibreSignage user guide

Create, organize, schedule, preview, and publish digital signage from one central dashboard.

Install a local or remotely hosted server, connect screen clients, and follow the complete workflow from your first item to published playback.

Start with the basics Open dashboard

How LibreSignage works

LibreSignage separates preparation from delivery. You add reusable items to the content library, arrange them in playlists, optionally control when they play with schedules or where they appear with layouts, and then assign the result to managed screens.

{% for title, description in [ ("Content", "The individual images, videos, PDFs, messages, web pages, feeds, clocks, and QR codes."), ("Playlist", "An ordered sequence of content with timing, transitions, and looping settings."), ("Schedule", "A rule that activates a playlist by date, weekday, local time, and priority."), ("Layout", "A fixed multi-zone design in which each zone plays its own playlist."), ("Screen", "A registered display with a stable player URL, profile, assignment, and published revision."), ("Publish", "The action that delivers all staged screen changes to the players.") ] %}

{{ title }}

{{ description }}

{% endfor %}
Draft versus published: assignment changes are staged first. Screens keep showing their last published revision until an administrator selects Publish.

Install the LibreSignage server

The server hosts the CMS, media library, and public player URLs. Use the local setup for development or a trusted private network. Use the remote setup when screens connect over the internet.

Server requirements: Python 3.10 or newer, Node.js 20 or newer, uv, and FFmpeg when video uploads are enabled. The host also needs enough persistent storage for the SQLite database and uploaded media.

Local server

This path runs directly from a source checkout and is suitable for evaluating LibreSignage on one computer or a trusted LAN.

  1. Get the source and install locked dependencies.
    git clone <repository-url> libresignage
    cd libresignage
    uv sync --locked --group dev
    npm ci
    npm run build
  2. Create the local configuration.
    cp .env.example .env
    python -c "import secrets; print(secrets.token_hex(32))"

    Put the generated value in LIBRESIGNAGE_SECRET_KEY and review the database, upload folder, timezone, and FFmpeg settings in .env. Do not commit that file.

  3. Start the development server.
    uv run flask --app libresignage run --debug

    Open http://127.0.0.1:5000/auth/setup and create the first administrator. To test from another device on the same trusted network, bind to the LAN interface:

    uv run flask --app libresignage run --host 0.0.0.0 --port 5000
Flask's development server is not a production internet server. Do not expose port 5000 directly to the public internet.

Remote production server

A remote deployment uses the same application behind a production WSGI server and an HTTPS reverse proxy. The following example assumes a Linux host and a checkout at /opt/libresignage.

  1. Install and build the application.
    cd /opt
    git clone <repository-url> libresignage
    cd /opt/libresignage
    uv sync --locked
    npm ci
    npm run build
  2. Configure production paths and secrets.

    Copy .env.example to .env, restrict it to the service account, and set at least these values:

    LIBRESIGNAGE_CONFIG=production
    LIBRESIGNAGE_SECRET_KEY=<generated-random-secret>
    LIBRESIGNAGE_DATABASE=/var/lib/libresignage/libresignage.sqlite
    LIBRESIGNAGE_UPLOAD_FOLDER=/var/lib/libresignage/uploads
    LIBRESIGNAGE_TIMEZONE=America/Chicago
    LIBRESIGNAGE_TRUSTED_PROXY_COUNT=1

    Create the data directories with write access for the dedicated service account. Back up both the database and uploads together. Set the trusted proxy count only to the exact number of proxies controlled by your deployment; it lets login throttling use the original client address safely.

  3. Run a production WSGI server.
    uv run --with gunicorn gunicorn \
      --workers 2 \
      --bind 127.0.0.1:8000 \
      'libresignage:create_app()'

    Manage this command with the host's service manager so it starts after reboot and restarts after failure. Keep its working directory set to /opt/libresignage so the project-level .env is loaded.

  4. Put HTTPS in front of the service.

    Configure Nginx, Caddy, or an equivalent reverse proxy to terminate TLS and forward requests to http://127.0.0.1:8000. Preserve the original Host and forwarding headers, allow uploads up to the configured LIBRESIGNAGE_MAX_CONTENT_LENGTH, and use a publicly trusted certificate for internet-connected clients.

  5. Finish setup and verify access.

    Open https://signage.example.com/auth/setup, create the first administrator, sign in, and register a test screen. From the display network, confirm that the server URL and the screen's public status URL are reachable without a VPN login or proxy authentication prompt.

Before going live: allow only HTTPS through the firewall, persist and back up application data, enable automatic service startup, verify FFmpeg, and test a complete upload, publish, playback, and offline-cache cycle.

Install the LibreSignage screen client

Install one client on each display computer. A client needs the base URL of a reachable LibreSignage server and the stable slug of a screen registered in the CMS. The server can be local, elsewhere on the LAN, or remotely hosted over HTTPS.

Install from source

  1. Install the client environment.
    cd libresignage/client
    uv sync --locked

    On Debian or Ubuntu, the bundled Qt renderer also needs the standard X11/XCB desktop libraries:

    sudo apt install libxcb-cursor0 libxcb-icccm4 libxcb-image0 \
      libxcb-keysyms1 libxcb-render-util0 libxcb-xkb1 libxkbcommon-x11-0

    Windows uses WebView2 and macOS uses the system WKWebView. Install the client on the same operating system on which it will run.

  2. Register this physical display.

    Sign in to LibreSignage, open Screens, add the display, and copy its complete authenticated setup command. The command contains both the screen slug and its private token. Assign content and publish it before provisioning the client.

  3. Configure the server connection.

    For an HTTPS server on the same trusted LAN:

    uv run libresignage-client configure \
      --server-url https://signage.lan \
      --screen-slug lobby-display-a1b2c3d4 \
      --screen-token YOUR_SCREEN_TOKEN

    For a remotely hosted server:

    uv run libresignage-client configure \
      --server-url https://signage.example.com \
      --screen-slug lobby-display-a1b2c3d4 \
      --screen-token YOUR_SCREEN_TOKEN

    Supply only the server's base URL—not the complete player URL. Reverse-proxy subpaths such as https://example.com/signage are supported.

  4. Verify and start the player.
    uv run libresignage-client show
    uv run libresignage-client diagnose
    uv run libresignage-client run

    The diagnostic command must report the screen's published revision before kiosk deployment. Use configure --windowed --not-on-top while testing if you do not want a fullscreen always-on-top window.

Build a standalone client

Build on each target operating system; PyInstaller does not cross-compile the client for another platform.

cd libresignage/client
uv sync --locked --group dev
uv run pyinstaller libresignage-client.spec --clean --noconfirm

The build writes the graphical libresignage-client and terminal libresignage-client-cli executables below client/dist/libresignage-client/. Double-clicking an unconfigured graphical client opens its first-run connection screen.

Prepare for unattended playback

  • Configure the operating system to sign in to a restricted signage account and launch the client after login.
  • Keep the client's persistent browser profile; private sessions cannot retain offline media.
  • Open the player while online and wait for Offline playlist ready.
  • Disconnect the network, restart the client, and reboot the device to verify cached playback.
  • On Linux Qt clients, use the server-normalized WebM/VP9 video output rather than assuming H.264 support.
Never reuse one screen slug on several physical displays. Each client needs its own registered screen so revisions, health reports, and remote commands are attributed correctly.

Quick start: put content on one screen

{% for number, title, description, endpoint, link_text in [ (1, "Add content", "Upload a file or create a text, clock, QR, feed, or web item. Give it a clear title and duration.", "content.index", "Open Content"), (2, "Build a playlist", "Create a playlist, open it, add library items, and arrange their playback order.", "content.playlists", "Open Playlists"), (3, "Register a screen", "Add the display, record its location, and set its resolution and media-scaling preference.", "dashboard.screen_inventory", "Open Screens"), (4, "Stage the assignment", "Choose Direct playlist as the screen playback source and select the playlist.", "dashboard.screen_inventory", "Assign content"), (5, "Preview and publish", "Preview the draft, correct anything unexpected, then publish the staged changes.", "dashboard.index", "Open Dashboard"), (6, "Open the player", "Open the screen player URL on the display and wait until the offline playlist reports ready.", "dashboard.screen_inventory", "Find player URL") ] %} {% endfor %}

Manage the content library

Go to Content to add and organize everything that can appear on a display.

Supported content

TypeWhat to provideImportant behavior
ImageAn image fileUses the screen's fit, crop, or stretch setting.
VideoA video fileProcesses in the background and is skipped until ready.
PDFA PDF fileDisplayed for the item's configured duration.
TextA messageRendered locally and available offline.
ClockAn IANA timezone, such as America/ChicagoContinues updating offline.
QR codeA website or contact detailsGenerated locally; contact codes can include a structured address.
Web pageAn HTTPS URLThe site must allow iframe embedding and requires connectivity.
FeedAn RSS or Atom URLRefreshes periodically and keeps the last successful result.

Organize and maintain assets

  • Set the default duration; a playlist entry can override it.
  • Use one folder and up to ten comma-separated tags for filtering.
  • Set an expiry date for temporary campaigns. Expired items remain visible but are skipped during playback.
  • Search by title, text, URL, folder, or tag, and use the folder filter for a narrower view.
  • Use Edit / replace to update an asset without losing its playlist positions.
  • Check the usage badge before deleting. An in-use item requires explicit confirmation and is removed from its playlists.
Video uploads show Video processing… while the server prepares them. Do not expect a new video to appear in players until its status is ready. A conversion failure is shown in the library.

Create designs from templates

Templates provide accessible announcement, promotion, and information-notice designs without requiring design software.

Restaurant and food-truck presets include a six-item menu board, daily special, combo deal, and current-stop announcement. Menu rows keep item names, descriptions, and prices aligned; special and combo layouts give the price a prominent treatment.

  1. Choose the template that best matches the message.
  2. Enter its labeled text, duration, brand color, and text color.
  3. If you upload an image, provide alternative text that describes it.
  4. For menu boards, enter a name and price for every row you use; descriptions are optional.
  5. Review the live preview, then create the item.

Reuse your brand

Administrators can open Brand kits to save a logo, accessible primary/secondary/text colors, and locally hosted WOFF2 heading and body fonts. Editors can apply a kit and adjust colors for a specific design. Existing designs retain the brand snapshot they were saved with.

Bind menu rows

Menu boards can read up to six rows from CSV, JSON, or a publicly published Google Sheets CSV URL. Map columns to name, description, and price; every used row needs a name and price. Remote sheets refresh every five minutes and keep showing the last successful rows if the source is temporarily unavailable.

Repeat and recover changes

  • Use Duplicate as next week's special to review a prefilled copy dated for the following Monday before creating it.
  • Every template save records the operator, time, metadata, design values, assets, and data binding.
  • Open Version history to inspect or restore a prior snapshot; restoration itself creates a new version.

LibreSignage checks text contrast for accessibility. The finished design becomes a normal content item and can be reused anywhere.

Build and arrange playlists

Go to Playlists, create a named playlist, and open it to add items from the library.

  • Place entries in the exact order they should play.
  • Keep an entry's default duration or set an override for this playlist only.
  • Choose none, fade, slide left, slide up, or soft zoom. Each option is brief and restrained for signage; players also honor the device's reduced-motion preference.
  • Enable looping for continuous signage, or disable it for one-time playback.
  • Use the playlist player to review the complete sequence.

A player automatically moves past media that fails. Expired and not-yet-ready items are excluded from the playable sequence.

Control playback with schedules

Use Schedules when screens should switch playlists automatically.

  1. Choose a playlist and give the schedule a descriptive name.
  2. Target all scheduled screens or one screen group.
  3. Select its IANA timezone. All date and time rules use that local timezone.
  4. Optionally limit the rule to a start date, end date, and selected weekdays.
  5. Choose all-day playback or enter a start and end time. Overnight ranges are supported.
  6. Set its priority and leave it enabled.
When several rules match, the enabled schedule with the highest priority wins. If priorities are equal, the newest matching rule wins. Assign the screen to Scheduled channel for these rules to take effect.

Holidays and one-off exceptions

Open Date rules to create an inclusive, whole-date exception in a specific timezone. A blackout plays nothing for closed days. A playlist override temporarily replaces normal schedules, such as a holiday menu from December 24 through 26.

  • Target every scheduled screen or a single screen group.
  • When date rules overlap, highest priority wins; newest wins a tie.
  • The winning date rule takes precedence over every recurring schedule.
  • Groups in use cannot be deleted until their rules are retargeted or removed.

Calendar view

Use the schedule calendar to switch between month and week views. Filter by timezone and target. Blue entries are schedules, yellow entries are overrides, and dark entries are blackouts.

Use multi-zone layouts

Layouts divide a display into independently playing zones. Available presets include a 70/30 split, main content with a ticker, and a 70/30 split with a ticker.

  1. Create a layout and choose a preset.
  2. Open the layout and assign one playlist to each zone.
  3. Preview the layout and confirm that each zone has useful content.
  4. Stage the layout as a screen's playback source, then publish.

Each zone advances independently. On portrait displays, split zones stack vertically. All local media used by the layout is included in the screen's offline cache.

Register and organize screens

Use Screens to manage each physical display.

Screen profile

  • Use a recognizable name, physical location, and operator notes.
  • Select a common resolution or enter custom dimensions.
  • Fit with letterboxing shows the whole image; Fill and crop fills the screen; Stretch changes the media proportions to match.
  • Add screens to reusable groups such as “Front of house” or “North campus.”

Assign playback

Choose Scheduled channel, Direct playlist, or Multi-zone layout. Assign one screen directly, select several screens, target a group, or target the whole fleet. Bulk targeting resolves the current members when you stage the change.

Connect the display

Select Open player to obtain the permanent managed player URL. A native PyWebView deployment can use the configuration command shown under PyWebView client setup for that screen. Keep each device on its own screen URL so health and commands are attributed correctly.

Preview drafts and publish safely

  1. Stage the desired assignment on the dashboard or screen inventory.
  2. Select Preview draft and check the content at the screen's saved resolution.
  3. Temporarily compare another resolution or scaling mode if needed.
  4. Return to the dashboard and select Publish.
  5. Confirm that the screen reports the new published revision and remains online.

Publish delivers all staged screen assignments as one fleet batch. Connected players normally detect a new revision within two seconds and switch to it atomically.

Previewing does not publish, advance a revision, or count as device contact. An external web page may also refuse to appear in Preview because of that website's embedding policy.

Monitor screens and offline playback

The Dashboard labels screens as online, degraded, offline, or never connected. It also shows last contact, cache readiness, service-worker state, storage use, revision, last played item, and the latest cache error.

  • After the first publish, open the player while online and wait for Offline playlist ready.
  • Local images, videos, PDFs, text, templates, and player assets can then survive a connection loss.
  • RSS feeds cache their last successful publish-time snapshot for outages.
  • Web items can opt into static screenshots when the optional server capture service is enabled; other live pages show an offline message.
  • The player warns when a revision approaches available browser storage and refuses updates that cannot fit, while preserving the last complete revision.
  • A failed cache update keeps the last complete published revision.
  • Administrators can request Sync now, restart the browser player, or clear LibreSignage caches.
  • Run uv run libresignage-monitor beside the server for email, signed webhook, and Telegram transition, recovery, and digest notifications.

The native client can opt into operating-system reboot with configure --allow-os-reboot. The action appears only while its independent agent is connected, and the local account must have reboot permission.

Verify playback history

Open Proof of play to answer when an asset ran on a managed screen. Filter the report by date, screen, asset title or ID, layout zone, and outcome, then export the same result as CSV.

  • Played means the item reached its natural configured duration.
  • Skipped means playback was interrupted or superseded before completion.
  • Error means the player detected a media loading or playback failure.
  • Multi-zone layouts report each zone independently.
  • Offline players queue events locally and upload them after reconnecting.
Proof of play is client-reported lifecycle evidence. It does not verify pixels on the physical display or confirm that an audience saw the content. Draft previews and emergency messages are not included.

Send an emergency message

Administrators can use the emergency override on the dashboard to interrupt normal playback on selected screens, a group, or the entire fleet.

  1. Enter a short title and clear message.
  2. Choose critical, warning, or information severity.
  3. Choose the target and activate the override.
  4. When the event ends, select Restore published playback.

Restoring clears only the override; it does not alter the screen's playlist, schedule, layout, or published assignment.

Accounts and roles

RoleTypical access
AdminGlobal access, including users, groups/sites, publishing, remote commands, emergency overrides, credentials, and the audit log.
EditorCreate shared content and stage assignments on visible screens. An administrator can grant publishing for individual groups/sites or the global fleet.
ViewerInspect shared content and the screens in assigned groups/sites without making changes.

Administrators manage accounts {% if g.user.role == "admin" %} from Users. {% else %} from the Users page. {% endif %} Use an individual account for each person; passwords must contain at least 12 characters.

Screen groups also act as site scopes. A scoped account sees the union of screens in its assigned groups; ungrouped screens remain admin-only. Content, playlists, layouts, and schedules are shared across the CMS, so group scope limits fleet operations rather than asset ownership. Group publishers publish one authorized group at a time. Administrators can review publishes, emergencies, account changes, and credential rotations in the Audit log.

REST API and webhooks

Create a personal bearer credential from API tokens. Tokens use your current role and screen-group permissions and can be revoked at any time. The versioned API base is /api/v1.

curl -H "Authorization: Bearer $LIBRESIGNAGE_API_TOKEN" \
  {{ request.url_root.rstrip('/') }}/api/v1/screens

Download the machine-readable OpenAPI 3.1 contract for media, playlists, schedules, screens, health, publish, emergency, and webhook operations.

Administrators configure signed subscriptions from Webhooks. Run libresignage-monitor continuously to deliver and retry screen.offline, publish.completed, and emergency.activated events.

Troubleshooting checklist

{% for slug, question, answer in [ ("not-playing", "My change is not playing", "Look for a Draft changes badge. Confirm the correct source is staged for the screen, then publish. Compare the screen's published revision with the latest publish."), ("black-screen", "The player is blank or black", "Open Preview draft and inspect every playlist or layout zone. Confirm that content is not expired, a video is ready, and a web page permits iframe embedding. Check the dashboard for the player's cache or media error."), ("offline", "A screen is offline", "Check power and network access, confirm the display is using the correct permanent player URL, and review its last-contact time. Once connected, use Sync now if the published revision is stale."), ("cache", "Offline playlist is not ready", "Keep the player open while online. Check storage quota, service-worker state, and the latest cache error. Clear LibreSignage caches only when you can reconnect and download the full revision again."), ("schedule", "The wrong scheduled playlist is active", "Verify the screen uses Scheduled channel. Check timezone, date range, weekday, daypart, enabled state, and overlapping priorities. Remember that overnight ranges cross midnight."), ("web", "A web page or feed does not appear", "Test the URL from the player network. Web pages must allow iframe embedding. Feeds must be valid RSS or Atom and publicly reachable; live web content is unavailable offline.") ] %}

{{ answer }}
{% endfor %}
{% endblock %}