Meeting 2021-06-26 Raspberry Pi Diskless Workstation

The chatter of the meeting is at the bottom of the page, it’s just me talking, and talk on subject starts about 15 minutes in.
So – this meeting I was talking about setting up a Raspberry Pi as a Diskless Workstation – the files I describe have been anonymized, they won’t work as given, but the flow is correct and complete.

We are currently deploying this to end users at a cost of about $100 for the compute end, it doesn’t include the Monitors (Dual 27inch 1920×1080 LCDs), or a wireless Keyboard and Mouse.

This is the script that is run on the ‘Pi to set it up, it can be placed in /boot or downloaded with wget or curl.


#!/bin/bash
# Save this script as /boot/RDbuild.sh
# This script sets up most everything you should need for a Raspberry Pi
# to connect a Remote Desktop Session with 2FA to the corporate RD-Gateway
# Run this after setting the country code then bringing up the network, do
# not update the software on the pi beforehand - this script does that and
# logs everything in case something breaks in the future.

# Still to do
## Set config, set backgrounds
#

mkdir -p /home/pi/.Logs
Log()
{
tee -a /home/pi/.Logs/$(date +"%Y-%m-%d.txt")
}

sudo apt install -y git tig etckeeper | Log
sudo apt update | Log
sudo apt -y upgrade | Log
sudo apt install -y freerdp2-x11 vim vim-doc vim-scripts mc speedtest-cli inxi fonts-ubuntu* | Log
sudo pip3 install easygui

mkdir /home/pi/bin
cd /home/pi/bin
# The construction below creates a file (adminaccess.service) and then cats
# everything to it until it matches the string 'EndOfText'. 
cat << 'EndOfText' > adminaccess.service
[Unit]
Description=Permit admin access from secretuser@www.clug.org
After=network-online.target
Before=multi-user.target
DefaultDependencies=no
Wants=network-online.target

[Service]
# SSH connection runs as, and uses the private key stored in this users home dir (~/.ssh/)
User=pi

# SSH connection with port forwarding, forwards port 22 on the client through port 2280 on the server
# and creates the reverse (-R2288) port, which must be unique on the server.
ExecStart=/usr/bin/ssh -o StrictHostKeyChecking=no -o ServerAliveInterval=60 -o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes -N -T -R2288:localhost:22 -i ~/.ssh/ed25519 -p 2280 \
secretuser@www.clug.org

# Wait one minute before trying to restart the connection if it disconnects, and keep retrying.
RestartSec=60
Restart=always

[Install]
WantedBy=multi-user.target
EndOfText
chmod a+x adminaccess.service
sudo cp adminaccess.service /etc/systemd/system/adminaccess.service
echo "Added adminaccess.service (1)" | Log

cat << 'EndOfText' > ConnectToWork
#!/bin/bash
User=${1}
Pass=${2}
# Uncomment only one of the three lines below.
LBI="tsv://MS Terminal Services Plugin.1.Desktop"
# LBI="tsv://MS Terminal Services Plugin.1.DevOps"
# LBI="tsv://MS Terminal Services Plugin.1.Finance"

xfreerdp /cert-ignore /g:rd-gateway.example.com:4430 /gd:exampl /gu:${User} /gp:${Pass} /sound:sys:alsa \
/gdi:hw /multimon /f /u:EXAMPLE\\${User} /p:${Pass} /load-balance-info:"${LBI}" /v:rd-gateway.example.com

EndOfText
chmod a+x ConnectToWork
echo "Added ConnectToWork (2)" | Log

cat << 'EndOfText' > Help
#!/bin/bash
# This script connects to www.clug.org for assistance, opening
# a tunnel that remote admins can connect back through.
ScriptName=adminaccess.service
[ ${1} ] && Opt=$( echo ${1} | tr A-Z a-z )
case ${Opt} in
q|x )
sudo systemctl disable ${ScriptName}
sudo systemctl stop ${ScriptName}
;;
* )
sudo systemctl enable ${ScriptName}
sudo systemctl start ${ScriptName} && echo "Started ${ScriptName}"
esac
EndOfText
chmod a+x Help
echo "Added Help (3)" | Log

