This commit is contained in:
Lukas Wurzinger 2025-06-01 16:47:14 +02:00
commit ee5313c9bf
No known key found for this signature in database
5 changed files with 471 additions and 0 deletions

2
.envrc Normal file
View file

@ -0,0 +1,2 @@
# shellcheck shell=bash
use flake

142
flake.lock generated Normal file
View file

@ -0,0 +1,142 @@
{
"nodes": {
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1743550720,
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1747372754,
"narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1748460289,
"narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1743296961,
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"root": {
"inputs": {
"flake-parts": "flake-parts",
"hooks": "hooks",
"nixpkgs": "nixpkgs",
"treefmt": "treefmt"
}
},
"treefmt": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1748243702,
"narHash": "sha256-9YzfeN8CB6SzNPyPm2XjRRqSixDopTapaRsnTpXUEY8=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "1f3f7b784643d488ba4bf315638b2b0a4c5fb007",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

78
flake.nix Normal file
View file

@ -0,0 +1,78 @@
{
description = "Disk zapper";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
flake-parts,
hooks,
treefmt,
}@inputs:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [
hooks.flakeModule
treefmt.flakeModule
];
systems = nixpkgs.lib.systems.flakeExposed;
perSystem =
{
config,
pkgs,
self',
...
}:
{
treefmt = {
projectRootFile = "flake.nix";
programs = {
nixfmt = {
enable = true;
package = pkgs.nixfmt-rfc-style;
};
shfmt = {
enable = true;
includes = [
"zap"
];
};
shellcheck.enable = true;
};
};
pre-commit.settings.hooks = {
treefmt.enable = true;
};
devShells.default = pkgs.mkShellNoCC {
packages = [
self'.packages.default
];
shellHook = ''
${config.pre-commit.installationScript}
'';
};
packages.default = pkgs.callPackage ./package.nix { };
};
};
}

19
package.nix Normal file
View file

@ -0,0 +1,19 @@
{
writeShellApplication,
util-linux,
jq,
e2fsprogs,
dosfstools,
}:
writeShellApplication {
name = "zap";
runtimeInputs = [
util-linux
jq
e2fsprogs
dosfstools
];
text = builtins.readFile ./zap;
}

230
zap Executable file
View file

@ -0,0 +1,230 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
progname="$0"
warn() {
local line
for line in "$@"; do
echo "$progname: $line" 1>&2
done
}
error() {
warn "$@"
exit 1
}
skips=()
skip() {
if (($# < 1)); then
error 'name of value to be skipped is required'
fi
if (($# > 1)); then
error 'too many arguments'
fi
local skip=$1
for s in "${skips[@]}"; do
if [[ $s == "$skip" ]]; then
return 0
fi
done
return 1
}
args=$(
getopt \
--options v \
--longoptions mount:,create-boot,label:,boot-label:,crypt-label:,mapping:,mount-options:,boot-mount-options:,verbose \
--name "$progname" \
-- "$@"
)
eval set -- "$args"
mount=/mnt
mkboot=0
bootlbl=BOOT
lbl=main
cryptlbl=cryptmain
mapping=main
bootmntflags=()
mntflags=()
fatflags=()
ext4flags=()
while true; do
case "$1" in
--mount)
mount=$2
shift 2
;;
--create-boot)
skips+=(mkboot)
mkboot=1
shift
;;
--label)
skips+=(lbl)
lbl=$2
shift 2
;;
--boot-label)
skips+=(bootlbl)
bootlbl=${2^^}
shift 2
;;
--crypt-label)
skips+=(cryptlbl)
cryptlbl=$2
shift 2
;;
--mapping)
skips+=(mapping)
mapping=$2
shift 2
;;
--mount-options)
mntflags+=(--options "$2")
shift 2
;;
--boot-mount-options)
bootmntflags+=(--options "$2")
shift 2
;;
-v | --verbose)
fatflags+=(-v)
ext4flags+=(-v)
shift
;;
--)
shift
break
;;
esac
done
if (($# < 1)); then
error 'an argument specifying the block device is required'
fi
if (($# > 1)); then
error 'too many arguments'
fi
blkdev=$1
if ! skip mkboot; then
while true; do
read -rep 'Do you want to create a boot partition? [y/N] ' input
case "$input" in
[Yy]*)
mkboot=1
break
;;
'' | [Nn]*)
mkboot=0
break
;;
*) warn 'Please answer with yes or no' ;;
esac
done
fi
{
if ((mkboot)); then
echo ',512M,U;'
fi
echo ',,L;'
} | sfdisk --label gpt --quiet -- "$blkdev"
parts=()
json=$(sfdisk --json -- "$blkdev")
while IFS= read -r k; do
parts+=("$(jq --argjson k "$k" --raw-output '.partitiontable.partitions[$k].node' <<<"$json")")
done < <(jq '.partitiontable.partitions | keys[]' <<<"$json")
if ((mkboot)); then
bootfs="${parts[0]}"
blkdev="${parts[1]}"
else
blkdev="${parts[0]}"
fi
if ((mkboot)); then
if ! skip bootlbl; then
read -rep "Which label should the boot file system have? [$bootlbl] " input
if [[ -n $input ]]; then
bootlbl=$input
fi
fi
mkfs.fat -F 32 -n "$bootlbl" "${fatflags[@]}" -- "$bootfs" >/dev/null
fi
while true; do
read -rep 'Do you want this disk to be encrypted? [y/N] ' input
case "$input" in
[Yy]*)
while true; do
read -rsp 'Enter password: ' password
echo >&2
read -rsp 'Re-enter password: ' repassword
echo >&2
if [[ $password == "$repassword" ]]; then
break
fi
done
if ! skip cryptlbl; then
read -rep "Which label should the LUKS partition have? [$cryptlbl] " input
if [[ -n $input ]]; then
cryptlbl=$input
fi
fi
cryptsetup luksFormat --batch-mode --label "$cryptlbl" -- "$blkdev" <<<"$password"
if ! skip mapping; then
read -rep "Which name should the LUKS mapping have? [$mapping] " input
if [[ -n $input ]]; then
mapping=$input
fi
fi
cryptsetup open -- "$blkdev" "$mapping" <<<"$password"
fs=/dev/mapper/$mapping
break
;;
'' | [Nn]*)
fs=$blkdev
break
;;
*) warn 'Please answer with yes or no' ;;
esac
done
if ! skip lbl; then
read -rep "Which label should the file system have? [$lbl] " input
if [[ -n $input ]]; then
lbl=$input
fi
fi
mkfs.ext4 -qFL "$lbl" "${ext4flags[@]}" -- "$fs"
mkdir --parents -- "$mount"
mount "${mntflags[@]}" -- "$fs" "$mount"
if ((mkboot)); then
mkdir -- "$mount/boot"
mount "${bootmntflags[@]}" -- "$bootfs" "$mount/boot"
fi