Passer au contenu principal

Installation du kiosque

Objectif

→ Créer un environnement kiosque sécurisé, minimaliste et clonable, basé sur Debian + Openbox + OpenKiosk.
→ Utilisation visée : bornes de visioconférence, affichage municipal, postes en accès public.
→ À la fin : une image système prête à être clonée pour un déploiement rapide sur d’autres machines.

Procédure d'installation

Debian

Conseil pour la création du compte utilisateur :
Utilisez le login : kiosk pour simplifier les étapes.
(Si vous choisissez un autre nom, pensez à adapter toutes les commandes et configurations de la documentation en conséquence.)

Pendant l’installation choisir uniquement :

  • Serveur SSH
  • Utilitaires usuels du système

Attention : ne pas installer d’environnement graphique !

 

Connexion Réseau

Dans les exemples ci-dessous, pensez à adapter le nom de l’interface réseau (ici les interfaces sont enp... et wlp...)

Connexion filaire

Dans le cas d’une connexion filaire ajouter dans le fichier /etc/network/interfaces :

auto enp0s31f6
allow-hotplug enp0s31f6
iface enp0s31f6 inet dhcp
    metric 100

Puis pour activer l’interface :

ifup enp0s31f6

WiFi (WPA Personal)

Créer un ficher /etc/wpa_supplicant/wpa_supplicant.conf

network={
    ssid="NOM_DU_WIFI"
    psk="MOT_DE_PASSE_DU_WIFI"
}

Puis ajouter dans le fichier /etc/network/interfaces :

auto wlp0s20f3
iface wlp0s20f3 inet dhcp
   wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
   metric 200

Puis pour activer l’interface :

ifup wlp0s20f3

WiFi (WPA Enterprise)

Adaptez cette configuration en fonction de vos paramètres de chiffrement et d'authentification

Créer un ficher /etc/wpa_supplicant/wpa_supplicant.conf

network={
    ssid="mon-ssid"
    key_mgmt=WPA-EAP
    eap=PEAP
    identity="LOGIN"
    password="PASSWORD"
    phase2="auth=MSCHAPV2"
}

Puis ajouter dans le fichier /etc/network/interfaces :

auto wlp0s20f3
iface wlp0s20f3 inet dhcp
   wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
   metric 200

Puis pour activer l’interface :

ifup wlp0s20f3

 

Openbox

Installer xorg et openbox:

apt install -y xorg openbox jq

 

OpenKiosk

Site d'OpenKiosk

Comme mentionné sur le site, installer OpenKiosk avec ces commandes (avec wget, car curl n’est pas installé par défaut sur Debian).

wget https://www.mozdevgroup.com/dropbox/okcd/115/release/OpenKiosk115.20.0-2025-02-16-x86_64.deb
apt install -y ./OpenKiosk115.20.0-2025-02-16-x86_64.deb

Pensez à vérifier sur le site qu'OpenKiosk n’a pas été mis à jour. Si une nouvelle version est disponible, adaptez les commandes avec le nom du nouveau fichier.

 

Configuration

Désactiver le menu grub au démarrage du PC & les messages kernel au boot

Éditer le fichier /etc/default/grub et changez la valeur de GRUB_TIMEOUT à 0 puis GRUB_CMDLINE_LINUX_DEFAULT à "quiet loglevel=0"

Pour appliquer ce changement, exécuter la commande suivante :

update-grub

 

Configuration d’un auto-login

Éditer le fichier /etc/systemd/system/getty@tty1.service.d/override.conf avec :

systemctl edit getty@tty1.service

Rajouter ces trois lignes :

Attention il faut les rajouter à la 3ème ligne du fichier (juste en dessous de la ligne n°2, donc) !

