Cached at:
08/03/26, 01:29 AM
# Sharing an X Server Across Hosts with FamilyWild · dobrowolski.dev
Source: [https://dobrowolski.dev/article/sharing-an-x-server-across-hosts-with-familywild](https://dobrowolski.dev/article/sharing-an-x-server-across-hosts-with-familywild)
2026\-08\-02
Ever tried running an X11 application from inside a container, a chroot, or over`ssh`with a bind\-mounted`\.Xauthority`— only to be greeted by the ever\-helpful`Authorization required, but no authorization protocol specified`?
The file is right there, mounted read\-only where the client expects it, and yet X refuses the connection\. The reason is subtle, and the fix is a single line of`sed`\.
---
## Why the cookie is rejected
An`\.Xauthority`file is a list of cookies, and every entry is keyed by a*family*and a*hostname*\. When a client connects, it doesn't just grab the first cookie it finds — it looks for the entry whose hostname matches the machine the client believes it's running on\.
That's exactly what breaks the moment the client runs somewhere other than where the cookie was minted\. Inside a container the hostname is different; over an un\-forwarded socket the client resolves a different name entirely\. The cookie is present and valid, but its hostname doesn't match, so the client never offers it and X falls back to "no authorization protocol\."
You can see the family/hostname keying for yourself:
```
$ xauth list
myhost/unix:0 MIT-MAGIC-COOKIE-1 a1b2c3d4e5f6...
```
That leading`myhost/unix:0`is the problem — it pins the cookie to`myhost`\.
---
## FamilyWild to the rescue
X has a wildcard family,`FamilyWild`, whose numeric value is`0xffff`\. A cookie in this family matches*any*hostname\. So instead of trying to make the client's hostname match the cookie, we rewrite the cookie to match every host\.
`xauth nlist`prints entries in a numeric format where the first field is the 4\-hex\-digit family\. Overwrite it with`ffff`and merge the result into a fresh file:
```
: > /tmp/portable.Xauthority && xauth nlist :0 | \
sed 's/^..../ffff/' | xauth -f /tmp/portable.Xauthority nmerge -
# Replace :0 with your $DISPLAY value
```
---
## The change is a single field
It's worth seeing just how small the edit is\. An`\.Xauthority`entry is a packed binary record: a 2\-byte*family*, then length\-prefixed address, display number, auth name, and the cookie itself\. Dump the original file and the family sits in the very first two bytes —`0100`, i\.e\.`FamilyLocal`:
```
00000000: 0100 0006 6d79 686f 7374 0001 3000 124d ....myhost..0..M
00000010: 4954 2d4d 4147 4943 2d43 4f4f 4b49 452d IT-MAGIC-COOKIE-
00000020: 3100 10a1 b2c3 d4e5 f607 1829 3a4b 5c6d 1..........):K\m
00000030: 7e8f 90 ~..
```
Now dump the FamilyWild version we just built\. Everything is byte\-for\-byte identical — same`myhost`address, same cookie — except those first two bytes, now flipped to`ffff`:
```
00000000: ffff 0006 6d79 686f 7374 0001 3000 124d ....myhost..0..M
00000010: 4954 2d4d 4147 4943 2d43 4f4f 4b49 452d IT-MAGIC-COOKIE-
00000020: 3100 10a1 b2c3 d4e5 f607 1829 3a4b 5c6d 1..........):K\m
00000030: 7e8f 90 ~..
```
That one field is the whole trick: the address bytes still spell`myhost`, but X no longer cares, because family`0xffff`matches unconditionally\.
Bind\-mount \(or`scp`\)`/tmp/portable\.Xauthority`wherever the client runs, point`XAUTHORITY`at it, and the connection is accepted regardless of the hostname mismatch\.
---
## What about`xhost \+`?
You'll often see`xhost \+`suggested as the "just make it work" answer, and it does — by turning host\-based access control off entirely\. Every client from every host can then connect to your display*without any cookie at all*\.
On a single\-user machine that sounds harmless, but X has no isolation between clients: anyone who can reach the server can read your keystrokes, grab the contents of any window, and inject synthetic input\.`xhost \+`hands that capability to every local user and, if your server listens on TCP, to the network\. Even the narrower`xhost \+local:`still trusts every UID on the box\.
The FamilyWild cookie keeps the door locked — a client still has to*present the secret*— while removing only the hostname constraint that was getting in the way\. Reach for it instead of`xhost \+`, and keep the cookie file at`0600`\.
---
## One caveat
A FamilyWild cookie is deliberately less specific than the one it replaces: anyone who can both reach your X socket*and*read this file can talk to your display\. Hand it only to the environments that actually need it, and don't leave copies lying around on shared machines\.
This trick is one small piece of a larger setup — I use it to forward X into unprivileged LXC containers, which I wrote up in detail in[Enhancing x11 Application Security with LXC](https://dobrowolski.dev/article/enhancing-x11-application-security-with-lxc/)\.
---
*Discussed on[Hacker News](https://news.ycombinator.com/item?id=49147978)\.*