diff --git a/.env.dist b/.env.dist
index c4cd2f5..b750865 100755
--- a/.env.dist
+++ b/.env.dist
@@ -1,4 +1,4 @@
DEBUG=false
PORT=5000
SECRET_KEY=ANY_SECRET_KEY_HERE
-AUTOCONFIGURE_LX_FILE=/home/pi/.config/lxsession/LXDE-pi/autostart # Replace by "/dev/null" if not needed
+PLAYER_AUTOSTART_FILE=/home/pi/obscreen/system/start-chromium.sh # Replace by "/dev/null" if not needed
diff --git a/Dockerfile b/Dockerfile
index 1cac868..0c1b186 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,9 @@
FROM python:3.9.17-alpine3.17
-RUN apk add --no-cache git chromium \
- && apk add --no-cache --virtual .build-deps git gcc musl-dev
-
WORKDIR /app
COPY . .
-RUN pip install -r requirements.txt && apk del .build-deps gcc musl-dev
+RUN pip install -r requirements.txt
ENTRYPOINT ["python", "/app/obscreen.py"]
diff --git a/README.md b/README.md
index 9fa0eca..a4cd5a3 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
-#
Obscreen
+#
Obscreen
+
π§βπ Open to feature request and pull request
@@ -22,112 +23,8 @@ Use a RaspberryPi (with desktop) to show a full-screen slideshow (Kiosk-mode)

