Anaconda provisioning: Many fixes, first working autoinstall
This commit is contained in:
@@ -1,8 +1,15 @@
|
|||||||
|
#Basic settings:
|
||||||
graphical
|
graphical
|
||||||
text
|
text
|
||||||
skipx
|
|
||||||
cdrom
|
# Configure installation method
|
||||||
|
url --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-43&arch=x86_64"
|
||||||
|
repo --name=fedora-updates --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=updates-released-f43&arch=x86_64" --cost=0
|
||||||
|
repo --name=fedora-cisco-openh264 --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-cisco-openh264-43&arch=x86_64" --install
|
||||||
|
repo --name=rpmfusion-free --mirrorlist="https://mirrors.rpmfusion.org/mirrorlist?repo=free-fedora-43&arch=x86_64"
|
||||||
|
repo --name=rpmfusion-free-updates --mirrorlist="https://mirrors.rpmfusion.org/mirrorlist?repo=free-fedora-updates-released-43&arch=x86_64" --cost=0
|
||||||
|
repo --name=rpmfusion-nonfree --mirrorlist="https://mirrors.rpmfusion.org/mirrorlist?repo=nonfree-fedora-43&arch=x86_64"
|
||||||
|
repo --name=rpmfusion-nonfree-updates --mirrorlist="https://mirrors.rpmfusion.org/mirrorlist?repo=nonfree-fedora-updates-released-43&arch=x86_64" --cost=0
|
||||||
|
|
||||||
# Keyboard layouts
|
# Keyboard layouts
|
||||||
keyboard --vckeymap=de-nodeadkeys --xlayouts='de (nodeadkeys)'
|
keyboard --vckeymap=de-nodeadkeys --xlayouts='de (nodeadkeys)'
|
||||||
@@ -11,23 +18,53 @@ lang de_DE.UTF-8
|
|||||||
# System timezone
|
# System timezone
|
||||||
timezone Europe/Berlin --utc
|
timezone Europe/Berlin --utc
|
||||||
|
|
||||||
|
%pre --log=/root/ks-pre.log
|
||||||
|
mkdir /mnt/anaconda_pre
|
||||||
|
mount -L OEMDRV /mnt/anaconda_pre
|
||||||
|
/bin/sh /mnt/anaconda_pre/ks_base_profiles/basic_pre_script.inc
|
||||||
|
%end
|
||||||
|
|
||||||
%packages
|
%packages
|
||||||
#@^kde-desktop-environment
|
#@^kde-desktop-environment
|
||||||
|
@core
|
||||||
@admin-tools
|
@admin-tools
|
||||||
@domain-client
|
@domain-client
|
||||||
@system-tools
|
@system-tools
|
||||||
|
@kde-desktop
|
||||||
|
@kde-media
|
||||||
|
@kde-spin-initial-setup
|
||||||
|
@libreoffice
|
||||||
|
@office
|
||||||
|
@sound-and-video
|
||||||
|
@vlc
|
||||||
|
openssh-server
|
||||||
|
bash
|
||||||
|
sudo
|
||||||
|
gocryptfs
|
||||||
|
htop
|
||||||
|
mc
|
||||||
|
mediawriter
|
||||||
|
pykickstart
|
||||||
|
@editors
|
||||||
|
@firefox
|
||||||
|
thunderbird
|
||||||
|
xrdp
|
||||||
|
xorgxrdp
|
||||||
|
plasma-workspace-x11
|
||||||
|
xterm
|
||||||
|
flatpak
|
||||||
|
btrfs-assistant
|
||||||
|
btrbk
|
||||||
|
ktorrent
|
||||||
#@development-tools
|
#@development-tools
|
||||||
#@editors
|
kdevelop
|
||||||
#@firefox
|
git
|
||||||
#@kde-apps
|
ffmpeg
|
||||||
#@kde-desktop
|
-kpat
|
||||||
#@kde-media
|
-kmines
|
||||||
#@kde-spin-initial-setup
|
#Needed by SSSD
|
||||||
#@libreoffice
|
oddjob-mkhomedir
|
||||||
#@office
|
nss-pam-ldapd
|
||||||
#@sound-and-video
|
|
||||||
#@vlc
|
|
||||||
|
|
||||||
%end
|
%end
|
||||||
|
|
||||||
# System authorization information
|
# System authorization information
|
||||||
@@ -36,8 +73,6 @@ authselect enable-feature with-fingerprint
|
|||||||
# Run the Setup Agent on first boot
|
# Run the Setup Agent on first boot
|
||||||
firstboot --enable
|
firstboot --enable
|
||||||
|
|
||||||
timesource --ntp-server=_gateway
|
|
||||||
|
|
||||||
# Generated using Blivet version 3.12.1
|
# Generated using Blivet version 3.12.1
|
||||||
ignoredisk --only-use=sda
|
ignoredisk --only-use=sda
|
||||||
# Partition clearing information
|
# Partition clearing information
|
||||||
@@ -50,5 +85,8 @@ autopart --type=btrfs
|
|||||||
rootpw --iscrypted $y$j9T$jpKVkxaFqL6GH6GAgB0Yb/$oc.rfZgnHNlTAIj/boJeI.ZFf1QHvMF7fymZww9bzE3
|
rootpw --iscrypted $y$j9T$jpKVkxaFqL6GH6GAgB0Yb/$oc.rfZgnHNlTAIj/boJeI.ZFf1QHvMF7fymZww9bzE3
|
||||||
|
|
||||||
%post --log=/root/ks-post.log
|
%post --log=/root/ks-post.log
|
||||||
/bin/sh /mnt/tmp/system_setup/setup_system_full.sh install
|
mkdir /opt/sys_config
|
||||||
|
mount -L OEMDRV /opt/sys_config
|
||||||
|
/bin/sh /opt/sys_config/system_setup/setup_system_full.sh install
|
||||||
|
umount /opt/sys_config
|
||||||
%end
|
%end
|
||||||
|
|||||||
@@ -24,16 +24,16 @@ fi
|
|||||||
|
|
||||||
# Usually, the pre section is run in the sh- shell, the OEMDRV will be mountet at /mnt/tmp
|
# Usually, the pre section is run in the sh- shell, the OEMDRV will be mountet at /mnt/tmp
|
||||||
# So we need to check if this is the case
|
# So we need to check if this is the case
|
||||||
FQFILENAME="/mnt/tmp/ks_base_profiles/basic_pre_script.inc"
|
FQFILENAME="/mnt/anaconda_pre/ks_base_profiles/basic_pre_script.inc"
|
||||||
if [ ! -f ${FQFILENAME} ]; then
|
if [ ! -f ${FQFILENAME} ]; then
|
||||||
echo "* Error finding the expeted Directory/File structure: Missing File"
|
echo "* Error finding the expeted Directory/File structure: Missing File"
|
||||||
echo "${FQFILENAME}"
|
echo "${FQFILENAME}"
|
||||||
echo "* Please check to run from Kickstart- Installation, or mount the OEMDRV with this File in /mnt/tmp before."
|
echo "* Please check to run from Kickstart- Installation, or mount the OEMDRV with this File in /mnt/anaconda_pre before."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if there is a Partition OEMDRV and on which Drive
|
# Check if there is a Partition OEMDRV and on which Drive
|
||||||
source /mnt/tmp/system_setup/setup_system.conf
|
/mnt/anaconda_pre/system_setup/setup_system.inc.sh
|
||||||
OEMDRVINFO=$(blkid | grep 'LABEL="OEMDRV"')
|
OEMDRVINFO=$(blkid | grep 'LABEL="OEMDRV"')
|
||||||
if [ "${OEMDRVINFO}." == "." ] ; then
|
if [ "${OEMDRVINFO}." == "." ] ; then
|
||||||
echo "* Error: Required partition with label 'OEMDRV' is not found."
|
echo "* Error: Required partition with label 'OEMDRV' is not found."
|
||||||
@@ -78,7 +78,7 @@ if [ "${REMPARTS}." != "." ]; then
|
|||||||
for (( i=0; i<${#REMPART}; i++ )); do
|
for (( i=0; i<${#REMPART}; i++ )); do
|
||||||
CHAR="${REMPART:$i:1}"
|
CHAR="${REMPART:$i:1}"
|
||||||
if [[ "${CHAR}" =~ [0-9] ]]; then
|
if [[ "${CHAR}" =~ [0-9] ]]; then
|
||||||
PARTNR+="${CHAR}" # Append if it's a digit
|
PARTNR+="${CHAR}" # Append if its a digit
|
||||||
else
|
else
|
||||||
PARTNR="" # Reset if a non-digit is encountered
|
PARTNR="" # Reset if a non-digit is encountered
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -14,11 +14,10 @@ cd /etc
|
|||||||
sudo rm -f -r /etc/skel
|
sudo rm -f -r /etc/skel
|
||||||
sudo tar -xf ${SRCFILE}
|
sudo tar -xf ${SRCFILE}
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Sucessfully wrote skel new"
|
echo "Sucessfully wrote skel."
|
||||||
sudo chown -R root:root /etc/skel
|
sudo chown -R root:root /etc/skel
|
||||||
sudo setfacl -R -m u::rwX,g::rX,o::rX /etc/skel
|
sudo setfacl -R -m u::rwX,g::rX,o::rX /etc/skel
|
||||||
else
|
else
|
||||||
echo "Something went wrong, please check Output"
|
echo "Something went wrong, please check Output"
|
||||||
fi
|
fi
|
||||||
cd ${EXECDIR}
|
cd ${EXECDIR}
|
||||||
|
|
||||||
|
|||||||
Regular → Executable
@@ -21,7 +21,7 @@
|
|||||||
# - Make it check for what to do each time so that it can be called every startup
|
# - Make it check for what to do each time so that it can be called every startup
|
||||||
# - Make it callable from anakondas kickstart post- script to setup system at first run
|
# - Make it callable from anakondas kickstart post- script to setup system at first run
|
||||||
# (kickstart post-script must be non-interactive, while first start with systemd can have a service bounf to tty for getting user-input too)
|
# (kickstart post-script must be non-interactive, while first start with systemd can have a service bounf to tty for getting user-input too)
|
||||||
# - Detect System Environement and make User-Logon- Setup Start after first Logon
|
# - Detect System Environment and make User-Logon- Setup Start after first Logon
|
||||||
# Supported: Cinnamon, KDE
|
# Supported: Cinnamon, KDE
|
||||||
# - Not needed: Import Firefox-Cert from IPA automatically at first run to system -> Somehow this is not needed any more, firefox will work from scratch!
|
# - Not needed: Import Firefox-Cert from IPA automatically at first run to system -> Somehow this is not needed any more, firefox will work from scratch!
|
||||||
|
|
||||||
@@ -32,26 +32,28 @@
|
|||||||
|
|
||||||
# TODO write a doc!
|
# TODO write a doc!
|
||||||
|
|
||||||
#Load Sytem Settings
|
#Load Sytem Settings - MUST BE SOURCED, otherwise Variables will not be available
|
||||||
source $(dirname "$0")/setup_system.inc.sh
|
source $(dirname "$0")/setup_system.inc.sh
|
||||||
|
|
||||||
# TODO
|
# Setup needed boot- service
|
||||||
# Install System settings to installed system
|
|
||||||
# read system settings from that file
|
|
||||||
|
|
||||||
##Step 1 - Install at System boot
|
|
||||||
firstrun_prepare()
|
firstrun_prepare()
|
||||||
{
|
{
|
||||||
#Checking Service
|
#Checking Service
|
||||||
|
if [[ -z ${FIRSTRUN_SERVICENAME} ]]; then
|
||||||
|
echo "Error in Config, no Servicename found. Please check your Environment for FIRSTRUN_SERVICENAME."
|
||||||
|
env
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
FIRSTRUN_SERVICESTATUS=$( systemctl is-enabled ${FIRSTRUN_SERVICENAME} )
|
FIRSTRUN_SERVICESTATUS=$( systemctl is-enabled ${FIRSTRUN_SERVICENAME} )
|
||||||
echo "Current Service Status of ${FIRSTRUN_SERVICENAME} is ${FIRSTRUN_SERVICESTATUS}"
|
echo "Current Service Status of ${FIRSTRUN_SERVICENAME} is ${FIRSTRUN_SERVICESTATUS}"
|
||||||
if [ ${FIRSTRUN_SERVICESTATUS} != "enabled" ]; then
|
if [ "${FIRSTRUN_SERVICESTATUS}." != "enabled." ]; then
|
||||||
echo "Installing Service at ${FIRSTRUN_SCRIPTPATH}/${FIRSTRUN_SERVICENAME}"
|
echo "Installing Service at ${FIRSTRUN_SCRIPTPATH}/${FIRSTRUN_SERVICENAME}"
|
||||||
( cat <<EOF | sudo tee ${FIRSTRUN_SCRIPTPATH}/${FIRSTRUN_SERVICENAME}
|
( cat <<EOF | sudo tee ${FIRSTRUN_SCRIPTPATH}/${FIRSTRUN_SERVICENAME}
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=First time setup of this PC
|
Description=First time setup of this PC
|
||||||
After=NetworkManager-wait-online.service
|
After=NetworkManager-wait-online.service
|
||||||
Before=sssd.service
|
Before=systemd-user-sessions.service nss-user-lookup.target
|
||||||
|
Wants=nss-user-lookup.target
|
||||||
ConditionKernelCommandLine=!inst.nofirstrun
|
ConditionKernelCommandLine=!inst.nofirstrun
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
@@ -65,7 +67,7 @@ ExecStart=/bin/sh ${SCRIPTPATH}/${SCRIPTNAME} firstrun_run
|
|||||||
#ExecStart=-/sbin/agetty --noclear -n -l "/bin/sh ${SCRIPTPATH}/${SCRIPTNAME} firstrun_run" %I 38400
|
#ExecStart=-/sbin/agetty --noclear -n -l "/bin/sh ${SCRIPTPATH}/${SCRIPTNAME} firstrun_run" %I 38400
|
||||||
# user interaction in tty8
|
# user interaction in tty8
|
||||||
StandardInput=tty
|
StandardInput=tty
|
||||||
TTYPath=/dev/tty8
|
TTYPath=/dev/tty2
|
||||||
TTYReset=yes
|
TTYReset=yes
|
||||||
TTYVHangup=yes
|
TTYVHangup=yes
|
||||||
|
|
||||||
@@ -88,7 +90,10 @@ firstrun_remove()
|
|||||||
#Do updates
|
#Do updates
|
||||||
upgrade_interactive()
|
upgrade_interactive()
|
||||||
{
|
{
|
||||||
check_root
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "ERROR: Not running as root, cannot continue."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
dnf upgrade --refresh
|
dnf upgrade --refresh
|
||||||
#Check if restart is needed
|
#Check if restart is needed
|
||||||
dnf needs-restarting
|
dnf needs-restarting
|
||||||
@@ -109,29 +114,36 @@ fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
#Software needed and additional stuff
|
#Software needed and additional stuff
|
||||||
|
# Moved all to syc_client_software.sh to make it more interactive
|
||||||
install_sw()
|
install_sw()
|
||||||
{
|
{
|
||||||
check_root
|
if [ "$EUID" -ne 0 ]; then
|
||||||
dnf install -y mc htop ipa-client thunderbird pykickstart gocryptfs mediawriter
|
echo "ERROR: Not running as root, cannot continue."
|
||||||
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
return 1
|
||||||
|
fi
|
||||||
#Set default Umask 0077
|
#Set default Umask 0077
|
||||||
sudo cp -f /etc/login.defs /etc/login.defs_backup_${CDATEC8}_${CTIMEC6}
|
sudo cp -f /etc/login.defs /etc/login.defs_backup_${CDATEC8}_${CTIMEC6}
|
||||||
( sed 's/^UMASK.*022$/UMASK\t077/' /etc/login.defs | sudo tee /etc/login.defs ) >/dev/null
|
( sed 's/^UMASK.*022$/UMASK\t077/' /etc/login.defs | sudo tee /etc/login.defs ) >/dev/null
|
||||||
|
#Append OEMDRV mount to SYSCONFIGPATH in fstab
|
||||||
|
echo "LABEL=OEMDRV ${SYSCONFIGPATH} btrfs noatime,nodiratime,nofail 0 0" >> /etc/fstab
|
||||||
}
|
}
|
||||||
|
|
||||||
ipa_register_host()
|
ipa_register_host()
|
||||||
{
|
{
|
||||||
#Integrate this PC into Domain
|
#Integrate this PC into Domain
|
||||||
chvt 8
|
chvt 2
|
||||||
#Check if IPA is already Configured
|
#Check if IPA is already Configured
|
||||||
echo "Checking for existing IPA- Setup."
|
echo "Checking for existing IPA- Setup."
|
||||||
if ( grep -q "${FQDN}" /etc/ipa/default.conf ); then
|
if ( grep -q "${FQDN}" /etc/ipa/default.conf ); then
|
||||||
echo "IPA is already installed, skipping setup."
|
echo "IPA is already installed, skipping setup."
|
||||||
|
chvt 1
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
echo "IPA not jet installed, doing Setup."
|
echo "IPA not jet installed, doing Setup."
|
||||||
check_root
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "ERROR: Not running as root, cannot continue."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
#Serialnr of this device
|
#Serialnr of this device
|
||||||
echo "This PC is called ${FQDN} and will join Domain ${DOMAIN}"
|
echo "This PC is called ${FQDN} and will join Domain ${DOMAIN}"
|
||||||
#Always set determined hostname - see setup_system.conf
|
#Always set determined hostname - see setup_system.conf
|
||||||
@@ -147,22 +159,41 @@ echo -n "Please Enter your Domain- Userid: "
|
|||||||
read IPAUSERID
|
read IPAUSERID
|
||||||
echo -n "Please Enter your Domain- Password: "
|
echo -n "Please Enter your Domain- Password: "
|
||||||
read -s IPAPASSWD
|
read -s IPAPASSWD
|
||||||
INSTCMD="ipa-client-install -U --mkhomedir --force-join --no-ntp --principal=${IPAUSERID} --domain=${DOMAIN} --server=${SERVERFQDN_IPA} --hostname=${FQDN} -w ${IPAPASSWD}"
|
echo ""
|
||||||
echo ${INSTCMD}
|
INSTCMD="ipa-client-install -U --mkhomedir --force-join --no-ntp --principal=${IPAUSERID} --domain=${DOMAIN} --server=${SERVERFQDN_IPA} -w ${IPAPASSWD}"
|
||||||
|
echo "${INSTCMD/${IPAPASSWD}/*PASSWD*}"
|
||||||
${INSTCMD}
|
${INSTCMD}
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Some Error. Please check what went wrong and redo."
|
echo "Some Error. Please check what went wrong and redo."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
echo "The PC was integrated into the Domain. You should now be able to Logon with tha User. If not, restart SSSD- Service and check the Logs."
|
echo "The PC was integrated into the Domain. You should now be able to Logon with tha User. If not, check the Logs at /var/sssd."
|
||||||
echo ""
|
echo ""
|
||||||
echo "ADVISE: for the First Logon, you may use Console (Using e.g. CONTROL+ALT+F3) - as maybe you will be prompted for Changing your Password there"
|
echo "ADVISE: for the First Logon, you may use Console (Using e.g. CONTROL+ALT+F3) - as maybe you will be prompted for Changing your Password there"
|
||||||
echo "which may not work on graphical logon. After that works, use CONTROL+ALT+F2 (or F7) to get back to the graphical logon."
|
echo "which may not work on graphical logon. After that works, use CONTROL+ALT+F2 (or F7) to get back to the graphical logon."
|
||||||
echo ""
|
echo ""
|
||||||
read -n 1 -s -r -p "Press any key to continue."
|
read -n 1 -s -r -p "Press any key to continue."
|
||||||
|
chvt 1
|
||||||
echo ""
|
echo ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepare_skel()
|
||||||
|
{
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "ERROR: Not running as root, cannot continue."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
#Copy and extrakt Skel-Archive
|
||||||
|
#Include: Autostart for Getting WEB-DAV-Token if not there
|
||||||
|
#+An empty Firefox Profile - already integrated into domain with one single Startup-Page: Get Token
|
||||||
|
# https://nextcloud.obel1x.de/settings/user/security
|
||||||
|
#
|
||||||
|
#File was created with from Draft-Folder and then transferred to NC
|
||||||
|
#tar -I 'zstd -9' -cf system_setup.tar.zst ~/system_setup
|
||||||
|
#
|
||||||
|
./setup_skel.sh
|
||||||
|
}
|
||||||
|
|
||||||
test_tty()
|
test_tty()
|
||||||
{
|
{
|
||||||
#Use TTY3 and show it
|
#Use TTY3 and show it
|
||||||
@@ -175,23 +206,10 @@ test_tty()
|
|||||||
echo "========== END ========"
|
echo "========== END ========"
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_skel()
|
|
||||||
{
|
|
||||||
check_root
|
|
||||||
#Copy and extrakt Skel-Archive
|
|
||||||
#Include: Autostart for Getting WEB-DAV-Token if not there
|
|
||||||
#+An empty Firefox Profile - already integrated into domain with one single Startup-Page: Get Token
|
|
||||||
# https://nextcloud.obel1x.de/settings/user/security
|
|
||||||
#
|
|
||||||
#File was created with from Draft-Folder and then transferred to NC
|
|
||||||
#tar -I 'zstd -9' -cf system_setup.tar.zst ~/system_setup
|
|
||||||
#
|
|
||||||
./setup_skel.sh
|
|
||||||
}
|
|
||||||
|
|
||||||
### MAIN
|
### MAIN
|
||||||
case $1 in
|
case $1 in
|
||||||
'install')
|
'install')
|
||||||
|
# Executed after base installation (anaconda post script)
|
||||||
echo "Mode: Install"
|
echo "Mode: Install"
|
||||||
install_sw
|
install_sw
|
||||||
prepare_skel
|
prepare_skel
|
||||||
@@ -204,7 +222,6 @@ case $1 in
|
|||||||
firstrun_remove
|
firstrun_remove
|
||||||
;;
|
;;
|
||||||
'firstrun_run')
|
'firstrun_run')
|
||||||
# test_tty
|
|
||||||
ipa_register_host
|
ipa_register_host
|
||||||
echo "========== END FIRSTRUN-SERVICE ========"
|
echo "========== END FIRSTRUN-SERVICE ========"
|
||||||
;;
|
;;
|
||||||
|
|||||||
Binary file not shown.
@@ -37,6 +37,7 @@ mkdir -p ${TEMPDIR}
|
|||||||
|
|
||||||
#Install or update Nextcloud com.nextcloud.desktopclient.nextcloud
|
#Install or update Nextcloud com.nextcloud.desktopclient.nextcloud
|
||||||
echo "Update or install Nextcloud client"
|
echo "Update or install Nextcloud client"
|
||||||
|
/usr/bin/flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
||||||
/usr/bin/flatpak install -y --or-update --noninteractive flathub com.nextcloud.desktopclient.nextcloud && echo "Done Update/Install of Nextcloud."
|
/usr/bin/flatpak install -y --or-update --noninteractive flathub com.nextcloud.desktopclient.nextcloud && echo "Done Update/Install of Nextcloud."
|
||||||
|
|
||||||
#Sync Files
|
#Sync Files
|
||||||
|
|||||||
Reference in New Issue
Block a user