Documentation menu
Ubuntu sign-in

Install

One package goes on every machine: the PAM module, the helper it runs, and the admin tool. Installing it changes nothing until the administrator configures the machine.

Install from the U2 Secured repository

bash
curl -fsSL https://u2secured.com/downloads/linux/u2secured.gpg | sudo tee /usr/share/keyrings/u2secured.gpg > /dev/null
gpg --show-keys /usr/share/keyrings/u2secured.gpg   # B725 4213 9302 02C4 8B19  6810 E6C4 2653 4D95 43BA
echo "deb [signed-by=/usr/share/keyrings/u2secured.gpg] https://u2secured.com/downloads/linux stable main" \
  | sudo tee /etc/apt/sources.list.d/u2secured.list
sudo apt update && sudo apt install u2auth
u2auth-admin help

Add the signed U2 Secured APT repository once, then install u2auth like any other package; apt upgrade brings each new release, security fixes included. The packages are signed with the key whose fingerprint is B725 4213 9302 02C4 8B19 6810 E6C4 2653 4D95 43BA: check it before trusting the key. Ubuntu 22.04, 24.04 and Debian 12 or newer, on amd64 and arm64. Installing it gates nothing: the desktop profile it ships is off by default, and SSH is gated only once the administrator edits sshd and PAM. Upgrading to a newer .deb keeps the config, the registration, users’ codes and any PAM lines. It installs:

  • /usr/lib/u2auth/pam_u2auth.so and /usr/lib/u2auth/u2auth-pam-helper: the module, and the logic it runs for each login (as root).
  • /usr/sbin/u2auth-admin: the admin tool.
  • /usr/share/pam-configs/u2auth: the profile for desktops, sudo and su, off until enabled.
  • /usr/share/doc/u2auth/u2auth.conf.example: the starting point for the config.
  • /etc/u2auth and /var/lib/u2auth (0700): config, registration and users’ offline codes, empty for now.

Or download the .deb

bash
curl -fsSLO https://u2secured.com/downloads/linux/u2auth_amd64.deb     # u2auth_arm64.deb on ARM
curl -fsSL https://u2secured.com/downloads/linux/SHA256SUMS | sha256sum -c --ignore-missing
sudo apt install ./u2auth_amd64.deb

For a single machine, or one with no route to the repository. Check the download against SHA256SUMS before installing it. A machine installed this way gets no updates from apt, so download again for each release.

Build the .deb yourself

bash
cd apps/authenticator/integrations/ssh-mfa
packaging/build-deb.sh                  # amd64 + arm64 into packaging/dist/; needs Go and Docker
ARCHES=arm64 packaging/build-deb.sh     # one architecture

build-deb.sh compiles the PAM module inside ubuntu:22.04, so the package runs on Ubuntu 22.04, Debian 12 and newer. The Go binaries are static.

Or build the pieces from source

bash
cd apps/authenticator/integrations/ssh-mfa
export GOOS=linux GOARCH=amd64 CGO_ENABLED=0     # arm64 for ARM machines
go build -o u2auth-pam-helper ./cmd/u2auth-pam-helper
go build -o u2auth-admin      ./cmd/u2auth-admin
gcc -O2 -Wall -fPIC -shared -o pam_u2auth.so pam/pam_u2auth.c -lpam

The Go binaries are static, so build them once per architecture. Build the C module against the PAM headers of the distribution you deploy to.

Install the pieces by hand

bash
sudo install -d -m 0755 /usr/lib/u2auth /etc/u2auth
sudo install -d -m 0700 /var/lib/u2auth
sudo install -m 0644 pam_u2auth.so     /usr/lib/u2auth/pam_u2auth.so
sudo install -m 0755 u2auth-pam-helper /usr/lib/u2auth/u2auth-pam-helper
sudo install -m 0755 u2auth-admin      /usr/sbin/u2auth-admin
sudo install -m 0644 pam/pam-configs/u2auth /usr/share/pam-configs/u2auth   # only for desktops

pam_u2auth.so stays deliberately small: it starts u2auth-pam-helper for each login and relays its prompts. All the logic lives in the helper, which runs as root inside the PAM stack. That is why the config can be root-only.

Alternative: ForceCommand

bash
CGO_ENABLED=0 GOOS=linux go build -o login_u2auth ./cmd/login_u2auth
sudo useradd --system --no-create-home --shell /usr/sbin/nologin u2auth
sudo install -o u2auth -g root -m 4755 login_u2auth /usr/local/bin/login_u2auth

login_u2auth is not in the .deb. ForceCommand runs as the user logging in, so login_u2auth is setuid to a dedicated u2auth user: the only account that can read its config and API key. It drops back to the user before starting their shell. Without the setuid bit every login fails. With a readable config, any user could take the key and pair a phone as anyone.