-## π³ Run with docker
-### With docker (for test)
-```bash
-# Prepare application data file tree
-mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
+# Two setups available
-# For RaspberryPi only - Prepare LXDE autostart file
-touch /home/pi/.config/lxsession/LXDE-pi/autostart
-
-# Run the Docker container
-# π¨ If you ARE NOT on a RaspberryPi
-# - replace '/home/pi/.config/lxsession/LXDE-pi/autostart' with '/dev/null'
-# π¨ Else make sure that
-# - file '/home/pi/.config/lxsession/LXDE-pi/autostart' exists and is writeable
-docker run --rm --name obscreen --pull=always \
- -e DEBUG=false \
- -e PORT=5000 \
- -e AUTOCONFIGURE_LX_FILE=/app/var/run/lxfile \
- -e SECRET_KEY=ANY_SECRET_KEY_HERE \
- -p 5000:5000 \
- -v ./data/db:/app/data/db \
- -v ./data/uploads:/app/data/uploads \
- -v /home/pi/.config/lxsession/LXDE-pi/autostart:/app/var/run/lxfile \
- jierka/obscreen:latest
-```
-
-### With docker-compose
-```bash
-# Prepare application data file tree
-mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
-
-# For RaspberryPi only - Prepare LXDE autostart file
-touch /home/pi/.config/lxsession/LXDE-pi/autostart
-
-# Download docker-compose.yml
-# π¨ If you ARE NOT on a RaspberryPi
-curl https://raw.githubusercontent.com/jr-k/obscreen/master/docker-compose.norpi.yml > docker-compose.yml
-# π¨ If you ARE on a RaspberryPi
-curl https://raw.githubusercontent.com/jr-k/obscreen/master/docker-compose.yml > docker-compose.yml
-
-# Run
-docker compose up
-```
-
-## π Run system wide
-### Install
-```bash
-# Install system dependencies
-sudo apt-get update
-sudo apt-get install -y git chromium-browser unclutter
-
-# Get files
-git clone https://github.com/jr-k/obscreen.git && cd obscreen
-
-# Install application dependencies
-pip3 install -r requirements.txt
-
-# Add some sample data
-cp data/db/slideshow.json.dist data/db/slideshow.json
-
-# Customize server default values
-cp .env.dist .env
-
-# For RaspberryPi only - Prepare LXDE autostart file
-touch /home/pi/.config/lxsession/LXDE-pi/autostart
-```
-
-### Configure
-- Server configuration is editable in `.env` file.
-- Application configuration is available in `http://localhost:5000/settings` page.
-
-### Start server (for test)
-```bash
-./obscreen.py
-```
-
-### Start server forever with systemctl
-```bash
-sudo ln -s "$(pwd)/system/obscreen.service" /etc/systemd/system/obscreen.service
-sudo systemctl daemon-reload
-sudo systemctl enable obscreen.service
-sudo systemctl start obscreen.service
-```
-
-To troubleshoot you can check logs
-```bash
-sudo journalctl -u obscreen -f
-```
-
-## π Usage
-- Page which plays slideshow is reachable at `http://localhost:5000`
-- Slideshow manager is reachable at `http://localhost:5000/manage`
-
-## β¨ You are done now :)
-- If everything is set up correctly, the RaspberryPi shall start chromium in fullscreen directly after boot screen and after some seconds of showing the date & time (`views/player/default.jinja.html`) your slideshow shall start and loop endlessly.
-- Make sure that `AUTOCONFIGURE_LX_FILE` exists and is writeable !
-
-## π Additional
-
-### Hardware checks
-- Basic Setup
-For basic RaspberryPi setup you can use most of the available guides, for example this one:
-https://gist.github.com/blackjid/dfde6bedef148253f987
-
-- HDMI Mode
-You may need to set the HDMI Mode on the raspi to ensure the hdmi resolution matches your screen exactly. Here is the official documentation:
-https://www.raspberrypi.org/documentation/configuration/config-txt/video.md
-
-However, I used this one: `(2,82) = 1920x1080 60Hz 1080p`
+### π΄ [I want to power RaspberryPi and automatically see my slideshow on a screen connected to it and manage the slideshow](docs/setup-run-on-rpi.md)
+### π΅ [I want to start browser and setup playlist url manually on my device and just want a slideshow manager](docs/setup-run-headless.md)
+
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 6bfb574..4d15f21 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -9,10 +9,10 @@ services:
environment:
- DEBUG=${DEBUG-false}
- PORT=${PORT-5000}
- - AUTOCONFIGURE_LX_FILE=/app/var/run/lxfile
+ - PLAYER_AUTOSTART_FILE=/app/var/run/play
- SECRET_KEY=${SECRET_KEY-ANY_SECRET_KEY_HERE}
volumes:
- .:/app
- - ${AUTOCONFIGURE_LX_FILE-/dev/null}:/app/var/run/lxfile
+ - ${PLAYER_AUTOSTART_FILE-/dev/null}:/app/var/run/play
ports:
- ${PORT}:${PORT}
\ No newline at end of file
diff --git a/docker-compose.norpi.yml b/docker-compose.headless.yml
similarity index 78%
rename from docker-compose.norpi.yml
rename to docker-compose.headless.yml
index 450c8c1..052dea2 100644
--- a/docker-compose.norpi.yml
+++ b/docker-compose.headless.yml
@@ -6,10 +6,10 @@ services:
environment:
- DEBUG=false
- PORT=5000
- - AUTOCONFIGURE_LX_FILE=/app/var/run/lxfile
+ - PLAYER_AUTOSTART_FILE=/app/var/run/play
- SECRET_KEY=ANY_SECRET_KEY_HERE
volumes:
- - /dev/null:/app/var/run/lxfile
+ - /dev/null:/app/var/run/play
- ./data/db:/app/data/db
- ./data/uploads:/app/data/uploads
ports:
diff --git a/docker-compose.yml b/docker-compose.yml
index 44e71c9..eb7cbc2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -6,10 +6,10 @@ services:
environment:
- DEBUG=false
- PORT=5000
- - AUTOCONFIGURE_LX_FILE=/app/var/run/lxfile
+ - PLAYER_AUTOSTART_FILE=/app/var/run/play
- SECRET_KEY=ANY_SECRET_KEY_HERE
volumes:
- - /home/pi/.config/lxsession/LXDE-pi/autostart:/app/var/run/lxfile
+ - /home/pi/obscreen/system/start-chromium.sh:/app/var/run/play
- ./data/db:/app/data/db
- ./data/uploads:/app/data/uploads
ports:
diff --git a/docs/obscreen.png b/docs/img/obscreen.png
similarity index 100%
rename from docs/obscreen.png
rename to docs/img/obscreen.png
diff --git a/docs/setup-run-headless.md b/docs/setup-run-headless.md
new file mode 100644
index 0000000..c5c7da9
--- /dev/null
+++ b/docs/setup-run-headless.md
@@ -0,0 +1,83 @@
+#
Obscreen - Headless run on any server
+
+> #### π [back to readme](README.md)
+
+#### π΅ You want to start browser and setup playlist url manually on your device and just want a slideshow manager ? You're in the right place.
+
+
+## π³ Run with docker
+### With docker (for test)
+```bash
+# Prepare application data file tree
+mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
+
+# Run the Docker container
+docker run --rm --name obscreen --pull=always \
+ -e DEBUG=false \
+ -e PORT=5000 \
+ -e PLAYER_AUTOSTART_FILE=/app/var/run/play \
+ -e SECRET_KEY=ANY_SECRET_KEY_HERE \
+ -p 5000:5000 \
+ -v ./data/db:/app/data/db \
+ -v ./data/uploads:/app/data/uploads \
+ -v /dev/null:/app/var/run/play \
+ jierka/obscreen:latest
+```
+
+### With docker-compose
+```bash
+# Prepare application data file tree
+mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
+
+# Download docker-compose.yml
+curl https://raw.githubusercontent.com/jr-k/obscreen/master/docker-compose.headless.yml > docker-compose.yml
+
+# Run
+docker compose up --detach --pull always
+```
+
+## π Run system wide
+### Install
+```bash
+# Install system dependencies
+sudo apt-get update
+sudo apt-get install -y git
+
+# Get files
+git clone https://github.com/jr-k/obscreen.git && cd obscreen
+
+# Install application dependencies
+pip3 install -r requirements.txt
+
+# Add some sample data
+cp data/db/slideshow.json.dist data/db/slideshow.json
+
+# Customize server default values
+cp .env.dist .env
+```
+
+### Configure
+- Server configuration is editable in `.env` file.
+- Application configuration will be available at `http://localhost:5000/settings` page after run.
+
+### Start server (for test)
+```bash
+./obscreen.py
+```
+
+### Start server forever with systemctl
+```bash
+sudo ln -s "$(pwd)/system/obscreen-manager.service" /etc/systemd/system/obscreen-manager.service
+sudo systemctl daemon-reload
+sudo systemctl enable obscreen-manager.service
+sudo systemctl start obscreen-manager.service
+```
+
+To troubleshoot you can check logs
+```bash
+sudo journalctl -u obscreen -f
+```
+
+## π Usage
+- Page which plays slideshow is reachable at `http://localhost:5000`
+- Slideshow manager is reachable at `http://localhost:5000/manage`
diff --git a/docs/setup-run-on-rpi.md b/docs/setup-run-on-rpi.md
new file mode 100644
index 0000000..3cc22e1
--- /dev/null
+++ b/docs/setup-run-on-rpi.md
@@ -0,0 +1,117 @@
+#
Obscreen - Autorun on RaspberryPi
+
+> #### π [back to readme](README.md)
+
+#### π΄ You want to power RaspberryPi and automatically see your slideshow on a screen connected to it and manage your slideshow ? You're in the right place.
+
+## ποΈ Hardware installation
+
+1. Download RaspberryPi Imager and setup an sdcard with `Raspberry Pi OS Lite` (π¨without desktop, only `Lite` version!). You'll find it under category `Raspberry PI OS (other)`
+2. Log into your pi user locally or via ssh (`ssh pi@raspberrypi.local`)
+3. Install player autorun by executing `curl -fsSL https://raw.githubusercontent.com/jr-k/obscreen/master/system/install-autorun-rpi.sh | sudo bash`
+
+---
+## π³ Run with docker
+### Install docker if needed
+```bash
+curl -sSL get.docker.com | sh
+sudo usermod -aG docker $(whoami)
+logout
+#then login again
+```
+
+
+### With docker (for test)
+```bash
+# Prepare application data file tree and prepare player autostart file
+cd /home/pi && mkdir -p obscreen/data/db obscreen/data/uploads obscreen/system && touch system/start-chromium.sh && cd obscreen
+
+# Run the Docker container
+ocker run --rm --name obscreen --pull=always \
+ -e DEBUG=false \
+ -e PORT=5000 \
+ -e PLAYER_AUTOSTART_FILE=/app/var/run/play \
+ -e SECRET_KEY=ANY_SECRET_KEY_HERE \
+ -p 5000:5000 \
+ -v ./data/db:/app/data/db \
+ -v ./data/uploads:/app/data/uploads \
+ -v /home/pi/obscreen/system/start-chromium.sh:/app/var/run/play \
+ jierka/obscreen:latest
+```
+
+### Or with docker-compose
+```bash
+# Prepare application data file tree
+cd /home/pi && mkdir -p obscreen/data/db obscreen/data/uploads obscreen/system && touch system/start-chromium.sh && cd obscreen
+
+# Download docker-compose.yml
+curl https://raw.githubusercontent.com/jr-k/obscreen/master/docker-compose.yml > docker-compose.yml
+
+# Run
+docker compose up --detach --pull always
+```
+---
+## π Run system wide
+### Install
+```bash
+# Install system dependencies
+sudo apt-get update
+sudo apt-get install -y git xinit xserver-xorg chromium-browser unclutter
+
+# Get files
+git clone https://github.com/jr-k/obscreen.git && cd obscreen
+
+# Install application dependencies
+pip3 install -r requirements.txt
+
+# Add some sample data
+cp data/db/slideshow.json.dist data/db/slideshow.json
+
+# Customize server default values
+cp .env.dist .env
+```
+
+### Configure
+- Server configuration is editable in `.env` file.
+- Application configuration will be available at `http://raspberrypi.local:5000/settings` page after run.
+
+### Start server (for test)
+```bash
+./obscreen.py
+```
+
+### Start server forever with systemctl
+```bash
+sudo ln -s "$(pwd)/system/obscreen-manager.service" /etc/systemd/system/obscreen-manager.service
+sudo systemctl daemon-reload
+sudo systemctl enable obscreen-manager.service
+sudo systemctl start obscreen-manager.service
+```
+
+To troubleshoot you can check logs
+```bash
+sudo journalctl -u obscreen -f
+```
+---
+## π Usage
+- Page which plays slideshow is reachable at `http://raspberrypi.local:5000`
+- Slideshow manager is reachable at `http://raspberrypi.local:5000/manage`
+
+## β¨ You are done now :)
+- If everything is set up correctly, the RaspberryPi shall start chromium in fullscreen directly after boot screen and after some seconds of showing the date & time (`views/player/default.jinja.html`) your slideshow shall start and loop endlessly.
+- Make sure that `PLAYER_AUTOSTART_FILE` exists and is writeable !
+
+## π Additional
+
+### Hardware checks
+- Basic Setup
+For basic RaspberryPi setup you can use most of the available guides, for example this one:
+https://gist.github.com/blackjid/dfde6bedef148253f987
+
+- HDMI Mode
+You may need to set the HDMI Mode on the raspi to ensure the hdmi resolution matches your screen exactly. Here is the official documentation:
+https://www.raspberrypi.org/documentation/configuration/config-txt/video.md
+
+However, I used this one: `(2,82) = 1920x1080 60Hz 1080p`
+
+
diff --git a/src/manager/ConfigManager.py b/src/manager/ConfigManager.py
index 97b0cc4..712817b 100644
--- a/src/manager/ConfigManager.py
+++ b/src/manager/ConfigManager.py
@@ -12,7 +12,7 @@ load_dotenv()
class ConfigManager:
DEFAULT_PORT = 5000
- DEFAULT_LXDE_AUTOSTART_PATH = '/home/pi/.config/lxsession/LXDE-pi/autostart'
+ DEFAULT_PLAYER_AUTOSTART_PATH = '/home/pi/obscreen/system/start-chromium.sh'
VERSION_FILE = 'version.txt'
def __init__(self, variable_manager: VariableManager):
@@ -22,7 +22,7 @@ class ConfigManager:
'port': self.DEFAULT_PORT,
'bind': '0.0.0.0',
'debug': False,
- 'autoconfigure_lx_file': self.DEFAULT_LXDE_AUTOSTART_PATH,
+ 'player_autostart_file': self.DEFAULT_PLAYER_AUTOSTART_PATH,
'log_file': None,
'log_level': 'INFO',
'log_stdout': True,
@@ -50,7 +50,7 @@ class ConfigManager:
parser.add_argument('--port', '-p', default=self._CONFIG['port'], help='Application port')
parser.add_argument('--bind', '-b', default=self._CONFIG['bind'], help='Application bind address')
parser.add_argument('--secret-key', '-s', default=self._CONFIG['secret_key'], help='Application secret key (any random string)')
- parser.add_argument('--autoconfigure-lx-file', '-x', default=self._CONFIG['autoconfigure_lx_file'], help='Path to lx autostart file')
+ parser.add_argument('--player-autostart-file', '-x', default=self._CONFIG['player_autostart_file'], help='Path to player autostart file')
parser.add_argument('--log-file', '-lf', default=self._CONFIG['log_file'], help='Log File path')
parser.add_argument('--log-level', '-ll', default=self._CONFIG['log_level'], help='Log Level')
parser.add_argument('--log-stdout', '-ls', default=self._CONFIG['log_stdout'], action='store_true', help='Log to standard output')
@@ -67,8 +67,8 @@ class ConfigManager:
if args.debug:
self._CONFIG['debug'] = args.debug
- if args.autoconfigure_lx_file:
- self._CONFIG['autoconfigure_lx_file'] = args.autoconfigure_lx_file
+ if args.player_autostart_file:
+ self._CONFIG['player_autostart_file'] = args.player_autostart_file
if args.log_file:
self._CONFIG['log_file'] = args.log_file
if args.secret_key:
@@ -95,8 +95,8 @@ class ConfigManager:
def autoconfigure(self) -> None:
self.autoconfigure_player_url()
- if self.map().get('autoconfigure_lx_file'):
- self.autoconfigure_lxconf()
+ if self.map().get('player_autostart_file'):
+ self.autoconfigure_player_autostart_file()
def autoconfigure_player_url(self) -> str:
@@ -104,36 +104,46 @@ class ConfigManager:
return self._CONFIG['player_url']
- def autoconfigure_lxconf(self) -> None:
- path = self.map().get('autoconfigure_lx_file')
+ def autoconfigure_player_autostart_file(self) -> None:
+ path = self.map().get('player_autostart_file')
in_docker = am_i_in_docker()
- lx_path = self.DEFAULT_LXDE_AUTOSTART_PATH if in_docker else path
+ player_autostart_path = self.DEFAULT_PLAYER_AUTOSTART_PATH if in_docker else path
if os.path.isdir(path) or not os.path.exists(path):
logging.error(
- "LXDE autostart file {} doesn't exist on your server, please create it by executing follow command: \n'rm -rf ./var/run/lxfile 2>/dev/null ; sudo rm -rf /home/pi/.config/lxsession/LXDE-pi 2>/dev/null; sudo mkdir -p /home/pi/.config/lxsession/LXDE-pi 2>/dev/null ; sudo touch {}'\n".format(
- lx_path,
- self.DEFAULT_LXDE_AUTOSTART_PATH
+ "Player autostart file {} doesn't exist on your server, please create it by executing follow command: \n'rm -rf ./var/run/play 2>/dev/null ; sudo touch {}'\n".format(
+ player_autostart_path,
+ self.DEFAULT_PLAYER_AUTOSTART_PATH
)
)
sys.exit(1)
else:
- logging.info("Overriding LXDE autostart file {}".format(lx_path))
+ logging.info("Overriding player autostart file {}".format(player_autostart_path))
player_url = self.map().get('player_url')
- os.makedirs(os.path.dirname(lx_path), exist_ok=True)
- xenv_presets = f"""
-@lxpanel --profile LXDE-pi
-@pcmanfm --desktop --profile LXDE-pi
-@xscreensaver -no-splash
-#@point-rpi
-@xset s off
-@xset -dpms
-@xset s noblank
-@unclutter -display :0 -noevents -grab
-@sed -i 's/"exited_cleanly": false/"exited_cleanly": true/' ~/.config/chromium/Default/Preferences
-#@sleep 10
-@chromium-browser --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --disable-restore-session-state --noerrdialogs --kiosk --incognito --window-position=0,0 --display=:0 {player_url}
- """
- with open(lx_path, 'w') as file:
+ os.makedirs(os.path.dirname(player_autostart_path), exist_ok=True)
+ xenv_presets = """
+#!/bin/bash
+
+# Disable screensaver and DPMS
+xset s off
+xset -dpms
+xset s noblank
+
+# Start unclutter to hide the mouse cursor
+unclutter -display :0 -noevents -grab &
+
+# Modify Chromium preferences to avoid restore messages
+mkdir -p /home/pi/.config/chromium/Default 2>/dev/null
+touch /home/pi/.config/chromium/Default/Preferences
+sed -i 's/"exited_cleanly": false/"exited_cleanly": true/' /home/pi/.config/chromium/Default/Preferences
+
+RESOLUTION=$(DISPLAY=:0 xrandr | grep '*' | awk '{print $1}')
+WIDTH=$(echo $RESOLUTION | cut -d 'x' -f 1)
+HEIGHT=$(echo $RESOLUTION | cut -d 'x' -f 2)
+
+# Start Chromium in kiosk mode
+chromium-browser --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --noerrdialogs --kiosk --incognito --window-position=0,0 --window-size=${WIDTH},${HEIGHT} --display=:0 __PLAYER_URL__
+ """.replace('__PLAYER_URL__', player_url)
+ with open(player_autostart_path, 'w') as file:
file.write(xenv_presets)
diff --git a/system/install-autorun-rpi.sh b/system/install-autorun-rpi.sh
new file mode 100644
index 0000000..4539619
--- /dev/null
+++ b/system/install-autorun-rpi.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# Update and install necessary packages
+apt update
+apt install -y xinit xserver-xorg chromium-browser unclutter
+
+# Add user pi to tty and video groups
+usermod -aG tty pi
+usermod -aG video pi
+
+# Configure Xwrapper
+touch /etc/X11/Xwrapper.config
+grep -qxF "allowed_users=anybody" /etc/X11/Xwrapper.config || echo "allowed_users=anybody" | tee -a /etc/X11/Xwrapper.config
+grep -qxF "needs_root_rights=yes" /etc/X11/Xwrapper.config || echo "needs_root_rights=yes" | tee -a /etc/X11/Xwrapper.config
+
+# Create the systemd service to start Chromium in kiosk mode
+curl https://raw.githubusercontent.com/jr-k/obscreen/master/system/obscreen-player.yml > /etc/systemd/system/obscreen-player.service
+
+# Reload systemd, enable and start the service
+systemctl daemon-reload
+systemctl enable obscreen-player.service
+systemctl set-default graphical.target
+
+# Reboot the system
+reboot
\ No newline at end of file
diff --git a/system/obscreen.service b/system/obscreen-manager.service
similarity index 89%
rename from system/obscreen.service
rename to system/obscreen-manager.service
index 2cc76ec..8bc752f 100644
--- a/system/obscreen.service
+++ b/system/obscreen-manager.service
@@ -1,5 +1,5 @@
[Unit]
-Description=Obscreen
+Description=Obscreen Manager
After=network.target
[Service]
diff --git a/system/obscreen-player.service b/system/obscreen-player.service
new file mode 100644
index 0000000..c631117
--- /dev/null
+++ b/system/obscreen-player.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Obscreen Player
+After=network.target
+
+[Service]
+Type=simple
+ExecStart=/usr/bin/xinit /home/pi/obscreen/system/start-chromium.sh -- :0 -nolisten tcp vt7 -keeptty
+User=pi
+Group=pi
+Restart=on-failure
+Environment=DISPLAY=:0
+
+[Install]
+WantedBy=graphical.target
\ No newline at end of file
diff --git a/system/start-chromium.sh b/system/start-chromium.sh
new file mode 100755
index 0000000..2ba2b8a
--- /dev/null
+++ b/system/start-chromium.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# Disable screensaver and DPMS
+xset s off
+xset -dpms
+xset s noblank
+
+# Start unclutter to hide the mouse cursor
+unclutter -display :0 -noevents -grab &
+
+# Modify Chromium preferences to avoid restore messages
+mkdir -p /home/pi/.config/chromium/Default 2>/dev/null
+touch /home/pi/.config/chromium/Default/Preferences
+sed -i 's/"exited_cleanly": false/"exited_cleanly": true/' /home/pi/.config/chromium/Default/Preferences
+
+RESOLUTION=$(DISPLAY=:0 xrandr | grep '*' | awk '{print $1}')
+WIDTH=$(echo $RESOLUTION | cut -d 'x' -f 1)
+HEIGHT=$(echo $RESOLUTION | cut -d 'x' -f 2)
+
+# Start Chromium in kiosk mode
+chromium-browser --disable-features=Translate --ignore-certificate-errors --disable-web-security --disable-restore-session-state --autoplay-policy=no-user-gesture-required --start-maximized --allow-running-insecure-content --remember-cert-error-decisions --noerrdialogs --kiosk --incognito --window-position=0,0 --window-size=${WIDTH},${HEIGHT} --display=:0 http://localhost:5000