Kiosk

Материал из wiki.nntc.nnov.ru
Версия от 13:13, 25 апреля 2023; Vovan (обсуждение | вклад) (Создание стартового скрипта в домашнем каталоге пользователя kiosk)
Перейти к навигации Перейти к поиску

Содержание

Киоск на базе пустого образа 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