SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

authd: cloud logins on your Ubuntu server

How Canonical's authd logs Ubuntu server users in with Google or Entra ID, what the broker snaps cost you, and the break-glass account to build first.

What authd does on an Ubuntu server

authd is Canonical's authentication daemon for Ubuntu, and it lets a person log in to an Ubuntu server with a Google or Microsoft Entra ID account instead of a local password. It plugs into PAM (pluggable authentication modules), the layer that decides whether a login attempt succeeds, and it answers user lookups so the account exists on the box without anyone running adduser. A separate process called a broker does the talking to the identity provider.

For a small team the value is narrow and real: it removes the hand-made account. Today, when someone leaves, you visit each server, find their local user, and delete it. With authd you disable them once at the provider and their next login attempt on every box is refused. That is worth having. It is also smaller than Canonical's marketing suggests, and the parts the marketing skips are what decide whether this fits three servers and a Google Workspace.

One note before any commands. The authd package and the broker snaps both move, so version numbers and prompt wording printed in a guide go stale within weeks. Every step below names the command that prints the truth on your own machine. Trust that over any text you read here.

Which Ubuntu releases can run authd

Checked against Canonical's authd installation guide on 30 August 2026: Ubuntu Desktop or Server, release 24.04 LTS or later, on amd64 or arm64. On Ubuntu 26.04 LTS the authd package comes from the Ubuntu archive. On 24.04 LTS it does not, so you add Canonical's PPA (personal package archive) first. Nothing older is in scope, so a 22.04 box needs a release upgrade before it needs authd at all.

lsb_release -a
dpkg --print-architecture

Run those first. If the release is older than 24.04, stop here and upgrade the server, which is a bigger job than this one.

The broker model, and why device code flow is the interesting part

authd never speaks OAuth itself. It exposes an interface over D-Bus, the local message bus, and a broker implements that interface for exactly one provider. Canonical ships three broker snaps: authd-google for Google IAM, authd-msentraid for Microsoft Entra ID, and authd-oidc, a generic OpenID Connect broker whose documented example is Keycloak. More than one broker can be installed and enabled on the same machine.

The flow is the part worth understanding, because a server has no browser and no screen. authd uses the OAuth 2.0 device authorisation grant, normally called device code flow. At the login prompt the server shows a URL and a short code. You open that URL on your phone or laptop, sign in there, and enter the code. The server polls the provider until it sees the approval, then finishes the PAM conversation and hands you a shell.

Two things follow from that design. The server never receives your password, so a compromised box does not hand an attacker your Workspace credentials, and whatever multi-factor method your provider already enforces applies to an SSH login with nothing extra installed on the server. Against that, a login now requires a human holding a second device. That single fact is why authd cannot cover automation, and the section below on authorized_keys follows directly from it.

Install authd and one broker

# Ubuntu 24.04 LTS only. Skip this line on 26.04 LTS.
sudo add-apt-repository ppa:ubuntu-enterprise-desktop/authd
sudo apt update
sudo apt install authd

Then install the broker for your provider. Pick one line:

sudo snap install authd-google
sudo snap install authd-msentraid
sudo snap install authd-oidc

Check both halves landed. systemctl is-active authd should report the daemon running, and snap list shows the broker with the revision and version your machine actually pulled, which is the number to quote in a bug report.

systemctl is-active authd
snap list authd-google

Notice what just happened: the broker arrived as a snap, and there is no Debian package alternative. On a server you keep deliberately snap-light, that is a real decision, not a detail. snapd refreshes snaps on its own schedule, so an authentication component on your box updates without you asking. You can hold refreshes and pick your own window, and the trade-offs of doing that are covered in holding and scheduling snap refreshes on Ubuntu Server. Decide that before you make logins depend on the snap, not after.

Point authd at the broker

authd only uses a broker it has been told about. Each broker snap ships a small declaration file, and you copy it into /etc/authd/brokers.d/:

sudo install -d /etc/authd/brokers.d
sudo cp /snap/authd-google/current/conf/authd/google.conf /etc/authd/brokers.d/

For the other two brokers the source paths are /snap/authd-msentraid/current/conf/authd/msentraid.conf and /snap/authd-oidc/current/conf/authd/oidc.conf. Read the file you copied rather than trusting a copy printed anywhere: cat /etc/authd/brokers.d/google.conf shows you what your version actually declares. Then restart the daemon so it picks up the new broker.

sudo systemctl restart authd

Register an application at your provider

Device code flow needs an OAuth client registered at the provider, and this step happens in a web console, not on the server. For Google IAM you create credentials of the client type meant for televisions and limited input devices, which is the type that supports device code. For Microsoft Entra ID you create an app registration in the Entra admin center and grant it delegated Microsoft Graph permissions. For Keycloak you create an OpenID Connect client.

