selfhost.directory

The index of self-hostable projects — ranked, categorized and served with live updates.
Own your data and stop giving it to big tech.

ScreenTinker logo

Self-host ScreenTinker

v3.0.3

Open-source digital signage CMS for self-hosted screens

ReleaseOpen SourceMIT
Updated11 hours ago
LanguageJavaScript
Setup difficultyModerate
MobileResponsive
Stars
239
CPU
1 vCPU (up to 25 displays)
RAM
1 GB RAM (up to 25 displays)
Storage
20 GB disk (up to 25 displays)
Ports
3001 (HTTP server), 3443 (HTTPS server (when SSL certs present))
Requires
SQLite
Docker
ghcr.io/screentinker/screentinker
Install with Docker Compose
ScreenTinker dashboard showing online displays with playlist assignments

What is ScreenTinker?

Should you self-host ScreenTinker?

ScreenTinker scores 53/100 on selfhost.directory (how scoring works) and ranks #4 of 7 in Digital Signage. It has 239 GitHub stars.

It shipped 10 stable releases in the past year. The latest, v3.0.3, came out on 25 October 2026. New versions land roughly every 2 days.

Setup is moderate: expect some configuration beyond a single command. An official Docker image is available. It is MIT-licensed and written mostly in JavaScript.

Its closest alternative on selfhost.directory is anthias (67/100, 3 706 stars). It scores higher overall, so compare the two before you pick. See ScreenTinker vs anthias side by side.

Features

  • Device groups
  • Meeting Room Signs
  • Multi-Zone Layouts
  • Playlist Management
  • Remote Control
  • Slide Editor
  • Video Walls

ScreenTinker README

How to install ScreenTinker

Install ScreenTinker with Docker Compose

Docker Engine and Docker Compose
Environment variables
Same as Docker plus STORAGE_PROVIDER, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, GO2RTC_URL, GO2RTC_API_TOKEN, GO2RTC_STUN_URLS, GO2RTC_TURN_URL

services: screentinker: image: ghcr.io/screentinker/screentinker:latest environment: SELF_HOSTED: "true" APP_URL: https://signage.example.com volumes: - /opt/screentinker/data:/data ports: - "3001:3001"

Optional: MinIO for S3 storage

minio: image: minio/minio command: server /data --console-address :9001 environment: MINIO_ROOT_USER: screentinker MINIO_ROOT_PASSWORD: changeme volumes: - /opt/minio/data:/data

Optional: go2rtc for live video

go2rtc: image: alexxit/go2rtc ports: - "1984:1984" - "8555:8555/tcp" - "8555:8555/udp"

Full compose example in docs/storage.md and docs/live-video.md

