Add 2x on

This commit is contained in:
John Dorman 2023-02-18 19:31:32 -08:00
parent b337a1a292
commit 01145574eb
31 changed files with 957 additions and 0 deletions

View File

@ -0,0 +1,18 @@
FROM debian:stretch-slim
RUN set -ex \
&& echo 'deb http://deb.debian.org/debian stretch-backports main' > /etc/apt/sources.list.d/backports.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
devscripts \
fakeroot \
debhelper=12.\* dh-autoreconf=17\* \
&& apt-get -y autoremove \
&& apt-get clean \
&& rm -rf /tmp/* /var/tmp/* /var/log/* /var/lib/apt/lists/* /var/log/alternatives.log
RUN chmod a+rwx,u+t /tmp
ENTRYPOINT []
CMD ["/bin/sh"]

View File

@ -0,0 +1,60 @@
# UDM / UDMPro Boot Script
## Features
1. Allows you to run a shell script at S95 anytime your UDM starts / reboots
## Compatibility
1. Should work on any UDM/UDMPro after 2.4.x
* [build_deb.sh](build_deb.sh) can be used to build the package by yourself.
* [dpkg-build-files](dpkg-build-files) contains the sources that debuild uses to build the package if you want to build it yourself / change it
* by default it uses docker or podman to build the debian package
* use ```./build_deb.sh build``` to not use a container
* the resulting package will be in [packages/](packages/)
* Built on Ubuntu-20.04 on Windows 10/WSL2
## Install
You can execute in UDM/Pro/SE and UDR with:
```bash
curl -fsL "https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/on-boot-script/remote_install.sh" | /bin/sh
```
This is a force to install script so will uninstall any previous version and install on_boot keeping your on boot files.
This will also install CNI Plugins & CNI Bridge scripts. If you are using UDMSE/UDR remember that you must install podman manually because there is no podman.
## Manually Install Steps
1. Get into the unifios shell on your udm
```bash
unifi-os shell
```
2. Download [udm-boot-2x_1.0.1_all.deb](packages/udm-boot_1.0.0-2x_all.deb) and install it and go back to the UDM.
```bash
curl -L [[https://udm-boot.boostchicken.dev](https://unifi.boostchicken.io/udm-boot-2x_1.0.0_all.deb)](https://unifi.boostchicken.io/udm-boot-2x_1.0.0_all.deb) -o udm-boot-2x_1.0.0_all.deb
dpkg -i udm-boot-2x_1.0.0_all.deb
systemctl enable udm-boot
exit
```
3. Copy any shell scripts you want to run to /mnt/data/on_boot.d on your UDM (not the unifi-os shell) and make sure they are executable and have the correct shebang (#!/bin/sh). Additionally, scripts need to have a `.sh` extention in their filename.
Examples:
* Start a DNS Container [10-dns.sh](../dns-common/on_boot.d/10-dns.sh)
* Start wpa_supplicant [on_boot.d/10-wpa_supplicant.sh](examples/udm-files/on_boot.d/10-wpa_supplicant.sh)
* Add a persistent ssh key for the root user [on_boot.d/15-add-root-ssh-keys.sh](examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh)
## Version History
### 1.0.0
* First release that persists through firmware

101
on-boot-script-2.x/build_deb.sh Executable file
View File

@ -0,0 +1,101 @@
#!/bin/sh
set -e
WORK_DIR="$(cd "$(dirname "$0")" && echo "${PWD}")"
TARGET_DIR="${WORK_DIR}/packages"
SOURCE_DIR="${WORK_DIR}/dpkg-build-files"
CONTAINER_FILE="${WORK_DIR}/Dockerfile"
CONTAINER_CONTEXT="${WORK_DIR}"
fatal() {
echo "ERROR: ${1}" 1>&2
exit ${2-1}
}
build_in_container=false
build=false
build_container=false
if [ $# -eq 0 ]; then
build_in_container=true
fi
if [ "${1}" = "build" ]; then
build=true
fi
if [ "${1}" = "build_container" ]; then
build_container=true
fi
build_in_container() {
docker_exec="$(command -v docker || true)"
podman_exec="$(command -v podman || true)"
container_exec="${docker_exec:-"${podman_exec}"}"
container_args=""
if [ ! -f "${container_exec}" ]; then
fatal "docker or podman not found"
fi
if [ ! -f "${CONTAINER_FILE}" ]; then
fatal "container file ${CONTAINER_FILE} not found"
fi
if [ "${container_exec}" = "${docker_exec}" ]; then
# docker does not map user, so we run it as user
container_args="--user "$(id -u):$(id -g)""
fi
"${container_exec}" build --file "${CONTAINER_FILE}" --tag udm-boot-deb-builder "${CONTAINER_CONTEXT}"
"${container_exec}" run -it \
${container_args} \
-v "${SOURCE_DIR}:/source:ro" \
-v "${TARGET_DIR}:/target:rw" \
-v "${WORK_DIR}/build_deb.sh:/build_deb.sh:ro" \
--rm \
udm-boot-deb-builder \
/build_deb.sh build_container
}
build() {
source_dir=$1
target_dir=$2
version="$(dpkg-parsechangelog --show-field version -l "${source_dir}/debian/changelog")"
name="$(dpkg-parsechangelog --show-field source -l "${source_dir}/debian/changelog")"
package_name="${name}-${version}"
build_dir="$(mktemp --tmpdir="/tmp" --directory "${name}.XXXXXXXXXX")"
build_package_dir="${build_dir}/${package_name}"
if [ ! -d "${source_dir}" ]; then
fatal "source dir ${source_dir} not found"
fi
if [ ! -d "${target_dir}" ]; then
fatal "target dir ${target_dir} not found"
fi
mkdir -p "${build_package_dir}"
cp -r "${source_dir}"/* "${build_package_dir}"
(
cd "${build_package_dir}"
# we could exclude "source" here to skip building the source,
# but lintian warns only in the source build about some stuff
debuild -us -uc --build=source,all --lintian-opts --profile debian
)
find "${build_dir}" -maxdepth 1 -type f -exec mv {} "${target_dir}" \;
rm -rf "${build_dir}"
}
build_container() {
build "/source" "/target"
}
if [ $build_in_container = true ]; then
build_in_container
fi
if [ $build = true ]; then
build "${SOURCE_DIR}" "${TARGET_DIR}"
fi
if [ $build_container = true ]; then
build_container
fi

View File

@ -0,0 +1,5 @@
udm-boot-2x (1.0.0) stable; urgency=medium
* Initial release, happy firmware persisting!
-- Boostchicken <john@boostchicken.dev> Sat, 18 Feb 2023 18:46:14 -0700

View File

@ -0,0 +1,15 @@
Source: udm-boot-2x
Section: contrib/utils
Priority: optional
Maintainer: Boostchicken <john@boostchicken.dev>
Build-Depends: debhelper-compat (= 12)
Standards-Version: 4.4.1
Homepage: https://github.com/unifi-utilities/unifios-utilities
#Vcs-Browser: https://salsa.debian.org/debian/udmboot
#Vcs-Git: https://salsa.debian.org/debian/udmboot.git
Package: udm-boot-2x
Architecture: all
Depends: ${misc:Depends}
Description: Run things on boot on UDM 2.x
Run things on boot!

View File

@ -0,0 +1,9 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: udm-boot-2x
Upstream-Contact: John Dorman / Boostchicken
Source: https://github.com/unifi-utilities/unifi-utilities
Files: *
Copyright: 2023 john@boostchicken.dev
License: GPL-3
https://github.com/unifi-utilities/unifi-utilities/blob/main/LICENSE

View File

@ -0,0 +1 @@
udm-boot.service lib/systemd/system/

View File

@ -0,0 +1,40 @@
#!/bin/sh
# postinst script for udm-boot
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
alias deb-systemd-invoke='systemctl --no-block --'
case "$1" in
configure)
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

@ -0,0 +1,38 @@
#!/bin/sh
# postrm script for udm-boot
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
true
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

@ -0,0 +1,37 @@
#!/bin/sh
# preinst script for udm-boot
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <new-preinst> `install'
# * <new-preinst> `install' <old-version>
# * <new-preinst> `upgrade' <old-version>
# * <old-preinst> `abort-upgrade' <new-version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
install|upgrade)
true
;;
abort-upgrade)
;;
*)
echo "preinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

@ -0,0 +1,40 @@
#!/bin/sh
# prerm script for udm-boot
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <prerm> `remove'
# * <old-prerm> `upgrade' <new-version>
# * <new-prerm> `failed-upgrade' <old-version>
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
# * <deconfigured's-prerm> `deconfigure' `in-favour'
# <package-being-installed> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
remove|upgrade|deconfigure)
# reserved for future use
true
;;
failed-upgrade)
;;
*)
echo "prerm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

View File

@ -0,0 +1,5 @@
#!/usr/bin/make -f
%:
dh $@

View File

@ -0,0 +1 @@
3.0 (native)

View File

@ -0,0 +1,3 @@
udm-boot-2x source: changelog-should-mention-nmu
udm-boot-2x source: source-nmu-has-incorrect-version-number
udm-boot-2x source: odd-historical-debian-changelog-version

View File

@ -0,0 +1,16 @@
[Unit]
Description=Run On Startup UDM 2.x
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=500
StartLimitBurst=5
[Service]
Restart=on-failure
RestartSec=5s
ExecStart='mkdir -p /data/on_boot.d && find -L /data/on_boot.d -mindepth 1 -maxdepth 1 -type f -print0 | sort -z | xargs -0 -r -n 1 -- sh -c '\''if test -x "$0"; then echo "%n: running $0"; "$0"; else case "$0" in *.sh) echo "%n: sourcing $0"; . "$0";; *) echo "%n: ignoring $0";; esac; fi'\'
RemainAfterExit=true
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,29 @@
#!/bin/sh
## Configure shell profile
device_info() {
echo $(/usr/bin/ubnt-device-info "$1")
}
# Modify login banner (motd)
cat > /etc/motd <<EOF
Welcome to UniFi Dream Machine!
(c) 2010-$(date +%Y) Ubiquiti Inc. | http://www.ui.com
Model: $(device_info model)
Version: $(device_info firmware)
MAC Address: $(device_info mac)
EOF
# Extend UbiOS prompt to include useful information
cat > /etc/profile.d/prompt.sh <<'EOF'
UDM_NAME="$(grep -m 1 '^name:' /data/unifi-core/config/settings.yaml | awk -F: '{ gsub(/^[ \t]+|[ \t]+$/, "", $2); print tolower($2) }')"
PROMPT_MAIN="\u@${UDM_NAME}:\w"
export PS1="[UDM] ${PROMPT_MAIN}${PS1}"
EOF
# Copy all global profile scripts (for all users) from `/mnt/data/on_boot.d/settings/profile/global.profile.d/` directory
mkdir -p /mnt/data/on_boot.d/settings/profile/global.profile.d
cp -rf /mnt/data/on_boot.d/settings/profile/global.profile.d/* /etc/profile.d/

View File

@ -0,0 +1,7 @@
#!/bin/sh
## create files like this with different numbers for execution order
## ala /etc/profile.d
## example command to run, please replace with your own.
podman start wpa_supplicant-udmpro

View File

@ -0,0 +1,3 @@
#!/bin/sh
cp -f /mnt/data/on_boot.d/files/.profile /root/

View File

@ -0,0 +1,63 @@
#!/bin/sh
## Config Variables - please edit these
# Set to true to download public keys from a github user account
USE_GITHUB_KEYS=true
# Enter your username on github to get the public keys for
GITHUB_USER="<YOUR_USERNAME>"
# File location for the output of the git download
GITHUB_KEY_PATH="/mnt/data/podman/ssh"
GITHUB_KEY_FILE="${GITHUB_KEY_PATH}/github.keys"
# Set to true to use a file containing a key per line in the format ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAA...\n
USE_KEY_FILE=true
# IF using an input file, list it here
INPUT_KEY_PATH="/mnt/data/podman/ssh"
INPUT_KEY_FILE="${INPUT_KEY_PATH}/ssh.keys"
# The target key file for the script
OUTPUT_KEY_PATH="/root/.ssh"
OUTPUT_KEY_FILE="${OUTPUT_KEY_PATH}/authorized_keys"
## Functions
# This function downloads the keys from the selected github user
download_from_github(){
if curl --output /dev/null --silent --head --fail https://github.com/${GITHUB_USER}.keys; then
curl https://github.com/${GITHUB_USER}.keys -o ${GITHUB_KEY_FILE}
echo "Downloaded keys from Github"
else
echo "Could not download ${GITHUB_USER}'s key file from github"
fi
}
# Write line to the output line. Add the input line as an arguement.
write_to_output(){
# Check the file exits
if ! test -f ${OUTPUT_KEY_FILE}; then
echo "File at ${OUTPUT_KEY_FILE} does not exist, creating it"
touch ${OUTPUT_KEY_FILE}
fi
echo "${1}" >> ${OUTPUT_KEY_FILE}
}
# This function reads keys from a file into the requested file. The arguement is the input file.
use_key_from_file(){
if ! test -f $1; then
echo "File $1 does not exist"
return
fi
counter=0;
while IFS= read -r line;
do
write_to_output "${line}"
let "counter++"
done < $1
echo "${counter} number of entries read from "
}
## Script
# Makes paths if they don't exit
mkdir -p ${GITHUB_KEY_PATH} ${INPUT_KEY_PATH} ${OUTPUT_KEY_PATH}
#Check flags to see which files to use
if [ ${USE_GITHUB_KEYS} = true ]; then
download_from_github
use_key_from_file ${GITHUB_KEY_FILE}
fi
if [ ${USE_KEY_FILE} = true ]; then
use_key_from_file ${INPUT_KEY_FILE}
fi

View File

@ -0,0 +1,29 @@
#!/bin/sh
## Places public keys in ~/.ssh/authorized_keys
KEYS_SOURCE_FILE="/mnt/data/on_boot.d/settings/ssh/authorized_keys"
KEYS_TARGET_FILE="/root/.ssh/authorized_keys"
count_added=0
count_skipped=0
while read -r key; do
# Places public key in ~/.ssh/authorized_keys if not present
if ! grep -Fxq "$key" "$KEYS_TARGET_FILE"; then
let count_added++
echo "$key" >> "$KEYS_TARGET_FILE"
else
let count_skipped++
fi
done < "$KEYS_SOURCE_FILE"
echo "${count_added} keys added to ${KEYS_TARGET_FILE}"
if [ $count_skipped -gt 0 ]; then
echo "${count_skipped} already added keys skipped"
fi
# Convert ssh key to dropbear for shell interaction
echo "Converting SSH private key to dropbear format"
dropbearconvert openssh dropbear /mnt/data/ssh/id_rsa /root/.ssh/id_dropbear
exit 0

View File

@ -0,0 +1,29 @@
#!/bin/sh
#####################################################
# ADD KNOWN HOSTS AS BELOW - CHANGE BEFORE RUNNING #
#####################################################
# set -- "known host text on a line with quotes " \ #
# "second known host on another line " \ #
# "one per line, last line has no backslash" #
#####################################################
set -- "hostname ecdsa-sha2-nistp256 AAAABIGHOSTIDENTIFIERWITHMAGICSTUFF=" \
"otherhost ecdsa-sha2-nistp256 AAAADIFFERENTHOSTMAGICSTUFF!@HJKSL="
KNOWN_HOSTS_FILE="/root/.ssh/known_hosts"
counter=0
for host in "$@"
do
## Places known host in ~/.ssh/known_hosts if not present
if ! grep -Fxq "$host" "$KNOWN_HOSTS_FILE"; then
let counter++
echo "$host" >> "$KNOWN_HOSTS_FILE"
fi
done
echo $counter hosts added to $KNOWN_HOSTS_FILE
exit 0;

View File

@ -0,0 +1,13 @@
#!/bin/sh
mkdir -p /mnt/data/.home
for file in .ash_history .bash_history
if [ ! -f /mnt/data/.home/$file ]; then
touch /root/$file
cp /root/$file /mnt/data/.home/$file
chown root:root /mnt/data/.home/$file
chmod 0600 /mnt/data/.home/$file
fi
ln -sf /mnt/data/.home/$file /root/$file

View File

@ -0,0 +1,7 @@
#!/bin/sh
## create files like this with different numbers for execution order
## ala /etc/profile.d
## Start the ntopng-udm container, from https://github.com/tusc/ntopng-udm
podman start ntopng

View File

@ -0,0 +1,9 @@
#!/bin/sh
## Store crontab files in /mnt/data/cronjobs/ (you will need to create this folder).
## This script will re-add them on startup.
cp /mnt/data/cronjobs/* /etc/cron.d/
/etc/init.d/crond restart
exit 0

View File

@ -0,0 +1,10 @@
#!/bin/sh
CONTAINER=node-exporter
# Starts a Prometheus node-exporter container that is deleted after it is stopped.
if podman container exists "${CONTAINER}"; then
podman start "${CONTAINER}"
else
podman run -d --rm --name "${CONTAINER}" --net="host" --pid="host" -v "/:/host:ro,rslave" quay.io/prometheus/node-exporter:latest --path.rootfs=/host
fi

View File

@ -0,0 +1,15 @@
#!/bin/sh
alias -='cd -'
alias ...=../..
alias ....=../../..
alias .....=../../../..
alias ......=../../../../..
alias cp='cp -i'
alias la='ls -lAFh'
alias ll='ls -l'
alias md='mkdir -p'
alias mkcd='foo(){ mkdir -p "$1"; cd "$1" }; foo'
alias mv='mv -i'
alias rd=rmdir
alias rm='rm -i'

View File

@ -0,0 +1,87 @@
#!/bin/sh
## ----------------------------------------------------------------------
## Script to add/remove time-of-day restrictions on internet access for selected clients.
##
## Use DHCP reservations to encourage the selected clients to always obtain the same IP address.
##
## To install:
## * Copy this script into /mnt/data/on_boot.d/, using something like WinSCP or SSH + vi.
## * Grant Execute permission: chmod +x /mnt/data/on_boot.d/iptables_timerestrict.sh
## * Run it once, to activate it (crontab entries will keep it active forever after):
## Via SSH into UDM shell: /mnt/data/on_boot.d/iptables_timerestrict.sh
##
## Notes:
## * Changes to firewall rules in the Unifi Network Application will remove your restriction;
## re-run this script to re-apply the restriction rule, or wait for the next activation/deactivation hour.
## * To apply changes to this script (i.e. new client addresses, or changes to the time of day),
## re-run this script manually to apply the updates, or wait for the next activation/deactivation hour.
## * When this script activates or deactivates the blocking, it will log to /var/log/messages.
## * While the blocking is active, you'll see one "TIMERESTRICT BLOCK: " log message per hour
## in /var/log/messages if any blocked clients are attempting to use the internet.
##
## Caveats:
## * No support for wake_minute/sleep_minute - currently this only turns on/off at the top of an hour.
## * Assumption exists that sleep_hour is always greater-than wake_hour; i.e., you can't currently
## have a blocked time in the middle of the day.
## ----------------------------------------------------------------------
## List all client addresses you'd like to restrict. Separate multiple with spaces.
timerestricted_addresses='192.168.1.101 192.168.1.102'
## Hour of day to remove the restriction.
wake_hour=06
## Hour of day to activate the restriction.
sleep_hour=23
## ----------------------------------------------------------------------
## ----------------------------------------------------------------------
## ----------------------------------------------------------------------
myrule="FORWARD -i br0 -j TIMERESTRICT"
## report on blocks if rule exists
iptables -C $myrule 2>/dev/null && iptables -vL TIMERESTRICT | logger
echo "Setting up timerestrict firewall rules between $sleep_hour:00 and $wake_hour:00"
## initial setup
iptables -N TIMERESTRICT_LOGNDROP 2>/dev/null
iptables -F TIMERESTRICT_LOGNDROP 2>/dev/null
iptables -A TIMERESTRICT_LOGNDROP -m limit --limit 1/hour --limit-burst 1 -j LOG --log-prefix "TIMERESTRICT BLOCK: "
iptables -A TIMERESTRICT_LOGNDROP -j REJECT --reject-with icmp-net-prohibited
iptables -N TIMERESTRICT 2>/dev/null
iptables -F TIMERESTRICT 2>/dev/null
for ip in $timerestricted_addresses ; do
iptables -A TIMERESTRICT -s $ip -j TIMERESTRICT_LOGNDROP
done
myrule="FORWARD -i br0 -j TIMERESTRICT"
## install or remove rule based on current time and whether the rule already exists
if [ `date +%H` -ge $sleep_hour ]; then
logger "TIMERESTRICT: Activating sleep time"
iptables -C $myrule 2>/dev/null || iptables -I $myrule
elif [ `date +%H` -ge $wake_hour ]; then
logger "TIMERESTRICT: Activating awake time"
iptables -C $myrule 2>/dev/null && iptables -D $myrule
fi
## setup cron job to activate/deactivate on time of day
echo "00 $sleep_hour * * * `readlink -f $0`" > /etc/cron.d/iptables_timerestrict
echo "00 $wake_hour * * * `readlink -f $0`" >> /etc/cron.d/iptables_timerestrict
## Format: <minute> <hour> <day> <month> <dow> <tags and command>
/etc/init.d/crond restart
echo "Done with firewall rule setup:"
echo "-------------------------------------------------------------------"
iptables -vL FORWARD | egrep '(Chain|pkts|TIMERESTRICT)'
echo ...
iptables -vL TIMERESTRICT
iptables -vL TIMERESTRICT_LOGNDROP
echo

View File

@ -0,0 +1,8 @@
#!/bin/sh
## Create network bridge for CNI
ip link show cni0 > /dev/null 2>&1
if [ $? -ne 0 ]; then
ip link add cni0 type bridge
fi

View File

@ -0,0 +1,13 @@
#!/bin/sh
# Download and install the service
podman exec unifi-os curl -fsSLo /lib/systemd/system/udm-boot.service https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/on-boot-script/dpkg-build-files/udm-boot.service
# If you want to manually install this offline,
# Have that file downloaded first, scp it to udm (e.g. /tmp/udm-boot.service)
# Then copy it from host to container with this command:
#
# podman cp /tmp/udm-boot.service unifi-os:/lib/systemd/system/udm-boot.service
# Start the service
podman exec unifi-os systemctl enable --now udm-boot.service

Binary file not shown.

View File

@ -0,0 +1,246 @@
#!/usr/bin/env sh
# Get DataDir location
DATA_DIR="/mnt/data"
case "$(ubnt-device-info firmware || true)" in
1*)
DATA_DIR="/mnt/data"
;;
2*)
DATA_DIR="/data"
;;
3*)
DATA_DIR="/data"
;;
*)
echo "ERROR: No persistent storage found." 1>&2
exit 1
;;
esac
# A change in the name udm-boot would need to be reflected as well in systemctl calls.
SYSTEMCTL_PATH="/etc/systemd/system/udm-boot.service"
SYMLINK_SYSTEMCTL="/etc/systemd/system/multi-user.target.wants/udm-boot.service"
CNI_PLUGINS_SCRIPT_RAW_URL="https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/cni-plugins/05-install-cni-plugins.sh"
CNI_PLUGINS_ON_BOOT_FILENAME="$(basename "$CNI_PLUGINS_SCRIPT_RAW_URL")"
CNI_BRIDGE_SCRIPT_RAW_URL="https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/on-boot-script/examples/udm-networking/on_boot.d/06-cni-bridge.sh"
CNI_BRIDGE_ON_BOOT_FILENAME="$(basename "$CNI_BRIDGE_SCRIPT_RAW_URL")"
GITHUB_API_URL="https://api.github.com/repos"
GITHUB_REPOSITORY="unifi-utilities/unifios-utilities"
# --- Functions ---
header() {
cat << EOF
_ _ ___ __ __ ___ _
| | | | \| \/ | | _ ) ___ ___| |_
| |_| | |) | |\/| | | _ \/ _ \/ _ \ _|
\___/|___/|_| |_| |___/\___/\___/\__|
Execute any script when your udm system
starts.
EOF
}
command_exists() {
command -v "${1:-}" >/dev/null 2>&1
}
depends_on() {
! command_exists "${1:-}" && echo "Missing dependencie(s): \`$*\`" 1>&2 && exit 1
}
udm_model() {
case "$(ubnt-device-info model || true)" in
"UniFi Dream Machine SE")
echo "udmse"
;;
"UniFi Dream Machine Pro")
if test $(ubnt-device-info firmware) \< "2.0.0"; then
echo "udmprolegacy"
else
echo "udmpro"
fi
;;
"UniFi Dream Machine")
if test $(ubnt-device-info firmware) \< "2.0.0"; then
echo "udmlegacy"
else
echo "udm"
fi
;;
"UniFi Dream Router")
echo "udr"
;;
*)
echo "unknown"
;;
esac
}
get_latest_download_url() {
depends_on awk
curl -fsL "${GITHUB_API_URL}/${GITHUB_REPOSITORY}/releases/latest" |
awk '$0 ~ /"browser_download_url"/ {sub(/.*:\s*"/,"",$0); gsub("\"", "", $0); print $0}'
}
# download_on_path <path> <url>
download_on_path() {
[ $# -lt 2 ] &&
echo "Missing arguments: \`$*\`" 1>&2 &&
return 1
curl -sLJo "$1" "$2"
[ -r "$1" ]
}
install_on_boot_udm_series() {
download_url="$(get_latest_download_url)"
tmp_path="/tmp/$(basename "${download_url}")"
podman exec unifi-os systemctl disable udmboot >/dev/null 2>&1 || true
podman exec unifi-os systemctl disable udm-boot >/dev/null 2>&1 || true
podman exec unifi-os systemctl daemon-reload >/dev/null 2>&1 || true
podman exec unifi-os rm -rf /etc/init.d/udm.sh >/dev/null 2>&1 || true
podman exec unifi-os rm -f "/etc/systemd/system/udmboot.service" "/etc/systemd/system/udm-boot.service" >/dev/null 2>&1 || true
echo "Downloading UDM boot package..."
podman exec unifi-os curl -sLJo "$tmp_path" "$download_url" || return 1
echo
sleep 1s
echo "Installing UDM boot package..."
podman exec unifi-os dpkg -i "$tmp_path" || return 1
echo
unset download_url tmp_path
}
# Credits @peacey: https://github.com/unifi-utilities/unifios-utilities/issues/214#issuecomment-886869295
udmse_on_boot_systemd() {
cat << EOF
[Unit]
Description=Run On Startup UDM
Wants=network-online.target
After=network-online.target
[Service]
Type=forking
ExecStart=bash -c 'mkdir -p $DATA_DIR/on_boot.d && find -L $DATA_DIR/on_boot.d -mindepth 1 -maxdepth 1 -type f -print0 | sort -z | xargs -0 -r -n 1 -- bash -c \'if test -x "\$0"; then echo "%n: running \$0"; "\$0"; else case "\$0" in *.sh) echo "%n: sourcing \$0"; . "\$0";; *) echo "%n: ignoring \$0";; esac; fi\''
[Install]
WantedBy=multi-user.target
EOF
}
install_on_boot_udr_se() {
systemctl disable udm-boot
systemctl daemon-reload
rm -f "$SYMLINK_SYSTEMCTL"
echo "Creating systemctl service file"
udmse_on_boot_systemd > "$SYSTEMCTL_PATH" || return 1
sleep 1s
echo "Enabling UDM boot..."
systemctl daemon-reload
systemctl enable "udm-boot"
systemctl start "udm-boot"
[ -e "$SYMLINK_SYSTEMCTL" ]
}
# --- main ---
header
depends_on ubnt-device-info
depends_on curl
ON_BOOT_D_PATH="$DATA_DIR/on_boot.d"
case "$(udm_model)" in
udmlegacy|udmprolegacy)
echo "$(ubnt-device-info model) version $(ubnt-device-info firmware) was detected"
echo "Installing on-boot script..."
depends_on podman
if ! install_on_boot_udm_series; then
echo
echo "Failed to install on-boot script service" 1>&2
exit 1
fi
echo "UDM Boot Script installed"
;;
udr|udmse|udm|udmpro)
echo "$(ubnt-device-info model) version $(ubnt-device-info firmware) was detected"
echo "Installing on-boot script..."
depends_on systemctl
if ! install_on_boot_udr_se; then
echo
echo "Failed to install on-boot script service" 1>&2
exit 1
fi
echo "UDM Boot Script installed"
;;
*)
echo "Unsupported model: $(ubnt-device-info model)" 1>&2
exit 1
;;
esac
echo
if [ ! -f "${ON_BOOT_D_PATH}/${CNI_PLUGINS_ON_BOOT_FILENAME}" ]; then
echo "Downloading CNI plugins script..."
if
! download_on_path "${ON_BOOT_D_PATH}/${CNI_PLUGINS_ON_BOOT_FILENAME}" "$CNI_PLUGINS_SCRIPT_RAW_URL"
then
echo
echo "Failed to download CNI plugins script" 1>&2
exit 1
fi
else
echo "Downloading of CNI bridge script skipped"
fi
chmod +x "${ON_BOOT_D_PATH}/${CNI_PLUGINS_ON_BOOT_FILENAME}"
echo "CNI plugins script installed"
echo "Executing CNI plugins script..."
"${ON_BOOT_D_PATH}/${CNI_PLUGINS_ON_BOOT_FILENAME}" || true
echo
if [ ! -f "${ON_BOOT_D_PATH}/${CNI_BRIDGE_ON_BOOT_FILENAME}" ]; then
echo "Downloading CNI bridge script..."
if
! download_on_path "${ON_BOOT_D_PATH}/${CNI_BRIDGE_ON_BOOT_FILENAME}" "$CNI_BRIDGE_SCRIPT_RAW_URL"
then
echo
echo "Failed to download CNI bridge script" 1>&2
exit 1
fi
else
echo "Downloading of CNI bridge script skipped"
fi
chmod +x "${ON_BOOT_D_PATH}/${CNI_BRIDGE_ON_BOOT_FILENAME}"
echo "CNI bridge script installed"
echo "Executing CNI bridge script..."
echo "${ON_BOOT_D_PATH}/${CNI_BRIDGE_ON_BOOT_FILENAME}"
"${ON_BOOT_D_PATH}/${CNI_BRIDGE_ON_BOOT_FILENAME}" || true
echo
echo "On boot script installation finished"
echo
echo "You can now place your scripts in \`${ON_BOOT_D_PATH}\`"
echo