cat << 'EndOfText' > StartHere
#!/usr/bin/python3
import easygui as eg
import os
msg = "Employee Information"
title = "Associates Login"
fieldNames = "Login","Password"
fieldValues = eg.multpasswordbox(msg,title, fieldNames)
Cmd = ["/home/pi/bin/ConnectToWork", fieldValues[0], fieldValues[1]]
os.system(" ".join(Cmd))
EndOfText
chmod a+x StartHere
echo "Added StartHere (4)" | Log

cat << 'EndOfText' > autostart
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@/home/pi/bin/StartHere
EndOfText
sudo cp autostart /etc/xdg/lxsession/LXDE-pi/
echo "Added autostart (5)" | Log

cat << 'EndOfText' > Update
#!/bin/bash
Log()
{
tee -a /home/pi/.Logs/$(date +"%Y-%m-%d.txt")
}
[ -e /home/pi/.Logs/$(date +"%Y-%m-%d.txt") ] && echo '='$_{1..38} | Log
sudo apt update | Log
sudo apt upgrade -y | Log
sudo apt-get -y autoremove | Log
if [ -f /var/run/reboot-required ]; then
echo 'Reboot required' | Log
sudo shutdown -r +2 "Rebooting in two minutes..."
else
echo 'No reboot needed' | Log
fi
EndOfText
chmod a+x Update
echo "Added Update (6)" | Log

cd
mkdir -m 0700 /home/pi/.ssh
cd .ssh
echo "Created .ssh (7)" | Log

cat << 'EndOfText' > ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBImfS6jC8eknCw06KssCszdiLMINBvmi4679Fact18a For reverse tunnel only
EndOfText
cat ed25519.pub >> authorized_keys
chmod 644 authorized_keys
chmod 600 ed25519.pub
echo "Added ed25519.pub (8)" | Log

cat << 'EndOfText' > ed25519
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGgAAAJDO/g1wzv4N
cAAAAAtzc2gtZWQyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGg
AAAEAxDSzm5ImkNJ32LceDv98MsZWnxg1Qfdr8jO0CwDq6GRImfS6jC8eknCw06KssCszd
iLMINBvmi4679Fact18aAAAACXN0ZXZlQFNSSgECAwQ=
-----END OPENSSH PRIVATE KEY-----
EndOfText
chmod 600 ed25519
echo "Added ed25519 (9)" | Log

cat << 'EndOfText' > known_hosts
|1|F1nKHIysQLR79CbrWewcYJ74mY6=|5Mw5E0QDksfb54FGHbEDTRCER75= ecdsa-sha2-nistp256 AAAAE2VjZerHFeh47GNmlL64gfMH3thQoPUtKt456fartbyty7JGTDGFweqf54bflwpkEd84WXnUQxCWyz4VvTXW2wyrnqhEe2kzFDMIZfCzMbb9yDiKu5ZTS8uPuLIgq1gkJkXo3mk=
|1|qDyy9RISBVo76huTetVrt5H6MF4=|dU4HqdQZJ6HEghi6DGFJ6gfhj6V= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXDGHH6HDDD3ytum768hgf9hjg89DFG7684nbBVCNHwjD5wAMiv5lwpkEd84WXnUQxCWyz4VvTXW2wyrnqhEe2kzFDMIZfCzMbb9yDiKu5ZTS8uPuLIgq1gkJkXo3mk=
EndOfText
chmod 644 known_hosts
echo "Added known_hosts (10)" | Log

