This guide aims to answer to the (reccuring?) question: How can I make my wifi connection remember my password?
In the "Configuration file" main section, you have 3 methods.
In the "RPC service" main section, you have an example of how to store your wifi credentials outside of the disposable template.
Connect to your wifi with the Network-Manager panel icon.
Once connected, open the Network-Manager setting (right cick on the panel icon) and edit your connection:
Network-Manager > Edit Connections > Wi-FI: YOUR_SSID > Wi-Fi tab
In the Device field you might have wls6 or wls7 value (or else).
Delete it and leave the field empty.
Optionaly, instead of empty value, you could use your MAC address only (e.g. 3C:97:0E:42:1A:19).
Save and close the Network-Manager setting.
In your sys-net disposable:
Copy your config file to your dispobable template:
[user@sys-net-dvm ~]$ qvm-copy /etc/NetworkManager/system-connections/MY_SSID.nmconnection
Replace MY_SSID with your wireless SSID name.
Choose your sys-net disposable template in the popup prompt.
Shutdown your sys-net disposable.
In your sys-net disposable template:
Create NM-system-connections directory:
[user@sys-net-dvm-template ~]$ sudo mkdir -p /rw/config/NM-system-connections/
Copy your config file into it:
[user@sys-net-dvm-template ~]$ sudo cp /home/user/QubesIncoming/sys-net-dvm/MY_SSID.nmconnection /rw/config/NM-system-connections/
Delete QubesIncoming directory:
[user@sys-net-dvm-template ~]$ rm -r /home/user/QubesIncoming
Shutdown your sys-net disposable template.
Start your sys-net disposable.
In your sys-net disposable template:
Create the following script (e.g /home/user/auto_connect_wifi.sh).
#!/usr/bin/bash
wifi_dir=/rw/config/NM-system-connections/
wifi_cfg=$wifi_dir/home.nmconnection
sudo mkdir -p $wifi_dir
echo '
[wifi]
ssid=MY_SSID_NAME
[wifi-security]
key-mgmt=wpa-psk
psk=MY_PASSWORD' | sudo tee $wifi_cfg > /dev/null
sudo chmod 600 $wifi_cfg
These 3 fields (ssid, key-mgmt and psk) are the minimum required.
The non-defined fields will use default values.
Replace home.nmconnection with your SSID or any meaningful name (e.g. SSID.nmconnection).
Replace MY_SSID_NAME and MY_PASSWORD with your values.
Make your script executable and launch it.
[user@sys-net-dvm-template ~]$ chmod +x auto_connect_wifi.sh
[user@sys-net-dvm-template ~]$ ./auto_connect_wifi.sh
[user@sys-net-dvm-template ~]$ rm auto_connect_wifi.sh
Shutdown your sys-net disposable template.
Start your sys-net disposable.
This method is not recommended. Because it require to connect your disposable template to the network. And because there are other methods available.
Shutdown your sys-net disposable.
Change the setting of your sys-net disposable template:
Set the virtualization mode to hvm:
[user@dom0 ~]$ qvm-prefs sys-net-dvm-template virt_mode hvm
wifi_devid is your wireless network id as shown by qvm-pci (e.g. dom0:00_42.0).
[user@dom0 ~]$ wifi_devid=$(qvm-pci | grep Network | cut -d ' ' -f 1)
[user@dom0 ~]$ qvm-pci attach sys-net-dvm-template $wifi_devid
Enable the Network-Manager service:
netvm must be set to none (it should already be the case).
[user@dom0 ~]$ qvm-prefs sys-net-dvm-template provides_network true
Start your sys-net disposable template.
Connect to your wifi with the Network-Manager panel icon.
In your connection setting:
Delete the Device field value and leave the field empty.
Shutdown your sys-net disposable template.
Disable the Network-Manager service:
[user@dom0 ~]$ qvm-prefs sys-net-dvm-template provides_network false
Detach your wireless controller:
[user@dom0 ~]$ qvm-pci detach sys-net-dvm-template $wifi_devid
Set back the virtualization mode to pvh:
[user@dom0 ~]$ qvm-prefs sys-net-dvm-template virt_mode pvh
Start your sys-net disposable.
Somehow mandatory reading to understand this part of the guide. https://www.qubes-os.org/doc/qrexec/
Brief summary of client/server definition for this guide:
The client is your sys-net disposable.
The server is where you will store your wifi credentials.
The client will ask the server to send the wifi credentials (via stdin/stdout).
In this section, the wifi credentials will be stored in the @adminvm (aka dom0).
In dom0, create the policies to allow the communication between the server and the client.
echo '
qubes.user.ConnectWifi + sys-net-dvm @adminvm allow
qubes.user.ConnectWifi * @anyvm @anyvm deny' \
| sudo tee -a /etc/qubes/policy.d/30-user.policy > /dev/null
In dom0, create the script that will send the wifi credentials to the client.
server_script=/etc/qubes-rpc/qubes.user.ConnectWifi
echo "
#!/usr/bin/bash
echo 'MY_SSID' 'MY_PASSWD'" | sudo tee $server_script > /dev/null
sudo chmod +x $server_script
In your sys-net disposable template, create the script that will connect your wifi.
client_script=/rw/config/qConnectWifi
echo '
#!/usr/bin/bash
read my_ssid my_passwd
nmcli device wifi connect "$my_ssid" password "$my_passwd"' \
| sudo tee $client_script > /dev/null
sudo chown user:user $client_script
sudo chmod +x $client_script
In your sys-net disposable template, append the below code to the rc.local script.
The sys-net disposable template could be used for all of your system qubes (e.g. sys-net, sys-firewall and sys-usb).
Therefore, we test if the qube is sys-net-dvm.
If this is the case, we wait until the network and Network-Manager are ready, then we make an RPC call to connect our wifi.
echo '
/etc/qubes-rpc/qubes.WaitForSession
if [[ $(qubesdb-read /name) == sys-net-dvm ]]
then
until systemctl is-active network.target; do sleep 1; done
nm-online --quiet --wait-for-startup
qrexec-client-vm @adminvm qubes.user.ConnectWifi '$client_script'
fi' | sudo tee -a /rw/config/rc.local > /dev/null
In this section, the wifi credentials will be stored in an app qube (e.g vault-wifi).
In dom0, create the policies (@adminvm is replaced with vault-wifi).
echo '
qubes.user.ConnectWifi + sys-net-dvm vault-wifi allow
qubes.user.ConnectWifi * @anyvm @anyvm deny' \
| sudo tee -a /etc/qubes/policy.d/30-user.policy > /dev/null
https://www.qubes-os.org/doc/admin-api/
In dom0, add these policies.
admin.vm.CurrentState will be used in the client to know when vault-wifi is running/ready.
admin.vm.Start and admin.vm.Shutdown will allow the client to start and stop the server.
These 2 policies (Start and Shutdown) are optional, you could instead make vault-wifi to start automatically on boot.
echo '
admin.vm.CurrentState + sys-net-dvm vault-wifi allow target=@adminvm
admin.vm.Start + sys-net-dvm vault-wifi allow target=@adminvm
admin.vm.Shutdown + sys-net-dvm vault-wifi allow target=@adminvm' \
| sudo tee -a /etc/qubes/policy.d/30-admin-policy.policy > /dev/null
In your vault-wifi app qube, create the script to send the wifi credentials.
This time, instead of creating it directly in /etc/qubes-rpc/, let's store it in the home directory.
server_script=/home/user/qubes_connect_wifi.sh
echo "
#!/usr/bin/bash
echo 'MY_SSID' 'MY_PASSWD'" > $server_script
chmod +x $server_script
As you want to use this script only in the app qube and not in the template, create a symbolic link to /usr/local/etc/qubes-rpc/qubes.user.ConnectWifi (instead of /etc/qubes-rpc/ in the template).
sudo mkdir -p /usr/local/etc/qubes-rpc/
sudo ln -s $server_script /usr/local/etc/qubes-rpc/qubes.user.ConnectWifi
In your sys-net disposable template, create the script that will connect your wifi.
This is the same one as with dom0 as server.
In your sys-net disposable template, append the below code to the rc.local script.
(optional) We start the vault-wifi qube.
We wait until vault-wifi is running before making the RPC call.
(optional) We shutdown the vault-wifi qube.
client_script=/rw/config/qConnectWifi
echo '
/etc/qubes-rpc/qubes.WaitForSession
if [[ $(qubesdb-read /name) == sys-net-dvm ]]
then
qrexec-client-vm vault-wifi admin.vm.Start < /dev/null
while [[ $(qrexec-client-vm vault-wifi admin.vm.CurrentState < /dev/null \
| sed -E "s/.*power_state=([^ ]+).*/\1/") != Running ]]
do
sleep 1
done
until systemctl is-active network.target; do sleep 1; done
nm-online --quiet --wait-for-startup
qrexec-client-vm vault-wifi qubes.user.ConnectWifi '$client_script'
qrexec-client-vm vault-wifi admin.vm.Shutdown < /dev/null
fi' | sudo tee -a /rw/config/rc.local > /dev/null
In this section, the wifi credentials of several wifi connections will be stored in @adminvm.
This can be adjusted to store them in an app qube.
In dom0, create the necessary policies.
We use the RPC service argument to differentiate each network (the +something after the service).
echo '
qubes.user.ConnectWifi +home sys-net-dvm @adminvm allow
qubes.user.ConnectWifi +work sys-net-dvm @adminvm allow
qubes.user.ConnectWifi * @anyvm @anyvm deny' \
| sudo tee -a /etc/qubes/policy.d/30-user.policy > /dev/null
In dom0, create the script that will send the wifi credentials to the client.
We will send different wifi credentials according to the received argument.
server_script=/etc/qubes-rpc/qubes.user.ConnectWifi
echo "
#!/usr/bin/bash
case $1 in
home) echo 'MY_HOME_SSID' 'MY_HOME_PASSWD';;
work) echo 'MY_WORK_SSID' 'MY_WORK_PASSWD';;
*) ;;
esac" | sudo tee $server_script > /dev/null
sudo chmod +x $server_script
In your sys-net disposable template, create the script that will connect your wifi.
This is the same one as with dom0 as server.
In your sys-net disposable template, append the below code to the rc.local script.
We scan the available wifi connection and connect accordingly.
The first match will be use as an argument to our RPC call.
client_script=/rw/config/qConnectWifi
echo '
/etc/qubes-rpc/qubes.WaitForSession
if [[ $(qubesdb-read /name) == sys-net-dvm ]]
then
until systemctl is-active network.target; do sleep 1; done
nm-online --quiet --wait-for-startup
wifi_ssids=($(nmcli --get-values SSID device wifi))
rpc_arg=$(for ssid in "${wifi_ssids[@]}"
do
[[ $ssid == home ]] && echo home && break
[[ $ssid == work ]] && echo work && break
done)
qrexec-client-vm @adminvm qubes.user.ConnectWifi+$rpc_arg '$client_script'
fi' | sudo tee -a /rw/config/rc.local > /dev/null
For the RPC service:
It shouldn't happens, but if there is a race condition and your wifi is not automatically connected.
Open your sys-net disposable terminal and launch the RPC call manually.
[user@sys-net-dvm ~]$ cat /rw/config/rc.local
qrexec-client-vm call and execute it.
This race condition only happens to me twice in a month of testing.
And the two times was because I had modified dom0 max memory.