massive setup rework

This commit is contained in:
jr-k 2024-05-16 01:43:13 +02:00
parent e9eb0605f2
commit 5deb6bf709
14 changed files with 314 additions and 150 deletions

View File

@ -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

View File

@ -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"]

113
README.md
View File

@ -1,4 +1,5 @@
# <img src="https://github.com/jr-k/obscreen/blob/master/docs/obscreen.png" width="22"> Obscreen
# <img src="https://github.com/jr-k/obscreen/blob/master/docs/img/obscreen.png" width="22"> 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)
![Obscreen Screenshot](https://github.com/jr-k/obscreen/blob/master/docs/screenshot.png "Obscreen Screenshot")
## 🐳 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
### 🔴 [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)
# 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`

View File

@ -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}

View File

@ -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:

View File

@ -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:

View File

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 187 KiB

View File

@ -0,0 +1,83 @@
# <img src="https://github.com/jr-k/obscreen/blob/master/docs/img/obscreen.png" width="22"> 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`

117
docs/setup-run-on-rpi.md Normal file
View File

@ -0,0 +1,117 @@
# <img src="https://github.com/jr-k/obscreen/blob/master/docs/img/obscreen.png" width="22"> 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`

View File

@ -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)

View File

@ -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

View File

@ -1,5 +1,5 @@
[Unit]
Description=Obscreen
Description=Obscreen Manager
After=network.target
[Service]

View File

@ -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

21
system/start-chromium.sh Executable file
View File

@ -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