[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin root --noclear %I 38400 linux

Puis, pour activer ce changement au démarrage du PC :

systemctl enable getty@tty1.service

 

Création du script de configuration de premier lancement

Vérifiez que Python3 est installé sur la machine. Si ce n'est pas le cas, installez-le.

Dans /root/.profile ajouter à la fin :

if [ ! -e /home/kiosk/firstTime.ok ]; then
    python3 /home/kiosk/firstTime.py
    sleep 2
    reboot
fi

Puis créer un fichier /home/kiosk/firstTime.py avec ce contenu :

import os
import subprocess
from time import sleep
import requests
import ipaddress
import json
import uuid
import signal
import time


def command(command):
    """Executes a command and returns the output"""
    result = subprocess.run(command, shell=True, capture_output=True, text=True)
    return result.stdout, result.stderr


# Prevent ctrl-c
def handler(signum, frame):
    pass

signal.signal(signal.SIGINT, handler)


def list_network_interfaces():
    """Lists available network interfaces"""
    stdout, stderr = command("ip link show")
    interfaces = []
    if stderr:
        print(f"Error retrieving interfaces: {stderr}")
    else:
        for line in stdout.splitlines():
            if line[0].isdigit():
                interface_name = line.split(":")[1].split()[0]
                interfaces.append(interface_name)
            if "lo" in interfaces:
                interfaces.remove("lo")
    return interfaces


def configure_wired(interface):
    """Configures the wired connection"""
    print(f"Configuring wired connection on {interface}...")
    dhcp = input("Do you want to use DHCP? (yes/no): ").strip().lower()

    if dhcp == 'yes':
        # Configure DHCP for a wired interface
        with open("/etc/network/interfaces", "w") as myfile:
            myfile.write("source /etc/network/interfaces.d/*\n")
            myfile.write("auto lo\niface lo inet loopback\n")
            myfile.write(f"auto {interface}\nallow-hotplug {interface}\niface {interface} inet dhcp")

        command(f"ifup {interface}")
        print(f"{interface} configured with DHCP.")
    else:
        # Manual configuration (static IP)
        ip = input("Enter the static IP address: ").strip()
        netmask = input("Enter the subnet mask (e.g., 255.255.255.0): ").strip()
        cidr = ipaddress.IPv4Network(f"0.0.0.0/{netmask}").prefixlen
        gateway = input("Enter the default gateway: ").strip()
        dns = input("Enter the DNS address: ").strip()

        # Static IP configuration
        with open("/etc/network/interfaces", "w") as myfile:
            myfile.write("source /etc/network/interfaces.d/*\n")
            myfile.write("auto lo\niface lo inet loopback\n")
            myfile.write(f"auto {interface}\nallow-hotplug {interface}\niface {interface} inet static\n\taddress {ip}/{cidr})\n\tgateway {gateway}")

        command(f"echo nameserver {dns} > /etc/resolv.conf")
        command(f"ifup {interface}")
        print(f"{interface} configured with static IP {ip}.")


def configure_wifi(interface):
    """Configures the Wi-Fi connection"""
    print(f"Configuring Wi-Fi on {interface}...")
    ssid = input("Enter the Wi-Fi network name (SSID): ").strip()
    password = input("Enter the Wi-Fi network password: ").strip()

    # Configure Wi-Fi via `nmcli` (NetworkManager)
    with open("/etc/network/interfaces", "w") as myfile:
            myfile.write("source /etc/network/interfaces.d/*\n")
            myfile.write("auto lo\niface lo inet loopback\n")
            myfile.write(f"auto {interface}\nallow-hotplug {interface}\niface {interface} inet dhcp\n\twpa-ssid {ssid}\n\twpa-psk {password}")

    command(f"ifup {interface}")
    print(f"Wi-Fi connection established on {interface}.")


def configure_network():
    """Main function to configure the network interface"""
    interfaces = list_network_interfaces()

    if not interfaces:
        print("No network interfaces found.")
        return

    print("Available network interfaces:")
    print("0. Skip this step")
    for i, iface in enumerate(interfaces, 1):
        print(f"{i}. {iface}")

    choice = int(input("Choose the network interface to configure (number): ").strip()) - 1

    if choice not in range(len(interfaces)):
        print("Invalid choice.")
        return


    selected_interface = interfaces[choice]
    print(f"Chosen interface: {selected_interface}")

    connection_type = input("Do you want to configure a wired connection or Wi-Fi (only WPA with password)? (wired/wifi): ").strip().lower()

    if connection_type == "wired":
        configure_wired(selected_interface)
    elif connection_type == "wifi":
        configure_wifi(selected_interface)
    else:
        print("Invalid choice.")


if not os.path.isfile("firstTime.ok"):
    print('''

    ██   ██ ██  ██████  ███████ ██   ██
    ██  ██  ██ ██    ██ ██      ██  ██
    █████   ██ ██    ██ ███████ █████
    ██  ██  ██ ██    ██      ██ ██  ██
    ██   ██ ██  ██████  ███████ ██   ██

    ''')

    sleep(2)
    print("[*] First-time configuration script [*]")
    print("[*] - Version: 1.0                  [*]")
    print("[*] - By: Alexandre Salmetoz        [*]")
    sleep(2)

    try:
        print("\n1. Hostname configuration")
        hostname = input("Hostname: ")
        command(f"hostnamectl set-hostname {hostname}")
        print("Hostname: OK")
    except Exception as e:
        print(f"Error: {e}")

    try:
        print("\n2. Network connection configuration")
        configure_network()
    except Exception as e:
        print(f"Error: {e}")

    try:
        command("touch /home/kiosk/firstTime.ok")

        with open("/etc/systemd/system/getty@tty1.service.d/override.conf", 'r') as file:
            content = file.read()
        content = content.replace('root', 'kiosk')
        with open("/etc/systemd/system/getty@tty1.service.d/override.conf", 'w') as file:
            file.write(content)

        command("systemctl mask getty@tty1.service")

    except Exception as e:
        print(f"Error: {e}")


    print("\n[ Configuration complete! ]\n")

    print("The device will restart...")

Ce script est lancé au premier lancement du pc seulement, pour permettre de configurer le hostname, le réseau et redémarrer

 

Création d’un service système pour récupérer les fichiers de configuration au démarrage du PC

Pour ce faire, créer un fichier /etc/systemd/system/kiosk.service avec ce contenu :

[Unit]
Description=Execute start.sh at startup

[Service]
ExecStart=/home/kiosk/start.sh
Restart=on-failure
User=root
StandardInput=tty
StandardOutput=journal
StandardError=journal
TTYPath=/dev/tty3

[Install]
WantedBy=multi-user.target

Puis, pour activer le service  :

systemctl enable kiosk.service

Voici le script qui permet de récupérer les fichiers de configuration auprès du serveur à chaque démarrage, à placer dans /home/kiosk/start.sh :

Ce script va récupérer avec « python3 /home/kiosk/getConfig.py » le fichier de configuration pour OpenKiosk, une Whitelist, un ficher de configuration système et un script qui sera exécuté à chaque démarrage du pc sur un serveur (dont l’url est contenue dans la variable $DOMAIN_NAME), puis placer ces fichiers dans /usr/lib/OpenKiosk/

#!/bin/bash

start_time=$(date +%s)
timeout=10  # Délai d'attente en secondes avant que le script saute cette étape du ping
while ! ping -c 1 -W 1 "8.8.8.8" &> /dev/null; do
    elapsed_time=$(($(date +%s) - start_time))
    if [ "$elapsed_time" -ge "$timeout" ]; then
        log_message "!! Aucune connexion à Internet !!"
        break
    fi
    sleep 0.1
done

if [ -e /home/kiosk/firstTime.ok ]; then
        echo "Démarrage..."
        python3 /home/kiosk/getConfig.py
        source /home/kiosk/boot_script.sh
fi