diff --git a/.editorconfig b/.editorconfig index 88a15bf3..c67480b9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,11 +3,11 @@ root = true [*] # charset = utf-8 end_of_line = lf -# indent_size = 4 -# indent_style = space +indent_size = 4 +indent_style = space insert_final_newline = true # max_line_length = 120 -# tab_width = 4 +# tab_width = 2 [*.rs] max_line_length = 100 diff --git a/Cargo.lock b/Cargo.lock index 562da970..d7161817 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" + [[package]] name = "atty" version = "0.2.14" @@ -80,6 +86,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + [[package]] name = "daemonize" version = "0.4.1" @@ -96,6 +111,30 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "filetime" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "flate2" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + [[package]] name = "getrandom" version = "0.2.2" @@ -174,6 +213,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "miniz_oxide" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "ntapi" version = "0.3.6" @@ -190,11 +239,13 @@ dependencies = [ "cargo-husky", "clap", "daemonize", + "flate2", "log", "rand", "serde", "serde_json", "sysinfo", + "tar", "which", ] @@ -298,6 +349,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + [[package]] name = "ryu" version = "1.0.5" @@ -367,6 +427,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "tar" +version = "0.4.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0313546c01d59e29be4f09687bcb4fb6690cec931cc3607b6aec7a0e417f4cc6" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -482,6 +553,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "xattr" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +dependencies = [ + "libc", +] + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/Cargo.toml b/Cargo.toml index e723314a..24172198 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,9 @@ serde = { version = "1.0", features = ["derive"], default_features = false } sysinfo = { version = "0.16.1", default_features = false } serde_json = "1.0" daemonize = "0.4" +tar = "0.4" +flate2 = "1.0" + [dev-dependencies] rand = "0.8.3" diff --git a/Dockerfile b/Dockerfile index e86b9e0c..ee61e7a1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,13 @@ ENV PASSWORD "12345" ENV AUTO_UPDATE "0" ENV AUTO_UPDATE_SCHEDULE "0 1 * * *" +# Auto Backup Configs +ENV AUTO_BACKUP "0" +ENV AUTO_BACKUP_SCHEDULE "*/15 * * * *" +ENV AUTO_BACKUP_REMOVE_OLD "1" +ENV AUTO_BACKUP_DAYS_TO_LIVE "3" +ENV AUTO_BACKUP_ON_UPDATE "0" +ENV AUTO_BACKUP_ON_SHUTDOWN "0" COPY --chmod=755 ./src/scripts/*.sh /home/steam/scripts/ COPY --chmod=755 ./src/scripts/entrypoint.sh /entrypoint.sh diff --git a/README.md b/README.md index 7be5bec5..6bbc87e1 100644 --- a/README.md +++ b/README.md @@ -10,22 +10,29 @@ ### Environment Variables -| Variable | Default | Required | Description | -|----------------------|------------------------|----------|-------------| -| TZ | `America/Los_Angeles` | FALSE | Sets what timezone your container is running on. This is used for timestamps and cron jobs. [Click Here for which timezones are valid.](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | -| PUID | `1000` | FALSE | Sets the User Id of the steam user. | -| PGID | `1000` | FALSE | Sets the Group Id of the steam user. | -| PORT | `2456` | TRUE | Sets the port your server will listen on. Take not it will also listen on +2 (ex: 2456, 2457, 2458) | -| NAME | `Valheim Docker` | TRUE | The name of your server! Make it fun and unique! | -| WORLD | `Dedicated` | TRUE | This is used to generate the name of your world. | -| PUBLIC | `1` | FALSE | Sets whether or not your server is public on the server list. | -| PASSWORD | `12345` | TRUE | Set this to something unique! | -| AUTO_UPDATE | `0` | FALSE | Set to `1` if you want your container to auto update! This means at 1 am it will update, stop, and then restart your server. | -| AUTO_UPDATE_SCHEDULE | `0 1 * * *` | FALSE | This works in conjunction with `AUTO_UPDATE` and sets the schedule to which it will run an auto update. [If you need help figuring out a cron schedule click here](https://crontab.guru/#0_1_*_*_*) | - +| Variable | Default | Required | Description | +|--------------------------|------------------------|----------|-------------| +| TZ | `America/Los_Angeles` | FALSE | Sets what timezone your container is running on. This is used for timestamps and cron jobs. [Click Here for which timezones are valid.](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | +| PUID | `1000` | FALSE | Sets the User Id of the steam user. | +| PGID | `1000` | FALSE | Sets the Group Id of the steam user. | +| PORT | `2456` | TRUE | Sets the port your server will listen on. Take not it will also listen on +2 (ex: 2456, 2457, 2458) | +| NAME | `Valheim Docker` | TRUE | The name of your server! Make it fun and unique! | +| WORLD | `Dedicated` | TRUE | This is used to generate the name of your world. | +| PUBLIC | `1` | FALSE | Sets whether or not your server is public on the server list. | +| PASSWORD | `12345` | TRUE | Set this to something unique! | +| AUTO_UPDATE | `0` | FALSE | Set to `1` if you want your container to auto update! This means at 1 am it will update, stop, and then restart your server. | +| AUTO_UPDATE_SCHEDULE | `0 1 * * *` | FALSE | This works in conjunction with `AUTO_UPDATE` and sets the schedule to which it will run an auto update. [If you need help figuring out a cron schedule click here] +| AUTO_BACKUP | `0` | FALSE | Set to `1` to enable auto backups. Backups are stored under `/home/steam/backups` which means you will have to add a volume mount for this directory. | +| AUTO_BACKUP_SCHEDULE | `*/15 * * * *` | FALSE | Change to set how frequently you would like the server to backup. [If you need help figuring out a cron schedule click here]. +| AUTO_BACKUP_REMOVE_OLD | `1` | FALSE | Set to `0` to keep all backups or manually manage them. | +| AUTO_BACKUP_DAYS_TO_LIVE | `3` | FALSE | This is the number of days you would like to keep backups for. While backups are compressed and generally small it is best to change this number as needed. | +| AUTO_BACKUP_ON_UPDATE | `0` | FALSE | Create a backup on right before updating and starting your server. | +| AUTO_BACKUP_ON_SHUTDOWN | `0` | FALSE | Create a backup on shutdown. | ### Docker Compose +#### Simple + > This is a basic example of a docker compose, you can apply any of the variables above to the `environment` section below but be sure to follow each variables description notes! ```yaml @@ -49,6 +56,37 @@ services: - ./valheim/server:/home/steam/valheim ``` +#### Everything but the kitchen sink + +```yaml +version: "3" +services: + valheim: + image: mbround18/valheim:latest + ports: + - 2456:2456/udp + - 2457:2457/udp + - 2458:2458/udp + environment: + - PORT=2456 + - NAME="Created With Valheim Docker" + - WORLD="Dedicated" + - PASSWORD="Strong! Password @ Here" + - TZ=America/Chicago + - PUBLIC=1 + - AUTO_UPDATE=1 + - AUTO_UPDATE_SCHEDULE="0 1 * * *" + - AUTO_BACKUP=1 + - AUTO_BACKUP_SCHEDULE="*/15 * * * *" + - AUTO_BACKUP_REMOVE_OLD=1 + - AUTO_BACKUP_DAYS_TO_LIVE=3 + - AUTO_BACKUP_ON_UPDATE=1 + - AUTO_BACKUP_ON_SHUTDOWN=1 +volumes: + - ./valheim/saves:/home/steam/.config/unity3d/IronGate/Valheim + - ./valheim/server:/home/steam/valheim + - ./valheim/backups:/home/steam/backups +``` ### [Odin] @@ -58,6 +96,7 @@ This repo has a CLI tool called [Odin] in it! It is used for managing the server ## Versions: - latest (Stable): + - [#100] Added backup feature to run based on cronjob. - 1.2.0 (Stable): - Readme update to include the versions section and environment variables section. - [#18] Changed to `root` as the default user to allow updated steams User+Group IDs. @@ -84,6 +123,7 @@ This repo has a CLI tool called [Odin] in it! It is used for managing the server - Has a bug in which it does not read passed in variables appropriately to Odin. Env variables are not impacted see [#3]. [//]: <> (Github Issues below...........) +[#100]: https://github.com/mbround18/valheim-docker/pull/100 [#89]: https://github.com/mbround18/valheim-docker/pull/89 [#77]: https://github.com/mbround18/valheim-docker/pull/77 [#53]: https://github.com/mbround18/valheim-docker/pull/53 @@ -99,5 +139,6 @@ This repo has a CLI tool called [Odin] in it! It is used for managing the server [//]: <> (Links below...................) [Odin]: ./docs/odin.md [Valheim]: https://www.valheimgame.com/ +[If you need help figuring out a cron schedule click here]: https://crontab.guru/#0_1_*_*_* [//]: <> (Image Base Url: https://github.com/mbround18/valheim-docker/blob/main/docs/assets/name.png?raw=true) diff --git a/docker-compose.yml b/docker-compose.yml index eae27a38..45b117e7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,6 +28,7 @@ services: volumes: - ./tmp/saves:/home/steam/.config/unity3d/IronGate/Valheim - ./tmp/server:/home/steam/valheim + - ./tmp/backups:/home/steam/backups - odin-output:/home/steam/.odin volumes: diff --git a/src/cli.yaml b/src/cli.yaml index 20c765e6..f5c501ad 100644 --- a/src/cli.yaml +++ b/src/cli.yaml @@ -16,7 +16,7 @@ args: about: Will output the commands that it intends to run. subcommands: - - init: + - configure: about: Initializes Odin with its configuration variables. version: "1.0" author: mbround18 @@ -69,3 +69,16 @@ subcommands: about: Stops Valheim version: "1.1" author: mbround18 + - backup: + about: Backups the current saves to a specifc location + version: "1.0" + author: mbround18 + args: + - INPUT_DIR: + about: Directory to back up + required: true + index: 1 + - OUTPUT_FILE: + about: Sets the output file to use + required: true + index: 2 diff --git a/src/commands/backup.rs b/src/commands/backup.rs new file mode 100644 index 00000000..ab1c0de0 --- /dev/null +++ b/src/commands/backup.rs @@ -0,0 +1,29 @@ +use clap::ArgMatches; +use flate2::write::GzEncoder; +use flate2::Compression; +use log::{debug, error}; +use std::fs::File; +use std::process::exit; + +pub fn invoke(args: &ArgMatches) { + let input = args.value_of("INPUT_DIR").unwrap(); + let output = args.value_of("OUTPUT_FILE").unwrap(); + debug!("Creating archive of {}", input); + debug!("Output set to {}", output); + let tar_gz = match File::create(output) { + Ok(file) => file, + Err(_) => { + error!("Failed to create backup file at {}", output); + exit(1) + } + }; + let enc = GzEncoder::new(tar_gz, Compression::default()); + let mut tar = tar::Builder::new(enc); + match tar.append_dir_all("saves", input) { + Ok(_) => debug!("Successfully created backup zip at {}", output), + Err(_) => { + error!("Failed to add {} to backup file", input); + exit(1) + } + }; +} diff --git a/src/commands/initialize.rs b/src/commands/configure.rs similarity index 100% rename from src/commands/initialize.rs rename to src/commands/configure.rs diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 195612b6..777e3ef1 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,4 +1,5 @@ -pub mod initialize; +pub mod backup; +pub mod configure; pub mod install; pub mod start; pub mod stop; diff --git a/src/commands/start.rs b/src/commands/start.rs index ad152fee..dbf1e7cd 100644 --- a/src/commands/start.rs +++ b/src/commands/start.rs @@ -1,10 +1,9 @@ use crate::executable::create_execution; use crate::files::config::{config_file, read_config}; -use crate::utils::get_working_dir; +use crate::utils::{create_file, get_working_dir}; use clap::ArgMatches; use daemonize::Daemonize; use log::{error, info}; -use std::fs::File; use std::process::exit; pub fn invoke(args: &ArgMatches) { @@ -19,10 +18,8 @@ pub fn invoke(args: &ArgMatches) { let dry_run: bool = args.is_present("dry_run"); info!("Looking for burial mounds..."); if !dry_run { - let stdout = - File::create(format!("{}/{}", get_working_dir(), "valheim_server.out")).unwrap(); - let stderr = - File::create(format!("{}/{}", get_working_dir(), "valheim_server.err")).unwrap(); + let stdout = create_file(format!("{}/logs/valheim_server.log", get_working_dir()).as_str()); + let stderr = create_file(format!("{}/logs/valheim_server.err", get_working_dir()).as_str()); let daemonize = Daemonize::new() .working_directory(get_working_dir()) .user("steam") @@ -51,8 +48,8 @@ pub fn invoke(args: &ArgMatches) { }); match daemonize.start() { - Ok(_) => println!("Success, daemonized"), - Err(e) => eprintln!("Error, {}", e), + Ok(_) => info!("Success, daemonized"), + Err(e) => error!("Error, {}", e), } } else { info!( diff --git a/src/main.rs b/src/main.rs index 86a26053..193c6694 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,8 +31,8 @@ fn main() { let app = App::from(yaml).version(VERSION); let matches = app.get_matches(); setup_logger(matches.is_present("debug")).unwrap(); - if let Some(ref init_matches) = matches.subcommand_matches("init") { - commands::initialize::invoke(init_matches); + if let Some(ref configure_matches) = matches.subcommand_matches("configure") { + commands::configure::invoke(configure_matches); }; if let Some(ref _match) = matches.subcommand_matches("install") { let result = commands::install::invoke(GAME_ID); @@ -41,8 +41,10 @@ fn main() { if let Some(ref start_matches) = matches.subcommand_matches("start") { commands::start::invoke(start_matches); }; - if let Some(ref stop_matches) = matches.subcommand_matches("stop") { commands::stop::invoke(stop_matches); }; + if let Some(ref backup_matches) = matches.subcommand_matches("backup") { + commands::backup::invoke(backup_matches); + }; } diff --git a/src/scripts/auto_backup.sh b/src/scripts/auto_backup.sh new file mode 100644 index 00000000..ec9c8929 --- /dev/null +++ b/src/scripts/auto_backup.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# Cron uses blank env and does not pick up /usr/local/bin files. +export PATH="/usr/local/bin:$PATH" +cd /home/steam/ || exit 1 + +log() { + PREFIX="[Valheim][steam]" + printf "%-16s: %s\n" "${PREFIX}" "$1" +} + +file_name="$(date +"%Y%m%d-%H%M%S")-${1:-"backup"}.tar.gz" + +log "Starting auto backup process..." +odin backup /home/steam/.config/unity3d/IronGate/Valheim "/home/steam/backups/${file_name}" || exit 1 + +if [ "${AUTO_BACKUP_REMOVE_OLD:=0}" -eq 1 ]; then + find /home/steam/backups/*.tar.gz -mtime +${AUTO_BACKUP_DAYS_TO_LIVE:-5} -exec rm {} \; +fi + +log "Backup process complete! Created ${file_name}" diff --git a/src/scripts/auto_update.sh b/src/scripts/auto_update.sh index a5a6aba7..413cd296 100644 --- a/src/scripts/auto_update.sh +++ b/src/scripts/auto_update.sh @@ -26,6 +26,11 @@ line cd /home/steam/valheim || exit 1 log "Stopping server..." odin stop || exit 1 + +if [ "${AUTO_BACKUP_ON_UPDATE:=0}" -eq 1 ]; then + /bin/bash /home/steam/scripts/auto_backup.sh "pre-update-backup" +fi + log "Installing Updates..." odin install || exit 1 log "Starting server..." diff --git a/src/scripts/entrypoint.sh b/src/scripts/entrypoint.sh index ac1c7cff..7ebba671 100644 --- a/src/scripts/entrypoint.sh +++ b/src/scripts/entrypoint.sh @@ -11,70 +11,76 @@ ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ >/etc/timezone # shellcheck disable=SC2039 if [ "${EUID}" -ne 0 ]; then - log "Please run as root" - exit + log "Please run as root" + exit fi log() { - PREFIX="[Valheim][root]" - printf "%-16s: %s\n" "${PREFIX}" "$1" + PREFIX="[Valheim][root]" + printf "%-16s: %s\n" "${PREFIX}" "$1" } line() { - log "###########################################################################" + log "###########################################################################" } check_version() { - file="/home/steam/.version" - sha="$(tail -n+1 $file | head -n1)" - branch="$(tail -n+2 $file | head -n1)" - repository="$(tail -n+3 $file | head -n1)" - github_version="$(curl -s "https://api.github.com/repos/${repository}/branches/${branch//refs\/heads\/}" | jq '.commit.sha')" - if [ -z "$github_version" ] || [ "$github_version" == "null" ]; then - log "You must be in development. Good luck!" - elif [ "${github_version//\"}" != "${sha//\"}" ]; then - log "Hey you! It looks like there is an update on $repository for $branch" - log "Please consider running \`docker-compose pull valheim\` or pull the image based on your use case" - fi + file="/home/steam/.version" + sha="$(tail -n+1 $file | head -n1)" + branch="$(tail -n+2 $file | head -n1)" + repository="$(tail -n+3 $file | head -n1)" + github_version="$(curl -s "https://api.github.com/repos/${repository}/branches/${branch//refs\/heads\//}" | jq '.commit.sha')" + if [ -z "$github_version" ] || [ "$github_version" == "null" ]; then + log "You must be in development. Good luck!" + elif [ "${github_version//\"/}" != "${sha//\"/}" ]; then + log "Hey you! It looks like there is an update on $repository for $branch" + log "Please consider running \`docker-compose pull valheim\` or pull the image based on your use case" + fi } clean_up() { - echo "Safely shutting down..." >>/home/steam/output.log - if [[ -n $CRON_PID ]]; then - kill $CRON_PID - fi + echo "Safely shutting down..." >>/home/steam/output.log + if [[ -n $CRON_PID ]]; then + kill $CRON_PID + fi } trap 'clean_up' INT TERM setup_cron() { - set -f - log "Auto Update Enabled..." - log "Schedule: ${AUTO_UPDATE_SCHEDULE}" - AUTO_UPDATE_SCHEDULE=$(echo "$AUTO_UPDATE_SCHEDULE" | tr -d '"') - printf "%s /usr/sbin/gosu steam /bin/bash /home/steam/scripts/auto_update.sh 2>&1 | tee -a /home/steam/valheim/valheim_server.out" "${AUTO_UPDATE_SCHEDULE}" >/etc/cron.d/auto-update - echo "" >>/etc/cron.d/auto-update - # Give execution rights on the cron job - chmod 0644 /etc/cron.d/auto-update - # Apply cron job - crontab /etc/cron.d/auto-update - set +f - /usr/sbin/cron -f & - export CRON_PID=$! + set -f + CRON_NAME=$1 + SCRIPT_PATH="/home/steam/scripts/$2" + CRON_SCHEDULE=$3 + CRON_ENV="$4" + LOG_LOCATION="/home/steam/valheim/logs/$CRON_NAME.out" + rm $LOG_LOCATION + printf "%s %s /usr/sbin/gosu steam /bin/bash %s >> %s 2>&1" \ + "${CRON_SCHEDULE}" \ + "${CRON_ENV:-""}" \ + "${SCRIPT_PATH}" \ + "${LOG_LOCATION}" \ + >/etc/cron.d/${CRON_NAME} + echo "" >>/etc/cron.d/${CRON_NAME} + # Give execution rights on the cron job + chmod 0644 /etc/cron.d/${CRON_NAME} + set +f } setup_filesystem() { - log "Setting up file systems" - STEAM_UID=${PUID:=1000} - STEAM_GID=${PGID:=1000} - mkdir -p /home/steam/valheim - chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim - mkdir -p /home/steam/scripts - chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/scripts - mkdir -p /home/steam/valheim - cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim - chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/ - chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim + log "Setting up file systems" + STEAM_UID=${PUID:=1000} + STEAM_GID=${PGID:=1000} + mkdir -p /home/steam/valheim + mkdir -p /home/steam/valheim/logs + mkdir -p /home/steam/backups + chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim + mkdir -p /home/steam/scripts + chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/scripts + mkdir -p /home/steam/valheim + cp /home/steam/steamcmd/linux64/steamclient.so /home/steam/valheim + chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/ + chown -R ${STEAM_UID}:${STEAM_GID} /home/steam/valheim } line @@ -90,7 +96,31 @@ log "$(usermod -u ${PUID} steam)" log "$(groupmod -g ${PGID} steam)" # Configure Cron -[ "${AUTO_UPDATE:=0}" -eq 1 ] && setup_cron +if [ "${AUTO_UPDATE:=0}" -eq 1 ]; then + log "Auto Update Enabled..." + log "Auto Update Schedule: ${AUTO_UPDATE_SCHEDULE}" + AUTO_UPDATE_SCHEDULE=$(echo "$AUTO_UPDATE_SCHEDULE" | tr -d '"') + setup_cron \ + "auto-update" \ + "auto_update.sh" \ + "${AUTO_UPDATE_SCHEDULE}" \ + "AUTO_BACKUP_ON_UPDATE=${AUTO_BACKUP_ON_UPDATE:-0}" +fi +if [ "${AUTO_BACKUP:=0}" -eq 1 ]; then + log "Auto Backup Enabled..." + log "Auto Backup Schedule: ${AUTO_BACKUP_SCHEDULE}" + AUTO_BACKUP_SCHEDULE=$(echo "$AUTO_BACKUP_SCHEDULE" | tr -d '"') + setup_cron \ + "auto-backup" \ + "auto_backup.sh" \ + "${AUTO_BACKUP_SCHEDULE}" \ + "AUTO_BACKUP_REMOVE_OLD=${AUTO_BACKUP_REMOVE_OLD} AUTO_BACKUP_DAYS_TO_LIVE=${AUTO_BACKUP_DAYS_TO_LIVE}" +fi + +# Apply cron job +cat /etc/cron.d/* | crontab - +/usr/sbin/cron -f & +export CRON_PID=$! # Configure filesystem setup_filesystem diff --git a/src/scripts/start_valheim.sh b/src/scripts/start_valheim.sh index d3573431..f236501f 100644 --- a/src/scripts/start_valheim.sh +++ b/src/scripts/start_valheim.sh @@ -19,6 +19,18 @@ initialize () { line } +cleanup() { + log "Halting server! Received interrupt!" + odin stop + if [ "${AUTO_BACKUP_ON_SHUTDOWN:=0}" -eq 1 ]; then + log "Backup on shutdown triggered! Running backup tool..." + /bin/bash /home/steam/scripts/auto_backup.sh "shutdown" + fi + if [[ -n $TAIL_PID ]];then + kill $TAIL_PID + fi +} + initialize "Installing Valheim via Odin..." log "Variables loaded....." @@ -37,32 +49,26 @@ log "Running Install..." odin install || exit 1 log "Initializing Variables...." -odin init || exit 1 +odin configure || exit 1 +trap 'cleanup' INT TERM log "Herding Cats..." log "Starting server..." odin start || exit 1 -cleanup() { - log "Halting server! Received interrupt!" - odin stop - if [[ -n $TAIL_PID ]];then - kill $TAIL_PID - fi -} - -trap 'cleanup' INT TERM - - initialize " Valheim Server Started... Keep an eye out for 'Game server connected' in the log! (this indicates its online without any errors.) -" >> /home/steam/valheim/valheim_server.out +" >> /home/steam/valheim/logs/output.log + -tail -f /home/steam/valheim/valheim_server.out /home/steam/valheim/valheim_server.err & +log_names=("valheim_server.log" "valheim_server.err" "output.log" "auto-update.out" "auto-backup.out") +log_files=("${log_names[@]/#/\/home\/steam\/valheim\/logs/}") +touch "${log_files[@]}" +tail -F ${log_files[*]} & export TAIL_PID=$! wait $TAIL_PID diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 15ca3369..e88b862b 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,7 +1,10 @@ use clap::ArgMatches; use log::debug; +use log::error; use std::env; +use std::fs::File; use std::path::Path; +use std::process::exit; pub const VALHEIM_EXECUTABLE_NAME: &str = "valheim_server.x86_64"; @@ -29,3 +32,14 @@ pub fn get_variable(args: &ArgMatches, name: &str, default: String) -> String { pub fn server_installed() -> bool { Path::new(&[get_working_dir(), VALHEIM_EXECUTABLE_NAME.to_string()].join("/")).exists() } + +pub fn create_file(path: &str) -> File { + let output_path = Path::new(path); + match File::create(output_path) { + Ok(file) => file, + Err(_) => { + error!("Failed to create {}", path); + exit(1) + } + } +}