The VPN client starts from the application menu, the tunnel connects, and the icon never appears after sign-in on one machine while the same package behaves on another. Three observations are being collapsed into one complaint: whether the program launched, whether its interface is visible, and whether the tunnel is up. The launcher is governed by a desktop entry with filtering keys, and that entry has nothing to do with the VPN protocol. Work the runbook in order and stop when one of the three separates cleanly.

Three separate facts: launch, icon, tunnel

A desktop entry launches a program. It cannot install a tray implementation, and it cannot make an indicator appear in a panel that does not support the protocol the application uses. If the process is already running, the launch question is answered and you are looking at an integration problem instead.

The tunnel is a third fact again. A missing icon is not evidence that the connection dropped, and killing and restarting the client to "fix" the icon is how a working tunnel gets interrupted for no reason. Users report the missing icon and the broken tunnel as the same sentence, which is exactly why the two need separating on paper.

Separate them before you change anything. Check whether the process exists, then whether the panel supports the indicator, then whether the interface reports a connection. Each answer points at a different layer and a different owner.

Find the entry the session actually reads

Autostart entries live in the user directory and the system directory, and the user copy wins when the file names match. Reading the wrong one is the most common reason a change appears to have no effect. List both directories before you edit anything, and note which file the session will actually load.

ls -l ~/.config/autostart/ /etc/xdg/autostart/
echo "$XDG_CURRENT_DESKTOP"
grep -H -E '^(OnlyShowIn|NotShowIn|TryExec|Hidden|Exec)=' ~/.config/autostart/*.desktop /etc/xdg/autostart/*.desktop

The environment variable prints the session name the filtering keys are compared against, which is usually a colon-separated list. Compare it literally with the values in the entry, because those names are case-sensitive configuration details rather than a description of the session. A value of GNOME does not match gnome, and the resulting silence has no error message attached. Print it rather than assuming it.

If the same file name exists in both directories, the user copy is the one that matters. Editing the system file and wondering why nothing changed is a very common hour lost.

Read the filtering keys, in order

The illustrative entry below shows the keys that decide whether a session launches the program. It is a fragment, not a complete launcher, and the values belong to a fictional path.

[Desktop Entry]
Type=Application
Name=Example VPN
Exec=/opt/example-vpn/client --minimized
TryExec=/opt/example-vpn/client
OnlyShowIn=GNOME;

OnlyShowIn restricts the entry to the listed environments and NotShowIn excludes the listed ones. The specification does not define useful behaviour when both appear in one entry, so treat a file containing both as a defect rather than a clever combination. Remove the key you do not need instead of adding the second one and hoping for a precedence rule.

TryExec asks whether the executable exists before the session launches it. A path left over from an older installation therefore suppresses autostart even though the new package works when started from the menu, and that failure looks exactly like a desktop filter.

Override at user level, not system level

When the filter is genuinely wrong for this machine, copy the system entry into the user directory and change the copy. Under the XDG autostart rules, a same-named user entry takes precedence, and Hidden=true disables one without deleting the system file.

mkdir -p ~/.config/autostart
cp /etc/xdg/autostart/example-vpn.desktop ~/.config/autostart/
sed -i '/^OnlyShowIn=/d' ~/.config/autostart/example-vpn.desktop
desktop-file-validate ~/.config/autostart/example-vpn.desktop

Validate the result before you log out, because a malformed entry is silently ignored and the next test tells you nothing. Reinstalling the package will not remove your override, which is the point and also the reason to record that it exists. Note the file path in the ticket so the next person finds the override instead of re-deriving it.

Prefer this to editing shared system launchers, which changes behaviour for every user on the machine and is not reviewable in the same way. A user-level override is visible in one place, reversible by deleting one file, and easy to explain in a ticket. The system file stays as the vendor shipped it, so a package update does not silently undo your reasoning.

Confirm the launch without touching the tunnel

Log out and back in, then confirm the process exists before you look at the panel. A successful launch and a visible icon are two different results, and only the second one needs desktop-integration work. Mixing them up sends you reinstalling a package that was working the whole time.

pgrep -af example-vpn
systemctl --user status example-vpn.service
journalctl --user -b --no-pager | grep -i example-vpn | tail -20

If the process is absent, re-read the entry for a remaining filter or a stale TryExec path. If it is present, the launcher worked and the missing icon is a separate problem with the panel's indicator support rather than with the entry you just edited.

Record the three observations in the ticket: launched, visible, connected. That record prevents the next person from repeating the same three-way confusion, and it makes clear which layer still needs work.

Artitgels cun il medem tema