The broker then needs those details. Its configuration lives at /var/snap/authd-<broker>/current/broker.conf, so /var/snap/authd-google/current/broker.conf for the Google broker. Open it and set the issuer URL and client ID under the [oidc] section, plus a client secret where your provider issues one. The file ships with comments describing every key it supports, and those comments match your installed version, which no blog post can promise. Read them.

Brokers run as their own systemd units, so a config change needs the broker restarted, not just authd:

sudo systemctl restart snap.authd-google.authd-google.service
sudo systemctl restart snap.authd-msentraid.authd-msentraid.service
sudo systemctl restart snap.authd-oidc.authd-oidc.service

If a broker refuses to come up, journalctl -u snap.authd-google.authd-google.service -n 50 is where the reason appears. A broker that fails to start after a config edit is normal on the first try, because a wrong issuer URL is caught at startup and not at login.

Who is allowed to log in

By default the first user who authenticates on a machine becomes its owner, and only that person may log in. Everyone else is refused until they are listed. That default surprises people, because the second team member gets a clean rejection with the tenant configured correctly. The [users] section of broker.conf controls it, with allowed_users taking a list of provider handles, the literal OWNER, or ALL for every user who authenticates successfully.

Group membership from the provider is a thinner story. As of the August 2026 documentation, groups are supported for the msentraid broker only. With Google Workspace, a Workspace group does not become a Linux group, so sudo is not driven by your directory. You grant it per machine through extra_groups and owner_extra_groups in the broker config. That is bookkeeping you keep doing by hand on every box, which matters because the whole promise was fewer hand-edits. Keep those grants tight while you are there, on the same reasoning as running services and people under least-privilege accounts.

Build the break-glass account before you touch sshd

Do this step first. An authd deployment adds a dependency on a third party to the act of logging in, and there are several ways that ends with nobody able to reach the server: a provider outage, a tenant misconfiguration, an OAuth client someone deletes, or a broker snap that refreshes into a version your config no longer suits.

sudo adduser breakglass
sudo usermod -aG sudo breakglass

Now test it, from a second SSH session, while your first session stays open. Log in as breakglass with its password and run sudo -v. An untested break-glass account is not a break-glass account, it is an assumption. This works over SSH because the sshd settings in the next section turn on PAM keyboard-interactive authentication, which lets local accounts log in by password through PAM even where PasswordAuthentication no is set. Keep the password long and store it where you would store a recovery key. If you have never set one on this box, changing a VPS password from the provider console covers the console route you would fall back to, and that console is your last resort if SSH is gone entirely. This belongs in the same checklist as the first ten minutes on a new VPS.

Making SSH logins work, including the very first one

authd needs sshd to hand the login to PAM. Create /etc/ssh/sshd_config.d/authd.conf:

UsePAM yes
KbdInteractiveAuthentication yes

Validate before restarting, because sshd -t prints nothing when the config parses and prints the offending file and line when it does not. A syntax error plus a restart is how people lock themselves out of a working server.

sudo sshd -t
sudo systemctl restart ssh

The second half is the one that catches everybody. A user who has never logged in does not exist on the server yet, so sshd rejects the connection before authd is ever consulted. Allow first-time logins by domain in the broker's [users] section:

[users]
ssh_allowed_suffixes_first_auth = @example.com

Several domains go in the same key, separated by commas. Restart the broker afterwards. Then connect with the full provider handle in front of the host, which looks wrong the first time and is correct: ssh alice@example.com@server.example.net. After a successful login, getent passwd alice@example.com returns a passwd entry for that user, which is the proof that authd created the account rather than sshd matching something local.

One more practical setting. Device code flow takes longer than typing a password, because you are moving to another device to approve it. LOGIN_TIMEOUT in /etc/login.defs bounds how long a login may take, and Canonical's documentation notes the default is often too short for this flow. If logins abort while you are still on your phone, that is the value to raise. If they fail instantly instead, you are looking at a different problem, and the usual causes of SSH permission denied still apply here.

What authd does not replace

authd authenticates humans at an interactive login. It does not authenticate your automation, and it never will, because device code flow needs a person with a browser. Your CI jobs, backup scripts, Ansible runs and deploy hooks keep using SSH keys, so authorized_keys stays on every box and so does the hygiene around it: naming keys, rotating them, and knowing which key belongs to which robot. Start from the basics of managing SSH keys across servers if that is currently informal.

