Merge pull request #265 from femtofox/new_working

Add Samba file sharing support (disabled by default)
This commit is contained in:
noon92 2025-01-30 14:18:59 +02:00 • committed by GitHub
commit 7dce5f3df7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 552 additions and 100 deletions

View file

@ -9,25 +9,21 @@ echo "tmpfs /run tmpfs rw,nodev,nosuid,size=32M 0 0" | tee -a /etc/fstab
#echo "deb [arch=all signed-by=/etc/apt/keyrings/meshtastic-deb.asc] https://meshtastic.github.io/deb stable main" | tee /etc/apt/sources.list.d/meshtastic-deb.list >/dev/null
echo "Removing netdevice rules..."
ln -s /dev/null /etc/udev/rules.d/80-net-setup-link.rules
echo "Setting up kernel modules..."
touch /lib/modules/5.10.160/modules.order
touch /lib/modules/5.10.160/modules.builtin
depmod -a 5.10.160
if [[ $? -eq 2 ]]; then echo "Error, step failed..."; fi
echo "Setting localtime to UTC..."
rm /etc/localtime
ln -sf /usr/share/zoneinfo/UTC /etc/localtime
echo "Installing packages..."
apt update
DEBIAN_FRONTEND=noninteractive apt install -y --option Dpkg::Options::="--force-confold" linux-firmware wireless-tools git python3.10-venv libgpiod-dev libyaml-cpp-dev libbluetooth-dev openssl libssl-dev libulfius-dev liborcania-dev evtest screen avahi-daemon protobuf-compiler telnet fonts-noto-color-emoji ninja-build chrony qrencode software-properties-common python-is-python3 python3.10-venv lsof spi-tools python3-luma.oled
DEBIAN_FRONTEND=noninteractive apt install -y --option Dpkg::Options::="--force-confold" linux-firmware wireless-tools git python3.10-venv libgpiod-dev libyaml-cpp-dev libbluetooth-dev openssl libssl-dev libulfius-dev liborcania-dev evtest screen avahi-daemon protobuf-compiler telnet fonts-noto-color-emoji ninja-build chrony qrencode software-properties-common python-is-python3 python3.10-venv lsof spi-tools python3-luma.oled samba
if [[ $? -eq 2 ]]; then echo "Error, step failed..."; fi
DEBIAN_FRONTEND=noninteractive apt upgrade -y --option Dpkg::Options::="--force-confold"
@ -42,16 +38,13 @@ pip3 install requests pyephem pytap2 meshtastic pypubsub geopy maidenhead beauti
if [[ $? -eq 2 ]]; then echo "Error, step failed..."; fi
echo "Setting MOTD..."
mv /etc/update-motd.d/10-help-text /etc/update-motd.d/10-help-text.bak
mv /etc/update-motd.d/60-unminimize /etc/update-motd.d/60-unminimize.bak
echo "Setting hostname to femtofox..."
echo "femtofox" | tee /etc/hostname > /dev/null
echo "Configuring autostart of systemd services..."
systemctl enable button
systemctl enable meshtasticd
systemctl enable femto-runonce.service
@ -59,6 +52,7 @@ systemctl enable femto-usb-config-tool.service
systemctl enable femto-boot-complete.service
systemctl enable wifi-mesh-control
systemctl disable smbd nmbd # samba services, can be enabled via menu
systemctl disable NetworkManager
systemctl disable NetworkManager-dispatcher
systemctl disable NetworkManager-wait-online
@ -77,7 +71,6 @@ systemctl disable veritysetup.target
systemctl disable systemd-pstore.service
echo "Adding femto and pico users/groups..."
groupmod -n femto pico
usermod -l femto pico
usermod -aG sudo,input femto
@ -85,7 +78,6 @@ echo "femto ALL=(ALL:ALL) ALL" | tee /etc/sudoers.d/femto > /dev/null
chmod 440 /etc/sudoers.d/femto
# this seems messy, user:group should be set cleanly and not corrected after? OSC: somethings were owned my pico from factory
find / -group pico -exec chgrp femto {} \; 2>/dev/null
find / -user pico -exec chown femto {} \; 2>/dev/null
usermod -d /home/femto -m femto
@ -96,6 +88,5 @@ usermod -a -G tty femto
usermod -a -G dialout femto
echo "Cleaning up chroot..."
apt clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* && rm -rf /var/tmp/* && find /var/log -type f -exec truncate -s 0 {} + && : > /root/.bash_history && history -c
exit

View file

@ -0,0 +1,253 @@
#
# Sample configuration file for the Samba suite for Debian GNU/Linux.
#
#
# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options most of which
# are not shown in this example
#
# Some options that are often worth tuning have been included as
# commented-out examples in this file.
# - When such options are commented with ";", the proposed setting
# differs from the default Samba behaviour
# - When commented with "#", the proposed setting is the default
# behaviour of Samba but the option is considered important
# enough to be mentioned here
#
# NOTE: Whenever you modify this file you should run the command
# "testparm" to check that you have not made any basic syntactic
# errors.
#======================= Global Settings =======================
[global]
## Browsing/Identification ###
# Change this to the workgroup/NT-domain name your Samba server will part of
workgroup = WORKGROUP
# server string is the equivalent of the NT Description field
server string = %h server (Samba, Ubuntu)
#### Networking ####
# The specific set of interfaces / networks to bind to
# This can be either the interface name or an IP address/netmask;
# interface names are normally preferred
; interfaces = 127.0.0.0/8 eth0
# Only bind to the named interfaces and/or networks; you must use the
# 'interfaces' option above to use this.
# It is recommended that you enable this feature if your Samba machine is
# not protected by a firewall or is a firewall itself. However, this
# option cannot handle dynamic or non-broadcast interfaces correctly.
; bind interfaces only = yes
#### Debugging/Accounting ####
# This tells Samba to use a separate log file for each machine
# that connects
log file = /var/log/samba/log.%m
# Cap the size of the individual log files (in KiB).
max log size = 1000
# We want Samba to only log to /var/log/samba/log.{smbd,nmbd}.
# Append syslog@1 if you want important messages to be sent to syslog too.
logging = file
# For more verbose logging:
; log level = 3
# Do something sensible when Samba crashes: mail the admin a backtrace
panic action = /usr/share/samba/panic-action %d
####### Authentication #######
# Server role. Defines in which mode Samba will operate. Possible
# values are "standalone server", "member server", "classic primary
# domain controller", "classic backup domain controller", "active
# directory domain controller".
#
# Most people will want "standalone server" or "member server".
# Running as "active directory domain controller" will require first
# running "samba-tool domain provision" to wipe databases and create a
# new domain.
server role = standalone server
obey pam restrictions = yes
# This boolean parameter controls whether Samba attempts to sync the Unix
# password with the SMB password when the encrypted SMB password in the
# passdb is changed.
unix password sync = yes
# For Unix password sync to work on a Debian GNU/Linux system, the following
# parameters must be set (thanks to Ian Kahan <<kahan@informatik.tu-muenchen.de> for
# sending the correct chat script for the passwd program in Debian Sarge).
passwd program = /usr/bin/passwd %u
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
# This boolean controls whether PAM will be used for password changes
# when requested by an SMB client instead of the program listed in
# 'passwd program'. The default is 'no'.
pam password change = yes
# This option controls how unsuccessful authentication attempts are mapped
# to anonymous connections
map to guest = bad user
########## Domains ###########
#
# The following settings only takes effect if 'server role = classic
# primary domain controller', 'server role = classic backup domain controller'
# or 'domain logons' is set
#
# It specifies the location of the user's
# profile directory from the client point of view) The following
# required a [profiles] share to be setup on the samba server (see
# below)
; logon path = \\%N\profiles\%U
# Another common choice is storing the profile in the user's home directory
# (this is Samba's default)
# logon path = \\%N\%U\profile
# The following setting only takes effect if 'domain logons' is set
# It specifies the location of a user's home directory (from the client
# point of view)
; logon drive = H:
# logon home = \\%N\%U
# The following setting only takes effect if 'domain logons' is set
# It specifies the script to run during logon. The script must be stored
# in the [netlogon] share
# NOTE: Must be store in 'DOS' file format convention
; logon script = logon.cmd
# This allows Unix users to be created on the domain controller via the SAMR
# RPC pipe. The example command creates a user account with a disabled Unix
# password; please adapt to your needs
; add user script = /usr/sbin/adduser --quiet --disabled-password --gecos "" %u
# This allows machine accounts to be created on the domain controller via the
# SAMR RPC pipe.
# The following assumes a "machines" group exists on the system
; add machine script = /usr/sbin/useradd -g machines -c "%u machine account" -d /var/lib/samba -s /bin/false %u
# This allows Unix groups to be created on the domain controller via the SAMR
# RPC pipe.
; add group script = /usr/sbin/addgroup --force-badname %g
############ Misc ############
# Using the following line enables you to customise your configuration
# on a per machine basis. The %m gets replaced with the netbios name
# of the machine that is connecting
; include = /home/samba/etc/smb.conf.%m
# Some defaults for winbind (make sure you're not using the ranges
# for something else.)
; idmap config * : backend = tdb
; idmap config * : range = 3000-7999
; idmap config YOURDOMAINHERE : backend = tdb
; idmap config YOURDOMAINHERE : range = 100000-999999
; template shell = /bin/bash
# Setup usershare options to enable non-root users to share folders
# with the net usershare command.
# Maximum number of usershare. 0 means that usershare is disabled.
# usershare max shares = 100
# Allow users who've been granted usershare privileges to create
# public shares, not just authenticated ones
usershare allow guests = yes
#======================= Share Definitions =======================
# Un-comment the following (and tweak the other settings below to suit)
# to enable the default home directory shares. This will share each
# user's home directory as \\server\username
;[homes]
; comment = Home Directories
; browseable = no
# By default, the home directories are exported read-only. Change the
# next parameter to 'no' if you want to be able to write to them.
; read only = yes
# File creation mask is set to 0700 for security reasons. If you want to
# create files with group=rw permissions, set next parameter to 0775.
; create mask = 0700
# Directory creation mask is set to 0700 for security reasons. If you want to
# create dirs. with group=rw permissions, set next parameter to 0775.
; directory mask = 0700
# By default, \\server\username shares can be connected to by anyone
# with access to the samba server.
# Un-comment the following parameter to make sure that only "username"
# can connect to \\server\username
# This might need tweaking when using external authentication schemes
; valid users = %S
# Un-comment the following and create the netlogon directory for Domain Logons
# (you need to configure Samba to act as a domain controller too.)
;[netlogon]
; comment = Network Logon Service
; path = /home/samba/netlogon
; guest ok = yes
; read only = yes
# Un-comment the following and create the profiles directory to store
# users profiles (see the "logon path" option above)
# (you need to configure Samba to act as a domain controller too.)
# The path below should be writable by all users so that their
# profile directory may be created the first time they log on
;[profiles]
; comment = Users profiles
; path = /home/samba/profiles
; guest ok = no
; browseable = no
; create mask = 0600
; directory mask = 0700
[printers]
comment = All Printers
browseable = no
path = /var/spool/samba
printable = yes
guest ok = no
read only = yes
create mask = 0700
# Windows clients look for this share name as a source of downloadable
# printer drivers
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
browseable = yes
read only = yes
guest ok = no
# Uncomment to allow remote administration of Windows print drivers.
# You may need to replace 'lpadmin' with the name of the group your
# admin users are members of.
# Please note that you also need to set appropriate Unix permissions
# to the drivers directory for these users to have write rights in it
; write list = root, @lpadmin
[home]
path = /home/femto
browseable = yes
writable = yes
read only = no
create mask = 0775
directory mask = 0775
valid users = femto

View file

@ -13,11 +13,18 @@ if ! grep -qE '^first_boot=true' /etc/femto.conf; then # if not the first boot
export LANG=C.UTF-8
dialog --title "Femtofox run once utility" --yesno "\
This does not appear to be this system's first boot.\n\
Re-running this script will resize the filesystem to fit the SD card, allocate a swap file, add RTC support, add terminal type to .bashrc, set the eth0 MAC address to be derivative of the CPU serial number and then reboot.\n\
\n\
Re-running this script will:\n\
* Resize filesystem to fit the SD card\n\
* Allocate the swap file\n\
* Add terminal type to user femto's .bashrc\n\
* Set the eth0 MAC to be derivative of CPU serial number\n\
\n\
Finally, the Femtofox will reboot.\n\
\n\
Re-running this script after first boot should not cause any harm, but may not work as expected.\n\
\n\
Proceed?" 15 60
Proceed?" 19 60
if [ $? -eq 1 ]; then #if cancel/no
exit 0
fi
@ -35,26 +42,24 @@ echo -e "\e[32m******* First boot *******\e[0m"
done
) &
# Disable LED to prevent boot codes from showing during this boot
#sh -c "echo 34 > /sys/class/gpio/unexport"
# Perform filesystem resize
log_message "Resizing filesystem. This can take up to 10 minutes, depending on microSD card size and speed"
sudo resize2fs /dev/mmcblk1p5
sudo resize2fs /dev/mmcblk1p6
sudo resize2fs /dev/mmcblk1p7
log_message "Resizing filesystem. This can take several minutes, depending on microSD card size and speed"
resize2fs /dev/mmcblk1p5
resize2fs /dev/mmcblk1p6
resize2fs /dev/mmcblk1p7
log_message "Resizing filesystem complete"
# allocate swap file
if [ ! -f /swapfile ]; then # check if swap file already exists
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile > /dev/null
sudo swapon /swapfile > /dev/null
log_message "Allocating swap file. This can take up to 10 minutes, depending on microSD card speed"
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile > /dev/null
swapon /swapfile > /dev/null
echo '/swapfile none swap sw 0 0' | tee -a /etc/fstab > /dev/null
# touch /etc/.filesystem_swap # no longer used
log_message "Swap file allocated."
else
log_message "Swap file already allocated, skipping."
log_message "Swap file already allocated, skipping"
fi
# add RTC support - looks unneeded?
@ -62,16 +67,17 @@ fi
#log_message "Added ds1307/ds3231 RTC support."
# prevent randomized mac address for eth0. If `eth0`` is already present in /etc/network/interfaces, skip
mac="$(awk '/Serial/ {print $3}' /proc/cpuinfo | tail -c 11 | sed 's/^\(.*\)/a2\1/' | sed 's/\(..\)/\1:/g;s/:$//')"
if ! grep -q "eth0" /etc/network/interfaces; then
log_message "Setting eth0 MAC address to derivative of CPU s/n."
log_message "Setting eth0 MAC address to $mac (derivative of CPU s/n)"
cat <<EOF >> /etc/network/interfaces
# static mac address for onboard ethernet (castellated pins)
allow-hotplug eth0
iface eth0 inet dhcp
hwaddress ether $(awk '/Serial/ {print $3}' /proc/cpuinfo | tail -c 11 | sed 's/^\(.*\)/a2\1/' | sed 's/\(..\)/\1:/g;s/:$//')
hwaddress ether $mac
EOF
else
log_message "eth0 already exists in /etc/network/interfaces, skipping."
log_message "eth0 already exists in /etc/network/interfaces, skipping"
fi
# Add term stuff to .bashrc
@ -85,17 +91,8 @@ else
echo "TERM, LANG and NCURSES_NO_UTF8_ACS already present in .bashrc, skipping"
fi
# set meshtastic nodeid to derivative of CPU serial number (unique to this board)
#seed=$(sed -n '/Serial/ s/^.*: \(.*\)$/\U\1/p' /proc/cpuinfo | bc | tail -c 9)
#seed=$((0x$(awk '/Serial/ {print $3}' /proc/cpuinfo) & 0x3B9AC9FF)) #alternate method for generating seed - not in use
#sed -i "s|^ExecStart=/usr/sbin/meshtasticd.*|ExecStart=/usr/sbin/meshtasticd -h $seed|" /usr/lib/systemd/system/meshtasticd.service
#log_message "Using Luckfox CPU S/N to generate nodeid for Meshtastic."
#systemctl daemon-reload
#systemctl enable meshtasticd
#systemctl restart meshtasticd
# remove first boot flag
sed -i -E 's/^first_boot=.*/first_boot=false/' /etc/femto.conf
log_message "Removing first boot flag and rebooting in 5 seconds..."
sleep 5
reboot
reboot

