Flatpak on Ubuntu CLI install is broken

I’m using Obsidian 1.12.7 installed as a system flatpak with Insider-Builds enabled in setttings.

Installing the CLI from the global settings puts a binary into $HOME/.local/bin/obsidian that subsequently fails with the error message of

`The CLI is unable to find Obsidian. Please make sure Obsidian is running and try again.`

The method described in the docs (`ln -s /var/lib/flatpak/exports/bin/md.obsidian.Obsidian ~/.local/bin/obsidian`) works for me, so I’m assuming this is a system/ecosystem detection going wrong. Happy to provide other debug info if I can.

Sorry, forgot to mention: This is on Ubuntu (running Plasma as DE) questing quokka (25.10) x64.

So it looks like the flatpak sandboxes the socket, meaning the cli tool can’t find it. The below is my current work around which has to be run each time before obsidian starts up. Maybe the devs can see this and implement a more durable solution for their flatpak builds.

`alias obsidian=‘ln -sf /run/user/$(id -u)/.flatpak/md.obsidian.Obsidian/xdg-run/.obsidian-cli.sock /run/user/$(id
-u)/.obsidian-cli.sock 2>/dev/null; command obsidian’ `

We don’t directly make the flatpak. It’s a community maintained package. There are also some changes that we made in how the CLI works.

I suggest you to review the docs

And visit the flatpak GitHub repo
GitHub - flathub/md.obsidian.Obsidian · GitHub

Thank you! That was really helpfull. However, i use zsh so the single quotes broke the command. For other folks using obsidian and zsh, that’s the workaround that worked for me:

Edit your ~/.zshrc and add the following:

unalias obsidian 2>/dev/null # clear any existing alias that may break
obsidian() {
ln -sf /run/user/$(id -u)/.flatpak/md.obsidian.Obsidian/xdg-run/.obsidian-cli.sock
/run/user/$(id -u)/.obsidian-cli.sock 2>/dev/null
command obsidian “$@”

Thanks very much, this solved the problem for me.

I renamed .local/bin/obsidian to obsidian-exe, then added this wrapper script for .local/bin/obsidian:

#! /usr/bin/env nu
# vim: set filetype=nu :

def main [...cmd: string] {
  ln -sf /run/user/1000/.flatpak/md.obsidian.Obsidian/xdg-run/.obsidian-cli.sock /run/user/1000/.obsidian-cli.sock;
  obsidian-exe ...$cmd
}

Here the solution I reach with a bit of help of deepseek

| Package | Purpose | Version |

|---------|---------|---------|

| md.obsidian.Obsidian | Markdown knowledge base (flatpak) | 1.12.7 |

| xorg-server-xvfb | Virtual X11 for headless service | repo |

## Installation

```bash

flatpak install flathub md.obsidian.Obsidian

sudo pacman -S xorg-server-xvfb

```

## Components

### 1. Desktop Entry

`~/.local/share/applications/md.obsidian.Obsidian.desktop` — custom override for the app grid/menu (Fuzzel):

```ini

[Desktop Entry]

Name=Obsidian

Comment=Obsidian notes

Exec=flatpak run md.obsidian.Obsidian %U

Terminal=false

Type=Application

Icon=md.obsidian.Obsidian

StartupWMClass=obsidian

Categories=Office;Utility;

```

The system flatpak desktop file was inaccessible because `XDG_DATA_DIRS` didn’t include the flatpak export path on Hyprland.

### 2. CLI (command-line interface)

The flatpak ships a companion CLI binary (`~/.local/bin/obsidian`) that communicates with a running Obsidian instance via a Unix socket.

**Problem:** The flatpak sandbox creates the socket at:

```

/run/user/UID/.flatpak/md.obsidian.Obsidian/xdg-run/.obsidian-cli.sock

```

But the CLI binary looks for it at:

```

/run/user/UID/.obsidian-cli.sock

```

**Fix:** A zsh function in `~/.zshrc` bridges the gap with a symlink:

```zsh

# obsidian cli fix flatpak sandbox

unalias obsidian 2>/dev/null

obsidian() {

local sock=“/run/user/$(id -u)/.flatpak/md.obsidian.Obsidian/xdg-run/.obsidian-cli.sock”

ln -sf “$sock” “/run/user/$(id -u)/.obsidian-cli.sock” 2>/dev/null

if [ ! -S “$sock” ]; then

echo “error: Obsidian is not running or CLI not enabled.” >&2

echo " Open Obsidian and go to Settings → Core Plugins → enable ‘Open URI’ or ‘CLI’." >&2

return 1

fi

command obsidian “$@”

}

```

The function:

1. Creates/refreshes the symlink from sandbox path → expected path

2. Verifies the socket exists (Obsidian is running with CLI enabled)

3. Delegates to the real `obsidian` binary

**Prerequisite:** Obsidian’s CLI must be enabled in the app. Go to Settings → search “CLI” or “URI” and enable it.

### 3. Headless systemd service

Runs Obsidian without a visible window via `xvfb-run`, keeping the CLI always available.

**Service:** `~/.config/systemd/user/obsidian-headless.service`

```ini

[Unit]

Description=Obsidian (headless, for CLI)

After=graphical-session.target

PartOf=graphical-session.target

[Service]

Type=simple

ExecStart=/usr/bin/xvfb-run -a -s “-screen 0 1920x1080x24 -ac” /usr/bin/flatpak run md.obsidian.Obsidian

Restart=on-failure

RestartSec=5

[Install]

WantedBy=graphical-session.target

```

`xvfb-run` creates a virtual X11 framebuffer (`Xvfb :99`) that satisfies Electron’s display requirement, so Obsidian initializes fully and creates the CLI socket — but no window appears on the desktop.

**How it works:**

- Flatpak Obsidian has `sockets=x11` permission

- `xvfb-run -a` auto-assigns a free display number

- `-screen 0 1920x1080x24` creates a 24-bit color virtual screen

- `-ac` disables X11 access control (required for flatpak sandbox)

**Management:**

```bash

# Enable auto-start on login

systemctl --user enable obsidian-headless.service

# Start/stop manually

systemctl --user start obsidian-headless

systemctl --user stop obsidian-headless

# Check status

systemctl --user status obsidian-headless

# View logs

journalctl --user -u obsidian-headless -f

```

**Conflict:** Only one Obsidian instance can run at a time. Stop the headless service before opening the GUI (`systemctl --user stop obsidian-headless`), or the GUI will fail to start.