# The lines from here down set a known set of keys, which keeps us from needing
# to remove keys on the remote end.
cat << 'EndOfText' > ssh_host_dsa_key
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH
NzAAAAgQDdUNGSdLxCZ3fR2ClVSeS22yFzYCg12Cv7zEagmxfRseMSVSZMVfYGEXNyXMrr
I5yNkH2wc4CTAwoIDMqZs1r1JkWar7ohKUD10ANvpYPMNjUvY0RXyRq5FRfcm27dUSkCUE
czFXRk1UhhKmvWwc+r2/VFh5J6bywW/X6A40hIAQAAABUAvgdKFYWKwsu4BRZcc9CeqqQ3
LKsAAACAaC9XWH2/qQQVb6uLz3af9ckMb059UYxXkzsNJv6WdMBQHXnQDXKJO+sKXBirXi
HT/mpJFeYnaydyTOenBL1v3PpMbE2oYVLQ4bBtV1S8MuI7FAcXRVc7pS7hG+nj1A1dd6Ho
2NbT4cbv/Zk2Af6vgXxq7PvkFystXinT9zSpyaoAAACBAKapw6rgRO0qmu3WWDA6yfWEDa
XAWaLmk+Wj2GrFknRHD6P8l/OnwAbW+3JzwD8fgCmzSszCmpxyiMg9A5L7lb8StP2g8sil
jMrndfmhIlTX/YgSJyNmVhGl5KgHxjxRNwOJYIXjltbQ3Lu0hXBtOVuk9/+iiVweA4kGfW
xcfSHpAAAB4OqgjpHqoI6RAAAAB3NzaC1kc3MAAACBAN1Q0ZJ0vEJnd9HYKVVJ5LbbIXNg
KDXYK/vMRqCbF9Gx4xJVJkxV9gYRc3JcyusjnI2QfbBzgJMDCggMypmzWvUmRZqvuiEpQP
XQA2+lg8w2NS9jRFfJGrkVF9ybbt1RKQJQRzMVdGTVSGEqa9bBz6vb9UWHknpvLBb9foDj
SEgBAAAAFQC+B0oVhYrCy7gFFlxz0J6qpDcsqwAAAIBoL1dYfb+pBBVvq4vPdp/1yQxvTn
1RjFeTOw0m/pZ0wFAdedANcok76wpcGKteIdP+akkV5idrJ3JM56cEvW/c+kxsTahhUtDh
sG1XVLwy4jsUBxdFVzulLuEb6ePUDV13oejY1tPhxu/9mTYB/q+BfGrs++QXKy1eKdP3NK
nJqgAAAIEApqnDquBE7Sqa7dZYMDrJ9YQNpcBZouaT5aPYasWSdEcPo/yX86fABtb7cnPA
Px+AKbNKzMKanHKIyD0DkvuVvxK0/aDyyKWMyud1+aEiVNf9iBInI2ZWEaXkqAfGPFE3A4
lgheOW1tDcu7SFcG05W6T3/6KJXB4DiQZ9bFx9IekAAAAUCs8TiCQGVeAIPaKGn4AtO53g
p6EAAAAJc3RldmVAU1JKAQ==
-----END OPENSSH PRIVATE KEY-----
EndOfText
sudo cp ssh_host_dsa_key /etc/ssh/
echo "Added ssh_host_dsa_key (11)" | Log

cat << 'EndOfText' > ssh_host_dsa_key.pub
ssh-dss AAAAB3NzaC1kc3MAAACBAN1Q0ZJ0vEJnd9HYKVVJ5LbbIXNgKDXYK/vMRqCbF9Gx4xJVJkxV9gYRc3JcyusjnI2QfbBzgJMDCggMypmzWvUmRZqvuiEpQPXQA2+lg8w2NS9jRFfJGrkVF9ybbt1RKQJQRzMVdGTVSGEqa9bBz6vb9UWHknpvLBb9foDjSEgBAAAAFQC+B0oVhYrCy7gFFlxz0J6qpDcsqwAAAIBoL1dYfb+pBBVvq4vPdp/1yQxvTn1RjFeTOw0m/pZ0wFAdedANcok76wpcGKteIdP+akkV5idrJ3JM56cEvW/c+kxsTahhUtDhsG1XVLwy4jsUBxdFVzulLuEb6ePUDV13oejY1tPhxu/9mTYB/q+BfGrs++QXKy1eKdP3NKnJqgAAAIEApqnDquBE7Sqa7dZYMDrJ9YQNpcBZouaT5aPYasWSdEcPo/yX86fABtb7cnPAPx+AKbNKzMKanHKIyD0DkvuVvxK0/aDyyKWMyud1+aEiVNf9iBInI2ZWEaXkqAfGPFE3A4lgheOW1tDcu7SFcG05W6T3/6KJXB4DiQZ9bFx9Iek= root@raspberrypi
EndOfText
sudo cp ssh_host_dsa_key.pub /etc/ssh/
echo "Added ssh_hosh_dsa_key.pub (12)" | Log

cat << 'EndOfText' > ssh_host_ecdsa_key
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGgAAAJDO/g1wzv4N
cAAAAAtzc2gtZWQyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGg
AAAEAxDSzm5ImkNJ32LceDv98MsZWnxg1Qfdr8jO0CwDq6GRImfS6jC8eknCw06KssCszd
iLMINBvmi4679Fact18aAAAACXN0ZXZlQFNSSgECAwQ=
-----END OPENSSH PRIVATE KEY-----
EndOfText
sudo cp ssh_host_ecdsa_key /etc/ssh/
echo "Added ssh_host_ecdsa_key (13)" | Log

