Systemd services fails to start custom service

I am using systemd services to launch my vpn at startup of the vm using my script/expect tool. I think the problem I am having is a permissions issue but I can not be certain without someones help. My .sh file is launched by my .exp file and are in the same directory. My services file executes the .exp file and the .exp file fails on the execute of the .sh file.

Can someone please help me determine why this is failing at “./expressvpn.sh”: no such file or directory?

The services error is as follows:

[user@Coding bin]$ sudo systemctl status expressvpnauto.service
× expressvpnauto.service - Autostart ExpressVPN
     Loaded: loaded (/etc/systemd/system/expressvpnauto.service; enabled; vendor preset: disabled)
     Active: failed (Result: exit-code) since Wed 2022-10-12 15:52:17 EDT; 9min ago
   Main PID: 379 (code=exited, status=1/FAILURE)
        CPU: 10ms

Oct 12 15:52:17 Coding systemd[1]: Started expressvpnauto.service - Autostart ExpressVPN.
**Oct 12 15:52:17 Coding expectvpn.exp[379]: spawn ./expressvpn.sh**
**Oct 12 15:52:17 Coding expectvpn.exp[379]: couldn't execute "./expressvpn.sh": no such file or directory**
**Oct 12 15:52:17 Coding expectvpn.exp[379]:     while executing**
**Oct 12 15:52:17 Coding expectvpn.exp[379]: "spawn ./expressvpn.sh"**
**Oct 12 15:52:17 Coding expectvpn.exp[379]:     (file "/bin/expectvpn.exp" line 3)**
Oct 12 15:52:17 Coding systemd[1]: expressvpnauto.service: Main process exited, code=exited, status=1/FAILURE
Oct 12 15:52:17 Coding systemd[1]: expressvpnauto.service: Failed with result 'exit-code'.

Below is what I have…

expressvpnauto.service

[Unit]
Description=Autostart ExpressVPN

Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/bin/expectvpn.exp

[Install]
WantedBy=multi-user.target

-rwxr-xr-x 1 root root 234 Oct 12 14:26 expectvpn.exp

#!/usr/bin/expect
set timeout -1
spawn ./expressvpn.sh
expect "Enter activation code: "
send -- "????my code??????????\r"
expect -exact "(Y/n) "
send -- "n\r"
exec expressvpn connect
exec expressvpn autoconnect true
expect eof


-rwxr-xr-x 1 root root 37 Oct 12 15:56 expressvpn.sh

exec expressvpn activate


Have you tried using the full path to expressvpn.sh?

Jeez! I thought I tried that but apparently not because it fixed the issue. Then I ran into an issue that the expressvpn daemon was starting before mine. So far anyone in the future exploring this same stuff, I had to add Requires=expressvpn.service and ExecStartPre=/bin/sleep 15 to my service file below.

[Unit]
Description=Autostart ExpressVPN

Wants=network.target
Requires=expressvpn.service
After=syslog.target network-online.target

[Service]
Type=simple
ExecStartPre=/bin/sleep 15
ExecStart=/bin/expectvpn.exp

[Install]
WantedBy=multi-user.target

I use the proton client it also has issues with using systemd, I found that using /home/user/.config/autostart works well.

So now I have a different issue related to my setup. I have the .sh and .exp files in my fedora 36 template at /usr/bin/ and I have the .services file also in the template at /etc/systemd/system/

My problem now is that when sys-net starts (based on my fedora 36 template) it connects to my VPN perfectly. But when I start any other VM based on the fedora 36 template, they also start and connect to their own instance of my VPN. This doesn’t work. My goal was to have my VPN turn on and have all Qubes traffic flow through it.
So how do I tell them system to only connect with sys-net ? And if sys-net connects to my VPN successfully doesn’t all other traffic route through the VPN in sys-net?

Add the service to the template as masked/disable.

Add the .sh script to /rw in net-sys, and in net-sys use rc.local to unmake/enable the service before starting it.

1 Like

OK let me work with that and I will report back. Thanks @renehoj

I think I have everything set correctly but my rc.local script isn’t starting. My edited rc.local script in sys-net is in /rw/config/ and looks like this:

#!/bin/sh

# This script will be executed at every VM startup, you can place your own
# custom commands here. This includes overriding some configuration in /etc,
# starting services etc.

# Example for overriding the whole CUPS configuration:
#  rm -rf /etc/cups
#  ln -s /rw/config/cups /etc/cups
#  systemctl --no-block restart cups

sudo systemctl unmask /etc/systemd/system/expressvpnauto.service
sudo systemctl enable /etc/systemd/system/expressvpnauto.service
sudo systemctl start /etc/systemd/system/expressvpnauto.service

exit 0

But the rc-local.service doesn’t point there???

[user@sys-net system]$ sudo cat rc-local.service
#  SPDX-License-Identifier: LGPL-2.1-or-later
#
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

# This unit gets pulled automatically into multi-user.target by
# systemd-rc-local-generator if /etc/rc.d/rc.local is executable.
[Unit]
Description=/etc/rc.d/rc.local Compatibility
Documentation=man:systemd-rc-local-generator(8)
ConditionFileIsExecutable=/etc/rc.d/rc.local
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.d/rc.local start
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

Does rc.local work if you execute it manually?

Nope it doesn’t…

[user@sys-net config]$ bash rc.local
Failed to get properties: Unit name /etc/systemd/system/expressvpnauto.service is neither a valid invocation ID nor unit name.
Failed to enable unit: Unit file /etc/systemd/system/expressvpnauto.service is masked.
Failed to start etc-systemd-system-expressvpnauto.service.mount: Unit etc-systemd-system-expressvpnauto.service.mount not found.

should that be /usr/lib/systemd/system/expressvpnauto.service

Should it not just be expressvpnauto.service, I think you should use the name not the path.

Thank you so much for your help @renehoj ! This has been a fun learning curve for me and I hope this documentation will help someone else down the line. So here is what my final rc.local looked like and it all worked seamlessly when I rebooted sys-net.

#!/bin/sh

# This script will be executed at every VM startup, you can place your own
# custom commands here. This includes overriding some configuration in /etc,
# starting services etc.

# Example for overriding the whole CUPS configuration:
#  rm -rf /etc/cups
#  ln -s /rw/config/cups /etc/cups
#  systemctl --no-block restart cups

sudo systemctl unmask expressvpnauto.service
sudo systemctl enable expressvpnauto.service
sudo systemctl start expressvpnauto.service

exit 0
1 Like