Skip to content

FullPageOS kiosk

Richard edited this page Sep 5, 2026 · 4 revisions

Based on a how-to by @romeo1984. Original discussion post is here

Instructions updated August 2026 for PiKaraoke 1.23.0. The hardware and OS versions listed under "Tested on" are from the original build and were last verified on hardware in October 2024.


FullPageOS is a Raspberry Pi image that boots straight into a full-screen Chromium session with no desktop. That makes it a good fit for a dedicated karaoke machine: the Pi powers on, PiKaraoke starts as a service, and the TV shows the splash screen with nothing else around it. Guests connect from their phones over your network.

This guide sets that up. The core setup is steps 1 to 8 and produces a working machine. Everything after that is optional and can be done in any order, or not at all.

What you need

Required:

  • A Raspberry Pi 4 or better
  • A microSD card, or a USB SSD if your library is large
  • An HDMI connection to a TV or monitor
  • A wired or wireless network connection
  • Somewhere to put your songs, if you are bringing an existing library

Optional, depending on how you want to use it:

  • A USB SSD and an SSD case or HAT if your library runs to tens or hundreds of gigabytes. A microSD card is fine for a smaller library or a download-as-you-go setup
  • An Argon case or similar, if you want a physical remote and fan control (see "Argon case: remote and fan")
  • An amplifier, mixer or stereo connected to the 3.5mm jack, if you do not want to use the TV's speakers (see "Audio through the headphone jack")

Skills assumed:

  • Installing an OS image onto a Pi
  • Basic Linux command line
  • Connecting over SSH
  • Editing files with nano or vi

Tested on:

  1. Raspberry Pi 4 Model B Rev 1.4
  2. PiKaraoke 1.23.0 (the release these instructions target)
  3. Debian 1:6.6.20-1+rpt1 (2024-03-07) (bookworm)
  4. Chromium 122.0.6261.89, built on Raspbian, running on Raspbian 12
  5. ffmpeg 5.1.6-0+deb12u1+rpt1
  6. yt-dlp, installed alongside PiKaraoke; 2026.07.04 or newer

Upgrading from an older version of this guide? Read "Notes for people upgrading" at the bottom first. PiKaraoke moved its config file and added a song database since this page was first written, and the service file below no longer runs as root.

Core setup

1. Install the OS

If you are booting from a USB SSD rather than a microSD card, switch the Pi's boot source from SD to USB first.

Write the FullPageOS image to your drive. Images are here: https://unofficialpi.org/Distros/FullPageOS/nightly/

Find the Pi's IP address on your network and connect to it over SSH. Your router's client list is the usual place to look.

2. Update the OS then reboot

sudo apt-get update && sudo apt-get upgrade -y
sudo reboot

3. Install PiKaraoke

Run the project's install script. It installs ffmpeg, a JavaScript runtime and PiKaraoke itself, so this one command covers everything:

curl -fsSL https://raw.githubusercontent.com/vicwomg/pikaraoke/master/build_scripts/install/install.sh | bash

The JavaScript runtime is not optional. yt-dlp needs one to solve YouTube's player challenges, and without it your searches will work but some downloads will silently fail. The script installs Deno unless you already have Node.js, in which case it uses that.

PiKaraoke ends up at ~/.local/bin/pikaraoke, which is the path the service file below uses. Re-running the same command later upgrades an existing installation.

If you would rather not pipe a script into your shell, do the same three things by hand. No virtual environment is needed — uv tool install isolates the package for you:

sudo apt-get install ffmpeg nodejs -y
curl -fsSL https://astral.sh/uv/install.sh | sh
~/.local/bin/uv tool install pikaraoke

The older version of this guide used a venv and pip install pikaraoke. That still works if you prefer it, but it needs the service file below to point at /home/pi/.venv/bin/pikaraoke instead, and upgrades become your job.

4. Create the systemd service

sudo nano /etc/systemd/system/pikaraoke.service

