[!IMPORTANT] This project is not affiliated with Immich
[!WARNING] Like the Immich project, this project is currently in beta and may experience breaking changes.
Immich Kiosk is a lightweight slideshow for running on kiosk devices and browsers that uses Immich as a data source.
Image shot by Damon Golding
You have a two Raspberry Pi's. One hooked up to a LCD screen and the other you connect to your TV. You install a fullscreen browser OS or service on them (I use DietPi).
You want the pi connected to the LCD screen to only show images from your recent holiday, which are stored in a album on Immich. It's an older pi so you want to disable CSS transitions, also we don't want to display the time of the image.
Using this URL http://{URL}?album={ALBUM_ID}&transtion=none&show_time=false
would achieve what we want.
On the pi connected to the TV you want to display a random image from your library but only images of two specific people. We want the image to cover the whole screen (knowing some cropping will happen) and we want to use the fade transition.
Using this URL http://{URL}?image_fit=cover&transition=fade&person=PERSON_1_ID&person=PERSON_2_ID
would achieve what we want.
Fanyang Meng created a digital picture frame using a Raspberry Pi Zero 2 W and Kiosk. You can read the blog post about the process here.
There are two main ways to install Kiosk.
Add the kiosk service to your Immich docker-compose.yaml
file.
Follow from step 3 in option 2 to create the config.yaml
file.
Create a directory of your choice (e.g. ./immich-kiosk) to hold the docker-compose.yaml
and config file.
mkdir ./immich-kiosk
cd ./immich-kiosk
Download docker-compose.yaml
.
wget -O docker-compose.yaml https://raw.githubusercontent.com/damongolding/immich-kiosk/refs/heads/main/docker-compose.yaml
Set TZ
to a TZ identifier
from this list
Create the config.yaml
file.
You may use environment variables if preferred.
Create config dir and download config.yaml
file.
mkdir ./config
wget -O ./config/config.yaml https://raw.githubusercontent.com/damongolding/immich-kiosk/refs/heads/main/config.example.yaml
Modify config.yaml
file.
Only the immich_url
and immich_api_key
are required fields.
Start the container
docker compose up -d
[!TIP] Use something like
systemd
to automate starting the Kiosk binary.
Download the binary file Vist the latest release and scroll to the assets at the bottom of the release notes. Download the archive file that matches your machines architecture and unarchive.
Create config dir and download config.yaml
file.
mkdir ./config
wget -O ./config/config.yaml url
Modify config.yaml
file.
Only the immich_url
and immich_api_key
are required fields.
Start Kiosk
./kiosk
[!NOTE] You can use both a yaml file and environment variables but environment variables will overwrite settings from the yaml file Set
TZ
to aTZ identifier
from this list
config.yaml
config fileservices:
immich-kiosk:
image: damongolding/immich-kiosk:latest
container_name: immich-kiosk
environment:
TZ: "Europe/London"
volumes:
# Mount the directory with config.yaml inside
- ./config:/config
restart: always
ports:
- 3000:3000
[!TIP] You do not need to specifiy all of these. If you want the default behaviour/value you can omit it from you compose file.
services:
immich-kiosk:
image: damongolding/immich-kiosk:latest
container_name: immich-kiosk
environment:
TZ: "Europe/London"
# Required settings
KIOSK_IMMICH_API_KEY: "****"
KIOSK_IMMICH_URL: "****"
# Clock
KIOSK_SHOW_TIME: false
KIOSK_TIME_FORMAT: 24
KIOSK_SHOW_DATE: false
KIOSK_DATE_FORMAT: YYYY/MM/DD
# Kiosk behaviour
KIOSK_REFRESH: 60
KIOSK_DISABLE_SCREENSAVER: false
# Asset sources
KIOSK_SHOW_ARCHIVED: false
KIOSK_ALBUM: "ALBUM_ID,ALBUM_ID,ALBUM_ID"
KIOSK_PERSON: "PERSON_ID,PERSON_ID,PERSON_ID"
# UI
KIOSK_DISABLE_UI: false
KIOSK_FRAMELESS: false
KIOSK_HIDE_CURSOR: false
KIOSK_FONT_SIZE: 100
KIOSK_BACKGROUND_BLUR: true
KIOSK_THEME: fade
KIOSK_LAYOUT: single
# Sleep mode
# KIOSK_SLEEP_START: 22
# KIOSK_SLEEP_END: 7
# Transistion options
KIOSK_TRANSITION: none
KIOSK_FADE_TRANSITION_DURATION: 1
KIOSK_CROSS_FADE_TRANSITION_DURATION: 1
# Image display settings
KIOSK_SHOW_PROGRESS: false
KIOSK_IMAGE_FIT: contain
KIOSK_IMAGE_EFFECT: smart-zoom
KIOSK_IMAGE_EFFECT_AMOUNT: 120
KIOSK_USE_ORIGINAL_IMAGE: false
# Image metadata
KIOSK_SHOW_IMAGE_TIME: false
KIOSK_IMAGE_TIME_FORMAT: 24
KIOSK_SHOW_IMAGE_DATE: false
KIOSK_IMAGE_DATE_FORMAT: YYYY-MM-DD
KIOSK_SHOW_IMAGE_DESCRIPTION: false
KIOSK_SHOW_IMAGE_EXIF: false
KIOSK_SHOW_IMAGE_LOCATION: false
KIOSK_HIDE_COUNTRIES: "HIDDEN_COUNTRY,HIDDEN_COUNTRY"
KIOSK_SHOW_IMAGE_ID: false
# Kiosk settings
KIOSK_WATCH_CONFIG: false
KIOSK_FETCHED_ASSETS_SIZE: 1000
KIOSK_HTTP_TIMEOUT: 20
KIOSK_PASSWORD: ""
KIOSK_CACHE: true
KIOSK_PREFETCH: true
KIOSK_ASSET_WEIGHTING: true
KIOSK_PORT: 3000
ports:
- 3000:3000
restart: always
See the file config.example.yaml for an example config file
yaml | ENV | Value | Default | Description |
---|---|---|---|---|
immich_url | KIOSK_IMMICH_URL | string | "" | The URL of your Immich server. MUST include a port if one is needed e.g. http://192.168.1.123:2283 . |
immich_api_key | KIOSK_IMMICH_API_KEY | string | "" | The API for your Immich server. |
show_time | KIOSK_SHOW_TIME | bool | false | Display clock. |
time_format | KIOSK_TIME_FORMAT | 12 | 24 | 24 | Display clock time in either 12 hour or 24 hour format. Can either be 12 or 24. |
show_date | KIOSK_SHOW_DATE | bool | false | Display the date. |
date_format | KIOSK_DATE_FORMAT | string | DD/MM/YYYY | The format of the date. default is day/month/year. See date format for more information. |
refresh | KIOSK_REFRESH | int | 60 | The amount in seconds a image will be displayed for. |
disable_screensaver | KIOSK_DISABLE_SCREENSAVER | bool | false | Ask browser to request a lock that prevents device screens from dimming or locking. NOTE: I haven't been able to get this to work constantly on IOS. |
show_archived | KIOSK_SHOW_ARCHIVED | bool | false | Allow assets marked as archived to be displayed. |
album | KIOSK_ALBUM | []string | [] | The ID(s) of a specific album or albums you want to display. See Albums for more information. |
person | KIOSK_PERSON | []string | [] | The ID(s) of a specific person or people you want to display. See People for more information. |
disable_ui | KIOSK_DISABLE_UI | bool | false | A shortcut to set show_time, show_date, show_image_time and image_date_format to false. |
frameless | KIOSK_FRAMELESS | bool | false | Remove borders and rounded corners on images. |
hide_cursor | KIOSK_HIDE_CURSOR | bool | false | Hide cursor/mouse via CSS. |
font_size | KIOSK_FONT_SIZE | int | 100 | The base font size for Kiosk. Default is 100% (16px). DO NOT include the % character. |
background_blur | KIOSK_BACKGROUND_BLUR | bool | true | Display a blurred version of the image as a background. |
theme | KIOSK_THEME | fade | solid | fade | Which theme to use. See Themes for more information. |
layout | KIOSK_LAYOUT | single | splitview | single | Which layout to use. See Layouts for more information. |
sleep_start | KIOSK_SLEEP_START | string | "" | Time (in 24hr format) to start sleep mode. See Sleep mode for more information. |
sleep_end | KIOSK_SLEEP_END | string | "" | Time (in 24hr format) to end sleep mode. See Sleep mode for more information. |
custom_css | N/A | bool | true | Allow custom CSS to be used. See Custom CSS for more information. |
transition | KIOSK_TRANSITION | none | fade | cross-fade | none | Which transition to use when changing images. |
fade_transition_duration | KIOSK_FADE_TRANSITION_DURATION | float | 1 | The duration of the fade (in seconds) transition. |
cross_fade_transition_duration | KIOSK_CROSS_FADE_TRANSITION_DURATION | float | 1 | The duration of the cross-fade (in seconds) transition. |
show_progress | KIOSK_SHOW_PROGRESS | bool | false | Display a progress bar for when image will refresh. |
image_fit | KIOSK_IMAGE_FIT | cover | contain | none | contain | How your image will fit on the screen. Default is contain. See Image fit for more info. |
image_effect | KIOSK_IMAGE_EFFECT | zoom | smart-zoom | "" | Add an effect to images. |
image_effect_amount | KIOSK_IMAGE_EFFECT_AMOUNT | int | 120 | Set the intensity of the image effect. Use a number between 100 (minimum) and higher, without the % symbol. |
use_original_image | KIOSK_USE_ORIGINAL_IMAGE | bool | false | Use the original image. NOTE: This will mostly likely cause kiosk to use more CPU and RAM resources. |
show_image_time | KIOSK_SHOW_IMAGE_TIME | bool | false | Display image time from METADATA (if available). |
image_time_format | KIOSK_IMAGE_TIME_FORMAT | 12 | 24 | 24 | Display image time in either 12 hour or 24 hour format. Can either be 12 or 24. |
show_image_date | KIOSK_SHOW_IMAGE_DATE | bool | false | Display the image date from METADATA (if available). |
image_date_format | KIOSK_IMAGE_DATE_FORMAT | string | DD/MM/YYYY | The format of the image date. default is day/month/year. See date format for more information. |
show_image_description | KIOSK_SHOW_IMAGE_DESCRIPTION | bool | false | Display image description from METADATA (if available). |
show_image_exif | KIOSK_SHOW_IMAGE_EXIF | bool | false | Display image Fnumber, Shutter speed, focal length, ISO from METADATA (if available). |
show_image_location | KIOSK_SHOW_IMAGE_LOCATION | bool | false | Display the image location from METADATA (if available). |
hide_countries | KIOSK_HIDE_COUNTRIES | []string | [] | List of countries to hide from image_location |
weather | N/A | []WeatherLocation | [] | Display the current weather. See weather for more information. |
The below options are NOT configurable through URL params. In the config.yaml
file they sit under kiosk
(demo below and in example config.yaml
)
immich_url: "****"
immich_api_key: "****"
// all your other config options
// 👇 Additional options
kiosk:
password: ""
cache: true
prefetch: true
yaml | ENV | Value | Default | Description |
---|---|---|---|---|
port | KIOSK_PORT | int | 3000 | Which port Kiosk should use. NOTE: that is port will need to be reflected in your compose file, e.g. KIOSK_PORT:HOST_PORT |
watch_config | KIOSK_WATCH_CONFIG | bool | false | Should Kiosk watch config.yaml file for changes. Reloads all connect clients if a change is detected. |
fetched_assets_size | KIOSK_FETCHED_ASSETS_SIZE | int | 1000 | The number of assets (data) requested from Immich per api call. min=1 max=1000. |
http_timeout | KIOSK_HTTP_TIMEOUT | int | 20 | The number of seconds before an http request will time out. |
password | KIOSK_PASSWORD | string | "" | Please see FAQs for more info. If set, requests MUST contain the password in the GET parameters, e.g. http://192.168.0.123:3000?password=PASSWORD . |
cache | KIOSK_CACHE | bool | true | Cache selective Immich api calls to reduce unnecessary calls. |
prefetch | KIOSK_PREFETCH | bool | true | Pre-fetch assets in the background, so images load much quicker when refresh timer ends. |
asset_weighting | KIOSK_ASSET_WEIGHTING | bool | true | Balances asset selection when multiple sources are used, e.g. multiple people and albums. When enabled, sources with fewer assets will show less often. |
You can configure settings for individual devices through the URL. This feature is particularly useful when you need different settings for different devices, especially if the only input option available is a URL, such as with kiosk devices.
example:
https://{URL}?refresh=120&background_blur=false&transition=none
The above would set refresh to 120 seconds (2 minutes), turn off the background blurred image and remove all transitions for this device/browser.
http://192.168.86.123:2283/albums/a04175f4-97bb-4d97-8d49-3700263043e5
.albums/
, so in this example it would be a04175f4-97bb-4d97-8d49-3700263043e5
.When you specify multiple albums and/or people, Immich Kiosk creates a pool of all the requested person and album IDs. For each image refresh, Kiosk randomly selects one ID from this pool and fetches an image associated with that album or person.
There are three ways you can set multiple albums:
[!NOTE] These methods are applied in order of precedence. URL queries take highest priority, followed by environment variables, and finally the config.yaml file. Each subsequent method overwrites the settings from the previous ones.
via config.yaml file
album:
- ALBUM_ID
- ALBUM_ID
via ENV in your docker-compose file use a ,
to separate IDs
environment:
KIOSK_ALBUM: "ALBUM_ID,ALBUM_ID,ALBUM_ID"
via url quires:
http://{URL}?album=ALBUM_ID&album=ALBUM_ID&album=ALBUM_ID
all
Will use all albums.
e.g. http://{URL}?album=all
shared
Will use only shared albums.
e.g. http://{URL}?album=shared
favorites
or favourites
Will use only favourited assets.
e.g. http://{URL}?album=favorites
or http://{URL}?album=favourites
http://192.168.86.123:2283/people/a04175f4-97bb-4d97-8d49-3700263043e5
.people/
, so in this example it would be a04175f4-97bb-4d97-8d49-3700263043e5
.When you specify multiple people and/or albums, Immich Kiosk creates a pool of all the requested album and person IDs. For each image refresh, Kiosk randomly selects one ID from this pool and fetches an image associated with that person or album.
There are three ways you can set multiple people ID's:
[!NOTE] These methods are applied in order of precedence. URL queries take highest priority, followed by environment variables, and finally the config.yaml file. Each subsequent method overwrites the settings from the previous ones.
person:
- PERSON_ID
- PERSON_ID
,
to separate IDsenvironment:
KIOSK_PERSON: "PERSON_ID,PERSON_ID,PERSON_ID"
http://{URL}?person=PERSON_ID&person=PERSON_ID&person=PERSON_ID
This controls how the image will fit on your screen. The options are:
The image keeps its aspect ratio, but is resized to fit the whole screen. If the image is smaller than your screen, there will be some fuzzyness to your image.
The image will cover the whole screen. To achieve this the image will mostly likely have some clipping/cropping and if the image is smaller than your screen, there will be some fuzzyness to your image.
The image is centered and displayed "as is". If the image is larger than your screen it will be scaled down to fit your screen.
[!NOTE] Image fit is set to
cover
automatically when this effect is used.
This effect zooms in or out to add movement to your images, with the center of the image as the focal point.
[!NOTE] Image fit is set to
cover
automatically when this effect is used. If the image has multiple faces, Kiosk calculates the center of all faces to use as the focal point.
Smart zoom works like the regular zoom but focuses on faces and includes both zooming and panning.
[!TIP] To achieve a "Ken Burns" style effect change the
image_effect_amount
to somewhere between 200-400.
[!NOTE] Some characters, such as
/
and:
are not allowed in URL params. So while you can set the date layout via URL params, I would suggest setting them viaconfig.yaml
or environment variables.
You can use the below values to create your preferred date layout.
Value | Example output |
---|---|
YYYY | 2024 |
YY | 24 |
MMMM | August |
MMM | Aug |
MM | 08 |
M | 8 |
DDDD | Monday |
DDD | Mon |
DD | 04 |
D | 4 |
These examples assume that today's date is the 22nd of August 2024.
Soft gradient background for the clock and image metadata.
Solid background for the clock and image metadata.
Display one image.
[!NOTE] Kiosk attempts to determine the orientation of each image. However, if an image lacks EXIF data, it may be displayed in an incorrect orientation (e.g., a portrait image shown in landscape format).
When a portrait image is fetched, Kiosk automatically retrieves a second portrait image* and displays them side by side vertically. Landscape and square images are displayed individually.
* If Kiosk is unable to retrieve a second unique image, the first image will be displayed individually.
[!NOTE] Kiosk attempts to determine the orientation of each image. However, if an image lacks EXIF data, it may be displayed in an incorrect orientation (e.g., a portrait image shown in landscape format).
When a landscape image is fetched, Kiosk automatically retrieves a second landscape image* and displays them stacked horizontally. portrait and square images are displayed individually.
* If Kiosk is unable to retrieve a second unique image, the first image will be displayed individually.
Setting both sleep_start
and sleep_end
using the 24 hour format will enable sleep mode.
Kiosk will display a black screen and can optionally shows a faint clock if show_time
or show_date
and enabled.
sleep_start=22
and sleep_end=7
will enable sleep mode from 22:00 (10pm) to 07:00 (7am).sleep_start=1332
and sleep_end=1508
will enable sleep mode from 13:32 (1:32pm) to 15:08 (3:08pm).[!NOTE] Custom CSS is applied after all other styles, allowing you to override any default styles.
[!WARNING] Be cautious when using custom CSS, as it may interfere with the normal functioning of Kiosk if not implemented correctly. While I'm happy to help with general Kiosk issues, I may not be able to provide specific support for problems related to custom CSS implementations.
Custom CSS allows you to further customize Kiosk's appearance beyond the built-in themes and settings.
To use custom CSS:
custom.css
in the same directory as your docker-compose.yml
file.custom.css
file in your container by adding the following line to the volumes
section of your docker-compose.yml
:
volumes:
- ./config:/config
- ./custom.css:/custom.css
[!TIP] Ensure that the path to your
custom.css
file is relative to yourdocker-compose.yml
file.
There is a custom.example.css
file included that contains all the CSS selectors used by Kiosk, which you can use as a reference for your customizations.
The custom CSS will apply to all devices connected to Kiosk by default.
To disable custom CSS for a specific device, add custom_css=false
to the URL parameters e.g. http://{URL}?custom_css=false
[!NOTE] To use the weather feature, you’ll need an API key from OpenWeatherMap.
[!TIP] OpenWeatherMap limits API usage to 60 calls per hour. Since the kiosk refreshes weather data every 10 minutes, you can monitor up to 6 locations with a single API key.
You can configure multiple locations in the config.yaml
file, and choose which one to display using the URL query weather=NAME
.
Value | Description |
---|---|
name | The location’s display name (used in the URL query). |
lat | Latitude of the location. |
lon | Longitude of the location. |
api | OpenWeatherMap API key. |
unit | Units of measurement (standard , metric , or imperial ). |
lang | Language code for weather descriptions (see the full list here). |
Here’s an example of how to add London and New York to the config.yaml file. These locations would be selectable via the URL, like this: http://{URL}?weather=london or http://{URL}?weather=new-york.
weather:
- name: london
lat: 51.5285262
lon: -0.2663999
api: API_KEY
unit: metric
lang: en
- name: new-york
lat: 40.6973709
lon: -74.1444838
api: API_KEY
unit: imperial
lang: en
You can interact with Kiosk in three ways: touch, mouse, or keyboard.
Kiosk's display is divided into interactive zones:
Key | Action |
---|---|
_ Spacebar | Play/Pause and Toggle Menu |
→ Right Arrow | Next Image(s) |
← Left Arrow | Previous Image(s) |
[!NOTE] IOS does not allow PWA's to prevent the screen from going to sleep. A work around is to lauch Kiosk then enable the guided access feature.
[!NOTE] These examples are community Kiosk implementations. I am unable to provide support for Home Assistant via issues.
While I did not create Kiosk with Home Assistant in mind. I thought it would be useful to add Kiosk implementations I have come across.
http://192.168.0.123:3000
* I would suggest disabling all the UI i.e. http://192.168.0.123:3000?disable_ui=true
* If you want to specify an album or a person you can also add that to the url e.g. http://192.168.0.123:3000/image?album=ALBUM_ID
wallpanel:
enabled: true
image_fit: cover
idle_time: 10
screensaver_entity: input_boolean.kiosk
screensaver_stop_navigation_path: /dashboard-kiosk
fullscreen: true
display_time: 86400
image_url: >-
http://{immich-kiosk-url}/image?person=PERSON_1_ID&person=PERSON_2_ID
cards:
- type: vertical-stack
cards:
- type: custom:weather-card
details: true
forecast: true
hourly_forecast: false
name: Weather
entity: weather.pirateweather
current: true
number_of_forecasts: '6'
- type: custom:horizon-card
darkMode: true
showAzimuth: true
showElevation: true
Q: What is the difference between ImmichFrame and ImmichKiosk?\ A:The main differences between ImmichFrame and ImmichKiosk are in how they are set up and how they interact with Immich:
ImmichFrame: For individual devices
ImmichKiosk: For multiple devices
In short, ImmichFrame is a 'one device, one installation, direct connection' setup, while ImmichKiosk is 'one installation, multiple devices, indirect connection.'"
\ Q: What is the no wifi icon?\ A: This icon shows when the front end can't connect to the back end.
\ Q: What is this icon in the menu?\ A: Clicking this icon tells Kiosk to delete all cached data and refresh the current device.
Q: Can I use this to set Immich images as my Home Assistant dashboard background?\
A: Yes! Just navigate to the dashboard with the view you wish to add the image background to.
Enter edit mode and click the ✏ next to the view you want to add the image to.
Then select the "background" tab and toggle on "Local path or web URL" and enter your url with path /image
e.g. http://192.168.0.123:3000/image
.
If you want to specify an album or a person you can also add that to the url e.g. http://192.168.0.123:3000/image?album=ALBUM_ID
Q: Do I need to a docker service for each client?\ A: You only need one docker service (or binary running) that your devices(s) will connect to.
Q: Do I have to use port 3000?\
A: Nope. Just change the host port in your docker compose file i.e. - 3000:3000
to - PORT_YOU_WANT:3000
Q: How do I set/use a password?\ A: 👇
[!WARNING] This feature is meant for edgecase scenarios and offers very little in terms of protection. If you are aiming to expose Kiosk beyond your local network, please investigate more secure alternatives.
via config.yaml file
kiosk:
password: 12345
via ENV in your docker-compose file
environment:
KIOSK_PASSWORD: "12345"
Then to access Kiosk you MUST add the password param in your URL e.g. http://{URL}?password=12345
If this project has been helpful to you and you wish to support me, you can do so with the button below 🙂.
If you have found a bug or have an issue you can submit it here.
If you'd like to chat or need some informal help, feel free to find me in the Kiosk channel on the Immich discord server.