Last active
July 31, 2024 15:38
-
-
Save dgeo/2190aea81f7bfcb15e3af6be440935b8 to your computer and use it in GitHub Desktop.
nextcloud upgrade script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -e | |
# | |
# Updater script for nextcloud + apps | |
# | |
# Designed for "maintenance" user different from "run" user | |
# eg: here php runs with _nextcloud:nextcloud and maintenance is done by nextcloud:nextcloud | |
# this way, an exploit cannot rewrite the code in place (datadir does not allow php execution) | |
# | |
# Needs curl, xpath (perl module XML::XPath), jq | |
# | |
# To start/stop nginx and create zfs snapshots, you need a sudo config like: | |
# Cmnd_Alias NCUPGRADE = /sbin/zfs snapshot -r zroot/iocage/jails/claude/data@*,/usr/sbin/service nginx * | |
# nextcloud ALL=(root) NOPASSWD:NCUPGRADE | |
# | |
NCDIR=/home/nextcloud/nextcloud | |
APPSDIR=$NCDIR/apps-local | |
NCUSER=nextcloud | |
# start/stop nginx (need sudo) | |
NGINX=YES | |
# create zfs snapshot (need sudo) | |
ZFS=YES | |
[ "$(id -un)" != "$NCUSER" ] && exec su -l $NCUSER -c "$0 $*" | |
occ() { | |
umask 002; php -dapc.enable_cli=1 $NCDIR/occ $* | |
} | |
# nginx_service [stop|start] | |
nginx_service() { | |
if [ "$NGINX" = "YES" ]; then | |
sudo /usr/sbin/service nginx $1 | |
fi | |
} | |
# do_zfs_snapshot version | |
do_zfs_snapshot() { | |
if [ "$ZFS" = "YES" ]; then | |
ZCODE=$(df -h -t zfs $NCDIR | tail -1 | cut -w -f1) | |
ZDATA=$(df -h -t zfs $(occ config:system:get datadirectory) | tail -1 | cut -w -f1) | |
if [ -n "$ZCODE" ]; then | |
zfs list -Honame $ZCODE@nc_$1 2>/dev/null && sudo /sbin/zfs destroy -r $ZCODE@nc_$1 | |
sudo /sbin/zfs snapshot -r $ZCODE@nc_$1 | |
fi | |
if [ -n "$ZDATA" ] && ! echo "$ZDATA" | grep -q "${ZCODE:-NEVERMATCHDATADIR}"; then | |
zfs list -Honame $ZDATA@nc_$1 2>/dev/null && sudo /sbin/zfs destroy -r $ZDATA@nc_$1 | |
sudo /sbin/zfs snapshot -r $ZDATA@nc_$1 | |
fi | |
fi | |
} | |
grep -q 'config_is_read_only.*rue' ${NCDIR}/config/config.php | |
ROCONFIG=$? | |
[ -e "${NCDIR}/config/config.php.noro.php" ] && ROCONFIG=0 | |
# get running version | |
eval $(php -r 'include("'${NCDIR}'/version.php"); print("curvers=$OC_VersionString\ncvers=".join("x",$OC_Version)."\nbuild=\"".urlencode($OC_Build)."\"\nfullvers=".join(".",$OC_Version)."\nphpversion=".PHP_MAJOR_VERSION."x".PHP_MINOR_VERSION."x".PHP_RELEASE_VERSION);') | |
if [ -z "$fullvers" ] || [ -z "$curvers" ] || [ -z "$phpversion" ] || [ -z "$build" ] || [ -z "$cvers" ]; then | |
echo "Impossible de trouver la version de nextcloud dans ${NCDIR}/version.php :(" | |
exit 1 | |
fi | |
# get next version for updater | |
if newvers=$(curl -s "https://updates.nextcloud.com/updater_server/?version=${cvers}xxxproductionxx${build}x${phpversion}" | xpath -q -e '/nextcloud/version/text()' 2>/dev/null); then | |
if [ -z "$newvers" ]; then | |
echo "Impossible de trouver une nouvelle version" | |
elif [ "${newvers%%.*}" != "${curvers%%.*}" ]; then | |
echo "MAJ majeure: $curvers -> $newvers" | |
if [ $# -ne 1 ] && [ "$1" != "OKMAJ" ]; then | |
echo "$0 OKMAJ pour l'installer" | |
NOUP=1 | |
fi | |
fi | |
else | |
echo "pas de nouvelle version pour nextcloud (${curvers})" | |
fi | |
# OK, there is an upgrade to do… go ! | |
if [ -n "$newvers" ] && [ "${newvers}" != "${fullvers}" ] && [ -z "$NOUP" ]; then | |
nginx_service stop | |
do_zfs_snapshot ${fullvers} | |
[ $ROCONFIG = 0 ] && sed -i .noro.php '/config_is_read_only/d' "${NCDIR}/config/config.php" | |
php -dapc.enable_cli=1 ${NCDIR}/updater/updater.phar --no-backup -v --no-interaction | |
# re-get new running version | |
eval $(php -r 'include("'${NCDIR}'/version.php"); print("curvers=$OC_VersionString\ncvers=".join("x",$OC_Version)."\nbuild=\"".urlencode($OC_Build)."\"\nfullvers=".join(".",$OC_Version)."\nphpversion=".PHP_MAJOR_VERSION."x".PHP_MINOR_VERSION."x".PHP_RELEASE_VERSION);') | |
fi | |
# apps upgrade | |
v=${fullvers%%.*} | |
cd $APPSDIR | |
curl -s -o /tmp/apps.json https://apps.nextcloud.com/api/v1/platform/${curvers}/apps.json | |
for app in *; do | |
curvers=$(xpath -q -e '/info/version/text()' $app/appinfo/info.xml) | |
version=$(jq -r '.[] | select (.id=="'$app'") | {releases}.[] | .[].version' < /tmp/apps.json | sort -t. -nk1 -nk2 -nk3 | tail -1) | |
url=$(jq -r '.[] | select (.id=="'$app'") | {releases}.[].[] | select (.version=="'$version'") | .download' < /tmp/apps.json) | |
UP="" | |
if [ -z "$version" ]; then | |
echo "$app-$curvers : no version found" | |
continue | |
fi | |
if [ "$version" = "$curvers" ]; then | |
echo "$app-$curvers a jour ($version)" | |
continue | |
else | |
echo "$app-$curvers: version $version disponible" | |
UP=YES | |
fi | |
if [ -d $app/.git ]; then | |
# if git-managed, upgrade to stableXX branch or master | |
git -C $app fetch origin | |
branch=$(git -C $app branch -r | grep 'stable'$v'$' || echo origin/master) | |
if [ "$branch" = "origin/master" ]; then | |
tag=$(git -C $app tag | grep "^v" | sort -nk1 -k2 -k3 -t. | grep $version) | |
if [ -n "$tag" ]; then | |
branch=$tag | |
echo "found tag $tag for $app-$curvers" | |
fi | |
fi | |
git -C $app checkout $branch | |
[ -f $app/package.json ] && ( cd $app; npm install --no-dev ) | |
[ -f $app/composer.json ] && ( cd $app; composer install --no-dev ) | |
else | |
# if no git, get tar.gz | |
if [ -n "$url" ]; then | |
fetch -o- $url | tar xzf - | |
fi | |
fi | |
if [ "YES" = "$UP" ]; then | |
[ $ROCONFIG = 0 ] && [ ! -f "${NCDIR}/config/config.php.noro.php" ] && sed -i .noro.php '/config_is_read_only/d' "${NCDIR}/config/config.php" | |
occ upgrade -n | |
fi | |
# delete old files | |
occ integrity:check-app --output=json $app | jq -r '.EXTRA_FILE | select(any(.expected == "")) | keys | map("'$app/'"+.) | .[]' 2>/dev/null | xargs -t rm | |
done | |
# make config read-write | |
[ $ROCONFIG = 0 ] && sed -i .noro.php '/config_is_read_only/d' "${NCDIR}/config/config.php" | |
occ upgrade -n | |
# re-make config read-only | |
[ $ROCONFIG = 0 ] && occ config:system:set --value=true config_is_read_only && rm -f "${NCDIR}/config/config.php.noro.php" | |
# start nginx if it was stopped | |
if [ "$NGINX" = "YES" ]; then | |
nginx_service start | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
use
sort -t. -nk1 -nk2 -nk3
to get latest version of application (lite semver sorting)