diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9310640..feea70d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,14 @@ jobs: submodules: 'recursive' - name: Install kcov and shellcheck - run: sudo apt-get install -y kcov shellcheck + run: sudo apt-get install -y kcov shellcheck + + - name: Install restic + run: | + wget https://github.com/restic/restic/releases/download/v0.12.0/restic_0.12.0_linux_amd64.bz2 + bzip2 -d restic_0.12.0_linux_amd64.bz2 + sudo cp restic_0.12.0_linux_amd64 /usr/local/bin/restic + sudo chmod +x /usr/local/bin/restic - name: Run tests run: test/test.sh @@ -39,10 +46,3 @@ jobs: - name: shellcheck run: shellcheck backup.sh - - - name: Build the Docker image - run: | - echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin - docker build . --file Dockerfile --tag ghcr.io/nicolaschan/minecraft-backup:$GITHUB_SHA --tag ghcr.io/nicolaschan/minecraft-backup:latest - docker push ghcr.io/nicolaschan/minecraft-backup:$GITHUB_SHA - docker push ghcr.io/nicolaschan/minecraft-backup:latest diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..cab6284 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,55 @@ +# This is a basic workflow to help you get started with Actions + +name: CI + +# Controls when the action will run. +on: + push: + pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v2 + with: + submodules: 'recursive' + + - name: Install kcov and shellcheck + run: sudo apt-get install -y kcov shellcheck + + - name: Install restic + run: | + wget https://github.com/restic/restic/releases/download/v0.12.0/restic_0.12.0_linux_amd64.bz2 + bzip2 -d restic_0.12.0_linux_amd64.bz2 + sudo cp restic_0.12.0_linux_amd64 /usr/local/bin/restic + sudo chmod +x /usr/local/bin/restic + + - name: Run tests + run: test/test.sh + + - name: Run coverage + run: kcov --include-pattern=backup.sh "$(pwd)"/coverage test/test.sh + + - name: Codecov + uses: codecov/codecov-action@v1.2.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage/test.sh/cov.xml + + - name: shellcheck + run: shellcheck backup.sh + + - name: Build the Docker image + run: | + echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u $GITHUB_ACTOR --password-stdin + docker build . --file Dockerfile --tag ghcr.io/nicolaschan/minecraft-backup:$GITHUB_SHA --tag ghcr.io/nicolaschan/minecraft-backup:latest + docker push ghcr.io/nicolaschan/minecraft-backup:$GITHUB_SHA + docker push ghcr.io/nicolaschan/minecraft-backup:latest diff --git a/README.md b/README.md index 3f1a4bb..c46073a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![codecov](https://codecov.io/gh/nicolaschan/minecraft-backup/branch/master/graph/badge.svg?token=LCbVC4TbYJ)](https://codecov.io/gh/nicolaschan/minecraft-backup) Backup script for Minecraft servers on Linux. -Supports servers running in [screen](https://en.wikipedia.org/wiki/GNU_Screen), [tmux](https://en.wikipedia.org/wiki/Tmux), or with [RCON](https://wiki.vg/RCON) enabled. +Supports servers running in [screen](https://en.wikipedia.org/wiki/GNU_Screen), [tmux](https://en.wikipedia.org/wiki/Tmux), or with [RCON](https://wiki.vg/RCON) enabled. Supports `tar` file or [`restic`](https://restic.net/) backup backends. ## Features - Create backups of your world folder @@ -32,6 +32,18 @@ If using RCON, you will also need to have the [`xxd`](https://linux.die.net/man/ # If running on tmux session 0: ./backup.sh -c -i /home/user/server/world -o /mnt/storage/backups -s 0 -w tmux + +# Using restic (and RCON) +export RESTIC_PASSWORD="restic-pass-secret" # your password here +./backup.sh -c -i /home/user/server/world -r /mnt/storage/backups-restic -s localhost:25575:secret -w rcon + +# Using Docker and RCON +# You will have to set up networking so that this Docker image can access the RCON server +# In this example, the RCON server hostname is `server-host` +docker run \ + -v /home/user/server/world:/mnt/server \ + -v /mnt/storage/backups:/mnt/backups \ + ghcr.io/nicolaschan/minecraft-backup -c -i /mnt/server -o /mnt/backups -s server-host:25575:secret -w rcon ``` This will show chat messages (`-c`) and save a backup of `/home/user/server/world` into `/mnt/storage/backups` using the default thinning deletion policy for old backups. @@ -50,6 +62,7 @@ Command line options: -o Output directory -p Prefix that shows in Minecraft chat (default: Backup) -q Suppress warnings +-r Restic repo name (if using restic) -s Screen name, tmux session name, or hostname:port:password for RCON -v Verbose mode -w Window manager: screen (default), tmux, RCON @@ -74,6 +87,9 @@ tar -xzvf /path/to/backups/2019-04-09_02-15-01.tar.gz Then you can move your restored world (`restored-world` in this case) to your Minecraft server folder and rename it (usually called `world`) so the Minecraft server uses it. +### With `restic` +Use [`restic restore`](https://restic.readthedocs.io/en/latest/050_restore.html) to restore from backup. + ## Why not use `tar` directly? If you use `tar` while the server is running, you will likely get an error like this because Minecraft autosaves the world periodically: ``` diff --git a/backup.sh b/backup.sh index 06bad21..ae5a15a 100755 --- a/backup.sh +++ b/backup.sh @@ -57,9 +57,9 @@ while getopts 'a:cd:e:f:hi:l:m:o:p:qr:s:vw:' FLAG; do echo "-l Compression level (default: 3)" echo "-m Maximum backups to keep, use -1 for unlimited (default: 128)" echo "-o Output directory" - echo "-r Restic repo name (if using restic)" echo "-p Prefix that shows in Minecraft chat (default: Backup)" echo "-q Suppress warnings" + echo "-r Restic repo name (if using restic)" echo "-s Screen name, tmux session name, or hostname:port:password for RCON" echo "-v Verbose mode" echo "-w Window manager: screen (default), tmux, RCON" diff --git a/test/test.sh b/test/test.sh index 21179fa..9f13e4e 100755 --- a/test/test.sh +++ b/test/test.sh @@ -9,7 +9,7 @@ RCON_PORT="8088" RCON_PASSWORD="supersecret" export RESTIC_PASSWORD="restic-pass-secret" setUp () { - chmod -R 755 "$TEST_TMP" + chmod -R 755 "$TEST_TMP" || true rm -rf "$TEST_TMP" mkdir -p "$TEST_TMP/server/world" mkdir -p "$TEST_TMP/backups" @@ -84,6 +84,7 @@ test-restic-incomplete-snapshot () { chmod 000 "$TEST_TMP/server/world/file1.txt" TIMESTAMP="$(date +%F_%H-%M-%S --date="2021-01-01")" OUTPUT="$(./backup.sh -i "$TEST_TMP/server/world" -r "$TEST_TMP/backups-restic" -s "$SCREEN_TMP" -f "$TIMESTAMP")" + assertEquals 1 "$(restic list snapshots -r "$TEST_TMP/backups-restic" | wc -l)" assertContains "$OUTPUT" "Incomplete snapshot taken" }