View file

@ -11,10 +11,9 @@ install() {
echo "Installing $($package_dir/$1.sh -N)..."
# Run the installation script, capturing the output and displaying it in real time
output=$($package_dir/$1.sh -i)
echo $output
install_status=$? # Capture the exit status of the eval command
user_message=$(echo "$output" | awk '/user_message: / {found=1; split($0, arr, "user_message: "); print arr[2]; next} found {print}' | sed '/^$/q') # grab the user_message, if present
#output=$(echo -e "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
output=$(echo -e "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
if [ $install_status -eq 0 ]; then # if the installation was successful
dialog --no-collapse --colors --title "$title" --beep --msgbox "\ZuInstallation of $($package_dir/$1.sh -N) successful!\Zn$([ -n "$user_message" ] && echo "\n\n$user_message")\n\nLog:\n$(echo $output)" 0 0 # if there's a user_message, display it with two preceeding line breaks
@ -24,7 +23,7 @@ install() {
}
uninstall() {
dialog --no-collapse --title "$title" --yesno "\nUninstall $1\n\nProceed?" 10 40
dialog --no-collapse --title "$title" --yesno "\nUninstall $($package_dir/$1.sh -N)\n\nProceed?" 10 40
if [ $? -eq 1 ]; then #if cancel/no
return 1
fi
@ -32,16 +31,31 @@ uninstall() {
output=$(eval "$package_dir/$1.sh -u 2>&1 | tee /dev/tty")
install_status=$? # Capture the exit status of the eval command
user_message=$(echo "$output" | awk '/user_message: / {found=1; split($0, arr, "user_message: "); print arr[2]; next} found {print}' | sed '/^$/q') # grab the user_message, if present
#output=$(echo "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
output=$(echo "$output" | sed '/user_message: /,$d') # remove the user message from the detailed output
if [ $install_status -eq 0 ]; then # if the installation was successful
dialog --no-collapse --colors --title "$title" --beep --msgbox "\n\ZuUninstallation of $($package_dir/$1.sh -N) successful!\Zn$([ -n "$user_message" ] && echo "\n\n$user_message")\n\nLog:\n$(echo -e "$output")" 0 0 # if there's a user_message, display it with two preceeding line breaks
else
dialog --no-collapse --colors --title "$title" --beep --msgbox "\n\ZuUninstallation of $($package_dir/$1.sh -N) FAILED!\Zn\n\n$user_message\n\nLog:\n$(echo "$output")" 0 0 # if there's a user_message, display it with two preceeding line breaks
fi
fi
}
initialize() {
dialog --no-collapse --title "$title" --yesno "\nIntialize $($package_dir/$1.sh -N)\n\nInitialization runs commands that require user interaction and so can only be run from terminal.\n\nProceed?" 13 50
if [ $? -eq 1 ]; then #if cancel/no
return 1
fi
clear
echo "Initializing $($package_dir/$1.sh -N)..."
eval "$package_dir/$1.sh -a"
if [ $? -eq 0 ]; then # if the installation was successful
dialog --no-collapse --colors --title "$title" --beep --msgbox "\nInitialization of $($package_dir/$1.sh -N) successful!" 8 50 # if there's a user_message, display it with two preceeding line breaks
else
dialog --no-collapse --colors --title "$title" --beep --msgbox "\nInitialization of $($package_dir/$1.sh -N) FAILED!" 8 50 # if there's a user_message, display it with two preceeding line breaks
fi
}
upgrade() {
dialog --no-collapse --title "$title" --yesno "\nUpgrade $1\n\nProceed?" 10 40
dialog --no-collapse --title "$title" --yesno "\nUpgrade $($package_dir/$1.sh -N)\n\nProceed?" 10 40
if [ $? -eq 1 ]; then #if cancel/no
return 1
fi
@ -55,7 +69,6 @@ upgrade() {
else
dialog --no-collapse --colors --title "$title" --beep --msgbox "\n\ZuUpgrade of $($package_dir/$1.sh -N) FAILED!\Zn\n\n$user_message\n\nLog:\n$output" 0 0 # if there's a user_message, display it with two preceeding line breaks
fi
}
@ -68,7 +81,7 @@ package_intro() {
$(if $package_dir/$1.sh -O | grep -q 'A'; then echo -e "by $($package_dir/$1.sh -A)"; fi)\n\
$(if $package_dir/$1.sh -O | grep -q 'D'; then echo "\n$($package_dir/$1.sh -D)"; fi)\n\
\n\
$(echo "Currently: " && $package_dir/$1.sh -I && echo "\Zuinstalled\Zn" || echo " \Zunot installed\Zn")\n\
$(echo "Currently: " && $package_dir/$1.sh -I && echo "\Zuinstalled\Zn" || echo "\Zunot installed\Zn")\n\
$(if output=$($package_dir/$1.sh -L); [ -n "$output" ]; then echo "Installs to: \Zu$output\Zn\n"; fi)\
$(if output=$($package_dir/$1.sh -C); [ -n "$output" ]; then echo "Conflicts with: \Zu$output\Zn\n"; fi)\
An internet connection is required for installation.\n\
@ -81,17 +94,18 @@ package_menu() {
while true; do
echo "Loading package menu..."
# for each line, check if it's supported by the package, display it if the current install state of the package is appropriate (example: don't display "install" if the package is already installed, don't display "stop service" for a package with no services)
choice=$(dialog --no-collapse --title "$title" --cancel-label "Back" --default-item "$choice" --menu "$($package_dir/$1.sh -N)" 17 45 5 \
choice=$(dialog --no-collapse --title "$title" --cancel-label "Back" --default-item "$choice" --menu "$($package_dir/$1.sh -N)" 18 45 5 \
$(if $package_dir/$1.sh -O | grep -q 'l' && $package_dir/$1.sh -I; then echo "Run software x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'i' && ! $package_dir/$1.sh -I; then echo "Install x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'u' && $package_dir/$1.sh -I; then echo "Uninstall x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'a' && $package_dir/$1.sh -I; then echo "Initialize x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'g' && $package_dir/$1.sh -I; then echo "Upgrade x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'e' && $package_dir/$1.sh -I; then echo "Enable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'd' && $package_dir/$1.sh -I; then echo "Disable service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 's' && $package_dir/$1.sh -I; then echo "Stop service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'r' && $package_dir/$1.sh -I; then echo "Start/restart service x"; fi) \
$(if $package_dir/$1.sh -O | grep -q 'S' && $package_dir/$1.sh -I; then echo "Get service status x"; fi) \
"" "" \
" " "" \
"Back to software manager" "" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
@ -105,42 +119,51 @@ package_menu() {
"Run software") eval "$package_dir/$1.sh -l" ;;
"Install") install $1 ;;
"Uninstall") uninstall $1 ;;
"Initialize") initialize $1 ;;
"Upgrade") upgrade $1 ;;
"Enable service") eval "$package_dir/$1.sh -e" ;;
"Disable service") eval "$package_dir/$1.sh -d" ;;
"Stop service") eval "$package_dir/$1.sh -s" ;;
"Start/restart service") eval "$package_dir/$1.sh -r" ;;
"Get service status") dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Enable service") echo "Enabling and starting service..." && eval "$package_dir/$1.sh -e" && eval "$package_dir/$1.sh -r" ;;
"Disable service") echo "Disabling and stopping service..." && eval "$package_dir/$1.sh -d" && eval "$package_dir/$1.sh -s" ;;
"Stop service") echo "Stopping service..." && eval "$package_dir/$1.sh -s" ;;
"Start/restart service") echo "Starting/restarting service..." && eval "$package_dir/$1.sh -r" ;;
"Get service status") echo "Getting service status..." && dialog --no-collapse --title "$title" --msgbox "$(eval "$package_dir/$1.sh -S")" 0 0 ;;
"Back to software manager") break ;;
esac
done
}
# generate menu from filenames in /usr/local/bin/packages
while true; do
title="$title"
software_option=$(dialog --no-collapse --cancel-label "Back" --default-item "$software_option" --menu "$title" 0 0 6 \
1 "The Comms Channel BBS, TC²BBS" \
2 "Contact (Meshtastic client)" \
3 "Meshing Around by Spud" \
4 "Mosquitto MQTT Broker" \
5 "Mosquitto MQTT Client" \
" " ""\
6 "Back to Main Menu" 3>&1 1>&2 2>&3)
menu_entries=()
index=1
for file in /usr/local/bin/packages/*.sh; do
filename=$(basename "$file" .sh)
[[ "$filename" == "package_template" ]] && continue # skip package_template.sh
menu_entries+=("$index" "$(/usr/local/bin/packages/"$filename".sh -N)")
((index++))
done
menu_entries+=(" " "") # add blank line and "Back to Main Menu" entry
menu_entries+=("$index" "Back to main menu")
software_option=$(dialog --no-collapse --cancel-label "Back" --default-item "$software_option" --menu "$title" $((9 + index)) 50 $((index + 1)) "${menu_entries[@]}" 3>&1 1>&2 2>&3)
exit_status=$? # This line checks the exit status of the dialog command
if [ $exit_status -ne 0 ]; then # Exit the loop if the user selects "Cancel" or closes the dialog
break
fi
case $software_option in
1) package_intro "tc2_bbs" ;;
2) package_intro "contact_client" ;;
3) package_intro "meshing_around" ;;
4) package_intro "mosquitto_mqtt_broker" ;;
5) package_intro "mosquitto_mqtt_client" ;;
6) break ;;
esac
case_block=" case \$software_option in"
index=1
for file in /usr/local/bin/packages/*.sh; do
filename=$(basename "$file" .sh)
[[ "$filename" == "package_template" ]] && continue # skip package_template.sh
case_block+="
$index) package_intro \"$filename\" ;;"
((index++))
done
case_block+="
$index) break ;;
esac" #add return to main menu option
eval "$case_block" # Execute the generated case statement
done
exit 0

View file

@ -48,7 +48,7 @@ name="Contact" # software name
author="pdxlocations" # software author - OPTIONAL
description="A Text-Based Console UI for Meshtastic Nodes.\nAfter install, run \`contact\` to launch." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/pdxlocations/contact/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuglNADUOLIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuglNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="python /opt/contact/main.py --host" # command to launch software, if applicable
service_name="" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/contact" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -85,7 +85,9 @@ $launch" | sudo tee /usr/local/bin/contact > /dev/null
# uninstall script
uninstall() {
rm -rf $location
echo "Removed \`$location\`."
rm /usr/local/bin/contact
echo "Removed \`contact\` shortcut."
echo "user_message: All files removed."
exit 0 # should be `exit 1` if the installation failed
}

View file

@ -19,6 +19,7 @@ Arguments:
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
@ -52,7 +53,7 @@ name="Meshing Around" # software name
author="Spud" # software author - OPTIONAL
description="Meshing Around is a feature-rich bot designed to enhance your Meshtastic network experience with a variety of powerful tools and fun features. Connectivity and utility through text-based message delivery. Whether you're looking to perform network tests, send messages, or even play games, mesh_bot.py has you covered." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/SpudGunMan/meshing-around" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrNADUOSLCIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuagedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mesh_bot pong_bot mesh_bot_reporting" # the name of the service, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/meshing-around" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -65,16 +66,13 @@ install() {
exit 1
fi
if [ "$interactive" = "true" ]; then #interactive install
"$location/install.sh" | tee /dev/tty
echo "user_message: To change settings, run \`sudo nano $location/config.ini\`"
exit 0
interactive_init
else
echo "user_message: IMPORTANT: To complete installation, run \`sudo $location/install.sh\`\nTo change settings, run \`sudo nano $location/config.ini\`"
exit 0
fi
}
# uninstall script
uninstall() {
# stop, disable and remove the service, reload systemctl daemon, remove the installation directory and quit
@ -96,6 +94,12 @@ uninstall() {
exit 0
}
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
"$location/install.sh" | tee /dev/tty
echo "user_message: To change settings, run \`sudo nano $location/config.ini\`"
exit 0
}
#upgrade script
upgrade() {
@ -129,6 +133,9 @@ while getopts ":h$options" opt; do
i) # Option -i (install)
install
;;
a) # Option -a (interactive initialization)
interactive_init
;;
u) # Option -u (uninstall)
uninstall
;;

View file

@ -53,17 +53,18 @@ name="Mosquitto MQTT Broker" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedslNADUOSLCIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="mosquitto" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="mosquitto" # apt package name, if applicable
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt-get install mosquitto -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
DEBIAN_FRONTEND=noninteractive apt-get install $package_name -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt install failed. Is internet connected?"; exit 1; }
echo "user_message: Installation requires more setup. For a guide, see https://docs.vultr.com/how-to-install-mosquitto-mqtt-broker-on-ubuntu-24-04"
exit 0 # should be `exit 1` if operation failed
}
@ -71,7 +72,7 @@ install() {
# uninstall script
uninstall() {
DEBIAN_FRONTEND=noninteractive apt remove -y mosquitto 2>&1 | tee /dev/tty
DEBIAN_FRONTEND=noninteractive apt remove -y $package_name 2>&1 | tee /dev/tty
/usr/local/bin/mosquitto_mqtt_broker.sh -s # stop service
/usr/local/bin/mosquitto_mqtt_broker.sh -d # disable service
echo "user_message: Some files may remain on system. To remove, run \`sudo apt remove --purge mosquitto -y\` and \`sudo apt autoremove -y\`."
@ -82,14 +83,14 @@ uninstall() {
#upgrade script
upgrade() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt upgrade -y mosquitto 2>&1 | tee /dev/tty
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
DEBIAN_FRONTEND=noninteractive apt upgrade -y $package_name 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt upgrade failed. Is internet connected?"; exit 1; }
exit 0 # should be `exit 1` if operation failed
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
if dpkg -l | grep -q mosquitto; then
if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
exit 0
else
exit 1

View file

@ -53,17 +53,18 @@ name="Mosquitto MQTT Client" # software name
author="Eclipse Foundation" # software author - OPTIONAL
description="Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.\n\nThe MQTT protocol provides a lightweight method of carrying out messaging using a publish/subscribe model. This makes it suitable for Internet of Things messaging such as with low power sensors or mobile devices such as phones, embedded computers or microcontrollers.\n\nThe Mosquitto project also provides a C library for implementing MQTT clients, and the very popular mosquitto_pub and mosquitto_sub command line MQTT clients.\n\nMosquitto is part of the Eclipse Foundation, and is an iot.eclipse.org project. The development is driven by Cedalo." # software description - OPTIONAL (but strongly recommended!)
URL="https://mosquitto.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedslNADUOSLCIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
package_name="mosquitto-clients" # apt package name, if applicable
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt-get install mosquitto-clients -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
DEBIAN_FRONTEND=noninteractive apt-get install $package_name -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt install failed. Is internet connected?"; exit 1; }
echo "user_message: Installation requires more setup. For a guide, see https://docs.vultr.com/how-to-install-mosquitto-mqtt-broker-on-ubuntu-24-04"
exit 0 # should be `exit 1` if operation failed
}
@ -80,14 +81,14 @@ uninstall() {
#upgrade script
upgrade() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
DEBIAN_FRONTEND=noninteractive apt upgrade -y mosquitto-clients 2>&1 | tee /dev/tty
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
DEBIAN_FRONTEND=noninteractive apt upgrade -y $package_name 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt upgrade failed. Is internet connected?"; exit 1; }
exit 0 # should be `exit 1` if operation failed
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
if dpkg -l | grep -q mosquitto-clients; then
if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
exit 0
else
exit 1

View file

@ -10,7 +10,7 @@ if [ $# -eq 0 ]; then
fi
args="$@" # arguments to this script
interaction="true"
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
@ -19,6 +19,7 @@ Arguments:
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
@ -48,32 +49,36 @@ EOF
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
name="name" # software name
author="author" # software author - OPTIONAL
description="description" # software description - OPTIONAL (but strongly recommended!)
URL="URL" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrlNADUOSLCIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiuagedsrlNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="service_name" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
package_name="apt_package" # apt package name, if applicable. Can be multiple packages separated by spaces, but if at least one is installed the package will show as "installed" even if the others aren't
location="/opt/location" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
conflicts="package name, other package name" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
# for apt packages, this method allows onscreen output during install:
# DEBIAN_FRONTEND=noninteractive sudo apt-get install mosquitto -y 2>&1 | tee /dev/tty # allows output to be shown onscreen
# DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty || { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
# DEBIAN_FRONTEND=noninteractive apt-get install $package_name -y 2>&1 | tee /dev/tty || { echo "user_message: apt install failed. Is internet connected?"; exit 1; }
echo "user_message: Exit message to user, displayed prominently in post-install"
exit 0 # should be `exit 1` if operation failed
}
# uninstall script
uninstall() {
echo "user_message: Exit message to user, displayed prominently in post-install"
exit 0 # should be `exit 1` if operation failed
}
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
exit 0 # should be `exit 1` if operation failed
}
# upgrade script
upgrade() {
@ -91,7 +96,7 @@ check() {
fi
# this works for apt packages
if [ dpkg -l | grep -q package-name ] ; then
if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
exit 0
else
exit 1
@ -112,6 +117,9 @@ while getopts ":h$options" opt; do
u) # Option -u (uninstall)
uninstall
;;
a) # Option -a (interactive initialization)
interactive_init
;;
g) # Option -g (upgrade)
upgrade
;;

View file

@ -0,0 +1,167 @@
#!/bin/bash
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root. Try \`sudo\`."
exit 1
fi
if [ $# -eq 0 ]; then
echo "No arguments provided."
echo -e "$help"
exit 1
fi
args="$@" # arguments to this script
interactive="true"
help=$(cat <<EOF
Arguments:
-h This message
Environment - must be first argument:
-x User UI is not terminal (script interaction unavailable)
Actions:
-i Install
-u Uninstall
-a Interactive initialization script: code that must be run to initialize the installation prior to use, but can only be run from terminal
-g Upgrade
-e Enable service, if applicable
-d Disable service, if applicable
-s Stop service
-r Start/Restart
-l Command to run software
Information:
-N Get name
-A Get author
-D Get description
-U Get URL
-O Get options supported by this script
-S Get service status
-L Get Install location
-C Get Conflicts
-I Check if installed. Returns an error if not installed
EOF
)
### For package maintainer:
# Fill the following fields and choose the options that are in use by this package
# Populate the install, uninstall and upgrade functions
# Remember that this script may be launched in terminal, via web UI or another method, so inputs aren't really possible
# Arguments to the script are stored in $args
# This system supports both interactive and non-interactive installs. For non-interactive installs, $interaction="false". In this cause special instructions to the user should be given as user_message, such as `After installation, edit /opt/software/config.ini`
# Successful operations should `exit 0`, fails should `exit 1`
# Messages to the user (such as configuration instructions, explanatory error messages, etc) should be given as: `echo "user_message: text"`
# Everything following `user_message: ` will be displayed prominently to the user, so it must the last thing echoed
user_message="To connect to network share, enter \`\\\\femtofox\\home\` from Windows, \`smb://$(hostname)\\home\` from MacOS or \`smbclient //$(hostname)/femto -U femto\` from Linux.\nDefault configuration shares /home/femto. Edit \`/etc/samba/smb.conf\` to add other shares.\n\nTroubleshooting: if Windows refuses to connect, especially after succeeding previously, hit [win]+R and enter \`net use * /delete\`."
init_instructions="To enable file sharing, run \`Initialize\` in the femto-config Samba menu, or enable the Samba service, run \`sudo smbpasswd -a femto\` to set a Samba password, and then restart the Samba service."
name="Samba File Sharing" # software name
author="Software Freedom Conservancy" # software author - OPTIONAL
description="Femtofox comes with Samba preinstalled but disabled. $init_instructions\n\n$user_message" # software description - OPTIONAL (but strongly recommended!)
URL="https://www.samba.org/" # software URL. Can contain multiple URLs - OPTIONAL
options="xiuagedsrNADUOSCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="" # command to launch software, if applicable
service_name="smbd nmbd" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
package_name="samba" # apt package name, if applicable
conflicts="" # comma delineated plain-text list of packages with which this package conflicts. Blank if none. Use the name as it appears in the $name field of the other package. Extra plaintext is allowed, such as "packageA, packageB, any other software that uses the Meshtastic CLI"
# install script
install() {
echo "apt update can take a long while..."
# DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
# DEBIAN_FRONTEND=noninteractive apt-get install $package_name -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt install failed. Is internet connected?"; exit 1; }
if [ "$interactive" = "true" ]; then # interactive install
interactive_init
else # noninteractive installation (such as web-UI)
echo -e "user_message: IMPORTANT: $init_instructions\n\n$user_message"
exit 0 # should be `exit 1` if operation failed
fi
}
# uninstall script
uninstall() {
DEBIAN_FRONTEND=noninteractive apt remove -y $package_name 2>&1 | tee /dev/tty
echo "Removing unused dependencies..."
DEBIAN_FRONTEND=noninteractive apt autoremove -y $package_name 2>&1 | tee /dev/tty
echo "user_message: Some files may remain on system. To remove, run \`sudo apt remove --purge $package_name -y\` and \`sudo apt autoremove -y\`."
exit 0 # should be `exit 1` if operation failed
}
# code that must be run to initialize the installation prior to use, but can only be run from terminal
interactive_init() {
echo -e "\nSet user \`Femto\` login password:"
smbpasswd -a femto
/usr/local/bin/packages/samba.sh -e
/usr/local/bin/packages/samba.sh -r
echo -e "user_message: Samba initialized, and service enabled and started. $user_message"
exit 0
}
#upgrade script
upgrade() {
echo "apt update can take a long while..."
DEBIAN_FRONTEND=noninteractive apt-get update -y 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt update failed. Is internet connected?"; exit 1; }
DEBIAN_FRONTEND=noninteractive apt upgrade -y $package_name 2>&1 | tee /dev/tty | grep -q "Err" && { echo "user_message: apt upgrade failed. Is internet connected?"; exit 1; }
exit 0 # should be `exit 1` if operation failed
}
# Check if already installed. `exit 0` if yes, `exit 1` if no
check() {
if dpkg-query -W -f='${Status}' $package_name 2>/dev/null | grep -q "install ok installed"; then
exit 0
else
exit 1
fi
}
while getopts ":h$options" opt; do
case ${opt} in
h) # Option -h (help)
echo -e "$help"
;;
x) # Option -x (no user interaction available)
interaction="false"
;;
i) # Option -i (install)
install
;;
a) # Option -a (interactive initialization)
interactive_init
;;
u) # Option -u (uninstall)
uninstall
;;
g) # Option -g (upgrade)
upgrade
;;
e) # Option -e (Enable service, if applicable)
systemctl enable $service_name
;;
d) # Option -d (Disable service, if applicable)
systemctl disable $service_name
;;
s) # Option -s (Stop service)
systemctl stop $service_name
;;
r) # Option -r (Start/Restart)
systemctl restart $service_name
;;
l) # Option -l (Run software)
echo "Launching $name..."
sudo -u ${SUDO_USER:-$(whoami)} $launch
;;
N) echo -e $name ;;
A) echo -e $author ;;
D) echo $description ;;
U) echo -e $URL ;;
O) echo -e $options ;;
S) # Option -S (Get service status)
systemctl status $service_name
;;
L) echo -e $location ;;
C) echo -e $conflicts ;;
I) # Option -I (Check if already installed)
check
;;
esac
done
exit 0

View file

@ -53,7 +53,7 @@ name="TC2-BBS" # software name
author="The Comms Channel" # software author - OPTIONAL
description="The TC²-BBS system integrates with Meshtastic devices. The system allows for message handling, bulletin boards, mail systems, and a channel directory." # software description - OPTIONAL (but strongly recommended!)
URL="https://github.com/TheCommsChannel/TC2-BBS-mesh" # software URL. Can contain multiple URLs - OPTIONAL
options="xiugedsrlNADUOSLCIto" # script options in use by software package. For example, for a package with no service, exclude `edsr`
options="xiugedsrNADUOSLCI" # script options in use by software package. For example, for a package with no service, exclude `edsr`
launch="python /opt/TC2-BBS-mesh/server.py" # command to launch software, if applicable
service_name="mesh-bbs" # the name of the service/s, such as `chrony`. REQUIRED if service options are in use. If multiple services, separate by spaces "service1 service2"
location="/opt/TC2-BBS-mesh" # install location REQUIRED if not apt installed. Generally, we use `/opt/software-name`
@ -93,7 +93,9 @@ uninstall() {
systemctl stop $service_name
rm /etc/systemd/system/$service_name.service
systemctl daemon-reload
echo "Disabled and removed \`$service_name\` service."
rm -rf $location
echo "Removed \`$location\`."
echo "user_message: Service removed, all files deleted."
exit 0
}