{"id":13513021,"url":"https://github.com/carniz/ubuntu-yubikey-setup","last_synced_at":"2025-03-31T00:30:47.743Z","repository":{"id":44708170,"uuid":"163108820","full_name":"carniz/ubuntu-yubikey-setup","owner":"carniz","description":"A guide for setting up Yubikey support on an Ubuntu 18.04 / 20.04-based distribution (such as elementaryOS 5.x / 6.x) ","archived":false,"fork":false,"pushed_at":"2022-01-29T19:14:08.000Z","size":22,"stargazers_count":41,"open_issues_count":2,"forks_count":7,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T15:52:00.421Z","etag":null,"topics":["elementaryos","ubuntu","yubikey"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carniz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-25T20:10:15.000Z","updated_at":"2025-03-14T21:32:59.000Z","dependencies_parsed_at":"2022-09-07T16:13:39.240Z","dependency_job_id":null,"html_url":"https://github.com/carniz/ubuntu-yubikey-setup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carniz%2Fubuntu-yubikey-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carniz%2Fubuntu-yubikey-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carniz%2Fubuntu-yubikey-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carniz%2Fubuntu-yubikey-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carniz","download_url":"https://codeload.github.com/carniz/ubuntu-yubikey-setup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246399816,"owners_count":20770907,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elementaryos","ubuntu","yubikey"],"created_at":"2024-08-01T04:00:36.421Z","updated_at":"2025-03-31T00:30:47.400Z","avatar_url":"https://github.com/carniz.png","language":null,"funding_links":[],"categories":["Configuration Guides"],"sub_categories":[],"readme":"# ubuntu-yubikey-setup\n\nThis is a guide for configuring an Ubuntu 18.04/20.04-based distribution (such as elementaryOS 5.0 \"Juno\" / elementaryOS 6.0 \"Odin\") with:\n* Yubikey-backed full disk encryption (using challenge-response mode)\n* System wide Yubikey login (graphical lightdm + non-graphical TTYs)\n* Yubikey challenge-response mode for SUDO\n* FIDO U2F authentication\n* Yubikey for SSH authentication\n\n## Prerequisites\n- An existing installation of an Ubuntu 18.04/20.04-based distro with full-disk encryption\n- A 2-pack of Yubikeys (version 5 NFC), if you only have one Yubikey you can skip the steps for the second key.\n\n### Add the Yubico APT repository (NOTE: not needed for Ubuntu 20.04)\n```\nsudo apt install software-properties-common  # provides add-apt-repository\nsudo add-apt-repository ppa:yubico/stable \u0026\u0026 sudo apt-get update\n```\n\n### Install required packages\n```\nsudo apt install libpam-yubico yubikey-manager\n```\n\n### For each yubikey:\nIf you require that the Yubikey must be touched for each challenge-response operation, pass `--touch` to `ykman otp chalresp`. This greatly enhances the security of the challenge-response mode since it needs a physical confirmation.\n```\nykman otp chalresp --touch --generate 2\nykpamcfg -2\n```\nIf you on the other hand want the key to automatically send a response to each challenge, omit the `--touch`. **Note that this is less secure since a malicious script could get a response from the key without your permission.**\n```\nykman otp chalresp --generate 2\nykpamcfg -2\n```\n\n### Require yubikey for system-wide authentication\nThis will require a yubikey present for graphical (lightdm) logins, non-graphical logins on TTYs, as well as `sudo`:\n\n```\necho \"auth    required   pam_yubico.so mode=challenge-response\" | sudo tee -a /etc/pam.d/common-auth\n```\n\n### Full disk encryption setup\n\nInstall the `yubikey-luks` package:\n```\nsudo apt install yubikey-luks\n```\nIf you are unsure of which device that contains your LUKS partition, run `lsblk`. In the below example, the device is `/dev/sda3`:\n```\n$ lsblk\nNAME                                        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT\nsda                                           8:0    1 119,3G  0 disk\n├─sda1                                        8:1    1   512M  0 part  /boot/efi\n├─sda2                                        8:2    1   732M  0 part  /boot\n└─sda3                                        8:3    1   118G  0 part\n  └─sdb3_crypt                              253:0    0   118G  0 crypt\n    ├─elementary--vg-root                   253:1    0   117G  0 lvm   /\n    └─elementary--vg-swap_1                 253:2    0   976M  0 lvm   [SWAP]\nnvme0n1                                     259:0    0 953,9G  0 disk\n├─nvme0n1p1                                 259:1    0   512M  0 part\n├─nvme0n1p2                                 259:2    0 937,5G  0 part\n└─nvme0n1p3                                 259:3    0  15,9G  0 part\n```\nList key slots for your LUKS device (only slot 0 should be used by default)\n```\nsudo cryptsetup luksDump /dev/sda3\n```\nConfigure slot 1 for yubikey number 1:\n```\nsudo yubikey-luks-enroll -d /dev/sda3 -s 1\n```\nConfigure slot 2 for yubikey number 2:\n```\nsudo yubikey-luks-enroll -d /dev/sda3 -s 2\n```\n*Hint: You will be asked to enter the `yubikey challenge password`. This is a password you can choose, which will be used for unlocking the yubikey prior to unlocking the FDE.*  \n\nNow restart your computer. Once verified that the yubikey can be used to unlock the disk, remove the default slot for the static password (slot 0):\n```\nsudo cryptsetup -q luksKillSlot /dev/sda3 0\n```\n\n**Update for Ubuntu 20.04:**\nThe Yubikey won't get used for unlocking the disk with Ubuntu 20.04 / elementaryOS 6 unless you first run the below:\n```\nsudo sed -i 's|none luks|none luks,keyscript=/usr/share/yubikey-luks/ykluks-keyscript,discard|' /etc/crypttab\nsudo update-initramfs -u\n```\n\n### Lock the screen when yubikey is removed\nInstall the `finger` package:\n```\nsudo apt install -y finger\n```\n**NB: For elementaryOS 6.x you'll also need to install gnome-screensaver:**\n```\nsudo apt install -y gnome-screensaver\n```\n\nCreate the `yubikey-removed-script`:\n```\ncat \u003c\u003c 'EOF' | sudo tee /usr/local/bin/yubikey-removed-script\n#!/usr/bin/env bash\n# Locks the screen if a Yubikey is not plugged in\n\nif ! env | grep DEVNAME; then\n  exit 0;\nfi\n\ngetXuser() {\n  user=`finger | grep -m1 \":$displaynum \" | awk '{print $1}'`\n  if [ x\"$user\" = x\"\" ]; then\n    user=`finger| grep -m1 \":$displaynum\" | awk '{print $1}'`\n  fi\n  if [ x\"$user\" != x\"\" ]; then\n    userhome=`getent passwd $user | cut -d: -f6`\n    export XAUTHORITY=$userhome/.Xauthority\n  else\n    export XAUTHORITY=\"\"\n  fi\n}\n\nif [ -z \"$(lsusb | grep Yubico)\" ] ; then\n  for x in /tmp/.X11-unix/*; do\n      displaynum=`echo $x | sed s#/tmp/.X11-unix/X## | sed s#/##`\n      getXuser\n      if [ x\"$XAUTHORITY\" != x\"\" ]; then\n          # extract current state\n          export DISPLAY=\":$displaynum\"\n      fi\n  done\n\n  enable_timer=true\n\n  if [ \"${enable_timer}\" == \"true\" ]; then\n    for i in {1..5}; do\n      sleep 1;\n      echo $(( $i*20 ));\n    done | zenity --title \"Yubikey removed\" --text \"Locking the screen\\n(Press Escape to cancel)\" --width 400 --progress --no-cancel --auto-close\n    answer=$?\n  fi\n\n  LOCKER=\"light-locker\"\n  LOCKER_COMMAND=\"${LOCKER}-command\"\n  if [ -z \"$(which ${LOCKER_COMMAND})\" ]; then\n    LOCKER=\"gnome-screensaver\"\n    LOCKER_COMMAND=\"${LOCKER}-command\"\n  fi\n\n  if [[ \"${enable_timer}\" != \"true\" ]] || [[ ${answer} -eq 0 ]]; then\n    export grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pidof ${LOCKER})/environ\n    logger \"YubiKey Removed - Locking Workstation\"\n    su $user -c \"/usr/bin/${LOCKER_COMMAND} -l\"\n  fi\n\nfi\n\nEOF\n```\n\nMake it executable:\n```\nsudo chmod +x /usr/local/bin/yubikey-removed-script\n```\n\nCreate a udev rule to trigger the `yubikey-removed-script`:\n```\ncat \u003c\u003cEOF | sudo tee /etc/udev/rules.d/yubikey-screenlock.rules\nACTION==\"remove\", ENV{ID_VENDOR}==\"Yubico\", RUN+=\"/usr/local/bin/yubikey-removed-script\"\nEOF\n```\n\n## FIDO U2F setup\nDownload https://raw.githubusercontent.com/Yubico/libu2f-host/master/70-u2f.rules and put it in `/etc/udev/rules.d/70-u2f.rules`. Reboot your computer and then head over to https://demo.yubico.com/u2f and follow the instructions. After the process, your browser will be capable of using U2F authentication with a number of services.\n\nFor Github, you can add your Yubikeys as U2F devices at https://github.com/settings/two_factor_authentication/configure after you first have enabled generic 2-factor authentication using a mobile app such as Google Authenticator, see https://help.github.com/articles/configuring-two-factor-authentication/#configuring-two-factor-authentication-using-fido-u2f\n\n## GPG/SSH setup\n\nInstall the `opensc` package:\n```\nsudo apt install opensc -y\n```\nFor each yubikey: change the default PIN+PUK:\n```\nyubico-piv-tool --action change-pin\nyubico-piv-tool --action change-puk\n```\n\nGenerate a public RSA certificate:\n```\nyubico-piv-tool --slot 9a --action generate -o public.pem\n```\n\nGenerate a self-signed RSA certificate:\n```\nCERT_CANONICAL_NAME=\"${USER}'s SSH Key\"\nPUBLIC_KEY_FILE=\"public.pem\"\nOUTPUT_FILENAME=\"private.pem\"\nyubico-piv-tool \\\n  --action verify-pin \\\n  --action selfsign-certificate \\\n  --slot 9a \\\n  --subject \"/CN=$CERT_CANONICAL_NAME/\" \\\n  --input $PUBLIC_KEY_FILE \\\n  --output $OUTPUT_FILENAME\n```\n\nImport the newly created .pem file:\n```\nyubico-piv-tool \\\n  --action import-certificate \\\n  --slot 9a \\\n  --input private.pem \\\n  --touch-policy cached\n```\n\nCheck the status:\n```\nyubico-piv-tool --action status\n```\n\nAdd the PKCS11Provider to the SSH config on the client side:\n```\necho \"PKCS11Provider /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so\" | sudo tee -a /etc/ssh/ssh_config\n```\n\n## On the server (Ubuntu)\nInstall required packages:\n```\nsudo apt install software-properties-common  # provides add-apt-repository\nsudo add-apt-repository ppa:yubico/stable -y\nsudo apt update\nsudo apt install libpam-yubico -y\n```\nEnable `ChallengeResponseAuthentication` and PAM usage in `/etc/ssh/sshd_config`:\n```\nChallengeResponseAuthentication yes\nUsePAM yes\n```\n\nCreate the SSH authfile:\n```\nkey1=$(echo \u003ctouch first yubikey\u003e | cut -c -12)\nkey2=$(echo \u003ctouch second yubikey\u003e | cut -c -12)\necho \"vagrant:${key1}:${key2}\" | sudo tee /etc/ssh/authorized_yubikeys\n```\n### Configure the SSH daemon\nNote: get API keys from https://upgrade.yubico.com/getapikey/ (Needed for configuring the server side)\n```\nYubikey 1\nClient ID:\t\u003cclient id 1\u003e\nSecret key:\t\u003csecret key 1\u003e\n\nYubikey 2\nClient ID:\t\u003cclient id 2\u003e\nSecret key:\t\u003csecret key 2\u003e\n```\nUsing the API keys above, add an entry to the `key_map` for each Yubikey. If you want\n1-factor authentication with only the Yubikey present instead of 2-factor authentication (SSH key + YubiKey present), set REQUIRED_OR_SUFFICIENT\nto \"sufficient\" instead of \"required\".\n```\ndeclare -A key_map\nkey_map[\"\u003cclient id 1\u003e\"]=\"secret key 1\u003e\"\nkey_map[\"\u003cclient id 2\u003e\"]=\"secret key 2\u003e\"\nREQUIRED_OR_SUFFICIENT=\"required\"\nFILE=\"/etc/pam.d/sshd\"\nfor key in ${!key_map[@]}; do\n    secret=${key_map[${key}]}\n    LINE=\"auth $REQUIRED_OR_SUFFICIENT pam_yubico.so id=$key key=$secret authfile=/etc/ssh/authorized_yubikeys\"\n    sudo sed -i \"1s|^|$LINE \\n|\"  $FILE\ndone\n```\n\n### Links:\nhttps://support.yubico.com/support/solutions/articles/15000011355-ubuntu-linux-login-guide-challenge-response\n\nhttps://dgunter.com/2018/09/30/securing-linux-full-disk-encryption-with-a-multi-factor-hardware-token/\n\nhttps://blog.programster.org/yubikey-cheatsheet\n\nhttps://www.linode.com/docs/security/authentication/how-to-use-yubikey-for-two-factor-ssh-authentication/\n\nhttps://newbedev.com/yubikey-two-factor-authentication-full-disk-encryption-via-luks\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarniz%2Fubuntu-yubikey-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarniz%2Fubuntu-yubikey-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarniz%2Fubuntu-yubikey-setup/lists"}