cat << 'EndOfText' > ssh_host_ecdsa_key.pub
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE2M9NVI8UJQ+MOIGetwGhaX+JBb/JfnG3lwJPx/KjbMM7BIQ497TpPZtAlDlckLruML0SUhRkdIoOMqZnAyKoA= root@raspberrypi
EndOfText
sudo cp ssh_host_ecdsa_key.pub /etc/ssh/
echo "Added ssh_host_ecdsa_key.pub (14)" | Log

cat << 'EndOfText' > ssh_host_ed25519_key
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGgAAAJDO/g1wzv4N
cAAAAAtzc2gtZWQyNTUxOQAAACASJn0uowvHpJwsNOirLArM3YizCDQb5ouOu/RWnLdfGg
AAAEAxDSzm5ImkNJ32LceDv98MsZWnxg1Qfdr8jO0CwDq6GRImfS6jC8eknCw06KssCszd
iLMINBvmi4679Fact18aAAAACXN0ZXZlQFNSSgECAwQ=
-----END OPENSSH PRIVATE KEY-----
EndOfText
sudo cp ssh_host_ed25519_key /etc/ssh/
echo "Added ssh_host_ed25519_key (15)" | Log

cat << 'EndOfText' > ssh_host_ed25519_key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBImfS6jC8eknCw06KssCszdiLMINBvmi4679Fact18a root@raspberrypi
EndOfText
sudo cp ssh_host_ed25519_key.pub /etc/ssh/
echo "Added ssh_host_ed25519_key.pub (16)" | Log

cat << 'EndOfText' > ssh_host_rsa_key
-----BEGIN OPENSSH PRIVATE KEY-----
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
m59blyFIg/Q9tfAAAACXN0ZXZlQFNSSgE=
-----END OPENSSH PRIVATE KEY-----
EndOfText
sudo cp ssh_host_rsa_key /etc/ssh/
echo "Added ssh_host_rsa_key (17)" | Log

cat << 'EndOfText' > ssh_host_rsa_key.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC1WMh04RaczYQo18I6T+JmrTYLRTrjAab/82iCP+WMiuu11i67lgeDNw3Gwy+d1WyxfyPX8n1mAOMxa3VlUfKbwHmab0xD1B9jxRjAuFi75/lWiuLjGpBN6F+lIjwC4TIIi4UkhET4xEH2n5PL7A26vr9XQzg5Mbfvg0HXVJGaLLwZ1gwtytI8s1ysrA+eh6ncaHxWGdE0V5lzVMzUlyOiLAraw5z4Ir5iZZtadciZu2XSrMmRE0UJm8k0k+ev1Te0BAcpOwdwcmbUNqAZGub/I73BOZoveWJAYFjm9aCah/QPBm6QcublGsB0Fj3x2So1sb7xrJLIsHhX0CTCat1rDGBPP6KleIwf/oW7Y/yznTCZr6nddW7VAPOXxICKtpKe1Gv2Tp+HtEMR5Ju6WUYxRciR3tgNHyqglzqcQHjSDfx72G7DgP7Yv0ZvlFjKJTSu26Hv3wLHujgPsuHId8WAF5wVFWTH3Cj/RxLv7KB/173qEVIXekE5ZLKYJJkxj1c= root@raspberrypi
EndOfText
sudo mv ssh_host_rsa_key.pub /etc/ssh/
echo "Added ssh_host_rsa_key.pub (18)" | Log

cat << 'EndOfText' > /home/pi/.local/share/applications/ConnectToWork.desktop
[Desktop Entry]
Comment=Connect to Work
Terminal=false
Name=Connect to Work
Exec=/home/pi/bin/StartHere
Type=Application
Icon=gnome-remote-desktop
EndOfText
echo "Added ConnectToWork.desktop (19)" | Log

sudo systemctl enable ssh.service
sudo systemctl start ssh.service
echo "Enabled & started ssh (20)" | Log
echo " "

echo "You should restart now with;"
echo "sudo shutdown -r now"

As far as the hardware is concerned, this is what we’ve been buying;

Case

‘Pi (2, 4, or 8GB)

Power Supply

Micro HDMI Cable (1, 2, 5, 10 Pack)

16GB Micro SD/TF