There is a sharper edge here, and Canonical's own security overview states it. If SSH public key authentication is enabled, a user whose access has been revoked at the identity provider can still log in with their key, because key authentication never reaches authd. Disabling someone in Workspace does nothing to a public key sitting in ~/.ssh/authorized_keys on your server. So if you deploy authd expecting central revocation and leave key authentication on for those users, you have the reporting benefit and not the security one. The documented fix is a match block in /etc/ssh/sshd_config.d/authd.conf:

Match User *@example.com
    PubkeyAuthentication no

The mirror image is worth writing too, so that only authd users get the interactive prompt and everyone else stays key-only:

KbdInteractiveAuthentication no
PasswordAuthentication no

Match User *@example.com
    KbdInteractiveAuthentication yes

If what you actually wanted was one place to control who reaches which server, without a cloud tenant in the path, an SSH certificate authority solves a different half of this problem. Comparing LDAP against an SSH certificate authority lays out which of the two matches which pain, and the two combine cleanly: authd for the humans at a shell, short-lived certificates for everything scripted.

The costs, stated plainly

A provider outage is a login outage, unless you accept the opposite risk. By default, a user who has authenticated once can log in with a local password when the provider cannot be reached, which prevents lockouts and lets a revoked user in during an outage. Setting force_access_check_with_provider to true closes that gap and makes reaching the provider a hard requirement for logging in. Both settings are defensible. Pick one on purpose, write down which you picked, and make sure the break-glass account exists either way.

UIDs and GIDs are per machine. authd assigns each user a unique numeric ID on the box where they first log in, and those numbers are not coordinated between machines. So alice@example.com can be 1002 on one server and 1005 on another. NFS and Samba need ID mapping, and any workflow that copies files by numeric owner across hosts will land them on the wrong account. This is the point where running a small fleet of servers with consistent configuration starts to matter more than the login itself.

The box stores live tokens. OAuth refresh tokens and cached provider user info are kept under /var/snap/authd-<broker>/current/, currently unencrypted, in directories restricted to root. Canonical's recommendation is full disk encryption, which on a rented VPS you may not fully control. Treat the server as holding a usable credential for each user who has logged in.

You are trusting one more administrator. Whoever runs the Workspace or Entra tenant can now grant themselves a login on your servers. In a three-person team that is usually the same person, so it is fine. Say it out loud anyway.

Is this the right tool for three servers?

If you already pay for Google Workspace or Entra ID, and your real pain is that offboarding means SSH-ing into every box, authd is a good fit and the setup above is an afternoon. If your pain is instead that you have accumulated SSH keys nobody can attribute, authd does not fix that, and adding it will not make the keys go away. If you have no cloud tenant and were considering standing one up purely to enable this, price the whole thing first, because a self-hosted identity provider is a service you then operate and back up. The authd-oidc broker does make that path work, and the trade-offs between Keycloak, Authentik and Zitadel is the comparison to read before you commit to running one.

FAQ

Which Ubuntu releases support authd?

Canonical's installation guide lists Ubuntu Desktop or Server, release 24.04 LTS or later, on amd64 or arm64, checked on 30 August 2026. On Ubuntu 26.04 LTS the authd package is in the Ubuntu archive. On 24.04 LTS you first add the PPA with sudo add-apt-repository ppa:ubuntu-enterprise-desktop/authd. Releases older than 24.04 are not supported, so check with lsb_release -a before planning anything.

Can I use authd for CI jobs, Ansible or backup scripts?

No. authd logs in through the OAuth 2.0 device authorisation grant, which requires a person to open a URL in a browser and enter a code. Nothing non-interactive can complete that. Automation keeps using SSH keys and authorized_keys, so key management stays part of your job after authd is deployed.

What happens if my identity provider goes down?

By default a user who has already authenticated once can still log in with the local password they set, so an outage does not lock everybody out. That default also means a user revoked at the provider can log in while the provider is unreachable. Setting force_access_check_with_provider to true in the broker config removes that window and makes provider reachability a requirement for every login. Either way, create a local account with sudo and a password before you deploy, and test logging in as that account from a second SSH session.

Why does SSH refuse my provider username on a fresh server?

Because the user does not exist on the machine yet, so sshd rejects the connection before authd is consulted. Set ssh_allowed_suffixes_first_auth in the [users] section of /var/snap/authd-<broker>/current/broker.conf to the domains you accept, for example @example.com, then restart the broker unit. Connect with the whole handle in front of the host, as in ssh alice@example.com@server.example.net.

Does authd require snapd on the server?

Yes. The authd daemon is a Debian package, but every identity broker ships only as a snap: authd-google, authd-msentraid and authd-oidc. There is no deb-only route, so a server kept free of snapd cannot run authd. snapd also refreshes those snaps on its own schedule, which means an authentication component updates without you initiating it unless you hold the refresh.