Greg Vedders
  • About
  • Tags
  • Posts

Introducing Signage Suite — Self-Hosted Wall Displays in PHP

An open-source stack for home and SOC wall displays — rotation, admin UI, Splunk panels, and kiosk setup without a database.

posts
June 21, 2026 • 5 min read • 1020 words

I put a lot of effort into wall displays.

At work, I wrote about building a stable SOC monitoring wall — Splunk reports, Grafana, static pages, four screens, and a lot of time spent making Chrome behave on Wayland.

At home, I wanted the same thing on the TV in the living room: weather, lake conditions, calendar, photos, RSS headlines, traffic, sports scores. Useful information, always on, no remote required.

Commercial signage platforms exist. I tried the DIY route first — individual PHP pages, one per board, tuned for 1920×1080. That worked. Then I kept adding boards, and the gaps became obvious.

There was no shared admin. No rotation shell I trusted. API keys lived in PHP constants scattered across files. Splunk and Grafana needed special handling so tokens never reached the browser. Operators could not update slides without SSH.

So I packaged everything into one project and put it on GitHub: signage-suite.


What it is

Signage Suite is a collection of seventeen self-contained PHP boards — weather, lake buoy data, air quality, calendar, photo rotator, custom slides, RSS, local YouTube playback, Splunk REST panels, Grafana iframes, homelab status, and more. They share a dark-navy/amber design language and a common caching layer.

Drop the files in a web directory with PHP 8+ and php-curl. Each board caches API responses under ./cache/ and falls back to stale data when an upstream API flakes, so a bad NWS response does not blank the wall.

Configuration lives in admin.php, not in the board files themselves. Settings save to config/settings.json. The PHP pages stay read-only on disk, which keeps upgrades simple: pull the repo, re-run the setup script, your playlists and API keys stay put.


The parts that matter

board.php — the rotation shell

Each display points at board.php?screen=main (or garage, soc, whatever you define). The shell crossfades between playlist entries, preloads the next page in a hidden iframe, skips hung pages after a timeout, and keeps the weather alert ticker visible across transitions.

Playlists, dwell times, hour windows, weighted rotation, and per-display HDMI-CEC off/on schedules are all edited in the admin UI. No file edits on the Pi after initial kiosk setup.

admin.php — one frontend for everything

Super admins configure API keys, rotation, users, and security. Operators get a narrower view: slides, photos, RSS feeds, videos, Grafana URLs, Splunk panels — scoped to the one display they are assigned.

Accounts live in config/users.json. SSO via Entra ID or Authentik is optional. Board saves use file locking so two people editing different boards at the same time do not clobber each other.

Splunk without a login wall

splunk.php runs oneshot searches server-side against the Splunk REST API. The auth token never reaches the kiosk browser. Panels render as big numbers, bar lists, and trend charts in the same style as the rest of the wall.

splunkdash.php wraps published Dashboard Studio dashboards for Splunk 10.x — the pixel-perfect dashboard view when you have already published it inside Splunk.

This is the pattern I wish I had leaned on harder in the SOC wall build: fetch server-side, display static HTML, instead of fighting iframe auth and session timeouts.

Kiosk setup that stays hands-off

Two scripts cover the boring infrastructure work:

# Server (Apache/nginx, PHP, permissions, cache dirs)
sudo bash setup-server.sh --with-video-cron

# Each Pi or kiosk PC
sudo bash setup-kiosk.sh "http://your-server/boards/board.php?screen=main"

The kiosk script installs cage + Chromium, boots straight into the rotation, restarts on crash, and optionally syncs HDMI-CEC power with the off/on hours you set in admin. After that, content changes happen on the server. The Pi mostly just needs apt full-upgrade now and then.


Deliberately boring infrastructure

No database. Settings, users, audit logs, and kiosk heartbeats are JSON files on disk with lock files during writes. That is enough for a home lab or a small SOC team — dozens of users, not thousands.

No framework. Plain PHP, a handful of shared libs, Apache or nginx. Video downloads use yt-dlp locally so YouTube embeds never run on the wall (no ads, no bot-check embed failures on a headless Pi).

Security defaults assume you care about this stuff:

  • config/, cache/, slides/, and photos/ are blocked from direct HTTP access (with explicit Apache/nginx config — Ubuntu’s default AllowOverride None will silently leave your settings downloadable if you skip this step)
  • RSS and ICS fetches block private IPs unless you explicitly allow them
  • Admin sessions use CSRF protection, idle timeout, and lockout after failed logins
  • Outbound fetch policy and audit logging are configurable under Security

Put HTTPS in front if admin is reachable from the internet. A Cloudflare Tunnel works fine here — same idea as the rest of my homelab.


Home vs SOC

The same codebase covers both use cases.

Home: weather radar, Lake Michigan buoy + NWS alerts, Grand Haven webcam embed, photo golden-hour conditions, ICS calendar with trash/recycling cadence, Detroit sports scores, TomTom traffic tiles, RSS from Krebs or Petapixel, local video playback.

SOC / homelab: SignalTrace threat stats, Proxmox + AdGuard homelab panel, Grafana dashboard iframes, Splunk REST panels, Splunk published dashboards.

You pick the boards, build playlists per screen, and point each display at its URL. Ten screens hitting the same server do not multiply API usage — the file cache is shared.


Quick start

Clone the repo, run the server script, open admin, create your super-admin account with the one-time setup key, paste your API keys, build a rotation, point a browser at board.php.

Full board-by-board docs live in the README. The repo is public — issues and PRs welcome if you try it and hit something weird.


Why open-source it

This started as scripts on a wall in my house. It grew because wall displays are a solved problem until they are not — until you need SSO for the person updating slides, or Splunk tokens kept out of the browser, or a Pi that reboots itself at 4 AM and keeps rotating without a keyboard attached.

I wrote the SOC wall post from the ops side. Signage Suite is the software side of the same obsession: information that stays visible, stays stable, and stays maintainable.

Repo: github.com/veddegre/signage-suite

Share this post
← Older Rebuilding gregvedders.com Without a Hugo Theme Newer → Teaching Git: What I Covered in Class

About

Greg Vedders writes about information security, troubleshooting, photography, and the occasional unexpected fix.

Recent Posts

  • Teaching Git: What I Covered in Class
  • Rebuilding gregvedders.com Without a Hugo Theme
  • Hardening a Public Honeypot Server
  • What Happens When You Leave a Door Slightly Open?

Tags

Digital Signage Self-Hosting PHP Monitoring Linux Splunk SOC

Related Posts

  • Building a Stable SOC Monitoring Wall with Open Tools
  • Rebuilding gregvedders.com Without a Hugo Theme
  • Hardening a Public Honeypot Server
  • What Happens When You Leave a Door Slightly Open?
© Greg Vedders 2026