Build Your Own Aurora Deck

Run Aurora Deck on a dedicated display, self-host it on your own hardware, or just point any device at auroradeck.com. Pick the path that suits you.

Docker Compose

If you plan to use Google Calendar sync or the Google Photos screensaver, complete the Google Integration section below before deploying — those environment variables must be set for those features to work.

Start

docker compose -f aurora-deck-docker-compose.yaml up -d

Stop

docker compose -f aurora-deck-docker-compose.yaml down
Open Aurora Deck
# Aurora Deck — Self-Hosted Docker Compose
#
# Quick start:
#   1. Copy this file to your server
#   2. Review and update any Environment Variables you see fit
#   3. Run: docker compose -f aurora-deck-docker-compose.yaml up -d
#
# Full setup guide: https://auroradeck.com/build-your-own

services:
  # ── Local photo storage (fake GCS) ───────────────────────────────────────────
  # Provides a local GCS-compatible bucket for screensaver photo uploads.
  # Comment out this service (and GCS_BUCKET / GCS_ENDPOINT below) if you want
  # to use a real Google Cloud Storage bucket instead.
  fake-gcs-server:
    image: fsouza/fake-gcs-server
    container_name: aurora-deck-fake-gcs
    ports:
      - "4443:4443"
    command: ["-scheme", "http", "-port", "4443", "-backend", "filesystem", "-filesystem-root", "/storage"]
    volumes:
      - gcs-data:/storage
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:4443/storage/v1/b"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  postgres:
    image: postgres:17-alpine
    container_name: aurora-deck-postgres
    environment:
      POSTGRES_DB: aurora_deck_db
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres   # must match DB_PASSWORD in the aurora-deck service below
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  aurora-deck:
    image: us-east1-docker.pkg.dev/aurora-deck-483804/aurora-deck/aurora-deck:latest
    container_name: aurora-deck
    ports:
      - "8080:8080"
    environment:

      # ── Database ─────────────────────────────────────────────────────────────
      # Aurora Deck connects to the postgres service defined above.
      # DB_HOST must match the service name ("postgres").
      DB_HOST: postgres
      DB_PORT: 5432
      DB_NAME: aurora_deck_db
      DB_USERNAME: postgres
      DB_PASSWORD: postgres         # same value as POSTGRES_PASSWORD above

      # ── Application URLs ─────────────────────────────────────────────────────
      # The address where Aurora Deck is reachable from a browser.
      # For a home server use your LAN IP, e.g. http://192.168.1.100:8080
      APP_BASE_URL: http://localhost:8080        # URL of this server, used for OAuth redirects and API links
      APP_FRONTEND_URL: http://localhost:8080    # URL the browser uses to reach the app (usually same as APP_BASE_URL)

      # ── Security ─────────────────────────────────────────────────────────────
      # JWT_SECRET signs authentication tokens. Use a long random string (min 32 chars).
      # Generate one with: openssl rand -hex 32
      JWT_SECRET: f28559313e4523279dda7163807667c331632132f9eb481dd6480b64902c0433

      # OAUTH_STATE_SECRET_KEY protects the OAuth state parameter against CSRF.
      # Generate one with: openssl rand -hex 16
      OAUTH_STATE_SECRET_KEY: b59fff3fa51d0e582a42acf6fd22970ddc7221e5393036528ff1677d59d3d46c

      # ── Local Auth ───────────────────────────────────────────────────────────
      # Enables email/password login so you don't need a Google Cloud project.
      # Set to false only if you are using Google OAuth as the sole sign-in method.
      LOCAL_AUTH_ENABLED: "true"

      # VITE_LOCAL_AUTH_ENABLED is a frontend build-time flag that was embedded in
      # this image at build time (already set to true). It skips the marketing
      # landing page and sends unauthenticated visitors straight to /login.
      # If you build your own image, pass this at build time: --build-arg VITE_LOCAL_AUTH_ENABLED=true
      VITE_LOCAL_AUTH_ENABLED: "true"

      # ── Local Photo Storage (fake GCS) ───────────────────────────────────────
      # Points Aurora Deck at the local fake-gcs-server for photo uploads.
      # Comment these out if you remove the fake-gcs-server service above and
      # want to use a real GCS bucket instead.
      GCS_BUCKET: aurora-deck-local
      GCS_ENDPOINT: http://fake-gcs-server:4443

      # ── Local Network Photos (Samba / CIFS) ──────────────────────────────────
      # Enables SMB/CIFS network shares as a screensaver photo source.
      # Requires a Samba server on your local network (e.g. NAS, Windows share).
      LOCAL_NETWORK_PHOTOS_ENABLED: "true"

      # ── Optional: Weather ────────────────────────────────────────────────────
      # Sign up at https://openweathermap.org/api to get a free API key.
      # Leave blank to disable the weather widget.
      # OPENWEATHERMAP_API_KEY: <your-key>

      # ── Optional: Stock Ticker ───────────────────────────────────────────────
      # Sign up at https://finnhub.io to get a free API key.
      # Leave blank to disable the stock ticker widget.
      # FINNHUB_API_KEY: <your-key>

      # ── Optional: News Feed ──────────────────────────────────────────────────
      # Sign up at https://newsapi.org to get a free API key.
      # Leave blank to disable the news overlay.
      # NEWS_API_KEY: <your-key>

      # ── Optional: Google Integration (Calendar & Photos) ─────────────────────
      # Required only if you want Google Sign-In, Google Calendar sync, or
      # Google Photos as a screensaver source. See the Google Integration section
      # on the self-hosting page for step-by-step setup instructions.
      # GOOGLE_CLIENT_ID: <your-client-id>.apps.googleusercontent.com
      # GOOGLE_CLIENT_SECRET: <your-client-secret>
      # CALENDAR_TOKEN_KEY: <random-32-char-string>  # encrypts stored calendar tokens; generate with: openssl rand -hex 16
      # PHOTOS_TOKEN_KEY: <random-32-char-string>    # encrypts stored photos tokens; generate with: openssl rand -hex 16

    depends_on:
      postgres:
        condition: service_healthy
      fake-gcs-server:
        condition: service_healthy
    restart: unless-stopped