Replace pi with your username throughout if you created a different one:

[Unit]
Description=pikaraoke
After=network-online.target sound.target
Wants=network-online.target

[Service]
Type=simple
User=pi
Group=pi
WorkingDirectory=/home/pi
Environment="HOME=/home/pi"
ExecStart=/home/pi/.local/bin/pikaraoke --headless
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Notes on the choices in that file:

  • User=pi, not User=root. PiKaraoke keeps its config file, song database and generated cookie-signing secret in ~/.pikaraoke. Running as root hides all of that in /root/.pikaraoke, where your normal user cannot reach it, and makes every downloaded song root-owned. The one thing you lose is the Shutdown and Reboot buttons in the web UI, which need root; the physical power button still works. If you would rather keep those buttons, set User=root and Group=root back, and know that your database lives in /root/.pikaraoke.
  • Environment="HOME=/home/pi" so ~/.pikaraoke resolves. systemd does not always set HOME for a service user.
  • --headless is an alias for --hide-splash-screen; pikaraoke --help lists both. It stops PiKaraoke launching its own browser, because FullPageOS provides the browser.
  • --headless is the only option here, and that is deliberate. Almost everything else on the command line is a stored preference with a control on the Settings page — volume, video quality, folder browsing, keep-awake, the screensaver timeout and the rest. Set those in the web UI, where they persist and can be changed mid-party from a phone. Options in this file are re-applied on every boot, so a value you set here overwrites whatever you changed in the UI last time.
  • No --download-path. On a Raspberry Pi, songs default to ~/pikaraoke-songs, which with the HOME set above is /home/pi/pikaraoke-songs. The directory is created on first run. Add --download-path /mnt/songs (or wherever) only if your library lives somewhere else, such as a mounted SSD — that one is not a stored preference, so the service file is the only place it can go.

There is one trap worth knowing if you ignore that advice. PiKaraoke reads an absent on/off flag as "leave the stored value alone", not as "off" — so once, say, --high-quality has run once, it stays on, and deleting it from this file will not turn it off again. Only the Settings page can.

--admin-password is also best left out, for a different reason: see step 7.

Install the service:

sudo systemctl enable pikaraoke.service

Tip: after any change to the service file, reload systemd before restarting:

sudo systemctl --system daemon-reload

5. Point the kiosk at the splash page

sudo nano /boot/firmware/fullpageos.txt

Replace the default page with:

http://localhost:5555/splash?scale=2

?scale= sizes the splash screen overlays — logo, QR code, session name, up-next box and score screen — without touching the video, so the video still fills the panel. On a large TV the defaults look small; start around 1.5 to 2 and adjust to taste. It takes decimals. Leave the parameter off entirely for the default size.

If you are following an older copy of this guide, note that ?confirm=false no longer does anything. PiKaraoke tests the browser's autoplay policy itself and only shows a Confirm button if the test fails. The fix for that is a Chromium flag, in the next step.

6. Chromium flags

sudo nano ~/scripts/start_chromium_browser

Add to the flags=() section:

--autoplay-policy=no-user-gesture-required
--disable-session-crashed-bubble
--disable-infobars
--disable-dev-shm-usage

These are the flags PiKaraoke passes when it launches its own browser, and each one removes something that would otherwise end up on your TV:

  • --autoplay-policy=no-user-gesture-required is the important one. Without it Chromium blocks the first video from playing and the splash screen sits there showing a Confirm button that nobody can click on a TV with no mouse.
  • --disable-session-crashed-bubble stops the "Restore pages?" prompt. A karaoke machine gets switched off at the wall, so Chromium thinks it crashed nearly every time it starts.
  • --disable-infobars suppresses the notification strips Chromium shows across the top of the page.
  • --disable-dev-shm-usage avoids Chromium's shared-memory crashes on a Pi, where /dev/shm is small. PiKaraoke adds this one only on Raspberry Pi hardware.

