#!/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 [ [...]] Available commands: Interactive menu to install or uninstall software install ... Install each software given by space-separated list of IDs reinstall ... Reinstall each software given by space-separated list of IDs uninstall ... 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' G_CHECK_ROOT_USER G_CHECK_ROOTFS_RW G_INIT # 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() { local encrypt=0 # Read encrypted password if [[ -f '/var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin' ]] then if ! 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) then # Allow decryption without pbkdf2/"-iter 10000" and re-encrypt on dist-upgraded Buster systems encrypt=1 # In case of error, assure empty password to fallback to default GLOBAL_PW=$(openssl enc -d -a -md sha256 -aes-256-cbc -salt -pass pass:'DietPiRocks!' -in /var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin) || GLOBAL_PW= fi # If encryption has not yet been done, do it now! else encrypt=1 GLOBAL_PW=$(sed -n '/^[[:blank:]]*AUTO_SETUP_GLOBAL_PASSWORD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) grep -q '^[[:blank:]]*AUTO_SETUP_GLOBAL_PASSWORD=' /boot/dietpi.txt && G_EXEC sed -i '/^[[:blank:]]*AUTO_SETUP_GLOBAL_PASSWORD=/c\#AUTO_SETUP_GLOBAL_PASSWORD= # Password has been encrypted and saved to rootfs' /boot/dietpi.txt fi # Fallback if [[ ! $GLOBAL_PW ]] then encrypt=1 GLOBAL_PW='dietpi' G_WHIP_MSG "[FAILED] Unable to obtain your global software password \nThe following fallback password will be used:\n - $GLOBAL_PW \nYou can change it via:\n - dietpi-config > Security Options > Change Passwords" fi # Encrypt # https://github.com/koalaman/shellcheck/issues/1009 # shellcheck disable=SC2086 [[ $encrypt == 1 ]] && openssl enc -e -a -md sha256 -aes-256-cbc -iter 10000 -salt -pass pass:'DietPiRocks!' -out /var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin <<< $GLOBAL_PW # Apply safe permissions chown 0:0 /var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin chmod 0600 /var/lib/dietpi/dietpi-software/.GLOBAL_PW.bin } # 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 5) PHP_VERSION='7.3';; 6) PHP_VERSION='7.4';; *) PHP_VERSION='8.2';; 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 '●─ File Managers ' #22 '●─ System ' #23 '●─ Databases & Data Stores ' #24 '●─ Network Tools ' #25 '●─ Development & Programming ' #26 '●─ Text Editors ' #27 '●─ Desktop Utilities ' #28 ) #-------------------------------------------------------------------------------- # 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: No package: 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.org repo, libraspberrypi0 dependency, license) (( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=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' # Bullseye + RPi 32-bit + Odroid N2 + Odroid C4: Kodi starts without X server [[ $G_DISTRO -ge 6 || ( $G_HW_MODEL -le 9 && $(dpkg --print-architecture) == 'armhf' ) || $G_HW_MODEL == 1[56] ]] || aSOFTWARE_DEPS[$software_id]+=' 6' # Odroids from Bullseye on (no Amlogic fbdev Kodi build available) require an X server when no DRM is available. [[ $G_HW_MODEL == 1[56] && $G_DISTRO -ge 6 && ! -e '/dev/dri' ]] && aSOFTWARE_DEPS[$software_id]+=' 6' #------------------ 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' # - Bookworm: No libssl3 support aSOFTWARE_AVAIL_G_DISTRO[$software_id,7]=0 # - RISC-V: No binary: https://dietpi.com/downloads/binaries/all/ympd_1.2.3.7z aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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: No package: https://download.opensuse.org/repositories/home:/jcorporation/Debian_Unstable/ aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=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]='Logitech Media Server' aSOFTWARE_DESC[$software_id]='fka. SlimServer, SqueezeboxServer, SliMP3' aSOFTWARE_CATX[$software_id]=2 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#logitech-media-server' # - RISC-V: No package: https://downloads.slimdevices.com/releases/latest.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: No package: 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: No package aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ software_id=43 aSOFTWARE_NAME[$software_id]='Murmur' aSOFTWARE_DESC[$software_id]='mumble 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: No archive: 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' #------------------ 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=141 aSOFTWARE_NAME[$software_id]='Spotify Connect Web' aSOFTWARE_DESC[$software_id]='web interface for Spotify premium' aSOFTWARE_CATX[$software_id]=2 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#spotify-connect-web' aSOFTWARE_DEPS[$software_id]='5' # ARMv7 only (( $G_HW_ARCH == 2 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,$G_HW_ARCH]=0 #------------------ 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 65 88 89 96 124 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' #------------------ 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]='Spotify connect client' aSOFTWARE_CATX[$software_id]=2 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/media/#raspotify' aSOFTWARE_DEPS[$software_id]='5' # - Buster: https://dtcooper.github.io/raspotify/ aSOFTWARE_AVAIL_G_DISTRO[$software_id,5]=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: No package: https://repo.jellyfin.org/releases/server/debian/unstable/ aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=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' # - ARMv8: https://github.com/badaix/snapcast/issues/706 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0 # - RISC-V: https://github.com/badaix/snapcast/releases aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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' aSOFTWARE_INTERACTIVE[$software_id]=1 # - ARMv8: https://github.com/badaix/snapcast/issues/706 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0 # - RISC-V: https://github.com/badaix/snapcast/releases aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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' # - ARMv8 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,3]=0 # - 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: No archive: https://github.com/navidrome/navidrome/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' aSOFTWARE_DEPS[$software_id]='87 150' # - RISC-V: Missing package 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' aSOFTWARE_DEPS[$software_id]='87' (( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]+=' 150' # - RISC-V: Missing package 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' aSOFTWARE_DEPS[$software_id]='87' (( $G_HW_ARCH == 1 )) && aSOFTWARE_DEPS[$software_id]+=' 150' # - RISC-V: Missing package 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 required on ARM, 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 required on ARMv6/7, ARMv8 and x86_64 binaries are shipped with Bazarr: https://github.com/morpheus65535/bazarr-binaries/tree/master/bin/Linux (( $G_HW_ARCH < 3 )) && 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: Missing package 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' aSOFTWARE_DEPS[$software_id]='87' # - ARMv6 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 # - RISC-V: Missing package 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' aSOFTWARE_DEPS[$software_id]='87' # - ARMv6 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 # - RISC-V: Missing package 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 video sites' aSOFTWARE_CATX[$software_id]=3 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/bittorrent/#youtube-dl' # 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: No PHP 8.x support yet aSOFTWARE_AVAIL_G_DISTRO[$software_id,7]=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' # Currently requires manual domain and Coturn server port input. # - To resolve: Default port 5349 could be used, but reliable method to get external domain/static IP is required. aSOFTWARE_INTERACTIVE[$software_id]=1 #------------------ 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' #------------------ 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' # - ARMv6 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 # - RISC-V: Missing package aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=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' #------------------ 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: Missing package 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: Missing package 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' # - RISC-V: Missing binary: https://github.com/go-gitea/gitea/releases aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ software_id=177 aSOFTWARE_NAME[$software_id]='Firefox Sync Server' aSOFTWARE_DESC[$software_id]='Sync bookmarks, tabs, history & passwords' aSOFTWARE_CATX[$software_id]=4 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/cloud/#firefox-sync-server' aSOFTWARE_DEPS[$software_id]='87' # Python 2 only, hence supported only on Buster (( $G_DISTRO == 5 )) || aSOFTWARE_AVAIL_G_DISTRO[$software_id,$G_DISTRO]=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' # Gaming & Emulation #-------------------------------------------------------------------------------- software_id=108 aSOFTWARE_NAME[$software_id]='Amiberry' aSOFTWARE_DESC[$software_id]='Optimised Amiga emulator for ARM-based SoCs' aSOFTWARE_CATX[$software_id]=5 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/gaming/#amiberry' aSOFTWARE_DEPS[$software_id]='5' # - RISC-V: Missing target aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=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 #------------------ 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: Missing binary 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' aSOFTWARE_INTERACTIVE[$software_id]=1 # As of Java 16+ need, currently only works on Bullseye+ and not on ARMv6 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 aSOFTWARE_AVAIL_G_DISTRO[$software_id,5]=0 #------------------ 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 == 7 )) || 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 # 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' aSOFTWARE_INTERACTIVE[$software_id]=1 #----------------- 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://docs.microblog.pub/' # Camera & Surveillance #-------------------------------------------------------------------------------- software_id=59 aSOFTWARE_NAME[$software_id]='RPi Cam Web Interface' aSOFTWARE_DESC[$software_id]='Web interface & controls for your RPi camera' aSOFTWARE_CATX[$software_id]=7 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/camera/#rpi-cam-control' 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 #------------------ 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' # System Stats & Management #-------------------------------------------------------------------------------- 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' #------------------ 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/programming/#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/programming/#portainer' aSOFTWARE_DEPS[$software_id]='162' # - ARMv6: https://dietpi.com/forum/t/armv6-bookworm-software-test-matrix-question/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/programming/#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' #------------------ 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' #------------------ software_id=200 aSOFTWARE_NAME[$software_id]='DietPi-Dashboard' aSOFTWARE_DESC[$software_id]='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' # - RISC-V: Missing archive: https://github.com/prometheus/node_exporter/releases aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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: Missing package 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: Missing package 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 only (( $G_HW_MODEL > 19 )) && 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=169 aSOFTWARE_NAME[$software_id]='Google AIY' aSOFTWARE_DESC[$software_id]='voice kit' aSOFTWARE_CATX[$software_id]=10 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#google-aiy' aSOFTWARE_DEPS[$software_id]='5 17 69 130' # RPi only (( $G_HW_MODEL > 9 )) && aSOFTWARE_AVAIL_G_HW_MODEL[$software_id,$G_HW_MODEL]=0 #------------------ software_id=176 aSOFTWARE_NAME[$software_id]='Mycroft AI' aSOFTWARE_DESC[$software_id]='Open Source Voice Assistant' aSOFTWARE_CATX[$software_id]=10 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/hardware_projects/#mycroft-ai' aSOFTWARE_DEPS[$software_id]='5 17' aSOFTWARE_INTERACTIVE[$software_id]=1 #------------------ 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: Missing package 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' # 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' #------------------ 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' #------------------ 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]=-1 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#apache2' aSOFTWARE_CONFLICTS[$software_id]='78 79 81 82 84 85' #------------------ software_id=84 aSOFTWARE_NAME[$software_id]='Lighttpd' aSOFTWARE_DESC[$software_id]='Extremely lightweight webserver' aSOFTWARE_CATX[$software_id]=-1 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]=-1 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]=-1 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#php' #------------------ 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]=12 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/system_security/#lets-encrypt' # 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 89 webserver' aSOFTWARE_INTERACTIVE[$software_id]=1 aSOFTWARE_CONFLICTS[$software_id]='126' # - RISC-V: Missing archive: https://github.com/AdguardTeam/AdGuardHome/releases aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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' # - RISC-V: Missing binary aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ 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]='Efficient, lightweight FTP server' 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]='Very secure FTP 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' # Required to ask for public domain/IP and desired VPN server port aSOFTWARE_INTERACTIVE[$software_id]=1 # Requires the WireGuard kernel module: We do not support DKMS builds anymore, which were required only for legacy kernel versions, which are not supported by WireGuard anymore: https://dietpi.com/forum/t/wireguard-install-failed-now-cant-do-anything-else-with-dietpi-software/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=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' aSOFTWARE_INTERACTIVE[$software_id]=1 # 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' # - Bookworm: No libssl3 support: https://github.com/domoticz/domoticz/issues/5233 aSOFTWARE_AVAIL_G_DISTRO[$software_id,7]=0 #------------------ 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' # 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]='distributed disease research project' aSOFTWARE_CATX[$software_id]=19 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/distributed_projects/#foldinghome' # - ARMv6 - ARMv7 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,2]=0 # - RISC-V: No package: https://download.foldingathome.org/releases/public/release/fahclient/ 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=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' aSOFTWARE_INTERACTIVE[$software_id]=1 #------------------ software_id=186 aSOFTWARE_NAME[$software_id]='IPFS Node' aSOFTWARE_DESC[$software_id]='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: Missing package 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' # File Managers #-------------------------------------------------------------------------------- software_id=3 aSOFTWARE_NAME[$software_id]='MC' aSOFTWARE_DESC[$software_id]='Midnight Commander - a powerful file manager' aSOFTWARE_CATX[$software_id]=22 #------------------ software_id=4 aSOFTWARE_NAME[$software_id]='ViFM' aSOFTWARE_DESC[$software_id]='file manager with vi bindings' aSOFTWARE_CATX[$software_id]=22 # System #-------------------------------------------------------------------------------- software_id=5 aSOFTWARE_NAME[$software_id]='ALSA' aSOFTWARE_DESC[$software_id]='Advanced Linux Sound Architecture' aSOFTWARE_CATX[$software_id]=23 #------------------ software_id=7 aSOFTWARE_NAME[$software_id]='FFmpeg' aSOFTWARE_DESC[$software_id]='Audio & video codec libary and programs' aSOFTWARE_CATX[$software_id]=23 #------------------ software_id=6 aSOFTWARE_NAME[$software_id]='X.Org X Server' aSOFTWARE_DESC[$software_id]='aka X11 - X Window System implementation' aSOFTWARE_CATX[$software_id]=23 #------------------ software_id=170 aSOFTWARE_NAME[$software_id]='UnRAR' aSOFTWARE_DESC[$software_id]='unarchiver for .rar files' aSOFTWARE_CATX[$software_id]=23 # Databases & Data Stores #-------------------------------------------------------------------------------- software_id=87 aSOFTWARE_NAME[$software_id]='SQLite' aSOFTWARE_DESC[$software_id]='Persistent single-file database system' aSOFTWARE_CATX[$software_id]=24 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]=24 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]=24 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]=24 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]=24 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]=24 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/databases/#postgresql' # Network Tools #-------------------------------------------------------------------------------- software_id=10 aSOFTWARE_NAME[$software_id]='iftop' aSOFTWARE_DESC[$software_id]='displays bandwidth usage information' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=11 aSOFTWARE_NAME[$software_id]='IPTraf' aSOFTWARE_DESC[$software_id]='interactive colorful IP LAN monitor' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=12 aSOFTWARE_NAME[$software_id]='Iperf' aSOFTWARE_DESC[$software_id]='internet protocol bandwidth measuring tool' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=13 aSOFTWARE_NAME[$software_id]='MTR-Tiny' aSOFTWARE_DESC[$software_id]='full screen ncurses traceroute tool' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=14 aSOFTWARE_NAME[$software_id]='nLoad' aSOFTWARE_DESC[$software_id]='realtime console network usage monitor' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=15 aSOFTWARE_NAME[$software_id]='tcpdump' aSOFTWARE_DESC[$software_id]='command-line network traffic analyzer' aSOFTWARE_CATX[$software_id]=25 #------------------ software_id=152 aSOFTWARE_NAME[$software_id]='Avahi-Daemon' aSOFTWARE_DESC[$software_id]='Hostname broadcast via mDNS (Zeroconf, Bonjour)' aSOFTWARE_CATX[$software_id]=25 # Development & Programming #-------------------------------------------------------------------------------- software_id=17 aSOFTWARE_NAME[$software_id]='Git' aSOFTWARE_DESC[$software_id]='Clone and manage Git repositories locally' aSOFTWARE_CATX[$software_id]=26 #------------------ 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]=26 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]=26 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#vscodium' aSOFTWARE_DEPS[$software_id]='5 6 17' # - RISC-V: Missing package 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]=26 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]=26 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]=26 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]=26 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#nodejs' #------------------ software_id=150 aSOFTWARE_NAME[$software_id]='Mono' aSOFTWARE_DESC[$software_id]='Runtime libraries and repository' aSOFTWARE_CATX[$software_id]=26 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/programming/#mono' #------------------ software_id=34 aSOFTWARE_NAME[$software_id]='PHP Composer' aSOFTWARE_DESC[$software_id]='Package manager for PHP' aSOFTWARE_CATX[$software_id]=26 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/webserver_stack/#php-composer' aSOFTWARE_DEPS[$software_id]='89' # Text Editors #-------------------------------------------------------------------------------- software_id=18 aSOFTWARE_NAME[$software_id]='Emacs' aSOFTWARE_DESC[$software_id]='GNU Emacs editor' aSOFTWARE_CATX[$software_id]=27 #------------------ software_id=19 aSOFTWARE_NAME[$software_id]='Jed' aSOFTWARE_DESC[$software_id]='editor for programmers' aSOFTWARE_CATX[$software_id]=27 #------------------ software_id=20 aSOFTWARE_NAME[$software_id]='Vim' aSOFTWARE_DESC[$software_id]='vi enhanced text editor' aSOFTWARE_CATX[$software_id]=27 #------------------ software_id=21 aSOFTWARE_NAME[$software_id]='Vim-Tiny' aSOFTWARE_DESC[$software_id]='compact release of vim' aSOFTWARE_CATX[$software_id]=27 #------------------ software_id=127 aSOFTWARE_NAME[$software_id]='Neovim' aSOFTWARE_DESC[$software_id]='heavily refactored vim fork' aSOFTWARE_CATX[$software_id]=27 # Desktop Utilities #-------------------------------------------------------------------------------- software_id=22 aSOFTWARE_NAME[$software_id]='QuiteRSS' aSOFTWARE_DESC[$software_id]='cross-platform, free rss reader' aSOFTWARE_CATX[$software_id]=28 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#quiterss' aSOFTWARE_DEPS[$software_id]='6' #------------------ software_id=113 aSOFTWARE_NAME[$software_id]='Chromium' aSOFTWARE_DESC[$software_id]='web browser for desktop or autostart' aSOFTWARE_CATX[$software_id]=28 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#chromium' aSOFTWARE_DEPS[$software_id]='5 6' # - ARMv6 since Bullseye: https://github.com/RPi-Distro/chromium-browser/issues/21 (( $G_DISTRO < 6 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 # - RISC-V: Missing package 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]=28 aSOFTWARE_DOCS[$software_id]='https://dietpi.com/docs/software/desktop/#firefox' aSOFTWARE_DEPS[$software_id]='5 6' # - ARMv6 since Bullseye: https://github.com/RPi-Distro/chromium-browser/issues/21#issuecomment-997044303 (( $G_DISTRO < 6 )) || aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,1]=0 # - RISC-V: Missing package aSOFTWARE_AVAIL_G_HW_ARCH[$software_id,11]=0 #------------------ software_id=174 aSOFTWARE_NAME[$software_id]='GIMP' aSOFTWARE_DESC[$software_id]='mspaint on steroids' aSOFTWARE_CATX[$software_id]=28 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]=28 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 Bullseye+ systems: https://github.com/RPi-Distro/chromium-browser/issues/21 (( $G_HW_ARCH == 1 && $G_DISTRO > 5 )) && 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 -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 local type=${file##*.} # Grab file type from file name to special handle deb|zip|tar(.gz|.bz2)|tgz|tbz2|txz|7z|xz # 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" type= G_EXEC cd "$G_WORKING_DIR" # Failsafe # Add decompressor to deps list if missing [[ $type == 'xz' || $type == 'txz' ]] && ! command -v xz > /dev/null && aDEPS+=('xz-utils') # 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 [[ $type == 'xz' ]] && G_EXEC xz -df "$file" && file=${file%.xz} if [[ $type == 'deb' ]] then G_AGI "./$file" elif [[ $type == 'zip' ]] then G_EXEC unzip -o "$file" ${target:+"-d$target"} elif [[ $type =~ ^(t?gz|t?bz2|txz|tar)$ ]] then G_EXEC tar xf "$file" ${target:+"--one-top-level=$target"} elif [[ $type == '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 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 SysV $1 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 -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 fi } # $1: Software name, so config can be created and removed per-software Enable_IP_forwarding() { G_DIETPI-NOTIFY 2 'Enabling IP forwarding to allow access across network interfaces' 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" sysctl 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 } To_Install() { (( ${aSOFTWARE_INSTALL_STATE[$1]} == 1 )) || return 1 G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "Installing ${aSOFTWARE_NAME[$1]}: ${aSOFTWARE_DESC[$1]}" software_id=$1 shift [[ $1 ]] || return 0 [[ $(readlink -m "/etc/systemd/system/$1.service") == '/dev/null' ]] && G_EXEC systemctl unmask "$1" aENABLE_SERVICES+=("$@") } 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 # X.Org X Server then # Generic X server + Mesa OpenGL libraries and utilities aDEPS=('xserver-xorg-core' 'xserver-xorg-input-libinput' 'xinit' 'dbus-user-session' 'xfonts-base' 'x11-xserver-utils' 'x11-utils') # 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') # 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 dps_index=$software_id Download_Install '98-dietpi-disable_dpms.conf' /etc/X11/xorg.conf.d/98-dietpi-disable_dpms.conf 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 4 # Vifm then G_AGI vifm fi if To_Install 20 # Vim then G_AGI vim fi if To_Install 21 # Vim-Tiny then G_AGI vim-tiny fi if To_Install 127 # Neovim then G_AGI neovim fi if To_Install 18 # Emacs then G_AGI emacs fi if To_Install 12 then G_AGI iperf fi if To_Install 3 # Midnight Commander then G_AGI mc fi if To_Install 19 then G_AGI jed fi if To_Install 10 then G_AGI iftop fi if To_Install 11 then G_AGI iptraf fi if To_Install 13 then G_AGI mtr-tiny fi if To_Install 14 then G_AGI nload fi if To_Install 15 then G_AGI tcpdump 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 # On Buster, Dropbear packages have been split: Install "dropbear-run" only to skip "dropbear-initramfs" # With Bullseye, "dropbear-run" has become a transitional dummy package for "dropbear" which does not include "dropbear-initramfs" anymore. if (( $G_DISTRO > 5 )) then G_AGI dropbear else G_AGI dropbear-run fi # 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 -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 [[ -d '/mnt/dietpi_userdata/beets' ]] || G_EXEC mkdir /mnt/dietpi_userdata/beets [[ -f '/mnt/dietpi_userdata/beets/config.yaml' ]] || 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 # Raspberry Pi Bullseye: Enable hardware codecs (( $G_HW_MODEL > 9 )) || (( $G_DISTRO < 6 )) || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1 G_AGI ffmpeg fi if To_Install 196 # Java JRE then # ARMv6 if (( $G_HW_ARCH == 1 )) then local version=8 # Buster elif (( $G_DISTRO == 5 )) then local version=11 # Bullseye else local version=17 fi G_AGI "openjdk-$version-jre-headless" fi if To_Install 8 # Java JDK then # ARMv6 if (( $G_HW_ARCH == 1 )) then local version=8 # Buster elif (( $G_DISTRO == 5 )) then local version=11 # Bullseye else local version=17 fi G_AGI "openjdk-$version-jdk-headless" fi if To_Install 9 # Node.js then # Deps: https://github.com/MichaIng/DietPi/issues/3614 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 unofficial=() (( $G_HW_ARCH == 1 || $G_HW_ARCH == 11 )) && unofficial=('-u') G_EXEC_OUTPUT=1 G_EXEC ./node-install.sh "${unofficial[@]}" G_EXEC rm node-install.sh fi if To_Install 130 # Python 3 then # Workaround for pip v23 >> /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\]' # Disable cache 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\]' # Workaround for missing and failing numpy >=v1.21.5 build: https://github.com/piwheels/packages/issues/287#issuecomment-1036500818 if (( $G_HW_ARCH < 3 && $G_DISTRO == 5 )) then G_EXEC eval 'echo "numpy<1.21.5; python_version=='\''3.7'\''" > /etc/pip-constraints.txt' G_CONFIG_INJECT '\[install\]' '[install]' /etc/pip.conf G_CONFIG_INJECT 'constraint[[:blank:]]*=[[:blank:]]*/etc/pip-constraints.txt' 'constraint=/etc/pip-constraints.txt' /etc/pip.conf '\[install\]' fi # 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 then # https://www.mono-project.com/download/stable/#download-lin-debian # 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_HW_MODEL < 10 )) && (( $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 # APT package G_AGI mono-devel G_EXEC rm -f /tmp/mono* # https://github.com/MichaIng/DietPi/issues/1877#issuecomment-403856446 fi if To_Install 188 # Go then # https://go.dev/doc/install#install if (( $G_HW_ARCH == 11 )) then G_AGI golang-go else case $G_HW_ARCH in 3) local arch='arm64';; 10) local arch='amd64';; *) local arch='armv6l';; esac # Get latest version local file=$(curl -sSfL 'https://go.dev/dl/?mode=json' | grep -wo "go[0-9.]*\.linux-$arch\.tar\.gz" | head -1) [[ $file ]] || { file="go1.20.1.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 fi 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.org/raspbian/pool/non-free/u/unrar-nonfree/ if (( $G_HW_ARCH == 1 )) then G_AGI unrar-free elif (( $G_HW_MODEL < 10 )) && (( $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 # RPi: Block packages from RPi desktop which conflict with a native LXDE desktop: # - https://github.com/MichaIng/DietPi/issues/1558#issuecomment-691206284 # - https://github.com/MichaIng/DietPi/issues/4687 (( $G_HW_MODEL > 9 )) || cat << '_EOF_' > /etc/apt/preferences.d/dietpi-lxde Package: openbox* obconf* libob* pcmanfm* libfm* gtk-* libgtk* libgail* gir1.2-gtk-* lx* Pin: origin archive.raspberrypi.org Pin-Priority: -1 _EOF_ # Bullseye: https://github.com/MichaIng/DietPi/issues/4687 local apackages=() (( $G_DISTRO > 5 )) && apackages+=('librsvg2-common') # 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 G_AGI lxde lxhotkey-plugin-openbox upower "${apackages[@]}" [[ $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_HW_MODEL > 9 )) || chromium='chromium-browser' G_EXEC sed -i "s/firefox-esr/$chromium/" /etc/xdg/lxpanel/LXDE/panels/panel else G_EXEC sed -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 '[0-9]*' '1' /etc/xdg/openbox/LXDE/rc.xml '' G_CONFIG_INJECT '.*' 'no' /etc/xdg/openbox/LXDE/rc.xml '' # 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 G_AGI lxqt qterminal xarchiver lxde-icon-theme upower xscreensaver featherpad 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 upower policykit-1 xterm Create_Desktop_Shared_Items fi if To_Install 25 # Xfce then G_AGI xfce4 xfce4-terminal gnome-icon-theme tango-icon-theme upower policykit-1 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 local version='8.4.2_1' # https://downloads.nomachine.com/ case $G_HW_ARCH in 1) local url="Raspberry/nomachine_${version}_armv6hf";; 2) local url="Arm/nomachine_${version}_armhf";; 3) local url="Arm/nomachine_${version}_arm64";; *) local url="Linux/nomachine_${version}_amd64";; esac Download_Install "https://download.nomachine.com/download/${version%.*}/$url.deb" aSTART_SERVICES+=('nxserver') fi if To_Install 200 # DietPi-Dashboard then # Stable release or nightly? 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 # Backend only? local backend=$(sed -n '/^[[:blank:]]*SOFTWARE_DIETPI_DASHBOARD_BACKEND=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) [[ $backend == 1 ]] && G_WHIP_DEFAULT_ITEM='Yes' || G_WHIP_DEFAULT_ITEM='No' G_WHIP_BUTTON_OK_TEXT='Yes' G_WHIP_BUTTON_CANCEL_TEXT='No' G_WHIP_YESNO 'Would you like to install only the backend, for viewing on another dashboard page?' && backend='Yes' || backend='No' [[ $backend == 'Yes' ]] && backend='-backend' || backend= # Download binary and set config URL local url if [[ $version == 'Stable' ]] then Download_Install "$(curl -sSfL 'https://api.github.com/repos/ravenclaw900/dietpi-dashboard/releases/latest' | mawk -F\" "/\"browser_download_url\": \".*dietpi-dashboard-$G_HW_ARCH_NAME$backend\"/{print \$4}")" /opt/dietpi-dashboard/dietpi-dashboard url="https://raw.githubusercontent.com/ravenclaw900/DietPi-Dashboard/$(curl -sSfL 'https://api.github.com/repos/ravenclaw900/dietpi-dashboard/releases/latest' | mawk -F\" '/"tag_name": ".*"/{print $4}')/config.toml" elif [[ $version == 'Nightly' ]] then Download_Install "https://nightly.link/ravenclaw900/DietPi-Dashboard/workflows/push-build/main/dietpi-dashboard-$G_HW_ARCH_NAME$backend.zip" /opt/dietpi-dashboard url='https://raw.githubusercontent.com/ravenclaw900/DietPi-Dashboard/main/config.toml' fi G_EXEC chmod +x /opt/dietpi-dashboard/dietpi-dashboard # Config if [[ ! -f '/opt/dietpi-dashboard/config.toml' ]] then G_EXEC curl -sSfL "$url" -o /opt/dietpi-dashboard/config.toml # Enable password protection with global software password by default G_CONFIG_INJECT 'pass[[:blank:]]' 'pass = true' /opt/dietpi-dashboard/config.toml G_CONFIG_INJECT 'hash[[:blank:]]' "hash = \"$(echo -n "$GLOBAL_PW" | sha512sum | mawk '{print $1}')\"" /opt/dietpi-dashboard/config.toml G_CONFIG_INJECT 'secret[[:blank:]]' "secret = \"$(openssl rand -hex 32)\"" /opt/dietpi-dashboard/config.toml fi # Service cat << '_EOF_' > /etc/systemd/system/dietpi-dashboard.service [Unit] Description=Web Dashboard (DietPi) Wants=network-online.target After=network-online.target [Service] ExecStart=/opt/dietpi-dashboard/dietpi-dashboard # TTY input is required for web terminal input StandardInput=tty TTYPath=/dev/tty42 StandardOutput=journal [Install] WantedBy=multi-user.target _EOF_ # Service needs to be started manually as dietpi-services must not control it to prevent it from stopping during software installs done via dashboard itself. aSTART_SERVICES+=('dietpi-dashboard') 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';; *) local arch='amd64';; esac # Download binary local fallback_url="https://github.com/prometheus/node_exporter/releases/download/v1.5.0/node_exporter-1.5.0.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 '"port-forwarding-enabled"' ' "port-forwarding-enabled": true,' /etc/transmission-daemon/settings.json '^\{$' G_CONFIG_INJECT '"encryption"' ' "encryption": 2,' /etc/transmission-daemon/settings.json '^\{$' G_CONFIG_INJECT '"idle-seeding-limit"' ' "idle-seeding-limit": 1,' /etc/transmission-daemon/settings.json '^\{$' G_CONFIG_INJECT '"idle-seeding-limit-enabled"' ' "idle-seeding-limit-enabled": true,' /etc/transmission-daemon/settings.json '^\{$' G_CONFIG_INJECT '"ratio-limit"' ' "ratio-limit": 1.1,' /etc/transmission-daemon/settings.json '^\{$' G_CONFIG_INJECT '"ratio-limit-enabled"' ' "ratio-limit-enabled": true,' /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 '^\{$' G_CONFIG_INJECT '"message-level"' ' "message-level": 0,' /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 # Config G_BACKUP_FP /etc/proftpd/proftpd.conf dps_index=$software_id Download_Install 'conf' /etc/proftpd/proftpd.conf # Do not allow root access via FTP G_EXEC sed -i 's/^[[:blank:]]*root/#root/' /etc/ftpusers # Bullseye: Fix ident lookup: https://github.com/MichaIng/DietPi/issues/4666 (( $G_DISTRO < 6 )) || G_EXEC sed -i '/IdentLookups/c\\nIdentLookups off\n' /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 [[ -d '/run/samba-cache' ]] || G_EXEC mkdir /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 if [[ ! -f '/etc/samba/smb.conf' ]] then 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 fi G_AGI samba G_EXEC systemctl stop nmbd smbd echo -e "$GLOBAL_PW\n$GLOBAL_PW" | smbpasswd -s -a dietpi 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 -i 's/^[[:blank:]]*root/#root/' /etc/ftpusers fi if To_Install 109 nfs-kernel-server # NFS Server then G_AGI nfs-kernel-server G_EXEC systemctl stop nfs-kernel-server [[ -d '/etc/exports.d' ]] || G_EXEC mkdir /etc/exports.d [[ -f '/etc/exports.d/dietpi.exports' ]] || echo '/mnt/dietpi_userdata *(rw,async,no_root_squash,fsid=0,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 [[ -d '/etc/apache2/sites-available' ]] || G_EXEC mkdir -p /etc/apache2/sites-available cat << _EOF_ > /etc/apache2/sites-available/000-default.conf # /etc/apache2/sites-available/000-default.conf ServerName $(G_GET_NET ip) _EOF_ # Otherwise assure that the webroot is changed, as all our install options depend on it. else G_EXEC sed -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:local7 # 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 "1; mode=block" 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 [[ -f '/var/www/html/index.html' && ! -f '/var/www/index.html' ]] && G_EXEC mv /var/www/html/index.html /var/www/ [[ -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') # 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 [[ -d '/etc/nginx/sites-dietpi' ]] || G_EXEC mkdir /etc/nginx/sites-dietpi G_BACKUP_FP /etc/nginx/nginx.conf dps_index=$software_id Download_Install 'nginx.conf' /etc/nginx/nginx.conf # Adjust socket name to PHP version G_EXEC sed -i "s#/run/php/php.*-fpm.sock#/run/php/php$PHP_VERSION-fpm.sock#g" /etc/nginx/nginx.conf # CPU core count G_EXEC sed -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 [[ -f '/var/www/html/index.nginx-debian.html' ]] && G_EXEC mv /var/www/html/index.nginx-debian.html /var/www/ [[ -d '/var/www/html' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/www/html fi if To_Install 84 lighttpd # Lighttpd then # Migrate existing configs in case of distro upgrades local deflate=() openssl=() if [[ -f '/etc/lighttpd/lighttpd.conf' ]] then # Buster: "create-mime.assign.pl" has been renamed to "create-mime.conf.pl" if grep -q 'create-mime\.assign\.pl' /etc/lighttpd/lighttpd.conf then G_DIETPI-NOTIFY 2 'Buster upgrade detected: Migrating from "create-mime.assign.pl" to "create-mime.conf.pl"' G_EXEC sed -i 's/create-mime\.assign\.pl/create-mime.conf.pl/' /etc/lighttpd/lighttpd.conf fi # Bullseye: mod_compress has been superseded by mod_deflate if (( $G_DISTRO > 5 )) && grep -q '^[[:blank:]]*"mod_compress",$' /etc/lighttpd/lighttpd.conf then G_DIETPI-NOTIFY 2 'Bullseye upgrade detected: Migrating from mod_compress to mod_deflate' G_EXEC sed -Ei '/^compress\..*=[[:blank:]]*["(].*[")]$/d' /etc/lighttpd/lighttpd.conf G_EXEC sed -i '/^[[:blank:]]*"mod_compress",$/d' /etc/lighttpd/lighttpd.conf deflate=('lighttpd-mod-deflate') fi # Bullseye: Install OpenSSL module if DietPi-LetsEncrypt was used if [[ $G_DISTRO -gt 5 && -f '/boot/dietpi/.dietpi-letsencrypt' ]] then G_DIETPI-NOTIFY 2 'DietPi-LetsEncrypt usage detected: Installing OpenSSL module' openssl=('lighttpd-mod-openssl') [[ -f '/etc/lighttpd/conf-available/50-dietpi-https.conf' ]] && ! grep -q '"mod_openssl"' /etc/lighttpd/conf-available/50-dietpi-https.conf && G_EXEC sed -i '1iserver.modules += ( "mod_openssl" )' /etc/lighttpd/conf-available/50-dietpi-https.conf fi # Bullseye: Remove obsolete socket version string from FPM module if [[ $G_DISTRO -gt 5 && -f '/etc/lighttpd/conf-available/15-fastcgi-php-fpm.conf' ]] && grep -q 'php.\..-fpm\.sock' /etc/lighttpd/conf-available/15-fastcgi-php-fpm.conf then G_DIETPI-NOTIFY 2 'Bullseye upgrade detected: Removing obsolete socket version string from FPM module' G_EXEC sed -i 's/php.\..-fpm\.sock/php-fpm.sock/' /etc/lighttpd/conf-available/15-fastcgi-php-fpm.conf fi fi # perl is required for lighty-enable-mod, it has been degraded to recommends only with Buster. G_AGI lighttpd perl "${deflate[@]}" "${openssl[@]}" G_EXEC systemctl stop lighttpd Remove_SysV lighttpd # Enable mod_deflate, if flagged [[ ${deflate[0]} && ! -f '/etc/lighttpd/conf-enabled/20-deflate.conf' ]] && G_EXEC lighty-enable-mod deflate # 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 G_EXEC mv /var/www/html/index.lighttpd.html /var/www/ G_EXEC sed -i 's|/var/www/html|/var/www|' /etc/lighttpd/lighttpd.conf fi [[ -d '/var/www/html' ]] && G_EXEC rmdir --ignore-fail-on-non-empty /var/www/html # Configure PHP handler # - Buster: Create missing fastcgi-php-fpm module (( $G_DISTRO < 6 )) && cat << _EOF_ > /etc/lighttpd/conf-available/15-fastcgi-php-fpm.conf # -*- depends: fastcgi -*- # -*- conflicts: fastcgi-php -*- # /usr/share/doc/lighttpd/fastcgi.txt.gz # http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ConfigurationOptions#mod_fastcgi-fastcgi ## Use PHP-FPM service for PHP via FastCGI fastcgi.server += ( ".php" => (( "socket" => "/run/php/php$PHP_VERSION-fpm.sock", "broken-scriptfilename" => "enable" )) ) _EOF_ # - 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 [[ $(stat -c '%U' /mnt/dietpi_userdata/mysql/mysql) == 'mysql' ]] || G_EXEC chown -R mysql:mysql /mnt/dietpi_userdata/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' 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 # - 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 all available PHP modules local amodules=() mapfile -t amodules < <(find "/etc/php/$PHP_VERSION/mods-available" -type f -name '*.ini' -printf '%f\n') G_EXEC phpenmod "${amodules[@]%.ini}" unset -v amodules # 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/latest' | mawk -F\" '/"name": /{print $4}') [[ $version ]] || { version='5.2.1'; 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"; } # ToDo: Add xz support Download_Install "https://files.phpmyadmin.net/phpMyAdmin/$version/phpMyAdmin-$version-english.tar.gz" # - 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 [[ -d '/var/www/phpmyadmin/tmp' ]] || G_EXEC mkdir /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 then # APT deps for Synapse with PostgreSQL case $G_HW_ARCH in [12]|11) if (( $G_DISTRO < 7 )) then G_AGI libtiff5 libopenjp2-7 libxcb1 # ARMv6/7: Runtime libs for Pillow from piwheels (libtiff5 pulls libjpeg62-turbo) else # Bookworm: Most wheels need to be compiled: gcc and libffi-dev for cffi, Rust for matrix-synapse, libpq-dev for psycopg2, make for PyNaCl, libjpeg62-turbo-dev for Pillow G_AGI gcc libffi-dev libpq-dev make libjpeg62-turbo-dev G_EXEC curl -sSf 'https://sh.rustup.rs/' -o rustup-init.sh G_EXEC chmod +x rustup-init.sh G_EXEC_OUTPUT=1 G_EXEC ./rustup-init.sh -y --profile minimal G_EXEC rm rustup-init.sh export PATH="/root/.cargo/bin:$PATH" fi ;; *) G_AGI gcc libpq-dev;; # ARMv8/x86_64: psycopg2 needs to be compiled esac # 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=$(command -v 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 [[ $(sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='synapse'") != 1 ]] then G_EXEC sudo -u postgres psql -c "CREATE ROLE synapse WITH LOGIN PASSWORD '$synapse_pass';" else G_EXEC sudo -u postgres psql -c "ALTER ROLE synapse WITH PASSWORD '$synapse_pass';" fi if [[ $(sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname='synapse'") != 1 ]] then G_EXEC sudo -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 local invalid_text= while : do if G_WHIP_INPUTBOX "${invalid_text}Please enter the name for this homeserver.\nIt is recommended that this be the domain that this server will be hosted on." then local servername=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] Please enter a name for your Matrix homserver.\n\n' fi done if G_WHIP_BUTTON_OK_TEXT='Yes' G_WHIP_BUTTON_CANCEL_TEXT='No' G_WHIP_YESNO 'Would you like to report basic anonymous analytics, like number of users, to the Matrix foundation?' then local analytics='yes' else local analytics='no' fi 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 "$analytics" # 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 -i 's/ handlers: \[.*\]$/ handlers: [console]/' "$servername.log.config" G_EXEC sed -i 's/ level: .*/ level: WARNING/' "$servername.log.config" # Permissions G_EXEC chown -R synapse:synapse . G_EXEC chmod -R 0660 homeserver.yaml{,.d/*.yaml} G_EXEC chmod 0770 homeserver.yaml.d # Register new user (interactive) G_EXEC systemctl daemon-reload G_EXEC systemctl start synapse G_EXEC_OUTPUT=1 G_EXEC register_new_matrix_user -c homeserver.yaml 'http://127.0.0.1:8008' G_EXEC cd "$G_WORKING_DIR" else # Permissions G_EXEC chown -R synapse:synapse /mnt/dietpi_userdata/synapse G_EXEC chmod -R 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 --no-daemon _EOF_ 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 -Ei 's/^[[:blank:]]*log_file[[:blank:]]+/#log_file /' /etc/mpd.conf # - PID file is not required for systemd G_EXEC sed -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 -Ei 's/^[[:blank:]]*user[[:blank:]]+/#user /' /etc/mpd.conf G_EXEC sed -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 Download_Install 'https://download.phpbb.com/pub/release/3.3/3.3.10/phpBB-3.3.10.tar.bz2' # Files are shipped with strange 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 -wo 'yacy_v[0-9._]*\.tar\.gz' | head -1) [[ $file ]] || { file='yacy_v1.924_20210209_10069.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_ fi if To_Install 186 ipfs # IPFS Node then case $G_HW_ARCH in 3) local arch='arm64';; 10) local arch='amd64';; *) local arch='arm';; esac # Download latest version local version=$(curl -sSfL 'https://dist.ipfs.io/go-ipfs/versions' | tail -1) [[ $version ]] || { version='v0.18.1'; 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://dist.ipfs.io/go-ipfs/$version/go-ipfs_${version}_linux-$arch.tar.gz" # Install G_EXEC_OUTPUT=1 G_EXEC go-ipfs/install.sh # Data and config directory [[ -d '/mnt/dietpi_userdata/ipfs' ]] || G_EXEC mkdir /mnt/dietpi_userdata/ipfs # User Create_User -d /mnt/dietpi_userdata/ipfs ipfs # Service cat << '_EOF_' > /etc/systemd/system/ipfs.service [Unit] Description=IPFS (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 packet receive buffer: https://github.com/lucas-clemente/quic-go/wiki/UDP-Receive-Buffer-Size G_EXEC eval "echo 'net.core.rmem_max=2500000' > /etc/sysctl.d/dietpi-ipfs.conf" G_EXEC sysctl -w net.core.rmem_max=2500000 fi if To_Install 16 microblog-pub # microblog.pub then local micro_name='microblog-pub' local micro_python_version='3.10.9' 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" # User Create_User -d "$micro_data_dir" "$micro_name" # Dependencies # - gcc, libc6-dev, make, libssl-dev, zlib1g-dev for Python build. libbz2-dev; libreadline-dev, libsqlite3-dev, liblzma-dev to suppress warnings; libffi-dev for ModuleNotFoundError: No module named '_ctypes' aDEPS=('gcc' 'libc6-dev' 'make' 'libssl-dev' 'zlib1g-dev' 'libbz2-dev' 'libreadline-dev' 'libsqlite3-dev' 'liblzma-dev' 'libffi-dev') # 1. Create a Python 3.10 environment via pyenv # - https://python-poetry.org/docs/managing-environments/ Download_Install 'https://github.com/pyenv/pyenv/archive/master.tar.gz' # - 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" # 2. 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 -i 's/uvicorn app/uvicorn --host 0.0.0.0 --port 8007 app/' "$micro_data_dir/misc/supervisord.conf" G_EXEC sed -i 's/8000/8007/' "$micro_data_dir/data/tests.toml" fi # 3. Disable pip 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'" # 4. 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 PS1=\"(microblog.pub) \$PS1\"" > "$micro_pyenv_activate_file" # 5. Install Python 3.10 and Poetry G_EXEC chown -R "$micro_name:$micro_name" "$micro_pyenv_dir" "$micro_data_dir" G_EXEC_DESC='Installing Python with Poetry into pyenv' G_EXEC_OUTPUT=1 G_EXEC sudo -u "$micro_name" dash -c " . $micro_pyenv_activate_file || exit 1 pyenv install $micro_python_version || exit 1 pyenv local $micro_python_version || exit 1 pip3 install -U pip setuptools wheel || exit 1 pip3 install poetry || exit 1 poetry install || exit 1 # Skip these for now: #poetry run inv configuration-wizard #poetry run inv migrate-db poetry env info | grep -oP '(?<=^Path:\s).*/virtualenvs/.*' > '$micro_virtualenv'" read -r VENV_DIR < "$micro_virtualenv" # shellcheck disable=SC2016 G_EXEC_DESC='Checking for Poetry virtualenv' G_EXEC eval '[[ $VENV_DIR ]]' G_EXEC rm "$micro_virtualenv" # 6. Generate functions for later configuration and install to profile cat << _EOF_ > "$micro_functions" #!/bin/dash microblog-pub() { case \$1 in v*) sudo -u '$micro_name' bash --init-file '$micro_pyenv_activate_file';; # venv c*) sudo -u '$micro_name' dash -c '. $micro_pyenv_activate_file; poetry run inv configuration-wizard && poetry run inv migrate-db';; # configure u*) sudo -u '$micro_name' dash -c '. $micro_pyenv_activate_file; git pull && poetry run inv update';; # update *) echo 'microblog.pub helper script usage: microblog-pub 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_ # 7. Generate systemd service cat << _EOF_ > "$micro_systemd" [Unit] Description=microblog.pub (DietPi) Wants=network-online.target After=network-online.target [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 arch=$(dpkg --print-architecture) local fallback_url="https://download.foldingathome.org/releases/public/release/fahclient/debian-stable-${arch/amd64/64bit}/v7.6/latest.deb" Download_Install "$(curl -sSfL 'https://download.foldingathome.org/' | mawk -F\" "/^ *\"url\": \".*\/fahclient_.*_$arch\.deb\"$/{print \$4}")" # 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 [[ -d '/mnt/dietpi_userdata/fahclient' ]] || G_EXEC mkdir /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 # ownCloud 10.12 drops PHP 7.3 support: https://github.com/owncloud/core/pull/40394 if (( $G_DISTRO < 6 )) then G_DIETPI-NOTIFY 2 'Downloading latest ownCloud 10.11, since ownCloud 10.12 does not support PHP7.3 anymore' Download_Install 'https://download.owncloud.com/server/stable/owncloud-10.11.0.tar.bz2' /var/www else Download_Install 'https://download.owncloud.com/server/stable/owncloud-latest.tar.bz2' /var/www fi 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' if [[ -f $owncloud_conf ]]; then owncloud_conf+='.dietpi-new' G_WHIP_MSG "Existing ownCloud Apache configuration found, will preserve the old one and save the new one for review and comparison to: $owncloud_conf" fi dps_index=$software_id Download_Install 'apache.owncloud.conf' "$owncloud_conf" a2ensite dietpi-owncloud 1> /dev/null # Cal/CardDAV redirects to ownCloud DAV endpoint if [[ ! -f '/etc/apache2/conf-available/dietpi-dav_redirect.conf' ]]; then 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 fi 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_.+",' G_CONFIG_INJECT '"mod_setenv",' ' "mod_setenv",' /etc/lighttpd/lighttpd.conf '"mod_.+",' # Move ownCloud configuration file in place and activate it owncloud_conf='/etc/lighttpd/conf-available/99-dietpi-owncloud.conf' if [[ -f $owncloud_conf ]]; then owncloud_conf+='.dietpi-new' G_WHIP_MSG "Existing ownCloud Lighttpd configuration found, will preserve the old one and save the new one for review and comparison to: $owncloud_conf" fi 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 if [[ ! -f '/etc/lighttpd/conf-enabled/99-dietpi-dav_redirect.conf' ]]; then 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 G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already G_EXEC lighty-enable-mod dietpi-dav_redirect fi 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' if [[ -f $owncloud_conf ]]; then owncloud_conf+='.dietpi-new' G_WHIP_MSG "Existing ownCloud Nginx configuration found, will preserve the old one and save the new one for review and comparison to: $owncloud_conf" fi dps_index=$software_id Download_Install 'nginx.owncloud.conf' "$owncloud_conf" # Cal/CardDAV redirects to ownCloud DAV endpoint if [[ ! -f '/etc/nginx/sites-dietpi/dietpi-dav_redirect.conf' ]]; then 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 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(){ sudo -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) # - Failsafe: Use non-blocking entropy source, if /dev/random fails (( ${#oc_password} == 30 )) || oc_password=$(tr -dc '[:alnum:]' < /dev/urandom | 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 -i "/0 => 'localhost'/a 1 => '$(G_GET_NET ip)'," "$config_php" sed -i "/1 => '/a 2 => '$HOSTNAME'," "$config_php" fi # Set CLI URL to ownCloud sub directory: G_EXEC sed -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 local version='latest' # Nextcloud 24 doesn't support PHP7.3 anymore: https://github.com/nextcloud/server/pull/29286 if (( $G_DISTRO < 6 )) then G_DIETPI-NOTIFY 2 'Downloading latest Nextcloud 23, since Nextcloud 24 does not support PHP7.3 anymore' version='latest-23' # Nextcloud 26 doesn't support PHP7.4 anymore: https://github.com/nextcloud/server/pull/34997 elif (( $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 -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 -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\napc.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' if [[ -f $nextcloud_conf ]]; then nextcloud_conf+='.dietpi-new' G_WHIP_MSG "Existing Nextcloud Apache configuration found, will preserve the old one and save the new one for review and comparison to: $nextcloud_conf" fi dps_index=$software_id Download_Install 'apache.nextcloud.conf' "$nextcloud_conf" a2ensite dietpi-nextcloud 1> /dev/null # Cal/CardDAV redirects to Nextcloud DAV endpoint if [[ ! -f '/etc/apache2/conf-available/dietpi-dav_redirect.conf' ]]; then 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 fi 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_.+",' G_CONFIG_INJECT '"mod_setenv",' ' "mod_setenv",' /etc/lighttpd/lighttpd.conf '"mod_.+",' # Move Nextcloud configuration file in place and activate it nextcloud_conf='/etc/lighttpd/conf-available/99-dietpi-nextcloud.conf' if [[ -f $nextcloud_conf ]]; then nextcloud_conf+='.dietpi-new' G_WHIP_MSG "Existing Nextcloud Lighttpd configuration found, will preserve the old one and save the new one for review and comparison to: $nextcloud_conf" fi 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 if [[ ! -f '/etc/lighttpd/conf-enabled/99-dietpi-dav_redirect.conf' ]]; then 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 G_EXEC_POST_FUNC(){ [[ $exit_code == 2 ]] && exit_code=0; } # Do not fail if modules are enabled already G_EXEC lighty-enable-mod dietpi-dav_redirect fi 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 local nextcloud_conf='/etc/nginx/sites-dietpi/dietpi-nextcloud.conf' if [[ -f $nextcloud_conf ]]; then nextcloud_conf+='.dietpi-new' G_WHIP_MSG "Existing Nextcloud Nginx configuration found, will preserve the old one and save the new one for review and comparison to: $nextcloud_conf" fi dps_index=$software_id Download_Install 'nginx.nextcloud.conf' "$nextcloud_conf" # Cal/CardDAV redirects to Nextcloud DAV endpoint if [[ ! -f '/etc/nginx/sites-dietpi/dietpi-dav_redirect.conf' ]]; then 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 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(){ sudo -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) # - Failsafe: Use non-blocking entropy source, if /dev/random fails (( ${#nc_password} == 30 )) || nc_password=$(tr -dc '[:alnum:]' < /dev/urandom | 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 -i "/0 => 'localhost'/a 1 => '*'," "$config_php" # Set CLI URL to Nextcloud sub directory: G_EXEC sed -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 local invalid_text= local domain=$(hostname -f) while : do G_WHIP_DEFAULT_ITEM=$domain if G_WHIP_INPUTBOX "${invalid_text}Please enter your server's external domain to allow Nextcloud Talk access your TURN server:" then domain=${G_WHIP_RETURNED_VALUE#http*://} break else invalid_text='[ERROR] This input is required!\n\n' fi done invalid_text= local port=3478 while : do G_WHIP_DEFAULT_ITEM=$port if G_WHIP_INPUTBOX "${invalid_text}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" && disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 0 then port=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n' fi done # 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 -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 config:app:set spreed stun_servers --value="[\"$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 config:app:set spreed turn_servers --value="[{\"server\":\"$domain:$port\",\"secret\":\"$secret\",\"protocols\":\"udp,tcp\"}]" | sed 's/"secret":".*","protocols"/"secret":"","protocols"/' unset -v secret domain port invalid_text fi if To_Install 32 ympd # ympd then Download_Install 'https://dietpi.com/downloads/binaries/all/ympd_1.2.3.7z' case $G_HW_ARCH in 1) local arch='armv6';; 2) local arch='armv7';; 3) local arch='armv8';; *) local arch='amd64';; esac # We have no Buster binaries yet, so always use Stretch binaries G_EXEC mv "ympd_${arch}_stretch" /usr/bin/ympd G_EXEC chmod +x /usr/bin/ympd G_EXEC rm ympd_* # User Create_User -g dietpi ympd # Service cat << '_EOF_' > /etc/systemd/system/ympd.service [Unit] Description=ympd (DietPi) After=mpd.service [Service] User=ympd ExecStart=/usr/bin/ympd -h /run/mpd/socket -w 1337 # Hardenings ProtectSystem=strict PrivateTmp=true ProtectHome=true PrivateDevices=true ProtectKernelTunables=true ProtectKernelModules=true ProtectControlGroups=true NoNewPrivileges=true [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 148 mympd # myMPD then # Distro: https://download.opensuse.org/repositories/home:/jcorporation/ local distro='Debian_' (( $G_HW_MODEL < 10 )) && (( $G_RASPBIAN )) && distro='Raspbian_' if (( $G_DISTRO == 5 )) then distro+='10' elif [[ $G_DISTRO == 6 || $distro == 'Raspbian_' ]] # No Testing suite available for Raspbian, use Bullseye package on Raspbian Bookworm then distro+='11' else distro+='Testing' fi # APT key local url="https://download.opensuse.org/repositories/home:/jcorporation/$distro/Release.key" G_CHECK_URL "$url" G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-mympd.gpg --yes" # 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 url='https://download.roonlabs.net/builds/RoonBridge_linuxarmv7hf.tar.bz2';; 3) local url='https://download.roonlabs.net/builds/RoonBridge_linuxarmv8.tar.bz2';; *) local url='https://download.roonlabs.net/builds/RoonBridge_linuxx64.tar.bz2';; esac Download_Install "$url" # 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_ fi if To_Install 119 # CAVA then # Debian ships packages from Bullseye on if (( $G_DISTRO > 5 )) then G_AGI cava # CAVA conf, 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 else case $G_HW_ARCH in 1) local arch='armv6';; 2) local arch='armv7';; 3) local arch='arm64';; *) local arch='amd64';; esac aDEPS=('libfftw3-double3' 'libncursesw5') Download_Install "https://dietpi.com/downloads/binaries/all/cava_0.6.1-1_$arch.deb" # CAVA conf, preserve existing [[ -f '/root/.config/cava/config' ]] || dps_index=$software_id Download_Install 'cava.conf' /root/.config/cava/config 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 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 # Install official APT repo whre available if (( $G_HW_ARCH != 11 )) then # 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 local distro=${G_DISTRO_NAME/bookworm/bullseye} G_EXEC eval "echo 'deb https://apt.mopidy.com/ ${distro/bullseye/buster} main contrib non-free' > /etc/apt/sources.list.d/mopidy.list" G_AGUP fi # 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 [[ -d '/mnt/dietpi_userdata/mopidy/.hidden_data' ]] || G_EXEC mkdir /mnt/dietpi_userdata/mopidy/.hidden_data # Non-hidden files/folders 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 [[ -d '/mnt/dietpi_userdata/mopidy/data' ]] || 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 [[ -d '/mnt/dietpi_userdata/mopidy/cache' ]] || G_EXEC mkdir /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 echo -e '[Service]\nExecStartPre=' > /etc/systemd/system/mopidy.service.d/dietpi.conf Download_Test_Media fi if To_Install 31 # Kodi then local aDEPS=('kodi') # RPi if (( $G_HW_MODEL < 10 )) 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 # Bullseye, RPi 4 and 64-bit userland: Use KMS driver: https://www.raspberrypi.org/forums/viewtopic.php?t=251645 if [[ $G_DISTRO -ge 6 || $G_HW_MODEL == 4 || $(dpkg --print-architecture) == 'arm64' ]] then # Enhance 4k support on RPi 4 local cma=() (( $G_HW_MODEL == 4 )) && cma=(512) /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d "${cma[@]}" (( $G_DISTRO < 6 )) || aDEPS+=('libgl1-mesa-dri') # Missing dependency on Bullseye package # Else legacy framebuffer driver else /boot/dietpi/func/dietpi-set_hardware rpi-opengl disable fi # 64-bit Buster: Debian repo: https://github.com/MichaIng/DietPi/issues/4194 if [[ $G_DISTRO -le 5 && $(dpkg --print-architecture) == 'arm64' ]] then echo -e 'Package: kodi*\nPin: origin archive.raspberrypi.org\nPin-Priority: -1' > /etc/apt/preferences.d/dietpi-kodi aDEPS+=('kodi-repository-kodi') # Else: RPi repo else [[ -f '/etc/apt/preferences.d/dietpi-kodi' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-kodi # 32-bit Buster: Apply missing dir workaround: https://github.com/RPi-Distro/repo/issues/153 [[ $G_DISTRO == 5 && $(dpkg --print-architecture) == 'armhf' && ! -d '/etc/polkit-1/localauthority/50-local.d' ]] && G_EXEC mkdir -p /etc/polkit-1/localauthority/50-local.d # Buster: fbset required to recover desktop with custom resolution and fix startup warning # Bullseye: Enable hardware codecs # shellcheck disable=SC2015 (( $G_DISTRO < 6 )) && aDEPS+=('fbset') || /boot/dietpi/func/dietpi-set_hardware rpi-codec 1 fi # Everything else else aDEPS+=('kodi-repository-kodi') (( $G_HW_ARCH == 10 || $G_DISTRO > 6 )) || aDEPS+=('libgles2') # Missing ARM dependency until Bookworm fi # Buster: Missing dependencies for CEC + NFS support (( $G_DISTRO == 5 )) && aDEPS+=('libcec4' 'libnfs12') # 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 G_AGI minidlna G_EXEC systemctl stop minidlna # Remove obsolete service files Remove_SysV minidlna 1 [[ -f '/lib/systemd/system/minidlna.service' ]] && G_EXEC rm /lib/systemd/system/minidlna.service [[ -d '/var/log/minidlna' ]] && G_EXEC rm -R /var/log/minidlna # 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 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 ExecStart=$(command -v minidlnad) -S -R -f /etc/minidlna.conf -P /dev/null [Install] WantedBy=multi-user.target _EOF_ # Bullseye: Debian patched forced file logging inside, overriding "-S": https://github.com/MichaIng/DietPi/issues/4745 (( $G_DISTRO < 6 )) || G_CONFIG_INJECT 'LogsDirectory=' 'LogsDirectory=minidlna' /etc/systemd/system/minidlna.service 'User=' # Config G_BACKUP_FP /etc/minidlna.conf dps_index=$software_id Download_Install 'minidlna.conf' /etc/minidlna.conf # 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 # Obtain platform: https://github.com/BlitterStudio/amiberry/blob/master/Makefile local platform='rpi1' if (( $G_HW_MODEL < 10 )) # RPi then (( $G_HW_MODEL > 1 )) && platform="rpi$G_HW_MODEL" # ID 0 is rpi1 # 64-bit: For RPi 2 v1.2 use RPi 3 64-bit build (( $G_HW_ARCH == 3 )) && platform="${platform/[12]/3}-64-dmx" /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-fkms-v3d elif (( $G_HW_MODEL == 10 )) # Odroid C1 then platform='c1' elif (( $G_HW_MODEL == 11 )) # Odroid XU4 then platform='xu4' elif (( $G_HW_MODEL == 16 )) # Odroid C4 then platform='AMLSM1' elif (( $G_HW_MODEL == 52 )) # ASUS Tinker Board then platform='RK3288' elif (( $G_HW_CPUID == 1 )) # Allwinner H3 then platform='sun8i' elif [[ $G_HW_CPUID == [34] ]] # RK3399 and S922X (Odroid N2) then platform='n2' elif (( $G_HW_CPUID == 11 )) # RK3588 then platform='rk3588' elif (( $G_HW_ARCH == 2 )) # Generic ARMv7 then platform='s812' elif (( $G_HW_ARCH == 3 )) # Generic ARMv8 then platform='a64' elif (( $G_HW_ARCH == 10 )) # x86_64 then platform='x86-64' fi # Install Amiberry DEB package Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/amiberry_$platform.deb" # Permissions: Enable access for kickstart uploads via file servers G_EXEC chgrp dietpi /mnt/dietpi_userdata/amiberry/kickstarts G_EXEC chmod g=rwx /mnt/dietpi_userdata/amiberry/kickstarts # 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 [[ -e '/mnt/dietpi_userdata/amiberry/lib/libSDL2.so' ]] && G_EXEC rm -f /mnt/dietpi_userdata/amiberry/lib/libSDL2*.so{,.0.*} [[ -f '/etc/systemd/system/amiberry.service' ]] && G_EXEC rm /etc/systemd/system/amiberry.service fi if To_Install 112 # DXX-Rebirth then aDEPS=('libsdl-mixer1.2' 'libsdl1.2debian' 'libphysfs1') 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'" # Install latest version local arch=$(dpkg --print-architecture) local url=$(curl -sSfL 'https://hndl.urbackup.org/Server/latest' | mawk -F\" "/\"urbackup-server_.*_$arch\.deb\"/{print \$8}") [[ $url ]] && url="https://hndl.urbackup.org/Server/latest/$url" local fallback_url="https://hndl.urbackup.org/Server/2.5.30/urbackup-server_2.5.27_$arch.deb" Download_Install "$url" G_EXEC systemctl stop urbackupsrv unset -v backuppath arch url 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 [[ -d '/var/www/rpicam' ]] || G_EXEC mkdir /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_DISTRO == 5 )) && G_EXEC mv bin/raspimjpeg{-buster,} 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 -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 [[ -d '/mnt/dietpi_userdata/rpicam' ]] || G_EXEC mkdir /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_EXEC systemctl stop deluged # 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 -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=002 ExecStart=$(command -v deluged) -d [Install] WantedBy=multi-user.target _EOF_ # https://github.com/deluge-torrent/deluge/blob/develop/packaging/systemd/deluge-web.service # - Bullseye: deluge-web v2 requires the "-d" flag to stay in foreground, but v1 does not understand it yet local flag= (( $G_DISTRO < 6 )) || flag=' -d' cat << _EOF_ > /etc/systemd/system/deluge-web.service [Unit] Description=Deluge Web UI (DietPi) Documentation=man:deluge-web After=deluged.service [Service] User=debian-deluged UMask=027 ExecStart=$(command -v deluge-web)$flag [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 115 webmin # Webmin then # RISC-V workaround until arch has been added to repo: https://download.webmin.com/download/repository/dists/sarge/contrib/ if (( $G_HW_ARCH == 11 )) then Download_Install "https://download.webmin.com/download/repository/pool/contrib/w/webmin/$(curl -sSf 'https://download.webmin.com/download/repository/pool/contrib/w/webmin/' | grep -o 'webmin_[^_]*_all.deb' | tail -1)" else # APT key local url='https://webmin.com/jcameron-key.asc' G_CHECK_URL "$url" G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-webmin.gpg --yes" # APT list G_EXEC eval "echo 'deb https://download.webmin.com/download/repository/ sarge contrib' > /etc/apt/sources.list.d/webmin.list" G_AGUP # APT package G_AGI webmin fi G_EXEC systemctl stop webmin Remove_SysV webmin fi if To_Install 195 # youtube-dl then aDEPS=('python3') Download_Install 'https://yt-dl.org/downloads/latest/youtube-dl' /usr/local/bin/youtube-dl G_EXEC chmod +x /usr/local/bin/youtube-dl # youtube-dl supports Python 2 and Python 3, but its shebang calls Python 2, else fails: https://github.com/ytdl-org/youtube-dl/issues/27649 G_EXEC sed -i '1s/python$/python3/' /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 _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} fi if To_Install 135 icecast2 darkice # IceCast + DarkIce then G_AGI darkice icecast2 G_EXEC systemctl stop darkice icecast2 # IceCast: Set passwords if not yet done (default found) sed -i "/hackme/c\ $GLOBAL_PW" /etc/icecast2/icecast.xml sed -i "/hackme/c\ $GLOBAL_PW" /etc/icecast2/icecast.xml sed -i "/hackme/c\ $GLOBAL_PW" /etc/icecast2/icecast.xml # - Remove default service config [[ -f '/etc/default/icecast2' ]] && G_EXEC rm /etc/default/icecast2 # DarkIce [[ -f '/etc/darkice.cfg' ]] || > /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 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_ Remove_SysV darkice 1 cat << _EOF_ > /etc/systemd/system/darkice.service [Unit] Description=DarkIce (DietPi) Requires=icecast2.service After=icecast2.service [Service] User=nobody Group=dietpi ExecStart=$(command -v 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 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." && disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 1 then orport=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n' fi 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 local choice_required= 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_MENU "${choice_required}Please choose which type of relay this should be set up as:" || { choice_required='[ERROR] A choice is required to finish the Tor install.\n\n'; continue; } 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 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." && disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 1; then obfs4port=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n' fi 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 -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 echo 'ControlPort 9051' >> /etc/tor/torrc echo 'CookieAuthentication 1' >> /etc/tor/torrc [[ $nickname ]] && echo "Nickname $nickname" >> /etc/tor/torrc [[ $email ]] && echo "ContactInfo $email" >> /etc/tor/torrc [[ $ipv6 ]] && 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' # Install/update root trust anchors and hints (( $G_DISTRO > 6 )) && aDEPS=('dns-root-data') # https://github.com/MichaIng/DietPi/issues/5612 Download_Install 'https://www.internic.net/domain/named.root' /var/lib/unbound/root.hints # Create monthly cron job to keep root hints updated echo -e '#!/bin/dash\n# Update Unbound root hints\ncurl -sSfL '\''https://www.internic.net/domain/named.root'\'' -o /var/lib/unbound/root.hints' > /etc/cron.monthly/dietpi-unbound G_EXEC chmod +x /etc/cron.monthly/dietpi-unbound # 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 else G_CONFIG_INJECT 'do-ip6:[[:blank:]]' ' do-ip6: no' /etc/unbound/unbound.conf.d/dietpi.conf 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 G_CONFIG_INJECT 'interface:[[:blank:]]' ' interface: 127.0.0.1' /etc/unbound/unbound.conf.d/dietpi.conf fi [[ -f '/lib/systemd/system/unbound.service' ]] && G_EXEC systemctl restart unbound G_AGI unbound G_EXEC systemctl --no-reload disable --now unbound-resolvconf # https://github.com/MichaIng/DietPi/issues/5133 G_EXEC systemctl enable --now unbound # Failsafe # Pi-hole part 2 if (( ${aSOFTWARE_INSTALL_STATE[93]} == 2 )) then G_DIETPI-NOTIFY 2 'Configuring Pi-hole to use Unbound' if [[ -f '/etc/dnsmasq.d/01-pihole.conf' ]] then G_EXEC sed -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 -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 local url='https://raw.githubusercontent.com/pi-hole/pi-hole/master/automated%20install/basic-install.sh' G_CHECK_URL "$url" # 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 # Dependencies: https://github.com/pi-hole/pi-hole/blob/development/automated%20install/basic-install.sh#L250 G_AGI "php$PHP_VERSION-"{xml,sqlite3,intl} # 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 G_EXEC curl -sSfL "$url" -o install.sh G_EXEC chmod +x install.sh # - Skip web interface dialogue (which defaults to "true"), since we install a web server and PHP anyway # - Skip query logging dialogue (which affects file logging only, not database>web UI) and set to "false" # - Skip supported OS check. We do not support Debian testing but we are testing it already now. # - Workaround "dialog" issues with "xterm" by faking "linux" terminal # - Skip web server install, since we allow to choose and install it prior to Pi-hole G_EXEC sed -Ei '/^[[:blank:]]*set(AdminFla|Loggin)g$/d' install.sh G_EXEC sed -i 's/QUERY_LOGGING=true/QUERY_LOGGING=false/' install.sh export PIHOLE_SKIP_OS_CHECK=true local retry TERM_old= [[ $TERM == 'xterm' ]] && { TERM_old=$TERM; export TERM=linux; } while : do ./install.sh --disable-install-webserver && break (( $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 setup if installer errored out if (( ${aSOFTWARE_INSTALL_STATE[$software_id]} == 1 )); then # Apply most resource friendly and officially recommended NULL blocking: https://docs.pi-hole.net/ftldns/blockingmode/ G_CONFIG_INJECT 'BLOCKINGMODE=' 'BLOCKINGMODE=NULL' /etc/pihole/pihole-FTL.conf # Disable pihole.log query logging: https://github.com/pi-hole/FTL/issues/614#issuecomment-510564476 G_EXEC pihole -l off # Unbound: Configure Pi-hole to use it if (( ${aSOFTWARE_INSTALL_STATE[182]} > 0 )) then G_DIETPI-NOTIFY 2 'Configuring Pi-hole to use Unbound' G_EXEC sed -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 G_CONFIG_INJECT 'PIHOLE_DNS_1=' 'PIHOLE_DNS_1=127.0.0.1#5335' /etc/pihole/setupVars.conf G_EXEC sed -i '/^[[:blank:]]*PIHOLE_DNS_2=/d' /etc/pihole/setupVars.conf fi # Enable required PHP modules: https://github.com/pi-hole/pi-hole/blob/development/automated%20install/basic-install.sh#L250 G_EXEC phpenmod xml sqlite3 intl # Webserver configs # - Lighttpd if (( ${aSOFTWARE_INSTALL_STATE[84]} > 0 )) then # Enable required modules G_CONFIG_INJECT '"mod_setenv",' ' "mod_setenv",' /etc/lighttpd/lighttpd.conf '"mod_.+",' # Add and enable Pi-hole config dps_index=$software_id Download_Install 'lighttpd.pihole.conf' /etc/lighttpd/conf-available/99-dietpi-pihole.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-pihole # Optional config to block public access to admin panel dps_index=$software_id Download_Install 'lighttpd.block_public_admin.conf' /etc/lighttpd/conf-available/99-dietpi-pihole-block_public_admin.conf local enable_cmd='lighty-enable-mod dietpi-pihole-block_public_admin' local disable_cmd='lighty-disable-mod dietpi-pihole-block_public_admin' # - Apache elif (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 )) then # Enable required modules G_EXEC a2enmod headers # Add and enable Pi-hole config dps_index=$software_id Download_Install 'apache.pihole.conf' /etc/apache2/sites-available/dietpi-pihole.conf G_EXEC a2ensite dietpi-pihole # Optional config to block public access to admin panel dps_index=$software_id Download_Install 'apache.block_public_admin.conf' /etc/apache2/sites-available/dietpi-pihole-block_public_admin.conf local enable_cmd='a2ensite dietpi-pihole-block_public_admin' local disable_cmd='a2dissite dietpi-pihole-block_public_admin' # - Nginx elif (( ${aSOFTWARE_INSTALL_STATE[85]} > 0 )) then # Add Pi-hole config dps_index=$software_id Download_Install 'nginx.pihole.conf' /etc/nginx/sites-dietpi/dietpi-pihole.conf # Optional config to block public access to admin panel dps_index=$software_id Download_Install 'nginx.block_public_admin.conf' /etc/nginx/sites-dietpi/dietpi-pihole-block_public_admin.off local enable_cmd='mv /etc/nginx/sites-dietpi/dietpi-pihole-block_public_admin.{off,on}' local disable_cmd='mv /etc/nginx/sites-dietpi/dietpi-pihole-block_public_admin.{on,off}' fi # Ask user if they want to block public access to the admin panel G_WHIP_BUTTON_OK_TEXT='YES' G_WHIP_BUTTON_CANCEL_TEXT='NO' G_WHIP_YESNO "In order to increase security, it is recommended to block public access to the Pi-hole admin panel, so that only connections from within your LAN or via VPN are possible. \nPractically this means to deny access from all IPs that do not match the reserved loopback and LAN ranges: - 127.* - 192.168.* - 10.* - 172.16.* - 172.31.* - ::1 - fe80:* - febf:* - fc00:* - fdff:* \nYou can always enable/disable this later using the commands: - $enable_cmd - $disable_cmd \nDo you want to block public access to the admin panel now?" && eval "$enable_cmd" # Create symlinks to align Pi-hole admin and 404 page relative to webroot [[ -e '/var/www/admin' && ! -L '/var/www/admin' ]] && G_EXEC mv /var/www/admin{,.bak} G_EXEC ln -sf /var/www/{html/admin,admin} [[ -e '/var/www/pihole' && ! -L '/var/www/pihole' ]] && G_EXEC mv /var/www/pihole{,.bak} G_EXEC ln -sf /var/www/{html/pihole,pihole} # Pi-hole v5: Add webserver user to pihole group to allow gravity.db access from web UI: https://github.com/MichaIng/DietPi/issues/3391 G_EXEC usermod -aG pihole www-data # Set web interface PW: https://github.com/MichaIng/DietPi/issues/662 pihole -a -p "$GLOBAL_PW" # Reduce long-term database TTL: https://github.com/MichaIng/DietPi-Docs/issues/476 G_DIETPI-NOTIFY 2 'The DNS query database logging duration is reduced to 2 days. If you require long-term query logs, read our docs about how to change the log duration: - https://dietpi.com/docs/software/dns_servers/#pi-hole' G_CONFIG_INJECT 'MAXDBDAYS=' 'MAXDBDAYS=2' /etc/pihole/pihole-FTL.conf 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';; *) local arch='amd64';; 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=5 [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 # ARMv6: Download latest v10 as v11 does not support Java 8 if (( $G_HW_ARCH == 1 )) then Download_Install 'https://github.com/airsonic-advanced/airsonic-advanced/releases/download/v10.6.0/airsonic.war' /mnt/dietpi_userdata/airsonic/airsonic.war else # 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.20220625052932/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 fi # User Create_User -g dietpi -G audio -d /mnt/dietpi_userdata/airsonic airsonic # Optimise memory limit local memory_limit=$(( $RAM_PHYS / 5 )) (( $memory_limit < 200 )) && memory_limit=200 # 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=$(command -v java) -Xmx${memory_limit}m -Dairsonic.home=/mnt/dietpi_userdata/airsonic -Dserver.servlet.context-path=/airsonic -Dserver.port=8080 -jar /mnt/dietpi_userdata/airsonic/airsonic.war [Install] WantedBy=multi-user.target _EOF_ # Enable FFmpeg transcode [[ -d '/mnt/dietpi_userdata/airsonic/transcode' ]] || G_EXEC mkdir /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='x86_64';; esac local fallback_url="https://github.com/navidrome/navidrome/releases/download/v0.49.3/navidrome_0.49.3_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 [[ -d '/mnt/dietpi_userdata/navidrome' ]] || G_EXEC mkdir /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' CoverArtPriority = 'embedded' _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 [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 navidrome:root /mnt/dietpi_userdata/navidrome Download_Test_Media 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#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 G_AGI python3-rpi.gpio 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 [[ -d '/usr/local/include' ]] || G_EXEC mkdir /usr/local/include G_EXEC_OUTPUT=1 G_EXEC ./build # Odroids else 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 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 G_AGI pijuice-base G_EXEC systemctl stop pijuice G_EXEC mkdir -p /var/lib/dietpi/dietpi-software/installed/pijuice 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 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_ fi if To_Install 171 # frp then case $G_HW_ARCH in 3) local arch='arm64';; 10) local arch='amd64';; 11) local arch='riscv64';; *) local arch='arm';; esac # Download local fallback_url="https://github.com/fatedier/frp/releases/download/v0.48.0/frp_0.48.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_* local choice_required= while : do 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_MENU "${choice_required}Please choose how you are going to run frp." && break choice_required='[ERROR] A choice is required to finish the frp install.\n\n' done local mode=$G_WHIP_RETURNED_VALUE [[ -d '/etc/frp' ]] || G_EXEC mkdir /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=5 [Service] User=frp AmbientCapabilities=CAP_NET_BIND_SERVICE ExecStart=/usr/local/bin/frps -c /etc/frp/frps.ini Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target _EOF_ # Pre-create config file to turn on dashboard token=$(openssl rand -hex 15) [[ -f '/etc/frp/frps.ini' ]] || cat << _EOF_ > /etc/frp/frps.ini [common] bind_port = 7000 dashboard_port = 7500 dashboard_user = admin dashboard_pwd = $GLOBAL_PW authentication_method = token token = $token _EOF_ G_EXEC chmod 0640 /etc/frp/frps.ini G_EXEC chown root:frp /etc/frp/frps.ini 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=5 [Service] User=frp ExecStart=/usr/local/bin/frpc -c /etc/frp/frpc.ini ExecReload=/usr/local/bin/frpc reload -c /etc/frp/frpc.ini Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target _EOF_ local server_addr=127.0.0.1 server_port=7000 if [[ $G_WHIP_RETURNED_VALUE == 'Client' ]] then local invalid_entry= while : do if G_WHIP_INPUTBOX "${invalid_entry}Please enter the IP address of your frp server, including port (default 7000)" && [[ $G_WHIP_RETURNED_VALUE =~ ^[0-9.:]+$ ]] then server_addr=${G_WHIP_RETURNED_VALUE#*:} [[ $G_WHIP_RETURNED_VALUE =~ : ]] && server_port=${G_WHIP_RETURNED_VALUE%:*} invalid_entry= break else invalid_entry='[FAILED] Please enter a valid IP address\n\n' fi done while : do if G_WHIP_INPUTBOX "${invalid_entry}Please enter the authentication token of your frp server" && [[ $G_WHIP_RETURNED_VALUE =~ ^[0-9.]+$ ]] then token=$G_WHIP_RETURNED_VALUE break else invalid_entry='[FAILED] Please enter a token\n\n' fi done fi # Pre-create config file to turn on admin UI [[ -f '/etc/frp/frpc.ini' ]] || cat << _EOF_ > /etc/frp/frpc.ini [common] server_addr = $server_addr server_port = $server_port admin_addr = 0.0.0.0 admin_port = 7400 admin_user = admin admin_pwd = $GLOBAL_PW token=$token _EOF_ G_EXEC chmod 0660 /etc/frp/frpc.ini G_EXEC chown root:frp /etc/frp/frpc.ini 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 G_EXEC_OUTPUT=1 G_EXEC sudo -u nodered npm i --no-audit node-red 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_HW_ARCH == 2 || $G_HW_ARCH == 10 ]] then # APT key local url='https://repo.mosquitto.org/debian/mosquitto-repo.gpg.key' 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/bookworm/bullseye} 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 > /etc/mosquitto/passwd # Pre-create file, required for pre-v1.6.10 (ARMv8 up to Buster): https://github.com/MichaIng/DietPi/issues/4424 G_EXEC_PRE_FUNC(){ acommand[4]=$GLOBAL_PW; } G_EXEC mosquitto_passwd -b /etc/mosquitto/passwd mosquitto "${GLOBAL_PW//?/X}" G_EXEC chown root:mosquitto /etc/mosquitto/passwd 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 -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 -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++') # ARMv6: Install Java 8 build and apply Log4Shell mitigation as the last Java 8 build does not contain it: https://github.com/Peterkn2001/blynk-server/releases local log4shell= if (( $G_HW_ARCH == 1 )) then log4shell=' -Dlog4j2.formatMsgNoLookups=true' Download_Install 'https://github.com/Peterkn2001/blynk-server/releases/download/v0.41.16/server-0.41.16-java8.jar' /mnt/dietpi_userdata/blynk/blynkserver.jar else Download_Install 'https://github.com/Peterkn2001/blynk-server/releases/download/v0.41.17/server-0.41.17.jar' /mnt/dietpi_userdata/blynk/blynkserver.jar fi # RPi: Install "onoff" for GPIO access (( $G_HW_MODEL > 9 )) || G_EXEC_OUTPUT=1 G_EXEC npm i -g --no-audit onoff # Install Blynk JS library G_EXEC_OUTPUT=1 G_EXEC npm i -g --no-audit blynk-library # 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 -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=$(command -v java)$log4shell -jar /mnt/dietpi_userdata/blynk/blynkserver.jar # 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://www.signalyst.eu/bins/naa/linux/${G_DISTRO_NAME/bookworm/bullseye}/" case $G_HW_ARCH in 3) local arch='arm64';; 10) local arch='amd64';; *) local arch='armhf' esac # Get latest version local package=$(curl -sSfL "$url" | sed -n "/href=\"networkaudiod_[^\"]*_$arch.deb\"/{s/^[^\"]*\"//;s/\".*$//p}" | tail -1) # Check final URL before applying debconf settings G_CHECK_URL "$url$package" # Skip license G_EXEC eval 'debconf-set-selections <<< '\''networkaudiod networkaudiod/license note false'\' # Install Download_Install "$url$package" G_EXEC systemctl stop networkaudiod unset -v url arch 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 -i '/SEARCH="python python3"/c\SEARCH="python3"' setup.sh # Skip Weaved install prompt G_EXEC sed -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 -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=$(command -v 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 local version='2.7.6' # https://www.haproxy.org/download/ aDEPS=('make' 'gcc' 'libpcre3-dev' 'libssl-dev' 'zlib1g-dev' 'libsystemd-dev') Download_Install "https://www.haproxy.org/download/${version%.*}/src/haproxy-$version.tar.gz" # Compile G_EXEC cd "haproxy-$version" G_EXEC_OUTPUT=1 G_EXEC make -j "$G_HW_CPU_CORES" TARGET=linux-glibc USE_PCRE=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-$version/examples/errorfiles/"*.http /etc/haproxy/errors/ # Cleanup G_EXEC rm -R "haproxy-$version" # 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 logitechmediaserver # Logitech Media Server then # https://wiki.slimdevices.com/index.php/DebianPackage#installing_7.9.2 # Grab architecture local arch='arm' (( $G_HW_ARCH == 10 )) && arch='amd64' # Grab latest package URL local fallback_url="https://downloads.slimdevices.com/LogitechMediaServer_v8.3.1/logitechmediaserver_8.3.1_$arch.deb" Download_Install "$(curl -sSfL "https://www.mysqueezebox.com/update/?version=8.3&geturl=1&os=deb$arch")" G_EXEC systemctl stop logitechmediaserver Remove_SysV logitechmediaserver # 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 local version=$(curl -sSfL 'https://api.github.com/repos/FreshRSS/FreshRSS/releases/latest' | mawk -F\" '/"tag_name": /{print $4}') [[ $version ]] || { version='1.21.0'; 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"; } 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 AllowOverride AuthConfig FileInfo Indexes Limit Require all granted Options FollowSymLinks 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 sudo -u www-data php ./cli/prepare.php sudo -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 sudo -u www-data php ./cli/create-user.php --user dietpi --password "$GLOBAL_PW" --api_password "$GLOBAL_PW" sudo -u www-data php ./cli/actualize-user.php --user dietpi sudo -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 # netbase is required until Bullseye to solve: "Use of uninitialized value $proto in socket at /usr/bin/tigervncserver" # - It is a recommendation and no dependency of perl, but expected by some packages depending on perl only: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=939055 # tigervnc-common is required as it is a recommendation only until Bullseye. local apackages=() (( $G_DISTRO > 5 )) || apackages=('tigervnc-common' 'netbase') G_AGI tigervnc-standalone-server tigervnc-scraping-server "${apackages[@]}" fi if To_Install 120 # RealVNC Server then G_AGI realvnc-vnc-server 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') # RealVNC: Assure that its services are disabled when ours is enabled (( ${aSOFTWARE_INSTALL_STATE[120]} == 1 )) && G_EXEC systemctl --no-reload disable vncserver-virtuald vncserver-x11-serviced 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' [ -f '/usr/bin/X0tigervnc' ] && FP_SHARED='/usr/bin/X0tigervnc' || FP_SHARED='/usr/bin/x0tigervncserver' FP_SHARED="$FP_SHARED -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:-1}" -geometry "${WIDTH:-1280}x${HEIGHT:-720}" -depth "${DEPTH:-16}" 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 x0tigervncserver 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:-1}" 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: Permit remote connections which implies TLSVnc authentications being enabled additionally # shellcheck disable=SC2016 [[ -f '/etc/vnc.conf' ]] && GCI_PRESERVE=1 G_CONFIG_INJECT '\$localhost[[:blank:]]*=' '$localhost = "no";' /etc/vnc.conf # Buster # shellcheck disable=SC2016 [[ -f '/etc/tigervnc/vncserver-config-defaults' ]] && GCI_PRESERVE=1 G_CONFIG_INJECT '\$localhost[[:blank:]]*=' '$localhost = "no";' /etc/tigervnc/vncserver-config-defaults # Bullseye # TigerVNC: Set control + read-only passwords if [[ ${aSOFTWARE_INSTALL_STATE[28]} == 1 && ! -f '/root/.vnc/passwd' ]] then [[ -d '/root/.vnc' ]] || G_EXEC mkdir /root/.vnc tigervncpasswd -f <<< "$GLOBAL_PW $GLOBAL_PW" > /root/.vnc/passwd G_EXEC chmod 600 /root/.vnc/passwd fi # RealVNC: Set virtual + shared desktop passwords, repeat virtual password command two times: https://github.com/MichaIng/DietPi/pull/4679#issuecomment-908196511 if [[ ${aSOFTWARE_INSTALL_STATE[120]} == 1 && ! -s '/root/.vnc/config.d/Xvnc' ]] then vncpasswd -virtual <<< "$GLOBAL_PW $GLOBAL_PW" vncpasswd -service <<< "$GLOBAL_PW $GLOBAL_PW" [[ -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 [[ -d '/etc/fail2ban/fail2ban.d' ]] || G_EXEC mkdir -p /etc/fail2ban/fail2ban.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' G_AGI python3-systemd fail2ban Remove_SysV fail2ban 1 # 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 G_EXEC eval "echo 'deb https://repos.influxdata.com/debian/ ${G_DISTRO_NAME/bookworm/bullseye} stable' > /etc/apt/sources.list.d/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 then # ARMv6: Install package manually since repo is not compatible: https://grafana.com/grafana/download?platform=arm&edition=oss if (( $G_HW_ARCH == 1 )) then Download_Install 'https://dl.grafana.com/oss/release/grafana-rpi_9.4.7_armhf.deb' # Else use official APT repo: https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/#install-from-apt-repository 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 G_EXEC unzip -o Ubooquity.zip G_EXEC rm Ubooquity.zip [[ -d '/mnt/dietpi_userdata/ubooquity' ]] || G_EXEC mkdir /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 # Optimise memory limit local memory_limit=$(( $RAM_PHYS / 5 )) (( $memory_limit < 200 )) && memory_limit=200 # 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=$(command -v java) -Xmx${memory_limit}m -jar /mnt/dietpi_userdata/ubooquity/Ubooquity.jar --headless --remoteadmin --adminport 2038 --libraryport 2039 [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/v0.165.0/komga-0.165.0.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} # 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_ # Optimise memory limit local memory_limit=$(( $RAM_PHYS / 5 )) (( $memory_limit < 200 )) && memory_limit=200 # 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=$(command -v java) -Xmx${memory_limit}m -jar komga.jar [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 775 /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.11.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 [[ -d '/var/www/gallery/DietPi' ]] || G_EXEC mkdir /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 [[ -d '/var/www/gallery/Tr-Zero' ]] || G_EXEC mkdir /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') # Bullseye+ if (( $G_DISTRO > 5 )) then local fallback_url='https://github.com/ampache/ampache/releases/download/5.5.3/ampache-5.5.3_all.zip' Download_Install "$(curl -sSfL 'https://api.github.com/repos/ampache/ampache/releases/latest' | mawk -F\" '/"browser_download_url": ".*\/ampache-[0-9\.]*_all.zip"/{print $4}')" ampache # Ampache is installed to /mnt/dietpi_userdata/ampache and the "public" directory linked to /var/www/ampache: https://github.com/MichaIng/DietPi/pull/5205 local fp_install='/mnt/dietpi_userdata' fp_public='ampache/public' # Ampache v5 requires PHP7.4, hence pull latest Ampache v4 on Buster: https://github.com/ampache/ampache/wiki/Ampache-Next-Changes else Download_Install 'https://github.com/ampache/ampache/releases/download/4.4.3/ampache-4.4.3_all.zip' ampache # Ampache is installed to /var/www/ampache. local fp_install='/var/www' fp_public='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 "$fp_public/channel/" [[ -f '/var/www/ampache/rest/.htaccess' ]] && G_EXEC mv /var/www/ampache/rest/.htaccess "$fp_public/rest/" [[ -f '/var/www/ampache/play/.htaccess' ]] && G_EXEC mv /var/www/ampache/play/.htaccess "$fp_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 {,"$fp_install/"}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[@]}" # Import our pre-made Ampache database, if not existent already if [[ ! -d '/mnt/dietpi_userdata/mysql/ampache' ]] then /boot/dietpi/func/create_mysql_db ampache ampache "$GLOBAL_PW" Download_Install 'https://dietpi.com/downloads/mysql_databases/ampache_mysql_3.8.2-v6.0.zip' G_EXEC mysql ampache < ampache.sql G_EXEC rm ampache.sql # Also update password here for rare but possible case that database was lost but config file still exists [[ -f $fp_install/ampache/config/ampache.cfg.php ]] && G_CONFIG_INJECT 'database_password[[:blank:]]+=' "database_password = \"$GLOBAL_PW\"" "$fp_install/ampache/config/ampache.cfg.php" fi # Create new config, if not existent already if [[ ! -f $fp_install/ampache/config/ampache.cfg.php ]] then G_EXEC mv "$fp_install/ampache/config/ampache.cfg.php"{.dist,} G_CONFIG_INJECT 'web_path[[:blank:]]+=' 'web_path = "/ampache"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'database_hostname[[:blank:]]+=' 'database_hostname = /run/mysqld/mysqld.sock' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'database_name[[:blank:]]+=' 'database_name = ampache' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'database_username[[:blank:]]+=' 'database_username = ampache' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'database_password[[:blank:]]+=' "database_password = \"$GLOBAL_PW\"" "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'waveform[[:blank:]]+=' 'waveform = "true"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'tmp_dir_path[[:blank:]]+=' 'tmp_dir_path = "/tmp"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'generate_video_preview[[:blank:]]+=' 'generate_video_preview = "true"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'channel[[:blank:]]+=' 'channel = "true"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_m4a[[:blank:]]+=' 'transcode_m4a = "required"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_flac[[:blank:]]+=' 'transcode_flac = "required"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_mpc[[:blank:]]+=' 'transcode_mpc = "required"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_ogg[[:blank:]]+=' 'transcode_ogg = "allowed"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_wav[[:blank:]]+=' 'transcode_wav = "required"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_avi[[:blank:]]+=' 'transcode_avi = "allowed"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_mkv[[:blank:]]+=' 'transcode_mkv = "allowed"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_mpg[[:blank:]]+=' 'transcode_mpg = "allowed"' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'encode_target[[:blank:]]+=' 'encode_target = mp3' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'encode_video_target[[:blank:]]+=' 'encode_video_target = webm' "$fp_install/ampache/config/ampache.cfg.php" G_CONFIG_INJECT 'transcode_cmd[[:blank:]]+=' 'transcode_cmd = "ffmpeg"' "$fp_install/ampache/config/ampache.cfg.php" fi # Permissions: Ampache can automatically migrate old configs to the new config file G_EXEC chown www-data "$fp_install/ampache/config/ampache.cfg.php" fi if To_Install 58 tailscale # 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 " \n$( \n$( \n$(" >> 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 -i '/^Thank you for using PiVPN./a\exit 0' install.bash G_DIETPI-NOTIFY 2 'Preventing install of unattended-upgrades' G_EXEC sed -i '/^[[:blank:]]*askUnattendedUpgrades$/c\UNATTUPG=0' install.bash G_DIETPI-NOTIFY 2 'Prevent dhcpcd from being installed' G_EXEC sed -i '/^checkStaticIpSupported() {$/,/^}$/d' install.bash G_EXEC sed -i '/^####### FUNCTIONS ##########$/a\checkStaticIpSupported(){ 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 dnsutils grepcidr net-tools bsdmainutils iptables-persistent # https://github.com/pivpn/pivpn/blob/master/auto_install/install.sh#L37 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 G_EXEC eval "echo 'deb https://download.zerotier.com/debian/$G_DISTRO_NAME/ $G_DISTRO_NAME 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' 'libnl-3-200') 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 ddns-update-style none; default-lease-time 600; max-lease-time 7200; authoritative; log-facility local7; subnet 192.168.42.0 netmask 255.255.255.0 { range 192.168.42.10 192.168.42.50; 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 echo "INTERFACESv4=\"$wifi_iface\"" > /etc/default/isc-dhcp-server # Remove all entries below wlan, so we can recreate them G_EXEC sed -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 wireless-power off # iptables NAT rules up iptables-restore < /etc/iptables.ipv4.nat up ip6tables-restore < /etc/iptables.ipv6.nat _EOF_ # Assign static IP for wlan now G_EXEC ip a add 192.168.42.1 dev "$wifi_iface" # Create access point config G_BACKUP_FP /etc/hostapd/hostapd.conf cat << _EOF_ > /etc/hostapd/hostapd.conf interface=$wifi_iface driver=nl80211 ssid=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_SSID=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) country_code=00 hw_mode=g channel=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_CHANNEL=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_passphrase=$(sed -n '/^[[:blank:]]*SOFTWARE_WIFI_HOTSPOT_KEY=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP _EOF_ G_EXEC chmod 0600 /etc/hostapd/hostapd.conf # Set WiFi country code /boot/dietpi/func/dietpi-set_hardware wificountrycode # RPi3/4 onboard WiFi: Enable Wi-Fi 4 support [[ $G_HW_MODEL == [34] ]] && G_CONFIG_INJECT 'ieee80211n=' 'ieee80211n=1' /etc/hostapd/hostapd.conf # 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 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://paulcarroty.gitlab.io/vscodium-deb-rpm-repo/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 -i '/^[[:blank:]]*SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=/c\#SOFTWARE_SHAIRPORT_SYNC_AIRPLAY=2' /boot/dietpi.txt airplay2= fi Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/shairport-sync${airplay2}_$G_HW_ARCH_NAME.deb" G_EXEC systemctl stop shairport-sync 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_.+",' G_CONFIG_INJECT '"mod_setenv",' ' "mod_setenv",' /etc/lighttpd/lighttpd.conf '"mod_.+",' # 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 Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/squeezelite_$G_HW_ARCH_NAME.deb" 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="/sda1 Used: "+KMG(data.usbhdd_used,'M')+" ("+Percent(data.usbhdd_used,data.usbhdd_total,'M')+") Free: "+KMG(data.usbhdd_total-data.usbhdd_used,'M')+ " Total: "+ KMG(data.usbhdd_total,'M') +"" 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 -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") local fallback_url='https://github.com/sabre-io/Baikal/releases/download/0.9.3/baikal-0.9.3.zip' Download_Install "$(curl -sSfL 'https://api.github.com/repos/sabre-io/Baikal/releases/latest' | mawk -F\" '/^ *"browser_download_url": ".*\/baikal-[^"\/]*\.zip"$/{print $4}')" # 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 # Cap total connections local max_users=$(( $G_HW_CPU_CORES * 8 )) G_EXEC sed -i "/users=/c\users=$max_users" /etc/mumble-server.ini # Name the root channel G_EXEC sed -i '/registerName=/c\registerName=DietPi Mumble Server' /etc/mumble-server.ini # Disable DB logging G_EXEC sed -i '/logdays=/c\logdays=-1' /etc/mumble-server.ini # Set Superuser passwd: https://dietpi.com/forum/t/mumble-murmur-server-superuser-error/1371 murmurd -ini /etc/mumble-server.ini -supw "$GLOBAL_PW" fi if To_Install 41 emby-server # Emby Server 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.7.11.0/emby-server-deb_4.7.11.0_$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 [[ -d '/etc/systemd/system/plexmediaserver.service.d' ]] || G_EXEC mkdir /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 path='aarch64/Cuberite.tar.gz';; 10) local path='x86_64/Cuberite.tar.gz';; *) local path='armhf-raspbian/Cuberite.tar.gz';; esac Download_Install "https://download.cuberite.org/linux-$path" /mnt/dietpi_userdata/cuberite # User Create_User -d /mnt/dietpi_userdata/cuberite cuberite # Service: Needs to be Type=forking, else it shuts down automatically after startup has finished :/ ... cat << '_EOF_' > /etc/systemd/system/cuberite.service [Unit] Description=Cuberite (DietPi) Wants=network-online.target After=network-online.target [Service] Type=forking User=cuberite WorkingDirectory=/mnt/dietpi_userdata/cuberite ExecStart=/mnt/dietpi_userdata/cuberite/Cuberite -d [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://minecraft.codeemo.com/mineoswiki/index.php?title=MineOS-node_(apt-get) local url='https://github.com/hexparrot/mineos-node.git' G_CHECK_URL "$url" # APT deps # - Buster: Python 3 is not pulled by rdiff-backup on Buster, but required to compile Node.js posix. local python=() (( $G_DISTRO > 5 )) || python=('python3') G_AGI rdiff-backup rsync screen make g++ "${python[@]}" # Download/Update MineOS [[ -d '/mnt/dietpi_userdata/mineos' ]] || G_EXEC mkdir /mnt/dietpi_userdata/mineos G_EXEC cd /mnt/dietpi_userdata/mineos if [[ -d 'minecraft' ]] then # https://minecraft.codeemo.com/mineoswiki/index.php?title=Updating_the_Webui G_EXEC cd minecraft if [[ -x 'update_webui.sh' ]] then G_EXEC_OUTPUT=1 G_EXEC ./update_webui.sh else G_EXEC_OUTPUT=1 G_EXEC git fetch G_EXEC_OUTPUT=1 G_EXEC git merge origin/master fi 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 # 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 # Install MineOS G_EXEC_OUTPUT=1 G_EXEC npm i --no-audit G_EXEC cd "$G_WORKING_DIR" # Config: Preserve existing [[ -f '/etc/mineos.conf' ]] || G_EXEC cp /mnt/dietpi_userdata/mineos/minecraft/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 rm -Rf /var/games/minecraft G_EXEC mkdir -p /var/games /mnt/dietpi_userdata/mineos/serverdata G_EXEC ln -s /mnt/dietpi_userdata/mineos/serverdata /var/games/minecraft # Setup SSL cert G_EXEC cd /mnt/dietpi_userdata/mineos/minecraft 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=$(command -v node) webui.js KillMode=process [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 49 gogs # Gogs then # ARMv6/RISC-V: No pre-compiled binaries available, so we host our own. if (( $G_HW_ARCH == 1 || $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 2) local arch='armv7';; 3) local arch='armv8';; *) local arch='amd64';; esac local fallback_url="https://github.com/gogs/gogs/releases/download/v0.13.0/gogs_0.13.0_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 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 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_ha1=@ByteArray($(echo -n "$GLOBAL_PW" | md5sum | mawk '{print $1}')) WebUI\Port=1340 WebUI\SecureCookie=true WebUI\UseUPnP=true WebUI\Username=qbittorrent _EOF_ fi # Since v4.2.0, PBKDF2 needs to be used: https://github.com/MichaIng/DietPi/issues/4711 (( $G_DISTRO < 6 )) || G_EXEC sed -i '/^WebUI\\Password_ha1/c\WebUI\\Password_PBKDF2="@ByteArray(tpgNK76AcpP14rjOZP9vwg==:rQNtOB0P4HfNj20pJtxiTBi9miduS6L1Xqqazc4Y6Gpm3Rn02jMXnPPT3KH2JMDKhFQjAaTGVJz0dz5JVw2QUQ==)"' /home/qbittorrent/.config/qBittorrent/qBittorrent.conf # 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=$(command -v 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='v4.0.3'; 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"; } 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 AllowOverride All AuthType Basic AuthName "ruTorrent login" AuthBasicProvider file AuthUserFile "/etc/.rutorrent-htaccess" Require valid-user AuthType Basic AuthName "rTorrent login" AuthBasicProvider file AuthUserFile "/etc/.rutorrent-htaccess" Require valid-user 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 -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 [[ -d '/mnt/dietpi_userdata/downloads/.session' ]] || G_EXEC mkdir /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 [[ -d '/mnt/dietpi_userdata/rtorrent' ]] || G_EXEC mkdir /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 -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 [[ -d '/mnt/dietpi_userdata/aria2' ]] || G_EXEC mkdir /mnt/dietpi_userdata/aria2 [[ -f '/mnt/dietpi_userdata/aria2/aria2.conf' ]] || cat << _EOF_ > /mnt/dietpi_userdata/aria2/aria2.conf # DietPi default aria2c options served as aria2.conf file via --conf-path # https://aria2.github.io/manual/en/html/aria2c.html#options # Logging log=/var/log/aria2.log log-level=warn # 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 log file local fp_log=$(sed -n '/^[[:blank:]]*log=/{s/^[^=]*=//p;q}' /mnt/dietpi_userdata/aria2/aria2.conf) [[ ${fp_log//\"} && ! -f $fp_log ]] && >> "$fp_log" # 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:root /mnt/dietpi_userdata/aria2 "$fp_input" G_EXEC chown aria2:dietpi "$fp_log" G_EXEC chmod 600 /mnt/dietpi_userdata/aria2/aria2.conf unset -v fp_log 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' /mnt/dietpi_userdata G_EXEC mv /mnt/dietpi_userdata/{Medusa-master,medusa} fi # User Create_User -g dietpi -d /mnt/dietpi_userdata/medusa medusa # Service: https://github.com/pymedusa/Medusa/blob/master/runscripts/init.systemd G_EXEC cp /mnt/dietpi_userdata/medusa/runscripts/init.systemd /etc/systemd/system/medusa.service # - Prevent unlimited restarts on failure: Permit up to three restarts in 10 minutes G_CONFIG_INJECT 'StartLimitIntervalSec=' 'StartLimitIntervalSec=600' /etc/systemd/system/medusa.service '\[Unit\]' G_CONFIG_INJECT 'StartLimitBurst=' 'StartLimitBurst=3' /etc/systemd/system/medusa.service 'StartLimitIntervalSec=' # - Remove "Group=medusa" which does not exist, instead fallback to primary group "dietpi" G_EXEC sed -i '/^[[:blank:]]*Group=/d' /etc/systemd/system/medusa.service # - Launch from our install and data directory G_CONFIG_INJECT 'ExecStart=' "ExecStart=$(command -v python3) /mnt/dietpi_userdata/medusa/start.py -q --nolaunch --datadir=/mnt/dietpi_userdata/medusa" /etc/systemd/system/medusa.service # Permissions G_EXEC chown -R medusa:dietpi /mnt/dietpi_userdata/medusa fi if To_Install 50 syncthing syncthing-inotify # 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/v1.23.4/syncthing-linux-$arch-v1.23.4.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 # Permit self-updates G_EXEC chown -R dietpi /opt/syncthing # Pre-create and edit default config only on fresh installs if [[ ! -f '/mnt/dietpi_userdata/syncthing/config.xml' ]] then # Failsafe: Assure that "dietpi" has permission to create the /mnt/dietpi_userdata/syncthing directory G_EXEC chown dietpi /mnt/dietpi_userdata # Run Syncthing to pre-create config dir and exit G_EXEC_OUTPUT=1 G_EXEC sudo -u dietpi /opt/syncthing/syncthing -generate=/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 -i '\|:8384|c\
0.0.0.0:8384
' /mnt/dietpi_userdata/syncthing/config.xml # Set default data directory G_EXEC mkdir -p /mnt/dietpi_userdata/syncthing_data G_EXEC chown -R dietpi:dietpi /mnt/dietpi_userdata/syncthing_data G_EXEC sed -i '\| /etc/systemd/system/syncthing.service [Unit] Description=Syncthing (DietPi) Wants=network-online.target After=network-online.target StartLimitIntervalSec=60 StartLimitBurst=4 [Service] User=dietpi ExecStart=/opt/syncthing/syncthing --no-browser --no-restart --logflags=0 -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#how-do-i-increase-the-inotify-limit-to-get-my-filesystem-watcher-to-work G_EXEC eval "echo 'fs.inotify.max_user_watches=204800' > /etc/sysctl.d/dietpi-syncthing.conf" 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 G_AGI chromium-browser chromium-codecs-ffmpeg-extra libpam-systemd Create_Desktop_Shortcut chromium-browser # Enable KMS grep -Eq '^[[:blank:]]*dtoverlay=vc4-f?kms-v3d' /boot/config.txt || /boot/dietpi/func/dietpi-set_hardware rpi-opengl vc4-kms-v3d # Bullseye: Enable hardware codecs (( $G_DISTRO < 6 )) || /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/ local flags="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" # - x86_64: OpenGL, else GLES (( $G_HW_ARCH == 10 )) && flags+='"' || flags+=' --use-gl=egl"' # - RPi Buster: Uses /etc/chromium-browser/customizations, else /etc/chromium.d: https://github.com/RPi-Distro/chromium-browser/commit/f4a599d local path='chromium.d' (( $G_DISTRO > 5 || $G_HW_MODEL > 9 )) || path='chromium-browser/customizations' echo "$flags" > "/etc/$path/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+=' --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_ [[ $path == 'chromium.d' ]] || G_EXEC sed -i 's|chromium\.d|chromium-browser/customizations|' /var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh G_EXEC chmod +x /var/lib/dietpi/dietpi-software/installed/chromium-autostart.sh fi if To_Install 136 motioneye # motionEye then # x86_64/ARMv8 dependencies: libcurl4-openssl-dev gcc libssl-dev for pycurl build [[ $G_HW_MODEL == [12] ]] || G_AGI libcurl4-openssl-dev gcc libssl-dev # RPi: Enable camera module (( $G_HW_MODEL > 9 )) || /boot/dietpi/func/dietpi-set_hardware rpi-camera enable # motionEye G_EXEC_OUTPUT=1 G_EXEC pip3 install -U 'https://github.com/motioneye-project/motioneye/archive/dev.tar.gz' G_EXEC_OUTPUT=1 G_EXEC motioneye_init --skip-apt-update G_EXEC systemctl stop motioneye G_EXEC systemctl --no-reload disable --now motion # motionEye starts motion directly. # 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') # - On RPi, add RPi Camera support by default (( $G_HW_MODEL > 9 )) || 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 # - On RPi, if the RPi camera module is enabled already, use it by default. local input='input_uvc.so -d /dev/video0' [[ $G_HW_MODEL -gt 9 || -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 sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.stream "http://$(G_GET_NET ip):8082/?action=stream" G_EXEC sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.snapshot 'http://127.0.0.1:8082/?action=snapshot' G_EXEC sudo -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 then # https://sabnzbd.org/wiki/installation/install-off-modules # APT deps aDEPS=('par2' 'p7zip-full') # ARMv8: No sabyenc3 wheels available: https://pypi.org/project/sabyenc3/#files (( $G_HW_ARCH == 3 )) && aDEPS+=('gcc') # Download 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 ") # 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 [Service] SyslogIdentifier=SABnzbd User=sabnzbd ExecStart=$(command -v 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 /etc/sabnzbd/sabnzbd.ini sabnzbd then G_SLEEP 1 # Additional wait, config being overwritten after below changes: https://dietpi.com/forum/t/bug-sabnzbd/1224 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 177 firefox-sync # Firefox Sync Server then # Dependencies: https://github.com/mozilla-services/syncserver#quickstart aDEPS=('make' 'python-virtualenv' 'python-dev' 'g++' 'libmariadb-dev') # - ARM: libffi-dev for cffi, libssl-dev for cryptography (( $G_HW_ARCH < 10 )) && aDEPS+=('libffi-dev' 'libssl-dev') # Download & Install Download_Install "https://github.com/mozilla-services/syncserver/archive/master.tar.gz" [[ -d '/opt/firefox-sync' ]] && G_EXEC rm -R /opt/firefox-sync G_EXEC mv syncserver-master /opt/firefox-sync # Build G_EXEC cd /opt/firefox-sync G_EXEC sed -i -e '/^psycopg2/d' -e 's/.zip$/.tar.gz/' requirements.txt # We use SQLite, and save some bytes G_EXEC_OUTPUT=1 G_EXEC make build G_EXEC cd "$G_WORKING_DIR" # User Create_User -d /mnt/dietpi_userdata/firefox-sync ffsync # Create database and config directory [[ -d '/mnt/dietpi_userdata/firefox-sync' ]] || G_EXEC mkdir /mnt/dietpi_userdata/firefox-sync # Create database if it doesn't exist [[ -f '/mnt/dietpi_userdata/firefox-sync/FF-Sync-DB.db' ]] || G_EXEC sqlite3 /mnt/dietpi_userdata/firefox-sync/FF-Sync-DB.db 'create table aTable(field1 int); drop table aTable;' # Copy and modify default config file if it doesn't exist local ffsync_conf='/mnt/dietpi_userdata/firefox-sync/syncserver.ini' if [[ ! -f $ffsync_conf ]] then G_EXEC cp -a /opt/firefox-sync/syncserver.ini "$ffsync_conf" local ffsync_ip=$(G_GET_NET ip) G_CONFIG_INJECT 'host =' "host = $ffsync_ip" "$ffsync_conf" G_CONFIG_INJECT 'port =' 'port = 5002' "$ffsync_conf" # Avoid port conflict with Shairport Sync G_CONFIG_INJECT 'public_url =' "public_url = http://$ffsync_ip:5002/" "$ffsync_conf" G_CONFIG_INJECT 'sqluri = sqlite:' 'sqluri = sqlite:////mnt/dietpi_userdata/firefox-sync/FF-Sync-DB.db' "$ffsync_conf" fi # Service cat << _EOF_ > /etc/systemd/system/firefox-sync.service [Unit] Description=Firefox Sync Server (DietPi) Documentation=https://github.com/mozilla-services/syncserver Wants=network-online.target After=network-online.target [Service] SyslogIdentifier=Firefox Sync Server User=ffsync WorkingDirectory=/mnt/dietpi_userdata/firefox-sync ExecStart=/opt/firefox-sync/local/bin/gunicorn --paste $ffsync_conf # Hardening ProtectSystem=strict ProtectHome=true PrivateTmp=true PrivateDevices=true ProtectKernelTunables=true ProtectControlGroups=true ReadWritePaths=-/mnt/dietpi_userdata/firefox-sync [Install] WantedBy=multi-user.target _EOF_ # Permissions G_EXEC chown -R ffsync:ffsync /mnt/dietpi_userdata/firefox-sync fi if To_Install 183 vaultwarden # vaultwarden then [[ -f '/opt/vaultwarden/target/release/vaultwarden' ]] && G_EXEC rm -R /opt/vaultwarden # Pre-v8.7 [[ -f '/etc/systemd/system/vaultwarden.service' ]] && G_EXEC rm /etc/systemd/system/vaultwarden.service # Pre-v8.7 Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/vaultwarden_$G_HW_ARCH_NAME.deb" 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) G_EXEC_NOEXIT=1 G_EXEC_OUTPUT=1 G_EXEC ./install.sh || aSOFTWARE_INSTALL_STATE[$software_id]=-1 G_EXEC rm install.sh # 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 fi if To_Install 142 # MicroK8s then # APT deps G_AGI snapd # Install or upgrade 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 141 spotify-connect-web # Spotify Connect Web then # Download and merge into existing directory Download_Install 'https://github.com/Fornoth/spotify-connect-web/releases/download/0.0.4-alpha/spotify-connect-web_0.0.4-alpha.tar.gz' /mnt/dietpi_userdata # Service cat << '_EOF_' > /etc/systemd/system/spotify-connect-web.service [Unit] Description=Spotify Connect Web (DietPi) Wants=network-online.target After=network-online.target sound.target [Service] WorkingDirectory=/mnt/dietpi_userdata/spotify-connect-web ExecStart=/mnt/dietpi_userdata/spotify-connect-web/spotify-connect-web [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 143 koel # Koel then # APT dependencies: https://docs.koel.dev/#server > https://laravel.com/docs/9.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 and Koel v5.1 requires PHP 7.4 if (( ${PHP_VERSION::1} > 7 )) then aDEPS+=("php$PHP_VERSION-curl") local fallback_url='https://github.com/koel/koel/releases/download/v6.11.0/koel-v6.11.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') if [[ $PHP_VERSION == '7.4' ]] then Download_Install 'https://github.com/koel/koel/releases/download/v5.1.14/koel-v5.1.14.tar.gz' else Download_Install 'https://github.com/koel/koel/releases/download/v5.0.2/koel-v5.0.2.tar.gz' fi 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 sudo -u koel "php$PHP_VERSION" artisan koel:init -n --no-assets G_EXEC_OUTPUT=1 G_EXEC sudo -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 # https://sonarr.tv/#downloads-v3-linux-debian # APT repo key G_EXEC apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-keys '2009837CBFFD68F45BC180471F4F90DE2A9B4BF8' # APT repo list local distro=${G_DISTRO_NAME/bookworm/bullseye} G_EXEC eval "echo 'deb https://apt.sonarr.tv/debian/ ${distro/bullseye/buster} main' > /etc/apt/sources.list.d/sonarr.list" # Update package lists 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 # Pre-v7.1: Remove Sonarr v2 key, PID file and database backups from DietPi-Arr_to_RAM [[ $(apt-key list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]] && G_EXEC apt-key del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' [[ -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 [[ -d '/mnt/dietpi_userdata/sonarr' ]] || G_EXEC mkdir /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 [Service] SyslogIdentifier=Sonarr User=sonarr UMask=002 LogsDirectory=sonarr ExecStart=$(command -v mono) /usr/lib/sonarr/bin/Sonarr.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=-/usr/lib/sonarr -/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 /usr/lib/sonarr fi if To_Install 145 radarr # Radarr then # APT dependencies aDEPS=('mediainfo') # - .NET: https://github.com/dotnet/core/blob/main/Documentation/linux-prereqs.md if (( $G_HW_ARCH != 1 )) then case $G_DISTRO in 5) aDEPS+=('libicu63');; 6) aDEPS+=('libicu67');; *) aDEPS+=('libicu72');; esac fi # Reinstall: Skip download and install, advice to use internal updater from web UI if [[ -d '/opt/radarr' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/radarr\" 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 reinstall $software_id\"." G_AGI "${aDEPS[@]}" aDEPS=() else # ARMv6: Radarr v4 does not support Mono anymore if (( $G_HW_ARCH == 1 )) then local url='https://github.com/Radarr/Radarr/releases/download/v3.2.2.5080/Radarr.master.3.2.2.5080.linux.tar.gz' # ARMv7 else local url=$(curl -sSfL 'https://api.github.com/repos/Radarr/Radarr/releases/latest' | mawk -F\" '/"browser_download_url": .*linux-core-arm\.tar\.gz"/{print $4}') local fallback_url='https://github.com/Radarr/Radarr/releases/download/v4.3.2.6857/Radarr.master.4.3.2.6857.linux-core-arm.tar.gz' fi # ARMv8 if (( $G_HW_ARCH == 3 )) then url=${url/arm/arm64} fallback_url=${fallback_url/arm/arm64} # x86_64 elif (( $G_HW_ARCH == 10 )) then url=${url/arm/x64} fallback_url=${fallback_url/arm/x64} fi Download_Install "$url" G_EXEC mv Radarr /opt/radarr fi # 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 [[ -d '/mnt/dietpi_userdata/radarr' ]] || G_EXEC mkdir /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 [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/core/blob/main/Documentation/linux-prereqs.md if (( $G_HW_ARCH != 1 )) then case $G_DISTRO in 5) aDEPS+=('libicu63');; 6) aDEPS+=('libicu67');; *) aDEPS+=('libicu72');; esac fi # Pre-v7.5 ARMv6: Migrate old install dir [[ -d '/opt/Lidarr' && ! -d '/opt/lidarr' ]] && G_EXEC mv /opt/{L,l}idarr # Reinstall: Skip download and install, advice to use internal updater from web UI if [[ -d '/opt/lidarr' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/lidarr\" 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 reinstall $software_id\"." G_AGI "${aDEPS[@]}" aDEPS=() else # ARMv6: Lidarr v1 does not support Mono anymore if (( $G_HW_ARCH == 1 )) then local url='https://github.com/Lidarr/Lidarr/releases/download/v0.8.1.2135/Lidarr.master.0.8.1.2135.linux.tar.gz' # ARMv7 else local url=$(curl -sSfL 'https://api.github.com/repos/Lidarr/Lidarr/releases/latest' | mawk -F\" '/"browser_download_url": .*linux-core-arm\.tar\.gz"/{print $4}') local fallback_url='https://github.com/Lidarr/Lidarr/releases/download/v1.0.2.2592/Lidarr.master.1.0.2.2592.linux-core-arm.tar.gz' fi # ARMv8 if (( $G_HW_ARCH == 3 )) then url=${url/arm/arm64} fallback_url=${fallback_url/arm/arm64} # x86_64 elif (( $G_HW_ARCH == 10 )) then url=${url/arm/x64} fallback_url=${fallback_url/arm/x64} fi Download_Install "$url" G_EXEC mv Lidarr /opt/lidarr fi # Data dir [[ -d '/mnt/dietpi_userdata/lidarr' ]] || G_EXEC mkdir /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 [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 then # https://wiki.bazarr.media/Getting-Started/Installation/Linux/linux/ Download_Install 'https://github.com/morpheus65535/bazarr/releases/latest/download/bazarr.zip' bazarr # Dependencies (( $G_HW_ARCH < 3 )) && G_AGI libatlas3-base # numpy from piwheels deps: https://piwheels.org/project/numpy/ (( $G_HW_ARCH == 3 || ( $G_HW_ARCH == 10 && $G_DISTRO > 5 ) )) && G_AGI gcc # webrtcvad-wheels build on ARMv8 and x86_64 Bullseye+: https://pypi.org/project/webrtcvad-wheels/#files G_EXEC cd bazarr G_EXEC_OUTPUT=1 G_EXEC pip3 install -Ur requirements.txt G_EXEC cd .. # Always perform a clean full reinstall [[ -d '/opt/bazarr' ]] && G_EXEC rm -R /opt/bazarr G_EXEC mv bazarr /opt # Data dir [[ -d '/mnt/dietpi_userdata/bazarr' ]] || G_EXEC mkdir /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:dietpi /mnt/dietpi_userdata/bazarr /opt/bazarr # Service: https://github.com/morpheus65535/bazarr/wiki/Autostart-on-Linux-Windows-MacOS-FreeBSD#systemd-service-file-for-debian-ubuntu 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 ExecStart=$(command -v python3) /opt/bazarr/bazarr.py -c /mnt/dietpi_userdata/bazarr # 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 /mnt/dietpi_userdata/bazarr/config/config.ini 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 '/[0-9]+<\/Port>/{s/^.*([0-9]+)<\/Port>.*$/\1/p;q}' /mnt/dietpi_userdata/sonarr/config.xml) local apikey=$(sed -nE '/.+<\/ApiKey>/{s/^.*(.+)<\/ApiKey>.*$/\1/p;q}' /mnt/dietpi_userdata/sonarr/config.xml) G_EXEC sed -i '/\[sonarr\]/,/^$/s/^ip = .*$/ip = 127.0.0.1/' /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i "/\[sonarr\]/,/^$/s/^port = .*$/port = $port/" /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i '/\[sonarr\]/,/^$/s/^base_url = .*$/base_url = \//' /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i "/\[sonarr\]/,/^$/s/^apikey = .*$/apikey = $apikey/" /mnt/dietpi_userdata/bazarr/config/config.ini G_CONFIG_INJECT 'use_sonarr[[:blank:]]*=' 'use_sonarr = True' /mnt/dietpi_userdata/bazarr/config/config.ini '\[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 '/[0-9]+<\/Port>/{s/^.*([0-9]+)<\/Port>.*$/\1/p;q}' /mnt/dietpi_userdata/radarr/config.xml) local apikey=$(sed -nE '/.+<\/ApiKey>/{s/^.*(.+)<\/ApiKey>.*$/\1/p;q}' /mnt/dietpi_userdata/radarr/config.xml) G_EXEC sed -i '/\[radarr\]/,/^$/s/^ip = .*$/ip = 127.0.0.1/' /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i "/\[radarr\]/,/^$/s/^port = .*$/port = $port/" /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i '/\[radarr\]/,/^$/s/^base_url = .*$/base_url = \//' /mnt/dietpi_userdata/bazarr/config/config.ini G_EXEC sed -i "/\[radarr\]/,/^$/s/^apikey = .*$/apikey = $apikey/" /mnt/dietpi_userdata/bazarr/config/config.ini G_CONFIG_INJECT 'use_radarr[[:blank:]]*=' 'use_radarr = True' /mnt/dietpi_userdata/bazarr/config/config.ini '\[general\]' fi fi fi if To_Install 146 tautulli # Tautulli then # Reinstall: Skip download and install, advice to use internal updater from web UI if [[ -d '/opt/tautulli' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/tautulli\" 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 reinstall $software_id\"." G_AGI python3-pkg-resources else 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 G_EXEC mv Tautulli /opt/tautulli fi # User Create_User -d /mnt/dietpi_userdata/tautulli tautulli # Directory [[ -d '/mnt/dietpi_userdata/tautulli' ]] || G_EXEC mkdir /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=$(command -v 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/core/blob/main/Documentation/linux-prereqs.md if (( $G_HW_ARCH != 1 )) then case $G_DISTRO in 5) aDEPS=('libicu63');; 6) aDEPS=('libicu67');; *) aDEPS=('libicu72');; esac fi 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.20.2444/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/ # Remove existing install dir [[ -d '/opt/jackett' ]] && G_EXEC rm -R /opt/jackett # Move unpacked install dir in place 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=5 [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 G_EXEC curl -sSfL 'https://nzbget.net/download/nzbget-latest-bin-linux.run' -o package.run G_EXEC mkdir -p /mnt/dietpi_userdata/nzbget G_EXEC_OUTPUT=1 G_EXEC dash package.run --destdir /mnt/dietpi_userdata/nzbget G_EXEC rm package.run # User Create_User -g dietpi -d /mnt/dietpi_userdata/nzbget nzbget # Permissions G_EXEC chown -R nzbget:root /mnt/dietpi_userdata/nzbget G_EXEC chmod 0600 /mnt/dietpi_userdata/nzbget/nzbget.conf # Config G_BACKUP_FP /mnt/dietpi_userdata/nzbget/nzbget.conf 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 'LogFile=' 'LogFile=/var/log/nzbget.log' /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 'Server1.Cipher=' 'Server1.Cipher=RC4-MD5' /mnt/dietpi_userdata/nzbget/nzbget.conf 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 'CrashTrace=' 'CrashTrace=no' /mnt/dietpi_userdata/nzbget/nzbget.conf G_CONFIG_INJECT 'DetailTarget=' 'DetailTarget=none' /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 # Service cat << '_EOF_' > /etc/systemd/system/nzbget.service [Unit] Description=NZBGet (DietPi) Wants=network-online.target After=network-online.target remote-fs.targe [Service] Type=forking User=nzbget WorkingDirectory=/mnt/dietpi_userdata/nzbget ExecStart=/mnt/dietpi_userdata/nzbget/nzbget -D [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 151 prowlarr # Prowlarr then # .NET dependency: https://github.com/dotnet/core/blob/main/Documentation/linux-prereqs.md case $G_DISTRO in 5) aDEPS=('libicu63');; 6) aDEPS=('libicu67');; *) aDEPS=('libicu72');; esac # Reinstall: Skip download and install, advice to use internal updater from web UI if [[ -d '/opt/prowlarr' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/prowlarr\" 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 reinstall $software_id\"." G_AGI "${aDEPS[@]}" aDEPS=() else 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/v1.3.2.3006/Prowlarr.master.1.3.2.3006.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}")" G_EXEC mv Prowlarr /opt/prowlarr fi # Data dir [[ -d '/mnt/dietpi_userdata/prowlarr' ]] || G_EXEC mkdir /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 [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/core/blob/main/Documentation/linux-prereqs.md case $G_DISTRO in 5) aDEPS=('libicu63');; 6) aDEPS=('libicu67');; *) aDEPS=('libicu72');; esac # Reinstall: Skip download and install, advice to use internal updater from web UI if [[ -d '/opt/readarr' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/readarr\" 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 reinstall $software_id\"." G_AGI "${aDEPS[@]}" aDEPS=() else 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.1.4.1596/Readarr.develop.0.1.4.1596.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)" G_EXEC mv Readarr /opt/readarr fi # Data dir [[ -d '/mnt/dietpi_userdata/readarr' ]] || G_EXEC mkdir /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 [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.git' G_CHECK_URL "$url" # APT deps case $G_HW_ARCH in [12]|11) if (( $G_DISTRO < 7 )) then G_AGI libtiff5 libopenjp2-7 libxcb1 # ARMv6/7: Runtime libs for Pillow from piwheels (libtiff5 pulls libjpeg62-turbo) else # Bookworm: Most wheels need to be compiled: gcc and libffi-dev for cffi, libssl-dev and Rust for cryptography and bcrypt, make for PyNaCl, libjpeg62-turbo-dev for Pillow G_AGI gcc libffi-dev libssl-dev make libjpeg62-turbo-dev G_EXEC curl -sSf 'https://sh.rustup.rs/' -o rustup-init.sh G_EXEC chmod +x rustup-init.sh G_EXEC_OUTPUT=1 G_EXEC ./rustup-init.sh -y --profile minimal G_EXEC rm rustup-init.sh export PATH="/root/.cargo/bin:$PATH" fi ;; 3) G_AGI gcc;; # gcc for psutil *) :;; esac 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=$(command -v python3) -OO /mnt/dietpi_userdata/htpc-manager/Htpc.py [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 153 octoprint # OctoPrint then # ARMv8 and x86_64 Bookworm: gcc for netifaces, psutil (ARMv8-only) (( $G_HW_ARCH == 3 )) || (( $G_HW_ARCH == 10 && $G_DISTRO > 6 )) && G_AGI gcc # RISC-V: gcc and libffi-dev for cffi (( $G_HW_ARCH == 11 )) && G_AGI gcc libffi-dev # Pre-create user and its home directory to allow user-level Python instance Create_User -G dialout,tty,video -d /mnt/dietpi_userdata/octoprint octoprint [[ -d '/mnt/dietpi_userdata/octoprint' ]] || G_EXEC mkdir /mnt/dietpi_userdata/octoprint G_EXEC chown -R octoprint:octoprint /mnt/dietpi_userdata/octoprint # 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 G_EXEC_OUTPUT=1 G_EXEC sudo -u octoprint 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 sudo -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 echo "octoprint ALL=NOPASSWD: $(command -v systemctl) restart octoprint, $(command -v reboot), $(command -v poweroff)" > /etc/sudoers.d/octoprint G_EXEC sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.commands.serverRestartCommand 'sudo systemctl restart octoprint' G_EXEC sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set server.commands.systemRestartCommand 'sudo reboot' G_EXEC sudo -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 sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.stream "http://$(G_GET_NET ip):8082/?action=stream" G_EXEC sudo -u octoprint /mnt/dietpi_userdata/octoprint/.local/bin/octoprint config set webcam.snapshot 'http://127.0.0.1:8082/?action=snapshot' G_EXEC sudo -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 then # https://help.roonlabs.com/portal/en/kb/articles/linux-install#Manual_Install # .NET dependency: https://github.com/dotnet/core/blob/main/Documentation/linux-prereqs.md case $G_DISTRO in 5) aDEPS=('libicu63');; 6) aDEPS=('libicu67');; *) aDEPS=('libicu72');; esac # Reinstall: Skip download and install, advice to use internal updater if [[ -d '/opt/roonserver' ]] then G_DIETPI-NOTIFY 2 "${aSOFTWARE_NAME[$software_id]} install dir \"/opt/roonserver\" already exists. Download and install steps will be skipped. - If you want to update ${aSOFTWARE_NAME[$software_id]}, please use the internal updater. - If you need to reinstall (e.g. broken instance), please manually remove the install dir and rerun \"dietpi-software (re)install $software_id\"." G_AGI "${aDEPS[@]}" aDEPS=() else Download_Install 'https://download.roonlabs.net/builds/RoonServer_linuxx64.tar.bz2' G_EXEC mv RoonServer /opt/roonserver fi # 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 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/bullseye/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 :9199" # 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 # Detect distro local distro='debian' (( $G_HW_MODEL < 10 )) && (( $G_RASPBIAN )) && distro='raspbian' # 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/ $G_DISTRO_NAME stable' > /etc/apt/sources.list.d/docker.list" G_AGUP # 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 docker-ce 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 [[ -d '/lib/systemd/system/docker.service.d' ]] || G_EXEC mkdir /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 [[ -d '/mnt/dietpi_userdata/docker-data' ]] || G_EXEC mkdir /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 [[ -d '/etc/docker' ]] || G_EXEC mkdir /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 [[ -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 G_AGI docker-compose-plugin 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://repo.opencollab.dev/artifactory/maven-snapshots/cn/nukkit/nukkit/1.0-SNAPSHOT/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=$(command -v java) -jar /usr/local/bin/nukkit/nukkit.jar [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';; *) local arch='arm-6';; esac local fallback_url="https://github.com/go-gitea/gitea/releases/download/v1.19.0/gitea-1.19.0-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 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 163 gmediarender # GMediaRender then # Pre-v8.10 [[ -f '/etc/systemd/system/gmediarender.service' ]] && G_EXEC rm /etc/systemd/system/gmediarender.service [[ -d '/etc/systemd/system/gmediarender.service.d' ]] && grep -Rq '/usr/local/bin/gmediarender' /etc/systemd/system/gmediarender.service.d && G_EXEC rm -R /etc/systemd/system/gmediarender.service.d getent passwd gmrender > /dev/null && G_EXEC userdel gmrender getent group gmrender > /dev/null && G_EXEC groupdel gmrender [[ -f '/usr/local/bin/gmediarender' ]] && G_EXEC rm /usr/local/bin/gmediarender [[ -d '/usr/local/share/gmediarender' ]] && G_EXEC rm -R /usr/local/share/gmediarender Download_Install "https://dietpi.com/downloads/binaries/$G_DISTRO_NAME/gmediarender_$G_HW_ARCH_NAME.deb" G_EXEC systemctl stop gmediarender fi if To_Install 160 # Allo GUI then # Get latest compatible version local version=$(curl -sSf 'https://api.github.com/repos/MichaIng/DietPi-AlloGUI/tags' | mawk -F\" '/"name": "v14\..*",/{print $4;exit}'); version=${version#v} [[ $version ]] || { version='14.2'; 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 Download_Install "https://github.com/MichaIng/DietPi-AlloGUI/archive/v$version.tar.gz" G_EXEC mv "DietPi-AlloGUI-$version" 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/urandom | 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 [[ -e '/var/www/allo' ]] && G_EXEC rm -R /var/www/allo # Failsafe G_EXEC ln -sf /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 /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 Boot OK : GPIO22=out, High Soft Shutdown : GPIO04=out, Low' 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...' poweroff 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 then # https://dtcooper.github.io/raspotify/#hard-installation # 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' # ARMv7/ARMv8/x86_64 else # APT key local url='https://dtcooper.github.io/raspotify/key.asc' G_CHECK_URL "$url" G_EXEC eval "curl -sSfL '$url' | gpg --dearmor -o /etc/apt/trusted.gpg.d/dietpi-raspotify.gpg --yes" # APT list G_EXEC eval 'echo '\''deb https://dtcooper.github.io/raspotify/ raspotify main'\'' > /etc/apt/sources.list.d/raspotify.list' G_AGUP # APT package G_AGI raspotify fi # Stop service G_EXEC systemctl stop raspotify fi if To_Install 169 alsa-init voice-recognizer # Google AIY then G_EXEC_OUTPUT=1 G_EXEC git clone -b voicekit 'https://github.com/google/aiyprojects-raspbian.git' /mnt/dietpi_userdata/voice-recognizer-raspi G_EXEC cd /mnt/dietpi_userdata/voice-recognizer-raspi G_EXEC_OUTPUT=1 G_EXEC pip3 install -U pip virtualenv G_EXEC_OUTPUT=1 G_EXEC virtualenv --system-site-packages -p python3 env G_EXEC_OUTPUT=1 G_EXEC env/bin/pip install -Ur requirements.txt #??? ARMv7 only (( $G_HW_ARCH == 2 )) && G_EXEC_OUTPUT=1 G_EXEC env/bin/pip install 'google-assistant-library==0.0.3' # Services G_EXEC sed -i 's|/home/pi|/mnt/dietpi_userdata|g' systemd/voice-recognizer.service G_CONFIG_INJECT 'User=' 'User=dietpi' systemd/voice-recognizer.service '\[Service\]' G_EXEC cp systemd/alsa-init.service /etc/systemd/system/ G_EXEC cp systemd/voice-recognizer.service /etc/systemd/system/ # shellcheck disable=SC1091 source env/bin/activate # Enable default app for service start G_EXEC cp src/assistant_library_with_button_demo.py src/main.py G_EXEC cd "$G_WORKING_DIR" # Symlink userdata location for assistant.json G_EXEC ln -sf /mnt/dietpi_userdata/voice-recognizer-raspi/assistant.json /home/dietpi/assistant.json # Generate cache dir G_EXEC mkdir -p /home/dietpi/.cache/voice-recognizer # Setup soundcard /boot/dietpi/func/dietpi-set_hardware soundcard googlevoicehat-soundcard # Permissions getent passwd dietpi > /dev/null && G_EXEC chown -R dietpi:dietpi /mnt/dietpi_userdata/voice-recognizer-raspi fi if To_Install 176 mycroft # Mycroft AI then # Git clone to DietPi userdata G_EXEC cd /mnt/dietpi_userdata if [[ ! -d 'mycroft-core/.git' ]] then [[ -d 'mycroft-core' ]] && G_EXEC rm -R mycroft-core G_THREAD_START git clone -b master --depth 1 https://github.com/MycroftAI/mycroft-core.git fi # APT deps aDEPS=('vorbis-tools') # Pre-create global config to reflect correct data dir and audio settings within install # - Overwrite existing config, user should use /mnt/dietpi_userdata/mycroft-data/.mycroft/mycroft.conf instead to override. dps_index=$software_id Download_Install 'mycroft.conf' /etc/mycroft/mycroft.conf # Pre-create user and directories with correct permissions Create_User -G audio -d /mnt/dietpi_userdata/mycroft-data mycroft G_EXEC mkdir -p /mnt/dietpi_userdata/mycroft-data/skills G_EXEC chown -R mycroft:mycroft /etc/mycroft /mnt/dietpi_userdata/mycroft-{core,data} # - Force skills to be placed directly into data dir G_EXEC rm -Rf /opt/mycroft # symlink G_EXEC ln -s /mnt/dietpi_userdata/mycroft-data /opt/mycroft # - Grant mycroft user sudo permissions which is required for dev_setup.sh and some other Mycroft scripts G_EXEC eval 'echo '\''mycroft ALL=NOPASSWD: ALL'\'' > /etc/sudoers.d/mycroft' # Assure 2 GiB overall memory (-100 MiB to avoid tiny swap space) is available if (( $RAM_TOTAL < 1948 )) then G_DIETPI-NOTIFY 2 '\e[33m[WARNING] Insufficient overall memory size: Mycroft AI requires at least 2 GiB memory on first start. We will now attempt to increase your swap size to satisfy this requirement.' /boot/dietpi/func/dietpi-set_swapfile 1 fi # Run installer as user mycroft G_EXEC cd /mnt/dietpi_userdata/mycroft-core # -sm: Skip mimic build which is time intense and can be manually done any time later. # - Remove PulseAudio from dependencies, we use ALSA G_EXEC sed -Ei 's/[^[:blank:]"'\'']*pulseaudio[^[:blank:]"'\'']*//g' ./dev_setup.sh G_EXEC_OUTPUT=1 G_EXEC sudo -u mycroft ./dev_setup.sh -sm G_EXEC cd "$G_WORKING_DIR" # Service cat << '_EOF_' > /etc/systemd/system/mycroft.service [Unit] Description=Mycroft AI (DietPi) Wants=network-online.target After=network-online.target [Service] Type=forking SyslogIdentifier=Mycroft AI User=mycroft LogsDirectory=mycroft WorkingDirectory=/mnt/dietpi_userdata/mycroft-data ExecStart=/mnt/dietpi_userdata/mycroft-core/start-mycroft.sh all ExecStop=/mnt/dietpi_userdata/mycroft-core/stop-mycroft.sh [Install] WantedBy=multi-user.target _EOF_ # Add Mycroft binaries to $PATH and create CLI alias: https://github.com/MichaIng/DietPi/issues/5100 cat << '_EOF_' > /etc/bashrc.d/mycroft.sh #!/bin/dash case "$PATH" in *'/mnt/dietpi_userdata/mycroft-core/bin'*) :;; *) export PATH="$PATH:/mnt/dietpi_userdata/mycroft-core/bin";; esac alias mycroft-cli-client='sudo -u mycroft /mnt/dietpi_userdata/mycroft-core/bin/mycroft-cli-client' _EOF_ # Enable ALSA automatic software conversion plugin local soundcard=$(sed -n '/^[[:blank:]]*CONFIG_SOUNDCARD=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) soundcard=${soundcard%-eq} soundcard=${soundcard%-plug} /boot/dietpi/func/dietpi-set_hardware soundcard "$soundcard-plug" fi if To_Install 86 roon-extension-manager # Roon Extension Manager then # Data dir [[ -d '/mnt/dietpi_userdata/roon-extension-manager' ]] || G_EXEC mkdir /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 # Raspberry Pi Bullseye: Enable hardware codecs (( $G_HW_MODEL > 9 )) || (( $G_DISTRO < 6 )) || /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 main' > /etc/apt/sources.list.d/dietpi-jellyfin.list" G_AGUP # APT meta package: Server, web component and FFmpeg implementation G_AGI jellyfin if [[ -d '/mnt/dietpi_userdata/jellyfin' || -f '/etc/jellyfin/network.xml' ]] then G_EXEC systemctl stop jellyfin else CREATE_CONFIG_CONTENT='AddPeopleQueryIndex' Create_Config '/etc/jellyfin/migrations.xml' jellyfin 60 fi # 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 # Start service until /etc/jellyfin/network.xml exists Create_Config '/etc/jellyfin/network.xml' jellyfin # 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 [[ -d '/etc/systemd/system/jellyfin.service.d' ]] || G_EXEC mkdir /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 # shellcheck disable=SC2015 [[ -d '/var/cache/jellyfin' ]] && G_EXEC mv /var/cache/jellyfin /mnt/dietpi_userdata/jellyfin/cache || G_EXEC mkdir /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 G_CONFIG_INJECT '' '8097' /etc/jellyfin/network.xml G_CONFIG_INJECT '' ' 8097' /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.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"; } 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 .. -DRPI2=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RPi 3 elif (( $G_HW_MODEL == 3 )) then G_EXEC cmake .. -DRPI3=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RPi 4 elif (( $G_HW_MODEL == 4 )) then G_EXEC cmake .. -DRPI4=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - Odroids elif (( $G_HW_MODEL < 20 )) then G_EXEC cmake .. -DODROID=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - ASUS Tinker Board elif (( $G_HW_MODEL == 52 )) then G_EXEC cmake .. -DRK3288=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - Others else G_EXEC cmake .. -DARM_DYNAREC=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo 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 # 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.2.2'; 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 .. -DRV64=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RPi 3 elif (( $G_HW_MODEL == 3 )) then G_EXEC cmake .. -DRPI3ARM64=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RPi 4 elif (( $G_HW_MODEL == 4 )) then G_EXEC cmake .. -DRPI4ARM64=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - Odroid N2 elif (( $G_HW_MODEL == 15 )) then G_EXEC cmake .. -DODROIDN2=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RK3399 elif (( $G_HW_CPUID == 3 )) then G_EXEC cmake .. -DRK3399=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - RK3588 elif (( $G_HW_CPUID == 11 )) then G_EXEC cmake .. -DRK3588=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo # - Others else G_EXEC cmake .. -DARM_DYNAREC=1 -DNOGIT=1 -DCMAKE_BUILD_TYPE=RelWithDebInfo 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 # 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 27 # TasmoAdmin then # Install required PHP modules aDEPS=("php$PHP_VERSION-curl" "php$PHP_VERSION-zip") # https://github.com/reloxx13/TasmoAdmin#linux # 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/v3.0.1/tasmoadmin_v3.0.1.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}')" # v2 drops PHP <7.4 support: https://github.com/TasmoAdmin/TasmoAdmin/releases/tag/v2.0.0 elif (( $G_DISTRO > 5 )) then Download_Install 'https://github.com/TasmoAdmin/TasmoAdmin/releases/download/v2.4.2/tasmoadmin_v2.4.2.tar.gz' else Download_Install 'https://github.com/TasmoAdmin/TasmoAdmin/releases/download/v1.8.0/tasmoadmin_v1.8.0.tar.gz' fi G_EXEC chown -R www-data:www-data tasmoadmin G_EXEC mv tasmoadmin /var/www/ fi # Webserver config if (( ${aSOFTWARE_INSTALL_STATE[83]} > 0 )) then G_DIETPI-NOTIFY 2 'Apache webserver found, enabling TasmoAdmin specific configuration.' 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" a2enmod setenvif rewrite authz_core authn_core authn_file 1> /dev/null a2ensite dietpi-tasmoadmin 1> /dev/null 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.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.conf' "$tasmoadmin_conf" fi 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" local ha_python_version='3.10.11' # https://github.com/pyenv/pyenv/tree/master/plugins/python-build/share/python-build 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" # Dependencies # - MariaDB support: G_AGI libmariadb-dev; pip3 install mysqlclient|PyMySQL # - Read custom dependencies local custom_apt_deps=$(sed -n '/^[[:blank:]]*SOFTWARE_HOMEASSISTANT_APT_DEPS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) local custom_pip_deps=$(sed -n '/^[[:blank:]]*SOFTWARE_HOMEASSISTANT_PIP_DEPS=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) # - All: gcc, libc6-dev, make, libssl-dev, zlib1g-dev for Python build and libbz2-dev, libreadline-dev, libsqlite3-dev, liblzma-dev to suppress warnings # - All: libffi-dev to solve "ModuleNotFoundError: No module named '_ctypes'", for python-slugify==4.0.1 build on ARMv8/x86_64 and cffi build on ARMv6/7 Bookworm aDEPS=('gcc' 'libc6-dev' 'make' 'libssl-dev' 'zlib1g-dev' 'libbz2-dev' 'libreadline-dev' 'libsqlite3-dev' 'liblzma-dev' 'libffi-dev') mapfile -t -d' ' -O "${#aDEPS[@]}" aDEPS < <(echo -n "$custom_apt_deps") # - ARMv6/7 G_EXEC mkdir -p "$ha_home" G_EXEC chown "$ha_user:$ha_user" "$ha_home" if [[ $G_HW_ARCH == [12] ]] then # libjpeg62-turbo-dev for Pillow, libatlas-base-dev for numpy aDEPS+=('libjpeg62-turbo-dev' 'libatlas-base-dev') # Rust for cryptography G_EXEC curl -sSf 'https://sh.rustup.rs/' -o rustup-init.sh G_EXEC chmod +x rustup-init.sh G_EXEC_OUTPUT=1 G_EXEC sudo -u "$ha_user" ./rustup-init.sh -y --profile minimal G_EXEC rm rustup-init.sh fi # 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" [[ -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" /mnt/dietpi_userdata/homeassistant/deps # Disable pip cache G_EXEC mkdir -p "$ha_home/.pip" G_EXEC eval "echo -e '[global]\nno-cache-dir=true' > '$ha_home/.pip/pip.conf'" # 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 export PYENV_ROOT='$ha_home/.pyenv' export PATH=\"\$PYENV_ROOT/bin:\$PATH\" eval \"\$(pyenv init --path)\" eval \"\$(pyenv init -)\" [ -f '.cargo/env' ] && . .cargo/env" > "$ha_home/pyenv-activate.sh" G_EXEC_DESC='Installing Python with Home Assistant module into pyenv' G_EXEC_OUTPUT=1 G_EXEC sudo -u "$ha_user" dash -c " $ha_pyenv_activation pyenv install $ha_python_version pyenv local $ha_python_version pip3 install -U pip setuptools wheel [ -z '$custom_pip_deps' ] || pip3 install $custom_pip_deps exec pip3 install homeassistant" # 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'" > "$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 [[ -d '/mnt/dietpi_userdata/homeassistant/custom_components' ]] || G_EXEC mkdir /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 version of PaperMC local url='https://papermc.io/api/v2/projects/paper' local 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 [[ -d '/mnt/dietpi_userdata/papermc' ]] || G_EXEC mkdir /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' 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 Download_Install 'https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/master/lastStableBuild/artifact/bootstrap/spigot/target/Geyser-Spigot.jar' /mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot.jar Download_Install 'https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/lastStableBuild/artifact/spigot/target/floodgate-spigot.jar' /mnt/dietpi_userdata/papermc/plugins/floodgate-bukkit.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 1.5 GiB overall memory (-100 MiB to avoid tiny swap space) is available. local heap_size='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 )) # On 2 GiB+ physical RAM devices, apply 1 GiB heap size by default elif (( $RAM_PHYS > 1848 )) then heap_size='1024' 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=$(command -v java) -Xmx${heap_size}m -jar /opt/papermc/paperclip.jar --nogui --noconsole [Install] WantedBy=multi-user.target _EOF_ # Config if [[ -f '/mnt/dietpi_userdata/papermc/plugins/Geyser-Spigot.jar' && -f '/mnt/dietpi_userdata/papermc/plugins/floodgate-bukkit.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 aborted due to outstanding EULA agreement" fi fi if To_Install 140 domoticz # Domoticz then # APT deps aDEPS=('libusb-0.1-4') Download_Install "https://releases.domoticz.com/releases/release/domoticz_linux_${G_HW_ARCH_NAME/armv6l/armv7l}.tgz" domoticz # Reinstall: Clean old install dir [[ -d '/opt/domoticz' ]] && G_EXEC rm -R /opt/domoticz G_EXEC mv domoticz /opt/ # Data dir G_EXEC mkdir -p /mnt/dietpi_userdata/domoticz # Config file if [[ ! -f '/mnt/dietpi_userdata/domoticz/domoticz.conf' ]] then G_EXEC cp /opt/domoticz/scripts/domoticz.conf /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'http_port=' 'http_port=8124' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'ssl_port=' 'ssl_port=8424' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'ssl_cert=' 'ssl_cert=/opt/domoticz/server_cert.pem' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'ssl_key=' 'ssl_key=/opt/domoticz/server_cert.pem' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'ssl_dhparam=' 'ssl_dhparam=/opt/domoticz/server_cert.pem' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'loglevel=' 'loglevel=error' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'syslog=' 'syslog=local7' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'dbase_file=' "dbase_file=/mnt/dietpi_userdata/domoticz/domoticz.db" /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'app_path=' 'app_path=/opt/domoticz' /mnt/dietpi_userdata/domoticz/domoticz.conf G_CONFIG_INJECT 'userdata_path=' "userdata_path=/mnt/dietpi_userdata/domoticz" /mnt/dietpi_userdata/domoticz/domoticz.conf fi # User Create_User -G dialout -d /mnt/dietpi_userdata/domoticz domoticz # Permissions G_EXEC chown -R domoticz:domoticz /opt/domoticz /mnt/dietpi_userdata/domoticz # Copy scripts directory to data dir: https://dietpi.com/forum/t/domoticz-cannot-save-scripts/4945 G_EXEC cp -a /opt/domoticz/scripts /mnt/dietpi_userdata/domoticz/ # Service cat << '_EOF_' > /etc/systemd/system/domoticz.service [Unit] Description=Domoticz (DietPi) Wants=network-online.target After=network-online.target [Service] User=domoticz ExecStart=/opt/domoticz/domoticz -f /mnt/dietpi_userdata/domoticz/domoticz.conf [Install] WantedBy=multi-user.target _EOF_ fi if To_Install 191 snapserver # Snapcast Server then local arch='armhf' (( $G_HW_ARCH == 10 )) && arch='amd64' local fallback_url="https://github.com/badaix/snapcast/releases/download/v0.27.0/snapserver_0.27.0-1_$arch.deb" Download_Install "$(curl -sSfL 'https://api.github.com/repos/badaix/snapcast/releases/latest' | mawk -F\" "/\"browser_download_url\": .*\/snapserver_[^\"\/]*_$arch.deb\"/{print \$4}")" G_EXEC systemctl stop snapserver # Disable JSON RPC by default, if setting was never touched yet G_EXEC sed -i '/^\[tcp\]/,/^\[/s/^#enabled = true$/enabled = false/' /etc/snapserver.conf fi if To_Install 192 snapclient # Snapcast Client then local arch='armhf' (( $G_HW_ARCH == 10 )) && arch='amd64' local fallback_url="https://github.com/badaix/snapcast/releases/download/v0.27.0/snapclient_0.27.0-1_without-pulse_$arch.deb" Download_Install "$(curl -sSfL 'https://api.github.com/repos/badaix/snapcast/releases/latest' | mawk -F\" "/\"browser_download_url\": .*\/snapclient_[^\"\/]*_without-pulse_$arch.deb\"/{print \$4}")" G_EXEC systemctl stop snapclient # Client IP needs to be added to allowed IP list local snapcast_server_ip local invalid_entry= while : do if G_WHIP_INPUTBOX "${invalid_entry}Please enter the IPv4 address of your Snapcast server machine" && [[ $G_WHIP_RETURNED_VALUE =~ ^[0-9.]+$ ]] then snapcast_server_ip=$G_WHIP_RETURNED_VALUE break else invalid_entry='[ERROR] Please enter a valid IP address. Please retry...\n\n' fi done local snapcast_server_port=1704 invalid_entry= while : do G_WHIP_DEFAULT_ITEM=$snapcast_server_port if G_WHIP_INPUTBOX "${invalid_text}Please enter the network port of your Snapcast server machine\n - default: 1704" && disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 1 then snapcast_server_port=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] Please enter a valid port number. Please retry...\n\n' fi done G_CONFIG_INJECT 'SNAPCLIENT_OPTS[[:blank:]=]' "SNAPCLIENT_OPTS=\"-h $snapcast_server_ip -p $snapcast_server_port\"" /etc/default/snapclient 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.62.2/rclone-v1.62.2-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 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';; *) local arch='amd64';; esac local fallback_url="https://github.com/filebrowser/filebrowser/releases/download/v2.23.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 [[ -d '/mnt/dietpi_userdata/filebrowser' ]] || G_EXEC mkdir /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 G_EXEC /opt/filebrowser/filebrowser config set -a 0.0.0.0 -p 8084 -r /mnt 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 case $G_HW_ARCH in 1) local file='spotifyd-linux-armv6-slim';; 2) local file='spotifyd-linux-armhf-full';; *) local file='spotifyd-linux-full';; esac # Reinstall: Remove old install dir [[ -d '/opt/spotifyd' ]] && G_EXEC rm -R /opt/spotifyd # x86_64 only deps: Both ARM binaries are not compiled against these. dbus would be required for MPRIS support, but let's keep it slim for now. (( $G_HW_ARCH == 10 )) && aDEPS=('libdbus-1-3' 'libpulse0') local fallback_url="https://github.com/Spotifyd/spotifyd/releases/download/v0.3.4/$file.tar.gz" Download_Install "$(curl -sSfL 'https://api.github.com/repos/Spotifyd/spotifyd/releases/latest' | mawk -F\" "/\"browser_download_url\": .*\/$file\.tar\.gz\"/{print \$4}")" /opt/spotifyd # 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 [[ -d '/mnt/dietpi_userdata/spotifyd/cache' ]] || 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 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 # Check for existing Portainer container local container=$(docker container ls -a | mawk '/portainer\/portainer(-ce)?( |$)/{print $1;exit}') [[ $container ]] && G_EXEC docker container rm -f "$container" local image=$(docker image ls -a | mawk '/portainer\/portainer(-ce)?( |$)/{print $3;exit}') [[ $image ]] && G_EXEC docker image rm "$image" docker volume ls -q | grep -xq 'portainer_data' || G_EXEC docker volume create portainer_data # Deploy the Portainer container G_DIETPI-NOTIFY 2 'Portainer will be deployed now. This could take a while...' G_EXEC_OUTPUT=1 G_EXEC docker run -d -p '9002:9000' --name=portainer --restart=always -v '/run/docker.sock:/var/run/docker.sock' -v 'portainer_data:/data' 'portainer/portainer-ce' fi if To_Install 172 # WireGuard then # Packages available on Buster backports and Bullseye: For Raspbian Buster add Bullseye repo if (( $G_HW_MODEL < 10 && ${G_RASPBIAN:-1} && $G_DISTRO == 5 )) then G_EXEC eval "echo 'deb http://raspbian.raspberrypi.org/raspbian/ bullseye main' > /etc/apt/sources.list.d/dietpi-wireguard.list" # Disable repo via priority "-1", to prevent any accidental package upgrades: https://github.com/MichaIng/DietPi/issues/2568 # Enable but set WireGuard package priorities low enough to install only if not available in main repo(s) echo -e 'Package: *\nPin: release n=bullseye\nPin-Priority: -1\n Package: wireguard-tools\nPin: release n=bullseye\nPin-Priority: 100' > /etc/apt/preferences.d/dietpi-wireguard G_AGUP fi # 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 local choice_required= while : do 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_MENU "${choice_required}Please choose, if this machine should be set up as VPN server or client:" && break choice_required='[ERROR] A choice is required to finish the WireGuard install.\n\n' done # Server choice if [[ $G_WHIP_RETURNED_VALUE == 'Server' ]]; then # Public IP/domain and desired WireGuard server port local invalid_text= local domain=$(hostname -f) while : do G_WHIP_DEFAULT_ITEM=$domain if G_WHIP_INPUTBOX "${invalid_text}Please enter your servers public IP/domain for WireGuard client access:" && [[ $G_WHIP_RETURNED_VALUE ]] then domain=${G_WHIP_RETURNED_VALUE#http*://} break else invalid_text='[ERROR] No valid entry found. Please retry...\n\n' fi done invalid_text= local port=51820 while : do G_WHIP_DEFAULT_ITEM=$port if G_WHIP_INPUTBOX "${invalid_text}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" && disable_error=1 G_CHECK_VALIDINT "$G_WHIP_RETURNED_VALUE" 0 then port=$G_WHIP_RETURNED_VALUE break else invalid_text='[ERROR] No valid entry found, value needs to be a sequence of integers. Please retry...\n\n' fi done # 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 [Interface] Address = 10.9.0.1/24 PrivateKey = $( wg0-client.conf [Interface] Address = 10.9.0.2/24 PrivateKey = $( 256 )) || suggest_gpu_mem=128 # DXX-Rebirth elif (( ${aSOFTWARE_INSTALL_STATE[112]} == 1 )) then suggest_gpu_mem=128 # RPi Cam Web Interface, Amiberry, Chromium elif (( ${aSOFTWARE_INSTALL_STATE[59]} == 1 || ${aSOFTWARE_INSTALL_STATE[108]} == 1 || ${aSOFTWARE_INSTALL_STATE[113]} == 1 )) then suggest_gpu_mem=96 # Desktops, OpenTyrian elif (( ${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 )) then suggest_gpu_mem=1 # default fi # RPi Bullseye: No need to raise GPU memory above default with CMA (( $G_DISTRO > 5 && $suggest_gpu_mem > 1 )) && suggest_gpu_mem=1 # Disable headless/enable GPU when GUI software was installed (( $suggest_gpu_mem )) || return 0 /boot/dietpi/func/dietpi-set_hardware headless 0 # RPi: Apply memory split (( $G_HW_MODEL < 10 )) || return 0 # Never override a higher existing value 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 (( $suggest_gpu_mem == 1 )) && suggest_gpu_mem=$default_gpu_mem (( $current_gpu_mem < $suggest_gpu_mem )) && G_WHIP_DEFAULT_ITEM='Ok' G_WHIP_YESNO "[ INFO ] DietPi has detected an increased GPU memory is required for your installed software: - Current: $current_gpu_mem MiB\n - Recommended: $suggest_gpu_mem MiB\n\nWould you like DietPi to apply the recommended GPU memory split?\n\nIf unsure, select 'Ok'." || return 0 /boot/dietpi/func/dietpi-set_hardware gpumemsplit "$suggest_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} [[ -f '/etc/apt/preferences.d/dietpi-lxde' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-lxde 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 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 apt-mark auto upower policykit-1 2> /dev/null G_AGP x-window-system-core wmaker gnustep gnustep-devel gnustep-games fi if To_Uninstall 25 # Xfce then apt-mark auto gnome-icon-theme tango-icon-theme upower policykit-1 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 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 sudo -u www-data php /var/www/nextcloud/occ maintenance:mode --off sudo -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 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' 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 [[ -f '/etc/apt/sources.list.d/webmin.list' ]] && G_EXEC rm /etc/apt/sources.list.d/webmin.list [[ -f '/etc/apt/trusted.gpg.d/dietpi-webmin.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-webmin.gpg fi if To_Uninstall 32 # ympd then Remove_Service ympd 1 1 # group for pre-v6.33 [[ -f '/usr/bin/ympd' ]] && G_EXEC rm /usr/bin/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.gpg' ]] && G_EXEC rm /etc/apt/trusted.gpg.d/dietpi-mympd.gpg [[ -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 libmpdclient2 [[ -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/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 && sudo -u postgres dropdb synapse command -v dropuser > /dev/null && sudo -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 1 G_AGP aria2 [[ -d '/mnt/dietpi_userdata/aria2' ]] && G_EXEC rm -R /mnt/dietpi_userdata/aria2 [[ -f '/mnt/dietpi_userdata/downloads/aria2.session' ]] && G_EXEC rm /mnt/dietpi_userdata/downloads/aria2.session [[ -f '/usr/local/bin/aria2c' ]] && G_EXEC rm /usr/local/bin/aria2c # Previous fi if To_Uninstall 133 # YaCy then Remove_Service yacy [[ -d '/etc/yacy' ]] && G_EXEC rm -R /etc/yacy 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 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 177 # Firefox Sync Server then Remove_Service firefox-sync ffsync ffsync [[ -d '/opt/firefox-sync' ]] && G_EXEC rm -R /opt/firefox-sync [[ -d '/mnt/dietpi_userdata/firefox-sync' ]] && G_EXEC rm -R /mnt/dietpi_userdata/firefox-sync 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 141 # Spotify Connect Web then Remove_Service spotify-connect-web [[ -d '/mnt/dietpi_userdata/spotify-connect-web' ]] && G_EXEC rm -R /mnt/dietpi_userdata/spotify-connect-web fi if To_Uninstall 182 # Unbound then # Pi-hole: Assure that it does not resolve via Unbound anymore 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 [[ -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 /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 [[ $(apt-key list '2009837CBFFD68F45BC180471F4F90DE2A9B4BF8' 2> /dev/null) ]] && G_EXEC apt-key del '2009837CBFFD68F45BC180471F4F90DE2A9B4BF8' [[ $(apt-key list 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' 2> /dev/null) ]] && G_EXEC apt-key del 'A236C58F409091A18ACA53CBEBFF6B99D9B78493' # Pre-v7.1 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 [[ -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 # Pre-v6.29 Remove_Service shairport-sync [[ -f '/lib/systemd/system/shairport-sync.service' ]] && G_EXEC rm /lib/systemd/system/shairport-sync.service G_EXEC rm -f /usr/local/bin/shairport-sync /usr/local/etc/shairport-sync.conf* /usr/local/share/man/man7/shairport-sync.7.gz 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 '/usr/local/bin/box86' ]] && G_EXEC rm /usr/local/bin/box86 [[ -f '/etc/binfmt.d/box86.conf' ]] && G_EXEC rm /etc/binfmt.d/box86.conf [[ -f '/usr/lib/i386-linux-gnu/libstdc++.so.6' ]] && G_EXEC rm /usr/lib/i386-linux-gnu/libstdc++.so.6 [[ -f '/usr/lib/i386-linux-gnu/libstdc++.so.5' ]] && G_EXEC rm /usr/lib/i386-linux-gnu/libstdc++.so.5 [[ -f '/usr/lib/i386-linux-gnu/libgcc_s.so.1' ]] && G_EXEC rm /usr/lib/i386-linux-gnu/libgcc_s.so.1 [[ -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 '/usr/local/bin/box64' ]] && G_EXEC rm /usr/local/bin/box64 [[ -f '/etc/binfmt.d/box64.conf' ]] && G_EXEC rm /etc/binfmt.d/box64.conf [[ -f '/usr/lib/x86_64-linux-gnu/libstdc++.so.6' ]] && G_EXEC rm /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [[ -f '/usr/lib/x86_64-linux-gnu/libgcc_s.so.1' ]] && G_EXEC rm /usr/lib/x86_64-linux-gnu/libgcc_s.so.1 [[ -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 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/mopidy.list' ]] && G_EXEC rm /etc/apt/sources.list.d/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 '/etc/apt/preferences.d/dietpi-kodi' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-kodi [[ -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 [[ -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 command -v pihole > /dev/null && G_EXEC_OUTPUT=1 G_EXEC pihole uninstall # pihole-FTL service+binary Remove_Service pihole-FTL [[ -f '/usr/bin/pihole-FTL' ]] && G_EXEC rm /usr/bin/pihole-FTL # 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 # Symlinks [[ -L '/var/www/pihole' ]] && G_EXEC rm /var/www/pihole [[ -L '/var/www/admin' ]] && G_EXEC rm /var/www/admin # Disable and remove webserver configs # - Apache [[ -d '/etc/apache2/sites-available' ]] && G_EXEC rm -f /etc/apache2/sites-{available,enabled}/dietpi-pihole{,-block_public_admin}.conf # - Lighttpd [[ -d '/etc/lighttpd/conf-available' ]] && G_EXEC rm -f /etc/lighttpd/conf-{available,enabled}/99-dietpi-pihole{,-block_public_admin}.conf # - Nginx [[ -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 -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 -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 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 # IPFS Node 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 # Logitech Media Server then # Stop systemd service, which is not done by postinst, failing to remove user then Remove_Service logitechmediaserver G_AGP logitechmediaserver [[ -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 -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 [[ -f '/etc/apt/preferences.d/dietpi-wireguard' ]] && G_EXEC rm /etc/apt/preferences.d/dietpi-wireguard fi if To_Uninstall 58 # Tailscale then G_AGP tailscale [[ -d '/etc/systemd/system/tailscale.service.d' ]] && G_EXEC rm -R /etc/systemd/system/tailscale.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.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 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/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 # Remove binary (used a -f trigger to detect WiFi hotspot mode in dietpi-config). [[ -f '/usr/sbin/hostapd' ]] && G_EXEC rm /usr/sbin/hostapd [[ -f '/usr/sbin/hostapd_cli' ]] && G_EXEC rm /usr/sbin/hostapd_cli # IP forwarding [[ -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 -Ei '/(allow-hotplug|auto)[[:blank:]]+wlan/q0' /etc/network/interfaces # - Disable G_EXEC sed -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 wireless-power off wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf _EOF_ # - 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 then G_AGP mumble-server fi if To_Uninstall 41 # Emby Server then G_AGP emby-server embymagick [[ -f '/etc/apt/sources.list.d/emby-server.list' ]] && G_EXEC rm /etc/apt/sources.list.d/emby-server.list # Pre v6.15 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 # user and group for pre-v6.34 [[ -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 # Symlinks [[ -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 [[ -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 -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' && $( /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-engine [[ -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 # Pre-v8.10 Remove_Service gmediarender gmrender gmrender [[ -f '/usr/local/bin/gmediarender' ]] && G_EXEC rm /usr/local/bin/gmediarender [[ -d '/usr/local/share/gmediarender' ]] && G_EXEC rm -R /usr/local/share/gmediarender fi if To_Uninstall 67 # Firefox then G_AGP firefox-esr 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/influxdb.list' ]] && G_EXEC rm /etc/apt/sources.list.d/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 15 then G_AGP tcpdump fi if To_Uninstall 14 then G_AGP nload fi if To_Uninstall 13 then G_AGP mtr-tiny fi if To_Uninstall 11 then G_AGP iptraf fi if To_Uninstall 10 then G_AGP iftop fi if To_Uninstall 19 then G_AGP jed fi if To_Uninstall 3 # Midnight Commander then G_AGP mc fi if To_Uninstall 18 # Emacs then G_AGP emacs fi if To_Uninstall 20 # Vim then G_AGP vim fi if To_Uninstall 21 # Vim-Tiny then G_AGP vim-tiny fi if To_Uninstall 127 # Neovim then G_AGP neovim 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 -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 -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 # 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 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 # X.Org X Server 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 'default-jdk*' 'openjdk-*-jdk*' 'openjdk-*-doc' 'openjdk-*-source' 2> /dev/null | mawk '{print $1}') 2> /dev/null fi if To_Uninstall 196 # Java JRE then # shellcheck disable=SC2046 apt-mark auto $(dpkg --get-selections 'default-jre*' 'openjdk-*-jre*' 'openjdk-*-dbg' 'openjdk-*-demo' 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 -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 2> /dev/null then sed -i '/^[[:blank:]]*INDEX_LOGGING=/c\INDEX_LOGGING=-3' /boot/dietpi/.installed else sed -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 4 then G_AGP vifm 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 [[ -f '/etc/pip-constraints.txt' ]] && G_EXEC rm /etc/pip-constraints.txt 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 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 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 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' # 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 2> /dev/null && /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 # Interactive software post-configuration # 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=$(sed -n '/^[[:blank:]]*AUTO_SETUP_AUTOMATED=/{s/^[^=]*=//p;q}' /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_FILESERVERINDEX=$(sed -n '/^[[:blank:]]*AUTO_SETUP_FILE_SERVER_INDEX=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) # pre-v7.9 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_TIMESYNCMODE=$(sed -n '/^[[:blank:]]*CONFIG_NTP_MODE=/{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=$(sed -n '/^[[:blank:]]*AUTO_SETUP_DHCP_TO_STATIC=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) # Else set defaults [[ $AUTOINSTALL_ENABLED ]] || AUTOINSTALL_ENABLED=0 [[ $AUTOINSTALL_AUTOSTARTTARGET ]] || AUTOINSTALL_AUTOSTARTTARGET=0 [[ $AUTOINSTALL_SSHINDEX ]] || AUTOINSTALL_SSHINDEX=-1 [[ $AUTOINSTALL_FILESERVERINDEX ]] || AUTOINSTALL_FILESERVERINDEX=0 # pre-v7.9 [[ $AUTOINSTALL_LOGGINGINDEX ]] || AUTOINSTALL_LOGGINGINDEX=-1 [[ $AUTOINSTALL_CUSTOMSCRIPTURL ]] || AUTOINSTALL_CUSTOMSCRIPTURL=0 [[ $AUTOINSTALL_TIMESYNCMODE ]] || AUTOINSTALL_TIMESYNCMODE=2 [[ $AUTOINSTALL_RESTORE ]] || AUTOINSTALL_RESTORE=0 [[ $AUTOINSTALL_RAMLOG_SIZE ]] || AUTOINSTALL_RAMLOG_SIZE=50 [[ $AUTO_SETUP_DHCP_TO_STATIC == 1 ]] || AUTO_SETUP_DHCP_TO_STATIC=0 # 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 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 # Do not repeat APT update in Run_Installations() SKIP_APT_UPDATE=1 G_AGDUG # 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'; reboot; } fi # Global PW # - Automation: Apply from dietpi.txt if (( $AUTOINSTALL_ENABLED )) then Update_Global_Pw # Set again to apply for UNIX users as well /boot/dietpi/func/dietpi-set_software passwords "$GLOBAL_PW" # - Prompt to change global software password and login passwords for root and dietpi users else # 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 && dpkg-reconfigure keyboard-configuration && setupcon --save # https://bugs.debian.org/818065 /boot/dietpi/func/dietpi-set_software passwords fi # Disable serial console? if (( $G_HW_MODEL != 75 )) && ! grep -q '^[[:blank:]]*CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt && [[ ! $(tty) =~ ^/dev/(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 )) then if [[ -e '/dev/serial0' ]] && ! grep -q '^[[:blank:]]*CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt then local tty=$(readlink -f /dev/serial0); tty=${tty#/dev/} if [[ $( /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 "$AUTOINSTALL_TIMESYNCMODE" # Apply choice and preference system settings Apply_SSHServer_Choices "$AUTOINSTALL_SSHINDEX" Apply_Logging_Choices "$AUTOINSTALL_LOGGINGINDEX" # - Pre-v7.9 case "$AUTOINSTALL_FILESERVERINDEX" in '-1') (( ${aSOFTWARE_INSTALL_STATE[94]} == 2 )) || aSOFTWARE_INSTALL_STATE[94]=1;; '-2') (( ${aSOFTWARE_INSTALL_STATE[96]} == 2 )) || aSOFTWARE_INSTALL_STATE[96]=1;; *) :;; esac G_DIETPI-NOTIFY 0 'Applied initial first run setup steps' # Automated installs (( $AUTOINSTALL_ENABLED > 0 )) || 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' while read -r software_id 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[$i,$G_HW_ARCH]:=1} )) then G_DIETPI-NOTIFY 1 "Software title ${aSOFTWARE_NAME[$software_id]} is not supported on $G_HW_ARCH_NAME systems. Skipping it." elif (( ! ${aSOFTWARE_AVAIL_G_HW_MODEL[$i,$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[$i,$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 < <(grep '^[[:blank:]]*AUTO_SETUP_INSTALL_SOFTWARE_ID=' /boot/dietpi.txt | mawk '{print $1}' | sed 's/[^0-9]*//g') } # 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 )) && grep -q 'org.qemu.guest_agent.0' /sys/class/virtio-ports/*/name 2> /dev/null then G_DIETPI-NOTIFY 2 'QEMU VM detected, installing guest agent ...' G_AGI dbus G_EXEC systemctl unmask systemd-logind G_EXEC systemctl start systemd-logind G_AGI qemu-guest-agent # RPi4 EEPROM update: https://github.com/MichaIng/DietPi/issues/3217 elif (( $G_HW_MODEL == 4 )) then /boot/dietpi/func/dietpi-set_hardware rpi-eeprom fi # 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 -i "0,\|^.*address[[:blank:]].*\$|s||address $eth_ip|" /etc/network/interfaces sed -i "0,\|^.*netmask[[:blank:]].*\$|s||netmask $eth_mask|" /etc/network/interfaces sed -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 -i "\|^iface wlan|,\$s|^.*address[[:blank:]].*\$|address $wlan_ip|" /etc/network/interfaces sed -i "\|^iface wlan|,\$s|^.*netmask[[:blank:]].*\$|netmask $wlan_mask|" /etc/network/interfaces sed -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 -i "/dns-nameservers[[:blank:]]/c\dns-nameservers ${nameservers% }" /etc/network/interfaces else sed -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 # Install user set GPU driver from dietpi.txt if set. local gpu_current=$(sed -n '/^[[:blank:]]*CONFIG_GPU_DRIVER=/{s/^[^=]*=//p;q}' /boot/dietpi.txt) if [[ ${gpu_current,,} != 'none' ]] then /boot/dietpi/func/dietpi-set_hardware gpudriver "$gpu_current" fi # 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' # 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+=("$i") done done fi G_WHIP_SIZE_X_MAX=93 # 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 to confirm. - Press ESC or select 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_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_YESNO 'A static IP address is essential for a DNS server installations. 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=$(\" 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 (( $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 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' # 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 # 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 #------------------------------------------------------------------------------------- }