From 6ce12a3f8168a257befac52033f088b90084d6a0 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Sun, 21 Jun 2026 15:29:49 +1000 Subject: [PATCH 01/12] Add extensions for new save format --- valheim-backup | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/valheim-backup b/valheim-backup index 1aecba5b..8281b9c9 100755 --- a/valheim-backup +++ b/valheim-backup @@ -123,7 +123,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -name "worlds-*.zip" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -fv -- 2>/dev/null else - for extension in {db,fwl,db.old,fwl.old}; do + for extension in {db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk}; do find "$BACKUPS_DIRECTORY" -type f -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -v -- 2>/dev/null done fi @@ -133,7 +133,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "worlds-*.zip" -print -exec rm -f "{}" \; else - for extension in {db,fwl,db.old,fwl.old}; do + for extension in {db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk}; do find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -print -exec rm -f "{}" \; done fi From a67e0384c1d0830e01b00755043c78af97963e36 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Sun, 21 Jun 2026 15:45:08 +1000 Subject: [PATCH 02/12] Move backup world file extensions to variable --- valheim-backup | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/valheim-backup b/valheim-backup index 8281b9c9..1da1c842 100755 --- a/valheim-backup +++ b/valheim-backup @@ -11,6 +11,7 @@ BACKUPS_DIRECTORY=${BACKUPS_DIRECTORY%/} pidfile=$valheim_backup_pidfile next_backup=$(date +%s) run=true +worldFileExtensions={db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk} main() { @@ -71,7 +72,7 @@ backup() { local backup_suffix backup_suffix=$(date +%Y%m%d-%H%M%S) - for extension in {db,fwl,db.old,fwl.old}; do + for extension in worldFileExtensions; do world_file="$WORLDS_DIR/$WORLD_NAME.$extension" if [ ! -f "$world_file" ]; then debug "World file $world_file not found - skipping" @@ -123,7 +124,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -name "worlds-*.zip" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -fv -- 2>/dev/null else - for extension in {db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk}; do + for extension in worldFileExtensions; do find "$BACKUPS_DIRECTORY" -type f -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -v -- 2>/dev/null done fi @@ -133,7 +134,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "worlds-*.zip" -print -exec rm -f "{}" \; else - for extension in {db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk}; do + for extension in worldFileExtensions; do find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -print -exec rm -f "{}" \; done fi From 86aab9ee9114a039048506861f8cdee8f5ed03a8 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Sun, 21 Jun 2026 16:06:35 +1000 Subject: [PATCH 03/12] Correct backup world file extensions --- valheim-backup | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/valheim-backup b/valheim-backup index 1da1c842..d6177d4c 100755 --- a/valheim-backup +++ b/valheim-backup @@ -11,7 +11,7 @@ BACKUPS_DIRECTORY=${BACKUPS_DIRECTORY%/} pidfile=$valheim_backup_pidfile next_backup=$(date +%s) run=true -worldFileExtensions={db,fwl,db.old,fwl.old,chunks,db2,fwl2,ok,chunk} +worldFileExtensions=(db fwl db.old fwl.old chunks db2 fwl2 ok chunk) main() { @@ -72,7 +72,7 @@ backup() { local backup_suffix backup_suffix=$(date +%Y%m%d-%H%M%S) - for extension in worldFileExtensions; do + for extension in "${worldFileExtensions[@]}"; do world_file="$WORLDS_DIR/$WORLD_NAME.$extension" if [ ! -f "$world_file" ]; then debug "World file $world_file not found - skipping" @@ -124,7 +124,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -name "worlds-*.zip" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -fv -- 2>/dev/null else - for extension in worldFileExtensions; do + for extension in "${worldFileExtensions[@]}"; do find "$BACKUPS_DIRECTORY" -type f -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -v -- 2>/dev/null done fi @@ -134,7 +134,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "worlds-*.zip" -print -exec rm -f "{}" \; else - for extension in worldFileExtensions; do + for extension in "${worldFileExtensions[@]}"; do find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -print -exec rm -f "{}" \; done fi From 1969107dd8441d20262e7740feaed86d2a1f9841 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Mon, 22 Jun 2026 00:12:42 +1000 Subject: [PATCH 04/12] Set World Folder Permissions, Refactor backups --- common | 4 ++++ valheim-backup | 30 +++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/common b/common index efe6e586..964e321d 100644 --- a/common +++ b/common @@ -130,6 +130,10 @@ ensure_permissions() { if [ -d "$worlds_dir" ]; then chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir" chmod "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* + if [ -d "${worlds_dir}/${WORLD_NAME}" ]; then + chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir/${WORLD_NAME}" + chmod "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/${WORLD_NAME}/"* + fi fi if [ "$VALHEIM_PLUS" = true ] && [ -d /config/valheimplus ]; then find /config/valheimplus -type d -exec chmod "$VALHEIM_PLUS_CONFIG_DIRECTORY_PERMISSIONS" "{}" + diff --git a/valheim-backup b/valheim-backup index d6177d4c..49872c8c 100755 --- a/valheim-backup +++ b/valheim-backup @@ -11,7 +11,8 @@ BACKUPS_DIRECTORY=${BACKUPS_DIRECTORY%/} pidfile=$valheim_backup_pidfile next_backup=$(date +%s) run=true -worldFileExtensions=(db fwl db.old fwl.old chunks db2 fwl2 ok chunk) +oldWorldFileExtensions=(db fwl db.old fwl.old) +worldFileExtensions=(db2 fwl2 chunks chunk ok) main() { @@ -64,15 +65,17 @@ backup() { backup_file="$BACKUPS_DIRECTORY/worlds-$(date +%Y%m%d-%H%M%S).zip" pre_backup_hook "$backup_file" info "Backing up Valheim server worlds to $backup_file" - zip -r "$backup_file" "$WORLDS_DIR/" -x '*_backup_auto-*.*' + zip -r "$backup_file" "$WORLDS_DIR/" -x '*_backup_auto-*.*' '*_backup_auto-*/*' chmod "$BACKUPS_FILE_PERMISSIONS" "$backup_file" post_backup_hook "$backup_file" else local world_file + local world_folder + local backup_folder local backup_suffix backup_suffix=$(date +%Y%m%d-%H%M%S) - for extension in "${worldFileExtensions[@]}"; do + for extension in "${oldWorldFileExtensions[@]}"; do world_file="$WORLDS_DIR/$WORLD_NAME.$extension" if [ ! -f "$world_file" ]; then debug "World file $world_file not found - skipping" @@ -85,6 +88,23 @@ backup() { chmod "$BACKUPS_FILE_PERMISSIONS" "$backup_file" post_backup_hook "$backup_file" done + world_folder="${worlds_dir}/${WORLD_NAME}" + if [ -d "${world_folder}" ]; then + backup_folder="$BACKUPS_DIRECTORY/AUTOBACKUP-${WORLD_NAME}-$backup_suffix" + pre_backup_hook "$backup_folder" + info "Backing up Valheim server world folder $world_folder to $backup_folder" + mkdir -v -p "$backup_folder" + for extension in "${worldFileExtensions[@]}"; do + for file in "$world_folder"/*.$extension; do + if [ -f "$file" ]; then + info "Backing up Valheim server world file $file to $backup_folder" + cp -v "$file" "$backup_folder" + fi + done + done + chmod "$BACKUPS_DIRECTORY_PERMISSIONS" "$backup_folder" + post_backup_hook "$backup_folder" + fi fi } @@ -124,7 +144,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -name "worlds-*.zip" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -fv -- 2>/dev/null else - for extension in "${worldFileExtensions[@]}"; do + for extension in "${oldWorldFileExtensions[@]}"; do find "$BACKUPS_DIRECTORY" -type f -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -printf '%T@ %p\0' | sort -z -n -r | cut -z -s -d " " -f "2-" | tail -z -n +$((BACKUPS_MAX_COUNT+1)) | xargs -0 rm -v -- 2>/dev/null done fi @@ -134,7 +154,7 @@ flush_old() { if [ "${BACKUPS_ZIP}" = true ]; then find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "worlds-*.zip" -print -exec rm -f "{}" \; else - for extension in "${worldFileExtensions[@]}"; do + for extension in "${oldWorldFileExtensions[@]}"; do find "$BACKUPS_DIRECTORY" -type f -mmin "+$((BACKUPS_MAX_AGE*60*24))" -name "AUTOBACKUP-${WORLD_NAME}-*.${extension}" -print -exec rm -f "{}" \; done fi From ac3b247b16cacd9c5aa2a33710dd8fbcf67f927c Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Mon, 22 Jun 2026 00:16:56 +1000 Subject: [PATCH 05/12] Update valheim-backup --- valheim-backup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valheim-backup b/valheim-backup index 49872c8c..a9f35755 100755 --- a/valheim-backup +++ b/valheim-backup @@ -95,7 +95,7 @@ backup() { info "Backing up Valheim server world folder $world_folder to $backup_folder" mkdir -v -p "$backup_folder" for extension in "${worldFileExtensions[@]}"; do - for file in "$world_folder"/*.$extension; do + for file in "$world_folder/*.$extension"; do if [ -f "$file" ]; then info "Backing up Valheim server world file $file to $backup_folder" cp -v "$file" "$backup_folder" From 1232db86184fa7d747cb164ff961c3d7c29e15d0 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Mon, 22 Jun 2026 00:25:08 +1000 Subject: [PATCH 06/12] Update valheim-backup --- valheim-backup | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/valheim-backup b/valheim-backup index a9f35755..b7120b7d 100755 --- a/valheim-backup +++ b/valheim-backup @@ -88,14 +88,14 @@ backup() { chmod "$BACKUPS_FILE_PERMISSIONS" "$backup_file" post_backup_hook "$backup_file" done - world_folder="${worlds_dir}/${WORLD_NAME}" + world_folder="$worlds_dir/$WORLD_NAME" if [ -d "${world_folder}" ]; then backup_folder="$BACKUPS_DIRECTORY/AUTOBACKUP-${WORLD_NAME}-$backup_suffix" pre_backup_hook "$backup_folder" info "Backing up Valheim server world folder $world_folder to $backup_folder" mkdir -v -p "$backup_folder" for extension in "${worldFileExtensions[@]}"; do - for file in "$world_folder/*.$extension"; do + for file in "$world_folder/*".$extension; do if [ -f "$file" ]; then info "Backing up Valheim server world file $file to $backup_folder" cp -v "$file" "$backup_folder" From 580f72366adb5824ff64329cc8dba4c6019f1dcd Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 19:04:55 +1000 Subject: [PATCH 07/12] Force LF line endings --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..09bc62c1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto \ No newline at end of file From 48589e3aefff10282a53d378c91df3e2b92b344b Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 19:06:40 +1000 Subject: [PATCH 08/12] Update .gitattributes --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 09bc62c1..dd1999e5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,2 @@ # Set the default behavior, in case people don't have core.autocrlf set. -* text=auto \ No newline at end of file +* text=auto eol=lf \ No newline at end of file From 874cbe0f19aaa09bc1a4fb47403aa33bb73f22b7 Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 19:26:59 +1000 Subject: [PATCH 09/12] Improve world directory permission setting Make sure all files/folders have correct permissions --- common | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/common b/common index 964e321d..16ddf1a2 100644 --- a/common +++ b/common @@ -129,11 +129,15 @@ ensure_permissions() { fi if [ -d "$worlds_dir" ]; then chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir" - chmod "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* - if [ -d "${worlds_dir}/${WORLD_NAME}" ]; then - chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir/${WORLD_NAME}" - chmod "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/${WORLD_NAME}/"* - fi + # Set permissions for all files in the worlds dir + chmod -R -type f "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* + # Set permissions for all folders in the worlds dir + find "${worlds_dir}/" -type d -exec chmod "$WORLDS_DIRECTORY_PERMISSIONS" {} \; + # Set permissions specifically for WORLD_NAME, misses auto-backup files (which will cause a failure to start server) + #if [ -d "${worlds_dir}/${WORLD_NAME}" ]; then + # chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir/${WORLD_NAME}" + # chmod "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/${WORLD_NAME}/"* + #fi fi if [ "$VALHEIM_PLUS" = true ] && [ -d /config/valheimplus ]; then find /config/valheimplus -type d -exec chmod "$VALHEIM_PLUS_CONFIG_DIRECTORY_PERMISSIONS" "{}" + From 95dec01055a8bf4d864bd8816683d36656c74d0b Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 20:16:16 +1000 Subject: [PATCH 10/12] Update common --- common | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common b/common index 16ddf1a2..0978b574 100644 --- a/common +++ b/common @@ -129,8 +129,8 @@ ensure_permissions() { fi if [ -d "$worlds_dir" ]; then chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir" - # Set permissions for all files in the worlds dir - chmod -R -type f "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* + # Set permissions for all files and folders in the worlds dir + chmod -R "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* # Set permissions for all folders in the worlds dir find "${worlds_dir}/" -type d -exec chmod "$WORLDS_DIRECTORY_PERMISSIONS" {} \; # Set permissions specifically for WORLD_NAME, misses auto-backup files (which will cause a failure to start server) From b30d0ba86629ef6e04cb1d5d8d149559c26f9ecb Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 21:01:07 +1000 Subject: [PATCH 11/12] Update common --- common | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common b/common index 0978b574..311f2afe 100644 --- a/common +++ b/common @@ -129,10 +129,10 @@ ensure_permissions() { fi if [ -d "$worlds_dir" ]; then chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir" - # Set permissions for all files and folders in the worlds dir - chmod -R "$WORLDS_FILE_PERMISSIONS" "${worlds_dir}/"* # Set permissions for all folders in the worlds dir find "${worlds_dir}/" -type d -exec chmod "$WORLDS_DIRECTORY_PERMISSIONS" {} \; + # Set permissions for all files in the worlds dir + find "${worlds_dir}/" -type f -exec chmod "$WORLDS_FILE_PERMISSIONS" {} \; # Set permissions specifically for WORLD_NAME, misses auto-backup files (which will cause a failure to start server) #if [ -d "${worlds_dir}/${WORLD_NAME}" ]; then # chmod "$WORLDS_DIRECTORY_PERMISSIONS" "$worlds_dir/${WORLD_NAME}" From 2bbe51dadedafd356e78c910acceb28c29ac6f0f Mon Sep 17 00:00:00 2001 From: PanicPaintbrush Date: Thu, 25 Jun 2026 21:44:27 +1000 Subject: [PATCH 12/12] Update valheim-backup --- valheim-backup | 2 ++ 1 file changed, 2 insertions(+) diff --git a/valheim-backup b/valheim-backup index b7120b7d..144f09bf 100755 --- a/valheim-backup +++ b/valheim-backup @@ -61,6 +61,8 @@ backup() { mkdir -p "$BACKUPS_DIRECTORY" chmod "$BACKUPS_DIRECTORY_PERMISSIONS" "$BACKUPS_DIRECTORY" + ensure_permissions # in case new chunks have been created + if [ "${BACKUPS_ZIP}" = true ]; then backup_file="$BACKUPS_DIRECTORY/worlds-$(date +%Y%m%d-%H%M%S).zip" pre_backup_hook "$backup_file"