volumes:
  postgres-data:
  gcs-data:

Build Your Own Aurora Deck

Aurora Deck runs in any modern browser no special app required. Point a smartphone, tablet, laptop, or dedicated wall display at your self-hosted instance (or auroradeck.com) and you're up and running. The experience scales to whatever hardware you have available.

TouchscreenRecommended

Full experience — gesture scroll, on-screen keyboard, and tap navigation. Works in both landscape and portrait. A screen 15″ or larger gives the best readability as a wall display.

Android / TabletGreat option

Open Chrome or any browser, navigate to your Aurora Deck URL, and add it to your home screen. Works locally or via the internet — no app install needed.

Non-touchscreenLimited

Aurora Deck includes a Static Shareable Dashboard URL — perfect for devices with no touchscreen and no input devices. Any device with a web browser can display the dashboard without any interaction.

Setups I've personally tried

Hearth Displaymy daily driver

A dedicated smart display designed for the home. I run Aurora Deck on one at home full-time — it's a great fit. See the hearth-hacking guide on GitHub for setup details.

Raspberry Pi 3B+ / 4 / 5 + 7″ DSI displayguide below

All three models work. The 3B+ is usable but sluggish — the Pi 4 or 5 gives a much smoother experience. The config files below are specific to this hardware; your setup may differ.

Raspberry Pi 3B+ / 4 / 5 Setup

This is my personal experiment — the scripts and config files are specific to the hardware listed below. If your display, touchscreen, or compositor differs, you'll likely need to adapt them.

Parts list

Raspberry Pi 3 Model B+ (1GB)

Minimum viable option. Works but expect some sluggishness — good if you already have one on hand.

~$40
Raspberry Pi 4 Model B (1GB)

Recommended. Noticeably smoother than the 3B+ — the 1GB model is sufficient for Aurora Deck.

~$40
Raspberry Pi 5 (1GB)

Best performance. Overkill for Aurora Deck but very snappy. Worth it if you plan to use the display for anything else too.

~$50
SanDisk 32GB Ultra microSDHC

32 GB is plenty for Raspberry Pi OS, Docker, and the Aurora Deck images with room to spare.

~$20
7" Touchscreen IPS DSI Display (800×480)

Driver-free MIPI DSI interface — plug straight into the Pi's display connector, no HDMI adapter needed.

~$38
1

Flash Raspberry Pi OS with Imager

Download and open Raspberry Pi Imager. Choose Raspberry Pi OS (64-bit) — the Desktop edition, which includes Chromium pre-installed.

Before flashing, click the OS Customisation button (pencil icon) to configure everything in one place:

  • Set hostname to aurora-deck
  • Set a username (e.g. pi) and password
  • Enter your Wi-Fi SSID and password — or skip this if using Ethernet
  • Under Services, enable SSH with password authentication

