hexopi/hexopi.sh
2020-05-26 11:35:37 +02:00

204 lines
5.2 KiB
Bash

#!/usr/bin/env sh
# SPDX-License-Identifier: GPL-3.0
# Denis Kanuf <https://denkn.at>
die() {
>&2 printf '\e[1;31mdied: %s\e[0m\n' "$*"
exit 1
}
l() {
>&2 printf '\e[1m%s\e[0m\n' "$*"
}
d() {
>&2 printf '\e[1;34m# %s\e[0m\n' "$*"
"$@" || die "$*"
}
MNAME=octoprint
MDIR=/var/lib/machines/$MNAME
TDIR=/var/lib/machines/$MNAME-template
DEVPTN='/dev/ttyUSB*'
LICENSE="$(cat <<EOF
# SPDX-License-Identifier: GPL-3.0
# Denis Knauf <https://denkn.at>
EOF
)"
alias OP='d systemd-nspawn --machine=$MNAME --hostname=$MNAME --directory="$MDIR" --tmpfs=/run --tmpfs=/run/lock'
t_mkdir() {
for d
do
d install -d "$TDIR/$d"
done
}
###############################################################################
ho_install() {
d apt install -y systemd-container debootstrap cron-apt dnsmasq
d dd of=/etc/cron-apt/action.d/6-upgrade <<EOF
safe-upgrade -y
EOF
if [ -d "$MDIR" ]
then
l skipping debootstrap
else
d rm -rf "$MDIR".tmp
d debootstrap --include=systemd-container stable "$MDIR".tmp
d mv "$MDIR".tmp "$MDIR"
fi
OP apt update
OP apt dist-upgrade -y
OP apt install -y nullmailer python3-pip cron-apt ffmpeg
OP pip3 install octoprint
OP sh -c 'getent passwd octoprint || useradd -mrUd /var/lib/octoprint -G dialout octoprint'
d install -o root -g root -m 0755 "$0" /usr/local/sbin/hexapi
d install -o root -g root -m 0755 "$0" "$MDIR"/usr/local/sbin/hexapi
d dd of="$MDIR"/etc/cron-apt/action.d/6-upgrade <<EOF
safe-upgrade -y
EOF
d dd of=/etc/systemd/system/octoprint-container@.service <<EOF
${LICENSE}
# Based on systemd-nspawn@.service
[Unit]
Description=OctoPrint Container for %i
Documentation=man:systemd-nspawn(1)
PartOf=machines.target
Before=machines.target
After=network.target systemd-resolved.service
RequiresMountsFor=/var/lib/machines
BindTo=dev-%i.device
[Service]
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest \
--settings=override \
--directory=/var/lib/machines/octoprint@ttyUSB0 --template=/var/lib/machines/octoprint-template \
--overlay=/var/lib/machines/octoprint/etc:/var/lib/machines/octoprint@%i/etc:/etc \
--bind-ro=/var/lib/machines/octoprint/usr:/usr --bind=/dev/%i --machine=%i --hostname=%i
KillMode=mixed
Type=notify
RestartForceExitStatus=133
SuccessExitStatus=133
WatchdogSec=3min
Slice=machine.slice
Delegate=yes
TasksMax=16384
# Enforce a strict device policy, similar to the one nspawn configures when it
# allocates its own scope unit. Make sure to keep these policies in sync if you
# change them!
DevicePolicy=closed
DeviceAllow=/dev/net/tun rwm
DeviceAllow=char-pts rw
# nspawn itself needs access to /dev/loop-control and /dev/loop, to implement
# the --image= option. Add these here, too.
DeviceAllow=/dev/loop-control rw
DeviceAllow=block-loop rw
DeviceAllow=block-blkext rw
# nspawn can set up LUKS encrypted loopback files, in which case it needs
# access to /dev/mapper/control and the block devices /dev/mapper/*.
DeviceAllow=/dev/mapper/control rw
DeviceAllow=block-device-mapper rw
# octoprint needs access to serial-interfaces.
DeviceAllow=/dev/%i rw
DeviceAllow=char-ttyUSB rw
[Install]
WantedBy=machines.target
EOF
d dd of="/etc/udev/rules.d/50-octoprint-container.rules" <<EOF
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="octoprint-container@%k.service" ENV{SYSTEMD_ALIAS}+="/dev/%k"
EOF
d dd of="$MDIR"/etc/systemd/system/octoprint-init.service <<EOF
${LICENSE}
[Unit]
Description=Initialize Octoprint 3d-printer web interface
Before=octoprint.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/hexapi install_env
[Install]
WantedBy=multi-user.target
EOF
d ln -fs ../octoprint-init.service "$MDIR"/etc/systemd/system/multi-user.target.wants/octoprint-init.service
d dd of="$MDIR"/etc/systemd/system/octoprint.service <<EOF
${LICENSE}
[Unit]
Description=OctoPrint 3D-printer web interface
After=octoprint-init.service
[Service]
EnvironmentFile=/local/env
EnvironmentFile=-/env
ExecStart=/usr/local/bin/octoprint serve --host=\${OCTOPRINT_HOST} --port=\${OCTOPRINT_PORT}
User=octoprint
Group=octoprint
[Install]
WantedBy=multi-user.target
EOF
t_mkdir /dev /media /opt /etc /mnt /usr /usr/lib /local /home /srv /run /boot /tmp /root /var \
/var/backups /var/opt /var/lib /var/local /var/spool /var/spool/cron /var/spool/rsyslog \
/var/spool/mail /var/log /var/cache /var/tmp /var/mail /proc /sys
d systemctl daemon-reload
}
###############################################################################
ho_list() {
for f in $DEVPTN
do
echo "found: $f"
done
}
###############################################################################
ho_environment() {
device=$(hostname)
if [ "$device" = "${device#ttyUSB}" ]
then
>&2 echo "not a container for running octoprint - no device"
exit 0
elif [ -e "/dev/$device" ]
then
> /local/env echo OCTOPRINT_HOST=0.0.0.0
>>/local/env echo OCTOPRINT_PORT=$((2000+${device#*USB}))
install -o octoprint -g octoprint -m 700 -d /var/lib/octoprint
/usr/bin/systemctl enable --no-block --now octoprint.service
/usr/bin/systemctl disable octoprint-init.service
else
>&2 echo "Device not found: $device"
exit 1
fi
}
###############################################################################
case "$1" in
install) ho_install ;;
list) ho_list ;;
install_env) ho_environment ;;
*)
>&2 echo "Usage: $0 install"
exit 1
;;
esac