#!/usr/bin/env bash # AUTHOR: coding@lirion.de # LICENCE: LGPL-3.0-only # Error codes: 131-159 (130 is reserved for sigint et al!) # Define help function function hayulp { printf 'USAGE: %b [-a|--app-update] [-c|--core-update VERSION]\n\n' "$(basename "$0")" ( printf -- '-a,\n' printf -- '--app-update;Update all apps\n' printf -- '-c,\n' printf -- '--core-update;Update the Nextcloud core (including apps update)\n' printf -- ';VERSION is mandatory. "0" for no update at all (e.g. for wrapper scripts).\n' printf -- '-s,\n' printf -- '--status;Status including version\n' printf -- '-u,\n' printf -- '--update-check;Status including update check\n' printf -- '-h,\n' printf -- '--help;This help text\n' )|column -ts \; printf '\n' } ##### PARSE: COMMAND LINE PARAMETERS ##### NC_APPSUPD=0; NC_COREUPD=0 while [[ $# -gt 0 ]]; do case "$1" in "-h"|"--help") hayulp exit 0 ;; "-a"|"--app-update") NC_APPSUPD=1 shift ;; "-c"|"--core-update") NC_COREUPD=1 shift UPDVER="$1" shift ;; "-"*) hayulp printf '\033[93mUnknown option: %b\033[0m\n' "$1" >&2 exit 104 ;; esac done if [ "$UPDVER" == '0' ]; then NC_COREUPD=2 fi # shellcheck disable=SC1091 source /etc/lirion/nextcloud.conf || exit 102 # shellcheck disable=SC1091 source /usr/lib/lirion/ln-initfunctions || exit 103 /usr/bin/sudo -u "$NCUSER" /usr/bin/whoami > /dev/null || exit 133 /usr/bin/sudo /usr/bin/whoami > /dev/null || exit 133 if [ "$NC_COREUPD" -gt 0 ]; then lnbegin "File inventory" if [ "$NC_COREUPD" -gt 1 ]; then lnskip else if ! /usr/bin/sudo -u "$NCUSER" /usr/bin/stat -tL "${NCDLTGT}/nextcloud-${1}.tar.bz2" > /dev/null 2>&1; then lnfail "archive not found" exit 131 elif ! /usr/bin/sudo -u "$NCUSER" /usr/bin/stat -tL "${NCDLTGT}/nextcloud-${1}.tar.bz2.sha512" >/dev/null 2>&1; then lnfail "checksum file not found" exit 131 elif ! /usr/bin/sudo -u "$NCUSER" /usr/bin/stat -tL "${NCDLTGT}/nextcloud-${1}.tar.bz2.asc" >/dev/null 2>&1; then lnfail "signature file not found" exit 131 fi lnok # TODO: implement script parameter skipping this - if we execute right after nextcloud-download, # this is redundant as the latter also verifies. We need this only on separate execution (so # by default as well). lnbegin "Verifying download" lnprog 'GPG' if ! /usr/bin/sudo -u "$NCUSER" /usr/bin/gpg --no-default-keyring --keyring /var/www/keyrings/nextcloud-security.gpg \ --quiet --verify "${NCDLTGT}/nextcloud-${1}.tar.bz2.asc" "${NCDLTGT}/nextcloud-${1}.tar.bz2" 2>/dev/null then lnfail 'GPG failed' exit 132 fi lnok fi fi if [ "$NC_COREUPD" -gt 0 ]; then lnbegin 'Setting maintenance mode' if [ "$NC_COREUPD" -gt 1 ]; then lnskip else if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" 'maintenance:mode' '--on' >/dev/null 2>&1; then lnfail 'enabling failed' exit 133 fi lnok lnbegin "Grace period with maintenance mode" while [ "$NCGRACE" -ge 1 ]; do lnprog "$NCGRACE" NCGRACE="$((NCGRACE-1))" sleep 1 done lnok fi fi if [ "$NC_COREUPD" -gt 0 ]; then lnbegin 'Move old Nextcloud folder' if [ "$NC_COREUPD" -gt 1 ]; then lnskip else lnprog 'folder backup removal' if ! /usr/bin/sudo rm -rf "${NCAPPLDIR}.bak" >/dev/null 2>&1; then lnfail 'folder backup removal failed' exit 134 fi lnprog 'folder backup' if ! /usr/bin/sudo /usr/bin/mv -v "${NCAPPLDIR}" "${NCAPPLDIR}.bak" >/dev/null 2>&1; then lnfail 'folder backup failed' exit 135 fi lnok fi fi if [ "$NC_COREUPD" -gt 0 ]; then lnbegin 'NC download extraction' if [ "$NC_COREUPD" -gt 1 ]; then lnskip else if ! /usr/bin/sudo /usr/bin/install -dm'0750' -o"$NCUSER" -g"$NCUSER" "$NCAPPLDIR" > /dev/null 2>&1; then lnfail 'folder creation failed' exit 136 elif ! MYTMP="$(/usr/bin/sudo -u "$NCUSER" /usr/bin/mktemp -d -p /tmp nextcloud.XXXXXX 2>/dev/null)"; then lnfail 'temp creation failed' exit 137 elif ! /usr/bin/sudo -u "$NCUSER" /usr/bin/tar -C "$MYTMP" --checkpoint-action='.' --checkpoint=16384 \ -xjf "${NCDLTGT}/nextcloud-${1}.tar.bz2"; then lnfail 'tarball extraction failed' exit 138 elif [ "$(/usr/bin/sudo -u "$NCUSER" /usr/bin/find "$MYTMP" -mindepth 1 -maxdepth 1 -name 'nextcloud' 2>/dev/null | wc -w)" -ne 1 ]; then lnfail 'subfolder nextcloud not found' exit 139 elif ! /usr/bin/sudo rsync -rlptD "${MYTMP}/nextcloud/" "${NCAPPLDIR}/" >/dev/null 2>&1; then lnfail 'folder sync failed' exit 140 fi lnok fi fi function ctrl_c { printf '\n' lnbegin 'Caught TERM/INT, aborting.' lnquit if [[ "$NC_COREUPD" -eq 1 ]]; then if ! /usr/bin/sudo /usr/bin/rm -rf "$MYTMP"; then exit 141 fi fi exit 130 } trap ctrl_c INT trap ctrl_c TERM if [ "$NC_COREUPD" -gt 0 ]; then lnbegin 'Temp dir removal' if [ "$NC_COREUPD" -gt 1 ]; then lnskip else if ! /usr/bin/sudo -u "$NCUSER" /usr/bin/rm -rf "$MYTMP" >/dev/null 2>&1; then lnfail 142 fi lnok fi fi if [ "$NC_COREUPD" -gt 0 ]; then lnbegin 'Sync old config/apps' if [ "$NC_COREUPD" -gt 1 ]; then lnskip else # do use trailing slashes for folders here, we are rsyncing! for src in 'config/config.php' 'apps/' 'apps-extras/' 'apps-external/'; do lnprog "$src" if ! stat -tL "${NCAPPLDIR}.bak/$src" >/dev/null 2>&1; then lnprog "$src not existing in backup" sleep 0.314159 continue fi if ! /usr/bin/sudo /usr/bin/rsync -rulptgoD "${NCAPPLDIR}.bak/$src" "${NCAPPLDIR}/$src" >/dev/null 2>&1; then lnfail "syncing $src failed" exit 143 fi done lnok fi fi if [ "$NC_COREUPD" -gt 0 ]; then lnbegin "Nextcloud file permissions" if [ "$NC_COREUPD" -gt 1 ]; then lnskip else if ! /usr/bin/sudo /usr/bin/chown -R "${NCUSER}:" "${NCAPPLDIR}/" >/dev/null 2>&1 && \ /usr/bin/sudo /usr/bin/chmod o-rwx "${NCAPPLDIR}/" >/dev/null 2>&1; then lnfail exit 144 fi lnok fi fi # Play it safe: disable maintenance mode independent of what was executed before. Currently, this # gives an output of "already disabled" and RC=0, so we're fine. lnbegin 'Disabling maintenance mode' if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" 'maintenance:mode' '--off' >/dev/null 2>&1; then lnfail 'disabling failed' exit 152 fi lnok lnbegin "Nextcloud upgrade" if ! /usr/bin/sudo -u "$NCUSER" /usr/bin/stat -tL "${NCAPPLDIR}/occ" >/dev/null 2>&1 &&\ [ "$(/usr/bin/sudo -u "$NCUSER" /usr/bin/stat -c '%f' "${NCAPPLDIR}/occ" 2>/dev/null)" != '81a0' ]; then lnfail exit 145 fi # Play it safe: Run the upgrade command in any case. Doesn't hurt; unless necessary it'll tell that there's # "No upgrade required." and give an RC=0 in any case, so we're fine. lnprog "occ upgrade" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" upgrade -q >/dev/null 2>&1; then lnfail exit 146 fi if [ "$NC_APPSUPD" -eq 1 ]; then lnprog "occ app:update --all" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" app:update -q --all >/dev/null 2>&1; then lnfail "occ app:update" exit 147 fi fi lnprog "occ db:add-missing-primary-keys" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" db:add-missing-primary-keys -q >/dev/null 2>&1; then lnfail "occ db:add-missing-primary-keys" exit 148 fi lnprog "occ db:add-missing-columns" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" db:add-missing-columns -q >/dev/null 2>&1; then lnfail "occ db:add-missing-columns" exit 149 fi lnprog "occ db:add-missing-indices" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" "${NCAPPLDIR}/occ" db:add-missing-indices -q >/dev/null 2>&1; then lnfail "occ db:add-missing-indices" exit 150 fi if [[ "$NC_APPSUPD" -eq 1 || "$NC_COREUPD" -eq 1 ]]; then lnprog "cron.php" if ! /usr/bin/sudo -u "$NCUSER" "$NCPHPBIN" -f "${NCAPPLDIR}/cron.php" 2>/dev/null; then lnfail "cron.php" exit 151 fi sleep 1 fi lnok