Flash to your SD card, then eject and insert it into the Pi.

2

Boot and SSH into the Pi

Connect the Pi to power and your network, then wait about 60 seconds for the first boot to complete. SSH in from another machine using the hostname you set:

ssh pi@aurora-deck.local

Use the password you set in the Imager. If aurora-deck.local doesn't resolve, find the Pi's IP address in your router's DHCP client list and connect to that directly.

3

Configure Chromium, touch, and the on-screen keyboard

Raspberry Pi OS Bookworm uses the labwc Wayland compositor. The script below installs maliit-keyboard — a Wayland-native OSK that integrates with Chromium via the text-input protocol, so the keyboard appears automatically whenever you tap a text field. Run the script to configure everything in one shot, or follow the manual steps below.

configure-aurora-deck-display.sh
curl -fsSL https://auroradeck.com/configure-aurora-deck-display.sh -o configure-aurora-deck-display.sh
chmod +x configure-aurora-deck-display.sh
./configure-aurora-deck-display.sh

The script prompts for your Aurora Deck URL, installs maliit-keyboard, disables autotouch, and writes the autostart. Reboot when done.

Or configure manually:

1. Disable autotouch

Raspberry Pi OS ships a script called /usr/bin/autotouch that runs at every login and overwrites rc.xml with mouseEmulation="yes", which converts touch drags into mouse events and breaks native scrolling. Disable it with a user-level XDG override:

mkdir -p ~/.config/autostart
cat > ~/.config/autostart/autotouch.desktop << 'EOF'
[Desktop Entry]
Hidden=true
EOF

2. Autostart — touch, window rules, keyboard, and Chromium

The autostart uses libinput to detect the exact touch device name and active display output on every boot, then writes rc.xml fresh with mouseEmulation="no" for native scroll and maximizedDecoration=none to hide the title bar. maliit-server provides the on-screen keyboard via the Wayland text-input protocol — it appears automatically when a text field is tapped. The --enable-wayland-ime flag wires Chromium into it:

cat > ~/.config/labwc/autostart << 'EOF'
TOUCH=$(libinput list-devices | tr '\n' @ | sed 's/@@/\n/g' | grep "Capabilities:.*touch" | sed 's/Device:[ \t]*//' | cut -d @ -f 1)
DISPLAY_OUT=$(wlr-randr | grep '^\S' | cut -d ' ' -f 1)

if [ -n "$TOUCH" ] && [ -n "$DISPLAY_OUT" ]; then
  mkdir -p ~/.config/labwc
  cat > ~/.config/labwc/rc.xml << RCEOF
<?xml version="1.0"?>
<openbox_config xmlns="http://openbox.org/3.4/rc">
  <theme>
    <maximizedDecoration>none</maximizedDecoration>
    <keepBorder>no</keepBorder>
  </theme>
  <touch deviceName="$TOUCH"
         mapToOutput="$DISPLAY_OUT"
         mouseEmulation="no"/>
  <windowRules>
    <windowRule identifier="chromium"
                matchType="identifier"
                serverDecoration="yes">
      <action name="Maximize"/>
    </windowRule>
  </windowRules>
</openbox_config>
RCEOF
  labwc --reconfigure
fi

maliit-server &
chromium --app=https://your-aurora-deck-url \
  --start-maximized \
  --noerrdialogs --disable-infobars \
  --disable-session-crashed-bubble --no-first-run \
  --hide-scrollbars --touch-events=enabled \
  --ozone-platform=wayland --password-store=basic \
  --enable-wayland-ime &
EOF
4

Run the Aurora Deck setup script

Download the setup script to the Pi, make it executable, and run it. It will install Docker, download the docker-compose file, generate your secret keys, and register Aurora Deck as a systemd service that starts on every boot.

curl -fsSL https://auroradeck.com/setup-aurora-deck-pi.sh -o setup-aurora-deck-pi.sh
chmod +x setup-aurora-deck-pi.sh
./setup-aurora-deck-pi.sh

The script pauses before rebooting so you can optionally open ~/aurora-deck/docker-compose.yaml and add Google credentials if you need Calendar or Photos integration.

5

Pi reboots into Aurora Deck

After the reboot, the desktop loads and Chromium launches automatically in full-screen app mode pointing to your Aurora Deck URL. Aurora Deck and its database start via the systemd service before the browser opens. The first boot may take 30–60 seconds while Docker pulls images.