Some of these may already be in the FullPageOS flags list; a duplicate is harmless.

If you used --force-device-scale-factor from an older version of this guide, remove it. The ?scale= parameter in step 5 does the same job without shrinking the video.

7. Set an admin password

PiKaraoke refuses host-only actions — player controls, song editing, shutdown — unless you are signed in as the admin. With no password set, everyone on your network is the admin, including whichever guest finds the reboot button.

Open the web UI, go to Settings, and set the password there. It takes effect immediately and persists across restarts.

Do not put --admin-password in the service file. It re-sets the password on every boot, which logs out every phone in the room, and it leaves the password in plain text in a file anyone with SSH can read.

The splash screen on the TV keeps working without signing in — it is meant to be public.

While you are on the Settings page, turn on Keep awake. It holds an idle inhibit so a long queue is not interrupted by the machine idling out, which matters here because there is no local player window to keep it busy. Set the volume and anything else you want at the same time; it all persists.

8. First boot

sudo reboot

The first startup after installing or upgrading takes a while. PiKaraoke scans your library into a database before the interface is ready. On a large library this is minutes rather than seconds, and it happens once — later boots load immediately and sync in the background. Do not assume it has hung.

At this point PiKaraoke should work. Try searching for a song and playing it. If search returns results but downloads fail, go back to step 3.

If the loading screen hangs, check the service over SSH:

sudo service pikaraoke status
journalctl -u pikaraoke.service

Audio comes out of the TV over HDMI by default. If that is what you want, you are finished. The rest of this page is optional.

Optional: audio through the headphone jack

Only needed if you are running audio into an amplifier, mixer or stereo rather than using the TV's speakers.

Select the headphone jack:

sudo raspi-config

Go to System Options -> Audio and pick the headphone entry, then finish and reboot.

Then set the system volume. Do this before your first party — if the system level is at maximum, turning PiKaraoke up will overdrive your speakers rather than get louder. 70% is a reasonable starting point:

amixer set Master 70%
sudo alsactl store

alsactl store writes the level so it survives a reboot. These tools come from alsa-utils, which is already installed.

If the output does not stick to the jack, ALSA is picking a different default card. Find the card number:

aplay -l

Look for the bcm2835 Headphones entry and note its card number — commonly 2, but it moves between OS versions and Pi models. Then pin it:

sudo nano /etc/asound.conf
defaults.ctl.card 2
defaults.pcm.card 2
defaults.pcm.device 0

Use /etc/asound.conf, not /usr/share/alsa/alsa.conf. The latter belongs to the alsa-lib package and your edits will be reverted the next time it updates.

PulseAudio is not needed for any of the above. Install it only if you want --enable-mic-passthrough, which uses pactl to find microphones:

sudo apt install pulseaudio -y

Optional: sharing your library over the network

Useful if you have an existing collection to copy across, or want to add files from another computer later. Downloaded songs go to /home/pi/pikaraoke-songs/ regardless.

If you want to keep formats in separate folders, create them and turn on Folder browsing in Settings so they appear as a Folders view on the Songs page:

mkdir -p /home/pi/pikaraoke-songs/CDG /home/pi/pikaraoke-songs/YT

They are owned by your user already, and force user below makes Samba write as that user, so no permission changes are needed.

sudo apt-get install samba samba-common-bin
sudo nano /etc/samba/smb.conf

Add:

	[karaoke]
	comment = Karaoke library
	path = /home/pi/pikaraoke-songs
	browseable = yes
	writeable = yes
	guest ok = yes
	force user = pi
	create mask = 0664
	directory mask = 0775

Set force user to whichever username you configured on the Pi.

guest ok = yes means no password, which is fine on a home network and wrong on any network you do not control. Drop that line to require a Samba account instead, created with sudo smbpasswd -a pi.

sudo service smbd restart
sudo service nmbd restart