How to configure ScreenTinker

  • APP_URLnoneYour public URL (used for Stripe callbacks and invite-accept URLs in emailed invites)

    Your public URL (used for Stripe callbacks and invite-accept URLs in emailed invites)

    values: valid URL

  • AZURE_STORAGE_ACCOUNTnoneAzure storage account name

    Azure storage account name

    values: account name

  • AZURE_STORAGE_ACCOUNT_KEYnoneAzure storage account key

    Azure storage account key

    values: account key

  • AZURE_STORAGE_CONNECTION_STRINGnoneAzure storage connection string (or account + key below)

    Azure storage connection string (or account + key below)

    values: connection string

  • AZURE_STORAGE_CONTAINERnoneAzure storage container name

    Azure storage container name

    values: container name

  • DATA_DIRserver/Data directory for uploads, database, plugins, etc.

    Data directory for uploads, database, plugins, etc.

    values: path

  • DISABLE_HOMEPAGEfalseRedirect / to /app instead of serving the marketing landing page. For internal-only self-hosted deployments.

    Redirect / to /app instead of serving the marketing landing page. For internal-only self-hosted deployments.

    values: true, false

  • DISABLE_REGISTRATIONfalseBlock new account creation (including OAuth auto-signup). First-user setup on an empty DB is still allowed.

    Block new account creation (including OAuth auto-signup). First-user setup on an empty DB is still allowed.

    values: true, false

  • EMAIL_TRANSPORTgraphEmail transport: graph (Microsoft Graph) or smtp (any mail server)

    Email transport: graph (Microsoft Graph) or smtp (any mail server)

    values: graph, smtp

  • GO2RTC_API_TOKENnoneShared secret if you protect go2rtc's API; must match go2rtc.yaml.

    Shared secret if you protect go2rtc's API; must match go2rtc.yaml.

    values: secret string

  • GO2RTC_STUN_URLSstun:stun.l.google.com:19302Comma-separated STUN servers; a public STUN helps most NATs.

    Comma-separated STUN servers; a public STUN helps most NATs.

    values: comma-separated STUN URLs

  • GO2RTC_TURN_URLnoneTURN relay, only needed when UDP 8555 and host candidates are both unreachable.

    TURN relay, only needed when UDP 8555 and host candidates are both unreachable.

    values: TURN URL

  • GO2RTC_URLhttp://go2rtc:1984The sidecar's API, reached over the compose network only (never exposed to the browser).

    The sidecar's API, reached over the compose network only (never exposed to the browser).

    values: URL

  • GOOGLE_CLIENT_IDnoneOAuth 2.0 client ID from Google Cloud Console

    OAuth 2.0 client ID from Google Cloud Console

    values: client ID

  • GOOGLE_CLIENT_SECRETnoneOptional — PKCE means a public client works

    Optional — PKCE means a public client works

    values: client secret

  • GRAPH_CLIENT_IDnoneAzure AD app registration client ID

    Azure AD app registration client ID

    values: client ID

  • GRAPH_CLIENT_SECRETnoneAzure AD app registration client secret

    Azure AD app registration client secret

    values: client secret

  • GRAPH_SENDER_EMAILnoneMailbox to send from (must be a valid mailbox or alias in the tenant)

    Mailbox to send from (must be a valid mailbox or alias in the tenant)

    values: email address

  • GRAPH_SENDER_NAMEScreenTinkerDisplay name shown in the email From field (defaults to ScreenTinker)

    Display name shown in the email From field (defaults to ScreenTinker)

    values: any string

  • GRAPH_TENANT_IDnoneMicrosoft Azure AD tenant ID

    Microsoft Azure AD tenant ID

    values: tenant GUID

  • HIDE_BILLINGfalseHide the Subscription nav item + billing view; #/billing redirects to the dashboard (UI-only, opt-in)

    Hide the Subscription nav item + billing view; #/billing redirects to the dashboard (UI-only, opt-in)

    values: true, false

  • HTTPS_PORT3443HTTPS port (used when SSL certs are present)

    HTTPS port (used when SSL certs are present)

    values: any valid port

  • JWT_SECRETauto-generatedJWT signing key, also the source of the key that encrypts saved secrets. Auto-generated into certs/.jwt_secret if not set.

    JWT signing key, also the source of the key that encrypts saved secrets. Auto-generated into certs/.jwt_secret if not set.

    values: any string

  • LIVE_VIDEO_ENABLEDfalseMaster switch for live video. Also enable per workspace + per device.

    Master switch for live video. Also enable per workspace + per device.

    values: true, false

  • MAX_FILE_SIZE500MBLargest upload the server will accept. Bytes, or a suffix (2GB, 1500MB).

    Largest upload the server will accept. Bytes, or a suffix (2GB, 1500MB).

    values: bytes with optional suffix

  • MICROSOFT_CLIENT_IDnoneApplication (client) ID from the Azure portal

    Application (client) ID from the Azure portal

    values: client ID

  • MICROSOFT_CLIENT_SECRETnoneRequired in practice — register the redirect URI under the Web platform

    Required in practice — register the redirect URI under the Web platform

    values: client secret

  • MICROSOFT_TENANT_IDnoneYour tenant GUID — required. common/organizations are refused

    Your tenant GUID — required. common/organizations are refused

    values: tenant GUID

  • NODE_ENVnoneRuntime env (production enables Express production optimizations + stricter error handling)

    Runtime env (production enables Express production optimizations + stricter error handling)

    values: production, development

  • OIDC_PROVIDERSnoneComma-separated slugs for additional OIDC providers (e.g. okta,authentik)

    Comma-separated slugs for additional OIDC providers (e.g. okta,authentik)

    values: comma-separated slugs

  • OUTBOUND_ALLOW_HOSTSnoneHosts, *.suffixes, IPs or CIDRs that calendars, data sources, webhooks, OIDC and AI may reach on a private network

    Hosts, *.suffixes, IPs or CIDRs that calendars, data sources, webhooks, OIDC and AI may reach on a private network

    values: comma-separated hosts/CIDRs

  • OUTBOUND_ALLOW_PRIVATEfalseOpen every private-network range at once (single-tenant installs)

    Open every private-network range at once (single-tenant installs)

    values: true, false

  • PLUGINS_DIR$DATA_DIR/pluginsOperator-installed plugins. Survives git pull.

    Operator-installed plugins. Survives git pull.

    values: path

  • PLUGINS_ENABLEDunsetLoad the plugin system (widget types, data-source resolvers, optional routes). Off by default and invisible.

    Load the plugin system (widget types, data-source resolvers, optional routes). Off by default and invisible.

    values: true, false

  • PORT3001HTTP port

    HTTP port

    values: any valid port

  • RATE_LIMIT_BACKSTOP6000Global abuse backstop: requests per minute allowed for ONE credential

    Global abuse backstop: requests per minute allowed for ONE credential

    values: integer, 0 to disable

  • RATE_LIMIT_BACKSTOP_ANON6000Same backstop for requests with no credential: per minute, per client IP

    Same backstop for requests with no credential: per minute, per client IP

    values: integer, 0 to disable

  • S3_ACCESS_KEY_IDnoneS3 access key ID

    S3 access key ID

    values: access key

  • S3_BUCKETnoneS3 bucket name

    S3 bucket name

    values: bucket name

  • S3_ENDPOINTblank = AWSS3 endpoint (blank = AWS)

    S3 endpoint (blank = AWS)

    values: URL

  • S3_REGIONus-east-1S3 region (required by SDK even if store ignores it; R2 uses auto)

    S3 region (required by SDK even if store ignores it; R2 uses auto)

    values: region string

  • S3_SECRET_ACCESS_KEYnoneS3 secret access key

    S3 secret access key

    values: secret key

  • SELF_HOSTEDfalseFirst user gets all features unlocked

    First user gets all features unlocked

    values: true, false

  • SMTP_FROMfalls back to SMTP_USERFrom address — Name <addr@example.com> or addr@example.com

    From address — Name <addr@example.com> or addr@example.com

    values: email address

  • SMTP_HOSTrequiredMail server hostname (e.g. mail.example.com)

    Mail server hostname (e.g. mail.example.com)

    values: hostname

  • SMTP_PASSWORDnoneAuth password. Required if SMTP_USER is set

    Auth password. Required if SMTP_USER is set

    values: password

  • SMTP_PORTrequiredPort — 587 for STARTTLS, 465 for implicit TLS

    Port — 587 for STARTTLS, 465 for implicit TLS

    values: 587, 465, etc.

  • SMTP_SECUREfalsetrue = implicit TLS (465); false = STARTTLS (587)

    true = implicit TLS (465); false = STARTTLS (587)

    values: true, false

  • SMTP_USERnoneAuth username. Omit (with SMTP_PASSWORD) for an unauthenticated relay

    Auth username. Omit (with SMTP_PASSWORD) for an unauthenticated relay

    values: username

  • SSL_CERTserver/certs/cert.pemPath to SSL certificate

    Path to SSL certificate

    values: path

  • SSL_KEYserver/certs/key.pemPath to SSL private key

    Path to SSL private key

    values: path

  • STORAGE_PROVIDERlocalStorage provider: local, s3, or azure

    Storage provider: local, s3, or azure

    values: local, s3, azure

  • TALK_ENABLEDfalseMaster switch for Talk (voice intercom / PA). Then enable per organization under Admin → Organizations.

    Master switch for Talk (voice intercom / PA). Then enable per organization under Admin → Organizations.

    values: true, false

  • VIEW_ONLY_ENABLEDtrue when SELF_HOSTED=true, else falseView-only display links (/view/<token>). Each display is still off until a workspace admin turns it on.

    View-only display links (/view/<token>). Each display is still off until a workspace admin turns it on.

    values: true, false

