From dbbd570d92f36f00446805a6c755063b153af3dc Mon Sep 17 00:00:00 2001 From: Joe Monk Date: Sun, 7 Sep 2025 02:30:04 +0100 Subject: [PATCH] first commit --- .gitea/workflows/deploy.yaml | 38 +++++++++++++++++++++++++++++ Dockerfile | 13 ++++++++++ README.md | 7 ++++++ bun.lock | 46 ++++++++++++++++++++++++++++++++++++ index.ts | 22 +++++++++++++++++ package.json | 14 +++++++++++ tsconfig.json | 29 +++++++++++++++++++++++ 7 files changed, 169 insertions(+) create mode 100644 .gitea/workflows/deploy.yaml create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 bun.lock create mode 100644 index.ts create mode 100644 package.json create mode 100644 tsconfig.json diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..c41705b --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,38 @@ +name: Build and deploy +run-name: Build and deploy +on: + push: + branches: + - main + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + github-server-url: "https://gitea.home.joemonk.co.uk" + + - name: Set up docker + run: "curl -fsSL https://get.docker.com | sh" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to private registry + uses: docker/login-action@v3 + with: + registry: "gitea.home.joemonk.co.uk/${{ github.repository }}" + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + gitea.home.joemonk.co.uk/${{ gitea.repository }}:latest + gitea.home.joemonk.co.uk/${{ gitea.repository }}:${{ gitea.sha }} + gitea.home.joemonk.co.uk/${{ gitea.repository }}:${{ gitea.run_number }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8ad130f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM oven/bun:1-debian AS base + +RUN apt-get update && apt-get install -y xz-utils + +WORKDIR /usr/src/app +ENV NODE_ENV=production + +VOLUME [ "/appdata", "/backup" ] + +COPY . . +RUN bun install --frozen-lockfile --production + +ENTRYPOINT [ "bun", "run", "index.ts" ] diff --git a/README.md b/README.md new file mode 100644 index 0000000..7248c8a --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Tiny backup script + +Stop all the running docker services, then run this backup all appdata except plex +`docker run -it -v /mnt/user/data/backups/2025-09-06:/backup -v /mnt/cache/appdata:/appdata gitea.home.joemonk.co.uk/joe/appdzip:1` + +But also: +`XZ_OPT=-8 XZ_OPT=-T0 tar cJf /mnt/user/data/backups/2025-09-06/flash.tar.xz /boot` just to capture the flash drive \ No newline at end of file diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..36259e6 --- /dev/null +++ b/bun.lock @@ -0,0 +1,46 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "zip", + "devDependencies": { + "@biomejs/biome": "2.2.3", + "@types/bun": "^1.2.21", + "typescript": "^5.9.2", + }, + }, + }, + "packages": { + "@biomejs/biome": ["@biomejs/biome@2.2.3", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.3", "@biomejs/cli-darwin-x64": "2.2.3", "@biomejs/cli-linux-arm64": "2.2.3", "@biomejs/cli-linux-arm64-musl": "2.2.3", "@biomejs/cli-linux-x64": "2.2.3", "@biomejs/cli-linux-x64-musl": "2.2.3", "@biomejs/cli-win32-arm64": "2.2.3", "@biomejs/cli-win32-x64": "2.2.3" }, "bin": { "biome": "bin/biome" } }, "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.3", "", { "os": "win32", "cpu": "x64" }, "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ=="], + + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], + + "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="], + + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], + + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + } +} diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..74c0acf --- /dev/null +++ b/index.ts @@ -0,0 +1,22 @@ +import { readdir } from "node:fs/promises"; +import { $ } from "bun"; + +const target = "/backup"; +const backup = "/appdata"; + +const dirs = ( + await readdir(backup, { + withFileTypes: true, + }) +) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name) + .filter((dir) => dir !== "plex"); + +console.log("backing up", backup, dirs, "to", target); + +for (const dir in dirs) { + console.log(`Backing up ${dir}`) + await $`XZ_OPT=-8 XZ_OPT=-T0 tar cJf ${target}/${dir}.tar.xz ${backup}/${dir}`; + console.log(`Finished backing up ${dir}`) +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..015be63 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "zip", + "module": "index.ts", + "type": "module", + "private": true, + "scripts": { + "format": "biome check --write" + }, + "devDependencies": { + "@biomejs/biome": "2.2.3", + "@types/bun": "^1.2.21", + "typescript": "^5.9.2" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..146fe4e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + // Environment setup & latest features + "lib": ["ESNext"], + "target": "ESNext", + "module": "Preserve", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedIndexedAccess": true, + "noImplicitOverride": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +}