I have a machine I netinstalled, with german keyboard set, but it ignored my setting, and it is installed with US keyboard. I'm sure I set it, because if I don't set it, it asks interactively, but I wanted an unattended install.

It's Ubuntu 12.04.3

So now afterwards, i want to script a fix to make it the german keyboard.

So first I interactively set the settings on one machine, then read the settings to see their values, and then on another machine, I set the selections with:

debconf-set-selections <<< "keyboard-configuration keyboard-configuration/altgr select The default for the keyboard layout"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/compose select No compose key"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean false"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/layoutcode string de"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/layout select German"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/modelcode string pc105"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/model select Generic 105-key (Intl) PC"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/optionscode string "
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/store_defaults_in_debconf_db boolean true"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/switch select No temporary switch"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/toggle select No toggling"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/unsupported_config_layout boolean true"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/unsupported_config_options boolean true"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/unsupported_layout boolean true"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/unsupported_options boolean true"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/variantcode string "
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/variant select German"
debconf-set-selections <<< "keyboard-configuration keyboard-configuration/xkb-keymap select "

Then I show the selections with:

debconf-show keyboard-configuration

And here is the output:

* keyboard-configuration/modelcode: pc105
* keyboard-configuration/unsupported_config_options: true
* keyboard-configuration/unsupported_config_layout: true
* keyboard-configuration/toggle: No toggling
* keyboard-configuration/compose: No compose key
* keyboard-configuration/layout: German
* keyboard-configuration/xkb-keymap:
* keyboard-configuration/variant: German
* keyboard-configuration/switch: No temporary switch
* keyboard-configuration/unsupported_options: true
* keyboard-configuration/altgr: The default for the keyboard layout
* keyboard-configuration/ctrl_alt_bksp: false
* keyboard-configuration/unsupported_layout: true
* keyboard-configuration/variantcode:
* keyboard-configuration/model: Generic 105-key (Intl) PC
* console-setup/ask_detect: false
* keyboard-configuration/layoutcode: de
* keyboard-configuration/store_defaults_in_debconf_db: true
* keyboard-configuration/optionscode:

And then to reconfigure the package to make the system actually use the settings, I run:

DEBIAN_FRONTEND=noninteractive dpkg-reconfigure keyboard-configuration

And here is the output:

update-initramfs: deferring update (trigger activated)

And then to check what happened, I check the settings again:

debconf-show keyboard-configuration

And here is the output:

* keyboard-configuration/modelcode: a4techKB21
  keyboard-configuration/unsupported_config_options: true
  keyboard-configuration/unsupported_config_layout: true
* keyboard-configuration/toggle: Caps Lock
* keyboard-configuration/compose: No compose key
* keyboard-configuration/layout: Afghani
* keyboard-configuration/xkb-keymap: af
* keyboard-configuration/variant: Afghani
* keyboard-configuration/switch: No temporary switch
  keyboard-configuration/unsupported_options: true
* keyboard-configuration/altgr: The default for the keyboard layout
* keyboard-configuration/ctrl_alt_bksp: false
  keyboard-configuration/unsupported_layout: true
* keyboard-configuration/variantcode: ,
* keyboard-configuration/model: A4Tech KB-21
* console-setup/ask_detect: false
* keyboard-configuration/layoutcode: us,af
* keyboard-configuration/store_defaults_in_debconf_db: true
* keyboard-configuration/optionscode: grp:caps_toggle,grp_led:scroll

Why oh why did it turn it into an Afghani layout (selected first in the alphabetical list for every question)? Why can't it just use my settings, or at least ignore, them, not set them with bogus values!

And in the past, I have used something more like this instead, but with other things (like postfix, etc.):

apt-get install --reinstall keyboard-configuration

But in this case with keyboard-configuration, it does the same as

DEBIAN_FRONTEND=noninteractive dpkg-reconfigure.

I also compared the interactively set up machine to the one scripted with the above before the reconfigure, and the entire machine's debconf is identical except for "grub-pc grub-pc/install_devices ..." which has an id, and is obviously not relevant. And if I run the scripted method on the interactively installed machine, it doesn't reset to Afghani, so the systems act different despite identical debconf.

Is there a solution to this?

I have already seen:

What does "dpkg-reconfigure keyboard-configuration" actually do? http://ubuntuforums.org/showthread.php?t=1793250 automate dpkg-reconfigure tzdata


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 '
' > /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 '

' > /etc/default/keyboard.ENbadr

echo '

' > /etc/default/keyboard.FRbadr

#activate the lang you want with
setupcon FRbadr

but this do not work inside chroot.

  • I tried your solution 1 on an Ubuntu 18.04 machine, and it didn't work. Do you have a table for the possible values for the variables? Maybe I just set something wrong. Or is there a parser or some way to get verbose output? debconf-show keyboard-configuration actually says what I entered, but the keyboard acts like it's in US mode.
    – Peter
    Jan 22 at 18:21
  • @peter do you mean the variables (XKBLAYOUT, XKBVARIANT...)? if yes then you can find it with: less /usr/share/X11/xkb/rules/xorg.lst. you have absolutely to create a correct /etc/default/keyboard, because if it contains any error then keyboard-configuration will silently fallback to US keyboard. just make a test with XKBLAYOUT="fr" (use localectl to see if the keyboard was changed successfully), if it works with fr then you will know that it works at less, so you can investigate with the correct variables for your language. test it and tell me if it doesn't work. Jan 22 at 21:09
  • using only what's in xorg.lst, it works. Great!
    – Peter
    Jan 25 at 12:15
  • one thing to add... I tested again adding wrong values and noticed after some unknown time that /etc/default/keyboard had the previous working values again, not the wrong values. So I suppose that can be a test to see if it's valid.
    – Peter
    Jan 25 at 14:31
  • yes if I put invalid values they are discarded silently and the defaults one are used, there is a service responsible of this: systemctl cat keyboard-setup which runs /lib/console-setup/keyboard-setup.sh which runs at the end setupcon -k Jan 26 at 1:57

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

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:

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
  • Great workaround this one.
    – Wtower
    Feb 1 '16 at 15:54

Turned out that in my case, I'd not specified the correct type for the debconf modules in Ansible. If anyone else is trying to do this with Ansible, then in your "template" machine (the one you're using to get all the right settings in the first place) install debconf-utils and run debconf-get-selections | grep keyboard-config then run debconf-show keyboard-configuration. This gives you a list of the things which are changed (items with the *'s next to them). Note that the items in the debconf-get-selections tell you what type they are.

For me to set them to English (UK) I needed the following ansible playbook task:

- name: Set keyboard layout debconf: name: "keyboard-configuration" question: "keyboard-configuration/{{ item.key }}" value: "{{ item.value }}" vtype: "{{ item.type|default('string') }}" with_items: - { key: "altgr", value: "The default for the keyboard layout", vtype: "select" } - { key: "compose", value: "No compose key", vtype: "select" } - { key: "ctrl_alt_bksp", value: "false", type: "boolean" } - { key: "variant", value: "English (UK)", vtype: "select" } - { key: "layout", value: "English (UK)", vtype: "select" } - { key: "model", value: "Generic 105-key PC (intl.)", vtype: "select" }

Here's two sample lines from the debconf-* commands I referenced above:

  • (debconf-get-selections) keyboard-configuration keyboard-configuration/layout select English (UK)
  • (debconf-show) * keyboard-configuration/layout: English (UK)

I used the answers here, to get it running with saltstack:

I used a jinja template for the configuration (I removed some entries to get it shorter):

{% if grains["domain"] == "mydomain.de" %}
{% load_yaml as keyboard_data %}
    "type": "string"
    "value": "de"
    "type": "select"
    "value": "German"
{% endload %}
{% else %}
{% load_yaml as keyboard_data %}
    "type": "string"
    "value": "us"
    "type": "select"
    "value": "English (US)"
{% endload %}
{% endif %}

and now my state is like this:

  - name: "keyboard-configuration"
  - data: {{ keyboard_data }}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.