Gajim with netctl and systemd - Reconnection after suspend

When using netctl, Gajim does not automatically reconnect after the machine has been suspended out of the box. However, there is an easy way to achieve that by using gajim-remote which uses dbus.

First of all, you need to enable Gajims dbus listener. Therefore, open the Advanced Configuration Editor (Edit->Preferences->Advanced) and enable the option remote_control. After that, you may need to restart Gajim for the new setting to take effect.

To test whether the dbus listener is working, execute

gajim-remote get_status

If this returns your correct online status of Gajim, its dbus listener is working now.

netctl hook (for wireless connections)

The next step is to configure the hook for netctl. Create an executable file inside /etc/netctl/hooks (i.e. called gajim) with the following content:

#!/bin/sh
ExecUpPost="su - user -c 'export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus; gajim-remote change_status online' | exit 0"

You need to replace user by the name and 1000 by the id of your user. If your bus has a different socket address than /run/user/1000/bus, you will need to change that too.

The hook does the following:

  • export DBUS_SESSION_BUS_ADDRESS: Set the environment variable in order to be able to access the dbus
  • gajim-remote change_status online: Send Gajim a dbus notification to set the status to online which causes a reconnect if the current status is offline.
  • exit 0: Always exit with return code 0 to avoid netctl failures when gajim-remote is unable to connect to Gajim (i.e. during boot when no dbus is active at all or Gajim is not running)

As the recognition of the suspend works reliable, I have not configured a DownPre hook; however, if you have problems with that, you may want to add that hook too. You could use the same hook as for UpPost but replace online with offline.

After you have configured that hook, you will need to restart netctl to use it. After doing that, Gajim should automatically try to reconnect your accounts after your network interface reconnects.

systemd unit (for wired connections)

When using a wired connection, the solution described above may not work properly as that connection is not considered as down during suspension and therefore does not trigger the UpPost netctl hook. One way to tell Gajim to reconnect after wakeup is a systemd service. That could look like the following (store it for example at /etc/systemd/system/gajim-resume.service):

[Unit]
Description=Reconnect gajim on resume.
After=sleep.target

[Service]
Type=oneshot
Environment="DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus"
User=user
Group=user
ExecStart=/usr/bin/gajim-remote change_status online

[Install]
WantedBy=sleep.target

Where again user and 1000 need to be replaced by your users values. After enabling that service (systemctl enable gajim-resume.service - replace gajim-resume by the name of the service file you have created), Gajim should trigger a connection immediately after wakeup - thus not checking whether there is a network connection at all; therefore you should not use this unit if you are using wireless connections (which do need to reconnect and require some time for that) - otherwise Gajim may fails while trying to reconnect after the second connect signal from the netctl hook has been sent and as a result does not retry it.

Additional note: If you have changed your status to something other than online before your interface lost the connection (or you entered sleep), it will be set to online after reconnection no matter what it has been before. If you have multiple active network interfaces, the status will also be set to online if one of them reconnects - unchecked whether there has already been an active connection before. So if you are heavily using Gajims status feature, you may want to adapt the hook a little bit.