This is part of a series of posts on the design and technical steps of creating Himblick, a digital signage box based on the Raspberry Pi 4.
Time to setup ssh. We want to have admin access to the pi
user, and we'd like
to have a broader access to a different, locked down user, to use to manage
media on the boxes via sftp.
The first step is to mount the exFAT media partition into /srv/media
:
---
- name: "Install exfat drivers"
apt:
name: exfat-fuse,exfat-utils
state: present
update_cache: no
- name: "Create /srv directory"
file:
path: "/srv"
state: directory
owner: root
group: root
mode: 0755
- name: "Create /media mount point"
file:
path: "/srv/media"
state: directory
owner: pi
group: pi
mode: 0755
- name: "Configure mounting media directory"
copy:
src: srv-media.mount
dest: /etc/systemd/system/srv-media.mount
owner: root
group: root
mode: 0644
Mounting exFAT before Linux kernel 5.4 requires FUSE. Using a mount unit allows us to bring up the mount after FUSE is up, and get it mounted at boot reliably.
We add a round of filesystem checking, too: if people plug the SD into a computer to load media into it, we can't be sure that they unmount it cleanly.
This is srv-media.mount
; note that .mount
unit names need to match the
path of the mount point:
[Unit]
Description=Media Directory (/srv/media)
Before=local-fs.target
After=sys-fs-fuse-connections.mount
[Mount]
What=/dev/disk/by-label/media
Where=/srv/media
Type=exfat
Options=uid=0,gid=1001,fmask=117,dmask=007,rw,noatime,nosuid,nodev
ExecStartPre=-/sbin/fsck.exfat -a /dev/disk/by-label/media
[Install]
WantedBy=local-fs.target
gid 1001
is the media
group id, shared by the pi
user that runs the media
player, and by the media
user that does sftp
. We make everything the media
mount group-writable by the media
user so both users can access it.
Next, we prepare a chroot jail for the media
user. The root of the jail
needs to be writable only by root,
so we bind mount the media directory inside it:
- name: "Create the chroot jail for media: /srv"
file:
path: "/srv"
state: directory
owner: root
group: root
mode: 0755
- name: "Create the chroot jail for media: /srv/jail"
file:
path: "/srv/jail"
state: directory
owner: root
group: root
mode: 0755
- name: "Create the chroot jail for media: /srv/jail/media"
file:
path: "/srv/jail/media"
state: directory
owner: root
group: media
mode: 0755
- name: "Bind mount /srv/media under /srv/jail/media"
copy:
src: srv-jail-media.mount
dest: /etc/systemd/system/srv-jail-media.mount
owner: root
group: root
mode: 0644
This is the srv-jail-media.mount
mount unit, neatly ordered to start after
/srv/media
is mounted:
[Unit]
Description=Media Directory in sftp jail (/srv/jail/media)
Before=local-fs.target
After=srv-media.target
[Mount]
What=/srv/media
Where=/srv/jail/media
Type=none
Options=bind
[Install]
WantedBy=local-fs.target
Finally, the ssh configuration:
---
- name: "Disable ssh password authentication"
lineinfile:
path: /etc/ssh/sshd_config
regexp: '\bPasswordAuthentication\b'
line: 'PasswordAuthentication no'
- name: "Install ssh admin access key"
authorized_key:
user: pi
state: present
key: "{{SSH_AUTHORIZED_KEY}}"
when: SSH_AUTHORIZED_KEY is defined
- name: "Install ssh media access key"
authorized_key:
user: media
state: present
key: "{{SSH_MEDIA_PUBLIC_KEY}}"
when: SSH_MEDIA_PUBLIC_KEY is defined
- name: "Install media access key for the pi user"
copy:
dest: "/home/pi/.ssh/id_media"
content: "{{SSH_MEDIA_PRIVATE_KEY}}"
owner: pi
group: pi
mode: 0600
when: SSH_MEDIA_PRIVATE_KEY is defined
- name: "Configure internal sftp, so ssh does not need binaries inside the jail"
lineinfile:
path: /etc/ssh/sshd_config
regexp: ".*Subsystem\\s+sftp"
line: "Subsystem sftp internal-sftp"
- name: "Configure sftp chroot jail for user media"
blockinfile:
path: /etc/ssh/sshd_config
block: |
Match User media
ChrootDirectory /srv/jail
AllowTcpForwarding no
X11Forwarding no
ForceCommand internal-sftp
Don't forget to enable the media units:
# Enable the /srv/media mount point, which ansible, as we run it
# now, is unable to do
chroot.systemctl_enable("srv-media.mount")
chroot.systemctl_enable("srv-jail-media.mount")