From another computer, browse to \\<ip>\karaoke and sign in with your Pi username. PiKaraoke picks up new files in the background, so there is no need to restart it after a transfer.

If you only needed Samba for a one-off transfer, you can disable it afterwards:

sudo systemctl disable smbd.service
sudo systemctl disable nmbd.service

Optional: a custom loading screen

FullPageOS shows a background image while Chromium starts. To replace it, copy a PNG to /home/pi/loading.png and point the startup script at it:

sudo nano /opt/custompios/scripts/run_onepageos
feh --bg-scale /home/pi/loading.png
#feh --bg-center /opt/custompios/background.png

An example, contributed by @romeo1984:

loading

363741102-f77131ab-808d-481d-9d33-e375cf452075

Optional: Argon case remote and fan

Only applies if you are using an Argon case. It provides a fan controller and an infrared remote.

wget https://download.argon40.com/argon1.sh
sudo chmod 700 argon1.sh
sudo ./argon1.sh
sudo argon-config

Set the remote and fan to your preference.

Optional: hide the boot messages

For a machine that lives under a TV, the Linux boot text is worth suppressing:

sudo nano /boot/firmware/cmdline.txt

Add these to the existing options:

quiet loglevel=3 logo.nologo vt.global_cursor_default=0

quiet and loglevel=3 suppress the kernel messages, logo.nologo removes the raspberry logos, and the last one hides the blinking cursor that otherwise sits on screen until Chromium starts.

cmdline.txt must stay a single line. Append to the end of the existing line, separated by spaces — a stray newline stops the Pi booting.

Older versions of this guide used consoleblank=1, which blanks the console after a second rather than suppressing the messages. It works, but you see the text first.

Optional: disable unused services

Trims things a karaoke machine does not need. Some may not exist on your image, and the errors are harmless:

sudo systemctl disable lighttpd.service
sudo systemctl disable bluetooth.service
sudo systemctl disable x11vnc.service

Disabling x11vnc can leave the image without an autologin. This works around it:

sudo mkdir -p /var/lib/userconf-pi
sudo touch /var/lib/userconf-pi/autologin
sudo systemctl set-default graphical.target
sudo systemctl disable triggerhappy.service
sudo systemctl disable printing.service
sudo systemctl disable splashscreen.service

Notes for people upgrading from an older version of this guide

Upgrading PiKaraoke itself is one command, if you installed it as in step 3:

uv tool upgrade pikaraoke
sudo systemctl restart pikaraoke

Re-running the install script from step 3 does the same thing.

If you are moving off a venv installation, install with step 3, point ExecStart at /home/pi/.local/bin/pikaraoke, and delete ~/.venv once it works. Your songs and settings are untouched — they live in ~/pikaraoke-songs and ~/.pikaraoke, not in the virtual environment.

Your config moved. PiKaraoke keeps config.ini and its song database in ~/.pikaraoke now, not in the working directory. It migrates an old config.ini automatically the first time it starts, but only for the user it runs as.

If you are switching the service from User=root to User=pi, move your data across before the first restart, or you will start with an empty database and lose your stored preferences:

sudo systemctl stop pikaraoke
sudo cp -a /root/.pikaraoke /home/pi/.pikaraoke
sudo chown -R pi:pi /home/pi/.pikaraoke /home/pi/pikaraoke-songs
sudo systemctl start pikaraoke

Streaming format changed. The default is now HLS, which is easier on a Pi. If you hit playback trouble you did not have before, --streaming-format mp4 restores the old behaviour.

Other options worth knowing about. Most are on the Settings page rather than the service file: the screensaver timeout (default 300s, 0 disables it), the splash clock, and hiding the URL or the on-screen overlays for a cleaner TV.

One exception: --enable-mic-passthrough, if you want singers to hear themselves through the Pi rather than through a mixer, is experimental and deliberately not stored — it has to be passed in the service file each run. Run pikaraoke --help for the full list.

Clone this wiki locally