setting debconf selections for keyboard-configuration fails... layout ends up as Afghani

Finally here is the solution and it is so simple but I lost two days to find it :(

Solution 1:

  • this will serve to configure the keyboard when you install keyboard-configuration for the first time, or when you have already installed it and you want to reconfigure it again.
  • this will work inside chroot too :)
  • and you do not need to use debconf-set-selections anymore.
DEBIAN_FRONTEND=noninteractive apt-get install -y console-setup keyboard-configuration
    
# this is the trick, you have to change the default keyboard config before 
# running dpkg-reconfigure or you will always end with what it is configured
#  in /etc/default/keyboard, so for a french keyboard for example:
echo '
XKBMODEL="pc105"
XKBLAYOUT="fr"
XKBVARIANT=""
XKBOPTIONS=""
    
BACKSPACE="guess"
' > /etc/default/keyboard
    
dpkg-reconfigure --frontend noninteractive keyboard-configuration

that's all. Note that the keyboard will not be set while in the chroot, but will be configured for the next reboot.

I tested the above method with debian 10, debian testing (11),debian SID, ubuntu 16.04, ubuntu 18.04, ubuntu 20.04, all installed with debootstrap.

you can see the list of suported options (XKBLAYOUT, XKBVARIANT...) with:

less /usr/share/X11/xkb/rules/xorg.lst

dpkg-reconfigure will use its default us keyboard if there is any error in /etc/default/keyboard, so be sure that you put supported options only (for example ubuntu 16 do not have the azerty variant for the fr layout, so if you put azerty then dpkg-reconfigure will revert to the default us keyboard!)

TIP: if you are attempting to connect with vnc (qemu vnc for example), then you absolutly need to use the tigervnc client for the keyboard to work as wanted, all the other vnc clients are broken. How to set keyboard layout with a VNC client to KVM (libvirt)

Solution 2:

another simple solution for OS's with systemd is:

localectl set-keymap fr 
localectl set-x11-keymap fr

Note: this can not be used inside a chroot, because it require an active dbus connection.

Solution 3:

using setupcon

# let's create  multiple keyboard config
echo '
XKBMODEL="pc105"
XKBLAYOUT="us"
XKBVARIANT=""
XKBOPTIONS=""

BACKSPACE="guess"
' > /etc/default/keyboard.ENbadr

echo '
XKBMODEL="pc105"
XKBLAYOUT="fr"
XKBVARIANT="azerty"
XKBOPTIONS=""

BACKSPACE="guess"
' > /etc/default/keyboard.FRbadr

#activate the lang you want with
setupcon FRbadr

but this do not work inside chroot.


I understand your frustration on this one. Here is how I deal with this in similar context (vagrant provisions), so hopefully the day has come.

The key is to use debconf-utils in order to describe the configuration. First:

sudo apt-get install debconf-utils

You can see the current configuration with:

debconf-get-selections | grep keyboard-configuration

Dealing with all these configuration options can be a bit tedious, so you might want to perform an interactive dpkg-reconfigure keyboard-configuration on one machine, as in the proposed solution. Then, export the new settings with the command above to a new file, say file.conf.

Transfer the file to the machines that need configuration and:

debconf-set-selections < file.conf
dpkg-reconfigure keyboard-configuration -f noninteractive

That's it really.

BONUS: Ansible tasks

In case you use Ansible, here is a piece of my playbook for this matter:

- name: Configuring keyboard [creating file]
  template: src=templates/deb-keyboard.conf.j2 dest=/home/vagrant/.deb-keybard.conf
  register: debconf_template

- name: Configuring keyboard [setting selections]
  shell: debconf-set-selections < /home/vagrant/.deb-keybard.conf
  become: true
  when: debconf_template.changed
  # or use handlers

- name: Configuring keyboard [reconfiguring dpkg]
  command: dpkg-reconfigure keyboard-configuration -f noninteractive
  become: true
  when: debconf_template.changed

So ... hopefully some day someone else will have a proper answer, but here's what I ended up doing, which is the same thing I did years ago without preseed:

interactive keyboard setup on one node:

dpkg-reconfigure keyboard-configuration

Then when that's done, copy the console setup stuff

cd
tar czf console-setup.tgz /etc/console-setup

Then send that file to all nodes, or put it on http somewhere.

Then install it on every node with a script, rather than interactively one at a time:

cd
wget http://somewebserver/console-setup.gz -O ~/console-setup.tgz
cd /
mv /etc/console-setup /etc/console-setup.bak
tar xzf ~/console-setup.tgz
gunzip -c /etc/console-setup/cached.kmap.gz | loadkeys

And as long as you don't reconfigure the keyboard some other way, it'll probably remain this way (as it has for years on the previous install). But maybe there are some things that would mess again, such as:

DEBIAN_FRONTEND=noninteractive dpkg-reconfigure keyboard-configuration