Setup script

#!/usr/bin/env bash
# Aurora Deck — Raspberry Pi Setup Script
#
# Installs Docker, downloads the Aurora Deck docker-compose file, generates
# secret keys, and registers a systemd service so Aurora Deck starts
# automatically on every boot.
#
# Run this on your Raspberry Pi after completing the initial setup steps:
#   bash setup-aurora-deck-pi.sh

set -euo pipefail

AURORA_DIR="$HOME/aurora-deck"
SERVICE_USER="${USER:-pi}"
COMPOSE_URL="https://auroradeck.com/aurora-deck-docker-compose.yaml"

# ── Helper ────────────────────────────────────────────────────────────────────
info()  { echo "[aurora] $*"; }
warn()  { echo "[aurora] WARNING: $*" >&2; }
abort() { echo "[aurora] ERROR: $*" >&2; exit 1; }

# ── Require root access ───────────────────────────────────────────────────────
if ! sudo -n true 2>/dev/null; then
  info "This script needs sudo for Docker installation and systemd setup."
  sudo -v
fi

# ── 1. Install Docker ─────────────────────────────────────────────────────────
if command -v docker &>/dev/null; then
  info "Docker is already installed ($(docker --version))."
else
  info "Installing Docker..."
  curl -fsSL https://get.docker.com | sh
  info "Adding $SERVICE_USER to the docker group..."
  sudo usermod -aG docker "$SERVICE_USER"
fi

# ── 2. Create aurora-deck directory ──────────────────────────────────────────
info "Creating $AURORA_DIR..."
mkdir -p "$AURORA_DIR"
cd "$AURORA_DIR"

# ── 3. Download docker-compose file ──────────────────────────────────────────
if [ -f docker-compose.yaml ]; then
  warn "docker-compose.yaml already exists — skipping download."
else
  info "Downloading docker-compose.yaml..."
  curl -fsSL "$COMPOSE_URL" -o docker-compose.yaml
fi

# ── 4. Generate secrets ───────────────────────────────────────────────────────
JWT_SECRET="$(openssl rand -hex 32)"
OAUTH_SECRET="$(openssl rand -hex 16)"

info "Generated secrets — updating docker-compose.yaml..."

# Replace the commented-out placeholders with real values
sed -i \
  "s|# JWT_SECRET: <CHANGE_ME>|JWT_SECRET: $JWT_SECRET|" \
  docker-compose.yaml

sed -i \
  "s|# OAUTH_STATE_SECRET_KEY: <CHANGE_ME>|OAUTH_STATE_SECRET_KEY: $OAUTH_SECRET|" \
  docker-compose.yaml

echo ""
echo "  JWT_SECRET and OAUTH_STATE_SECRET_KEY have been set automatically."
echo "  If you need Google Calendar or Photos, open the file and fill in:"
echo "    GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, CALENDAR_TOKEN_KEY, PHOTOS_TOKEN_KEY"
echo ""
echo "  File location: $AURORA_DIR/docker-compose.yaml"
echo ""
read -rp "Press Enter to continue (or Ctrl-C to edit the file first)..."

# ── 5. Register systemd service ───────────────────────────────────────────────
info "Registering aurora-deck systemd service..."
sudo tee /etc/systemd/system/aurora-deck.service > /dev/null << EOF
[Unit]
Description=Aurora Deck
Documentation=https://auroradeck.com/self-hosting
After=docker.service network-online.target
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=$AURORA_DIR
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
User=$SERVICE_USER
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# ── 6. Enable and start ───────────────────────────────────────────────────────
info "Enabling aurora-deck service..."
sudo systemctl daemon-reload
sudo systemctl enable aurora-deck

info "Pulling Docker images (this may take a few minutes)..."
docker compose -f "$AURORA_DIR/docker-compose.yaml" pull

info "Starting Aurora Deck..."
sudo systemctl start aurora-deck

echo ""
echo "  Aurora Deck is running at http://localhost:8080"
echo "  It will start automatically on every boot."
echo ""
echo "  Rebooting in 10 seconds to apply Docker group membership..."
echo "  (Press Ctrl-C to skip the reboot and reboot manually later.)"
echo ""
sleep 10
sudo reboot

License

Aurora Deck is distributed under the Polyform Shield License 1.0.0. Free to self-host for personal use. Commercial redistribution or building a competing service is prohibited without a commercial license.

© 2026 Aurora Deck. All Rights Reserved.

Back to Home