ScreenTinker releases & version history

FAQ

Do my displays keep playing if the internet goes down?

Yes. ScreenTinker players cache their content locally and keep playing during an internet or server outage, then sync automatically once the connection returns.

Are there ready-made templates?

Yes. The template library installs slide and code templates from a catalog where every template is cryptographically signed so the server can verify it hasn't been tampered with.

Can I show live data from Google Sheets or an API?

Yes, on every plan including Free. Connect a Google Sheet by pasting its share link, or point at any REST/JSON API with a bearer token, API key or basic auth.

What can I put on my screens?

Images, video, PDFs, slides and templates, live data from Google Sheets and APIs, playlists, multi-zone layouts, and live widgets like clocks, weather, RSS tickers, countdowns, QR codes, web pages, and scrolling directories.

What's the difference between self-hosted and cloud digital signage?

With cloud, the vendor hosts everything and you just sign in. With self-hosting, you deploy on your own server so your content and device data never leave your network, with no recurring SaaS fees.

Does ScreenTinker run on BrightSign players?

Yes. A BrightSign runs the same web player the browser does, so it gets the same playlists, layouts, scheduling and remote control as every other screen.

Does ScreenTinker work on Android TV and Fire TV?

Yes. Install the free APK on any Android TV box or Amazon Fire TV Stick to turn it into a managed signage display with kiosk mode and live remote control.

Can I run digital signage on a Raspberry Pi?

Yes. A Raspberry Pi 4 or newer makes an excellent low-cost signage player. The one-line installer sets up kiosk mode, auto-start, and pairing.

Does audience counting record people?

No. The player counts faces turned toward the screen and discards each frame immediately. No image or video is stored or sent, nobody is recognized.

Can I show a Power BI dashboard on a TV screen?

Yes. An organization admin adds your Power BI service principal once, and editors pick a report. Screens get a view-only embed token that expires within the hour.

Can digital signage show emergency alerts?

Yes. Subscribe to public CAP feeds like US National Weather Service or MeteoAlarm, or connect Alertus, InformaCast or any CAP 1.2 system. Alerts take over screens instantly.

Does ScreenTinker support single sign-on with SAML or OIDC?

Yes. Each organization can connect its own identity provider over SAML 2.0 or OpenID Connect, including Entra ID, Okta, Google Workspace, ADFS and OneLogin.

How long is the free trial, and what does it include?

14 days of the Pro plan on the hosted service: up to 15 screens and 20 GB of storage, with every integration. No credit card needed.

Is there free digital signage software?

Yes. ScreenTinker is free and open source (MIT licensed). The free cloud plan runs 1 display with 500 MB of storage, and if you self-host there's no per-screen fee at all.

More in Digital Signage

Rate this project

Click to rate — no account needed.

0 comments

Posting as guest
Loading comments…