diff --git a/AdguardHome/README.md b/AdguardHome/README.md index 7504a23..91df880 100644 --- a/AdguardHome/README.md +++ b/AdguardHome/README.md @@ -2,47 +2,49 @@ ## Features -1. Run AdguardHome on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti +1. Run AdguardHome on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti 2. Persists through reboots and firmware updates. ## Requirements 1. You have setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script) -1. AdguardHome persists through firmware updates as it will store the configuration in a folder (you need to create this). It needs 2 folders, a Work and Configuration folder. Please create the 2 folders in "/mnt/data/". In my example I created "AdguardHome-Confdir" and "AdguardHome-Workdir" +1. AdguardHome persists through firmware updates as it will store the configuration in a folder (you need to create this). It needs 2 folders, a Work and Configuration folder. Please create the 2 folders in "/data/". In my example I created "AdguardHome-Confdir" and "AdguardHome-Workdir" ## Customization -* Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP and MAC address of the container. -* Update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with your own values -* If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments. +- Feel free to change [20-dns.conflist](../cni-plugins/20-dns.conflist) to change the IP and MAC address of the container. +- Update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with your own values +- If you want IPv6 support use [20-dnsipv6.conflist](../cni-plugins/20-dnsipv6.conflist) and update [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) with the IPv6 addresses. Also, please provide IPv6 servers to podman using --dns arguments. ## Steps -Please note if you have firmware v2 or above you have to copy all files into /data instead of /mnt/data. You can see what version you are running by running: ubnt-device-info firmware -1. Copy [05-install-cni-plugins.sh](../cni-plugins/05-install-cni-plugins.sh) to /mnt/data/on_boot.d -1. On your controller, make a Corporate network with no DHCP server and give it a VLAN. For this example we are using VLAN 5. You should confirm the bridge is created for this VLAN by running `netstat -r` otherwise the script will fail. If it is not there, initiate a provisioning of the UDM (Controller > UDM > Config > Manage Device > Force provision). -1. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to `/mnt/data/on_boot.d` and update its values to reflect your environment -1. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to `/mnt/data/podman/cni` after generating a MAC address. This will create your podman macvlan network. -1. Execute /mnt/data/on_boot.d/05-install-cni-plugins.sh -3. Execute `/mnt/data/on_boot.d/10-dns.sh` -4. Run the AdguardHome docker container, be sure to make the directories for your persistent AdguardHome configuration. They are mounted as volumes in the command below. +Please note if you have firmware v2 or above you have to copy all files into /data instead of /data. You can see what version you are running by running: ubnt-device-info firmware - ```shell script - mkdir /mnt/data/AdguardHome-Confdir - mkdir /mnt/data/AdguardHome-Workdir - - podman run -d --network dns --restart always \ - --name adguardhome \ - -v "/mnt/data/AdguardHome-Confdir/:/opt/adguardhome/conf/" \ - -v "/mnt/data/AdguardHome-Workdir/:/opt/adguardhome/work/" \ - --dns=127.0.0.1 --dns=1.1.1.1 \ - --hostname adguardhome \ - adguard/adguardhome:latest - ``` +1. Check if you have either `/mnt/data/` or `/data/` and use the correct one below. +2. Copy [05-install-cni-plugins.sh](../cni-plugins/05-install-cni-plugins.sh) to /data/on_boot.d +3. On your controller, make a Corporate network with no DHCP server and give it a VLAN. For this example we are using VLAN 5. You should confirm the bridge is created for this VLAN by running `netstat -r` otherwise the script will fail. If it is not there, initiate a provisioning of the UDM (Controller > UDM > Config > Manage Device > Force provision). +4. Copy [10-dns.sh](../dns-common/on_boot.d/10-dns.sh) to `/data/on_boot.d` and update its values to reflect your environment +5. Copy [20-dns.conflist](../cni-plugins/20-dns.conflist) to `/data/podman/cni` after generating a MAC address. This will create your podman macvlan network. +6. Execute /data/on_boot.d/05-install-cni-plugins.sh +7. Execute `/data/on_boot.d/10-dns.sh` +8. Run the AdguardHome docker container, be sure to make the directories for your persistent AdguardHome configuration. They are mounted as volumes in the command below. -1. Browse to 10.0.5.3:3000 and follow the setup wizard -1. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs. -1. Access the AdguardHome like you would normally. + ```shell script + mkdir /data/AdguardHome-Confdir + mkdir /data/AdguardHome-Workdir + + podman run -d --network dns --restart always \ + --name adguardhome \ + -v "/data/AdguardHome-Confdir/:/opt/adguardhome/conf/" \ + -v "/data/AdguardHome-Workdir/:/opt/adguardhome/work/" \ + --dns=127.0.0.1 --dns=1.1.1.1 \ + --hostname adguardhome \ + adguard/adguardhome:latest + ``` + +9. Browse to 10.0.5.3:3000 and follow the setup wizard +10. Update your DNS Servers to 10.0.5.3 (or your custom ip) in all your DHCP configs. +11. Access the AdguardHome like you would normally. ## Troubleshooting diff --git a/README.md b/README.md index 4d782cf..12fb802 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Script to persist ssh keys after reboot or firmware update. | WireGuard kernel module | | Uses a prebuilt linux kernel module, without the need to move to a custom kernel. | | OpenConnect VPN | | OpenConnect VPN Client for the UniFi Dream Machine Pro (Unofficial).| | split-vpn | |A split tunnel VPN script for the UDM with policy based routing. This helper script can be used on your UDM to route select VLANs, clients, or even domains through a VPN connection. It supports OpenVPN, WireGuard, and OpenConnect (Cisco AnyConnect) clients running directly on your UDM, and external VPN clients running on other servers on your network. | +| Zerotier | |ZeroTier provides network control and P2P functionality ยท Use ZeroTier to create products which run on their own decentralized networks | ## DNS Providers diff --git a/att-ipv6/10-att-ipv6.sh b/att-ipv6/10-att-ipv6.sh index e3b5fab..fcd064a 100755 --- a/att-ipv6/10-att-ipv6.sh +++ b/att-ipv6/10-att-ipv6.sh @@ -1,20 +1,47 @@ #! /bin/sh set -eo pipefail -wan_iface="eth8" # "eth9" for UDM Pro WAN2 -vlans="br0" # "br0 br100 br101..." -domain="example.invalid" # DNS domain +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "$DATA_DIR" ]; then + # If it does not exist, create the directory + mkdir -p "$DATA_DIR" + echo "Directory '$DATA_DIR' created." +else + # If it already exists, print a message + echo "Directory '$DATA_DIR' already exists. Moving on." +fi + +wan_iface="eth8" # "eth9" for UDM Pro WAN2 +vlans="br0" # "br0 br100 br101..." +domain="example.invalid" # DNS domain dns6="[2001:4860:4860::8888],[2001:4860:4860::8844]" # Google CONTAINER=att-ipv6 -confdir=/mnt/data/att-ipv6 +confdir=${DATA_DIR}/att-ipv6 # main mkdir -p "${confdir}/dhcpcd" test -f "${confdir}/dhcpcd.conf" || { - : > "${confdir}/dhcpcd.conf.tmp" - cat >> "${confdir}/dhcpcd.conf.tmp" <"${confdir}/dhcpcd.conf.tmp" + cat >>"${confdir}/dhcpcd.conf.tmp" <> "${confdir}/dhcpcd.conf.tmp" + ix=$((ix + 1)) + done >>"${confdir}/dhcpcd.conf.tmp" mv "${confdir}/dhcpcd.conf.tmp" "${confdir}/dhcpcd.conf" } test -f "${confdir}/att-ipv6-dnsmasq.conf" || { - : > "${confdir}/att-ipv6-dnsmasq.conf.tmp" - cat >> "${confdir}/att-ipv6-dnsmasq.conf.tmp" <"${confdir}/att-ipv6-dnsmasq.conf.tmp" + cat >>"${confdir}/att-ipv6-dnsmasq.conf.tmp" <> "${confdir}/att-ipv6-dnsmasq.conf.tmp" -mv "${confdir}/att-ipv6-dnsmasq.conf.tmp" "${confdir}/att-ipv6-dnsmasq.conf" + done >>"${confdir}/att-ipv6-dnsmasq.conf.tmp" + mv "${confdir}/att-ipv6-dnsmasq.conf.tmp" "${confdir}/att-ipv6-dnsmasq.conf" } - if podman container exists "$CONTAINER"; then podman start "$CONTAINER" else podman run -d --restart=always --name "$CONTAINER" -v "${confdir}/dhcpcd.conf:/etc/dhcpcd.conf" -v "${confdir}/dhcpcd:/var/lib/dhcpcd" --net=host --privileged ghcr.io/michaelw/dhcpcd fi - # Fix DHCP, assumes DHCPv6 is turned off in UI cp "${confdir}/att-ipv6-dnsmasq.conf" /run/dnsmasq.conf.d/ start-stop-daemon -K -q -x /usr/sbin/dnsmasq diff --git a/att-ipv6/README.md b/att-ipv6/README.md index 18cac02..0ac9cd7 100644 --- a/att-ipv6/README.md +++ b/att-ipv6/README.md @@ -1,6 +1,6 @@ # AT&T IPv6 -On ATT IPv6, the RG (residential gateway) receives a /60 prefix itself, but only hands out one /64 to routers in IP Passthrough mode, regardless how big of a prefix was requested. The RG keeps the lower 8 /64s for its own purposes (`2600:1700:X:yyy0::/63`), and Unifi normally only receives `2600:1700:X:yyyf::/64`. +On ATT IPv6, the RG (residential gateway) receives a /60 prefix itself, but only hands out one /64 to routers in IP Passthrough mode, regardless how big of a prefix was requested. The RG keeps the lower 8 /64s for its own purposes (`2600:1700:X:yyy0::/63`), and Unifi normally only receives `2600:1700:X:yyyf::/64`. This script enables UDM to receive up to 8 PDs on ATT IPv6 (tested with RG BGW320-500), usually starting at `2600:1700:X:yyyf::/64` down to `2600:1700:X:yyy8::/64`. Note that these may not always be assigned contiguous or in order. @@ -14,10 +14,10 @@ Firewall and routing rules remain functional, however. 2. You must set up the ATT RG in ["IP Passthrough" mode](https://patrickdomingues.com/2022/09/03/udm-pro-vpn-on-att-fiber-bgw320/) 3. You must turn off IPv6 on the ATT WAN connection, AND on each network/VLAN (IPv6 Interface Type: None) 4. You must add Firewall rules equivalent to (this can be done in the UI, select `Internet v6 Local` chain) - ``` - -A UBIOS_WAN_LOCAL_USER -p udp -m udp --sport 547 --dport 546 -j RETURN # select IPv6 Protocol "UDP" and create port groups for source port 547 and dest port 546 - -A UBIOS_WAN_LOCAL_USER -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j RETURN # select IPv6 Protocol "ICMPv6" and IPv6ICMP Type Name "Router Advertisement" - ``` + ``` + -A UBIOS_WAN_LOCAL_USER -p udp -m udp --sport 547 --dport 546 -j RETURN # select IPv6 Protocol "UDP" and create port groups for source port 547 and dest port 546 + -A UBIOS_WAN_LOCAL_USER -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j RETURN # select IPv6 Protocol "ICMPv6" and IPv6ICMP Type Name "Router Advertisement" + ``` 5. You may want to add a "Traffic Management" route on your ATT WAN device to access 192.168.1.254/32, so that you can access the RG after it is in passthrough mode. ## Customization @@ -31,13 +31,13 @@ Near the top of `10-att-ipv6.sh`: dns6="[2001:4860:4860::8888],[2001:4860:4860::8844]" # Google ``` -This generates configuration files in directory `/mnt/data/att-ipv6`, if they don't exist. +This generates configuration files in directory `/data/att-ipv6`, if they don't exist. The files can be edited, or regenerated by deleting them and re-running the script. ## Installation ```sh - cd /mnt/data/on_boot.d + cd /data/on_boot.d curl -LO https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/HEAD/att-ipv6/10-att-ipv6.sh chmod +x 10-att-ipv6.sh ./10-att-ipv6.sh @@ -47,11 +47,12 @@ The dhcpcd container being used is built [here](https://github.com/michaelw/dhcp ## Validation -Running the script starts dhcpcd within the `att-ipv6` container on `eth8` (WAN1) and only for the default network (`br0`). This can be customized, see above. +Running the script starts dhcpcd within the `att-ipv6` container on `eth8` (WAN1) and only for the default network (`br0`). This can be customized, see above. To check that everything is working as expected, and the ATT RG delegates multiple prefixes: On UDM: + ```sh $ ip -6 r # should see a default route on the WAN interface, and a 2600:1700:X:Y::/64 prefix on each configured VLAN bridge interface 2600:1700:X:yyy0::/64 dev eth9 proto ra metric 203 mtu 1500 pref medium @@ -106,8 +107,8 @@ $ ps auxw|grep dnsmasq # should see dnsmasq running On BGW320-500, check https://192.168.1.254/cgi-bin/lanstatistics.ha for multiple PDs in `IPv6 Delegated Prefix Subnet (including length)`. - On clients: + ``` ip -6 addr show # should see SLAAC and/or DHCPv6 addresses received (if not, check dnsmasq configuration in `/run/dnsmasq.conf.d`) ``` diff --git a/cloudflare-ddns/README.md b/cloudflare-ddns/README.md index e11828c..a9e3f02 100644 --- a/cloudflare-ddns/README.md +++ b/cloudflare-ddns/README.md @@ -1,4 +1,4 @@ -# Cloudflare Dynamic DNS +# Cloudflare Dynamic DNS ## Features @@ -8,7 +8,6 @@ Complete feature list and documentation can be found [here](https://github.com/timothymiller/cloudflare-ddns) - ## Requirements 1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script) @@ -18,6 +17,7 @@ Complete feature list and documentation can be found [here](https://github.com/t ## Customization Update [config.json](configs/config.json) with the following options: + - your cloudflare api token - your zone id - each subdomain you'd like to point at your udm-pro @@ -28,14 +28,14 @@ Update [config.json](configs/config.json) with the following options: 2. Make a directory for your configuration - ```sh - mkdir -p /mnt/data/cloudflare-ddns - ``` + ```sh + mkdir -p /data/cloudflare-ddns + ``` -3. Create a [cloudflare-ddns configuration](configs/config.json) in `/mnt/data/cloudflare-ddns` and update the configuration to meet your needs. -4. Copy [30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh) to `/mnt/data/on_boot.d`. -5. Execute /mnt/data/on_boot.d/[30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh) -7. Execute `podman logs cloudflare-ddns` to verify the continer is running without error (ipv6 warnings are normal). +3. Create a [cloudflare-ddns configuration](configs/config.json) in `/data/cloudflare-ddns` and update the configuration to meet your needs. +4. Copy [30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh) to `/data/on_boot.d`. +5. Execute /data/on_boot.d/[30-cloudflare-ddns.sh](on_boot.d/30-cloudflare-ddns.sh) +6. Execute `podman logs cloudflare-ddns` to verify the continer is running without error (ipv6 warnings are normal). ### Useful commands @@ -43,4 +43,3 @@ Update [config.json](configs/config.json) with the following options: # view cloudflare-ddns logs to verify the continer is running without error (ipv6 warnings are normal). podman logs cloudflare-ddns ``` - diff --git a/cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh b/cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh index f2ff1ca..04f2073 100644 --- a/cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh +++ b/cloudflare-ddns/on_boot.d/30-cloudflare-ddns.sh @@ -2,7 +2,7 @@ CONTAINER=cloudflare-ddns # Starts a cloudflare ddns container that is deleted after it is stopped. -# All configs stored in /mnt/data/cloudflare-ddns +# All configs stored in /data/cloudflare-ddns if podman container exists "$CONTAINER"; then podman start "$CONTAINER" else @@ -10,6 +10,6 @@ else --net=host \ --name "$CONTAINER" \ --security-opt=no-new-privileges \ - -v /mnt/data/cloudflare-ddns/config.json:/config.json \ + -v /data/cloudflare-ddns/config.json:/config.json \ timothyjmiller/cloudflare-ddns:latest fi diff --git a/cni-plugins/05-install-cni-plugins.sh b/cni-plugins/05-install-cni-plugins.sh index 176cc47..cec79ee 100644 --- a/cni-plugins/05-install-cni-plugins.sh +++ b/cni-plugins/05-install-cni-plugins.sh @@ -1,7 +1,7 @@ #!/bin/sh # Get DataDir location -DATA_DIR="/mnt/data" +DATA_DIR="/data" case "$(ubnt-device-info firmware || true)" in 1*) DATA_DIR="/mnt/data" @@ -22,9 +22,9 @@ case "$(ubnt-device-info firmware || true)" in # Examples of valid version code would be "latest", "v0.9.1" and "v0.9.0". CNI_PLUGIN_VER=latest # location of the CNI Plugin cached tar files -CNI_CACHE="$DATA_DIR/.cache/cni-plugins" +CNI_CACHE="${DATA_DIR}/.cache/cni-plugins" # location of the conf files to go in the net.d folder of the cni-plugin directory -CNI_NETD="$DATA_DIR/podman/cni" +CNI_NETD="${DATA_DIR}/podman/cni" # The checksum to use. For CNI Plugin sha1, sha256 and sha512 are available. CNI_CHECKSUM="sha256" # Maximum number of loops to attempt to download the plugin if required - setting a 0 or negative value will reinstalled the currently installed version (if in cache) diff --git a/container-common/README.md b/container-common/README.md index ffcf64c..5df4fe5 100644 --- a/container-common/README.md +++ b/container-common/README.md @@ -10,26 +10,31 @@ ## Customization -While a 100Mb log limit per container should give plenty of log data for all featured in this repo projects, you can increase or decrease max_log_size value in /mnt/data/on_boot.d/05-container-common.sh file after installation. +While a 100Mb log limit per container should give plenty of log data for all featured in this repo projects, you can increase or decrease max_log_size value in /data/on_boot.d/05-container-common.sh file after installation. ## Steps 1. Run as root on UDM Pro to download and set permissions of on_boot.d script: + ```sh # Download 05-container-common.sh from GitHub -curl -L https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/container-common/on_boot.d/05-container-common.sh -o /mnt/data/on_boot.d/05-container-common.sh; +curl -L https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/container-common/on_boot.d/05-container-common.sh -o /data/on_boot.d/05-container-common.sh; # Set execute permission -chmod a+x /mnt/data/on_boot.d/05-container-common.sh; +chmod a+x /data/on_boot.d/05-container-common.sh; ``` -2. Review the script /mnt/data/on_boot.d/05-container-common.sh and when happy execute it. + +2. Review the script /data/on_boot.d/05-container-common.sh and when happy execute it. + ```sh # Review script -cat /mnt/data/on_boot.d/05-container-common.sh; +cat /data/on_boot.d/05-container-common.sh; # Apply container-common settings -/mnt/data/on_boot.d/05-container-common.sh; +/data/on_boot.d/05-container-common.sh; ``` + 3. Already running containers will pick up new defaults after either container restart ("podman restart \") or after UDM Pro restart. New containers will pick up a change from first run. 4. To list containers that are running with log size limits: + ```sh # List container monitor processes with "--log-size-max" custom argument set ps -ef | grep conmon | grep log-size-max diff --git a/dns-common/on_boot.d/10-dns.sh b/dns-common/on_boot.d/10-dns.sh index df5cb19..87b7fde 100644 --- a/dns-common/on_boot.d/10-dns.sh +++ b/dns-common/on_boot.d/10-dns.sh @@ -1,5 +1,21 @@ #!/bin/sh - +# Get DataDir location +DATA_DIR="/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 ## configuration variables: VLAN=5 IPV4_IP="10.0.5.3" @@ -32,9 +48,9 @@ FORCED_INTFC="" CONTAINER=pihole if ! test -f /opt/cni/bin/macvlan; then - echo "Error: CNI plugins not found. You can install it with the following command:" >&2 - echo " curl -fsSLo /mnt/data/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh /mnt/data/on_boot.d/05-install-cni-plugins.sh" >&2 - exit 1 + echo "Error: CNI plugins not found. You can install it with the following command:" >&2 + echo " curl -fsSLo ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh" >&2 + exit 1 fi # set VLAN bridge promiscuous @@ -63,8 +79,8 @@ fi # Make DNSMasq listen to the container network for split horizon or conditional forwarding if ! grep -qxF "interface=br${VLAN}.mac" /run/dnsmasq.conf.d/custom.conf; then - echo "interface=br${VLAN}.mac" >> /run/dnsmasq.conf.d/custom.conf - kill -9 "$(cat /run/dnsmasq.pid)" + echo "interface=br${VLAN}.mac" >>/run/dnsmasq.conf.d/custom.conf + kill -9 "$(cat /run/dnsmasq.pid)" fi if podman container exists "${CONTAINER}"; then diff --git a/haproxy/50-haproxy.sh b/haproxy/50-haproxy.sh index a2c6e6e..85c1dce 100644 --- a/haproxy/50-haproxy.sh +++ b/haproxy/50-haproxy.sh @@ -1,14 +1,41 @@ #!/bin/sh CONTAINER=haproxy +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/haproxy" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/haproxy" + echo "Directory '${DATA_DIR}/haproxy' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/haproxy' already exists. Moving on." +fi # Starts an haproxy container that is deleted after it is stopped. -# All configs stored in /mnt/data/haproxy +# All configs stored in /data/haproxy if podman container exists "$CONTAINER"; then podman start "$CONTAINER" else podman run -d --net=host --restart always \ --name haproxy \ --hostname ha.proxy \ - -v "/mnt/data/haproxy/:/usr/local/etc/haproxy/" \ + -v "${DATA_DIR}/haproxy/:/usr/local/etc/haproxy/" \ haproxy:latest fi diff --git a/haproxy/README.md b/haproxy/README.md index f52c175..740d644 100644 --- a/haproxy/README.md +++ b/haproxy/README.md @@ -12,30 +12,29 @@ ## Steps -1. Pull your image with `podman pull docker.io/library/haproxy`. +1. Check if you either have `/mnt/data` or `/data/` and adjust below accordingly +2. Pull your image with `podman pull docker.io/library/haproxy`. +3. Copy [50-haproxy.sh](./50-haproxy.sh) to `/data/on_boot.d/50-haproxy.sh`. +4. Choose network configuration - You can run either on the host network or on a seperate docker network. Running on the host network is easier but does mean you can't clash with the ports already in use on the UDM. + 1. If you want to run on the host network + 1. You don't have to do anything extra to run on the host network all the instructions / scripts assume this setup. + 2. If you want to run on a custom docker network do the following: + 1. Setup the network - there are some instructions in the Customizations setting of the pihole instructions: https://github.com/unifi-utilities/unifios-utilities/tree/main/run-pihole#customizations + 2. Copy [21-haproxy.conflist](./21-haproxy.conflist) to `/data/podman/cni/` and update its values to reflect your environment. + 3. Execute the `/data/on_boot.d/05-install-cni-plugins.sh` script to create the network. + 4. Edit `/data/on_boot.d/50-haproxy.sh` and change `--net=host` to `--network haproxy` +5. Create a persistant directory and config for haproxy to use: -1. Copy [50-haproxy.sh](./50-haproxy.sh) to `/mnt/data/on_boot.d/50-haproxy.sh`. + ```sh + mkdir -p /data/haproxy + touch /data/haproxy/haproxy.cfg + ``` -1. Choose network configuration - You can run either on the host network or on a seperate docker network. Running on the host network is easier but does mean you can't clash with the ports already in use on the UDM. - 1. If you want to run on the host network - 1. You don't have to do anything extra to run on the host network all the instructions / scripts assume this setup. - 1. If you want to run on a custom docker network do the following: - 1. Setup the network - there are some instructions in the Customizations setting of the pihole instructions: https://github.com/unifi-utilities/unifios-utilities/tree/main/run-pihole#customizations - 1. Copy [21-haproxy.conflist](./21-haproxy.conflist) to `/mnt/data/podman/cni/` and update its values to reflect your environment. - 1. Execute the `/mnt/data/on_boot.d/05-install-cni-plugins.sh` script to create the network. - 1. Edit `/mnt/data/on_boot.d/50-haproxy.sh` and change `--net=host` to `--network haproxy` -1. Create a persistant directory and config for haproxy to use: - - ```sh - mkdir -p /mnt/data/haproxy - touch /mnt/data/haproxy/haproxy.cfg - ``` - -1. Add your config to `/mnt/data/haproxy/haproxy.cfg`. Each configuration is unique, so check out some resouces like [haproxy.com](https://www.haproxy.com/documentation/hapee/latest/configuration/config-sections/) for basics. -1. Run `/mnt/data/on_boot.d/50-haproxy.sh` +6. Add your config to `/data/haproxy/haproxy.cfg`. Each configuration is unique, so check out some resouces like [haproxy.com](https://www.haproxy.com/documentation/hapee/latest/configuration/config-sections/) for basics. +7. Run `/data/on_boot.d/50-haproxy.sh` ## Upgrading Easily (if at all) 1. Edit [update-haproxy.sh](./update-haproxy.sh) to use the same command you used at installation (if changed). If you added your own network config ensure you change the `--net=host` to `--network haproxy` -2. Copy the [update-haproxy.sh](./update-haproxy.sh) to `/mnt/data/scripts` -3. Anytime you want to update your installation, simply run `/mnt/data/scripts/update-haproxy.sh` +2. Copy the [update-haproxy.sh](./update-haproxy.sh) to `/data/scripts` +3. Anytime you want to update your installation, simply run `/data/scripts/update-haproxy.sh` diff --git a/haproxy/update-haproxy.sh b/haproxy/update-haproxy.sh index 727351b..65b3e3e 100644 --- a/haproxy/update-haproxy.sh +++ b/haproxy/update-haproxy.sh @@ -1,4 +1,21 @@ IMAGE=haproxy:latest +# Get DataDir location +DATA_DIR="/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 podman pull $IMAGE podman stop haproxy @@ -6,5 +23,5 @@ podman rm haproxy podman run -d --net=host --restart always \ --name haproxy \ --hostname ha.proxy \ - -v "/mnt/data/haproxy/:/usr/local/etc/haproxy/" \ + -v "${DATA_DIR}/haproxy/:/usr/local/etc/haproxy/" \ $IMAGE diff --git a/hdhomerun/on_boot.d/99-hdhomerun.sh b/hdhomerun/on_boot.d/99-hdhomerun.sh index 8abe3ab..ca93d1f 100644 --- a/hdhomerun/on_boot.d/99-hdhomerun.sh +++ b/hdhomerun/on_boot.d/99-hdhomerun.sh @@ -1,5 +1,32 @@ #!/bin/sh -# Place cross compiled version of `socat` in /mnt/data/hdhomerun +# Place cross compiled version of `socat` in /data/hdhomerun HDHOMERUN_IP=10.10.30.146 -/mnt/data/hdhomerun/socat -d -d -v udp4-recvfrom:65001,broadcast,fork udp4-sendto:$HDHOMERUN_IP:65001 & +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "$DATA_DIR" ]; then + # If it does not exist, create the directory + mkdir -p "$DATA_DIR" + echo "Directory '$DATA_DIR' created." +else + # If it already exists, print a message + echo "Directory '$DATA_DIR' already exists. Moving on." +fi + +${DATA_DIR}/hdhomerun/socat -d -d -v udp4-recvfrom:65001,broadcast,fork udp4-sendto:$HDHOMERUN_IP:65001 & diff --git a/homebridge/README.md b/homebridge/README.md index d15e118..bfdc470 100644 --- a/homebridge/README.md +++ b/homebridge/README.md @@ -1,37 +1,39 @@ # Run Homebridge on your UDM ### Features + 1. Run [Homebridge](https://homebridge.io/) on your UDM(P). 2. Integrate Unifi Protect cameras in HomeKit via `homebridge-unifi-protect`. 3. Persists through reboots and firmware updates. ### Requirements + 1. You have successfully setup the on boot script described [here](https://github.com/unifi-utilities/unifios-utilities/tree/main/on-boot-script). 2. You have applied [container-common](https://github.com/unifi-utilities/unifios-utilities/tree/main/container-common) change to prevent UDM storage to fill up with Homebridge logs and addon error messages that can move fast. 3. You have applied [cni-plugins](https://github.com/unifi-utilities/unifios-utilities/tree/main/cni-plugins "cni-plugins") to setup for cni configeration. (You dont need the configeration files, just place the script in the on boot folder.) ### Steps -1. Type this command: `mkdir -p /mnt/data/homebridge/run` -2. Copy [25-homebridge.sh](on_boot.d/25-homebridge.sh) to `/mnt/data/on_boot.d`. To do this, cd into `/mnt/data/on_boot.d`, then type `vim 25-homebridge.sh` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/on_boot.d/25-homebridge.sh "this page") and copy everything using CTRL + A and then CTRL + C and then paste it into vim then click ESC and then type `:x` then click the enter key. -3. Copy [90-homebridge.conflist](cni/90-homebridge.conflist) to `/mnt/data/podman/cni`. This will create the podman network that bridges the container to your VLAN. To do this, cd into `/mnt/data/podman/cni` and type `vim 90-homebridge.conflist` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/cni/90-homebridge.conflist "this page") and the press CTRL + A and then CTRL + C and then paste it into vim and click ESC and then type `:x` then click the enter key. +1. Type this command: `mkdir -p /data/homebridge/run` +2. Copy [25-homebridge.sh](on_boot.d/25-homebridge.sh) to `/data/on_boot.d`. To do this, cd into `/data/on_boot.d`, then type `vim 25-homebridge.sh` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/on_boot.d/25-homebridge.sh "this page") and copy everything using CTRL + A and then CTRL + C and then paste it into vim then click ESC and then type `:x` then click the enter key. +3. Copy [90-homebridge.conflist](cni/90-homebridge.conflist) to `/data/podman/cni`. This will create the podman network that bridges the container to your VLAN. To do this, cd into `/data/podman/cni` and type `vim 90-homebridge.conflist` then go to [this page](https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/homebridge/cni/90-homebridge.conflist "this page") and the press CTRL + A and then CTRL + C and then paste it into vim and click ESC and then type `:x` then click the enter key. 4. Run the Homebridge docker container. Change the timezone (`-e TZ`) to match your timezone, and DNS (`--dns`) to match your VLAN gateway. - ```shell script - podman run -d --restart always \ - --privileged \ - --name homebridge \ - --net homebridge \ - --dns 192.168.1.1 \ - --dns-search lan \ - -e TZ=America/Chicago \ - -e PGID=0 -e PUID=0 \ - -e HOMEBRIDGE_CONFIG_UI=1 \ - -e HOMEBRIDGE_CONFIG_UI_PORT=80 \ - -v "/mnt/data/homebridge/:/homebridge/" \ - -v "/mnt/data/homebridge/run/:/run/" \ - oznu/homebridge:latest - ``` + ```shell script + podman run -d --restart always \ + --privileged \ + --name homebridge \ + --net homebridge \ + --dns 192.168.1.1 \ + --dns-search lan \ + -e TZ=America/Chicago \ + -e PGID=0 -e PUID=0 \ + -e HOMEBRIDGE_CONFIG_UI=1 \ + -e HOMEBRIDGE_CONFIG_UI_PORT=80 \ + -v "/data/homebridge/:/homebridge/" \ + -v "/data/homebridge/run/:/run/" \ + oznu/homebridge:latest + ``` 5. Access the Homebridge UI based on the IP you assigned, like [http://192.168.1.20/](http://192.168.1.20/). 6. If using the UDM Pro, the `homebridge-unifi-protect` plugin can be installed via the Homebridge UI to integrate Unifi Protect cameras. diff --git a/homebridge/on_boot.d/25-homebridge.sh b/homebridge/on_boot.d/25-homebridge.sh index ef788ee..950f10d 100755 --- a/homebridge/on_boot.d/25-homebridge.sh +++ b/homebridge/on_boot.d/25-homebridge.sh @@ -1,31 +1,56 @@ #!/bin/sh CONTAINER=homebridge +# Get DataDir location +DATA_DIR="/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 + ## network configuration and startup: -CNI_PATH=/mnt/data/podman/cni +CNI_PATH=${DATA_DIR}/podman/cni +# Check if the directory exists +if [ ! -d "$CNI_PATH" ]; then + # If it does not exist, create the directory + mkdir -p "$CNI_PATH" + echo "Directory '$CNI_PATH' created." +else + # If it already exists, print a message + echo "Directory '$CNI_PATH' already exists. Moving on." +fi + if [ ! -f "$CNI_PATH"/tuning ]; then - mkdir -p $CNI_PATH - curl -L https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-arm64-v0.9.1.tgz | tar -xz -C $CNI_PATH + mkdir -p $CNI_PATH + curl -L https://github.com/containernetworking/plugins/releases/download/v0.9.1/cni-plugins-linux-arm64-v0.9.1.tgz | tar -xz -C $CNI_PATH fi mkdir -p /opt/cni rm -f /opt/cni/bin ln -s $CNI_PATH /opt/cni/bin -for file in "$CNI_PATH"/*.conflist -do - if [ -f "$file" ]; then - ln -s "$file" "/etc/cni/net.d/$(basename "$file")" - fi +for file in "$CNI_PATH"/*.conflist; do + if [ -f "$file" ]; then + ln -s "$file" "/etc/cni/net.d/$(basename "$file")" + fi done - # Starts the homebridge container on boot. -# All configs stored in /mnt/data/homebridge +# All configs stored in /data/homebridge if podman container exists ${CONTAINER}; then podman start ${CONTAINER} else logger -s -t homebridge -p ERROR Container $CONTAINER not found, make sure you set the proper name, you can ignore this error if it is your first time setting it up fi - diff --git a/ipt-enable-logs/README.md b/ipt-enable-logs/README.md index 32a465e..893e276 100644 --- a/ipt-enable-logs/README.md +++ b/ipt-enable-logs/README.md @@ -25,16 +25,16 @@ Here's an example snippet of an iptable modified by this program: ## Steps -1. Copy [on_boot.d/30-ipt-enable-logs-launch.sh](./on_boot.d/30-ipt-enable-logs-launch.sh) to /mnt/data/on_boot.d -1. Copy the [scripts/ipt-enable-logs](./scripts/ipt-enable-logs) folder to /mnt/data/scripts -1. Copy [scripts/ipt-enable-logs.sh](./scripts/ipt-enable-logs.sh) to /mnt/data/scripts -1. Execute /mnt/data/on_boot.d/30-ipt-enable-logs-launch.sh -1. Copy [scripts/refresh-iptables.sh](./scripts/refresh-iptables.sh) to /mnt/data/scripts +1. Copy [on_boot.d/30-ipt-enable-logs-launch.sh](./on_boot.d/30-ipt-enable-logs-launch.sh) to /data/on_boot.d +1. Copy the [scripts/ipt-enable-logs](./scripts/ipt-enable-logs) folder to /data/scripts +1. Copy [scripts/ipt-enable-logs.sh](./scripts/ipt-enable-logs.sh) to /data/scripts +1. Execute /data/on_boot.d/30-ipt-enable-logs-launch.sh +1. Copy [scripts/refresh-iptables.sh](./scripts/refresh-iptables.sh) to /data/scripts ## Refreshing iptables Whenever you update the firewall rules on the Network application, the iptables will be reprovisioned and will need to be reprocessed -by calling /mnt/data/scripts/refresh-iptables.sh. +by calling /data/scripts/refresh-iptables.sh. ## Looking at logs diff --git a/ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh b/ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh index 2ac67ae..284d330 100755 --- a/ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh +++ b/ipt-enable-logs/on_boot.d/30-ipt-enable-logs-launch.sh @@ -1,9 +1,37 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/scripts" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/scripts" + echo "Directory '${DATA_DIR}/scripts' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/scripts' already exists. Moving on." +fi + set -e -if ! iptables-save | grep -e '\-A UBIOS_.* \--log-prefix "\[' > /dev/null; then - /mnt/data/scripts/ipt-enable-logs.sh | iptables-restore -c +if ! iptables-save | grep -e '\-A UBIOS_.* \--log-prefix "\[' >/dev/null; then + ${DATA_DIR}/scripts/ipt-enable-logs.sh | iptables-restore -c else echo "iptables already contains USER log prefixes, ignoring." fi diff --git a/ipt-enable-logs/scripts/ipt-enable-logs.sh b/ipt-enable-logs/scripts/ipt-enable-logs.sh index 3ed4be9..7d248ea 100755 --- a/ipt-enable-logs/scripts/ipt-enable-logs.sh +++ b/ipt-enable-logs/scripts/ipt-enable-logs.sh @@ -1,7 +1,34 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/scripts" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/scripts" + echo "Directory '${DATA_DIR}/scripts' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/scripts' already exists. Moving on." +fi set -e -docker run -it --rm -v /mnt/data/scripts/ipt-enable-logs:/src -w /src --network=none golang:1.17.3 go build -v -o /src/ipt-enable-logs /src >&2 +docker run -it --rm -v ${DATA_DIR}/scripts/ipt-enable-logs:/src -w /src --network=none golang:1.17.3 go build -v -o /src/ipt-enable-logs /src >&2 -/mnt/data/scripts/ipt-enable-logs/ipt-enable-logs +${DATA_DIR}/scripts/ipt-enable-logs/ipt-enable-logs diff --git a/ipt-enable-logs/scripts/refresh-iptables.sh b/ipt-enable-logs/scripts/refresh-iptables.sh index 4983d40..d3195a0 100755 --- a/ipt-enable-logs/scripts/refresh-iptables.sh +++ b/ipt-enable-logs/scripts/refresh-iptables.sh @@ -1,13 +1,39 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "${DATA_DIR}/on_boot.d" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/on_boot.d" + echo "Directory '${DATA_DIR}/on_boot.d' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/on_boot.d' already exists. Moving on." +fi set -e -if [ -f /mnt/data/on_boot.d/10-dns.sh ]; then - if ! iptables-save | grep -e '\-A PREROUTING.* \--log-prefix "\[' > /dev/null; then - /mnt/data/on_boot.d/10-dns.sh +if [ -f ${DATA_DIR}/on_boot.d/10-dns.sh ]; then + if ! iptables-save | grep -e '\-A PREROUTING.* \--log-prefix "\[' >/dev/null; then + ${DATA_DIR}/on_boot.d/10-dns.sh else echo "iptables already contains DNAT log prefixes, ignoring." fi fi -/mnt/data/on_boot.d/30-ipt-enable-logs-launch.sh +${DATA_DIR}/on_boot.d/30-ipt-enable-logs-launch.sh diff --git a/mosquitto/README.md b/mosquitto/README.md index aa3d023..223cf07 100644 --- a/mosquitto/README.md +++ b/mosquitto/README.md @@ -23,44 +23,44 @@ _Adjust according to your setup._ 1. First, lets create the folder structure we'll be working with. - `$ mkdir -p /mnt/data/mosquitto/config /mnt/data/mosquitto/data` + `$ mkdir -p /data/mosquitto/config /data/mosquitto/data` - This is where Mosquitto's configuration file and data ("persistence database"; if enabled) will live. - If you're unsure on how to configure mosquitto, use the provided barebone config [`config/mosquitto.conf`](config/mosquitto.conf) to get it initially running. + This is where Mosquitto's configuration file and data ("persistence database"; if enabled) will live. + If you're unsure on how to configure mosquitto, use the provided barebone config [`config/mosquitto.conf`](config/mosquitto.conf) to get it initially running. -2. **Optional:** Customize [`on_boot.d/45-mosquitto.sh`](on_boot.d/45-mosquitto.sh) to your setup and copy to `/mnt/data/on_boot.d/`. - Most likely you'll need to mark the script as executable, this will do the trick: +2. **Optional:** Customize [`on_boot.d/45-mosquitto.sh`](on_boot.d/45-mosquitto.sh) to your setup and copy to `/data/on_boot.d/`. + Most likely you'll need to mark the script as executable, this will do the trick: - `$ chmod a+x /mnt/data/on_boot.d/45-mosquitto.sh` + `$ chmod a+x /data/on_boot.d/45-mosquitto.sh` -3. Then take a loot at [`cni/45-mosquitto.conflist`](cni/45-mosquitto.conflist) and make sure it matches your previously defined configuration; then place it in `/mnt/data/podman/cni/` +3. Then take a loot at [`cni/45-mosquitto.conflist`](cni/45-mosquitto.conflist) and make sure it matches your previously defined configuration; then place it in `/data/podman/cni/` 4. Run boot script (to create the mosquitto network set it's ip routes) - `$ sh /mnt/data/on_boot.d/45-mosquitto.sh` + `$ sh /data/on_boot.d/45-mosquitto.sh` - It fail when trying to run the container, but thats okay, its just for setting op needed configuration before initial image run. - The script will also create a [minimal configuration](config/mosquitto.conf) for Mosquitto in `/mnt/data/mosquitto/config/`, _**only if it doesn't already exist**_. + It fail when trying to run the container, but thats okay, its just for setting op needed configuration before initial image run. + The script will also create a [minimal configuration](config/mosquitto.conf) for Mosquitto in `/data/mosquitto/config/`, _**only if it doesn't already exist**_. - > **Note:** You can use this config to get everything started, but I highly recommend securing your instance with authentication (links to the offical documentation & other resources are at the bottom) + > **Note:** You can use this config to get everything started, but I highly recommend securing your instance with authentication (links to the offical documentation & other resources are at the bottom) 5. Register the container with podman: - ```shell - $ podman run -d --network mosquitto \ - --restart always \ - --security-opt=no-new-privileges \ - --name mosquitto \ - --hostname mosquitto.local \ - -e "TZ=Europe/Berlin" \ - -v /mnt/data/mosquitto/config/:/mosquitto/config \ - -v /mnt/data/mosquitto/data/:/mosquitto/data \ - eclipse-mosquitto:latest - ``` + ```shell + $ podman run -d --network mosquitto \ + --restart always \ + --security-opt=no-new-privileges \ + --name mosquitto \ + --hostname mosquitto.local \ + -e "TZ=Europe/Berlin" \ + -v /data/mosquitto/config/:/mosquitto/config \ + -v /data/mosquitto/data/:/mosquitto/data \ + eclipse-mosquitto:latest + ``` 6. Run boot script again and we are done! - `$ sh /mnt/data/on_boot.d/45-mosquitto.sh` + `$ sh /data/on_boot.d/45-mosquitto.sh` > You should now be able to connect with any MQTT client to Mosquitto, in my case `mqtt://10.0.20.4:1883` diff --git a/mosquitto/on_boot.d/45-mosquitto.sh b/mosquitto/on_boot.d/45-mosquitto.sh index e8c817d..fc70c11 100755 --- a/mosquitto/on_boot.d/45-mosquitto.sh +++ b/mosquitto/on_boot.d/45-mosquitto.sh @@ -1,17 +1,43 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "${DATA_DIR}/podman/cni" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/podman/cni" + echo "Directory '${DATA_DIR}/podman/cni' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/podman/cni' already exists. Moving on." +fi ## network configuration VLAN_ID=20 IPV4_IP_CONTAINER="10.0.20.4" IPV4_IP_GATEWAY="10.0.20.1" CONTAINER_NAME="mosquitto" -CONTAINER_CNI_PATH="/mnt/data/podman/cni/45-mosquitto.conflist" +CONTAINER_CNI_PATH="${DATA_DIR}/podman/cni/45-mosquitto.conflist" # make sure cni plugs are installed if ! test -f /opt/cni/bin/macvlan; then - echo "Error: CNI plugins not found. You can install it with the following command:" >&2 - echo " curl -fsSLo /mnt/data/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh /mnt/data/on_boot.d/05-install-cni-plugins.sh" >&2 - exit 1 + echo "Error: CNI plugins not found. You can install it with the following command:" >&2 + echo " curl -fsSLo ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh" >&2 + exit 1 fi ## network configuration and startup @@ -38,9 +64,9 @@ ip link set br${VLAN_ID}.mac up ip route add ${IPV4_IP_CONTAINER}/32 dev br${VLAN_ID}.mac # create basic config if not exist -if ! test -f /mnt/data/mosquitto/config/mosquitto.conf; then - mkdir -p /mnt/data/mosquitto/data /mnt/data/mosquitto/config - cat > /mnt/data/mosquitto/config/mosquitto.conf<< EOF +if ! test -f "$DATA_DIR"/mosquitto/config/mosquitto.conf; then + mkdir -p "$DATA_DIR"/mosquitto"$DATA_DIR" "$DATA_DIR"/mosquitto/config + cat >"$DATA_DIR"/mosquitto/config/mosquitto.conf <&2 + exit 1 + ;; +esac ## Configure shell profile device_info() { @@ -7,7 +23,7 @@ device_info() { } # Modify login banner (motd) -cat > /etc/motd </etc/motd < /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) }')" +cat >/etc/profile.d/prompt.sh <<'EOF' +UDM_NAME="$(grep -m 1 '^name:' ${DATA_DIR}/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/ +# Copy all global profile scripts (for all users) from `${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/` directory +mkdir -p ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d +cp -rf ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/* /etc/profile.d/ diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh index 0df36d2..9ac4857 100755 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-.profile.sh @@ -1,3 +1,19 @@ #!/bin/sh - -cp -f /mnt/data/on_boot.d/files/.profile /root/ +# Get DataDir location +DATA_DIR="/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 +cp -f ${DATA_DIR}/on_boot.d/files/.profile /root/ diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh index 1eb301e..8a469fd 100644 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh @@ -1,16 +1,34 @@ #!/bin/sh + +# Get DataDir location +DATA_DIR="/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 ## 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="" # File location for the output of the git download -GITHUB_KEY_PATH="/mnt/data/podman/ssh" +GITHUB_KEY_PATH="${DATA_DIR}/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_PATH="${DATA_DIR}/podman/ssh" INPUT_KEY_FILE="${INPUT_KEY_PATH}/ssh.keys" # The target key file for the script OUTPUT_KEY_PATH="/root/.ssh" @@ -18,7 +36,7 @@ OUTPUT_KEY_FILE="${OUTPUT_KEY_PATH}/authorized_keys" ## Functions # This function downloads the keys from the selected github user -download_from_github(){ +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" @@ -27,26 +45,25 @@ download_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} +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(){ +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 + counter=0 + while IFS= read -r line; do write_to_output "${line}" let "counter++" - done < $1 + done <$1 echo "${counter} number of entries read from " } diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh index 77c32d8..70e7646 100644 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh @@ -1,8 +1,24 @@ #!/bin/sh - +# Get DataDir location +DATA_DIR="/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 ## Places public keys in ~/.ssh/authorized_keys -KEYS_SOURCE_FILE="/mnt/data/on_boot.d/settings/ssh/authorized_keys" +KEYS_SOURCE_FILE="${DATA_DIR}/on_boot.d/settings/ssh/authorized_keys" KEYS_TARGET_FILE="/root/.ssh/authorized_keys" count_added=0 @@ -11,19 +27,19 @@ 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" + echo "$key" >>"$KEYS_TARGET_FILE" else - let count_skipped++ + let count_skipped++ fi -done < "$KEYS_SOURCE_FILE" +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" + 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 +dropbearconvert openssh dropbear ${DATA_DIR}/ssh/id_rsa /root/.ssh/id_dropbear exit 0 diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-ssh-known-hosts.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-ssh-known-hosts.sh index 17fe07b..0a4c2bc 100644 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-ssh-known-hosts.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-add-ssh-known-hosts.sh @@ -1,5 +1,21 @@ #!/bin/sh - +# Get DataDir location +DATA_DIR="/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 ##################################################### # ADD KNOWN HOSTS AS BELOW - CHANGE BEFORE RUNNING # ##################################################### @@ -8,22 +24,19 @@ # "one per line, last line has no backslash" # ##################################################### set -- "hostname ecdsa-sha2-nistp256 AAAABIGHOSTIDENTIFIERWITHMAGICSTUFF=" \ - "otherhost ecdsa-sha2-nistp256 AAAADIFFERENTHOSTMAGICSTUFF!@HJKSL=" + "otherhost ecdsa-sha2-nistp256 AAAADIFFERENTHOSTMAGICSTUFF!@HJKSL=" KNOWN_HOSTS_FILE="/root/.ssh/known_hosts" - counter=0 -for host in "$@" -do +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" + echo "$host" >>"$KNOWN_HOSTS_FILE" fi done echo $counter hosts added to $KNOWN_HOSTS_FILE - -exit 0; +exit 0 diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh index 40993de..2a7f82b 100755 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/15-preserve-history.sh @@ -1,13 +1,29 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +mkdir -p ${DATA_DIR}/.home -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 - +for file in .ash_history .bash_history; do + if [ ! -f ${DATA_DIR}/.home/$file ]; then + touch /root/$file + cp /root/$file ${DATA_DIR}/.home/$file + chown root:root ${DATA_DIR}/.home/$file + chmod 0600 ${DATA_DIR}/.home/$file + fi + ln -sf ${DATA_DIR}/.home/$file /root/$file +done diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/25-add-cron-jobs.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/25-add-cron-jobs.sh index f6ae6f1..6326a2d 100644 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/25-add-cron-jobs.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/25-add-cron-jobs.sh @@ -1,9 +1,25 @@ #!/bin/sh - -## Store crontab files in /mnt/data/cronjobs/ (you will need to create this folder). +# Get DataDir location +DATA_DIR="/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 +## Store crontab files in ${DATA_DIR}/cronjobs/ (you will need to create this folder). ## This script will re-add them on startup. -cp /mnt/data/cronjobs/* /etc/cron.d/ +cp ${DATA_DIR}/cronjobs/* /etc/cron.d/ /etc/init.d/crond restart exit 0 diff --git a/on-boot-script-2.x/examples/udm-files/on_boot.d/iptables_timerestrict.sh b/on-boot-script-2.x/examples/udm-files/on_boot.d/iptables_timerestrict.sh index 8cff433..af498a6 100644 --- a/on-boot-script-2.x/examples/udm-files/on_boot.d/iptables_timerestrict.sh +++ b/on-boot-script-2.x/examples/udm-files/on_boot.d/iptables_timerestrict.sh @@ -1,87 +1,100 @@ -#!/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: -/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 +#!/bin/sh +# Get DataDir location +DATA_DIR="/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 +## ---------------------------------------------------------------------- +## 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 ${DATA_DIR}/on_boot.d/, using something like WinSCP or SSH + vi. +## * Grant Execute permission: chmod +x ${DATA_DIR}/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: ${DATA_DIR}/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: +/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 diff --git a/on-boot-script-2.x/remote_install.sh b/on-boot-script-2.x/remote_install.sh index 0a15ca4..c08f8e4 100755 --- a/on-boot-script-2.x/remote_install.sh +++ b/on-boot-script-2.x/remote_install.sh @@ -1,22 +1,22 @@ #!/usr/bin/env sh # Get DataDir location -DATA_DIR="/mnt/data" +DATA_DIR="/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 +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" @@ -25,17 +25,16 @@ 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_SCRIPT_RAW_URL="https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/on-boot-script-2.x/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 + cat < "$SYSTEMCTL_PATH" || return 1 + udmse_on_boot_systemd >"$SYSTEMCTL_PATH" || return 1 sleep 1s echo "Enabling UDM boot..." @@ -165,43 +164,42 @@ header depends_on ubnt-device-info depends_on curl -ON_BOOT_D_PATH="$DATA_DIR/on_boot.d" +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 +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 + 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 @@ -220,7 +218,6 @@ 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 diff --git a/on-boot-script/README.md b/on-boot-script/README.md index bc7e9db..caaaeaa 100644 --- a/on-boot-script/README.md +++ b/on-boot-script/README.md @@ -3,7 +3,7 @@ ## Features 1. Allows you to run a shell script at S95 anytime your UDM starts / reboots -1. Persists through reboot and **firmware updates**! It is able to do this because Ubiquiti caches all debian package installs on the UDM in /mnt/data, then re-installs them on reset of unifi-os container. +1. Persists through reboot and **firmware updates**! It is able to do this because Ubiquiti caches all debian package installs on the UDM in /data, then re-installs them on reset of unifi-os container. ## Compatibility @@ -12,21 +12,22 @@ ### Upgrade from earlier way -* As long as you didn't change the filenames, installing the deb package is all you need to do. If you want to clean up beforehand anyways.... +- As long as you didn't change the filenames, installing the deb package is all you need to do. If you want to clean up beforehand anyways.... - ```bash - rm /etc/init.d/udm.sh - systemctl disable udmboot - rm /etc/systemd/system/udmboot.service - ``` + ```bash + rm /etc/init.d/udm.sh + systemctl disable udmboot + rm /etc/systemd/system/udmboot.service + ``` -* [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/) +- [build_deb.sh](build_deb.sh) can be used to build the package by yourself. -* Built on Ubuntu-20.04 on Windows 10/WSL2 + - [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 @@ -44,60 +45,61 @@ This will also install CNI Plugins & CNI Bridge scripts. If you are using UDMSE/ 1. Get into the unifios shell on your udm - ```bash - unifi-os shell - ``` + ```bash + unifi-os shell + ``` -2. Download [udm-boot_1.0.7_all.deb](packages/udm-boot_1.0.7_all.deb) and install it and go back to the UDM. The latest package will always be found at https://udm-boot.boostchicken.dev +2. Download [udm-boot_1.0.7_all.deb](packages/udm-boot_1.0.7_all.deb) and install it and go back to the UDM. The latest package will always be found at https://udm-boot.boostchicken.dev - ```bash - curl -L https://unifi.boostchicken.io/udm-boot_1.0.7_all.deb -o udm-boot_1.0.7_all.deb - dpkg -i udm-boot_1.0.7_all.deb - systemctl enable udm-boot - exit - ``` + ```bash + curl -L https://unifi.boostchicken.io/udm-boot_1.0.7_all.deb -o udm-boot_1.0.7_all.deb + dpkg -i udm-boot_1.0.7_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. +3. Copy any shell scripts you want to run to /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) + 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.7 -* Support for Legacy and Current Firmware +- Support for Legacy and Current Firmware ### 1.0.6 -* Fix timeouts +- Fix timeouts ### 1.0.5 -* Remove on_boot.sh from UDM -* Follow symlinks -* move to network-online.target +- Remove on_boot.sh from UDM +- Follow symlinks +- move to network-online.target ### 1.0.4 -* Fix 600s timeout issues -* Fix rc.d policy issue +- Fix 600s timeout issues +- Fix rc.d policy issue ### 1.0.3 -* Fix not working after firmware upgrade -* Added udm-boot.boostchicken.dev domain +- Fix not working after firmware upgrade +- Added udm-boot.boostchicken.dev domain ### 1.0.2 -* Some build improvements and more clean installation +- Some build improvements and more clean installation ### 1.0.1 -* Fully automated install, all that is left is populating /mnt/data/on_boot.d +- Fully automated install, all that is left is populating /data/on_boot.d ### 1.0.0 -* First release that persists through firmware +- First release that persists through firmware diff --git a/on-boot-script/README.old.md b/on-boot-script/README.old.md index 56f1f45..d60fb70 100644 --- a/on-boot-script/README.old.md +++ b/on-boot-script/README.old.md @@ -2,72 +2,73 @@ ## Automated Setup -* NB! THESE WILL NOT PERSIST THROUGH FIRMWARE. They still work however +- NB! THESE WILL NOT PERSIST THROUGH FIRMWARE. They still work however 1. Copy [install.sh](manual-install/install.sh) to your UDM and execute it -1. Copy any shell scripts you want to run to /mnt/data/on_boot.d and make sure they are executable and have the correct shebang (#!/bin/sh) - 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-start-containers.sh) +1. Copy any shell scripts you want to run to /data/on_boot.d and make sure they are executable and have the correct shebang (#!/bin/sh) + 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-start-containers.sh) ## Manual Setup 1. Copy on_boot.sh and make on_boot.d and add scripts to on_boot.d - ```sh - mkdir -p /mnt/data/on_boot.d - vi /mnt/data/on_boot.sh - chmod u+x /mnt/data/on_boot.sh - ``` + ```sh + mkdir -p /data/on_boot.d + vi /data/on_boot.sh + chmod u+x /data/on_boot.sh + ``` - Example: [on_boot.sh](examples/udm-files/on_boot.sh) + Example: [on_boot.sh](examples/udm-files/on_boot.sh) 2. Enter the container shell - ```sh - unifi-os shell - ``` + ```sh + unifi-os shell + ``` 3. make a script that sshs to the udm and runs on our boot script. 127.0.1.1 always points to the UDM - ```sh - echo "#!/bin/sh - ssh -o StrictHostKeyChecking=no root@127.0.1.1 '/mnt/data/on_boot.sh'" > /etc/init.d/udm.sh - chmod u+x /etc/init.d/udm.sh - ``` + ```sh + echo "#!/bin/sh + ssh -o StrictHostKeyChecking=no root@127.0.1.1 '/data/on_boot.sh'" > /etc/init.d/udm.sh + chmod u+x /etc/init.d/udm.sh + ``` + + Example: [udm.sh](examples/unifi-os-files/udm.sh) - Example: [udm.sh](examples/unifi-os-files/udm.sh) 4. make a service that runs on startup, after we have networking - ```sh - echo "[Unit] - Description=Run On Startup UDM - After=network.target + ```sh + echo "[Unit] + Description=Run On Startup UDM + After=network.target - [Service] - ExecStart=/etc/init.d/udm.sh + [Service] + ExecStart=/etc/init.d/udm.sh - [Install] - WantedBy=multi-user.target" > /etc/systemd/system/udmboot.service - ``` + [Install] + WantedBy=multi-user.target" > /etc/systemd/system/udmboot.service + ``` - Example: [udmboot.service](examples/unifi-os-files/udmboot.service) + Example: [udmboot.service](examples/unifi-os-files/udmboot.service) 5. enable it and test - ```sh - systemctl enable --now udmboot - ``` + ```sh + systemctl enable --now udmboot + ``` 6. back to the udm - ```sh - exit - ``` + ```sh + exit + ``` 7. reboot your udm/udmpro and make sure it worked - ```sh - reboot - exit - ``` + ```sh + reboot + exit + ``` diff --git a/on-boot-script/dpkg-build-files/debian/postrm b/on-boot-script/dpkg-build-files/debian/postrm index e5ba8ba..46b7f1e 100755 --- a/on-boot-script/dpkg-build-files/debian/postrm +++ b/on-boot-script/dpkg-build-files/debian/postrm @@ -22,7 +22,7 @@ set -e case "$1" in purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) if [ -x /sbin/ssh-proxy ]; then - /sbin/ssh-proxy rm -f /mnt/data/on_boot.sh + /sbin/ssh-proxy rm -f /data/on_boot.sh fi true ;; diff --git a/on-boot-script/dpkg-build-files/debian/preinst b/on-boot-script/dpkg-build-files/debian/preinst index 55e7e6d..b961282 100755 --- a/on-boot-script/dpkg-build-files/debian/preinst +++ b/on-boot-script/dpkg-build-files/debian/preinst @@ -17,7 +17,7 @@ set -e case "$1" in install|upgrade) if [ -x /sbin/ssh-proxy ]; then - /sbin/ssh-proxy rm -f /mnt/data/on_boot.sh + /sbin/ssh-proxy rm -f /data/on_boot.sh fi true ;; diff --git a/on-boot-script/dpkg-build-files/udm-boot.service b/on-boot-script/dpkg-build-files/udm-boot.service index d82e3f6..02671ef 100644 --- a/on-boot-script/dpkg-build-files/udm-boot.service +++ b/on-boot-script/dpkg-build-files/udm-boot.service @@ -8,7 +8,7 @@ StartLimitBurst=5 [Service] Restart=on-failure RestartSec=5s -ExecStart=/sbin/ssh-proxy 'mkdir -p /mnt/data/on_boot.d && find -L /mnt/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'\' +ExecStart=/sbin/ssh-proxy '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] diff --git a/on-boot-script/examples/udm-files/on_boot.d/10-shell-profile.sh b/on-boot-script/examples/udm-files/on_boot.d/10-shell-profile.sh index be3a5f4..4998125 100644 --- a/on-boot-script/examples/udm-files/on_boot.d/10-shell-profile.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/10-shell-profile.sh @@ -1,5 +1,21 @@ #!/bin/sh - +# Get DataDir location +DATA_DIR="/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 ## Configure shell profile device_info() { @@ -7,7 +23,7 @@ device_info() { } # Modify login banner (motd) -cat > /etc/motd </etc/motd < /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) }')" +cat >/etc/profile.d/prompt.sh <<'EOF' +UDM_NAME="$(grep -m 1 '^name:' ${DATA_DIR}/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/ +# Copy all global profile scripts (for all users) from `${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/` directory +mkdir -p ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d +cp -rf ${DATA_DIR}/on_boot.d/settings/profile/global.profile.d/* /etc/profile.d/ diff --git a/on-boot-script/examples/udm-files/on_boot.d/15-add-.profile.sh b/on-boot-script/examples/udm-files/on_boot.d/15-add-.profile.sh index 0df36d2..b524b38 100755 --- a/on-boot-script/examples/udm-files/on_boot.d/15-add-.profile.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/15-add-.profile.sh @@ -1,3 +1,20 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 -cp -f /mnt/data/on_boot.d/files/.profile /root/ +cp -f ${DATA_DIR}/on_boot.d/files/.profile /root/ diff --git a/on-boot-script/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh b/on-boot-script/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh index 1eb301e..b934b1c 100644 --- a/on-boot-script/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/15-add-github-ssh-keys.sh @@ -1,16 +1,35 @@ #!/bin/sh + +# Get DataDir location +DATA_DIR="/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 + ## 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="" # File location for the output of the git download -GITHUB_KEY_PATH="/mnt/data/podman/ssh" +GITHUB_KEY_PATH="${DATA_DIR}/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_PATH="${DATA_DIR}/podman/ssh" INPUT_KEY_FILE="${INPUT_KEY_PATH}/ssh.keys" # The target key file for the script OUTPUT_KEY_PATH="/root/.ssh" @@ -18,7 +37,7 @@ OUTPUT_KEY_FILE="${OUTPUT_KEY_PATH}/authorized_keys" ## Functions # This function downloads the keys from the selected github user -download_from_github(){ +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" @@ -27,26 +46,25 @@ download_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} +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(){ +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 + counter=0 + while IFS= read -r line; do write_to_output "${line}" let "counter++" - done < $1 + done <$1 echo "${counter} number of entries read from " } diff --git a/on-boot-script/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh b/on-boot-script/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh index 77c32d8..70e7646 100644 --- a/on-boot-script/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/15-add-root-ssh-keys.sh @@ -1,8 +1,24 @@ #!/bin/sh - +# Get DataDir location +DATA_DIR="/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 ## Places public keys in ~/.ssh/authorized_keys -KEYS_SOURCE_FILE="/mnt/data/on_boot.d/settings/ssh/authorized_keys" +KEYS_SOURCE_FILE="${DATA_DIR}/on_boot.d/settings/ssh/authorized_keys" KEYS_TARGET_FILE="/root/.ssh/authorized_keys" count_added=0 @@ -11,19 +27,19 @@ 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" + echo "$key" >>"$KEYS_TARGET_FILE" else - let count_skipped++ + let count_skipped++ fi -done < "$KEYS_SOURCE_FILE" +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" + 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 +dropbearconvert openssh dropbear ${DATA_DIR}/ssh/id_rsa /root/.ssh/id_dropbear exit 0 diff --git a/on-boot-script/examples/udm-files/on_boot.d/15-preserve-history.sh b/on-boot-script/examples/udm-files/on_boot.d/15-preserve-history.sh index 40993de..2a7f82b 100755 --- a/on-boot-script/examples/udm-files/on_boot.d/15-preserve-history.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/15-preserve-history.sh @@ -1,13 +1,29 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +mkdir -p ${DATA_DIR}/.home -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 - +for file in .ash_history .bash_history; do + if [ ! -f ${DATA_DIR}/.home/$file ]; then + touch /root/$file + cp /root/$file ${DATA_DIR}/.home/$file + chown root:root ${DATA_DIR}/.home/$file + chmod 0600 ${DATA_DIR}/.home/$file + fi + ln -sf ${DATA_DIR}/.home/$file /root/$file +done diff --git a/on-boot-script/examples/udm-files/on_boot.d/25-add-cron-jobs.sh b/on-boot-script/examples/udm-files/on_boot.d/25-add-cron-jobs.sh index f6ae6f1..6326a2d 100644 --- a/on-boot-script/examples/udm-files/on_boot.d/25-add-cron-jobs.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/25-add-cron-jobs.sh @@ -1,9 +1,25 @@ #!/bin/sh - -## Store crontab files in /mnt/data/cronjobs/ (you will need to create this folder). +# Get DataDir location +DATA_DIR="/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 +## Store crontab files in ${DATA_DIR}/cronjobs/ (you will need to create this folder). ## This script will re-add them on startup. -cp /mnt/data/cronjobs/* /etc/cron.d/ +cp ${DATA_DIR}/cronjobs/* /etc/cron.d/ /etc/init.d/crond restart exit 0 diff --git a/on-boot-script/examples/udm-files/on_boot.d/iptables_timerestrict.sh b/on-boot-script/examples/udm-files/on_boot.d/iptables_timerestrict.sh index 8cff433..af498a6 100644 --- a/on-boot-script/examples/udm-files/on_boot.d/iptables_timerestrict.sh +++ b/on-boot-script/examples/udm-files/on_boot.d/iptables_timerestrict.sh @@ -1,87 +1,100 @@ -#!/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: -/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 +#!/bin/sh +# Get DataDir location +DATA_DIR="/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 +## ---------------------------------------------------------------------- +## 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 ${DATA_DIR}/on_boot.d/, using something like WinSCP or SSH + vi. +## * Grant Execute permission: chmod +x ${DATA_DIR}/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: ${DATA_DIR}/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: +/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 diff --git a/on-boot-script/remote_install.sh b/on-boot-script/remote_install.sh index 0a15ca4..52918c7 100755 --- a/on-boot-script/remote_install.sh +++ b/on-boot-script/remote_install.sh @@ -1,22 +1,22 @@ #!/usr/bin/env sh # Get DataDir location -DATA_DIR="/mnt/data" +DATA_DIR="/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 +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" @@ -31,11 +31,10 @@ 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 + cat < "$SYSTEMCTL_PATH" || return 1 + udmse_on_boot_systemd >"$SYSTEMCTL_PATH" || return 1 sleep 1s echo "Enabling UDM boot..." @@ -165,43 +164,42 @@ header depends_on ubnt-device-info depends_on curl -ON_BOOT_D_PATH="$DATA_DIR/on_boot.d" +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 +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 + 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 @@ -220,7 +218,6 @@ 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 diff --git a/persist-changes/README.md b/persist-changes/README.md index 2103f03..8748e9f 100644 --- a/persist-changes/README.md +++ b/persist-changes/README.md @@ -11,20 +11,20 @@ For example, [configuring two IP addresses on your WAN interface, so that you ca ## Installation 1. [Enable on-boot-script](https://github.com/unifi-utilities/unifios-utilities/blob/main/on-boot-script/README.md) -1. Copy `42-watch-for-changes.sh` to `/mnt/data/on_boot.d/` - * Check the `FILE` variable, it should point to a file that exists, it might be in `/data` or in `/mnt/data` -1. Copy `on-state-change.sh` to `/mnt/data/scripts/` -1. Edit `/mnt/data/scripts/on-state-change.sh` to your heart's content +1. Copy `42-watch-for-changes.sh` to `/data/on_boot.d/` + - Check the `FILE` variable, it should point to a file that exists, it might be in `/data` or in `/data` +1. Copy `on-state-change.sh` to `/data/scripts/` +1. Edit `/data/scripts/on-state-change.sh` to your heart's content > Make sure that your script doesn't error in the likely case that it tries to execute an update which has already been made ## Example: configuring two IP addresses on your WAN interface -`/mnt/data/scripts/on-state-change.sh` +`/data/scripts/on-state-change.sh` ``` #!/bin/sh # give port9 this IP, allows access to router web interface ip addr add 192.168.0.2/24 dev eth8 || true -``` \ No newline at end of file +``` diff --git a/persist-changes/on_boot.d/42-watch-for-changes.sh b/persist-changes/on_boot.d/42-watch-for-changes.sh index 4df1b34..55ad24a 100644 --- a/persist-changes/on_boot.d/42-watch-for-changes.sh +++ b/persist-changes/on_boot.d/42-watch-for-changes.sh @@ -1,41 +1,68 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 -EXECUTE01='/mnt/data/scripts/on-state-change.sh' -FILE="/data/udapi-config/ubios-udapi-server/ubios-udapi-server.state" +# Check if the directory exists +if [ ! -d "${DATA_DIR}/scripts" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/scripts" + echo "Directory '${DATA_DIR}/scripts' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/scripts' already exists. Moving on." +fi + +EXECUTE01="${DATA_DIR}/scripts/on-state-change.sh" +FILE="${DATA_DIR}/udapi-config/ubios-udapi-server/ubios-udapi-server.state" # /usr/bin/logger -t "${PROCESSNAME}" "$*" # run on boot aswell $EXECUTE01 if [ "$1" = "DAEMON" ]; then - # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP) - trap '' INT - cd /tmp - shift - ### daemonized section ###### - # RUNNING=`ps aux | grep $CMD | grep -v grep | wc -l` - # echo $RUNNING - # if [ "$RUNNING" -lt 1 ]; then - LAST=`ls -l "$FILE"` - # echo $LAST - while true; do - sleep 1 - NEW=`ls -l "$FILE"` - # echo $NEW - if [ "$NEW" != "$LAST" ]; then - DATE=`date` - echo "${DATE}: Executing ${EXECUTE01}" - $EXECUTE01 - LAST="$NEW" - fi - done - # fi - #### end of daemonized section #### - exit 0 + # is this necessary? Add other signals at will (TTIN TTOU INT STOP TSTP) + trap '' INT + cd /tmp || exit + shift + ### daemonized section ###### + # RUNNING=`ps aux | grep $CMD | grep -v grep | wc -l` + # echo $RUNNING + # if [ "$RUNNING" -lt 1 ]; then + LAST=$(ls -l "$FILE") + # echo $LAST + while true; do + sleep 1 + NEW=$(ls -l "$FILE") + # echo $NEW + if [ "$NEW" != "$LAST" ]; then + DATE=$(date) + echo "${DATE}: Executing ${EXECUTE01}" + $EXECUTE01 + LAST="$NEW" + fi + done + # fi + #### end of daemonized section #### + exit 0 fi export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin umask 022 # You can add nice and ionice before nohup but they might not be installed # nohup setsid $0 DAEMON $* 2>/var/log/mydaemon.err >/var/log/mydaemon.log & -nohup setsid $0 DAEMON WATCH $* 2>/var/log/watch.err >/var/log/watch.log & \ No newline at end of file +nohup setsid $0 DAEMON WATCH $* 2>/var/log/watch.err >/var/log/watch.log & diff --git a/podman-install/cronjobs/update-podman b/podman-install/cronjobs/update-podman index 4bd0ac2..be3eadc 100644 --- a/podman-install/cronjobs/update-podman +++ b/podman-install/cronjobs/update-podman @@ -1,3 +1,2 @@ # update and reinstall podman each day #00 00 * * * root sh -c '/data/on_boot.d/00-podman.sh --download-only && /data/on_boot.d/00-podman.sh --force' - diff --git a/podman-install/on_boot.d/00-podman.sh b/podman-install/on_boot.d/00-podman.sh index 3df7ba1..147802b 100755 --- a/podman-install/on_boot.d/00-podman.sh +++ b/podman-install/on_boot.d/00-podman.sh @@ -7,61 +7,58 @@ fi udm_model() { case "$(ubnt-device-info model || true)" in - "UniFi Dream Machine SE") - echo "udmse" - ;; - "UniFi Dream Machine Pro") - echo "udmpro" - ;; - "UniFi Dream Machine") - echo "udm" - ;; - "UniFi Dream Router") - echo "udr" - ;; - *) - echo "unknown" - ;; + "UniFi Dream Machine SE") + echo "udmse" + ;; + "UniFi Dream Machine Pro") + echo "udmpro" + ;; + "UniFi Dream Machine") + echo "udm" + ;; + "UniFi Dream Router") + echo "udr" + ;; + *) + echo "unknown" + ;; esac } - DESIRED_ZIPFILE='udmse-podman-install.zip' case "$(udm_model)" in - udmse|udmpro) - DESIRED_ZIPFILE="$(udm_model)-podman-install.zip" - ;; - udm) - # base UDM works fine with udmpro podman version, but has issues with udmse variant - DESIRED_ZIPFILE="udmpro-podman-install.zip" - ;; - *) - # shrug - # udmse-podman-install.zip seems to work fine on UDM 2.4.x - true - ;; +udmse | udmpro) + DESIRED_ZIPFILE="$(udm_model)-podman-install.zip" + ;; +udm) + # base UDM works fine with udmpro podman version, but has issues with udmse variant + DESIRED_ZIPFILE="udmpro-podman-install.zip" + ;; +*) + # shrug + # udmse-podman-install.zip seems to work fine on UDM 2.4.x + true + ;; esac - # Get DataDir location -DATA_DIR="/mnt/data" +DATA_DIR="/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 - ;; +1*) + DATA_DIR="/mnt/data" + ;; +2*) + DATA_DIR="/data" + ;; +3*) + DATA_DIR="/data" + ;; +*) + echo "ERROR: No persistent storage found." 1>&2 + exit 1 + ;; esac - CACHE_DIR="${DATA_DIR}/podman/cache" INSTALL_ROOT="${DATA_DIR}/podman/install" CONF_DIR="${DATA_DIR}/podman/conf" @@ -71,9 +68,9 @@ mkdir -p "${CACHE_DIR}" "${INSTALL_ROOT}" "${CONF_DIR}" URL="https://unifi.boostchicken.io/${DESIRED_ZIPFILE}" if [ "$1" = '--download-only' ]; then - echo "downloading ${URL}" \ - && curl -Lsfo "${CACHE_DIR}/${DESIRED_ZIPFILE}" "${URL}" \ - && echo "downloaded ${URL}" + echo "downloading ${URL}" && + curl -Lsfo "${CACHE_DIR}/${DESIRED_ZIPFILE}" "${URL}" && + echo "downloaded ${URL}" exit $? fi @@ -88,8 +85,8 @@ fi if [ -f "${CACHE_DIR}/${DESIRED_ZIPFILE}" ]; then echo "(using cache at ${CACHE_DIR}/${DESIRED_ZIPFILE})" -elif echo "downloading ${URL}" \ - && curl -Lsfo "${CACHE_DIR}/${DESIRED_ZIPFILE}" "${URL}"; then +elif echo "downloading ${URL}" && + curl -Lsfo "${CACHE_DIR}/${DESIRED_ZIPFILE}" "${URL}"; then echo "downloaded ${URL}" else echo 'download failed' @@ -119,4 +116,3 @@ fi echo 'Something went wrong' exit 1 - diff --git a/podman-update/01-podman-update.sh b/podman-update/01-podman-update.sh index 8aa864d..6459be6 100644 --- a/podman-update/01-podman-update.sh +++ b/podman-update/01-podman-update.sh @@ -1,13 +1,39 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 -mkdir -p /mnt/data/.cache +# Check if the directory exists +if [ ! -d "${DATA_DIR}/scripts" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/scripts" + echo "Directory '${DATA_DIR}/scripts' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/scripts' already exists. Moving on." +fi +mkdir -p ${DATA_DIR}/.cache PODMAN_VERSION=3.3.0 RUNC_VERSION=1.0.2 CONMON_VERSION=2.0.29 -PODMAN_DL=/mnt/data/.cache/podman-$PODMAN_VERSION -RUNC_DL=/mnt/data/.cache/runc-$RUNC_VERSION -CONMON_DL=/mnt/data/.cache/conmon-$CONMON_VERSION +PODMAN_DL=${DATA_DIR}/.cache/podman-$PODMAN_VERSION +RUNC_DL=${DATA_DIR}/.cache/runc-$RUNC_VERSION +CONMON_DL=${DATA_DIR}/.cache/conmon-$CONMON_VERSION SECCOMP=/usr/share/containers/seccomp.json while [ ! -f $CONMON_DL ]; do @@ -46,4 +72,3 @@ sed -i 's/driver = ""/driver = "overlay"/' /etc/containers/storage.conf sed -i 's/ostree_repo = ""/#ostree_repo = ""/' /etc/containers/storage.conf # Comment out if you don't want to enable docker-compose or remote docker admin /usr/bin/podman system service --time=0 tcp:0.0.0.0:2375 & - diff --git a/rclone/10-rclone.sh b/rclone/10-rclone.sh index a14029f..1918e12 100644 --- a/rclone/10-rclone.sh +++ b/rclone/10-rclone.sh @@ -1,21 +1,48 @@ #!/bin/sh CONTAINER=rclone +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/backups" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/backups" + echo "Directory '${DATA_DIR}/backups' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/backups' already exists. Moving on." +fi if podman container exists "$CONTAINER"; then podman start "$CONTAINER" else podman run -i -d --rm \ --net=host \ - -v /mnt/data/rclone:/data/backups/rclone \ - -v /mnt/data/pihole:/data/backups/pihole \ - -v /mnt/data/on_boot.d:/data/backups/on_boot.d \ - -v /data/unifi/data/backup/autobackup:/data/backups//data/unifi/data/backup/autobackup \ - -v /mnt/data/podman/cni:/data/backups/podman/cni \ - -v /mnt/data/rclone:/config/rclone \ - -v /mnt/data/rclone/sync.sh:/data/sync.sh \ + -v ${DATA_DIR}/rclone:${DATA_DIR}/backups/rclone \ + -v ${DATA_DIR}/pihole:${DATA_DIR}/backups/pihole \ + -v ${DATA_DIR}/on_boot.d:${DATA_DIR}/backups/on_boot.d \ + -v ${DATA_DIR}/unifi/data/backup/autobackup:${DATA_DIR}/backup/unifi/autobackup \ + -v ${DATA_DIR}/podman/cni:${DATA_DIR}/backups/podman/cni \ + -v ${DATA_DIR}/rclone:/config/rclone \ + -v ${DATA_DIR}/rclone/sync.sh:${DATA_DIR}/sync.sh \ --name "$CONTAINER" \ --security-opt=no-new-privileges \ rclone/rclone:latest \ rcd --rc-web-gui --rc-addr :5572 \ --rc-user rclone --rc-pass randompassword12345 -fi \ No newline at end of file +fi diff --git a/rclone/README.md b/rclone/README.md index ab4f6fe..cd7d9c7 100644 --- a/rclone/README.md +++ b/rclone/README.md @@ -12,22 +12,22 @@ 1. Make a directory for your configuration - ```sh - mkdir -p /mnt/data/rclone - ``` + ```sh + mkdir -p /data/rclone + ``` -2. Create [rclone.conf](https://rclone.org/commands/rclone_config/) in `/mnt/data/rclone` and update it to meet yours needs. -3. Copy [sync.sh](sync.sh) in `/mnt/data/rclone` and update it to meet your needs. -4. Copy [10-rclone.sh](10-rclone.sh) to `/mnt/data/on_boot.d` and update it to meet your needs. -5. Execute `/mnt/data/on_boot.d/10-rclone.sh` +2. Create [rclone.conf](https://rclone.org/commands/rclone_config/) in `/data/rclone` and update it to meet yours needs. +3. Copy [sync.sh](sync.sh) in `/data/rclone` and update it to meet your needs. +4. Copy [10-rclone.sh](10-rclone.sh) to `/data/on_boot.d` and update it to meet your needs. +5. Execute `/data/on_boot.d/10-rclone.sh` 6. Execute `podman logs rclone`, this will provide a link to the Web GUI. 7. Copy [rclone](rclone) in `/etc/cron.hourly/`. 8. Set permissions to executable `chmod +x /etc/cron.hourly/rclone`. ## Customization -1. Login to run rclone commands locally to create and test configs +1. Login to run rclone commands locally to create and test configs - ```sh - podman exec -ti rclone /bin/sh - ``` + ```sh + podman exec -ti rclone /bin/sh + ``` diff --git a/run-pihole/10-cloudflared.sh b/run-pihole/10-cloudflared.sh index ed8c608..7cd582a 100644 --- a/run-pihole/10-cloudflared.sh +++ b/run-pihole/10-cloudflared.sh @@ -1,14 +1,13 @@ #!/bin/bash ARCH=$(uname -m) -if [ $ARCH == "x86_64" ] -then +if [ "$ARCH" == "x86_64" ]; then ARCH="amd64" -elif [ $ARCH == "aarch64" ]; then - ARCH="arm64" +elif [ "$ARCH" == "aarch64" ]; then + ARCH="arm64" fi -curl -fsSLo "/opt/cloudflared" https://github.com/cloudflare/cloudflared/releases/download/2021.5.9/cloudflared-linux-$ARCH +curl -fsSLo "/opt/cloudflared" https://github.com/cloudflare/cloudflared/releases/download/2021.5.9/cloudflared-linux-"$ARCH" chmod +x /opt/cloudflared /opt/cloudflared update -/opt/cloudflared proxy-dns $CLOUDFLARED_OPTS & +/opt/cloudflared proxy-dns "$CLOUDFLARED_OPTS" & diff --git a/run-pihole/README.md b/run-pihole/README.md index 734a6e1..fc5c9f6 100644 --- a/run-pihole/README.md +++ b/run-pihole/README.md @@ -2,7 +2,7 @@ ## Features -1. Run Pi-hole on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti +1. Run Pi-hole on your UDM with a completely isolated network stack. This will not port conflict or be influenced by any changes on by Ubiquiti 2. Persists through reboots and firmware updates. ## Requirements @@ -13,108 +13,103 @@ Note: IP and VLAN settings for you pihole network, 20-dns-conflist and 10-dns.sh MUST all match each other. -* Example settings for pihole network: - Network Name: Pihole - Host address: 10.0.5.1 - Netmask: 24 - VLAN ID: 5 - Network Type: Standard - Multicast DNS: Enable - DHCP: None - Ipv6 Interface Type: None +- Example settings for pihole network: + Network Name: Pihole + Host address: 10.0.5.1 + Netmask: 24 + VLAN ID: 5 + Network Type: Standard + Multicast DNS: Enable + DHCP: None + Ipv6 Interface Type: None - -* YOU WILL NEED TO CHANGE [`20-dns.conflist`](../cni-plugins/20-dns.conflist) +- YOU WILL NEED TO CHANGE [`20-dns.conflist`](../cni-plugins/20-dns.conflist) Change the line: "mac": "add 3 fake hex portions, replacing x's here 00:1c:b4:xx:xx:xx", - to create a legitimate mac address that matches some vendor space(first 6 digits ). It needs to be unique on your network. - The example gives one option. Locally administered mac addresses do not work. - + to create a legitimate mac address that matches some vendor space(first 6 digits ). It needs to be unique on your network. + The example gives one option. Locally administered mac addresses do not work. + If you are using a different IP address than the example: Change these lines to match your settings: - "address": "10.0.5.3/24", - "gateway": "10.0.5.1" - + "address": "10.0.5.3/24", + "gateway": "10.0.5.1" If you are using a different VLAN than the example: Change this line to match your VLAN number: - "master": "br5", - -* You MAY need to change[`10-dns.sh`](../dns-common/on_boot.d/10-dns.sh). + "master": "br5", + +- You MAY need to change[`10-dns.sh`](../dns-common/on_boot.d/10-dns.sh). If you are using a different IP address than the example: Change these lines to match your settings: - IPV4_IP="10.0.5.3" - IPV4_GW="10.0.5.1/24" - + IPV4_IP="10.0.5.3" + IPV4_GW="10.0.5.1/24" If you are using a different VLAN than the example: Change this line to match your VLAN number: - VLAN=5 - + VLAN=5 If you want the pihole container to have a different name than the example: Change this line to match the different name: - CONTAINER=pihole - -* If you want IPv6 support + CONTAINER=pihole +- If you want IPv6 support Use 20-dnsipv6.conflist and update 10-dns.sh with the IPv6 addresses. - Also, please provide IPv6 servers to podman using --dns arguments. - + Also, please provide IPv6 servers to podman using --dns arguments. + ## Steps ### Configuration files and scripts -1.0 Copy [`05-install-cni-plugins.sh`](../cni-plugins/05-install-cni-plugins.sh) to `/mnt/data/on_boot.d` -1.1 Execute `chmod +x /mnt/data/on_boot.d/05-install-cni-plugins.sh` -1.2 Execute `/mnt/data/on_boot.d/05-install-cni-plugins.sh` +1.0 Copy [`05-install-cni-plugins.sh`](../cni-plugins/05-install-cni-plugins.sh) to `/data/on_boot.d` +1.1 Execute `chmod +x /data/on_boot.d/05-install-cni-plugins.sh` +1.2 Execute `/data/on_boot.d/05-install-cni-plugins.sh` 2.0 On your controller, create a network with no DHCP server and give it a VLAN.(see example settings above). -2.1 Copy YOUR modified [`20-dns.conflist`] to `/mnt/data/podman/cni` -2.2 Execute `chmod +x /mnt/data/podman/cni/20-dns.conflist` -2.3 Execute `cp /mnt/data/podman/cni/20-dns.conflist /etc/cni/net.d/dns.conflist` +2.1 Copy YOUR modified [`20-dns.conflist`] to `/data/podman/cni` +2.2 Execute `chmod +x /data/podman/cni/20-dns.conflist` +2.3 Execute `cp /data/podman/cni/20-dns.conflist /etc/cni/net.d/dns.conflist` To check progress - run the command: ```shell podman network inspect dns ``` - You should see a copy of your 20-dns.conflist displayed. - -3.0 Copy your [`10-dns.sh`] to `/mnt/data/on_boot.d` -3.1 Execute `chmod +x /mnt/data/on_boot.d/10-dns.sh` -3.2 Execute `/mnt/data/on_boot.d/10-dns.sh` + You should see a copy of your 20-dns.conflist displayed. +3.0 Copy your [`10-dns.sh`] to `/data/on_boot.d` +3.1 Execute `chmod +x /data/on_boot.d/10-dns.sh` +3.2 Execute `/data/on_boot.d/10-dns.sh` ### Create directories for persistent Pi-hole configuration 4.0 Execute the following commands: - ```sh - mkdir -p /mnt/data/etc-pihole - mkdir -p /mnt/data/pihole/etc-dnsmasq.d - ``` + +```sh +mkdir -p /data/etc-pihole +mkdir -p /data/pihole/etc-dnsmasq.d +``` ### Create the pihole container Note: - --name MUST match the name you set in 10-dns.sh - -e FTLCONF_REPLY_ADDR4 MUST be in the range you set for your pihole network - -e TZ MUST match the timezone for your controller - +--name MUST match the name you set in 10-dns.sh +-e FTLCONF_REPLY_ADDR4 MUST be in the range you set for your pihole network +-e TZ MUST match the timezone for your controller + The example uses these upstream DNS servers The following command sets the upstream DNS servers to `1.1.1.1` ([Cloudflare DNS](https://1.1.1.1/)) and `8.8.8.8` ([Google DNS](https://developers.google.com/speed/public-dns/)). If you want to use different upstream DNS servers, change the following lines: - --dns=1.1.1.1 \ - --dns=8.8.8.8 \ - +--dns=1.1.1.1 \ + --dns=8.8.8.8 \ + If you want to run a DHCP server as well you need to add the following lines: - --cap-add=NET_ADMIN - -5.0 Run the following (or your modified version) by copy / pasting the entire set. - +--cap-add=NET_ADMIN + +5.0 Run the following (or your modified version) by copy / pasting the entire set. + ```sh - podman run -d \ + podman run -d \ --network dns \ --restart always \ --name pihole \ -e TZ="America/Los Angeles" \ - --cap-add=NET_ADMIN \ - -v "/mnt/data/etc-pihole/:/etc/pihole/" \ - -v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ + --cap-add=NET_ADMIN \ + -v "/data/etc-pihole/:/etc/pihole/" \ + -v "/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ --dns=127.0.0.1 \ --dns=1.1.1.1 \ --dns=8.8.8.8 \ @@ -125,19 +120,20 @@ If you want to run a DHCP server as well you need to add the following lines: -e IPv6="False" \ pihole/pihole:latest ``` - + The below errors are expected and acceptable: - + > ``` > ERRO[0022] unable to get systemd connection to add healthchecks: dial unix /run/systemd/private: connect: no such file or directory > ERRO[0022] unable to get systemd connection to start healthchecks: dial unix /run/systemd/private: connect: no such file or directory - > ``` + > ``` 6.0 Set the pihole admin password ```sh podman exec -it pihole pihole -a -p YOURNEWPASSHERE ``` + ## Set the new DNS in your UDM 7.0 Update your DNS Servers to `10.0.5.3` (or your custom ip) for each of your Networks (UDM GUI | Networks | Advanced | DHCP Name Server) @@ -145,27 +141,27 @@ If you want to run a DHCP server as well you need to add the following lines: ## Upgrading your PiHole container -1. Edit `upd_pihole.sh` script to use the same `podman run` command you used at installation. -2. Copy the `upd_pihole.sh` script to /mnt/data/scripts -3. Anytime you want to update your pihole installation, simply run `/mnt/data/scripts/upd_pihole.sh` +1. Edit `upd_pihole.sh` script to use the same `podman run` command you used at installation. +2. Copy the `upd_pihole.sh` script to /data/scripts +3. Anytime you want to update your pihole installation, simply run `/data/scripts/upd_pihole.sh` ## Optional Builds -The cloudflared command is written in Go and is not very lightweight. In my -experience, it's not made for long-term running. Instead, the project DoTe +The cloudflared command is written in Go and is not very lightweight. In my +experience, it's not made for long-term running. Instead, the project DoTe has a tiny memory footprint and operates on an event loop with some major -optimisations for connection caching. It allows you to forward traffic to any +optimisations for connection caching. It allows you to forward traffic to any DNS-over-TLS provider. ### PiHole with CloudFlareD Command - + podman run -d \ - --network dns + --network dns --restart always \ --name pihole \ -e TZ="America/Los Angeles" \ - -v "/mnt/data/etc-pihole/:/etc/pihole/" \ - -v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ + -v "/data/etc-pihole/:/etc/pihole/" \ + -v "/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ --dns=127.0.0.1 \ --dns=1.1.1.1 \ --hostname pi.hole \ @@ -179,8 +175,8 @@ DNS-over-TLS provider. ### PiHole with DoTe -Simply copy the `custom_pihole_dote.sh` script to `/mnt/data/scripts` and run it -to forward all DNS traffic over TLS to Cloudflare 1.1.1.1 / 1.0.0.1. You can modify the +Simply copy the `custom_pihole_dote.sh` script to `/data/scripts` and run it +to forward all DNS traffic over TLS to Cloudflare 1.1.1.1 / 1.0.0.1. You can modify the script to forward to different services with ease and full configuration options including certificate pinning is available in the DoTe README here: https://github.com/chrisstaite/DoTe/ @@ -190,8 +186,8 @@ https://github.com/chrisstaite/DoTe/ --restart always \ --name pihole \ -e TZ="America/Los Angeles" \ - -v "/mnt/data/etc-pihole/:/etc/pihole/" \ - -v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ + -v "/data/etc-pihole/:/etc/pihole/" \ + -v "/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ --dns=127.0.0.1 \ --dns=1.1.1.1 \ --hostname pi.hole \ @@ -202,6 +198,6 @@ https://github.com/chrisstaite/DoTe/ -e PIHOLE_DNS_="127.0.0.1#5053" \ -e IPv6="False" \ boostchicken/pihole-dote:latest - -## New releases will be made when PiHole updates their labels + +## New releases will be made when PiHole updates their labels diff --git a/run-pihole/custom_pihole_dote.sh b/run-pihole/custom_pihole_dote.sh index 1e9f4a4..2666b05 100755 --- a/run-pihole/custom_pihole_dote.sh +++ b/run-pihole/custom_pihole_dote.sh @@ -1,11 +1,38 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "${DATA_DIR}/pihole" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/pihole" + mkdir -p "${DATA_DIR}/pihole/etc" + echo "Directory '${DATA_DIR}/pihole' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/pihole' already exists. Moving on." +fi set -e tmpdir="$(mktemp -d)" curl -sSLo "${tmpdir}/dote" https://github.com/chrisstaite/DoTe/releases/latest/download/dote_arm64 -cat > "${tmpdir}/Dockerfile" <"${tmpdir}/Dockerfile" <&2 + exit 1 + ;; +esac +# Check if the directory exists +if [ ! -d "${DATA_DIR}/pihole" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/pihole" + mkdir -p "${DATA_DIR}/pihole/etc" + echo "Directory '${DATA_DIR}/pihole' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/pihole' already exists. Moving on." +fi podman pull $IMAGE podman stop pihole podman rm pihole podman run -d --network dns --restart always \ --name pihole \ -e TZ="America/Chicago" \ - -v "/mnt/data/etc-pihole/:/etc/pihole/" \ - -v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ + -v "${DATA_DIR}/pihole/etc:/etc/pihole/" \ + -v "${DATA_DIR}/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ --dns=127.0.0.1 \ --dns=1.1.1.1 \ --dns=1.0.0.1 \ diff --git a/suricata/README.md b/suricata/README.md index aca9a1c..123707d 100644 --- a/suricata/README.md +++ b/suricata/README.md @@ -1,5 +1,7 @@ # Run Suricata 5.0.3 with custom rules + ## UBNT updated Suricata in 1.9.x firmwares make this unneeded + ## Features 1. Run a newer suricata with custom rules @@ -11,9 +13,9 @@ ## Customization -* Put customs rules files in /mnt/data/suricata-rules +- Put customs rules files in /data/suricata-rules ## Steps -1. Copy [25-suricata.sh](on_boot.d/25-suricata.sh) to /mnt/data/on_boot.d and update its values to reflect your environment -2. Execute /mnt/data/on_boot.d/25-suricata.sh +1. Copy [25-suricata.sh](on_boot.d/25-suricata.sh) to /data/on_boot.d and update its values to reflect your environment +2. Execute /data/on_boot.d/25-suricata.sh diff --git a/suricata/on_boot.d/25-suricata.sh b/suricata/on_boot.d/25-suricata.sh index dca4bd1..4646354 100644 --- a/suricata/on_boot.d/25-suricata.sh +++ b/suricata/on_boot.d/25-suricata.sh @@ -1,10 +1,36 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 +# Check if the directory exists +if [ ! -d "${DATA_DIR}/suricata-rules" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/suricata-rules" + echo "Directory '${DATA_DIR}/suricata-rules' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/suricata-rules' already exists. Moving on." +fi APP_PID="/run/suricata.pid" -cat <<"EOF" > /tmp/suricata.sh +cat <<"EOF" >/tmp/suricata.sh #!/bin/sh -CUSTOM_RULES="/mnt/data/suricata-rules" +CUSTOM_RULES="${DATA_DIR}/suricata-rules" for file in $(find ${CUSTOM_RULES} -name '*.rules' -print) do diff --git a/tailscale/README.md b/tailscale/README.md index 18d9660..33eed4d 100644 --- a/tailscale/README.md +++ b/tailscale/README.md @@ -1,23 +1,29 @@ # Tailscale -Run Tailscale in a container on your Unifi Dream Machine. -In combination with the DNS modules, setting up a Tailscale exit node on the UDM Pro can be quite powerful. -Additionally, the UDM is well positioned to add a tailscale subnet router to permit remote access to the manged network. + +Run Tailscale in a container on your Unifi Dream Machine. +In combination with the DNS modules, setting up a Tailscale exit node on the UDM Pro can be quite powerful. +Additionally, the UDM is well positioned to add a tailscale subnet router to permit remote access to the manged network. ## Prerequisites + Follow the instructions and set up the scripts in these directories (in order) before continuing further: + 1. `on-boot-script` 2. `container-common` 3. `cni-plugins` 4. (optional, but recommended if you want to set up an exit node and benefit from ad-blocking) `dns-common` followed by your favorite DNS server such as `run-pihole` or `AdguardHome` ## Installation -1. Copy `on_boot.d/20-tailscale.sh` to `/mnt/data/on_boot.d/20-tailscale.sh`. -2. Make sure the boot script is executable with `chmod +x /mnt/data/on_boot.d/20-tailscale.sh`. + +1. Copy `on_boot.d/20-tailscale.sh` to `/data/on_boot.d/20-tailscale.sh`. +2. Make sure the boot script is executable with `chmod +x /data/on_boot.d/20-tailscale.sh`. ## Tailscale Configuration -After installing the boot script, you will want to set up the included shell alias and check network connectivity before continuing. -1. Run `/mnt/data/on_boot.d/20-tailscale.sh alias` to print a helpful shell alias to the terminal, inside a shell comment. -2. Add the alias to your running session, after which you can run `tailscale status` or `tailscale netcheck` from the host shell to make sure the running tailscale agent is healthy and has a good network connection. -3. `/mnt/data/on_boot.d/20-tailscale.sh status` will also perform status checks, if the alias setup isn't working for some reason. -How to proceed from here is largely up to you. It is possible to authenticate by simply running `tailscale up` (if you installed the shell alias) and doing most of the rest of the configuration in the admin console. You will likely want to provide additional options to `tailscale up` to use an auth key, advertise tags or subnet routes, or other configuration. \ No newline at end of file +After installing the boot script, you will want to set up the included shell alias and check network connectivity before continuing. + +1. Run `/data/on_boot.d/20-tailscale.sh alias` to print a helpful shell alias to the terminal, inside a shell comment. +2. Add the alias to your running session, after which you can run `tailscale status` or `tailscale netcheck` from the host shell to make sure the running tailscale agent is healthy and has a good network connection. +3. `/data/on_boot.d/20-tailscale.sh status` will also perform status checks, if the alias setup isn't working for some reason. + +How to proceed from here is largely up to you. It is possible to authenticate by simply running `tailscale up` (if you installed the shell alias) and doing most of the rest of the configuration in the admin console. You will likely want to provide additional options to `tailscale up` to use an auth key, advertise tags or subnet routes, or other configuration. diff --git a/unbound/README.md b/unbound/README.md index a8057ab..37a2279 100644 --- a/unbound/README.md +++ b/unbound/README.md @@ -14,12 +14,12 @@ In the current examples, the DNS resolver (e.g., pi-hole) is listening on `10.0. Follow the steps in [run-pihole](../run-pihole) to create a separate IP address, by copying the files in the sub-directories to UDM/P. -Adjust the `11-unbound-macvlanip` and `.conflist` files, run [init_unbound.sh](./scripts/init_unbound.sh), *or* execute the commands below manually. +Adjust the `11-unbound-macvlanip` and `.conflist` files, run [init_unbound.sh](./scripts/init_unbound.sh), _or_ execute the commands below manually. -* Link the boot script [11-unbound-macvlanip.sh](./on_boot.d/11-unbound-macvlanip.sh) -> `ln -s /mnt/data/unbound/on_boot.d/11-unbound-macvlanip.sh /mnt/data/on_boot.d/11-unbound-macvlanip.sh` -* Link the IPv4 only configuration: [21-unbound.conflist](./cni_plugins/21-unbound.conflist) -> `ln -s /mnt/data/unbound/cni_plugins/21-unbound.conflist /etc/cni/net.d/21-unbound.conflist` *or* -* Link the IPv4 and IPv6 configuration: [21-unboundipv6.conflist](./cni_plugins/21-unboundipv6.conflist) -> `ln -s /mnt/data/unbound/cni_plugins/21-unboundipv6.conflist /etc/cni/net.d/21-unbound.conflist` -* Create the network +- Link the boot script [11-unbound-macvlanip.sh](./on_boot.d/11-unbound-macvlanip.sh) -> `ln -s /data/unbound/on_boot.d/11-unbound-macvlanip.sh /data/on_boot.d/11-unbound-macvlanip.sh` +- Link the IPv4 only configuration: [21-unbound.conflist](./cni_plugins/21-unbound.conflist) -> `ln -s /data/unbound/cni_plugins/21-unbound.conflist /etc/cni/net.d/21-unbound.conflist` _or_ +- Link the IPv4 and IPv6 configuration: [21-unboundipv6.conflist](./cni_plugins/21-unboundipv6.conflist) -> `ln -s /data/unbound/cni_plugins/21-unboundipv6.conflist /etc/cni/net.d/21-unbound.conflist` +- Create the network ```bash podman network create unbound @@ -42,9 +42,9 @@ Two things are left to do: set the upstream server and de-activate caching in Pi To use `unbound` as the upstream server for Pi-hole, change the following settings in Pi-hole's admin interface: -* Settings -> DNS -> Upstream DNS Servers - * Custom 1 (IPv4): 10.0.5.3 (or the IPv4 address you chose) - * Custom 2 (IPv6): fdca:5c13:1fb8::3 (or the IPv6 address you chose) +- Settings -> DNS -> Upstream DNS Servers + - Custom 1 (IPv4): 10.0.5.3 (or the IPv4 address you chose) + - Custom 2 (IPv6): fdca:5c13:1fb8::3 (or the IPv6 address you chose) Both Pi-hole as well as `unbound` are caching their requests. To make the changes of your upstream DNS and to de-activate caching in Pi-hole permanent, modify your `podman run` command **for pi-hole** in this way: @@ -52,8 +52,8 @@ Both Pi-hole as well as `unbound` are caching their requests. To make the change podman run -d --network dns --restart always \ --name pihole \ -e TZ="America/Los Angeles" \ - -v "/mnt/data/pihole/etc-pihole/:/etc/pihole/" \ - -v "/mnt/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ + -v "/data/pihole/etc-pihole/:/etc/pihole/" \ + -v "/data/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/" \ --dns=127.0.0.1 \ --dns=10.0.5.3 \ --hostname pi.hole \ diff --git a/unbound/on_boot.d/11-unbound-macvlanip.sh b/unbound/on_boot.d/11-unbound-macvlanip.sh index 16d3208..54e1c08 100644 --- a/unbound/on_boot.d/11-unbound-macvlanip.sh +++ b/unbound/on_boot.d/11-unbound-macvlanip.sh @@ -1,4 +1,32 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/unbound" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/unbound" + mkdir -p "${DATA_DIR}/unbound.conf.d" + echo "Directory '${DATA_DIR}/unbound' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/unbound' already exists. Moving on." +fi ## configuration variables: VLAN=5 @@ -31,9 +59,9 @@ IPV6_GW="fdca:5c13:1fb8::1/64" CONTAINER=unbound if ! test -f /opt/cni/bin/macvlan; then - echo "Error: CNI plugins not found. You can install it with the following command:" >&2 - echo " curl -fsSLo /mnt/data/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh /mnt/data/on_boot.d/05-install-cni-plugins.sh" >&2 - exit 1 + echo "Error: CNI plugins not found. You can install it with the following command:" >&2 + echo " curl -fsSLo ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh https://raw.githubusercontent.com/unifi-utilities/unifios-utilities/main/cni-plugins/05-install-cni-plugins.sh && /bin/sh ${DATA_DIR}/on_boot.d/05-install-cni-plugins.sh" >&2 + exit 1 fi # we assume that the VLAN bridge already exists, created by the filtering DNS (pi-hole) script diff --git a/unbound/scripts/init_unbound.sh b/unbound/scripts/init_unbound.sh index 3be6391..575169a 100755 --- a/unbound/scripts/init_unbound.sh +++ b/unbound/scripts/init_unbound.sh @@ -1,20 +1,37 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 # init unbound container - quick and dirty for now # no checks, no balances echo "Creating links..." # link the script to create an IP on the macvlan for unbound -ln -s /mnt/data/unbound/on_boot.d/11-unbound-macvlanip.sh /mnt/data/on_boot.d/11-unbound-macvlanip.sh +ln -s ${DATA_DIR}/unbound/on_boot.d/11-unbound-macvlanip.sh ${DATA_DIR}/on_boot.d/11-unbound-macvlanip.sh # configure either IPv4 only or IPv4 and IPv6 by uncommenting the proper line # # link the IPv4 configuration for CNI -# ln -s /mnt/data/unbound/cni_plugins/21-unbound.conflist /etc/cni/net.d/21-unbound.conflist +# ln -s ${DATA_DIR}/unbound/cni_plugins/21-unbound.conflist /etc/cni/net.d/21-unbound.conflist # link the IPv4 and IPv6 configuration for CNI -ln -s /mnt/data/unbound/cni_plugins/21-unboundipv6.conflist /etc/cni/net.d/21-unbound.conflist +ln -s ${DATA_DIR}/unbound/cni_plugins/21-unboundipv6.conflist /etc/cni/net.d/21-unbound.conflist # create the podman network unbound echo "Creating podman network..." @@ -22,4 +39,4 @@ podman network create unbound # create the container IP echo "Creating container IP..." -sh /mnt/data/on_boot.d/11-unbound-macvlanip.sh +sh ${DATA_DIR}/on_boot.d/11-unbound-macvlanip.sh diff --git a/unbound/scripts/upd_unbound.sh b/unbound/scripts/upd_unbound.sh index eedcbf2..6e7bc3e 100755 --- a/unbound/scripts/upd_unbound.sh +++ b/unbound/scripts/upd_unbound.sh @@ -1,4 +1,33 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/unbound" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/unbound" + mkdir -p "${DATA_DIR}/unbound.conf.d" + echo "Directory '${DATA_DIR}/unbound' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/unbound' already exists. Moving on." +fi + CONTAINER=unbound IMAGE=klutchell/unbound:latest @@ -7,12 +36,11 @@ podman pull $IMAGE echo "Stopping container..." podman stop $CONTAINER echo "Removing container..." -podman rm $CONTAINER +podman rm $CONTAINER echo "Updating root hints..." -mkdir -p /mnt/data/unbound/unbound.conf.d/ -curl -m 30 -o /mnt/data/unbound/unbound.conf.d/root.hints https://www.internic.net/domain/named.root +curl -m 30 -o ${DATA_DIR}/unbound/unbound.conf.d/root.hints https://www.internic.net/domain/named.root echo "Running $CONTAINER container" podman run -d --net unbound --restart always \ - --name $CONTAINER \ - -v "/mnt/data/unbound/unbound.conf.d/:/opt/unbound/etc/unbound/ " \ - $IMAGE \ No newline at end of file + --name $CONTAINER \ + -v "${DATA_DIR}/unbound/unbound.conf.d/:/opt/unbound/etc/unbound/ " \ + $IMAGE diff --git a/wireguard-go/README.md b/wireguard-go/README.md index 7fa457e..4d71156 100644 --- a/wireguard-go/README.md +++ b/wireguard-go/README.md @@ -13,44 +13,44 @@ ## Customization -* Update [wg0.conf](configs/wg0.conf) to match your environment -* You can use a custom interface name by changing wg0.conf to whatever you like -* Use PostUp and PostDown in your wg.conf to execute any commands after the interface is created or destroyed +- Update [wg0.conf](configs/wg0.conf) to match your environment +- You can use a custom interface name by changing wg0.conf to whatever you like +- Use PostUp and PostDown in your wg.conf to execute any commands after the interface is created or destroyed ## Steps 1. Make a directory for your keys and configuration: - ```sh - mkdir -p /mnt/data/wireguard - ``` + ```sh + mkdir -p /data/wireguard + ``` 2. Create your public and private keys: - ```sh - podman run -i --rm --net=host --name wireguard_conf masipcat/wireguard-go wg genkey > /mnt/data/wireguard/privatekey - podman run -i --rm --net=host --name wireguard_conf masipcat/wireguard-go wg pubkey < /mnt/data/wireguard/privatekey > /mnt/data/wireguard/publickey - ``` + ```sh + podman run -i --rm --net=host --name wireguard_conf masipcat/wireguard-go wg genkey > /data/wireguard/privatekey + podman run -i --rm --net=host --name wireguard_conf masipcat/wireguard-go wg pubkey < /data/wireguard/privatekey > /data/wireguard/publickey + ``` -3. Create a [Wireguard configuration](configs/wg0.conf) in /mnt/data/wireguard -4. Copy [20-wireguard.sh](on_boot.d/20-wireguard.sh) to /mnt/data/on_boot.d and update its values to reflect your environment -5. Execute /mnt/data/on_boot.d/[20-wireguard.sh](on_boot.d/20-wireguard.sh) +3. Create a [Wireguard configuration](configs/wg0.conf) in /data/wireguard +4. Copy [20-wireguard.sh](on_boot.d/20-wireguard.sh) to /data/on_boot.d and update its values to reflect your environment +5. Execute /data/on_boot.d/[20-wireguard.sh](on_boot.d/20-wireguard.sh) 6. If you are running a server, make the appropriate firewall rules / port forwards 7. Execute the wg command in the container to verify the tunnel is up. It should look something like this: - ```sh - $ podman exec -it wireguard wg - interface: wg0 - public key: - private key: (hidden) - listening port: 54321 + ```sh + $ podman exec -it wireguard wg + interface: wg0 + public key: + private key: (hidden) + listening port: 54321 - peer: - endpoint: 10.0.0.2:54321 - allowed ips: 10.1.0.0/16, 10.2.0.0/16 - latest handshake: 1 day, 14 hours, 46 minutes, 27 seconds ago - transfer: 138.44 MiB received, 5.00 GiB sent - ``` + peer: + endpoint: 10.0.0.2:54321 + allowed ips: 10.1.0.0/16, 10.2.0.0/16 + latest handshake: 1 day, 14 hours, 46 minutes, 27 seconds ago + transfer: 138.44 MiB received, 5.00 GiB sent + ``` ### Useful commands diff --git a/wireguard-go/on_boot.d/20-wireguard.sh b/wireguard-go/on_boot.d/20-wireguard.sh index f8b82c5..9a38cfd 100644 --- a/wireguard-go/on_boot.d/20-wireguard.sh +++ b/wireguard-go/on_boot.d/20-wireguard.sh @@ -1,14 +1,42 @@ #!/bin/sh + +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/wireguard" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/wireguard" + echo "Directory '${DATA_DIR}/wireguard' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/wireguard' already exists. Moving on." +fi + CONTAINER=wireguard # Starts a wireguard container that is deleted after it is stopped. -# All configs stored in /mnt/data/wireguard +# All configs stored in ${DATA_DIR}/wireguard if podman container exists ${CONTAINER}; then podman start ${CONTAINER} else podman run -i -d --rm --net=host --name ${CONTAINER} --privileged \ - -v /mnt/data/wireguard:/etc/wireguard \ + -v ${DATA_DIR}/wireguard:/etc/wireguard \ -v /dev/net/tun:/dev/net/tun \ -e LOG_LEVEL=info -e WG_COLOR_MODE=always \ masipcat/wireguard-go:0.0.20210424 fi - diff --git a/zerotier-one/20-zerotier.sh b/zerotier-one/20-zerotier.sh index cda56b0..4105133 100755 --- a/zerotier-one/20-zerotier.sh +++ b/zerotier-one/20-zerotier.sh @@ -1,10 +1,37 @@ #!/bin/sh +# Get DataDir location +DATA_DIR="/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 + +# Check if the directory exists +if [ ! -d "${DATA_DIR}/zerotier-one" ]; then + # If it does not exist, create the directory + mkdir -p "${DATA_DIR}/zerotier-one" + echo "Directory '${DATA_DIR}/zerotier-one' created." +else + # If it already exists, print a message + echo "Directory '${DATA_DIR}/zerotier-one' already exists. Moving on." +fi + CONTAINER=zerotier-one # Starts a ZeroTier container that is deleted after it is stopped. -# All configs stored in /mnt/data/zerotier-one +# All configs stored in ${DATA_DIR}/zerotier-one if podman container exists ${CONTAINER}; then podman start ${CONTAINER} else - podman run --device=/dev/net/tun --net=host --cap-add=NET_ADMIN --cap-add=SYS_ADMIN --cap-add=CAP_SYS_RAWIO -v /mnt/data/zerotier-one:/var/lib/zerotier-one --name zerotier-one -d bltavares/zerotier + podman run --device=/dev/net/tun --net=host --cap-add=NET_ADMIN --cap-add=SYS_ADMIN --cap-add=CAP_SYS_RAWIO -v ${DATA_DIR}/zerotier-one:/var/lib/zerotier-one --name zerotier-one -d bltavares/zerotier fi - diff --git a/zerotier-one/README.md b/zerotier-one/README.md index 3f96b5e..6ce54ca 100644 --- a/zerotier-one/README.md +++ b/zerotier-one/README.md @@ -1,12 +1,14 @@ # Run ZeroTier VPN on your UDM ## Install -1. Copy 20-zerotier.sh to /mnt/data/on_boot.d + +1. Copy 20-zerotier.sh to /data/on_boot.d 2. Create directories for persistent Zerotier configuration ``` - mkdir -p /mnt/data/zerotier-one + mkdir -p /data/zerotier-one ``` + 3. Start the zeriotier container ``` podman run -d \ @@ -16,7 +18,7 @@ --cap-add=NET_ADMIN \ --cap-add=SYS_ADMIN \ --cap-add=CAP_SYS_RAWIO \ - -v /mnt/data/zerotier-one:/var/lib/zerotier-one \ + -v /data/zerotier-one:/var/lib/zerotier-one \ bltavares/zerotier ``` 4. Join your zerotier network