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")