A native Linux client for Azure Virtual Desktop and Windows 365 with real feed discovery, Entra ID sign-in, and a hardened FreeRDP: packaged as a Flatpak. If you use Azure Virtual Desktop (AVD) or Windows 365 from a Linux machine, you already know the problem. Microsoft ships clients for Windows, macOS, iOS, Android, and the web. For Linux there is nothing: and the web client is what you fall back to when you've given up. The threads asking for a Linux client go back years. So I built one. AVD Feed + Connect is an unofficial, MIT-licensed, native Linux client. You sign in with your Entra ID account, it shows the desktops and remote apps you're entitled to: exactly like the Windows App does: and you double-click to connect. flatpak install --user https://shakeelosmani.github.io/avd_feed_connect/avd_feed_connect.flatpakref flatpak run io.github.shakeelosmani.avd_feed_connect That's the whole install. The rest of this post is about why the existing options fall short and what it took to close the gap. The problem isn't RDP. It's feed discovery. Linux has had a capable RDP client for a long time: FreeRDP. Recent versions even speak AVD's ARM gateway and Entra ID auth (/gateway:type:arm /sec:aad). So why can't you just use it? Because AVD isn't "RDP to a host." It's a feed. When you sign in on Windows, the client calls a discovery endpoint, gets back the list of workspaces you're assigned, and for each resource it downloads an .rdp file that carries a per-resource gateway address and identity. Those files are what FreeRDP needs, and nothing on Linux fetches them for you. The workarounds people use today: Web client: works, but you lose local audio devices, camera, multi-monitor, clipboard richness, and it's a browser tab. Hand-authored .rdp files: you export one from a Windows machine per host pool, hope it doesn't change, and pass it to FreeRDP. Fragile, and impossible if you don't have a Windows box. Remmina / third-party clients: they wrap FreeRDP but still don't do feed discovery. Feed discovery is the missing 20% that makes the other 80% usable. That's what this app adds. How it works The app is Python + GTK, and it does four things: Interactive Entra ID sign-in. It uses the OAuth2 authorization-code flow with PKCE inside an embedded WebKit view: the same flow the official clients use. This matters more than it sounds: many tenants have Conditional Access policies that block the device-code flow, which is what most CLI tools reach for. Doing the real interactive flow means the app works in locked-down enterprise tenants instead of failing at sign-in. Feed discovery. With a token in hand, it queries rdweb.wvd.microsoft.com/api/arm/feeddiscovery. The service checks for an approved X-MS-User-Agent header, so the app sends one it accepts. The response is your list of workspaces and resources, including the per-resource icons. Workspace grid. Those resources are rendered in a grid with their real icons. Double-click to connect. Connect. The app downloads the resource's .rdp from the feed and launches a bundled sdl-freerdp with /gateway:type:arm /sec:aad. Token refresh uses the standard refresh_token grant (offline_access), so the access token is renewed silently before it expires and you aren't re-prompted to sign in every hour. There's also a CLI if you'd rather script it: bash python3 src/avdfeed.py list # list workspaces python3 src/avdfeed.py connect 0 # connect to resource 0 Why the bundled FreeRDP matters I could have shelled out to whatever xfreerdp is on your PATH. I didn't, because the stock build has two problems that make it painful for real work — specifically Teams calls, which is what most people are doing in these sessions. Audio hot-unplug freezes the session. Plug in or unplug headphones during a call and upstream FreeRDP's PulseAudio backend can hit a busy loop in rdpsnd that freezes the entire session. The fix is in FreeRDP#13334; the bundled build includes it. No camera redirection. The bundled build is compiled with CHANNEL_RDPECAM_CLIENT, so your webcam shows up inside the session. Microphone and multi-monitor are enabled too. Shipping it as a Flatpak means you get this specific FreeRDP regardless of what your distro packages, and it can't conflict with a system FreeRDP you use for other things. Install options One command (recommended). The .flatpakref above adds a small signed remote hosted on GitHub Pages, so the app updates with a normal flatpak update. Opening the file in a browser installs it through GNOME Software or your Flatpak handler. The GNOME 49 runtime is pulled from Flathub automatically. Single-file bundle. Grab avd_feed_connect.flatpak from the latest release and: flatpak install --user avd_feed_connect.flatpak Build it yourself. flatpak install flathub org.gnome.Platform//49 org.gnome.Sdk//49 org.flatpak.Builder flatpak run org.flatpak.Builder --user --install --force-clean build-dir \ io.github.shakeelosmani.avd_feed_connect.yml flatpak run io.github.shakeelosmani.avd_feed_connect Unpackaged (development). The same code runs without Flatpak if you have PyGObject (GTK 3, WebKit2 4.1) and an SDL3 sdl-freerdp on PATH. AVD_TENANT and AVD_UPN override the tenant/account, and AVD_SDL_FREERDP points at a different client binary. Status and what's next It's early. Sign-in, feed discovery, the workspace grid, and connect all work. A Flathub listing is planned so it shows up in your software center like anything else. What I'd most like help with: Testing in tenants with unusual Conditional Access setups. I can only test against the policies I have access to. Distro coverage. It's Flatpak so it should be portable, but "should" is doing work in that sentence. Remote app (RAIL) polish. Full desktops are the main path today. If it works for you, or especially if it doesn't, open an issue: https://github.com/shakeelosmani/avd_feed_connect This is an independent project, not affiliated with or endorsed by Microsoft.