16078 lines
660 KiB
Bash
16078 lines
660 KiB
Bash
#!/bin/bash
|
|
{
|
|
#////////////////////////////////////
|
|
# DietPi Software
|
|
#
|
|
#////////////////////////////////////
|
|
# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
|
|
#
|
|
#////////////////////////////////////
|
|
#
|
|
# Info:
|
|
# - Location: /boot/dietpi/dietpi-software
|
|
# - Installs "ready to run" software with optimisations unique to the device.
|
|
# - Generates and uses /boot/dietpi/.installed listing installed software.
|
|
USAGE='
|
|
Usage: dietpi-software [<command> [<software_id>...]]
|
|
Available commands:
|
|
<empty> Interactive menu to install or uninstall software
|
|
install <software_id>... Install each software given by space-separated list of IDs
|
|
reinstall <software_id>... Reinstall each software given by space-separated list of IDs
|
|
uninstall <software_id>... Uninstall each software given by space-separated list of IDs
|
|
list [--machine-readable] Print a list with IDs and info for all available software titles
|
|
free Print an unused software ID, free for a new software implementation
|
|
' #////////////////////////////////////
|
|
|
|
# Import DietPi-Globals ---------------------------------------------------------------
|
|
. /boot/dietpi/func/dietpi-globals
|
|
readonly G_PROGRAM_NAME='DietPi-Software'
|
|
if [[ $1 != 'list' ]]
|
|
then
|
|
G_CHECK_ROOT_USER "$@"
|
|
G_CHECK_ROOTFS_RW
|
|
G_INIT
|
|
fi
|
|
# Import DietPi-Globals ---------------------------------------------------------------
|
|
|
|
[[ $1 == 'list' && $2 == '--machine-readable' ]] && MACHINE_READABLE=1 || MACHINE_READABLE=
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Install states file
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
Write_InstallFileList()
|
|
{
|
|
# Update webserver stack meta install states
|
|
aSOFTWARE_INSTALL_STATE[75]=0 aSOFTWARE_INSTALL_STATE[76]=0
|
|
aSOFTWARE_INSTALL_STATE[78]=0 aSOFTWARE_INSTALL_STATE[79]=0
|
|
aSOFTWARE_INSTALL_STATE[81]=0 aSOFTWARE_INSTALL_STATE[82]=0
|
|
if (( ${aSOFTWARE_INSTALL_STATE[89]} == 2 ))
|
|
then
|
|
# Apache
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} == 2 ))
|
|
then
|
|
(( ${aSOFTWARE_INSTALL_STATE[87]} == 2 )) && aSOFTWARE_INSTALL_STATE[75]=2 # SQLite: LASP
|
|
(( ${aSOFTWARE_INSTALL_STATE[88]} == 2 )) && aSOFTWARE_INSTALL_STATE[76]=2 # MariaDB: LAMP
|
|
|
|
# Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} == 2 ))
|
|
then
|
|
(( ${aSOFTWARE_INSTALL_STATE[87]} == 2 )) && aSOFTWARE_INSTALL_STATE[78]=2 # SQLite: LESP
|
|
(( ${aSOFTWARE_INSTALL_STATE[88]} == 2 )) && aSOFTWARE_INSTALL_STATE[79]=2 # MariaDB: LEMP
|
|
|
|
# Lighttpd
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} == 2 ))
|
|
then
|
|
(( ${aSOFTWARE_INSTALL_STATE[87]} == 2 )) && aSOFTWARE_INSTALL_STATE[81]=2 # SQLite: LLSP
|
|
(( ${aSOFTWARE_INSTALL_STATE[88]} == 2 )) && aSOFTWARE_INSTALL_STATE[82]=2 # MariaDB: LLMP
|
|
fi
|
|
fi
|
|
|
|
# Save installed states
|
|
local i install_states
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
# Don't save pending and uninstalled states (-1/0/1)
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 ))
|
|
then
|
|
install_states+="aSOFTWARE_INSTALL_STATE[$i]=2
|
|
"
|
|
# Store DietPi-RAMlog and Dropbear uninstalled state as well, as it is initialised as installed matching our image defaults
|
|
elif (( $i == 103 || $i == 104 ))
|
|
then
|
|
install_states+="aSOFTWARE_INSTALL_STATE[$i]=0
|
|
"
|
|
fi
|
|
done
|
|
|
|
# Save logging choice
|
|
install_states+="INDEX_LOGGING=$INDEX_LOGGING"
|
|
|
|
echo "$install_states" > /boot/dietpi/.installed
|
|
}
|
|
|
|
Read_InstallFileList()
|
|
{
|
|
if [[ -f '/boot/dietpi/.installed' ]]
|
|
then
|
|
# shellcheck disable=SC1091
|
|
if [[ $MACHINE_READABLE ]]
|
|
then
|
|
. /boot/dietpi/.installed
|
|
else
|
|
G_EXEC_DESC='Reading database' G_EXEC . /boot/dietpi/.installed
|
|
fi
|
|
else
|
|
# Assure that the file exists to allow choice/preference selections on first run: https://github.com/MichaIng/DietPi/issues/5080
|
|
>> /boot/dietpi/.installed
|
|
fi
|
|
}
|
|
|
|
Check_Net_and_Time_sync()
|
|
{
|
|
# Check network connectivity and sync system clock
|
|
G_CHECK_NET
|
|
/boot/dietpi/func/run_ntpd
|
|
}
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Installation system
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Flag to trigger Run_Installations()
|
|
GOSTARTINSTALL=0
|
|
|
|
# Flag to skip APT update in Run_Installations(), set by DietPi-Automation_Pre()
|
|
SKIP_APT_UPDATE=0
|
|
|
|
# Logging choice index
|
|
INDEX_LOGGING=-1
|
|
|
|
# Array to collect all installed services to be enabled after installs have finished
|
|
aENABLE_SERVICES=()
|
|
# Since no automated reboot is done anymore after installs, collect services to start manually, when not controlled by DietPi-Services
|
|
aSTART_SERVICES=()
|
|
|
|
# Global password for software installs
|
|
GLOBAL_PW=
|
|
Update_Global_Pw()
|
|
{
|
|
# Loop until password is valid or dietpi-set_software fails
|
|
while :
|
|
do
|
|
# Read encrypted password
|
|
if [[ -f '/var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin' ]]
|
|
then
|
|
# In case of error, assure empty password to fallback to default
|
|
GLOBAL_PW=$(openssl enc -d -a -md sha256 -aes-256-cbc -iter 10000 -salt -pass pass:'DietPiRocks!' -in /var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin) || GLOBAL_PW=
|
|
|
|
# Return on valid password
|
|
[[ $GLOBAL_PW && $GLOBAL_PW != 'dietpi' ]] && return 0
|
|
|
|
G_DIETPI-NOTIFY 1 'Global software password failed to be read, is empty, or still the default. Asking to set a new one ...'
|
|
fi
|
|
|
|
# Apply default password as fallback if empty
|
|
[[ $GLOBAL_PW ]] || GLOBAL_PW='dietpi'
|
|
|
|
# In case ask for and apply new valid password
|
|
/boot/dietpi/func/dietpi-set_software password software check || return 1
|
|
done
|
|
}
|
|
|
|
# Total physical system RAM: Used to calculate percentage based value for software cache limits, e.g.: OPcache/APCu
|
|
readonly RAM_PHYS=$(free -m | mawk '/^Mem:/{print $2;exit}')
|
|
# Total RAM + swap space: Used to estimate whether the swap file size needs to be increased.
|
|
readonly RAM_TOTAL=$(free -tm | mawk '/^Total:/{print $2;exit}')
|
|
|
|
# Whether to restart Deluge web UI once, required on fresh installs for auto-connection to work, more precisely a little delay between daemon and web UI is required
|
|
RESTART_DELUGE_WEB=0
|
|
|
|
# PHP version
|
|
case $G_DISTRO in
|
|
6) PHP_VERSION='7.4';;
|
|
7) PHP_VERSION='8.2';;
|
|
*) PHP_VERSION='8.4';;
|
|
esac
|
|
|
|
# Available for [$software_id,$G_*] 2D array
|
|
declare -A aSOFTWARE_AVAIL_G_HW_MODEL
|
|
declare -A aSOFTWARE_AVAIL_G_HW_ARCH
|
|
declare -A aSOFTWARE_AVAIL_G_DISTRO
|
|
|
|
# ToDo: On RPi 4, the 64-bit kernel is now used by default, without "arm_64bit=1" set: https://forums.raspberrypi.com/viewtopic.php?p=2088935#p2088935
|
|
# - We could set "arm_64bit=0", but for now lets assure that 32-bit software is installed and see how it goes. This enables general support for RPi with 64-bit kernel running 32-bit userland.
|
|
# - Also set a little flag here for the "dietpi-software list" command to correctly show that a software title is disabled because of the userland architecture, not because of the kernel architecture.
|
|
RPI_64KERNEL_32OS=
|
|
[[ $G_HW_MODEL == [2-9] && $G_HW_ARCH == 3 && $(dpkg --print-architecture) == 'armhf' ]] && G_HW_ARCH=2 G_HW_ARCH_NAME='armv7l' RPI_64KERNEL_32OS='32-bit image'
|
|
|
|
# Generate arrays for all available software titles
|
|
Software_Arrays_Init()
|
|
{
|
|
[[ $MACHINE_READABLE ]] || G_DIETPI-NOTIFY -2 'Initialising database'
|
|
|
|
#--------------------------------------------------------------------------------
|
|
# Software categories
|
|
# NB: Unique IDs, do not re-arrange or re-order!
|
|
#--------------------------------------------------------------------------------
|
|
readonly aSOFTWARE_CATEGORIES=(
|
|
|
|
# Use "-1" to hide software title from menu
|
|
'●─ Desktops ' #0
|
|
'●─ Remote Desktop ' #1
|
|
'●─ Media Systems ' #2
|
|
'●─ BitTorrent & Download ' #3
|
|
'●─ Cloud & Backup ' #4
|
|
'●─ Gaming & Emulation ' #5
|
|
'●─ Social & Search ' #6
|
|
'●─ Camera & Surveillance ' #7
|
|
'●─ System Stats & Management ' #8
|
|
'●─ Remote Access ' #9
|
|
'●─ Hardware Projects ' #10
|
|
'●─ System Security ' #11
|
|
'●─ Webserver Stacks ' #12
|
|
'●─ DNS Servers ' #13
|
|
'●─ File Servers ' #14
|
|
'●─ VPN Servers ' #15
|
|
'●─ Advanced Networking ' #16
|
|
'●─ Home Automation ' #17
|
|
'●─ Printing ' #18
|
|
'●─ Distributed Projects ' #19
|
|
'●─ SSH Clients ' #20
|
|
'●─ File Server Clients ' #21
|
|
'●─ System ' #22
|
|
'●─ Databases & Data Stores ' #23
|
|
'●─ Development & Programming ' #24
|
|
'●─ Desktop Utilities ' #25
|
|
)
|
|
|
|
#--------------------------------------------------------------------------------
|
|
# Software items
|
|
#--------------------------------------------------------------------------------
|
|
# Before adding, please check 'dietpi-software free' to list free IDs for use.
|
|
|
|
# Assign unique ID to each item
|
|
local software_id i
|
|
|
|
# Desktops
|
|
#--------------------------------------------------------------------------------
|
|
software_id=23
|
|
aSOFTWARE_NAME[$software_id]='LXDE'
|
|
aSOFTWARE_DESC[$software_id]='ultra lightweight desktop'
|
|
aSOFTWARE_CATX[$software_id]=0
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#lxde'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 browser'
|
|
#------------------
|
|
software_id=24
|
|
aSOFTWARE_NAME[$software_id]='MATE'
|
|
aSOFTWARE_DESC[$software_id]='desktop enviroment'
|
|
aSOFTWARE_CATX[$software_id]=0
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#mate'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 browser'
|
|
#------------------
|
|
software_id=25
|
|
aSOFTWARE_NAME[$software_id]='Xfce'
|
|
aSOFTWARE_DESC[$software_id]='lightweight desktop'
|
|
aSOFTWARE_CATX[$software_id]=0
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#xfce'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 browser'
|
|
#------------------
|
|
software_id=26
|
|
aSOFTWARE_NAME[$software_id]='GNUstep'
|
|
aSOFTWARE_DESC[$software_id]='lightweight desktop based on OpenStep'
|
|
aSOFTWARE_CATX[$software_id]=0
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#gnustep'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 browser'
|
|
#------------------
|
|
software_id=173
|
|
aSOFTWARE_NAME[$software_id]='LXQt'
|
|
aSOFTWARE_DESC[$software_id]='lightweight desktop'
|
|
aSOFTWARE_CATX[$software_id]=0
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#lxqt'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 browser'
|
|
|
|
# Remote Desktop
|
|
#--------------------------------------------------------------------------------
|
|
software_id=28
|
|
aSOFTWARE_NAME[$software_id]='TigerVNC Server'
|
|
aSOFTWARE_DESC[$software_id]='desktop for remote connection'
|
|
aSOFTWARE_CATX[$software_id]=1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#tigervnc-server'
|
|
aSOFTWARE_DEPS[$software_id]='desktop'
|
|
aSOFTWARE_CONFLICTS[$software_id]='120'
|
|
#------------------
|
|
software_id=29
|
|
aSOFTWARE_NAME[$software_id]='XRDP'
|
|
aSOFTWARE_DESC[$software_id]='remote desktop protocol (rdp) server'
|
|
aSOFTWARE_CATX[$software_id]=1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#xrdp'
|
|
aSOFTWARE_DEPS[$software_id]='desktop'
|
|
#------------------
|
|
software_id=30
|
|
aSOFTWARE_NAME[$software_id]='NoMachine'
|
|
aSOFTWARE_DESC[$software_id]='multi-platform server and client access'
|
|
aSOFTWARE_CATX[$software_id]=1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#nomachine'
|
|
aSOFTWARE_DEPS[$software_id]='desktop'
|
|
# - RISC-V: https://downloads.nomachine.com/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=120
|
|
aSOFTWARE_NAME[$software_id]='RealVNC Server'
|
|
aSOFTWARE_DESC[$software_id]='desktop for remote connection'
|
|
aSOFTWARE_CATX[$software_id]=1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#realvnc-server'
|
|
aSOFTWARE_DEPS[$software_id]='desktop'
|
|
aSOFTWARE_CONFLICTS[$software_id]='28'
|
|
# RPi only (archive.raspberrypi.com repo, libraspberrypi0 dependency, license)
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=12
|
|
aSOFTWARE_NAME[$software_id]='RustDesk Server'
|
|
aSOFTWARE_DESC[$software_id]='open-source remote desktop server, written in Rust'
|
|
aSOFTWARE_CATX[$software_id]=1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#rustdesk-server'
|
|
# - RISC-V & ARMv6: https://github.com/rustdesk/rustdesk-server/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
|
|
# Media Systems
|
|
#--------------------------------------------------------------------------------
|
|
software_id=31
|
|
aSOFTWARE_NAME[$software_id]='Kodi'
|
|
aSOFTWARE_DESC[$software_id]='The media centre for Linux'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#kodi'
|
|
aSOFTWARE_DEPS[$software_id]='5 152'
|
|
#------------------
|
|
software_id=32
|
|
aSOFTWARE_NAME[$software_id]='ympd'
|
|
aSOFTWARE_DESC[$software_id]='lightweight web interface music player for mpd'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#ympd'
|
|
aSOFTWARE_DEPS[$software_id]='128'
|
|
#------------------
|
|
software_id=148
|
|
aSOFTWARE_NAME[$software_id]='myMPD'
|
|
aSOFTWARE_DESC[$software_id]='fork of ympd with improved features'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#mympd'
|
|
aSOFTWARE_DEPS[$software_id]='128'
|
|
# - RISC-V: https://download.opensuse.org/repositories/home:/jcorporation/Debian_Testing/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
# - ARMv6 Trixie: No Raspbian_13 suite available and Bookworm package depends on libflac12
|
|
(( $G_HW_ARCH == 1 && $G_DISTRO > 7 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=119
|
|
aSOFTWARE_NAME[$software_id]='CAVA'
|
|
aSOFTWARE_DESC[$software_id]='Console audio visualisation for MPD'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#cava'
|
|
aSOFTWARE_DEPS[$software_id]='128'
|
|
#------------------
|
|
software_id=33
|
|
aSOFTWARE_NAME[$software_id]='Airsonic-Advanced'
|
|
aSOFTWARE_DESC[$software_id]='Web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#airsonic'
|
|
aSOFTWARE_DEPS[$software_id]='5 7 196'
|
|
#------------------
|
|
software_id=35
|
|
aSOFTWARE_NAME[$software_id]='Lyrion Music Server'
|
|
aSOFTWARE_DESC[$software_id]='formerly Logitech Media Server and Squeezebox Server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#lyrion-music-server'
|
|
# - RISC-V: https://lms-community.github.io/lms-server-repository/stable.xml
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=36
|
|
aSOFTWARE_NAME[$software_id]='Squeezelite'
|
|
aSOFTWARE_DESC[$software_id]='audio player for LMS & Squeezebox'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#squeezelite'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
#------------------
|
|
software_id=37
|
|
aSOFTWARE_NAME[$software_id]='Shairport Sync'
|
|
aSOFTWARE_DESC[$software_id]='AirPlay audio player with multiroom sync'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#shairport-sync'
|
|
aSOFTWARE_DEPS[$software_id]='5 152'
|
|
#------------------
|
|
software_id=39
|
|
aSOFTWARE_NAME[$software_id]='ReadyMedia'
|
|
aSOFTWARE_DESC[$software_id]='(MiniDLNA) media streaming server (DLNA, UPnP)'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#readymedia'
|
|
#------------------
|
|
software_id=40
|
|
aSOFTWARE_NAME[$software_id]='Ampache'
|
|
aSOFTWARE_DESC[$software_id]='web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#ampache'
|
|
aSOFTWARE_DEPS[$software_id]='5 7 88 89 webserver'
|
|
#------------------
|
|
software_id=41
|
|
aSOFTWARE_NAME[$software_id]='Emby'
|
|
aSOFTWARE_DESC[$software_id]='web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#emby'
|
|
# - ARMv6: https://github.com/MichaIng/DietPi/issues/534#issuecomment-416405968
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://github.com/MediaBrowser/Emby.Releases/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=42
|
|
aSOFTWARE_NAME[$software_id]='Plex Media Server'
|
|
aSOFTWARE_DESC[$software_id]='web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#plex-media-server'
|
|
# - ARMv6: https://github.com/MichaIng/DietPi/issues/648
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://www.plex.tv/media-server-downloads/?cat=computer&plat=linux#plex-media-server
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=43
|
|
aSOFTWARE_NAME[$software_id]='Mumble Server'
|
|
aSOFTWARE_DESC[$software_id]='(Murmur) Low latency encrypted VoIP server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#murmur'
|
|
#------------------
|
|
software_id=118
|
|
aSOFTWARE_NAME[$software_id]='Mopidy'
|
|
aSOFTWARE_DESC[$software_id]='Web interface music & radio player'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#mopidy'
|
|
aSOFTWARE_DEPS[$software_id]='5 130'
|
|
#------------------
|
|
software_id=121
|
|
aSOFTWARE_NAME[$software_id]='Roon Bridge'
|
|
aSOFTWARE_DESC[$software_id]='Turns device into Roon capable audio player'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#roon-bridge'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# - ARMv6
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://help.roonlabs.com/portal/en/kb/articles/linux-install
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=124
|
|
aSOFTWARE_NAME[$software_id]='NAA Daemon'
|
|
aSOFTWARE_DESC[$software_id]='Signalyst Network Audio Adaptor (NAA)'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#naa-daemon'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# - RISC-V: https://signalyst.com/bins/naa/linux/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=128
|
|
aSOFTWARE_NAME[$software_id]='MPD'
|
|
aSOFTWARE_DESC[$software_id]='music player daemon'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DEPS[$software_id]='5 152'
|
|
#------------------
|
|
software_id=129
|
|
aSOFTWARE_NAME[$software_id]='O!MPD'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich, web interface audio player for MPD'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#ompd'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 128 195 webserver'
|
|
#------------------
|
|
software_id=135
|
|
aSOFTWARE_NAME[$software_id]='Icecast'
|
|
aSOFTWARE_DESC[$software_id]='Shoutcast streaming server (+DarkIce)'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#icecast'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
#------------------
|
|
software_id=143
|
|
aSOFTWARE_NAME[$software_id]='Koel'
|
|
aSOFTWARE_DESC[$software_id]='web interface audio streamer'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#koel'
|
|
aSOFTWARE_DEPS[$software_id]='7 88 89'
|
|
#------------------
|
|
software_id=146
|
|
aSOFTWARE_NAME[$software_id]='Tautulli'
|
|
aSOFTWARE_DESC[$software_id]='monitoring and tracking tool for Plex'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#tautulli'
|
|
aSOFTWARE_DEPS[$software_id]='17'
|
|
#------------------
|
|
software_id=154
|
|
aSOFTWARE_NAME[$software_id]='Roon Server'
|
|
aSOFTWARE_DESC[$software_id]='Roon capable audio player and core'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#roon-server'
|
|
aSOFTWARE_DEPS[$software_id]='1 5 7'
|
|
# x86_64 only: https://help.roonlabs.com/portal/en/kb/articles/linux-install
|
|
(( $G_HW_ARCH == 10 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]=0
|
|
#------------------
|
|
software_id=159
|
|
aSOFTWARE_NAME[$software_id]='Allo GUI full'
|
|
aSOFTWARE_DESC[$software_id]='Audiophile web interface with all dependencies'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/forum/t/dietpi-allo-com-web-gui-image/1523'
|
|
aSOFTWARE_DEPS[$software_id]='36 37 88 89 96 128 129 152 160 163 webserver'
|
|
# Roon Bridge is not supported on ARMv6 and RISC-V
|
|
(( $G_HW_ARCH == 1 || $G_HW_ARCH == 11 )) || aSOFTWARE_DEPS[$software_id]+=' 121'
|
|
# Netdata not available on Trixie
|
|
(( $G_DISTRO > 7 )) || aSOFTWARE_DEPS[$software_id]+=' 65'
|
|
# NAA Daemon not available for RISC-V
|
|
(( $G_HW_ARCH == 11 )) || aSOFTWARE_DEPS[$software_id]+=' 124'
|
|
#------------------
|
|
software_id=160
|
|
aSOFTWARE_NAME[$software_id]='Allo GUI'
|
|
aSOFTWARE_DESC[$software_id]='Audiophile web interface without dependencies'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
#------------------
|
|
software_id=163
|
|
aSOFTWARE_NAME[$software_id]='GMediaRender'
|
|
aSOFTWARE_DESC[$software_id]='Resource efficient UPnP/DLNA renderer'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#gmediarender'
|
|
aSOFTWARE_DEPS[$software_id]='5 152'
|
|
#------------------
|
|
software_id=167
|
|
aSOFTWARE_NAME[$software_id]='Raspotify'
|
|
aSOFTWARE_DESC[$software_id]='A Spotify Connect client that mostly Just Works™'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#raspotify'
|
|
aSOFTWARE_DEPS[$software_id]='5 152'
|
|
# - Bookworm/Trixie on ARMv6 (older package): "/usr/bin/librespot: error while loading shared libraries: ld-linux.so.3: cannot open shared object file: No such file or directory"
|
|
(( $G_HW_ARCH == 1 && $G_DISTRO > 6 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=80
|
|
aSOFTWARE_NAME[$software_id]='Ubooquity'
|
|
aSOFTWARE_DESC[$software_id]='free home server for your comics and ebooks library'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#ubooquity'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=179
|
|
aSOFTWARE_NAME[$software_id]='Komga'
|
|
aSOFTWARE_DESC[$software_id]='free and open source comics/mangas media server with web UI'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#komga'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=86
|
|
aSOFTWARE_NAME[$software_id]='Roon Extension Manager'
|
|
aSOFTWARE_DESC[$software_id]='manage extensions from within Roon'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#roon-extension-manager'
|
|
aSOFTWARE_DEPS[$software_id]='162'
|
|
# - ARMv6
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
#------------------
|
|
software_id=178
|
|
aSOFTWARE_NAME[$software_id]='Jellyfin'
|
|
aSOFTWARE_DESC[$software_id]='FOSS web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#jellyfin'
|
|
# - ARMv6: https://github.com/jellyfin/jellyfin/issues/5011
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://repo.jellyfin.org/?path=/server/debian/latest-unstable
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
# - ARMv7 Trixie: https://repo.jellyfin.org/?path=/server/debian/latest-stable/armhf
|
|
(( $G_HW_ARCH == 2 && $G_DISTRO > 7 )) && aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0
|
|
#------------------
|
|
software_id=190
|
|
aSOFTWARE_NAME[$software_id]='Beets'
|
|
aSOFTWARE_DESC[$software_id]='music organizer and manager'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#beets'
|
|
#------------------
|
|
software_id=191
|
|
aSOFTWARE_NAME[$software_id]='Snapcast Server'
|
|
aSOFTWARE_DESC[$software_id]='Multiroom audio server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#snapcast-server'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
#------------------
|
|
software_id=192
|
|
aSOFTWARE_NAME[$software_id]='Snapcast Client'
|
|
aSOFTWARE_DESC[$software_id]='Multiroom audio client'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#snapcast-client'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
#------------------
|
|
software_id=199
|
|
aSOFTWARE_NAME[$software_id]='Spotifyd'
|
|
aSOFTWARE_DESC[$software_id]='Open source Spotify client running as UNIX daemon'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#spotifyd'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# - RISC-V: No archive: https://github.com/Spotifyd/spotifyd/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=204
|
|
aSOFTWARE_NAME[$software_id]='Navidrome'
|
|
aSOFTWARE_DESC[$software_id]='Web interface media streaming server'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#navidrome'
|
|
aSOFTWARE_DEPS[$software_id]='5 7'
|
|
# - RISC-V: https://github.com/navidrome/navidrome/releases/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=212
|
|
aSOFTWARE_NAME[$software_id]='Kavita'
|
|
aSOFTWARE_DESC[$software_id]='open source comics/mangas/ebooks media server with web reader'
|
|
aSOFTWARE_CATX[$software_id]=2
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#kavita'
|
|
# - ARMv6: ARM binaries are ARMv7+ Only
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - No RISC-V support yet: https://github.com/Kareadita/Kavita/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
|
|
# BitTorrent & Download
|
|
#--------------------------------------------------------------------------------
|
|
software_id=44
|
|
aSOFTWARE_NAME[$software_id]='Transmission'
|
|
aSOFTWARE_DESC[$software_id]='BitTorrent server with web interface (C)'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#transmission'
|
|
#------------------
|
|
software_id=45
|
|
aSOFTWARE_NAME[$software_id]='Deluge'
|
|
aSOFTWARE_DESC[$software_id]='BitTorrent server with web interface (Python)'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#deluge'
|
|
#------------------
|
|
software_id=46
|
|
aSOFTWARE_NAME[$software_id]='qBittorrent'
|
|
aSOFTWARE_DESC[$software_id]='BitTorrent server with web interface (C++)'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#qbittorrent'
|
|
#------------------
|
|
software_id=107
|
|
aSOFTWARE_NAME[$software_id]='rTorrent'
|
|
aSOFTWARE_DESC[$software_id]='BitTorrent server (C++) with rutorrent web interface (PHP)'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#rtorrent'
|
|
aSOFTWARE_DEPS[$software_id]='89 170 webserver'
|
|
#------------------
|
|
software_id=116
|
|
aSOFTWARE_NAME[$software_id]='Medusa'
|
|
aSOFTWARE_DESC[$software_id]='Automatic video library manager for TV shows'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#medusa'
|
|
aSOFTWARE_DEPS[$software_id]='170'
|
|
#------------------
|
|
software_id=132
|
|
aSOFTWARE_NAME[$software_id]='Aria2'
|
|
aSOFTWARE_DESC[$software_id]='Download manager with web interface'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#arias'
|
|
aSOFTWARE_DEPS[$software_id]='87 89 webserver'
|
|
#------------------
|
|
software_id=139
|
|
aSOFTWARE_NAME[$software_id]='SABnzbd'
|
|
aSOFTWARE_DESC[$software_id]='NZB download manager'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#sabnzbd'
|
|
aSOFTWARE_DEPS[$software_id]='130 170'
|
|
#------------------
|
|
software_id=144
|
|
aSOFTWARE_NAME[$software_id]='Sonarr'
|
|
aSOFTWARE_DESC[$software_id]='Automatically download TV shows'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#sonarr'
|
|
(( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]='150'
|
|
# - RISC-V: https://github.com/Sonarr/Sonarr/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=145
|
|
aSOFTWARE_NAME[$software_id]='Radarr'
|
|
aSOFTWARE_DESC[$software_id]='Automatically download movies'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#radarr'
|
|
(( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]='150'
|
|
# - RISC-V: https://github.com/Radarr/Radarr/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=106
|
|
aSOFTWARE_NAME[$software_id]='Lidarr'
|
|
aSOFTWARE_DESC[$software_id]='Automatically download music'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#lidarr'
|
|
(( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]='150'
|
|
# - RISC-V: https://github.com/Lidarr/Lidarr/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=180
|
|
aSOFTWARE_NAME[$software_id]='Bazarr'
|
|
aSOFTWARE_DESC[$software_id]='Automatically download subtitles'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#bazarr'
|
|
aSOFTWARE_DEPS[$software_id]='130'
|
|
# FFmpeg x86_64 binaries are shipped with Bazarr: https://github.com/morpheus65535/bazarr-binaries/tree/master/bin/Linux/x86_64/ffmpeg
|
|
(( $G_HW_ARCH == 10 )) || aSOFTWARE_DEPS[$software_id]+=' 7'
|
|
# UnRAR x86_64 and ARMv8 binaries are shipped with Bazarr, ARMv6 needs to use "unar": https://github.com/morpheus65535/bazarr-binaries/tree/master/bin/Linux, https://github.com/morpheus65535/bazarr/issues/2172
|
|
(( $G_HW_ARCH == 2 || $G_HW_ARCH == 11 )) && aSOFTWARE_DEPS[$software_id]+=' 170'
|
|
#------------------
|
|
software_id=147
|
|
aSOFTWARE_NAME[$software_id]='Jackett'
|
|
aSOFTWARE_DESC[$software_id]='API support for your torrent trackers'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#jackett'
|
|
(( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]='150'
|
|
# - RISC-V: https://github.com/Jackett/Jackett/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=149
|
|
aSOFTWARE_NAME[$software_id]='NZBGet'
|
|
aSOFTWARE_DESC[$software_id]='NZB download manager'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#nzbget'
|
|
#------------------
|
|
software_id=151
|
|
aSOFTWARE_NAME[$software_id]='Prowlarr'
|
|
aSOFTWARE_DESC[$software_id]='Indexer manager & proxy for PVR'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#prowlarr'
|
|
# - ARMv6
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://github.com/Prowlarr/Prowlarr/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=203
|
|
aSOFTWARE_NAME[$software_id]='Readarr'
|
|
aSOFTWARE_DESC[$software_id]='Ebook and audiobook collection manager'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#readarr'
|
|
# - ARMv6
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://github.com/Readarr/Readarr/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=155
|
|
aSOFTWARE_NAME[$software_id]='HTPC Manager'
|
|
aSOFTWARE_DESC[$software_id]='Manage your HTPC from anywhere'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#htpc-manager'
|
|
aSOFTWARE_DEPS[$software_id]='17 130'
|
|
#------------------
|
|
software_id=195
|
|
aSOFTWARE_NAME[$software_id]='youtube-dl'
|
|
aSOFTWARE_DESC[$software_id]='Download videos from YouTube and other sites (using yt-dlp fork)'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#youtube-dl'
|
|
aSOFTWARE_DEPS[$software_id]='7'
|
|
#------------------
|
|
software_id=169
|
|
aSOFTWARE_NAME[$software_id]='LazyLibrarian'
|
|
aSOFTWARE_DESC[$software_id]='Ebook and audiobook collection manager'
|
|
aSOFTWARE_CATX[$software_id]=3
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#lazylibrarian'
|
|
aSOFTWARE_DEPS[$software_id]='130'
|
|
# - ARMv6/7 Bullseye: https://github.com/piwheels/packages/issues/210#issuecomment-3401251677
|
|
(( $G_HW_ARCH < 3 && $G_DISTRO < 7 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
|
|
# Cloud & Backup
|
|
#--------------------------------------------------------------------------------
|
|
software_id=47
|
|
aSOFTWARE_NAME[$software_id]='ownCloud'
|
|
aSOFTWARE_DESC[$software_id]='File sync, sharing and collaboration platform'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#owncloud'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 91 webserver'
|
|
# - Bookworm/Trixie: No PHP 8.x support yet
|
|
(( $G_DISTRO > 6 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=114
|
|
aSOFTWARE_NAME[$software_id]='Nextcloud'
|
|
aSOFTWARE_DESC[$software_id]='File sync, sharing and collaboration platform'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#nextcloud'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 91 webserver'
|
|
#------------------
|
|
software_id=168
|
|
aSOFTWARE_NAME[$software_id]='Nextcloud Talk'
|
|
aSOFTWARE_DESC[$software_id]='Video calls with configured Coturn server'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#nextcloud-talk'
|
|
aSOFTWARE_DEPS[$software_id]='114'
|
|
#------------------
|
|
software_id=48
|
|
aSOFTWARE_NAME[$software_id]='Pydio'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich backup and sync server'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#pydio'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
# - Bookworm/Trixie: No support for PHP 8: https://github.com/MichaIng/DietPi/issues/3469
|
|
(( $G_DISTRO > 6 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=111
|
|
aSOFTWARE_NAME[$software_id]='UrBackup Server'
|
|
aSOFTWARE_DESC[$software_id]='Full system backup server'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#urbackup'
|
|
# - RISC-V: https://www.urbackup.org/download.html#server_debian
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
# - ARMv6 Trixie: 64-bit time_t transition: https://download.opensuse.org/repositories/home:/uroni/Raspbian_13/
|
|
(( $G_HW_ARCH == 1 && $G_DISTRO > 7 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=49
|
|
aSOFTWARE_NAME[$software_id]='Gogs'
|
|
aSOFTWARE_DESC[$software_id]='Personal Git server with web interface'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#gogs'
|
|
aSOFTWARE_DEPS[$software_id]='17 88 0'
|
|
aSOFTWARE_CONFLICTS[$software_id]='165 177'
|
|
#------------------
|
|
software_id=50
|
|
aSOFTWARE_NAME[$software_id]='Syncthing'
|
|
aSOFTWARE_DESC[$software_id]='Backup and sync server with web interface'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#syncthing'
|
|
#------------------
|
|
software_id=158
|
|
aSOFTWARE_NAME[$software_id]='MinIO'
|
|
aSOFTWARE_DESC[$software_id]='S3 compatible distributed object server'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#minio'
|
|
# - RISC-V: https://dl.minio.io/server/minio/release/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=161
|
|
aSOFTWARE_NAME[$software_id]='FuguHub'
|
|
aSOFTWARE_DESC[$software_id]='Lightweight WebDAV cloud with a CMS, album and blog integration'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#fuguhub'
|
|
# - ARMv8
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0
|
|
# - RISC-V: https://fuguhub.com/download.lsp
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=165
|
|
aSOFTWARE_NAME[$software_id]='Gitea'
|
|
aSOFTWARE_DESC[$software_id]='Git with a cup of tea'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#gitea'
|
|
aSOFTWARE_DEPS[$software_id]='17 88 0'
|
|
aSOFTWARE_CONFLICTS[$software_id]='49 177'
|
|
#------------------
|
|
software_id=177
|
|
aSOFTWARE_NAME[$software_id]='Forgejo'
|
|
aSOFTWARE_DESC[$software_id]='Self-hosted lightweight software forge. Fork of Gitea.'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#forgejo'
|
|
aSOFTWARE_DEPS[$software_id]='17 88 0'
|
|
aSOFTWARE_CONFLICTS[$software_id]='49 165'
|
|
# - RISC-V: https://codeberg.org/forgejo/forgejo/releases
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=183
|
|
aSOFTWARE_NAME[$software_id]='vaultwarden'
|
|
aSOFTWARE_DESC[$software_id]='Unofficial Bitwarden password manager server written in Rust'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#vaultwarden'
|
|
aSOFTWARE_DEPS[$software_id]='87'
|
|
#------------------
|
|
software_id=198
|
|
aSOFTWARE_NAME[$software_id]='File Browser'
|
|
aSOFTWARE_DESC[$software_id]='web based file manager'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#filebrowser'
|
|
#------------------
|
|
software_id=202
|
|
aSOFTWARE_NAME[$software_id]='Rclone'
|
|
aSOFTWARE_DESC[$software_id]='Utility to sync your files to cloud storages'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#rclone'
|
|
#------------------
|
|
software_id=209
|
|
aSOFTWARE_NAME[$software_id]='Restic'
|
|
aSOFTWARE_DESC[$software_id]='Fast, efficient and secure command-line backup program'
|
|
aSOFTWARE_CATX[$software_id]=4
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#restic'
|
|
|
|
# Gaming & Emulation
|
|
#--------------------------------------------------------------------------------
|
|
software_id=108
|
|
aSOFTWARE_NAME[$software_id]='Amiberry'
|
|
aSOFTWARE_DESC[$software_id]='Optimised Amiga emulator for multiple platforms'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#amiberry'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
#------------------
|
|
software_id=10
|
|
aSOFTWARE_NAME[$software_id]='Amiberry-Lite'
|
|
aSOFTWARE_DESC[$software_id]='Optimised Amiga emulator recommended for smaller ARM/RISC-V SBCs'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#amiberry-lite'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# - ARMv6: Compile error: "selected processor does not support `ubfx r5,r2,...' in ARM mode"
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
#------------------
|
|
software_id=51
|
|
aSOFTWARE_NAME[$software_id]='OpenTyrian'
|
|
aSOFTWARE_DESC[$software_id]='a classic retro game, addictive'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#opentyrian'
|
|
aSOFTWARE_DEPS[$software_id]='5 6'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
# - ARMv8
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0
|
|
#------------------
|
|
software_id=112
|
|
aSOFTWARE_NAME[$software_id]='DXX-Rebirth'
|
|
aSOFTWARE_DESC[$software_id]='Descent 1/2'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#dxx-rebirth'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
# - ARMv8
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0
|
|
#------------------
|
|
software_id=52
|
|
aSOFTWARE_NAME[$software_id]='Cuberite'
|
|
aSOFTWARE_DESC[$software_id]='Minecraft server with web interface (C++)'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#cuberite'
|
|
# - RISC-V: https://cuberite.org/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=53
|
|
aSOFTWARE_NAME[$software_id]='MineOS'
|
|
aSOFTWARE_DESC[$software_id]='Minecraft servers with web interface (Java/Node.js)'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#mineos'
|
|
aSOFTWARE_DEPS[$software_id]='9 17 196'
|
|
#------------------
|
|
software_id=156
|
|
aSOFTWARE_NAME[$software_id]='Steam'
|
|
aSOFTWARE_DESC[$software_id]='Valve gaming platform client'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#steam'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 desktop'
|
|
# Box86 required on ARM
|
|
(( $G_HW_ARCH == 2 )) && aSOFTWARE_DEPS[$software_id]+=' 62'
|
|
# x86_64 and ARMv7 only
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=164
|
|
aSOFTWARE_NAME[$software_id]='Nukkit'
|
|
aSOFTWARE_DESC[$software_id]='A nuclear-powered server for Minecraft Pocket Edition'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#nukkit'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=181
|
|
aSOFTWARE_NAME[$software_id]='PaperMC'
|
|
aSOFTWARE_DESC[$software_id]='Highly optimised Minecraft server with plugins, written in Java'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#papermc'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
# Allow unattended installs if EULA has been accepted already
|
|
[[ -f '/mnt/dietpi_userdata/papermc/eula.txt' ]] || aSOFTWARE_INTERACTIVE[$software_id]=1
|
|
#------------------
|
|
software_id=62
|
|
aSOFTWARE_NAME[$software_id]='Box86'
|
|
aSOFTWARE_DESC[$software_id]='x86 userspace emulation'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#box86'
|
|
# ARMv7 only
|
|
(( $G_HW_ARCH == 2 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]=0
|
|
#------------------
|
|
software_id=197
|
|
aSOFTWARE_NAME[$software_id]='Box64'
|
|
aSOFTWARE_DESC[$software_id]='x86_64 userspace emulation'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#box64'
|
|
# ARMv8 and RISC-V only
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,10]=0
|
|
#------------------
|
|
software_id=207
|
|
aSOFTWARE_NAME[$software_id]='Moonlight (CLI)'
|
|
aSOFTWARE_DESC[$software_id]='CLI game streaming client for Sunshine and NVIDIA GameStream'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#moonlight-cli'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
# - ARMv6: https://github.com/moonlight-stream/moonlight-embedded/issues/832
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - Trixie on ARMv7: There is no Trixie suite yet, and the Bookworm packages depend on libssl3. On Trixie, libssl3t64 is provided instead, but it "provides" libssl3 for 64-bit only. The 64-bit time_t transition to prevent year 2038 problems is relevant for 32-bit systems only. So for 64-bit systems, libssl3t64 equals libssl3, and the package name has been changed only to align with the 32-bit one.
|
|
(( $G_DISTRO > 7 && $G_HW_ARCH < 3 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=208
|
|
aSOFTWARE_NAME[$software_id]='Moonlight (GUI)'
|
|
aSOFTWARE_DESC[$software_id]='GUI game streaming client for Sunshine and NVIDIA GameStream'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#moonlight-gui'
|
|
# - ARMv6: https://github.com/moonlight-stream/moonlight-embedded/issues/832
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - x86_64
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,10]=0
|
|
#------------------
|
|
software_id=11
|
|
aSOFTWARE_NAME[$software_id]='GZDoom'
|
|
aSOFTWARE_DESC[$software_id]='Modder-friendly OpenGL and Vulkan source port based on the DOOM engine'
|
|
aSOFTWARE_CATX[$software_id]=5
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#gzdoom'
|
|
aSOFTWARE_DEPS[$software_id]='5'
|
|
# - ARMv6/7: https://github.com/ZDoom/gzdoom/commit/1dedcee
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0
|
|
|
|
# Social & Search
|
|
#--------------------------------------------------------------------------------
|
|
software_id=54
|
|
aSOFTWARE_NAME[$software_id]='phpBB'
|
|
aSOFTWARE_DESC[$software_id]='bulletin board forum software'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#phpbb'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=55
|
|
aSOFTWARE_NAME[$software_id]='WordPress'
|
|
aSOFTWARE_DESC[$software_id]='website blog and publishing platform'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#wordpress'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=38
|
|
aSOFTWARE_NAME[$software_id]='FreshRSS'
|
|
aSOFTWARE_DESC[$software_id]='self-hosted RSS feed aggregator'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#freshrss'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=56
|
|
aSOFTWARE_NAME[$software_id]='Single File PHP Gallery'
|
|
aSOFTWARE_DESC[$software_id]='Website to host and browse your images'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#single-file-php-gallery'
|
|
aSOFTWARE_DEPS[$software_id]='89 webserver'
|
|
#------------------
|
|
software_id=57
|
|
aSOFTWARE_NAME[$software_id]='Baïkal'
|
|
aSOFTWARE_DESC[$software_id]='lightweight caldav + carddav server'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#baikal'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=125
|
|
aSOFTWARE_NAME[$software_id]='Synapse'
|
|
aSOFTWARE_DESC[$software_id]='Matrix homeserver implementation'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#synapse'
|
|
aSOFTWARE_DEPS[$software_id]='130 194'
|
|
#-----------------
|
|
software_id=16
|
|
aSOFTWARE_NAME[$software_id]='microblog.pub'
|
|
aSOFTWARE_DESC[$software_id]='A self-hosted, single-user, ActivityPub powered microblog.'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DEPS[$software_id]='17'
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#microblogpub'
|
|
#------------------
|
|
software_id=210
|
|
aSOFTWARE_NAME[$software_id]='MediaWiki'
|
|
aSOFTWARE_DESC[$software_id]='A collaboration and documentation platform'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#mediawiki'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=213
|
|
aSOFTWARE_NAME[$software_id]='soju'
|
|
aSOFTWARE_DESC[$software_id]='A user-friendly IRC bouncer'
|
|
aSOFTWARE_CATX[$software_id]=6
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/social/#soju'
|
|
aSOFTWARE_DEPS[$software_id]='188'
|
|
|
|
# Camera & Surveillance
|
|
#--------------------------------------------------------------------------------
|
|
software_id=59
|
|
aSOFTWARE_NAME[$software_id]='RPi Cam Web Interface'
|
|
aSOFTWARE_DESC[$software_id]='Web interface & controls for your RPi camera module'
|
|
aSOFTWARE_CATX[$software_id]=7
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/camera/#rpi-cam-web-interface'
|
|
aSOFTWARE_DEPS[$software_id]='89 webserver'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
# - ARMv8: https://github.com/silvanmelchior/RPi_Cam_Web_Interface/tree/master/bin
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0
|
|
# - Bookworm: raspimjpeg depends on legacy MMAL, removed from RPi userland libs since Bookworm
|
|
(( $G_DISTRO > 6 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=136
|
|
aSOFTWARE_NAME[$software_id]='motionEye'
|
|
aSOFTWARE_DESC[$software_id]='Web interface & surveillance for your camera'
|
|
aSOFTWARE_CATX[$software_id]=7
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/camera/#motioneye'
|
|
aSOFTWARE_DEPS[$software_id]='7 130'
|
|
#------------------
|
|
software_id=137
|
|
aSOFTWARE_NAME[$software_id]='mjpg-streamer'
|
|
aSOFTWARE_DESC[$software_id]='Simple camera streaming tool with HTML plugin'
|
|
aSOFTWARE_CATX[$software_id]=7
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/camera/#mjpg-streamer'
|
|
#------------------
|
|
software_id=127
|
|
aSOFTWARE_NAME[$software_id]='BirdNET-Go'
|
|
aSOFTWARE_DESC[$software_id]='Continuous avian monitoring and identification'
|
|
aSOFTWARE_CATX[$software_id]=7
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/camera/#birdnet-go'
|
|
aSOFTWARE_DEPS[$software_id]='7 87'
|
|
# - ARMv6/7/RISC-V: https://github.com/tphakala/birdnet-go/releases
|
|
(( $G_HW_ARCH == 3 || $G_HW_ARCH == 10 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]=0
|
|
# - Bullseye: Too old libc6/libstdc++6 and missing yq
|
|
aSOFTWARE_AVAIL_G_DISTRO[$software_id,6]=0
|
|
|
|
# System Stats & Management
|
|
#--------------------------------------------------------------------------------
|
|
software_id=3
|
|
aSOFTWARE_NAME[$software_id]='MC'
|
|
aSOFTWARE_DESC[$software_id]='Midnight Commander - a powerful file manager'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
#------------------
|
|
software_id=63
|
|
aSOFTWARE_NAME[$software_id]='LinuxDash'
|
|
aSOFTWARE_DESC[$software_id]='web interface system stats'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#linuxdash'
|
|
aSOFTWARE_DEPS[$software_id]='89 webserver'
|
|
#------------------
|
|
software_id=64
|
|
aSOFTWARE_NAME[$software_id]='phpSysInfo'
|
|
aSOFTWARE_DESC[$software_id]='web interface system stats'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#phpsysinfo'
|
|
aSOFTWARE_DEPS[$software_id]='89 webserver'
|
|
#------------------
|
|
software_id=65
|
|
aSOFTWARE_NAME[$software_id]='Netdata'
|
|
aSOFTWARE_DESC[$software_id]='real-time performance monitoring'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#netdata'
|
|
# - Trixie: https://bugs.debian.org/1107082
|
|
(( $G_DISTRO > 7 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=66
|
|
aSOFTWARE_NAME[$software_id]='RPi-Monitor'
|
|
aSOFTWARE_DESC[$software_id]='Web interface for Raspberry Pi real-time monitoring'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#rpi-monitor'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=115
|
|
aSOFTWARE_NAME[$software_id]='Webmin'
|
|
aSOFTWARE_DESC[$software_id]='web interface system management'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#webmin'
|
|
#------------------
|
|
software_id=162
|
|
aSOFTWARE_NAME[$software_id]='Docker'
|
|
aSOFTWARE_DESC[$software_id]='Build, ship, and run distributed applications'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#docker'
|
|
#------------------
|
|
software_id=185
|
|
aSOFTWARE_NAME[$software_id]='Portainer'
|
|
aSOFTWARE_DESC[$software_id]='Simplifies container management in Docker (standalone host)'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#portainer'
|
|
aSOFTWARE_DEPS[$software_id]='162'
|
|
# - ARMv6: https://dietpi.com/forum/t/16380/11
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
#------------------
|
|
software_id=134
|
|
aSOFTWARE_NAME[$software_id]='Docker Compose'
|
|
aSOFTWARE_DESC[$software_id]='Manage multi-container Docker applications'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#docker-compose'
|
|
aSOFTWARE_DEPS[$software_id]='162'
|
|
#------------------
|
|
software_id=193
|
|
aSOFTWARE_NAME[$software_id]='K3s'
|
|
aSOFTWARE_DESC[$software_id]='The certified Kubernetes distribution built for IoT & Edge computing'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#k3s'
|
|
# - RISC-V: Not yet supported: https://get.k3s.io/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=142
|
|
aSOFTWARE_NAME[$software_id]='MicroK8s'
|
|
aSOFTWARE_DESC[$software_id]='The simplest production-grade upstream K8s, light and focused'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#microk8s'
|
|
# - ARMv6/7/RISC-V: https://snapcraft.io/microk8s
|
|
(( $G_HW_ARCH == 3 || $G_HW_ARCH == 10 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]=0
|
|
#------------------
|
|
software_id=200
|
|
aSOFTWARE_NAME[$software_id]='DietPi-Dashboard'
|
|
aSOFTWARE_DESC[$software_id]='(rework beta!) Official lightweight DietPi web interface (Rust)'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#dietpi-dashboard'
|
|
#------------------
|
|
software_id=99
|
|
aSOFTWARE_NAME[$software_id]='Prometheus Node Exporter'
|
|
aSOFTWARE_DESC[$software_id]='Prometheus exporter for hardware and OS metrics'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#prometheus_node_exporter'
|
|
#------------------
|
|
software_id=205
|
|
aSOFTWARE_NAME[$software_id]='Homer'
|
|
aSOFTWARE_DESC[$software_id]='Simple HOMepage for your servER to keep your services on hand'
|
|
aSOFTWARE_CATX[$software_id]=8
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_stats/#homer'
|
|
aSOFTWARE_DEPS[$software_id]='webserver'
|
|
|
|
# Remote Access
|
|
#--------------------------------------------------------------------------------
|
|
software_id=68
|
|
aSOFTWARE_NAME[$software_id]='Remote.It'
|
|
aSOFTWARE_DESC[$software_id]='Provides secure connections to your networked devices'
|
|
aSOFTWARE_CATX[$software_id]=9
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#remot3it'
|
|
# - RISC-V: https://www.remote.it/download-list
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=138
|
|
aSOFTWARE_NAME[$software_id]='VirtualHere'
|
|
aSOFTWARE_DESC[$software_id]='server: share USB devices over the network'
|
|
aSOFTWARE_CATX[$software_id]=9
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/remote_desktop/#virtualhere'
|
|
aSOFTWARE_DEPS[$software_id]='152'
|
|
# - RISC-V: https://github.com/virtualhere/script/blob/main/install_server
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
|
|
# Hardware Projects
|
|
#--------------------------------------------------------------------------------
|
|
software_id=69
|
|
aSOFTWARE_NAME[$software_id]='Python 3 RPi.GPIO'
|
|
aSOFTWARE_DESC[$software_id]='Control Raspberry Pi GPIO channels in Python 3'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#rpigpio'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=70
|
|
aSOFTWARE_NAME[$software_id]='WiringPi'
|
|
aSOFTWARE_DESC[$software_id]='GPIO interface library (C)'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#wiringpi'
|
|
# RPi, Odroids and Orange Pi only
|
|
(( $G_HW_MODEL > 19 )) && [[ ! $G_HW_MODEL =~ ^(80|82|83|87|88|89|91|93|94|95|96|97|98)$ ]] && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=71
|
|
aSOFTWARE_NAME[$software_id]='WebIOPi'
|
|
aSOFTWARE_DESC[$software_id]='Web interface to control RPi GPIO channels'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#webiopi'
|
|
aSOFTWARE_DEPS[$software_id]='69'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=72
|
|
aSOFTWARE_NAME[$software_id]='I2C'
|
|
aSOFTWARE_DESC[$software_id]='enables support for I2C based hardware'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=100
|
|
aSOFTWARE_NAME[$software_id]='PiJuice'
|
|
aSOFTWARE_DESC[$software_id]='pisupply ups'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#pijuice'
|
|
aSOFTWARE_DEPS[$software_id]='72'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=122
|
|
aSOFTWARE_NAME[$software_id]='Node-RED'
|
|
aSOFTWARE_DESC[$software_id]='tool for wiring devices, APIs and online services'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#node-red'
|
|
aSOFTWARE_DEPS[$software_id]='9'
|
|
(( $G_HW_MODEL > 9 )) || aSOFTWARE_DEPS[$software_id]+=' 69'
|
|
#------------------
|
|
software_id=123
|
|
aSOFTWARE_NAME[$software_id]='Mosquitto'
|
|
aSOFTWARE_DESC[$software_id]='MQTT messaging broker'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#mosquitto'
|
|
#------------------
|
|
software_id=131
|
|
aSOFTWARE_NAME[$software_id]='Blynk Server'
|
|
aSOFTWARE_DESC[$software_id]='msg controller for blynk mobile app and sbcs'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#blynk-server'
|
|
aSOFTWARE_DEPS[$software_id]='196 9'
|
|
#------------------
|
|
software_id=166
|
|
aSOFTWARE_NAME[$software_id]='Audiophonics PI-SPC'
|
|
aSOFTWARE_DESC[$software_id]='Raspberry Pi power management module'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#audiophonics-pi-spc'
|
|
aSOFTWARE_DEPS[$software_id]='70'
|
|
# RPi only
|
|
(( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=77
|
|
aSOFTWARE_NAME[$software_id]='Grafana'
|
|
aSOFTWARE_DESC[$software_id]='platform for analytics and monitoring'
|
|
aSOFTWARE_CATX[$software_id]=10
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#grafana'
|
|
# - RISC-V: https://apt.grafana.com/dists/stable/main/binary-riscv64/Packages
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
|
|
# System Security
|
|
#--------------------------------------------------------------------------------
|
|
software_id=73
|
|
aSOFTWARE_NAME[$software_id]='Fail2Ban'
|
|
aSOFTWARE_DESC[$software_id]='prevents brute-force attacks with ip ban'
|
|
aSOFTWARE_CATX[$software_id]=11
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_security/#fail2ban'
|
|
#------------------
|
|
software_id=92
|
|
aSOFTWARE_NAME[$software_id]='Certbot'
|
|
aSOFTWARE_DESC[$software_id]="Obtain and renew Let's Encrypt SSL certs for HTTPS"
|
|
aSOFTWARE_CATX[$software_id]=11
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_security/#lets-encrypt'
|
|
|
|
# Webserver Stacks
|
|
#--------------------------------------------------------------------------------
|
|
software_id=75
|
|
aSOFTWARE_NAME[$software_id]='LASP'
|
|
aSOFTWARE_DESC[$software_id]='Apache + SQLite + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#lasp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='83 87 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='78 79 81 82 84 85'
|
|
aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,70]=0
|
|
#------------------
|
|
software_id=76
|
|
aSOFTWARE_NAME[$software_id]='LAMP'
|
|
aSOFTWARE_DESC[$software_id]='Apache + MariaDB + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#lamp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='83 88 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='78 79 81 82 84 85'
|
|
aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,70]=0
|
|
#------------------
|
|
software_id=78
|
|
aSOFTWARE_NAME[$software_id]='LESP'
|
|
aSOFTWARE_DESC[$software_id]='Nginx + SQLite + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#lesp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='85 87 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 81 82 83 84'
|
|
#------------------
|
|
software_id=79
|
|
aSOFTWARE_NAME[$software_id]='LEMP'
|
|
aSOFTWARE_DESC[$software_id]='Nginx + MariaDB + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#lemp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='85 88 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 81 82 83 84'
|
|
#------------------
|
|
software_id=81
|
|
aSOFTWARE_NAME[$software_id]='LLSP'
|
|
aSOFTWARE_DESC[$software_id]='Lighttpd + SQLite + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#llsp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='84 87 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 78 79 83 85'
|
|
#------------------
|
|
software_id=82
|
|
aSOFTWARE_NAME[$software_id]='LLMP'
|
|
aSOFTWARE_DESC[$software_id]='Lighttpd + MariaDB + PHP'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#llmp-web-stack'
|
|
aSOFTWARE_DEPS[$software_id]='84 88 89'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 78 79 83 85'
|
|
#------------------
|
|
software_id=83
|
|
aSOFTWARE_NAME[$software_id]='Apache'
|
|
aSOFTWARE_DESC[$software_id]='Popular webserver'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#apache2'
|
|
aSOFTWARE_CONFLICTS[$software_id]='78 79 81 82 84 85'
|
|
aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,70]=0
|
|
#------------------
|
|
software_id=84
|
|
aSOFTWARE_NAME[$software_id]='Lighttpd'
|
|
aSOFTWARE_DESC[$software_id]='Extremely lightweight webserver'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#lighttpd'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 78 79 83 85'
|
|
#------------------
|
|
software_id=85
|
|
aSOFTWARE_NAME[$software_id]='Nginx'
|
|
aSOFTWARE_DESC[$software_id]='Lightweight webserver'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#nginx'
|
|
aSOFTWARE_CONFLICTS[$software_id]='75 76 81 82 83 84'
|
|
#------------------
|
|
software_id=89
|
|
aSOFTWARE_NAME[$software_id]='PHP'
|
|
aSOFTWARE_DESC[$software_id]='Hypertext Preprocessor for dynamic web content'
|
|
aSOFTWARE_CATX[$software_id]=12
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#php'
|
|
|
|
# DNS Servers
|
|
#--------------------------------------------------------------------------------
|
|
software_id=93
|
|
aSOFTWARE_NAME[$software_id]='Pi-hole'
|
|
aSOFTWARE_DESC[$software_id]='block adverts for any device on your network'
|
|
aSOFTWARE_CATX[$software_id]=13
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/dns_servers/#pi-hole'
|
|
aSOFTWARE_DEPS[$software_id]='17'
|
|
aSOFTWARE_INTERACTIVE[$software_id]=1
|
|
aSOFTWARE_CONFLICTS[$software_id]='126'
|
|
#------------------
|
|
software_id=126
|
|
aSOFTWARE_NAME[$software_id]='AdGuard Home'
|
|
aSOFTWARE_DESC[$software_id]='powerful network-wide ads & trackers blocking DNS server'
|
|
aSOFTWARE_CATX[$software_id]=13
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/dns_servers/#adguard-home'
|
|
aSOFTWARE_CONFLICTS[$software_id]='93'
|
|
#------------------
|
|
software_id=182
|
|
aSOFTWARE_NAME[$software_id]='Unbound'
|
|
aSOFTWARE_DESC[$software_id]='validating, recursive, caching DNS resolver'
|
|
aSOFTWARE_CATX[$software_id]=13
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/dns_servers/#unbound'
|
|
|
|
# File Servers
|
|
#--------------------------------------------------------------------------------
|
|
software_id=94
|
|
aSOFTWARE_NAME[$software_id]='ProFTPD'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich FTP server with Apache-like config and FTPS+SFTP modules'
|
|
aSOFTWARE_CATX[$software_id]=14
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/file_servers/#proftpd'
|
|
aSOFTWARE_CONFLICTS[$software_id]='95'
|
|
#------------------
|
|
software_id=95
|
|
aSOFTWARE_NAME[$software_id]='vsftpd'
|
|
aSOFTWARE_DESC[$software_id]='Lightweight FTP/FTPS server'
|
|
aSOFTWARE_CATX[$software_id]=14
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/file_servers/#vsftpd'
|
|
aSOFTWARE_CONFLICTS[$software_id]='94'
|
|
#------------------
|
|
software_id=96
|
|
aSOFTWARE_NAME[$software_id]='Samba Server'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich SMB/CIFS server'
|
|
aSOFTWARE_CATX[$software_id]=14
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/file_servers/#samba'
|
|
#------------------
|
|
software_id=109
|
|
aSOFTWARE_NAME[$software_id]='NFS Server'
|
|
aSOFTWARE_DESC[$software_id]='Network File System server'
|
|
aSOFTWARE_CATX[$software_id]=14
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/file_servers/#nfs'
|
|
|
|
# VPN Servers
|
|
#--------------------------------------------------------------------------------
|
|
software_id=97
|
|
aSOFTWARE_NAME[$software_id]='OpenVPN'
|
|
aSOFTWARE_DESC[$software_id]='vpn server'
|
|
aSOFTWARE_CATX[$software_id]=15
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/vpn/#openvpn'
|
|
#------------------
|
|
software_id=172
|
|
aSOFTWARE_NAME[$software_id]='WireGuard'
|
|
aSOFTWARE_DESC[$software_id]='an extremely simple yet fast and modern VPN'
|
|
aSOFTWARE_CATX[$software_id]=15
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/vpn/#wireguard'
|
|
# Requires the WireGuard kernel module: We do not support DKMS builds anymore, which were required only for legacy kernel versions, not supported by WireGuard anymore: https://dietpi.com/forum/t/15173
|
|
(( $G_HW_MODEL == 75 )) || modprobe -nq wireguard || aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0
|
|
#------------------
|
|
software_id=117
|
|
aSOFTWARE_NAME[$software_id]='PiVPN'
|
|
aSOFTWARE_DESC[$software_id]='openvpn/wireguard server install & management tool'
|
|
aSOFTWARE_CATX[$software_id]=15
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/vpn/#pivpn'
|
|
aSOFTWARE_DEPS[$software_id]='17'
|
|
# Require interactive install if no config file containing options for unattended install is present
|
|
[[ -f '/boot/unattended_pivpn.conf' ]] || aSOFTWARE_INTERACTIVE[$software_id]=1
|
|
#------------------
|
|
software_id=58
|
|
aSOFTWARE_NAME[$software_id]='Tailscale'
|
|
aSOFTWARE_DESC[$software_id]='Zero config VPN'
|
|
aSOFTWARE_CATX[$software_id]=15
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/vpn/#tailscale'
|
|
#-----------------
|
|
software_id=201
|
|
aSOFTWARE_NAME[$software_id]='ZeroTier'
|
|
aSOFTWARE_DESC[$software_id]='Free easy to deploy cloud-hosted VPN service'
|
|
aSOFTWARE_CATX[$software_id]=15
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/vpn/#zerotier'
|
|
|
|
# Advanced Networking
|
|
#--------------------------------------------------------------------------------
|
|
software_id=60
|
|
aSOFTWARE_NAME[$software_id]='WiFi Hotspot'
|
|
aSOFTWARE_DESC[$software_id]='turn your device into a WiFi hotspot'
|
|
aSOFTWARE_CATX[$software_id]=16
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/advanced_networking/#wifi-hotspot'
|
|
#------------------
|
|
software_id=61
|
|
aSOFTWARE_NAME[$software_id]='Tor Hotspot'
|
|
aSOFTWARE_DESC[$software_id]='optional: route hotspot traffic through tor'
|
|
aSOFTWARE_CATX[$software_id]=16
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/advanced_networking/#tor-hotspot'
|
|
aSOFTWARE_DEPS[$software_id]='60'
|
|
aSOFTWARE_CONFLICTS[$software_id]='184'
|
|
#------------------
|
|
software_id=98
|
|
aSOFTWARE_NAME[$software_id]='HAProxy'
|
|
aSOFTWARE_DESC[$software_id]='high performance TCP/HTTP load balancer'
|
|
aSOFTWARE_CATX[$software_id]=16
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/advanced_networking/#haproxy'
|
|
#------------------
|
|
software_id=152
|
|
aSOFTWARE_NAME[$software_id]='Avahi-Daemon'
|
|
aSOFTWARE_DESC[$software_id]='Hostname broadcast via mDNS (Zeroconf, Bonjour)'
|
|
aSOFTWARE_CATX[$software_id]=16
|
|
#------------------
|
|
software_id=171
|
|
aSOFTWARE_NAME[$software_id]='frp'
|
|
aSOFTWARE_DESC[$software_id]='reverse proxy'
|
|
aSOFTWARE_CATX[$software_id]=16
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/advanced_networking/#frp'
|
|
|
|
# Home Automation
|
|
#--------------------------------------------------------------------------------
|
|
software_id=157
|
|
aSOFTWARE_NAME[$software_id]='Home Assistant'
|
|
aSOFTWARE_DESC[$software_id]='Open source home automation platform'
|
|
aSOFTWARE_CATX[$software_id]=17
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/home_automation/#home-assistant'
|
|
#------------------
|
|
software_id=140
|
|
aSOFTWARE_NAME[$software_id]='Domoticz'
|
|
aSOFTWARE_DESC[$software_id]='Open source home automation platform'
|
|
aSOFTWARE_CATX[$software_id]=17
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/home_automation/#domoticz'
|
|
#------------------
|
|
software_id=27
|
|
aSOFTWARE_NAME[$software_id]='TasmoAdmin'
|
|
aSOFTWARE_DESC[$software_id]='Website to manage ESP8266 devices flashed with Tasmota'
|
|
aSOFTWARE_CATX[$software_id]=17
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/home_automation/#tasmoadmin'
|
|
aSOFTWARE_DEPS[$software_id]='89 webserver'
|
|
#------------------
|
|
software_id=206
|
|
aSOFTWARE_NAME[$software_id]='openHAB'
|
|
aSOFTWARE_DESC[$software_id]='Vendor and technology agnostic FLOSS home automation software'
|
|
aSOFTWARE_CATX[$software_id]=17
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/home_automation/#openhab'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=211
|
|
aSOFTWARE_NAME[$software_id]='Homebridge'
|
|
aSOFTWARE_DESC[$software_id]='Bringing HomeKit support where there is none'
|
|
aSOFTWARE_CATX[$software_id]=17
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/home_automation/#homebridge'
|
|
# - RISC-V: https://repo.homebridge.io/dists/stable/Release
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
|
|
# Printing
|
|
#--------------------------------------------------------------------------------
|
|
software_id=153
|
|
aSOFTWARE_NAME[$software_id]='OctoPrint'
|
|
aSOFTWARE_DESC[$software_id]='web interface for controlling 3d printers'
|
|
aSOFTWARE_CATX[$software_id]=18
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/printing/#octoprint'
|
|
aSOFTWARE_DEPS[$software_id]='130'
|
|
#------------------
|
|
software_id=187
|
|
aSOFTWARE_NAME[$software_id]='CUPS'
|
|
aSOFTWARE_DESC[$software_id]='common UNIX printing system'
|
|
aSOFTWARE_CATX[$software_id]=18
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/printing/#cups'
|
|
aSOFTWARE_DEPS[$software_id]='152'
|
|
|
|
# Distributed Projects
|
|
#--------------------------------------------------------------------------------
|
|
software_id=2
|
|
aSOFTWARE_NAME[$software_id]='Folding@Home'
|
|
aSOFTWARE_DESC[$software_id]='Help disease research with your computing power!'
|
|
aSOFTWARE_CATX[$software_id]=19
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#foldinghome'
|
|
# - ARMv6/7/RISC-V: No package: https://download.foldingathome.org/releases/public/release/fahclient/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=133
|
|
aSOFTWARE_NAME[$software_id]='YaCy'
|
|
aSOFTWARE_DESC[$software_id]='decentralised open source search engine'
|
|
aSOFTWARE_CATX[$software_id]=19
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#yacy'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=141
|
|
aSOFTWARE_NAME[$software_id]='ADS-B Feeder'
|
|
aSOFTWARE_DESC[$software_id]='track airplanes using SDRs and feed the data to ADS-B aggregators'
|
|
aSOFTWARE_CATX[$software_id]=19
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#adsb-feeder'
|
|
aSOFTWARE_DEPS[$software_id]='17 130 134 162' # Git, Python, Docker & Docker Compose
|
|
#------------------
|
|
software_id=184
|
|
aSOFTWARE_NAME[$software_id]='Tor Relay'
|
|
aSOFTWARE_DESC[$software_id]='add a node to the Tor network'
|
|
aSOFTWARE_CATX[$software_id]=19
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#tor-relay'
|
|
aSOFTWARE_CONFLICTS[$software_id]='61'
|
|
#------------------
|
|
software_id=186
|
|
aSOFTWARE_NAME[$software_id]='Kubo'
|
|
aSOFTWARE_DESC[$software_id]='(IPFS Node) contribute to a decentralized Internet'
|
|
aSOFTWARE_CATX[$software_id]=19
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#ipfs-node'
|
|
# - RISC-V: https://dist.ipfs.io/kubo/
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
|
|
# SSH Clients
|
|
#--------------------------------------------------------------------------------
|
|
software_id=0
|
|
aSOFTWARE_NAME[$software_id]='OpenSSH Client'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich SSH, SFTP and SCP client'
|
|
aSOFTWARE_CATX[$software_id]=20
|
|
|
|
# File Server Clients
|
|
#--------------------------------------------------------------------------------
|
|
software_id=1
|
|
aSOFTWARE_NAME[$software_id]='Samba Client'
|
|
aSOFTWARE_DESC[$software_id]='access SMB/CIFS/Samba network shares'
|
|
aSOFTWARE_CATX[$software_id]=21
|
|
aSOFTWARE_DOCS[$software_id]=' dietpi-drive_manager > Add network drive'
|
|
#------------------
|
|
software_id=110
|
|
aSOFTWARE_NAME[$software_id]='NFS Client'
|
|
aSOFTWARE_DESC[$software_id]='network file system client'
|
|
aSOFTWARE_CATX[$software_id]=21
|
|
aSOFTWARE_DOCS[$software_id]=' dietpi-drive_manager > Add network drive'
|
|
|
|
# System
|
|
#--------------------------------------------------------------------------------
|
|
software_id=5
|
|
aSOFTWARE_NAME[$software_id]='ALSA'
|
|
aSOFTWARE_DESC[$software_id]='Advanced Linux Sound Architecture'
|
|
aSOFTWARE_CATX[$software_id]=22
|
|
#------------------
|
|
software_id=7
|
|
aSOFTWARE_NAME[$software_id]='FFmpeg'
|
|
aSOFTWARE_DESC[$software_id]='Audio & video codec library and programs'
|
|
aSOFTWARE_CATX[$software_id]=22
|
|
#------------------
|
|
software_id=6
|
|
aSOFTWARE_NAME[$software_id]='X11'
|
|
aSOFTWARE_DESC[$software_id]='X.Org X Window System implementation'
|
|
aSOFTWARE_CATX[$software_id]=22
|
|
#------------------
|
|
software_id=170
|
|
aSOFTWARE_NAME[$software_id]='UnRAR'
|
|
aSOFTWARE_DESC[$software_id]='unarchiver for .rar files'
|
|
aSOFTWARE_CATX[$software_id]=22
|
|
#------------------
|
|
software_id=4
|
|
aSOFTWARE_NAME[$software_id]='fish'
|
|
aSOFTWARE_DESC[$software_id]='friendly interactive shell'
|
|
aSOFTWARE_CATX[$software_id]=22
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system/#fish'
|
|
|
|
# Databases & Data Stores
|
|
#--------------------------------------------------------------------------------
|
|
software_id=87
|
|
aSOFTWARE_NAME[$software_id]='SQLite'
|
|
aSOFTWARE_DESC[$software_id]='Persistent single-file database system'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#sqlite'
|
|
#------------------
|
|
software_id=88
|
|
aSOFTWARE_NAME[$software_id]='MariaDB'
|
|
aSOFTWARE_DESC[$software_id]='Persistent cached file-per-table database server'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#mariadb'
|
|
#------------------
|
|
software_id=90
|
|
aSOFTWARE_NAME[$software_id]='phpMyAdmin'
|
|
aSOFTWARE_DESC[$software_id]='Optional MariaDB web interface admin tools'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#phpmyadmin'
|
|
aSOFTWARE_DEPS[$software_id]='88 89 webserver'
|
|
#------------------
|
|
software_id=91
|
|
aSOFTWARE_NAME[$software_id]='Redis'
|
|
aSOFTWARE_DESC[$software_id]='Volatile in-memory non-SQL database server'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#redis'
|
|
#------------------
|
|
software_id=74
|
|
aSOFTWARE_NAME[$software_id]='InfluxDB'
|
|
aSOFTWARE_DESC[$software_id]='Persistent time-series database server'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#influxdb'
|
|
#------------------
|
|
software_id=194
|
|
aSOFTWARE_NAME[$software_id]='PostgreSQL'
|
|
aSOFTWARE_DESC[$software_id]='Persistent advanced object-relational database server'
|
|
aSOFTWARE_CATX[$software_id]=23
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#postgresql'
|
|
|
|
# Development & Programming
|
|
#--------------------------------------------------------------------------------
|
|
software_id=17
|
|
aSOFTWARE_NAME[$software_id]='Git'
|
|
aSOFTWARE_DESC[$software_id]='Clone and manage Git repositories locally'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
#------------------
|
|
software_id=130
|
|
aSOFTWARE_NAME[$software_id]='Python 3'
|
|
aSOFTWARE_DESC[$software_id]='Runtime system, pip package installer and development headers'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#python-3'
|
|
#------------------
|
|
software_id=189
|
|
aSOFTWARE_NAME[$software_id]='VSCodium'
|
|
aSOFTWARE_DESC[$software_id]='FLOSS version of MS VSCode'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#vscodium'
|
|
aSOFTWARE_DEPS[$software_id]='5 6 17'
|
|
# - ARMv6/7/RISC-V: https://download.vscodium.com/debs/dists/vscodium/Release
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=188
|
|
aSOFTWARE_NAME[$software_id]='Go'
|
|
aSOFTWARE_DESC[$software_id]='Runtime environment and package installer'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#go'
|
|
aSOFTWARE_DEPS[$software_id]='17'
|
|
#------------------
|
|
software_id=8
|
|
aSOFTWARE_NAME[$software_id]='Java JDK'
|
|
aSOFTWARE_DESC[$software_id]='OpenJDK Development Kit'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#java'
|
|
aSOFTWARE_DEPS[$software_id]='196'
|
|
#------------------
|
|
software_id=196
|
|
aSOFTWARE_NAME[$software_id]='Java JRE'
|
|
aSOFTWARE_DESC[$software_id]='OpenJDK Runtime Environment'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#java'
|
|
#------------------
|
|
software_id=9
|
|
aSOFTWARE_NAME[$software_id]='Node.js'
|
|
aSOFTWARE_DESC[$software_id]='JavaScript runtime environment'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#nodejs'
|
|
#------------------
|
|
software_id=150
|
|
aSOFTWARE_NAME[$software_id]='Mono'
|
|
aSOFTWARE_DESC[$software_id]='Runtime libraries and repository'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#mono'
|
|
# - RISC-V: https://download.mono-project.com/repo/debian/dists/buster/main/, https://packages.debian.org/trixie/mono-runtime
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=34
|
|
aSOFTWARE_NAME[$software_id]='PHP Composer'
|
|
aSOFTWARE_DESC[$software_id]='Package manager for PHP'
|
|
aSOFTWARE_CATX[$software_id]=24
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#php-composer'
|
|
aSOFTWARE_DEPS[$software_id]='89'
|
|
|
|
# Desktop Utilities
|
|
#--------------------------------------------------------------------------------
|
|
software_id=22
|
|
aSOFTWARE_NAME[$software_id]='QuiteRSS'
|
|
aSOFTWARE_DESC[$software_id]='cross-platform, free rss reader'
|
|
aSOFTWARE_CATX[$software_id]=25
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#quiterss'
|
|
aSOFTWARE_DEPS[$software_id]='6'
|
|
# - Trixie: https://bugs.debian.org/1093725
|
|
(( $G_DISTRO > 7 )) && aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=0
|
|
#------------------
|
|
software_id=113
|
|
aSOFTWARE_NAME[$software_id]='Chromium'
|
|
aSOFTWARE_DESC[$software_id]='web browser for desktop or autostart'
|
|
aSOFTWARE_CATX[$software_id]=25
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#chromium'
|
|
aSOFTWARE_DEPS[$software_id]='5 6'
|
|
# - ARMv6: https://github.com/RPi-Distro/chromium-browser/issues/21
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
# - RISC-V: https://packages.debian.org/trixie/chromium
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0
|
|
#------------------
|
|
software_id=67
|
|
aSOFTWARE_NAME[$software_id]='Firefox'
|
|
aSOFTWARE_DESC[$software_id]='web browser for desktop'
|
|
aSOFTWARE_CATX[$software_id]=25
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#firefox'
|
|
aSOFTWARE_DEPS[$software_id]='5 6'
|
|
# - ARMv6: https://github.com/RPi-Distro/chromium-browser/issues/21#issuecomment-997044303
|
|
aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0
|
|
#------------------
|
|
software_id=174
|
|
aSOFTWARE_NAME[$software_id]='GIMP'
|
|
aSOFTWARE_DESC[$software_id]='mspaint on steroids'
|
|
aSOFTWARE_CATX[$software_id]=25
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#gimp'
|
|
aSOFTWARE_DEPS[$software_id]='6'
|
|
#------------------
|
|
software_id=175
|
|
aSOFTWARE_NAME[$software_id]='Xfce Power Manager'
|
|
aSOFTWARE_DESC[$software_id]='with brightness control, recommended for LXDE/LXQt'
|
|
aSOFTWARE_CATX[$software_id]=25
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#xfce-power-manager'
|
|
aSOFTWARE_DEPS[$software_id]='6'
|
|
|
|
#--------------------------------------------------------------------------------
|
|
# Logging Systems (hidden)
|
|
#--------------------------------------------------------------------------------
|
|
software_id=101
|
|
aSOFTWARE_NAME[$software_id]='Logrotate'
|
|
aSOFTWARE_DESC[$software_id]='Rotates and compresses old log files in /var/log'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/log_system/#full-logging'
|
|
#------------------
|
|
software_id=102
|
|
aSOFTWARE_NAME[$software_id]='Rsyslog'
|
|
aSOFTWARE_DESC[$software_id]='Writes system logs (journalctl) as plain text files to /var/log'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/log_system/#full-logging'
|
|
#------------------
|
|
software_id=103
|
|
aSOFTWARE_NAME[$software_id]='DietPi-RAMlog'
|
|
aSOFTWARE_DESC[$software_id]='Makes /var/log a RAM disk, preserves file structure on reboot'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/log_system/#dietpi-ramlog'
|
|
|
|
#--------------------------------------------------------------------------------
|
|
# SSH Servers (hidden)
|
|
#--------------------------------------------------------------------------------
|
|
software_id=104
|
|
aSOFTWARE_NAME[$software_id]='Dropbear'
|
|
aSOFTWARE_DESC[$software_id]='Lightweight SSH server'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/ssh/#dropbear'
|
|
#------------------
|
|
software_id=105
|
|
aSOFTWARE_NAME[$software_id]='OpenSSH Server'
|
|
aSOFTWARE_DESC[$software_id]='Feature-rich SSH server with SFTP and SCP support'
|
|
aSOFTWARE_CATX[$software_id]=-1
|
|
aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/ssh/#openssh'
|
|
aSOFTWARE_DEPS[$software_id]='0'
|
|
|
|
#--------------------------------------------------------------------------------
|
|
# Init install state for defined software
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
aSOFTWARE_INSTALL_STATE[$i]=0
|
|
done
|
|
# - Pre-installed on DietPi images:
|
|
aSOFTWARE_INSTALL_STATE[103]=2 # DietPi-RAMlog
|
|
aSOFTWARE_INSTALL_STATE[104]=2 # Dropbear
|
|
#--------------------------------------------------------------------------------
|
|
|
|
[[ $MACHINE_READABLE ]] || G_DIETPI-NOTIFY 0 'Initialised database'
|
|
}
|
|
|
|
# Unmark software installs for automated installs if user input is required
|
|
Unmark_Unattended()
|
|
{
|
|
(( $G_INTERACTIVE )) && return
|
|
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 && ${aSOFTWARE_INTERACTIVE[$i]:-0} == 1 ))
|
|
then
|
|
aSOFTWARE_INSTALL_STATE[$i]=0
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$i]}: Install requires user input and cannot be automated."
|
|
G_DIETPI-NOTIFY 1 "${aSOFTWARE_NAME[$i]}: Please run 'dietpi-software' to install manually."
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Unmark all dependants of a software title
|
|
# $1: software ID
|
|
Unmark_Dependants()
|
|
{
|
|
aSOFTWARE_INSTALL_STATE[$1]=0
|
|
local i
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
# NB: This does not work for dependencies given as "webserver", "desktop" or "browser". However, there are no conflicts among desktops and browser, and webservers only conflict with other webservers, hence obviously one is installed already which satisfies the dependency.
|
|
[[ ${aSOFTWARE_INSTALL_STATE[$i]} == 1 && ${aSOFTWARE_DEPS[$i]} =~ (^|[[:blank:]])$1([[:blank:]]|$) ]] || continue
|
|
aSOFTWARE_INSTALL_STATE[$i]=0
|
|
[[ $dependants_text ]] || dependants_text='\n\nThe following dependants will be unmarked as well:'
|
|
dependants_text+="\n\n - ${aSOFTWARE_NAME[$i]}: It depends on ${aSOFTWARE_NAME[$1]}."
|
|
# Recursive call to unmark all dependants of this dependant
|
|
Unmark_Dependants "$i"
|
|
done
|
|
}
|
|
|
|
# Unmark conflicting software titles
|
|
CONFLICTS_RESOLVED=0
|
|
Unmark_Conflicts()
|
|
{
|
|
# Loop through marked software
|
|
local i j unmarked_text dependants_text
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) || continue
|
|
|
|
# Loop through installed or marked conflicts
|
|
for j in ${aSOFTWARE_CONFLICTS[$i]}
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$j]} > 0 )) || continue
|
|
|
|
# At least one conflict is installed or marked: Unmark software
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && { unmarked_text+="\n\n${aSOFTWARE_NAME[$i]} won't be installed, as it conflicts with:"; Unmark_Dependants "$i"; }
|
|
|
|
# Unmark all marked conflicts
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$j]} == 1 ))
|
|
then
|
|
unmarked_text+="\n\n - ${aSOFTWARE_NAME[$j]}: It won't be installed either."
|
|
Unmark_Dependants "$j"
|
|
else
|
|
unmarked_text+="\n\n - ${aSOFTWARE_NAME[$j]}: It is installed already."
|
|
fi
|
|
done
|
|
done
|
|
|
|
CONFLICTS_RESOLVED=1
|
|
[[ $unmarked_text ]] || return 0
|
|
|
|
# Conflicts have been unmarked: Inform user!
|
|
G_WHIP_MSG "[WARNING] Conflicting installs have been detected!$unmarked_text$dependants_text"
|
|
}
|
|
|
|
Select_Webserver_Dependency()
|
|
{
|
|
# Check for existing webserver (Apache, Nginx, Lighttpd) installation
|
|
# - Do no reinstalls, as those are currently too intrusive, overriding custom configs
|
|
(( ${aSOFTWARE_INSTALL_STATE[83]} < 1 && ${aSOFTWARE_INSTALL_STATE[84]} < 1 && ${aSOFTWARE_INSTALL_STATE[85]} < 1 )) || return 1
|
|
|
|
# Auto-select webserver if manually installed
|
|
if dpkg-query -s 'apache2' &> /dev/null
|
|
then
|
|
SELECTED_WEBSERVER=83; return 0
|
|
|
|
elif dpkg-query -s 'nginx-common' &> /dev/null
|
|
then
|
|
SELECTED_WEBSERVER=85; return 0
|
|
|
|
elif dpkg-query -s 'lighttpd' &> /dev/null
|
|
then
|
|
SELECTED_WEBSERVER=84; return 0
|
|
fi
|
|
|
|
local dependant=$1 preference_index=$(sed -n '/^[[:blank:]]*AUTO_SETUP_WEB_SERVER_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) software_id
|
|
# Preference index to software ID
|
|
case $preference_index in
|
|
-2) software_id=84;; # Lighttpd
|
|
-1) software_id=85;; # Nginx
|
|
*) software_id=83;; # Apache (default)
|
|
esac
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
"${aSOFTWARE_NAME[83]}" ": ${aSOFTWARE_DESC[83]}"
|
|
"${aSOFTWARE_NAME[85]}" ": ${aSOFTWARE_DESC[85]}"
|
|
"${aSOFTWARE_NAME[84]}" ": ${aSOFTWARE_DESC[84]}"
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=${aSOFTWARE_NAME[$software_id]}
|
|
G_WHIP_BUTTON_OK_TEXT='Confirm' G_WHIP_NOCANCEL=1
|
|
G_WHIP_MENU "${aSOFTWARE_NAME[$dependant]} requires a webserver. Which one shall be installed?
|
|
\n- Apache: Feature-rich and popular. Recommended for beginners and users who are looking to follow Apache based guides.
|
|
\n- Nginx: Lightweight alternative to Apache. Nginx claims faster webserver performance compared to Apache.
|
|
\n- Lighttpd: Extremely lightweight and is generally considered to offer the \"best\" webserver performance for SBCs. Recommended for users who expect low webserver traffic.
|
|
\n- More info: https://dietpi.com/docs/software/webserver_stack/" || G_WHIP_RETURNED_VALUE=${aSOFTWARE_NAME[$software_id]}
|
|
|
|
# Software name to ID and preference index
|
|
if [[ $G_WHIP_RETURNED_VALUE == "${aSOFTWARE_NAME[83]}" ]]
|
|
then
|
|
SELECTED_WEBSERVER=83 preference_index=0
|
|
|
|
elif [[ $G_WHIP_RETURNED_VALUE == "${aSOFTWARE_NAME[85]}" ]]
|
|
then
|
|
SELECTED_WEBSERVER=85 preference_index=-1
|
|
|
|
elif [[ $G_WHIP_RETURNED_VALUE == "${aSOFTWARE_NAME[84]}" ]]
|
|
then
|
|
SELECTED_WEBSERVER=84 preference_index=-2
|
|
fi
|
|
|
|
G_CONFIG_INJECT 'AUTO_SETUP_WEB_SERVER_INDEX=' "AUTO_SETUP_WEB_SERVER_INDEX=$preference_index" /boot/dietpi.txt
|
|
return 0
|
|
}
|
|
|
|
Select_Desktop_Dependency()
|
|
{
|
|
# Check for existing desktop (LXDE, MATE, Xfce, GNUstep, LXQt) installation
|
|
# - Do no reinstalls, as those are loose dependencies
|
|
(( ${aSOFTWARE_INSTALL_STATE[23]} < 1 && ${aSOFTWARE_INSTALL_STATE[24]} < 1 && ${aSOFTWARE_INSTALL_STATE[25]} < 1 && ${aSOFTWARE_INSTALL_STATE[26]} < 1 && ${aSOFTWARE_INSTALL_STATE[173]} < 1 )) || return 1
|
|
|
|
# Auto-select desktop if manually installed
|
|
if dpkg-query -s 'lxde' &> /dev/null
|
|
then
|
|
SELECTED_DESKTOP=23; return 0
|
|
|
|
elif dpkg-query -s 'xfce4' &> /dev/null
|
|
then
|
|
SELECTED_DESKTOP=25; return 0
|
|
|
|
elif dpkg-query -s 'mate-desktop-environment-core' &> /dev/null
|
|
then
|
|
SELECTED_DESKTOP=24; return 0
|
|
|
|
elif dpkg-query -s 'lxqt' &> /dev/null
|
|
then
|
|
SELECTED_DESKTOP=173; return 0
|
|
|
|
elif dpkg-query -s 'gnustep' &> /dev/null
|
|
then
|
|
SELECTED_DESKTOP=26; return 0
|
|
fi
|
|
|
|
local dependant=$1 preference_index=$(sed -n '/^[[:blank:]]*AUTO_SETUP_DESKTOP_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) software_id
|
|
# Preference index to software ID
|
|
case $preference_index in
|
|
-1) software_id=25;; # Xfce
|
|
-2) software_id=24;; # MATE
|
|
-3) software_id=173;; # LXQt
|
|
-4) software_id=26;; # GNUstep
|
|
*) software_id=23;; # LXDE (default)
|
|
esac
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
"${aSOFTWARE_NAME[23]}" ": ${aSOFTWARE_DESC[23]}"
|
|
"${aSOFTWARE_NAME[25]}" ": ${aSOFTWARE_DESC[25]}"
|
|
"${aSOFTWARE_NAME[24]}" ": ${aSOFTWARE_DESC[24]}"
|
|
"${aSOFTWARE_NAME[173]}" ": ${aSOFTWARE_DESC[173]}"
|
|
"${aSOFTWARE_NAME[26]}" ": ${aSOFTWARE_DESC[26]}"
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=${aSOFTWARE_NAME[$software_id]}
|
|
G_WHIP_BUTTON_OK_TEXT='Confirm' G_WHIP_NOCANCEL=1
|
|
G_WHIP_MENU "${aSOFTWARE_NAME[$dependant]} requires a desktop. Which one shall be installed?" || G_WHIP_RETURNED_VALUE=${aSOFTWARE_NAME[$software_id]}
|
|
|
|
# Software name to ID and preference index
|
|
case $G_WHIP_RETURNED_VALUE in
|
|
"${aSOFTWARE_NAME[25]}") SELECTED_DESKTOP=25 preference_index=-1;;
|
|
"${aSOFTWARE_NAME[24]}") SELECTED_DESKTOP=24 preference_index=-2;;
|
|
"${aSOFTWARE_NAME[173]}") SELECTED_DESKTOP=173 preference_index=-3;;
|
|
"${aSOFTWARE_NAME[26]}") SELECTED_DESKTOP=26 preference_index=-4;;
|
|
*) SELECTED_DESKTOP=23 preference_index=0;;
|
|
esac
|
|
|
|
G_CONFIG_INJECT 'AUTO_SETUP_DESKTOP_INDEX=' "AUTO_SETUP_DESKTOP_INDEX=$preference_index" /boot/dietpi.txt
|
|
return 0
|
|
}
|
|
|
|
Select_Browser_Dependency()
|
|
{
|
|
# Check for existing browser (Firefox, Chromium) installation
|
|
# - Do no reinstalls, as those are loose dependencies
|
|
(( ${aSOFTWARE_INSTALL_STATE[67]} < 1 && ${aSOFTWARE_INSTALL_STATE[113]} < 1 )) || return 1
|
|
|
|
# Disable browser preference on ARMv6 and RISC-V systems: https://github.com/RPi-Distro/chromium-browser/issues/21
|
|
(( $G_HW_ARCH == 1 || $G_HW_ARCH == 11 )) && return 1
|
|
|
|
# Auto-select browser if manually installed
|
|
if dpkg-query -s 'firefox-esr' &> /dev/null
|
|
then
|
|
SELECTED_BROWSER=67; return 0
|
|
|
|
elif dpkg-query -s 'chromium' &> /dev/null || dpkg-query -s 'chromium-browser' &> /dev/null
|
|
then
|
|
SELECTED_BROWSER=113; return 0
|
|
fi
|
|
|
|
local dependant=$1 preference_index=$(sed -n '/^[[:blank:]]*AUTO_SETUP_BROWSER_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) software_id
|
|
# Preference index to software ID
|
|
case $preference_index in
|
|
0) return 1;; # None: Skip menu if "None" was explicitly selected or set via dietpi.txt before
|
|
-2) software_id=113;; # Chromium
|
|
*) software_id=67;; # Firefox (default)
|
|
esac
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'None' ': If you do not require a web browser'
|
|
"${aSOFTWARE_NAME[67]}" ": ${aSOFTWARE_DESC[67]}"
|
|
"${aSOFTWARE_NAME[113]}" ": ${aSOFTWARE_DESC[113]}"
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=${aSOFTWARE_NAME[$software_id]}
|
|
G_WHIP_BUTTON_OK_TEXT='Confirm' G_WHIP_NOCANCEL=1
|
|
G_WHIP_MENU "Which web browser shall be installed with the ${aSOFTWARE_NAME[$dependant]} desktop environment?" || G_WHIP_RETURNED_VALUE=${aSOFTWARE_NAME[$software_id]}
|
|
|
|
# Software name to ID and preference index
|
|
case $G_WHIP_RETURNED_VALUE in
|
|
'None') preference_index=0;;
|
|
"${aSOFTWARE_NAME[113]}") SELECTED_BROWSER=113 preference_index=-2;;
|
|
*) SELECTED_BROWSER=67 preference_index=-1;;
|
|
esac
|
|
|
|
G_CONFIG_INJECT 'AUTO_SETUP_BROWSER_INDEX=' "AUTO_SETUP_BROWSER_INDEX=$preference_index" /boot/dietpi.txt
|
|
[[ $G_WHIP_RETURNED_VALUE == 'None' ]] && return 1 || return 0
|
|
}
|
|
|
|
# $1: software ID
|
|
Resolve_Dependencies()
|
|
{
|
|
# Loop through dependencies
|
|
local i
|
|
for i in ${aSOFTWARE_DEPS[$1]}
|
|
do
|
|
# Resolve webserver dependency based on install state and user preference
|
|
if [[ $i == 'webserver' ]]
|
|
then
|
|
Select_Webserver_Dependency "$1" || continue
|
|
i=$SELECTED_WEBSERVER
|
|
|
|
# Resolve desktop dependency based on install state
|
|
elif [[ $i == 'desktop' ]]
|
|
then
|
|
Select_Desktop_Dependency "$1" || continue
|
|
i=$SELECTED_DESKTOP
|
|
|
|
# Resolve browser dependency based on install state
|
|
elif [[ $i == 'browser' ]]
|
|
then
|
|
Select_Browser_Dependency "$1" || continue
|
|
i=$SELECTED_BROWSER
|
|
fi
|
|
|
|
# Skip if dependency is marked for install already
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && continue
|
|
|
|
# Is it reinstalled or freshly installed?
|
|
local re_installed='installed'
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 )) && re_installed='reinstalled'
|
|
|
|
aSOFTWARE_INSTALL_STATE[$i]=1
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$i]} will be $re_installed"
|
|
# Recursive call to resolve dependencies of this dependency
|
|
Resolve_Dependencies "$i"
|
|
done
|
|
}
|
|
|
|
# Work out which additional software we need to install
|
|
# - We do reinstall most =2 marked software as well, just to be sure.
|
|
Mark_Dependencies()
|
|
{
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Checking for prerequisite software'
|
|
|
|
# If OctoPrint and mjpg-streamer both are installed, OctoPrint is automatically configured to use mjpg-streamer. For the integrated time-lapse feature, FFmpeg is required.
|
|
if (( ${aSOFTWARE_INSTALL_STATE[137]} > 0 && ${aSOFTWARE_INSTALL_STATE[153]} > 0 && ${aSOFTWARE_INSTALL_STATE[137]} + ${aSOFTWARE_INSTALL_STATE[153]} < 4 ))
|
|
then
|
|
aSOFTWARE_INSTALL_STATE[7]=1
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[7]} will be installed"
|
|
fi
|
|
|
|
# Loop through marked software to resolve dependencies each
|
|
local i
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) || continue
|
|
Resolve_Dependencies "$i"
|
|
done
|
|
}
|
|
|
|
Create_Desktop_Shared_Items()
|
|
{
|
|
# Pre-create dirs
|
|
G_EXEC mkdir -p /usr/share/applications /var/lib/dietpi/dietpi-software/installed/desktop/{icons,wallpapers}
|
|
|
|
# Icons
|
|
G_THREAD_START curl -sSfL 'https://raw.githubusercontent.com/MichaIng/DietPi-Website/master/images/dietpi-logo_128x128.png' -o /var/lib/dietpi/dietpi-software/installed/desktop/icons/dietpi-icon.png
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/icons/grey_16x16.png" -o /var/lib/dietpi/dietpi-software/installed/desktop/icons/grey_16x16.png
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/icons/justboom.png" -o /var/lib/dietpi/dietpi-software/installed/desktop/icons/justboom.png
|
|
|
|
# Wallpapers
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/wallpapers/dietpi-logo_inverted_1080p.png" -o /var/lib/dietpi/dietpi-software/installed/desktop/wallpapers/dietpi-logo_inverted_1080p.png
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/wallpapers/dietpi-logo_1080p.png" -o /var/lib/dietpi/dietpi-software/installed/desktop/wallpapers/dietpi-logo_1080p.png
|
|
|
|
# File manager bookmarks
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/gtk/.gtk-bookmarks" -o /var/lib/dietpi/dietpi-software/installed/desktop/.gtk-bookmarks
|
|
|
|
# Desktop applications
|
|
local adesktop_items=(
|
|
|
|
'dietpi-software'
|
|
'dietpi-drive_manager'
|
|
'dietpi-update'
|
|
'dietpi-config'
|
|
'dietpi-backup'
|
|
'dietpi-sync'
|
|
'dietpi-services'
|
|
'dietpi-cleaner'
|
|
'dietpi-cron'
|
|
'dietpi-launcher'
|
|
'dietpi-justboom'
|
|
)
|
|
|
|
local i
|
|
for i in "${adesktop_items[@]}"
|
|
do
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/apps/$i.desktop" -o "/usr/share/applications/$i.desktop"
|
|
done
|
|
|
|
# Create autostart script to add default desktop icons and configs to users that login the first time into a desktop
|
|
cat << '_EOF_' > /var/lib/dietpi/dietpi-software/installed/desktop/dietpi-desktop_setup.sh
|
|
#!/bin/dash
|
|
|
|
# Create desktop shortcuts
|
|
set 'opentyrian' 'kodi' 'steam' 'dxx-rebirth' 'chromium' 'chromium-browser' 'htop' 'codium'
|
|
[ $USER = 'root' ] && set "$@" 'dietpi-launcher' 'dietpi-software' 'dietpi-config'
|
|
[ -d ~/Desktop ] || mkdir -p ~/Desktop
|
|
for i in "$@"
|
|
do
|
|
[ -f /usr/share/applications/$i.desktop ] && ! [ -f ~/Desktop/$i.desktop ] && ln -sf /usr/share/applications/$i.desktop ~/Desktop/$i.desktop
|
|
done
|
|
|
|
# Create file manager bookmarks
|
|
if ! [ -f ~/.gtk-bookmarks ]
|
|
then
|
|
cp /var/lib/dietpi/dietpi-software/installed/desktop/.gtk-bookmarks ~/.gtk-bookmarks
|
|
sed --follow-symlinks -i "s|/root|$HOME|g" ~/.gtk-bookmarks
|
|
fi
|
|
|
|
# Disable this autostart entry
|
|
[ -d ~/.config/autostart ] || mkdir -p ~/.config/autostart
|
|
echo '[Desktop Entry]\nHidden=true' > ~/.config/autostart/dietpi-desktop_setup.desktop
|
|
_EOF_
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/desktop/dietpi-desktop_setup.sh
|
|
cat << '_EOF_' > /etc/xdg/autostart/dietpi-desktop_setup.desktop
|
|
[Desktop Entry]
|
|
Version=1.0
|
|
Name=DietPi-Desktop_setup
|
|
Type=Application
|
|
Comment=Adds default desktop entries and configs to the users desktop
|
|
NoDisplay=true
|
|
Exec=/var/lib/dietpi/dietpi-software/installed/desktop/dietpi-desktop_setup.sh
|
|
Icon=/var/lib/dietpi/dietpi-software/installed/desktop/icons/dietpi-icon.png
|
|
_EOF_
|
|
G_THREAD_WAIT
|
|
# https://gitlab.xfce.org/xfce/thunar/-/merge_requests/317 > https://packages.debian.org/bookworm/thunar
|
|
if (( $G_DISTRO < 7 && ${aSOFTWARE_INSTALL_STATE[25]} == 1 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Adding execute bit to our default desktop launchers/icons'
|
|
adesktop_items=()
|
|
for i in 'opentyrian' 'kodi' 'steam' 'dxx-rebirth' 'chromium' 'chromium-browser' 'htop' 'codium' 'dietpi-launcher' 'dietpi-software' 'dietpi-config'
|
|
do
|
|
[[ -f /usr/share/applications/$i.desktop ]] && adesktop_items+=("/usr/share/applications/$i.desktop")
|
|
done
|
|
G_EXEC chmod +x "${adesktop_items[@]}"
|
|
fi
|
|
}
|
|
|
|
# Add desktop entry for users which logged into a desktop already and hence have DietPi-Desktop_setup disabled.
|
|
# $1 = Application name
|
|
Create_Desktop_Shortcut()
|
|
{
|
|
local uid gid app=$1
|
|
for i in /root /home/*
|
|
do
|
|
[[ -f $i/.config/autostart/dietpi-desktop_setup.desktop && ! -f $i/Desktop/$app.desktop ]] || continue
|
|
if [[ ! -d $i/Desktop ]]
|
|
then
|
|
# shellcheck disable=SC2012
|
|
read -r uid gid < <(ls -dn "$i" | mawk '{print $3,$4}')
|
|
G_EXEC mkdir -p "$i/Desktop"
|
|
G_EXEC chown "$uid:$gid" "$i/Desktop"
|
|
fi
|
|
G_EXEC ln -sf "/usr/share/applications/$app.desktop" "$i/Desktop/$app.desktop"
|
|
# https://gitlab.xfce.org/xfce/thunar/-/issues/50
|
|
(( ${aSOFTWARE_INSTALL_STATE[25]} > 0 )) && G_EXEC chmod +x "/usr/share/applications/$app.desktop"
|
|
done
|
|
}
|
|
|
|
Create_Required_Dirs()
|
|
{
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/{Music,Pictures,Video,downloads} /var/www /opt /usr/local/bin
|
|
getent passwd dietpi > /dev/null && G_EXEC chown dietpi:dietpi /mnt/dietpi_userdata/{Music,Pictures,Video,downloads}
|
|
G_EXEC chmod 0775 /mnt/dietpi_userdata/{Music,Pictures,Video,downloads}
|
|
}
|
|
|
|
Download_Test_Media()
|
|
{
|
|
[[ -f '/mnt/dietpi_userdata/Music/fourdee_tech.ogg' ]] && return
|
|
G_EXEC curl -sSf 'https://dietpi.com/downloads/audio/fourdee_tech.ogg' -o /mnt/dietpi_userdata/Music/fourdee_tech.ogg
|
|
getent passwd dietpi > /dev/null && G_EXEC chown dietpi:dietpi /mnt/dietpi_userdata/Music/fourdee_tech.ogg
|
|
G_EXEC chmod 0664 /mnt/dietpi_userdata/Music/fourdee_tech.ogg
|
|
}
|
|
|
|
# Return optimisation values for BitTorrent servers based on device and hardware capabilities.
|
|
Optimise_BitTorrent()
|
|
{
|
|
local gigabit_ethernet=1
|
|
(( $G_HW_MODEL < 4 || $G_HW_MODEL == 40 || $G_HW_MODEL == 60 || $G_HW_MODEL == 70 )) && gigabit_ethernet=0
|
|
|
|
local output
|
|
case $1 in
|
|
0) output=$(( $RAM_PHYS / 10 ));; # Cache size (MiB) 10% of RAM size
|
|
1)
|
|
# Max active downloads
|
|
output=2
|
|
# Bump up for x86_64
|
|
(( $G_HW_ARCH == 10 )) && output=3
|
|
;;
|
|
2)
|
|
# Max global connections
|
|
output=20
|
|
# Bump up for Gbit Ethernet
|
|
(( $gigabit_ethernet )) && output=30
|
|
# Bump up for x86_64
|
|
(( $G_HW_ARCH == 10 )) && output=40
|
|
# Reduce for RPi 1-3 due to the USB bus Ethernet in the ARM SoC, which cripples network throughput/performance/latency.
|
|
case $G_HW_MODEL in
|
|
3) output=15;;
|
|
2) output=13;;
|
|
1) output=7;;
|
|
*) :;;
|
|
esac
|
|
;;
|
|
3)
|
|
# Max upload slots
|
|
output=3
|
|
# Bump up for Gbit Ethernet
|
|
(( $gigabit_ethernet )) && output=4
|
|
# Bump up for x86_64
|
|
(( $G_HW_ARCH == 10 )) && output=5
|
|
# Reduce for RPi 1-3 due to the USB bus Ethernet in the ARM SoC, which cripples network throughput/performance/latency.
|
|
(( $G_HW_MODEL < 4 )) && output=2
|
|
;;
|
|
*) G_DIETPI-NOTIFY 1 "Invalid argument \$1=\"$1\" for function Optimise_BitTorrent()"; return 1;;
|
|
esac
|
|
|
|
echo "$output"
|
|
}
|
|
|
|
# Usage:
|
|
# Download_Install 'https://file.com/file' [/path/to/target]
|
|
# dps_index=$software_id Download_Install 'conf_0' /etc/conf.conf
|
|
# Optional input variables:
|
|
# fallback_url='http...' = URL to use if e.g. grabbing URL from api.github.com fails
|
|
# dps_index=$software_id = Download from DietPi GitHub repo based on software ID/index
|
|
# aDEPS=('pkg1' 'pkg2' ...) = Install APT dependency packages
|
|
# NB: This does not support installs that require user input (e.g.: a whiptail prompt for deb installs)
|
|
Download_Install()
|
|
{
|
|
# Verify input URL
|
|
if [[ $1 ]]
|
|
then
|
|
local url=$1
|
|
|
|
elif [[ $fallback_url ]]
|
|
then
|
|
G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} download URL detection failed."
|
|
G_DIETPI-NOTIFY 1 "\"$fallback_url\" will be used as fallback, but a newer version might be available."
|
|
G_DIETPI-NOTIFY 1 'Please report this at: https://github.com/MichaIng/DietPi/issues'
|
|
local url=$fallback_url
|
|
else
|
|
G_DIETPI-NOTIFY 1 "An empty download URL was passed during ${aSOFTWARE_NAME[$software_id]} install. Please report this at: https://github.com/MichaIng/DietPi/issues"
|
|
return 1
|
|
fi
|
|
|
|
local target=$2 # Target path
|
|
local file=${url##*/} # Grab file name from URL
|
|
|
|
# DietPi-Software conf/service mode
|
|
# shellcheck disable=SC2154
|
|
[[ $dps_index && ${aSOFTWARE_NAME[$dps_index]} ]] && url="https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/dps_$dps_index/$url"
|
|
|
|
G_EXEC cd "$G_WORKING_DIR" # Failsafe
|
|
|
|
# Add decompressor to deps list if missing
|
|
case $file in
|
|
*'.xz'|*'.txz') command -v xz > /dev/null || aDEPS+=('xz-utils');;
|
|
*'.bz2'|*'.tbz2') command -v bzip2 > /dev/null || aDEPS+=('bzip2');;
|
|
*'.zip') command -v unzip > /dev/null || aDEPS+=('unzip');;
|
|
*'.7z') command -v 7zr > /dev/null || { (( $G_DISTRO > 7 )) && aDEPS+=('7zip') || aDEPS+=('p7zip'); };;
|
|
*) :;;
|
|
esac
|
|
|
|
# Download file
|
|
if [[ ${aDEPS[0]} ]]
|
|
then
|
|
# Check URL before starting background download, as a failure does not terminate the install
|
|
# shellcheck disable=SC2154
|
|
G_CHECK_URL "$url"
|
|
|
|
# Download as background thread if dependencies are to be installed
|
|
G_THREAD_START curl -sSfL "$url" -o "$file"
|
|
# shellcheck disable=SC2086
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
G_THREAD_WAIT
|
|
else
|
|
G_EXEC curl -sSfL "$url" -o "$file"
|
|
fi
|
|
|
|
unset -v fallback_url dps_index
|
|
|
|
# Process downloaded file
|
|
case $file in
|
|
*'.gz') [[ $file == *'.tar.gz' ]] || { G_EXEC gzip -df "$file" && file=${file%.gz}; };;
|
|
*'.xz') [[ $file == *'.tar.xz' ]] || { G_EXEC xz -df "$file" && file=${file%.xz}; };;
|
|
*'.bz2') [[ $file == *'.tar.bz2' ]] || { G_EXEC bzip2 -df "$file" && file=${file%.bz2}; };;
|
|
*) :;;
|
|
esac
|
|
if [[ $file == *'.deb' ]]
|
|
then
|
|
G_AGI "./$file"
|
|
|
|
elif [[ $file == *'.zip' ]]
|
|
then
|
|
G_EXEC unzip -o "$file" ${target:+"-d$target"}
|
|
|
|
elif [[ $file =~ \.(t?gz|t?xz|t?bz2|tar)$ ]]
|
|
then
|
|
G_EXEC tar xf "$file" ${target:+"--one-top-level=$target"}
|
|
|
|
elif [[ $file == *'.7z' ]]
|
|
then
|
|
[[ $target && ! -d $target ]] && G_EXEC mkdir -p "$target" # Workaround for 7zr ignoring umask: https://github.com/MichaIng/DietPi/issues/4251
|
|
G_EXEC 7zr x -y "$file" ${target:+"-o$target"}
|
|
|
|
elif [[ $target && $target != "$file" ]]
|
|
then
|
|
# Pre-create target dir if given: $target can be a file name only, so assure it is a path containing a dir
|
|
[[ $target == *'/'* && ! -d ${target%/*} ]] && G_EXEC mkdir -p "${target%/*}"
|
|
G_EXEC mv "$file" "$target"
|
|
else
|
|
return 0
|
|
fi
|
|
|
|
[[ -f $file ]] && G_EXEC rm "$file"
|
|
}
|
|
|
|
Create_User()
|
|
{
|
|
# Parse input and mark as read-only to throw an error if given doubled
|
|
local group_primary groups_supplementary home shell password user
|
|
while (( $# ))
|
|
do
|
|
case $1 in
|
|
'-g') shift; readonly group_primary=$1;; # Primary group is always pre-created and defaults to same name as user for new users
|
|
'-G') shift; readonly groups_supplementary=$1;; # User is only added to supplementary groups that do exist
|
|
'-d') shift; readonly home=$1;; # Home is never pre-created and defaults to "/nonexistent" which prevents login
|
|
'-s') shift; readonly shell=$1;; # Shell defaults to "nologin" which prevents shell access on login even if home exists
|
|
'-p') shift; readonly password=$1;; # Password is only set for new users while existing users' passwords stay untouched
|
|
*) readonly user=$1;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Pre-create given primary group, as useradd and usermod fail if it does not exist
|
|
[[ $group_primary ]] && ! getent group "$group_primary" > /dev/null && G_EXEC groupadd -r "$group_primary"
|
|
|
|
# Only add to supplementary groups that do exist
|
|
local group groups
|
|
for group in ${groups_supplementary//,/ }
|
|
do
|
|
getent group "$group" > /dev/null && groups+=",$group"
|
|
done
|
|
groups=${groups#,}
|
|
|
|
# Create user if missing, else modify it according to input
|
|
if getent passwd "$user" > /dev/null
|
|
then
|
|
G_EXEC usermod ${group_primary:+-g "$group_primary"} ${groups:+-aG "$groups"} -d "${home:-/nonexistent}" -s "${shell:-$(command -v nologin)}" "$user"
|
|
else
|
|
local options='-rMU'
|
|
[[ $group_primary ]] && options='-rMN'
|
|
G_EXEC useradd "$options" ${group_primary:+-g "$group_primary"} ${groups:+-G "$groups"} -d "${home:-/nonexistent}" -s "${shell:-$(command -v nologin)}" "$user"
|
|
[[ $password ]] && G_EXEC_DESC="Applying user password: \e[33m${password//?/*}\e[0m" G_EXEC eval "chpasswd <<< '$user:$password'"
|
|
fi
|
|
}
|
|
|
|
# Start a service and wait for a default config file to be created.
|
|
Create_Config()
|
|
{
|
|
local file=$1 service=$2 # Config file path and service name
|
|
local timeout=${3:-25} # Optional [s]
|
|
local output=$4 pid # Optional, if timeout is set, hence for startups which may take long so that showing some process becomes reasonable
|
|
# shellcheck disable=SC2154
|
|
local content=$CREATE_CONFIG_CONTENT stop=$CC_STOP # Optional required config file content and whether to stop service afterwards (!= 0)
|
|
unset -v CREATE_CONFIG_CONTENT CC_STOP
|
|
|
|
# If file exists already and contains required content, continue install
|
|
[[ -f $file ]] && { [[ ! $content ]] || grep -q "$content" "$file"; } && return 0
|
|
|
|
# Reload services
|
|
G_EXEC systemctl daemon-reload
|
|
|
|
# File does not exist or does not contain required content: Start service
|
|
G_EXEC_DESC="Starting ${aSOFTWARE_NAME[$software_id]} to pre-create config file in max $timeout seconds" G_EXEC systemctl start "$service"
|
|
|
|
# Print and follow output of the service startup
|
|
[[ $output ]] && { journalctl -fn 0 -u "$service" & pid=$!; }
|
|
|
|
# Wait for max $timeout seconds until config file has been created and required content added if given
|
|
local i=0
|
|
until [[ -f $file ]] && { [[ ! $content ]] || grep -q "$content" "$file"; } || (( $i >= $timeout )) || ! systemctl -q is-active "$service"
|
|
do
|
|
((i++))
|
|
[[ $output ]] || G_DIETPI-NOTIFY -2 "Waiting for ${aSOFTWARE_NAME[$software_id]} config file to be created ($i/$timeout)"
|
|
G_SLEEP 1
|
|
done
|
|
|
|
# Stop journal prints
|
|
[[ $output ]] && { kill "$pid"; wait "$pid"; } 2> /dev/null
|
|
|
|
# Stop service
|
|
if [[ $stop != 0 ]]
|
|
then
|
|
G_SLEEP 1
|
|
G_EXEC_NOHALT=1 G_EXEC systemctl stop "$service"
|
|
G_SLEEP 1
|
|
fi
|
|
|
|
# If file exists already and contains required content, continue install
|
|
if [[ -f $file ]] && { [[ ! $content ]] || grep -q "$content" "$file"; }
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} config file got created after $i seconds"
|
|
return 0
|
|
fi
|
|
|
|
G_DIETPI-NOTIFY 1 "Waiting for ${aSOFTWARE_NAME[$software_id]} config file failed, skipping pre-configuration"
|
|
return 1
|
|
}
|
|
|
|
# Remove obsolete SysV service
|
|
# $1: Service name
|
|
# $2: If set, remove defaults file as well (optional)
|
|
Remove_SysV()
|
|
{
|
|
G_DIETPI-NOTIFY 2 "Removing obsolete $1 SysV service"
|
|
[[ -f '/etc/init.d/'$1 ]] && G_EXEC rm "/etc/init.d/$1"
|
|
G_EXEC update-rc.d "$1" remove
|
|
[[ $2 && -f '/etc/default/'$1 ]] && G_EXEC rm "/etc/default/$1"
|
|
}
|
|
|
|
# Run marked software installs
|
|
Install_Software()
|
|
{
|
|
local software_id aDEPS=()
|
|
|
|
# Configure iptables to use nf_tables or legacy API, depending on which is supported by kernel
|
|
Configure_iptables()
|
|
{
|
|
local alt='nft'
|
|
iptables-nft -L &> /dev/null || alt='legacy'
|
|
G_EXEC update-alternatives --set iptables "/usr/sbin/iptables-$alt"
|
|
G_EXEC update-alternatives --set ip6tables "/usr/sbin/ip6tables-$alt"
|
|
}
|
|
|
|
Enable_memory_cgroup()
|
|
{
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
grep -Eq '(^|[[:blank:]])cgroup_enable=memory([[:blank:]]|$)' /boot/cmdline.txt || G_EXEC sed --follow-symlinks -i '/root=/s/[[:blank:]]*$/ cgroup_enable=memory/' /boot/cmdline.txt
|
|
|
|
elif [[ -f '/boot/boot.scr' ]] && grep -q 'docker_optimizations' /boot/boot.scr
|
|
then
|
|
# DietPi mainline U-Boot
|
|
[[ -f '/boot/dietpiEnv.txt' ]] && G_CONFIG_INJECT 'docker_optimizations=' 'docker_optimizations=on' /boot/dietpiEnv.txt
|
|
# Armbian
|
|
[[ -f '/boot/armbianEnv.txt' ]] && G_CONFIG_INJECT 'docker_optimizations=' 'docker_optimizations=on' /boot/armbianEnv.txt
|
|
# Radxa Zero
|
|
[[ -f '/boot/uEnv.txt' ]] && G_CONFIG_INJECT 'docker_optimizations=' 'docker_optimizations=on' /boot/uEnv.txt
|
|
|
|
elif [[ -f '/boot/extlinux/extlinux.conf' ]]
|
|
then
|
|
grep -Eq '^[[:blank:]]*append[[:blank:]].*cgroup_enable=memory([[:blank:]]|$)' /boot/extlinux/extlinux.conf || G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*append[[:blank:]]/s/[[:blank:]]*$/ cgroup_enable=memory/' /boot/extlinux/extlinux.conf
|
|
fi
|
|
}
|
|
|
|
# $1: Software name, so config can be created and removed per-software
|
|
Enable_IP_forwarding()
|
|
{
|
|
if (( $G_HW_MODEL == 75 ))
|
|
then
|
|
[[ $(sysctl -n net.ipv4.ip_forward net.ipv6.conf.default.accept_ra net.ipv6.conf.all.accept_ra net.ipv6.conf.default.forwarding net.ipv6.conf.all.forwarding) == $'1\n2\n2\n1\n1' ]] || G_WHIP_MSG "[WARNING] IP forwarding needs to be enabled on container host
|
|
\nIP forwarding is not enabled for all interfaces, hence ${aSOFTWARE_NAME[$software_id]} clients cannot access the LAN or Internet behind this DietPi system vice versa.
|
|
\nIP forwarding can only be enabled on the host of this container. E.g. add the following lines to a new sysctl config file like /etc/sysctl.d/dietpi-$1.conf:
|
|
net.ipv4.ip_forward=1
|
|
net.ipv6.conf.default.accept_ra=2
|
|
net.ipv6.conf.all.accept_ra=2
|
|
net.ipv6.conf.default.forwarding=1
|
|
net.ipv6.conf.all.forwarding=1
|
|
\nApply them without reboot like this:
|
|
sudo sysctl -p /etc/sysctl.d/dietpi-$1.conf"
|
|
else
|
|
G_DIETPI-NOTIFY 2 'Enabling IP forwarding to allow access across network interfaces'
|
|
G_EXEC eval "echo -e 'net.ipv4.ip_forward=1\nnet.ipv6.conf.default.accept_ra=2\nnet.ipv6.conf.all.accept_ra=2\nnet.ipv6.conf.default.forwarding=1\nnet.ipv6.conf.all.forwarding=1' > '/etc/sysctl.d/dietpi-$1.conf'"
|
|
local dryrun=()
|
|
[[ ! -w '/proc/sys/net/ipv4/ip_forward' ]] && systemd-detect-virt -cq && dryrun=('--dry-run')
|
|
G_EXEC sysctl -p "${dryrun[@]}" "/etc/sysctl.d/dietpi-$1.conf"
|
|
fi
|
|
}
|
|
|
|
# Store APT dependencies for Python modules in aDEPS array, or optionally install them directly
|
|
# Arguments:
|
|
# --install, -i Install APT packages directly
|
|
# --user, -u User to install Rust with
|
|
# --rust, -r Install Rust in any case
|
|
# --no-piwheels, -P Declare that piwheels is not used
|
|
# pyenv Add APT dependencies needed to compile Python for pyenv
|
|
# <module> Add APT dependencies needed to compile and in case run the named module
|
|
# Environment variables:
|
|
# PYTHON_VERSION Python version in case e.g. pyenv is used
|
|
Python_Deps()
|
|
{
|
|
local install=0 user rust=0 piwheels=0
|
|
|
|
if [[ $PYTHON_VERSION ]]
|
|
then
|
|
until [[ $PYTHON_VERSION =~ ^3\.[0-9]+$ ]]; do PYTHON_VERSION=${PYTHON_VERSION%\.*}; done
|
|
else
|
|
case $G_DISTRO in
|
|
6) PYTHON_VERSION='3.9';;
|
|
7) PYTHON_VERSION='3.11';;
|
|
*) PYTHON_VERSION='3.13';;
|
|
esac
|
|
fi
|
|
PYTHON_VERSION=${PYTHON_VERSION/.} # so we can check in bash arithmetic
|
|
|
|
# Can piwheels be used? The Python version needs to match the Debian version, else dynamically linked shared libraries may not match!
|
|
if (( $G_HW_ARCH < 3 ))
|
|
then
|
|
if (( ( $G_DISTRO == 6 && $PYTHON_VERSION == 39 ) ||
|
|
( $G_DISTRO == 7 && $PYTHON_VERSION == 311 ) ||
|
|
( $G_DISTRO > 7 && $PYTHON_VERSION == 313 ) ))
|
|
then
|
|
piwheels=1
|
|
fi
|
|
fi
|
|
|
|
# Process arguments
|
|
while (( $# ))
|
|
do
|
|
case $1 in
|
|
'--install'|'-i') install=1;;
|
|
'--user'|'-u') shift; user=$1;;
|
|
'--rust'|'-r') rust=1;;
|
|
'--no-piwheels'|'-P') piwheels=0;;
|
|
'av') (( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && $PYTHON_VERSION != 313 ) )) && aDEPS+=('libavdevice-dev');;
|
|
'bcrypt') (( $G_HW_ARCH == 11 || ( $G_HW_ARCH == 1 && ! $piwheels ) )) && rust=1;;
|
|
'brotli'|'sabctools'|'ujson') (( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ! $piwheels ) )) && aDEPS+=('g++');;
|
|
'cffi') (( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && $PYTHON_VERSION != 311 ) )) && aDEPS+=('gcc' 'libffi-dev');;
|
|
'cryptography')
|
|
if (( $G_HW_ARCH == 11 || ( $G_HW_ARCH == 1 && ! $piwheels ) ))
|
|
then
|
|
aDEPS+=('pkg-config' 'libssl-dev')
|
|
rust=1
|
|
fi
|
|
set -- "$@" cffi
|
|
;;
|
|
'greenlet113') (( $PYTHON_VERSION > 311 || $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ! $piwheels ) )) && aDEPS+=('g++');;
|
|
'libsass') (( $G_HW_ARCH == 10 || $piwheels )) || aDEPS+=('g++');;
|
|
'lxml') (( $G_HW_ARCH == 1 && ( ! $piwheels || $PYTHON_VERSION == 313 ) )) && aDEPS+=('libxslt1-dev');;
|
|
'matrix-synapse') (( $PYTHON_VERSION > 311 || $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ! $piwheels ) )) && rust=1;;
|
|
'netifaces') (( $piwheels || ( $G_HW_ARCH == 10 && $PYTHON_VERSION <= 39 ) )) || aDEPS+=('gcc');;
|
|
'numpy')
|
|
if (( $G_HW_ARCH == 11 || ( $G_HW_ARCH == 1 && ! $piwheels ) ))
|
|
then
|
|
aDEPS+=('g++' 'pkg-config' 'libopenblas-pthread-dev')
|
|
# cmake + make + automake > patchelf > meson-python > numpy
|
|
# cmake > ninja > meson-python > numpy
|
|
(( $G_HW_ARCH == 1 )) && aDEPS+=('cmake' 'make' 'automake')
|
|
fi
|
|
if (( $piwheels ))
|
|
then
|
|
aDEPS+=('libgfortran5' 'libopenblas0-pthread')
|
|
fi
|
|
;;
|
|
'pillow')
|
|
(( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ( ! $piwheels || $PYTHON_VERSION == 39 ) ) )) && aDEPS+=('gcc' 'libjpeg62-turbo-dev')
|
|
if (( $piwheels && $PYTHON_VERSION != 39 ))
|
|
then
|
|
aDEPS+=('libopenjp2-7' 'libxcb1')
|
|
(( $G_DISTRO > 6 )) && aDEPS+=('libtiff6') || aDEPS+=('libtiff5')
|
|
fi
|
|
;;
|
|
'poetry')
|
|
# cryptography > SecretStorage > keyring > poetry
|
|
set -- "$@" cryptography
|
|
;;
|
|
'psutil') (( $G_HW_ARCH < 3 || $G_HW_ARCH == 11 )) && aDEPS+=('gcc');;
|
|
'psycopg2') (( $piwheels && $PYTHON_VERSION != 39 )) || aDEPS+=('gcc' 'libpq-dev');;
|
|
'pycurl') (( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ! $piwheels ) )) && aDEPS+=('gcc' 'libcurl4-openssl-dev' 'libssl-dev');;
|
|
'pydantic')
|
|
# pydantic_core > pydantic
|
|
(( $G_HW_ARCH == 1 || $G_HW_ARCH == 11 )) && rust=1
|
|
;;
|
|
'pyenv')
|
|
# Required: gcc libc6-dev make libssl-dev zlib1g-dev
|
|
# Optional to suppress warnings: libbz2-dev libreadline-dev libsqlite3-dev liblzma-dev
|
|
# libffi-dev for the optional _ctypes module, needed at least for Home Assistant => include it in all pyenv builds to avoid surprises
|
|
aDEPS+=('gcc' 'libc6-dev' 'make' 'libssl-dev' 'zlib1g-dev' 'libbz2-dev' 'libreadline-dev' 'libsqlite3-dev' 'liblzma-dev' 'libffi-dev')
|
|
;;
|
|
'pymicro-vad') aDEPS+=('g++');;
|
|
'pynacl')
|
|
(( $G_HW_ARCH == 11 || ( $G_HW_ARCH < 3 && ! $piwheels ) )) && aDEPS+=('make')
|
|
set -- "$@" cffi
|
|
;;
|
|
*) G_DIETPI-NOTIFY 1 "Unknown argument \"$1\" for Python_Deps(). This should never happen unless you are developing a software implementation. Otherwise, please report this at https://github.com/MichaIng/DietPi/issues. Aborting ..."; exit 1;;
|
|
esac
|
|
shift
|
|
done
|
|
unset -v PYTHON_VERSION
|
|
|
|
# Install Rust if needed
|
|
if (( $rust ))
|
|
then
|
|
G_EXEC curl -sSfo rustup-init.sh 'https://sh.rustup.rs'
|
|
G_EXEC chmod +x rustup-init.sh
|
|
# ARMv6 Bullseye: rustup-init depends on libatomic1, not assured to be pre-installed on Bullseye
|
|
(( $G_HW_ARCH == 1 && $G_DISTRO == 6 )) && G_AGI libatomic1 "${aDEPS[@]}" && aDEPS=() install=0
|
|
G_EXEC_OUTPUT=1 G_EXEC ${user:+runuser -u "$user" --} ./rustup-init.sh -y --profile minimal
|
|
G_EXEC rm rustup-init.sh
|
|
[[ $user ]] || export PATH="/root/.cargo/bin:$PATH"
|
|
fi
|
|
|
|
[[ ${aDEPS[*]} ]] || return 0
|
|
|
|
# Deduplicate
|
|
declare -A dedupe
|
|
for i in "${aDEPS[@]}"; do dedupe["$i"]=; done
|
|
aDEPS=("${!dedupe[@]}")
|
|
|
|
# Return or install packages
|
|
(( $install )) || return 0
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
}
|
|
|
|
To_Install()
|
|
{
|
|
(( ${aSOFTWARE_INSTALL_STATE[$1]} == 1 )) || return 1
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "Installing ${aSOFTWARE_NAME[$1]}: ${aSOFTWARE_DESC[$1]}"
|
|
aDEPS=() # failsafe
|
|
software_id=$1
|
|
shift
|
|
[[ $1 ]] || return 0
|
|
[[ $(readlink -m "/etc/systemd/system/$1.service") == '/dev/null' ]] && G_EXEC systemctl --no-reload unmask "$1"
|
|
aENABLE_SERVICES+=("$@")
|
|
}
|
|
|
|
if To_Install 4 # fish
|
|
then
|
|
G_AGI fish
|
|
# Create DietPi source script
|
|
G_EXEC mkdir -p /etc/fish/conf.d
|
|
# - Run only if interactive
|
|
G_EXEC eval 'echo '\''if status is-interactive'\'' > /etc/fish/conf.d/dietpi.fish'
|
|
# - Take aliases from /etc/bashrc.d/dietpi.bash
|
|
mawk '/# - DietPi programs/ {flag=1; next}
|
|
/# - Optional DietPi software aliases/ {flag=0}
|
|
flag {print}' /etc/bashrc.d/dietpi.bash >> /etc/fish/conf.d/dietpi.fish
|
|
# - Launch dietpi-login script for first run setup and autostart features
|
|
cat << '_EOF_' >> /etc/fish/conf.d/dietpi.fish
|
|
function fish_greeting
|
|
/boot/dietpi/dietpi-login
|
|
end
|
|
end
|
|
_EOF_
|
|
G_EXEC chsh root -s /usr/bin/fish
|
|
getent passwd dietpi &> /dev/null && G_EXEC chsh dietpi -s /usr/bin/fish
|
|
fi
|
|
|
|
if To_Install 5 # ALSA
|
|
then
|
|
# Get chosen sound card, use default if unset or "none"
|
|
local soundcard=$(sed -n '/^[[:blank:]]*CONFIG_SOUNDCARD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ ! $soundcard || $soundcard == 'none' ]] && soundcard='default'
|
|
|
|
# Apply: Installs "alsa-utils"
|
|
/boot/dietpi/func/dietpi-set_hardware soundcard "$soundcard"
|
|
fi
|
|
|
|
if To_Install 6 # X11
|
|
then
|
|
# Generic X server and utilities
|
|
aDEPS=('xserver-xorg-core' 'xserver-xorg-input-libinput' 'xinit' 'dbus-user-session' 'xfonts-base' 'x11-xserver-utils' 'x11-utils')
|
|
|
|
# Pre-create config dir: https://dietpi.com/forum/t/19963
|
|
G_EXEC mkdir -p /etc/X11/xorg.conf.d
|
|
|
|
# RPi
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
# Add fbdev display driver for legacy framebuffer graphics support, as modesetting requires KMS driver overlay for /dev/dri/card0 to exists.
|
|
aDEPS+=('xserver-xorg-video-fbdev')
|
|
# RPi 5: Add config to force X11 using the correct DRM device: https://forums.raspberrypi.com/viewtopic.php?t=358853
|
|
(( $G_HW_MODEL == 5 )) && cat << '_EOF_' > /etc/X11/xorg.conf.d/02-dietpi-rpi5.conf
|
|
Section "OutputClass"
|
|
Identifier "vc4"
|
|
MatchDriver "vc4"
|
|
Driver "modesetting"
|
|
Option "PrimaryGPU" "true"
|
|
EndSection
|
|
_EOF_
|
|
# x86_64 VM
|
|
elif (( $G_HW_ARCH == 10 && $G_HW_MODEL == 20 ))
|
|
then
|
|
# If KMS/DRM is supported, add VMware DDX, which offers slightly better performance compared to modesetting. VirtualBox can emulate it as well, which is even the nowadays recommended default.
|
|
# Else (e.g. Hyper-V) add classic framebuffer DDX
|
|
[[ -d '/dev/dri' ]] && aDEPS+=('xserver-xorg-video-vmware') || aDEPS+=('xserver-xorg-video-fbdev')
|
|
|
|
# Amlogic S905
|
|
elif [[ $G_HW_CPUID == 7 && -d '/dev/dri' ]]
|
|
then
|
|
cat << '_EOF_' > /etc/X11/xorg.conf.d/02-dietpi-aml-s905.conf
|
|
Section "OutputClass"
|
|
Identifier "Amlogic"
|
|
MatchDriver "meson"
|
|
Driver "modesetting"
|
|
Option "PrimaryGPU" "true"
|
|
EndSection
|
|
Section "Screen"
|
|
Identifier "Default Screen"
|
|
Device "Meson"
|
|
Monitor "foo"
|
|
DefaultDepth 24
|
|
SubSection "Display"
|
|
Depth 24
|
|
Modes "1920x1080" "1440x900" "1280x720" "1280x1024" "1280x960" "1024x768" "800x600" "640x480" "720x400"
|
|
EndSubSection
|
|
EndSection
|
|
_EOF_
|
|
fi
|
|
|
|
# Disable DPMS and screen blanking
|
|
cat << '_EOF_' > /etc/X11/xorg.conf.d/98-dietpi-disable_dpms.conf
|
|
Section "Extensions"
|
|
Option "DPMS" "Disable"
|
|
EndSection
|
|
Section "ServerFlags"
|
|
Option "BlankTime" "0"
|
|
EndSection
|
|
_EOF_
|
|
# Install packages
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
fi
|
|
|
|
if To_Install 191 snapserver # Snapcast Server
|
|
then
|
|
# RISC-V: Install from Debian repo: https://github.com/snapcast/snapcast/releases
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
G_AGI snapserver
|
|
|
|
# Install and enable snapweb web UI, not included in Debian's snapserver package: https://github.com/MichaIng/DietPi/issues/7073
|
|
local fallback_url='https://github.com/snapcast/snapweb/releases/download/v0.9.2/snapweb_0.9.2-1_all.deb'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/snapcast/snapweb/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/snapweb_[^"\/]*_all.deb"$/{print $4}')"
|
|
G_CONFIG_INJECT 'doc_root[[:blank:]=]' 'doc_root = /usr/share/snapweb' /etc/snapserver.conf '\[http\]'
|
|
|
|
# Fix /var/lib/snapserver permissions, just in case snapcast's package was previously used, which uses the "snapserver" user, instead of "_snapserver"
|
|
[[ -d '/var/lib/snapserver' ]] && G_EXEC chown -R '_snapserver:_snapserver' /var/lib/snapserver
|
|
getent passwd snapserver > /dev/null && G_EXEC userdel snapserver
|
|
else
|
|
local arch=$(dpkg --print-architecture)
|
|
local dist=${G_DISTRO_NAME/forky/trixie}
|
|
local fallback_url="https://github.com/snapcast/snapcast/releases/download/v0.34.0/snapserver_0.34.0-1_${arch}_$dist.deb"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/snapcast/snapcast/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/snapserver_[^\"\/]*_${arch}_$dist.deb\"$/{print \$4}")"
|
|
|
|
# Fix /var/lib/snapserver permissions, just in case Debian's package was previously used, which uses the "_snapserver" user, instead of "snapserver"
|
|
[[ -d '/var/lib/snapserver' ]] && G_EXEC chown -R 'snapserver:snapserver' /var/lib/snapserver
|
|
getent passwd _snapserver > /dev/null && G_EXEC userdel _snapserver
|
|
fi
|
|
G_EXEC systemctl stop snapserver
|
|
|
|
# Disable JSON RPC by default if setting was never touched yet
|
|
G_EXEC sed --follow-symlinks -i '/^\[tcp\]/,/^\[/s/^#enabled = true$/enabled = false/' /etc/snapserver.conf
|
|
fi
|
|
|
|
if To_Install 192 snapclient # Snapcast Client
|
|
then
|
|
# RISC-V: Install from Debian repo: https://github.com/snapcast/snapcast/releases
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
G_AGI snapclient
|
|
else
|
|
local arch=$(dpkg --print-architecture)
|
|
local dist=${G_DISTRO_NAME/forky/trixie}
|
|
local fallback_url="https://github.com/snapcast/snapcast/releases/download/v0.34.0/snapclient_0.34.0-1_${arch}_$dist.deb"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/snapcast/snapcast/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/snapclient_[^\"\/]*_${arch}_$dist.deb\"$/{print \$4}")"
|
|
fi
|
|
G_EXEC systemctl stop snapclient
|
|
|
|
# Config: Skip it host has been applied before. ToDo: v0.32.0 deprecated "--host"/"--port" in favour of "host:port" URI argument. But v0.31.0 from Debian does not support this yet.
|
|
if ! grep -q '^[[:blank:]]*SNAPCLIENT_OPTS=.*["[:blank:]]-h[[:blank:]]' /etc/default/snapclient
|
|
then
|
|
# Ask for server, use local one by default if installed
|
|
dpkg-query -s 'snapserver' &> /dev/null && G_WHIP_DEFAULT_ITEM='127.0.0.1'
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX 'Please enter the IP address or hostname of your Snapcast server to connect this client to:'
|
|
if [[ $G_WHIP_RETURNED_VALUE ]]
|
|
then
|
|
local snapcast_server_host=$G_WHIP_RETURNED_VALUE
|
|
|
|
G_WHIP_DEFAULT_ITEM=1704 G_WHIP_NOCANCEL=1 G_WHIP_INPUTBOX_REGEX='^[1-9][0-9]*$' G_WHIP_INPUTBOX_REGEX_TEXT='a valid port number'
|
|
G_WHIP_INPUTBOX 'Please enter the network port of your Snapcast server (default: 1704):'
|
|
local snapcast_server_port=$G_WHIP_RETURNED_VALUE
|
|
|
|
G_CONFIG_INJECT 'SNAPCLIENT_OPTS=' "SNAPCLIENT_OPTS=\"-h $snapcast_server_host -p $snapcast_server_port\"" /etc/default/snapclient
|
|
fi
|
|
fi
|
|
|
|
# If no Snapcast server was defined explicitly, e.g. on unattended install without having the server installed first, server and client use Avahi to find each other.
|
|
# The client throws endless errors if Avahi is not running, and endless messages until the server announced itself: https://github.com/snapcast/snapcast/issues/647
|
|
# Hence Avahi-Daemon is added as fixed dependency for the server, and added for the client hereby if no server was explicitly defined. But is this as fallback only for unattended installs.
|
|
if ! grep -q '^[[:blank:]]*SNAPCLIENT_OPTS=.*["[:blank:]]-h[[:blank:]]' /etc/default/snapclient
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Adding Avahi-Daemon as dependency for the Snapcast client to be able to auto-detect a server'
|
|
aSOFTWARE_INSTALL_STATE[152]=1
|
|
fi
|
|
fi
|
|
|
|
if To_Install 152 avahi-daemon # Avahi-Daemon
|
|
then
|
|
G_AGI avahi-daemon
|
|
G_EXEC systemctl stop avahi-daemon
|
|
fi
|
|
|
|
if To_Install 17 # Git
|
|
then
|
|
G_AGI git
|
|
fi
|
|
|
|
if To_Install 3 # Midnight Commander
|
|
then
|
|
G_AGI mc
|
|
fi
|
|
|
|
if To_Install 0 # OpenSSH Client
|
|
then
|
|
G_AGI openssh-client
|
|
fi
|
|
|
|
if To_Install 1 # Samba Client
|
|
then
|
|
G_AGI cifs-utils smbclient
|
|
fi
|
|
|
|
if To_Install 110 # NFS Client
|
|
then
|
|
# "netbase" is required for mounting NFSv3 and showmount to solve "clnt_create: RPC: Unknown host": https://github.com/MichaIng/DietPi/issues/1898#issuecomment-406247814
|
|
G_AGI nfs-common netbase
|
|
fi
|
|
|
|
if To_Install 104 dropbear # Dropbear
|
|
then
|
|
# Stop OpenSSH service to unbind port 22
|
|
systemctl -q is-active ssh && G_EXEC systemctl stop ssh
|
|
|
|
G_AGI dropbear
|
|
|
|
# Enable Dropbear daemon, obsolete since Bookworm
|
|
(( $G_DISTRO > 6 )) || G_CONFIG_INJECT 'NO_START=' 'NO_START=0' /etc/default/dropbear
|
|
|
|
# Apply password login setting from dietpi.txt or default (implies a restart)
|
|
# - Assure service is active
|
|
G_EXEC systemctl unmask dropbear
|
|
G_EXEC systemctl start dropbear
|
|
/boot/dietpi/func/dietpi-set_software disable_ssh_password_logins
|
|
|
|
# Mark OpenSSH for uninstall
|
|
dpkg-query -s 'openssh-server' &> /dev/null && aSOFTWARE_INSTALL_STATE[105]=-1
|
|
fi
|
|
|
|
if To_Install 105 ssh # OpenSSH Server
|
|
then
|
|
# Stop Dropbear service to unbind port 22
|
|
systemctl -q is-active dropbear && G_EXEC systemctl stop dropbear
|
|
|
|
G_AGI openssh-server
|
|
|
|
# Apply password login setting from dietpi.txt or default (implies a restart)
|
|
# - Assure service is active
|
|
G_EXEC systemctl unmask ssh
|
|
G_EXEC systemctl start ssh
|
|
/boot/dietpi/func/dietpi-set_software disable_ssh_password_logins
|
|
|
|
# Mark Dropbear for uninstall
|
|
dpkg-query -s 'dropbear' &> /dev/null || dpkg-query -s 'dropbear-run' &> /dev/null && aSOFTWARE_INSTALL_STATE[104]=-1
|
|
fi
|
|
|
|
if To_Install 194 postgresql # PostgreSQL
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Preparing database directory at: /mnt/dietpi_userdata/postgresql'
|
|
if [[ -d '/mnt/dietpi_userdata/postgresql' ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 '/mnt/dietpi_userdata/postgresql exists, will migrate containing databases'
|
|
|
|
else
|
|
# Otherwise use possibly existent /var/lib/postgresql
|
|
# - Remove possible dead symlinks/files:
|
|
G_EXEC rm -f /mnt/dietpi_userdata/postgresql
|
|
if [[ -d '/var/lib/postgresql' ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 '/var/lib/postgresql exists, will migrate containing databases'
|
|
# Failsafe: Move symlink target in case, otherwise readlink will resolve to dir
|
|
G_EXEC mv "$(readlink -f '/var/lib/postgresql')" /mnt/dietpi_userdata/postgresql
|
|
|
|
else
|
|
|
|
G_EXEC mkdir /mnt/dietpi_userdata/postgresql
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
G_EXEC rm -Rf /var/lib/postgresql
|
|
G_EXEC ln -s /mnt/dietpi_userdata/postgresql /var/lib/postgresql
|
|
|
|
G_AGI postgresql
|
|
G_EXEC systemctl stop postgresql
|
|
|
|
# Disable TCP/IP listener and assure that UNIX domain socket is enabled at expected path
|
|
for i in /etc/postgresql/*/main/conf.d
|
|
do
|
|
[[ -d $i ]] || continue
|
|
echo "# Disable TCP listener and assure that UNIX socket is enabled at expected path
|
|
# NB: Do not edit this file, instead override settings via e.g.: conf.d/99local.conf
|
|
listen_addresses = ''
|
|
unix_socket_directories = '/run/postgresql'" > "$i/00dietpi.conf"
|
|
done
|
|
fi
|
|
|
|
if To_Install 103 dietpi-ramlog # DietPi-RAMlog
|
|
then
|
|
# Install persistent tmpfs
|
|
local var_log_size=$(sed -n '/^[[:blank:]]*AUTO_SETUP_RAMLOG_MAXSIZE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
sed --follow-symlinks -i '/[[:blank:]]\/var\/log[[:blank:]]/d' /etc/fstab
|
|
echo "tmpfs /var/log tmpfs size=${var_log_size:-50}M,noatime,lazytime,nodev,nosuid" >> /etc/fstab
|
|
|
|
# Apply logging choice index
|
|
[[ $INDEX_LOGGING == -[12] ]] || INDEX_LOGGING=-1
|
|
|
|
# Sync logs to disk once
|
|
local acommand=('/boot/dietpi/func/dietpi-ramlog' '1')
|
|
systemctl -q is-active dietpi-ramlog && acommand=('systemctl' 'stop' 'dietpi-ramlog')
|
|
G_EXEC_DESC='Storing /var/log metadata to disk' G_EXEC "${acommand[@]}"
|
|
unset -v acommand
|
|
|
|
# Cleanup mount point
|
|
findmnt /var/log > /dev/null && G_EXEC_DESC='Unmounting /var/log' G_EXEC_NOHALT=1 G_EXEC umount -Rfl /var/log
|
|
G_EXEC_DESC='Cleaning /var/log mount point' G_EXEC rm -Rf /var/log/{,.??,.[^.]}*
|
|
|
|
# Start DietPi-RAMlog
|
|
G_EXEC_DESC='Mounting tmpfs to /var/log' G_EXEC mount /var/log
|
|
G_EXEC_DESC='Restoring metadata to /var/log tmpfs' G_EXEC systemctl start dietpi-ramlog
|
|
fi
|
|
|
|
if To_Install 101 # Logrotate
|
|
then
|
|
G_AGI logrotate
|
|
fi
|
|
|
|
if To_Install 190 # Beets
|
|
then
|
|
# Config: Preserve existing on reinstall
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/beets
|
|
[[ -f '/mnt/dietpi_userdata/beets/config.yaml' ]] || G_EXEC eval 'echo -e '\''directory: /mnt/dietpi_userdata/Music\nlibrary: /mnt/dietpi_userdata/beets/library.db'\'' > /mnt/dietpi_userdata/beets/config.yaml'
|
|
|
|
# Allow dietpi user and audio group members to manage library
|
|
[[ -f '/mnt/dietpi_userdata/beets/library.db' ]] || > /mnt/dietpi_userdata/beets/library.db
|
|
[[ -f '/mnt/dietpi_userdata/beets/state.pickle' ]] || > /mnt/dietpi_userdata/beets/state.pickle
|
|
# shellcheck disable=SC2015
|
|
getent passwd dietpi > /dev/null && G_EXEC chown -R dietpi:audio /mnt/dietpi_userdata/beets || G_EXEC chgrp -R audio /mnt/dietpi_userdata/beets
|
|
G_EXEC chmod -R g+w /mnt/dietpi_userdata/beets
|
|
|
|
# Load global beets config in all interactive bash shells
|
|
echo 'export BEETSDIR=/mnt/dietpi_userdata/beets' > /etc/bashrc.d/dietpi-beets.sh
|
|
# shellcheck disable=SC1091
|
|
. /etc/bashrc.d/dietpi-beets.sh
|
|
|
|
# Install
|
|
G_AGI beets
|
|
fi
|
|
|
|
if To_Install 102 rsyslog # Rsyslog
|
|
then
|
|
# Workaround for dpkg failure on 1st install if service is already running but APT not installed: https://github.com/MichaIng/DietPi/pull/2277/#issuecomment-441460925
|
|
systemctl -q is-active rsyslog && G_EXEC systemctl stop rsyslog
|
|
G_AGI rsyslog
|
|
G_EXEC systemctl start rsyslog
|
|
|
|
# Apply logging choice index
|
|
grep -q '[[:blank:]]/var/log[[:blank:]]' /etc/fstab || findmnt -t tmpfs -M /var/log > /dev/null || INDEX_LOGGING=-3
|
|
fi
|
|
|
|
if To_Install 7 # FFmpeg
|
|
then
|
|
# RPi: Enable hardware codecs
|
|
(( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1
|
|
|
|
G_AGI ffmpeg
|
|
fi
|
|
|
|
if To_Install 196 # Java JRE
|
|
then
|
|
local JAVA_VERSION=21
|
|
|
|
# ARMv6/7: Install Debian's OpenJDK packages since Adoptium does not support it
|
|
if (( $G_HW_ARCH < 3 ))
|
|
then
|
|
# ARMv6/Bullseye/Bookworm: Java 17 is the latest available one
|
|
(( $G_DISTRO < 8 || $G_HW_ARCH == 1 )) && JAVA_VERSION=17
|
|
|
|
G_AGI "openjdk-$JAVA_VERSION-jre-headless"
|
|
JAVA_PATH="/usr/lib/jvm/java-$JAVA_VERSION-openjdk-$(dpkg --print-architecture)/bin/java"
|
|
else
|
|
# APT key: https://adoptium.net/installation/linux
|
|
G_EXEC mkdir -p /etc/apt/keyrings
|
|
G_EXEC curl -sSfLo /etc/apt/keyrings/dietpi-adoptium.asc 'https://packages.adoptium.net/artifactory/api/gpg/key/public'
|
|
|
|
# APT source
|
|
G_EXEC eval "cat << '_EOF_' > /etc/apt/sources.list.d/dietpi-adoptium.sources
|
|
Types: deb
|
|
URIs: https://packages.adoptium.net/artifactory/deb
|
|
Suites: ${G_DISTRO_NAME/forky/trixie}
|
|
Components: main
|
|
Signed-By: /etc/apt/keyrings/dietpi-adoptium.asc"
|
|
G_AGUP
|
|
|
|
# Allow Debian's OpenJDK to be autopurged
|
|
G_EXEC apt-mark auto 'openjdk-*-jre-headless'
|
|
|
|
G_AGI "temurin-$JAVA_VERSION-jre"
|
|
JAVA_PATH="/usr/lib/jvm/temurin-$JAVA_VERSION-jre-$(dpkg --print-architecture)/bin/java"
|
|
fi
|
|
|
|
# Define some default max heap size here
|
|
local JAVA_MAX_HEAP_SIZE=$(( $RAM_PHYS / 5 ))
|
|
(( $JAVA_MAX_HEAP_SIZE < 200 )) && JAVA_MAX_HEAP_SIZE=200
|
|
# - On 32-bit systems the head size cannot be above 3 GiB
|
|
(( $G_HW_ARCH < 3 && $JAVA_MAX_HEAP_SIZE > 3072 )) && JAVA_MAX_HEAP_SIZE=3072
|
|
fi
|
|
|
|
if To_Install 8 # Java JDK
|
|
then
|
|
if (( $G_HW_ARCH < 3 ))
|
|
then
|
|
G_AGI "openjdk-$JAVA_VERSION-jdk-headless"
|
|
else
|
|
# Allow OpenJDK to be autopurged
|
|
G_EXEC apt-mark auto 'openjdk-*-jdk-headless'
|
|
|
|
G_AGI "temurin-$JAVA_VERSION-jdk"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 9 # Node.js
|
|
then
|
|
# Deps (verified 2025-10-22): https://github.com/MichaIng/DietPi/issues/3614, https://dietpi.com/forum/t/24574
|
|
(( $G_HW_ARCH == 1 && $G_DISTRO > 6 )) || aDEPS=('libatomic1')
|
|
|
|
# Download installer
|
|
Download_Install 'https://raw.githubusercontent.com/MichaIng/nodejs-linux-installer/master/node-install.sh'
|
|
G_EXEC chmod +x node-install.sh
|
|
|
|
# ARMv6/RISC-V: Use unofficial builds to get the latest version: https://github.com/MichaIng/nodejs-linux-installer/pull/2, https://github.com/MichaIng/nodejs-linux-installer/commit/cd952fe
|
|
local options=()
|
|
(( $G_HW_ARCH == 1 || $G_HW_ARCH == 11 )) && options=('-u')
|
|
# ARMv6/7 Bullseye: node: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.30'/`GLIBCXX_3.4.29' not found (required by node)
|
|
if (( $G_HW_ARCH < 3 && $G_DISTRO < 7 ))
|
|
then
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
version='v20.19.4' # newest ARMv6 builds which does not depend on GLIBCXX_3.4.30
|
|
else
|
|
local version=22 fallback='v22.21.0'
|
|
version=$(./node-install.sh -l | mawk "/^v$version/{print \$1;exit}")
|
|
[[ $version ]] || version=$fallback
|
|
fi
|
|
options+=('-v' "$version")
|
|
fi
|
|
G_EXEC_OUTPUT=1 G_EXEC ./node-install.sh "${options[@]}"
|
|
G_EXEC rm node-install.sh
|
|
fi
|
|
|
|
if To_Install 130 # Python 3
|
|
then
|
|
# Allow pip to install modules on system level, and mute the warning when doing so as root (which is needed, of course)
|
|
>> /etc/pip.conf
|
|
G_CONFIG_INJECT '\[global\]' '[global]' /etc/pip.conf
|
|
G_CONFIG_INJECT 'break-system-packages[[:blank:]]*=' 'break-system-packages=true' /etc/pip.conf '\[global\]'
|
|
G_CONFIG_INJECT 'root-user-action[[:blank:]]*=' 'root-user-action=ignore' /etc/pip.conf '\[global\]'
|
|
|
|
# Disable cache: It is rarely ever needed to install the very same module and version twice, hence this usually only causes unnecessary disk writes and usage.
|
|
G_CONFIG_INJECT 'no-cache-dir[[:blank:]]*=' 'no-cache-dir=true' /etc/pip.conf '\[global\]'
|
|
|
|
# ARMv6/7: Add piwheels
|
|
(( $G_HW_ARCH < 3 )) && G_CONFIG_INJECT 'extra-index-url[[:blank:]]*=' 'extra-index-url=https://www.piwheels.org/simple/' /etc/pip.conf '\[global\]'
|
|
|
|
# Perform pip3 install (which includes setuptools and wheel modules)
|
|
aDEPS=('python3-dev')
|
|
Download_Install 'https://bootstrap.pypa.io/get-pip.py'
|
|
G_EXEC_OUTPUT=1 G_EXEC python3 get-pip.py
|
|
G_EXEC rm get-pip.py
|
|
fi
|
|
|
|
if To_Install 150 # Mono: https://www.mono-project.com/download/stable/#download-lin-debian
|
|
then
|
|
# Trixie: Install from Debian repo instead: "mono-devel : Depends: libglib2.0-0 (>= 2.58.3) but it is not installable"
|
|
if (( $G_DISTRO < 8 ))
|
|
then
|
|
# APT key
|
|
G_EXEC curl -sSfL 'https://download.mono-project.com/repo/xamarin_ring.gpg' -o /etc/apt/trusted.gpg.d/dietpi-mono.gpg
|
|
|
|
# APT list
|
|
# - Only Buster suites are available: https://download.mono-project.com/repo/debian/dists/
|
|
# - On Raspbian use separate suite: https://github.com/MichaIng/DietPi/issues/1023
|
|
local suite='buster'
|
|
(( $G_RASPBIAN )) && suite='raspbianbuster'
|
|
G_EXEC eval "echo 'deb https://download.mono-project.com/repo/debian $suite main' > /etc/apt/sources.list.d/dietpi-mono.list"
|
|
G_AGUP
|
|
fi
|
|
|
|
# APT package
|
|
G_AGI mono-devel
|
|
|
|
# Cleanup: https://github.com/MichaIng/DietPi/issues/1877#issuecomment-403856446
|
|
G_EXEC rm -f /tmp/mono*
|
|
fi
|
|
|
|
if To_Install 188 # Go
|
|
then
|
|
# https://go.dev/doc/install#install
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='armv6l';;
|
|
esac
|
|
|
|
# Get latest version
|
|
local file=$(curl -sSfL 'https://go.dev/dl/?mode=json' | grep -o "go[0-9.]*\.linux-$arch\.tar\.gz" | head -1)
|
|
[[ $file ]] || { file="go1.25.5.linux-$arch.tar.gz"; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. \"$file\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
|
|
# Reinstall: Remove previous instance
|
|
[[ -d '/usr/local/go' ]] && G_EXEC rm -R /usr/local/go
|
|
|
|
Download_Install "https://dl.google.com/go/$file" /usr/local
|
|
|
|
# Add to PATH, but do not overwrite existing script since we did set GOPATH until v8.9 and do not want to cause a breaking change for existing installs
|
|
# shellcheck disable=SC2016
|
|
[[ -f '/etc/bashrc.d/go.sh' ]] || G_EXEC eval 'echo '\''export PATH="$PATH:/usr/local/go/bin"'\'' > /etc/bashrc.d/go.sh'
|
|
# shellcheck disable=SC1091
|
|
. /etc/bashrc.d/go.sh
|
|
|
|
# RISC-V pre-v8.24 and general failsafe action: Purge Go APT Package
|
|
dpkg-query -s 'golang-go' &> /dev/null && G_AGP golang-go
|
|
fi
|
|
|
|
if To_Install 170 # UnRAR
|
|
then
|
|
# On Raspbian, only "unrar-free" is available which does not support all RAR formats, thus we use "unrar" [non-free] from Debian on ARMv7+ models: http://raspbian.raspberrypi.com/raspbian/pool/non-free/u/unrar-nonfree/
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
G_AGI unrar-free
|
|
|
|
elif (( $G_RASPBIAN ))
|
|
then
|
|
Download_Install "https://dietpi.com/downloads/binaries/rpi/unrar-armhf-$G_DISTRO_NAME.deb"
|
|
else
|
|
G_AGI unrar
|
|
fi
|
|
fi
|
|
|
|
if To_Install 23 # LXDE
|
|
then
|
|
# LXDE pulls in LightDM as dependency, which sets up itself as display manager so that the system boots automatically into it. So check whether a default display manager is present first, and if not, remove it afterwards.
|
|
local display_manager=0
|
|
[[ -f '/etc/systemd/system/display-manager.service' ]] && display_manager=1
|
|
|
|
# librsvg2-common: https://github.com/MichaIng/DietPi/issues/4687
|
|
G_AGI lxde lxhotkey-plugin-openbox upower librsvg2-common
|
|
|
|
[[ $display_manager == 0 && -f '/etc/systemd/system/display-manager.service' ]] && G_EXEC rm /etc/systemd/system/display-manager.service
|
|
|
|
# lxpanel
|
|
G_EXEC curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/lxde/panel" -o /etc/xdg/lxpanel/LXDE/panels/panel
|
|
# - Adjust Firefox app icon if it is not installed
|
|
if (( ${aSOFTWARE_INSTALL_STATE[67]} < 1 ))
|
|
then
|
|
# Chromium
|
|
if (( ${aSOFTWARE_INSTALL_STATE[113]} > 0 ))
|
|
then
|
|
local chromium='chromium'
|
|
(( $G_DISTRO < 7 && $G_HW_MODEL < 10 )) && chromium='chromium-browser'
|
|
G_EXEC sed --follow-symlinks -i "s/firefox-esr/$chromium/" /etc/xdg/lxpanel/LXDE/panels/panel
|
|
else
|
|
G_EXEC sed --follow-symlinks -i 's/firefox-esr/mousepad/' /etc/xdg/lxpanel/LXDE/panels/panel
|
|
fi
|
|
fi
|
|
|
|
# Openbox: Enable only one desktop and disable icon animations
|
|
G_CONFIG_INJECT '<number>[0-9]*</number>' '<number>1</number>' /etc/xdg/openbox/LXDE/rc.xml '<desktops>'
|
|
G_CONFIG_INJECT '<animateIconify>.*</animateIconify>' '<animateIconify>no</animateIconify>' /etc/xdg/openbox/LXDE/rc.xml '<theme>'
|
|
|
|
# PCmanFM: Set wallpaper and desktop icon text shadow color
|
|
G_CONFIG_INJECT '\[desktop\]' '[desktop]' /etc/xdg/pcmanfm/LXDE/pcmanfm.conf
|
|
G_CONFIG_INJECT 'wallpaper_mode=' 'wallpaper_mode=fit' /etc/xdg/pcmanfm/LXDE/pcmanfm.conf '\[desktop\]'
|
|
G_CONFIG_INJECT 'wallpaper=' 'wallpaper=/var/lib/dietpi/dietpi-software/installed/desktop/wallpapers/dietpi-logo_inverted_1080p.png' /etc/xdg/pcmanfm/LXDE/pcmanfm.conf '\[desktop\]'
|
|
G_CONFIG_INJECT 'desktop_shadow=' 'desktop_shadow=#333333' /etc/xdg/pcmanfm/LXDE/pcmanfm.conf '\[desktop\]'
|
|
|
|
# Apply better default icon theme: nuoveXT2 has more individual icons than Adwaita, but lower resolution and overrides the Firefox application icon with an old low res version.
|
|
G_CONFIG_INJECT 'sNet/IconThemeName=' 'sNet/IconThemeName=Adwaita' /etc/xdg/lxsession/LXDE/desktop.conf '\[GTK\]'
|
|
|
|
# Workaround for "No session for pid" error: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=864402
|
|
G_CONFIG_INJECT 'polkit/command=' 'polkit/command=' /etc/xdg/lxsession/LXDE/desktop.conf '\[Session\]'
|
|
|
|
# Disable trash
|
|
G_CONFIG_INJECT 'use_trash=' 'use_trash=0' /etc/xdg/libfm/libfm.conf '\[config\]'
|
|
|
|
# Execute desktop icons and executable files directly without asking what to do
|
|
G_CONFIG_INJECT 'quick_exec=' 'quick_exec=1' /etc/xdg/libfm/libfm.conf '\[config\]'
|
|
|
|
Create_Desktop_Shared_Items
|
|
fi
|
|
|
|
if To_Install 173 # LXQt
|
|
then
|
|
# SpeedCrunch has been removed from Debian since Trixie: https://tracker.debian.org/pkg/speedcrunch
|
|
local speedcrunch=('speedcrunch')
|
|
(( $G_DISTRO > 7 )) && speedcrunch=()
|
|
# lxqt-archiver is the default dependency from Trixie on, but our config uses Archiver=xarchiver.
|
|
G_AGI lxqt xarchiver xscreensaver "${speedcrunch[@]}"
|
|
|
|
# Configs
|
|
Download_Install "https://github.com/$G_GITOWNER/DietPi/raw/$G_GITBRANCH/.conf/desktop/lxqt/lxqt-$G_DISTRO_NAME.7z" /etc/xdg/
|
|
|
|
Create_Desktop_Shared_Items
|
|
|
|
# Composition manager: LXQt has one integrated with xfwm4, which is blocked by xcompmgr, breaking settings and leading to ugly results: https://github.com/MichaIng/DietPi/issues/3665
|
|
[[ -f '/etc/xdg/autostart/xcompmgr.desktop' ]] && G_EXEC rm /etc/xdg/autostart/xcompmgr.desktop
|
|
fi
|
|
|
|
if To_Install 24 # MATE
|
|
then
|
|
# Add xterm, as the mate-terminal is not compatible with desktop console shortcuts: https://github.com/MichaIng/DietPi/issues/3160#issuecomment-828305136
|
|
G_AGI mate-desktop-environment-core mate-media upower xterm
|
|
|
|
Create_Desktop_Shared_Items
|
|
fi
|
|
|
|
if To_Install 26 # GNUstep
|
|
then
|
|
G_AGI wmaker gnustep gnustep-devel gnustep-games xterm
|
|
|
|
Create_Desktop_Shared_Items
|
|
fi
|
|
|
|
if To_Install 25 # Xfce
|
|
then
|
|
# Elevated permissions for non-root users to perform e.g. reboot and shutdown from logout menu
|
|
local polkit='polkitd'
|
|
(( $G_DISTRO < 7 )) && polkit='policykit-1'
|
|
|
|
G_AGI xfce4 xfce4-terminal gnome-icon-theme tango-icon-theme upower "$polkit"
|
|
|
|
Create_Desktop_Shared_Items
|
|
|
|
# Composition manager: Xfce has one integrated with xfwm4, which is blocked by xcompmgr, breaking settings and leading to ugly results: https://github.com/MichaIng/DietPi/issues/3665
|
|
[[ -f '/etc/xdg/autostart/xcompmgr.desktop' ]] && G_EXEC rm /etc/xdg/autostart/xcompmgr.desktop
|
|
fi
|
|
|
|
if To_Install 175 # Xfce Power Manager
|
|
then
|
|
G_AGI xfce4-power-manager
|
|
fi
|
|
|
|
if To_Install 22 # QuiteRSS
|
|
then
|
|
G_AGI quiterss
|
|
fi
|
|
|
|
if To_Install 67 # Firefox
|
|
then
|
|
# libpci3: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=993308
|
|
G_AGI firefox-esr libpci3
|
|
|
|
# Config
|
|
#G_CONFIG_INJECT 'pref\("extensions.update.enabled"' 'pref("extensions.update.enabled", false);' /etc/firefox-esr/firefox-esr.js
|
|
#G_CONFIG_INJECT 'pref\("datareporting.healthreport.uploadEnabled"' 'pref("datareporting.healthreport.uploadEnabled", false);' /etc/firefox-esr/firefox-esr.js
|
|
#G_CONFIG_INJECT 'pref\("browser.cache.disk.parent_directory"' 'pref("browser.cache.disk.parent_directory", "/tmp/firefox_cache");' /etc/firefox-esr/firefox-esr.js
|
|
#G_CONFIG_INJECT 'pref\("general.smoothScroll"' 'pref("general.smoothScroll", false);' /etc/firefox-esr/firefox-esr.js
|
|
fi
|
|
|
|
if To_Install 174 # GIMP
|
|
then
|
|
G_AGI gimp
|
|
fi
|
|
|
|
if To_Install 29 # XRDP
|
|
then
|
|
G_AGI xrdp xorgxrdp
|
|
aSTART_SERVICES+=('xrdp')
|
|
|
|
# Workaround for failing mouse and keyboard input: https://github.com/neutrinolabs/xorgxrdp/issues/164
|
|
# - Solved on Bookworm, but G_CONFIG_INJECT detects and skips it then, and keeping it covers dist-upgraded systems.
|
|
GGI_PRESERVE=1 G_CONFIG_INJECT 'Option[[:blank:]]+"DefaultServerLayout"' ' Option "DefaultServerLayout" "X11 Server"' /etc/X11/xrdp/xorg.conf 'Section[[:blank:]]+"ServerFlags"'
|
|
|
|
# Enable TLS with snakeoil certificate: https://github.com/MichaIng/DietPi/issues/5976
|
|
G_EXEC usermod -aG ssl-cert xrdp
|
|
fi
|
|
|
|
if To_Install 30 # NoMachine
|
|
then
|
|
case $G_HW_ARCH in
|
|
1) local url='raspberry/v6/deb/nomachine_latest_armv6hf';;
|
|
2) local url='arm/v7/deb/nomachine_latest_armhf';;
|
|
3) local url='arm/v8/deb/nomachine_latest_arm64';;
|
|
*) local url='linux/64/deb/nomachine_latest_amd64';;
|
|
esac
|
|
Download_Install "https://www.nomachine.com/free/$url.deb"
|
|
aSTART_SERVICES+=('nxserver')
|
|
fi
|
|
|
|
if To_Install 200 # DietPi-Dashboard
|
|
then
|
|
G_WHIP_MSG '[ WARN ] Reworked DietPi-Dashboard beta version
|
|
\nYou are about to install a reworked beta version of the DietPi-Dashboard which has not undergone much testing yet. Please assure to close its network ports (default: TCP 5252 and 5253) on your NAT/router or via firewall, to protect them from public access.
|
|
\nIf you need to access the DietPi-Dashboard remotely, please use a VPN server on this system, like WireGuard.
|
|
\nIf the old version is currently installed, it will remain on the system but its service is disabled. So you can switch between the versions for now, if needed. They use different config files and executables.'
|
|
|
|
# Stable release or nightly?
|
|
local version='Nightly' # Enforce nightly until 0.7.0 is released
|
|
#local version=$(sed -n '/^[[:blank:]]*SOFTWARE_DIETPI_DASHBOARD_VERSION=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
#[[ $version == 'Nightly' ]] || version='Stable'
|
|
|
|
#G_WHIP_MENU_ARRAY=(
|
|
# 'Stable' ': Use a release version of DietPi-Dashboard.'
|
|
# 'Nightly' ': Use an unstable version of DietPi-Dashboard.'
|
|
#)
|
|
#G_WHIP_DEFAULT_ITEM=$version
|
|
#G_WHIP_BUTTON_CANCEL_TEXT=$version
|
|
#G_WHIP_MENU 'Please choose which version of DietPi-Dashboard should be installed.' && version=$G_WHIP_RETURNED_VALUE
|
|
|
|
# Determine which components to install
|
|
local components=('backend')
|
|
local backend=$(sed -n '/^[[:blank:]]*SOFTWARE_DIETPI_DASHBOARD_BACKEND=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
|
|
[[ $backend == 1 ]] && G_WHIP_DEFAULT_ITEM='Backend' || G_WHIP_DEFAULT_ITEM='Frontend'
|
|
G_WHIP_MENU_ARRAY=(
|
|
'Backend' ': Install the DietPi-Dashboard backend only.'
|
|
'Frontend' ': Install both the DietPi-Dashboard backend and webserver.'
|
|
)
|
|
G_WHIP_MENU 'DietPi-Dashboard has two components, a frontend and a backend.
|
|
\nThe frontend is required to be installed on at least one node to view the webpage. The backend must be installed on all nodes.'
|
|
|
|
[[ $G_WHIP_RETURNED_VALUE == 'Backend' ]] || components+=('frontend')
|
|
|
|
# Download binary/binaries
|
|
if [[ $version == 'Nightly' ]]
|
|
then
|
|
command -v unzip > /dev/null || G_AGI unzip # G_CHECK_URL => HEAD request on nightly.link always returns 404, hence prevent Download_Install() from doing concurrent unzip install, which forks the download into background and runs G_CHECK_URL first.
|
|
|
|
for component in "${components[@]}"; do
|
|
Download_Install "https://nightly.link/nonnorm/DietPi-Dashboard/workflows/push-build/main/dietpi-dashboard-$G_HW_ARCH_NAME-$component.zip" /opt/dietpi-dashboard
|
|
done
|
|
else
|
|
# NB: Will not work until 0.7.0 is released
|
|
local manifest
|
|
# shellcheck disable=SC2016
|
|
G_EXEC eval 'manifest=$(curl -sSfL '\''https://api.github.com/repos/nonnorm/dietpi-dashboard/releases/latest'\'')'
|
|
for component in "${components[@]}"; do
|
|
Download_Install "$(echo "$manifest" | mawk -F\" "/^ *\"browser_download_url\": \".*dietpi-dashboard-$G_HW_ARCH_NAME-$component\"$/{print \$4}")" /opt/dietpi-dashboard
|
|
done
|
|
fi
|
|
|
|
# Users
|
|
Create_User dietpi-dashboard-frontend
|
|
|
|
# Services
|
|
G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/systemd/system/dietpi-dashboard-backend.service
|
|
[Unit]
|
|
Description=Dashboard Backend (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
ExecStart=/opt/dietpi-dashboard/backend
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_'
|
|
[[ ${components[1]} ]] && G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/systemd/system/dietpi-dashboard-frontend.service
|
|
[Unit]
|
|
Description=Dashboard Web Server (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=dietpi-dashboard-frontend
|
|
ExecStart=/opt/dietpi-dashboard/frontend
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
PrivateTmp=true
|
|
ProtectKernelTunables=true
|
|
ProtectKernelModules=true
|
|
ProtectControlGroups=true
|
|
NoNewPrivileges=true
|
|
ReadWritePaths=-/opt/dietpi-dashboard
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_'
|
|
# Derive based on existing backend config (since the backend is always installed) whether this is a new instance or a reinstall, so we know whether to pre-configure it
|
|
local new_instance=0
|
|
[[ -f '/opt/dietpi-dashboard/config-backend.toml' ]] || new_instance=1
|
|
|
|
# Pre-create empty frontend config with needed owner
|
|
[[ ${components[1]} && $new_instance == 1 ]] && G_EXEC install -m 0640 -o dietpi-dashboard-frontend /dev/null /opt/dietpi-dashboard/config-frontend.toml
|
|
|
|
for component in "${components[@]}"; do
|
|
G_EXEC chmod +x "/opt/dietpi-dashboard/$component"
|
|
CREATE_CONFIG_CONTENT='.' Create_Config "/opt/dietpi-dashboard/config-$component.toml" "dietpi-dashboard-$component"
|
|
aSTART_SERVICES+=("dietpi-dashboard-$component")
|
|
done
|
|
|
|
# Config: Touch for new instances only
|
|
if (( $new_instance ))
|
|
then
|
|
# If frontend is installed
|
|
if [[ ${components[1]} ]]
|
|
then
|
|
# Enable TLS OOTB with self-signed certificate
|
|
G_DIETPI-NOTIFY 2 'Generating a self-signed HTTPS certificate for the DietPi-Dashboard ...'
|
|
openssl req -reqexts SAN -subj '/CN=DietPi-Dashboard' -config <(cat /etc/ssl/openssl.cnf <(echo -ne "[SAN]\nsubjectAltName=DNS:$(</etc/hostname),IP:$(G_GET_NET ip)\nbasicConstraints=CA:TRUE,pathlen:0"))\
|
|
-x509 -days 7200 -sha256 -extensions SAN -out /opt/dietpi-dashboard/cert.pem\
|
|
-newkey ec:<(openssl ecparam -name prime256v1) -nodes -keyout /opt/dietpi-dashboard/privkey.pem || exit 1 # Replace deprecated -nodes with -noenc when dropping Bullseye support
|
|
G_EXEC chown dietpi-dashboard-frontend /opt/dietpi-dashboard/{cert,privkey}.pem
|
|
G_CONFIG_INJECT 'cert_path[[:blank:]]' 'cert_path = "/opt/dietpi-dashboard/cert.pem"' /opt/dietpi-dashboard/config-frontend.toml
|
|
G_CONFIG_INJECT 'key_path[[:blank:]]' 'key_path = "/opt/dietpi-dashboard/privkey.pem"' /opt/dietpi-dashboard/config-frontend.toml
|
|
G_CONFIG_INJECT 'enable_tls[[:blank:]]' 'enable_tls = true' /opt/dietpi-dashboard/config-frontend.toml
|
|
|
|
# Enable password authentication OOTB with default software password
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'hash[[:blank:]]' "hash = \"$(echo -n "$GLOBAL_PW" | sha512sum | mawk '{print $1}')\"" /opt/dietpi-dashboard/config-frontend.toml
|
|
G_CONFIG_INJECT 'enable_login[[:blank:]]' 'enable_login = true' /opt/dietpi-dashboard/config-frontend.toml
|
|
|
|
# Create and assign a new random secret to match frontend and backend
|
|
local secret=$(openssl rand -hex 32)
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'secret[[:blank:]]' "secret = \"$secret\"" /opt/dietpi-dashboard/config-frontend.toml
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'secret[[:blank:]]' "secret = \"$secret\"" /opt/dietpi-dashboard/config-backend.toml
|
|
unset -v secret
|
|
else
|
|
# Ask for frontend address to connect
|
|
G_WHIP_DEFAULT_ITEM="$(G_GET_NET gateway):5253"
|
|
G_WHIP_INPUTBOX_REGEX='^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9]):[1-9][0-9]+$'
|
|
G_WHIP_INPUTBOX_REGEX_TEXT="match the format \"<ip/hostname>:<port>\", e.g. \"$G_WHIP_DEFAULT_ITEM\""
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
G_WHIP_INPUTBOX "Please enter the IP address or hostname and network port of the frontend this backend shall connect to, in the format \"<ip/hostname>:<port>\", e.g. \"$G_WHIP_DEFAULT_ITEM\".
|
|
\nYou can find the port in /opt/dietpi-dashboard/config-frontend.toml on the frontend host system, or the \"Config\" page of its web UI.
|
|
\nThis can be changed any time later in /opt/dietpi-dashboard/config-backend.toml." &&
|
|
G_CONFIG_INJECT 'frontend_addr[[:blank:]]' "frontend_addr = \"$G_WHIP_RETURNED_VALUE\"" /opt/dietpi-dashboard/config-backend.toml
|
|
|
|
# Ask for frontend secret
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
G_WHIP_PASSWORD 'Please enter the secret of the frontend this backend shall connect to.
|
|
\nYou can find the secret in /opt/dietpi-dashboard/config-frontend.toml on the frontend host system, or the "Config" page of its web UI.
|
|
\nThis can be changed any time later in /opt/dietpi-dashboard/config-backend.toml.' &&
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'secret[[:blank:]]' "secret = \"${result//\"/\\\"}\"" /opt/dietpi-dashboard/config-backend.toml
|
|
unset -v result
|
|
fi
|
|
|
|
# If /mnt/dietpi_userdata points to a mount point, add that one to disks shown on system page
|
|
local userdata=$(findmnt -no TARGET -T "$(realpath /mnt/dietpi_userdata)")
|
|
[[ $userdata != '/' ]] && G_CONFIG_INJECT 'disks[[:blank:]]' "disks = [\"/\", \"$userdata\"]" /opt/dietpi-dashboard/config-backend.toml
|
|
fi
|
|
|
|
# Pre-v9.18: Disable old version but leave installed for now
|
|
if systemctl -q is-enabled dietpi-dashboard
|
|
then
|
|
G_EXEC systemctl disable dietpi-dashboard
|
|
G_WHIP_MSG '[ INFO ] Reboot required for new dashboard to load
|
|
\nThe old dashboard has been disabled, but not stopped, so this install does not kill itself in case it was triggered from the dashboard. This prevents the startup of the new service, unless network ports have been changed.
|
|
\nHence a reboot may be required afterwards for the new dashboard to replace the old one at port 5252.'
|
|
fi
|
|
fi
|
|
|
|
if To_Install 99 node_exporter # Prometheus Node Exporter
|
|
then
|
|
case $G_HW_ARCH in
|
|
1) local arch='armv6';;
|
|
2) local arch='armv7';;
|
|
3) local arch='arm64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
# Download binary
|
|
local fallback_url="https://github.com/prometheus/node_exporter/releases/download/v1.10.2/node_exporter-1.10.2.linux-$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/prometheus/node_exporter/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/node_exporter-.*\.linux-$arch\.tar\.gz\"$/{print \$4}")"
|
|
G_EXEC mkdir -p /opt/node_exporter
|
|
G_EXEC cp --preserve=mode node_exporter*/node_exporter /opt/node_exporter/
|
|
G_EXEC rm -R node_exporter*
|
|
|
|
# User
|
|
Create_User node_exporter
|
|
|
|
# Services
|
|
cat << '_EOF_' > /etc/systemd/system/node_exporter.service
|
|
[Unit]
|
|
Description=Prometheus Node Exporter (DietPi)
|
|
Documentation=https://prometheus.io/docs/guides/node-exporter/
|
|
|
|
[Service]
|
|
User=node_exporter
|
|
RuntimeDirectory=node_exporter
|
|
ExecStart=/opt/node_exporter/node_exporter --log.level=warn --collector.textfile.directory=/run/node_exporter
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# RPi: Install raspberrypi_exporter
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
Download_Install 'https://github.com/fahlke/raspberrypi_exporter/archive/master.tar.gz'
|
|
G_CONFIG_INJECT 'ConditionPathExists=' 'ConditionPathExists=/run/node_exporter' raspberrypi_exporter-master/raspberrypi_exporter.service '\[Unit\]'
|
|
G_CONFIG_INJECT 'ExecStart=' 'ExecStart=/opt/node_exporter/raspberrypi_exporter' raspberrypi_exporter-master/raspberrypi_exporter.service
|
|
G_CONFIG_INJECT 'METRICS_FILE=' 'METRICS_FILE='\''/run/node_exporter/raspberrypi-metrics.prom'\' raspberrypi_exporter-master/raspberrypi_exporter
|
|
|
|
G_EXEC mv {raspberrypi_exporter-master,/opt/node_exporter}/raspberrypi_exporter
|
|
G_EXEC mv {raspberrypi_exporter-master,/etc/systemd/system}/raspberrypi_exporter.service
|
|
G_EXEC mv {raspberrypi_exporter-master,/etc/systemd/system}/raspberrypi_exporter.timer
|
|
G_EXEC rm -R raspberrypi_exporter-master
|
|
aENABLE_SERVICES+=('raspberrypi_exporter')
|
|
fi
|
|
fi
|
|
|
|
if To_Install 44 transmission-daemon # Transmission
|
|
then
|
|
G_AGI transmission-daemon
|
|
G_EXEC systemctl stop transmission-daemon
|
|
|
|
# Remove obsolete service and environment files
|
|
Remove_SysV transmission-daemon 1
|
|
G_EXEC rm -f /etc/init/transmission-daemon.conf
|
|
|
|
# Apply optimised settings
|
|
G_CONFIG_INJECT '"download-queue-size"' " \"download-queue-size\": $(Optimise_BitTorrent 1)," /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"peer-limit-global"' " \"peer-limit-global\": $(Optimise_BitTorrent 2)," /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"upload-slots-per-torrent"' " \"upload-slots-per-torrent\": $(Optimise_BitTorrent 3)," /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"encryption"' ' "encryption": 2,' /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"trash-original-torrent-files"' ' "trash-original-torrent-files": true,' /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"download-dir"' ' "download-dir": "/mnt/dietpi_userdata/downloads",' /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"rpc-username"' ' "rpc-username": "root",' /etc/transmission-daemon/settings.json '^\{$'
|
|
G_CONFIG_INJECT '"rpc-whitelist-enabled"' ' "rpc-whitelist-enabled": false,' /etc/transmission-daemon/settings.json '^\{$'
|
|
# - Generate hash from global software password: https://github.com/transmission/transmission/blob/7367d46/libtransmission/crypto-utils.cc#L58
|
|
local salt=$(tr -dc '[:alnum:]./' < /dev/random | head -c8)
|
|
local hash=$(echo -n "$GLOBAL_PW$salt" | sha1sum | mawk '{print $1}')
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT '"rpc-password"' " \"rpc-password\": \"{$hash$salt\"," /etc/transmission-daemon/settings.json '^\{$'
|
|
unset -v hash salt
|
|
|
|
# Grant R/W access to and from download managers, media and file servers: Make "dietpi" the primary group, "debian-transmission" a supplementary group and create downloads with group write mode
|
|
G_EXEC usermod -g dietpi -aG debian-transmission debian-transmission
|
|
G_CONFIG_INJECT '"umask"' ' "umask": 7,' /etc/transmission-daemon/settings.json '^\{$'
|
|
fi
|
|
|
|
if To_Install 94 proftpd # ProFTPD
|
|
then
|
|
G_EXEC eval "debconf-set-selections <<< 'proftpd-basic shared/proftpd/inetd_or_standalone select standalone'"
|
|
G_AGI proftpd-basic
|
|
G_EXEC systemctl stop proftpd
|
|
|
|
# Disable conflicting activation socket: It would require "ServerType inetd" and replaces proftpd.service with ondemand proftpd@.service starts for each client connection.
|
|
G_EXEC systemctl --no-reload disable --now proftpd.socket
|
|
|
|
# Config
|
|
G_BACKUP_FP /etc/proftpd/proftpd.conf
|
|
dps_index=$software_id Download_Install 'conf' /etc/proftpd/proftpd.conf
|
|
fi
|
|
|
|
if To_Install 96 nmbd smbd # Samba Server
|
|
then
|
|
# Link disk cache to RAM: https://github.com/MichaIng/DietPi/issues/2396
|
|
# - Remove previous disk cache dir or symlink
|
|
G_EXEC rm -Rf /var/cache/samba
|
|
# - Pre-create RAM cache dir
|
|
G_EXEC mkdir -p /run/samba-cache
|
|
# - Link disk cache to RAM
|
|
G_EXEC ln -s /run/samba-cache /var/cache/samba
|
|
# - Create RAM cache dir automatically on boot
|
|
echo 'd /run/samba-cache' > /etc/tmpfiles.d/dietpi-samba_cache.conf
|
|
|
|
# Config: Preserve on reinstall
|
|
local reinstall=1
|
|
if [[ ! -f '/etc/samba/smb.conf' ]] || diff /usr/share/samba/smb.conf /etc/samba/smb.conf &> /dev/null
|
|
then
|
|
reinstall=0
|
|
dps_index=$software_id Download_Install 'conf' /etc/samba/smb.conf
|
|
G_CONFIG_INJECT 'max connections =' " max connections = $(( $G_HW_CPU_CORES * 2 ))" /etc/samba/smb.conf
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata samba
|
|
G_CONFIG_INJECT 'valid users =' ' valid users = samba' /etc/samba/smb.conf
|
|
fi
|
|
|
|
G_AGI samba
|
|
G_EXEC systemctl stop nmbd smbd
|
|
|
|
(( $reinstall )) || echo -e "$GLOBAL_PW\n$GLOBAL_PW" | smbpasswd -s -a samba
|
|
fi
|
|
|
|
if To_Install 95 vsftpd # vsftpd
|
|
then
|
|
# Config: Preserve on reinstall
|
|
[[ -f '/etc/vsftpd.conf' ]] || dps_index=$software_id Download_Install 'conf' /etc/vsftpd.conf
|
|
|
|
G_AGI vsftpd
|
|
G_EXEC systemctl stop vsftpd
|
|
|
|
# Do not allow root access via FTP
|
|
G_EXEC sed --follow-symlinks -i 's/^[[:blank:]]*root/#root/' /etc/ftpusers
|
|
fi
|
|
|
|
if To_Install 109 nfs-server # NFS Server
|
|
then
|
|
G_AGI nfs-kernel-server
|
|
G_EXEC systemctl stop nfs-server
|
|
|
|
G_EXEC mkdir -p /etc/exports.d
|
|
[[ -f '/etc/exports.d/dietpi.exports' ]] || G_EXEC eval 'echo '\''/mnt/dietpi_userdata *(rw,async,no_root_squash,crossmnt,no_subtree_check)'\'' > /etc/exports.d/dietpi.exports'
|
|
fi
|
|
|
|
if To_Install 83 apache2 # Apache
|
|
then
|
|
# Pre-create a dummy port 80 vhost if it does not exist yet, so we can avoid overwriting it on reinstalls.
|
|
if [[ ! -f '/etc/apache2/sites-available/000-default.conf' ]]
|
|
then
|
|
G_EXEC mkdir -p /etc/apache2/sites-available
|
|
cat << _EOF_ > /etc/apache2/sites-available/000-default.conf
|
|
# /etc/apache2/sites-available/000-default.conf
|
|
<VirtualHost *:80>
|
|
ServerName $(G_GET_NET ip)
|
|
</VirtualHost>
|
|
_EOF_
|
|
# Otherwise assure that the webroot is changed, as all our install options depend on it.
|
|
else
|
|
G_EXEC sed --follow-symlinks -i 's|/var/www/html|/var/www|g' /etc/apache2/sites-available/000-default.conf
|
|
fi
|
|
|
|
local apackages=('apache2')
|
|
# Install Certbot module if Certbot was already installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[92]} == 2 )) && apackages+=('python3-certbot-apache')
|
|
G_AGI "${apackages[@]}"
|
|
G_EXEC systemctl stop apache2
|
|
apachectl -M | grep -q 'cache_disk' || G_EXEC systemctl --no-reload disable --now apache-htcacheclean
|
|
|
|
# Enable event MPM and headers module
|
|
G_EXEC a2dismod -fq mpm_prefork
|
|
G_EXEC a2enmod -q mpm_event headers
|
|
|
|
# Disable obsolete default configs
|
|
for i in 'charset' 'localized-error-pages' 'other-vhosts-access-log' 'security' 'serve-cgi-bin'
|
|
do
|
|
[[ -L /etc/apache2/conf-enabled/$i.conf ]] && G_EXEC a2disconf "$i"
|
|
done
|
|
|
|
# Config
|
|
cat << _EOF_ > /etc/apache2/conf-available/dietpi.conf
|
|
# /etc/apache2/conf-available/dietpi.conf
|
|
# Default server name and webroot
|
|
ServerName $(G_GET_NET ip)
|
|
DocumentRoot /var/www
|
|
|
|
# Logging to: journalctl -u apache2
|
|
ErrorLog syslog
|
|
|
|
# Allow unlimited Keep-Alive requests
|
|
MaxKeepAliveRequests 0
|
|
|
|
# MPM event configuration
|
|
# - Run a single process which does not expire
|
|
# - Limit request handler threads to 64
|
|
StartServers 1
|
|
ServerLimit 1
|
|
MaxConnectionsPerChild 0
|
|
ThreadsPerChild 64
|
|
ThreadLimit 64
|
|
MinSpareThreads 1
|
|
MaxSpareThreads 64
|
|
MaxRequestWorkers 64
|
|
|
|
# Minimize public info
|
|
ServerTokens Prod
|
|
ServerSignature Off
|
|
TraceEnable Off
|
|
|
|
# Security headers
|
|
Header set X-Content-Type-Options "nosniff"
|
|
Header set X-Frame-Options "sameorigin"
|
|
Header set X-XSS-Protection "0"
|
|
Header set X-Robots-Tag "noindex, nofollow"
|
|
Header set X-Permitted-Cross-Domain-Policies "none"
|
|
Header set Referrer-Policy "no-referrer"
|
|
_EOF_
|
|
G_EXEC a2enconf dietpi
|
|
|
|
# Force service to start after PHP-FPM
|
|
G_EXEC mkdir -p /etc/systemd/system/apache2.service.d
|
|
G_EXEC eval "echo -e '[Unit]\nAfter=php$PHP_VERSION-fpm.service' > /etc/systemd/system/apache2.service.d/dietpi.conf"
|
|
|
|
# Webroot
|
|
if [[ -f '/var/www/html/index.html' ]]
|
|
then
|
|
# shellcheck disable=SC2015
|
|
[[ -f '/var/www/index.html' ]] && G_EXEC rm /var/www/html/index.html || G_EXEC mv /var/www/html/index.html /var/www/index.html
|
|
fi
|
|
[[ -d '/var/www/html' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/www/html
|
|
fi
|
|
|
|
if To_Install 85 nginx # Nginx
|
|
then
|
|
local apackages=('nginx-light')
|
|
# From Bookworm on, the "nginx" package does not include any extra modules while "nginx-light" pulls in "nginx" and additionally the "echo" module.
|
|
(( $G_DISTRO > 6 )) && apackages=('nginx')
|
|
# Install Certbot module if Certbot was already installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[92]} == 2 )) && apackages+=('python3-certbot-nginx')
|
|
G_AGI "${apackages[@]}"
|
|
G_EXEC systemctl stop nginx
|
|
|
|
# Custom configs included by sites-enabled/default within server directive, while nginx/(conf.d|sites-enabled) is included by nginx.conf outside server directive
|
|
G_EXEC mkdir -p /etc/nginx/sites-dietpi
|
|
|
|
G_BACKUP_FP /etc/nginx/nginx.conf
|
|
dps_index=$software_id Download_Install 'nginx.conf' /etc/nginx/nginx.conf
|
|
|
|
# CPU core count
|
|
G_EXEC sed --follow-symlinks -i "/worker_processes/c\worker_processes $G_HW_CPU_CORES;" /etc/nginx/nginx.conf
|
|
|
|
# Default site
|
|
dps_index=$software_id Download_Install 'nginx.default' /etc/nginx/sites-available/default
|
|
|
|
# Force service to start after PHP-FPM
|
|
G_EXEC mkdir -p /etc/systemd/system/nginx.service.d
|
|
G_EXEC eval "echo -e '[Unit]\nAfter=php$PHP_VERSION-fpm.service' > /etc/systemd/system/nginx.service.d/dietpi.conf"
|
|
|
|
# Webroot
|
|
if [[ -f '/var/www/html/index.nginx-debian.html' ]]
|
|
then
|
|
# shellcheck disable=SC2015
|
|
[[ -f '/var/www/index.html' ]] && G_EXEC rm /var/www/html/index.nginx-debian.html || G_EXEC mv /var/www/html/index.nginx-debian.html /var/www/index.html
|
|
fi
|
|
[[ -d '/var/www/html' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/www/html
|
|
fi
|
|
|
|
if To_Install 84 lighttpd # Lighttpd
|
|
then
|
|
G_AGI lighttpd
|
|
G_EXEC systemctl stop lighttpd
|
|
|
|
Remove_SysV lighttpd
|
|
|
|
# Change webroot from /var/www/html to /var/www
|
|
G_CONFIG_INJECT 'server.document-root' 'server.document-root = "/var/www"' /etc/lighttpd/lighttpd.conf
|
|
if [[ -f '/var/www/html/index.lighttpd.html' ]]
|
|
then
|
|
# shellcheck disable=SC2015
|
|
[[ -f '/var/www/index.html' ]] && G_EXEC rm /var/www/html/index.lighttpd.html || G_EXEC mv /var/www/html/index.lighttpd.html /var/www/index.html
|
|
fi
|
|
[[ -d '/var/www/html' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/www/html
|
|
[[ -f '/etc/lighttpd/conf-enabled/99-unconfigured.conf' ]] && G_EXEC lighty-disable-mod unconfigured
|
|
|
|
# Disable conflicting fastcgi-php module
|
|
[[ -f '/etc/lighttpd/conf-enabled/15-fastcgi-php.conf' ]] && G_EXEC lighty-disable-mod fastcgi-php
|
|
[[ -f '/etc/lighttpd/conf-enabled/15-fastcgi-php-fpm.conf' ]] || G_EXEC lighty-enable-mod fastcgi-php-fpm
|
|
|
|
# Force service to start after PHP-FPM
|
|
G_EXEC mkdir -p /etc/systemd/system/lighttpd.service.d
|
|
G_EXEC eval "echo -e '[Unit]\nAfter=php$PHP_VERSION-fpm.service' > /etc/systemd/system/lighttpd.service.d/dietpi.conf"
|
|
fi
|
|
|
|
if To_Install 88 mariadb # MariaDB
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Preparing database directory at: /mnt/dietpi_userdata/mysql'
|
|
if [[ -d '/mnt/dietpi_userdata/mysql' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 '/mnt/dietpi_userdata/mysql exists, will migrate containing databases'
|
|
else
|
|
# Otherwise use possibly existent /var/lib/mysql
|
|
# - Remove possible dead symlinks/files:
|
|
G_EXEC rm -f /mnt/dietpi_userdata/mysql
|
|
if [[ -d '/var/lib/mysql' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 '/var/lib/mysql exists, will migrate containing databases'
|
|
# Failsafe: Move symlink target in case, otherwise readlink will resolve to dir
|
|
G_EXEC mv "$(readlink -f '/var/lib/mysql')" /mnt/dietpi_userdata/mysql
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/mysql
|
|
fi
|
|
fi
|
|
|
|
G_EXEC rm -Rf /var/lib/mysql
|
|
G_EXEC ln -s /mnt/dietpi_userdata/mysql /var/lib/mysql
|
|
|
|
local apackages=('mariadb-server')
|
|
# Install PHP module if PHP was already installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[89]} == 2 )) && apackages+=("php$PHP_VERSION-mysql")
|
|
G_AGI "${apackages[@]}"
|
|
G_EXEC systemctl stop mariadb
|
|
|
|
Remove_SysV mysql 1
|
|
|
|
# Assure correct owner in case the database dir got migrated from a different system: https://github.com/MichaIng/DietPi/issues/4721#issuecomment-917051930
|
|
# - The group is correctly recursively fixed by the preinst script already.
|
|
[[ -d '/mnt/dietpi_userdata/mysql/mysql' && $(stat -c '%U' /mnt/dietpi_userdata/mysql/mysql) != 'mysql' ]] && find /mnt/dietpi_userdata/mysql ! -user root ! -user mysql -exec chown mysql {} +
|
|
|
|
# Force service to start before cron
|
|
G_EXEC mkdir -p /etc/systemd/system/mariadb.service.d
|
|
G_EXEC eval 'echo -e '\''[Unit]\nBefore=cron.service'\'' > /etc/systemd/system/mariadb.service.d/dietpi.conf'
|
|
fi
|
|
|
|
if To_Install 87 # SQLite
|
|
then
|
|
local apackages=('sqlite3')
|
|
# Install PHP module if PHP was already installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[89]} == 2 )) && apackages+=("php$PHP_VERSION-sqlite3")
|
|
G_AGI "${apackages[@]}"
|
|
fi
|
|
|
|
if To_Install 91 redis-server # Redis
|
|
then
|
|
local apackages=('redis-server')
|
|
# Install PHP module if PHP was already installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[89]} == 2 )) && apackages+=("php$PHP_VERSION-redis")
|
|
G_AGI "${apackages[@]}"
|
|
G_EXEC systemctl stop redis-server
|
|
|
|
# Enable Redis php module if installed
|
|
command -v phpenmod > /dev/null && G_EXEC phpenmod redis
|
|
|
|
# Disable file logging and enable syslog instead, which resolves reported startup issues in cases as well: https://github.com/MichaIng/DietPi/issues/3291
|
|
G_CONFIG_INJECT 'loglevel[[:blank:]]' 'loglevel warning' /etc/redis/redis.conf
|
|
G_CONFIG_INJECT 'logfile[[:blank:]]' 'logfile ""' /etc/redis/redis.conf
|
|
G_CONFIG_INJECT 'syslog-enabled[[:blank:]]' 'syslog-enabled yes' /etc/redis/redis.conf
|
|
G_CONFIG_INJECT 'always-show-logo[[:blank:]]' 'always-show-logo no' /etc/redis/redis.conf
|
|
|
|
# Force service to start before cron
|
|
G_EXEC mkdir -p /etc/systemd/system/redis-server.service.d
|
|
G_EXEC eval 'echo -e '\''[Unit]\nBefore=cron.service'\'' > /etc/systemd/system/redis-server.service.d/dietpi.conf'
|
|
|
|
# Enable memory overcomit: https://github.com/jemalloc/jemalloc/issues/1328
|
|
if (( $G_HW_MODEL == 75 ))
|
|
then
|
|
[[ $(sysctl -n vm.overcommit_memory) == 1 ]] || G_WHIP_MSG '[WARNING] Memory overcomit is disabled
|
|
\nFor Redis to run reliably, memory overcomit should be enabled. This can only be done on the host system of this container. E.g. run the following two commands on the host:
|
|
echo vm.overcommit_memory=1 | sudo tee /etc/sysctl.d/98-dietpi-redis.conf
|
|
sudo sysctl -p /etc/sysctl.d/98-dietpi-redis.conf'
|
|
else
|
|
G_EXEC eval 'echo '\''vm.overcommit_memory=1'\'' > /etc/sysctl.d/98-dietpi-redis.conf'
|
|
local dryrun=()
|
|
[[ ! -w '/proc/sys/vm/overcommit_memory' ]] && systemd-detect-virt -cq && dryrun=('--dry-run')
|
|
G_EXEC sysctl -p "${dryrun[@]}" /etc/sysctl.d/98-dietpi-redis.conf
|
|
fi
|
|
fi
|
|
|
|
if To_Install 89 # PHP
|
|
then
|
|
# Base PHP modules
|
|
# - Webserver: PHP-FPM
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 || ${aSOFTWARE_INSTALL_STATE[84]} > 0 || ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
local apackages=("php$PHP_VERSION-fpm")
|
|
aENABLE_SERVICES+=("php$PHP_VERSION-fpm")
|
|
|
|
# - No webserver: CLI usage only (php binary)
|
|
else
|
|
local apackages=("php$PHP_VERSION-cli")
|
|
fi
|
|
|
|
# Additional PHP modules, commonly used by most web applications
|
|
apackages+=("php$PHP_VERSION-apcu" "php$PHP_VERSION-curl" "php$PHP_VERSION-gd" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-xml" "php$PHP_VERSION-zip")
|
|
|
|
# MySQL/MariaDB PHP module
|
|
(( ${aSOFTWARE_INSTALL_STATE[88]} > 0 )) && apackages+=("php$PHP_VERSION-mysql")
|
|
|
|
# SQLite PHP module
|
|
(( ${aSOFTWARE_INSTALL_STATE[87]} > 0 )) && apackages+=("php$PHP_VERSION-sqlite3")
|
|
|
|
# Redis PHP module
|
|
(( ${aSOFTWARE_INSTALL_STATE[91]} > 0 )) && apackages+=("php$PHP_VERSION-redis")
|
|
|
|
G_AGI "${apackages[@]}"
|
|
systemctl -q is-active "php$PHP_VERSION-fpm" && G_EXEC systemctl stop "php$PHP_VERSION-fpm"
|
|
|
|
# Assure that mod_php is purged in favour of PHP-FPM
|
|
G_AGP 'libapache2-mod-php*'
|
|
G_EXEC rm -Rf /{etc/php,var/lib/php/modules}/*/apache2
|
|
|
|
# PHP-FPM
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 || ${aSOFTWARE_INSTALL_STATE[84]} > 0 || ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
# Optimisations based on total cores
|
|
G_CONFIG_INJECT 'pm.max_children[[:blank:]=]' "pm.max_children = $(( $G_HW_CPU_CORES * 3 ))" "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf"
|
|
G_CONFIG_INJECT 'pm.start_servers[[:blank:]=]' "pm.start_servers = $G_HW_CPU_CORES" "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf"
|
|
G_CONFIG_INJECT 'pm.min_spare_servers[[:blank:]=]' "pm.min_spare_servers = $G_HW_CPU_CORES" "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf"
|
|
G_CONFIG_INJECT 'pm.max_spare_servers[[:blank:]=]' "pm.max_spare_servers = $G_HW_CPU_CORES" "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf"
|
|
# Set static PATH, not passed by Lighttpd and Nginx by default but required by some web applications: https://github.com/MichaIng/DietPi/issues/5161#issuecomment-1013381362
|
|
G_CONFIG_INJECT 'env\[PATH\][[:blank:]=]' 'env[PATH] = /usr/local/bin:/usr/bin:/bin' "/etc/php/$PHP_VERSION/fpm/pool.d/www.conf"
|
|
|
|
# Force service to start after database servers
|
|
G_EXEC mkdir -p "/etc/systemd/system/php$PHP_VERSION-fpm.service.d"
|
|
G_EXEC eval "echo -e '[Unit]\nAfter=redis-server.service mariadb.service postgresql.service' > '/etc/systemd/system/php$PHP_VERSION-fpm.service.d/dietpi.conf'"
|
|
fi
|
|
|
|
# We create our own PHP mod to add DietPi specific configs.
|
|
target_php_ini="/etc/php/$PHP_VERSION/mods-available/dietpi.ini"
|
|
echo -e '; DietPi PHP settings\n; priority=97' > "$target_php_ini"
|
|
|
|
# Session files need to be outside of /tmp and /var/tmp due to PrivateTmp=true, else phpsessionclean.service cannot clean sessions
|
|
G_EXEC mkdir -p /run/php_sessions
|
|
G_EXEC chmod 1733 /run/php_sessions
|
|
echo -e '# Pre-create PHP sessions dir\nd /run/php_sessions 1733' > /etc/tmpfiles.d/dietpi-php_sessions.conf
|
|
G_CONFIG_INJECT 'session.save_path[[:blank:]=]' 'session.save_path="/run/php_sessions"' "$target_php_ini"
|
|
|
|
# File uploads: https://github.com/MichaIng/DietPi/issues/546
|
|
# - This is especially relevant for cloud software like ownCloud/Nextcloud.
|
|
# - Generally we want to hold tmp upload files in RAM to reduce disk (especially SD card) writes for performance and disk wear reasons.
|
|
# - By default only max 2 MiB file uploads are allowed, hold in /tmp tmpfs, which is safe but not usable for usual cloud usage.
|
|
# - ownCloud/Nextcloud do/did override this limit to 512 MiB, a reasonable limit which can usually still be hold in RAM without issues.
|
|
# - Low RAM devices (RPi1 256 MiB model) require a swap file for this, however, it is still better to cause disk writes through swap file during large file uploads only, then doing this for each and every uploaded file.
|
|
# - When larger file uploads are required, it depends on the system total RAM, rootfs disk and available external drives if/where to move tmp file uploads, resize or move swap file. This should be then left to user.
|
|
G_CONFIG_INJECT 'upload_tmp_dir[[:blank:]=]' 'upload_tmp_dir="/tmp"' "$target_php_ini"
|
|
G_CONFIG_INJECT 'upload_max_filesize[[:blank:]=]' 'upload_max_filesize=512M' "$target_php_ini"
|
|
G_CONFIG_INJECT 'post_max_size[[:blank:]=]' 'post_max_size=512M' "$target_php_ini"
|
|
# - Nginx: https://github.com/MichaIng/DietPi/issues/546 => https://github.com/MichaIng/DietPi/blob/dev/.conf/dps_85/nginx.conf
|
|
|
|
# Cache settings
|
|
local cache_size=$(( $RAM_PHYS / 30 ))
|
|
(( $cache_size < 16 )) && cache_size=16
|
|
# - OPcache
|
|
G_CONFIG_INJECT 'opcache.memory_consumption[[:blank:]=]' "opcache.memory_consumption=$cache_size" "$target_php_ini"
|
|
G_CONFIG_INJECT 'opcache.revalidate_freq[[:blank:]=]' 'opcache.revalidate_freq=60' "$target_php_ini" # 1 minute
|
|
# - JIT is available since PHP 8.0 for x86_64 and since PHP 8.2 for ARMv8. Enable it with 2 MiB size, since we never saw usage far above 1 MiB for whatever reason.
|
|
# - Skip on ARMv8 for now, since tracing JIT produces segmentation faults there, and function JIT requires a lot more memory: https://github.com/php/php-src/issues/7817
|
|
# - On dietpi.com x86_64 server, we suffered from segmentation faults as well for a while, but there it seems to have been solved.
|
|
if (( $G_DISTRO > 6 && $G_HW_ARCH == 10 ))
|
|
then
|
|
G_CONFIG_INJECT 'opcache.jit[[:blank:]=]' 'opcache.jit=1' "$target_php_ini" # 1/on = "tracing", follow default for now: https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit
|
|
G_CONFIG_INJECT 'opcache.jit_buffer_size[[:blank:]=]' 'opcache.jit_buffer_size=2M' "$target_php_ini"
|
|
fi
|
|
# - APCu
|
|
G_CONFIG_INJECT 'apc.shm_size[[:blank:]=]' "apc.shm_size=$(( $cache_size / 2 ))M" "$target_php_ini"
|
|
G_CONFIG_INJECT 'apc.ttl[[:blank:]=]' 'apc.ttl=259200' "$target_php_ini" # 3 days
|
|
# - Enable
|
|
G_EXEC phpenmod dietpi
|
|
|
|
# Apache: Enable PHP-FPM
|
|
command -v a2enconf > /dev/null && { G_EXEC a2enmod proxy_fcgi setenvif; G_EXEC a2enconf "php$PHP_VERSION-fpm"; }
|
|
fi
|
|
|
|
if To_Install 34 # PHP Composer
|
|
then
|
|
G_EXEC curl -sSfL 'https://getcomposer.org/composer-stable.phar' -o /usr/local/bin/composer
|
|
G_EXEC chmod +x /usr/local/bin/composer
|
|
fi
|
|
|
|
if To_Install 90 # phpMyAdmin
|
|
then
|
|
# Install required PHP modules: https://docs.phpmyadmin.net/en/latest/require.html#php
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
local json=()
|
|
[[ $PHP_VERSION == 8* ]] || json=("php$PHP_VERSION-json")
|
|
G_AGI "php$PHP_VERSION"-{curl,gd,mbstring,xml,zip} "${json[@]}"
|
|
|
|
# Quick install: https://docs.phpmyadmin.net/en/latest/setup.html#quick-install
|
|
# - Get latest version name
|
|
local version=$(curl -sSfL 'https://api.github.com/repos/phpmyadmin/phpmyadmin/releases' | mawk -F\" '/^ *"name": "/ && $4!~/rc/ {print $4}' | sort -rV | head -1)
|
|
[[ $version ]] || { version='5.2.3'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
Download_Install "https://files.phpmyadmin.net/phpMyAdmin/$version/phpMyAdmin-$version-english.tar.xz"
|
|
# - Reinstall: Clean install but preserve existing config file
|
|
[[ -f '/var/www/phpmyadmin/config.inc.php' ]] && G_EXEC mv /var/www/phpmyadmin/config.inc.php "phpMyAdmin-$version-english/"
|
|
G_EXEC rm -Rf /var/www/phpmyadmin # Include pre-v6.27 symlink: https://github.com/MichaIng/DietPi/issues/3304
|
|
# - Remove GUI setup: https://docs.phpmyadmin.net/en/latest/setup.html#securing-your-phpmyadmin-installation
|
|
G_EXEC rm -R "phpMyAdmin-$version-english/setup"
|
|
# - Move new instance in place
|
|
G_EXEC mv "phpMyAdmin-$version-english" /var/www/phpmyadmin
|
|
|
|
# Enable required PHP modules: https://docs.phpmyadmin.net/en/latest/require.html#php
|
|
G_EXEC phpenmod ctype curl gd mbstring xml zip "${json[@]##*-}"
|
|
|
|
# Install and enable webserver config
|
|
# - Apache
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'apache.phpmyadmin.conf' /etc/apache2/sites-available/dietpi-phpmyadmin.conf
|
|
G_EXEC a2ensite dietpi-phpmyadmin
|
|
|
|
# - Lighttpd
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'lighttpd.phpmyadmin.conf' /etc/lighttpd/conf-available/98-dietpi-phpmyadmin.conf
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod dietpi-phpmyadmin
|
|
|
|
# - Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'nginx.phpmyadmin.conf' /etc/apache2/sites-dietpi/dietpi-phpmyadmin.conf
|
|
fi
|
|
|
|
# Copy default config in place and adjust if not already existent
|
|
if [[ ! -f '/var/www/phpmyadmin/config.inc.php' ]]
|
|
then
|
|
G_EXEC cp -a /var/www/phpmyadmin/config.sample.inc.php /var/www/phpmyadmin/config.inc.php
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT "\\\$cfg\\['blowfish_secret'][[:blank:]]*=" "\$cfg['blowfish_secret'] = '$(openssl rand -base64 32)';" /var/www/phpmyadmin/config.inc.php
|
|
fi
|
|
|
|
# Create MariaDB database and user
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/phpmyadmin' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'phpMyAdmin MariaDB database found, will NOT overwrite.'
|
|
else
|
|
/boot/dietpi/func/create_mysql_db phpmyadmin phpmyadmin "$GLOBAL_PW"
|
|
mysql phpmyadmin < /var/www/phpmyadmin/sql/create_tables.sql
|
|
# Since "root" user cannot be used for login (unix_socket authentication), grant full admin privileges to "phpmyadmin"
|
|
mysql -e 'grant all privileges on *.* to phpmyadmin@localhost with grant option;'
|
|
fi
|
|
|
|
# Pre-create TempDir: https://docs.phpmyadmin.net/en/latest/config.html#cfg_TempDir
|
|
G_EXEC mkdir -p /var/www/phpmyadmin/tmp
|
|
G_EXEC chown www-data:root /var/www/phpmyadmin/tmp
|
|
G_EXEC chmod 700 /var/www/phpmyadmin/tmp
|
|
fi
|
|
|
|
if To_Install 125 synapse # Synapse: https://element-hq.github.io/synapse/latest/setup/installation.html#installing-as-a-python-module-from-pypi
|
|
then
|
|
# Dependencies
|
|
Python_Deps -i bcrypt cryptography pillow psycopg2 pynacl matrix-synapse
|
|
|
|
# Install
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -U matrix-synapse psycopg2
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/synapse synapse
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/synapse.service
|
|
[Unit]
|
|
Description=Synapse (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target postgresql.service
|
|
|
|
[Service]
|
|
Type=notify
|
|
SyslogIdentifier=Synapse
|
|
User=synapse
|
|
WorkingDirectory=/mnt/dietpi_userdata/synapse
|
|
ExecStart=/usr/bin/python3 -m synapse.app.homeserver -c homeserver.yaml -c homeserver.yaml.d
|
|
ExecReload=/bin/kill -HUP $MAINPID
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Database
|
|
G_EXEC systemctl start postgresql
|
|
local synapse_pass=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
if [[ $(runuser -u postgres -- psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='synapse'") != 1 ]]
|
|
then
|
|
G_EXEC runuser -u postgres -- psql -c "CREATE ROLE synapse WITH LOGIN PASSWORD '$synapse_pass';"
|
|
else
|
|
G_EXEC runuser -u postgres -- psql -c "ALTER ROLE synapse WITH PASSWORD '$synapse_pass';"
|
|
fi
|
|
if [[ $(runuser -u postgres -- psql -tAc "SELECT 1 FROM pg_database WHERE datname='synapse'") != 1 ]]
|
|
then
|
|
G_EXEC runuser -u postgres -- createdb --encoding=UTF8 --locale=C --template=template0 --owner=synapse synapse
|
|
fi
|
|
|
|
# Pre-create drop-in config for database access details
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/synapse/homeserver.yaml.d
|
|
cat << _EOF_ > /mnt/dietpi_userdata/synapse/homeserver.yaml.d/00-dietpi.yaml
|
|
# PostgreSQL access details
|
|
# NB: Do not edit this file, instead override settings via e.g.: homeserver.yaml.d/99-local.conf
|
|
database:
|
|
name: psycopg2
|
|
args:
|
|
host: /run/postgresql
|
|
port: 5432
|
|
user: synapse
|
|
password: $synapse_pass
|
|
database: synapse
|
|
cp_min: 5
|
|
cp_max: 10
|
|
_EOF_
|
|
# Config
|
|
if [[ ! -f '/mnt/dietpi_userdata/synapse/homeserver.yaml' ]]
|
|
then
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_PUBLIC_DOMAIN_NAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(find /etc/letsencrypt/live -mindepth 1 -maxdepth 1 -type d -print -quit 2> /dev/null)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(hostname -f)
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX 'Please enter the name for this homeserver.\nIt is recommended that this be the public domain name that this server will be hosted on.'
|
|
local servername=${G_WHIP_RETURNED_VALUE#http*://}
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'SOFTWARE_PUBLIC_DOMAIN_NAME=' "SOFTWARE_PUBLIC_DOMAIN_NAME=$servername" /boot/dietpi.txt
|
|
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_SYNAPSE_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM='dietpi'
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX 'Please enter the admin username for this homeserver. It will use the default software password.'
|
|
local username=$G_WHIP_RETURNED_VALUE
|
|
|
|
G_EXEC cd /mnt/dietpi_userdata/synapse
|
|
|
|
# Create initial config
|
|
G_EXEC python3 -m synapse.app.homeserver -H "$servername" -c homeserver.yaml --generate-config --report-stats 'no'
|
|
|
|
# Enable registrations via random shared secret
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'registration_shared_secret:[[:blank:]]' "registration_shared_secret: $(openssl rand -hex 16)" homeserver.yaml
|
|
|
|
# Allow remote access
|
|
G_CONFIG_INJECT 'bind_addresses:[[:blank:]]' " bind_addresses: ['::']" homeserver.yaml
|
|
|
|
# Log to journal with log level WARNING
|
|
G_EXEC sed --follow-symlinks -i 's/ handlers: \[.*\]$/ handlers: [console]/' "$servername.log.config"
|
|
G_EXEC sed --follow-symlinks -i 's/ level: .*/ level: WARNING/' "$servername.log.config"
|
|
|
|
# Permissions
|
|
G_EXEC chown -R synapse:synapse .
|
|
G_EXEC chmod 0660 homeserver.yaml{,.d/*.yaml}
|
|
G_EXEC chmod 0770 homeserver.yaml.d
|
|
|
|
# Register admin user
|
|
G_EXEC systemctl daemon-reload
|
|
G_EXEC systemctl start synapse
|
|
G_EXEC_PRE_FUNC(){ acommand[4]="$GLOBAL_PW"; } # Mask password in console output
|
|
G_EXEC_OUTPUT=1 G_EXEC register_new_matrix_user -u "$username" -p "${GLOBAL_PW//?/X}" -a -c homeserver.yaml 'http://127.0.0.1:8008'
|
|
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
unset -v servername username
|
|
else
|
|
# Permissions
|
|
G_EXEC chown -R synapse:synapse /mnt/dietpi_userdata/synapse
|
|
G_EXEC chmod 0660 /mnt/dietpi_userdata/synapse/homeserver.yaml{,.d/*.yaml}
|
|
G_EXEC chmod 0770 /mnt/dietpi_userdata/synapse/homeserver.yaml.d
|
|
fi
|
|
fi
|
|
|
|
if To_Install 128 mpd # MPD
|
|
then
|
|
G_AGI mpd
|
|
G_EXEC systemctl stop mpd
|
|
|
|
# Service
|
|
# - Run systemd unit as "mpd" user instead of using config file based user change, to preserve supplementary group permissions (i.e. "dietpi")
|
|
# - Skip environment file so that usage of our config file is assured
|
|
G_EXEC mkdir -p /etc/systemd/system/mpd.service.d
|
|
cat << '_EOF_' > /etc/systemd/system/mpd.service.d/dietpi.conf
|
|
[Service]
|
|
User=mpd
|
|
RuntimeDirectory=mpd
|
|
EnvironmentFile=
|
|
ExecStart=
|
|
ExecStart=/usr/bin/mpd --systemd
|
|
_EOF_
|
|
(( $G_DISTRO < 7 )) && G_EXEC sed --follow-symlinks -i 's/systemd/no-daemon/' /etc/systemd/system/mpd.service.d/dietpi.conf
|
|
Remove_SysV mpd 1
|
|
|
|
# Config
|
|
G_CONFIG_INJECT 'music_directory[[:blank:]]' 'music_directory "/mnt/dietpi_userdata/Music"' /etc/mpd.conf
|
|
G_CONFIG_INJECT 'playlist_directory[[:blank:]]' 'playlist_directory "/mnt/dietpi_userdata/Music"' /etc/mpd.conf
|
|
G_CONFIG_INJECT 'db_file[[:blank:]]' 'db_file "/mnt/dietpi_userdata/.mpd_cache/db_file"' /etc/mpd.conf
|
|
# - Log to journal
|
|
G_EXEC sed --follow-symlinks -Ei 's/^[[:blank:]]*log_file[[:blank:]]+/#log_file /' /etc/mpd.conf
|
|
# - PID file is not required for systemd
|
|
G_EXEC sed --follow-symlinks -Ei 's/^[[:blank:]]*pid_file[[:blank:]]+/#pid_file /' /etc/mpd.conf
|
|
G_CONFIG_INJECT 'state_file[[:blank:]]' 'state_file "/mnt/dietpi_userdata/.mpd_cache/state"' /etc/mpd.conf
|
|
G_CONFIG_INJECT 'sticker_file[[:blank:]]' 'sticker_file "/mnt/dietpi_userdata/.mpd_cache/sticker.sql"' /etc/mpd.conf
|
|
# - Our service starts as "mpd" user already
|
|
G_EXEC sed --follow-symlinks -Ei 's/^[[:blank:]]*user[[:blank:]]+/#user /' /etc/mpd.conf
|
|
G_EXEC sed --follow-symlinks -Ei 's/^[[:blank:]]*group[[:blank:]]+/#group /' /etc/mpd.conf
|
|
# - Enable UNIX socket
|
|
G_CONFIG_INJECT 'bind_to_address[[:blank:]]+"/run/mpd/socket"' 'bind_to_address "/run/mpd/socket"' /etc/mpd.conf
|
|
# - Add simple ALSA output if none present yet
|
|
grep -q '^[[:blank:]]*audio_output[[:blank:]]' /etc/mpd.conf || cat << '_EOF_' >> /etc/mpd.conf
|
|
# Simple ALSA output
|
|
audio_output {
|
|
type "alsa"
|
|
name "DietPi ALSA"
|
|
}
|
|
_EOF_
|
|
# RPi JustBoom can handle SOXR VH @ 192khz 32bit: https://github.com/MichaIng/DietPi/issues/581#issuecomment-256643079
|
|
if grep -q '^[[:blank:]]*CONFIG_SOUNDCARD=justboom' /boot/dietpi.txt
|
|
then
|
|
# Force 192khz 32bit for all outputs: Better would be to apply it to the single JustBoom output device, but we'll leave this for now for simplicity.
|
|
G_CONFIG_INJECT 'audio_output_format[[:blank:]]' 'audio_output_format "32:192000:2"' /etc/mpd.conf
|
|
# Use highest SOXR quality: "samplerate_converter" is actually deprecated with v0.20.0 and replaced by a "resampler" block, but we'll leave this for now for simplicity.
|
|
G_CONFIG_INJECT 'samplerate_converter[[:blank:]]' 'samplerate_converter "soxr very high"' /etc/mpd.conf
|
|
fi
|
|
|
|
# User
|
|
Create_User -g audio -G dietpi -d /mnt/dietpi_userdata/.mpd_cache mpd
|
|
|
|
# Dirs
|
|
# - Move possibly existing audio and playlist files to userdata
|
|
[[ ! -e '/var/lib/mpd/music' || -L '/var/lib/mpd/music' || $(find /var/lib/mpd/music -maxdepth 0 -empty) ]] || G_EXEC mv -n /var/lib/mpd/music/* /mnt/dietpi_userdata/Music/
|
|
[[ ! -e '/var/lib/mpd/playlists' || -L '/var/lib/mpd/playlists' || $(find /var/lib/mpd/playlists -maxdepth 0 -empty) ]] || G_EXEC mv -n /var/lib/mpd/playlists/* /mnt/dietpi_userdata/Music/
|
|
# - Purge obsolete data and log dirs and clear cache
|
|
G_EXEC rm -Rf /var/lib/mpd /var/log/mpd /mnt/dietpi_userdata/.mpd_cache
|
|
# - Recreate cache dir
|
|
G_EXEC mkdir /mnt/dietpi_userdata/.mpd_cache
|
|
|
|
Download_Test_Media
|
|
|
|
# Permissions
|
|
G_EXEC chown -R mpd:root /mnt/dietpi_userdata/.mpd_cache /etc/mpd.conf
|
|
fi
|
|
|
|
if To_Install 54 # phpBB
|
|
then
|
|
# Pre-v6.33: Support old and new location
|
|
PHPBB_LOC='phpbb'
|
|
[[ -d '/var/www/phpBB3' ]] && PHPBB_LOC='phpBB3'
|
|
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d /var/www/$PHPBB_LOC ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/var/www/$PHPBB_LOC\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please follow the instructions from web UI ACP.
|
|
- If you need to reinstall (e.g. broken instance), please manually backup your config files+data, remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
else
|
|
local fallback_url='https://download.phpbb.com/pub/release/3.3/3.3.15/phpBB-3.3.15.tar.bz2'
|
|
Download_Install "$(curl -sSf 'https://version.phpbb.com/phpbb/versions.json' | sed -En '/"stable":/,/"unstable":/s/.*"current": "(.+)",.*/\1/p' | sort -Vr | head -1)"
|
|
# Files are shipped with UID:GID 1000:1000 while for security reasons it should be root:root.
|
|
G_EXEC chown -R root:root phpBB3
|
|
G_EXEC mv phpBB3 /var/www/phpbb
|
|
fi
|
|
|
|
# Preserve old database name
|
|
[[ -d '/mnt/dietpi_userdata/mysql/phpbb3' ]] || /boot/dietpi/func/create_mysql_db phpbb phpbb "$GLOBAL_PW"
|
|
|
|
# Permissions: The web-based installer writes setup and database access information to this file. Upload, cache and store directories are shipped with 777 modes already.
|
|
G_EXEC chown www-data "/var/www/$PHPBB_LOC/config.php"
|
|
fi
|
|
|
|
if To_Install 133 yacy # YaCy
|
|
then
|
|
# Get latest download
|
|
local file=$(curl -sSfL 'https://download.yacy.net/?C=N;O=D' | grep -o 'yacy_v[0-9._a-f]*\.tar\.gz' | head -1)
|
|
[[ $file ]] || { file='yacy_v1.940_202405270005_70454654f.tar.gz'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. \"$file\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
|
|
Download_Install "https://download.yacy.net/$file" /etc
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/yacy.service
|
|
[Unit]
|
|
Description=YaCy (DietPi)
|
|
Documentation=https://wiki.yacy.net/index.php/En:Start
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=forking
|
|
ExecStart=/etc/yacy/startYACY.sh
|
|
ExecStop=/etc/yacy/stopYACY.sh
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Set admin interface passwd:
|
|
if [[ ! -f '/etc/yacy/DATA/SETTINGS/yacy.conf' ]]
|
|
then
|
|
Create_Config /etc/yacy/DATA/SETTINGS/yacy.conf yacy
|
|
/etc/yacy/bin/passwd.sh "$GLOBAL_PW"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 186 ipfs # Kubo
|
|
then
|
|
local version=
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='arm' version='v0.33.2';; # latest version with 32-bit builds
|
|
esac
|
|
|
|
if [[ $version ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "For your architecture, the latest available ${aSOFTWARE_NAME[$software_id]} builds are $version."
|
|
else
|
|
# Find latest version
|
|
version=$(curl -sSfL 'https://dist.ipfs.tech/kubo/versions' | sed '/-rc[0-9]*$/d' | tail -1)
|
|
[[ $version ]] || { version='v0.39.0'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
fi
|
|
Download_Install "https://dist.ipfs.tech/kubo/$version/kubo_${version}_linux-$arch.tar.gz"
|
|
|
|
# Install
|
|
G_EXEC_OUTPUT=1 G_EXEC kubo/install.sh
|
|
|
|
# Data and config directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/ipfs
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/ipfs ipfs
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/ipfs.service
|
|
[Unit]
|
|
Description=Kubo IPFS Node (DietPi)
|
|
Documentation=https://docs.ipfs.io/reference/go/api/
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=ipfs
|
|
Environment=IPFS_PATH=/mnt/dietpi_userdata/ipfs
|
|
ExecStart=/usr/local/bin/ipfs daemon
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Config: Preserve existing on reinstall
|
|
if [[ ! -f '/mnt/dietpi_userdata/ipfs/config' ]]
|
|
then
|
|
IPFS_PATH='/mnt/dietpi_userdata/ipfs' G_EXEC_OUTPUT=1 G_EXEC ipfs init
|
|
IPFS_PATH='/mnt/dietpi_userdata/ipfs' G_EXEC ipfs config --json Addresses.Gateway '"/ip4/0.0.0.0/tcp/8087"'
|
|
IPFS_PATH='/mnt/dietpi_userdata/ipfs' G_EXEC ipfs config --json Addresses.API '"/ip4/0.0.0.0/tcp/5003"'
|
|
IPFS_PATH='/mnt/dietpi_userdata/ipfs' G_EXEC ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R 'ipfs:ipfs' /mnt/dietpi_userdata/ipfs
|
|
|
|
# CLI alias
|
|
echo 'alias ipfs='\''sudo -u ipfs IPFS_PATH=/mnt/dietpi_userdata/ipfs ipfs'\' > /etc/bashrc.d/dietpi-ipfs.sh
|
|
|
|
# Raise UDP buffer sizes: https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes
|
|
if (( $G_HW_MODEL == 75 ))
|
|
then
|
|
(( $(sysctl -n net.core.rmem_max) >= 7500000 && $(sysctl -n net.core.wmem_max) >= 7500000 )) || G_WHIP_MSG '[WARNING] UDP buffer size limits might be too small
|
|
\nFor QUIC, used by the Kubo, the bandwidth can be limited by the UDP buffer sizes. Hence it is recommended to raise their limit. This can only be done on the host of this container. E.g. add the following lines to a new sysctl config file like /etc/sysctl.d/dietpi-ipfs.conf:
|
|
net.core.rmem_max=7500000
|
|
net.core.wmem_max=7500000
|
|
\nApply them without reboot like this:
|
|
sudo sysctl -p /etc/sysctl.d/dietpi-ipfs.conf
|
|
\nMore info: https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes'
|
|
else
|
|
G_EXEC eval 'echo -e '\''net.core.rmem_max=7500000\nnet.core.wmem_max=7500000'\'' > /etc/sysctl.d/dietpi-ipfs.conf'
|
|
local dryrun=()
|
|
[[ ! -w '/proc/sys/net/core/rmem_max' ]] && systemd-detect-virt -cq && dryrun=('--dry-run')
|
|
G_EXEC sysctl -p "${dryrun[@]}" /etc/sysctl.d/dietpi-ipfs.conf
|
|
fi
|
|
fi
|
|
|
|
if To_Install 16 # microblog.pub
|
|
then
|
|
local micro_name='microblog-pub'
|
|
# Obtain latest Python 3.11.y version supported by pyenv
|
|
local micro_python_version=$(curl -sSfL 'https://api.github.com/repos/pyenv/pyenv/contents/plugins/python-build/share/python-build?ref=master' | mawk -F\" '/^ *"name": "3\.11\.[0-9]*",$/{print $4}' | sort -Vr | head -1)
|
|
[[ $micro_python_version ]] || { micro_python_version='3.11.14'; G_DIETPI-NOTIFY 1 "Automatic latest Python version detection failed. Version \"$micro_python_version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
local micro_pyenv_dir="/opt/$micro_name"
|
|
local micro_pyenv_activate_file="$micro_pyenv_dir/pyenv-activate.sh"
|
|
local micro_virtualenv="$micro_pyenv_dir/.virtual_path"
|
|
local micro_data_dir="/mnt/dietpi_userdata/$micro_name"
|
|
local micro_systemd="/etc/systemd/system/$micro_name.service"
|
|
local micro_functions="/etc/bashrc.d/$micro_name.sh"
|
|
|
|
# Clone the repo into data dir
|
|
if [[ ! -d $micro_data_dir ]]
|
|
then
|
|
G_EXEC_OUTPUT=1 G_EXEC git clone 'https://git.sr.ht/~tsileo/microblog.pub' "$micro_data_dir"
|
|
# Enable remote access on port 8007
|
|
G_EXEC sed --follow-symlinks -i 's/uvicorn app/uvicorn --host 0.0.0.0 --port 8007 app/' "$micro_data_dir/misc/supervisord.conf"
|
|
G_EXEC sed --follow-symlinks -i 's/8000/8007/' "$micro_data_dir/data/tests.toml"
|
|
fi
|
|
|
|
# Configure pip
|
|
# - Disable cache
|
|
G_EXEC mkdir -p "$micro_data_dir/.pip"
|
|
G_EXEC eval "echo -e '[global]\nno-cache-dir=true' > '$micro_data_dir/.pip/pip.conf'"
|
|
|
|
# Configure Poetry
|
|
# - > The "poetry.dev-dependencies" section is deprecated and will be removed in a future version. Use "poetry.group.dev.dependencies" instead.
|
|
G_EXEC sed --follow-symlinks -i '/^\[poetry.dev-dependencies\]$/c\[poetry.group.dev.dependencies]' "$micro_data_dir/pyproject.toml"
|
|
# - Disable package mode to prevent: "Error: The current project could not be installed: No file/folder found for package microblogpub"
|
|
G_CONFIG_INJECT 'package-mode[[:blank:]]' 'package-mode = false' "$micro_data_dir/pyproject.toml" '\[tool.poetry\]'
|
|
|
|
# User
|
|
Create_User -d "$micro_data_dir" "$micro_name"
|
|
G_EXEC chown -R "$micro_name:$micro_name" "$micro_data_dir"
|
|
|
|
# Dependencies: https://git.sr.ht/~tsileo/microblog.pub/tree/v2/item/pyproject.toml
|
|
PYTHON_VERSION=$micro_python_version Python_Deps -u "$micro_name" -P pyenv poetry bcrypt brotli greenlet113 libsass lxml pillow
|
|
|
|
# Create a Python environment via pyenv
|
|
# - https://python-poetry.org/docs/managing-environments/
|
|
Download_Install 'https://github.com/pyenv/pyenv/archive/master.tar.gz'
|
|
G_EXEC chown -R "$micro_name:$micro_name" pyenv-master
|
|
# - Start with fresh instance to allow clean pyenv and Python updates and fix broken instances.
|
|
[[ -d $micro_pyenv_dir ]] && G_EXEC rm -R "$micro_pyenv_dir"
|
|
G_EXEC mv pyenv-master "$micro_pyenv_dir"
|
|
|
|
# Generate script to activate pyenv
|
|
echo "#!/bin/dash
|
|
cd $micro_pyenv_dir || return 1
|
|
export PYENV_ROOT='$micro_pyenv_dir' || return 1
|
|
export PATH=\"\$PYENV_ROOT/bin:\$PATH\" || return 1
|
|
eval \"\$(pyenv init --path)\" || return 1
|
|
eval \"\$(pyenv init -)\" || return 1
|
|
cd $micro_data_dir
|
|
[ -f '.cargo/env' ] && . .cargo/env
|
|
PS1=\"(microblog.pub) \$PS1\"" > "$micro_pyenv_activate_file"
|
|
|
|
G_EXEC_DESC="Compiling and installing Python $micro_python_version into pyenv, which will take a while ..."
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec pyenv install $micro_python_version"
|
|
G_EXEC_DESC="Setting Python $micro_python_version as global version for this pyenv instance"
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec pyenv global $micro_python_version"
|
|
G_EXEC_DESC='Upgrading base modules: pip setuptools wheel'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec pip3 install -U pip setuptools wheel"
|
|
G_EXEC_DESC='Installing Poetry'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec pip3 install poetry"
|
|
G_EXEC_DESC='Updating dependency locks'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec poetry update --lock"
|
|
G_EXEC_DESC='Adding setuptools dependency for Poetry needed for config wizard' # <81: /mnt/dietpi_userdata/microblog-pub/.cache/pypoetry/virtualenvs/microblogpub-qTlMHCqJ-py3.11/lib/python3.11/site-packages/boussole/__init__.py:7: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec poetry add --lock 'setuptools<81'"
|
|
G_EXEC_DESC='Installing microblog.pub'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; exec poetry install"
|
|
G_EXEC_DESC='Storing Poetry virtualenv path'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$micro_name" -- dash -c ". $micro_pyenv_activate_file; poetry env info | grep -Po '(?<=^Path:\s).*/virtualenvs/.*' > '$micro_virtualenv'"
|
|
read -r VENV_DIR < "$micro_virtualenv"
|
|
# shellcheck disable=SC2016
|
|
G_EXEC_DESC='Checking Poetry virtualenv path' G_EXEC eval '[[ $VENV_DIR ]]'
|
|
G_EXEC rm "$micro_virtualenv"
|
|
|
|
# Generate functions for later configuration and install to profile
|
|
cat << _EOF_ > "$micro_functions"
|
|
#!/bin/dash
|
|
microblog-pub()
|
|
{
|
|
case \$1 in
|
|
c*) sudo -u '$micro_name' dash -c '. $micro_pyenv_activate_file; poetry run inv configuration-wizard && poetry run inv migrate-db' && systemctl enable '$micro_name';;
|
|
u*) sudo -u '$micro_name' dash -c '. $micro_pyenv_activate_file; git pull && poetry run inv update';;
|
|
v*) sudo -u '$micro_name' bash --init-file '$micro_pyenv_activate_file';;
|
|
*) echo 'microblog.pub helper script
|
|
|
|
usage: microblog-pub <configure|update|venv>
|
|
|
|
where:
|
|
configure runs the configuration wizard and updates the microblog environment.
|
|
update pulls the latest changes from the microblog repository and reconfigures.
|
|
venv starts a virtual environment where the microblog can be configured.' && return 1;;
|
|
esac
|
|
|
|
sudo systemctl restart '$micro_name'
|
|
}
|
|
_EOF_
|
|
# Generate systemd service
|
|
cat << _EOF_ > "$micro_systemd"
|
|
[Unit]
|
|
Description=microblog.pub (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
ConditionPathExists=$micro_data_dir/data/profile.toml
|
|
|
|
[Service]
|
|
User=$micro_name
|
|
SyslogIdentifier=microblog.pub
|
|
WorkingDirectory=$micro_data_dir
|
|
Environment="VENV_DIR=$VENV_DIR"
|
|
ExecStart=/bin/dash -c '. $micro_pyenv_activate_file; exec poetry run supervisord -c misc/supervisord.conf -n'
|
|
RestartForceExitStatus=100
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
G_WHIP_MSG '[ INFO ] microblog.pub installation finished\n\nIn order to complete the setup, please run "microblog-pub configure" in a new bash session.\n\nNB: Append the port ":8007" to the domain when being asked for it if you do not use a reverse proxy.'
|
|
G_DIETPI-NOTIFY 0 'microblog.pub installation finished. In order to complete the setup, please run "microblog-pub configure" in a new bash session. Append the port ":8007" to the domain when being asked for it if you do not use a reverse proxy.'
|
|
fi
|
|
|
|
if To_Install 2 fahclient # Folding@Home
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Pre-configuring FAHClient DEB package'
|
|
debconf-set-selections <<< 'fahclient fahclient/autostart boolean false' # Do not start SysV service after package install
|
|
debconf-set-selections <<< 'fahclient fahclient/power select light'
|
|
debconf-set-selections <<< 'fahclient fahclient/team string 234437' # Team "DietPi"
|
|
debconf-set-selections <<< 'fahclient fahclient/user string DietPi' # User "DietPi"
|
|
debconf-set-selections <<< 'fahclient fahclient/passkey string 06c869246e88c00cb05cc4d1758a97f9' # Passkey for user "DietPi"
|
|
|
|
local arch1='64bit' arch2='amd64'
|
|
(( $G_HW_ARCH == 3 )) && arch1='arm64' arch2='arm64'
|
|
Download_Install "https://download.foldingathome.org/releases/v7/public/fahclient/debian-stable-$arch1/release/fahclient_7.6.21_$arch2.deb"
|
|
|
|
# Remove obsolete config + data directories and SysV service + config
|
|
[[ -d '/var/lib/fahclient' ]] && G_EXEC rm -R /var/lib/fahclient
|
|
[[ -d '/etc/fahclient' ]] && G_EXEC rm -R /etc/fahclient
|
|
[[ -f '/etc/default/fahclient' ]] && G_EXEC rm /etc/default/fahclient
|
|
Remove_SysV FAHClient
|
|
|
|
# Prepare our new config + data directory if not yet present
|
|
if [[ ! -f '/mnt/dietpi_userdata/fahclient/config.xml' ]]
|
|
then
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/fahclient
|
|
dps_index=$software_id Download_Install 'config.xml' /mnt/dietpi_userdata/fahclient/config.xml
|
|
fi
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/fahclient.service
|
|
[Unit]
|
|
Description=Folding@Home (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=fahclient
|
|
WorkingDirectory=/mnt/dietpi_userdata/fahclient
|
|
ExecStart=$(command -v FAHClient)
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R fahclient /mnt/dietpi_userdata/fahclient
|
|
fi
|
|
|
|
if To_Install 47 # ownCloud
|
|
then
|
|
aDEPS=("php$PHP_VERSION-intl") # https://doc.owncloud.com/server/next/admin_manual/installation/manual_installation/manual_installation_prerequisites.html#php-extensions
|
|
|
|
if [[ -f '/var/www/owncloud/occ' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Existing ownCloud installation found, will NOT overwrite...'
|
|
else
|
|
local datadir=$(sed -n '/^[[:blank:]]*SOFTWARE_OWNCLOUD_DATADIR=/{s/^[^=]*=//;s|/$||;p;q}' /boot/dietpi.txt)
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/owncloud_data'
|
|
if [[ -f $datadir/dietpi-owncloud-installation-backup/occ ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'ownCloud installation backup found, starting recovery...'
|
|
G_EXEC cp -a "$datadir/dietpi-owncloud-installation-backup/." /var/www/owncloud/
|
|
# Correct config.php data directory entry, in case it changed due to server migration:
|
|
G_CONFIG_INJECT "'datadirectory'" "'datadirectory' => '$datadir'," /var/www/owncloud/config/config.php "'dbtype'"
|
|
else
|
|
Download_Install 'https://download.owncloud.com/server/stable/owncloud-latest.tar.bz2' /var/www
|
|
fi
|
|
fi
|
|
|
|
[[ ${aDEPS[0]} ]] && { G_DIETPI-NOTIFY 2 'Installing required PHP modules'; G_AGI "${aDEPS[@]}"; aDEPS=(); }
|
|
|
|
G_DIETPI-NOTIFY 2 'Enabling required PHP modules'
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
local json=()
|
|
[[ $PHP_VERSION == 8* ]] || json=('json')
|
|
G_EXEC phpenmod ctype curl dom gd iconv intl mbstring pdo_mysql posix simplexml xmlreader xmlwriter zip fileinfo opcache apcu redis exif "${json[@]}"
|
|
G_DIETPI-NOTIFY 2 'Enabling APCu memory cache for PHP command line usage (CLI) as well, including ownCloud occ command and cron jobs.'
|
|
echo -e '; ownCloud PHP settings\n; priority=98\napc.enable_cli=1' > "/etc/php/$PHP_VERSION/mods-available/dietpi-owncloud.ini"
|
|
G_EXEC phpenmod dietpi-owncloud
|
|
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Apache webserver found, enabling ownCloud specific configuration.' # https://doc.owncloud.com/server/next/admin_manual/installation/manual_installation/manual_installation_apache.html
|
|
a2enmod rewrite headers env dir mime 1> /dev/null
|
|
local owncloud_conf='/etc/apache2/sites-available/dietpi-owncloud.conf'
|
|
[[ -f $owncloud_conf ]] && G_EXEC mv "$owncloud_conf" "$owncloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'apache.owncloud.conf' "$owncloud_conf"
|
|
a2ensite dietpi-owncloud 1> /dev/null
|
|
# Cal/CardDAV redirects to ownCloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to ownCloud endpoint:
|
|
Redirect 301 /.well-known/carddav /owncloud/remote.php/dav
|
|
Redirect 301 /.well-known/caldav /owncloud/remote.php/dav' > /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
a2enconf dietpi-dav_redirect
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Lighttpd webserver found, enabling ownCloud specific configuration.'
|
|
|
|
# Enable required modules
|
|
G_CONFIG_INJECT '"mod_access",' ' "mod_access",' /etc/lighttpd/lighttpd.conf '"mod_.+",'
|
|
[[ -f '/etc/lighttpd/conf-enabled/05-setenv.conf' ]] || G_EXEC lighty-enable-mod setenv
|
|
|
|
# Move ownCloud configuration file in place and activate it
|
|
owncloud_conf='/etc/lighttpd/conf-available/99-dietpi-owncloud.conf'
|
|
[[ -f $owncloud_conf ]] && G_EXEC mv "$owncloud_conf" "$owncloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'lighttpd.owncloud.conf' "$owncloud_conf"
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod rewrite dietpi-owncloud
|
|
|
|
# Cal/CardDAV redirects to ownCloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to ownCloud endpoint:
|
|
url.redirect += (
|
|
"^/.well-known/caldav" => "/owncloud/remote.php/dav",
|
|
"^/.well-known/carddav" => "/owncloud/remote.php/dav"
|
|
)' > /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
[[ -f '/etc/lighttpd/conf-enabled/99-dietpi-dav_redirect.conf' ]] || G_EXEC lighty-enable-mod dietpi-dav_redirect
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Nginx webserver found, enabling ownCloud specific configuration.' # https://github.com/owncloud/docs/blob/deda107/modules/admin_manual/examples/installation/nginx/subdirectory-configuration.conf
|
|
local owncloud_conf='/etc/nginx/sites-dietpi/dietpi-owncloud.conf'
|
|
[[ -f $owncloud_conf ]] && G_EXEC mv "$owncloud_conf" "$owncloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'nginx.owncloud.conf' "$owncloud_conf"
|
|
|
|
# Cal/CardDAV redirects to ownCloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to ownCloud endpoint:
|
|
location = /.well-known/carddav { return 301 /owncloud/remote.php/dav/; }
|
|
location = /.well-known/caldav { return 301 /owncloud/remote.php/dav/; }' > /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
fi
|
|
|
|
# Start MariaDB and Redis (for reinstalls) for database creation and occ command
|
|
G_EXEC systemctl restart mariadb
|
|
G_EXEC systemctl restart redis-server
|
|
|
|
# Initially add occ command shortcut, will be added as alias by /etc/bashrc.d/dietpi.bash if occ file exist:
|
|
occ(){ runuser -u www-data -- php /var/www/owncloud/occ "$@"; }
|
|
|
|
# Adjusting config file:
|
|
local config_php='/var/www/owncloud/config/config.php'
|
|
|
|
local datadir=$(sed -n '/^[[:blank:]]*SOFTWARE_OWNCLOUD_DATADIR=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/owncloud_data'
|
|
G_EXEC mkdir -p "$datadir"
|
|
G_EXEC chown -R www-data:www-data /var/www/owncloud "$datadir"
|
|
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/owncloud' ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 'ownCloud database found, will NOT overwrite.'
|
|
if [[ ! -f $config_php ]]; then
|
|
|
|
G_WHIP_MSG '[WARNING] Existing ownCloud database was found, but no related install directory\n
|
|
A remaining MariaDB "owncloud" database from an earlier installed instance was found. But the related install directory "/var/www/owncloud/config/config.php" does not exist.
|
|
Since running a fresh install with an existing database can produce data corruption if the versions do not exactly match, you either need to remove the database or find and place the related install directory.\n
|
|
We cannot predict your aim and do not want to mess or break your data, so please do this manually.\n
|
|
To remove the existing database (including e.g. contacts, calendar, file tags etc.):
|
|
# mysqladmin drop owncloud
|
|
Otherwise to copy an existing instance in place:
|
|
# rm -R /var/www/owncloud
|
|
# mkdir /var/www/owncloud
|
|
# cp -a /path/to/existing/owncloud/. /var/www/owncloud/
|
|
The install script will now exit. After applying one of the the above, rerun dietpi-software, e.g.:
|
|
# dietpi-software install 47'
|
|
/boot/dietpi/dietpi-services start
|
|
exit 1
|
|
|
|
fi
|
|
|
|
elif [[ -f $datadir/dietpi-owncloud-database-backup.sql ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 'ownCloud database backup found, starting recovery...'
|
|
local dbuser=$(grep -m1 "^[[:blank:]]*'dbuser'" "$config_php" | mawk -F\' '{print $4}')
|
|
local dbpass=$(grep -m1 "^[[:blank:]]*'dbpassword'" "$config_php" | mawk -F\' '{print $4}')
|
|
/boot/dietpi/func/create_mysql_db owncloud "$dbuser" "$dbpass"
|
|
mysql owncloud < "$datadir/dietpi-owncloud-database-backup.sql"
|
|
# Adjust database data directory entry, in case it changed due to server migration
|
|
local datadir_old=$(grep -m1 "^[[:blank:]]*'datadirectory'" "$config_php" | mawk -F\' '{print $4}')
|
|
G_EXEC mysql -e "update owncloud.oc_storages set id='local::$datadir/' where id rlike 'local::$datadir_old';"
|
|
|
|
elif ! grep -q "'installed' => true," "$config_php" 2>/dev/null; then
|
|
|
|
local username=$(sed -n '/^[[:blank:]]*SOFTWARE_OWNCLOUD_NEXTCLOUD_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $username ]] || username='admin'
|
|
|
|
# For MariaDB, temporary database admin user needs to be created, as 'root' uses unix_socket login, which cannot be accessed by sudo -u www-data.
|
|
# - Create random temporary alphanumeric 30 characters password
|
|
local oc_password=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
G_EXEC mysql -e "grant all privileges on *.* to tmp_root@localhost identified by '$oc_password' with grant option;"
|
|
|
|
G_EXEC_DESC='ownCloud occ install'
|
|
# - Replace password strings internally to avoid printing it to console
|
|
G_EXEC_PRE_FUNC(){ acommand[6]="--database-pass=$oc_password" acommand[8]="--admin-pass=$GLOBAL_PW"; }
|
|
# - Checking output for stack trace to handle internal errors that do not lead to php error exit code
|
|
G_EXEC_POST_FUNC(){ grep -qi 'Stack trace' "$fp_log" && exit_code=255; }
|
|
G_EXEC occ maintenance:install --no-interaction --database='mysql' --database-name='owncloud' --database-user='tmp_root' --database-pass="${oc_password//?/X}" --admin-user="$username" --admin-pass="${GLOBAL_PW//?/X}" --data-dir="$datadir"
|
|
G_EXEC mysql -e 'drop user tmp_root@localhost;'
|
|
unset -v oc_password
|
|
|
|
# Remove obsolete default data dir
|
|
[[ $(readlink -f "$datadir") != $(readlink -f /var/www/owncloud/data) ]] && G_EXEC rm -R /var/www/owncloud/data
|
|
|
|
fi
|
|
|
|
# Enable ownCloud to use 4-byte database
|
|
G_CONFIG_INJECT "'mysql.utf8mb4'" "'mysql.utf8mb4' => true," "$config_php" "'dbpassword'"
|
|
|
|
# Add local IP and hostname to trusted domains.
|
|
# If "1 => '" does not exist, the config.php is not copied e.g. from older instance, so we add entries.
|
|
if ! grep -q "1 => '" "$config_php"; then
|
|
|
|
sed --follow-symlinks -i "/0 => 'localhost'/a 1 => '$(G_GET_NET ip)'," "$config_php"
|
|
sed --follow-symlinks -i "/1 => '/a 2 => '$HOSTNAME'," "$config_php"
|
|
|
|
fi
|
|
|
|
# Set CLI URL to ownCloud sub directory:
|
|
G_EXEC sed --follow-symlinks -i "s|'http://localhost'|'http://localhost/owncloud'|" "$config_php"
|
|
|
|
# Set pretty URLs (without /index.php/) on Apache:
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 )); then
|
|
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT "'htaccess.RewriteBase'" "'htaccess.RewriteBase' => '/owncloud'," "$config_php" "'overwrite.cli.url'"
|
|
occ maintenance:update:htaccess
|
|
|
|
fi
|
|
|
|
# APCu Memcache
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT "'memcache.local'" "'memcache.local' => '\\\\OC\\\\Memcache\\\\APCu'," "$config_php" "'version'"
|
|
|
|
# Redis for transactional file locking:
|
|
G_DIETPI-NOTIFY 2 'Enabling Redis for transactional file locking.' # https://doc.owncloud.org/server/administration_manual/configuration/server/caching_configuration.html#configuring-transactional-file-locking
|
|
local redis_conf='/etc/redis/redis.conf'
|
|
# - Enable Redis socket and grant www-data access to it
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'unixsocket[[:blank:]]' 'unixsocket /run/redis/redis-server.sock' "$redis_conf"
|
|
G_CONFIG_INJECT 'unixsocketperm[[:blank:]]' 'unixsocketperm 770' "$redis_conf"
|
|
G_EXEC usermod -aG redis www-data
|
|
G_EXEC systemctl restart redis-server
|
|
# - Enable ownCloud to use Redis socket for transactional file locking:
|
|
G_CONFIG_INJECT "'filelocking.enabled'" "'filelocking.enabled' => true," "$config_php" "'memcache.local'"
|
|
local redis_sock=$(grep -m1 '^[[:blank:]]*unixsocket[[:blank:]]' "$redis_conf" | mawk '{print $2}') # Re-estimate in case of existing custom path
|
|
GCI_PRESERVE=1 GCI_NEWLINE=1 G_CONFIG_INJECT "'memcache.locking'" "'memcache.locking' => '\\\\OC\\\\Memcache\\\\Redis',\n'redis' => array ('host' => '$redis_sock', 'port' => 0,)," "$config_php" "'filelocking.enabled'"
|
|
|
|
# Enable ownCloud background cron job:
|
|
crontab -u www-data -l | grep -q '/var/www/owncloud/.*cron' || { crontab -u www-data -l; echo '*/15 * * * * php /var/www/owncloud/occ system:cron'; } | crontab -u www-data -
|
|
occ background:cron
|
|
|
|
# On <1 GiB devices assure at least 512 MiB swap space are available to stand 512 MiB file uploads + increased PHP cache and session file usage: https://github.com/MichaIng/DietPi/issues/2293
|
|
(( $RAM_PHYS < 924 && $(free -m | mawk '/^Swap:/{print $2;exit}') < 512 )) && /boot/dietpi/func/dietpi-set_swapfile 512
|
|
fi
|
|
|
|
if To_Install 114 # Nextcloud
|
|
then
|
|
aDEPS=("php$PHP_VERSION-intl") # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#prerequisites-for-manual-installation
|
|
|
|
if [[ -f '/var/www/nextcloud/occ' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Existing Nextcloud installation found, will NOT overwrite...'
|
|
else
|
|
local datadir=$(sed -n '/^[[:blank:]]*SOFTWARE_NEXTCLOUD_DATADIR=/{s/^[^=]*=//;s|/$||;p;q}' /boot/dietpi.txt)
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/nextcloud_data'
|
|
if [[ -f $datadir/dietpi-nextcloud-installation-backup/occ ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Nextcloud installation backup found, starting recovery...'
|
|
G_EXEC cp -a "$datadir/dietpi-nextcloud-installation-backup/." /var/www/nextcloud/
|
|
# Correct config.php data directory entry, in case it changed due to server migration:
|
|
G_CONFIG_INJECT "'datadirectory'" "'datadirectory' => '$datadir'," /var/www/nextcloud/config/config.php "'dbtype'"
|
|
else
|
|
# Nextcloud 26 doesn't support PHP7.4 anymore: https://github.com/nextcloud/server/pull/34997
|
|
local version='latest'
|
|
if (( $G_DISTRO < 7 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Downloading latest Nextcloud 25, since Nextcloud 26 does not support PHP7.4 anymore'
|
|
version='latest-25'
|
|
fi
|
|
Download_Install "https://download.nextcloud.com/server/releases/$version.tar.bz2" /var/www
|
|
fi
|
|
fi
|
|
|
|
# Bookworm: Patch for PHP 8.2 support, which works quite well: https://github.com/nextcloud/server/issues/32595#issuecomment-1387559520
|
|
if (( $G_DISTRO > 6 )) && grep -q '>= 80200' /var/www/nextcloud/lib/versioncheck.php
|
|
then
|
|
G_WHIP_MSG '[WARNING] Patching Nextcloud to support PHP 8.2 for Bookworm
|
|
\nNextcloud 25 does not support PHP 8.2, but it does work quite well:
|
|
- https://github.com/nextcloud/server/issues/32595#issuecomment-1387559520
|
|
\nWe are patching the PHP version check, but this has two implications:
|
|
- You will see an integrity check error on Nextcloud admin panel.
|
|
- You will need to redo the patch after Nextcloud updates to future 25.x versions:
|
|
# sed --follow-symlinks -i '\''s/>= 80200/>= 80300/'\'' /var/www/nextcloud/lib/versioncheck.php
|
|
\nWe recommend to update to Nextcloud 26 as fast as possible to get official PHP 8.2 support.'
|
|
G_EXEC sed --follow-symlinks -i 's/>= 80200/>= 80300/' /var/www/nextcloud/lib/versioncheck.php
|
|
fi
|
|
|
|
[[ ${aDEPS[0]} ]] && { G_DIETPI-NOTIFY 2 'Installing required PHP modules'; G_AGI "${aDEPS[@]}"; aDEPS=(); }
|
|
|
|
G_DIETPI-NOTIFY 2 'Enabling required PHP modules'
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
local json=()
|
|
[[ $PHP_VERSION == 8* ]] || json=('json')
|
|
G_EXEC phpenmod ctype curl dom gd intl mbstring pdo_mysql posix simplexml xmlreader xmlwriter zip fileinfo opcache apcu redis exif "${json[@]}"
|
|
|
|
G_DIETPI-NOTIFY 2 'Apply PHP override settings for Nextcloud.' # https://docs.nextcloud.com/server/stable/admin_manual/installation/server_tuning.html#enable-php-opcache
|
|
local memory_consumption=$(sed -n '/^[[:blank:]]*opcache.memory_consumption=/{s/^[^=]*=//p;q}' "/etc/php/$PHP_VERSION/mods-available/dietpi.ini")
|
|
(( $memory_consumption < 64 )) && memory_consumption='\nopcache.memory_consumption=64' || memory_consumption=
|
|
echo -e "; Nextcloud PHP settings\n; priority=98\nmemory_limit=512M$memory_consumption\nopcache.revalidate_freq=5" > "/etc/php/$PHP_VERSION/mods-available/dietpi-nextcloud.ini"
|
|
# Enable APCu for CLI only for Nextcloud 30 and lower: https://github.com/nextcloud/server/pull/46151
|
|
(( $(mawk -F[\'.] '/^\$OC_VersionString/{print $2}' /var/www/nextcloud/version.php) < 31 )) && G_EXEC eval "echo 'apc.enable_cli=1' >> '/etc/php/$PHP_VERSION/mods-available/dietpi-nextcloud.ini'"
|
|
G_EXEC phpenmod dietpi-nextcloud
|
|
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Apache webserver found, enabling Nextcloud specific configuration.' # https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html#apache-web-server-configuration
|
|
a2enmod rewrite headers env dir mime 1> /dev/null
|
|
local nextcloud_conf='/etc/apache2/sites-available/dietpi-nextcloud.conf'
|
|
[[ -f $nextcloud_conf ]] && G_EXEC mv "$nextcloud_conf" "$nextcloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'apache.nextcloud.conf' "$nextcloud_conf"
|
|
a2ensite dietpi-nextcloud 1> /dev/null
|
|
# Cal/CardDAV redirects to Nextcloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to Nextcloud endpoint:
|
|
Redirect 301 /.well-known/carddav /nextcloud/remote.php/dav
|
|
Redirect 301 /.well-known/caldav /nextcloud/remote.php/dav' > /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
a2enconf dietpi-dav_redirect
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Lighttpd webserver found, enabling Nextcloud specific configuration.'
|
|
|
|
# Enable required modules
|
|
G_CONFIG_INJECT '"mod_access",' ' "mod_access",' /etc/lighttpd/lighttpd.conf '"mod_.+",'
|
|
[[ -f '/etc/lighttpd/conf-enabled/05-setenv.conf' ]] || G_EXEC lighty-enable-mod setenv
|
|
|
|
# Move Nextcloud configuration file in place and activate it
|
|
nextcloud_conf='/etc/lighttpd/conf-available/99-dietpi-nextcloud.conf'
|
|
[[ -f $nextcloud_conf ]] && G_EXEC mv "$nextcloud_conf" "$nextcloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'lighttpd.nextcloud.conf' "$nextcloud_conf"
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod rewrite dietpi-nextcloud
|
|
|
|
# Cal/CardDAV redirects to Nextcloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to Nextcloud endpoint:
|
|
url.redirect += (
|
|
"^/.well-known/caldav" => "/nextcloud/remote.php/dav",
|
|
"^/.well-known/carddav" => "/nextcloud/remote.php/dav"
|
|
)' > /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
[[ -f '/etc/lighttpd/conf-enabled/99-dietpi-dav_redirect.conf' ]] || G_EXEC lighty-enable-mod dietpi-dav_redirect
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Nginx webserver found, enabling Nextcloud specific configuration.' # https://docs.nextcloud.com/server/stable/admin_manual/installation/nginx.html
|
|
# shellcheck disable=SC2016
|
|
echo '# Set the "immutable" cache control option for assets with a cache busting "v=" argument
|
|
map $arg_v $asset_immutable {
|
|
"" "";
|
|
default ", immutable";
|
|
}' > /etc/nginx/conf.d/dietpi-nextcloud.conf
|
|
local nextcloud_conf='/etc/nginx/sites-dietpi/dietpi-nextcloud.conf'
|
|
[[ -f $nextcloud_conf ]] && G_EXEC mv "$nextcloud_conf" "$nextcloud_conf.dietpi-old"
|
|
dps_index=$software_id Download_Install 'nginx.nextcloud.conf' "$nextcloud_conf"
|
|
|
|
# Cal/CardDAV redirects to Nextcloud DAV endpoint
|
|
echo '# Redirect Cal/CardDAV requests to Nextcloud endpoint:
|
|
location = /.well-known/carddav { return 301 /nextcloud/remote.php/dav/; }
|
|
location = /.well-known/caldav { return 301 /nextcloud/remote.php/dav/; }' > /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
fi
|
|
|
|
# Start MariaDB and Redis (for reinstalls) for database creation and ncc command
|
|
G_EXEC systemctl restart mariadb
|
|
G_EXEC systemctl restart redis-server
|
|
|
|
# Initially add occ command shortcut, will be added as alias by /etc/bashrc.d/dietpi.bash if occ file exist:
|
|
ncc(){ runuser -u www-data -- php /var/www/nextcloud/occ "$@"; }
|
|
|
|
# Adjusting config file:
|
|
local config_php='/var/www/nextcloud/config/config.php'
|
|
|
|
local datadir=$(sed -n '/^[[:blank:]]*SOFTWARE_NEXTCLOUD_DATADIR=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/nextcloud_data'
|
|
G_EXEC mkdir -p "$datadir"
|
|
G_EXEC chown -R www-data:www-data /var/www/nextcloud "$datadir"
|
|
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/nextcloud' ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 'Nextcloud database found, will NOT overwrite.'
|
|
if [[ ! -f $config_php ]]; then
|
|
|
|
G_WHIP_MSG '[WARNING] Existing Nextcloud database was found, but no related install directory\n
|
|
A remaining MariaDB "nextcloud" database from an earlier installed instance was found. But the related install directory "/var/www/nextcloud/config/config.php" does not exist.
|
|
Since running a fresh install with an existing database can produce data corruption if the versions do not exactly match, you either need to remove the database or find and place the related install directory.\n
|
|
We cannot predict your aim and do not want to mess or break your data, so please do this manually.\n
|
|
To remove the existing database (including e.g. contacts, calendar, file tags etc.):
|
|
# mysqladmin drop nextcloud
|
|
Otherwise to copy an existing instance in place:
|
|
# rm -R /var/www/nextcloud
|
|
# mkdir /var/www/nextcloud
|
|
# cp -a /path/to/existing/nextcloud/. /var/www/nextcloud/
|
|
The install script will now exit. After applying one of the the above, rerun dietpi-software, e.g.:
|
|
# dietpi-software install 114'
|
|
/boot/dietpi/dietpi-services start
|
|
exit 1
|
|
|
|
fi
|
|
|
|
elif [[ -f $datadir/dietpi-nextcloud-database-backup.sql ]]; then
|
|
|
|
G_DIETPI-NOTIFY 2 'Nextcloud database backup found, starting recovery...'
|
|
local dbuser=$(grep -m1 "^[[:blank:]]*'dbuser'" "$config_php" | mawk -F\' '{print $4}')
|
|
local dbpass=$(grep -m1 "^[[:blank:]]*'dbpassword'" "$config_php" | mawk -F\' '{print $4}')
|
|
/boot/dietpi/func/create_mysql_db nextcloud "$dbuser" "$dbpass"
|
|
mysql nextcloud < "$datadir/dietpi-nextcloud-database-backup.sql"
|
|
# Adjust database data directory entry, in case it changed due to server migration
|
|
local datadir_old=$(grep -m1 "^[[:blank:]]*'datadirectory'" "$config_php" | mawk -F\' '{print $4}')
|
|
G_EXEC mysql -e "update nextcloud.oc_storages set id='local::$datadir/' where id rlike 'local::$datadir_old';"
|
|
|
|
elif ! grep -q "'installed' => true," "$config_php" 2>/dev/null; then
|
|
|
|
local username=$(sed -n '/^[[:blank:]]*SOFTWARE_OWNCLOUD_NEXTCLOUD_USERNAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $username ]] || username='admin'
|
|
|
|
# For MariaDB, temporary database admin user needs to be created, as 'root' uses unix_socket login, which cannot be accessed by sudo -u www-data.
|
|
# - Create random temporary alphanumeric 30 characters password
|
|
local nc_password=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
G_EXEC mysql -e "grant all privileges on *.* to tmp_root@localhost identified by '$nc_password' with grant option;"
|
|
|
|
G_EXEC_DESC='Nextcloud ncc install'
|
|
# - Replace password strings internally to avoid printing it to console
|
|
G_EXEC_PRE_FUNC(){ acommand[6]="--database-pass=$nc_password" acommand[8]="--admin-pass=$GLOBAL_PW"; }
|
|
# - Checking output for stack trace to handle internal errors that do not lead to php error exit code
|
|
# - Workaround Nextcloud 14.0.3 throwing an error, when data dir path contains a symlink: https://github.com/nextcloud/server/issues/12247
|
|
G_EXEC_POST_FUNC(){
|
|
|
|
if (( $exit_code )); then
|
|
|
|
grep -q 'Following symlinks is not allowed' "$fp_log" && { cp -a /var/www/nextcloud/core/skeleton/. "$datadir/$username/files/"; exit_code=0; }
|
|
|
|
else
|
|
|
|
grep -qi 'Stack trace' "$fp_log" && exit_code=255
|
|
|
|
fi
|
|
|
|
}
|
|
G_EXEC ncc maintenance:install --no-interaction --database='mysql' --database-name='nextcloud' --database-user='tmp_root' --database-pass="${nc_password//?/X}" --admin-user="$username" --admin-pass="${GLOBAL_PW//?/X}" --data-dir="$datadir"
|
|
G_EXEC mysql -e 'drop user tmp_root@localhost;'
|
|
unset -v nc_password
|
|
|
|
# Remove obsolete default data dir
|
|
[[ $(readlink -f "$datadir") != $(readlink -f /var/www/nextcloud/data) ]] && G_EXEC rm -R /var/www/nextcloud/data
|
|
|
|
fi
|
|
|
|
# Enable Nextcloud to use 4-byte database
|
|
G_CONFIG_INJECT "'mysql.utf8mb4'" "'mysql.utf8mb4' => true," "$config_php" "'dbpassword'"
|
|
|
|
# Disable trusted_domains.
|
|
grep -q "1 => '*'" "$config_php" || sed --follow-symlinks -i "/0 => 'localhost'/a 1 => '*'," "$config_php"
|
|
|
|
# Set CLI URL to Nextcloud sub directory:
|
|
G_EXEC sed --follow-symlinks -i "s|'http://localhost'|'http://localhost/nextcloud'|" "$config_php"
|
|
|
|
# Set pretty URLs (without /index.php/) on Apache:
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 )); then
|
|
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT "'htaccess.RewriteBase'" "'htaccess.RewriteBase' => '/nextcloud'," "$config_php" "'overwrite.cli.url'"
|
|
ncc maintenance:update:htaccess
|
|
|
|
fi
|
|
|
|
# APCu Memcache
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT "'memcache.local'" "'memcache.local' => '\\\\OC\\\\Memcache\\\\APCu'," "$config_php" "'version'"
|
|
|
|
# Redis for transactional file locking:
|
|
G_DIETPI-NOTIFY 2 'Enabling Redis for transactional file locking.' # https://docs.nextcloud.com/server/stable/admin_manual/configuration_files/files_locking_transactional.html
|
|
local redis_conf='/etc/redis/redis.conf'
|
|
# - Enable Redis socket and grant www-data access to it
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'unixsocket[[:blank:]]' 'unixsocket /run/redis/redis-server.sock' "$redis_conf"
|
|
G_CONFIG_INJECT 'unixsocketperm[[:blank:]]' 'unixsocketperm 770' "$redis_conf"
|
|
G_EXEC usermod -aG redis www-data
|
|
G_EXEC systemctl restart redis-server
|
|
# - Enable Nextcloud to use Redis socket:
|
|
G_CONFIG_INJECT "'filelocking.enabled'" "'filelocking.enabled' => true," "$config_php" "'memcache.local'"
|
|
local redis_sock=$(grep -m1 '^[[:blank:]]*unixsocket[[:blank:]]' "$redis_conf" | mawk '{print $2}') # Re-estimate in case of existing custom path
|
|
GCI_PRESERVE=1 GCI_NEWLINE=1 G_CONFIG_INJECT "'memcache.locking'" "'memcache.locking' => '\\\\OC\\\\Memcache\\\\Redis',\n'redis' => array ('host' => '$redis_sock', 'port' => 0,)," "$config_php" "'filelocking.enabled'"
|
|
|
|
# Tweak Argon2 hashing
|
|
# - Use all available CPU threads
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT "'hashingThreads'" "'hashingThreads' => ${G_HW_CPU_CORES}," "$config_php" "'version'"
|
|
# - ToDo: Configure the other settings after getting some clarification: https://github.com/nextcloud/server/pull/19023#issuecomment-660071524
|
|
#GCI_PRESERVE=1 G_CONFIG_INJECT "'hashingMemoryCost'" "'hashingMemoryCost' => 65536," $config_php "'hashingThreads'"
|
|
#GCI_PRESERVE=1 G_CONFIG_INJECT "'hashingTimeCost'" "'hashingTimeCost' => 4," $config_php "'hashingMemoryCost'"
|
|
|
|
# Enable Nextcloud background cron job: https://docs.nextcloud.com/server/17/admin_manual/configuration_server/background_jobs_configuration.html#cron
|
|
crontab -u www-data -l | grep -q '/var/www/nextcloud/cron.php' || { crontab -u www-data -l; echo '*/5 * * * * php /var/www/nextcloud/cron.php'; } | crontab -u www-data -
|
|
ncc background:cron
|
|
|
|
# Convert filecache table to bigint, which is not done automatically by Nextcloud since v15
|
|
ncc db:convert-filecache-bigint -n
|
|
|
|
# Add missing database columns and indices, which is not done automatically by Nextcloud
|
|
ncc db:add-missing-columns
|
|
ncc db:add-missing-indices
|
|
ncc db:add-missing-primary-keys
|
|
|
|
# On <1 GiB devices assure at least 512 MiB swap space are available to stand 512 MiB file uploads + increased PHP cache and session file usage: https://github.com/MichaIng/DietPi/issues/2293
|
|
(( $RAM_PHYS < 924 && $(free -m | mawk '/^Swap:/{print $2;exit}') < 512 )) && /boot/dietpi/func/dietpi-set_swapfile 512
|
|
fi
|
|
|
|
if To_Install 168 coturn # Nextcloud Talk
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Installing Coturn TURN server'
|
|
|
|
# Install Coturn server only, install Nextcloud Talk app after Nextcloud has been fully configured
|
|
G_AGI coturn
|
|
G_EXEC systemctl stop coturn
|
|
Remove_SysV coturn 1
|
|
|
|
# Ask user for server domain and desired TURN server port
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_PUBLIC_DOMAIN_NAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(find /etc/letsencrypt/live -mindepth 1 -maxdepth 1 -type d -print -quit 2> /dev/null)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(hostname -f)
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX 'Please enter your server'\''s public domain name to allow Nextcloud Talk access your TURN server:'
|
|
local domain=${G_WHIP_RETURNED_VALUE#http*://}
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'SOFTWARE_PUBLIC_DOMAIN_NAME=' "SOFTWARE_PUBLIC_DOMAIN_NAME=$domain" /boot/dietpi.txt
|
|
|
|
G_WHIP_DEFAULT_ITEM=3478 G_WHIP_NOCANCEL=1 G_WHIP_INPUTBOX_REGEX='^[1-9][0-9]*$' G_WHIP_INPUTBOX_REGEX_TEXT='a valid port number'
|
|
G_WHIP_INPUTBOX 'Please enter the network port, that should be used for your TURN server:
|
|
\nNB: This port (UDP + TCP) needs to be forwarded by your router and/or opened in your firewall settings. Default value is: 3478'
|
|
local port=$G_WHIP_RETURNED_VALUE
|
|
|
|
# Adjust Coturn settings
|
|
# - If /etc/turnserver.conf is not present, use default or create empty file
|
|
if [[ ! -f '/etc/turnserver.conf' ]]
|
|
then
|
|
# shellcheck disable=SC2015
|
|
[[ -f '/usr/share/doc/coturn/examples/etc/turnserver.conf.gz' ]] && gzip -cd /usr/share/doc/coturn/examples/etc/turnserver.conf.gz > /etc/turnserver.conf || > /etc/turnserver.conf
|
|
fi
|
|
# https://help.nextcloud.com/t/howto-setup-nextcloud-talk-with-turn-server/30794
|
|
G_CONFIG_INJECT 'listening-port=' "listening-port=$port" /etc/turnserver.conf
|
|
G_CONFIG_INJECT 'fingerprint' 'fingerprint' /etc/turnserver.conf
|
|
G_CONFIG_INJECT 'use-auth-secret' 'use-auth-secret' /etc/turnserver.conf
|
|
G_CONFIG_INJECT 'realm=' "realm=$domain" /etc/turnserver.conf
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'total-quota=' 'total-quota=100' /etc/turnserver.conf
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'bps-capacity=' 'bps-capacity=0' /etc/turnserver.conf
|
|
G_CONFIG_INJECT 'stale-nonce' 'stale-nonce' /etc/turnserver.conf
|
|
G_EXEC sed --follow-symlinks -i 's/^[[:blank:]]*allow-loopback-peers/#allow-loopback-peers/' /etc/turnserver.conf
|
|
G_CONFIG_INJECT 'no-multicast-peers' 'no-multicast-peers' /etc/turnserver.conf
|
|
|
|
# Install Nextcloud Talk app
|
|
G_EXEC systemctl start mariadb
|
|
G_EXEC systemctl start redis-server
|
|
G_EXEC ncc maintenance:mode --off
|
|
if [[ ! -d '/var/www/nextcloud/apps/spreed' ]]
|
|
then
|
|
# Succeed if app is already installed and on "Cannot declare class" bug: https://github.com/MichaIng/DietPi/issues/3499#issuecomment-622955490
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code != 0 && $(<"$fp_log") =~ (' already installed'$|' Cannot declare class ') ]] && exit_code=0; }
|
|
G_EXEC ncc app:install spreed
|
|
fi
|
|
ncc app:enable spreed
|
|
|
|
# Adjust Nextcloud Talk settings to use Coturn
|
|
ncc talk:stun:add "$domain:$port"
|
|
# - Generate random secret to secure TURN server access
|
|
local secret=$(openssl rand -hex 32)
|
|
GCI_PASSWORD=1 GCI_PRESERVE=1 G_CONFIG_INJECT 'static-auth-secret=' "static-auth-secret=$secret" /etc/turnserver.conf
|
|
# - Scrape existing secret, in case user manually chose/edited it
|
|
secret=$(sed -n '/^[[:blank:]]*static-auth-secret=/{s/^[^=]*=//p;q}' /etc/turnserver.conf)
|
|
ncc talk:turn:add --secret "$secret" -- 'turn' "$domain:$port" 'udp,tcp'
|
|
unset -v secret domain port
|
|
fi
|
|
|
|
if To_Install 32 ympd # ympd
|
|
then
|
|
G_AGI ympd
|
|
fi
|
|
|
|
if To_Install 148 mympd # myMPD
|
|
then
|
|
# Distro: https://download.opensuse.org/repositories/home:/jcorporation/
|
|
local distro='Debian_'
|
|
(( $G_HW_ARCH == 1 )) && distro='Raspbian_'
|
|
case $G_DISTRO in
|
|
6) distro+='11';;
|
|
7) distro+='12';;
|
|
8) (( $G_HW_ARCH == 1 )) && distro+='12' || distro+='13';;
|
|
*) (( $G_HW_ARCH == 1 )) && distro+='12' || distro+='Testing';;
|
|
esac
|
|
|
|
# APT key
|
|
G_EXEC curl -sSfLo '/etc/apt/trusted.gpg.d/dietpi-mympd.asc' "https://download.opensuse.org/repositories/home:/jcorporation/$distro/Release.key"
|
|
|
|
# APT list
|
|
G_EXEC eval "echo 'deb https://download.opensuse.org/repositories/home:/jcorporation/$distro/ /' > /etc/apt/sources.list.d/dietpi-mympd.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI mympd
|
|
G_EXEC systemctl stop mympd
|
|
|
|
# Config: Create on fresh install
|
|
# - On reinstall /var/lib/mympd exists, so use its existence as reinstall flag
|
|
if [[ ! -d '/var/lib/mympd' ]]
|
|
then
|
|
G_EXEC_OUTPUT=1 G_EXEC systemd-run -p DynamicUser=yes -p StateDirectory=mympd -p CacheDirectory=mympd -p Environment='MYMPD_LOGLEVEL=4 MYMPD_MPD_HOST=/run/mpd/socket MYMPD_HTTP=false MYMPD_SSL_PORT=1333' mympd -c
|
|
|
|
# Add myMPD CA to trusted store: https://github.com/jcorporation/myMPD/issues/914
|
|
G_EXEC mkdir -p /usr/local/share/ca-certificates
|
|
G_EXEC ln -sf /var/lib/mympd/ssl/ca.pem /usr/local/share/ca-certificates/DietPi_myMPD_CA.crt
|
|
G_EXEC update-ca-certificates
|
|
fi
|
|
|
|
# myMPD pre-v8.0.0 cleanup
|
|
[[ -f '/etc/mympd.conf' ]] && G_EXEC rm /etc/mympd.conf
|
|
[[ -f '/etc/mympd.conf.dist' ]] && G_EXEC rm /etc/mympd.conf.dist
|
|
command -v mympd-config > /dev/null && G_EXEC rm "$(command -v mympd-config)"
|
|
fi
|
|
|
|
if To_Install 121 roonbridge # Roon Bridge
|
|
then
|
|
case $G_HW_ARCH in
|
|
2) local arch='armv7hf';;
|
|
3) local arch='armv8';;
|
|
*) local arch='x64';;
|
|
esac
|
|
Download_Install "https://download.roonlabs.net/builds/RoonBridge_linux$arch.tar.bz2"
|
|
|
|
# Always perform a clean install
|
|
[[ -d '/opt/roonbridge' ]] && G_EXEC rm -R /opt/roonbridge
|
|
[[ -d '/etc/roonbridge' ]] && G_EXEC rm -R /etc/roonbridge # Pre-v8.2
|
|
G_EXEC mv RoonBridge /opt/roonbridge
|
|
|
|
# Pre-v8.2 migration
|
|
[[ -d '/mnt/dietpi_userdata/roon' && ! -d '/mnt/dietpi_userdata/roonbridge' ]] && G_EXEC mv /mnt/dietpi_userdata/roon{,bridge}
|
|
|
|
# Log to /var/log/roonbridge
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/roonbridge/{RoonBridge,RAATServer}
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/roonbridge/{RoonBridge,RAATServer}/Logs /var/log/roon # /var/log/roon: Pre-v8.2
|
|
G_EXEC ln -s /var/log/roonbridge /mnt/dietpi_userdata/roonbridge/RoonBridge/Logs
|
|
G_EXEC ln -s /var/log/roonbridge /mnt/dietpi_userdata/roonbridge/RAATServer/Logs
|
|
|
|
# User
|
|
Create_User -G audio -d /mnt/dietpi_userdata/roonbridge roonbridge
|
|
|
|
# Permissions
|
|
G_EXEC chown -R roonbridge:root /{mnt/dietpi_userdata,opt}/roonbridge
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/roonbridge.service
|
|
[Unit]
|
|
Description=Roon Bridge (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target sound.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Roon Bridge
|
|
User=roonbridge
|
|
AmbientCapabilities=CAP_SYS_NICE
|
|
LogsDirectory=roonbridge
|
|
Environment=ROON_DATAROOT=/mnt/dietpi_userdata/roonbridge
|
|
Environment=ROON_ID_DIR=/mnt/dietpi_userdata/roonbridge
|
|
ExecStart=/opt/roonbridge/start.sh
|
|
Restart=on-abort
|
|
|
|
# Hardening
|
|
PrivateTmp=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Sparky SBC: Workaround for failing service start: https://dietpi.com/forum/t/allogui-not-working-apache-service-doesnt-start/15708
|
|
(( $G_HW_MODEL == 70 )) && G_EXEC sed --follow-symlinks -i '/^AmbientCapabilities=/d' /etc/systemd/system/roonbridge.service
|
|
fi
|
|
|
|
if To_Install 119 # CAVA
|
|
then
|
|
G_AGI cava
|
|
|
|
# Config: Preserve existing
|
|
if [[ ! -f '/root/.config/cava/config' ]]
|
|
then
|
|
G_EXEC mkdir -p /root/.config/cava
|
|
G_EXEC cp /usr/share/cava/example_files/config /root/.config/cava/
|
|
G_CONFIG_INJECT 'method[[:blank:]]+=' 'method = fifo' /root/.config/cava/config '\[input\]'
|
|
G_CONFIG_INJECT 'foreground[[:blank:]]+=' 'foreground = cyan' /root/.config/cava/config '\[color\]'
|
|
fi
|
|
|
|
# FIFO stream for MPD
|
|
grep -q '/tmp/mpd.fifo' /etc/mpd.conf || cat << '_EOF_' >> /etc/mpd.conf
|
|
|
|
# CAVA FIFO stream
|
|
audio_output {
|
|
type "fifo"
|
|
name "CAVA"
|
|
path "/tmp/mpd.fifo"
|
|
format "44100:16:2"
|
|
}
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 118 mopidy # Mopidy: https://docs.mopidy.com/stable/installation/debian/
|
|
then
|
|
# Install our config file only if not yet existent, to preserve manual user config.
|
|
# - This needs to be done prior to APT install, since this would otherwise install a default config file as well.
|
|
[[ -f '/etc/mopidy/mopidy.conf' ]] || dps_index=$software_id Download_Install 'mopidy.conf' /etc/mopidy/mopidy.conf
|
|
|
|
# APT key
|
|
local url='https://apt.mopidy.com/mopidy.gpg'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-mopidy.gpg --yes"
|
|
|
|
# APT list: https://apt.mopidy.com/dists/
|
|
G_EXEC eval "echo 'deb https://apt.mopidy.com ${G_DISTRO_NAME/forky/trixie} main' > /etc/apt/sources.list.d/dietpi-mopidy.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI mopidy gstreamer1.0-alsa mopidy-local
|
|
G_EXEC systemctl stop mopidy
|
|
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -U Mopidy-MusicBox-Webclient
|
|
|
|
# Assure user home, data and cache dir as well on custom configs
|
|
G_CONFIG_INJECT 'data_dir[[:blank:]]*=' 'data_dir = /mnt/dietpi_userdata/mopidy/data' /etc/mopidy/mopidy.conf '\[core\]'
|
|
G_CONFIG_INJECT 'cache_dir[[:blank:]]*=' 'cache_dir = /mnt/dietpi_userdata/mopidy/cache' /etc/mopidy/mopidy.conf '\[core\]'
|
|
|
|
# Move existing home+data to dietpi_userdata if not yet existent
|
|
if [[ -d '/var/lib/mopidy' && ! -d '/mnt/dietpi_userdata/mopidy' ]]
|
|
then
|
|
G_EXEC mv /var/lib/mopidy /mnt/dietpi_userdata/mopidy
|
|
# Workaround error about moving data dir into itself
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/mopidy/.hidden_data
|
|
# Non-hidden files/dirs are data
|
|
G_EXEC mv /mnt/dietpi_userdata/mopidy/* /mnt/dietpi_userdata/mopidy/.hidden_data
|
|
G_EXEC mv /mnt/dietpi_userdata/mopidy/.hidden_data /mnt/dietpi_userdata/mopidy/data
|
|
else
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/mopidy/data
|
|
[[ -d '/var/lib/mopidy' ]] && G_EXEC rm -R /var/lib/mopidy
|
|
fi
|
|
|
|
# Move existing cache to dietpi_userdata if not yet existent
|
|
if [[ -d '/var/cache/mopidy' && ! -d '/mnt/dietpi_userdata/mopidy/cache' ]]
|
|
then
|
|
G_EXEC mv /var/cache/mopidy /mnt/dietpi_userdata/mopidy/cache
|
|
else
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/mopidy/cache
|
|
[[ -d '/var/cache/mopidy' ]] && G_EXEC rm -R /var/cache/mopidy
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R mopidy:root /mnt/dietpi_userdata/mopidy
|
|
|
|
# User
|
|
G_EXEC usermod -g dietpi -aG audio -d /mnt/dietpi_userdata/mopidy mopidy
|
|
|
|
# Do not pre-create obsolete cache dir
|
|
G_EXEC mkdir -p /etc/systemd/system/mopidy.service.d
|
|
G_EXEC eval 'echo -e '\''[Service]\nExecStartPre='\'' > /etc/systemd/system/mopidy.service.d/dietpi.conf'
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 31 # Kodi
|
|
then
|
|
# RPi repo
|
|
if [[ -f '/etc/apt/sources.list.d/raspi.list' ]]
|
|
then
|
|
# Purge DietPi Bullseye build with higher epoch version
|
|
[[ $G_DISTRO == 6 && $(dpkg-query -Wf '${Version}' kodi 2> /dev/null) == '3:19.1-dietpi'[1-3] ]] && G_EXEC_OUTPUT=1 G_EXEC dpkg -P kodi
|
|
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
# Enhance 4k support on RPi 4 and above with 512 MiB CMA
|
|
local cma=()
|
|
(( $G_HW_MODEL > 3 )) && cma=(512)
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d "${cma[@]}"
|
|
|
|
# Enable hardware codecs
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-codec 1
|
|
fi
|
|
|
|
# Bookworm: Install Kodi 21
|
|
(( $G_DISTRO == 7 )) && aDEPS=('kodi21') || aDEPS=('kodi')
|
|
|
|
# Trixie: has now dedicated kodi-repository-kodi
|
|
(( $G_DISTRO > 7 )) && aDEPS+=('kodi-repository-kodi')
|
|
|
|
# Missing dependency
|
|
aDEPS+=('libgl1-mesa-dri')
|
|
|
|
# Bookworm: Apply missing dir workaround: https://github.com/RPi-Distro/repo/issues/153
|
|
(( $G_DISTRO == 7 )) && G_EXEC mkdir -p /etc/polkit-1/localauthority/50-local.d
|
|
|
|
# Everything else
|
|
else
|
|
aDEPS=('kodi' 'kodi-repository-kodi')
|
|
(( $G_HW_ARCH == 10 || $G_DISTRO > 6 )) || aDEPS+=('libgles2') # Missing ARM dependency until Bookworm
|
|
fi
|
|
|
|
# Desktop entry
|
|
G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed/desktop/icons /usr/share/applications
|
|
G_THREAD_START curl -sSfLo /var/lib/dietpi/dietpi-software/installed/desktop/icons/kodi-icon.png "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/icons/kodi-icon.png"
|
|
G_THREAD_START curl -sSfLo /usr/share/applications/kodi.desktop "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/apps/kodi.desktop"
|
|
|
|
# Grant R/W access to all input and console devices for members of the "input" respectively "tty" group
|
|
dps_index=$software_id Download_Install '99-dietpi-kodi.rules' /etc/udev/rules.d/99-dietpi-kodi.rules
|
|
|
|
# Desktop shortcut
|
|
Create_Desktop_Shortcut kodi
|
|
fi
|
|
|
|
if To_Install 39 minidlna # ReadyMedia
|
|
then
|
|
# Config
|
|
[[ -f '/etc/minidlna.conf' ]] || dps_index=$software_id Download_Install 'minidlna.conf' /etc/minidlna.conf
|
|
|
|
G_AGI minidlna
|
|
G_EXEC systemctl stop minidlna
|
|
|
|
# Remove obsolete service file
|
|
Remove_SysV minidlna 1
|
|
|
|
# User: Make "dietpi" the primary group to enable cross-access to media files
|
|
Create_User -g dietpi -G minidlna -d /var/lib/minidlna minidlna
|
|
|
|
# Service: Debian patch enforces file logging, overriding "-S": https://github.com/MichaIng/DietPi/issues/4745
|
|
cat << '_EOF_' > /etc/systemd/system/minidlna.service
|
|
[Unit]
|
|
Description=ReadyMedia (DietPi)
|
|
Documentation=man:minidlnad(1) man:minidlna.conf(5)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=minidlna
|
|
LogsDirectory=minidlna
|
|
ExecStart=/usr/sbin/minidlnad -S -R -f /etc/minidlna.conf -P /dev/null
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Cache
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/.MiniDLNA_Cache
|
|
G_EXEC chown -R minidlna:root /mnt/dietpi_userdata/.MiniDLNA_Cache
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 108 # Amiberry
|
|
then
|
|
# RPi: Enable KMS/DRM
|
|
(( $G_HW_MODEL < 10 )) && /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d
|
|
|
|
G_AGI amiberry
|
|
|
|
# Permissions: Enable access for kickstart uploads via file servers
|
|
local fp_roms='/mnt/dietpi_userdata/amiberry/roms'
|
|
# - ARMv6: Amiberry v5 used a different default dir for kickstart ROMs
|
|
(( $G_HW_ARCH == 1 )) && fp_roms='/mnt/dietpi_userdata/amiberry/kickstarts'
|
|
G_EXEC mkdir -p "$fp_roms"
|
|
G_EXEC chgrp dietpi "$fp_roms"
|
|
G_EXEC chmod g=rwx "$fp_roms"
|
|
|
|
# Pre-v6.26: Remove obsolete config file: https://github.com/BlitterStudio/amiberry/releases/tag/v2.25
|
|
[[ -f '/mnt/dietpi_userdata/amiberry/conf/adfdir.conf' ]] && G_EXEC rm /mnt/dietpi_userdata/amiberry/conf/adfdir.conf
|
|
# Pre-v8.5: Remove obsolete library and service files
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
[[ -e '/mnt/dietpi_userdata/amiberry/lib/libSDL2.so' ]] && G_EXEC rm -f /mnt/dietpi_userdata/amiberry/lib/libSDL2*.so{,.0.*}
|
|
else
|
|
[[ -d '/mnt/dietpi_userdata/amiberry/lib' ]] && G_EXEC rm -R /mnt/dietpi_userdata/amiberry/lib
|
|
fi
|
|
[[ -f '/etc/systemd/system/amiberry.service' ]] && G_EXEC rm /etc/systemd/system/amiberry.service
|
|
fi
|
|
|
|
if To_Install 10 # Amiberry-Lite
|
|
then
|
|
# RPi: Enable KMS/DRM
|
|
(( $G_HW_MODEL < 10 )) && /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d
|
|
|
|
G_AGI amiberry-lite
|
|
|
|
# Permissions: Enable access for kickstart uploads via file servers
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/amiberry-lite/roms
|
|
G_EXEC chgrp dietpi /mnt/dietpi_userdata/amiberry-lite/roms
|
|
G_EXEC chmod g=rwx /mnt/dietpi_userdata/amiberry-lite/roms
|
|
fi
|
|
|
|
if To_Install 112 # DXX-Rebirth
|
|
then
|
|
aDEPS=('libsdl-mixer1.2' 'libsdl1.2debian' 'libphysfs1' 'libgl1' 'libglu1-mesa')
|
|
Download_Install 'https://dietpi.com/downloads/binaries/rpi/dxx-rebirth.7z' /mnt/dietpi_userdata
|
|
|
|
# Symlink savegames to root
|
|
# - Remove existing symlinks
|
|
G_EXEC rm -Rf /root/.d{1,2}x-rebirth
|
|
|
|
G_EXEC ln -sf /mnt/dietpi_userdata/dxx-rebirth/descent_1_profiles /root/.d1x-rebirth
|
|
G_EXEC ln -sf /mnt/dietpi_userdata/dxx-rebirth/descent_2_profiles /root/.d2x-rebirth
|
|
|
|
# +exe
|
|
G_EXEC chmod -R +x /mnt/dietpi_userdata/dxx-rebirth/*
|
|
|
|
# Desktop menu entry
|
|
G_EXEC mkdir -p /usr/share/applications
|
|
G_EXEC ln -sf /mnt/dietpi_userdata/dxx-rebirth/dxx-rebirth.desktop /usr/share/applications/dxx-rebirth.desktop
|
|
|
|
# Desktop shortcut
|
|
Create_Desktop_Shortcut dxx-rebirth
|
|
fi
|
|
|
|
if To_Install 111 urbackupsrv # UrBackup Server
|
|
then
|
|
# Pre-configure backup path: Read from database on reinstall and align all configs
|
|
if [[ -f '/var/urbackup/backup_server_settings.db' ]] && command -v sqlite3 > /dev/null
|
|
then
|
|
local backuppath=$(sqlite3 /var/urbackup/backup_server_settings.db 'select value from settings where key = "backupfolder"')
|
|
else
|
|
local backuppath=$(sed -n '/^[[:blank:]]*SOFTWARE_URBACKUP_BACKUPPATH=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
fi
|
|
[[ $backuppath ]] || backuppath='/mnt/dietpi_userdata/urbackup'
|
|
[[ -f '/etc/urbackup/backupfolder' ]] && G_EXEC eval "echo '$backuppath' > /etc/urbackup/backupfolder"
|
|
[[ -f '/var/urbackup/backupfolder' ]] && G_EXEC eval "echo '$backuppath' > /var/urbackup/backupfolder"
|
|
G_EXEC eval "debconf-set-selections <<< 'urbackup-server urbackup/backuppath string $backuppath'"
|
|
|
|
# APT distro
|
|
local distro='Debian_'
|
|
(( $G_HW_ARCH == 1 )) && distro='Raspbian_'
|
|
case $G_DISTRO in
|
|
6) distro+='11';;
|
|
7) distro+='12';;
|
|
*) (( $G_HW_ARCH == 1 )) && distro+='12' || distro+='13';;
|
|
esac
|
|
|
|
# APT key
|
|
G_EXEC mkdir -p /etc/apt/keyrings
|
|
G_EXEC curl -sSfLo /etc/apt/keyrings/dietpi-urbackup.asc "https://download.opensuse.org/repositories/home:/uroni/$distro/Release.key"
|
|
|
|
# APT source
|
|
G_EXEC eval "cat << '_EOF_' > /etc/apt/sources.list.d/dietpi-urbackup.sources
|
|
Types: deb
|
|
URIs: https://download.opensuse.org/repositories/home:/uroni/$distro
|
|
Suites: /
|
|
Signed-By: /etc/apt/keyrings/dietpi-urbackup.asc
|
|
_EOF_"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI urbackup-server
|
|
G_EXEC systemctl stop urbackupsrv
|
|
unset -v backuppath distro
|
|
fi
|
|
|
|
if To_Install 51 # OpenTyrian
|
|
then
|
|
aDEPS=('libsdl1.2debian' 'libsdl-net1.2')
|
|
Download_Install 'https://dietpi.com/downloads/binaries/rpi/opentyrian_armhf.zip' /
|
|
|
|
# Move to /usr/games
|
|
G_EXEC cp -a /usr/local/games/opentyrian /usr/games/
|
|
G_EXEC rm -R /usr/local/games/opentyrian
|
|
G_EXEC chmod +x /usr/games/opentyrian/opentyrian
|
|
|
|
# Desktop menu entry
|
|
G_THREAD_START curl -sSfL "https://raw.githubusercontent.com/$G_GITOWNER/DietPi/$G_GITBRANCH/.conf/desktop/apps/opentyrian.desktop" -o /usr/share/applications/opentyrian.desktop
|
|
|
|
# Copy the DietPi run file for OpenTyrian
|
|
dps_index=$software_id Download_Install 'run' /usr/games/opentyrian/run
|
|
G_EXEC chmod +x /usr/games/opentyrian/run
|
|
|
|
# Desktop shortcut
|
|
Create_Desktop_Shortcut opentyrian
|
|
|
|
G_THREAD_WAIT
|
|
fi
|
|
|
|
if To_Install 59 raspimjpeg # RPi Cam Web Interface
|
|
then
|
|
aDEPS=('gpac')
|
|
Download_Install 'https://github.com/silvanmelchior/RPi_Cam_Web_Interface/archive/master.tar.gz'
|
|
|
|
G_EXEC cd RPi_Cam_Web_Interface-master
|
|
|
|
# Remove files which are not to be installed
|
|
[[ -f 'www/status_mjpeg.txt' ]] && G_EXEC rm www/status_mjpeg.txt
|
|
|
|
# Web base dir
|
|
G_EXEC mkdir -p /var/www/rpicam
|
|
G_EXEC cp -dR www/. /var/www/rpicam/
|
|
[[ -e '/var/www/rpicam/FIFO' ]] || G_EXEC mknod /var/www/rpicam/FIFO p
|
|
[[ -e '/var/www/rpicam/FIFO1' ]] || G_EXEC mknod /var/www/rpicam/FIFO1 p
|
|
# - Dynamic cam preview and status
|
|
G_EXEC ln -sf /run/shm/mjpeg/cam.jpg /var/www/rpicam/cam.jpg
|
|
G_EXEC ln -sf /run/shm/mjpeg/status_mjpeg.txt /var/www/rpicam/status_mjpeg.txt
|
|
|
|
# Allow shutdown and reboot via web interface
|
|
G_EXEC cp etc/sudoers.d/RPI_Cam_Web_Interface /etc/sudoers.d/dietpi-rpi_cam_control
|
|
|
|
# Install RaspiMJPEG
|
|
# - Binary
|
|
G_EXEC cp {,/usr/local/}bin/raspimjpeg
|
|
G_EXEC chmod +x /usr/local/bin/raspimjpeg
|
|
# - Config
|
|
G_EXEC cp etc/raspimjpeg/raspimjpeg.1 /etc/raspimjpeg
|
|
G_EXEC ln -sf /etc/raspimjpeg /var/www/rpicam/raspimjpeg
|
|
# - Web base dir
|
|
grep -q '/rpicam' /etc/raspimjpeg || G_EXEC sed --follow-symlinks -i 's|/var/www|/var/www/rpicam|g' /etc/raspimjpeg
|
|
# - Service
|
|
dps_index=$software_id Download_Install 'raspimjpeg.sh' /var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh
|
|
cat << '_EOF_' > /etc/systemd/system/raspimjpeg.service
|
|
[Unit]
|
|
Description=RaspiMJPEG (DietPi)
|
|
|
|
[Service]
|
|
RemainAfterExit=yes
|
|
ExecStart=/var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh start
|
|
ExecStop=/var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh stop
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Cleanup
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R RPi_Cam_Web_Interface-master
|
|
|
|
# Data directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/rpicam
|
|
G_EXEC rm -Rf /var/www/rpicam/media
|
|
G_EXEC ln -s /mnt/dietpi_userdata/rpicam /var/www/rpicam/media
|
|
|
|
# Enable RPi camera
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-camera enable
|
|
|
|
# Permissions
|
|
G_EXEC usermod -aG video www-data
|
|
G_EXEC chown -R www-data:www-data /var/www/rpicam /mnt/dietpi_userdata/rpicam
|
|
fi
|
|
|
|
if To_Install 45 deluged deluge-web # Deluge
|
|
then
|
|
# Packages
|
|
G_AGI deluged deluge-web deluge-console
|
|
(( $G_DISTRO > 6 )) && G_EXEC systemctl stop deluge-web
|
|
G_EXEC systemctl stop deluged
|
|
|
|
# Workaround for broken Bookworm package: https://github.com/MichaIng/DietPi/issues/6408
|
|
(( $G_DISTRO == 7 )) && G_EXEC_DESC='Fixing broken script in Bookworm package' G_EXEC sed --follow-symlinks -i '/bind_textdomain_codeset/d' /usr/lib/python3/dist-packages/deluge/i18n/util.py
|
|
|
|
# Remove SysV service leftovers, installed by Debian APT package
|
|
Remove_SysV deluged 1
|
|
[[ -d '/var/lib/deluged' ]] && G_EXEC rm -R /var/lib/deluged
|
|
[[ -d '/var/log/deluged' ]] && G_EXEC rm -R /var/log/deluged
|
|
|
|
# User
|
|
Create_User -g dietpi -G debian-deluged -d /mnt/dietpi_userdata/deluge debian-deluged
|
|
|
|
# Config
|
|
if [[ ! -f '/mnt/dietpi_userdata/deluge/.config/deluge/core.conf' ]]
|
|
then
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/deluge/.config/deluge
|
|
|
|
# Default configs
|
|
dps_index=$software_id Download_Install 'deluge.conf' /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
dps_index=$software_id Download_Install 'deluge_web.conf' /mnt/dietpi_userdata/deluge/.config/deluge/web.conf
|
|
dps_index=$software_id Download_Install 'hostlist.conf' /mnt/dietpi_userdata/deluge/.config/deluge/hostlist.conf
|
|
|
|
# Apply optimised settings
|
|
# - Cache size in 16 KiB units
|
|
G_CONFIG_INJECT '"cache_size":' " \"cache_size\": $(( $(Optimise_BitTorrent 0) * 1024 / 16 ))," /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
G_CONFIG_INJECT '"max_active_limit":' " \"max_active_limit\": $(Optimise_BitTorrent 1)," /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
G_CONFIG_INJECT '"max_active_downloading":' " \"max_active_downloading\": $(Optimise_BitTorrent 1)," /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
G_CONFIG_INJECT '"max_connections_global":' " \"max_connections_global\": $(Optimise_BitTorrent 2)," /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
G_CONFIG_INJECT '"max_upload_slots_global":' " \"max_upload_slots_global\": $(Optimise_BitTorrent 3)," /mnt/dietpi_userdata/deluge/.config/deluge/core.conf
|
|
|
|
# Web UI access
|
|
local salt=$(tr -dc '0-9a-f' < /dev/random | head -c40)
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT '"pwd_salt":' " \"pwd_salt\": \"$salt\"," /mnt/dietpi_userdata/deluge/.config/deluge/web.conf
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT '"pwd_sha1":' " \"pwd_sha1\": \"$(echo -n "$salt$GLOBAL_PW" | sha1sum | mawk '{print $1}')\"," /mnt/dietpi_userdata/deluge/.config/deluge/web.conf
|
|
unset -v salt
|
|
|
|
# Client access
|
|
local localpass=$(tr -dc '0-9a-f' < /dev/random | head -c40)
|
|
> /mnt/dietpi_userdata/deluge/.config/deluge/auth
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/deluge/.config/deluge/auth
|
|
echo -e "root:$GLOBAL_PW:10\nlocalclient:$localpass:10" > /mnt/dietpi_userdata/deluge/.config/deluge/auth
|
|
|
|
# Web UI autoconnect
|
|
local id=$(tr -dc '0-9a-f' < /dev/random | head -c32)
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/deluge/.config/deluge/hostlist.conf
|
|
G_CONFIG_INJECT '"[0-9a-f]{32}"' " \"$id\"," /mnt/dietpi_userdata/deluge/.config/deluge/hostlist.conf
|
|
sed --follow-symlinks -i "/\"[0-9a-f]\{40\}\"/c\ \"$localpass\"" /mnt/dietpi_userdata/deluge/.config/deluge/hostlist.conf
|
|
G_CONFIG_INJECT '"default_daemon":' " \"default_daemon\": \"$id\"," /mnt/dietpi_userdata/deluge/.config/deluge/web.conf
|
|
unset -v localpass id
|
|
RESTART_DELUGE_WEB=1
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R debian-deluged:root /mnt/dietpi_userdata/deluge
|
|
|
|
# Service: https://github.com/deluge-torrent/deluge/blob/develop/packaging/systemd/deluged.service
|
|
cat << '_EOF_' > /etc/systemd/system/deluged.service
|
|
[Unit]
|
|
Description=Deluge Daemon (DietPi)
|
|
Documentation=man:deluged
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=debian-deluged
|
|
UMask=007
|
|
ExecStart=/usr/bin/deluged -d
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# https://github.com/deluge-torrent/deluge/blob/develop/packaging/systemd/deluge-web.service
|
|
cat << _EOF_ > /etc/systemd/system/deluge-web.service
|
|
[Unit]
|
|
Description=Deluge Web UI (DietPi)
|
|
Documentation=man:deluge-web
|
|
Wants=network-online.target
|
|
After=network-online.target deluged.service
|
|
|
|
[Service]
|
|
User=debian-deluged
|
|
UMask=027
|
|
ExecStart=/usr/bin/deluge-web -d
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 115 webmin # Webmin: https://github.com/webmin/webmin/blob/master/webmin-setup-repo.sh
|
|
then
|
|
# APT key
|
|
G_EXEC curl -sSfLo '/etc/apt/trusted.gpg.d/dietpi-webmin.asc' 'https://webmin.com/developers-key.asc'
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://download.webmin.com/download/newkey/repository stable contrib'\'' > /etc/apt/sources.list.d/dietpi-webmin.list'
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI webmin
|
|
G_EXEC systemctl stop webmin
|
|
fi
|
|
|
|
if To_Install 195 # youtube-dl
|
|
then
|
|
aDEPS=('python3')
|
|
Download_Install 'https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp' /usr/local/bin/yt-dlp
|
|
G_EXEC chmod +x /usr/local/bin/yt-dlp
|
|
G_EXEC ln -sf /usr/local/bin/yt-dlp /usr/local/bin/youtube-dl
|
|
|
|
# Remove obsolete /usr/local/bin/youtube-dl-py2 we used previously
|
|
[[ -f '/usr/local/bin/youtube-dl-py2' ]] && G_EXEC rm /usr/local/bin/youtube-dl-py2
|
|
fi
|
|
|
|
if To_Install 129 # O!MPD
|
|
then
|
|
Download_Install 'https://github.com/ArturSierzant/OMPD/archive/master.tar.gz'
|
|
# Replace existing installs but preserve local config override
|
|
if [[ -d '/var/www/ompd' ]]
|
|
then
|
|
[[ -f '/var/www/ompd/include/config.local.inc.php' ]] && G_EXEC mv /var/www/ompd/include/config.local.inc.php OMPD-master/include/
|
|
G_EXEC rm -R /var/www/ompd
|
|
fi
|
|
G_EXEC mv OMPD-master /var/www/ompd
|
|
|
|
# Preserve config file, create local override if non-existent
|
|
# Database will be migrated automatically, so only create new on fresh install, using local override config as flag
|
|
if [[ ! -f '/var/www/ompd/include/config.local.inc.php' ]]
|
|
then
|
|
G_EXEC systemctl start mariadb
|
|
# Create database user only, database will be created automatically
|
|
mysql -e "grant all privileges on ompd.* to ompd@localhost identified by '$GLOBAL_PW';"
|
|
G_EXEC systemctl stop mariadb
|
|
|
|
cat << _EOF_ > /var/www/ompd/include/config.local.inc.php
|
|
<?php
|
|
# Database
|
|
\$cfg['mysqli_host'] = '127.0.0.1';
|
|
\$cfg['mysqli_db'] = 'ompd';
|
|
\$cfg['mysqli_user'] = 'ompd';
|
|
\$cfg['mysqli_password'] = '$GLOBAL_PW';
|
|
\$cfg['mysqli_port'] = '';
|
|
\$cfg['mysqli_socket'] = '/run/mysqld/mysqld.sock';
|
|
\$cfg['mysqli_auto_create_db'] = true;
|
|
# Media dir
|
|
\$cfg['media_dir'] = '/mnt/dietpi_userdata/Music/';
|
|
?>
|
|
_EOF_
|
|
fi
|
|
|
|
# Webserver configs
|
|
# - Lighttpd
|
|
if (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'lighttpd.ompd.conf' /etc/lighttpd/conf-available/99-dietpi-ompd.conf
|
|
[[ -f '/etc/lighttpd/conf-enabled/99-dietpi-ompd.conf' ]] || G_EXEC lighty-enable-mod dietpi-ompd
|
|
fi
|
|
|
|
# Permissions: http://ompd.pl/configuration
|
|
G_EXEC chown -R www-data:www-data /var/www/ompd/{tmp,stream,cache,covers,include/config.local.inc.php}
|
|
fi
|
|
|
|
if To_Install 135 icecast2 darkice # Icecast + DarkIce
|
|
then
|
|
G_AGI darkice icecast2
|
|
# Trixie does not ship init.d service anymore
|
|
local darkice=()
|
|
(( $G_DISTRO < 8 )) && darkice=('darkice')
|
|
G_EXEC systemctl stop "${darkice[@]}" icecast2
|
|
|
|
# Icecast
|
|
# - Config: Set passwords if not yet done (default found)
|
|
# - HTML-encode characters with special meaning in XML. Icecast treats those correctly for authentication.
|
|
local password=${GLOBAL_PW//&/\&}; password=${password//</\<}
|
|
sed --follow-symlinks -i "/<source-password>hackme/c\ <source-password>$password</source-password>" /etc/icecast2/icecast.xml
|
|
sed --follow-symlinks -i "/<relay-password>hackme/c\ <relay-password>$password</relay-password>" /etc/icecast2/icecast.xml
|
|
sed --follow-symlinks -i "/<admin-password>hackme/c\ <admin-password>$password</admin-password>" /etc/icecast2/icecast.xml
|
|
unset -v password
|
|
# - Service: Replace init.d service with native systemd service
|
|
Remove_SysV icecast2 1
|
|
cat << _EOF_ > /etc/systemd/system/icecast2.service
|
|
[Unit]
|
|
Description=Icecast (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=icecast2
|
|
Group=icecast
|
|
ExecStart=/usr/bin/icecast2 -c /etc/icecast2/icecast.xml
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# DarkIce
|
|
# - User
|
|
Create_User -g audio -G dietpi darkice
|
|
# - Config
|
|
[[ -f '/etc/darkice.cfg' ]] || > /etc/darkice.cfg
|
|
G_EXEC chown darkice:root /etc/darkice.cfg
|
|
G_EXEC chmod 0600 /etc/darkice.cfg
|
|
local input_device_index=$(arecord -l | mawk -F'[ :]' '/card/{print $2;exit}')
|
|
cat << _EOF_ > /etc/darkice.cfg
|
|
[general]
|
|
duration = 0
|
|
bufferSecs = 3
|
|
reconnect = yes
|
|
|
|
[input]
|
|
device = hw:${input_device_index:-0},0
|
|
sampleRate = 44100
|
|
bitsPerSample = 16
|
|
channel = 1
|
|
|
|
[icecast2-0]
|
|
bitrateMode = vbr
|
|
format = vorbis
|
|
quality = 0.8
|
|
server = localhost
|
|
port = 8000
|
|
password = $GLOBAL_PW
|
|
mountPoint = DietPi
|
|
name = DietPi
|
|
description = DarkIce on DietPi
|
|
url = http://localhost
|
|
genre = none
|
|
public = no
|
|
#localDumpFile = /mnt/dietpi_userdata/darkice_recording.ogg
|
|
_EOF_
|
|
# - Service: Replace init.d service with native systemd service
|
|
Remove_SysV darkice 1
|
|
cat << _EOF_ > /etc/systemd/system/darkice.service
|
|
[Unit]
|
|
Description=DarkIce (DietPi)
|
|
After=icecast2.service
|
|
|
|
[Service]
|
|
User=darkice
|
|
AmbientCapabilities=CAP_SYS_NICE
|
|
ExecStart=/usr/bin/darkice
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 63 # LinuxDash
|
|
then
|
|
Download_Install 'https://github.com/afaqurk/linux-dash/archive/master.tar.gz'
|
|
G_EXEC mkdir -p /var/www/linuxdash
|
|
G_EXEC cp -a linux-dash-master/* /var/www/linuxdash/
|
|
G_EXEC rm -R linux-dash-master
|
|
fi
|
|
|
|
if To_Install 184 tor # Tor Relay
|
|
then
|
|
G_AGI tor
|
|
G_EXEC systemctl stop tor
|
|
|
|
local nickname=
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
G_WHIP_INPUTBOX 'Pick a nickname for your relay.\n\nNB: This is optional, select "Skip" to leave it empty.' && nickname=$G_WHIP_RETURNED_VALUE
|
|
|
|
local email=
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
G_WHIP_INPUTBOX 'Pick a contact email for your relay.\n\nNB: This is optional but encouraged, and it will be published depending on your relay.' && email=$G_WHIP_RETURNED_VALUE
|
|
|
|
local orport=443
|
|
local invalid_text=
|
|
while :
|
|
do
|
|
G_WHIP_DEFAULT_ITEM=$orport G_WHIP_NOCANCEL=1
|
|
if G_WHIP_INPUTBOX "${invalid_text}Please enter the ORPort that people will use to connect to your Tor relay:
|
|
\nNB: This port needs to be forwarded by your router and/or opened in your firewall settings. Default value is: 443, which should be changed when running a webserver.
|
|
\nDo not use 9001, as this port is commonly associated with Tor and censors might scan for it."
|
|
then
|
|
disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 1 || { invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n'; continue; }
|
|
fi
|
|
orport=$G_WHIP_RETURNED_VALUE
|
|
break
|
|
done
|
|
|
|
local ipv6=
|
|
if G_GET_NET -6 -q gateway > /dev/null
|
|
then
|
|
for i in $(hostname -I)
|
|
do
|
|
[[ $i == *'.'* ]] && continue
|
|
G_WHIP_DEFAULT_ITEM=$i
|
|
break
|
|
done
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
G_WHIP_INPUTBOX "Please enter the private IPv6 address of this device. Skip this if you only want to use IPv4, or if this device doesn't have an IPv6 address." && ipv6=$G_WHIP_RETURNED_VALUE
|
|
fi
|
|
|
|
while :
|
|
do
|
|
G_WHIP_MENU_ARRAY=(
|
|
'Bridge' ': Use this machine as an obfs4 bridge. This is the safest to run from home.'
|
|
'Guard/Middle' ': Use this machine as a beginning or middle relay. Some info will be made public.'
|
|
'Exit' ': Use this machine as an exit relay. This is most at risk for legal complaints.'
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM='Bridge' G_WHIP_NOCANCEL=1
|
|
G_WHIP_MENU "Please choose which type of relay this should be set up as:"
|
|
|
|
if [[ $G_WHIP_RETURNED_VALUE == 'Exit' ]]
|
|
then
|
|
G_WHIP_BUTTON_OK_TEXT='YES'
|
|
G_WHIP_BUTTON_CANCEL_TEXT='NO'
|
|
G_WHIP_YESNO 'WARNING: DO NOT RUN AN EXIT RELAY FROM HOME.
|
|
\nAlso, it is highly recommended that you setup exit relays on dedicated servers.
|
|
\nBefore running an exit relay, check with your hosting provider to make sure they allow it.
|
|
\nAlso, set a reverse DNS (PTR) record (tor-exit is a good name), and preferably edit your WHOIS record to show that this is a Tor exit node.
|
|
\nWould you still like to continue?' || continue
|
|
fi
|
|
|
|
break
|
|
done
|
|
|
|
if [[ $G_WHIP_RETURNED_VALUE == 'Bridge' ]]
|
|
then
|
|
G_AGI obfs4proxy
|
|
local obfs4port=80
|
|
invalid_text=
|
|
while :
|
|
do
|
|
G_WHIP_DEFAULT_ITEM=$obfs4port G_WHIP_NOCANCEL=1
|
|
if G_WHIP_INPUTBOX "${invalid_text}Please enter the obfs4 port that people will use to connect to your bridge:
|
|
\nNB: This port needs to be forwarded by your router and/or opened in your firewall settings. Default value is: 80. Do not use default value if running a webserver.
|
|
\nDo not use 9001, as this port is commonly associated with Tor and censors might scan for it."
|
|
then
|
|
disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 1 || { invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n'; continue; }
|
|
fi
|
|
obfs4port=$G_WHIP_RETURNED_VALUE
|
|
break
|
|
done
|
|
|
|
# Grant capability to bind to privileged ports below 1024
|
|
(( $obfs4port < 1024 )) && G_EXEC setcap cap_net_bind_service=+ep "$(command -v obfs4proxy)"
|
|
|
|
cat << _EOF_ > /etc/tor/torrc
|
|
BridgeRelay 1
|
|
ORPort $orport
|
|
ServerTransportPlugin obfs4 exec $(command -v obfs4proxy)
|
|
ServerTransportListenAddr obfs4 0.0.0.0:$obfs4port
|
|
ExtORPort auto
|
|
_EOF_
|
|
G_EXEC mkdir -p /etc/systemd/system/tor@.service.d
|
|
G_EXEC eval "echo -e '[Service]\nNoNewPrivileges=no' > /etc/systemd/system/tor@.service.d/dietpi-relay.conf"
|
|
|
|
elif [[ $G_WHIP_RETURNED_VALUE == 'Guard/Middle' ]]
|
|
then
|
|
cat << _EOF_ > /etc/tor/torrc
|
|
ORPort $orport
|
|
ExitRelay 0
|
|
SocksPort 0
|
|
ControlSocket 0
|
|
_EOF_
|
|
elif [[ $G_WHIP_RETURNED_VALUE == 'Exit' ]]
|
|
then
|
|
G_AGI unbound
|
|
aSOFTWARE_INSTALL_STATE[182]=1
|
|
|
|
cat << _EOF_ > /etc/tor/torrc
|
|
ORPort $orport
|
|
ExitRelay 1
|
|
SocksPort 0
|
|
ControlSocket 0
|
|
|
|
ExitPolicy accept *:20-21
|
|
ExitPolicy accept *:43
|
|
ExitPolicy accept *:53
|
|
ExitPolicy accept *:79
|
|
ExitPolicy accept *:80-81
|
|
ExitPolicy accept *:88
|
|
ExitPolicy accept *:110
|
|
ExitPolicy accept *:143
|
|
ExitPolicy accept *:220
|
|
ExitPolicy accept *:389
|
|
ExitPolicy accept *:443
|
|
ExitPolicy accept *:464
|
|
ExitPolicy accept *:531
|
|
ExitPolicy accept *:543-544
|
|
ExitPolicy accept *:554
|
|
ExitPolicy accept *:636
|
|
ExitPolicy accept *:706
|
|
ExitPolicy accept *:749
|
|
ExitPolicy accept *:873
|
|
ExitPolicy accept *:902-904
|
|
ExitPolicy accept *:981
|
|
ExitPolicy accept *:989-990
|
|
ExitPolicy accept *:991
|
|
ExitPolicy accept *:992
|
|
ExitPolicy accept *:993
|
|
ExitPolicy accept *:995
|
|
ExitPolicy accept *:1194
|
|
ExitPolicy accept *:1220
|
|
ExitPolicy accept *:1293
|
|
ExitPolicy accept *:1500
|
|
ExitPolicy accept *:1533
|
|
ExitPolicy accept *:1677
|
|
ExitPolicy accept *:1723
|
|
ExitPolicy accept *:1755
|
|
ExitPolicy accept *:1863
|
|
ExitPolicy accept *:2082
|
|
ExitPolicy accept *:2083
|
|
ExitPolicy accept *:2086-2087
|
|
ExitPolicy accept *:2095-2096
|
|
ExitPolicy accept *:2102-2104
|
|
ExitPolicy accept *:3690
|
|
ExitPolicy accept *:4321
|
|
ExitPolicy accept *:4643
|
|
ExitPolicy accept *:5050
|
|
ExitPolicy accept *:5190
|
|
ExitPolicy accept *:5222-5223
|
|
ExitPolicy accept *:5228
|
|
ExitPolicy accept *:8008
|
|
ExitPolicy accept *:8074
|
|
ExitPolicy accept *:8082
|
|
ExitPolicy accept *:8087-8088
|
|
ExitPolicy accept *:8232-8233
|
|
ExitPolicy accept *:8332-8333
|
|
ExitPolicy accept *:8443
|
|
ExitPolicy accept *:8888
|
|
ExitPolicy accept *:9418
|
|
ExitPolicy accept *:10000
|
|
ExitPolicy accept *:11371
|
|
ExitPolicy accept *:19294
|
|
ExitPolicy accept *:19638
|
|
ExitPolicy accept *:50002
|
|
ExitPolicy accept *:64738
|
|
ExitPolicy reject *:*
|
|
_EOF_
|
|
[[ $ipv6 ]] && echo 'IPv6Exit 1' >> /etc/tor/torrc
|
|
# Apply Unbound as local DNS resolver for privacy reasons
|
|
command -v resolvconf > /dev/null && G_EXEC sed --follow-symlinks -i 's/dns-nameservers.*$/dns-nameservers 127.0.0.1/' /etc/network/interfaces
|
|
G_EXEC eval "echo 'nameserver 127.0.0.1' > /etc/resolv.conf" # Unbound is running and configured in the very next config step, so it is safe to switch the DNS nameserver right now.
|
|
fi
|
|
|
|
G_EXEC eval 'echo '\''ControlPort 9051'\'' >> /etc/tor/torrc'
|
|
G_EXEC eval 'echo '\''CookieAuthentication 1'\'' >> /etc/tor/torrc'
|
|
[[ $nickname ]] && G_EXEC eval "echo 'Nickname $nickname' >> /etc/tor/torrc"
|
|
[[ $email ]] && G_EXEC eval "echo 'ContactInfo $email' >> /etc/tor/torrc"
|
|
[[ $ipv6 ]] && G_EXEC eval "echo 'ORPort [$ipv6]:$orport' >> /etc/tor/torrc"
|
|
fi
|
|
|
|
if To_Install 182 unbound # Unbound
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Pre-configuring Unbound to avoid port binding conflicts'
|
|
|
|
# Download base configuration if it does not exist yet
|
|
[[ -f '/etc/unbound/unbound.conf.d/dietpi.conf' ]] || dps_index=$software_id Download_Install 'unbound.conf' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
|
|
# Toggle IPv6 preference based whether there is an IPv6 default route
|
|
if G_GET_NET -6 -q gateway > /dev/null
|
|
then
|
|
G_CONFIG_INJECT 'do-ip6:[[:blank:]]' ' do-ip6: yes' /etc/unbound/unbound.conf.d/dietpi.conf 'server:'
|
|
else
|
|
G_CONFIG_INJECT 'do-ip6:[[:blank:]]' ' do-ip6: no' /etc/unbound/unbound.conf.d/dietpi.conf 'server:'
|
|
fi
|
|
|
|
# Since IP binding might be used, start after network interfaces have been configured, not when they just start to be configured
|
|
G_EXEC mkdir -p /etc/systemd/system/unbound.service.d
|
|
G_EXEC eval "echo -e '[Unit]\nWants=network-online.target\nAfter=network-online.target' > /etc/systemd/system/unbound.service.d/dietpi.conf"
|
|
|
|
# Pi-hole + AdGuard Home part 1
|
|
if (( ${aSOFTWARE_INSTALL_STATE[93]} > 0 || ${aSOFTWARE_INSTALL_STATE[126]} > 0 )) && grep -q '^[[:blank:]]*port:[[:blank:]][[:blank:]]*53$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring Unbound to work for your selected AdBlocker'
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
G_CONFIG_INJECT 'port:[[:blank:]]' ' port: 5335' /etc/unbound/unbound.conf.d/dietpi.conf 'server:'
|
|
G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 127.0.0.1' /etc/unbound/unbound.conf.d/dietpi.conf 'server:'
|
|
fi
|
|
|
|
# Reinstall: Restart to apply possible config changes
|
|
[[ -f '/lib/systemd/system/unbound.service' ]] && G_EXEC systemctl restart unbound
|
|
|
|
# Disable and mask unbound-resolvconf.service: https://github.com/MichaIng/DietPi/issues/5133
|
|
[[ -f '/lib/systemd/system/unbound-resolvconf.service' ]] && G_EXEC systemctl --no-reload disable --now unbound-resolvconf
|
|
G_EXEC systemctl --no-reload mask unbound-resolvconf
|
|
|
|
G_AGI unbound dns-root-data
|
|
Remove_SysV unbound
|
|
G_EXEC systemctl enable --now unbound # Failsafe
|
|
|
|
# Prevent resolvconf from disabling Unbound's exclusive recursive resolving or DoT by adding upstream resolvers of the host to Unbound's forward zone: https://salsa.debian.org/dns-team/unbound/-/blob/master/debian/resolvconf-forwards
|
|
[[ -f '/etc/resolvconf/update.d/unbound' ]] && G_EXEC chmod -x /etc/resolvconf/update.d/unbound
|
|
|
|
# Pi-hole part 2
|
|
if (( ${aSOFTWARE_INSTALL_STATE[93]} == 2 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring Pi-hole to use Unbound'
|
|
# v6
|
|
if [[ $(pihole-FTL -v) == 'v6'* ]]
|
|
then
|
|
G_EXEC pihole-FTL --config dns.upstreams '[ "127.0.0.1#5335" ]'
|
|
fi
|
|
# v5
|
|
if [[ -f '/etc/dnsmasq.d/01-pihole.conf' ]]
|
|
then
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*server=/d' /etc/dnsmasq.d/01-pihole.conf
|
|
G_CONFIG_INJECT 'server=' 'server=127.0.0.1#5335' /etc/dnsmasq.d/01-pihole.conf
|
|
systemctl -q is-active pihole-FTL && G_EXEC systemctl restart pihole-FTL
|
|
fi
|
|
if [[ -f '/etc/pihole/setupVars.conf' ]]
|
|
then
|
|
G_CONFIG_INJECT 'PIHOLE_DNS_1=' 'PIHOLE_DNS_1=127.0.0.1#5335' /etc/pihole/setupVars.conf
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*PIHOLE_DNS_2=/d' /etc/pihole/setupVars.conf
|
|
fi
|
|
fi
|
|
|
|
# AdGuard Home part 2
|
|
if (( ${aSOFTWARE_INSTALL_STATE[126]} == 2 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring AdGuard Home to use Unbound'
|
|
if [[ ! -f '/mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' ]]
|
|
then
|
|
echo '127.0.0.1:5335' > /mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf
|
|
G_CONFIG_INJECT 'upstream_dns_file:[[:blank:]]' ' upstream_dns_file: /mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
systemctl -q is-active adguardhome && G_EXEC systemctl restart adguardhome
|
|
fi
|
|
fi
|
|
|
|
# Plex Media Server: Fix secure remote access: https://dietpi.com/forum/t/cant-connect-to-plex-directly-due-to-unbound/5199
|
|
(( ${aSOFTWARE_INSTALL_STATE[42]} > 0 )) && echo -e 'server:\n\tprivate-domain: "plex.direct"' > /etc/unbound/unbound.conf.d/dietpi-plex.conf
|
|
fi
|
|
|
|
if To_Install 93 pihole-FTL # Pi-hole
|
|
then
|
|
# Download
|
|
G_EXEC curl -sSfLo install.sh 'https://raw.githubusercontent.com/pi-hole/pi-hole/master/automated%20install/basic-install.sh'
|
|
G_EXEC chmod +x install.sh
|
|
|
|
# Check free available memory. Increase swap size to prevent gravity running out of memory.
|
|
if (( $(free -m | mawk '/^Mem:/{print $7;exit}') < 512 && $(free -m | mawk '/^Swap:/{print $2;exit}') < 512 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Increasing swap size to 512 MiB for running gravity.sh, please wait...\n'
|
|
/boot/dietpi/func/dietpi-set_swapfile 512
|
|
fi
|
|
|
|
# Unbound: Switch port to 5335 if it was installed before, else it got just configured within its install step above
|
|
if (( ${aSOFTWARE_INSTALL_STATE[182]} == 2 )) && grep -q '^[[:blank:]]*port:[[:blank:]][[:blank:]]*53$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring Unbound to work for Pi-hole'
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
G_CONFIG_INJECT 'port:[[:blank:]]' ' port: 5335' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 127.0.0.1' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_EXEC systemctl restart unbound
|
|
fi
|
|
|
|
# Install
|
|
# - Workaround "dialog" issues with "xterm" by faking "linux" terminal
|
|
local retry TERM_old=
|
|
[[ $TERM == 'xterm' ]] && { TERM_old=$TERM; export TERM=linux; }
|
|
# - Skip query logging dialogue and set to "false", which affects file logging only, not database>web UI.
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*setLogging$/d' install.sh
|
|
G_EXEC sed --follow-symlinks -i '/^QUERY_LOGGING=$/c\QUERY_LOGGING=false' install.sh
|
|
# - Skip final completion dialogue since we show our own
|
|
# shellcheck disable=SC2016
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*pihole setpassword "${pw}"/,/^[[:blank:]]*dialog --no-shadow --keep-tite/s/dialog --no-shadow --keep-tite/true/' install.sh
|
|
until ./install.sh
|
|
do
|
|
(( $G_INTERACTIVE )) && read -rp 'The Pi-hole installer failed. Do you want to retry? [yN]: ' retry
|
|
[[ $retry =~ ^[yY]([eE][sS])?$ ]] || { aSOFTWARE_INSTALL_STATE[$software_id]=0; break; }
|
|
done
|
|
G_EXEC rm install.sh
|
|
[[ $TERM_old ]] && TERM=$TERM_old
|
|
unset -v retry TERM_old
|
|
|
|
# Skip further setup if installer failed
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$software_id]} == 1 ))
|
|
then
|
|
# Set web UI password: https://github.com/MichaIng/DietPi/issues/662
|
|
G_EXEC_PRE_FUNC(){ acommand[2]=$GLOBAL_PW; }
|
|
G_EXEC pihole setpassword "${GLOBAL_PW//?/X}"
|
|
|
|
# Disable pihole.log query logging: https://github.com/pi-hole/FTL/issues/614#issuecomment-510564476
|
|
G_EXEC pihole-FTL --config dns.queryLogging 'false'
|
|
|
|
# Unbound: Configure Pi-hole to use it
|
|
(( ${aSOFTWARE_INSTALL_STATE[182]} > 0 )) && G_EXEC pihole-FTL --config dns.upstreams '[ "127.0.0.1#5335" ]'
|
|
|
|
# Apply most resource friendly and officially recommended NULL blocking: https://docs.pi-hole.net/ftldns/blockingmode/
|
|
G_EXEC pihole-FTL --config dns.blocking.mode 'NULL'
|
|
|
|
# Reduce long-term database TTL: https://github.com/MichaIng/DietPi-Docs/issues/476
|
|
G_EXEC pihole-FTL --config database.maxDBdays 2
|
|
|
|
# Change web UI port to 8089 and 8489 (HTTPS) to avoid conflict with webservers and other web applications
|
|
G_EXEC pihole-FTL --config webserver.port 8089,8489s
|
|
|
|
# Inform user about differences to stock Pi-hole installation
|
|
G_WHIP_MSG "[ INFO ] Differences to stock Pi-hole installation
|
|
\nCompared to installing Pi-hole via official one-line installer, DietPi applied the following changes:
|
|
- The Pi-hole web UI can be reached on port 8089, i.e. via: http://$(G_GET_NET ip):8089/admin/
|
|
- Additionally it can be accessed via encrypted HTTPS at port 8489, i.e. via: https://$(G_GET_NET ip):8489/admin/. Note that browsers will show a warning until a TLS certificate from by a trusted public certificate authority is used.
|
|
- The Pi-hole web UI is secured with the global software password you chose during first run setup, default: \"dietpi\"
|
|
- DNS query logging to /var/log/pihole/pihole.log has been disabled. This does not affect the query logs in the web UI and database, but the \"pihole -t\"/\"pihole tail\" command does not show DNS queries anymore. If you want to use this command or need query logs in /var/log/pihole/pihole.log for other reasons, it can be re-enabled via web UI privacy settings or \"sudo pihole-FTL --config dns.queryLogging true\".
|
|
- DNS query logging to database (as shown in web UI) has been reduced to 2 days. This can be changed via web UI privacy settings or e.g. \"sudo pihole-FTL --config database.maxDBdays 7\" to raise it to 7 days.
|
|
\nFor further details, read our online docs: https://dietpi.com/docs/software/dns_servers/#pi-hole"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 126 # AdGuard Home
|
|
then
|
|
# Deps: apache2-utils is required for htpasswd command to create bcrypt password hashes
|
|
aDEPS=('apache2-utils')
|
|
|
|
if [[ -f '/mnt/dietpi_userdata/adguardhome/AdGuardHome' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} executable \"/mnt/dietpi_userdata/adguardhome/AdGuardHome\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually remove the executable \"/mnt/dietpi_userdata/adguardhome/AdGuardHome\" and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
else
|
|
case $G_HW_ARCH in
|
|
1) local arch='armv6';;
|
|
2) local arch='armv7';;
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='riscv64';;
|
|
esac
|
|
|
|
Download_Install "https://static.adguard.com/adguardhome/release/AdGuardHome_linux_$arch.tar.gz"
|
|
|
|
# Install to userdata until it is possible to split binary and data/config without breaking the updater: https://github.com/AdguardTeam/AdGuardHome/issues/3286
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/adguardhome
|
|
G_EXEC cp -a AdGuardHome/. /mnt/dietpi_userdata/adguardhome/
|
|
G_EXEC rm -R AdGuardHome
|
|
fi
|
|
|
|
# Unbound: Switch port to 5335 if it was installed before, else it got just configured within its install step above
|
|
if (( ${aSOFTWARE_INSTALL_STATE[182]} == 2 )) && grep -q '^[[:blank:]]*port:[[:blank:]][[:blank:]]*53$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring Unbound to work for AdGuard Home'
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
G_CONFIG_INJECT 'port:[[:blank:]]' ' port: 5335' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 127.0.0.1' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_EXEC systemctl restart unbound
|
|
fi
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/adguardhome adguardhome
|
|
|
|
# Config
|
|
if [[ ! -f '/mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml' ]]
|
|
then
|
|
dps_index=$software_id Download_Install 'AdGuardHome.yaml' /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
# shellcheck disable=SC2016
|
|
G_CONFIG_INJECT 'password:[[:blank:]]' " password: $(htpasswd -bnBC 10 '' "$GLOBAL_PW" | tr -d ':\n' | sed 's/\$2y/\$2a/')" /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
fi
|
|
|
|
# Unbound: Configure AdGuard Home to use it
|
|
if [[ ${aSOFTWARE_INSTALL_STATE[182]} -gt 0 && ! -f '/mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring AdGuard Home to use Unbound'
|
|
echo '127.0.0.1:5335' > /mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf
|
|
G_CONFIG_INJECT 'upstream_dns_file:[[:blank:]]' ' upstream_dns_file: /mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
systemctl -q is-active adguardhome && G_EXEC systemctl restart adguardhome
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R adguardhome:adguardhome /mnt/dietpi_userdata/adguardhome
|
|
G_EXEC chmod 0755 /mnt/dietpi_userdata/adguardhome/AdGuardHome
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/adguardhome.service
|
|
[Unit]
|
|
Description=AdGuard Home (DietPi)
|
|
Wants=network-online.target nss-lookup.target
|
|
After=network-online.target
|
|
Before=nss-lookup.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=adguardhome
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW
|
|
ExecStart=/mnt/dietpi_userdata/adguardhome/AdGuardHome
|
|
ExecReload=/mnt/dietpi_userdata/adguardhome/AdGuardHome -s reload
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# AdGuard Home service needs to be started manually as dietpi-services must not control it to prevent it from killing the systems own DNS server.
|
|
aSTART_SERVICES+=('adguardhome')
|
|
fi
|
|
|
|
if To_Install 33 airsonic # Airsonic-Advanced
|
|
then
|
|
# Since v11 is not yet released, pull latest pre-release
|
|
local fallback_url='https://github.com/airsonic-advanced/airsonic-advanced/releases/download/11.0.0-SNAPSHOT.20240424015024/airsonic.war'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/airsonic-advanced/airsonic-advanced/releases' | mawk -F\" '/^ *"browser_download_url": ".*\/airsonic\.war"$/{print $4}' | head -1)" /mnt/dietpi_userdata/airsonic/airsonic.war
|
|
|
|
# User
|
|
Create_User -g dietpi -G audio -d /mnt/dietpi_userdata/airsonic airsonic
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/airsonic.service
|
|
[Unit]
|
|
Description=Airsonic-Advanced (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Airsonic
|
|
User=airsonic
|
|
WorkingDirectory=/mnt/dietpi_userdata/airsonic
|
|
ExecStart=$JAVA_PATH -mx${JAVA_MAX_HEAP_SIZE}m -Dairsonic.home=/mnt/dietpi_userdata/airsonic -Dserver.servlet.context-path=/airsonic -Dserver.port=8080 -jar /mnt/dietpi_userdata/airsonic/airsonic.war
|
|
SuccessExitStatus=143
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Enable FFmpeg transcode
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/airsonic/transcode
|
|
[[ -f '/mnt/dietpi_userdata/airsonic/transcode/ffmpeg' ]] || G_EXEC ln -sf "$(command -v ffmpeg)" /mnt/dietpi_userdata/airsonic/transcode
|
|
|
|
# Permissions
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/airsonic/airsonic.war
|
|
G_EXEC chown airsonic:root /mnt/dietpi_userdata/airsonic
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 204 navidrome # Navidrome
|
|
then
|
|
case $G_HW_ARCH in
|
|
1) local arch='armv6';;
|
|
2) local arch='armv7';;
|
|
3) local arch='arm64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/navidrome/navidrome/releases/download/v0.59.0/navidrome_0.59.0_linux_$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/navidrome/navidrome/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/navidrome_[0-9.]*_linux_$arch\.tar\.gz\"$/{print \$4}")" /opt/navidrome
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/navidrome
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/navidrome navidrome
|
|
|
|
# Config: https://www.navidrome.org/docs/usage/configuration-options/#available-options
|
|
[[ -f '/mnt/dietpi_userdata/navidrome/navidrome.toml' ]] || cat << '_EOF_' > /mnt/dietpi_userdata/navidrome/navidrome.toml
|
|
DataFolder = '/mnt/dietpi_userdata/navidrome/data'
|
|
MusicFolder = '/mnt/dietpi_userdata/Music'
|
|
ImageCacheSize = '100MiB'
|
|
|
|
LogLevel = 'warn'
|
|
SessionTimeout = '24h'
|
|
AuthRequestLimit = '5'
|
|
AuthWindowLength = '20s'
|
|
ScanSchedule = '@every 1h'
|
|
EnableLogRedacting = 'true'
|
|
Scanner.Extractor = 'taglib'
|
|
|
|
CoverJpegQuality = '75'
|
|
_EOF_
|
|
# Service: https://www.navidrome.org/docs/installation/linux/#create-a-systemd-unit
|
|
cat << '_EOF_' > /etc/systemd/system/navidrome.service
|
|
[Unit]
|
|
Description=Navidrome (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
AssertPathExists=/mnt/dietpi_userdata/navidrome
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=navidrome
|
|
ExecStart=/opt/navidrome/navidrome --configfile "/mnt/dietpi_userdata/navidrome/navidrome.toml"
|
|
WorkingDirectory=/mnt/dietpi_userdata/navidrome
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
|
DevicePolicy=closed
|
|
NoNewPrivileges=yes
|
|
PrivateTmp=yes
|
|
PrivateUsers=yes
|
|
ProtectControlGroups=yes
|
|
ProtectKernelModules=yes
|
|
ProtectKernelTunables=yes
|
|
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
|
RestrictNamespaces=yes
|
|
RestrictRealtime=yes
|
|
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap
|
|
ReadWritePaths=/mnt/dietpi_userdata/navidrome
|
|
|
|
# You can uncomment the following line if you're not using the jukebox This
|
|
# will prevent navidrome from accessing any real (physical) devices
|
|
#PrivateDevices=yes
|
|
|
|
# You can change the following line to `strict` instead of `full` if you don't
|
|
# want navidrome to be able to write anything on your filesystem outside of
|
|
# /mnt/dietpi_userdata/navidrome.
|
|
ProtectSystem=full
|
|
|
|
# You can uncomment the following line if you don't have any media in /home/*.
|
|
# This will prevent navidrome from ever reading/writing anything there.
|
|
#ProtectHome=true
|
|
|
|
# You can customize some Navidrome config options by setting environment variables here. Ex:
|
|
#Environment=ND_BASEURL="/navidrome"
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R root:root /opt/navidrome
|
|
G_EXEC chmod +x /opt/navidrome/navidrome
|
|
G_EXEC chown -R navidrome:root /mnt/dietpi_userdata/navidrome
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 212 kavita # Kavita
|
|
then
|
|
# .NET dependency: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/Kareadita/Kavita/releases/download/v0.8.8.3/kavita-linux-$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Kareadita/Kavita/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/kavita-linux-$arch\.tar\.gz\"$/{print \$4}")"
|
|
G_EXEC chmod +x Kavita/Kavita
|
|
|
|
# Change default port to 2036 to avoid conflict with Shairport Sync
|
|
G_CONFIG_INJECT '"Port":' ' "Port": 2036,' Kavita/config/appsettings-init.json
|
|
|
|
# Reinstall: Preserve config dir
|
|
if [[ -d '/opt/kavita' ]]
|
|
then
|
|
if [[ -d '/opt/kavita/config' ]]
|
|
then
|
|
G_EXEC rm -R Kavita/config
|
|
G_EXEC mv /opt/kavita/config Kavita/
|
|
fi
|
|
G_EXEC rm -R /opt/kavita
|
|
fi
|
|
G_EXEC mv Kavita /opt/kavita
|
|
|
|
# User
|
|
Create_User -g dietpi -d /opt/kavita kavita
|
|
G_EXEC chown -R kavita:root /opt/kavita
|
|
|
|
# Data
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/{ebooks,comics}
|
|
G_EXEC chown kavita:dietpi /mnt/dietpi_userdata/{ebooks,comics}
|
|
G_EXEC chmod 0775 /mnt/dietpi_userdata/{ebooks,comics}
|
|
|
|
# Service: https://wiki.kavitareader.com/en/install/linux-install
|
|
cat << '_EOF_' > /etc/systemd/system/kavita.service
|
|
[Unit]
|
|
Description=Kavita Server (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Kavita
|
|
User=kavita
|
|
WorkingDirectory=/opt/kavita
|
|
ExecStart=/opt/kavita/Kavita
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
G_DIETPI-NOTIFY 2 'Please wait for a few minutes to let the application starts. By default it runs on port 2036.'
|
|
fi
|
|
|
|
if To_Install 68 # Remote.It
|
|
then
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='armhf'
|
|
esac
|
|
|
|
export R3_PLATFORM_CODE=1072
|
|
Download_Install "https://downloads.remote.it/remoteit/latest/remoteit.$arch.deb"
|
|
|
|
G_WHIP_MSG "[ INFO ] The installation of Remote.It is complete.
|
|
\nThe final step is to register your claim code with your desktop application.
|
|
See the manual below for instructions on how to do this.
|
|
\nhttps://docs.remote.it/software/device-package/installation#id-3.-claim-and-register-the-device
|
|
\nYour claim code: $(mawk -F\" '/claim/{print $4}' /etc/remoteit/config.json)
|
|
\nThen this DietPi device will be online as your Remote.It device and you can start using it."
|
|
|
|
if dpkg-query -s 'connectd' &> /dev/null || dpkg-query -s 'weavedconnectd' &> /dev/null
|
|
then
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO '[WARNING] Legacy Remote.It package detected
|
|
\nOne of the legacy Remote.It packages "connectd" or "weavedconnectd" is installed on your system. These have been superseded by the new "remoteit" package.
|
|
\nDo you want the legacy packages to be uninstalled now?
|
|
\nNB: You can do this any time later, e.g. after connections with the new package have been set up:
|
|
G_AGP connectd weavedconnectd' && G_AGP connectd weavedconnectd
|
|
fi
|
|
fi
|
|
|
|
if To_Install 69 # Python 3 RPi.GPIO
|
|
then
|
|
if (( $G_DISTRO > 6 ))
|
|
then
|
|
G_AGI python3-rpi-lgpio
|
|
else
|
|
G_AGI python3-rpi.gpio
|
|
fi
|
|
fi
|
|
|
|
if To_Install 70 # WiringPi
|
|
then
|
|
aDEPS=('make' 'gcc' 'libc6-dev')
|
|
|
|
# RPi
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
Download_Install 'https://github.com/WiringPi/WiringPi/archive/master.tar.gz'
|
|
G_EXEC cd WiringPi-master
|
|
G_EXEC mkdir -p /usr/local/include
|
|
G_EXEC_OUTPUT=1 G_EXEC ./build
|
|
|
|
# Odroids
|
|
elif (( $G_HW_MODEL < 20 ))
|
|
then
|
|
aDEPS+=('automake' 'libtool' 'pkg-config' 'libgpiod-dev' 'libgpiod2') # Add libgpiod2 explicitly so purging *-dev packages, e.g. via dietpi-cleaner, does not break "gpio"
|
|
Download_Install 'https://github.com/hardkernel/wiringPi/archive/master.tar.gz'
|
|
G_EXEC mv {w,W}iringPi-master
|
|
G_EXEC cd WiringPi-master
|
|
G_EXEC_OUTPUT=1 G_EXEC ./autogen.sh
|
|
G_EXEC_OUTPUT=1 G_EXEC ./configure CFLAGS='-g0 -O3'
|
|
G_EXEC_OUTPUT=1 G_EXEC make "-j$(nproc)"
|
|
G_EXEC_OUTPUT=1 G_EXEC make install
|
|
|
|
# Orange Pi
|
|
else
|
|
# Requires /etc/orangepi-release or /etc/armbian-release with BOARD name: https://github.com/orangepi-xunlong/wiringOP/blob/next/wiringPi/wiringPi.c
|
|
local board=
|
|
case $G_HW_MODEL in
|
|
80) board='orangepi5';;
|
|
82) board='orangepi5plus';;
|
|
83) board='orangepizero3';;
|
|
87) board='orangepi3b';;
|
|
88) board='orangepizero2w';;
|
|
89) board='orangepi3-lts';;
|
|
91) board='orangepi5max';;
|
|
93) board='orangepi5pro';;
|
|
94) board='orangepi5ultra';;
|
|
95) board='orangepicm5';;
|
|
96) board='orangepi4a';;
|
|
97) board='orangepirv';;
|
|
98) board='orangepirv2';;
|
|
*) G_DIETPI-NOTIFY 1 "Invalid hardware model \"$G_HW_MODEL_NAME\" (ID \"$G_HW_MODEL\"). Aborting ..."; exit 1;;
|
|
esac
|
|
>> /etc/orangepi-release
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'BOARD=' "BOARD=$board" /etc/orangepi-release
|
|
Download_Install 'https://github.com/orangepi-xunlong/wiringOP/archive/next.tar.gz'
|
|
G_EXEC mv wiringOP-next WiringPi-master
|
|
G_EXEC cd WiringPi-master
|
|
G_EXEC mkdir -p /usr/local/include
|
|
G_EXEC_OUTPUT=1 G_EXEC ./build
|
|
fi
|
|
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note /usr/local/*bin/gpio
|
|
G_EXEC strip --strip-unneeded --remove-section=.comment --remove-section=.note /usr/local/lib/libwiringPi*.so
|
|
G_EXEC ldconfig
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Move source dir to disk, as it contains additional examples to compile
|
|
[[ -d '/root/wiringPi' ]] && G_EXEC rm -R /root/wiringPi # Pre-v7.2
|
|
[[ -d '/mnt/dietpi_userdata/WiringPi' ]] && G_EXEC rm -R /mnt/dietpi_userdata/WiringPi
|
|
G_EXEC mv WiringPi-master /mnt/dietpi_userdata/WiringPi
|
|
fi
|
|
|
|
if To_Install 72 # I2C
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware i2c enable
|
|
fi
|
|
|
|
if To_Install 100 pijuice # PiJuice
|
|
then
|
|
# Pre-create config so we can preserve user customisations but override the package default
|
|
G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed/pijuice /var/lib/pijuice
|
|
[[ -f '/var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func1.sh' ]] || G_EXEC eval 'echo -e '\''#!/bin/dash\npoweroff'\'' > /var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func1.sh'
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func1.sh
|
|
[[ -f '/var/lib/pijuice/pijuice_config.JSON' ]] || cat << '_EOF_' > /var/lib/pijuice/pijuice_config.JSON
|
|
{
|
|
"system_events": {
|
|
"low_battery_voltage": {
|
|
"function": "SYS_FUNC_HALT",
|
|
"enabled": true
|
|
},
|
|
"low_charge": {
|
|
"function": "NO_FUNC",
|
|
"enabled": true
|
|
},
|
|
"button_power_off": {
|
|
"function": "USER_FUNC1",
|
|
"enabled": true
|
|
},
|
|
"forced_power_off": {
|
|
"function": "USER_FUNC2",
|
|
"enabled": false
|
|
},
|
|
"no_power": {
|
|
"function": "SYS_FUNC_HALT_POW_OFF",
|
|
"enabled": true
|
|
},
|
|
"forced_sys_power_off": {
|
|
"function": "USER_FUNC3",
|
|
"enabled": false
|
|
},
|
|
"watchdog_reset": {
|
|
"function": "USER_EVENT",
|
|
"enabled": true
|
|
}
|
|
},
|
|
"user_functions": {
|
|
"USER_FUNC1": "/var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func1.sh",
|
|
"USER_FUNC2": "/var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func2.sh",
|
|
"USER_FUNC3": "/var/lib/dietpi/dietpi-software/installed/pijuice/pijuice_func3.sh",
|
|
"USER_FUNC4": "",
|
|
"USER_FUNC5": "",
|
|
"USER_FUNC6": "",
|
|
"USER_FUNC7": "",
|
|
"USER_FUNC8": ""
|
|
},
|
|
"system_task": {
|
|
"watchdog": {
|
|
"enabled": true,
|
|
"period": "60"
|
|
},
|
|
"min_bat_voltage": {
|
|
"threshold": "1",
|
|
"enabled": true
|
|
},
|
|
"min_charge": {
|
|
"threshold": "1",
|
|
"enabled": true
|
|
},
|
|
"enabled": true,
|
|
"wakeup_on_charge": {
|
|
"enabled": true,
|
|
"trigger_level": "1"
|
|
}
|
|
}
|
|
}
|
|
_EOF_
|
|
# Trixie: https://archive.raspberrypi.com/debian/dists/trixie/main/binary-arm64/Packages, https://github.com/PiSupply/PiJuice/tree/master/Software/Install
|
|
if apt-cache dumpavail | grep -q '^Package: pijuice-base$'
|
|
then
|
|
G_AGI pijuice-base
|
|
else
|
|
Download_Install 'https://archive.raspberrypi.com/debian/pool/main/p/pijuice-base/pijuice-base_1.8_all.deb'
|
|
fi
|
|
G_EXEC systemctl stop pijuice
|
|
fi
|
|
|
|
if To_Install 171 # frp
|
|
then
|
|
case $G_HW_ARCH in
|
|
1) local arch='arm';;
|
|
2) local arch='arm_hf';;
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='riscv64';;
|
|
esac
|
|
|
|
# Download
|
|
local fallback_url="https://github.com/fatedier/frp/releases/download/v0.65.0/frp_0.65.0_linux_$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/fatedier/frp/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/frp_[0-9.]*_linux_$arch\.tar\.gz\"$/{print \$4}")"
|
|
|
|
G_EXEC cd frp_*
|
|
|
|
# Mode choice
|
|
G_WHIP_MENU_ARRAY=(
|
|
'Server' ': Use this machine as a server, with a public IP'
|
|
'Client' ': Use this machine as a client, without a public IP'
|
|
'Both' ': Run the reverse proxy only on this machine'
|
|
)
|
|
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_DEFAULT_ITEM='Both'
|
|
G_WHIP_MENU 'Please choose how you are going to run frp:'
|
|
local mode=${G_WHIP_RETURNED_VALUE:-Both}
|
|
|
|
G_EXEC mkdir -p /etc/frp
|
|
Create_User frp -d /etc/frp
|
|
|
|
local token=
|
|
if [[ $mode == 'Server' || $mode == 'Both' ]]
|
|
then
|
|
G_EXEC mv frps /usr/local/bin/frps
|
|
cat << '_EOF_' > /etc/systemd/system/frps.service
|
|
[Unit]
|
|
Description=frp server (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=frp
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
ExecStart=/usr/local/bin/frps -c /etc/frp/frps.toml
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Pre-v9.9: Inform about config file migration
|
|
if [[ -f '/etc/frp/frps.ini' ]]
|
|
then
|
|
G_WHIP_MSG '[WARNING] New toml config file will be generated
|
|
\nfrp deprecated the ini format for its config files, hence /etc/frp/frps.toml will be generated and used from now on.
|
|
\nAn automated conversion is not possible and hence need to be done manually if you did changes. A backup of the ini config it kept in place:
|
|
- /etc/frp/frps.ini.bak
|
|
\nA full overview of all config keys can be found here:
|
|
- https://github.com/fatedier/frp/blob/dev/conf/frps_full_example.toml'
|
|
G_EXEC mv /etc/frp/frps.ini{,.bak}
|
|
fi
|
|
|
|
# Pre-create config file to turn on dashboard
|
|
token=$(openssl rand -hex 15)
|
|
[[ -f '/etc/frp/frps.toml' ]] || cat << _EOF_ > /etc/frp/frps.toml
|
|
bindAddr = "0.0.0.0"
|
|
bindPort = 7000
|
|
|
|
webServer.addr = "0.0.0.0"
|
|
webServer.port = 7500
|
|
webServer.user = "admin"
|
|
webServer.password = "$GLOBAL_PW"
|
|
|
|
auth.method = "token"
|
|
auth.token = "$token"
|
|
_EOF_
|
|
G_EXEC chmod 0640 /etc/frp/frps.toml
|
|
G_EXEC chown root:frp /etc/frp/frps.toml
|
|
aENABLE_SERVICES+=('frps')
|
|
fi
|
|
|
|
if [[ $mode == 'Client' || $mode == 'Both' ]]
|
|
then
|
|
G_EXEC mv frpc /usr/local/bin/frpc
|
|
cat << '_EOF_' > /etc/systemd/system/frpc.service
|
|
[Unit]
|
|
Description=frp client (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target frps.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=frp
|
|
ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.toml
|
|
ExecReload=/usr/local/bin/frpc reload -c /etc/frp/frpc.toml
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Pre-v9.9: Inform about config file migration
|
|
if [[ -f '/etc/frp/frpc.ini' ]]
|
|
then
|
|
G_WHIP_MSG '[WARNING] New toml config file will be generated
|
|
\nfrp deprecated the ini format for its config files, hence /etc/frp/frpc.toml will be generated and used from now on.
|
|
\nAn automated conversion is not possible and hence need to be done manually if you did changes. A backup of the ini config it kept in place:
|
|
- /etc/frp/frpc.ini.bak
|
|
\nA full overview of all config keys can be found here:
|
|
- https://github.com/fatedier/frp/blob/dev/conf/frpc_full_example.toml'
|
|
G_EXEC mv /etc/frp/frpc.ini{,.bak}
|
|
fi
|
|
|
|
# Pre-create config file to turn on admin UI
|
|
if [[ ! -f '/etc/frp/frpc.toml' ]]
|
|
then
|
|
local server_addr='127.0.0.1' server_port=7000
|
|
if [[ $G_WHIP_RETURNED_VALUE == 'Client' ]]
|
|
then
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_DEFAULT_ITEM="$server_addr:$server_port"
|
|
G_WHIP_INPUTBOX_REGEX='^[0-9.:]+$'
|
|
G_WHIP_INPUTBOX_REGEX_TEXT='be a valid IP address, optionally with appended network port number, like "192.168.1.100:7000"'
|
|
G_WHIP_INPUTBOX 'Please enter the IP address of your frp server, optionally including port (default 7000):'
|
|
[[ $G_WHIP_RETURNED_VALUE ]] && server_addr=${G_WHIP_RETURNED_VALUE%:*}
|
|
[[ $G_WHIP_RETURNED_VALUE =~ : ]] && server_port=${G_WHIP_RETURNED_VALUE##*:}
|
|
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX_REGEX='*'
|
|
G_WHIP_INPUTBOX 'Please enter the authentication token of your frp server:'
|
|
token=$G_WHIP_RETURNED_VALUE
|
|
fi
|
|
|
|
cat << _EOF_ > /etc/frp/frpc.toml
|
|
serverAddr = "$server_addr"
|
|
serverPort = $server_port
|
|
|
|
webServer.addr = "0.0.0.0"
|
|
webServer.port = 7400
|
|
webServer.user = "admin"
|
|
webServer.password = "$GLOBAL_PW"
|
|
|
|
auth.method = "token"
|
|
auth.token = "$token"
|
|
_EOF_
|
|
fi
|
|
|
|
G_EXEC chmod 0660 /etc/frp/frpc.toml
|
|
G_EXEC chown root:frp /etc/frp/frpc.toml
|
|
aENABLE_SERVICES+=('frpc')
|
|
fi
|
|
|
|
# Cleanup
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R frp_*
|
|
fi
|
|
|
|
if To_Install 122 node-red # Node-RED
|
|
then
|
|
# APT deps
|
|
G_AGI python3
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/node-red
|
|
|
|
# User
|
|
Create_User -G dialout,gpio,i2c,spi -d /mnt/dietpi_userdata/node-red nodered
|
|
# - Allow sudo calls
|
|
G_EXEC eval 'echo '\''nodered ALL=NOPASSWD: ALL'\'' > /etc/sudoers.d/nodered'
|
|
|
|
# Permissions
|
|
G_EXEC chown -R nodered:nodered /mnt/dietpi_userdata/node-red
|
|
|
|
# Install as local instance for "nodered" user
|
|
G_EXEC cd /mnt/dietpi_userdata/node-red
|
|
# - Disable cache
|
|
local cache=$(runuser -u nodered -- mktemp -d)
|
|
# - Reinstall: Remove all locally installed modules, to work around update issues, but preserve installed plugins from package.json: https://github.com/MichaIng/DietPi/issues/7128
|
|
[[ -f 'package.json' ]] && G_EXEC rm -Rf node_modules .npm/_cacache
|
|
# - Install v3 on ARMv6, since the @node-rs/bcrypt dependency does not support it: https://github.com/MichaIng/DietPi/issues/7252
|
|
local version='latest'
|
|
(( $G_HW_ARCH == 1 )) && version=3
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u nodered -- npm i --cache "$cache" --no-audit "node-red@$version"
|
|
G_EXEC rm -R "$cache"
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/node-red.service
|
|
[Unit]
|
|
Description=Node-RED (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=nodered
|
|
ExecStart=/mnt/dietpi_userdata/node-red/node_modules/.bin/node-red -u /mnt/dietpi_userdata/node-red
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# CLI alias
|
|
echo 'alias node-red-admin='\''sudo -u nodered /mnt/dietpi_userdata/node-red/node_modules/.bin/node-red-admin'\' > /etc/bashrc.d/dietpi-node-red.sh
|
|
fi
|
|
|
|
if To_Install 123 mosquitto # Mosquitto
|
|
then
|
|
# Use official APT repository where available: https://repo.mosquitto.org/debian/pool/main/m/mosquitto/
|
|
# - Current builds are not ARMv6 compatible: https://github.com/MichaIng/DietPi/issues/5140
|
|
if (( $G_DISTRO < 9 )) && (( $G_HW_ARCH == 2 || $G_HW_ARCH == 10 || ( $G_HW_ARCH == 3 && $G_DISTRO > 6 ) ))
|
|
then
|
|
# APT key
|
|
local url='https://repo.mosquitto.org/debian/mosquitto-repo.gpg'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-mosquitto.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval "echo 'deb https://repo.mosquitto.org/debian $G_DISTRO_NAME main' > /etc/apt/sources.list.d/dietpi-mosquitto.list"
|
|
G_AGUP
|
|
fi
|
|
|
|
G_AGI mosquitto
|
|
G_EXEC systemctl stop mosquitto
|
|
|
|
Remove_SysV mosquitto
|
|
|
|
# Password file
|
|
if [[ ! -f '/etc/mosquitto/passwd' ]]
|
|
then
|
|
G_EXEC umask 0037 # relevant for passwd mode until v2.0.18
|
|
G_EXEC_PRE_FUNC(){ acommand[5]=$GLOBAL_PW; }
|
|
G_EXEC mosquitto_passwd -c -b /etc/mosquitto/passwd mosquitto "${GLOBAL_PW//?/X}"
|
|
G_EXEC chown root:mosquitto /etc/mosquitto/passwd
|
|
G_EXEC chmod 0640 /etc/mosquitto/passwd # from v2.0.18 on, 0600 is the default mode, hence the "mosquitto" user has no read access
|
|
G_EXEC umask 0022
|
|
fi
|
|
|
|
# Config: /etc/mosquitto/conf.d exists, but doubled settings do not override each other and lead to a startup failure instead, which breaks the purpose we want to use it for.
|
|
# - Disable PID file, not required for systemd handling
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*pid_file[[:blank:]]/d' /etc/mosquitto/mosquitto.conf
|
|
[[ -d '/run/mosquitto' ]] && G_EXEC rm -R /run/mosquitto
|
|
# - Log to default STDERR > systemd-journald
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*log_dest[[:blank:]]/d' /etc/mosquitto/mosquitto.conf
|
|
[[ -d '/var/log/mosquitto' ]] && G_EXEC rm -R /var/log/mosquitto
|
|
# - Add default password file for authenticated requests: https://github.com/MichaIng/DietPi/issues/4133
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'password_file[[:blank:]]' 'password_file /etc/mosquitto/passwd' /etc/mosquitto/mosquitto.conf
|
|
# - Add default listener at port 1883 not bind to loopback IP: https://github.com/MichaIng/DietPi/issues/4133
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'listener[[:blank:]]' 'listener 1883' /etc/mosquitto/mosquitto.conf
|
|
|
|
# Add/override default systemd unit: https://github.com/eclipse/mosquitto/tree/master/service/systemd
|
|
cat << '_EOF_' > /etc/systemd/system/mosquitto.service
|
|
[Unit]
|
|
Description=Mosquitto MQTT Broker (DietPi)
|
|
Documentation=man:mosquitto.conf(5) man:mosquitto(8)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=notify
|
|
NotifyAccess=main
|
|
User=mosquitto
|
|
ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
|
|
ExecReload=/bin/kill -HUP $MAINPID
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 131 blynkserver # Blynk Server
|
|
then
|
|
# RPi: Install build deps for the "onoff" Node module
|
|
(( $G_HW_MODEL > 9 )) || aDEPS=('python3' 'make' 'g++')
|
|
|
|
Download_Install 'https://github.com/Peterkn2001/blynk-server/releases/download/v0.41.17/server-0.41.17.jar' /mnt/dietpi_userdata/blynk/blynkserver.jar
|
|
|
|
# RPi: Install "onoff" for GPIO access
|
|
(( $G_HW_MODEL > 9 )) || G_EXEC_OUTPUT=1 G_EXEC npm i -g --no-audit onoff@latest
|
|
|
|
# Install Blynk JS library
|
|
G_EXEC_OUTPUT=1 G_EXEC npm i -g --no-audit blynk-library@latest
|
|
|
|
# Preserve existing config
|
|
if [[ ! -f '/mnt/dietpi_userdata/blynk/server.properties' ]]
|
|
then
|
|
G_EXEC curl -sSfL 'https://raw.githubusercontent.com/Peterkn2001/blynk-server/master/server/core/src/main/resources/server.properties' -o /mnt/dietpi_userdata/blynk/server.properties
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/blynk/server.properties
|
|
G_CONFIG_INJECT 'logs.folder=' 'logs.folder=/var/log/blynk' /mnt/dietpi_userdata/blynk/server.properties
|
|
G_CONFIG_INJECT 'data.folder=' 'data.folder=/mnt/dietpi_userdata/blynk/data' /mnt/dietpi_userdata/blynk/server.properties
|
|
G_CONFIG_INJECT 'http.port=' 'http.port=8442' /mnt/dietpi_userdata/blynk/server.properties
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'admin.pass=' "admin.pass=$GLOBAL_PW" /mnt/dietpi_userdata/blynk/server.properties
|
|
fi
|
|
|
|
# Example local TCP connection script
|
|
if [[ ! -f '/mnt/dietpi_userdata/blynk/client-tcp-local.js' ]]
|
|
then
|
|
G_EXEC curl -sSfL 'https://raw.githubusercontent.com/vshymanskyy/blynk-library-js/master/examples/nodejs/client-tcp-local.js' -o /mnt/dietpi_userdata/blynk/client-tcp-local.js
|
|
G_EXEC sed --follow-symlinks -i "s|require('blynk-library')|require('/usr/local/lib/node_modules/blynk-library')|" /mnt/dietpi_userdata/blynk/client-tcp-local.js
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/blynk/client-tcp-local.js
|
|
fi
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/blynk blynk
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/blynkserver.service
|
|
[Unit]
|
|
Description=Blynk Server (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Blynk
|
|
User=blynk
|
|
LogsDirectory=blynk
|
|
WorkingDirectory=/mnt/dietpi_userdata/blynk
|
|
ExecStart=$JAVA_PATH -mx${JAVA_MAX_HEAP_SIZE}m -jar /mnt/dietpi_userdata/blynk/blynkserver.jar
|
|
SuccessExitStatus=143
|
|
|
|
# Hardening
|
|
PrivateTmp=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R blynk:blynk /mnt/dietpi_userdata/blynk
|
|
fi
|
|
|
|
if To_Install 124 networkaudiod # NAA Daemon
|
|
then
|
|
# Base URL
|
|
local url="https://signalyst.com/bins/naa/linux/${G_DISTRO_NAME/forky/trixie}/"
|
|
|
|
# Check download dir
|
|
G_CHECK_URL "$url"
|
|
|
|
# Get latest version
|
|
local package=$(curl -sSfL "$url" | grep -Po "(?<=href=\")networkaudiod_[^\"]*_$(dpkg --print-architecture).deb(?=\")" | tail -1)
|
|
|
|
# Skip license
|
|
G_EXEC eval 'debconf-set-selections <<< '\''networkaudiod networkaudiod/license note false'\'
|
|
|
|
# Install
|
|
Download_Install "${package:+$url$package}"
|
|
G_EXEC systemctl stop networkaudiod
|
|
|
|
unset -v url package
|
|
fi
|
|
|
|
if To_Install 71 webiopi # WebIOPi
|
|
then
|
|
# Check for reinstall
|
|
local reinstall=0
|
|
[[ -f '/etc/webiopi/config' ]] && reinstall=1
|
|
|
|
aDEPS=('python3-dev' 'python3-setuptools' 'gcc' 'patch')
|
|
Download_Install 'https://github.com/Freenove/WebIOPi/archive/master.tar.gz'
|
|
|
|
G_EXEC cd WebIOPi-master/WebIOPi-*
|
|
|
|
# Apply patch
|
|
G_EXEC_OUTPUT=1 G_EXEC patch -p1 -i webiopi-pi2bplus.patch
|
|
|
|
# Install for Python 3 only
|
|
G_EXEC sed --follow-symlinks -i '/SEARCH="python python3"/c\SEARCH="python3"' setup.sh
|
|
|
|
# Skip Weaved install prompt
|
|
G_EXEC sed --follow-symlinks -i '/read response/c\response="n"' setup.sh
|
|
|
|
# Run setup script, skipping APT installs
|
|
G_EXEC_OUTPUT=1 G_EXEC ./setup.sh skip-apt
|
|
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Cleanup
|
|
G_EXEC rm -R WebIOPi-master
|
|
|
|
# On fresh installs, change port to 8002 to avoid conflict with Icecast
|
|
(( $reinstall )) || G_EXEC sed --follow-symlinks -i 's/^port = 8000$/port = 8002/' /etc/webiopi/config
|
|
|
|
# Service
|
|
Remove_SysV webiopi 1
|
|
cat << '_EOF_' > /etc/systemd/system/webiopi.service
|
|
[Unit]
|
|
Description=WebIOPi (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=WebIOPi
|
|
ExecStart=/usr/bin/python3 -m webiopi -c /etc/webiopi/config
|
|
|
|
# Hardening
|
|
PrivateTmp=true
|
|
ProtectHome=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 98 haproxy # HAProxy
|
|
then
|
|
# Dependencies
|
|
aDEPS=('make' 'gcc' 'libpcre2-dev' 'libssl-dev' 'zlib1g-dev' 'libsystemd-dev')
|
|
|
|
# Obtain latest version: Stick with v3. Once v4 is released, we will surely need to adjust below code.
|
|
local url=$(curl -sSfL 'https://www.haproxy.org/' | grep -Po '(?<=href=")/download/3\..*/src/haproxy-.*\.tar\.gz(?=")' | head -1)
|
|
local fallback_url='https://www.haproxy.org/download/3.3/src/haproxy-3.3.0.tar.gz'
|
|
Download_Install "${url:+https://www.haproxy.org$url}"
|
|
|
|
# Compile
|
|
G_EXEC cd haproxy-3.*
|
|
G_EXEC_OUTPUT=1 G_EXEC make -j "$G_HW_CPU_CORES" TARGET=linux-glibc USE_PCRE2=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_PROMEX=1 DEBUG_CFLAGS='-g0 -O3' LDFLAGS='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed'
|
|
# Strip binary size
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note haproxy
|
|
# Install
|
|
G_EXEC_OUTPUT=1 G_EXEC make install
|
|
# - systemd unit
|
|
G_EXEC cd admin/systemd
|
|
G_EXEC_OUTPUT=1 G_EXEC make
|
|
G_EXEC mv {,/etc/systemd/system/}haproxy.service
|
|
# - Error pages
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC mkdir -p /etc/haproxy/errors
|
|
G_EXEC mv haproxy-3.*/examples/errorfiles/*.http /etc/haproxy/errors/
|
|
# Cleanup
|
|
G_EXEC rm -R haproxy-3.*
|
|
|
|
# Jail directory
|
|
G_EXEC mkdir -p /var/lib/haproxy
|
|
|
|
# Config
|
|
[[ -f '/etc/haproxy/haproxy.cfg' ]] || cat << _EOF_ > /etc/haproxy/haproxy.cfg
|
|
global
|
|
maxconn 64
|
|
# Jail directory
|
|
chroot /var/lib/haproxy
|
|
stats socket /run/haproxy.sock mode 660 level admin
|
|
stats timeout 30s
|
|
user root
|
|
group root
|
|
daemon
|
|
|
|
# Default SSL material locations
|
|
ca-base /etc/ssl/certs
|
|
crt-base /etc/ssl/private
|
|
|
|
# Default ciphers to use on SSL-enabled listening sockets.
|
|
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
|
ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
|
|
|
ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
|
|
ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
|
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
|
|
|
defaults
|
|
log global
|
|
mode http
|
|
option httplog
|
|
option dontlognull
|
|
timeout connect 5000
|
|
timeout client 50000
|
|
timeout server 50000
|
|
errorfile 400 /etc/haproxy/errors/400.http
|
|
errorfile 403 /etc/haproxy/errors/403.http
|
|
errorfile 408 /etc/haproxy/errors/408.http
|
|
errorfile 500 /etc/haproxy/errors/500.http
|
|
errorfile 502 /etc/haproxy/errors/502.http
|
|
errorfile 503 /etc/haproxy/errors/503.http
|
|
errorfile 504 /etc/haproxy/errors/504.http
|
|
|
|
frontend localnodes
|
|
bind *:80
|
|
mode http
|
|
default_backend nodes
|
|
|
|
backend nodes
|
|
mode http
|
|
balance roundrobin
|
|
option forwardfor
|
|
http-request set-header X-Forwarded-Port %[dst_port]
|
|
http-request add-header X-Forwarded-Proto https if { ssl_fc }
|
|
option httpchk HEAD / HTTP/1.1
|
|
http-check send meth HEAD uri / ver HTTP/1.1 hdr host localhost
|
|
server web01 127.0.0.1:9000 check
|
|
server web02 127.0.0.1:9001 check
|
|
server web03 127.0.0.1:9002 check
|
|
|
|
# Admin web page
|
|
listen stats
|
|
bind *:1338
|
|
stats enable
|
|
stats uri /
|
|
http-request use-service prometheus-exporter if { path /metrics }
|
|
stats hide-version
|
|
stats auth admin:$GLOBAL_PW
|
|
_EOF_
|
|
G_EXEC chmod 0600 /etc/haproxy/haproxy.cfg
|
|
fi
|
|
|
|
if To_Install 35 lyrionmusicserver # Lyrion Music Server
|
|
then
|
|
# Grab architecture
|
|
local arch='arm'
|
|
(( $G_HW_ARCH == 10 )) && arch='amd64'
|
|
|
|
# Grab latest package URL
|
|
local fallback_url="https://downloads.lms-community.org/nightly/lyrionmusicserver_9.0.4~1763927290_$arch.deb"
|
|
Download_Install "$(curl -sSfL 'https://raw.githubusercontent.com/LMS-Community/lms-server-repository/master/stable.xml' | grep -om1 "https://[^\"]*_$arch.deb")"
|
|
G_EXEC systemctl stop lyrionmusicserver
|
|
Remove_SysV lyrionmusicserver
|
|
|
|
# Grant user write access to DietPi media dirs for creating infobrowser.opml.
|
|
G_EXEC usermod -aG dietpi squeezeboxserver
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 55 # WordPress
|
|
then
|
|
Download_Install 'https://wordpress.org/latest.tar.gz' /var/www
|
|
|
|
# Permissions
|
|
G_EXEC chown -R www-data:www-data /var/www/wordpress
|
|
|
|
# Create MariaDB database
|
|
/boot/dietpi/func/create_mysql_db wordpress wordpress "$GLOBAL_PW"
|
|
fi
|
|
|
|
if To_Install 38 # FreshRSS
|
|
then
|
|
# Install required PHP modules: https://github.com/FreshRSS/FreshRSS#requirements
|
|
aDEPS=("php$PHP_VERSION-curl" "php$PHP_VERSION-gmp" "php$PHP_VERSION-intl" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-xml" "php$PHP_VERSION-zip")
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
local json=()
|
|
[[ $PHP_VERSION == 8* ]] || aDEPS+=("php$PHP_VERSION-json") json=('json')
|
|
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d '/opt/FreshRSS' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/FreshRSS\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually backup your config files+data, remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
else
|
|
# Bullseye: v1.25.0 requires PHP 8.1+: https://github.com/FreshRSS/FreshRSS/releases/tag/1.25.0
|
|
local version='1.24.3'
|
|
if (( $G_DISTRO > 6 ))
|
|
then
|
|
version=$(curl -sSfL 'https://api.github.com/repos/FreshRSS/FreshRSS/releases/latest' | mawk -F\" '/^ *"tag_name": "[^"]*",$/{print $4}')
|
|
[[ $version ]] || { version='1.27.1'; G_DIETPI-NOTIFY 1 "Automatic latest FreshRSS version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
fi
|
|
Download_Install "https://github.com/FreshRSS/FreshRSS/archive/$version.tar.gz"
|
|
G_EXEC mv "FreshRSS-$version" /opt/FreshRSS
|
|
fi
|
|
|
|
# Enable required PHP modules: https://github.com/FreshRSS/FreshRSS#requirements
|
|
G_EXEC phpenmod curl gmp iconv intl pdo_mysql ctype dom mbstring xml zip "${json[@]}"
|
|
|
|
# Apache config
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
# Required modules: https://github.com/FreshRSS/FreshRSS/blob/edge/p/.htaccess, https://github.com/FreshRSS/FreshRSS/blob/edge/p/api/.htaccess, https://github.com/FreshRSS/FreshRSS/blob/edge/p/themes/.htaccess
|
|
# - Do not enable mod_deflate since it may cause issues with concurrent ownCloud and Nextcloud installs: https://docs.nextcloud.com/server/latest/admin_manual/issues/general_troubleshooting.html#web-server-and-php-modules
|
|
G_EXEC a2enmod dir mime expires headers setenvif
|
|
|
|
# Better compatibility with mobile clients
|
|
cat << '_EOF_' > /etc/apache2/conf-available/dietpi-freshrss.conf
|
|
# Based on: https://freshrss.github.io/FreshRSS/en/admins/10_ServerConfig.html
|
|
<Directory /var/www/freshrss>
|
|
AllowOverride AuthConfig FileInfo Indexes Limit
|
|
Require all granted
|
|
Options FollowSymLinks
|
|
</Directory>
|
|
AllowEncodedSlashes On
|
|
_EOF_
|
|
G_EXEC a2enconf dietpi-freshrss
|
|
fi
|
|
|
|
# Create MariaDB database and user
|
|
# - Create random alphanumeric 30 characters password
|
|
local password=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/freshrss' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'FreshRSS MariaDB database found, will NOT overwrite.'
|
|
G_EXEC systemctl restart mariadb
|
|
# Update database password if do-install.php applies it to the FreshRSS config
|
|
[[ -f '/opt/FreshRSS/data/applied_migrations.txt' ]] || mysql -e "grant all privileges on \`freshrss\`.* to 'freshrss'@localhost identified by '$password';flush privileges"
|
|
else
|
|
/boot/dietpi/func/create_mysql_db freshrss freshrss "$password"
|
|
fi
|
|
|
|
# Set permissions for webserver access
|
|
G_EXEC chgrp -R www-data /opt/FreshRSS
|
|
G_EXEC chmod -R g+r+w /opt/FreshRSS
|
|
|
|
# CLI install: https://github.com/FreshRSS/FreshRSS/blob/master/cli/README.md#commands
|
|
G_EXEC cd /opt/FreshRSS
|
|
runuser -u www-data -- php ./cli/prepare.php
|
|
runuser -u www-data -- php ./cli/do-install.php --default_user dietpi --auth_type form --environment production --title FreshRSS --db-type mysql --db-host localhost --db-user freshrss --db-password "$password" --db-base freshrss --db-prefix freshrss
|
|
unset -v password
|
|
runuser -u www-data -- php ./cli/create-user.php --user dietpi --password "$GLOBAL_PW" --api_password "$GLOBAL_PW"
|
|
runuser -u www-data -- php ./cli/actualize-user.php --user dietpi
|
|
runuser -u www-data -- php ./cli/db-optimize.php --user dietpi
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Link web interface to webroot
|
|
G_EXEC rm -Rf /var/www/freshrss
|
|
G_EXEC ln -s /opt/FreshRSS/p /var/www/freshrss
|
|
|
|
# Create cron job for feed update every 30 minutes if it does not yet exist
|
|
crontab -u www-data -l 2>/dev/null | grep -q '/opt/FreshRSS/app/actualize_script.php' || { crontab -u www-data -l 2>/dev/null ; echo '*/30 * * * * php /opt/FreshRSS/app/actualize_script.php'; } | crontab -u www-data -
|
|
fi
|
|
|
|
if To_Install 28 # TigerVNC Server
|
|
then
|
|
# tigervnc-tools ships tigervncpasswd as dedicated package since Bookworm.
|
|
local apackages=()
|
|
(( $G_DISTRO > 6 )) && apackages=('tigervnc-tools')
|
|
G_AGI tigervnc-standalone-server tigervnc-scraping-server "${apackages[@]}"
|
|
fi
|
|
|
|
if To_Install 120 # RealVNC Server
|
|
then
|
|
local deps=()
|
|
# Bullseye: Depends on libbcm_host.so but does not pull libraspberrypi0 as dependency
|
|
(( $G_DISTRO < 7 )) && deps=('libraspberrypi0')
|
|
G_AGI realvnc-vnc-server "${deps[@]}"
|
|
fi
|
|
|
|
# TigerVNC/RealVNC Server: Shared setup
|
|
if (( ${aSOFTWARE_INSTALL_STATE[28]} == 1 || ${aSOFTWARE_INSTALL_STATE[120]} == 1 ))
|
|
then
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/vncserver.service
|
|
[Unit]
|
|
Description=VNC Server (DietPi)
|
|
Before=xrdp.service xrdp-sesman.service
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
RemainAfterExit=yes
|
|
PAMName=login
|
|
User=root
|
|
Environment=HOME=/root
|
|
ExecStart=/usr/local/bin/vncserver start
|
|
ExecStop=/usr/local/bin/vncserver stop
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
aSTART_SERVICES+=('vncserver')
|
|
|
|
cat << '_EOF_' > /usr/local/bin/vncserver
|
|
#!/bin/dash
|
|
if [ -f '/usr/bin/vncserver-virtual' ]
|
|
then
|
|
echo '[ OK ] RealVNC detected'
|
|
FP_BINARY='/usr/bin/vncserver-virtual -Authentication VncAuth'
|
|
FP_SHARED='exec /usr/bin/vncserver-x11 -service -Authentication VncAuth'
|
|
|
|
elif [ -f '/usr/bin/tigervncserver' ]
|
|
then
|
|
echo '[ OK ] TigerVNC detected'
|
|
FP_BINARY='/usr/bin/tigervncserver'
|
|
FP_SHARED="/usr/bin/X0tigervnc -display :0 -rfbauth $HOME/.vnc/passwd"
|
|
else
|
|
echo '[FAILED] No supported VNC server installed'
|
|
exit 1
|
|
fi
|
|
|
|
case "$1" in
|
|
start)
|
|
# Shared desktop mode
|
|
if grep -q '^[[:blank:]]*SOFTWARE_VNCSERVER_SHARE_DESKTOP=1' /boot/dietpi.txt
|
|
then
|
|
echo '[ INFO ] Waiting for X server...'
|
|
while :
|
|
do
|
|
until pgrep '^X' > /dev/null 2>&1; do sleep 1; done
|
|
echo '[ INFO ] Connecting to shared desktop'
|
|
$FP_SHARED
|
|
sleep 2
|
|
pgrep '^X' > /dev/null 2>&1 && exit 1
|
|
echo '[ INFO ] X server stopped, waiting for next session...'
|
|
done
|
|
|
|
# Virtual desktop mode
|
|
else
|
|
DISPLAY=$(sed -n '/^[[:blank:]]*SOFTWARE_VNCSERVER_DISPLAY_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
WIDTH=$(sed -n '/^[[:blank:]]*SOFTWARE_VNCSERVER_WIDTH=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
HEIGHT=$(sed -n '/^[[:blank:]]*SOFTWARE_VNCSERVER_HEIGHT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
DEPTH=$(sed -n '/^[[:blank:]]*SOFTWARE_VNCSERVER_DEPTH=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
echo "[ INFO ] Starting virtual desktop at display :${DISPLAY:=1} in ${WIDTH:=1280}x${HEIGHT:=720}x${DEPTH:=16}"
|
|
export SHELL='/bin/bash'
|
|
exec $FP_BINARY ":$DISPLAY" -geometry "${WIDTH}x$HEIGHT" -depth "$DEPTH"
|
|
fi
|
|
;;
|
|
stop)
|
|
# Shared desktop mode
|
|
if grep -q '^[[:blank:]]*SOFTWARE_VNCSERVER_SHARE_DESKTOP=1' /boot/dietpi.txt
|
|
then
|
|
echo '[ INFO ] Disconnecting from shared desktop'
|
|
killall -qw vncserver-x11-core X0tigervnc
|
|
|
|
# Virtual desktop mode
|
|
else
|
|
DISPLAY=$(sed -n '/^[[:blank:]]*SOFTWARE_VNCSERVER_DISPLAY_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
echo "[ INFO ] Stopping virtual desktop at display :${DISPLAY:=1}"
|
|
$FP_BINARY -kill ":$DISPLAY"
|
|
fi
|
|
;;
|
|
*)
|
|
echo "[FAILED] Invalid command ($1), please use \"start\" or \"stop\""
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
exit 0
|
|
_EOF_
|
|
G_EXEC chmod +x /usr/local/bin/vncserver
|
|
|
|
# TigerVNC
|
|
if (( ${aSOFTWARE_INSTALL_STATE[28]} == 1 ))
|
|
then
|
|
# TigerVNC: Permit remote connections which implies TLSVnc authentications being enabled additionally
|
|
# shellcheck disable=SC2016
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT '\$localhost[[:blank:]]*=' '$localhost = "no";' /etc/tigervnc/vncserver-config-defaults
|
|
|
|
# Set control + read-only passwords
|
|
local path='/root/.vnc'
|
|
(( $G_DISTRO > 7 )) && path='/root/.config/tigervnc'
|
|
if [[ ! -f $path/passwd ]]
|
|
then
|
|
G_EXEC mkdir -p "$path"
|
|
tigervncpasswd -f <<< "$GLOBAL_PW
|
|
$GLOBAL_PW" > "$path/passwd"
|
|
G_EXEC chmod 0600 "$path/passwd"
|
|
fi
|
|
fi
|
|
|
|
# RealVNC
|
|
if (( ${aSOFTWARE_INSTALL_STATE[120]} == 1 ))
|
|
then
|
|
# Assure that its services are disabled when ours is enabled
|
|
G_EXEC systemctl --no-reload disable vncserver-virtuald vncserver-x11-serviced
|
|
|
|
# Set (+verify) virtual + shared desktop passwords: https://github.com/MichaIng/DietPi/pull/4679#issuecomment-908196511
|
|
if [[ ! -s '/root/.vnc/config.d/Xvnc' ]]
|
|
then
|
|
vncpasswd -virtual <<< "$GLOBAL_PW
|
|
$GLOBAL_PW"
|
|
vncpasswd -service <<< "$GLOBAL_PW
|
|
$GLOBAL_PW"
|
|
fi
|
|
|
|
[[ -f '/root/.vnc/config.d/.Xvnc-v5-marker' ]] || > /root/.vnc/config.d/.Xvnc-v5-marker
|
|
fi
|
|
fi
|
|
|
|
if To_Install 73 fail2ban # Fail2Ban
|
|
then
|
|
# Create jail.conf (backend = systemd) first, to prevent APT failure due to missing /var/log/auth.log: https://github.com/MichaIng/DietPi/issues/475#issuecomment-310873879
|
|
G_EXEC mkdir -p /etc/fail2ban/{fail2ban,filter,jail}.d
|
|
[[ -f '/etc/fail2ban/jail.conf' ]] || cat << '_EOF_' > /etc/fail2ban/jail.conf
|
|
[DEFAULT]
|
|
enabled = true
|
|
ignoreip = 127.0.0.1/8
|
|
ignorecommand =
|
|
backend = systemd
|
|
mode = normal
|
|
filter = %(__name__)s[mode=%(mode)s]
|
|
findtime = 600
|
|
maxretry = 3
|
|
bantime = 600
|
|
banaction = route
|
|
action = %(banaction)s[blocktype=blackhole]
|
|
|
|
[dropbear]
|
|
|
|
[sshd]
|
|
# Mode: normal (default), ddos, extra or aggressive (combines all)
|
|
# See "filter.d/sshd.conf" for details.
|
|
#mode = normal
|
|
_EOF_
|
|
# Log to systemd by default
|
|
G_EXEC eval 'echo -e '\''[Definition]\nlogtarget = SYSOUT'\'' > /etc/fail2ban/fail2ban.d/97_dietpi.conf'
|
|
|
|
# Fix Dropbear filter for STDOUT logging since Bookworm: https://github.com/fail2ban/fail2ban/pull/3597
|
|
[[ -f '/etc/fail2ban/filter.d/dropbear.local' ]] || G_EXEC curl -sSfo /etc/fail2ban/filter.d/dropbear.local 'https://raw.githubusercontent.com/fail2ban/fail2ban/master/config/filter.d/dropbear.conf'
|
|
|
|
# Trixie: Prevent defaults-debian.conf to override our default banaction with nftables
|
|
G_EXEC eval '> /etc/fail2ban/jail.d/defaults-debian.conf'
|
|
|
|
# Trixie: python3-systemd has become hard package dependency
|
|
local deps=()
|
|
(( $G_DISTRO > 7 )) || deps=('python3-systemd')
|
|
G_AGI "${deps[@]}" fail2ban
|
|
Remove_SysV fail2ban 1
|
|
G_EXEC rm /etc/fail2ban/jail.d/defaults-debian.conf
|
|
|
|
# Failsafe
|
|
G_EXEC systemctl unmask fail2ban
|
|
G_EXEC systemctl start fail2ban
|
|
fi
|
|
|
|
if To_Install 74 influxdb # InfluxDB
|
|
then
|
|
# APT key
|
|
local url='https://repos.influxdata.com/influxdata-archive_compat.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-influxdb.gpg --yes"
|
|
|
|
# APT list
|
|
local dist=$G_DISTRO_NAME
|
|
(( $G_DISTRO > 7 )) && dist='bookworm'
|
|
G_EXEC eval "echo 'deb https://repos.influxdata.com/debian $dist stable' > /etc/apt/sources.list.d/dietpi-influxdb.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI influxdb
|
|
G_EXEC systemctl stop influxdb
|
|
|
|
# Link database to userdata location
|
|
if [[ -d '/mnt/dietpi_userdata/influxdb' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Existing database/plugin directory /mnt/dietpi_userdata/influxdb found. Will not overwrite...'
|
|
|
|
elif [[ -d '/var/lib/influxdb' ]]
|
|
then
|
|
G_EXEC mv /var/lib/influxdb /mnt/dietpi_userdata/
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/influxdb
|
|
G_EXEC chown -R influxdb:influxdb /mnt/dietpi_userdata/influxdb
|
|
fi
|
|
G_EXEC rm -Rf /var/lib/influxdb
|
|
G_EXEC ln -s /mnt/dietpi_userdata/influxdb /var/lib/influxdb
|
|
fi
|
|
|
|
if To_Install 77 grafana-server # Grafana: https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/#install-from-apt-repository
|
|
then
|
|
# ARMv6: Since Grafana repo is not compatible, install package from our repo, taken from here: https://grafana.com/grafana/download?platform=arm&edition=oss
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
G_AGI grafana-rpi
|
|
else
|
|
# APT key
|
|
local url='https://apt.grafana.com/gpg.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-grafana.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://apt.grafana.com stable main'\'' > /etc/apt/sources.list.d/grafana.list'
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI grafana
|
|
fi
|
|
G_EXEC systemctl stop grafana-server
|
|
Remove_SysV grafana-server
|
|
|
|
# Link DB/plugins to userdata location
|
|
if [[ -d '/mnt/dietpi_userdata/grafana' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Existing database/plugin directory /mnt/dietpi_userdata/grafana found. Will not overwrite...'
|
|
|
|
elif [[ -d '/var/lib/grafana' ]]
|
|
then
|
|
G_EXEC mv /var/lib/grafana /mnt/dietpi_userdata/
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/grafana
|
|
G_EXEC chown -R grafana:grafana /mnt/dietpi_userdata/grafana
|
|
fi
|
|
G_EXEC rm -Rf /var/lib/grafana
|
|
G_EXEC ln -s /mnt/dietpi_userdata/grafana /var/lib/grafana
|
|
|
|
# Config: Apply our defaults only if nothing was set before
|
|
# - Set password, wrap into tripled double quotes in case of ; or # being contained, according to docs: http://docs.grafana.org/installation/configuration/#password
|
|
GCI_PRESERVE=1 GCI_PASSWORD=1 G_CONFIG_INJECT 'admin_password[[:blank:]]*=' "admin_password = \"\"\"$GLOBAL_PW\"\"\"" /etc/grafana/grafana.ini
|
|
# - Set port to 3001 (away from default 3000) to avoid conflict with Gogs and Gitea
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'http_port[[:blank:]]*=' 'http_port = 3001' /etc/grafana/grafana.ini
|
|
fi
|
|
|
|
if To_Install 64 # phpSysInfo
|
|
then
|
|
# Download
|
|
Download_Install 'https://github.com/phpsysinfo/phpsysinfo/archive/stable.tar.gz'
|
|
|
|
# Clean reinstall, but preserve previous config
|
|
if [[ -d '/var/www/phpsysinfo' ]]
|
|
then
|
|
G_EXEC mv /var/www/phpsysinfo/phpsysinfo.ini phpsysinfo-stable/phpsysinfo.ini
|
|
G_EXEC rm -R /var/www/phpsysinfo
|
|
fi
|
|
G_EXEC mv phpsysinfo-stable /var/www/phpsysinfo
|
|
|
|
[[ -f '/var/www/phpsysinfo/phpsysinfo.ini' ]] || dps_index=$software_id Download_Install 'phpsysinfo.ini' /var/www/phpsysinfo/phpsysinfo.ini
|
|
fi
|
|
|
|
if To_Install 80 ubooquity # Ubooquity
|
|
then
|
|
G_EXEC curl -sSfL 'https://vaemendis.net/ubooquity/service/download.php' -o Ubooquity.zip
|
|
command -v unzip > /dev/null || G_AGI unzip
|
|
G_EXEC unzip -o Ubooquity.zip
|
|
G_EXEC rm Ubooquity.zip
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/ubooquity
|
|
G_EXEC mv {,/mnt/dietpi_userdata/ubooquity/}Ubooquity.jar
|
|
|
|
# User
|
|
Create_User -G dietpi -d /mnt/dietpi_userdata/ubooquity ubooquity
|
|
|
|
# Data
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/{ebooks,comics}
|
|
|
|
# Logs
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/ubooquity/logs
|
|
G_EXEC ln -s /var/log/ubooquity /mnt/dietpi_userdata/ubooquity/logs
|
|
|
|
# Service
|
|
G_DIETPI-NOTIFY 2 "Generating systemd service to start ${aSOFTWARE_NAME[$software_id]} on boot"
|
|
cat << _EOF_ > /etc/systemd/system/ubooquity.service
|
|
[Unit]
|
|
Description=Ubooquity (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Ubooquity
|
|
User=ubooquity
|
|
LogsDirectory=ubooquity
|
|
WorkingDirectory=/mnt/dietpi_userdata/ubooquity
|
|
ExecStart=$JAVA_PATH -mx${JAVA_MAX_HEAP_SIZE}m -jar /mnt/dietpi_userdata/ubooquity/Ubooquity.jar --headless --remoteadmin --adminport 2038 --libraryport 2039
|
|
SuccessExitStatus=143
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/ubooquity/Ubooquity.jar
|
|
G_EXEC chown -R ubooquity /mnt/dietpi_userdata/ubooquity
|
|
G_EXEC chown ubooquity:dietpi /mnt/dietpi_userdata/{ebooks,comics}
|
|
G_EXEC chmod 0775 /mnt/dietpi_userdata/{ebooks,comics}
|
|
fi
|
|
|
|
if To_Install 179 komga # Komga
|
|
then
|
|
local fallback_url='https://github.com/gotson/komga/releases/download/1.23.6/komga-1.23.6.jar'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/gotson/komga/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/komga-[^"\/]*\.jar"$/{print $4}')" /mnt/dietpi_userdata/komga/komga.jar
|
|
|
|
# User
|
|
Create_User -G dietpi -d /mnt/dietpi_userdata/komga komga
|
|
|
|
# Data
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/{ebooks,comics,komga/.komga}
|
|
|
|
# Config
|
|
[[ -f '/mnt/dietpi_userdata/komga/application.yml' ]] || cat << _EOF_ > /mnt/dietpi_userdata/komga/application.yml
|
|
komga:
|
|
libraries-scan-startup: true # Scan libraries at startup
|
|
libraries-scan-cron: "* 2 * * * *" # Scan libraries periodically every hour at :02
|
|
database:
|
|
file: /mnt/dietpi_userdata/komga/database.sqlite
|
|
remember-me:
|
|
key: $(openssl rand -hex 32)
|
|
logging:
|
|
file:
|
|
name: "" # Disable file logging, use: "journalctl -u komga"
|
|
level:
|
|
root: WARN # TRACE DEBUG INFO WARN ERROR
|
|
server:
|
|
port: 2037
|
|
_EOF_
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/komga.service
|
|
[Unit]
|
|
Description=Komga (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Komga
|
|
User=komga
|
|
WorkingDirectory=/mnt/dietpi_userdata/komga
|
|
ExecStart=$JAVA_PATH -mx${JAVA_MAX_HEAP_SIZE}m -jar komga.jar
|
|
SuccessExitStatus=143
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/komga/komga.jar
|
|
G_EXEC chown -R komga /mnt/dietpi_userdata/komga
|
|
G_EXEC chown komga:dietpi /mnt/dietpi_userdata/{ebooks,comics}
|
|
G_EXEC chmod 0775 /mnt/dietpi_userdata/{ebooks,comics}
|
|
fi
|
|
|
|
if To_Install 56 # Single File PHP Gallery
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Obtaining latest download from: https://sye.dk/sfpg/?latest'
|
|
local file=$(curl -sSfL 'https://sye.dk/sfpg/?latest')
|
|
[[ $file ]] || { file='Single_File_PHP_Gallery_4.14.0.zip'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} download detection failed. Downloading the last known \"$file\" is attempted as fallback, but may fail if a newer version is available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
|
|
# Install required PHP modules: https://sye.dk/sfpg/
|
|
aDEPS=("php$PHP_VERSION-gd")
|
|
Download_Install "https://sye.dk/sfpg/$file" /var/www/gallery
|
|
|
|
# Enable required PHP modules
|
|
G_EXEC phpenmod gd
|
|
|
|
# Thumbnails and metadata cache: Remove on reinstalls
|
|
[[ -d '/var/www/gallery/_sfpg_data' ]] && G_EXEC rm -R /var/www/gallery/_sfpg_data
|
|
G_EXEC mkdir /var/www/gallery/_sfpg_data
|
|
G_EXEC chown www-data /var/www/gallery/_sfpg_data
|
|
|
|
# Apply a random security phrase
|
|
local phrase=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT "define\('SECURITY_PHRASE'" "define('SECURITY_PHRASE', '$phrase');" /var/www/gallery/index.php
|
|
unset -v phrase
|
|
|
|
# Create test galleries
|
|
G_EXEC mkdir -p /var/www/gallery/DietPi
|
|
[[ -f '/var/www/gallery/DietPi/logo_256.png' ]] || G_THREAD_START curl -sSf 'https://dietpi.com/images/dietpi-logo_256x256.png' -o /var/www/gallery/DietPi/logo_256.png
|
|
G_EXEC mkdir -p /var/www/gallery/Tr-Zero
|
|
[[ -f '/var/www/gallery/Tr-Zero/SS_0.jpg' ]] || G_THREAD_START curl -sSfL 'https://media.indiedb.com/images/games/1/25/24673/SS_0.jpg' -o /var/www/gallery/Tr-Zero/SS_0.jpg
|
|
[[ -f '/var/www/gallery/Tr-Zero/SS_1.jpg' ]] || G_THREAD_START curl -sSfL 'https://media.indiedb.com/images/games/1/25/24673/SS_44.jpg' -o /var/www/gallery/Tr-Zero/SS_1.jpg
|
|
[[ -f '/var/www/gallery/Tr-Zero/SS_2.jpg' ]] || G_THREAD_START curl -sSfL 'https://media.indiedb.com/images/games/1/25/24673/3.png' -o /var/www/gallery/Tr-Zero/SS_2.jpg
|
|
G_THREAD_WAIT
|
|
fi
|
|
|
|
if To_Install 40 # Ampache
|
|
then
|
|
# Required PHP modules: https://github.com/ampache/ampache/wiki/Installation#prerequisites
|
|
aDEPS=("php$PHP_VERSION-curl" "php$PHP_VERSION-intl" "php$PHP_VERSION-xml")
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
local json=()
|
|
[[ $PHP_VERSION == 8* ]] || aDEPS+=("php$PHP_VERSION-json") json=('json')
|
|
|
|
# Download: Ampache v7 requires PHP 8.2
|
|
if (( $G_DISTRO > 6 ))
|
|
then
|
|
local fallback_url="https://github.com/ampache/ampache/releases/download/7.7.2/ampache-7.7.2_all_php$PHP_VERSION.zip"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/ampache/ampache/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/ampache-[0-9\.]*_all_php$PHP_VERSION.zip\"$/{print \$4}")" ampache
|
|
else
|
|
local fallback_url="https://github.com/ampache/ampache/releases/download/6.6.7/ampache-6.6.7_all_php$PHP_VERSION.zip"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/ampache/ampache/releases' | mawk -F\" "/^ *\"browser_download_url\": \".*\/ampache-[0-9\.]*_all_php$PHP_VERSION.zip\"$/{print \$4}" | head -1)" ampache
|
|
fi
|
|
|
|
# Reinstall: Preserve configs from old and new paths
|
|
[[ -f '/var/www/ampache/config/ampache.cfg.php' ]] && G_EXEC mv /var/www/ampache/config/ampache.cfg.php ampache/config/
|
|
[[ -f '/var/www/ampache/config/registration_agreement.php' ]] && G_EXEC mv /var/www/ampache/config/registration_agreement.php ampache/config/
|
|
[[ -f '/mnt/dietpi_userdata/ampache/config/ampache.cfg.php' ]] && G_EXEC mv /mnt/dietpi_userdata/ampache/config/ampache.cfg.php ampache/config/
|
|
[[ -f '/mnt/dietpi_userdata/ampache/config/registration_agreement.php' ]] && G_EXEC mv /mnt/dietpi_userdata/ampache/config/registration_agreement.php ampache/config/
|
|
[[ -f '/var/www/ampache/channel/.htaccess' ]] && G_EXEC mv /var/www/ampache/channel/.htaccess ampache/public/channel/
|
|
[[ -f '/var/www/ampache/rest/.htaccess' ]] && G_EXEC mv /var/www/ampache/rest/.htaccess ampache/public/rest/
|
|
[[ -f '/var/www/ampache/play/.htaccess' ]] && G_EXEC mv /var/www/ampache/play/.htaccess ampache/public/play/
|
|
[[ -d '/var/www/ampache' || -L '/var/www/ampache' ]] && G_EXEC rm -R /var/www/ampache
|
|
[[ -d '/mnt/dietpi_userdata/ampache' ]] && G_EXEC rm -R /mnt/dietpi_userdata/ampache
|
|
|
|
G_EXEC mv {,/mnt/dietpi_userdata/}ampache
|
|
[[ -d '/mnt/dietpi_userdata/ampache/public' ]] && G_EXEC ln -s /mnt/dietpi_userdata/ampache/public /var/www/ampache
|
|
|
|
Download_Test_Media
|
|
|
|
# Enable required PHP modules: https://github.com/ampache/ampache/wiki/Installation#prerequisites
|
|
G_EXEC phpenmod curl intl xml "${json[@]}"
|
|
|
|
# Create random temporary alphanumeric 30 characters database password
|
|
local password=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
|
|
# Fresh install: Create new config
|
|
if [[ ! -f '/mnt/dietpi_userdata/ampache/config/ampache.cfg.php' ]]
|
|
then
|
|
G_EXEC cp /mnt/dietpi_userdata/ampache/config/ampache.cfg.php{.dist,}
|
|
G_CONFIG_INJECT 'web_path[[:blank:]]+=' 'web_path = "/ampache"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'database_hostname[[:blank:]]+=' 'database_hostname = /run/mysqld/mysqld.sock' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'database_name[[:blank:]]+=' 'database_name = ampache' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'database_username[[:blank:]]+=' 'database_username = ampache' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'database_password[[:blank:]]+=' "database_password = \"$password\"" /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'tmp_dir_path[[:blank:]]+=' 'tmp_dir_path = "/tmp"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_cmd[[:blank:]]+=' 'transcode_cmd = "ffmpeg"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_m4a[[:blank:]]+=' 'transcode_m4a = "required"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_flac[[:blank:]]+=' 'transcode_flac = "required"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_mpc[[:blank:]]+=' 'transcode_mpc = "required"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_ogg[[:blank:]]+=' 'transcode_ogg = "allowed"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_wav[[:blank:]]+=' 'transcode_wav = "required"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_avi[[:blank:]]+=' 'transcode_avi = "allowed"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_mkv[[:blank:]]+=' 'transcode_mkv = "allowed"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'transcode_mpg[[:blank:]]+=' 'transcode_mpg = "allowed"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'encode_target[[:blank:]]+=' 'encode_target = mp3' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'encode_video_target[[:blank:]]+=' 'encode_video_target = webm' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'generate_video_preview[[:blank:]]+=' 'generate_video_preview = "true"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
G_CONFIG_INJECT 'waveform[[:blank:]]+=' 'waveform = "true"' /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
|
|
# Update password as well in rare but possible case that config file still exists but database was lost
|
|
elif [[ ! -d '/mnt/dietpi_userdata/mysql/ampache' ]]
|
|
then
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'database_password[[:blank:]]+=' "database_password = \"$password\"" /mnt/dietpi_userdata/ampache/config/ampache.cfg.php
|
|
fi
|
|
|
|
# Permissions: Permit config file updates via web UI
|
|
G_EXEC chown www-data /mnt/dietpi_userdata/ampache/config/ampache.cfg.php{.dist,}
|
|
|
|
# Fresh install: Generate database
|
|
G_EXEC systemctl start mariadb
|
|
if [[ ! -d '/mnt/dietpi_userdata/mysql/ampache' ]]
|
|
then
|
|
/boot/dietpi/func/create_mysql_db ampache ampache "$password"
|
|
# Import template
|
|
G_EXEC mysql ampache < /mnt/dietpi_userdata/ampache/resources/sql/ampache.sql
|
|
# Generate admin user: Replace password string internally to avoid printing it to console
|
|
G_EXEC_PRE_FUNC(){ acommand[6]=$GLOBAL_PW; }
|
|
G_EXEC php /mnt/dietpi_userdata/ampache/bin/cli admin:addUser -l 100 -p "${GLOBAL_PW//?/X}" dietpi
|
|
# Generate local music catalogue
|
|
G_EXEC_OUTPUT=1 G_EXEC php /mnt/dietpi_userdata/ampache/bin/cli run:addCatalog Music /mnt/dietpi_userdata/Music music
|
|
# Scan for music files
|
|
G_EXEC_OUTPUT=1 G_EXEC php /mnt/dietpi_userdata/ampache/bin/cli run:updateCatalog
|
|
|
|
# Reinstall: Update database
|
|
else
|
|
G_EXEC_OUTPUT=1 G_EXEC php /mnt/dietpi_userdata/ampache/bin/cli admin:updateDatabase
|
|
fi
|
|
unset -v password
|
|
fi
|
|
|
|
if To_Install 58 tailscaled # Tailscale
|
|
then
|
|
# APT key
|
|
G_EXEC curl -sSfL "https://pkgs.tailscale.com/stable/debian/$G_DISTRO_NAME.noarmor.gpg" -o /etc/apt/trusted.gpg.d/dietpi-tailscale.gpg
|
|
|
|
# APT list
|
|
G_EXEC eval "echo 'deb https://pkgs.tailscale.com/stable/debian $G_DISTRO_NAME main' > /etc/apt/sources.list.d/dietpi-tailscale.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI tailscale
|
|
|
|
Enable_IP_forwarding tailscale
|
|
fi
|
|
|
|
if To_Install 97 # OpenVPN Server
|
|
then
|
|
G_AGI openvpn iptables
|
|
Remove_SysV openvpn
|
|
Configure_iptables
|
|
aSTART_SERVICES+=('openvpn')
|
|
|
|
# Create initial server and client configs if not yet present
|
|
# - Wildcard config file detection via for loop
|
|
local i
|
|
for i in /etc/openvpn/*.conf
|
|
do
|
|
|
|
# Inform user if config exist, that config generation is skipped
|
|
if [[ -f $i ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "Existing OpenVPN configuration found: $i
|
|
- Config generation will be skipped.
|
|
- If you need a fresh key/cert/config set, please remove $i
|
|
and run: dietpi-software reinstall 97"
|
|
break
|
|
fi
|
|
|
|
# Pre-v6.26 cleanup
|
|
[[ -f '/etc/openvpn/dh2048.pem' ]] && G_EXEC rm /etc/openvpn/dh2048.pem
|
|
dpkg-query -s easy-rsa &> /dev/null && G_AGP easy-rsa
|
|
|
|
# Download latest easy-rsa from GitHub
|
|
G_DIETPI-NOTIFY 2 'Downloading latest easy-rsa for certificate and key generation...'
|
|
local fallback_url='https://github.com/OpenVPN/easy-rsa/releases/download/v3.1.0/EasyRSA-3.1.0.tgz'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/OpenVPN/easy-rsa/releases/latest' | mawk -F\" '/"browser_download_url": .*\/EasyRSA-[^"\/]*\.tgz"/{print $4}')"
|
|
[[ -d '/etc/openvpn/easy-rsa' ]] && G_EXEC rm -R /etc/openvpn/easy-rsa
|
|
G_EXEC mv EasyRSA-* /etc/openvpn/easy-rsa
|
|
|
|
# Cert and key generation via easy-rsa
|
|
G_DIETPI-NOTIFY 2 'Generating unique OpenVPN certificates and keys. Please wait...\n'
|
|
G_EXEC cd /etc/openvpn/easy-rsa
|
|
cat << '_EOF_' > vars
|
|
set_var EASYRSA_REQ_COUNTRY "UK"
|
|
set_var EASYRSA_REQ_PROVINCE "DietPi"
|
|
set_var EASYRSA_REQ_CITY "DietPi"
|
|
set_var EASYRSA_REQ_ORG "DietPi"
|
|
set_var EASYRSA_REQ_EMAIL "noreply@dietpi.com"
|
|
set_var EASYRSA_REQ_OU "DietPi"
|
|
set_var EASYRSA_BATCH "1"
|
|
_EOF_
|
|
./easyrsa init-pki
|
|
./easyrsa build-ca nopass
|
|
./easyrsa gen-dh
|
|
./easyrsa build-server-full DietPi_OpenVPN_Server nopass
|
|
./easyrsa build-client-full DietPi_OpenVPN_Client nopass
|
|
|
|
# Server config
|
|
cp -a pki/{ca.crt,dh.pem,issued/DietPi_OpenVPN_Server.crt,private/DietPi_OpenVPN_Server.key} /etc/openvpn/
|
|
G_EXEC cd /etc/openvpn
|
|
cat << '_EOF_' > server.conf
|
|
port 1194
|
|
proto udp
|
|
dev tun
|
|
|
|
ca ca.crt
|
|
cert DietPi_OpenVPN_Server.crt
|
|
key DietPi_OpenVPN_Server.key
|
|
dh dh.pem
|
|
|
|
server 10.8.0.0 255.255.255.0
|
|
|
|
client-to-client
|
|
keepalive 10 60
|
|
comp-lzo
|
|
max-clients 10
|
|
|
|
user nobody
|
|
group nogroup
|
|
|
|
persist-key
|
|
persist-tun
|
|
verb 3
|
|
|
|
# Web Forwarding (uncomment to enable)
|
|
#push "redirect-gateway"
|
|
#push "dhcp-option DNS 10.8.0.1"
|
|
_EOF_
|
|
# Client config
|
|
cat << '_EOF_' > DietPi_OpenVPN_Client.ovpn
|
|
client
|
|
proto udp
|
|
dev tun
|
|
|
|
# IP/domain name of DietPi system, running OpenVPN server
|
|
remote mywebsite.com 1194
|
|
|
|
resolv-retry infinite
|
|
nobind
|
|
|
|
user nobody
|
|
group nogroup
|
|
|
|
persist-key
|
|
persist-tun
|
|
|
|
remote-cert-tls server
|
|
comp-lzo
|
|
verb 3
|
|
_EOF_
|
|
# - Add CA cert, client cert and key
|
|
echo -e "
|
|
<ca>\n$(<ca.crt)\n</ca>
|
|
<cert>\n$(<easy-rsa/pki/issued/DietPi_OpenVPN_Client.crt)\n</cert>
|
|
<key>\n$(<easy-rsa/pki/private/DietPi_OpenVPN_Client.key)\n</key>" >> DietPi_OpenVPN_Client.ovpn
|
|
|
|
# - Copy to userdata
|
|
G_EXEC cp DietPi_OpenVPN_Client.ovpn /mnt/dietpi_userdata/
|
|
# - and /boot partition
|
|
G_EXEC cp DietPi_OpenVPN_Client.ovpn /boot/
|
|
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
break # Always break loop which is only for single wildcard file detection
|
|
|
|
done
|
|
|
|
Enable_IP_forwarding openvpn
|
|
|
|
# ToDo: iptables NAT rules: Those need to run via pre-up and post-down rules when the OpenSSH server starts
|
|
#iptables -A FORWARD -i tun0 -j ACCEPT
|
|
#iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o "$(G_GET_NET iface)" -j MASQUERADE
|
|
#ip6tables -A FORWARD -i tun0 -j ACCEPT
|
|
#ip6tables -t nat -A POSTROUTING -o "$(G_GET_NET iface)" -j MASQUERADE
|
|
fi
|
|
|
|
if To_Install 117 # PiVPN
|
|
then
|
|
G_EXEC curl -sSfL 'https://raw.githubusercontent.com/pivpn/pivpn/master/auto_install/install.sh' -o install.bash
|
|
G_EXEC chmod +x install.bash
|
|
G_DIETPI-NOTIFY 2 'Preventing reboot from within PiVPN installer'
|
|
G_EXEC sed --follow-symlinks -i '/^Thank you for using PiVPN./a\exit 0' install.bash
|
|
G_DIETPI-NOTIFY 2 'Preventing install of unattended-upgrades'
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*askUnattendedUpgrades$/c\UNATTUPG=0' install.bash
|
|
G_DIETPI-NOTIFY 2 'Prevent dhcpcd from being installed'
|
|
G_EXEC sed --follow-symlinks -i '/^checkStaticIpSupported() {$/a\return 1' install.bash
|
|
|
|
# Unattended install
|
|
local options=()
|
|
if [[ -f '/boot/unattended_pivpn.conf' ]]
|
|
then
|
|
G_CONFIG_INJECT 'UNATTUPG=[[:digit:]]' 'UNATTUPG=0' /boot/unattended_pivpn.conf
|
|
options=('--unattended' '/boot/unattended_pivpn.conf')
|
|
fi
|
|
|
|
# APT deps
|
|
G_AGI bind9-dnsutils grepcidr net-tools bsdmainutils iptables-persistent # https://github.com/pivpn/pivpn/blob/master/auto_install/install.sh#L39
|
|
Configure_iptables
|
|
|
|
G_EXEC_OUTPUT=1 G_EXEC_NOEXIT=1 G_EXEC ./install.bash "${options[@]}" || aSOFTWARE_INSTALL_STATE[$software_id]=0
|
|
G_EXEC rm install.bash
|
|
[[ -f '/boot/unattended_pivpn.conf' ]] && G_EXEC mv /boot/unattended_pivpn.conf{,.applied}
|
|
fi
|
|
|
|
if To_Install 201 zerotier-one # ZeroTier
|
|
then
|
|
# APT key: Download from GitHub instead of https://download.zerotier.com/contact%40zerotier.com.gpg for enhanced protection against corrupted download server
|
|
local url='https://raw.githubusercontent.com/zerotier/ZeroTierOne/master/doc/contact%40zerotier.com.gpg'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-zerotier.gpg --yes"
|
|
|
|
# APT list
|
|
local dist=${G_DISTRO_NAME/forky/trixie}
|
|
G_EXEC eval "echo 'deb https://download.zerotier.com/debian/$dist $dist main' > /etc/apt/sources.list.d/dietpi-zerotier.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI zerotier-one
|
|
|
|
Remove_SysV zerotier-one
|
|
|
|
# Wait for and print ZeroTier address
|
|
CC_STOP=0 Create_Config '/var/lib/zerotier-one/identity.secret' 'zerotier-one' && G_DIETPI-NOTIFY 0 "Your ZeroTier address is: $(mawk -F: '{print $1}' /var/lib/zerotier-one/identity.public)"
|
|
fi
|
|
|
|
if To_Install 92 # Certbot
|
|
then
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
G_AGI certbot python3-certbot-apache
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
G_AGI certbot python3-certbot-nginx
|
|
else
|
|
G_AGI certbot
|
|
fi
|
|
fi
|
|
|
|
if To_Install 60 # WiFi Hotspot
|
|
then
|
|
local packages=('hostapd' 'isc-dhcp-server' 'iptables')
|
|
|
|
G_AGI "${packages[@]}"
|
|
G_EXEC systemctl stop hostapd isc-dhcp-server
|
|
aSTART_SERVICES+=('hostapd' 'isc-dhcp-server')
|
|
Configure_iptables
|
|
|
|
# Unmask hostapd since it is masked via postinst when no config exists yet
|
|
G_EXEC systemctl --no-reload unmask hostapd
|
|
|
|
# Enable WiFi modules
|
|
/boot/dietpi/func/dietpi-set_hardware wifimodules enable
|
|
|
|
local eth_iface=$(G_GET_NET -t eth iface)
|
|
local wifi_iface=$(G_GET_NET -t wlan iface)
|
|
|
|
# DHCP server config
|
|
G_BACKUP_FP /etc/dhcp/dhcpd.conf
|
|
cat << '_EOF_' > /etc/dhcp/dhcpd.conf
|
|
authoritative;
|
|
#default-lease-time 43200;
|
|
#max-lease-time 86400;
|
|
|
|
subnet 192.168.42.0 netmask 255.255.255.0 {
|
|
range 192.168.42.10 192.168.42.250;
|
|
option broadcast-address 192.168.42.255;
|
|
option routers 192.168.42.1;
|
|
option domain-name "local";
|
|
option domain-name-servers 9.9.9.9, 149.112.112.112;
|
|
}
|
|
_EOF_
|
|
# Assign detected WLAN interface
|
|
G_EXEC eval "echo 'INTERFACESv4=\"$wifi_iface\"' > /etc/default/isc-dhcp-server"
|
|
|
|
# Remove all entries below wlan, so we can recreate them
|
|
G_EXEC sed --follow-symlinks -Ei '/(allow-hotplug|auto)[[:blank:]]+wlan/q0' /etc/network/interfaces
|
|
|
|
# Enable up wlan
|
|
G_CONFIG_INJECT 'allow-hotplug wlan' "allow-hotplug $wifi_iface" /etc/network/interfaces
|
|
|
|
# Add WiFi settings to network interfaces config
|
|
cat << _EOF_ >> /etc/network/interfaces
|
|
iface $wifi_iface inet static
|
|
address 192.168.42.1
|
|
netmask 255.255.255.0
|
|
#gateway 192.168.0.1
|
|
#dns-nameservers 9.9.9.9 149.112.112.112
|
|
pre-up iw dev $wifi_iface set power_save off
|
|
post-down iw dev $wifi_iface set power_save on
|
|
|
|
# iptables NAT rules
|
|
up iptables-restore < /etc/iptables.ipv4.nat
|
|
up ip6tables-restore < /etc/iptables.ipv6.nat
|
|
_EOF_
|
|
# Remove wireless-power setting if not supported by adapter/firmware
|
|
# shellcheck disable=SC2015
|
|
iw dev "$wifi_iface" set power_save on 2> /dev/null && iw dev "$wifi_iface" set power_save off 2> /dev/null || G_EXEC sed --follow-symlinks -i '/ iw dev .* set power_save /d' /etc/network/interfaces
|
|
|
|
# Access point config
|
|
# - Parse dietpi.txt
|
|
local ssid=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_SSID=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local key=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_KEY=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local wifi4=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_WIFI4=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local wifi5=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_WIFI5=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local wifi6=0
|
|
(( $G_DISTRO > 6 )) && wifi6=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_WIFI6=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local freq5=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_5G=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
# - Sanity checks
|
|
[[ $wifi4 == [01] ]] || wifi4=0
|
|
[[ $wifi5 == [01] ]] || wifi5=0
|
|
[[ $wifi6 == [01] ]] || wifi6=0
|
|
[[ $freq5 == [01] ]] || freq5=0
|
|
(( ${#key} > 8 )) || { G_DIETPI-NOTIFY 1 'WiFi key from dietpi.txt is too short (less than 8 characters), falling back to default: "dietpihotspot"'; key='dietpihotspot'; }
|
|
# - WiFi 5 implies 5 GHz and 5 GHz requires at least WiFi 4
|
|
(( $wifi5 )) && freq5=1
|
|
(( $freq5 && ! $wifi5 && ! $wifi6 )) && wifi4=1
|
|
# - Enable WMM with QoS if WiFi 4 or 5 is enabled
|
|
local wmm_enabled=0
|
|
(( $wifi4 || $wifi5 || $wifi6 )) && wmm_enabled=1
|
|
# - Apply mode channel based on frequency
|
|
local mode='g'
|
|
if (( $freq5 ))
|
|
then
|
|
mode='a'
|
|
local channel=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_5G_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
disable_error=1 G_CHECK_VALIDINT "$channel" 32 177 || channel=36
|
|
else
|
|
local channel=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
disable_error=1 G_CHECK_VALIDINT "$channel" 1 13 || channel=3
|
|
fi
|
|
# - Create config
|
|
G_BACKUP_FP /etc/hostapd/hostapd.conf
|
|
cat << _EOF_ > /etc/hostapd/hostapd.conf
|
|
interface=$wifi_iface
|
|
driver=nl80211
|
|
ssid=${ssid:-DietPi-Hotspot}
|
|
country_code=00
|
|
hw_mode=$mode
|
|
channel=$channel
|
|
ieee80211n=$wifi4
|
|
ieee80211ac=$wifi5
|
|
wmm_enabled=$wmm_enabled
|
|
macaddr_acl=0
|
|
auth_algs=1
|
|
ignore_broadcast_ssid=0
|
|
wpa=2
|
|
wpa_passphrase=$key
|
|
wpa_key_mgmt=WPA-PSK
|
|
wpa_pairwise=TKIP
|
|
rsn_pairwise=CCMP
|
|
_EOF_
|
|
(( $G_DISTRO > 6 )) && G_CONFIG_INJECT 'ieee80211ax=' "ieee80211ax=$wifi6" /etc/hostapd/hostapd.conf '^ieee80211ac'
|
|
G_EXEC chmod 0600 /etc/hostapd/hostapd.conf
|
|
|
|
# Set WiFi country code
|
|
/boot/dietpi/func/dietpi-set_hardware wificountrycode
|
|
|
|
# Enable access point config
|
|
G_EXEC eval 'echo '\''DAEMON_CONF="/etc/hostapd/hostapd.conf"'\'' > /etc/default/hostapd'
|
|
|
|
Enable_IP_forwarding wifihotspot
|
|
|
|
# Enable iptables NAT rules
|
|
iptables -t nat -A POSTROUTING -s 192.168.42.0/24 -o "$eth_iface" -j MASQUERADE
|
|
iptables -A FORWARD -i "$eth_iface" -o "$wifi_iface" -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
iptables -A FORWARD -i "$wifi_iface" -o "$eth_iface" -j ACCEPT
|
|
ip6tables -t nat -A POSTROUTING -o "$eth_iface" -j MASQUERADE
|
|
ip6tables -A FORWARD -i "$eth_iface" -o "$wifi_iface" -m state --state RELATED,ESTABLISHED -j ACCEPT
|
|
ip6tables -A FORWARD -i "$wifi_iface" -o "$eth_iface" -j ACCEPT
|
|
|
|
# Save iptables rules, applied via /etc/network/interfaces
|
|
iptables-save > /etc/iptables.ipv4.nat
|
|
ip6tables-save > /etc/iptables.ipv6.nat
|
|
|
|
# Bring up interface now
|
|
G_EXEC_NOHALT=1 G_EXEC ifup "$wifi_iface"
|
|
fi
|
|
|
|
if To_Install 61 tor # Tor Hotspot
|
|
then
|
|
G_AGI tor
|
|
G_EXEC systemctl stop tor
|
|
|
|
Remove_SysV tor 1
|
|
|
|
# Tor config
|
|
cat << '_EOF_' > /etc/tor/torrc
|
|
Log notice stdout
|
|
VirtualAddrNetwork 10.192.0.0/10
|
|
AutomapHostsSuffixes .onion,.exit
|
|
AutomapHostsOnResolve 1
|
|
TransPort 192.168.42.1:9040
|
|
DNSPort 192.168.42.1:53
|
|
_EOF_
|
|
# Flush iptables
|
|
iptables -F
|
|
iptables -t nat -F
|
|
ip6tables -F
|
|
ip6tables -t nat -F
|
|
|
|
# Generate Tor prerouting tables
|
|
local wifi_iface=$(G_GET_NET -t wlan iface)
|
|
iptables -t nat -A PREROUTING -i "$wifi_iface" -p tcp --dport 22 -j REDIRECT --to-ports 22
|
|
iptables -t nat -A PREROUTING -i "$wifi_iface" -p udp --dport 53 -j REDIRECT --to-ports 53
|
|
iptables -t nat -A PREROUTING -i "$wifi_iface" -p tcp --syn -j REDIRECT --to-ports 9040
|
|
ip6tables -t nat -A PREROUTING -i "$wifi_iface" -p tcp --dport 22 -j REDIRECT --to-ports 22
|
|
ip6tables -t nat -A PREROUTING -i "$wifi_iface" -p udp --dport 53 -j REDIRECT --to-ports 53
|
|
ip6tables -t nat -A PREROUTING -i "$wifi_iface" -p tcp --syn -j REDIRECT --to-ports 9040
|
|
|
|
# Save iptables rules, applied via /etc/network/interfaces
|
|
iptables-save > /etc/iptables.ipv4.nat
|
|
ip6tables-save > /etc/iptables.ipv6.nat
|
|
|
|
# User: Test tor is functional
|
|
#https://check.torproject.org
|
|
fi
|
|
|
|
if To_Install 189 # VSCodium
|
|
then
|
|
# APT key
|
|
local url='https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/raw/master/pub.gpg'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-vscodium.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://download.vscodium.com/debs vscodium main'\'' > /etc/apt/sources.list.d/dietpi-vscodium.list'
|
|
G_AGUP
|
|
|
|
# APT package
|
|
# - gnome-keyring is the backend daemon for the Secrets API used to store credentials, required e.g. for the GitHub PR and issues extension.
|
|
G_AGI codium gnome-keyring
|
|
|
|
# Desktop shortcut
|
|
Create_Desktop_Shortcut codium
|
|
fi
|
|
|
|
if To_Install 37 shairport-sync # Shairport Sync
|
|
then
|
|
# AirPlay 1 vs AirPlay 2 selection
|
|
local airplay2=$(sed -n '/^[[:blank:]]*SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $airplay2 == 2 ]] && G_WHIP_DEFAULT_ITEM='ok'
|
|
if G_WHIP_BUTTON_OK_TEXT='AirPlay 2' G_WHIP_BUTTON_CANCEL_TEXT='AirPlay 1' G_WHIP_YESNO '[OPTION] AirPlay 2 support
|
|
\nSince Shairport Sync v4.1, an experimental AirPlay 2 build is available:\n- https://github.com/mikebrady/shairport-sync/blob/master/AIRPLAY2.md
|
|
\nIt causes higher CPU load, about 150 MiB additional disk space with dependencies, the NQPTP (Not Quite PTP) companion service, and not all source systems are supported (check out the above URL).
|
|
\nYou can switch between AirPlay 1 and AirPlay 2 build any time later via reinstall:\n- dietpi-software reinstall 37
|
|
\nDo you want to install the AirPlay 2 ready Shairport Sync build?'
|
|
then
|
|
G_CONFIG_INJECT 'SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=' 'SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=2' /boot/dietpi.txt
|
|
airplay2='-airplay2'
|
|
else
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=/c\#SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=2' /boot/dietpi.txt
|
|
airplay2=
|
|
fi
|
|
|
|
G_AGI "shairport-sync$airplay2"
|
|
fi
|
|
|
|
if To_Install 48 # Pydio
|
|
then
|
|
# Install required PHP modules
|
|
aDEPS=("php$PHP_VERSION-apcu" "php$PHP_VERSION-gd" "php$PHP_VERSION-intl" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-opcache" "php$PHP_VERSION-xml")
|
|
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d '/var/www/pydio' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/var/www/pydio\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually backup your config files+data, remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
else
|
|
Download_Install 'https://download.pydio.com/pub/core/ci/pydio-latest.tar.gz'
|
|
G_EXEC mv pydio-latest /var/www/pydio
|
|
fi
|
|
|
|
# PHP configuration
|
|
G_EXEC phpenmod apcu gd intl pdo_mysql dom mbstring xml
|
|
|
|
# Webserver config
|
|
# - Apache
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
# Enable Apache rewrite engine
|
|
a2enmod rewrite
|
|
|
|
# Move Pydio Apache config in place
|
|
dps_index=$software_id Download_Install 'apache.pydio.conf' /etc/apache2/sites-available/dietpi-pydio.conf
|
|
a2ensite dietpi-pydio
|
|
|
|
# - Lighttpd
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
# Enable Lighttpd setenv, access and rewrite modules
|
|
G_CONFIG_INJECT '"mod_access",' ' "mod_access",' /etc/lighttpd/lighttpd.conf '"mod_.+",'
|
|
[[ -f '/etc/lighttpd/conf-enabled/05-setenv.conf' ]] || G_EXEC lighty-enable-mod setenv
|
|
|
|
# Move Pydio Lighttpd config in place
|
|
dps_index=$software_id Download_Install 'lighttpd.pydio.conf' /etc/lighttpd/conf-available/99-dietpi-pydio.conf
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod rewrite dietpi-pydio
|
|
|
|
# - Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
# Move Pydio Nginx config in place
|
|
dps_index=$software_id Download_Install 'nginx.pydio.conf' /etc/nginx/sites-dietpi/dietpi-pydio.conf
|
|
fi
|
|
|
|
# Database
|
|
/boot/dietpi/func/create_mysql_db pydio pydio "$GLOBAL_PW"
|
|
|
|
# Setup data directory
|
|
local data_dir='/mnt/dietpi_userdata/pydio_data'
|
|
# - Skip if already existent
|
|
if [[ -d $data_dir ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "Existing $data_dir found, will migrate..."
|
|
[[ -e '/var/www/pydio/data' ]] && G_EXEC rm -R /var/www/pydio/data
|
|
else
|
|
# Move data structure
|
|
[[ -e $data_dir || -L $data_dir ]] && G_EXEC rm -R "$data_dir"
|
|
if [[ -d '/var/www/pydio/data' ]]
|
|
then
|
|
G_EXEC mv /var/www/pydio/data "$data_dir"
|
|
else
|
|
G_EXEC mkdir "$data_dir"
|
|
fi
|
|
fi
|
|
# - Create symlink
|
|
G_EXEC ln -sf "$data_dir" /var/www/pydio/data
|
|
|
|
# Permissions: Fix some files being 444 mode, breaking internal updater
|
|
G_EXEC chown -R www-data:www-data /var/www/pydio "$data_dir"
|
|
G_EXEC chmod -R u+w /var/www/pydio
|
|
fi
|
|
|
|
if To_Install 36 squeezelite # Squeezelite
|
|
then
|
|
G_AGI squeezelite
|
|
G_EXEC systemctl stop squeezelite
|
|
fi
|
|
|
|
if To_Install 66 rpimonitor # RPi-Monitor
|
|
then
|
|
Download_Install 'https://raw.githubusercontent.com/XavierBerger/RPi-Monitor-deb/develop/packages/rpimonitor_2.13-beta6_all.deb'
|
|
G_EXEC systemctl stop rpimonitor
|
|
|
|
# Update APT package status
|
|
G_EXEC /usr/share/rpimonitor/scripts/updatePackagesStatus.pl
|
|
|
|
# Fix issue to display CPU temperature correctly: https://github.com/XavierBerger/RPi-Monitor/issues/374
|
|
# shellcheck disable=SC2016
|
|
G_CONFIG_INJECT 'dynamic.1.postprocess=' 'dynamic.1.postprocess=int($1/10 + 0.5)/100' /etc/rpimonitor/template/temperature.conf
|
|
|
|
# USB drive stats implementation by Rich
|
|
if [[ $G_ROOTFS_DEV != '/dev/sda1' && ! -f '/etc/rpimonitor/template/usb_hdd.conf' ]] && findmnt -S /dev/sda1 > /dev/null
|
|
then
|
|
cat << '_EOF_' > /etc/rpimonitor/template/usb_hdd.conf
|
|
########################################################################
|
|
# Extract USB HDD (sda1) information
|
|
# Page: 1
|
|
# Information Status Statistics
|
|
# - USBHDD1 total - yes - yes
|
|
# - USBHDD1 used - yes - yes
|
|
########################################################################
|
|
static.10.name=usbhdd_total
|
|
static.10.source=df -m
|
|
static.10.regexp=^/dev/sda1\s+(\d+)
|
|
|
|
dynamic.14.name=usbhdd_used
|
|
dynamic.14.source=df -m
|
|
dynamic.14.regexp=^/dev/sda1\s+\d+\s+(\d+)
|
|
dynamic.14.rrd=GAUGE
|
|
|
|
web.status.1.content.9.name=USB HDD
|
|
web.status.1.content.9.icon=usb_hdd.png
|
|
web.status.1.content.9.line.1="<b>/sda1</b> Used: <b>"+KMG(data.usbhdd_used,'M')+"</b> (<b>"+Percent(data.usbhdd_used,data.usbhdd_total,'M')+"</b>) Free: <b>"+KMG(data.usbhdd_total-data.usbhdd_used,'M')+ "</b> Total: <b>"+ KMG(data.usbhdd_total,'M') +"</b>"
|
|
web.status.1.content.9.line.2=ProgressBar(data.usbhdd_used,data.usbhdd_total)
|
|
|
|
web.statistics.1.content.9.name=USB HDD
|
|
web.statistics.1.content.9.graph.1=usbhdd_total
|
|
web.statistics.1.content.9.graph.2=usbhdd_used
|
|
web.statistics.1.content.9.ds_graph_options.usbhdd_total.label=USB HDD total space (MiB)
|
|
web.statistics.1.content.9.ds_graph_options.usbhdd_total.color="#FF7777"
|
|
web.statistics.1.content.9.ds_graph_options.usbhdd_used.label=USB HDD used space (MiB)
|
|
web.statistics.1.content.9.ds_graph_options.usbhdd_used.lines={ fill: true }
|
|
web.statistics.1.content.9.ds_graph_options.usbhdd_used.color="#7777FF"
|
|
_EOF_
|
|
G_EXEC sed --follow-symlinks -i '\|include=/etc/rpimonitor/template/sdcard.conf|a\include=/etc/rpimonitor/template/usb_hdd.conf' /etc/rpimonitor/data.conf
|
|
fi
|
|
fi
|
|
|
|
if To_Install 65 netdata # Netdata
|
|
then
|
|
G_AGI netdata
|
|
G_EXEC systemctl stop netdata
|
|
fi
|
|
|
|
if To_Install 57 # Baïkal
|
|
then
|
|
# APT deps: https://github.com/sabre-io/Baikal/wiki/Baïkal-dependencies
|
|
aDEPS=("php$PHP_VERSION-xml" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-mysql")
|
|
|
|
# Bullseye: v0.10 dropped support for PHP 7.4: https://github.com/MichaIng/DietPi/issues/7387
|
|
if (( $G_DISTRO < 7 ))
|
|
then
|
|
Download_Install 'https://github.com/sabre-io/Baikal/releases/download/0.9.5/baikal-0.9.5.zip'
|
|
else
|
|
local fallback_url='https://github.com/sabre-io/Baikal/releases/download/0.11.1/baikal-0.11.1.zip'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/sabre-io/Baikal/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/baikal-[^"\/]*\.zip"$/{print $4}')"
|
|
fi
|
|
|
|
# Reinstall: https://sabre.io/baikal/upgrade/
|
|
if [[ -d '/var/www/baikal' ]]
|
|
then
|
|
[[ -d '/var/www/baikal/Specific' ]] && G_EXEC cp -a /var/www/baikal/Specific/. baikal/Specific/
|
|
[[ -d '/var/www/baikal/config' ]] && G_EXEC cp -a /var/www/baikal/config/. baikal/config/
|
|
G_EXEC rm -R /var/www/baikal
|
|
fi
|
|
G_EXEC mv baikal /var/www/baikal
|
|
|
|
# Enable required PHP modules: https://github.com/sabre-io/Baikal/wiki/Baïkal-dependencies
|
|
G_EXEC phpenmod xml mbstring pdo_mysql
|
|
|
|
# Database
|
|
/boot/dietpi/func/create_mysql_db baikal baikal "$GLOBAL_PW"
|
|
|
|
# Web server configs: http://sabre.io/baikal/install/ + https://github.com/bambocher/docker-baikal/blob/master/lighttpd.conf
|
|
# - Apache
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'apache.baikal.conf' /etc/apache2/sites-available/dietpi-baikal.conf
|
|
a2ensite dietpi-baikal
|
|
echo '# Redirect Cal/CardDAV requests to Baïkal endpoint:
|
|
Redirect 301 /.well-known/carddav /baikal/html/dav.php
|
|
Redirect 301 /.well-known/caldav /baikal/html/dav.php' > /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
a2enconf dietpi-dav_redirect
|
|
|
|
# - Lighttpd
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'lighttpd.baikal.conf' /etc/lighttpd/conf-available/99-dietpi-baikal.conf
|
|
echo '# Redirect Cal/CardDAV requests to Baïkal endpoint:
|
|
url.redirect += (
|
|
"^/.well-known/caldav" => "/baikal/html/dav.php",
|
|
"^/.well-known/carddav" => "/baikal/html/dav.php"
|
|
)' > /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod dietpi-baikal dietpi-dav_redirect
|
|
|
|
# - Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
dps_index=$software_id Download_Install 'nginx.baikal.conf' /etc/nginx/sites-dietpi/dietpi-baikal.conf
|
|
# shellcheck disable=SC2016
|
|
echo '# Redirect Cal/CardDAV requests to Baïkal endpoint:
|
|
location = /.well-known/carddav { return 301 /baikal/html/dav.php; }
|
|
location = /.well-known/caldav { return 301 /baikal/html/dav.php; }' > /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R www-data:root /var/www/baikal/{Specific,config}
|
|
G_EXEC find /var/www/baikal/{Specific,config} \( -name '.ht*' -o -name '.git*' \) -exec chown root {} +
|
|
fi
|
|
|
|
if To_Install 43 mumble-server # Mumble Server
|
|
then
|
|
G_AGI mumble-server
|
|
G_EXEC systemctl stop mumble-server
|
|
|
|
# Trixie: config moved to sub dir and murmurd was renamed to mumble-server
|
|
local conf='/etc/mumble-server.ini' cli='murmurd'
|
|
(( $G_DISTRO > 7 )) && conf='/etc/mumble/mumble-server.ini' cli='mumble-server'
|
|
|
|
# Cap total connections
|
|
G_CONFIG_INJECT 'users=' "users=$(( $G_HW_CPU_CORES * 8 ))" "$conf"
|
|
|
|
# Name the root channel
|
|
G_CONFIG_INJECT 'registerName=' 'registerName=DietPi Mumble Server' "$conf"
|
|
|
|
# Disable DB logging
|
|
G_CONFIG_INJECT 'logdays=' 'logdays=-1' "$conf"
|
|
|
|
# Set Superuser passwd: https://dietpi.com/forum/t/1371
|
|
"$cli" -ini "$conf" -supw "$GLOBAL_PW"
|
|
fi
|
|
|
|
if To_Install 41 emby-server # Emby
|
|
then
|
|
case $G_HW_ARCH in
|
|
2) local arch='armhf';;
|
|
3) local arch='arm64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/MediaBrowser/Emby.Releases/releases/download/4.9.1.90/emby-server-deb_4.9.1.90_$arch.deb"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/MediaBrowser/Emby.Releases/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/emby-server-deb_[^\"\/]*_$arch\.deb\"$/{print \$4}")"
|
|
G_EXEC systemctl stop emby-server
|
|
|
|
# User: The DEB package install overrides this, hence the method needs to be changed when using an APT repository!
|
|
Create_User -g dietpi -G emby,video,render -d /var/lib/emby emby
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 42 plexmediaserver # Plex Media Server
|
|
then
|
|
# APT key
|
|
local url='https://downloads.plex.tv/plex-keys/PlexSign.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-plexmediaserver.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://downloads.plex.tv/repo/deb public main'\'' > /etc/apt/sources.list.d/plexmediaserver.list'
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI plexmediaserver
|
|
G_EXEC systemctl stop plexmediaserver
|
|
|
|
# User: Run service as "dietpi" group: https://github.com/MichaIng/DietPi/issues/350#issuecomment-423763518
|
|
Create_User -g dietpi -G plex,video,render -d /var/lib/plexmediaserver plex
|
|
# - Unset explicit group in service file (applied by DEB package) as this may override supplementary group permissions
|
|
G_EXEC mkdir -p /etc/systemd/system/plexmediaserver.service.d
|
|
G_EXEC eval 'echo -e '\''[Service]\nGroup='\'' > /etc/systemd/system/plexmediaserver.service.d/dietpi-group.conf'
|
|
|
|
# Unbound: Fix secure remote access: https://dietpi.com/forum/t/cant-connect-to-plex-directly-due-to-unbound/5199
|
|
(( ${aSOFTWARE_INSTALL_STATE[182]} == 2 )) && G_EXEC eval 'echo -e '\''server:\n\tprivate-domain: "plex.direct"'\'' > /etc/unbound/unbound.conf.d/dietpi-plex.conf'
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 52 cuberite # Cuberite
|
|
then
|
|
# https://github.com/cuberite/cuberite/blob/master/easyinstall.sh
|
|
case $G_HW_ARCH in
|
|
3) local arch='aarch64';;
|
|
10) local arch='x86_64';;
|
|
*) local arch='armhf-raspbian';;
|
|
esac
|
|
|
|
Download_Install "https://download.cuberite.org/linux-$arch/Cuberite.tar.gz" /mnt/dietpi_userdata/cuberite
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/cuberite cuberite
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/cuberite.service
|
|
[Unit]
|
|
Description=Cuberite (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=cuberite
|
|
WorkingDirectory=/mnt/dietpi_userdata/cuberite
|
|
ExecStart=/mnt/dietpi_userdata/cuberite/Cuberite --detached
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Web UI settings: Do not overwrite existing!
|
|
[[ -f '/mnt/dietpi_userdata/cuberite/webadmin.ini' ]] || > /mnt/dietpi_userdata/cuberite/webadmin.ini
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/cuberite/webadmin.ini
|
|
[[ -s '/mnt/dietpi_userdata/cuberite/webadmin.ini' ]] || cat << _EOF_ > /mnt/dietpi_userdata/cuberite/webadmin.ini
|
|
[User:admin]
|
|
Password=$GLOBAL_PW
|
|
|
|
[WebAdmin]
|
|
Ports=1339
|
|
Enabled=1
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R cuberite:cuberite /mnt/dietpi_userdata/cuberite
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/cuberite/Cuberite
|
|
fi
|
|
|
|
if To_Install 53 mineos # MineOS
|
|
then
|
|
# https://wiki.codeemo.com/install/debian_10.html
|
|
local url='https://github.com/hexparrot/mineos-node'
|
|
G_CHECK_URL "$url"
|
|
|
|
# APT deps
|
|
G_AGI rdiff-backup rsync screen make g++
|
|
|
|
# Download/Update MineOS
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/mineos
|
|
G_EXEC cd /mnt/dietpi_userdata/mineos
|
|
if [[ -d 'minecraft' ]]
|
|
then
|
|
# https://wiki.codeemo.com/maint/webui.html#updating-the-webui
|
|
G_EXEC cd minecraft
|
|
G_EXEC_OUTPUT=1 G_EXEC git pull origin master
|
|
else
|
|
G_EXEC_OUTPUT=1 G_EXEC git clone "$url" minecraft
|
|
G_EXEC cd minecraft
|
|
fi
|
|
|
|
# File modes
|
|
G_EXEC git config core.filemode false
|
|
G_EXEC chmod +x mineos_console.js webui.js update_webui.sh reset_webui.sh generate-sslcert.sh
|
|
|
|
# Bookworm: Workaround for failing userid 1.0.0-beta.9 build on weirdly Bookworm only. Latest stable 1.2.5 seems to work well: https://github.com/MichaIng/DietPi/issues/7265
|
|
G_CONFIG_INJECT '"userid"' ' "userid": "1.2.5",' package.json
|
|
|
|
# Workaround: Node.js posix needs to be installed alone first: https://github.com/MichaIng/DietPi/issues/5181
|
|
G_EXEC_OUTPUT=1 G_EXEC npm i --no-audit --no-package-lock posix@latest
|
|
|
|
# Install MineOS
|
|
G_EXEC_OUTPUT=1 G_EXEC npm i --no-audit
|
|
|
|
# Config: Preserve existing
|
|
[[ -f '/etc/mineos.conf' ]] || G_EXEC cp mineos.conf /etc/mineos.conf
|
|
|
|
# Create symlinks for console and userdata dir
|
|
G_EXEC ln -sf /mnt/dietpi_userdata/mineos/minecraft/mineos_console.js /usr/local/bin/mineos
|
|
G_EXEC mkdir -p /var/games ../serverdata
|
|
G_EXEC rm -Rf /var/games/minecraft
|
|
G_EXEC ln -s /mnt/dietpi_userdata/mineos/serverdata /var/games/minecraft
|
|
|
|
# Setup SSL cert
|
|
G_EXEC_OUTPUT=1 G_EXEC ./generate-sslcert.sh
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/mineos.service
|
|
[Unit]
|
|
Description=MineOS (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=MineOS
|
|
WorkingDirectory=/mnt/dietpi_userdata/mineos/minecraft
|
|
Environment="SHELL=/bin/bash" "HOME=/root"
|
|
ExecStart=/usr/local/bin/node webui.js
|
|
KillMode=process
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# User and permissions
|
|
local new_user=0
|
|
getent passwd mineos &> /dev/null || new_user=1
|
|
Create_User -d /mnt/dietpi_userdata/mineos/serverdata -p "$GLOBAL_PW" mineos
|
|
G_EXEC chown -R mineos /mnt/dietpi_userdata/mineos/serverdata
|
|
# - Assure SHA512 password hash algorithm, as MineOS does not support yescrypt, default since Bullseye: https://github.com/hexparrot/mineos-node/issues/441
|
|
(( $new_user )) && G_EXEC eval "chpasswd --crypt-method SHA512 <<< 'mineos:$GLOBAL_PW'"
|
|
fi
|
|
|
|
if To_Install 46 qbittorrent # qBittorrent
|
|
then
|
|
G_AGI qbittorrent-nox
|
|
|
|
# User
|
|
Create_User -g dietpi -d /home/qbittorrent qbittorrent
|
|
|
|
# Config: Create only on fresh install
|
|
if [[ ! -f '/home/qbittorrent/.config/qBittorrent/qBittorrent.conf' ]]; then
|
|
|
|
G_EXEC mkdir -p /home/qbittorrent/.config/qBittorrent
|
|
cat << _EOF_ > /home/qbittorrent/.config/qBittorrent/qBittorrent.conf
|
|
[General]
|
|
ported_to_new_savepath_system=true
|
|
|
|
[Application]
|
|
FileLogger\Enabled=true
|
|
FileLogger\Path=/var/log/qbittorrent
|
|
|
|
[AutoRun]
|
|
enabled=false
|
|
|
|
[LegalNotice]
|
|
Accepted=true
|
|
|
|
[Preferences]
|
|
Advanced\AnonymousMode=false
|
|
Advanced\IncludeOverhead=false
|
|
Bittorrent\DHT=true
|
|
Bittorrent\DHTPort=6881
|
|
Bittorrent\Encryption=1
|
|
Bittorrent\LSD=true
|
|
Bittorrent\MaxConnecs=$(Optimise_BitTorrent 2)
|
|
Bittorrent\MaxConnecsPerTorrent=$(Optimise_BitTorrent 2)
|
|
Bittorrent\MaxUploads=$(Optimise_BitTorrent 3)
|
|
Bittorrent\MaxUploadsPerTorrent=$(Optimise_BitTorrent 3)
|
|
Bittorrent\PeX=true
|
|
Bittorrent\sameDHTPortAsBT=true
|
|
Bittorrent\uTP=true
|
|
Bittorrent\uTP_rate_limited=false
|
|
Connection\GlobalDLLimit=-1
|
|
Connection\GlobalDLLimitAlt=10
|
|
Connection\GlobalUPLimit=-1
|
|
Connection\GlobalUPLimitAlt=10
|
|
Connection\PortRangeMin=6881
|
|
Connection\Proxy\Authentication=false
|
|
Connection\ProxyPeerConnections=false
|
|
Connection\ResolvePeerCountries=false
|
|
Connection\UPnP=true
|
|
Downloads\DiskWriteCacheSize=$(Optimise_BitTorrent 0)
|
|
Downloads\DiskWriteCacheTTL=60
|
|
Downloads\PreAllocation=false
|
|
Downloads\SavePath=/mnt/dietpi_userdata/downloads
|
|
Downloads\TempPath=/mnt/dietpi_userdata/downloads
|
|
Downloads\TempPathEnabled=false
|
|
Downloads\UseIncompleteExtension=false
|
|
DynDNS\Enabled=false
|
|
General\Locale=en
|
|
IPFilter\Enabled=false
|
|
MailNotification\enabled=false
|
|
Queueing\IgnoreSlowTorrents=false
|
|
Queueing\MaxActiveDownloads=$(Optimise_BitTorrent 1)
|
|
Queueing\MaxActiveTorrents=$(Optimise_BitTorrent 1)
|
|
Queueing\MaxActiveUploads=1
|
|
Queueing\QueueingEnabled=false
|
|
Scheduler\Enabled=false
|
|
WebUI\CSRFProtection=true
|
|
WebUI\ClickjackingProtection=true
|
|
WebUI\Enabled=true
|
|
WebUI\HTTPS\Enabled=false
|
|
WebUI\HostHeaderValidation=false
|
|
WebUI\LocalHostAuth=true
|
|
WebUI\Password_PBKDF2="@ByteArray(tpgNK76AcpP14rjOZP9vwg==:rQNtOB0P4HfNj20pJtxiTBi9miduS6L1Xqqazc4Y6Gpm3Rn02jMXnPPT3KH2JMDKhFQjAaTGVJz0dz5JVw2QUQ==)"
|
|
WebUI\Port=1340
|
|
WebUI\SecureCookie=true
|
|
WebUI\UseUPnP=true
|
|
WebUI\Username=qbittorrent
|
|
_EOF_
|
|
fi
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/qbittorrent.service
|
|
[Unit]
|
|
Description=qBittorrent (DietPi)
|
|
Documentation=man:qbittorrent-nox(1)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=qbittorrent
|
|
UMask=002
|
|
LogsDirectory=qbittorrent
|
|
ExecStart=/usr/bin/qbittorrent-nox
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R qbittorrent:root /home/qbittorrent
|
|
fi
|
|
|
|
if To_Install 107 rtorrent # rTorrent
|
|
then
|
|
aDEPS=('rtorrent' 'mediainfo')
|
|
|
|
# Install ruTorrent: Web UI for rTorrent
|
|
# - Grab current version
|
|
local version=$(curl -sSfL 'https://api.github.com/repos/Novik/ruTorrent/releases/latest' | mawk -F\" '/^ *"tag_name": "[^"]*",$/{print $4}')
|
|
[[ $version ]] || { version='v5.2.10'; G_DIETPI-NOTIFY 1 "Automatic latest ruTorrent version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
[[ $version == 'v5.'* ]] || version='v5.2.10'
|
|
Download_Install "https://github.com/Novik/ruTorrent/archive/$version.tar.gz"
|
|
|
|
# - Reinstall freshly with preserved configs and 3rd party plugins
|
|
if [[ -d '/var/www/rutorrent' ]]
|
|
then
|
|
# If old configs exist, preserve them and make new config files examples
|
|
[[ -f '/var/www/rutorrent/conf/config.php' ]] && { G_EXEC mv "ruTorrent-${version#v}/conf/config.php"{,.example}; G_EXEC cp -a {/var/www/rutorrent,"ruTorrent-${version#v}"}/conf/config.php; }
|
|
[[ -f '/var/www/rutorrent/conf/access.ini' ]] && { G_EXEC mv "ruTorrent-${version#v}/conf/access.ini"{,.example}; G_EXEC cp -a {/var/www/rutorrent,"ruTorrent-${version#v}"}/conf/access.ini; }
|
|
[[ -f '/var/www/rutorrent/conf/plugins.ini' ]] && { G_EXEC mv "ruTorrent-${version#v}/conf/plugins.ini"{,.example}; G_EXEC cp -a {/var/www/rutorrent,"ruTorrent-${version#v}"}/conf/plugins.ini; }
|
|
|
|
# Preserve 3rd party plugins
|
|
for i in /var/www/rutorrent/plugins/{,.??,.[^.]}*
|
|
do
|
|
[[ -e $i ]] || continue
|
|
[[ -e ruTorrent-${version#v}/plugins/${i#/var/www/rutorrent/plugins/} ]] && continue
|
|
G_EXEC cp -a "$i" "ruTorrent-${version#v}/plugins/"
|
|
done
|
|
|
|
# Preserve 3rd party themes
|
|
for i in /var/www/rutorrent/plugins/theme/themes/{,.??,.[^.]}*
|
|
do
|
|
[[ -e $i ]] || continue
|
|
[[ -e ruTorrent-${version#v}/plugins/theme/themes/${i#/var/www/rutorrent/plugins/theme/themes/} ]] && continue
|
|
G_EXEC cp -a "$i" "ruTorrent-${version#v}/plugins/theme/themes/"
|
|
done
|
|
|
|
# Reinstall freshly with preserved configs, 3rd party plugins and themes
|
|
G_EXEC rm -R /var/www/rutorrent
|
|
fi
|
|
|
|
G_EXEC mv "ruTorrent-${version#v}" /var/www/rutorrent
|
|
|
|
# Install DarkBetter theme manually: https://github.com/MichaIng/DietPi/issues/3271
|
|
if [[ -d '/var/www/rutorrent/plugins/theme/themes/DarkBetter' ]]
|
|
then
|
|
Download_Install 'https://github.com/chocolatkey/DarkBetter/archive/master.tar.gz'
|
|
G_EXEC rm -R /var/www/rutorrent/plugins/theme/themes/DarkBetter
|
|
G_EXEC mv DarkBetter-master /var/www/rutorrent/plugins/theme/themes/DarkBetter
|
|
fi
|
|
|
|
# ruTorrent: Enable HTTP authentication and RPC
|
|
# - Apache
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
# Enable SCGI module
|
|
G_EXEC a2enmod auth_basic authn_file authz_user proxy_scgi
|
|
|
|
# Enable HTTP authentication and rTorrent access via SCGI
|
|
[[ -f '/etc/.rutorrent-htaccess' ]] || htpasswd -cb /etc/.rutorrent-htaccess root "$GLOBAL_PW"
|
|
cat << '_EOF_' > /etc/apache2/sites-available/dietpi-rutorrent.conf
|
|
<Directory /var/www/rutorrent>
|
|
AllowOverride All
|
|
AuthType Basic
|
|
AuthName "ruTorrent login"
|
|
AuthBasicProvider file
|
|
AuthUserFile "/etc/.rutorrent-htaccess"
|
|
Require valid-user
|
|
</Directory>
|
|
<Location /RPC2>
|
|
AuthType Basic
|
|
AuthName "rTorrent login"
|
|
AuthBasicProvider file
|
|
AuthUserFile "/etc/.rutorrent-htaccess"
|
|
Require valid-user
|
|
</Location>
|
|
ProxyPass "/RPC2" "unix:/mnt/dietpi_userdata/downloads/.session/rpc.socket|scgi://127.0.0.1"
|
|
_EOF_
|
|
G_EXEC a2ensite dietpi-rutorrent
|
|
|
|
# - Lighttpd
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
[[ -f '/etc/.rutorrent-htaccess' ]] || echo "root:rtorrent:$(echo -n "root:rtorrent:$GLOBAL_PW" | md5sum | mawk '{print $1}')" > /etc/.rutorrent-htaccess
|
|
|
|
# Pre-v7.2: Remove obsolete entries from /etc/lighttpd/lighttpd.conf
|
|
grep -q '^#RUTORRENT_DIETPI' /etc/lighttpd/lighttpd.conf && G_EXEC sed --follow-symlinks -i '/#RUTORRENT_DIETPI/,/#RUTORRENT_DIETPI/d' /etc/lighttpd/lighttpd.conf
|
|
|
|
cat << '_EOF_' > /etc/lighttpd/conf-available/98-dietpi-rtorrent.conf
|
|
server.modules += ( "mod_auth", "mod_authn_file", "mod_scgi" )
|
|
auth.backend = "htdigest"
|
|
auth.backend.htdigest.userfile = "/etc/.rutorrent-htaccess"
|
|
auth.require = ( "/rutorrent" =>
|
|
(
|
|
"method" => "digest",
|
|
"realm" => "rtorrent",
|
|
"require" => "valid-user"
|
|
),
|
|
"/RPC2" =>
|
|
(
|
|
"method" => "digest",
|
|
"realm" => "rtorrent",
|
|
"require" => "valid-user"
|
|
)
|
|
)
|
|
scgi.server = ( "/RPC2" =>
|
|
( "rtorrent" =>
|
|
(
|
|
"socket" => "/mnt/dietpi_userdata/downloads/.session/rpc.socket",
|
|
"check-local" => "disable"
|
|
)
|
|
)
|
|
)
|
|
$HTTP["url"] =~ "^/rutorrent/(conf|share)($|/)" {
|
|
url.access-deny = ("")
|
|
}
|
|
_EOF_
|
|
[[ -f '/etc/lighttpd/conf-enabled/98-dietpi-rtorrent.conf' ]] || G_EXEC lighty-enable-mod dietpi-rtorrent
|
|
|
|
# - Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
# "openssl passwd -5" (sha256, even "-6" sha512) can be used from Buster on.
|
|
[[ -f '/etc/.rutorrent-htaccess' ]] || echo "root:$(openssl passwd -apr1 "$GLOBAL_PW")" > /etc/.rutorrent-htaccess
|
|
cat << '_EOF_' > /etc/nginx/sites-dietpi/dietpi-rutorrent.conf
|
|
location ^~ /rutorrent {
|
|
auth_basic "ruTorrent login";
|
|
auth_basic_user_file /etc/.rutorrent-htaccess;
|
|
location ~ ^/rutorrent/(?:conf|share)(?:/|$) { return 404; }
|
|
location ~ \.php(?:$|/) {
|
|
include snippets/fastcgi-php.conf;
|
|
fastcgi_pass php;
|
|
}
|
|
}
|
|
location ^~ /RPC2 {
|
|
auth_basic "rTorrent login";
|
|
auth_basic_user_file /etc/.rutorrent-htaccess;
|
|
include scgi_params;
|
|
scgi_pass unix:/mnt/dietpi_userdata/downloads/.session/rpc.socket;
|
|
}
|
|
_EOF_
|
|
fi
|
|
|
|
G_EXEC chmod 0400 /etc/.rutorrent-htaccess
|
|
G_EXEC chown www-data:www-data /etc/.rutorrent-htaccess
|
|
|
|
# ruTorrent config
|
|
# shellcheck disable=SC2016
|
|
G_CONFIG_INJECT '\$scgi_port[[:blank:]]' ' $scgi_port = 0;' /var/www/rutorrent/conf/config.php
|
|
# shellcheck disable=SC2016
|
|
G_CONFIG_INJECT '\$scgi_host[[:blank:]]' ' $scgi_host = "unix:///mnt/dietpi_userdata/downloads/.session/rpc.socket";' /var/www/rutorrent/conf/config.php
|
|
G_CONFIG_INJECT '"curl"[[:blank:]]' ' "curl" => "/usr/bin/curl",' /var/www/rutorrent/conf/config.php
|
|
|
|
# Session dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/downloads/.session
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/rtorrent rtorrent
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/rtorrent.service
|
|
[Unit]
|
|
Description=rTorrent (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=rtorrent
|
|
ExecStart=$(command -v rtorrent)
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# rTorrent config: Do not overwrite if existent
|
|
# - Example: https://github.com/rakshasa/rtorrent/blob/master/doc/rtorrent.rc
|
|
# - Deprecated commands:
|
|
# https://github.com/rakshasa/rtorrent/wiki/rTorrent-0.9-Comprehensive-Command-list-(WIP)
|
|
# https://github.com/rakshasa/rtorrent/blob/master/doc/scripts/update_commands_0.9.sed
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/rtorrent
|
|
if [[ -f '/mnt/dietpi_userdata/rtorrent/.rtorrent.rc' ]]
|
|
then
|
|
# In case dist-upgraded systems, assure that daemon mode is enabled
|
|
G_CONFIG_INJECT 'system.daemon.set[[:blank:]=]' 'system.daemon.set = true' /mnt/dietpi_userdata/rtorrent/.rtorrent.rc
|
|
# Reinstall: Assure that rpi.socket is used, else ruTorrent connection would fail
|
|
G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*network.scgi.open_port[[:blank:]=]/d' /mnt/dietpi_userdata/rtorrent/.rtorrent.rc
|
|
G_CONFIG_INJECT 'network.scgi.open_local[[:blank:]=]' 'network.scgi.open_local = /mnt/dietpi_userdata/downloads/.session/rpc.socket' /mnt/dietpi_userdata/rtorrent/.rtorrent.rc
|
|
G_CONFIG_INJECT 'execute.nothrow[[:blank:]]*=[[:blank:]]*chmod,666,/mnt/dietpi_userdata/downloads/.session/rpc.socket' 'execute.nothrow = chmod,666,/mnt/dietpi_userdata/downloads/.session/rpc.socket' /mnt/dietpi_userdata/rtorrent/.rtorrent.rc 'network.scgi.open_local[[:blank:]=]'
|
|
else
|
|
cat << _EOF_ > /mnt/dietpi_userdata/rtorrent/.rtorrent.rc
|
|
### Miscellaneous settings
|
|
system.daemon.set = true
|
|
# Default download dir
|
|
directory.default.set = /mnt/dietpi_userdata/downloads
|
|
# Session dir
|
|
session.path.set = /mnt/dietpi_userdata/downloads/.session
|
|
# Save session every 5 minutes
|
|
schedule2 = session_save, 240, 300, ((session.save))
|
|
# Close torrents on low diskspace, check every minute
|
|
schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
|
|
system.umask.set = 002
|
|
# Max memory mapping size, not max physical RAM usage!
|
|
pieces.memory.max.set = ${RAM_PHYS}M
|
|
pieces.hash.on_completion.set = no
|
|
|
|
### Connection settings
|
|
# Incoming connection ports
|
|
network.port_open.set = yes
|
|
network.port_random.set = no
|
|
network.port_range.set = 49164-49164
|
|
# SCGI connection, e.g. for ruTorrent web UI
|
|
network.scgi.open_local = /mnt/dietpi_userdata/downloads/.session/rpc.socket
|
|
execute.nothrow = chmod,666,/mnt/dietpi_userdata/downloads/.session/rpc.socket
|
|
|
|
### Network limits
|
|
network.http.max_open.set = $(Optimise_BitTorrent 2)
|
|
network.max_open_files.set = $(( $(Optimise_BitTorrent 2) * 2 ))
|
|
network.max_open_sockets.set = $(Optimise_BitTorrent 2)
|
|
# Global max download/upload rate in KiB, "0" for unlimited
|
|
throttle.global_down.max_rate.set_kb = 0
|
|
throttle.global_up.max_rate.set_kb = 0
|
|
|
|
### Peer settings
|
|
# Max downloads/uploads accross all torrents
|
|
throttle.max_downloads.global.set = $(Optimise_BitTorrent 2)
|
|
throttle.max_uploads.global.set = $(Optimise_BitTorrent 2)
|
|
# Max downloads/uploads per torrent
|
|
throttle.max_downloads.set = $(( $(Optimise_BitTorrent 2) / 2 ))
|
|
throttle.max_uploads.set = $(( $(Optimise_BitTorrent 2) / 2 ))
|
|
# Min/Max connected peers
|
|
throttle.min_peers.normal.set = $(( $(Optimise_BitTorrent 2) - 1))
|
|
throttle.max_peers.normal.set = $(Optimise_BitTorrent 2)
|
|
throttle.min_peers.seed.set = -1
|
|
throttle.max_peers.seed.set = -1
|
|
trackers.numwant.set = $(Optimise_BitTorrent 2)
|
|
# Public tracker support
|
|
trackers.use_udp.set = yes
|
|
dht.mode.set = on
|
|
#dht.port.set = 6881
|
|
protocol.pex.set = yes
|
|
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
|
|
_EOF_
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R rtorrent:root /mnt/dietpi_userdata/rtorrent /mnt/dietpi_userdata/downloads/.session
|
|
# - ruTorrent: https://github.com/Novik/ruTorrent/wiki/Config
|
|
G_EXEC chown -R www-data:root /var/www/rutorrent/share
|
|
G_EXEC chown root:root /var/www/rutorrent/share/.htaccess
|
|
fi
|
|
|
|
if To_Install 132 aria2 # Aria2
|
|
then
|
|
G_AGI aria2
|
|
|
|
# Web UI: Settings are stored client-wise, web UI files are never written by webserver. Thus root:root 022 permissions existing dir removal on reinstall can be done.
|
|
Download_Install 'https://github.com/ziahamza/webui-aria2/archive/master.tar.gz'
|
|
[[ -d '/var/www/aria2' ]] && G_EXEC rm -R /var/www/aria2
|
|
G_EXEC mv webui-aria2-master /var/www/aria2
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/aria2 aria2
|
|
|
|
# Config
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/aria2
|
|
[[ -f '/mnt/dietpi_userdata/aria2/aria2.conf' ]] || cat << _EOF_ > /mnt/dietpi_userdata/aria2/aria2.conf || exit 1
|
|
# DietPi default aria2c options served as aria2.conf file via --conf-path
|
|
# https://aria2.github.io/manual/en/html/aria2c.html#options
|
|
|
|
# Logging
|
|
console-log-level=notice
|
|
|
|
# Session
|
|
always-resume=true
|
|
continue=true
|
|
input-file=/mnt/dietpi_userdata/downloads/aria2.session
|
|
save-session=/mnt/dietpi_userdata/downloads/aria2.session
|
|
save-session-interval=60
|
|
|
|
# Connection
|
|
listen-port=6881-6999
|
|
ftp-pasv=true
|
|
check-certificate=false
|
|
# - Count
|
|
max-concurrent-downloads=$(Optimise_BitTorrent 1)
|
|
split=$(Optimise_BitTorrent 1)
|
|
max-connection-per-server=$(Optimise_BitTorrent 1)
|
|
bt-max-peers=$(Optimise_BitTorrent 2)
|
|
# - Bandwidth
|
|
max-overall-upload-limit=0
|
|
max-upload-limit=0
|
|
max-overall-download-limit=0
|
|
max-download-limit=0
|
|
# - Retries
|
|
max-file-not-found=3
|
|
max-tries=5
|
|
retry-wait=60
|
|
|
|
# RPC
|
|
enable-rpc=true
|
|
rpc-listen-all=true
|
|
rpc-listen-port=6800
|
|
rpc-secret=$GLOBAL_PW
|
|
rpc-allow-origin-all=true
|
|
pause=false
|
|
|
|
# Store
|
|
dir=/mnt/dietpi_userdata/downloads
|
|
allow-overwrite=false
|
|
auto-file-renaming=false
|
|
file-allocation=none
|
|
check-integrity=true
|
|
|
|
# Seeding
|
|
seed-ratio=0.1
|
|
seed-time=0
|
|
_EOF_
|
|
# Pre-create input file
|
|
local fp_input=$(sed -n '/^[[:blank:]]*input-file=/{s/^[^=]*=//p;q}' /mnt/dietpi_userdata/aria2/aria2.conf)
|
|
[[ ${fp_input//\"} && ! -f $fp_input ]] && > "$fp_input"
|
|
|
|
# Permissions
|
|
G_EXEC chown -R aria2:0 /mnt/dietpi_userdata/aria2 "$fp_input"
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/aria2/aria2.conf
|
|
unset -v fp_input
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/aria2.service
|
|
[Unit]
|
|
Description=Aria2 (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=aria2
|
|
UMask=002
|
|
ExecStart=$(command -v aria2c) --conf-path=/mnt/dietpi_userdata/aria2/aria2.conf
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 116 medusa # Medusa
|
|
then
|
|
aDEPS=('mediainfo' 'python3')
|
|
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d '/mnt/dietpi_userdata/medusa' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/mnt/dietpi_userdata/medusa\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually backup your config files+data, remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
else
|
|
Download_Install 'https://github.com/pymedusa/Medusa/archive/master.tar.gz'
|
|
G_EXEC mv Medusa-master /mnt/dietpi_userdata/medusa
|
|
fi
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/medusa medusa
|
|
|
|
# Service: https://github.com/pymedusa/Medusa/blob/master/runscripts/init.systemd
|
|
cat << '_EOF_' > /etc/systemd/system/medusa.service || exit 1
|
|
[Unit]
|
|
Description=Medusa (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Medusa
|
|
User=medusa
|
|
UMask=002
|
|
ExecStart=/usr/bin/python3 /mnt/dietpi_userdata/medusa/start.py -q --nolaunch --datadir=/mnt/dietpi_userdata/medusa
|
|
TimeoutStopSec=25
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=1
|
|
PrivateTmp=1
|
|
PrivateDevices=1
|
|
ProtectKernelTunables=1
|
|
ProtectControlGroups=1
|
|
ReadWritePaths=-/mnt /media -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R medusa:0 /mnt/dietpi_userdata/medusa
|
|
fi
|
|
|
|
if To_Install 50 syncthing # Syncthing
|
|
then
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d '/opt/syncthing' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/syncthing\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
else
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='arm';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/syncthing/syncthing/releases/download/v2.0.12/syncthing-linux-$arch-v2.0.12.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/syncthing/syncthing/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/syncthing-linux-$arch-[^\"\/]*\.tar\.gz\"$/{print \$4}")"
|
|
G_EXEC mv syncthing-* /opt/syncthing
|
|
fi
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/syncthing syncthing
|
|
|
|
# Permit self-updates
|
|
G_EXEC chown -R syncthing /opt/syncthing
|
|
|
|
# Generate and edit config only on fresh installs
|
|
if [[ ! -f '/mnt/dietpi_userdata/syncthing/config.xml' ]]
|
|
then
|
|
# Failsafe: Assure that "syncthing" (its "dietpi" group) has permission to create the /mnt/dietpi_userdata/syncthing directory
|
|
G_EXEC chgrp dietpi /mnt/dietpi_userdata
|
|
G_EXEC chmod 'g+rwx' /mnt/dietpi_userdata
|
|
|
|
# Generate config
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u syncthing -- /opt/syncthing/syncthing generate --home=/mnt/dietpi_userdata/syncthing
|
|
|
|
# Allow remote access: https://docs.syncthing.net/users/faq.html#how-do-i-access-the-web-gui-from-another-computer
|
|
G_EXEC sed --follow-symlinks -i '\|:8384</address>|c\ <address>0.0.0.0:8384</address>' /mnt/dietpi_userdata/syncthing/config.xml
|
|
|
|
# Set default data directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/syncthing_data
|
|
G_EXEC chown -R syncthing: /mnt/dietpi_userdata/syncthing_data
|
|
G_EXEC chmod 0775 /mnt/dietpi_userdata/syncthing_data
|
|
if grep -q '<folder id="default"' /mnt/dietpi_userdata/syncthing/config.xml
|
|
then
|
|
G_EXEC sed --follow-symlinks -i '\|<folder id="default"|s|label="[^"]*"|label="Syncthing Data"|' /mnt/dietpi_userdata/syncthing/config.xml
|
|
G_EXEC sed --follow-symlinks -i '\|<folder id="default"|s|path="[^"]*"|path="/mnt/dietpi_userdata/syncthing_data"|' /mnt/dietpi_userdata/syncthing/config.xml
|
|
else
|
|
G_CONFIG_INJECT '<folder id="default"' ' <folder id="default" label="Syncthing Data" path="/mnt/dietpi_userdata/syncthing_data"></folder>' /mnt/dietpi_userdata/syncthing/config.xml '^<configuration'
|
|
fi
|
|
fi
|
|
|
|
# Service: https://github.com/syncthing/syncthing/blob/main/etc/linux-systemd/system/syncthing@.service
|
|
cat << '_EOF_' > /etc/systemd/system/syncthing.service
|
|
[Unit]
|
|
Description=Syncthing (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=syncthing
|
|
UMask=002
|
|
ExecStart=/opt/syncthing/syncthing --no-browser --no-restart --log-level=WARN --home=/mnt/dietpi_userdata/syncthing
|
|
Restart=on-failure
|
|
RestartSec=1
|
|
SuccessExitStatus=3 4
|
|
RestartForceExitStatus=3 4
|
|
|
|
# Hardening
|
|
ProtectSystem=full
|
|
PrivateTmp=true
|
|
SystemCallArchitectures=native
|
|
MemoryDenyWriteExecute=true
|
|
NoNewPrivileges=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Increase fs watcher limit: https://docs.syncthing.net/users/faq.html#inotify-limits
|
|
# - 8192 until Linux 5.11, 7x RAM size in MiB since Linux 5.11, up to 1048576
|
|
# Raise UDP buffer sizes: https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes
|
|
if (( $G_HW_MODEL == 75 ))
|
|
then
|
|
(( $(sysctl -n fs.inotify.max_user_watches) >= 204800 && $(sysctl -n net.core.rmem_max) >= 7500000 && $(sysctl -n net.core.wmem_max) >= 7500000 )) || G_WHIP_MSG '[WARNING] Filesystem watcher and UDP buffer size limits might be too low
|
|
\nSyncthing uses filesystem (inotify) watchers to detect changes in your folders. Depending on the amount of files, the kernel version and physical RAM size of the host system, the current limit might be too low for Syncthing to start all watchers.
|
|
\nAdditionally, for HTTP3/QUIC connections, the bandwidth can be limited by UDP buffer sizes.
|
|
\nBoth limits can only be raised on the host of this container. E.g. add the following lines to a new sysctl config file like /etc/sysctl.d/dietpi-syncthing.conf:
|
|
fs.inotify.max_user_watches=204800
|
|
net.core.rmem_max=7500000
|
|
net.core.wmem_max=7500000
|
|
\nApply them without reboot like this:
|
|
sudo sysctl -p /etc/sysctl.d/dietpi-syncthing.confs
|
|
\nMore info:
|
|
- https://docs.syncthing.net/users/faq.html#inotify-limits
|
|
- https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Size'
|
|
else
|
|
G_EXEC eval 'echo -e '\''fs.inotify.max_user_watches=204800\nnet.core.rmem_max=7500000\nnet.core.wmem_max=7500000'\'' > /etc/sysctl.d/dietpi-syncthing.conf'
|
|
local dryrun=()
|
|
[[ ! -w '/proc/sys/net/core/rmem_max' ]] && systemd-detect-virt -cq && dryrun=('--dry-run')
|
|
G_EXEC sysctl -p "${dryrun[@]}" /etc/sysctl.d/dietpi-syncthing.conf
|
|
fi
|
|
fi
|
|
|
|
if To_Install 113 # Chromium
|
|
then
|
|
# libpam-systemd: Required for non-root users to start Chromium from console via "startx"
|
|
if (( $G_HW_MODEL > 9 ))
|
|
then
|
|
G_AGI chromium libpam-systemd
|
|
Create_Desktop_Shortcut chromium
|
|
|
|
# RPi: Use RPi repo package including non-free FFmpeg codecs integration
|
|
else
|
|
# From Bookworm on, "chromium-browser" is a dummy package only
|
|
if (( $G_DISTRO < 7 ))
|
|
then
|
|
G_AGI chromium-browser chromium-codecs-ffmpeg-extra libpam-systemd
|
|
Create_Desktop_Shortcut chromium-browser
|
|
else
|
|
G_AGI chromium libpam-systemd
|
|
Create_Desktop_Shortcut chromium
|
|
fi
|
|
|
|
# Enable KMS
|
|
grep -Eq '^[[:blank:]]*dtoverlay=vc4-f?kms-v3d' /boot/config.txt || /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d
|
|
|
|
# Enable hardware codecs
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-codec 1
|
|
fi
|
|
|
|
# Flags: Allow root (disable sandbox) and minimise CPU usage: https://peter.sh/experiments/chromium-command-line-switches/
|
|
G_EXEC eval "echo 'export CHROMIUM_FLAGS=\"\$CHROMIUM_FLAGS --no-sandbox --test-type --disable-smooth-scrolling --disable-low-res-tiling --enable-low-end-device-mode --num-raster-threads=$G_HW_CPU_CORES --disable-composited-antialiasing\"' > /etc/chromium.d/dietpi"
|
|
|
|
# Autostart script for kiosk mode, based on @AYapejian: https://github.com/MichaIng/DietPi/issues/1737#issue-318697621
|
|
G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed
|
|
cat << '_EOF_' > /var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh
|
|
#!/bin/dash
|
|
# Autostart script for kiosk mode, based on @AYapejian: https://github.com/MichaIng/DietPi/issues/1737#issue-318697621
|
|
|
|
# Resolution to use for kiosk mode, should ideally match current system resolution
|
|
RES_X=$(sed -n '/^[[:blank:]]*SOFTWARE_CHROMIUM_RES_X=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
RES_Y=$(sed -n '/^[[:blank:]]*SOFTWARE_CHROMIUM_RES_Y=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
|
|
# Command line switches: https://peter.sh/experiments/chromium-command-line-switches/
|
|
# - Review and add custom flags in: /etc/chromium.d
|
|
CHROMIUM_OPTS="--kiosk --window-size=${RES_X:-1280},${RES_Y:-720} --window-position=0,0"
|
|
|
|
# If you want tablet mode, uncomment the next line.
|
|
#CHROMIUM_OPTS="$CHROMIUM_OPTS --force-tablet-mode --tablet-ui"
|
|
|
|
# Home page
|
|
URL=$(sed -n '/^[[:blank:]]*SOFTWARE_CHROMIUM_AUTOSTART_URL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
|
|
# RPi or Debian Chromium package
|
|
FP_CHROMIUM=$(command -v chromium-browser)
|
|
[ "$FP_CHROMIUM" ] || FP_CHROMIUM=$(command -v chromium)
|
|
|
|
# Use "startx" as non-root user to get required permissions via systemd-logind
|
|
STARTX='xinit'
|
|
[ "$USER" = 'root' ] || STARTX='startx'
|
|
|
|
exec "$STARTX" "$FP_CHROMIUM" $CHROMIUM_OPTS "${URL:-https://dietpi.com/}"
|
|
_EOF_
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh
|
|
fi
|
|
|
|
if To_Install 136 motioneye # motionEye
|
|
then
|
|
# Dependencies
|
|
Python_Deps -i pillow pycurl
|
|
|
|
# RPi: Enable camera module
|
|
(( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-camera 1
|
|
|
|
# motionEye
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -U motioneye
|
|
G_EXEC_OUTPUT=1 G_EXEC motioneye_init --skip-apt-update
|
|
G_EXEC systemctl stop motioneye
|
|
|
|
# Prevent the conflicting motion daemon from starting
|
|
G_EXEC systemctl --no-reload disable --now motion
|
|
G_EXEC systemctl --no-reload mask motion
|
|
|
|
# Data directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/motioneye
|
|
G_EXEC chown -R motion /mnt/dietpi_userdata/motioneye
|
|
G_CONFIG_INJECT 'media_path' 'media_path /mnt/dietpi_userdata/motioneye' /etc/motioneye/motioneye.conf
|
|
fi
|
|
|
|
if To_Install 137 mjpg-streamer # mjpg-streamer
|
|
then
|
|
# Build dependencies
|
|
aDEPS=('make' 'cmake' 'gcc' 'libc6-dev' 'libjpeg62-turbo-dev')
|
|
# - RPi Bullseye: Add RPi Camera support by default
|
|
(( $G_HW_MODEL > 9 || $G_DISTRO > 6 )) || aDEPS+=('libraspberrypi-dev')
|
|
|
|
# Download sources
|
|
Download_Install 'https://github.com/jacksonliam/mjpg-streamer/archive/master.tar.gz'
|
|
|
|
# Compile
|
|
G_EXEC cd mjpg-streamer-master/mjpg-streamer-experimental
|
|
G_EXEC_OUTPUT=1 G_EXEC make CFLAGS='-g0 -O3' -j "$(nproc)"
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note _build/mjpg_streamer
|
|
|
|
# Move all plugin libraries into the executable's directory to avoid the need for LD_LIBRARY_PATH
|
|
G_EXEC mv _build/plugins/*/*.so _build/
|
|
|
|
# Remove all left build files
|
|
G_EXEC rm -R _build/{{,C,c}[Mm]ake*,plugins}
|
|
|
|
# Install to system, in case remove previous installs
|
|
[[ -d '/opt/mjpg-streamer' ]] && G_EXEC rm -R /opt/mjpg-streamer
|
|
G_EXEC mv _build /opt/mjpg-streamer
|
|
|
|
# Cleanup
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R mjpg-streamer-master
|
|
|
|
# User
|
|
Create_User -g video -d /opt/mjpg-streamer mjpg-streamer
|
|
|
|
# Service
|
|
# - RPi Bullseye: If the RPi legacy camera stack is enabled already, use it by default.
|
|
local input='input_uvc.so -d /dev/video0'
|
|
[[ $G_HW_MODEL -gt 9 || $G_DISTRO -gt 6 || -f '/etc/modprobe.d/dietpi-disable_rpi_camera.conf' ]] || input='input_raspicam.so'
|
|
cat << _EOF_ > /etc/systemd/system/mjpg-streamer.service
|
|
[Unit]
|
|
Description=mjpg-streamer (DietPi)
|
|
Documentation=https://github.com/jacksonliam/mjpg-streamer/tree/master/mjpg-streamer-experimental
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=mjpg-streamer
|
|
WorkingDirectory=/opt/mjpg-streamer
|
|
ExecStart=/opt/mjpg-streamer/mjpg_streamer -i '$input' -o 'output_http.so -p 8082 -n'
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
PrivateTmp=true
|
|
ProtectHome=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# OctoPrint: Configure it to use mjpg-streamer if installed
|
|
if [[ ${aSOFTWARE_INSTALL_STATE[153]} == 2 && -f '/mnt/dietpi_userdata/octoprint/.octoprint/config.yaml' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring OctoPrint to use mjpg-streamer for webcam support'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.stream "http://$(G_GET_NET ip):8082/?action=stream"
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.snapshot 'http://127.0.0.1:8082/?action=snapshot'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.ffmpeg "$(command -v ffmpeg)"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 138 virtualhere # VirtualHere
|
|
then
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='x86_64';;
|
|
*) local arch='arm';;
|
|
esac
|
|
|
|
Download_Install "https://virtualhere.com/sites/default/files/usbserver/vhusbd$arch" /opt/virtualhere/vhusbd
|
|
G_EXEC chmod +x /opt/virtualhere/vhusbd
|
|
|
|
# Config
|
|
if [[ ! -f '/opt/virtualhere/config.ini' ]]
|
|
then
|
|
if [[ -f '/etc/vhusbd/config.ini' ]]
|
|
then
|
|
G_EXEC mv /etc/vhusbd/config.ini /opt/virtualhere/config.ini
|
|
else
|
|
# shellcheck disable=SC2016
|
|
echo 'ServerName=$HOSTNAME$' > /opt/virtualhere/config.ini
|
|
fi
|
|
fi
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/virtualhere.service
|
|
[Unit]
|
|
Description=VirtualHere (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
ExecStart=/opt/virtualhere/vhusbd
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Pre-v8.4
|
|
[[ -d '/etc/vhusbd' ]] && G_EXEC rm -R /etc/vhusbd
|
|
[[ -f '/var/log/virtualhere.log' ]] && G_EXEC rm /var/log/virtualhere.log
|
|
fi
|
|
|
|
if To_Install 139 sabnzbd # SABnzbd: https://sabnzbd.org/wiki/installation/install-off-modules
|
|
then
|
|
# APT deps
|
|
aDEPS=('par2')
|
|
(( $G_DISTRO > 7 )) && aDEPS+=('7zip') || aDEPS+=('p7zip-full')
|
|
Python_Deps cffi cryptography sabctools ujson
|
|
|
|
Download_Install 'https://github.com/sabnzbd/sabnzbd/archive/master.tar.gz'
|
|
|
|
# Reinstall: Remove old install dir
|
|
if [[ -d '/etc/sabnzbd' ]]
|
|
then
|
|
# Preserve old config file
|
|
[[ -f '/etc/sabnzbd/sabnzbd.ini' ]] && G_EXEC mv /etc/sabnzbd/sabnzbd.ini sabnzbd-master/sabnzbd.ini
|
|
G_EXEC rm -R /etc/sabnzbd
|
|
fi
|
|
|
|
# Install
|
|
G_EXEC mv sabnzbd-master /etc/sabnzbd
|
|
|
|
# Python deps
|
|
G_EXEC cd /etc/sabnzbd
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -Ur requirements.txt
|
|
|
|
# User
|
|
Create_User -g dietpi -d /etc/sabnzbd sabnzbd
|
|
|
|
# Permissions
|
|
G_EXEC chown -R sabnzbd:root .
|
|
|
|
# Service: https://github.com/sabnzbd/sabnzbd/blob/master/linux/sabnzbd%40.service
|
|
# - Options: https://sabnzbd.org/wiki/advanced/command-line-parameters
|
|
# "-OO": Optimise code and remove doc lines (default shebang of SABnzbd.py, but we run python3 explicitly to avoid version conflicts)
|
|
# "-d": Run in daemon mode without terminal and browser start (requires "-f /path/to/config.ini")
|
|
# NB: In systemd unit leads to unreliable long taking webserver start. A new process is forked which allows web access, but sometimes after very long time, sometimes never: https://github.com/sabnzbd/sabnzbd/issues/1283
|
|
# "-n": Do no start browser with daemon
|
|
cat << '_EOF_' > /etc/systemd/system/sabnzbd.service
|
|
[Unit]
|
|
Description=SABnzbd (DietPi)
|
|
Documentation=https://sabnzbd.org/wiki/
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=SABnzbd
|
|
User=sabnzbd
|
|
ExecStart=/usr/bin/python3 -OO /etc/sabnzbd/SABnzbd.py -f /etc/sabnzbd/sabnzbd.ini -n --disable-file-log
|
|
Restart=on-failure
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Config
|
|
# - Touch only if it does not yet exist, assume reinstall otherwise and preserve custom changes
|
|
# - API keys and initial config are only generated during 1st run
|
|
# - We need to launch program, then apply our config tweaks, else, wizard setup in web interface simply loops without API keys.
|
|
if [[ ! -f '/etc/sabnzbd/sabnzbd.ini' ]] && CREATE_CONFIG_CONTENT='[misc]' Create_Config /etc/sabnzbd/sabnzbd.ini sabnzbd
|
|
then
|
|
G_CONFIG_INJECT 'log_level[[:blank:]]+=' 'log_level = 0' /etc/sabnzbd/sabnzbd.ini # Warnings and errors only
|
|
G_CONFIG_INJECT 'auto_browser[[:blank:]]+=' 'auto_browser = 0' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'host[[:blank:]]+=' 'host = 0.0.0.0' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'admin_dir[[:blank:]]+=' 'admin_dir = /mnt/dietpi_userdata/downloads/sabnzbd_admin' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'download_dir[[:blank:]]+=' 'download_dir = /mnt/dietpi_userdata/downloads/incomplete' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'complete_dir[[:blank:]]+=' 'complete_dir = /mnt/dietpi_userdata/downloads/complete' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'nzb_backup_dir[[:blank:]]+=' 'nzb_backup_dir = /mnt/dietpi_userdata/downloads/sabnzbd_nzb_backup' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'permissions[[:blank:]]+=' 'permissions = 0775' /etc/sabnzbd/sabnzbd.ini
|
|
G_CONFIG_INJECT 'refresh_rate[[:blank:]]+=' 'refresh_rate = 2' /etc/sabnzbd/sabnzbd.ini
|
|
|
|
[[ -d '/mnt/dietpi_userdata/downloads/sabnzbd_admin' ]] && G_EXEC chown -R sabnzbd:root /mnt/dietpi_userdata/downloads/sabnzbd_admin
|
|
[[ -d '/mnt/dietpi_userdata/downloads/sabnzbd_nzb_backup' ]] && G_EXEC chown -R sabnzbd:root /mnt/dietpi_userdata/downloads/sabnzbd_nzb_backup
|
|
[[ -d '/mnt/dietpi_userdata/downloads/incomplete' ]] && G_EXEC chown -R sabnzbd:dietpi /mnt/dietpi_userdata/downloads/incomplete
|
|
[[ -d '/mnt/dietpi_userdata/downloads/complete' ]] && G_EXEC chown -R sabnzbd:dietpi /mnt/dietpi_userdata/downloads/complete
|
|
fi
|
|
|
|
# Install language packs: https://github.com/MichaIng/DietPi/issues/1917#issue-340631943
|
|
G_EXEC python3 -OO tools/make_mo.py
|
|
G_EXEC chown -R sabnzbd:root .
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
fi
|
|
|
|
if To_Install 183 vaultwarden # vaultwarden
|
|
then
|
|
G_AGI vaultwarden
|
|
G_EXEC systemctl stop vaultwarden
|
|
fi
|
|
|
|
if To_Install 193 k3s # K3s
|
|
then
|
|
# APT deps
|
|
local disable_apparmor=1
|
|
systemctl -q is-active apparmor && disable_apparmor=0
|
|
G_AGI apparmor iptables
|
|
(( $disable_apparmor )) && G_EXEC systemctl --no-reload disable --now apparmor
|
|
Configure_iptables
|
|
|
|
# Fetch config file if it exists
|
|
if [[ -f '/boot/dietpi-k3s.yaml' && ! -f '/etc/rancher/k3s/config.yaml' ]]
|
|
then
|
|
G_EXEC mkdir -p '/etc/rancher/k3s'
|
|
G_EXEC cp '/boot/dietpi-k3s.yaml' '/etc/rancher/k3s/config.yaml'
|
|
fi
|
|
|
|
# Install
|
|
G_EXEC curl -sSfL 'https://get.k3s.io/' -o install.sh
|
|
G_EXEC chmod +x install.sh
|
|
export INSTALL_K3S_SKIP_ENABLE=true
|
|
export INSTALL_K3S_EXEC=$(sed -n '/^[[:blank:]]*SOFTWARE_K3S_EXEC=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
if G_EXEC_NOEXIT=1 G_EXEC_OUTPUT=1 G_EXEC ./install.sh
|
|
then
|
|
# Do not enter into a server restart loop on failure
|
|
G_EXEC mkdir -p /etc/systemd/system/k3s.service.d
|
|
G_EXEC eval 'echo -e '\''[Service]\nRestart=on-success'\'' > /etc/systemd/system/k3s.service.d/dietpi.conf'
|
|
|
|
Enable_memory_cgroup
|
|
else
|
|
aSOFTWARE_INSTALL_STATE[$software_id]=-1
|
|
fi
|
|
G_EXEC rm install.sh
|
|
fi
|
|
|
|
if To_Install 142 # MicroK8s
|
|
then
|
|
# MicroK8s itself is a snap, hence snapd is needed
|
|
G_AGI snapd
|
|
|
|
# Update snapd itself, needed on older Debian to install core20 snap. Both are pulled by the MicroK8s snap anyway, but while older snapd runs, installing MicroK8s fails at core20 before snapd is updated.
|
|
if snap list snapd &> /dev/null
|
|
then
|
|
G_EXEC_OUTPUT=1 G_EXEC snap refresh snapd
|
|
else
|
|
G_EXEC_OUTPUT=1 G_EXEC snap install snapd
|
|
fi
|
|
|
|
# Install or update microk8s snap
|
|
if snap list microk8s &> /dev/null
|
|
then
|
|
G_EXEC_OUTPUT=1 G_EXEC snap refresh microk8s
|
|
else
|
|
G_EXEC_OUTPUT=1 G_EXEC snap install microk8s --classic
|
|
fi
|
|
|
|
Enable_memory_cgroup
|
|
fi
|
|
|
|
if To_Install 143 koel # Koel
|
|
then
|
|
# APT dependencies: https://docs.koel.dev/guide/getting-started > https://laravel.com/docs/11.x/deployment#server-requirements / https://laravel.com/docs/10.x/deployment#server-requirements / https://laravel.com/docs/8.x/deployment#server-requirements
|
|
# - Skip JSON module from PHP 8.0 on, where it is embedded into core
|
|
# - pdo_sqlite module required for "artisan koel:init" < "artisan db:seed", despite MySQL database engine used
|
|
aDEPS=("php$PHP_VERSION-bcmath" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-sqlite3" "php$PHP_VERSION-xml")
|
|
|
|
# Grab latest supported release: Koel v6 requires PHP 8.0 or higher for Laravel 9
|
|
if (( ${PHP_VERSION::1} > 7 ))
|
|
then
|
|
aDEPS+=("php$PHP_VERSION-curl")
|
|
local fallback_url='https://github.com/koel/koel/releases/download/v8.1.0/koel-v8.1.0.tar.gz' aphp_deps=('curl' 'dom')
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/koel/koel/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/koel-[^"\/]*\.tar\.gz"$/{print $4}')"
|
|
else
|
|
aDEPS+=("php$PHP_VERSION-json")
|
|
local aphp_deps=('json')
|
|
Download_Install 'https://github.com/koel/koel/releases/download/v5.1.14/koel-v5.1.14.tar.gz'
|
|
fi
|
|
|
|
# Reinstall: Clear previous install, but keep existing config file
|
|
if [[ -d '/mnt/dietpi_userdata/koel' ]]
|
|
then
|
|
[[ -f '/mnt/dietpi_userdata/koel/.env' ]] && G_EXEC mv /mnt/dietpi_userdata/koel/.env koel/
|
|
G_EXEC rm -R /mnt/dietpi_userdata/koel
|
|
fi
|
|
[[ -f 'koel/.env' ]] || G_EXEC cp koel/.env{.example,}
|
|
G_EXEC mv koel /mnt/dietpi_userdata/koel
|
|
|
|
# Enable required PHP modules
|
|
G_EXEC phpenmod bcmath ctype fileinfo mbstring pdo_mysql pdo_sqlite tokenizer xml "${aphp_deps[@]}"
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/koel koel
|
|
|
|
# Permissions
|
|
G_EXEC cd /mnt/dietpi_userdata/koel
|
|
G_EXEC chmod 0600 .env
|
|
G_EXEC chown -R koel:root .
|
|
|
|
# Create database and apply to config file if it does not exist yet
|
|
if [[ ! -d '/mnt/dietpi_userdata/mysql/koel' ]]
|
|
then
|
|
# Create random alphanumeric 30 characters password
|
|
local password=$(tr -dc '[:alnum:]' < /dev/random | head -c30)
|
|
/boot/dietpi/func/create_mysql_db koel koel "$password"
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'DB_PASSWORD=' "DB_PASSWORD=$password" .env
|
|
unset -v password
|
|
G_CONFIG_INJECT 'DB_CONNECTION=' 'DB_CONNECTION=mysql' .env
|
|
G_CONFIG_INJECT 'DB_HOST=' 'DB_HOST=localhost' .env
|
|
G_CONFIG_INJECT 'DB_DATABASE=' 'DB_DATABASE=koel' .env
|
|
G_CONFIG_INJECT 'DB_USERNAME=' 'DB_USERNAME=koel' .env
|
|
G_CONFIG_INJECT 'MEDIA_PATH=' 'MEDIA_PATH=/mnt/dietpi_userdata/Music' .env
|
|
G_CONFIG_INJECT 'FFMPEG_PATH=' "FFMPEG_PATH=$(command -v ffmpeg)" .env
|
|
|
|
# Else assure database server runs
|
|
else
|
|
G_EXEC systemctl restart mariadb
|
|
fi
|
|
|
|
Download_Test_Media
|
|
|
|
# Init
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u koel -- "php$PHP_VERSION" artisan koel:init -n --no-assets
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u koel -- "php$PHP_VERSION" artisan koel:sync
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Service: Run on port 8003 by default to avoid conflict with Icecast
|
|
cat << _EOF_ > /etc/systemd/system/koel.service
|
|
[Unit]
|
|
Description=Koel (DietPi)
|
|
Documentation=https://docs.koel.dev/
|
|
Wants=network-online.target
|
|
After=network-online.target mariadb.service
|
|
|
|
[Service]
|
|
SyslogIdentifier=Koel
|
|
User=koel
|
|
WorkingDirectory=/mnt/dietpi_userdata/koel
|
|
ExecStart=$(command -v "php$PHP_VERSION") /mnt/dietpi_userdata/koel/artisan serve --host 0.0.0.0 --port 8003
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 144 sonarr # Sonarr
|
|
then
|
|
# Sonarr v4 does not support ARMv6
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
# https://sonarr.tv/#downloads-v3-linux-debian
|
|
# APT key
|
|
G_EXEC eval 'curl -sSf '\''https://keyserver.ubuntu.com/pks/lookup?search=0x2009837CBFFD68F45BC180471F4F90DE2A9B4BF8&op=get'\'' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-sonarr.gpg --yes'
|
|
|
|
# APT list: Buster is the latest available suite: https://apt.sonarr.tv/debian/dists/
|
|
G_EXEC eval 'echo '\''deb https://apt.sonarr.tv/debian buster main'\'' > /etc/apt/sources.list.d/sonarr.list'
|
|
G_AGUP
|
|
|
|
# Pre-configure DEB package
|
|
G_EXEC eval "debconf-set-selections <<< 'sonarr sonarr/owning_group string dietpi'"
|
|
G_EXEC eval "debconf-set-selections <<< 'sonarr sonarr/config_directory string /mnt/dietpi_userdata/sonarr'"
|
|
|
|
# Install Sonarr and mediainfo
|
|
G_AGI sonarr mediainfo
|
|
G_EXEC systemctl stop sonarr
|
|
|
|
local install_dir='/usr/lib/sonarr'
|
|
local exe="$(command -v mono) $install_dir/bin/Sonarr.exe"
|
|
else
|
|
# Pre-v9.9 cleanup
|
|
[[ -f '/etc/apt/sources.list.d/sonarr.list' ]] && G_EXEC rm /etc/apt/sources.list.d/sonarr.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-sonarr.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-sonarr.gpg
|
|
if dpkg-query -s 'sonarr' &> /dev/null
|
|
then
|
|
[[ -d '/mnt/dietpi_userdata/sonarr' ]] && G_EXEC mv /mnt/dietpi_userdata/sonarr{,_bak}
|
|
G_AGP sonarr
|
|
[[ -d '/mnt/dietpi_userdata/sonarr_bak' ]] && G_EXEC mv /mnt/dietpi_userdata/sonarr{_bak,}
|
|
# Offer to uninstall Mono
|
|
if (( ${aSOFTWARE_INSTALL_STATE[150]} == 2 ))
|
|
then
|
|
G_WHIP_BUTTON_OK_TEXT='Yes' G_WHIP_BUTTON_CANCEL_TEXT='No' G_WHIP_DEFAULT_ITEM='Yes'
|
|
G_WHIP_YESNO '[ INFO ] Mono is no dependency of Sonarr v4 anymore
|
|
\nA migration from Sonarr v3 to Sonarr v4 is done, which does not require Mono anymore. If you do not need Mono for something else, it can hence be uninstalled to free up some space.
|
|
\nDo you want to uninstall Mono now? It can be done any time later via "dietpi-software".' && aSOFTWARE_INSTALL_STATE[150]=-1
|
|
fi
|
|
fi
|
|
|
|
# APT dependencies
|
|
# - .NET: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
|
|
# Download
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/Sonarr/Sonarr/releases/download/v4.0.16.2944/Sonarr.main.4.0.16.2944.linux-$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Sonarr/Sonarr/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*linux-$arch\.tar\.gz\"$/{print \$4}")"
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/sonarr' ]] && G_EXEC rm -R /opt/sonarr
|
|
G_EXEC mv Sonarr /opt/sonarr
|
|
|
|
local install_dir='/opt/sonarr'
|
|
local exe="$install_dir/Sonarr"
|
|
fi
|
|
|
|
# Pre-v7.1: Remove Sonarr v2 key, PID file and database backups from DietPi-Arr_to_RAM
|
|
if [[ -f '/etc/apt/trusted.gpg' && $(apt-key --keyring /etc/apt/trusted.gpg list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]]
|
|
then
|
|
G_EXEC apt-key --keyring /etc/apt/trusted.gpg del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493'
|
|
[[ $(apt-key --keyring /etc/apt/trusted.gpg list 2> /dev/null) ]] || G_EXEC rm /etc/apt/trusted.gpg
|
|
fi
|
|
[[ -f '/mnt/dietpi_userdata/sonarr/nzbdrone.pid' ]] && G_EXEC rm /mnt/dietpi_userdata/sonarr/nzbdrone.pid
|
|
[[ -f '/mnt/dietpi_userdata/sonarr/nzbdrone.db.bak' ]] && G_EXEC rm /mnt/dietpi_userdata/sonarr/nzbdrone.db.bak
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/sonarr
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/sonarr sonarr
|
|
|
|
# Service: https://github.com/Sonarr/Sonarr/blob/phantom-develop/distribution/debian/sonarr.service
|
|
cat << _EOF_ > /etc/systemd/system/sonarr.service
|
|
[Unit]
|
|
Description=Sonarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Sonarr
|
|
User=sonarr
|
|
UMask=002
|
|
LogsDirectory=sonarr
|
|
ExecStart=$exe -nobrowser -data=/mnt/dietpi_userdata/sonarr
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-$install_dir -/mnt -/media -/var/log/sonarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/sonarr/logs*
|
|
G_EXEC ln -s /var/log/sonarr /mnt/dietpi_userdata/sonarr/logs
|
|
G_EXEC ln -s /var/log/sonarr/logs.db /mnt/dietpi_userdata/sonarr/logs.db
|
|
G_EXEC ln -s /var/log/sonarr/logs.db-shm /mnt/dietpi_userdata/sonarr/logs.db-shm
|
|
G_EXEC ln -s /var/log/sonarr/logs.db-wal /mnt/dietpi_userdata/sonarr/logs.db-wal
|
|
|
|
# Permissions
|
|
G_EXEC chown -R sonarr:dietpi /mnt/dietpi_userdata/sonarr "$install_dir"
|
|
fi
|
|
|
|
if To_Install 145 radarr # Radarr
|
|
then
|
|
# APT dependencies
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
aDEPS=('mediainfo')
|
|
else
|
|
# .NET: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
fi
|
|
|
|
# Download
|
|
# - ARMv6: Radarr v4 does not support Mono anymore
|
|
local url='https://github.com/Radarr/Radarr/releases/download/v3.2.2.5080/Radarr.master.3.2.2.5080.linux.tar.gz'
|
|
if (( $G_HW_ARCH != 1 ))
|
|
then
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
|
|
url=$(curl -sSfL 'https://api.github.com/repos/Radarr/Radarr/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*linux-core-$arch\.tar\.gz\"$/{print \$4}")
|
|
local fallback_url="https://github.com/Radarr/Radarr/releases/download/v6.0.4.10291/Radarr.master.6.0.4.10291.linux-core-$arch.tar.gz"
|
|
fi
|
|
Download_Install "$url"
|
|
|
|
# Bullseye: Use system SQLite library: https://wiki.servarr.com/radarr/faq#radarr-wont-start-on-debian-11-or-older-systems-due-to-sqlite-version
|
|
(( $G_DISTRO < 7 && $G_HW_ARCH != 1 )) && G_EXEC ln -sf /usr/lib/*/libsqlite3.so.0 Radarr/libe_sqlite3.so
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/radarr' ]] && G_EXEC rm -R /opt/radarr
|
|
G_EXEC mv Radarr /opt/radarr
|
|
|
|
# Radarr v2: Remove old PID file and database backups from DietPi-Arr_to_RAM
|
|
[[ -f '/mnt/dietpi_userdata/radarr/nzbdrone.pid' ]] && G_EXEC rm /mnt/dietpi_userdata/radarr/nzbdrone.pid
|
|
[[ -f '/mnt/dietpi_userdata/radarr/nzbdrone.db.bak' ]] && G_EXEC rm /mnt/dietpi_userdata/radarr/nzbdrone.db.bak
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/radarr
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/radarr radarr
|
|
|
|
# Service: https://github.com/Radarr/Radarr/wiki/Autostart-on-Linux#service-file
|
|
cat << '_EOF_' > /etc/systemd/system/radarr.service
|
|
[Unit]
|
|
Description=Radarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Radarr
|
|
User=radarr
|
|
UMask=002
|
|
LogsDirectory=radarr
|
|
ExecStart=/opt/radarr/Radarr -nobrowser -data=/mnt/dietpi_userdata/radarr
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/radarr -/mnt -/media -/var/log/radarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# - ARMv6 devices use Mono
|
|
(( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) /opt/radarr/Radarr.exe -nobrowser -data=/mnt/dietpi_userdata/radarr" /etc/systemd/system/radarr.service
|
|
|
|
# Logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/radarr/logs*
|
|
G_EXEC ln -s /var/log/radarr /mnt/dietpi_userdata/radarr/logs
|
|
G_EXEC ln -s /var/log/radarr/logs.db /mnt/dietpi_userdata/radarr/logs.db
|
|
G_EXEC ln -s /var/log/radarr/logs.db-shm /mnt/dietpi_userdata/radarr/logs.db-shm
|
|
G_EXEC ln -s /var/log/radarr/logs.db-wal /mnt/dietpi_userdata/radarr/logs.db-wal
|
|
|
|
# Permissions
|
|
G_EXEC chown -R radarr:dietpi /mnt/dietpi_userdata/radarr /opt/radarr
|
|
fi
|
|
|
|
if To_Install 106 lidarr # Lidarr
|
|
then
|
|
# APT dependencies
|
|
aDEPS=('mediainfo')
|
|
# - .NET: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
if (( $G_HW_ARCH != 1 ))
|
|
then
|
|
case $G_DISTRO in
|
|
6) aDEPS+=('libicu67');;
|
|
7) aDEPS+=('libicu72');;
|
|
*) aDEPS+=('libicu76');;
|
|
esac
|
|
fi
|
|
|
|
# Pre-v7.5 ARMv6: Migrate old install dir
|
|
[[ -d '/opt/Lidarr' && ! -d '/opt/lidarr' ]] && G_EXEC mv /opt/{L,l}idarr
|
|
|
|
# Download
|
|
# - ARMv6: Lidarr v1 does not support Mono anymore
|
|
local url='https://github.com/Lidarr/Lidarr/releases/download/v0.8.1.2135/Lidarr.master.0.8.1.2135.linux.tar.gz'
|
|
if (( $G_HW_ARCH != 1 ))
|
|
then
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
|
|
url=$(curl -sSfL 'https://api.github.com/repos/Lidarr/Lidarr/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*linux-core-$arch\.tar\.gz\"$/{print \$4}")
|
|
local fallback_url="https://github.com/Lidarr/Lidarr/releases/download/v3.1.0.4875/Lidarr.master.3.1.0.4875.linux-core-$arch.tar.gz"
|
|
fi
|
|
Download_Install "$url"
|
|
|
|
# Bullseye: Use system SQLite library: https://wiki.servarr.com/lidarr/faq#lidarr-wont-start-on-debian-11-or-older-systems-due-to-sqlite-version
|
|
(( $G_DISTRO < 7 && $G_HW_ARCH != 1 )) && G_EXEC ln -sf /usr/lib/*/libsqlite3.so.0 Lidarr/libe_sqlite3.so
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/lidarr' ]] && G_EXEC rm -R /opt/lidarr
|
|
G_EXEC mv Lidarr /opt/lidarr
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/lidarr
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/lidarr lidarr
|
|
|
|
# Service: https://github.com/lidarr/Lidarr/wiki/Autostart-on-Linux#systemd
|
|
cat << _EOF_ > /etc/systemd/system/lidarr.service
|
|
[Unit]
|
|
Description=Lidarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Lidarr
|
|
User=lidarr
|
|
UMask=002
|
|
LogsDirectory=lidarr
|
|
ExecStart=/opt/lidarr/Lidarr -nobrowser -data=/mnt/dietpi_userdata/lidarr
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/lidarr -/mnt -/media -/var/log/lidarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# - ARMv6 devices use Mono
|
|
(( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) /opt/lidarr/Lidarr.exe -nobrowser -data=/mnt/dietpi_userdata/lidarr" /etc/systemd/system/lidarr.service
|
|
|
|
# Logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/lidarr/logs*
|
|
G_EXEC ln -s /var/log/lidarr /mnt/dietpi_userdata/lidarr/logs
|
|
G_EXEC ln -s /var/log/lidarr/logs.db /mnt/dietpi_userdata/lidarr/logs.db
|
|
G_EXEC ln -s /var/log/lidarr/logs.db-shm /mnt/dietpi_userdata/lidarr/logs.db-shm
|
|
G_EXEC ln -s /var/log/lidarr/logs.db-wal /mnt/dietpi_userdata/lidarr/logs.db-wal
|
|
|
|
# Permissions
|
|
G_EXEC chown -R lidarr:dietpi /mnt/dietpi_userdata/lidarr /opt/lidarr
|
|
fi
|
|
|
|
if To_Install 180 bazarr # Bazarr: https://wiki.bazarr.media/Getting-Started/Installation/Linux/linux/
|
|
then
|
|
# APT deps
|
|
aDEPS=('unzip')
|
|
(( $G_DISTRO > 7 )) && aDEPS+=('7zip') || aDEPS+=('p7zip')
|
|
# - ARMv6 does not support unrar-nonfree and Bazarr does not support unrar-free, so we need to use "unar": https://github.com/morpheus65535/bazarr/issues/2172
|
|
(( $G_HW_ARCH == 1 )) && aDEPS+=('unar')
|
|
Python_Deps lxml numpy pillow
|
|
|
|
# Download
|
|
Download_Install 'https://github.com/morpheus65535/bazarr/releases/latest/download/bazarr.zip' bazarr
|
|
|
|
# Python deps
|
|
# - Allow Pillow to be compiled
|
|
G_EXEC sed --follow-symlinks -i 's/ --only-binary=Pillow$//' bazarr/requirements.txt
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -Ur bazarr/requirements.txt
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/bazarr' ]] && G_EXEC rm -R /opt/bazarr
|
|
G_EXEC mv bazarr /opt
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/bazarr
|
|
|
|
# Log to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/bazarr/log
|
|
G_EXEC ln -s /var/log/bazarr /mnt/dietpi_userdata/bazarr/log
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/bazarr bazarr
|
|
|
|
# Permissions
|
|
G_EXEC chown -R bazarr:0 /mnt/dietpi_userdata/bazarr /opt/bazarr
|
|
|
|
# Service: https://wiki.bazarr.media/Getting-Started/Autostart/Linux/linux/
|
|
cat << '_EOF_' > /etc/systemd/system/bazarr.service
|
|
[Unit]
|
|
Description=Bazarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target sonarr.service radarr.service
|
|
|
|
[Service]
|
|
SyslogIdentifier=Bazarr
|
|
User=bazarr
|
|
UMask=002
|
|
LogsDirectory=bazarr
|
|
WorkingDirectory=/mnt/dietpi_userdata/bazarr
|
|
ExecStart=/usr/bin/python3 /opt/bazarr/bazarr.py -c /mnt/dietpi_userdata/bazarr
|
|
KillSignal=SIGINT
|
|
TimeoutStopSec=20
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
PrivateTmp=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/bazarr -/mnt -/media -/var/log/bazarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# On fresh install, pre-configure for Sonarr and Radarr when found
|
|
if (( ${aSOFTWARE_INSTALL_STATE[144]} + ${aSOFTWARE_INSTALL_STATE[145]} > 0 )) && CREATE_CONFIG_CONTENT='^sonarr:' Create_Config /mnt/dietpi_userdata/bazarr/config/config.yaml bazarr
|
|
then
|
|
# Sonarr
|
|
if (( ${aSOFTWARE_INSTALL_STATE[144]} > 0 )) && CREATE_CONFIG_CONTENT='ApiKey' Create_Config /mnt/dietpi_userdata/sonarr/config.xml sonarr
|
|
then
|
|
local port=$(sed -nE '/<Port>[0-9]+<\/Port>/{s/^.*<Port>([0-9]+)<\/Port>.*$/\1/p;q}' /mnt/dietpi_userdata/sonarr/config.xml)
|
|
local apikey=$(sed -nE '/<ApiKey>.+<\/ApiKey>/{s/^.*<ApiKey>(.+)<\/ApiKey>.*$/\1/p;q}' /mnt/dietpi_userdata/sonarr/config.xml)
|
|
G_EXEC sed --follow-symlinks -i '/^sonarr:/,/^[^[:blank:]]/s/ ip: .*$/ ip: 127.0.0.1/' /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i "/^sonarr:/,/^[^[:blank:]]/s/ port = .*$/ port: $port/" /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i '/^sonarr:/,/^[^[:blank:]]/s/ base_url: .*$/ base_url: \//' /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i "/^sonarr:/,/^[^[:blank:]]/s/ apikey: .*$/ apikey: $apikey/" /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_CONFIG_INJECT 'use_sonarr:' ' use_sonarr: true' /mnt/dietpi_userdata/bazarr/config/config.yaml '^general:'
|
|
fi
|
|
# Radarr
|
|
if (( ${aSOFTWARE_INSTALL_STATE[145]} > 0 )) && CREATE_CONFIG_CONTENT='ApiKey' Create_Config /mnt/dietpi_userdata/radarr/config.xml radarr
|
|
then
|
|
local port=$(sed -nE '/<Port>[0-9]+<\/Port>/{s/^.*<Port>([0-9]+)<\/Port>.*$/\1/p;q}' /mnt/dietpi_userdata/radarr/config.xml)
|
|
local apikey=$(sed -nE '/<ApiKey>.+<\/ApiKey>/{s/^.*<ApiKey>(.+)<\/ApiKey>.*$/\1/p;q}' /mnt/dietpi_userdata/radarr/config.xml)
|
|
G_EXEC sed --follow-symlinks -i '/^radarr:/,/^[^[:blank:]]/s/ ip: .*$/ ip: 127.0.0.1/' /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i "/^radarr:/,/^[^[:blank:]]/s/ port: .*$/ port: $port/" /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i '/^radarr:/,/^[^[:blank:]]/s/ base_url: .*$/ base_url: \//' /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_EXEC sed --follow-symlinks -i "/^radarr:/,/^[^[:blank:]]/s/ apikey: .*$/ apikey: $apikey/" /mnt/dietpi_userdata/bazarr/config/config.yaml
|
|
G_CONFIG_INJECT 'use_radarr:' ' use_radarr: true' /mnt/dietpi_userdata/bazarr/config/config.yaml '^general:'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if To_Install 146 tautulli # Tautulli
|
|
then
|
|
# Download
|
|
local url='https://github.com/Tautulli/Tautulli.git'
|
|
G_CHECK_URL "$url"
|
|
G_THREAD_START git clone --depth 1 "$url"
|
|
G_AGI python3-pkg-resources
|
|
G_THREAD_WAIT
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/tautulli' ]] && G_EXEC rm -R /opt/tautulli
|
|
G_EXEC mv Tautulli /opt/tautulli
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/tautulli tautulli
|
|
|
|
# Directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/tautulli
|
|
|
|
# Service: https://github.com/Tautulli/Tautulli/blob/master/init-scripts/init.systemd
|
|
cat << '_EOF_' > /etc/systemd/system/tautulli.service
|
|
[Unit]
|
|
Description=Tautulli (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Tautulli
|
|
User=tautulli
|
|
ExecStart=/usr/bin/python3 /opt/tautulli/Tautulli.py -q --nolaunch --config /mnt/dietpi_userdata//tautulli/config.ini --datadir /mnt/dietpi_userdata/tautulli
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R tautulli:tautulli /{opt,mnt/dietpi_userdata}/tautulli
|
|
fi
|
|
|
|
if To_Install 147 jackett # Jackett
|
|
then
|
|
# ARMv6 requires Mono: https://github.com/Jackett/Jackett#installation-on-linux-armv6-or-below
|
|
# .NET dependency: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
if (( $G_HW_ARCH != 1 ))
|
|
then
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
fi
|
|
|
|
# Download
|
|
case $G_HW_ARCH in
|
|
1) local arch='Mono';;
|
|
2) local arch='LinuxARM32';;
|
|
3) local arch='LinuxARM64';;
|
|
*) local arch='LinuxAMDx64';;
|
|
esac
|
|
local fallback_url="https://github.com/Jackett/Jackett/releases/download/v0.24.445/Jackett.Binaries.$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Jackett/Jackett/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/Jackett\.Binaries\.$arch\.tar\.gz\"$/{print \$4}")"
|
|
|
|
# Move existing configs to unpacked install dir
|
|
[[ -d '/opt/jackett/Jackett' ]] && G_EXEC mv /opt/jackett/Jackett Jackett/
|
|
[[ -d '/opt/jackett/.mono' ]] && G_EXEC mv /opt/jackett/.mono Jackett/
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/jackett' ]] && G_EXEC rm -R /opt/jackett
|
|
G_EXEC mv Jackett /opt/jackett
|
|
|
|
# User
|
|
Create_User -d /opt/jackett jackett
|
|
|
|
# Permissions
|
|
G_EXEC chown -R jackett:jackett /opt/jackett
|
|
|
|
# Service: https://github.com/Jackett/Jackett/wiki/systemd-service
|
|
# - Wrap execution into shell to work around: https://github.com/Jackett/Jackett/issues/5208
|
|
cat << '_EOF_' > /etc/systemd/system/jackett.service
|
|
[Unit]
|
|
Description=Jackett (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Jackett
|
|
User=jackett
|
|
WorkingDirectory=/opt/jackett
|
|
Environment=XDG_CONFIG_HOME=/opt/jackett
|
|
ExecStart=/bin/dash -c '/opt/jackett/jackett --NoRestart; ec=$?; while pgrep -u jackett JackettUpdater > /dev/null; do sleep 1; done; exit $ec'
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
PrivateTmp=true
|
|
ProtectKernelTunables=true
|
|
ProtectKernelModules=true
|
|
ProtectControlGroups=true
|
|
NoNewPrivileges=true
|
|
ReadWritePaths=-/opt/jackett
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# - ARMv6 devices use Mono
|
|
(( $G_HW_ARCH == 1 )) && G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v mono) /opt/jackett/JackettConsole.exe --NoRestart" /etc/systemd/system/jackett.service
|
|
fi
|
|
|
|
if To_Install 149 nzbget # NZBGet
|
|
then
|
|
local reinstall=0
|
|
[[ -f '/mnt/dietpi_userdata/nzbget/nzbget.conf' ]] && reinstall=1
|
|
|
|
local fallback_url='https://github.com/nzbgetcom/nzbget/releases/download/v25.4/nzbget-25.4-bin-linux.run'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/nzbgetcom/nzbget/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/nzbget-[^"/]*-bin-linux.run"$/{print $4}')" nzbget.run
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/nzbget
|
|
G_EXEC_OUTPUT=1 G_EXEC dash nzbget.run --destdir /mnt/dietpi_userdata/nzbget
|
|
G_EXEC rm nzbget.run
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/nzbget nzbget
|
|
|
|
# Permissions
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_EXEC chown -R nzbget:root /mnt/dietpi_userdata/nzbget
|
|
|
|
# Config
|
|
if (( ! $reinstall ))
|
|
then
|
|
G_CONFIG_INJECT 'MainDir=' 'MainDir=/mnt/dietpi_userdata/downloads' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'DestDir=' 'DestDir=/mnt/dietpi_userdata/downloads/complete' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'WriteLog=' 'WriteLog=none' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'ControlUsername=' 'ControlUsername=admin' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'ControlPassword=' "ControlPassword=$GLOBAL_PW" /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
|
|
# Umask: https://github.com/MichaIng/DietPi/issues/1999
|
|
G_CONFIG_INJECT 'UMask=' 'UMask=0002' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
|
|
# Optimisations
|
|
G_CONFIG_INJECT 'CrcCheck=' 'CrcCheck=no' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'ParScan=' 'ParScan=limited' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'ParThreads=' "ParThreads=$G_HW_CPU_CORES" /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'DebugTarget=' 'DebugTarget=none' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'DetailTarget=' 'DetailTarget=none' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'CrashTrace=' 'CrashTrace=no' /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'ParBuffer=' "ParBuffer=$(Optimise_BitTorrent 0)" /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'ArticleCache=' "ArticleCache=$(Optimise_BitTorrent 0)" /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
G_CONFIG_INJECT 'WriteBuffer=' "WriteBuffer=$(Optimise_BitTorrent 0)" /mnt/dietpi_userdata/nzbget/nzbget.conf
|
|
fi
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/nzbget.service
|
|
[Unit]
|
|
Description=NZBGet (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=nzbget
|
|
WorkingDirectory=/mnt/dietpi_userdata/nzbget
|
|
ExecStart=/mnt/dietpi_userdata/nzbget/nzbget -so OutputMode=log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 151 prowlarr # Prowlarr
|
|
then
|
|
# .NET dependency: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
|
|
# Download
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
local fallback_url="https://github.com/Prowlarr/Prowlarr/releases/download/v2.3.0.5236/Prowlarr.master.2.3.0.5236.linux-core-$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Prowlarr/Prowlarr/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*linux-core-$arch\.tar\.gz\"$/{print \$4}")"
|
|
|
|
# Bullseye: Use system SQLite library: https://wiki.servarr.com/prowlarr/faq#prowlarr-wont-start-on-debian-11-or-older-systems-due-to-sqlite-version
|
|
(( $G_DISTRO < 7 )) && G_EXEC ln -sf /usr/lib/*/libsqlite3.so.0 Prowlarr/libe_sqlite3.so
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/prowlarr' ]] && G_EXEC rm -R /opt/prowlarr
|
|
G_EXEC mv Prowlarr /opt/prowlarr
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/prowlarr
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/prowlarr prowlarr
|
|
|
|
# Service: https://wiki.servarr.com/prowlarr/installation
|
|
cat << '_EOF_' > /etc/systemd/system/prowlarr.service
|
|
[Unit]
|
|
Description=Prowlarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Prowlarr
|
|
User=prowlarr
|
|
UMask=002
|
|
LogsDirectory=prowlarr
|
|
ExecStart=/opt/prowlarr/Prowlarr -nobrowser -data=/mnt/dietpi_userdata/prowlarr
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/prowlarr -/mnt -/media -/var/log/prowlarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/prowlarr/logs*
|
|
G_EXEC ln -s /var/log/prowlarr /mnt/dietpi_userdata/prowlarr/logs
|
|
G_EXEC ln -s /var/log/prowlarr/logs.db /mnt/dietpi_userdata/prowlarr/logs.db
|
|
G_EXEC ln -s /var/log/prowlarr/logs.db-shm /mnt/dietpi_userdata/prowlarr/logs.db-shm
|
|
G_EXEC ln -s /var/log/prowlarr/logs.db-wal /mnt/dietpi_userdata/prowlarr/logs.db-wal
|
|
|
|
# Permissions
|
|
G_EXEC chown -R prowlarr:dietpi /mnt/dietpi_userdata/prowlarr /opt/prowlarr
|
|
fi
|
|
|
|
if To_Install 203 readarr # Readarr
|
|
then
|
|
# .NET dependency: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
|
|
# Download
|
|
case $G_HW_ARCH in
|
|
2) local arch='arm';;
|
|
3) local arch='arm64';;
|
|
*) local arch='x64';;
|
|
esac
|
|
local fallback_url="https://github.com/Readarr/Readarr/releases/download/v0.4.18.2805/Readarr.develop.0.4.18.2805.linux-core-$arch.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Readarr/Readarr/releases' | mawk -F\" "/^ *\"browser_download_url\": \".*linux-core-$arch\.tar\.gz\"$/{print \$4}" | head -1)"
|
|
|
|
# Install: Remove previous instance on reinstall
|
|
[[ -d '/opt/readarr' ]] && G_EXEC rm -R /opt/readarr
|
|
G_EXEC mv Readarr /opt/readarr
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/readarr
|
|
|
|
# User
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/readarr readarr
|
|
|
|
# Service: https://wiki.servarr.com/readarr/installation
|
|
cat << '_EOF_' > /etc/systemd/system/readarr.service
|
|
[Unit]
|
|
Description=Readarr (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=Readarr
|
|
User=readarr
|
|
UMask=002
|
|
LogsDirectory=readarr
|
|
ExecStart=/opt/readarr/Readarr -nobrowser -data=/mnt/dietpi_userdata/readarr
|
|
TimeoutStopSec=20
|
|
KillMode=process
|
|
Restart=on-failure
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/readarr -/mnt -/media -/var/log/readarr -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/readarr/logs*
|
|
G_EXEC ln -s /var/log/readarr /mnt/dietpi_userdata/readarr/logs
|
|
G_EXEC ln -s /var/log/readarr/logs.db /mnt/dietpi_userdata/readarr/logs.db
|
|
G_EXEC ln -s /var/log/readarr/logs.db-shm /mnt/dietpi_userdata/readarr/logs.db-shm
|
|
G_EXEC ln -s /var/log/readarr/logs.db-wal /mnt/dietpi_userdata/readarr/logs.db-wal
|
|
|
|
# Permissions
|
|
G_EXEC chown -R readarr:dietpi /mnt/dietpi_userdata/readarr /opt/readarr
|
|
fi
|
|
|
|
if To_Install 155 htpc-manager # HTPC Manager
|
|
then
|
|
local url='https://github.com/HTPC-Manager/HTPC-Manager'
|
|
G_CHECK_URL "$url"
|
|
|
|
# APT deps
|
|
Python_Deps -i cryptography pillow psutil pynacl
|
|
|
|
if [[ -d '/mnt/dietpi_userdata/htpc-manager/.git' ]]
|
|
then
|
|
G_EXEC cd /mnt/dietpi_userdata/htpc-manager
|
|
G_EXEC_OUTPUT=1 G_EXEC git remote set-url origin "$url"
|
|
G_EXEC_OUTPUT=1 G_EXEC git fetch --depth=1 origin
|
|
G_EXEC_OUTPUT=1 G_EXEC git reset --hard origin
|
|
G_EXEC_OUTPUT=1 G_EXEC git clean -dxfe '/userdata'
|
|
else
|
|
G_EXEC_OUTPUT=1 G_EXEC git clone --depth=1 "$url"
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/htpc-manager
|
|
G_EXEC cp -a HTPC-Manager/. /mnt/dietpi_userdata/htpc-manager/
|
|
G_EXEC rm -R HTPC-Manager
|
|
G_EXEC cd /mnt/dietpi_userdata/htpc-manager
|
|
G_EXEC_OUTPUT=1 G_EXEC git reset --hard origin
|
|
G_EXEC_OUTPUT=1 G_EXEC git clean -dxfe '/userdata'
|
|
fi
|
|
|
|
# Python deps
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -Ur requirements.txt
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/htpc-manager.service
|
|
[Unit]
|
|
Description=HTPC Manager (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=HTPC Manager
|
|
ExecStart=/usr/bin/python3 -OO /mnt/dietpi_userdata/htpc-manager/Htpc.py
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 153 octoprint # OctoPrint
|
|
then
|
|
# Pre-create user and its home directory to allow user-level (Rust and) Python instance
|
|
Create_User -G dialout,tty,video -d /mnt/dietpi_userdata/octoprint octoprint
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/octoprint
|
|
G_EXEC chown -R octoprint:octoprint /mnt/dietpi_userdata/octoprint
|
|
|
|
# Deps
|
|
Python_Deps -i -u octoprint cffi netifaces psutil pydantic
|
|
|
|
# Clear pip cache in case it got somehow created
|
|
[[ -d '/mnt/dietpi_userdata/octoprint/.cache' ]] && G_EXEC rm -R /mnt/dietpi_userdata/octoprint/.cache
|
|
|
|
# Install OctoPrint
|
|
# shellcheck disable=SC2016
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u octoprint -- dash -c 'PATH="$HOME/.cargo/bin:$PATH" pip3 install -U --user --no-warn-script-location octoprint'
|
|
|
|
# Service: https://github.com/OctoPrint/OctoPrint/blob/master/scripts/octoprint.service
|
|
cat << '_EOF_' > /etc/systemd/system/octoprint.service
|
|
[Unit]
|
|
Description=OctoPrint (DietPi)
|
|
Documentation=https://dietpi.com/docs/software/printing/#octoprint
|
|
Wants=network-online.target
|
|
After=network-online.target mjpg-streamer.service
|
|
|
|
[Service]
|
|
Environment="LC_ALL=C.UTF-8" "LANG=C.UTF-8"
|
|
User=octoprint
|
|
ExecStart=/mnt/dietpi_userdata/octoprint/.local/bin/octoprint serve
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# CLI alias
|
|
echo "alias octoprint='sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint'" > /etc/bashrc.d/dietpi-octoprint.sh
|
|
|
|
# On fresh installs, change listening port to 5001 to avoid conflict with Shairport Sync.
|
|
[[ -f '/mnt/dietpi_userdata/octoprint/.octoprint/config.yaml' ]] || G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.port '5001'
|
|
|
|
# Apply service and system commands: Allow execution via specific sudoers config, use "which" for "reboot" and "poweroff", since we create shell functions in dietpi-globals to bypass logind calls if logind is not running.
|
|
# shellcheck disable=SC2230
|
|
echo "octoprint ALL=NOPASSWD: $(command -v systemctl) restart octoprint, $(which reboot), $(which poweroff)" > /etc/sudoers.d/octoprint
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.commands.serverRestartCommand 'sudo systemctl restart octoprint'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.commands.systemRestartCommand 'sudo reboot'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.commands.systemShutdownCommand 'sudo poweroff'
|
|
|
|
# mjpg-streamer: Configure OctoPrint to use it if installed
|
|
if (( ${aSOFTWARE_INSTALL_STATE[137]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Configuring OctoPrint to use mjpg-streamer for webcam support'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.stream "http://$(G_GET_NET ip):8082/?action=stream"
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.snapshot 'http://127.0.0.1:8082/?action=snapshot'
|
|
G_EXEC runuser -u octoprint -- /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.ffmpeg "$(command -v ffmpeg)"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 187 cups # CUPS
|
|
then
|
|
# Download base configuration if it does not exist yet
|
|
[[ -f '/etc/cups/cupsd.conf' ]] || dps_index=$software_id Download_Install 'cupsd.conf' /etc/cups/cupsd.conf
|
|
|
|
G_AGI cups
|
|
G_EXEC systemctl stop cups
|
|
|
|
G_EXEC chown root:lp /etc/cups/ /etc/cups/ppd/ /etc/cups/ssl/
|
|
fi
|
|
|
|
if To_Install 154 roonserver # Roon Server: https://help.roonlabs.com/portal/en/kb/articles/linux-install#Manual_Install
|
|
then
|
|
# .NET dependency: https://github.com/dotnet/docs/blob/main/docs/core/install/linux-debian.md#dependencies
|
|
case $G_DISTRO in
|
|
6) aDEPS=('libicu67');;
|
|
7) aDEPS=('libicu72');;
|
|
*) aDEPS=('libicu76');;
|
|
esac
|
|
|
|
G_WHIP_BUTTON_OK_TEXT='Early Access' G_WHIP_BUTTON_CANCEL_TEXT='Stable'
|
|
G_WHIP_DEFAULT_ITEM=$(grep -cm1 '^[[:blank:]]*SOFTWARE_ROONSERVER_EARLYACCESS=1' /boot/dietpi.txt)
|
|
if G_WHIP_YESNO 'Do you want to install regular stable Roon Server builds, or early access builds?
|
|
\nOfficial info about the Roon Early Access Program can be found here:
|
|
- https://help.roonlabs.com/portal/en/kb/articles/roon-early-access-program
|
|
\nNB: Early access builds have a higher chance to contain bugs, and you may need to restore a database backup when reverting from early access to stable builds.'
|
|
then
|
|
Download_Install 'https://download.roonlabs.net/builds/earlyaccess/RoonServer_linuxx64.tar.bz2'
|
|
G_CONFIG_INJECT 'SOFTWARE_ROONSERVER_EARLYACCESS=' 'SOFTWARE_ROONSERVER_EARLYACCESS=1' /boot/dietpi.txt
|
|
else
|
|
Download_Install 'https://download.roonlabs.net/builds/RoonServer_linuxx64.tar.bz2'
|
|
G_CONFIG_INJECT 'SOFTWARE_ROONSERVER_EARLYACCESS=' 'SOFTWARE_ROONSERVER_EARLYACCESS=0' /boot/dietpi.txt
|
|
fi
|
|
|
|
# Reinstall: Replace old instance
|
|
[[ -d '/opt/roonserver' ]] && G_EXEC rm -R /opt/roonserver
|
|
G_EXEC mv RoonServer /opt/roonserver
|
|
|
|
# Log to /var/log/roonserver
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/roonserver/{RoonServer,RAATServer}
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/roonserver/{RoonServer,RAATServer}/Logs
|
|
G_EXEC ln -s /var/log/roonserver /mnt/dietpi_userdata/roonserver/RoonServer/Logs
|
|
G_EXEC ln -s /var/log/roonserver /mnt/dietpi_userdata/roonserver/RAATServer/Logs
|
|
|
|
# User: Grant sudo permissions to create a mount point and mount SMB shares
|
|
Create_User -G dietpi,audio -d /mnt/dietpi_userdata/roonserver roonserver
|
|
G_EXEC eval 'echo '\''roonserver ALL=NOPASSWD:SETENV: /bin/mkdir -p /mnt/RoonStorage_*, /sbin/mount.cifs'\'' > /etc/sudoers.d/roonserver'
|
|
|
|
# Permissions
|
|
G_EXEC chmod 0755 /opt/roonserver
|
|
G_EXEC chown -R roonserver:root /{mnt/dietpi_userdata,opt}/roonserver
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/roonserver.service
|
|
[Unit]
|
|
Description=Roon Server (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Roon Server
|
|
User=roonserver
|
|
AmbientCapabilities=CAP_SYS_NICE
|
|
LogsDirectory=roonserver
|
|
Environment=ROON_DATAROOT=/mnt/dietpi_userdata/roonserver
|
|
Environment=ROON_ID_DIR=/mnt/dietpi_userdata/roonserver
|
|
ExecStart=/opt/roonserver/start.sh
|
|
|
|
# Hardening
|
|
PrivateTmp=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 156 # Steam
|
|
then
|
|
# Allow non-interactive install
|
|
G_EXEC eval "debconf-set-selections <<< 'steam steam/question select I AGREE'"
|
|
|
|
# x86_64: Install Debian i386 package
|
|
if [[ $G_HW_ARCH == 10 ]]
|
|
then
|
|
# Add i386 arch: https://packages.debian.org/steam
|
|
[[ $(dpkg --print-foreign-architectures) == *'i386'* ]] || { G_EXEC dpkg --add-architecture i386; G_AGUP; }
|
|
|
|
G_AGI steam
|
|
|
|
# Reapply GPU drivers to install required i386 items
|
|
local gpu_current=$(sed -n '/^[[:blank:]]*CONFIG_GPU_DRIVER=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
/boot/dietpi/func/dietpi-set_hardware gpudriver "$gpu_current"
|
|
|
|
# ARM: Install repacked Debian i386 package for armhf
|
|
elif [[ $G_HW_ARCH == 2 ]]
|
|
then
|
|
Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/steam_$G_HW_ARCH_NAME.deb"
|
|
fi
|
|
|
|
# Move data dir to dietpi_userdata
|
|
if [[ -d '/mnt/dietpi_userdata/steam' ]]
|
|
then
|
|
G_EXEC rm -Rf /root/.steam
|
|
|
|
elif [[ -d '/root/.steam' ]]
|
|
then
|
|
G_EXEC mv /root/.steam /mnt/dietpi_userdata/steam
|
|
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/steam
|
|
fi
|
|
G_EXEC ln -s /mnt/dietpi_userdata/steam /root/.steam
|
|
|
|
# Desktop shortcut
|
|
Create_Desktop_Shortcut steam
|
|
fi
|
|
|
|
if To_Install 158 minio # MinIO
|
|
then
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='arm';;
|
|
esac
|
|
|
|
G_EXEC curl -sSfLo /usr/local/bin/minio "https://dl.minio.io/server/minio/release/linux-$arch/minio"
|
|
G_EXEC chmod +x /usr/local/bin/minio
|
|
|
|
# Service
|
|
G_EXEC curl -sSfLo /etc/systemd/system/minio.service 'https://github.com/minio/minio-service/raw/master/linux-systemd/minio.service'
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/minio-data minio-user
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/minio-data
|
|
G_EXEC chown -R minio-user:minio-user /mnt/dietpi_userdata/minio-data
|
|
|
|
# Config
|
|
[[ -f '/etc/default/minio' ]] || cat << '_EOF_' > /etc/default/minio
|
|
# Default file path
|
|
MINIO_VOLUMES="/mnt/dietpi_userdata/minio-data"
|
|
# Use if you want to run MinIO on a custom port.
|
|
MINIO_OPTS="--address :9004 --console-address :9001"
|
|
# Access key of the server.
|
|
#MINIO_ACCESS_KEY=Server-Access-Key
|
|
# Secret key of the server.
|
|
#MINIO_SECRET_KEY=Server-Secret-Key
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 162 docker # Docker
|
|
then
|
|
# APT packages
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
# RISC-V: Use "docker.io" from Debian repo as the official Docker repo does not support RISC-V yet: https://download.docker.com/linux/debian/dists/
|
|
local packages=('docker.io')
|
|
# Trixie: Add split "docker-cli" package: https://packages.debian.org/trixie/docker-cli
|
|
(( $G_DISTRO > 7 )) && packages+=('docker-cli')
|
|
else
|
|
# Detect distro
|
|
local distro='debian' suite=${G_DISTRO_NAME/forky/trixie}
|
|
(( $G_RASPBIAN )) && distro='raspbian' suite=${suite/trixie/bookworm}
|
|
|
|
# APT key
|
|
local url="https://download.docker.com/linux/$distro/gpg"
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-docker.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval "echo 'deb https://download.docker.com/linux/$distro $suite stable' > /etc/apt/sources.list.d/docker.list"
|
|
G_AGUP
|
|
|
|
# APT package name
|
|
packages=('docker-ce')
|
|
fi
|
|
|
|
# APT package
|
|
# - Mask service to prevent iptables related startup failure: https://github.com/MichaIng/DietPi/issues/6013
|
|
G_EXEC systemctl mask --now docker
|
|
G_AGI "${packages[@]}"
|
|
G_EXEC systemctl unmask docker
|
|
G_EXEC systemctl start docker.socket
|
|
|
|
# Change Docker service type to "simple": https://github.com/MichaIng/DietPi/issues/2238#issuecomment-439474766
|
|
G_EXEC mkdir -p /lib/systemd/system/docker.service.d
|
|
G_EXEC eval "echo -e '[Service]\nType=simple' > /lib/systemd/system/docker.service.d/dietpi-simple.conf"
|
|
|
|
# Config: https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
|
|
# - Move Docker containers to dietpi_userdata
|
|
# - Log to systemd-journald (journalctl) by default with reduced log level: https://github.com/MichaIng/DietPi/issues/2388
|
|
# + containerd: https://github.com/docker/docker.github.io/issues/9091
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/docker-data
|
|
if [[ -f '/etc/docker/daemon.json' ]]
|
|
then
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT '"data-root":' ' "data-root": "/mnt/dietpi_userdata/docker-data",' /etc/docker/daemon.json '^\{([[:space:]]|$)'
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT '"log-driver":' ' "log-driver": "journald",' /etc/docker/daemon.json '^\{([[:space:]]|$)'
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT '"log-level":' ' "log-level": "warn",' /etc/docker/daemon.json '^\{([[:space:]]|$)'
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT '"debug":' ' "debug": false,' /etc/docker/daemon.json '^\{([[:space:]]|$)'
|
|
else
|
|
G_EXEC mkdir -p /etc/docker
|
|
echo '{
|
|
"data-root": "/mnt/dietpi_userdata/docker-data",
|
|
"log-driver": "journald",
|
|
"log-level": "warn",
|
|
"debug": false
|
|
}' > /etc/docker/daemon.json
|
|
fi
|
|
G_CONFIG_INJECT '\[debug\]' '[debug]' /etc/containerd/config.toml
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'level[[:blank:]]*=' ' level = "warn"' /etc/containerd/config.toml '^\[debug\]'
|
|
|
|
Enable_memory_cgroup
|
|
Configure_iptables
|
|
fi
|
|
|
|
if To_Install 134 # Docker Compose
|
|
then
|
|
# RISC-V: Official APT repo does not support RISC-V yet
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
G_AGI docker-compose
|
|
else
|
|
G_AGI docker-compose-plugin
|
|
fi
|
|
fi
|
|
|
|
if To_Install 161 bdd # FuguHub
|
|
then
|
|
local arch='RaspberryPi'
|
|
(( $G_HW_ARCH == 10 )) && arch='linux-x64'
|
|
|
|
# Download
|
|
Download_Install "https://fuguhub.com/FuguHub.$arch.tar.gz" bd
|
|
# - Remove first run wizard
|
|
G_EXEC rm bd/applications/Config-Wizard.zip
|
|
# - SSL addon: https://fuguhub.com/SSL-Certificate-Wizard.lsp
|
|
G_THREAD_START curl -sSfL 'https://fuguhub.com/unix/sslcert.zip' -o bd/applications/sslcert.zip
|
|
# - Drop Box addon: https://fuguhub.com/dropbox.lsp
|
|
G_THREAD_START curl -sSfL 'https://fuguhub.com/box.zip' -o bd/applications/box.zip
|
|
G_THREAD_WAIT
|
|
|
|
# Reinstall: Do not overwrite config and data
|
|
if [[ -d '/home/bd' ]]
|
|
then
|
|
G_EXEC rm -R bd/{cmsdocs,data,disk}
|
|
G_EXEC cp -a bd/. /home/bd/
|
|
else
|
|
G_EXEC rm -R bd/disk
|
|
G_EXEC mv bd /home/bd
|
|
fi
|
|
|
|
# File server root directory
|
|
if [[ ! -d '/mnt/dietpi_userdata/fuguhub-data' ]]
|
|
then
|
|
if [[ -d '/home/bd/disk' ]]
|
|
then
|
|
G_EXEC mv /home/bd/disk /mnt/dietpi_userdata/fuguhub-data # Pre-v8.0
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/fuguhub-data
|
|
fi
|
|
fi
|
|
G_EXEC rm -Rf /home/bd/disk # Pre-v8.0
|
|
[[ -e '/mnt/dietpi_userdata/fuguhub-data/cmsdocs' ]] || G_EXEC ln -s /home/bd/cmsdocs /mnt/dietpi_userdata/fuguhub-data/cmsdocs
|
|
[[ -e '/mnt/dietpi_userdata/fuguhub-data/applications' ]] || G_EXEC ln -s /home/bd/applications /mnt/dietpi_userdata/fuguhub-data/applications
|
|
|
|
# Create admin account
|
|
if [[ ! -f '/home/bd/user.dat' ]]
|
|
then
|
|
> /home/bd/user.dat
|
|
G_EXEC chmod 0600 /home/bd/user.dat
|
|
echo -n "{'v':{'dietpi':{'name':'dietpi','pwd':'$GLOBAL_PW','maxUsers':15,'recycle':true,'inactive':1200,'roles':{}}}}" > /home/bd/user.dat
|
|
fi
|
|
[[ -f '/home/bd/drvcnstr.dat' ]] || echo -n '{"v":{"admin":{"roles":["admin"],"urls":["\/*"],"methods":["GET","POST","PUT","PROPFIND","PROPPATCH","MKCOL","DELETE","MOVE","COPY"]}}}' > /home/bd/drvcnstr.dat
|
|
[[ -f '/home/bd/tuncnstr.dat' ]] || echo -n '{"v":{"TunFullAcc":{"roles":["TunFullAcc"],"urls":["\/*"],"methods":["GET"]}}}' > /home/bd/tuncnstr.dat
|
|
|
|
# User
|
|
Create_User -d /home/bd bd
|
|
|
|
# Permissions
|
|
G_EXEC chown -R bd:bd /home/bd /mnt/dietpi_userdata/fuguhub-data
|
|
|
|
Remove_SysV bdd # Pre-v8.0: https://github.com/MichaIng/DietPi/issues/5058
|
|
cat << '_EOF_' > /etc/systemd/system/bdd.service
|
|
[Unit]
|
|
Description=FuguHub (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=bd
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
WorkingDirectory=/home/bd
|
|
ExecStart=/home/bd/FuguHub -h/home/bd -r/mnt/dietpi_userdata/fuguhub-data --threads 3 --sessions 100 --connections 80
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 164 nukkit # Nukkit
|
|
then
|
|
Download_Install 'https://ci.opencollab.dev/job/NukkitX/job/Nukkit/job/master/lastStableBuild/artifact/target/nukkit-1.0-SNAPSHOT.jar' /usr/local/bin/nukkit/nukkit.jar
|
|
|
|
# Config
|
|
[[ -f '/usr/local/bin/nukkit/nukkit.yml' ]] || G_EXEC curl -sSfL 'https://raw.githubusercontent.com/CloudburstMC/Languages/master/eng/nukkit.yml' -o /usr/local/bin/nukkit/nukkit.yml
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/nukkit.service
|
|
[Unit]
|
|
Description=Nukkit (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=Nukkit
|
|
WorkingDirectory=/usr/local/bin/nukkit
|
|
ExecStart=$JAVA_PATH -jar /usr/local/bin/nukkit/nukkit.jar
|
|
SuccessExitStatus=143
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 49 gogs # Gogs
|
|
then
|
|
# ARMv6/ARMv7/RISC-V: No pre-compiled binaries available, so we host our own.
|
|
if (( $G_HW_ARCH == 1 || $G_HW_ARCH == 2 || $G_HW_ARCH == 11 ))
|
|
then
|
|
local url="https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/gogs_$G_HW_ARCH_NAME.7z"
|
|
|
|
# Else install latest binaries from GitHub
|
|
else
|
|
case $G_HW_ARCH in
|
|
3) local arch='armv8';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/gogs/gogs/releases/download/v0.13.3/gogs_0.13.3_linux_$arch.tar.gz"
|
|
local url=$(curl -sSfL 'https://api.github.com/repos/gogs/gogs/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/gogs_[^\"\/]*_linux_$arch.tar.gz\"$/{print \$4}")
|
|
fi
|
|
|
|
Download_Install "$url"
|
|
G_EXEC mkdir -p /etc/gogs
|
|
G_EXEC mv gogs/gogs /etc/gogs/gogs
|
|
G_EXEC rm -R gogs
|
|
|
|
# Pre-v8.14: Remove unnecessary init scripts
|
|
[[ -d '/etc/gogs/scripts' ]] && G_EXEC rm -R /etc/gogs/scripts
|
|
|
|
# User
|
|
Create_User -d /etc/gogs -s /bin/dash gogs
|
|
|
|
# Directories + permissions
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/gogs-repo
|
|
G_EXEC chown -R gogs:gogs /etc/gogs /mnt/dietpi_userdata/gogs-repo
|
|
|
|
# Database
|
|
/boot/dietpi/func/create_mysql_db gogs gogs "$GLOBAL_PW"
|
|
|
|
# Service: https://github.com/gogs/gogs/blob/main/scripts/systemd/gogs.service
|
|
cat << '_EOF_' > /etc/systemd/system/gogs.service
|
|
[Unit]
|
|
Description=Gogs (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target mariadb.service
|
|
|
|
[Service]
|
|
User=gogs
|
|
LogsDirectory=gogs
|
|
WorkingDirectory=/etc/gogs
|
|
ExecStart=/etc/gogs/gogs web
|
|
|
|
# Hardening
|
|
ProtectSystem=full
|
|
PrivateDevices=yes
|
|
PrivateTmp=yes
|
|
NoNewPrivileges=true
|
|
ReadWritePaths=-/etc/gogs
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 165 gitea # Gitea
|
|
then
|
|
# ARMv7: As of v1.8 there were issues with ARMv7 binaries on Raspbian which are hence not provided anymore: https://github.com/go-gitea/gitea/issues/6700
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='arm-6';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/go-gitea/gitea/releases/download/v1.25.2/gitea-1.25.2-linux-$arch.xz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/go-gitea/gitea/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/gitea-[^\"\/]*-linux-$arch\.xz\"$/{print \$4}")" /mnt/dietpi_userdata/gitea/gitea
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/gitea -s /bin/dash gitea
|
|
|
|
# Permissions
|
|
G_EXEC chown -R gitea:gitea /mnt/dietpi_userdata/gitea
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/gitea/gitea
|
|
|
|
# Database
|
|
/boot/dietpi/func/create_mysql_db gitea gitea "$GLOBAL_PW"
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/gitea.service
|
|
[Unit]
|
|
Description=Gitea (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target mariadb.service
|
|
|
|
[Service]
|
|
User=gitea
|
|
LogsDirectory=gitea
|
|
WorkingDirectory=/mnt/dietpi_userdata/gitea
|
|
ExecStart=/mnt/dietpi_userdata/gitea/gitea web
|
|
|
|
# Hardening
|
|
ProtectSystem=full
|
|
PrivateDevices=yes
|
|
PrivateTmp=yes
|
|
NoNewPrivileges=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Pre-v7.9: Migrate run user setting: https://github.com/MichaIng/DietPi/issues/5516
|
|
[[ -f '/mnt/dietpi_userdata/gitea/custom/conf/app.ini' ]] && G_CONFIG_INJECT 'RUN_USER[[:blank:]]' 'RUN_USER = gitea' /mnt/dietpi_userdata/gitea/custom/conf/app.ini
|
|
fi
|
|
|
|
if To_Install 177 forgejo # Forgejo
|
|
then
|
|
# ARMv7: Dedicated binaries are not provided: https://codeberg.org/forgejo/forgejo/releases
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
*) local arch='arm-6';;
|
|
esac
|
|
|
|
# Bullseye: Forgejo 13 requires Git >=2.34.1: https://codeberg.org/forgejo/forgejo/pulls/8328. This is also practically true, the daemon fails right after initial web UI setup steps.
|
|
if (( $G_DISTRO > 6 ))
|
|
then
|
|
local fallback_url="https://codeberg.org/forgejo/forgejo/releases/download/v13.0.3/forgejo-13.0.3-linux-$arch.xz"
|
|
Download_Install "$(curl -sSfL 'https://codeberg.org/api/v1/repos/forgejo/forgejo/releases/latest' | mawk -v RS=, -F\" "/^\"browser_download_url\":\".*-linux-$arch\.xz\"$/{print \$4;exit}")" /mnt/dietpi_userdata/forgejo/forgejo
|
|
else
|
|
local fallback_url="https://codeberg.org/forgejo/forgejo/releases/download/v12.0.4/forgejo-12.0.4-linux-$arch.xz"
|
|
Download_Install "$(curl -sSfL 'https://codeberg.org/api/v1/repos/forgejo/forgejo/releases' | mawk -v RS=, -F\" "/^\"browser_download_url\":\".*-12\..*-linux-$arch\.xz\"$/{print \$4}" | head -1)" /mnt/dietpi_userdata/forgejo/forgejo
|
|
fi
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/forgejo -s /bin/dash forgejo
|
|
|
|
# Permissions
|
|
G_EXEC chown -R forgejo:forgejo /mnt/dietpi_userdata/forgejo
|
|
G_EXEC chmod +x /mnt/dietpi_userdata/forgejo/forgejo
|
|
|
|
# Database
|
|
/boot/dietpi/func/create_mysql_db forgejo forgejo "$GLOBAL_PW"
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/forgejo.service
|
|
[Unit]
|
|
Description=Forgejo (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target mariadb.service
|
|
|
|
[Service]
|
|
User=forgejo
|
|
LogsDirectory=forgejo
|
|
WorkingDirectory=/mnt/dietpi_userdata/forgejo
|
|
ExecStart=/mnt/dietpi_userdata/forgejo/forgejo web
|
|
|
|
# Hardening
|
|
ProtectSystem=full
|
|
PrivateDevices=yes
|
|
PrivateTmp=yes
|
|
NoNewPrivileges=true
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 163 gmediarender # GMediaRender
|
|
then
|
|
G_AGI gmediarender
|
|
G_EXEC systemctl stop gmediarender
|
|
fi
|
|
|
|
if To_Install 160 # Allo GUI
|
|
then
|
|
# Download
|
|
Download_Install 'https://github.com/MichaIng/DietPi-AlloGUI/archive/v15.tar.gz'
|
|
G_EXEC mv DietPi-AlloGUI-15 allo
|
|
|
|
# Permissions
|
|
G_EXEC chmod -R 'o=,g-w' allo
|
|
G_EXEC chgrp -R www-data allo
|
|
G_EXEC chmod -R 'g=' allo/storage allo/bootstrap/cache
|
|
G_EXEC find allo/{storage,bootstrap/cache} -type d -exec chown www-data {} +
|
|
|
|
# Create database when missing, else reapply random database password
|
|
local db_password=$(tr -dc '[:alnum:]' < /dev/random | head -c32)
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/allo' ]]
|
|
then
|
|
G_EXEC systemctl start mariadb
|
|
mysql -e "grant all privileges on allo.* to allo@localhost identified by '$db_password';"
|
|
else
|
|
/boot/dietpi/func/create_mysql_db allo allo "$db_password"
|
|
G_EXEC mysql -e 'create table allo.users(id tinyint unsigned primary key auto_increment, name tinytext not null, email tinytext not null, password varchar(60) not null, remember_token varchar(60), created_at timestamp, updated_at timestamp default current_timestamp);'
|
|
mysql -e "insert into allo.users(name, email, password) values ('admin', 'admin@allo.com', '$(php -r "echo password_hash('$GLOBAL_PW',PASSWORD_BCRYPT);")');"
|
|
fi
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'DB_PASSWORD=' "DB_PASSWORD=$db_password" allo/.env
|
|
unset -v db_password
|
|
|
|
# Apply new app key
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'APP_KEY=' "APP_KEY=base64:$(base64 < <(tr -dc '[:graph:]' < /dev/random | head -c32))" allo/.env
|
|
|
|
# Install cleanly
|
|
[[ -d '/opt/allo' ]] && G_EXEC rm -R /opt/allo
|
|
G_EXEC mv allo /opt
|
|
|
|
# Grant sudo permissions
|
|
G_EXEC eval 'echo '\''www-data ALL=NOPASSWD: ALL'\'' > /etc/sudoers.d/allo'
|
|
|
|
# Link to webroot
|
|
G_EXEC ln -snf /opt/allo/public /var/www/allo
|
|
|
|
# Redirect to web interface by default
|
|
G_EXEC rm -f /var/www/index\.*
|
|
cat << '_EOF_' > /var/www/index.php || exit 1
|
|
<?php
|
|
header('Location: /allo/index.php');
|
|
exit;
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 166 pi-spc # Audiophonics PI-SPC
|
|
then
|
|
# https://github.com/audiophonics/Raspberry-pwr-management
|
|
G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed/pi-spc
|
|
cat << '_EOF_' > /var/lib/dietpi/dietpi-software/installed/pi-spc/sds.sh
|
|
#!/bin/dash
|
|
|
|
echo 'Audiophonics PI-SPC: Shutdown script starting...
|
|
Asserting pins:
|
|
ShutDown : GPIO17=in, Low
|
|
BootOK : GPIO22=out, High
|
|
SoftShutDown : GPIO04=out, Low'
|
|
|
|
[ -f '/proc/cpuinfo' ] || { echo 'Oops: Unable to determine board revision from /proc/cpuinfo: /proc/cpuinfo does not exist. Exiting ...'; exit 1; }
|
|
grep -q '^Hardware' /proc/cpuinfo || { echo 'Oops: Unable to determine board revision from /proc/cpuinfo: No "Hardware" line. Exiting ...'; exit 1; }
|
|
|
|
gpio -g mode 04 out
|
|
gpio -g write 04 0
|
|
gpio -g mode 17 in
|
|
gpio -g write 17 0
|
|
gpio -g mode 22 out
|
|
gpio -g write 22 1
|
|
|
|
until [ "$(gpio -g read 17)" = 1 ]
|
|
do
|
|
sleep 0.25
|
|
done
|
|
|
|
echo 'Audiophonics PI-SPC: Shutting down system as requested...'
|
|
systemctl start poweroff.target
|
|
exit 0
|
|
_EOF_
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/pi-spc/sds.sh
|
|
|
|
cat << '_EOF_' > /etc/systemd/system/pi-spc.service
|
|
[Unit]
|
|
Description=Audiophonics PI-SPC (DietPi)
|
|
|
|
[Service]
|
|
StandardOutput=tty
|
|
ExecStart=/var/lib/dietpi/dietpi-software/installed/pi-spc/sds.sh
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Alternative: Use native GPIO shutdown and poweroff device tree overlays
|
|
|
|
# systemd-logind < dbus is required for the gpio-shutdown device tree overlay to trigger the shutdown.
|
|
#G_AGI dbus
|
|
#G_EXEC systemctl unmask systemd-logind
|
|
#G_EXEC systemctl start systemd-logind
|
|
|
|
#G_CONFIG_INJECT 'dtoverlay=gpio-shutdown' 'dtoverlay=gpio-shutdown,gpio_pin=17,active_low=0,gpio_pull=down' /boot/config.txt
|
|
#G_CONFIG_INJECT 'dtoverlay=gpio-poweroff' 'dtoverlay=gpio-poweroff,gpiopin=22,active_low' /boot/config.txt
|
|
fi
|
|
|
|
if To_Install 167 raspotify # Raspotify: https://github.com/dtcooper/raspotify/blob/master/install.sh
|
|
then
|
|
# ARMv6: 0.31.8.1 is the last version supporting ARMv6: https://github.com/dtcooper/raspotify/wiki/Raspotify-on-Pi-v1's-and-Pi-Zero-v1.x, https://github.com/dtcooper/raspotify/commit/345f15c
|
|
if (( $G_HW_ARCH == 1 ))
|
|
then
|
|
Download_Install 'https://github.com/dtcooper/raspotify/releases/download/0.31.8.1/raspotify_0.31.8.1.librespot.v0.3.1-54-gf4be9bb_armhf.deb'
|
|
else
|
|
# APT key
|
|
Download_Install 'https://dtcooper.github.io/raspotify/key.asc' /etc/apt/trusted.gpg.d/dietpi-raspotify.asc
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://dtcooper.github.io/raspotify raspotify main'\'' > /etc/apt/sources.list.d/dietpi-raspotify.list'
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI raspotify
|
|
fi
|
|
|
|
# Stop service
|
|
G_EXEC systemctl stop raspotify
|
|
fi
|
|
|
|
if To_Install 86 roon-extension-manager # Roon Extension Manager
|
|
then
|
|
# Data dir
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/roon-extension-manager
|
|
|
|
# Pre-v8.2 migration
|
|
if [[ -f '/etc/systemd/system/roon-extension-manager.service' ]]
|
|
then
|
|
G_EXEC systemctl stop roon-extension-manager
|
|
G_EXEC rm /etc/systemd/system/roon-extension-manager.service
|
|
fi
|
|
[[ -d '/root/.roon-extension-manager' && ! -d '/mnt/dietpi_userdata/roon-extension-manager/.roon-extension-manager' ]] && G_EXEC mv /{root,mnt/dietpi_userdata/roon-extension-manager}/.roon-extension-manager
|
|
|
|
# User: Create with login shell first, since the REM installer uses "su"
|
|
Create_User -G docker -d /mnt/dietpi_userdata/roon-extension-manager -s /bin/dash roon-extension-manager
|
|
|
|
# Permissions
|
|
G_EXEC chown -R roon-extension-manager:root /mnt/dietpi_userdata/roon-extension-manager
|
|
|
|
# Store installer to data dir, so we can reuse it on uninstall
|
|
aDEPS=('wget')
|
|
Download_Install 'https://raw.githubusercontent.com/TheAppgineer/roon-extension-manager/v1.x/rem-setup.sh' /mnt/dietpi_userdata/roon-extension-manager/rem-setup.sh
|
|
G_EXEC cd /mnt/dietpi_userdata/roon-extension-manager
|
|
G_EXEC chmod +x rem-setup.sh
|
|
|
|
# Let the installer create everything for "roon-extension-manager" to run the service: https://github.com/MichaIng/DietPi/issues/5236
|
|
SUDO_USER='roon-extension-manager' G_EXEC_OUTPUT=1 G_EXEC ./rem-setup.sh
|
|
G_EXEC systemctl stop roon-extension-manager
|
|
G_EXEC usermod -s "$(command -v nologin)" roon-extension-manager
|
|
fi
|
|
|
|
if To_Install 178 jellyfin # Jellyfin
|
|
then
|
|
# RPi: Enable hardware codecs
|
|
(( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1
|
|
|
|
# APT key
|
|
local url='https://repo.jellyfin.org/jellyfin_team.gpg.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-jellyfin.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval "echo 'deb https://repo.jellyfin.org/debian ${G_DISTRO_NAME/forky/trixie} main' > /etc/apt/sources.list.d/dietpi-jellyfin.list"
|
|
G_AGUP
|
|
|
|
# Mask service to prevent potential XML parsing issue due to bad termination timing
|
|
G_EXEC systemctl --no-reload mask jellyfin
|
|
|
|
# APT meta package: Server, web component and FFmpeg implementation
|
|
G_AGI jellyfin
|
|
|
|
G_EXEC systemctl --no-reload unmask jellyfin
|
|
|
|
# Grant dietpi group permissions and assure video access
|
|
Create_User -G dietpi,video,render -d /mnt/dietpi_userdata/jellyfin jellyfin
|
|
|
|
# Config: Only apply on fresh install, assumed when /mnt/dietpi_userdata/jellyfin does not yet exist
|
|
if [[ ! -d '/mnt/dietpi_userdata/jellyfin' ]]
|
|
then
|
|
# Data dir
|
|
# shellcheck disable=SC2015
|
|
[[ -d '/var/lib/jellyfin' ]] && G_EXEC mv /var/lib/jellyfin /mnt/dietpi_userdata/jellyfin || G_EXEC mkdir /mnt/dietpi_userdata/jellyfin
|
|
G_CONFIG_INJECT 'JELLYFIN_DATA_DIR=' 'JELLYFIN_DATA_DIR=/mnt/dietpi_userdata/jellyfin' /etc/default/jellyfin
|
|
# Change default WorkingDirectory
|
|
G_EXEC mkdir -p /etc/systemd/system/jellyfin.service.d
|
|
G_EXEC eval 'echo -e '\''[Service]\nWorkingDirectory=/mnt/dietpi_userdata/jellyfin'\'' > /etc/systemd/system/jellyfin.service.d/dietpi.conf'
|
|
# Cache dir
|
|
[[ -d '/var/cache/jellyfin' ]] && G_EXEC mv /var/cache/jellyfin /mnt/dietpi_userdata/jellyfin/cache
|
|
G_CONFIG_INJECT 'JELLYFIN_CACHE_DIR=' 'JELLYFIN_CACHE_DIR=/mnt/dietpi_userdata/jellyfin/cache' /etc/default/jellyfin
|
|
# Change default port due to conflict with Emby
|
|
# - This config file is not generated at service start, but only when saving network settings via web UI. This also complements any existing config with defaults, hence we pre-create one with only the changes we need.
|
|
cat << '_EOF_' > /etc/jellyfin/network.xml
|
|
<NetworkConfiguration>
|
|
<InternalHttpPort>8097</InternalHttpPort>
|
|
<PublicHttpPort>8097</PublicHttpPort>
|
|
</NetworkConfiguration>
|
|
_EOF_
|
|
G_EXEC chown jellyfin: /etc/jellyfin/network.xml
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R jellyfin: /mnt/dietpi_userdata/jellyfin
|
|
|
|
Download_Test_Media
|
|
fi
|
|
|
|
if To_Install 62 # Box86
|
|
then
|
|
# APT deps
|
|
aDEPS=('cmake' 'make' 'gcc' 'libc6-dev' 'python3-minimal')
|
|
|
|
# Download
|
|
local version=$(curl -sSfL 'https://api.github.com/repos/ptitSeb/box86/releases/latest' | mawk -F\" '/^ *"tag_name": "[^"]*",$/{print $4}')
|
|
[[ $version ]] || { version='v0.3.8'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
Download_Install "https://github.com/ptitSeb/box86/archive/$version.tar.gz"
|
|
|
|
# Build for targets: https://github.com/ptitSeb/box86/blob/master/CMakeLists.txt
|
|
G_EXEC mkdir "box86-${version#v}/build"
|
|
G_EXEC cd "box86-${version#v}/build"
|
|
# - RPi 2
|
|
if (( $G_HW_MODEL == 2 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI2=1
|
|
# - RPi 3
|
|
elif (( $G_HW_MODEL == 3 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI3=1
|
|
# - RPi 4
|
|
elif (( $G_HW_MODEL == 4 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI4=1
|
|
# - Odroid XU4
|
|
elif (( $G_HW_MODEL == 11 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DODROIDXU4=1
|
|
# - ASUS Tinker Board
|
|
elif (( $G_HW_MODEL == 52 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRK3288=1
|
|
# - Others
|
|
else
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DARM_DYNAREC=1
|
|
fi
|
|
G_EXEC_OUTPUT=1 G_EXEC make CFLAGS='-g0 -O3' "-j$(nproc)"
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note box86
|
|
G_EXEC make install
|
|
|
|
# Cleanup
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R "box86-${version#v}"
|
|
|
|
# Reload binfmt if kernel module is available to have i386 binaries executed via box86 automatically from now on
|
|
modprobe binfmt_misc 2> /dev/null && G_EXEC systemctl restart systemd-binfmt
|
|
fi
|
|
|
|
if To_Install 197 # Box64
|
|
then
|
|
# APT deps
|
|
aDEPS=('cmake' 'make' 'gcc' 'libc6-dev' 'python3-minimal')
|
|
|
|
# Download
|
|
local version=$(curl -sSfL 'https://api.github.com/repos/ptitSeb/box64/releases/latest' | mawk -F\" '/^ *"tag_name": "[^"]*",$/{print $4}')
|
|
[[ $version ]] || { version='v0.3.8'; G_DIETPI-NOTIFY 1 "Automatic latest ${aSOFTWARE_NAME[$software_id]} version detection failed. Version \"$version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
Download_Install "https://github.com/ptitSeb/box64/archive/$version.tar.gz"
|
|
|
|
# Build for targets: https://github.com/ptitSeb/box64/blob/main/CMakeLists.txt
|
|
G_EXEC mkdir "box64-${version#v}/build"
|
|
G_EXEC cd "box64-${version#v}/build"
|
|
# - RISC-V
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRV64=1
|
|
# - RPi 2/3
|
|
elif (( $G_HW_MODEL == 2 || $G_HW_MODEL == 3 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI3ARM64=1
|
|
# - RPi 4
|
|
elif (( $G_HW_MODEL == 4 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI4ARM64=1
|
|
# - RPi 5
|
|
elif (( $G_HW_MODEL == 5 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRPI5ARM64=1
|
|
# - Odroid N2
|
|
elif (( $G_HW_MODEL == 15 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DODROIDN2=1
|
|
# - RK3399
|
|
elif (( $G_HW_CPUID == 3 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRK3399=1
|
|
# - RK3588
|
|
elif (( $G_HW_CPUID == 11 ))
|
|
then
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DRK3588=1
|
|
# - Generic ARMv8
|
|
else
|
|
G_EXEC cmake .. -DNOGIT=1 -DCMAKE_BUILD_TYPE=Release -DARM64=1
|
|
fi
|
|
G_EXEC_OUTPUT=1 G_EXEC make CFLAGS='-g0 -O3' "-j$(nproc)"
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note box64
|
|
G_EXEC make install
|
|
|
|
# Cleanup
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R "box64-${version#v}"
|
|
|
|
# Reload binfmt if kernel module is available to have x86_64 binaries executed via box64 automatically from now on
|
|
modprobe binfmt_misc 2> /dev/null && G_EXEC systemctl restart systemd-binfmt
|
|
fi
|
|
|
|
if To_Install 207 # Moonlight (CLI): https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-embedded/setup.deb.sh
|
|
then
|
|
# APT key
|
|
local url='https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-embedded/gpg.5AEE46706CF0453E.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-moonlight.gpg --yes"
|
|
|
|
# APT list
|
|
local dist=$G_DISTRO_NAME
|
|
(( $G_DISTRO > 7 )) && dist='bookworm'
|
|
G_EXEC eval "echo 'deb https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-embedded/deb/raspbian $dist main' > /etc/apt/sources.list.d/dietpi-moonlight.list"
|
|
G_AGUP
|
|
|
|
# APT deps
|
|
aDEPS=('libcec6')
|
|
(( $G_DISTRO > 7 )) && aDEPS=('libcec7')
|
|
|
|
# APT package
|
|
G_AGI moonlight-embedded "${aDEPS[@]}"
|
|
aDEPS=()
|
|
|
|
# Enable required fake KMS driver: https://github.com/moonlight-stream/moonlight-embedded/wiki/Packages
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-fkms-v3d
|
|
fi
|
|
|
|
if To_Install 208 # Moonlight (GUI): https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-qt/setup.deb.sh
|
|
then
|
|
# APT key
|
|
local url='https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-qt/gpg.2F6AE14E1C660D44.key'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-moonlight-qt.gpg --yes"
|
|
|
|
# APT list
|
|
local distro='debian' suite=${G_DISTRO_NAME/forky/trixie}
|
|
(( $G_HW_MODEL < 10 )) && distro='raspbian'
|
|
G_EXEC eval "echo 'deb https://dl.cloudsmith.io/public/moonlight-game-streaming/moonlight-qt/deb/$distro $suite main' > /etc/apt/sources.list.d/dietpi-moonlight-qt.list"
|
|
G_AGUP
|
|
|
|
# APT package
|
|
G_AGI moonlight-qt
|
|
|
|
# Raspberry Pi video setup: https://github.com/moonlight-stream/moonlight-docs/wiki/Installing-Moonlight-Qt-on-Raspberry-Pi-4#hevc-and-hdr-support
|
|
# - Usually requires vc4-fkms-v3d which also serves best performance
|
|
# - HEVC requires rpivid-v4l2, but it is deprecated and enabled OOTB since Bullseye
|
|
# - HDR requires vc4-kms-v3d, works on RPi 4 only (?) and breaks starting Moonlight from desktop
|
|
# => Compatible arrangement with HEVC but no HDR
|
|
if (( $G_HW_MODEL < 10 ))
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-fkms-v3d
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-codec 1
|
|
fi
|
|
fi
|
|
|
|
if To_Install 11 # GZDoom
|
|
then
|
|
G_AGI gzdoom
|
|
|
|
# Enable KMS/DRM on RPi
|
|
(( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d
|
|
fi
|
|
|
|
if To_Install 27 # TasmoAdmin
|
|
then
|
|
# Install required PHP modules: https://github.com/TasmoAdmin/TasmoAdmin/wiki/Guide-for-Debian-Server-10-(Buster)
|
|
aDEPS=("php$PHP_VERSION-curl" "php$PHP_VERSION-zip" "php$PHP_VERSION-mbstring" "php$PHP_VERSION-xml")
|
|
local adeps=("${aDEPS[@]#*-}")
|
|
|
|
# Reinstall: Skip download and install, advice to use internal updater from web UI
|
|
if [[ -d '/var/www/tasmoadmin' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/var/www/tasmoadmin\" already exists. Download and install steps will be skipped.
|
|
- If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater from web UI.
|
|
- If you need to reinstall (e.g. broken instance), please manually backup your config files+data, remove the install dir and rerun \"dietpi-software (re)install $software_id\"."
|
|
|
|
G_AGI "${aDEPS[@]}"
|
|
aDEPS=()
|
|
else
|
|
# v3 drops PHP 7.4 support: https://github.com/TasmoAdmin/TasmoAdmin/releases/tag/v3.0.0
|
|
if (( $G_DISTRO > 6 ))
|
|
then
|
|
local fallback_url='https://github.com/TasmoAdmin/TasmoAdmin/releases/download/v4.3.2/tasmoadmin_v4.3.2.tar.gz'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/TasmoAdmin/TasmoAdmin/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/tasmoadmin_v[^"\/]*\.tar\.gz"$/{print $4}')"
|
|
else
|
|
Download_Install 'https://github.com/TasmoAdmin/TasmoAdmin/releases/download/v2.4.2/tasmoadmin_v2.4.2.tar.gz'
|
|
fi
|
|
G_EXEC chown -R www-data:www-data tasmoadmin
|
|
G_EXEC mv tasmoadmin /var/www/
|
|
fi
|
|
|
|
# Webserver config
|
|
# - Config file Version
|
|
local version=
|
|
(( $G_DISTRO > 6 )) && version='.3'
|
|
if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Apache webserver found, enabling TasmoAdmin specific configuration.'
|
|
G_EXEC a2enmod setenvif rewrite authz_core authn_core authn_file
|
|
local tasmoadmin_conf='/etc/apache2/sites-available/dietpi-tasmoadmin.conf'
|
|
if [[ -f $tasmoadmin_conf ]]
|
|
then
|
|
tasmoadmin_conf+='.dietpi-new'
|
|
G_WHIP_MSG "Existing TasmoAdmin Apache configuration found, will preserve the old one and save the new one for review and comparison to: $tasmoadmin_conf"
|
|
fi
|
|
dps_index=$software_id Download_Install 'apache.tasmoadmin.conf' "$tasmoadmin_conf"
|
|
G_EXEC a2ensite dietpi-tasmoadmin
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Lighttpd webserver found, enabling TasmoAdmin specific configuration.'
|
|
local tasmoadmin_conf='/etc/lighttpd/conf-available/99-dietpi-tasmoadmin.conf'
|
|
if [[ -f $tasmoadmin_conf ]]
|
|
then
|
|
tasmoadmin_conf+='.dietpi-new'
|
|
G_WHIP_MSG "Existing TasmoAdmin Lighttpd configuration found, will preserve the old one and save the new one for review and comparison to: $tasmoadmin_conf"
|
|
fi
|
|
dps_index=$software_id Download_Install "lighttpd.tasmoadmin$version.conf" "$tasmoadmin_conf"
|
|
G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already
|
|
G_EXEC lighty-enable-mod rewrite dietpi-tasmoadmin
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Nginx webserver found, enabling TasmoAdmin specific configuration.'
|
|
local tasmoadmin_conf='/etc/nginx/sites-dietpi/dietpi-tasmoadmin.conf'
|
|
if [[ -f $tasmoadmin_conf ]]
|
|
then
|
|
owncloud_conf+='.dietpi-new'
|
|
G_WHIP_MSG "Existing TasmoAdmin Nginx configuration found, will preserve the old one and save the new one for review and comparison to: $tasmoadmin_conf"
|
|
fi
|
|
dps_index=$software_id Download_Install "nginx.tasmoadmin$version.conf" "$tasmoadmin_conf"
|
|
fi
|
|
|
|
# Enable required PHP modules
|
|
G_EXEC phpenmod "${adeps[@]}"
|
|
fi
|
|
|
|
if To_Install 206 openhab # openHAB: https://www.openhab.org/docs/installation/linux.html#package-repository-installation
|
|
then
|
|
# APT key
|
|
local url='https://openhab.jfrog.io/artifactory/api/gpg/key/public'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-openhab.gpg --yes"
|
|
|
|
# APT list
|
|
# - Enable RISC-V support by explicitly defining arch=all, which contains exactly the same packages (well, it's Java...)
|
|
local arch=
|
|
(( $G_HW_ARCH == 11 )) && arch=' [arch=all]'
|
|
G_EXEC eval "echo 'deb$arch https://openhab.jfrog.io/artifactory/openhab-linuxpkg stable main' > /etc/apt/sources.list.d/dietpi-openhab.list"
|
|
G_AGUP
|
|
|
|
# openHAB 5 requires Java 21
|
|
(( $JAVA_VERSION < 21 )) && G_EXEC eval 'cat << '\''_EOF_'\'' > /etc/apt/preferences.d/dietpi-openhab
|
|
Package: src:openhab*
|
|
Pin: version 5.*
|
|
Pin-Priority: -1
|
|
_EOF_'
|
|
# APT package
|
|
G_AGI openhab
|
|
G_EXEC systemctl stop openhab
|
|
|
|
# Disable plain HTTP and change HTTPS TCP port to avoid conflicts with SABnzbd, Airsonic-Advanced (8000) and MineOS (8443)
|
|
G_CONFIG_INJECT 'OPENHAB_HTTPS_PORT=' 'OPENHAB_HTTPS_PORT=8444' /etc/default/openhab
|
|
G_CONFIG_INJECT 'OPENHAB_HTTP_PORT=' 'OPENHAB_HTTP_PORT=0' /etc/default/openhab
|
|
|
|
# Do all logs to STDOUT => journalctl -u openhab
|
|
G_EXEC sed --follow-symlinks -i 's|<AppenderRef ref=".*"/>|<AppenderRef ref="STDOUT"/>|' /var/lib/openhab/etc/log4j2.xml
|
|
local line='' last=''
|
|
grep -n '<AppenderRef ref="STDOUT"/>' /var/lib/openhab/etc/log4j2.xml | while read -r line
|
|
do
|
|
line=${line%%:*}
|
|
(( $line == ${last:-$line} + 1 )) && G_EXEC sed --follow-symlinks -i "${last}d" /var/lib/openhab/etc/log4j2.xml
|
|
last=$line
|
|
done
|
|
G_EXEC rm -f /var/log/openhab/*
|
|
fi
|
|
|
|
if To_Install 157 home-assistant # Home Assistant
|
|
then
|
|
local ha_user='homeassistant'
|
|
local ha_home="/home/$ha_user"
|
|
local ha_pyenv_activation=". $ha_home/pyenv-activate.sh"
|
|
# Obtain latest Python 3.13.y version supported by pyenv
|
|
local ha_python_version=$(curl -sSfL 'https://api.github.com/repos/pyenv/pyenv/contents/plugins/python-build/share/python-build?ref=master' | mawk -F\" '/^ *"name": "3\.13\.[0-9]*",$/{print $4}' | sort -Vr | head -1)
|
|
[[ $ha_python_version ]] || { ha_python_version='3.13.11'; G_DIETPI-NOTIFY 1 "Automatic latest Python version detection failed. Version \"$ha_python_version\" will be installed as fallback, but a newer version might be available. Please report this at: https://github.com/MichaIng/DietPi/issues"; }
|
|
|
|
G_DIETPI-NOTIFY 2 "Home Assistant user: $ha_user"
|
|
G_DIETPI-NOTIFY 2 "Home Assistant home: $ha_home"
|
|
G_DIETPI-NOTIFY 2 "pyenv activation: \"$ha_pyenv_activation\""
|
|
G_DIETPI-NOTIFY 2 "pyenv Python version: $ha_python_version"
|
|
|
|
# User
|
|
Create_User -G dialout,gpio,i2c -d "$ha_home" "$ha_user"
|
|
G_EXEC mkdir -p "$ha_home"
|
|
G_EXEC chown "$ha_user:$ha_user" "$ha_home"
|
|
|
|
# Dependencies
|
|
# - Bullseye ARMv6/7: Depends on old bcrypt and cryptography versions which have no AMMv7 wheels yet, hence add dependency manually
|
|
local rust=()
|
|
(( $G_DISTRO < 7 && $G_HW_ARCH < 3 )) && rust=('-r') aDEPS=('pkg-config' 'libssl-dev')
|
|
PYTHON_VERSION=$ha_python_version Python_Deps -u "$ha_user" "${rust[@]}" av bcrypt cryptography numpy pillow pyenv pymicro-vad
|
|
# - Custom dependencies, e.g. MariaDB support: G_AGI libmariadb-dev; pip3 install mysqlclient|PyMySQL
|
|
local custom_apt_deps=$(sed -n '/^[[:blank:]]*SOFTWARE_HOMEASSISTANT_APT_DEPS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
mapfile -t -d' ' -O "${#aDEPS[@]}" aDEPS < <(echo -n "$custom_apt_deps")
|
|
# - Install isal compression library as faster drop-in replacement for zlib, to address a warning by aiohttp_fast_zlib: https://github.com/MichaIng/DietPi/issues/7525
|
|
local custom_pip_deps="isal $(sed -n '/^[[:blank:]]*SOFTWARE_HOMEASSISTANT_PIP_DEPS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)"
|
|
|
|
# Install pyenv to $ha_home
|
|
Download_Install 'https://github.com/pyenv/pyenv/archive/master.tar.gz'
|
|
G_EXEC chown -R "$ha_user:$ha_user" pyenv-master
|
|
# - Start with fresh instance, to allow clean pyenv and Python updates and fix broken instances. All userdata and configs are preserved in: /mnt/dietpi_userdata/homeassistant
|
|
[[ -d $ha_home/.pyenv ]] && G_EXEC rm -R "$ha_home/.pyenv"
|
|
[[ -f $ha_home/.python-version ]] && G_EXEC rm "$ha_home/.python-version" # pre-v9.13: remove "pyenv local" info as we use "pyenv global" now, stored to $ha_home/.python/version instead
|
|
[[ -d '/srv/homeassistant' ]] && G_EXEC rm -R /srv/homeassistant # pre-v6-27
|
|
G_EXEC mv pyenv-master "$ha_home/.pyenv"
|
|
|
|
# Link config and data to DietPi userdata
|
|
if [[ ! -d '/mnt/dietpi_userdata/homeassistant' ]]
|
|
then
|
|
if [[ -d $ha_home/.homeassistant ]]
|
|
then
|
|
G_EXEC mv "$ha_home/.homeassistant" /mnt/dietpi_userdata/homeassistant
|
|
else
|
|
G_EXEC mkdir /mnt/dietpi_userdata/homeassistant
|
|
fi
|
|
fi
|
|
[[ -d $ha_home/.homeassistant ]] && G_EXEC rm -R "$ha_home/.homeassistant"
|
|
G_EXEC ln -sf /mnt/dietpi_userdata/homeassistant "$ha_home/.homeassistant"
|
|
|
|
# Reset and merge pyenv and HA Python environment to avoid version mismatches on Python upgrades: https://github.com/MichaIng/DietPi/issues/6117
|
|
[[ -d '/mnt/dietpi_userdata/homeassistant/deps' ]] && G_EXEC rm -R /mnt/dietpi_userdata/homeassistant/deps
|
|
G_EXEC ln -sf "$ha_home/.pyenv/versions/$ha_python_version/lib/python${ha_python_version%.*}/site-packages" /mnt/dietpi_userdata/homeassistant/deps
|
|
|
|
# Configure pip
|
|
# - Disable cache
|
|
G_EXEC mkdir -p "$ha_home/.pip"
|
|
G_EXEC eval "echo -e '[global]\nno-cache-dir=true' > '$ha_home/.pip/pip.conf'"
|
|
# - ARMv6/7 Trixie/Forky: Add piwheels: The Python version needs to match the Debian version, else dynamically linked shared libraries may not match
|
|
(( $G_HW_ARCH < 3 && $G_DISTRO > 7 )) && G_CONFIG_INJECT 'extra-index-url[[:blank:]]*=' 'extra-index-url=https://www.piwheels.org/simple/' "$ha_home/.pip/pip.conf" '\[global\]'
|
|
|
|
# Generate script to activate pyenv: This must be sourced from the originating shell, hence it does not require execute permissions.
|
|
echo "#!/bin/dash
|
|
if [ \$(whoami) != '$ha_user' ]; then
|
|
echo '[FAILED] This pyenv must be activated as user \"$ha_user\". Aborting...'
|
|
kill -INT \$\$
|
|
fi
|
|
cd $ha_home
|
|
# Permit uv to install into system Python: https://github.com/astral-sh/uv/issues/7907
|
|
export PATH=\"$ha_home/.pyenv/bin:\$PATH\" UV_SYSTEM_PYTHON=1
|
|
eval \"\$(pyenv init -)\"
|
|
[ -f '.cargo/env' ] && . .cargo/env" > "$ha_home/pyenv-activate.sh"
|
|
|
|
local version=
|
|
# Bullseye: v2025.1.4 is the last which supports old SQLite: https://github.com/MichaIng/DietPi/issues/7374
|
|
(( $G_DISTRO < 7 )) && version='==2025.1.4'
|
|
G_EXEC_DESC="Compiling and installing Python $ha_python_version into pyenv, which will take a while ..."
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$ha_user" -- dash -c "$ha_pyenv_activation; exec pyenv install $ha_python_version"
|
|
G_EXEC_DESC="Set Python $ha_pyenv_activation as global version for this pyenv instance"
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$ha_user" -- dash -c "$ha_pyenv_activation; exec pyenv global $ha_python_version"
|
|
G_EXEC_DESC='Upgrading base modules: pip setuptools wheel'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$ha_user" -- dash -c "$ha_pyenv_activation; exec pip3 install -U pip setuptools wheel"
|
|
G_EXEC_DESC="Installing additional dependencies: $custom_pip_deps"
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$ha_user" -- dash -c "$ha_pyenv_activation; exec pip3 install $custom_pip_deps"
|
|
G_EXEC_DESC='Installing Home Assistant core module'
|
|
G_EXEC_OUTPUT=1 G_EXEC runuser -u "$ha_user" -- dash -c "$ha_pyenv_activation; exec pip3 install homeassistant$version"
|
|
|
|
# Generate script to launch HA using pyenv
|
|
echo "#!/bin/dash
|
|
$ha_pyenv_activation
|
|
exec hass -c '/mnt/dietpi_userdata/homeassistant'" > "$ha_home/homeassistant-start.sh"
|
|
G_EXEC chmod +x "$ha_home/homeassistant-start.sh"
|
|
|
|
# Generate script to update HA within pyenv
|
|
echo "#!/bin/dash
|
|
exec sudo -u $ha_user dash -c '$ha_pyenv_activation; exec pip3 install -U homeassistant$version'" > "$ha_home/homeassistant-update.sh"
|
|
G_EXEC chmod +x "$ha_home/homeassistant-update.sh"
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/home-assistant.service
|
|
[Unit]
|
|
Description=Home Assistant (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target mariadb.service
|
|
|
|
[Service]
|
|
SyslogIdentifier=Home Assistant
|
|
User=$ha_user
|
|
ExecStart=$ha_home/homeassistant-start.sh
|
|
RestartForceExitStatus=100
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Download HACS
|
|
Download_Install 'https://github.com/hacs/integration/releases/latest/download/hacs.zip' hacs
|
|
[[ -d '/mnt/dietpi_userdata/homeassistant/custom_components/hacs' ]] && G_EXEC rm -R /mnt/dietpi_userdata/homeassistant/custom_components/hacs
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/homeassistant/custom_components
|
|
G_EXEC mv hacs /mnt/dietpi_userdata/homeassistant/custom_components/
|
|
G_EXEC chown -R "$ha_user:$ha_user" /mnt/dietpi_userdata/homeassistant
|
|
G_DIETPI-NOTIFY 2 "Home Assistant Community Store (HACS) has been installed in addition. To activate it, follow this guide: https://hacs.xyz/docs/configuration/basic/"
|
|
fi
|
|
|
|
if To_Install 181 papermc # PaperMC
|
|
then
|
|
# Make sure user agrees to the EULA
|
|
if [[ -f '/mnt/dietpi_userdata/papermc/eula.txt' ]] || G_WHIP_BUTTON_OK_TEXT='Yes' G_WHIP_BUTTON_CANCEL_TEXT='Abort' G_WHIP_YESNO 'Do you agree to the Minecraft EULA found at:\n\nhttps://account.mojang.com/documents/minecraft_eula'
|
|
then
|
|
# Collect latest build of latest supported version of PaperMC
|
|
local url='https://api.papermc.io/v2/projects/paper'
|
|
# - Minecraft 1.20.5 and above requires Java 21: https://minecraft.wiki/w/Java_Edition_1.20.5
|
|
local version='1.20.4'
|
|
(( $JAVA_VERSION < 21 )) || { version=$(curl -sSfL "$url"); version=${version%\"*} version=${version##*\"}; }
|
|
local build=$(curl -sSfL "$url/versions/$version"); build=${build%]*} build=${build##*[,[]}
|
|
#local file=$(curl -sSfL "$url/versions/$version/builds/$build"); file=${file##*\"name\":\"} file=${file%%\"*}
|
|
# Download and install PaperMC
|
|
Download_Install "$url/versions/$version/builds/$build/downloads/paper-$version-$build.jar" /opt/papermc/paperclip.jar
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/papermc
|
|
G_EXEC eval 'echo '\''eula=true'\'' > /mnt/dietpi_userdata/papermc/eula.txt'
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/papermc papermc
|
|
|
|
# Bedrock compatibility
|
|
G_WHIP_BUTTON_OK_TEXT='Yes'
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip'
|
|
[[ -f '/mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot.jar' ]] && G_WHIP_DEFAULT_ITEM='Yes'
|
|
if G_WHIP_YESNO 'Would you like to install the Geyser and Floodgate plugins for compatibility with Bedrock Edition?\n\nNote that this may be buggy.'
|
|
then
|
|
local version='2.2.3'
|
|
(( $JAVA_VERSION < 21 )) || version='latest'
|
|
Download_Install "https://download.geysermc.org/v2/projects/geyser/versions/$version/builds/latest/downloads/spigot" /mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot.jar
|
|
Download_Install 'https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot' /mnt/dietpi_userdata/papermc/plugins/floodgate-spigot.jar
|
|
fi
|
|
|
|
# Minecraft rcon client for remote administration and server maintenance scripts
|
|
aDEPS=('gcc' 'libc6-dev')
|
|
Download_Install 'https://github.com/Tiiffi/mcrcon/archive/master.tar.gz'
|
|
G_EXEC gcc -g0 -O3 mcrcon-master/mcrcon.c -o /usr/local/bin/mcrcon
|
|
G_EXEC rm -R mcrcon-master
|
|
G_EXEC strip --remove-section=.comment --remove-section=.note /usr/local/bin/mcrcon
|
|
|
|
# Link logs to RAM
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/papermc/logs
|
|
G_EXEC ln -s /var/log/papermc /mnt/dietpi_userdata/papermc/logs
|
|
|
|
# Permissions
|
|
G_EXEC chown -R papermc:papermc /mnt/dietpi_userdata/papermc
|
|
|
|
# Assure 512 MiB heap size and 1.5 GiB overall memory (-100 MiB to avoid tiny swap space)
|
|
local memory_limit=$JAVA_MAX_HEAP_SIZE
|
|
if (( $memory_limit < 1024 ))
|
|
then
|
|
memory_limit=512
|
|
if (( $RAM_TOTAL < 1436 ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Stable PaperMC operation requires at least 1.5 GiB system memory. We will now increase your swap size to satisfy this requirement.'
|
|
/boot/dietpi/func/dietpi-set_swapfile $(( 1536 - $RAM_PHYS ))
|
|
|
|
# Apply 1 GiB heap size on 2 GiB+ physical RAM devices
|
|
elif (( $RAM_PHYS > 1848 ))
|
|
then
|
|
memory_limit=1024
|
|
fi
|
|
fi
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/papermc.service
|
|
[Unit]
|
|
Description=PaperMC (DietPi)
|
|
Documentation=https://paper.readthedocs.io/
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
SyslogIdentifier=PaperMC
|
|
User=papermc
|
|
LogsDirectory=papermc
|
|
WorkingDirectory=/mnt/dietpi_userdata/papermc
|
|
ExecStart=$JAVA_PATH -mx${memory_limit}m -jar /opt/papermc/paperclip.jar --nogui --noconsole
|
|
SuccessExitStatus=143
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Config
|
|
if [[ -f '/mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot.jar' ]]
|
|
then
|
|
Create_Config /mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot/config.yml papermc 1800 1 &&
|
|
G_CONFIG_INJECT 'auth-type:[[:blank:]]' ' auth-type: floodgate' /mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot/config.yml
|
|
else
|
|
Create_Config /mnt/dietpi_userdata/papermc/permissions.yml papermc 1800 1
|
|
fi
|
|
G_CONFIG_INJECT 'enable-rcon=' 'enable-rcon=true' /mnt/dietpi_userdata/papermc/server.properties
|
|
GCI_PASSWORD=1 G_CONFIG_INJECT 'rcon.password=' "rcon.password=$GLOBAL_PW" /mnt/dietpi_userdata/papermc/server.properties
|
|
|
|
else
|
|
aSOFTWARE_INSTALL_STATE[$software_id]=0
|
|
G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install skipped due to outstanding EULA agreement"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 140 domoticz # Domoticz
|
|
then
|
|
G_AGI domoticz
|
|
fi
|
|
|
|
if To_Install 202 # Rclone
|
|
then
|
|
# RISC-V: No upstream packages yet, hence use Debian repo
|
|
if (( $G_HW_ARCH == 11 ))
|
|
then
|
|
G_AGI rclone
|
|
else
|
|
case $G_HW_ARCH in
|
|
1) local arch='arm-v6';;
|
|
2) local arch='arm-v7';;
|
|
3) local arch='arm64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/rclone/rclone/releases/download/v1.72.1/rclone-v1.72.1-linux-$arch.deb"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/rclone/rclone/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/rclone-v[^\"\/]*-linux-$arch.deb\"$/{print \$4}")"
|
|
fi
|
|
fi
|
|
|
|
if To_Install 209 # Restic
|
|
then
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
10) local arch='amd64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='arm';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/restic/restic/releases/download/v0.18.1/restic_0.18.1_linux_$arch.bz2"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/restic/restic/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/restic_[^\"\/]*_linux_$arch\.bz2\"$/{print \$4}")" /usr/local/bin/restic
|
|
G_EXEC chmod +x /usr/local/bin/restic
|
|
fi
|
|
|
|
if To_Install 210 # MediaWiki
|
|
then
|
|
# Install required PHP modules: https://www.mediawiki.org/wiki/Manual:Installation_requirements#PHP
|
|
aDEPS=("php$PHP_VERSION-gd" "php$PHP_VERSION-intl")
|
|
# - Add JSON module for PHP7, as it does not exist (embedded in core package) on PHP8
|
|
[[ $PHP_VERSION == 8* ]] || aDEPS+=("php$PHP_VERSION-json")
|
|
local php_modules=("${aDEPS[@]##*-}")
|
|
|
|
# Create MariaDB database and user
|
|
if [[ -d '/mnt/dietpi_userdata/mysql/mediawiki' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'MediaWiki MariaDB database found, will NOT overwrite.'
|
|
else
|
|
/boot/dietpi/func/create_mysql_db mediawiki mediawiki "$GLOBAL_PW"
|
|
fi
|
|
|
|
# Get latest version
|
|
local fallback_url='https://releases.wikimedia.org/mediawiki/1.45/mediawiki-1.45.1.tar.gz'
|
|
Download_Install "$(curl -sSfL 'https://www.mediawiki.org/wiki/Download' | grep -o 'https://releases\.wikimedia\.org/mediawiki/[^/"]*/mediawiki-[^"]*\.tar\.gz' | head -1)"
|
|
|
|
# Enable required PHP modules
|
|
G_EXEC phpenmod "${php_modules[@]}"
|
|
|
|
# Webserver configs
|
|
# - Lighttpd
|
|
if (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 ))
|
|
then
|
|
[[ -f '/etc/lighttpd/conf-enabled/05-setenv.conf' ]] || G_EXEC lighty-enable-mod setenv
|
|
cat << '_EOF_' > /etc/lighttpd/conf-available/98-dietpi-mediawiki.conf
|
|
$HTTP["url"] =~ "^/wiki/images($|/)" {
|
|
setenv.set-response-header = ("X-Content-Type-Options" => "nosniff")
|
|
}
|
|
_EOF_
|
|
[[ -f '/etc/lighttpd/conf-enabled/98-dietpi-mediawiki.conf' ]] || lighty-enable-mod dietpi-mediawiki
|
|
|
|
# - Nginx
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 ))
|
|
then
|
|
cat << '_EOF_' > /etc/nginx/sites-dietpi/dietpi-mediawiki.conf
|
|
location ^~ /wiki/images {
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
}
|
|
_EOF_
|
|
fi
|
|
|
|
# Reinstall: Clean install but preserve existing config and uploaded images
|
|
if [[ -f '/var/www/wiki/LocalSettings.php' ]]
|
|
then
|
|
G_EXEC mv /var/www/wiki/LocalSettings.php mediawiki-*/
|
|
G_EXEC chmod 600 mediawiki-*/LocalSettings.php
|
|
fi
|
|
if [[ -d '/var/www/wiki/images' ]]
|
|
then
|
|
G_EXEC cp -a mediawiki-*/images/{.htaccess,README} /var/www/wiki/images/
|
|
G_EXEC cp -a /var/www/wiki/images/. mediawiki-*/images/
|
|
fi
|
|
G_EXEC chown -R www-data:www-data mediawiki-*
|
|
[[ -d '/var/www/wiki' ]] && G_EXEC rm -R /var/www/wiki
|
|
|
|
# Move new instance in place
|
|
G_EXEC mv mediawiki-* /var/www/wiki
|
|
fi
|
|
|
|
if To_Install 211 homebridge # Homebridge
|
|
then
|
|
# APT key
|
|
local url='https://repo.homebridge.io/KEY.gpg'
|
|
G_CHECK_URL "$url"
|
|
G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-homebridge.gpg --yes"
|
|
|
|
# APT list
|
|
G_EXEC eval 'echo '\''deb https://repo.homebridge.io stable main'\'' > /etc/apt/sources.list.d/dietpi-homebridge.list'
|
|
G_AGUP
|
|
|
|
G_AGI homebridge
|
|
G_EXEC systemctl stop homebridge
|
|
|
|
# Workaround for bug with wrong home directory /nonexistent
|
|
G_EXEC usermod -d /var/lib/homebridge homebridge
|
|
fi
|
|
|
|
if To_Install 205 # Homer
|
|
then
|
|
# Download the latest release
|
|
Download_Install 'https://github.com/bastienwirtz/homer/releases/latest/download/homer.zip' homer
|
|
|
|
# Backup existing instance
|
|
if [[ -d '/var/www/homer' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Existing Homer instance found, backing up to /mnt/dietpi_userdata/homer_backup ...'
|
|
[[ -d '/mnt/dietpi_userdata/homer_backup' ]] && G_EXEC rm -R /mnt/dietpi_userdata/homer_backup
|
|
G_EXEC cp -a /var/www/homer /mnt/dietpi_userdata/homer_backup
|
|
G_DIETPI-NOTIFY 2 'Removing old assets with hash in file name ...'
|
|
G_EXEC rm -Rf /var/www/homer/{workbox-*.js,resources}
|
|
fi
|
|
|
|
# Install latest release, preserve existing config
|
|
G_EXEC cp -a homer/. /var/www/homer/
|
|
G_EXEC rm -R homer
|
|
[[ -f '/var/www/homer/assets/config.yml' ]] || G_EXEC cp /var/www/homer/assets/config.yml{.dist,}
|
|
fi
|
|
|
|
if To_Install 198 filebrowser # File Browser
|
|
then
|
|
case $G_HW_ARCH in
|
|
1) local arch='armv6';;
|
|
2) local arch='armv7';;
|
|
3) local arch='arm64';;
|
|
11) local arch='riscv64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
local fallback_url="https://github.com/filebrowser/filebrowser/releases/download/v2.52.0/linux-$arch-filebrowser.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/filebrowser/filebrowser/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/linux-$arch-filebrowser\.tar\.gz\"$/{print \$4}")" ./filebrowser/
|
|
|
|
# Reinstall
|
|
[[ -d '/opt/filebrowser' ]] && G_EXEC rm -R /opt/filebrowser
|
|
|
|
# Install
|
|
G_EXEC mv filebrowser /opt/
|
|
|
|
# User
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/filebrowser
|
|
Create_User -g dietpi -d /mnt/dietpi_userdata/filebrowser filebrowser
|
|
|
|
# Config if not exist
|
|
if [[ ! -f '/mnt/dietpi_userdata/filebrowser/filebrowser.db' ]]
|
|
then
|
|
G_EXEC cd /mnt/dietpi_userdata/filebrowser
|
|
G_EXEC /opt/filebrowser/filebrowser config init
|
|
# Reduce minimum password length to match default software password if it is shorter
|
|
local extra_args=()
|
|
(( ${#GLOBAL_PW} < 12 )) && extra_args+=('--minimum-password-length' "${#GLOBAL_PW}")
|
|
G_EXEC /opt/filebrowser/filebrowser config set -a 0.0.0.0 -p 8084 -r /mnt "${extra_args[@]}"
|
|
G_EXEC_DESC='Setting up File Browser login user "dietpi"' G_EXEC /opt/filebrowser/filebrowser users add dietpi "$GLOBAL_PW" --perm.admin
|
|
fi
|
|
|
|
# Permissions
|
|
G_EXEC chown -R filebrowser:root /mnt/dietpi_userdata/filebrowser /opt/filebrowser
|
|
|
|
# Service
|
|
cat << '_EOF_' > /etc/systemd/system/filebrowser.service
|
|
[Unit]
|
|
Description=File Browser (DietPi)
|
|
Documentation=https://filebrowser.org/
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target
|
|
|
|
[Service]
|
|
User=filebrowser
|
|
UMask=002
|
|
ExecStart=/opt/filebrowser/filebrowser -d /mnt/dietpi_userdata/filebrowser/filebrowser.db
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 199 spotifyd # Spotifyd
|
|
then
|
|
# Obtain supported version, variant and related dependencies. It became very complicated: https://github.com/MichaIng/DietPi/issues/6419
|
|
local arch='' variant='full' version='' aDEPS=('libdbus-1-3' 'libpulse0')
|
|
case $G_HW_ARCH in
|
|
1) arch='armv6' variant='slim' version='0.3.5' aDEPS=();; # Last supported version and only supported variant for ARMv6
|
|
2) arch='armv7';;
|
|
3) arch='aarch64';;
|
|
*) arch='x86_64';;
|
|
esac
|
|
|
|
# Download specific version if given, else obtain latest version from GitHub API
|
|
if [[ $version ]]
|
|
then
|
|
Download_Install "https://github.com/Spotifyd/spotifyd/releases/download/v$version/spotifyd-linux-$arch-$variant.tar.gz" /opt/spotifyd
|
|
else
|
|
local fallback_url="https://github.com/Spotifyd/spotifyd/releases/download/v0.4.2/spotifyd-linux-$arch-$variant.tar.gz"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/Spotifyd/spotifyd/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/spotifyd-linux-$arch-$variant\.tar\.gz\"$/{print \$4}")" /opt/spotifyd
|
|
fi
|
|
|
|
# User
|
|
Create_User -G audio -d /mnt/dietpi_userdata/spotifyd spotifyd
|
|
|
|
# Config: Do not touch on reinstall
|
|
if [[ ! -f '/mnt/dietpi_userdata/spotifyd/spotifyd.conf' ]]
|
|
then
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/spotifyd/cache
|
|
dps_index=$software_id Download_Install 'spotifyd.conf' /mnt/dietpi_userdata/spotifyd/spotifyd.conf
|
|
G_EXEC chmod 0600 /mnt/dietpi_userdata/spotifyd/spotifyd.conf
|
|
fi
|
|
|
|
# Service: https://github.com/Spotifyd/spotifyd/blob/master/contrib/spotifyd.service
|
|
cat << '_EOF_' > /etc/systemd/system/spotifyd.service
|
|
[Unit]
|
|
Description=Spotifyd (DietPi)
|
|
Wants=network-online.target
|
|
After=network-online.target sound.target
|
|
|
|
[Service]
|
|
User=spotifyd
|
|
WorkingDirectory=/mnt/dietpi_userdata/spotifyd
|
|
ExecStart=/opt/spotifyd/spotifyd --no-daemon --config-path=/mnt/dietpi_userdata/spotifyd/spotifyd.conf
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Permissions
|
|
G_EXEC chown -R spotifyd:root /mnt/dietpi_userdata/spotifyd
|
|
G_EXEC chmod +x /opt/spotifyd/spotifyd
|
|
fi
|
|
|
|
if To_Install 185 # Portainer
|
|
then
|
|
# Remove existing container and image, including CE, BE, and old v1, and store image repo in variable to preserve BE instances
|
|
local container=$(docker container ls -aqf 'ancestor=portainer/portainer' -f 'ancestor=portainer/portainer-ce' -f 'ancestor=portainer/portainer-ee') image repo
|
|
[[ $container ]] && G_EXEC docker container rm -f "$container"
|
|
read -r image repo < <(docker image ls -af 'reference=portainer/portainer' -f 'reference=portainer/portainer-ce' -f 'reference=portainer/portainer-ee' --format '{{.ID}} {{.Repository}}')
|
|
[[ $image ]] && G_EXEC docker image rm "$image"
|
|
|
|
# Create volume if it does not exist yet
|
|
[[ $(docker volume ls -qf 'name=^portainer_data$') ]] || G_EXEC docker volume create portainer_data
|
|
|
|
# Deploy new Portainer container, migrate v1 to CE and preserve BE
|
|
[[ $repo == 'portainer/portainer-ee' ]] || repo='portainer/portainer-ce'
|
|
G_EXEC_OUTPUT=1 G_EXEC docker run -d -p '9002:9000' -p '9442:9443' --name=portainer --restart=always -v '/run/docker.sock:/var/run/docker.sock' -v '/etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro' -v 'portainer_data:/data' "$repo"
|
|
fi
|
|
|
|
if To_Install 141 adsb-setup adsb-docker # ADS-B Feeder
|
|
then
|
|
# clone the adsb-feeder repo into /tmp
|
|
G_EXEC_OUTPUT=1 G_EXEC git clone -b dietpi 'https://github.com/dirkhh/adsb-feeder-image' /tmp/adsb-feeder
|
|
|
|
# remove the service that isn't needed for an app install on DietPi and install the rest
|
|
G_EXEC cd /tmp/adsb-feeder/src/modules/adsb-feeder/filesystem/root
|
|
G_EXEC rm ./usr/lib/systemd/system/adsb-bootstrap.service
|
|
G_EXEC rm ./usr/lib/systemd/system/adsb-update.service
|
|
G_EXEC rm ./usr/lib/systemd/system/adsb-update.timer
|
|
# Fix bash path on potentially non-usr-merged systems
|
|
[[ -f '/usr/bin/bash' ]] || G_EXEC sed --follow-symlinks -i 's|/usr/bin/bash|/bin/bash|' ./usr/lib/systemd/system/adsb-*.service
|
|
G_EXEC mv ./usr/lib/systemd/system/* /etc/systemd/system/
|
|
|
|
# determine the version
|
|
local ADSB_FEEDER_DATE_COMPONENT=$(git log -20 --date='format:%y%m%d' --format='%ad' | uniq -c | mawk '{print $2"."$1;exit}')
|
|
local ADSB_FEEDER_TAG_COMPONENT=$(git describe --match 'v[0-9]*' --long | sed 's/-[0-9]*-g[0-9a-f]*//')
|
|
local ADSB_FEEDER_VERSION="$ADSB_FEEDER_TAG_COMPONENT(dietpi)-$ADSB_FEEDER_DATE_COMPONENT"
|
|
|
|
# create the target directory for the app and populated with the code from the git checkout
|
|
[[ -d '/opt/adsb' ]] && G_EXEC rm -R /opt/adsb
|
|
G_EXEC mv /tmp/adsb-feeder/src/modules/adsb-feeder/filesystem/root/opt/adsb /opt/
|
|
G_EXEC cd /opt/adsb
|
|
|
|
# remove the git clone of the repo we installed from
|
|
G_EXEC rm -R /tmp/adsb-feeder
|
|
|
|
# create a symlink so the config files reside where they should be in /mnt/dietpi_userdata/adsb-feeder
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/adsb-feeder/config
|
|
G_EXEC ln -s /mnt/dietpi_userdata/adsb-feeder/config .
|
|
|
|
# set the 'image name' and version that are shown in the footer of the Web UI and mark as app, not image
|
|
G_EXEC eval 'echo '\''ADSB Feeder app running on DietPi'\'' > feeder-image.name'
|
|
G_EXEC eval "echo '$ADSB_FEEDER_VERSION' > adsb.im.version"
|
|
G_EXEC rm -f os.adsb.feeder.image
|
|
G_EXEC touch app.adsb.feeder.image
|
|
|
|
# get the Python modules
|
|
G_EXEC_OUTPUT=1 G_EXEC pip3 install -U flask requests
|
|
|
|
# finally ensure that /run allows executables (this is needed for the containers to be able to not do excessive
|
|
# writes to physical storage - which might be an SD card)
|
|
G_EXEC mount -o remount,exec /run
|
|
fi
|
|
|
|
if To_Install 172 # WireGuard
|
|
then
|
|
# Pre-v8.12: Purge DKMS as it is not required and might mess with available kernel module
|
|
dpkg-query -s wireguard-dkms &> /dev/null && G_AGP wireguard-dkms
|
|
|
|
# Install user space tools
|
|
G_AGI wireguard-tools iptables qrencode
|
|
Configure_iptables
|
|
|
|
# Server/Client choice
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'Server' ': Use this machine as VPN server and allow clients to connect to it.'
|
|
'Client' ': Use this machine as VPN client to connect to another VPN server or service provider.'
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_WIREGUARD_MODE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ ${G_WHIP_DEFAULT_ITEM,,} == 'client' ]] || G_WHIP_DEFAULT_ITEM='Server'
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_MENU 'Please choose if this machine should be set up as VPN server or client:'
|
|
G_CONFIG_INJECT 'SOFTWARE_WIREGUARD_MODE=' "SOFTWARE_WIREGUARD_MODE=$G_WHIP_RETURNED_VALUE" /boot/dietpi.txt
|
|
|
|
# Server choice
|
|
if [[ $G_WHIP_RETURNED_VALUE == 'Server' ]]
|
|
then
|
|
# Public IP/domain and desired WireGuard server port
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_PUBLIC_DOMAIN_NAME=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(find /etc/letsencrypt/live -mindepth 1 -maxdepth 1 -type d -print -quit 2> /dev/null)
|
|
[[ $G_WHIP_DEFAULT_ITEM ]] || G_WHIP_DEFAULT_ITEM=$(hostname -f)
|
|
G_WHIP_NOCANCEL=1
|
|
G_WHIP_INPUTBOX 'Please enter your servers public IP/domain for WireGuard client access:'
|
|
local domain=${G_WHIP_RETURNED_VALUE#http*://}
|
|
GCI_PRESERVE=1 G_CONFIG_INJECT 'SOFTWARE_PUBLIC_DOMAIN_NAME=' "SOFTWARE_PUBLIC_DOMAIN_NAME=$domain" /boot/dietpi.txt
|
|
|
|
G_WHIP_DEFAULT_ITEM=$(sed -n '/^[[:blank:]]*SOFTWARE_WIREGUARD_PORT=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
disable_error=1 G_CHECK_VALIDINT "$G_WHIP_DEFAULT_ITEM" 0 || G_WHIP_DEFAULT_ITEM=51820
|
|
G_WHIP_NOCANCEL=1 G_WHIP_INPUTBOX_REGEX='^[1-9][0-9]*$' G_WHIP_INPUTBOX_REGEX_TEXT='a valid port number'
|
|
G_WHIP_INPUTBOX 'Please enter the network port that will be used to access your WireGuard server:\n
|
|
NB: This port needs to be forwarded by your router and/or opened in your firewall settings. Default value is: 51820'
|
|
local port=$G_WHIP_RETURNED_VALUE
|
|
|
|
# Create everything inside WireGuard config dir
|
|
G_EXEC cd /etc/wireguard
|
|
|
|
# For security reasons set umask to 0077
|
|
G_EXEC umask 0077
|
|
|
|
# Create server and client keys
|
|
[[ -f 'server_private.key' ]] || wg genkey > server_private.key
|
|
[[ -f 'server_public.key' ]] || wg pubkey < server_private.key > server_public.key
|
|
[[ -f 'client_private.key' ]] || wg genkey > client_private.key
|
|
[[ -f 'client_public.key' ]] || wg pubkey < client_private.key > client_public.key
|
|
|
|
# Server config
|
|
[[ -f 'wg0.conf' ]] || cat << _EOF_ > wg0.conf || exit 1
|
|
[Interface]
|
|
Address = 10.9.0.1/24
|
|
PrivateKey = $(<server_private.key)
|
|
ListenPort = $port
|
|
|
|
PostUp = sysctl net.ipv4.conf.%i.forwarding=1 net.ipv4.conf.\$(ip r l 0/0 | mawk '{print \$5;exit}').forwarding=1
|
|
PostUp = sysctl net.ipv6.conf.\$(ip r l 0/0 | mawk '{print \$5;exit}').accept_ra=2
|
|
PostUp = sysctl net.ipv6.conf.%i.forwarding=1 net.ipv6.conf.\$(ip r l 0/0 | mawk '{print \$5;exit}').forwarding=1
|
|
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -s 10.9.0.0/24 -o \$(ip r l 0/0 | mawk '{print \$5;exit}') -j MASQUERADE
|
|
PostUp = ip6tables -A FORWARD -i %i -j ACCEPT; ip6tables -t nat -A POSTROUTING -o \$(ip r l 0/0 | mawk '{print \$5;exit}') -j MASQUERADE
|
|
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -s 10.9.0.0/24 -o \$(ip r l 0/0 | mawk '{print \$5;exit}') -j MASQUERADE
|
|
PostDown = ip6tables -D FORWARD -i %i -j ACCEPT; ip6tables -t nat -D POSTROUTING -o \$(ip r l 0/0 | mawk '{print \$5;exit}') -j MASQUERADE
|
|
|
|
# Client 1
|
|
[Peer]
|
|
PublicKey = $(<client_public.key)
|
|
AllowedIPs = 10.9.0.2/32
|
|
|
|
# Client 2
|
|
#[Peer]
|
|
#PublicKey = XXXX
|
|
#AllowedIPs = 10.9.0.3/32
|
|
_EOF_
|
|
# Server local network IP
|
|
local server_ip=$(G_GET_NET ip)
|
|
|
|
# Server DNS nameserver
|
|
local server_dns=$(mawk '/nameserver/{print $2;exit}' /etc/resolv.conf)
|
|
# - Replace "127.0.0.1"/"localhost" loopback entries by server wg0 IP: https://github.com/MichaIng/DietPi/issues/2482
|
|
server_dns=${server_dns//127.0.0.1/10.9.0.1}
|
|
server_dns=${server_dns//localhost/10.9.0.1}
|
|
|
|
# Client config
|
|
[[ -f 'wg0-client.conf' ]] || cat << _EOF_ > wg0-client.conf
|
|
[Interface]
|
|
Address = 10.9.0.2/24
|
|
PrivateKey = $(<client_private.key)
|
|
|
|
# Comment the following to preserve the clients default DNS server, or force a desired one.
|
|
DNS = $server_dns
|
|
|
|
# Kill switch: Uncomment the following if the client should stop any network traffic, when disconnected from the VPN server
|
|
# NB: This requires "iptables" to be installed, thus will not work on most mobile phones.
|
|
#PostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark \$(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT; ip6tables -I OUTPUT ! -o %i -m mark ! --mark \$(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
|
|
#PreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark \$(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT; ip6tables -D OUTPUT ! -o %i -m mark ! --mark \$(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT
|
|
|
|
[Peer]
|
|
PublicKey = $(<server_public.key)
|
|
# Tunnel all network traffic through the VPN:
|
|
# AllowedIPs = 0.0.0.0/0, ::/0
|
|
# Tunnel access to server-side local network only:
|
|
# AllowedIPs = ${server_ip%.*}.0/24
|
|
# Tunnel access to VPN server only:
|
|
# AllowedIPs = $server_ip/32
|
|
AllowedIPs = 0.0.0.0/0, ::/0
|
|
Endpoint = $domain:$port
|
|
|
|
# Uncomment the following if you're behind a NAT and want the connection to be kept alive.
|
|
#PersistentKeepalive = 25
|
|
_EOF_
|
|
unset -v domain port server_ip server_dns
|
|
|
|
# Set umask back to default 0022
|
|
G_EXEC umask 0022
|
|
|
|
# Navigate back to DietPi-Software working dir
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
|
|
# Use wg-quick@.service to start VPN on boot
|
|
G_EXEC systemctl enable --now wg-quick@wg0
|
|
|
|
# Client choice
|
|
elif [[ $G_WHIP_RETURNED_VALUE == 'Client' ]]
|
|
then
|
|
G_AGI resolvconf # Use by wg-quick to apply DNS in client setup
|
|
G_WHIP_MSG '[ INFO ] WireGuard client setup has been chosen\n
|
|
Please follow the instructions of your VPN provider to configure WireGuard.\n
|
|
If no WireGuard (auto)start is included, but you require it, please do the following:
|
|
1. Check for the created config file/interface name:
|
|
ls -Al /etc/wireguard/
|
|
It has a ".conf" file ending, lets assume "wg0-client.conf".
|
|
2. To start the VPN interface, run:
|
|
systemctl start wg-quick@wg0-client
|
|
3. To autostart the VPN interface on boot, run:
|
|
systemctl enable wg-quick@wg0-client
|
|
4. To disable autostart again, run:
|
|
systemctl disable wg-quick@wg0-client'
|
|
fi
|
|
fi
|
|
|
|
if To_Install 213 soju # soju
|
|
then
|
|
# Dependencies
|
|
aDEPS=('make' 'scdoc' 'gcc' 'libsqlite3-dev' 'libpam-dev')
|
|
|
|
# Download
|
|
local fallback_url='https://github.com/emersion/soju/releases/download/v0.8.0/soju-0.8.0.tar.gz'
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/emersion/soju/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/soju-[^"\/]*\.tar\.gz"$/{print $4}')"
|
|
|
|
# Build
|
|
G_EXEC cd soju-*
|
|
G_EXEC_OUTPUT=1 G_EXEC make all "-j$(nproc)" config_path='/mnt/dietpi_userdata/soju/config' GOFLAGS='-tags=pam,libsqlite3'
|
|
|
|
# Install
|
|
local commands=('soju' 'sojuctl' 'sojudb')
|
|
local manpages=('doc/soju.1' 'doc/sojuctl.1')
|
|
G_EXEC cp "${commands[@]}" /usr/local/bin/
|
|
G_EXEC mkdir -p /usr/local/share/man/man1
|
|
G_EXEC cp "${manpages[@]}" /usr/local/share/man/man1/
|
|
|
|
# Config
|
|
if [[ ! -f '/mnt/dietpi_userdata/soju/config' ]]
|
|
then
|
|
# We shall default to on-disk chat logs
|
|
# It's a lossy format, as stated under `message-store` subsection in https://soju.im/doc/soju.1.html#CONFIG_FILE
|
|
# But it's the recommended setting as per https://git.sr.ht/~emersion/soju/tree/master/doc/getting-started.md
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/soju
|
|
cat <<- '_EOF_' > /mnt/dietpi_userdata/soju/config
|
|
db sqlite3 /mnt/dietpi_userdata/soju/data.db
|
|
message-store fs /mnt/dietpi_userdata/soju/logs
|
|
listen irc+insecure://
|
|
listen unix+admin://
|
|
_EOF_
|
|
fi
|
|
|
|
# User
|
|
Create_User -d /mnt/dietpi_userdata/soju soju
|
|
G_EXEC chown 'soju:soju' -R /mnt/dietpi_userdata/soju
|
|
G_EXEC chmod 0660 -R /mnt/dietpi_userdata/soju
|
|
G_EXEC chmod 0770 /mnt/dietpi_userdata/soju
|
|
|
|
# Service: https://github.com/emersion/soju/blob/master/contrib/soju.service
|
|
# - CAP_NET_BIND_SERVICE needed for builtin identd server: https://github.com/emersion/soju/blob/master/doc/packaging.md#binding-to-privileged-ports
|
|
cat << '_EOF_' > /etc/systemd/system/soju.service
|
|
[Unit]
|
|
Description=soju IRC bouncer service
|
|
Documentation=https://soju.im/
|
|
Documentation=man:soju(1) man:sojuctl(1)
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
User=soju
|
|
RuntimeDirectory=soju
|
|
WorkingDirectory=/mnt/dietpi_userdata/soju
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
ExecStart=/usr/local/bin/soju
|
|
ExecReload=/bin/kill -HUP $MAINPID
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 169 lazylibrarian # LazyLibrarian
|
|
then
|
|
# Dependencies
|
|
aDEPS=('python3-venv')
|
|
Python_Deps cryptography pillow
|
|
|
|
# Download
|
|
Download_Install 'https://gitlab.com/LazyLibrarian/LazyLibrarian/-/archive/master/LazyLibrarian-master.tar.bz2'
|
|
|
|
# Add dummy unbundled.libs to prevent unnecessary attempt to remove bundled libraries which do not exist. It is falsely determined since the venv is inside the install dir.
|
|
> LazyLibrarian-master/unbundled.libs
|
|
|
|
# Install: Clear existing instance
|
|
[[ -d '/opt/lazylibrarian' ]] && G_EXEC rm -R /opt/lazylibrarian
|
|
G_EXEC mv LazyLibrarian-master /opt/lazylibrarian
|
|
|
|
# Python venv
|
|
G_EXEC python3 -m venv /opt/lazylibrarian/venv
|
|
G_EXEC_OUTPUT=1 G_EXEC /opt/lazylibrarian/venv/bin/pip install /opt/lazylibrarian
|
|
|
|
# User
|
|
Create_User -g dietpi lazylibrarian
|
|
|
|
# Data directory
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/lazylibrarian
|
|
G_EXEC chmod 0750 /mnt/dietpi_userdata/lazylibrarian
|
|
|
|
# Config: Preserve existing
|
|
[[ -f '/mnt/dietpi_userdata/lazylibrarian/config.ini' ]] || G_EXEC eval 'cat << '\''_EOF_'\'' > /mnt/dietpi_userdata/lazylibrarian/config.ini
|
|
[GENERAL]
|
|
ebook_dir = /mnt/dietpi_userdata/ebooks
|
|
audio_dir = /mnt/dietpi_userdata/audiobooks
|
|
download_dir = /mnt/dietpi_userdata/downloads
|
|
|
|
[LOGGING]
|
|
logdir = /var/log/lazylibrarian
|
|
_EOF_'
|
|
# Add version info to prevent unnecessary update attempt on first service start of fresh install and make update checks meaningful
|
|
G_EXEC mkdir -p /mnt/dietpi_userdata/lazylibrarian/cache
|
|
curl -sSfL 'https://gitlab.com/api/v4/projects/9317860/repository/commits?per_page=1' | mawk -F\" '{print $8}' > /mnt/dietpi_userdata/lazylibrarian/cache/version.txt
|
|
|
|
# Permissions
|
|
G_EXEC chown -R 'lazylibrarian' /mnt/dietpi_userdata/lazylibrarian
|
|
|
|
# Service: https://gitlab.com/LazyLibrarian/LazyLibrarian/-/blob/master/init
|
|
cat << '_EOF_' > /etc/systemd/system/lazylibrarian.service
|
|
[Unit]
|
|
Description=LazyLibrarian
|
|
Documentation=https://lazylibrarian.gitlab.io
|
|
Wants=network-online.target
|
|
After=network-online.target remote-fs.target transmission-daemon.service qbittorrent.service rtorrent.service nzbget.service deluged.service aria2.service sabnzbd.service
|
|
|
|
[Service]
|
|
SyslogIdentifier=LazyLibrarian
|
|
User=lazylibrarian
|
|
UMask=002
|
|
LogsDirectory=lazylibrarian
|
|
ExecStart=/opt/lazylibrarian/venv/bin/python /opt/lazylibrarian/LazyLibrarian.py --datadir=/mnt/dietpi_userdata/lazylibrarian --nolaunch
|
|
ExitType=cgroup
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
PrivateDevices=true
|
|
PrivateTmp=true
|
|
ProtectKernelTunables=true
|
|
ProtectControlGroups=true
|
|
ReadWritePaths=-/opt/lazylibrarian -/mnt -/media -/var/log/lazylibrarian -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 127 birdnet # BirdNET-Go: https://github.com/tphakala/birdnet-go/blob/main/install.sh
|
|
then
|
|
local bnet_vers='nightly-20251028'
|
|
local bnet_inst='/opt/birdnet'
|
|
local bnet_data='/mnt/dietpi_userdata/birdnet'
|
|
local bnet_conf="$bnet_data/.config/birdnet-go/config.yaml"
|
|
local bnet_user='birdnet'
|
|
local bnet_port=8127
|
|
|
|
# Dependencies
|
|
aDEPS=('sox' 'patchelf')
|
|
# - Add yq only on first install
|
|
local install_yq=0
|
|
[[ -f $bnet_conf ]] || command -v yq > /dev/null || install_yq=1 aDEPS+=('yq')
|
|
|
|
case $G_HW_ARCH in
|
|
3) local arch='arm64';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
# Download
|
|
Download_Install "https://github.com/tphakala/birdnet-go/releases/download/$bnet_vers/birdnet-go-linux-$arch.tar.gz" birdnet
|
|
|
|
# Change rpath for birdnet-go to make use of libtensorflowlite_c.so in its own dir
|
|
G_EXEC patchelf --set-rpath "$bnet_inst" birdnet/birdnet-go
|
|
|
|
# Install: Remove old dir on reinstall
|
|
[[ -d $bnet_inst ]] && G_EXEC rm -R "$bnet_inst"
|
|
G_EXEC mv birdnet "$bnet_inst"
|
|
|
|
# User
|
|
Create_User -G audio -d "$bnet_data" "$bnet_user"
|
|
|
|
# Data dir
|
|
G_EXEC mkdir -p "$bnet_data"
|
|
G_EXEC chown -R "$bnet_user:$bnet_user" "$bnet_data"
|
|
|
|
# Config
|
|
# - Checks hard-coded paths in this order: ~/.config/birdnet-go/config.yaml > /etc/birdnet-go/config.yaml
|
|
if [[ ! -f $bnet_conf ]]
|
|
then
|
|
# Initial call to generate ~/.config/birdnet-go/config.yaml
|
|
G_EXEC runuser -u "$bnet_user" -- "$bnet_inst/birdnet-go"
|
|
# Replace paths, otherwise defaults to the working directory
|
|
# Disable MQTT and CPU/memory/disk monitoring
|
|
# Enable new web UI at $bnet_port
|
|
G_EXEC yq -yi "
|
|
.output.sqlite.path = \"$bnet_data/birdnet.db\" |
|
|
.main.log.path = \"$bnet_data/logs/birdnet.log\" |
|
|
.realtime.log.path = \"$bnet_data/logs/birdnet.txt\" |
|
|
.realtime.audio.export.path = \"$bnet_data/clips\" |
|
|
.realtime.output.file.path = \"$bnet_data/output\" |
|
|
.realtime.mqtt.enabled = false |
|
|
.realtime.monitoring.enabled = false |
|
|
.realtime.webserver.enabled = true |
|
|
.realtime.dashboard.newui = true |
|
|
.webserver.port = $bnet_port" "$bnet_conf"
|
|
# Purge yq if it was installed for BirdNET-Go only
|
|
(( $install_yq )) && G_AGP yq
|
|
fi
|
|
|
|
# Service
|
|
cat << _EOF_ > /etc/systemd/system/birdnet.service || exit 1
|
|
[Unit]
|
|
Description=BirdNet-Go
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
User=$bnet_user
|
|
WorkingDirectory=$bnet_data
|
|
ExecStart=$bnet_inst/birdnet-go realtime
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=1
|
|
PrivateTmp=1
|
|
ProtectKernelTunables=1
|
|
ProtectControlGroups=1
|
|
ReadWritePaths=-$bnet_data -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
fi
|
|
|
|
if To_Install 12 # RustDesk Server
|
|
then
|
|
local rd_inst='/opt/rustdesk'
|
|
local rd_data='/mnt/dietpi_userdata/rustdesk'
|
|
case "$G_HW_ARCH" in
|
|
2) local arch='armv7';;
|
|
3) local arch='arm64v8';;
|
|
*) local arch='amd64';;
|
|
esac
|
|
|
|
# Download
|
|
local fallback_url="https://github.com/rustdesk/rustdesk-server/releases/download/1.1.14/rustdesk-server-linux-$arch.zip"
|
|
Download_Install "$(curl -sSfL 'https://api.github.com/repos/rustdesk/rustdesk-server/releases/latest' | mawk -F\" "/^ *\"browser_download_url\": \".*\/rustdesk-server-linux-$arch\.zip\"$/{print \$4}")" rustdesk
|
|
|
|
# Install: remove old install dir
|
|
[[ -d $rd_inst ]] && G_EXEC rm -R "$rd_inst"
|
|
G_EXEC mv "rustdesk/$arch" "$rd_inst"
|
|
G_EXEC rm -R rustdesk
|
|
|
|
# User
|
|
Create_User -d "$rd_data" rustdesk
|
|
|
|
# Data dir and config files:
|
|
# - https://github.com/rustdesk/rustdesk-server/blob/c6502179/README.md
|
|
# - https://github.com/rustdesk/rustdesk-server/discussions/371#discussioncomment-13971105
|
|
G_EXEC mkdir -p "$rd_data"
|
|
[[ -f $rd_data/signal.env ]] || cat << _EOF_ > "$rd_data/signal.env" || exit 1
|
|
# RustDesk Signal Server settings: "$rd_data/signal.env
|
|
|
|
# TCP/UDP listening port (default: 21116)
|
|
#PORT=21116
|
|
|
|
# Client authentication key, else the auto-generated $rd_data/id_ed25519.pub is used
|
|
#KEY=
|
|
|
|
# Log level error|warn|info|debug|trace (default: info)
|
|
# NB: "info" logs client IPs, hence we suggest to switch to "warn" for production.
|
|
#RUST_LOG=info
|
|
|
|
# Database path relative to $rd_data (default: db_v2.sqlite3)
|
|
#DB_URL=db_v2.sqlite3
|
|
|
|
# Set to "Y" to disallows direct P2P connections (default: N)
|
|
#ALWAYS_USE_RELAY=N
|
|
_EOF_
|
|
[[ -f $rd_data/relay.env ]] || cat << _EOF_ > "$rd_data/relay.env" || exit 1
|
|
# RustDesk Relay Server settings: $rd_data/relay.env
|
|
|
|
# TCP listening port (default: 21117)
|
|
#PORT=21117
|
|
|
|
# Client authentication key, else the auto-generated $rd_data/id_ed25519.pub is used
|
|
#KEY=
|
|
|
|
# Log level error|warn|info|debug|trace (default: info)
|
|
# NB: "info" logs client IPs, hence we suggest to switch to "warn" for production.
|
|
#RUST_LOG=info
|
|
|
|
# Total bandwidth limit in MiB/s (default: 1024)
|
|
#TOTAL_BANDWIDTH=1024
|
|
|
|
# Single connection bandwidth limit in MiB/s (default: 128)
|
|
#SINGLE_BANDWIDTH=128
|
|
|
|
# Bandwidth limit for clients listed in $rd_data/blacklist.txt in MiB/s (default: 32)
|
|
#LIMIT_SPEED=32
|
|
|
|
# Delay before limiting bandwidth in seconds (default: 1800)
|
|
#DOWNGRADE_START_CHECK=1800
|
|
|
|
# Threshold before limiting bandwidth in bit/ms (default: 0.66)
|
|
#DOWNGRADE_THRESHOLD=0.66
|
|
_EOF_
|
|
G_EXEC chmod 0700 "$rd_data"
|
|
G_EXEC chmod 0600 "$rd_data"/*
|
|
G_EXEC chown -R rustdesk:0 "$rd_data"
|
|
|
|
# Service hbbs: https://github.com/rustdesk/rustdesk-server/blob/master/systemd/rustdesk-hbbs.service
|
|
cat << _EOF_ > /etc/systemd/system/rustdesksignal.service
|
|
[Unit]
|
|
Description=RustDesk Signal Server
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=RustDesk Signal Server
|
|
User=rustdesk
|
|
WorkingDirectory=$rd_data
|
|
EnvironmentFile=$rd_data/signal.env
|
|
ExecStart=$rd_inst/hbbs
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=1
|
|
PrivateUsers=1
|
|
PrivateTmp=1
|
|
PrivateDevices=1
|
|
ProtectKernelTunables=1
|
|
ProtectControlGroups=1
|
|
ProtectKernelModules=1
|
|
ProtectKernelLogs=1
|
|
ProtectClock=1
|
|
ReadWritePaths=-$rd_data -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
# Service hbbr: https://github.com/rustdesk/rustdesk-server/blob/master/systemd/rustdesk-hbbr.service
|
|
cat << _EOF_ > /etc/systemd/system/rustdeskrelay.service
|
|
[Unit]
|
|
Description=RustDesk Relay Server
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
StartLimitIntervalSec=60
|
|
StartLimitBurst=3
|
|
|
|
[Service]
|
|
SyslogIdentifier=RustDesk Relay Server
|
|
User=rustdesk
|
|
WorkingDirectory=$rd_data
|
|
EnvironmentFile=$rd_data/relay.env
|
|
ExecStart=$rd_inst/hbbr
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
LimitNOFILE=4096
|
|
|
|
# Hardening
|
|
ProtectSystem=strict
|
|
ProtectHome=1
|
|
PrivateUsers=1
|
|
PrivateTmp=1
|
|
PrivateDevices=1
|
|
ProtectKernelTunables=1
|
|
ProtectControlGroups=1
|
|
ProtectKernelModules=1
|
|
ProtectKernelLogs=1
|
|
ProtectClock=1
|
|
ReadWritePaths=-$rd_data -/tmp
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
_EOF_
|
|
aSTART_SERVICES+=('rustdesksignal' 'rustdeskrelay')
|
|
unset -v rd_inst rd_data
|
|
fi
|
|
}
|
|
|
|
# $1: 0=None -1=Dropbear -2=OpenSSH
|
|
Apply_SSHServer_Choices()
|
|
{
|
|
if (( $1 == 0 ))
|
|
then
|
|
[[ ${aSOFTWARE_INSTALL_STATE[104]} == [01] ]] && aSOFTWARE_INSTALL_STATE[104]=0 || aSOFTWARE_INSTALL_STATE[104]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[105]} == [01] ]] && aSOFTWARE_INSTALL_STATE[105]=0 || aSOFTWARE_INSTALL_STATE[105]=-1
|
|
|
|
elif (( $1 == -2 ))
|
|
then
|
|
[[ ${aSOFTWARE_INSTALL_STATE[104]} == [01] ]] && aSOFTWARE_INSTALL_STATE[104]=0 || aSOFTWARE_INSTALL_STATE[104]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[105]} == [01] ]] && aSOFTWARE_INSTALL_STATE[105]=1 || aSOFTWARE_INSTALL_STATE[105]=2
|
|
else
|
|
[[ ${aSOFTWARE_INSTALL_STATE[104]} == [01] ]] && aSOFTWARE_INSTALL_STATE[104]=1 || aSOFTWARE_INSTALL_STATE[104]=2
|
|
[[ ${aSOFTWARE_INSTALL_STATE[105]} == [01] ]] && aSOFTWARE_INSTALL_STATE[105]=0 || aSOFTWARE_INSTALL_STATE[105]=-1
|
|
fi
|
|
}
|
|
|
|
# $1: 0=None -1=DietPi-RAMlog #1 -2=DietPi-RAMlog #2 -3=Full
|
|
Apply_Logging_Choices()
|
|
{
|
|
if (( $1 == 0 ))
|
|
then
|
|
[[ ${aSOFTWARE_INSTALL_STATE[101]} == [01] ]] && aSOFTWARE_INSTALL_STATE[101]=0 || aSOFTWARE_INSTALL_STATE[101]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[102]} == [01] ]] && aSOFTWARE_INSTALL_STATE[102]=0 || aSOFTWARE_INSTALL_STATE[102]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[103]} == [01] ]] && aSOFTWARE_INSTALL_STATE[103]=0 || aSOFTWARE_INSTALL_STATE[103]=-1
|
|
|
|
elif (( $1 == -2 ))
|
|
then
|
|
[[ ${aSOFTWARE_INSTALL_STATE[101]} == [01] ]] && aSOFTWARE_INSTALL_STATE[101]=0 || aSOFTWARE_INSTALL_STATE[101]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[102]} == [01] ]] && aSOFTWARE_INSTALL_STATE[102]=0 || aSOFTWARE_INSTALL_STATE[102]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[103]} == [01] ]] && aSOFTWARE_INSTALL_STATE[103]=1 || aSOFTWARE_INSTALL_STATE[103]=2
|
|
|
|
elif (( $1 == -3 ))
|
|
then
|
|
[[ ${aSOFTWARE_INSTALL_STATE[101]} == [01] ]] && aSOFTWARE_INSTALL_STATE[101]=1 || aSOFTWARE_INSTALL_STATE[101]=2
|
|
[[ ${aSOFTWARE_INSTALL_STATE[102]} == [01] ]] && aSOFTWARE_INSTALL_STATE[102]=1 || aSOFTWARE_INSTALL_STATE[102]=2
|
|
[[ ${aSOFTWARE_INSTALL_STATE[103]} == [01] ]] && aSOFTWARE_INSTALL_STATE[103]=0 || aSOFTWARE_INSTALL_STATE[103]=-1
|
|
else
|
|
set -- '-1'
|
|
[[ ${aSOFTWARE_INSTALL_STATE[101]} == [01] ]] && aSOFTWARE_INSTALL_STATE[101]=0 || aSOFTWARE_INSTALL_STATE[101]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[102]} == [01] ]] && aSOFTWARE_INSTALL_STATE[102]=0 || aSOFTWARE_INSTALL_STATE[102]=-1
|
|
[[ ${aSOFTWARE_INSTALL_STATE[103]} == [01] ]] && aSOFTWARE_INSTALL_STATE[103]=1 || aSOFTWARE_INSTALL_STATE[103]=2
|
|
fi
|
|
INDEX_LOGGING=$1
|
|
|
|
# If DietPi-RAMlog is and stays installed, apply logging index now to make the change permanent for DietPi-LogClear even if no actual install is required.
|
|
[[ $INDEX_LOGGING == -[12] && ${aSOFTWARE_INSTALL_STATE[103]} == 2 ]] && G_CONFIG_INJECT 'INDEX_LOGGING=' "INDEX_LOGGING=$INDEX_LOGGING" /boot/dietpi/.installed
|
|
}
|
|
|
|
Install_Apply_GPU_Settings()
|
|
{
|
|
# Offer to install GPU driver when Xserver installed (x86_64 support currently only)
|
|
if (( $G_HW_ARCH == 10 && $G_HW_MODEL == 21 && ${aSOFTWARE_INSTALL_STATE[6]} == 1 ))
|
|
then
|
|
local gpu_current=$(sed -n '/^[[:blank:]]*CONFIG_GPU_DRIVER=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ ${gpu_current,,} == 'none' ]] && G_WHIP_YESNO 'No GPU Driver is currently installed.\n\nWould you like to select a GPU driver for installation now?' && /boot/dietpi/dietpi-config 2
|
|
fi
|
|
|
|
# RPi: Disable headless mode and raise memory split to default for GUI applications
|
|
(( $G_HW_MODEL < 10 )) || return 0
|
|
|
|
# Kodi, Jellyfin, DXX-Rebirth, RPi Cam Web Interface, Amiberry, Chromium, Desktops, OpenTyrian, Moonlight (CLI), Moonlight (GUI), GZDoom
|
|
(( ${aSOFTWARE_INSTALL_STATE[31]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[178]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[112]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[59]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[108]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[113]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[23]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[24]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[25]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[26]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[51]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[173]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[207]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[208]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[11]} == 1 )) || return 0
|
|
|
|
# Disable headless mode
|
|
/boot/dietpi/func/dietpi-set_hardware headless 0
|
|
|
|
# Raise memory split to default
|
|
local default_gpu_mem=76
|
|
(( $G_HW_MEMORY_SIZE < 1024 )) && default_gpu_mem=64
|
|
local current_gpu_mem=$(sed -n '/^[[:blank:]]*gpu_mem_1024=/{s/^[^=]*=//p;q}' /boot/config.txt)
|
|
[[ $current_gpu_mem ]] || current_gpu_mem=$default_gpu_mem
|
|
(( $current_gpu_mem < $default_gpu_mem )) && /boot/dietpi/func/dietpi-set_hardware gpumemsplit "$default_gpu_mem"
|
|
}
|
|
|
|
Uninstall_Software()
|
|
{
|
|
# $1: Service name
|
|
# $2: Remove user named $2 or $1 if $2 == 1 (optional)
|
|
# $3: Remove group named $3 or $1 if $3 == 1 (optional)
|
|
Remove_Service()
|
|
{
|
|
local unmasked disabled
|
|
if [[ -f '/etc/systemd/system/'$1'.service' ]]
|
|
then
|
|
G_EXEC systemctl --no-reload disable --now "$1" && disabled=1
|
|
G_EXEC rm "/etc/systemd/system/$1.service" && unmasked=1
|
|
|
|
elif [[ -f '/lib/systemd/system/'$1'.service' ]]
|
|
then
|
|
G_EXEC systemctl --no-reload unmask "$1" && unmasked=1
|
|
G_EXEC systemctl --no-reload disable --now "$1" && disabled=1
|
|
fi
|
|
if [[ -f '/etc/init.d/'$1 ]]
|
|
then
|
|
[[ $unmasked ]] || G_EXEC systemctl --no-reload unmask "$1"
|
|
[[ $disabled ]] || G_EXEC systemctl --no-reload disable "$1"
|
|
[[ $disabled ]] || G_EXEC systemctl stop "$1" # --now does not work with generated wrapper units
|
|
G_EXEC rm "/etc/init.d/$1"
|
|
G_EXEC update-rc.d "$1" remove
|
|
fi
|
|
[[ -d '/etc/systemd/system/'$1'.service.d' ]] && G_EXEC rm -R "/etc/systemd/system/$1.service.d"
|
|
[[ $2 ]] && getent passwd "${2/#1/$1}" > /dev/null && G_EXEC userdel "${2/#1/$1}"
|
|
[[ $3 ]] && getent group "${3/#1/$1}" > /dev/null && G_EXEC groupdel "${3/#1/$1}"
|
|
}
|
|
|
|
# $1: Database and username
|
|
Remove_Database()
|
|
{
|
|
systemctl start mariadb || return 1
|
|
mysqladmin -f drop "$1"
|
|
mysql -e "drop user $1@localhost;"
|
|
}
|
|
|
|
# NB: "systemctl daemon-reload" is executed at the end of this function
|
|
G_NOTIFY_3_MODE='Step'
|
|
local software_id
|
|
|
|
To_Uninstall()
|
|
{
|
|
(( ${aSOFTWARE_INSTALL_STATE[$1]} == -1 )) || return 1
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "Uninstalling ${aSOFTWARE_NAME[$1]}: ${aSOFTWARE_DESC[$1]}"
|
|
software_id=$1
|
|
}
|
|
|
|
if To_Uninstall 23 # LXDE
|
|
then
|
|
apt-mark auto lxhotkey-plugin-openbox upower librsvg2-common 2> /dev/null
|
|
G_AGP lxde 'lxde-*'
|
|
G_EXEC rm -Rf /{root,home/*}/.{config,cache}/{lxpanel,lxsession,lxterminal,openbox,pcmanfm,dconf}
|
|
fi
|
|
|
|
if To_Uninstall 173 # LXQt
|
|
then
|
|
apt-mark auto qterminal xarchiver lxde-icon-theme upower xscreensaver leafpad featherpad speedcrunch 2> /dev/null
|
|
G_AGP lxqt
|
|
G_EXEC rm -Rf /{root,home/*}/.config/lxqt
|
|
fi
|
|
|
|
if To_Uninstall 174 # GIMP
|
|
then
|
|
G_AGP gimp
|
|
fi
|
|
|
|
if To_Uninstall 175 # Xfce Power Manager
|
|
then
|
|
G_AGP xfce4-power-manager
|
|
fi
|
|
|
|
if To_Uninstall 24 # MATE
|
|
then
|
|
apt-mark auto upower policykit-1 2> /dev/null
|
|
G_AGP mate-desktop-environment-core mate-media
|
|
fi
|
|
|
|
if To_Uninstall 26 # GNUstep
|
|
then
|
|
G_AGP wmaker gnustep gnustep-devel gnustep-games
|
|
G_EXEC rm -Rf /{root,home/*}/GNUstep
|
|
fi
|
|
|
|
if To_Uninstall 25 # Xfce
|
|
then
|
|
apt-mark auto gnome-icon-theme tango-icon-theme upower policykit-1 polkitd 2> /dev/null
|
|
G_AGP xfce4 xfce4-terminal
|
|
fi
|
|
|
|
if To_Uninstall 22 # QuiteRSS
|
|
then
|
|
G_AGP quiterss
|
|
fi
|
|
|
|
if To_Uninstall 30 # NoMachine
|
|
then
|
|
G_AGP nomachine
|
|
G_EXEC rm -Rf /{root,home/*}/NoMachine
|
|
fi
|
|
|
|
if To_Uninstall 29 # XRDP
|
|
then
|
|
G_AGP xrdp xorgxrdp
|
|
fi
|
|
|
|
if To_Uninstall 44 # Transmission
|
|
then
|
|
Remove_Service transmission-daemon debian-transmission debian-transmission
|
|
G_AGP transmission-daemon
|
|
fi
|
|
|
|
if To_Uninstall 47 # ownCloud
|
|
then
|
|
# Remove background cron job
|
|
crontab -u www-data -l | grep -v '/var/www/owncloud/.*cron' | crontab -u www-data -
|
|
# Disable and remove PHP modules
|
|
command -v phpdismod > /dev/null && G_EXEC phpdismod dietpi-owncloud
|
|
G_EXEC rm -f /etc/php/*/mods-available/dietpi-owncloud.ini
|
|
# Disable and remove webserver configs
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-owncloud
|
|
[[ -f '/etc/apache2/sites-available/dietpi-owncloud.conf' ]] && G_EXEC rm /etc/apache2/sites-available/dietpi-owncloud.conf
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-owncloud.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-owncloud.conf
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-owncloud
|
|
[[ -f '/etc/lighttpd/conf-available/99-dietpi-owncloud.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-owncloud.conf
|
|
G_WHIP_MSG "DietPi will perform an automated backup of your ownCloud database and installation directory, which will be stored inside your ownCloud data directory.\n\nThe data directory won't be removed. So you can recover your whole ownCloud instance any time later.\n\nRemove the data directory manually if you don't need it anymore."
|
|
# Find datadir for backups
|
|
local datadir=$(grep -m1 "^[[:blank:]]*'datadirectory'" /var/www/owncloud/config/config.php | mawk '{print $3}' | sed "s/[',]//g")
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/owncloud_data'
|
|
# Drop MariaDB users and database
|
|
if systemctl start mariadb
|
|
then
|
|
local dbuser=$(grep -m1 "^[[:blank:]]*'dbuser'" /var/www/owncloud/config/config.php | mawk '{print $3}' | sed 's/,//')
|
|
local dbhost=$(grep -m1 "^[[:blank:]]*'dbhost'" /var/www/owncloud/config/config.php | mawk '{print $3}' | sed 's/,//')
|
|
mysql -e "drop user $dbuser@$dbhost;"
|
|
mysql -e "drop user $dbuser;" 2> /dev/null
|
|
# Perform database backup if existent, otherwise skip to not overwrite existing one
|
|
[[ -d '/mnt/dietpi_userdata/mysql/owncloud' ]] && mysqldump owncloud > "$datadir/dietpi-owncloud-database-backup.sql"
|
|
mysqladmin drop owncloud -f
|
|
fi
|
|
if [[ -d '/var/www/owncloud' ]]
|
|
then
|
|
# Backup ownCloud installation dir
|
|
G_EXEC cp -a /var/www/owncloud/. "$datadir/dietpi-owncloud-installation-backup/"
|
|
# Remove ownCloud installation dir
|
|
G_EXEC rm -R /var/www/owncloud
|
|
fi
|
|
# Remove redirect configs
|
|
if grep -q 'owncloud' /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf 2> /dev/null
|
|
then
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-dav_redirect
|
|
G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
fi
|
|
if grep -q 'owncloud' /etc/apache2/conf-available/dietpi-dav_redirect.conf 2> /dev/null
|
|
then
|
|
command -v a2disconf > /dev/null && a2disconf dietpi-dav_redirect
|
|
G_EXEC rm /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
fi
|
|
grep -q 'owncloud' /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf 2> /dev/null && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
fi
|
|
|
|
if To_Uninstall 168 # Nextcloud Talk + Coturn server
|
|
then
|
|
Remove_Service coturn
|
|
G_AGP coturn
|
|
[[ -f '/etc/turnserver.conf' ]] && G_EXEC rm /etc/turnserver.conf
|
|
systemctl start redis-server
|
|
if systemctl start mariadb
|
|
then
|
|
runuser -u www-data -- php /var/www/nextcloud/occ maintenance:mode --off
|
|
runuser -u www-data -- php /var/www/nextcloud/occ app:disable spreed
|
|
fi
|
|
G_DIETPI-NOTIFY 2 'Disabled Nextcloud Talk app, but you need to remove it manually from Nextcloud web UI if desired.'
|
|
fi
|
|
|
|
if To_Uninstall 114 # Nextcloud
|
|
then
|
|
crontab -u www-data -l | grep -v '/var/www/nextcloud/cron.php' | crontab -u www-data -
|
|
# Disable and remove PHP modules
|
|
command -v phpdismod > /dev/null && G_EXEC phpdismod dietpi-nextcloud
|
|
G_EXEC rm -f /etc/php/*/mods-available/dietpi-nextcloud.ini
|
|
# Disable and remove webserver configs
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-nextcloud
|
|
[[ -f '/etc/apache2/sites-available/dietpi-nextcloud.conf' ]] && G_EXEC rm /etc/apache2/sites-available/dietpi-nextcloud.conf
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-nextcloud.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-nextcloud.conf
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-nextcloud
|
|
[[ -f '/etc/lighttpd/conf-available/99-dietpi-nextcloud.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-nextcloud.conf
|
|
G_WHIP_MSG "DietPi will perform an automated backup of your Nextcloud database and installation directory, which will be stored inside your Nextcloud data directory.\n\nThe data directory won't be removed. So you can recover your whole Nextcloud instance any time later.\n\nRemove the data directory manually if you don't need it anymore."
|
|
# Find datadir for backups
|
|
local datadir=$(grep -m1 "^[[:blank:]]*'datadirectory'" /var/www/nextcloud/config/config.php | mawk '{print $3}' | sed "s/[',]//g")
|
|
[[ $datadir ]] || datadir='/mnt/dietpi_userdata/nextcloud_data'
|
|
# Drop MariaDB users and database
|
|
if systemctl start mariadb
|
|
then
|
|
local dbuser=$(grep -m1 "^[[:blank:]]*'dbuser'" /var/www/nextcloud/config/config.php | mawk '{print $3}' | sed 's/,//')
|
|
local dbhost=$(grep -m1 "^[[:blank:]]*'dbhost'" /var/www/nextcloud/config/config.php | mawk '{print $3}' | sed 's/,//')
|
|
mysql -e "drop user $dbuser@$dbhost;"
|
|
mysql -e "drop user $dbuser;" 2> /dev/null
|
|
# Perform database backup if existent, otherwise skip to not overwrite existing one
|
|
[[ -d '/mnt/dietpi_userdata/mysql/nextcloud' ]] && mysqldump nextcloud > "$datadir/dietpi-nextcloud-database-backup.sql"
|
|
mysqladmin drop nextcloud -f
|
|
fi
|
|
if [[ -d '/var/www/nextcloud' ]]
|
|
then
|
|
# Backup Nextcloud installation dir
|
|
G_EXEC cp -a /var/www/nextcloud/. "$datadir/dietpi-nextcloud-installation-backup/"
|
|
# Remove Nextcloud installation dir
|
|
G_EXEC rm -R /var/www/nextcloud
|
|
fi
|
|
# Remove redirect configs
|
|
if grep -q 'nextcloud' /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf 2> /dev/null
|
|
then
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-dav_redirect
|
|
G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
fi
|
|
if grep -q 'nextcloud' /etc/apache2/conf-available/dietpi-dav_redirect.conf 2> /dev/null
|
|
then
|
|
command -v a2disconf > /dev/null && a2disconf dietpi-dav_redirect
|
|
G_EXEC rm /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
fi
|
|
grep -q 'nextcloud' /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf 2> /dev/null && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
fi
|
|
|
|
if To_Uninstall 63 # LinuxDash
|
|
then
|
|
[[ -d '/var/www/linuxdash' ]] && G_EXEC rm -R /var/www/linuxdash
|
|
fi
|
|
|
|
if To_Uninstall 27 # TasmoAdmin
|
|
then
|
|
[[ -d '/var/www/tasmoadmin' ]] && G_EXEC rm -R /var/www/tasmoadmin
|
|
|
|
# Remove webserver configs
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-tasmoadmin
|
|
[[ -f '/etc/apache2/conf-available/dietpi-tasmoadmin.conf' ]] && G_EXEC rm /etc/apache2/conf-available/dietpi-tasmoadmin.conf
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-tasmoadmin.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-tasmoadmin.conf
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-tasmoadmin
|
|
[[ -f '/etc/lighttpd/conf-available/99-dietpi-tasmoadmin.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-tasmoadmin.conf
|
|
fi
|
|
|
|
if To_Uninstall 206 # openHAB
|
|
then
|
|
G_AGP openhab
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-openhab.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-openhab.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-openhab.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-openhab.gpg
|
|
[[ -f '/etc/apt/preferences.d/dietpi-openhab' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-openhab
|
|
fi
|
|
|
|
if To_Uninstall 83 # Apache
|
|
then
|
|
Remove_Service apache2
|
|
G_AGP apache2 libapache2-mod-php*
|
|
G_EXEC rm -Rf /{etc,var/{lib,log}}/apache2 /{etc/php,var/lib/php/modules}/*/apache2
|
|
fi
|
|
|
|
if To_Uninstall 85 # Nginx
|
|
then
|
|
Remove_Service nginx
|
|
G_AGP nginx 'nginx-*'
|
|
fi
|
|
|
|
if To_Uninstall 84 # Lighttpd
|
|
then
|
|
Remove_Service lighttpd
|
|
G_AGP lighttpd
|
|
|
|
# Config
|
|
[[ -d '/etc/lighttpd' ]] && G_EXEC rm -R /etc/lighttpd
|
|
[[ -d '/var/www/index.lighttpd.html' ]] && G_EXEC rm /var/www/index.lighttpd.html
|
|
|
|
# Certbot hook
|
|
[[ -f '/etc/letsencrypt/renewal-hooks/deploy/dietpi-lighttpd.sh' ]] && G_EXEC rm /etc/letsencrypt/renewal-hooks/deploy/dietpi-lighttpd.sh
|
|
# - Pre-v8.0
|
|
[[ -f 'etc/systemd/system/certbot.service.d/dietpi-lighttpd.conf' ]] && G_EXEC rm /etc/systemd/system/certbot.service.d/dietpi-lighttpd.conf
|
|
[[ -d '/etc/systemd/system/certbot.service.d' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /etc/systemd/system/certbot.service.d
|
|
fi
|
|
|
|
if To_Uninstall 91 # Redis
|
|
then
|
|
Remove_Service redis-server
|
|
G_AGP redis-server redis-tools 'php*-redis'
|
|
G_EXEC rm -f /etc/sysctl.d/98-dietpi-redis.conf
|
|
fi
|
|
|
|
if To_Uninstall 34 # PHP Composer
|
|
then
|
|
[[ -f '/usr/local/bin/composer' ]] && G_EXEC rm /usr/local/bin/composer
|
|
fi
|
|
|
|
if To_Uninstall 89 # PHP
|
|
then
|
|
Remove_Service "php$PHP_VERSION-fpm"
|
|
G_AGP 'php*-*' 'libapache2-mod-php*'
|
|
G_EXEC rm -Rf /{etc,var/lib}/php /var/log/php*-fpm.log
|
|
[[ -f '/etc/tmpfiles.d/dietpi-php_sessions.conf' ]] && G_EXEC rm /etc/tmpfiles.d/dietpi-php_sessions.conf
|
|
[[ -d '/var/tmp/php_upload_tmp' ]] && G_EXEC rm -R /var/tmp/php_upload_tmp # Pre-v6.32
|
|
fi
|
|
|
|
if To_Uninstall 90 # phpMyAdmin
|
|
then
|
|
G_EXEC rm -Rf /var/www/phpmyadmin
|
|
if [[ -f '/etc/apache2/sites-available/dietpi-phpmyadmin.conf' ]]
|
|
then
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-phpmyadmin
|
|
G_EXEC rm /etc/apache2/sites-available/dietpi-phpmyadmin.conf
|
|
fi
|
|
if [[ -f '/etc/lighttpd/conf-available/98-dietpi-phpmyadmin.conf' ]]
|
|
then
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-phpmyadmin
|
|
G_EXEC rm /etc/lighttpd/conf-available/98-dietpi-phpmyadmin.conf
|
|
fi
|
|
[[ -f '/etc/apache2/sites-dietpi/dietpi-phpmyadmin.conf' ]] && G_EXEC rm /etc/apache2/sites-dietpi/dietpi-phpmyadmin.conf
|
|
Remove_Database phpmyadmin
|
|
fi
|
|
|
|
if To_Uninstall 184 # Tor Relay
|
|
then
|
|
Remove_Service tor
|
|
G_AGP tor obfs4proxy
|
|
fi
|
|
|
|
if To_Uninstall 54 # phpBB
|
|
then
|
|
[[ -d '/var/www/phpbb' ]] && G_EXEC rm -R /var/www/phpbb
|
|
[[ -d '/var/www/phpBB3' ]] && G_EXEC rm -R /var/www/phpBB3 # Pre-v6.33
|
|
Remove_Database phpbb
|
|
Remove_Database phpbb3 # Pre-v6.33
|
|
fi
|
|
|
|
if To_Uninstall 115 # Webmin
|
|
then
|
|
Remove_Service webmin
|
|
G_AGP webmin
|
|
G_EXEC rm -f /etc/apt/sources.list.d/dietpi-webmin.list /etc/apt/trusted.gpg.d/dietpi-webmin.asc
|
|
fi
|
|
|
|
if To_Uninstall 32 # ympd
|
|
then
|
|
G_AGP ympd
|
|
fi
|
|
|
|
if To_Uninstall 148 # myMPD
|
|
then
|
|
Remove_Service mympd 1 1 # user and group for pre-v8.12
|
|
if [[ -f '/usr/local/share/ca-certificates/DietPi_myMPD_CA.crt' || -L '/usr/local/share/ca-certificates/DietPi_myMPD_CA.crt' ]]
|
|
then
|
|
G_EXEC rm /usr/local/share/ca-certificates/DietPi_myMPD_CA.crt
|
|
G_EXEC update-ca-certificates -f
|
|
fi
|
|
G_AGP mympd
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-mympd.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-mympd.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-mympd.asc' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-mympd.asc
|
|
[[ -d '/var/lib/mympd' ]] && G_EXEC rm -R /var/lib/mympd
|
|
[[ -d '/var/lib/private/mympd' ]] && G_EXEC rm -R /var/lib/private/mympd
|
|
[[ -d '/var/cache/mympd' ]] && G_EXEC rm -R /var/cache/mympd
|
|
[[ -d '/var/cache/private/mympd' ]] && G_EXEC rm -R /var/cache/private/mympd
|
|
# pre-v8.0
|
|
[[ -f '/lib/systemd/system/mympd.service' ]] && G_EXEC rm /lib/systemd/system/mympd.service
|
|
command -v mympd > /dev/null && G_EXEC rm "$(command -v mympd)"
|
|
command -v mympd-config > /dev/null && G_EXEC rm "$(command -v mympd-config)" # myMPD pre-v8.0.0
|
|
command -v mympd-script > /dev/null && G_EXEC rm "$(command -v mympd-script)"
|
|
[[ -d '/usr/share/doc/mympd' ]] && G_EXEC rm -R /usr/share/doc/mympd
|
|
G_EXEC rm -f /usr/share/man/man1/mympd* /etc/mympd.conf* # /etc: myMPD pre-v8.0.0
|
|
fi
|
|
|
|
if To_Uninstall 128 # MPD
|
|
then
|
|
Remove_Service mpd 1 1 # group for pre-v6.29
|
|
G_AGP mpd
|
|
[[ -d '/var/log/mpd' ]] && G_EXEC rm -R /var/log/mpd
|
|
[[ -d '/mnt/dietpi_userdata/.mpd_cache' ]] && G_EXEC rm -R /mnt/dietpi_userdata/.mpd_cache
|
|
[[ -f '/etc/mpd.conf' ]] && G_EXEC rm /etc/mpd.conf
|
|
[[ -f '/usr/local/etc/mpd.conf' ]] && G_EXEC rm /usr/local/etc/mpd.conf && G_EXEC rmdir --ignore-fail-on-non-empty /usr/local/etc # pre-v6.29
|
|
[[ -f '/etc/default/mpd' ]] && G_EXEC rm /etc/default/mpd # pre-v6.20
|
|
fi
|
|
|
|
if To_Uninstall 122 # Node-RED
|
|
then
|
|
Remove_Service node-red nodered nodered
|
|
|
|
# Configs
|
|
[[ -f '/etc/sudoers.d/nodered' ]] && G_EXEC rm /etc/sudoers.d/nodered
|
|
[[ -f '/etc/bashrc.d/dietpi-node-red.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-node-red.sh
|
|
|
|
# Data
|
|
[[ -d '/mnt/dietpi_userdata/node-red' ]] && G_EXEC rm -R /mnt/dietpi_userdata/node-red
|
|
G_EXEC rm -Rf /{root,home/*}/.node-red # Pre-v6.25
|
|
|
|
# Pre-v7.0
|
|
command -v npm > /dev/null && npm r -g node-red
|
|
[[ -f '/usr/local/bin/node-red' ]] && G_EXEC rm /usr/local/bin/node-red
|
|
[[ -f '/usr/local/bin/node-red-pi' ]] && G_EXEC rm /usr/local/bin/node-red-pi
|
|
fi
|
|
|
|
if To_Uninstall 195 # youtube-dl
|
|
then
|
|
G_EXEC rm -f /usr/local/bin/{yt-dlp,youtube-dl,youtube-dl-py2}
|
|
fi
|
|
|
|
if To_Uninstall 123 # Mosquitto
|
|
then
|
|
Remove_Service mosquitto
|
|
G_AGP mosquitto
|
|
|
|
[[ -d '/etc/mosquitto' ]] && G_EXEC rm -R /etc/mosquitto
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-mosquitto.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-mosquitto.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-mosquitto.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-mosquitto.gpg
|
|
fi
|
|
|
|
if To_Uninstall 124 # NAA Daemon
|
|
then
|
|
G_AGP networkaudiod
|
|
fi
|
|
|
|
if To_Uninstall 129 # O!MPD
|
|
then
|
|
[[ -d '/var/www/ompd' ]] && G_EXEC rm -R /var/www/ompd
|
|
[[ -f '/etc/lighttpd/conf-enabled/99-dietpi-ompd.conf' ]] && G_EXEC lighty-disable-mod dietpi-ompd
|
|
[[ -f '/etc/lighttpd/conf-available/99-dietpi-ompd.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-ompd.conf
|
|
|
|
Remove_Database ompd
|
|
fi
|
|
|
|
if To_Uninstall 131 # Blynk Server
|
|
then
|
|
Remove_Service blynkserver blynk blynk
|
|
[[ -d '/mnt/dietpi_userdata/blynk' ]] && G_EXEC rm -R /mnt/dietpi_userdata/blynk
|
|
[[ -d '/var/log/blynk' ]] && G_EXEC rm -R /var/log/blynk
|
|
command -v npm > /dev/null && npm r -g blynk-library
|
|
[[ -f '/usr/local/bin/blynk-ctrl' ]] && G_EXEC rm /usr/local/bin/blynk-ctrl
|
|
[[ -f '/usr/local/bin/blynk-client' ]] && G_EXEC rm /usr/local/bin/blynk-client
|
|
[[ -d '/etc/blynkserver' ]] && G_EXEC rm -R /etc/blynkserver # Pre-v6.19
|
|
fi
|
|
|
|
if To_Uninstall 125 # Synapse
|
|
then
|
|
Remove_Service synapse 1 1
|
|
[[ -d '/mnt/dietpi_userdata/synapse' ]] && G_EXEC rm -R /mnt/dietpi_userdata/synapse
|
|
|
|
command -v pip3 > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pip3 uninstall -y matrix-synapse
|
|
command -v dropdb > /dev/null && runuser -u postgres -- dropdb synapse
|
|
command -v dropuser > /dev/null && runuser -u postgres -- dropuser synapse
|
|
fi
|
|
|
|
if To_Uninstall 132 # Aria2
|
|
then
|
|
[[ -d '/var/www/aria2' ]] && G_EXEC rm -R /var/www/aria2
|
|
Remove_Service aria2 1
|
|
G_AGP aria2
|
|
# Remove input file
|
|
if [[ -f '/mnt/dietpi_userdata/aria2/aria2.conf' ]]
|
|
then
|
|
local fp_input=$(sed -n '/^[[:blank:]]*input-file=/{s/^[^=]*=//p;q}' /mnt/dietpi_userdata/aria2/aria2.conf)
|
|
[[ ${fp_input//\"} ]] && G_EXEC rm -f "$fp_input"
|
|
unset -v fp_input
|
|
fi
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/aria2
|
|
[[ -f '/mnt/dietpi_userdata/downloads/aria2.session' ]] && G_EXEC rm /mnt/dietpi_userdata/downloads/aria2.session
|
|
fi
|
|
|
|
if To_Uninstall 133 # YaCy
|
|
then
|
|
Remove_Service yacy
|
|
[[ -d '/etc/yacy' ]] && G_EXEC rm -R /etc/yacy
|
|
fi
|
|
|
|
if To_Uninstall 141 # ADS-B Feeder
|
|
then
|
|
G_EXEC_NOHALT=1 G_EXEC_OUTPUT=1 G_EXEC /opt/adsb/docker-compose-adsb down
|
|
Remove_Service adsb-docker
|
|
Remove_Service adsb-feeder-update
|
|
Remove_Service adsb-setup
|
|
[[ -f '/opt/adsb/pre-uninstall-cleanup' ]] && G_EXEC /opt/adsb/pre-uninstall-cleanup
|
|
G_EXEC rm -Rf /opt/adsb /mnt/dietpi_userdata/adsb-feeder /opt/adsb-feeder-update
|
|
fi
|
|
|
|
if To_Uninstall 2 # Folding@Home
|
|
then
|
|
# Un-check out all work units, so they can be picked up by other donors prior to timeout: https://github.com/FoldingAtHome/fah-issues/issues/1255
|
|
FAHClient --chdir /mnt/dietpi_userdata/fahclient --dump all
|
|
|
|
Remove_Service fahclient
|
|
G_AGP fahclient
|
|
[[ -d '/mnt/dietpi_userdata/fahclient' ]] && G_EXEC rm -R /mnt/dietpi_userdata/fahclient
|
|
fi
|
|
|
|
if To_Uninstall 135
|
|
then
|
|
Remove_Service darkice
|
|
G_AGP darkice icecast2
|
|
fi
|
|
|
|
if To_Uninstall 136 # motionEye
|
|
then
|
|
Remove_Service motioneye
|
|
command -v pip3 > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pip3 uninstall -y motioneye
|
|
G_AGP motion
|
|
[[ -d '/etc/motioneye' ]] && G_EXEC rm -R /etc/motioneye
|
|
[[ -d '/var/log/motioneye' ]] && G_EXEC rm -R /var/log/motioneye
|
|
[[ -d '/var/lib/motioneye' ]] && G_EXEC rm -R /var/lib/motioneye
|
|
[[ -d '/mnt/dietpi_userdata/motioneye' ]] && G_DIETPI-NOTIFY 2 'The motionEye media directory is left in place. You can manually remove it via:\n rm -R /mnt/dietpi_userdata/motioneye'
|
|
fi
|
|
|
|
if To_Uninstall 137 # mjpg-streamer
|
|
then
|
|
Remove_Service mjpg-streamer 1
|
|
[[ -d '/opt/mjpg-streamer' ]] && G_EXEC rm -R /opt/mjpg-streamer
|
|
fi
|
|
|
|
if To_Uninstall 127 # BirdNET-Go
|
|
then
|
|
Remove_Service birdnet 1 1
|
|
G_AGP sox
|
|
G_EXEC rm -Rf /opt/birdnet
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/birdnet
|
|
fi
|
|
|
|
if To_Uninstall 138 # VirtualHere
|
|
then
|
|
Remove_Service virtualhere
|
|
[[ -d '/opt/virtualhere' ]] && G_EXEC rm -R /opt/virtualhere
|
|
[[ -d '/etc/vhusbd' ]] && G_EXEC rm -R /etc/vhusbd # Pre-v8.4
|
|
[[ -f '/var/log/virtualhere.log' ]] && G_EXEC rm /var/log/virtualhere.log # Pre-v8.4
|
|
fi
|
|
|
|
if To_Uninstall 139 # SABnzbd
|
|
then
|
|
Remove_Service sabnzbd 1 1 # group for pre-v6.33
|
|
[[ -d '/etc/sabnzbd' ]] && G_EXEC rm -R /etc/sabnzbd
|
|
[[ -d '/mnt/dietpi_userdata/downloads/sabnzbd_admin' ]] && G_EXEC rm -R /mnt/dietpi_userdata/downloads/sabnzbd_admin
|
|
[[ -d '/mnt/dietpi_userdata/downloads/sabnzbd_nzb_backup' ]] && G_EXEC rm -R /mnt/dietpi_userdata/downloads/sabnzbd_nzb_backup
|
|
[[ -d '/var/log/sabnzbd' ]] && G_EXEC rm -R /var/log/sabnzbd # Pre-v7.9
|
|
fi
|
|
|
|
if To_Uninstall 183 # vaultwarden
|
|
then
|
|
Remove_Service vaultwarden 1 1 # Pre-v8.7
|
|
G_AGP vaultwarden
|
|
[[ -d '/mnt/dietpi_userdata/vaultwarden' ]] && G_EXEC rm -R /mnt/dietpi_userdata/vaultwarden
|
|
[[ -d '/opt/vaultwarden' ]] && G_EXEC rm -R /opt/vaultwarden # Pre-v8.7
|
|
fi
|
|
|
|
if To_Uninstall 193 # K3s
|
|
then
|
|
[[ -f '/usr/local/bin/k3s-uninstall.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC_NOEXIT=1 G_EXEC /usr/local/bin/k3s-uninstall.sh
|
|
[[ -f '/usr/local/bin/k3s-agent-uninstall.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC_NOEXIT=1 G_EXEC /usr/local/bin/k3s-agent-uninstall.sh
|
|
[[ -d '/etc/systemd/system/k3s.service.d' ]] && G_EXEC rm -R /etc/systemd/system/k3s.service.d
|
|
[[ -d '/etc/rancher' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /etc/rancher
|
|
[[ -d '/var/lib/rancher' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/lib/rancher
|
|
fi
|
|
|
|
if To_Uninstall 142 # MicroK8s
|
|
then
|
|
command -v snap > /dev/null && G_EXEC_OUTPUT=1 G_EXEC snap remove microk8s
|
|
fi
|
|
|
|
if To_Uninstall 182 # Unbound
|
|
then
|
|
# Pi-hole: Assure that it does not resolve via Unbound anymore
|
|
# - v6
|
|
if [[ $(pihole-FTL -v) == 'v6'* ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Removing Unbound from Pi-hole upstream DNS servers, and in case add Quad9 as new one.'
|
|
local upstreams=() i
|
|
read -ra upstreams < <(pihole-FTL --config dns.upstreams)
|
|
# Remove array brackets
|
|
unset -v 'upstreams[0]' 'upstreams[${#upstreams[@]}]'
|
|
for i in "${!upstreams[@]}"
|
|
do
|
|
# Remove loopback IP (Unbound)
|
|
[[ ${upstreams[i]} == '127.0.0.1'* ]] && { unset -v 'upstreams[i]'; break; }
|
|
# Remove trailing comma and readd double-quotes removed from pihole-FTL output
|
|
upstreams[i]="\"${upstreams[i]%,}\""
|
|
done
|
|
# Add Quad9 if no upstream DNS server is left
|
|
(( ${#upstreams[@]} )) || upstreams=('"9.9.9.9"')
|
|
upstreams[0]=${upstreams[*]}
|
|
G_EXEC pihole-FTL --config dns.upstreams "[ ${upstreams[0]// /,} ]"
|
|
fi
|
|
# - v5
|
|
if [[ -f '/etc/dnsmasq.d/01-pihole.conf' ]] && grep -q '^[[:blank:]]*server=127.0.0.1' /etc/dnsmasq.d/01-pihole.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'The Pi-hole upstream DNS server has been changed to Quad9 due to Unbound being uninstalled.'
|
|
G_CONFIG_INJECT 'server=127.0.0.1' 'server=9.9.9.9' /etc/dnsmasq.d/01-pihole.conf
|
|
systemctl -q is-active pihole-FTL && G_EXEC_NOEXIT=1 G_EXEC systemctl restart pihole-FTL
|
|
fi
|
|
[[ -f '/etc/pihole/setupVars.conf' ]] && grep -q '^[[:blank:]]*PIHOLE_DNS_1=127.0.0.1' /etc/pihole/setupVars.conf && G_CONFIG_INJECT 'PIHOLE_DNS_1=' 'PIHOLE_DNS_1=9.9.9.9' /etc/pihole/setupVars.conf
|
|
|
|
# AdGuard Home: Assure that it does not resolve via Unbound anymore
|
|
if [[ -f '/mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'AdGuard Home upstream DNS server has been changed back to default settings due to Unbound being uninstalled.'
|
|
G_CONFIG_INJECT 'upstream_dns_file:[[:blank:]]' ' upstream_dns_file: ""' /mnt/dietpi_userdata/adguardhome/AdGuardHome.yaml
|
|
[[ -f '/mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf' ]] && G_EXEC rm /mnt/dietpi_userdata/adguardhome/dietpi-unbound.conf
|
|
systemctl -q is-active adguardhome && G_EXEC_NOEXIT=1 G_EXEC systemctl restart adguardhome
|
|
fi
|
|
|
|
# Failsafe: Add Quad9 to system resolver if only Unbound was used
|
|
if [[ -f '/etc/unbound/unbound.conf.d/dietpi.conf' ]] && grep -Eq '^[[:blank:]]*port:[[:blank:]]+53$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
fi
|
|
|
|
G_AGP unbound
|
|
dpkg-query -s 'dns-root-data' &> /dev/null && G_EXEC apt-mark auto dns-root-data
|
|
[[ -d '/etc/unbound' ]] && G_EXEC rm -R /etc/unbound
|
|
[[ -d '/var/cache/unbound' ]] && G_EXEC rm -R /var/cache/unbound
|
|
fi
|
|
|
|
if To_Uninstall 143 # Koel
|
|
then
|
|
Remove_Service koel 1 1 # group for pre-v6.33
|
|
[[ -d '/mnt/dietpi_userdata/koel' ]] && G_EXEC rm -R /mnt/dietpi_userdata/koel
|
|
Remove_Database koel
|
|
fi
|
|
|
|
if To_Uninstall 144 # Sonarr
|
|
then
|
|
Remove_Service sonarr 1 1 # group for pre-v6.29
|
|
G_AGP sonarr nzbdrone # Pre-v7.1
|
|
[[ -d '/var/log/sonarr' ]] && G_EXEC rm -R /var/log/sonarr
|
|
G_EXEC rm -Rf /opt/sonarr /mnt/dietpi_userdata/sonarr /opt/NzbDrone # Pre-v7.1
|
|
[[ -f '/etc/apt/sources.list.d/sonarr.list' ]] && G_EXEC rm /etc/apt/sources.list.d/sonarr.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-sonarr.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-sonarr.gpg
|
|
# Pre-v7.1: Remove Sonarr v2 key
|
|
if [[ -f '/etc/apt/trusted.gpg' && $(apt-key --keyring /etc/apt/trusted.gpg list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]]
|
|
then
|
|
G_EXEC apt-key --keyring /etc/apt/trusted.gpg del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493'
|
|
[[ $(apt-key --keyring /etc/apt/trusted.gpg list 2> /dev/null) ]] || G_EXEC rm /etc/apt/trusted.gpg
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 145 # Radarr
|
|
then
|
|
Remove_Service radarr 1 1 # group for pre-v6.29
|
|
G_EXEC rm -Rf /opt/radarr /mnt/dietpi_userdata/radarr /var/log/radarr
|
|
fi
|
|
|
|
if To_Uninstall 106 # Lidarr
|
|
then
|
|
Remove_Service lidarr 1 1 # group for pre-v6.29
|
|
G_EXEC rm -Rf /opt/{L,l}idarr /mnt/dietpi_userdata/lidarr /var/log/lidarr
|
|
fi
|
|
|
|
if To_Uninstall 180 # Bazarr
|
|
then
|
|
Remove_Service bazarr 1
|
|
G_EXEC rm -Rf /opt/bazarr /mnt/dietpi_userdata/bazarr /var/log/bazarr
|
|
fi
|
|
|
|
if To_Uninstall 200 # DietPi-Dashboard
|
|
then
|
|
Remove_Service dietpi-dashboard # Pre-v9.18
|
|
Remove_Service dietpi-dashboard-backend
|
|
Remove_Service dietpi-dashboard-frontend
|
|
[[ -d '/opt/dietpi-dashboard' ]] && G_EXEC rm -R /opt/dietpi-dashboard
|
|
fi
|
|
|
|
if To_Uninstall 99 # Prometheus Node Exporter
|
|
then
|
|
if [[ -f '/etc/systemd/system/raspberrypi_exporter.timer' ]]
|
|
then
|
|
G_EXEC systemctl --no-reload disable --now raspberrypi_exporter.timer
|
|
G_EXEC rm /etc/systemd/system/raspberrypi_exporter.timer
|
|
fi
|
|
[[ -d '/etc/systemd/system/raspberrypi_exporter.timer.d' ]] && G_EXEC rm -R /etc/systemd/system/raspberrypi_exporter.timer.d
|
|
Remove_Service raspberrypi_exporter
|
|
Remove_Service node_exporter 1 1
|
|
[[ -d '/opt/node_exporter' ]] && G_EXEC rm -R /opt/node_exporter
|
|
fi
|
|
|
|
if To_Uninstall 146 # Tautulli
|
|
then
|
|
Remove_Service tautulli 1 1
|
|
[[ -d '/opt/tautulli' ]] && G_EXEC rm -R /opt/tautulli
|
|
[[ -d '/mnt/dietpi_userdata/tautulli' ]] && G_EXEC rm -R /mnt/dietpi_userdata/tautulli
|
|
fi
|
|
|
|
if To_Uninstall 147 # Jackett
|
|
then
|
|
Remove_Service jackett 1 1
|
|
[[ -d '/opt/jackett' ]] && G_EXEC rm -R /opt/jackett
|
|
fi
|
|
|
|
if To_Uninstall 149 # NZBGet
|
|
then
|
|
Remove_Service nzbget 1 1 # group for pre-v6.33
|
|
[[ -d '/mnt/dietpi_userdata/nzbget' ]] && G_EXEC rm -R /mnt/dietpi_userdata/nzbget
|
|
fi
|
|
|
|
if To_Uninstall 151 # Prowlarr
|
|
then
|
|
Remove_Service prowlarr 1
|
|
G_EXEC rm -Rf /opt/prowlarr /mnt/dietpi_userdata/prowlarr /var/log/prowlarr
|
|
fi
|
|
|
|
if To_Uninstall 203 # Readarr
|
|
then
|
|
Remove_Service readarr 1
|
|
G_EXEC rm -Rf /opt/readarr /mnt/dietpi_userdata/readarr /var/log/readarr
|
|
fi
|
|
|
|
if To_Uninstall 155 # HTPC Manager
|
|
then
|
|
Remove_Service htpc-manager
|
|
[[ -d '/mnt/dietpi_userdata/htpc-manager' ]] && G_EXEC rm -R /mnt/dietpi_userdata/htpc-manager
|
|
fi
|
|
|
|
if To_Uninstall 150 # Mono
|
|
then
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections 'mono-*' 'libmono-*' 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-mono.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-mono.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-mono.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-mono.gpg
|
|
fi
|
|
|
|
if To_Uninstall 37 # Shairport Sync
|
|
then
|
|
G_AGP shairport-sync shairport-sync-airplay2
|
|
fi
|
|
|
|
if To_Uninstall 152 # Avahi-Daemon
|
|
then
|
|
G_AGP avahi-daemon
|
|
fi
|
|
|
|
if To_Uninstall 153 # OctoPrint
|
|
then
|
|
Remove_Service octoprint 1 1
|
|
# CLI alias
|
|
[[ -f '/etc/bashrc.d/dietpi-octoprint.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-octoprint.sh
|
|
# Data
|
|
[[ -d '/mnt/dietpi_userdata/octoprint' ]] && G_EXEC rm -R /mnt/dietpi_userdata/octoprint
|
|
# sudoers
|
|
[[ -f '/etc/sudoers.d/octoprint' ]] && G_EXEC rm /etc/sudoers.d/octoprint
|
|
fi
|
|
|
|
if To_Uninstall 187 # CUPS
|
|
then
|
|
G_AGP cups
|
|
[[ -d '/etc/cups' ]] && G_EXEC rm -R /etc/cups
|
|
fi
|
|
|
|
if To_Uninstall 121 # Roon Bridge
|
|
then
|
|
Remove_Service roonbridge 1 1
|
|
[[ -d '/opt/roonbridge' ]] && G_EXEC rm -R /opt/roonbridge
|
|
[[ -d '/var/log/roonbridge' ]] && G_EXEC rm -R /var/log/roonbridge
|
|
[[ -d '/mnt/dietpi_userdata/roonbridge' ]] && G_EXEC rm -R /mnt/dietpi_userdata/roonbridge
|
|
# Pre-v8.2
|
|
[[ -d '/etc/roonbridge' ]] && G_EXEC rm -R /etc/roonbridge
|
|
[[ -d '/var/log/roon' ]] && G_EXEC rm -R /var/log/roon
|
|
[[ -d '/mnt/dietpi_userdata/roon' ]] && G_EXEC rm -R /mnt/dietpi_userdata/roon
|
|
fi
|
|
|
|
if To_Uninstall 154 # Roon Server
|
|
then
|
|
Remove_Service roonserver 1 1
|
|
[[ -f '/etc/sudoers.d/roonserver' ]] && G_EXEC rm /etc/sudoers.d/roonserver
|
|
[[ -d '/opt/roonserver' ]] && G_EXEC rm -R /opt/roonserver
|
|
[[ -d '/var/log/roonserver' ]] && G_EXEC rm -R /var/log/roonserver
|
|
[[ -d '/mnt/dietpi_userdata/roonserver' ]] && G_EXEC rm -R /mnt/dietpi_userdata/roonserver
|
|
fi
|
|
|
|
if To_Uninstall 156 # Steam
|
|
then
|
|
G_AGP steam
|
|
G_EXEC rm -Rf /{root,home/*}/{.steam{,path,pid},Desktop/steam.desktop} /mnt/dietpi_userdata/steam
|
|
fi
|
|
|
|
if To_Uninstall 62 # Box86
|
|
then
|
|
[[ -f '/etc/binfmt.d/box86.conf' ]] && G_EXEC rm /etc/binfmt.d/box86.conf
|
|
[[ -d '/proc/sys/fs/binfmt_misc' ]] && G_EXEC systemctl restart systemd-binfmt
|
|
[[ -f '/usr/local/bin/box86' ]] && G_EXEC rm /usr/local/bin/box86
|
|
for i in /usr/lib/i386-linux-gnu/lib{gcc_s,png12,stdc++,unwind}.so*
|
|
do
|
|
[[ -e $i ]] && ! dpkg-query -S "$i" &> /dev/null && G_EXEC rm "$i"
|
|
done
|
|
[[ -d '/usr/lib/i386-linux-gnu' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /usr/lib/i386-linux-gnu
|
|
fi
|
|
|
|
if To_Uninstall 197 # Box64
|
|
then
|
|
[[ -f '/etc/binfmt.d/box64.conf' ]] && G_EXEC rm /etc/binfmt.d/box64.conf
|
|
[[ -d '/proc/sys/fs/binfmt_misc' ]] && G_EXEC systemctl restart systemd-binfmt
|
|
[[ -f '/usr/local/bin/box64' ]] && G_EXEC rm /usr/local/bin/box64
|
|
for i in /usr/lib/x86_64-linux-gnu/lib{crypto,gcc_s,mbed,png12,ssl,stdc++,unwind}*
|
|
do
|
|
[[ -e $i ]] && ! dpkg-query -S "$i" &> /dev/null && G_EXEC rm "$i"
|
|
done
|
|
[[ -d '/usr/lib/x86_64-linux-gnu' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /usr/lib/x86_64-linux-gnu
|
|
fi
|
|
|
|
if To_Uninstall 207 # Moonlight (CLI)
|
|
then
|
|
G_AGP moonlight-embedded
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-moonlight.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-moonlight.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-moonlight.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-moonlight.gpg
|
|
fi
|
|
|
|
if To_Uninstall 208 # Moonlight (GUI)
|
|
then
|
|
dpkg-query -s 'libgl1' &> /dev/null && G_EXEC apt-mark auto libgl1
|
|
G_AGP moonlight-qt
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-moonlight-qt.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-moonlight-qt.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-moonlight-qt.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-moonlight-qt.gpg
|
|
fi
|
|
|
|
if To_Uninstall 11 # GZDoom
|
|
then
|
|
G_AGP gzdoom
|
|
fi
|
|
|
|
if To_Uninstall 119 # CAVA
|
|
then
|
|
G_AGP cava
|
|
G_EXEC rm -Rf /{root,home/*}/.config/cava
|
|
fi
|
|
|
|
if To_Uninstall 118 # Mopidy
|
|
then
|
|
Remove_Service mopidy
|
|
G_AGP 'mopidy*'
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-mopidy.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-mopidy.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-mopidy.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-mopidy.gpg
|
|
|
|
command -v pip3 > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pip3 uninstall -y Mopidy-MusicBox-Webclient
|
|
|
|
getent passwd mopidy > /dev/null && G_EXEC userdel mopidy
|
|
[[ -d '/mnt/dietpi_userdata/mopidy' ]] && G_EXEC rm -R /mnt/dietpi_userdata/mopidy
|
|
fi
|
|
|
|
if To_Uninstall 31 # Kodi
|
|
then
|
|
G_AGP kodi kodi-odroid kodi-aml-fbdev-odroid
|
|
G_EXEC rm -Rf /{root,home/*}/{.kodi,Desktop/kodi.desktop}
|
|
[[ -f '/usr/share/applications/kodi.desktop' ]] && G_EXEC rm /usr/share/applications/kodi.desktop
|
|
[[ -f '/etc/udev/rules.d/99-dietpi-kodi.rules' ]] && G_EXEC rm /etc/udev/rules.d/99-dietpi-kodi.rules
|
|
[[ -f '/etc/modules-load.d/dietpi-n2-kodi.conf' ]] && G_EXEC rm /etc/modules-load.d/dietpi-n2-kodi.conf
|
|
[[ -f '/etc/modules-load.d/dietpi-c4-kodi.conf' ]] && G_EXEC rm /etc/modules-load.d/dietpi-c4-kodi.conf
|
|
[[ -f '/var/lib/dietpi/dietpi-software/installed/desktop/icons/kodi-icon.png' ]] && G_EXEC rm /var/lib/dietpi/dietpi-software/installed/desktop/icons/kodi-icon.png
|
|
fi
|
|
|
|
if To_Uninstall 39 # ReadyMedia
|
|
then
|
|
Remove_Service minidlna 1 1
|
|
G_AGP minidlna
|
|
[[ -d '/mnt/dietpi_userdata/.MiniDLNA_Cache' ]] && G_EXEC rm -R /mnt/dietpi_userdata/.MiniDLNA_Cache
|
|
[[ -d '/var/log/minidlna' ]] && G_EXEC rm -R /var/log/minidlna
|
|
fi
|
|
|
|
if To_Uninstall 51 # OpenTyrian
|
|
then
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections libsdl1.2debian libsdl-net1.2 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
|
|
G_EXEC rm -f /{usr/share/applications,{root,home/*}/Desktop}/opentyrian.desktop
|
|
[[ -d '/usr/games/opentyrian' ]] && G_EXEC rm -R /usr/games/opentyrian
|
|
fi
|
|
|
|
if To_Uninstall 59 # RPi Cam Web Interface
|
|
then
|
|
Remove_Service raspimjpeg
|
|
[[ -f '/var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh' ]] && G_EXEC rm /var/lib/dietpi/dietpi-software/installed/raspimjpeg.sh
|
|
[[ -f '/usr/local/bin/raspimjpeg' ]] && G_EXEC rm /usr/local/bin/raspimjpeg
|
|
[[ -f '/etc/raspimjpeg' ]] && G_EXEC rm /etc/raspimjpeg
|
|
G_AGP gpac
|
|
[[ -d '/var/www/rpicam' ]] && G_EXEC rm -R /var/www/rpicam
|
|
[[ -f '/etc/sudoers.d/dietpi-rpi_cam_control' ]] && G_EXEC rm /etc/sudoers.d/dietpi-rpi_cam_control
|
|
fi
|
|
|
|
if To_Uninstall 45 # Deluge
|
|
then
|
|
Remove_Service deluge-web
|
|
Remove_Service deluged debian-deluged debian-deluged
|
|
[[ -d '/mnt/dietpi_userdata/deluge' ]] && G_EXEC rm -R /mnt/dietpi_userdata/deluge
|
|
G_AGP deluged deluge-web deluge-console
|
|
fi
|
|
|
|
if To_Uninstall 94 # ProFTPD
|
|
then
|
|
G_AGP proftpd-basic
|
|
fi
|
|
|
|
if To_Uninstall 96 # Samba Server
|
|
then
|
|
G_AGP samba samba-common-bin
|
|
getent passwd samba > /dev/null && G_EXEC userdel samba
|
|
[[ -f '/etc/tmpfiles.d/dietpi-samba_cache.conf' ]] && G_EXEC rm /etc/tmpfiles.d/dietpi-samba_cache.conf
|
|
[[ -d '/run/samba-cache' ]] && G_EXEC rm -R /run/samba-cache
|
|
G_EXEC rm -Rf /var/cache/samba # Symlink
|
|
fi
|
|
|
|
if To_Uninstall 95 # vsftpd
|
|
then
|
|
G_AGP vsftpd
|
|
fi
|
|
|
|
if To_Uninstall 109 # NFS Server
|
|
then
|
|
G_AGP nfs-kernel-server
|
|
G_EXEC rm -Rf /etc/exports{,.d}
|
|
fi
|
|
|
|
if To_Uninstall 93 # Pi-hole
|
|
then
|
|
# Uninstaller
|
|
# - Skip dialogue
|
|
[[ -f '/opt/pihole/uninstall.sh' ]] && G_EXEC sed --follow-symlinks -i '/^[[:blank:]]*read -rp .*Are you sure you would like to remove.* answer$/c\answer=y' /opt/pihole/uninstall.sh
|
|
command -v pihole > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pihole uninstall
|
|
# - Call script directly if pihole command was not available (anymore)
|
|
[[ -f '/opt/pihole/uninstall.sh' ]] && G_EXEC_OUTPUT=1 G_EXEC /opt/pihole/uninstall.sh
|
|
|
|
# Cleanup if uninstaller was not available (anymore)
|
|
# - Service
|
|
Remove_Service pihole-FTL pihole pihole
|
|
# - Files
|
|
[[ -f '/usr/bin/pihole-FTL' ]] && G_EXEC rm /usr/bin/pihole-FTL
|
|
[[ -e '/usr/local/bin/pihole' ]] && G_EXEC rm /usr/local/bin/pihole
|
|
# - Dirs
|
|
[[ -d '/etc/pihole' ]] && G_EXEC rm -R /etc/pihole
|
|
[[ -d '/etc/.pihole' ]] && G_EXEC rm -R /etc/.pihole
|
|
[[ -d '/opt/pihole' ]] && G_EXEC rm -R /opt/pihole
|
|
[[ -d '/var/www/html/admin' ]] && G_EXEC rm -R /var/www/html/admin
|
|
[[ -d '/var/www/html/pihole' ]] && G_EXEC rm -R /var/www/html/pihole
|
|
|
|
# v5
|
|
# - Symlinks
|
|
[[ -L '/var/www/pihole' ]] && G_EXEC rm /var/www/pihole
|
|
[[ -L '/var/www/admin' ]] && G_EXEC rm /var/www/admin
|
|
# - Webserver configs
|
|
[[ -d '/etc/apache2/sites-available' ]] && G_EXEC rm -f /etc/apache2/sites-{available,enabled}/dietpi-pihole*
|
|
[[ -d '/etc/lighttpd/conf-available' ]] && G_EXEC rm -f /etc/lighttpd/conf-{available,enabled}/99-dietpi-pihole*
|
|
[[ -d '/etc/nginx/sites-dietpi' ]] && G_EXEC rm -f /etc/nginx/sites-dietpi/dietpi-pihole*
|
|
|
|
# Unbound: Switch port to 53 if it is still installed
|
|
if (( ${aSOFTWARE_INSTALL_STATE[182]} == 2 )) && grep -Eq '^[[:blank:]]*port:[[:blank:]]+5335$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Reconfiguring Unbound to work on its own'
|
|
G_CONFIG_INJECT 'port:[[:blank:]]' ' port: 53' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 0.0.0.0' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
grep -E '^[[:blank:]]*nameserver[[:blank:]]+127.0.0.1:5335$' /etc/resolv.conf && sed --follow-symlinks -Ei '/^[[:blank:]]*nameserver[[:blank:]]+127.0.0.1:5335$/c\nameserver 127.0.0.1' /etc/resolv.conf # Failsafe
|
|
G_EXEC_NOEXIT=1 G_EXEC systemctl restart unbound
|
|
else
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 126 # AdGuard Home
|
|
then
|
|
Remove_Service adguardhome 1
|
|
|
|
# Data directory
|
|
[[ -d '/mnt/dietpi_userdata/adguardhome' ]] && G_EXEC rm -R /mnt/dietpi_userdata/adguardhome
|
|
|
|
# Unbound: Switch port to 53 if it is still installed
|
|
if (( ${aSOFTWARE_INSTALL_STATE[182]} == 2 )) && grep -Eq '^[[:blank:]]*port:[[:blank:]]+5335$' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Reconfiguring Unbound to work on its own'
|
|
G_CONFIG_INJECT 'port:[[:blank:]]' ' port: 53' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 0.0.0.0' /etc/unbound/unbound.conf.d/dietpi.conf
|
|
grep -E '^[[:blank:]]*nameserver[[:blank:]]+127.0.0.1:5335$' /etc/resolv.conf && sed --follow-symlinks -Ei '/^[[:blank:]]*nameserver[[:blank:]]+127.0.0.1:5335$/c\nameserver 127.0.0.1' /etc/resolv.conf # Failsafe
|
|
G_EXEC_NOEXIT=1 G_EXEC systemctl restart unbound
|
|
else
|
|
grep '^[[:blank:]]*nameserver[[:blank:]]' /etc/resolv.conf | grep -qvE '[[:blank:]]127.0.0.1(:53)?$' || echo 'nameserver 9.9.9.9' >> /etc/resolv.conf # Failsafe
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 33 # Airsonic-Advanced
|
|
then
|
|
Remove_Service airsonic 1
|
|
[[ -d '/mnt/dietpi_userdata/airsonic' ]] && G_EXEC rm -R /mnt/dietpi_userdata/airsonic
|
|
fi
|
|
|
|
if To_Uninstall 204 # Navidrome
|
|
then
|
|
Remove_Service navidrome 1
|
|
G_EXEC rm -Rf /opt/navidrome /mnt/dietpi_userdata/navidrome
|
|
fi
|
|
|
|
if To_Uninstall 212 # Kavita
|
|
then
|
|
Remove_Service kavita 1
|
|
G_EXEC rm -Rf /opt/kavita
|
|
fi
|
|
|
|
if To_Uninstall 71 # WebIOPi
|
|
then
|
|
Remove_Service webiopi
|
|
[[ -f '/usr/bin/webiopi' ]] && G_EXEC rm /usr/bin/webiopi # Executable
|
|
[[ -f '/usr/bin/webiopi-passwd' ]] && G_EXEC rm /usr/bin/webiopi-passwd # Password generator
|
|
[[ -d '/etc/webiopi' ]] && G_EXEC rm -R /etc/webiopi # Config dir
|
|
[[ -d '/usr/share/webiopi' ]] && G_EXEC rm -R /usr/share/webiopi # HTML resources
|
|
G_EXEC rm -Rf /usr/local/lib/python*/dist-packages/WebIOPi* # Python packages
|
|
fi
|
|
|
|
if To_Uninstall 68 # Remote.It
|
|
then
|
|
G_AGP remoteit connectd weavedconnectd # connectd: pre-v8.10, weavedconnectd: pre-v6.22
|
|
fi
|
|
|
|
if To_Uninstall 186 # Kubo
|
|
then
|
|
Remove_Service ipfs 1 1
|
|
G_EXEC rm -Rf /usr/local/bin/ipfs /etc/bashrc.d/dietpi-ipfs.sh /etc/sysctl.d/dietpi-ipfs.conf /mnt/dietpi_userdata/ipfs
|
|
fi
|
|
|
|
if To_Uninstall 16 # microblog.pub
|
|
then
|
|
Remove_Service microblog-pub 1 1
|
|
[[ -f '/etc/bashrc.d/microblog-pub.sh' ]] && G_EXEC rm /etc/bashrc.d/microblog-pub.sh
|
|
[[ -d '/opt/microblog-pub' ]] && G_EXEC rm -R /opt/microblog-pub
|
|
G_DIETPI-NOTIFY 2 'All microblog.pub data and settings are still retained.\n - You can remove these manually: rm -R /mnt/dietpi_userdata/microblog-pub'
|
|
fi
|
|
|
|
if To_Uninstall 98 # HAProxy
|
|
then
|
|
Remove_Service haproxy
|
|
G_EXEC rm -Rf /{etc,var/lib,/usr/local/{doc,sbin}}/haproxy /usr/local/share/man/man1/haproxy.1
|
|
[[ -d '/usr/local/share/man/man1' ]] && G_EXEC rmdir -p --ignore-fail-on-non-empty /usr/local/share/man/man1
|
|
fi
|
|
|
|
if To_Uninstall 35 # Lyrion Music Server
|
|
then
|
|
# Stop systemd service, which is not done by postinst, failing to remove user then
|
|
Remove_Service lyrionmusicserver
|
|
G_AGP lyrionmusicserver
|
|
[[ -d '/var/lib/squeezeboxserver' ]] && G_EXEC rm -R /var/lib/squeezeboxserver
|
|
fi
|
|
|
|
if To_Uninstall 55 # WordPress
|
|
then
|
|
[[ -d '/var/www/wordpress' ]] && G_EXEC rm -R /var/www/wordpress
|
|
Remove_Database wordpress
|
|
fi
|
|
|
|
if To_Uninstall 38 # FreshRSS
|
|
then
|
|
crontab -u www-data -l | grep -v '/opt/FreshRSS/app/actualize_script.php' | crontab -u www-data -
|
|
|
|
a2disconf dietpi-freshrss 2> /dev/null
|
|
[[ -f '/etc/apache2/conf-available/dietpi-freshrss.conf' ]] && G_EXEC rm /etc/apache2/conf-available/dietpi-freshrss.conf
|
|
|
|
G_EXEC rm -Rf /var/www/freshrss # symlink
|
|
[[ -d '/opt/FreshRSS' ]] && G_EXEC rm -R /opt/FreshRSS
|
|
[[ -f '/var/log/freshrss.log' ]] && G_EXEC rm /var/log/freshrss.log
|
|
|
|
Remove_Database freshrss
|
|
fi
|
|
|
|
if To_Uninstall 28 || To_Uninstall 120 # TigerVNC/RealVNC
|
|
then
|
|
# RealVNC services
|
|
Remove_Service vncserver-x11-serviced
|
|
Remove_Service vncserver-virtuald
|
|
|
|
G_AGP 'tigervnc-*' x11vnc realvnc-vnc-server
|
|
|
|
Remove_Service vncserver
|
|
[[ -f '/usr/local/bin/vncserver' ]] && G_EXEC rm /usr/local/bin/vncserver
|
|
G_EXEC rm -Rf /{root,home/*}/.vnc
|
|
fi
|
|
|
|
if To_Uninstall 73 # Fail2Ban
|
|
then
|
|
G_AGP fail2ban
|
|
dpkg-query -s 'python3-systemd' &> /dev/null && G_EXEC apt-mark auto python3-systemd
|
|
[[ -d '/etc/fail2ban' ]] && G_EXEC rm -R /etc/fail2ban
|
|
fi
|
|
|
|
if To_Uninstall 64 # phpSysInfo
|
|
then
|
|
[[ -d '/var/www/phpsysinfo' ]] && G_EXEC rm -R /var/www/phpsysinfo
|
|
fi
|
|
|
|
if To_Uninstall 56 # Single File PHP Gallery
|
|
then
|
|
[[ -f '/var/www/gallery/index.php' ]] && G_EXEC rm /var/www/gallery/index.php
|
|
[[ -f '/var/www/gallery/readme.txt' ]] && G_EXEC rm /var/www/gallery/readme.txt
|
|
[[ -d '/var/www/gallery/_sfpg_data' ]] && G_EXEC rm -R /var/www/gallery/_sfpg_data
|
|
G_DIETPI-NOTIFY 2 'The plain gallery image files are not removed. You may do this manually via "rm -R /var/www/gallery".'
|
|
fi
|
|
|
|
if To_Uninstall 40 # Ampache
|
|
then
|
|
[[ -d '/var/www/ampache' || -L '/var/www/ampache' ]] && G_EXEC rm -R /var/www/ampache
|
|
[[ -d '/mnt/dietpi_userdata/ampache' ]] && G_EXEC rm -R /mnt/dietpi_userdata/ampache
|
|
Remove_Database ampache
|
|
fi
|
|
|
|
if To_Uninstall 117 # PiVPN
|
|
then
|
|
[[ -f '/opt/pivpn/uninstall.sh' ]] && G_EXEC sed --follow-symlinks -i 's/ askreboot;//' /opt/pivpn/uninstall.sh
|
|
command -v pivpn > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pivpn -u
|
|
getent passwd pivpn > /dev/null && G_EXEC userdel pivpn
|
|
getent group pivpn > /dev/null && G_EXEC groupdel pivpn
|
|
[[ -f '/etc/apt/sources.list.d/swupdate.openvpn.net.list' ]] && G_EXEC rm /etc/apt/sources.list.d/swupdate.openvpn.net.list # Not part of current installer anymore
|
|
fi
|
|
|
|
if To_Uninstall 201 # ZeroTier
|
|
then
|
|
G_AGP zerotier-one
|
|
[[ -d '/etc/systemd/system/zerotier-one.service.d' ]] && G_EXEC rm -R /etc/systemd/system/zerotier-one.service.d
|
|
[[ -d '/var/lib/zerotier-one' ]] && G_EXEC rm -R /var/lib/zerotier-one
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-zerotier.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-zerotier.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-zerotier.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-zerotier.gpg
|
|
fi
|
|
|
|
if To_Uninstall 97 # OpenVPN Server
|
|
then
|
|
G_AGP openvpn
|
|
[[ -d '/etc/systemd/system/openvpn.service.d' ]] && G_EXEC rm -R /etc/systemd/system/openvpn.service.d
|
|
[[ -d '/etc/openvpn' ]] && G_EXEC rm -R /etc/openvpn
|
|
[[ -f '/etc/sysctl.d/dietpi-openvpn.conf' ]] && G_EXEC rm /etc/sysctl.d/dietpi-openvpn.conf
|
|
fi
|
|
|
|
if To_Uninstall 172 # WireGuard
|
|
then
|
|
G_AGP 'wireguard*'
|
|
[[ -d '/etc/systemd/system/wg-quick@wg0.service.d' ]] && G_EXEC rm -R /etc/systemd/system/wg-quick@wg0.service.d
|
|
[[ -d '/etc/wireguard' ]] && G_EXEC rm -R /etc/wireguard
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-wireguard.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-wireguard.list
|
|
fi
|
|
|
|
if To_Uninstall 58 # Tailscale
|
|
then
|
|
G_AGP tailscale
|
|
[[ -d '/etc/systemd/system/tailscaled.service.d' ]] && G_EXEC rm -R /etc/systemd/system/tailscaled.service.d
|
|
[[ -d '/var/lib/tailscale' ]] && G_EXEC rm -R /var/lib/tailscale
|
|
[[ -f '/etc/sysctl.d/dietpi-tailscale.conf' ]] && G_EXEC rm /etc/sysctl.d/dietpi-tailscale.conf
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-tailscale.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-tailscale.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-tailscale.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-tailscale.gpg
|
|
fi
|
|
|
|
if To_Uninstall 92 # Certbot
|
|
then
|
|
G_AGP python3-certbot-apache python3-certbot-nginx certbot
|
|
[[ -d '/etc/systemd/system/certbot.service.d' ]] && G_EXEC rm -R /etc/systemd/system/certbot.service.d
|
|
fi
|
|
|
|
if To_Uninstall 69 # Python 3 RPi.GPIO
|
|
then
|
|
G_AGP python3-rpi-lgpio python3-rpi.gpio
|
|
fi
|
|
|
|
if To_Uninstall 72 # I2C
|
|
then
|
|
G_AGP i2c-tools
|
|
/boot/dietpi/func/dietpi-set_hardware i2c disable
|
|
fi
|
|
|
|
if To_Uninstall 70 # WiringPi
|
|
then
|
|
if [[ -d '/mnt/dietpi_userdata/WiringPi' ]]
|
|
then
|
|
G_EXEC cd /mnt/dietpi_userdata/WiringPi
|
|
if [[ -f ./build ]]
|
|
then
|
|
G_EXEC_NOEXIT=1 G_EXEC_OUTPUT=1 G_EXEC ./build uninstall # RPi and pre-v8.5 Odroids
|
|
|
|
elif [[ -f ./Makefile ]]
|
|
then
|
|
G_EXEC_NOEXIT=1 G_EXEC_OUTPUT=1 G_EXEC make uninstall # Odroids
|
|
fi
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R /mnt/dietpi_userdata/WiringPi
|
|
fi
|
|
# Pre-v7.2
|
|
if [[ -d '/root/wiringPi' ]]
|
|
then
|
|
G_EXEC cd /root/wiringPi
|
|
G_EXEC_NOEXIT=1 G_EXEC_OUTPUT=1 G_EXEC ./build uninstall
|
|
G_EXEC cd "$G_WORKING_DIR"
|
|
G_EXEC rm -R /root/wiringPi
|
|
fi
|
|
# GPIO utility
|
|
[[ -f '/usr/local/bin/gpio' ]] && G_EXEC rm /usr/local/bin/gpio
|
|
[[ -f '/usr/local/sbin/gpio' ]] && G_EXEC rm /usr/local/sbin/gpio
|
|
[[ -f '/usr/local/share/man/man1/gpio.1' ]] && G_EXEC rm /usr/local/share/man/man1/gpio.1
|
|
[[ -d '/usr/local/share/man/man1' ]] && G_EXEC rmdir -p --ignore-fail-on-non-empty /usr/local/share/man/man1
|
|
# Library
|
|
G_EXEC rm -f /usr/local/lib/libwiringPi.so*
|
|
# Device library
|
|
G_EXEC rm -f /usr/local/lib/libwiringPiDev.so*
|
|
# Headers
|
|
G_EXEC rm -f /usr/local/include/wiringPi*.h
|
|
# Orange Pi
|
|
[[ -f '/etc/orangepi-release' ]] && grep -q '^# Added by DietPi:$' /etc/orangepi-release && G_EXEC rm /etc/orangepi-release
|
|
fi
|
|
|
|
if To_Uninstall 61 # Tor Hotspot
|
|
then
|
|
G_AGP tor
|
|
|
|
[[ -d '/var/log/tor' ]] && G_EXEC rm -R /var/log/tor # pre-v6.27
|
|
|
|
# Uninstall WiFi Hotspot too, due to iptables needing reset
|
|
aSOFTWARE_INSTALL_STATE[60]=-1
|
|
fi
|
|
|
|
if To_Uninstall 60 # WiFi Hotspot
|
|
then
|
|
G_AGP hostapd isc-dhcp-server
|
|
|
|
[[ -f '/etc/dhcp/dhcpd.conf' ]] && G_EXEC rm /etc/dhcp/dhcpd.conf
|
|
[[ -f '/etc/hostapd/hostapd.conf' ]] && G_EXEC rm /etc/hostapd/hostapd.conf
|
|
[[ -f '/etc/default/isc-dhcp-server' ]] && G_EXEC rm /etc/default/isc-dhcp-server
|
|
[[ -f '/etc/default/hostapd' ]] && G_EXEC rm /etc/default/hostapd
|
|
[[ -f '/etc/iptables.ipv4.nat' ]] && G_EXEC rm /etc/iptables.ipv4.nat
|
|
[[ -f '/etc/iptables.ipv6.nat' ]] && G_EXEC rm /etc/iptables.ipv6.nat
|
|
[[ -f '/etc/sysctl.d/dietpi-wifihotspot.conf' ]] && G_EXEC rm /etc/sysctl.d/dietpi-wifihotspot.conf
|
|
|
|
# Set WiFi interface back to inactive and ready for use with dietpi-config.
|
|
local wifi_iface=$(G_GET_NET -t wlan iface)
|
|
# - Remove WLAN block, so we can recreate it
|
|
G_EXEC sed --follow-symlinks -Ei '/(allow-hotplug|auto)[[:blank:]]+wlan/q0' /etc/network/interfaces
|
|
# - Disable
|
|
G_EXEC sed --follow-symlinks -i "/allow-hotplug wlan/c\#allow-hotplug $wifi_iface" /etc/network/interfaces
|
|
# - Add default WiFi settings to network interfaces config
|
|
cat << _EOF_ >> /etc/network/interfaces
|
|
iface $wifi_iface inet dhcp
|
|
address 192.168.0.101
|
|
netmask 255.255.255.0
|
|
#gateway 192.168.0.1
|
|
#dns-nameservers 9.9.9.9 149.112.112.112
|
|
pre-up iw dev $wifi_iface set power_save off
|
|
post-down iw dev $wifi_iface set power_save on
|
|
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
|
|
_EOF_
|
|
# shellcheck disable=SC2015
|
|
iw dev "$wifi_iface" set power_save on 2> /dev/null && iw dev "$wifi_iface" set power_save off 2> /dev/null || G_EXEC sed --follow-symlinks -i '/ iw dev .* set power_save /d' /etc/network/interfaces
|
|
# - Flush iptables
|
|
iptables -F
|
|
iptables -t nat -F
|
|
ip6tables -F
|
|
ip6tables -t nat -F
|
|
fi
|
|
|
|
if To_Uninstall 48 # Pydio
|
|
then
|
|
[[ -d '/var/www/pydio' ]] && G_EXEC rm -R /var/www/pydio
|
|
|
|
# Remove webserver configs
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-pydio
|
|
[[ -f '/etc/apache2/conf-available/dietpi-pydio.conf' ]] && G_EXEC rm /etc/apache2/conf-available/dietpi-pydio.conf
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-pydio.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-pydio.conf
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-pydio
|
|
[[ -f '/etc/lighttpd/conf-available/99-dietpi-pydio.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-pydio.conf
|
|
|
|
Remove_Database pydio
|
|
fi
|
|
|
|
if To_Uninstall 36 # Squeezelite
|
|
then
|
|
G_AGP squeezelite
|
|
Remove_Service squeezelite 1 1 # Pre-v7.3
|
|
fi
|
|
|
|
if To_Uninstall 66 # RPi-Monitor
|
|
then
|
|
G_AGP rpimonitor
|
|
[[ -d '/etc/rpimonitor' ]] && G_EXEC rm -R /etc/rpimonitor
|
|
[[ -d '/var/lib/rpimonitor' ]] && G_EXEC rm -R /var/lib/rpimonitor
|
|
[[ -f '/var/log/rpimonitor.log' ]] && G_EXEC rm /var/log/rpimonitor.log
|
|
fi
|
|
|
|
if To_Uninstall 57 # Baïkal
|
|
then
|
|
# Remove webserver configs
|
|
# - Lighttpd
|
|
if [[ -f '/etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf' ]]
|
|
then
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-dav_redirect
|
|
G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-dav_redirect.conf
|
|
fi
|
|
if [[ -f '/etc/lighttpd/conf-available/99-dietpi-baikal.conf' ]]
|
|
then
|
|
command -v lighty-disable-mod > /dev/null && lighty-disable-mod dietpi-baikal
|
|
G_EXEC rm /etc/lighttpd/conf-available/99-dietpi-baikal.conf
|
|
fi
|
|
# - Apache
|
|
if [[ -f '/etc/apache2/conf-available/dietpi-dav_redirect.conf' ]]
|
|
then
|
|
command -v a2disconf > /dev/null && a2disconf dietpi-dav_redirect
|
|
G_EXEC rm /etc/apache2/conf-available/dietpi-dav_redirect.conf
|
|
fi
|
|
if [[ -f '/etc/apache2/sites-available/dietpi-baikal.conf' ]]
|
|
then
|
|
command -v a2dissite > /dev/null && a2dissite dietpi-baikal
|
|
G_EXEC rm /etc/apache2/sites-available/dietpi-baikal.conf
|
|
fi
|
|
# - Nginx
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-dav_redirect.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-dav_redirect.conf
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-baikal.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-baikal.conf
|
|
|
|
[[ -d '/var/www/baikal' ]] && G_EXEC rm -R /var/www/baikal
|
|
|
|
Remove_Database baikal
|
|
fi
|
|
|
|
if To_Uninstall 65 # Netdata
|
|
then
|
|
G_AGP netdata
|
|
fi
|
|
|
|
if To_Uninstall 43 # Mumble Server
|
|
then
|
|
G_AGP mumble-server
|
|
fi
|
|
|
|
if To_Uninstall 41 # Emby
|
|
then
|
|
G_AGP emby-server
|
|
fi
|
|
|
|
if To_Uninstall 42 # Plex Media Server
|
|
then
|
|
# Force deletion of plex group which is not removed automatically because it is not the primary group of user plex
|
|
Remove_Service plexmediaserver plex plex
|
|
# Remove systemd unit which currently survives the package purging: https://github.com/MichaIng/DietPi/issues/3551
|
|
[[ -f '/lib/systemd/system/plexmediaserver.service' ]] && G_EXEC rm /lib/systemd/system/plexmediaserver.service
|
|
G_AGP plexmediaserver
|
|
[[ -d '/var/lib/plexmediaserver' ]] && G_EXEC rm -R /var/lib/plexmediaserver # Left over from purging package, still...
|
|
[[ -f '/etc/unbound/unbound.conf.d/dietpi-plex.conf' ]] && G_EXEC rm /etc/unbound/unbound.conf.d/dietpi-plex.conf
|
|
fi
|
|
|
|
if To_Uninstall 52 # Cuberite
|
|
then
|
|
Remove_Service cuberite 1 1
|
|
[[ -d '/mnt/dietpi_userdata/cuberite' ]] && G_EXEC rm -R /mnt/dietpi_userdata/cuberite
|
|
fi
|
|
|
|
if To_Uninstall 53 # MineOS
|
|
then
|
|
Remove_Service mineos 1 1
|
|
[[ -d '/mnt/dietpi_userdata/mineos' ]] && G_EXEC rm -R /mnt/dietpi_userdata/mineos
|
|
[[ -f '/etc/mineos.conf' ]] && G_EXEC rm /etc/mineos.conf
|
|
G_EXEC rm -Rf /var/games/minecraft /usr/local/bin/mineos /etc/ssl/certs/mineos.* # Symlinks and SSL cert
|
|
[[ -d '/home/mineos' ]] && G_EXEC rm -R /home/mineos # pre-v6.34
|
|
fi
|
|
|
|
if To_Uninstall 49 # Gogs
|
|
then
|
|
Remove_Service gogs 1 1
|
|
|
|
# Data
|
|
[[ -d '/etc/gogs' ]] && G_EXEC rm -R /etc/gogs
|
|
[[ -d '/var/log/gogs' ]] && G_EXEC rm -R /var/log/gogs
|
|
|
|
Remove_Database gogs
|
|
fi
|
|
|
|
if To_Uninstall 46 # qBittorrent
|
|
then
|
|
Remove_Service qbittorrent 1 1 # group for pre-v6.29
|
|
G_AGP qbittorrent-nox
|
|
[[ -d '/home/qbittorrent' ]] && G_EXEC rm -R /home/qbittorrent
|
|
[[ -d '/var/log/qbittorrent' ]] && G_EXEC rm -R /var/log/qbittorrent
|
|
fi
|
|
|
|
if To_Uninstall 50 # Syncthing
|
|
then
|
|
Remove_Service syncthing 1
|
|
|
|
[[ -d '/opt/syncthing' ]] && G_EXEC rm -R /opt/syncthing
|
|
[[ -d '/mnt/dietpi_userdata/syncthing' ]] && G_EXEC rm -R /mnt/dietpi_userdata/syncthing
|
|
#[[ -d '/mnt/dietpi_userdata/syncthing_data' ]] && G_EXEC rm -R /mnt/dietpi_userdata/syncthing_data # Leave data in place
|
|
[[ -f '/etc/sysctl.d/dietpi-syncthing.conf' ]] && G_EXEC rm /etc/sysctl.d/dietpi-syncthing.conf
|
|
fi
|
|
|
|
if To_Uninstall 116 # Medusa
|
|
then
|
|
Remove_Service medusa 1 1 # group for pre-v6.33
|
|
[[ -d '/mnt/dietpi_userdata/medusa' ]] && G_EXEC rm -R /mnt/dietpi_userdata/medusa
|
|
fi
|
|
|
|
if To_Uninstall 107 # rTorrent
|
|
then
|
|
# ruTorrent
|
|
[[ -d '/var/www/rutorrent' ]] && G_EXEC rm -R /var/www/rutorrent
|
|
# - Authentication
|
|
[[ -f '/etc/.rutorrent-htaccess' ]] && G_EXEC rm /etc/.rutorrent-htaccess
|
|
# - Lighttpd
|
|
# Pre-v7.2: Remove from #RUTORRENT_DIETPI to #RUTORRENT_DIETPI in /etc/lighttpd/lighttpd.conf if exist
|
|
[[ -f '/etc/lighttpd/lighttpd.conf' ]] && grep -q '^#RUTORRENT_DIETPI' /etc/lighttpd/lighttpd.conf && G_EXEC sed --follow-symlinks -i '/#RUTORRENT_DIETPI/,/#RUTORRENT_DIETPI/d' /etc/lighttpd/lighttpd.conf
|
|
|
|
# Remove rTorrent config from Lighttpd
|
|
[[ -f '/etc/lighttpd/conf-enabled/98-dietpi-rtorrent.conf' ]] && G_EXEC lighty-disable-mod dietpi-rtorrent
|
|
[[ -f '/etc/lighttpd/conf-available/98-dietpi-rtorrent.conf' ]] && G_EXEC rm /etc/lighttpd/conf-available/98-dietpi-rtorrent.conf
|
|
|
|
# - Nginx
|
|
[[ -f '/etc/nginx/sites-dietpi/dietpi-rutorrent.conf' ]] && G_EXEC rm /etc/nginx/sites-dietpi/dietpi-rutorrent.conf
|
|
# - Apache
|
|
command -v a2dissite &> /dev/null && a2dissite dietpi-rutorrent
|
|
[[ -f '/etc/apache2/sites-available/dietpi-rutorrent.conf' ]] && G_EXEC rm /etc/apache2/sites-available/dietpi-rutorrent.conf
|
|
|
|
# rTorrent
|
|
Remove_Service rtorrent 1 1 # group for pre-v6.29
|
|
G_AGP rtorrent
|
|
[[ -d '/mnt/dietpi_userdata/rtorrent' ]] && G_EXEC rm -R /mnt/dietpi_userdata/rtorrent
|
|
[[ -d '/mnt/dietpi_userdata/downloads/.session' ]] && G_EXEC rm -R /mnt/dietpi_userdata/downloads/.session
|
|
fi
|
|
|
|
if To_Uninstall 108 # Amiberry
|
|
then
|
|
G_AGP amiberry
|
|
Remove_Service amiberry # pre-v8.5
|
|
# Files
|
|
[[ -d '/mnt/dietpi_userdata/amiberry' ]] && G_EXEC rm -R /mnt/dietpi_userdata/amiberry
|
|
# Autostart index: If currently Amiberry, revert to console login
|
|
[[ -f '/boot/dietpi/.dietpi-autostart_index' && $(</boot/dietpi/.dietpi-autostart_index) == [68] ]] && /boot/dietpi/dietpi-autostart 0
|
|
fi
|
|
|
|
if To_Uninstall 10 # Amiberry-Lite
|
|
then
|
|
G_AGP amiberry-lite
|
|
# Files
|
|
[[ -d '/mnt/dietpi_userdata/amiberry-lite' ]] && G_EXEC rm -R /mnt/dietpi_userdata/amiberry-lite
|
|
fi
|
|
|
|
if To_Uninstall 112 # DXX-Rebirth
|
|
then
|
|
[[ -d '/mnt/dietpi_userdata/dxx-rebirth' ]] && G_EXEC rm -R /mnt/dietpi_userdata/dxx-rebirth
|
|
|
|
# Remove symlinks
|
|
[[ -f '/root/.d1x-rebirth' ]] && G_EXEC rm /root/.d1x-rebirth
|
|
[[ -f '/root/.d2x-rebirth' ]] && G_EXEC rm /root/.d2x-rebirth
|
|
G_EXEC rm -f /{root,home/*}/Desktop/dxx-rebirth.desktop
|
|
[[ -f '/usr/share/applications/dxx-rebirth.desktop' ]] && G_EXEC rm /usr/share/applications/dxx-rebirth.desktop
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections 'libsdl-mixer1.2' 'libsdl1.2debian' 'libphysfs1' 'libgl1' 'libglu1-mesa' 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
fi
|
|
|
|
if To_Uninstall 113 # Chromium
|
|
then
|
|
# Package
|
|
G_AGP 'chromium*'
|
|
# Files
|
|
[[ -d '/etc/chromium.d' ]] && G_EXEC rm -R /etc/chromium.d
|
|
[[ -d '/usr/lib/chromium' ]] && G_EXEC rm -R /usr/lib/chromium
|
|
[[ -d '/usr/lib/chromium-browser' ]] && G_EXEC rm -R /usr/lib/chromium-browser
|
|
G_EXEC rm -Rf /{root,home/*}/{.chromium-browser.init,.{cache,config}/chromium,Desktop/chromium{,-browser}.desktop}
|
|
[[ -f '/var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh' ]] && G_EXEC rm /var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh
|
|
# Autostart index: If currently Chromium, revert to console login
|
|
[[ -f '/boot/dietpi/.dietpi-autostart_index' && $(</boot/dietpi/.dietpi-autostart_index) == 11 ]] && /boot/dietpi/dietpi-autostart 0
|
|
fi
|
|
|
|
if To_Uninstall 190 # Beets
|
|
then
|
|
G_AGP beets
|
|
[[ -f '/etc/bashrc.d/dietpi-beets.sh' ]] && G_EXEC rm /etc/bashrc.d/dietpi-beets.sh
|
|
[[ -d '/mnt/dietpi_userdata/beets' ]] && G_EXEC rm -R /mnt/dietpi_userdata/beets
|
|
fi
|
|
|
|
if To_Uninstall 157 # Home Assistant
|
|
then
|
|
Remove_Service home-assistant homeassistant homeassistant
|
|
[[ -d '/home/homeassistant' ]] && G_EXEC rm -R /home/homeassistant
|
|
[[ -d '/srv/homeassistant' ]] && G_EXEC rm -R /srv/homeassistant # pre-v6-27
|
|
|
|
G_DIETPI-NOTIFY 2 'Home Assistant data and settings are not removed.\n - You may want to do this manually: rm -R /mnt/dietpi_userdata/homeassistant'
|
|
fi
|
|
|
|
if To_Uninstall 140 # Domoticz
|
|
then
|
|
G_AGP domoticz
|
|
fi
|
|
|
|
if To_Uninstall 165 # Gitea
|
|
then
|
|
Remove_Service gitea 1 1
|
|
|
|
# Data
|
|
[[ -d '/mnt/dietpi_userdata/gitea' ]] && G_EXEC rm -R /mnt/dietpi_userdata/gitea
|
|
[[ -d '/var/log/gitea' ]] && G_EXEC rm -R /var/log/gitea
|
|
|
|
Remove_Database gitea
|
|
fi
|
|
|
|
if To_Uninstall 177 # Forgejo
|
|
then
|
|
Remove_Service forgejo 1 1
|
|
|
|
# Data
|
|
[[ -d '/mnt/dietpi_userdata/forgejo' ]] && G_EXEC rm -R /mnt/dietpi_userdata/forgejo
|
|
[[ -d '/var/log/forgejo' ]] && G_EXEC rm -R /var/log/forgejo
|
|
|
|
Remove_Database forgejo
|
|
fi
|
|
|
|
if To_Uninstall 166 # Audiophonics PI-SPC
|
|
then
|
|
Remove_Service pi-spc
|
|
[[ -d '/var/lib/dietpi/dietpi-software/installed/pi-spc' ]] && G_EXEC rm -R /var/lib/dietpi/dietpi-software/installed/pi-spc
|
|
|
|
G_EXEC sed --follow-symlinks -Ei '/^[[:blank:]]*dtoverlay=gpio-(shutdown|poweroff)/d' /boot/config.txt
|
|
fi
|
|
|
|
if To_Uninstall 167 # Raspotify
|
|
then
|
|
G_AGP raspotify
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-raspotify.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-raspotify.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-raspotify.asc' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-raspotify.asc
|
|
fi
|
|
|
|
if To_Uninstall 100 # PiJuice
|
|
then
|
|
G_AGP pijuice-base
|
|
[[ -d '/var/lib/dietpi/dietpi-software/installed/pijuice' ]] && G_EXEC rm -R /var/lib/dietpi/dietpi-software/installed/pijuice
|
|
[[ -d '/var/lib/pijuice' ]] && G_EXEC rm -R /var/lib/pijuice
|
|
fi
|
|
|
|
if To_Uninstall 205 # Homer
|
|
then
|
|
[[ -d '/var/www/homer' ]] && G_EXEC rm -R /var/www/homer
|
|
if [[ -f '/mnt/dietpi_userdata/homer_backup' ]]
|
|
then
|
|
if G_WHIP_BUTTON_CANCEL_TEXT='Keep it' G_WHIP_YESNO 'Do you want to remove the Homer backup at /mnt/dietpi_userdata/homer_backup as well?'
|
|
then
|
|
G_EXEC rm -R /mnt/dietpi_userdata/homer_backup
|
|
else
|
|
G_DIETPI-NOTIFY 2 'Leaving Homer backup at /mnt/dietpi_userdata/homer_backup in place'
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 158 # MinIO
|
|
then
|
|
Remove_Service minio minio-user minio-user
|
|
|
|
# Files
|
|
[[ -f '/usr/local/bin/minio' ]] && G_EXEC rm /usr/local/bin/minio
|
|
[[ -f '/etc/default/minio' ]] && G_EXEC rm /etc/default/minio
|
|
|
|
# Certbot hook
|
|
[[ -f '/etc/letsencrypt/renewal-hooks/deploy/dietpi-minio.sh' ]] && G_EXEC rm /etc/letsencrypt/renewal-hooks/deploy/dietpi-minio.sh
|
|
# - Pre-v8.0
|
|
[[ -f '/etc/systemd/system/certbot.service.d/dietpi-minio.conf' ]] && G_EXEC rm /etc/systemd/system/certbot.service.d/dietpi-minio.conf
|
|
[[ -d '/etc/systemd/system/certbot.service.d' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /etc/systemd/system/certbot.service.d
|
|
fi
|
|
|
|
if To_Uninstall 161 # FuguHub
|
|
then
|
|
Remove_Service bdd bd bd
|
|
|
|
# Files
|
|
[[ -d '/home/bd' ]] && G_EXEC rm -R /home/bd
|
|
|
|
G_DIETPI-NOTIFY 2 'FuguHub file server data at /mnt/dietpi_userdata/fuguhub-data are not removed. You may do this manually:\n - rm -R /mnt/dietpi_userdata/fuguhub-data'
|
|
fi
|
|
|
|
if To_Uninstall 189 # VSCodium
|
|
then
|
|
G_AGP codium
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-vscodium.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-vscodium.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-vscodium.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-vscodium.gpg
|
|
G_EXEC rm -f /{usr/share/applications,{root,home/*}/Desktop}/codium.desktop
|
|
G_EXEC rm -Rf /{root,home/*}/{.config/VSCodium,.vscode-oss}
|
|
fi
|
|
|
|
if To_Uninstall 185 # Portainer
|
|
then
|
|
# Check if Docker is still installed
|
|
if [[ -d '/mnt/dietpi_userdata/docker-data' ]]
|
|
then
|
|
local container=$(docker container ls -aqf 'ancestor=portainer/portainer' -f 'ancestor=portainer/portainer-ce' -f 'ancestor=portainer/portainer-ee')
|
|
[[ $container ]] && G_EXEC docker container rm -f "$container"
|
|
local image=$(docker image ls -aqf 'reference=portainer/portainer' -f 'reference=portainer/portainer-ce' -f 'reference=portainer/portainer-ee')
|
|
[[ $image ]] && G_EXEC docker image rm "$image"
|
|
[[ $(docker volume ls -qf 'name=^portainer_data$') ]] && G_EXEC docker volume rm 'portainer_data'
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 134 # Docker Compose
|
|
then
|
|
G_AGP docker-compose-plugin docker-compose
|
|
[[ -f '/usr/local/bin/docker-compose' ]] && G_EXEC rm /usr/local/bin/docker-compose # Pre-v8.14
|
|
command -v docker-compose > /dev/null && command -v pip3 > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pip3 uninstall -y docker-compose # Pre-v8.2
|
|
fi
|
|
|
|
if To_Uninstall 162 # Docker
|
|
then
|
|
Remove_Service docker
|
|
|
|
# Packages, repo and key
|
|
G_AGP docker-ce docker-ce-cli docker.io docker-cli
|
|
[[ -f '/etc/apt/sources.list.d/docker.list' ]] && G_EXEC rm /etc/apt/sources.list.d/docker.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-docker.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-docker.gpg
|
|
|
|
# DietPi data dir
|
|
[[ -d '/mnt/dietpi_userdata/docker-data' ]] && G_EXEC rm -R /mnt/dietpi_userdata/docker-data
|
|
# Default data dir
|
|
[[ -d '/var/lib/docker' ]] && G_EXEC rm -R /var/lib/docker
|
|
# Config dir
|
|
[[ -d '/etc/docker' ]] && G_EXEC rm -R /etc/docker
|
|
|
|
# Set Portainer as not installed
|
|
aSOFTWARE_INSTALL_STATE[185]=0
|
|
fi
|
|
|
|
if To_Uninstall 164 # Nukkit
|
|
then
|
|
Remove_Service nukkit
|
|
[[ -d '/usr/local/bin/nukkit' ]] && G_EXEC rm -R /usr/local/bin/nukkit
|
|
fi
|
|
|
|
if To_Uninstall 163 # GMediaRender
|
|
then
|
|
G_AGP gmediarender
|
|
fi
|
|
|
|
if To_Uninstall 67 # Firefox
|
|
then
|
|
G_AGP firefox-esr
|
|
G_EXEC rm -Rf /{root,home/*}/.mozilla/firefox
|
|
for i in /{root,home/*}/.mozilla; do [[ -d $i ]] && G_EXEC rmdir --ignore-fail-on-non-empty "$i"; done
|
|
fi
|
|
|
|
if To_Uninstall 159 # Allo GUI full
|
|
then
|
|
# Mark standalone version for uninstall
|
|
aSOFTWARE_INSTALL_STATE[160]=-1
|
|
fi
|
|
|
|
if To_Uninstall 160 # Allo GUI
|
|
then
|
|
# Files
|
|
[[ -f '/var/www/index.php' ]] && G_EXEC rm /var/www/index.php
|
|
G_EXEC rm -Rf /var/www/allo
|
|
[[ -d '/opt/allo' ]] && G_EXEC rm -R /opt/allo
|
|
[[ -f '/etc/sudoers.d/allo' ]] && G_EXEC rm /etc/sudoers.d/allo
|
|
# Database
|
|
Remove_Database allo
|
|
# Mark full version as uninstalled
|
|
aSOFTWARE_INSTALL_STATE[159]=0
|
|
fi
|
|
|
|
if To_Uninstall 88 # MariaDB
|
|
then
|
|
# Do a full database backup if binary is still available: https://github.com/MichaIng/DietPi/issues/3257#issuecomment-568764107
|
|
if command -v mysqldump > /dev/null
|
|
then
|
|
G_WHIP_MSG "Creating MariaDB database backup before uninstallation:\n\nIn case of accident, we create a database backup for you. You can remove it manually if you are sure that you don't need it any more.\n\n/mnt/dietpi_userdata/mariadb-database-backup.sql"
|
|
G_EXEC systemctl start mariadb
|
|
mysqldump --all-databases > /mnt/dietpi_userdata/mariadb-database-backup.sql
|
|
systemctl stop mariadb
|
|
fi
|
|
|
|
G_AGP mariadb-server 'php*-mysql'
|
|
G_EXEC rm -Rf /{mnt/dietpi_userdata,var/lib,var/log,etc}/mysql /{root,home/*}/.mysql_history
|
|
fi
|
|
|
|
if To_Uninstall 77 # Grafana
|
|
then
|
|
Remove_Service grafana-server grafana grafana
|
|
G_AGP grafana
|
|
[[ -f '/etc/apt/sources.list.d/grafana.list' ]] && G_EXEC rm /etc/apt/sources.list.d/grafana.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-grafana.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-grafana.gpg
|
|
G_EXEC rm -Rf /{mnt/dietpi_userdata,var/{lib,log},etc}/grafana
|
|
fi
|
|
|
|
if To_Uninstall 74 # InfluxDB
|
|
then
|
|
Remove_Service influxdb 1 1
|
|
G_AGP influxdb
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-influxdb.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-influxdb.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-influxdb.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-influxdb.gpg
|
|
G_EXEC rm -Rf /{mnt/dietpi_userdata,var/{lib,log},etc}/influxdb
|
|
fi
|
|
|
|
if To_Uninstall 80 # Ubooquity
|
|
then
|
|
Remove_Service ubooquity 1 1
|
|
[[ -d '/mnt/dietpi_userdata/ubooquity' ]] && G_EXEC rm -R /mnt/dietpi_userdata/ubooquity
|
|
fi
|
|
|
|
if To_Uninstall 179 # Komga
|
|
then
|
|
Remove_Service komga 1 1
|
|
[[ -d '/mnt/dietpi_userdata/komga' ]] && G_EXEC rm -R /mnt/dietpi_userdata/komga
|
|
fi
|
|
|
|
if To_Uninstall 86 # Roon Extension Manager
|
|
then
|
|
local installer='/mnt/dietpi_userdata/roon-extension-manager/rem-setup.sh' user='roon-extension-manager'
|
|
# Pre-v8.2
|
|
if [[ ! -f $installer ]]
|
|
then
|
|
G_EXEC curl -sSfL 'https://raw.githubusercontent.com/TheAppgineer/roon-extension-manager/v1.x/rem-setup.sh' -o rem-setup.sh
|
|
G_EXEC chmod +x rem-setup.sh
|
|
installer='./rem-setup.sh' user='root'
|
|
fi
|
|
SUDO_USER=$user G_EXEC_OUTPUT=1 G_EXEC "$installer" --uninstall
|
|
G_EXEC rm "$installer"
|
|
getent passwd roon-extension-manager > /dev/null && G_EXEC userdel roon-extension-manager
|
|
getent group roon-extension-manager > /dev/null && G_EXEC groupdel roon-extension-manager
|
|
[[ -d '/mnt/dietpi_userdata/roon-extension-manager' ]] && G_EXEC rm -R /mnt/dietpi_userdata/roon-extension-manager
|
|
fi
|
|
|
|
if To_Uninstall 178 # Jellyfin
|
|
then
|
|
G_AGP jellyfin 'jellyfin-*'
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-jellyfin.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-jellyfin.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-jellyfin.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-jellyfin.gpg
|
|
[[ -d '/etc/systemd/system/jellyfin.service.d' ]] && G_EXEC rm -R /etc/systemd/system/jellyfin.service.d
|
|
[[ -d '/mnt/dietpi_userdata/jellyfin' ]] && G_EXEC rm -R /mnt/dietpi_userdata/jellyfin
|
|
fi
|
|
|
|
if To_Uninstall 3 # Midnight Commander
|
|
then
|
|
G_AGP mc
|
|
fi
|
|
|
|
if To_Uninstall 0 # OpenSSH Client
|
|
then
|
|
# The OpenSSH server depends on the OpenSSH client, hence only mark it for autoremoval only.
|
|
dpkg-query -s 'openssh-client' &> /dev/null && G_EXEC apt-mark auto openssh-client
|
|
fi
|
|
|
|
if To_Uninstall 1 # Samba Client
|
|
then
|
|
# Unmount default mount point
|
|
findmnt /mnt/samba > /dev/null && G_EXEC umount -Rfl /mnt/samba
|
|
|
|
# Remove from fstab
|
|
G_EXEC sed --follow-symlinks -i '\|/mnt/samba|d' /etc/fstab
|
|
|
|
G_AGP cifs-utils smbclient
|
|
|
|
[[ -d '/mnt/samba' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /mnt/samba
|
|
fi
|
|
|
|
if To_Uninstall 110 # NFS Client
|
|
then
|
|
# Unmount default mount point
|
|
findmnt /mnt/nfs_client > /dev/null && G_EXEC umount -Rfl /mnt/nfs_client
|
|
|
|
# Remove from fstab
|
|
G_EXEC sed --follow-symlinks -i '\|/mnt/nfs_client|d' /etc/fstab
|
|
|
|
# nfs-kernel-server depends on nfs-common
|
|
dpkg-query -s 'nfs-common' &> /dev/null && G_EXEC apt-mark auto nfs-common
|
|
|
|
[[ -d '/mnt/nfs_client' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /mnt/nfs_client
|
|
fi
|
|
|
|
if To_Uninstall 111 # UrBackup Server
|
|
then
|
|
# Pre-v6.29: ARMv8 source build and the package attempts to remove the non-existent "/etc/init.d/urbackup_srv" ...
|
|
Remove_Service urbackupsrv urbackup urbackup
|
|
|
|
if [[ -f '/var/urbackup/backup_server_settings.db' ]] && command -v sqlite3 > /dev/null
|
|
then
|
|
local backuppath=$(sqlite3 /var/urbackup/backup_server_settings.db 'select value from settings where key = "backupfolder"')
|
|
else
|
|
local backuppath=$(sed -n '/^[[:blank:]]*SOFTWARE_URBACKUP_BACKUPPATH=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
fi
|
|
G_AGP urbackup-server
|
|
G_EXEC rm -Rf /var/log/urbackup.log "${backuppath:-/mnt/dietpi_userdata/urbackup}"
|
|
unset -v backuppath
|
|
|
|
G_EXEC rm -f /etc/apt/sources.list.d/dietpi-urbackup.sources
|
|
G_EXEC rm -f /etc/apt/keyrings/dietpi-urbackup.asc
|
|
|
|
# Pre-v6.29: ARMv8 source build
|
|
command -v urbackupsrv > /dev/null && G_EXEC rm "$(command -v urbackupsrv)"
|
|
command -v urbackup_mount_helper > /dev/null && G_EXEC rm "$(command -v urbackup_mount_helper)"
|
|
command -v urbackup_snapshot_helper > /dev/null && G_EXEC rm "$(command -v urbackup_snapshot_helper)"
|
|
[[ -d '/usr/share/urbackup' ]] && G_EXEC rm -R /usr/share/urbackup
|
|
[[ -d '/usr/local/share/urbackup' ]] && G_EXEC rm -R /usr/local/share/urbackup
|
|
[[ -d '/var/urbackup' ]] && G_EXEC rm -R /var/urbackup
|
|
[[ -f '/etc/default/urbackupsrv' ]] && G_EXEC rm /etc/default/urbackupsrv
|
|
[[ -f '/etc/logrotate.d/urbackupsrv' ]] && G_EXEC rm /etc/logrotate.d/urbackupsrv
|
|
fi
|
|
|
|
if To_Uninstall 171 # frp
|
|
then
|
|
Remove_Service frpc
|
|
Remove_Service frps frp frp
|
|
|
|
# Binaries and configs
|
|
[[ -f '/usr/local/bin/frpc' ]] && G_EXEC rm /usr/local/bin/frpc
|
|
[[ -f '/usr/local/bin/frps' ]] && G_EXEC rm /usr/local/bin/frps
|
|
[[ -d '/etc/frp' ]] && G_EXEC rm -R /etc/frp
|
|
fi
|
|
|
|
if To_Uninstall 17 # Git
|
|
then
|
|
G_AGP git
|
|
fi
|
|
|
|
if To_Uninstall 4 # fish
|
|
then
|
|
getent passwd | while read -r line
|
|
do
|
|
[[ $line == *':/usr/bin/fish' ]] || continue
|
|
local user=${line%%:*}
|
|
G_EXEC chsh "$user" -s /bin/bash
|
|
done
|
|
G_AGP fish
|
|
[[ -d '/etc/fish/conf.d' ]] && G_EXEC rm -R /etc/fish/conf.d
|
|
fi
|
|
|
|
if To_Uninstall 5 # ALSA
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware soundcard none
|
|
G_AGP alsa-utils libasound2-plugin-equal firmware-intel-sound
|
|
[[ -d '/etc/systemd/system/alsa-state.service.d' ]] && G_EXEC rm -R /etc/systemd/system/alsa-state.service.d
|
|
fi
|
|
|
|
if To_Uninstall 6 # X11
|
|
then
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections 'x11-*' dbus-x11 dbus-user-session 'libegl1*' 'libgles2*' libgl1-mesa-dri 'mesa-*' libdrm-rockchip1 libmali-rk-utgard-450-r7p0 'xf86-video-*' malit628-odroid mali450-odroid aml-libs-odroid 'libump*' firmware-samsung 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
G_AGP 'xorg*' 'xserver-xorg*' xinit xcompmgr xterm xfonts-base
|
|
G_EXEC rm -f /etc/xdg/autostart/xcompmgr.desktop /etc/X11/xorg.conf /etc/X11/xorg.conf.d/98-dietpi-disable_dpms.conf
|
|
fi
|
|
|
|
if To_Uninstall 7 # FFmpeg
|
|
then
|
|
G_AGP ffmpeg
|
|
fi
|
|
|
|
if To_Uninstall 8 # Java JDK
|
|
then
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections 'temurin-*-jdk' 'default-jdk*' 'openjdk-*-jdk*' 'openjdk-*-doc' 'openjdk-*-demo' 'openjdk-*-source' 'openjdk-*-testsupport' 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
fi
|
|
|
|
if To_Uninstall 196 # Java JRE
|
|
then
|
|
G_EXEC rm -f /etc/apt/sources.list.d/dietpi-adoptium.sources
|
|
G_EXEC rm -f /etc/apt/keyrings/dietpi-adoptium.asc
|
|
# shellcheck disable=SC2046
|
|
apt-mark auto $(dpkg --get-selections 'temurin-*-jre' 'default-jre*' 'openjdk-*-jre*' 'openjdk-*-dbg' ca-certificates-java 2> /dev/null | mawk '{print $1}') 2> /dev/null
|
|
fi
|
|
|
|
if To_Uninstall 104 # Dropbear
|
|
then
|
|
G_AGP 'dropbear*'
|
|
fi
|
|
|
|
if To_Uninstall 105 # OpenSSH Server
|
|
then
|
|
G_AGP openssh-{,sftp-}server
|
|
fi
|
|
|
|
if To_Uninstall 181 # PaperMC
|
|
then
|
|
Remove_Service papermc 1 1
|
|
# Files
|
|
[[ -d '/opt/papermc' ]] && G_EXEC rm -R /opt/papermc
|
|
[[ -d '/var/log/papermc' ]] && G_EXEC rm -R /var/log/papermc
|
|
[[ -d '/mnt/dietpi_userdata/papermc' ]] && G_EXEC rm -R /mnt/dietpi_userdata/papermc
|
|
[[ -f '/usr/local/bin/mcrcon' ]] && G_EXEC rm /usr/local/bin/mcrcon
|
|
fi
|
|
|
|
if To_Uninstall 101 # Logrotate
|
|
then
|
|
G_AGP logrotate
|
|
fi
|
|
|
|
if To_Uninstall 102 # Rsyslog
|
|
then
|
|
dpkg-query -s 'rsyslog' &> /dev/null && G_EXEC apt-mark auto rsyslog # https://github.com/MichaIng/DietPi/issues/2454
|
|
|
|
# Update logging choice index
|
|
if [[ $INDEX_LOGGING == -3 ]]
|
|
then
|
|
grep -q '[[:blank:]]/var/log[[:blank:]]' /etc/fstab || findmnt -t tmpfs -M /var/log > /dev/null && INDEX_LOGGING=-1 || INDEX_LOGGING=0
|
|
fi
|
|
fi
|
|
|
|
if To_Uninstall 103 # DietPi-RAMlog
|
|
then
|
|
G_EXEC sed --follow-symlinks -i '/[[:blank:]]\/var\/log[[:blank:]]/d' /etc/fstab
|
|
|
|
G_EXEC mkdir -p /var/lib/dietpi/dietpi-ramlog
|
|
cat << '_EOF_' > /var/lib/dietpi/dietpi-ramlog/disable.sh
|
|
#!/bin/dash
|
|
{
|
|
systemctl --no-reload disable dietpi-ramlog
|
|
systemctl stop dietpi-ramlog
|
|
rm -R /var/tmp/dietpi/logs/dietpi-ramlog_store
|
|
if systemctl -q is-enabled rsyslog
|
|
then
|
|
sed --follow-symlinks -i '/^[[:blank:]]*INDEX_LOGGING=/c\INDEX_LOGGING=-3' /boot/dietpi/.installed
|
|
else
|
|
sed --follow-symlinks -i '/^[[:blank:]]*INDEX_LOGGING=/c\INDEX_LOGGING=0' /boot/dietpi/.installed
|
|
fi
|
|
systemctl --no-reload disable dietpi-ramlog_disable
|
|
rm /etc/systemd/system/dietpi-ramlog_disable.service
|
|
rm /var/lib/dietpi/dietpi-ramlog/disable.sh
|
|
}
|
|
_EOF_
|
|
G_EXEC chmod +x /var/lib/dietpi/dietpi-ramlog/disable.sh
|
|
|
|
cat << '_EOF_' > /etc/systemd/system/dietpi-ramlog_disable.service
|
|
[Unit]
|
|
Description=DietPi-RAMlog_disable
|
|
After=dietpi-ramlog.service
|
|
Before=dietpi-preboot.service rsyslog.service syslog.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
StandardOutput=tty
|
|
ExecStart=/bin/dash -c '/var/lib/dietpi/dietpi-ramlog/disable.sh > /var/tmp/dietpi/logs/dietpi-ramlog_disable_debug.log 2>&1'
|
|
|
|
[Install]
|
|
WantedBy=local-fs.target
|
|
_EOF_
|
|
G_EXEC systemctl daemon-reload
|
|
G_EXEC systemctl --no-reload enable dietpi-ramlog_disable
|
|
fi
|
|
|
|
if To_Uninstall 9 # Node.js
|
|
then
|
|
command -v npm > /dev/null && npm r -g n yarn npm
|
|
|
|
# Old install via repo
|
|
G_AGP nodejs
|
|
[[ -f '/etc/apt/sources.list.d/nodesource_nodejs.list' ]] && G_EXEC rm /etc/apt/sources.list.d/nodesource_nodejs.list
|
|
|
|
[[ -f '/usr/local/bin/node' ]] && G_EXEC rm /usr/local/bin/node
|
|
[[ -d '/usr/local/n' ]] && G_EXEC rm -R /usr/local/n
|
|
[[ -d '/usr/local/yarn' ]] && G_EXEC rm -R /usr/local/yarn
|
|
[[ -d '/usr/local/include/node' ]] && G_EXEC rm -R /usr/local/include/node
|
|
[[ -d '/usr/local/lib/node_modules' ]] && G_EXEC rm -R /usr/local/lib/node_modules
|
|
[[ -d '/usr/local/share/doc/node' ]] && G_EXEC rm -R /usr/local/share/doc/node
|
|
[[ -f '/usr/local/man/man1/node.1' ]] && G_EXEC rm /usr/local/man/man1/node.1
|
|
[[ -f '/usr/local/share/man/man1/node.1' ]] && G_EXEC rm /usr/local/share/man/man1/node.1
|
|
[[ -f '/usr/local/README.md' ]] && G_EXEC rm /usr/local/README.md
|
|
[[ -f '/usr/local/CHANGELOG.md' ]] && G_EXEC rm /usr/local/CHANGELOG.md
|
|
[[ -f '/usr/local/LICENSE' ]] && G_EXEC rm /usr/local/LICENSE
|
|
[[ -f '/usr/local/share/systemtap/tapset/node.stp' ]] && G_EXEC rm /usr/local/share/systemtap/tapset/node.stp
|
|
[[ -d '/root/.npm' ]] && G_EXEC rm -R /root/.npm
|
|
[[ -f '/root/.config/configstore/update-notifier-npm.json' ]] && G_EXEC rm /root/.config/configstore/update-notifier-npm.json
|
|
fi
|
|
|
|
if To_Uninstall 170 # UnRAR
|
|
then
|
|
G_AGP unrar
|
|
fi
|
|
|
|
if To_Uninstall 130 # Python 3
|
|
then
|
|
command -v pip3 > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pip3 uninstall -y pip setuptools wheel
|
|
G_AGP python3-dev python3-pip # python3-pip: Pre-v6.32
|
|
[[ -f '/etc/pip.conf' ]] && G_EXEC rm /etc/pip.conf
|
|
G_EXEC rm -Rf /{root,home/*}/.cache/pip
|
|
fi
|
|
|
|
if To_Uninstall 188 # Go
|
|
then
|
|
G_AGP golang-go
|
|
[[ -f '/etc/bashrc.d/go.sh' ]] && G_EXEC rm /etc/bashrc.d/go.sh
|
|
[[ -d '/usr/local/go' ]] && G_EXEC rm -R /usr/local/go
|
|
fi
|
|
|
|
if To_Uninstall 191 # Snapcast Server
|
|
then
|
|
G_AGP snapserver
|
|
# Remove users from Debian's and snapcast's packages, to cleanly cover upgrades from one to the other.
|
|
getent passwd snapserver > /dev/null && G_EXEC userdel snapserver
|
|
getent passwd _snapserver > /dev/null && G_EXEC userdel _snapserver
|
|
fi
|
|
|
|
if To_Uninstall 192 # Snapcast Client
|
|
then
|
|
G_AGP snapclient
|
|
fi
|
|
|
|
if To_Uninstall 194 # PostgreSQL
|
|
then
|
|
G_AGP postgresql 'postgresql-*'
|
|
G_EXEC rm -Rf /etc/postgresql*
|
|
[[ -d '/mnt/dietpi_userdata/postgresql' ]] && G_EXEC rm -R /mnt/dietpi_userdata/postgresql
|
|
fi
|
|
|
|
if To_Uninstall 87 # SQLite
|
|
then
|
|
G_AGP sqlite3 'php*-sqlite3'
|
|
fi
|
|
|
|
if To_Uninstall 202 # Rclone
|
|
then
|
|
G_AGP rclone
|
|
G_EXEC rm -Rf /{root,home/*}/.config/rclone
|
|
fi
|
|
|
|
if To_Uninstall 209 # Restic
|
|
then
|
|
[[ -f '/usr/local/bin/restic' ]] && G_EXEC rm /usr/local/bin/restic
|
|
fi
|
|
|
|
if To_Uninstall 210 # MediaWiki
|
|
then
|
|
[[ -d '/var/www/wiki' ]] && G_EXEC rm -R /var/www/wiki
|
|
Remove_Database mediawiki
|
|
fi
|
|
|
|
if To_Uninstall 211 # Homebridge
|
|
then
|
|
Remove_Service homebridge 1 1
|
|
G_AGP homebridge
|
|
|
|
[[ -f '/etc/apt/sources.list.d/dietpi-homebridge.list' ]] && G_EXEC rm /etc/apt/sources.list.d/dietpi-homebridge.list
|
|
[[ -f '/etc/apt/trusted.gpg.d/dietpi-homebridge.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-homebridge.gpg
|
|
fi
|
|
|
|
if To_Uninstall 198 # File Browser
|
|
then
|
|
Remove_Service filebrowser 1
|
|
[[ -d '/opt/filebrowser' ]] && G_EXEC rm -R /opt/filebrowser
|
|
[[ -d '/mnt/dietpi_userdata/filebrowser' ]] && G_EXEC rm -R /mnt/dietpi_userdata/filebrowser
|
|
fi
|
|
|
|
if To_Uninstall 199 # Spotifyd
|
|
then
|
|
Remove_Service spotifyd 1 1
|
|
[[ -d '/opt/spotifyd' ]] && G_EXEC rm -R /opt/spotifyd
|
|
[[ -d '/mnt/dietpi_userdata/spotifyd' ]] && G_EXEC rm -R /mnt/dietpi_userdata/spotifyd
|
|
fi
|
|
|
|
if To_Uninstall 213 # soju
|
|
then
|
|
Remove_Service soju 1 1
|
|
local x
|
|
local commands=('soju' 'sojuctl' 'sojudb')
|
|
local manpages=('soju.1' 'sojuctl.1')
|
|
for x in "${commands[@]}"
|
|
do
|
|
[[ -f /usr/local/bin/$x ]] && G_EXEC rm "/usr/local/bin/$x"
|
|
done
|
|
for x in "${manpages[@]}"
|
|
do
|
|
[[ -f /usr/local/share/man/man1/$x ]] && G_EXEC rm "/usr/local/share/man/man1/$x"
|
|
done
|
|
[[ -d '/usr/local/share/man/man1' ]] && G_EXEC rmdir -p --ignore-fail-on-non-empty /usr/local/share/man/man1
|
|
[[ -d '/mnt/dietpi_userdata/soju' ]] && G_EXEC rm -Rf /mnt/dietpi_userdata/soju
|
|
fi
|
|
|
|
if To_Uninstall 169 # LazyLibrarian
|
|
then
|
|
Remove_Service lazylibrarian 1 1
|
|
G_EXEC rm -Rf /opt/lazylibrarian
|
|
G_EXEC rm -Rf /var/log/lazylibrarian
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/lazylibrarian
|
|
fi
|
|
|
|
if To_Uninstall 12 # RustDesk Server
|
|
then
|
|
Remove_Service rustdeskrelay
|
|
Remove_Service rustdesksignal rustdesk rustdesk
|
|
G_EXEC rm -Rf /opt/rustdesk
|
|
G_EXEC rm -Rf /mnt/dietpi_userdata/rustdesk
|
|
fi
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Finalising uninstall'
|
|
|
|
# Uninstall finished, set all uninstalled software to state 0 (not installed)
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) && aSOFTWARE_INSTALL_STATE[$i]=0
|
|
done
|
|
|
|
G_AGA
|
|
G_EXEC systemctl daemon-reload
|
|
|
|
#----------------------------------------------------------------------
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Uninstall completed'
|
|
#----------------------------------------------------------------------
|
|
}
|
|
|
|
Run_Installations()
|
|
{
|
|
G_NOTIFY_3_MODE='Step'
|
|
#------------------------------------------------------------
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Checking for conflicts and missing inputs'
|
|
|
|
# Unmark software which requires user input during automated installs
|
|
Unmark_Unattended
|
|
|
|
# Unmark conflicting software if not done after interactive software selection already
|
|
(( $CONFLICTS_RESOLVED )) || Unmark_Conflicts
|
|
|
|
# Abort install if no selections are left and not first run setup
|
|
if (( $G_DIETPI_INSTALL_STAGE == 2 ))
|
|
then
|
|
local abort=1
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) || continue
|
|
abort=0
|
|
break
|
|
done
|
|
(( $abort )) && { G_DIETPI-NOTIFY 1 'No software installs are done. Aborting...'; exit 1; }
|
|
fi
|
|
#------------------------------------------------------------
|
|
# Disable powersaving on main screen during installation
|
|
command -v setterm > /dev/null && setterm -blank 0 -powersave off 2> /dev/null
|
|
|
|
# Mark dependencies for install
|
|
Mark_Dependencies
|
|
|
|
# Check network connectivity, DNS resolving and network time sync: https://github.com/MichaIng/DietPi/issues/786
|
|
# - Skip on first run installs where it is done in DietPi-Automation_Pre() already
|
|
(( $G_DIETPI_INSTALL_STAGE == 2 )) || Check_Net_and_Time_sync
|
|
|
|
# Pre-create directories which are required for many software installs
|
|
Create_Required_Dirs
|
|
|
|
# Read global software password
|
|
Update_Global_Pw
|
|
|
|
# Stop all services
|
|
# shellcheck disable=SC2154
|
|
[[ $G_SERVICE_CONTROL == 0 ]] || /boot/dietpi/dietpi-services stop
|
|
|
|
# Update package cache: Skip when flag was set by first run setup
|
|
(( $SKIP_APT_UPDATE )) || G_AGUP
|
|
|
|
# Install software
|
|
Install_Software
|
|
|
|
# Uninstall software if required by e.g. DietPi choice system
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) || continue
|
|
Uninstall_Software
|
|
break
|
|
done
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Finalising install'
|
|
|
|
# Enable installed services
|
|
if [[ ${aENABLE_SERVICES[0]}${aSTART_SERVICES[0]} ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Enabling installed services'
|
|
for i in "${aENABLE_SERVICES[@]}" "${aSTART_SERVICES[@]}"
|
|
do
|
|
G_EXEC_NOHALT=1 G_EXEC systemctl --no-reload enable "$i"
|
|
done
|
|
fi
|
|
|
|
# Reload systemd units
|
|
G_EXEC systemctl daemon-reload
|
|
|
|
# Unmask systemd-logind if Kodi or Chromium were installed, it's set in dietpi.txt or libpam-systemd was installed
|
|
if [[ $(readlink /etc/systemd/system/systemd-logind.service) == '/dev/null' ]] &&
|
|
{ (( ${aSOFTWARE_INSTALL_STATE[31]} == 1 || ${aSOFTWARE_INSTALL_STATE[113]} == 1 )) || grep -q '^[[:blank:]]*AUTO_UNMASK_LOGIND=1' /boot/dietpi.txt || dpkg-query -s 'libpam-systemd' &> /dev/null; }
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Enabling systemd-logind'
|
|
# dbus is required for systemd-logind to start
|
|
dpkg-query -s dbus &> /dev/null || G_AGI dbus
|
|
G_EXEC systemctl unmask dbus
|
|
G_EXEC systemctl start dbus
|
|
G_EXEC systemctl unmask systemd-logind
|
|
G_EXEC systemctl start systemd-logind
|
|
fi
|
|
|
|
# Sync DietPi-RAMlog to disk: https://github.com/MichaIng/DietPi/issues/4884
|
|
systemctl -q is-enabled dietpi-ramlog && /boot/dietpi/func/dietpi-ramlog 1
|
|
|
|
# Apply GPU Memory Splits
|
|
Install_Apply_GPU_Settings
|
|
|
|
# Offer to change DietPi-AutoStart option
|
|
if (( $G_DIETPI_INSTALL_STAGE == 2 )) && ((
|
|
${aSOFTWARE_INSTALL_STATE[23]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[24]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[25]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[26]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[31]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[51]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[108]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[112]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[113]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[119]} == 1 ||
|
|
${aSOFTWARE_INSTALL_STATE[173]} == 1 ))
|
|
then
|
|
G_WHIP_YESNO 'Would you like to configure the DietPi-AutoStart option?
|
|
\nThis will allow you to choose which program loads automatically, after the system has booted up, e.g.:
|
|
- Console\n - Desktop\n - Kodi' && /boot/dietpi/dietpi-autostart
|
|
fi
|
|
|
|
# Final user info
|
|
# - Home Assistant: https://dietpi.com/forum/t/home-assistant-finally-integrates-python-3-11/17033/40
|
|
if (( ${aSOFTWARE_INSTALL_STATE[157]} == 1 ))
|
|
then
|
|
G_WHIP_MSG '[ INFO ] Home Assistant may require a manual restart
|
|
\nOn first service start, Home Assistant installs and in case compiles a bunch of required Python module. This can take another while.
|
|
\nThe compilation of those modules can fail on first attempt for unknown reasons, but succeeds after restarting the service:
|
|
- sudo systemctl restart home-assistant
|
|
\nAlso check our documentation about this matter:
|
|
- https://dietpi.com/docs/software/home_automation/#home-assistant'
|
|
fi
|
|
|
|
# Install finished, set all installed software to state 2 (installed)
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && aSOFTWARE_INSTALL_STATE[$i]=2
|
|
done
|
|
|
|
# Write to .installed state file
|
|
Write_InstallFileList
|
|
}
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# First Run / Automation function
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Setup steps prior to software installs
|
|
DietPi-Automation_Pre()
|
|
{
|
|
G_NOTIFY_3_MODE='Step'
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Applying initial first run setup steps'
|
|
|
|
# Get settings
|
|
AUTOINSTALL_ENABLED=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_AUTOMATED=1' /boot/dietpi.txt)
|
|
AUTOINSTALL_AUTOSTARTTARGET=$(sed -n '/^[[:blank:]]*AUTO_SETUP_AUTOSTART_TARGET_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local AUTOINSTALL_SSHINDEX=$(sed -n '/^[[:blank:]]*AUTO_SETUP_SSH_SERVER_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local AUTOINSTALL_LOGGINGINDEX=$(sed -n '/^[[:blank:]]*AUTO_SETUP_LOGGING_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
AUTOINSTALL_CUSTOMSCRIPTURL=$(sed -n '/^[[:blank:]]*AUTO_SETUP_CUSTOM_SCRIPT_EXEC=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local AUTOINSTALL_RESTORE=$(sed -n '/^[[:blank:]]*AUTO_SETUP_BACKUP_RESTORE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
local AUTOINSTALL_RAMLOG_SIZE=$(sed -n '/^[[:blank:]]*AUTO_SETUP_RAMLOG_MAXSIZE=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
AUTO_SETUP_DHCP_TO_STATIC=$(grep -cm1 '^[[:blank:]]*AUTO_SETUP_DHCP_TO_STATIC=1' /boot/dietpi.txt)
|
|
|
|
# Else set defaults
|
|
[[ $AUTOINSTALL_AUTOSTARTTARGET ]] || AUTOINSTALL_AUTOSTARTTARGET=0
|
|
[[ $AUTOINSTALL_SSHINDEX ]] || AUTOINSTALL_SSHINDEX=-1
|
|
[[ $AUTOINSTALL_LOGGINGINDEX ]] || AUTOINSTALL_LOGGINGINDEX=-1
|
|
[[ $AUTOINSTALL_CUSTOMSCRIPTURL ]] || AUTOINSTALL_CUSTOMSCRIPTURL=0
|
|
[[ $AUTOINSTALL_RESTORE ]] || AUTOINSTALL_RESTORE=0
|
|
[[ $AUTOINSTALL_RAMLOG_SIZE ]] || AUTOINSTALL_RAMLOG_SIZE=50
|
|
|
|
# Restore DietPi-Backup
|
|
if (( $AUTOINSTALL_RESTORE )); then
|
|
|
|
# Reboot only when backup restore succeeded
|
|
restore_succeeded=0
|
|
|
|
G_DIETPI-NOTIFY 2 'DietPi-Backup restore selected, scanning and mounting attached drives...'
|
|
i=0
|
|
while read -r line
|
|
do
|
|
# Mount drives to temporary mount points
|
|
mkdir -p "/mnt/dietpi-backup$i" && mount "$line" "/mnt/dietpi-backup$i"
|
|
((i++))
|
|
|
|
done < <(lsblk -rnpo NAME,UUID,MOUNTPOINT | mawk '$2 && ! $3 {print $1}')
|
|
|
|
G_DIETPI-NOTIFY 2 'Searching all drives for DietPi-Backup instances...'
|
|
mapfile -t alist < <(find /mnt -type f -name '.dietpi-backup_stats')
|
|
|
|
# Interactive restore
|
|
if [[ $AUTOINSTALL_RESTORE == 1 ]]; then
|
|
|
|
# Do we have any results?
|
|
if [[ ${alist[0]} ]]
|
|
then
|
|
# Create List for Whiptail
|
|
G_WHIP_MENU_ARRAY=()
|
|
for i in "${alist[@]}"
|
|
do
|
|
last_backup_date=$(sed -n '/ompleted/s/^.*: //p' "$i" | tail -1) # Date of last backup for this backup
|
|
backup_directory=${i%/.dietpi-backup_stats} # Backup directory (minus the backup file), that we can use for target backup directory.
|
|
G_WHIP_MENU_ARRAY+=("$backup_directory" ": $last_backup_date")
|
|
done
|
|
|
|
export G_DIETPI_SERVICES_DISABLE=1
|
|
G_WHIP_MENU 'Please select a previous backup to restore:' && /boot/dietpi/dietpi-backup -1 "$G_WHIP_RETURNED_VALUE" && restore_succeeded=1
|
|
unset -v G_DIETPI_SERVICES_DISABLE
|
|
else
|
|
G_WHIP_MSG 'No previous backups were found in /mnt/*. Install will continue like normal.'
|
|
fi
|
|
|
|
# Non-interactive restore
|
|
elif [[ $AUTOINSTALL_RESTORE == 2 ]]; then
|
|
|
|
# Do we have any results?
|
|
if [[ ${alist[0]} ]]
|
|
then
|
|
# Restore first found backup
|
|
export G_DIETPI_SERVICES_DISABLE=1
|
|
/boot/dietpi/dietpi-backup -1 "${alist[0]%/.dietpi-backup_stats}" && restore_succeeded=1
|
|
unset -v G_DIETPI_SERVICES_DISABLE
|
|
else
|
|
G_DIETPI-NOTIFY 1 'DietPi-Backup auto-restore was selected but no backup has been found in /mnt/*. Install will continue like normal.'
|
|
fi
|
|
|
|
# Downgrade dietpi.txt option
|
|
G_CONFIG_INJECT 'AUTO_SETUP_BACKUP_RESTORE=' 'AUTO_SETUP_BACKUP_RESTORE=1' /boot/dietpi.txt
|
|
|
|
fi
|
|
|
|
# Remove mounted drives and mount points
|
|
findmnt /mnt/dietpi-backup[0-9]* > /dev/null && umount /mnt/dietpi-backup[0-9]*
|
|
[[ -d '/mnt/dietpi-backup0' ]] && rmdir /mnt/dietpi-backup[0-9]*
|
|
|
|
# Reboot on successful restore
|
|
if (( $restore_succeeded ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'The system will now reboot into the restored system'
|
|
sync # Failsafe
|
|
G_SLEEP 3
|
|
reboot
|
|
exit 0
|
|
fi
|
|
|
|
fi
|
|
|
|
# Check network connectivity, DNS resolving and network time sync: https://github.com/MichaIng/DietPi/issues/786
|
|
Check_Net_and_Time_sync
|
|
|
|
# Full package upgrade on first run installs: https://github.com/MichaIng/DietPi/issues/3098
|
|
if [[ ! -f '/boot/dietpi/.skip_distro_upgrade' ]]
|
|
then
|
|
G_AGUP
|
|
G_AGDUG
|
|
G_AGA
|
|
# Create a persistent flag to not repeat G_AGDUG and rule out a reboot loop when kernel modules remain missing
|
|
G_EXEC eval '> /boot/dietpi/.skip_distro_upgrade'
|
|
# Perform a reboot if required as of missing kernel modules
|
|
G_CHECK_KERNEL || { G_DIETPI-NOTIFY 2 'A reboot is done to finalise the kernel upgrade'; sync; reboot; exit 0; }
|
|
# Do not repeat APT update in Run_Installations()
|
|
SKIP_APT_UPDATE=1
|
|
fi
|
|
|
|
# Change password if default has not been changed via dietpi.txt
|
|
# - Non-automated interactive first run setup: Show password prompts
|
|
if (( ! $AUTOINSTALL_ENABLED && $G_INTERACTIVE ))
|
|
then
|
|
# Local console: Prompt to select keyboard layout first if default is still set: https://github.com/MichaIng/DietPi/issues/5925
|
|
[[ $(tty) == '/dev/tty1' ]] && grep -q '^XKBLAYOUT="gb"' /etc/default/keyboard && /boot/dietpi/func/dietpi-set_hardware keyboard
|
|
/boot/dietpi/func/dietpi-set_software password users check
|
|
Update_Global_Pw
|
|
|
|
# - Automated or non-interactive first run setup
|
|
else
|
|
# Update_Global_Pw is always executed right before installs start and in case forces users to change the default on any next interactive execution.
|
|
# Set flag for dietpi-login to check user passwords to in case enforce a change on next interactive login.
|
|
G_EXEC touch /var/lib/dietpi/.check_user_passwords
|
|
fi
|
|
|
|
# Disable serial console?
|
|
if (( $G_HW_MODEL != 75 )) && ! grep -q '^[[:blank:]]*CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt &&
|
|
[[ ! $(tty) =~ ^/dev/(serial|tty(S|AMA|SAC|AML|SC|GS|FIQ|MV)|hvc)[0-9] ]] &&
|
|
G_WHIP_BUTTON_OK_TEXT='Yes' G_WHIP_BUTTON_CANCEL_TEXT='No' G_WHIP_YESNO 'A serial/UART console is currently enabled, would you like to disable it?
|
|
\nTL;DR: If you do not know what a UART device or a serial console is, it is safe to select "Yes", which frees some MiB memory by stopping the related process(es).
|
|
\nA serial console is a way to interact with a system without any screen or network (SSH) required, but from another system physically connected. It is accessed with a UART adapter cable (often UART-to-USB), connected to a special UART port or GPIO pins. It can then be accessed via COM port from the attached system with a serial console client, e.g. PuTTY (which supports both, SSH and serial console access).
|
|
\nAnother benefit is that you can view early boot logs, before network or even screen output is up, which makes it a great way to debug issues with the bootloader or kernel. However, to allow as well common user logins via serial console, at least one additional login prompt process is running, which you may want to avoid when not using this feature at all.
|
|
\nSerial consoles can re-enabled at any time via dietpi-config > Advanced Options > Serial/UART'
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware serialconsole disable
|
|
fi
|
|
|
|
# RPi: Convert "serial0" to its actual symlink target without breaking the possibly currently used serial connection or starting a doubled console on the same serial device.
|
|
if (( $G_HW_MODEL < 10 )) && ! grep -q '^[[:blank:]]*CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt
|
|
then
|
|
if [[ -e '/dev/serial0' ]]
|
|
then
|
|
local tty=$(realpath /dev/serial0); tty=${tty#/dev/}
|
|
|
|
G_DIETPI-NOTIFY 2 "Converting serial console from symlink /dev/serial0 to native /dev/$tty"
|
|
if [[ $(</boot/cmdline.txt) == *'console=serial0'* ]]
|
|
then
|
|
if [[ $(</boot/cmdline.txt) == *"console=$tty"* ]]
|
|
then
|
|
G_EXEC sed --follow-symlinks -Ei 's/[[:blank:]]*console=serial0[^[:blank:]]*([[:blank:]]*$)?//' /boot/cmdline.txt
|
|
else
|
|
G_EXEC sed --follow-symlinks -i "s/console=serial0/console=$tty/" /boot/cmdline.txt
|
|
fi
|
|
fi
|
|
if systemctl -q is-enabled serial-getty@serial0
|
|
then
|
|
G_EXEC systemctl --no-reload disable serial-getty@serial0
|
|
G_EXEC systemctl --no-reload unmask "serial-getty@$tty"
|
|
G_EXEC systemctl --no-reload enable "serial-getty@$tty"
|
|
fi
|
|
unset -v tty
|
|
else
|
|
G_DIETPI-NOTIFY 2 'Disabling serial console on non-existing /dev/serial0 device node'
|
|
/boot/dietpi/func/dietpi-set_hardware serialconsole disable serial0
|
|
fi
|
|
fi
|
|
|
|
# Apply RAMlog size
|
|
sed --follow-symlinks -i "\|[[:blank:]]/var/log[[:blank:]]|c\tmpfs /var/log tmpfs size=${AUTOINSTALL_RAMLOG_SIZE}M,noatime,lazytime,nodev,nosuid" /etc/fstab
|
|
findmnt /var/log > /dev/null && G_EXEC mount -o remount /var/log
|
|
|
|
# Set time sync mode if no container system
|
|
(( $G_HW_MODEL == 75 )) || /boot/dietpi/func/dietpi-set_software ntpd-mode
|
|
|
|
# Apply choice and preference system settings
|
|
Apply_SSHServer_Choices "$AUTOINSTALL_SSHINDEX"
|
|
Apply_Logging_Choices "$AUTOINSTALL_LOGGINGINDEX"
|
|
|
|
G_DIETPI-NOTIFY 0 'Applied initial first run setup steps'
|
|
|
|
# Automated installs
|
|
(( $AUTOINSTALL_ENABLED )) || return 0
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Running automated install'
|
|
|
|
TARGETMENUID=-1 # Skip menu loop
|
|
GOSTARTINSTALL=1 # Set install start flag
|
|
|
|
# Find all software entries of AUTO_SETUP_INSTALL_SOFTWARE_ID= in dietpi.txt. Then set to state 1 for installation.
|
|
G_DIETPI-NOTIFY 2 'Checking AUTO_SETUP_INSTALL_SOFTWARE_ID entries'
|
|
# - Pre-v9.10: Support multiple AUTO_SETUP_INSTALL_SOFTWARE_ID lines
|
|
while read -ra software_ids
|
|
do
|
|
# v9.10: Support multiple IDs per AUTO_SETUP_INSTALL_SOFTWARE_ID line
|
|
for software_id in "${software_ids[@]}"
|
|
do
|
|
# Skip if software does not exist, is not supported on architecture, hardware model or Debian version
|
|
if [[ ! ${aSOFTWARE_NAME[$software_id]} ]]
|
|
then
|
|
G_DIETPI-NOTIFY 1 "Software title with ID $software_id does not exist. Skipping it."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]:=1} ))
|
|
then
|
|
G_DIETPI-NOTIFY 1 "Software title ${aSOFTWARE_NAME[$software_id]} is not supported on ${RPI_64KERNEL_32OS:-$G_HW_ARCH_NAME} systems. Skipping it."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]:=1} ))
|
|
then
|
|
G_DIETPI-NOTIFY 1 "Software title ${aSOFTWARE_NAME[$software_id]} is not supported on $G_HW_MODEL_NAME. Skipping it."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title ${aSOFTWARE_NAME[$software_id]} is not supported on Debian ${G_DISTRO_NAME^}. Skipping it."
|
|
else
|
|
aSOFTWARE_INSTALL_STATE[$software_id]=1
|
|
G_DIETPI-NOTIFY 0 "Software title ${aSOFTWARE_NAME[$software_id]} flagged for installation."
|
|
fi
|
|
done
|
|
done < <(grep '^[[:blank:]]*AUTO_SETUP_INSTALL_SOFTWARE_ID=' /boot/dietpi.txt | sed -e 's/^[^=]*=//' -e 's/#.*$//')
|
|
}
|
|
|
|
# Setup steps after software installs
|
|
DietPi-Automation_Post()
|
|
{
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Applying final first run setup steps'
|
|
|
|
# Remove fake-hwclock if real hwclock is available
|
|
# REMOVED: "hwclock" succeeds if an RTC connector is available but no battery attached (or empty), hence we cannot guarantee correct RTC time on boot by only testing "hwclock".
|
|
#hwclock &> /dev/null && G_AGP fake-hwclock
|
|
|
|
# x86_64 PC: Install microcode updates
|
|
if (( $G_HW_MODEL == 21 ))
|
|
then
|
|
grep -qi 'vendor_id.*intel' /proc/cpuinfo && G_AGI intel-microcode
|
|
grep -qi 'vendor_id.*amd' /proc/cpuinfo && G_AGI amd64-microcode
|
|
|
|
# VM: Enable QEMU guest agent if detected
|
|
elif (( $G_HW_MODEL == 20 ))
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware qga 1
|
|
|
|
# RPi 4/5 EEPROM update: https://github.com/MichaIng/DietPi/issues/3217
|
|
elif [[ $G_HW_MODEL == [45] ]]
|
|
then
|
|
/boot/dietpi/func/dietpi-set_hardware rpi-eeprom
|
|
fi
|
|
|
|
# Install GPU driver if set
|
|
local gpu_driver=$(sed -n '/^[[:blank:]]*CONFIG_GPU_DRIVER=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
[[ $gpu_driver && ${gpu_driver,,} != 'none' ]] && /boot/dietpi/func/dietpi-set_hardware gpudriver "$gpu_driver"
|
|
|
|
# Apply DHCP leased network settings as static network settings if requested
|
|
if (( $AUTO_SETUP_DHCP_TO_STATIC ))
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Applying DHCP leased network settings as static network settings'
|
|
|
|
# Function to convert CIDR notation into dot-decimal notation
|
|
cidr2mask()
|
|
{
|
|
local i mask full_octets=$(( $1 / 8 )) partial_octet=$(( $1%8 ))
|
|
for i in {0..3}
|
|
do
|
|
if (( $i < $full_octets ))
|
|
then
|
|
mask+='255'
|
|
|
|
elif (( $i == $full_octets ))
|
|
then
|
|
mask+=$(( 256 - 2 ** ( 8 - $partial_octet ) ))
|
|
else
|
|
mask+='0'
|
|
fi
|
|
(( $i < 3 )) && mask+=.
|
|
done
|
|
echo "$mask"
|
|
}
|
|
|
|
# Get Ethernet index
|
|
local nameservers eth_index=$(sed -En '/^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+eth[0-9]+$/{s/^.*eth//p;q}' /etc/network/interfaces)
|
|
# - Is enabled and uses DHCP
|
|
if [[ $eth_index ]] && grep -Eq "^[[:blank:]]*iface[[:blank:]]+eth${eth_index}[[:blank:]]+inet[[:blank:]]+dhcp$" /etc/network/interfaces
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Applying DHCP leased Ethernet settings as static Ethernet settings'
|
|
|
|
# Get current network info
|
|
local eth_ip=$(ip -br -f inet a s "eth$eth_index" | mawk '{print $3}' | sed 's|/.*$||')
|
|
local eth_mask=$(cidr2mask "$(ip -br -f inet a s "eth$eth_index" | mawk '{print $3}' | sed 's|^.*/||')")
|
|
local eth_gateway=$(ip r l dev "eth$eth_index" 0/0 | mawk '{print $3;exit}')
|
|
nameservers=$(mawk '/^[[:blank:]]*nameserver[[:blank:]]/{print $2}' ORS=' ' /etc/resolv.conf)
|
|
|
|
# Apply current network settings statically
|
|
G_CONFIG_INJECT "iface[[:blank:]]+eth$eth_index" "iface eth$eth_index inet static" /etc/network/interfaces
|
|
sed --follow-symlinks -i "0,\|^.*address[[:blank:]].*\$|s||address $eth_ip|" /etc/network/interfaces
|
|
sed --follow-symlinks -i "0,\|^.*netmask[[:blank:]].*\$|s||netmask $eth_mask|" /etc/network/interfaces
|
|
sed --follow-symlinks -i "0,\|^.*gateway[[:blank:]].*\$|s||gateway $eth_gateway|" /etc/network/interfaces
|
|
fi
|
|
|
|
# Get WiFi index
|
|
local wlan_index=$(sed -En '/^[[:blank:]]*(allow-hotplug|auto)[[:blank:]]+wlan[0-9]+$/{s/^.*wlan//p;q}' /etc/network/interfaces)
|
|
# - Is enabled and uses DHCP
|
|
if [[ $wlan_index ]] && grep -Eq "^[[:blank:]]*iface[[:blank:]]+wlan${wlan_index}[[:blank:]]+inet[[:blank:]]+dhcp$" /etc/network/interfaces
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Applying DHCP leased WiFi settings as static WiFi settings'
|
|
|
|
# Get current network info
|
|
local wlan_ip=$(ip -br -f inet a s "wlan$wlan_index" | mawk '{print $3}' | sed 's|/.*$||')
|
|
local wlan_mask=$(cidr2mask "$(ip -br -f inet a s "wlan$wlan_index" | mawk '{print $3}' | sed 's|^.*/||')")
|
|
local wlan_gateway=$(ip r l dev "wlan$wlan_index" 0/0 | mawk '{print $3;exit}')
|
|
[[ $nameservers ]] || nameservers=$(mawk '/^[[:blank:]]*nameserver[[:blank:]]/{print $2}' ORS=' ' /etc/resolv.conf)
|
|
|
|
# Apply current network settings statically
|
|
G_CONFIG_INJECT "iface[[:blank:]]+wlan$wlan_index" "iface wlan$wlan_index inet static" /etc/network/interfaces
|
|
sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*address[[:blank:]].*\$|address $wlan_ip|" /etc/network/interfaces
|
|
sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*netmask[[:blank:]].*\$|netmask $wlan_mask|" /etc/network/interfaces
|
|
sed --follow-symlinks -i "\|^iface wlan|,\$s|^.*gateway[[:blank:]].*\$|gateway $wlan_gateway|" /etc/network/interfaces
|
|
fi
|
|
unset -f cidr2mask
|
|
|
|
# Apply DNS nameservers
|
|
if [[ $nameservers ]]
|
|
then
|
|
G_DIETPI-NOTIFY 2 'Applying DHCP leased DNS nameservers as static nameservers'
|
|
|
|
if command -v resolvconf > /dev/null
|
|
then
|
|
sed --follow-symlinks -i "/dns-nameservers[[:blank:]]/c\dns-nameservers ${nameservers% }" /etc/network/interfaces
|
|
else
|
|
sed --follow-symlinks -i "/dns-nameservers[[:blank:]]/c\#dns-nameservers ${nameservers% }" /etc/network/interfaces
|
|
> /etc/resolv.conf
|
|
for i in $nameservers; do echo "nameserver $i" >> /etc/resolv.conf; done
|
|
fi
|
|
fi
|
|
|
|
G_DIETPI-NOTIFY 0 'Network changes will become effective with next reboot'
|
|
fi
|
|
|
|
# RPi: Disable onboard WiFi if WiFi modules didn't get enabled until now: https://github.com/MichaIng/DietPi/issues/5391
|
|
[[ $G_HW_MODEL -gt 9 || ! -f '/etc/modprobe.d/dietpi-disable_wifi.conf' ]] || /boot/dietpi/func/dietpi-set_hardware wifimodules onboard_disable
|
|
|
|
# Apply AutoStart choice
|
|
/boot/dietpi/dietpi-autostart "$AUTOINSTALL_AUTOSTARTTARGET"
|
|
|
|
# Disable console on TTY1 for purely headless SBCs, enabled for automated first run setup
|
|
[[ $G_HW_MODEL =~ ^(47|48|55|56|57|59|60|64|65|73)$ ]] && G_EXEC systemctl --no-reload disable getty@tty1
|
|
|
|
# Images are shipped with cron disabled, hence enable it now after first run setup has finished
|
|
G_EXEC systemctl enable cron
|
|
|
|
# Set install stage to finished
|
|
G_DIETPI_INSTALL_STAGE=2
|
|
G_EXEC eval 'echo 2 > /boot/dietpi/.install_stage'
|
|
|
|
# Remove now obsolete flag
|
|
[[ -f '/boot/dietpi/.skip_distro_upgrade' ]] && G_EXEC rm /boot/dietpi/.skip_distro_upgrade
|
|
|
|
G_DIETPI-NOTIFY 0 'Applied final first run setup steps'
|
|
|
|
# Process automatic APT package installs
|
|
local packages=() package
|
|
read -ra packages < <(sed -n '/^[[:blank:]]*AUTO_SETUP_APT_INSTALLS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt)
|
|
for package in "${packages[@]}"
|
|
do
|
|
G_EXEC_NOHALT=1 G_AGI "$package"
|
|
done
|
|
|
|
# Custom 1st run script
|
|
[[ $AUTOINSTALL_CUSTOMSCRIPTURL != '0' || -f '/boot/Automation_Custom_Script.sh' ]] || return 0
|
|
|
|
# Download online script
|
|
[[ -f '/boot/Automation_Custom_Script.sh' ]] || G_EXEC_NOEXIT=1 G_EXEC curl -sSfL "$AUTOINSTALL_CUSTOMSCRIPTURL" -o /boot/Automation_Custom_Script.sh || return $?
|
|
|
|
G_DIETPI-NOTIFY 2 'Running custom script, please wait...'
|
|
|
|
[[ -x '/boot/Automation_Custom_Script.sh' ]] || G_EXEC_NOEXIT=1 G_EXEC chmod +x /boot/Automation_Custom_Script.sh
|
|
/boot/Automation_Custom_Script.sh 2>&1 | tee /var/tmp/dietpi/logs/dietpi-automation_custom_script.log
|
|
G_DIETPI-NOTIFY $(( ! ! ${PIPESTATUS[0]} )) 'Custom script: /var/tmp/dietpi/logs/dietpi-automation_custom_script.log'
|
|
}
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Globals
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
Input_Modes()
|
|
{
|
|
# Process software and exit
|
|
if [[ $1 == 'install' || $1 == 'reinstall' || $1 == 'uninstall' ]]; then
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "Automated $1"
|
|
|
|
# Make sure we have at least one entry
|
|
[[ $2 ]] || { G_DIETPI-NOTIFY 1 'Please enter at least one software ID to process'; return 1; }
|
|
|
|
# Process software IDs
|
|
local command=$1
|
|
shift
|
|
for i in "$@"
|
|
do
|
|
# Check if input software ID exists, install state was defined
|
|
if disable_error=1 G_CHECK_VALIDINT "$i" 0 && disable_error=1 G_CHECK_VALIDINT "${aSOFTWARE_INSTALL_STATE[$i]}"; then
|
|
|
|
if [[ $command == 'uninstall' ]]; then
|
|
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 )); then
|
|
|
|
aSOFTWARE_INSTALL_STATE[$i]=-1
|
|
G_DIETPI-NOTIFY 0 "Uninstalling ${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}"
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[$i]} != -1 )); then
|
|
|
|
G_DIETPI-NOTIFY 2 "$i: ${aSOFTWARE_NAME[$i]} is not currently installed"
|
|
G_DIETPI-NOTIFY 0 "No changes applied for: ${aSOFTWARE_NAME[$i]}"
|
|
|
|
fi
|
|
|
|
elif [[ $command == 'reinstall' ]]; then
|
|
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && continue
|
|
|
|
if (( ${aSOFTWARE_INSTALL_STATE[$i]} != 2 )); then
|
|
|
|
G_DIETPI-NOTIFY 2 "$i: ${aSOFTWARE_NAME[$i]} is not currently installed"
|
|
G_DIETPI-NOTIFY 2 "Use \"dietpi-software install $i\" to install ${aSOFTWARE_NAME[$i]}."
|
|
G_DIETPI-NOTIFY 0 "No changes applied for: ${aSOFTWARE_NAME[$i]}"
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_ARCH[$i,$G_HW_ARCH]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported on $G_HW_ARCH_NAME systems."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$G_HW_MODEL]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported for $G_HW_MODEL_NAME."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_DISTRO[$i,$G_DISTRO]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported on Debian ${G_DISTRO_NAME^}."
|
|
|
|
else
|
|
|
|
aSOFTWARE_INSTALL_STATE[$i]=1
|
|
GOSTARTINSTALL=1 # Set install start flag
|
|
G_DIETPI-NOTIFY 0 "Reinstalling ${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}"
|
|
|
|
fi
|
|
|
|
elif [[ $command == 'install' ]]; then
|
|
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && continue
|
|
|
|
if (( ! ${aSOFTWARE_AVAIL_G_HW_ARCH[$i,$G_HW_ARCH]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported on $G_HW_ARCH_NAME systems."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$G_HW_MODEL]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported for $G_HW_MODEL_NAME."
|
|
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_DISTRO[$i,$G_DISTRO]:=1} )); then
|
|
|
|
G_DIETPI-NOTIFY 1 "Software title (${aSOFTWARE_NAME[$i]}) is not supported on Debian ${G_DISTRO_NAME^}."
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[$i]} != 2 )); then
|
|
|
|
aSOFTWARE_INSTALL_STATE[$i]=1
|
|
GOSTARTINSTALL=1 # Set install start flag
|
|
G_DIETPI-NOTIFY 0 "Installing ${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}"
|
|
|
|
else
|
|
|
|
G_DIETPI-NOTIFY 2 "$i: ${aSOFTWARE_NAME[$i]} is already installed"
|
|
G_DIETPI-NOTIFY 2 "Use \"dietpi-software reinstall $i\" to force rerun of installation and configuration steps for ${aSOFTWARE_NAME[$i]}."
|
|
G_DIETPI-NOTIFY 0 "No changes applied for: ${aSOFTWARE_NAME[$i]}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
# Reinstall, prompt for backup
|
|
if [[ $command == 'reinstall' && $GOSTARTINSTALL == 1 ]]; then
|
|
|
|
G_PROMPT_BACKUP
|
|
CONFLICTS_RESOLVED=1
|
|
|
|
# Uninstall | Finish up and clear non-required packages
|
|
elif [[ $command == 'uninstall' ]]; then
|
|
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) || continue
|
|
Uninstall_Software
|
|
Write_InstallFileList
|
|
break
|
|
done
|
|
|
|
fi
|
|
|
|
# List software IDs, names and additional info
|
|
elif [[ $1 == 'list' ]]; then
|
|
|
|
if [[ $MACHINE_READABLE ]]
|
|
then
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
# ID
|
|
local string=$i
|
|
|
|
# Show if disabled
|
|
(( ${aSOFTWARE_AVAIL_G_HW_ARCH[$i,$G_HW_ARCH]:=1} && ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$G_HW_MODEL]:=1} && ${aSOFTWARE_AVAIL_G_DISTRO[$i,$G_DISTRO]:=1} )) || string+=' DISABLED'
|
|
|
|
# Install state, software name, and description
|
|
string+="|${aSOFTWARE_INSTALL_STATE[$i]}|${aSOFTWARE_NAME[$i]}|${aSOFTWARE_DESC[$i]}|"
|
|
|
|
# Append dependencies
|
|
for j in ${aSOFTWARE_DEPS[$i]}
|
|
do
|
|
# Add software name or raw meta dependencies to string
|
|
[[ $j == *[^0-9]* ]] && string+="$j," || string+="${aSOFTWARE_NAME[$j]},"
|
|
done
|
|
|
|
echo "${string%,}|${aSOFTWARE_DOCS[$i]}"
|
|
done
|
|
else
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
# ID, install state, software name and description
|
|
local string="ID $i | =${aSOFTWARE_INSTALL_STATE[$i]} | ${aSOFTWARE_NAME[$i]}:\e[0m \e[90m${aSOFTWARE_DESC[$i]}\e[0m |"
|
|
|
|
# Paint green if installed
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 )) && string="\e[32m$string"
|
|
|
|
# Append dependencies
|
|
for j in ${aSOFTWARE_DEPS[$i]}
|
|
do
|
|
# Add software name or raw meta dependencies to string
|
|
[[ $j == *[^0-9]* ]] && string+=" +$j" || string+=" +${aSOFTWARE_NAME[$j]}"
|
|
done
|
|
|
|
# Available for G_HW_ARCH?
|
|
if (( ! ${aSOFTWARE_AVAIL_G_HW_ARCH[$i,$G_HW_ARCH]:=1} )); then
|
|
|
|
string+=" \e[31mDISABLED for ${RPI_64KERNEL_32OS:-$G_HW_ARCH_NAME}\e[0m"
|
|
|
|
# Available for G_HW_MODEL?
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$G_HW_MODEL]:=1} )); then
|
|
|
|
string+=" \e[31mDISABLED for $G_HW_MODEL_NAME\e[0m"
|
|
|
|
# Available for G_DISTRO?
|
|
elif (( ! ${aSOFTWARE_AVAIL_G_DISTRO[$i,$G_DISTRO]:=1} )); then
|
|
|
|
string+=" \e[31mDISABLED for Debian $G_DISTRO_NAME\e[0m"
|
|
|
|
fi
|
|
|
|
# Append online docs if available
|
|
[[ ${aSOFTWARE_DOCS[$i]} ]] && string+=" | \e[90m${aSOFTWARE_DOCS[$i]}\e[0m"
|
|
|
|
echo -e "$string"
|
|
done
|
|
fi
|
|
|
|
elif [[ $1 == 'free' ]]; then
|
|
|
|
# Get highest software array index
|
|
local max=0
|
|
for max in "${!aSOFTWARE_NAME[@]}"; do :; done
|
|
|
|
# Check for unused indices
|
|
local free=
|
|
for (( i=0; i<=$max; i++ )); do [[ ${aSOFTWARE_NAME[$i]} ]] || free+=" $i"; done
|
|
|
|
echo "Free software ID(s):${free:- None, so use $(($max+1))!}"
|
|
|
|
else
|
|
|
|
G_DIETPI-NOTIFY 1 "Invalid input command ($1). Aborting...\n$USAGE"
|
|
exit 1
|
|
|
|
fi
|
|
}
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Whip menus
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
MENU_MAIN_LASTITEM='Help!'
|
|
TARGETMENUID=0
|
|
|
|
# $1=search: Show search box and show only matches in menu
|
|
Menu_CreateSoftwareList()
|
|
{
|
|
local i j selected reset=()
|
|
|
|
# Search mode
|
|
if [[ $1 == 'search' ]]
|
|
then
|
|
G_WHIP_INPUTBOX 'Please enter a software title, ID or keyword to search, e.g.: desktop/cloud/media/torrent' || return 0
|
|
|
|
G_WHIP_CHECKLIST_ARRAY=()
|
|
|
|
# Loop through all software titles
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
# Check if this software is available for hardware, arch and distro
|
|
(( ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$G_HW_MODEL]:=1} && ${aSOFTWARE_AVAIL_G_HW_ARCH[$i,$G_HW_ARCH]:=1} && ${aSOFTWARE_AVAIL_G_DISTRO[$i,$G_DISTRO]:=1} )) || continue
|
|
|
|
# Check if input matches software ID, name or description
|
|
[[ $G_WHIP_RETURNED_VALUE == "$i" || ${aSOFTWARE_NAME[$i],,} == *"${G_WHIP_RETURNED_VALUE,,}"* || ${aSOFTWARE_DESC[$i],,} == *"${G_WHIP_RETURNED_VALUE,,}"* ]] || continue
|
|
|
|
# Set checkbox based on install state, including previous selection
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} > 0 )) && selected='on' || selected='off'
|
|
|
|
# Add this software title to whiptail menu
|
|
G_WHIP_CHECKLIST_ARRAY+=("$i" "${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}" "$selected")
|
|
|
|
# Add previously selected items to array to be unmarked if deselected when selection is confirmed.
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && reset+=("$i")
|
|
done
|
|
|
|
(( ${#G_WHIP_CHECKLIST_ARRAY[@]} )) || { G_WHIP_MSG "We couldn't find any available software title for the search term: \"$G_WHIP_RETURNED_VALUE\""; return 0; }
|
|
|
|
# Generate whiptail menu list of all software titles, sorted by category
|
|
else
|
|
G_WHIP_CHECKLIST_ARRAY=()
|
|
|
|
# Loop through software category IDs
|
|
for i in "${!aSOFTWARE_CATEGORIES[@]}"
|
|
do
|
|
# Add category to whiptail menu
|
|
G_WHIP_CHECKLIST_ARRAY+=('' "${aSOFTWARE_CATEGORIES[$i]}" 'off')
|
|
|
|
# Loop through software title IDs
|
|
for j in "${!aSOFTWARE_CATX[@]}"
|
|
do
|
|
# Check if this software's category matches the current category
|
|
(( ${aSOFTWARE_CATX[$j]} == $i )) || continue
|
|
|
|
# Check if this software is available for hardware, arch and distro
|
|
(( ${aSOFTWARE_AVAIL_G_HW_MODEL[$j,$G_HW_MODEL]:=1} && ${aSOFTWARE_AVAIL_G_HW_ARCH[$j,$G_HW_ARCH]:=1} && ${aSOFTWARE_AVAIL_G_DISTRO[$j,$G_DISTRO]:=1} )) || continue
|
|
|
|
# Set checkbox based on install state, including previous selection
|
|
(( ${aSOFTWARE_INSTALL_STATE[$j]} > 0 )) && selected='on' || selected='off'
|
|
|
|
# Add this software title to whiptail menu
|
|
G_WHIP_CHECKLIST_ARRAY+=("$j" "${aSOFTWARE_NAME[$j]}: ${aSOFTWARE_DESC[$j]}" "$selected")
|
|
|
|
# Add previously selected items to array to be unmarked if deselected when selection is confirmed.
|
|
(( ${aSOFTWARE_INSTALL_STATE[$j]} == 1 )) && reset+=("$j")
|
|
done
|
|
done
|
|
fi
|
|
|
|
G_WHIP_SIZE_X_MAX=96 # Assure this is enough to show full software descriptions + scroll bar
|
|
G_WHIP_BUTTON_OK_TEXT='Confirm'
|
|
G_WHIP_CHECKLIST 'Please use the spacebar to select the software you wish to install. Then press ENTER/RETURN or select <Confirm> to confirm.
|
|
- Press ESC or select <Cancel> to discard changes made.
|
|
- Software and usage details: https://dietpi.com/docs/software/' || return 0
|
|
|
|
# Unmark all listed pending state items, so deselected items are not installed.
|
|
for i in "${reset[@]}"
|
|
do
|
|
aSOFTWARE_INSTALL_STATE[$i]=0
|
|
done
|
|
|
|
# Mark selected items for install
|
|
for i in $G_WHIP_RETURNED_VALUE
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 )) || aSOFTWARE_INSTALL_STATE[$i]=1
|
|
done
|
|
|
|
# Unmark conflicting software
|
|
Unmark_Conflicts
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Install info/warnings/inputs
|
|
|
|
# DietPi-Drive_Manager can be used to setup Samba/NFS shares with ease!
|
|
(( ${aSOFTWARE_INSTALL_STATE[1]} == 1 || ${aSOFTWARE_INSTALL_STATE[110]} == 1 )) && G_WHIP_MSG "[ INFO ] Mount NFS/Samba shares via DietPi-Drive_Manager
|
|
\nDietPi-Drive_Manager is a powerful tool which vastly simplifies the mounting of NFS and Samba shares.
|
|
\nOnce $G_PROGRAM_NAME has finished installation, simply run 'dietpi-drive_manager' to setup required network mounts."
|
|
|
|
# PaperMC: Inform user about long install/startup time and possible swap file usage
|
|
if (( ${aSOFTWARE_INSTALL_STATE[181]} == 1 ))
|
|
then
|
|
local swap_info=
|
|
(( $RAM_PHYS < 924 )) && swap_info='\n\nThe server will be started with with minimal required memory usage, but a swap file will be created to assure that no out-of-memory crash can happen.
|
|
On servers with less than 1 GiB physical memory, we strongly recommend to move the swap file to an external drive if your system runs on an SD card, since during normal PaperMC operation this swap space will be heavily used.'
|
|
G_WHIP_MSG "PaperMC will be started during install to allow pre-configuring it's default configuration files. Especially on smaller SBCs, like Raspberry Pi Zero, this can take a long time.
|
|
We allow it to take up to 30 minutes, it's process can be followed, please be patient.$swap_info"
|
|
fi
|
|
|
|
# mjpg-streamer: Warn about unprotected stream and inform about additional plugins
|
|
(( ${aSOFTWARE_INSTALL_STATE[137]} == 1 )) && G_WHIP_MSG '[ WARN ] The mjpg-streamer camera stream will be accessible unprotected at port 8082 by default.
|
|
\nYou can configure a password protection, but this will break embedding the stream into other web interfaces, like OctoPrint.
|
|
\nWe hence recommend to not forward port 8082 through your NAT and/or block public access via firewall.
|
|
\nIf you require access from outside your local network to a web interface that embeds the camera stream, we recommend to setup a VPN connection for this.
|
|
\nRead more about this matter and how to configure mjpg-streamer at our online documentation: https://dietpi.com/docs/software/camera/#mjpg-streamer
|
|
\n[ INFO ] mjpg-streamer will not be compiled with all available plugins by default.
|
|
\nIf you require other input or output plugins, simply install the required dependencies. Plugins will be compiled automatically if dependencies are met.
|
|
\nFor available plugins and their dependencies, watch the info printed during the build and check out the official GitHub repository: https://github.com/jacksonliam/mjpg-streamer'
|
|
|
|
# RPi Cam Web Interface: Warn user of locking out camera: https://github.com/MichaIng/DietPi/issues/249
|
|
(( ${aSOFTWARE_INSTALL_STATE[59]} == 1 )) && G_WHIP_MSG 'RPi Cam Web Interface will automatically start and activate the camera during boot. This will prevent other programs (like raspistill) from using the camera.
|
|
\nYou can free up the camera by selecting "Stop Camera" from the web interface:\n - http://myip/rpicam'
|
|
|
|
# Offer to install Unbound along with AdGuard Home and Pi-hole
|
|
if (( ${aSOFTWARE_INSTALL_STATE[93]} == 1 || ${aSOFTWARE_INSTALL_STATE[126]} == 1 ))
|
|
then
|
|
# Add option to use Unbound as upstream DNS server
|
|
if (( ${aSOFTWARE_INSTALL_STATE[182]} == 0 ))
|
|
then
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO 'Would you like to use Unbound, a tiny recursive DNS server hosted on your device, as your upstream DNS server?
|
|
\nThis will increase privacy, because you will not be sending data to Google etc.
|
|
\nHowever, the downside is that some websites may load slower the first time you visit them.' && aSOFTWARE_INSTALL_STATE[182]=1
|
|
fi
|
|
|
|
# Prompt for static IP
|
|
if G_WHIP_BUTTON_CANCEL_TEXT='Skip' G_WHIP_YESNO 'A static IP address is essential for a DNS server installation. DietPi-Config can be used to quickly setup your static IP address.
|
|
\nIf you have already setup your static IP, please ignore this message.\n\nWould you like to setup your static IP address now?'
|
|
then
|
|
G_WHIP_MSG 'DietPi-Config will now be launched. Simply select your Ethernet or Wifi connection from the menu to access the IP address settings.
|
|
\nThe "copy current address to STATIC" menu option can be used to quickly setup your static IP. Please ensure you change the mode "DHCP" to "STATIC".
|
|
\nOnce completed, select "Apply Save Changes", then exit DietPi-Config to resume setup.'
|
|
/boot/dietpi/dietpi-config 8
|
|
fi
|
|
fi
|
|
|
|
# WiFi Hotspot Criteria
|
|
if (( ${aSOFTWARE_INSTALL_STATE[60]} == 1 || ${aSOFTWARE_INSTALL_STATE[61]} == 1 ))
|
|
then
|
|
# Enable WiFi modules
|
|
/boot/dietpi/func/dietpi-set_hardware wifimodules enable
|
|
|
|
while :
|
|
do
|
|
local criteria_passed=1
|
|
local output_string='The following criteria must be met for the installation of WiFi Hotspot to succeed:'
|
|
|
|
if [[ $(G_GET_NET -q -t eth ip) ]]
|
|
then
|
|
output_string+='\n\n - Ethernet online: PASSED'
|
|
else
|
|
criteria_passed=0
|
|
output_string+='\n\n - Ethernet online: FAILED.\nUse dietpi-config to connect and configure Ethernet.'
|
|
fi
|
|
|
|
if [[ $(G_GET_NET -q -t wlan iface) ]]
|
|
then
|
|
output_string+='\n\n - WiFi adapter detected: PASSED'
|
|
else
|
|
criteria_passed=0
|
|
output_string+='\n\n - WiFi adapter detected: FAILED.\nPlease connect a WiFi adapter and try again.'
|
|
fi
|
|
|
|
# Passed
|
|
if (( $criteria_passed ))
|
|
then
|
|
output_string+='\n\nPASSED: Criteria met. Good to go.'
|
|
G_WHIP_MSG "$output_string"
|
|
break
|
|
|
|
# Failed, retry?
|
|
else
|
|
output_string+='\n\nFAILED: Criteria not met. Would you like to check again?'
|
|
G_WHIP_YESNO "$output_string" && continue
|
|
|
|
(( ${aSOFTWARE_INSTALL_STATE[60]} == 1 )) && aSOFTWARE_INSTALL_STATE[60]=0
|
|
(( ${aSOFTWARE_INSTALL_STATE[61]} == 1 )) && aSOFTWARE_INSTALL_STATE[61]=0
|
|
G_WHIP_MSG 'WiFi Hotspot criteria were not met. The software will not be installed.'
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Let's Encrypt
|
|
(( ${aSOFTWARE_INSTALL_STATE[92]} == 1 )) && G_WHIP_MSG 'The DietPi installation of Certbot supports all offered web servers.\n\nOnce the installation has finished, you can setup your free SSL cert with:
|
|
- DietPi-LetsEncrypt\n\nThis is an easy to use frontend for Certbot and allows integration into DietPi systems.\n\nMore information:\n - https://dietpi.com/docs/software/system_security/#lets-encrypt'
|
|
|
|
# Steam on ARMv7 via Box86 warning
|
|
(( ${aSOFTWARE_INSTALL_STATE[156]} == 1 && $G_HW_ARCH == 2 )) && G_WHIP_MSG '[WARNING] Steam natively only runs on the x86 systems.\n\nBox86 will be used to run it on ARM, however there may be performance and compatibility issues.'
|
|
|
|
# Home Assistant: Inform about long install/build time: https://github.com/MichaIng/DietPi/issues/2897
|
|
(( ${aSOFTWARE_INSTALL_STATE[157]} == 1 )) && G_WHIP_MSG '[ INFO ] Home Assistant: Grab yourself a coffee
|
|
\nThe install process of Home Assistant within the virtual environment, especially the Python build, can take more than one hour, especially on slower SBCs like RPi Zero and similar.
|
|
\nPlease be patient. In the meantime you may study the documentation:
|
|
- https://dietpi.com/docs/software/home_automation/#home-assistant'
|
|
}
|
|
|
|
Menu_Main()
|
|
{
|
|
# Selected SSH server choice
|
|
local sshserver_text='None'
|
|
if (( ${aSOFTWARE_INSTALL_STATE[104]} > 0 )); then
|
|
|
|
sshserver_text=${aSOFTWARE_NAME[104]} # Dropbear
|
|
|
|
elif (( ${aSOFTWARE_INSTALL_STATE[105]} > 0 )); then
|
|
|
|
sshserver_text=${aSOFTWARE_NAME[105]} # OpenSSH
|
|
|
|
fi
|
|
|
|
# Selected logging system choice
|
|
local index_logging_text='None'
|
|
if (( $INDEX_LOGGING == -1 )); then
|
|
|
|
index_logging_text='DietPi-RAMlog #1'
|
|
|
|
elif (( $INDEX_LOGGING == -2 )); then
|
|
|
|
index_logging_text='DietPi-RAMlog #2'
|
|
|
|
elif (( $INDEX_LOGGING == -3 )); then
|
|
|
|
index_logging_text='Full'
|
|
|
|
fi
|
|
|
|
# Get real userdata location
|
|
local user_data_location_current=$(readlink -f /mnt/dietpi_userdata)
|
|
|
|
local user_data_location_description="Custom | $user_data_location_current"
|
|
if [[ $user_data_location_current == '/mnt/dietpi_userdata' ]]; then
|
|
|
|
user_data_location_description="SD/eMMC | $user_data_location_current"
|
|
|
|
elif [[ $user_data_location_current == "$(findmnt -Ufnro TARGET -S /dev/sda1)" ]]; then
|
|
|
|
user_data_location_description="USB Drive | $user_data_location_current"
|
|
|
|
fi
|
|
|
|
# Software to be installed or removed based on choice system
|
|
local tobeinstalled_text toberemoved_text
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'Help!' ': Links to online guides, docs and information'
|
|
'DietPi-Config' ': Feature-rich configuration tool for your device'
|
|
'' '●─ Select Software '
|
|
'Search Software' ': Find software to install via search box'
|
|
'Browse Software' ': Select software from the full list'
|
|
'SSH Server' ": [$sshserver_text]"
|
|
'Log System' ": [$index_logging_text]"
|
|
'User Data Location' ": [$user_data_location_description]"
|
|
'' '●─ Install or Remove Software '
|
|
'Uninstall' ': Select installed software for removal'
|
|
'Install' ': Go >> Start installation for selected software'
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=$MENU_MAIN_LASTITEM
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Exit'
|
|
G_WHIP_SIZE_X_MAX=80
|
|
if G_WHIP_MENU; then
|
|
|
|
MENU_MAIN_LASTITEM=$G_WHIP_RETURNED_VALUE
|
|
|
|
case "$G_WHIP_RETURNED_VALUE" in
|
|
|
|
'Uninstall') Menu_Uninstall_Software;;
|
|
|
|
'Search Software') Menu_CreateSoftwareList search;;
|
|
|
|
'Browse Software') Menu_CreateSoftwareList;;
|
|
|
|
'SSH Server')
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'None' ': Not required / manual setup'
|
|
"${aSOFTWARE_NAME[104]}" ": ${aSOFTWARE_DESC[104]} (recommended)"
|
|
"${aSOFTWARE_NAME[105]}" ": ${aSOFTWARE_DESC[105]}"
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=$sshserver_text
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Back'
|
|
G_WHIP_MENU 'Please select desired SSH server:
|
|
\n- None: Selecting this option will uninstall all SSH servers. This reduces system resources and improves performance. Useful for users who do NOT require networked/remote terminal access.
|
|
\n- Dropbear (recommended): Lightweight SSH server, installed by default on DietPi systems.
|
|
\n- OpenSSH: A feature-rich SSH server with SFTP/SCP support, at the cost of increased resource usage.' || return 0
|
|
|
|
# Apply selection
|
|
case "$G_WHIP_RETURNED_VALUE" in
|
|
|
|
'None') Apply_SSHServer_Choices 0;;
|
|
"${aSOFTWARE_NAME[105]}") Apply_SSHServer_Choices -2;;
|
|
*) Apply_SSHServer_Choices -1;;
|
|
esac
|
|
|
|
# Check for changes
|
|
for i in 104 105
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && tobeinstalled_text+="\n - ${aSOFTWARE_NAME[$i]}"
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) && toberemoved_text+="\n - ${aSOFTWARE_NAME[$i]}"
|
|
done
|
|
[[ $tobeinstalled_text || $toberemoved_text ]] || return 0
|
|
[[ $tobeinstalled_text ]] && tobeinstalled_text="\n\nThe following software will be installed:$tobeinstalled_text"
|
|
[[ $toberemoved_text ]] && toberemoved_text="\n\nThe following software will be uninstalled:$toberemoved_text"
|
|
|
|
G_WHIP_MSG "$G_WHIP_RETURNED_VALUE has been selected:\n- Your choice will be applied when 'Install Go >> Start installation' is selected.$tobeinstalled_text$toberemoved_text"
|
|
;;
|
|
|
|
'Log System')
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'None' ': Not required / manual setup'
|
|
'DietPi-RAMlog #1' ': Hourly clear (recommended)'
|
|
'DietPi-RAMlog #2' ': Hourly save, then clear'
|
|
'Full' ': Logrotate and Rsyslog'
|
|
)
|
|
|
|
G_WHIP_DEFAULT_ITEM=$index_logging_text
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Back'
|
|
G_WHIP_MENU 'Please select desired logging system:
|
|
\n- None: Selecting this option will uninstall DietPi-RAMlog, Logrotate and Rsyslog.
|
|
\n- DietPi-RAMlog #1 (Max performance): Mounts /var/log to RAM, reducing filesystem I/O. Logfiles are cleared every hour. Does NOT save logfiles to disk.
|
|
\n- DietPi-RAMlog #2: Same as #1, with the added feature of appending logfile contents to disk at /root/logfile_storage, before being cleared.
|
|
\n- Full (Reduces performance): Leaves /var/log on DISK, reduces SD card lifespan. Full logging system with Logrotate and Rsyslog.' || return 0
|
|
|
|
# Apply selection
|
|
case "$G_WHIP_RETURNED_VALUE" in
|
|
|
|
'None') Apply_Logging_Choices 0;;
|
|
'DietPi-RAMlog #2') Apply_Logging_Choices -2;;
|
|
'Full') Apply_Logging_Choices -3;;
|
|
*) Apply_Logging_Choices -1;;
|
|
esac
|
|
|
|
# Check for changes
|
|
for i in 101 102 103
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && tobeinstalled_text+="\n - ${aSOFTWARE_NAME[$i]}"
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) && toberemoved_text+="\n - ${aSOFTWARE_NAME[$i]}"
|
|
done
|
|
[[ $tobeinstalled_text || $toberemoved_text ]] || return 0
|
|
[[ $tobeinstalled_text ]] && tobeinstalled_text="\n\nThe following software will be installed:$tobeinstalled_text"
|
|
[[ $toberemoved_text ]] && toberemoved_text="\n\nThe following software will be uninstalled:$toberemoved_text"
|
|
|
|
G_WHIP_MSG "$G_WHIP_RETURNED_VALUE has been selected:\n- Your choice will be applied when 'Install : Go >> Start installation' is selected.$tobeinstalled_text$toberemoved_text"
|
|
;;
|
|
|
|
'User Data Location')
|
|
|
|
# - Vars if we need to move data.
|
|
local move_data_target=$user_data_location_current
|
|
|
|
G_WHIP_MENU_ARRAY=(
|
|
|
|
'List' ': Select from a list of available drives to move user data.'
|
|
'Custom' ': Manually enter a location to move user data.'
|
|
'Drive' ': Launch DietPi-Drive_Manager.'
|
|
)
|
|
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Back'
|
|
G_WHIP_MENU 'Choose where to store your user data. User data includes software such as ownCloud data store, BitTorrent downloads etc.
|
|
\nMore information on user data in DietPi:\n- https://dietpi.com/docs/dietpi_tools/#quick-selections
|
|
\n- DietPi-Drive_Manager: Launch DietPi-Drive_Manager to setup external drives, and, move user data to different locations.' || return 0
|
|
|
|
# Launch DietPi-Drive_Manager
|
|
if [[ $G_WHIP_RETURNED_VALUE == 'Drive' ]]; then
|
|
|
|
/boot/dietpi/dietpi-drive_manager
|
|
return 0
|
|
|
|
# List
|
|
elif [[ $G_WHIP_RETURNED_VALUE == 'List' ]]; then
|
|
|
|
/boot/dietpi/dietpi-drive_manager 1 || return 1
|
|
|
|
local return_value=$(</tmp/dietpi-drive_manager_selmnt)
|
|
[[ $return_value ]] || return 1
|
|
|
|
[[ $return_value == '/' ]] && return_value='/mnt'
|
|
move_data_target=$return_value
|
|
move_data_target+='/dietpi_userdata'
|
|
|
|
# Manual file path entry
|
|
elif [[ $G_WHIP_RETURNED_VALUE == 'Custom' ]]; then
|
|
|
|
G_WHIP_INPUTBOX 'Please input a location. Your user data will be stored inside this location.\n - eg: /mnt/MyDrive/MyData' || return 1
|
|
move_data_target=$G_WHIP_RETURNED_VALUE
|
|
|
|
fi
|
|
|
|
# Move data if the new entry has changed
|
|
[[ $user_data_location_current != "$move_data_target" ]] || return 0
|
|
|
|
# Ask before we begin
|
|
G_WHIP_YESNO "DietPi will now attempt to transfer your existing user data to the new location:
|
|
\n- From: $user_data_location_current\n- To: $move_data_target\n\nWould you like to begin?" || return 0
|
|
|
|
# Move data, setup symlinks
|
|
if /boot/dietpi/func/dietpi-set_userdata "$user_data_location_current" "$move_data_target"; then
|
|
|
|
G_WHIP_MSG "User data transfer: Completed\n\nYour user data has been successfully moved:\n\n- From: $user_data_location_current\n- To: $move_data_target"
|
|
|
|
else
|
|
|
|
G_WHIP_MSG "User data transfer: Failed\n\n$(</var/log/dietpi-move_userdata.log)\n\nNo changes have been applied."
|
|
|
|
fi
|
|
;;
|
|
|
|
'DietPi-Config') /boot/dietpi/dietpi-config;;
|
|
|
|
'Help!')
|
|
|
|
local string='───────────────────────────────────────────────────────────────
|
|
Welcome to DietPi:
|
|
───────────────────────────────────────────────────────────────
|
|
Use PageUp/Down or Arrow Up/Down to scroll this help screen.
|
|
Press ESC, or TAB then ENTER to exit this help screen.\n
|
|
Easy to follow, step by step guides for installing DietPi:
|
|
https://dietpi.com/docs/install/\n
|
|
For a list of all installation options and their details:
|
|
https://dietpi.com/docs/software/\n
|
|
───────────────────────────────────────────────────────────────
|
|
List of installed software and their online documentation URLs:
|
|
───────────────────────────────────────────────────────────────\n'
|
|
|
|
# Installed software
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
[[ ${aSOFTWARE_INSTALL_STATE[i]} -gt 0 && ${aSOFTWARE_DOCS[$i]} ]] || continue
|
|
string+="\n${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}\n${aSOFTWARE_DOCS[$i]}\n"
|
|
done
|
|
|
|
G_WHIP_SIZE_X_MAX=70
|
|
G_WHIP_MSG "$string"
|
|
;;
|
|
|
|
'Install') Menu_StartInstall;;
|
|
|
|
*) :;;
|
|
|
|
esac
|
|
|
|
# Exit/Abort Setup
|
|
else
|
|
Menu_Exit
|
|
fi
|
|
}
|
|
|
|
Menu_Exit()
|
|
{
|
|
TARGETMENUID=0 # Return to Main Menu
|
|
|
|
# Standard exit
|
|
if (( $G_DIETPI_INSTALL_STAGE == 2 ))
|
|
then
|
|
G_WHIP_DEFAULT_ITEM='ok'
|
|
G_WHIP_YESNO 'Do you wish to exit DietPi-Software?\n\nAll changes to software selections will be cleared.' || return 0
|
|
exit 0
|
|
fi
|
|
|
|
# Prevent exit on 1st run setup
|
|
G_WHIP_MSG 'DietPi has not fully been installed.\nThis must be completed prior to using DietPi by selecting:\n - Install : Go >> Start installation'
|
|
}
|
|
|
|
Menu_StartInstall()
|
|
{
|
|
local tobeinstalled_text toberemoved_text summary_text
|
|
|
|
# Obtain list of pending software installs and uninstalls
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 1 )) && tobeinstalled_text+="\n - ${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}"
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == -1 )) && toberemoved_text+="\n - ${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}"
|
|
done
|
|
|
|
# Check if user made/changed software selections
|
|
if [[ $tobeinstalled_text || $toberemoved_text ]]
|
|
then
|
|
# List selections and ask for confirmation
|
|
[[ $tobeinstalled_text ]] && tobeinstalled_text="\n\nThe following software will be installed:$tobeinstalled_text"
|
|
[[ $toberemoved_text ]] && toberemoved_text="\n\nThe following software will be uninstalled:$toberemoved_text"
|
|
[[ $G_SERVICE_CONTROL == 0 ]] || summary_text='\n\nNB: Software services will be temporarily controlled (stopped) by DietPi during this process. Please inform connected users, before continuing. SSH and VNC are not affected.'
|
|
|
|
G_WHIP_DEFAULT_ITEM='ok'
|
|
G_WHIP_YESNO "DietPi is now ready to apply your software choices:$tobeinstalled_text$toberemoved_text$summary_text
|
|
\nSoftware details, usernames, passwords etc:\n - https://dietpi.com/docs/software/\n\nWould you like to begin?" || return 0
|
|
|
|
# If due to choice changes only uninstalls are done and it is not the first run setup, skip the install function and call the uninstall function directly.
|
|
if [[ $G_DIETPI_INSTALL_STAGE == 2 && ! $tobeinstalled_text ]]
|
|
then
|
|
Uninstall_Software
|
|
Write_InstallFileList
|
|
else
|
|
GOSTARTINSTALL=1 # Set install start flag
|
|
fi
|
|
TARGETMENUID=-1 # Exit menu loop
|
|
|
|
# After first run setup has finished, abort install without any selections
|
|
elif (( $G_DIETPI_INSTALL_STAGE == 2 ))
|
|
then
|
|
G_WHIP_MSG 'No changes have been detected. Unable to start installation.'
|
|
|
|
# Allow to finish first run setup without any selections
|
|
else
|
|
G_WHIP_DEFAULT_ITEM='ok'
|
|
G_WHIP_YESNO 'DietPi was unable to detect any additional software selections for install.
|
|
\nNB: You can use dietpi-software at a later date, to install optimised software from our catalogue as required.
|
|
\nDo you wish to continue with DietPi as a pure minimal image?' || return 0
|
|
|
|
TARGETMENUID=-1 # Exit menu loop
|
|
GOSTARTINSTALL=1 # Set install start flag
|
|
fi
|
|
}
|
|
|
|
Menu_Uninstall_Software()
|
|
{
|
|
# Array which will hold all software IDs to be removed.
|
|
G_WHIP_CHECKLIST_ARRAY=()
|
|
|
|
# Obtain list of installed software
|
|
local i
|
|
for i in "${!aSOFTWARE_NAME[@]}"
|
|
do
|
|
(( ${aSOFTWARE_INSTALL_STATE[$i]} == 2 )) || continue
|
|
# Skip webserver stacks: Their install states will be aligned with webserver/database install states automatically.
|
|
[[ $i =~ ^(75|76|78|79|81|82)$ ]] || G_WHIP_CHECKLIST_ARRAY+=("$i" "${aSOFTWARE_NAME[$i]}: ${aSOFTWARE_DESC[$i]}" 'off')
|
|
done
|
|
|
|
# No software installed
|
|
if (( ! ${#G_WHIP_CHECKLIST_ARRAY[@]} ))
|
|
then
|
|
G_WHIP_MSG 'No software is currently installed.'
|
|
|
|
# Run menu
|
|
else
|
|
G_WHIP_DEFAULT_ITEM='ok' G_WHIP_BUTTON_CANCEL_TEXT='Back'
|
|
G_WHIP_CHECKLIST 'Use the spacebar to select the software you would like to remove:' && [[ $G_WHIP_RETURNED_VALUE ]] || return 0
|
|
|
|
# Create list for user to review before removal
|
|
local output_string='The following software will be REMOVED from your system:'
|
|
for i in $G_WHIP_RETURNED_VALUE
|
|
do
|
|
output_string+="\n - ${aSOFTWARE_NAME[$i]} (ID=$i): ${aSOFTWARE_DESC[$i]}"
|
|
done
|
|
|
|
G_WHIP_YESNO "$output_string
|
|
\nNB: Uninstalling usually PURGES any related userdata and configs. If you only need to repair or update software, please use \"dietpi-software reinstall <ID>\" instead.
|
|
\nDo you wish to continue?" || return 0
|
|
|
|
# Mark for uninstall
|
|
for i in $G_WHIP_RETURNED_VALUE
|
|
do
|
|
aSOFTWARE_INSTALL_STATE[$i]=-1
|
|
done
|
|
|
|
# Run uninstall
|
|
Uninstall_Software
|
|
|
|
# Save install states
|
|
Write_InstallFileList
|
|
|
|
G_WHIP_MSG 'Uninstall completed'
|
|
fi
|
|
}
|
|
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Main Loop
|
|
#/////////////////////////////////////////////////////////////////////////////////////
|
|
# Abort if a reboot is required as of missing kernel modules
|
|
if [[ $1 != 'list' && $G_DIETPI_INSTALL_STAGE == 2 ]] && ! G_CHECK_KERNEL
|
|
then
|
|
G_WHIP_BUTTON_CANCEL_TEXT='Abort' G_WHIP_YESNO "[ INFO ] A reboot is required
|
|
\nKernel modules for the loaded kernel at /lib/modules/$(uname -r) are missing. This is most likely the case as of a recently applied kernel upgrade where a reboot is required to load the new kernel.
|
|
\nTo assure that $G_PROGRAM_NAME can run successfully, especially when performing installs, it is required that you perform a reboot so that kernel modules can be loaded ondemand.
|
|
\nThere may be rare cases where no dedicated kernel modules are used but all require modules are builtin. If this is the case, please create the mentioned directory manually to proceed.
|
|
\nDo you want to reboot now?" && reboot || exit 1
|
|
exit 0
|
|
fi
|
|
# Init software arrays
|
|
Software_Arrays_Init
|
|
#-------------------------------------------------------------------------------------
|
|
# Load .installed file, update vars if it exists
|
|
Read_InstallFileList
|
|
#-------------------------------------------------------------------------------------
|
|
# CLI input mode: Force menu mode on first run
|
|
if [[ $1 && $G_DIETPI_INSTALL_STAGE == 2 ]]
|
|
then
|
|
Input_Modes "$@"
|
|
|
|
#-------------------------------------------------------------------------------------
|
|
# Standard launch
|
|
else
|
|
# DietPi-Automation pre install steps
|
|
(( $G_DIETPI_INSTALL_STAGE == 2 )) || DietPi-Automation_Pre
|
|
|
|
# Start DietPi Menu
|
|
until (( $TARGETMENUID < 0 ))
|
|
do
|
|
G_TERM_CLEAR
|
|
Menu_Main
|
|
done
|
|
fi
|
|
#-------------------------------------------------------------------------------------
|
|
# Start DietPi-Software installs
|
|
(( $GOSTARTINSTALL )) || exit 0
|
|
|
|
# Userdata location verify
|
|
G_CHECK_USERDATA
|
|
|
|
# Start software installs
|
|
Run_Installations
|
|
|
|
# DietPi-Automation post install steps
|
|
(( $G_DIETPI_INSTALL_STAGE == 2 )) || DietPi-Automation_Post
|
|
|
|
G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" 'Install completed'
|
|
|
|
# Upload DietPi-Survey data if opted in, prompt user choice if no settings file exists
|
|
# - Skip if G_SERVICE_CONTROL == 0, exported by "patches" (DietPi-Update) which sends survey already
|
|
# Start services, restart to reload configs of possibly running services
|
|
if [[ $G_SERVICE_CONTROL != 0 ]]
|
|
then
|
|
/boot/dietpi/dietpi-survey 1
|
|
/boot/dietpi/dietpi-services restart
|
|
(( $RESTART_DELUGE_WEB )) && { G_SLEEP 1; G_EXEC_NOHALT=1 G_EXEC systemctl restart deluge-web; }
|
|
fi
|
|
|
|
# Start installed services, not controlled by DietPi-Services
|
|
[[ ${aSTART_SERVICES[0]} ]] || exit 0
|
|
|
|
G_DIETPI-NOTIFY 2 'Starting installed services not controlled by DietPi-Services'
|
|
for i in "${aSTART_SERVICES[@]}"
|
|
do
|
|
G_EXEC_NOHALT=1 G_EXEC systemctl start "$i"
|
|
done
|
|
#-------------------------------------------------------------------------------------
|
|
exit 0
|
|
#-------------------------------------------------------------------------------------
|
|
} |