Kiosk
Содержание
- 1 Киоск на базе пустого образа Alt jeos
- 1.1 Образ для установки
- 1.2 Обновление ОС и ядра
- 1.3 Установка необходимых пакетов через apt-get
- 1.4 Установка браузера google-chrome через epm
- 1.5 Установка необходимых пакетов через npm
- 1.6 Установка LTS версии платформы nodejs и её пакетного менеджера npm
- 1.7 Создание и настройка пользователя kiosk
- 1.8 Создание стартового скрипта в домашнем каталоге пользователя kiosk
- 1.9 Конфигурирование оконного менеджера awesome на запуск единственного приложения в полноэкранном режиме
- 1.10 Конфигурирование X-сессии для запуска в дисплей менеджере gdm
- 1.11 Конфигурирование автоматического входа в систему под пользователем kiosk и установка по умолчанию сессии kiosk.desktop
- 2 Служба autosshd
- 3 Решение проблем
- 3.1 Гаснет дисплей при простое
- 3.2 Дать конкретное имя tty устройству
- 3.3 Система загружается и просит настройки по dhcp раньше чем usb-модем инициализировался и готов это дать
- 3.4 Установить временнУю зону вместо UTC
- 3.5 Перевернуть координаты touchscreen
- 3.6 Если координаты touchscreen не совпадают с местом, куда нажимать пальцем
- 3.7 Очистить очередь печати
- 3.8 Оптимизация journalctl
- 3.9 Синхронизация времени через crontab
- 3.10 Запуск одного приложения в startx без менеджера окон
Киоск на базе пустого образа Alt jeos
Образ для установки
Качаем отсюда, например средствами wget
wget https://mirror.yandex.ru/altlinux-starterkits/x86_64/release/alt-p10-jeos-systemd-20220910-x86_64.img.xz
Распаковываем (получим файл без .xz на конце)
unxz alt-p10-jeos-systemd-20220910-x86_64.img.xz
Пишем на носитель (например его у вас зовут /dev/sdb)
dd if=alt-p10-jeos-systemd-20220910-x86_64.img of=/dev/sdb
После записи не лишним будет взглянуть на носитель через gparted и увеличить файловую систему до физических размеров носителя (если нужно место в корне будущей ОС)
Рутовый пароль по умолчанию:
altlinux
Обновление ОС и ядра
В этом разделе всё делается в рутовой консоли. Т.к. sudo по умолчанию в ОС Альт не присутствует (ниже мы его добавим)
Примечание: Лучше сразу переключить репозиторий на зеркало яндекса. Для этого закоментируем всё в файле
/etc/apt/sources.list.d/alt.list
а файле
/etc/apt/sources.list.d/yandex.list
раскоментируем следующие строчки:
rpm [p10] http://mirror.yandex.ru/altlinux p10/branch/x86_64 classic rpm [p10] http://mirror.yandex.ru/altlinux p10/branch/x86_64-i586 classic rpm [p10] http://mirror.yandex.ru/altlinux p10/branch/noarch classic
Обновим индекс репозитория
apt-get update
Обновим дистрибутив (в рамках одной рабочей ветки. Например, P10)
apt-get dist-upgrade
Обновим ядро
apt-get install update-kernel update-kernel -f
Перезагружаемся
reboot
Установка необходимых пакетов через apt-get
apt-get -y -q install nano xorg-server xorg-server usb-modeswitch-data usb-modeswitch openssh sudo su xterm gnome3-minimal plymouth xhost awesome git npm gcc10-c++ gcc-c++ make epm usbutils autosshd unclutter firefox chromium wkhtmltopdf pulseaudio-daemon alsa-plugins-pulse pulseaudio-utils aplay amixer alsa-utils
Установка браузера google-chrome через epm
! Можно не ставить. В режиме киоска хром не позволяет отключить всякие диалоги про статистику в гугл и т.п. Вместо него хорошо справляется устанавливаемый из репозитория chromium
epm play chrome
Установка необходимых пакетов через npm
да-да: npm умеет себя обновлять сам...
npm install -g npm
а этот пакет глобально устанавливается чтобы иметь возможность установки различных версий патформы nodejs
npm install n -g
Установка LTS версии платформы nodejs и её пакетного менеджера npm
n lts
mv /usr/bin/node /usr/bin/node_old mv /usr/bin/npm /usr/bin/npm_old mv /usr/bin/npx /usr/bin/npx_old ln -s /usr/local/bin/node /usr/bin/node ln -s /usr/local/bin/npm /usr/bin/npm ln -s /usr/local/bin/npx /usr/bin/npx
Создание и настройка пользователя kiosk
useradd kiosk
установка пароля делается командой
passwd kiosk
делаем sudo su без пароля для пользователя kiosk. Просто бросьте это в рутовую консоль:
cat << 'EOF' > /etc/sudoers User_Alias WHEEL_USERS = %wheel User_Alias XGRP_USERS = %xgrp Defaults:XGRP_USERS env_keep += "DISPLAY XAUTHORITY" kiosk ALL=(ALL) NOPASSWD: ALL @includedir /etc/sudoers.d EOF
добавляем пользователя kiosk в группу wheel (для sudo su)
usermod kiosk -aG wheel
и в группу dialout (для доступа к устройствам /dev/tty*)
usermod kiosk -aG dialout
Создание стартового скрипта в домашнем каталоге пользователя kiosk
Скрипт запускает браузер google-chrome в режиме киоска и подгружает в него стартовую страницу ya.ru (в реальном применении здесь может быть запущено веб приложение, стартующее на локальном хосте (для этого стоит платформа nodejs))
Просто бросьте это в рутовый терминал:
cat << EOF > /home/kiosk/start.sh #!/bin/bash xrandr -s 1280x1024 unclutter -idle 0 & amixer -D default sset Master 100% amixer -D default sset PCM 100% /bin/rm -rf .config/chromium chromium-browser --kiosk --incognito "http://localhost:3000" #firefox --kiosk "http://localhost:3000/test" #google-chrome #google-chrome --kiosk --incognito --disable-pinch "http://localhost:3000/test" –overscroll-history-navigation=0 #google-chrome --kiosk --disable-pinch "http://localhost:3000" EOF
затем делаем хозяином скрипта пользователя kiosk и делаем его исполняемым
chown kiosk: /home/kiosk/start.sh chmod +x /home/kiosk/start.sh
Конфигурирование оконного менеджера awesome на запуск единственного приложения в полноэкранном режиме
Просто бросьте это в рутовую консоль:
cat << EOF > /etc/xdg/awesome/rc.lua -- If LuaRocks is installed, make sure that packages installed through it are -- found (e.g. lgi). If LuaRocks is not installed, do nothing. pcall(require, "luarocks.loader") -- Standard awesome library local gears = require("gears") local awful = require("awful") require("awful.autofocus") -- Widget and layout library local wibox = require("wibox") -- Theme handling library local beautiful = require("beautiful") require("menu") -- Notification library local naughty = require("naughty") local menubar = require("menubar") local hotkeys_popup = require("awful.hotkeys_popup") -- Enable hotkeys help widget for VIM and other apps -- when client with a matching name is opened: require("awful.hotkeys_popup.keys") -- {{{ Error handling -- Check if awesome encountered an error during startup and fell back to -- another config (This code will only ever execute for the fallback config) if awesome.startup_errors then naughty.notify({ preset = naughty.config.presets.critical, title = "Oops, there were errors during startup!", text = awesome.startup_errors }) end -- Handle runtime errors after startup do local in_error = false awesome.connect_signal("debug::error", function (err) -- Make sure we don't go into an endless error loop if in_error then return end in_error = true naughty.notify({ preset = naughty.config.presets.critical, title = "Oops, an error happened!", text = tostring(err) }) in_error = false end) end -- }}} -- {{{ Variable definitions -- Themes define colours, icons, font and wallpapers. beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") -- This is used later as the default terminal and editor to run. terminal = "xterm" editor = os.getenv("EDITOR") or "nano" editor_cmd = terminal .. " -e " .. editor awful.screen.connect_for_each_screen(function(s) -- Each screen has its own tag table. awful.tag({ "1" }, s, awful.layout.layouts[1]) -- Create a promptbox for each screen s.mypromptbox = awful.widget.prompt() -- Create an imagebox widget which will contain an icon indicating which layout we're using. -- We need one layoutbox per screen. s.mylayoutbox = awful.widget.layoutbox(s) s.mylayoutbox:buttons(gears.table.join( awful.button({ }, 1, function () awful.layout.inc( 1) end), awful.button({ }, 3, function () awful.layout.inc(-1) end), awful.button({ }, 4, function () awful.layout.inc( 1) end), awful.button({ }, 5, function () awful.layout.inc(-1) end))) end) -- }}} -- {{{ Rules -- Rules to apply to new clients (through the "manage" signal). awful.rules.rules = { -- All clients will match this rule. { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = awful.client.focus.filter, raise = true, size_hints_honor = false, keys = clientkeys, buttons = clientbuttons, screen = awful.screen.preferred, placement = awful.placement.no_overlap+awful.placement.no_offscreen } }, } -- }}} -- {{{ Signals -- Signal function to execute when a new client appears. client.connect_signal("manage", function (c) -- Set the windows at the slave, -- i.e. put it at the end of others instead of setting it master. -- if not awesome.startup then awful.client.setslave(c) end if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then -- Prevent clients from being unreachable after screen count changes. awful.placement.no_offscreen(c) end end) -- }}} awful.spawn("/home/kiosk/start.sh") EOF
Конфигурирование X-сессии для запуска в дисплей менеджере gdm
Просто бросьте это в рутовую консоль:
cat << EOF > /usr/share/xsessions/kiosk.desktop [Desktop Entry] Name=KIOSK Exec=/usr/bin/awesome TryExec=/usr/bin/gnome-session Type=Application DesktopNames=KIOSK X-GDM-SessionRegisters=true EOF
Конфигурирование автоматического входа в систему под пользователем kiosk и установка по умолчанию сессии kiosk.desktop
Просто бросьте это в консоль:
cat << EOF > /etc/X11/gdm/custom.conf # GDM configuration storage [daemon] # Uncomment the line below to force the login screen to use Xorg WaylandEnable=false AutomaticLoginEnable=true AutomaticLogin=kiosk #DefaultSession=gnome.desktop DefaultSession=kiosk.desktop [security] [xdmcp] [chooser] [debug] # Uncomment the line below to turn on debugging #Enable=true EOF
В итоге главное не забыть включить сервис gdm
systemctl enable gdm
Ну и стартовать его
systemctl start gdm
или перезагрузиться
reboot
Если не стартует gdm после перезагрузки, то поможет вот такой костыль
cat << EOF > /etc/systemd/system/gdm-reloader.service [Unit] Description=gdm-reloader Requires=network-online.target After=network-online.target [Service] Restart=on-failure ExecStart=systemctl restart gdm User=root Group=root [Install] WantedBy=multi-user.target EOF
systemctl enable gdm-reloader systemctl start gdm-reloader
Служба autosshd
apt-get install autosshd
Генерим ключевую пару
ssh-keygen
Все ответы по умолчанию. В результате в ~/.ssh будут находиться закрытая и открытая части ключа (id_rsa и id_rsa.pub, соответственно).
Представим что наш сервер имеет пользователя kiosk. Берём открытую часть ключа и её содержимое кладём на сервер в /home/kiosk/.ssh/authirized_keys
Перемещаем ключи из ~/.ssh в /var/lib/autosshd/.ssh/
mv ~/.ssh/id_rsa* /var/lib/autosshd/.ssh/
Создаём конфиги (просто бросаем содержимое в консоль, предварительно заменив в них ssh-server-domain.example на реальный домен или ip адрес удалённого ssh сервера, и задав уникальный номер в рамках одного сервера для подключения в переменной REMOTESSH_USER_NUMBER
Раз:
cat << EOF > /var/lib/autosshd/.ssh/config Host central-server Hostname ssh-server-domain.example Port 22 User kiosk IdentityFile ~/.ssh/id_rsa ForwardX11 no Compression yes EOF
Два:
cat << EOF > /etc/autossh.d/central-server.conf REMOTESSH_USER_NUMBER=100 HOST=ssh-server-domain.example # Note: It is not needed usually to change follow lines REMOTESSH_USER=wc #Copy user private key file (id_dsa (public key copy to $HOST server in $REMOTESSH_USER)) to /var/lib/autosshd/.ssh directory and check unix permissions: it must be 0600 REMOTE_KEY=/var/lib/autosshd/.ssh/id_rsa LOCAL_PORT=22 #port that linstening sshd REMOTE_PORT=22$REMOTESSH_USER_NUMBER #port for ssh comand on HOST $ ssh -p $REMOTE_PORT $REMOTESSH_USER@127.0.0.1 AUTOSSH_PORT=11$REMOTESSH_USER_NUMBER #monitoring local port (port+1 will used too, see man autossh) #Web adminconsole ports LOCAL_PORT_WEB=3000 REMOTE_PORT_WEB=30$REMOTESSH_USER_NUMBER AUTOSTART=yes SSH_OPTIONS="-N -i ${REMOTE_KEY} -R ${REMOTE_PORT}:localhost:${LOCAL_PORT} -R ${REMOTE_PORT_WEB}:localhost:${LOCAL_PORT_WEB} ${REMOTESSH_USER}@${HOST} -o StrictHostKeychecking=no" AUTOSSH_OPTIONS="-M ${AUTOSSH_PORT} -f ${SSH_OPTIONS}" EOF
Запускаем сервис
systemctl enable autosshd systemctl start autosshd
Проверяем
systemctl status autosshd
Проверяем на сервере: допустим REMOTESSH_USER_NUMBER=100.
Тогда с сервера доступ по ssh на подключаемую машину будет по порту 22100. А все, что на сервере работает на 3000 порту будет доступно с сервера по порту 30100.
Решение проблем
Гаснет дисплей при простое
Просто бросьте это в консоль:
cat << EOF > /etc/X11/xorg.conf.d/90-disable-timeouts.conf Section "ServerFlags" Option "StandbyTime" "0" Option "SuspendTime" "0" Option "OffTime" "0" Option "BlankTime" "0" EndSection EOF
Дать конкретное имя tty устройству
Сначала нужно узнать несколько параметров для конструирования строчки для udev: https://askubuntu.com/questions/978485/udev-rule-with-serial-for-ttyusb-not-working
Кратко: для выяснения idVendor и idProduct выполните команду
lsusb
,выдёргивая и вставляя устройство tty. Как будет понятно: какое из них нужное вам, берёте оттуда эти данные.
Когда всё будет готово, сформируйте вот такой текст и бросьте его в рутовую консоль:
cat << 'EOF' > /etc/udev/rules.d/42-usb-serial-ttyS42.rules SUBSYSTEM=="tty", ATTRS{idVendor}=="079b", ATTRS{idProduct}=="0028", MODE="0666", SYMLINK+="ttyS42" EOF
Если у существующего устройства нужно просто поменять режим доступа к файлу устройства:
cat << 'EOF' > /etc/udev/rules.d/47-usb-serial-ttyUSB0.rules SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0666" EOF
Затем
udevadm control --reload reboot
Система загружается и просит настройки по dhcp раньше чем usb-модем инициализировался и готов это дать
Добавить скрипт (просто бросьте это в консоль)
cat << 'EOF' > /opt/check_gw.sh #!/bin/bash check_result=$(ip ro | grep default | wc -l) if [ $check_result -eq 0 ]; then dhclient exit 0 fi #echo 'wg is ok' exit 0 EOF
chmod +x /opt/check_gw.sh
Запускать раз в минуту через crontab рута
Установить временнУю зону вместо UTC
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime
Перевернуть координаты touchscreen
echo 'options usbtouchscreen swap_xy=1' > /etc/modprobe.d/usbtouchscreen.conf reboot
Если координаты touchscreen не совпадают с местом, куда нажимать пальцем
Скорее всего дисплей работает не в родном разрешении. Нужно подобрать разрешение экспериментально пробуя варианты:
xrandr -s 1024x768
или
xrandr -s 1280x1024
или для совсем плохих мониторов
xrandr -s 800x600
И заменить соответствующую команду в файле
/home/kiosk/start.sh
Посмотреть список разрешений
xrandr -d :0
Перезапустить графическую сессию без перезагрузки системы
killall awesome
Очистить очередь печати
Однострочник берёт все задачи, кладёт команды для очистки задач в файл /tmp/clear-cups-queue.sh, выполняет его, удаляет файл, проверяет очередь
lpstat -o | awk {'print "cancel -a " $1'} >> /tmp/clear-cups-queue.sh;bash /tmp/clear-cups-queue.sh;/bin/rm /tmp/clear-cups-queue.sh;lpstat -o
Оптимизация journalctl
find /var/log/journal -name "*.journal" | xargs rm sed -i 's/#SystemMaxUse=/SystemMaxUse=1M/g' /etc/systemd/journald.conf systemctl restart systemd-journald
Синхронизация времени через crontab
apt-get update -q -y && apt-get install ntpdate -y
EDITOR=nano crontab -e
Добавить строчку
1 */3 * * * /usr/sbin/ntpdate 0.ru.pool.ntp.org
Проверить
crontab -l
Запуск одного приложения в startx без менеджера окон
cat << 'EOF' > ~/.xinitrc xrandr -s 1280x1024 firefox & sleep 5s xdotool search --sync --onlyvisible --class "firefox" windowsize 1280 1024 xdotool search --sync --onlyvisible --class "firefox" windowmove 5 5 EOF