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.

InstallationProcé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

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