proper amount of tabs
This commit is contained in:
parent
92abf91263
commit
349da643c6
27 changed files with 2591 additions and 2584 deletions
|
|
@ -1,38 +1,38 @@
|
|||
{lib, ...}: {
|
||||
disko.devices = {
|
||||
disk.disk1 = {
|
||||
device = lib.mkDefault "/dev/sda";
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
esp = {
|
||||
name = "ESP";
|
||||
start = "1M";
|
||||
end = "128M";
|
||||
type = "EF00";
|
||||
disko.devices = {
|
||||
disk.disk1 = {
|
||||
device = lib.mkDefault "/dev/sda";
|
||||
type = "disk";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
mountpoint = "/";
|
||||
mountOptions = ["noatime" "compress-force=zstd:3" "discard=async"];
|
||||
subvolumes = {
|
||||
"/home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = ["noatime" "compress-force=zstd:3" "discard=async"];
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
esp = {
|
||||
name = "ESP";
|
||||
start = "1M";
|
||||
end = "128M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
};
|
||||
};
|
||||
root = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
mountpoint = "/";
|
||||
mountOptions = ["noatime" "compress-force=zstd:3" "discard=async"];
|
||||
subvolumes = {
|
||||
"/home" = {
|
||||
mountpoint = "/home";
|
||||
mountOptions = ["noatime" "compress-force=zstd:3" "discard=async"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
{pkgs, ...}: {
|
||||
# services.displayManager.sddm.enable = true;
|
||||
# services.displayManager.cosmic-greeter.enable = false;
|
||||
services.desktopManager.cosmic.enable = true;
|
||||
# services.displayManager.sddm.enable = true;
|
||||
# services.displayManager.cosmic-greeter.enable = false;
|
||||
services.desktopManager.cosmic.enable = true;
|
||||
|
||||
environment.sessionVariables.COSMIC_DATA_CONTROL_ENABLED = 1;
|
||||
environment.sessionVariables.COSMIC_DATA_CONTROL_ENABLED = 1;
|
||||
|
||||
environment.cosmic.excludePackages = with pkgs; [
|
||||
cosmic-edit
|
||||
cosmic-player
|
||||
cosmic-term
|
||||
cosmic-wallpapers
|
||||
];
|
||||
environment.cosmic.excludePackages = with pkgs; [
|
||||
cosmic-edit
|
||||
cosmic-player
|
||||
cosmic-term
|
||||
cosmic-wallpapers
|
||||
];
|
||||
}
|
||||
|
|
|
|||
212
extras/dev.nix
212
extras/dev.nix
|
|
@ -1,118 +1,118 @@
|
|||
{pkgs, ...}: {
|
||||
# services.globalprotect = {
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# "vpn1.usfca.edu" = {
|
||||
# openconnect-args = "";
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
# services.globalprotect = {
|
||||
# enable = true;
|
||||
# settings = {
|
||||
# "vpn1.usfca.edu" = {
|
||||
# openconnect-args = "";
|
||||
# };
|
||||
# };
|
||||
# };
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# (llm.withPlugins (ps: with ps; [llm-openrouter]))
|
||||
# bash-language-server
|
||||
# digital
|
||||
# etcher
|
||||
# fontforge
|
||||
# freecad
|
||||
# llm
|
||||
# lychee # link checker
|
||||
# quickemu
|
||||
# radicle-node
|
||||
# vulkan-loader
|
||||
# act
|
||||
# aichat
|
||||
# aider-chat
|
||||
# asm-lsp
|
||||
b3sum
|
||||
devenv
|
||||
direnv
|
||||
gh
|
||||
# git-cliff
|
||||
hyperfine
|
||||
jujutsu
|
||||
just
|
||||
lldb
|
||||
# lua-language-server
|
||||
# markdown-oxide # markdown lsp
|
||||
qFlipper
|
||||
qemu
|
||||
sd
|
||||
sshfs
|
||||
taplo # toml lsp
|
||||
tio
|
||||
tokei # repo code stats
|
||||
typos
|
||||
environment.systemPackages = with pkgs; [
|
||||
# (llm.withPlugins (ps: with ps; [llm-openrouter]))
|
||||
# bash-language-server
|
||||
# digital
|
||||
# etcher
|
||||
# fontforge
|
||||
# freecad
|
||||
# llm
|
||||
# lychee # link checker
|
||||
# quickemu
|
||||
# radicle-node
|
||||
# vulkan-loader
|
||||
# act
|
||||
# aichat
|
||||
# aider-chat
|
||||
# asm-lsp
|
||||
b3sum
|
||||
devenv
|
||||
direnv
|
||||
gh
|
||||
# git-cliff
|
||||
hyperfine
|
||||
jujutsu
|
||||
just
|
||||
lldb
|
||||
# lua-language-server
|
||||
# markdown-oxide # markdown lsp
|
||||
qFlipper
|
||||
qemu
|
||||
sd
|
||||
sshfs
|
||||
taplo # toml lsp
|
||||
tio
|
||||
tokei # repo code stats
|
||||
typos
|
||||
|
||||
# # databases
|
||||
# sqlite
|
||||
# sqls
|
||||
# sqlx-cli
|
||||
# sea-orm-cli
|
||||
# rainfrog
|
||||
# # databases
|
||||
# sqlite
|
||||
# sqls
|
||||
# sqlx-cli
|
||||
# sea-orm-cli
|
||||
# rainfrog
|
||||
|
||||
# # arduino
|
||||
# arduino-language-server
|
||||
# arduino-cli
|
||||
# pkgsCross.avr.buildPackages.gcc
|
||||
# avrdude
|
||||
# ravedude
|
||||
# # arduino
|
||||
# arduino-language-server
|
||||
# arduino-cli
|
||||
# pkgsCross.avr.buildPackages.gcc
|
||||
# avrdude
|
||||
# ravedude
|
||||
|
||||
# c
|
||||
clang
|
||||
clang-tools
|
||||
gcc
|
||||
gdb
|
||||
gnumake
|
||||
# c
|
||||
clang
|
||||
clang-tools
|
||||
gcc
|
||||
gdb
|
||||
gnumake
|
||||
|
||||
# nix
|
||||
nil
|
||||
alejandra
|
||||
# nix
|
||||
nil
|
||||
alejandra
|
||||
|
||||
# python
|
||||
# pypy3
|
||||
python3
|
||||
# (python3.withPackages (ps:
|
||||
# with ps; [
|
||||
# llm
|
||||
# # llm-openrouter
|
||||
# ]))
|
||||
# python310Packages.python-lsp-server
|
||||
uv
|
||||
ruff
|
||||
# python
|
||||
# pypy3
|
||||
python3
|
||||
# (python3.withPackages (ps:
|
||||
# with ps; [
|
||||
# llm
|
||||
# # llm-openrouter
|
||||
# ]))
|
||||
# python310Packages.python-lsp-server
|
||||
uv
|
||||
ruff
|
||||
|
||||
# rust
|
||||
cargo-binstall
|
||||
bacon
|
||||
cargo-expand
|
||||
cargo-feature
|
||||
cargo-generate
|
||||
cargo-watch
|
||||
elf2uf2-rs
|
||||
flip-link
|
||||
mdbook
|
||||
mold-wrapped
|
||||
probe-rs
|
||||
rustup
|
||||
sccache
|
||||
trunk
|
||||
wasm-bindgen-cli
|
||||
];
|
||||
# rust
|
||||
cargo-binstall
|
||||
bacon
|
||||
cargo-expand
|
||||
cargo-feature
|
||||
cargo-generate
|
||||
cargo-watch
|
||||
elf2uf2-rs
|
||||
flip-link
|
||||
mdbook
|
||||
mold-wrapped
|
||||
probe-rs
|
||||
rustup
|
||||
sccache
|
||||
trunk
|
||||
wasm-bindgen-cli
|
||||
];
|
||||
|
||||
hardware.flipperzero.enable = true;
|
||||
hardware.flipperzero.enable = true;
|
||||
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM == "tty", GROUP="dialout", ATTRS{interface}=="Black Magic GDB Server", SYMLINK+="ttyBmpGdb"
|
||||
SUBSYSTEM == "tty", GROUP="dialout", ATTRS{interface}=="Black Magic UART Port", SYMLINK+="ttyBmpTarg"
|
||||
'';
|
||||
services.udev.extraRules = ''
|
||||
SUBSYSTEM == "tty", GROUP="dialout", ATTRS{interface}=="Black Magic GDB Server", SYMLINK+="ttyBmpGdb"
|
||||
SUBSYSTEM == "tty", GROUP="dialout", ATTRS{interface}=="Black Magic UART Port", SYMLINK+="ttyBmpTarg"
|
||||
'';
|
||||
|
||||
# virtualisation.docker = {
|
||||
# enable = true;
|
||||
# storageDriver = "btrfs";
|
||||
# };
|
||||
# virtualisation.docker.rootless = {
|
||||
# enable = true;
|
||||
# setSocketVariable = true;
|
||||
# };
|
||||
# users.extraGroups.docker.members = ["tao"];
|
||||
# virtualisation.docker = {
|
||||
# enable = true;
|
||||
# storageDriver = "btrfs";
|
||||
# };
|
||||
# virtualisation.docker.rootless = {
|
||||
# enable = true;
|
||||
# setSocketVariable = true;
|
||||
# };
|
||||
# users.extraGroups.docker.members = ["tao"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [
|
||||
# boinctui
|
||||
];
|
||||
services.boinc = {
|
||||
enable = false;
|
||||
};
|
||||
environment.systemPackages = with pkgs; [
|
||||
# boinctui
|
||||
];
|
||||
services.boinc = {
|
||||
enable = false;
|
||||
};
|
||||
|
||||
# services.foldingathome = {
|
||||
# enable = true;
|
||||
# team = 223518;
|
||||
# user = "Tao_Tien";
|
||||
# extraArgs = ["--passkey=76ba03d55acf116776ba03d55acf1167"];
|
||||
# };
|
||||
# services.foldingathome = {
|
||||
# enable = true;
|
||||
# team = 223518;
|
||||
# user = "Tao_Tien";
|
||||
# extraArgs = ["--passkey=76ba03d55acf116776ba03d55acf1167"];
|
||||
# };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
programs.steam = {
|
||||
enable = true;
|
||||
# remotePlay.openFirewall = true;
|
||||
gamescopeSession.enable = false;
|
||||
# gamescopeSession.enable = false;
|
||||
};
|
||||
programs.gamemode.enable = true;
|
||||
programs.gamescope.enable = true;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
{pkgs, ...}: {
|
||||
environment.systemPackages = with pkgs; [
|
||||
temurin-jre-bin-17
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [25565];
|
||||
environment.systemPackages = with pkgs; [
|
||||
temurin-jre-bin-17
|
||||
];
|
||||
networking.firewall.allowedTCPPorts = [25565];
|
||||
|
||||
services.snapper.configs = {
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = ["mc"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
TIMELINE_LIMIT_HOURLY = "5";
|
||||
TIMELINE_LIMIT_DAILY = "7";
|
||||
services.snapper.configs = {
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = ["mc"];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
TIMELINE_LIMIT_HOURLY = "5";
|
||||
TIMELINE_LIMIT_DAILY = "7";
|
||||
};
|
||||
};
|
||||
};
|
||||
services.snapper.snapshotInterval = "*:0/5";
|
||||
services.snapper.snapshotInterval = "*:0/5";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,359 +1,359 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.snapper;
|
||||
cfg = config.services.snapper;
|
||||
|
||||
mkValue = v:
|
||||
if lib.isList v
|
||||
then "\"${
|
||||
lib.concatMapStringsSep " " (lib.escape [
|
||||
"\\"
|
||||
" "
|
||||
])
|
||||
v
|
||||
}\""
|
||||
else if v == true
|
||||
then "yes"
|
||||
else if v == false
|
||||
then "no"
|
||||
else if lib.isString v
|
||||
then "\"${v}\""
|
||||
else builtins.toJSON v;
|
||||
mkValue = v:
|
||||
if lib.isList v
|
||||
then "\"${
|
||||
lib.concatMapStringsSep " " (lib.escape [
|
||||
"\\"
|
||||
" "
|
||||
])
|
||||
v
|
||||
}\""
|
||||
else if v == true
|
||||
then "yes"
|
||||
else if v == false
|
||||
then "no"
|
||||
else if lib.isString v
|
||||
then "\"${v}\""
|
||||
else builtins.toJSON v;
|
||||
|
||||
mkKeyValue = k: v: "${k}=${mkValue v}";
|
||||
mkKeyValue = k: v: "${k}=${mkValue v}";
|
||||
|
||||
# "it's recommended to always specify the filesystem type" -- man snapper-configs
|
||||
defaultOf = k:
|
||||
if k == "FSTYPE"
|
||||
then null
|
||||
else configOptions.${k}.default or null;
|
||||
# "it's recommended to always specify the filesystem type" -- man snapper-configs
|
||||
defaultOf = k:
|
||||
if k == "FSTYPE"
|
||||
then null
|
||||
else configOptions.${k}.default or null;
|
||||
|
||||
safeStr =
|
||||
lib.types.strMatching "[^\n\"]*"
|
||||
// {
|
||||
description = "string without line breaks or quotes";
|
||||
descriptionClass = "conjunction";
|
||||
safeStr =
|
||||
lib.types.strMatching "[^\n\"]*"
|
||||
// {
|
||||
description = "string without line breaks or quotes";
|
||||
descriptionClass = "conjunction";
|
||||
};
|
||||
|
||||
intOrNumberOrRange = lib.types.either lib.types.ints.unsigned (
|
||||
lib.types.strMatching "[[:digit:]]+(\-[[:digit:]]+)?"
|
||||
// {
|
||||
description = "string containing either a number or a range";
|
||||
descriptionClass = "conjunction";
|
||||
}
|
||||
);
|
||||
|
||||
configOptions = {
|
||||
SUBVOLUME = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
Path of the subvolume or mount point.
|
||||
This path is a subvolume and has to contain a subvolume named
|
||||
.snapshots.
|
||||
See also man:snapper(8) section PERMISSIONS.
|
||||
'';
|
||||
};
|
||||
|
||||
FSTYPE = lib.mkOption {
|
||||
type = lib.types.enum ["btrfs" "bcachefs"];
|
||||
default = "btrfs";
|
||||
description = ''
|
||||
Filesystem type. Only btrfs is stable and tested.
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_GROUPS = lib.mkOption {
|
||||
type = lib.types.listOf safeStr;
|
||||
default = [];
|
||||
description = ''
|
||||
List of groups allowed to operate with the config.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_USERS = lib.mkOption {
|
||||
type = lib.types.listOf safeStr;
|
||||
default = [];
|
||||
example = ["alice"];
|
||||
description = ''
|
||||
List of users allowed to operate with the config. "root" is always
|
||||
implicitly included.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CLEANUP = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Defines whether the timeline cleanup algorithm should be run for the config.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CREATE = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Defines whether hourly snapshots should be created.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_DAILY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_WEEKLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 0;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_MONTHLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_QUARTERLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 0;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_YEARLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
intOrNumberOrRange = lib.types.either lib.types.ints.unsigned (
|
||||
lib.types.strMatching "[[:digit:]]+(\-[[:digit:]]+)?"
|
||||
// {
|
||||
description = "string containing either a number or a range";
|
||||
descriptionClass = "conjunction";
|
||||
}
|
||||
);
|
||||
|
||||
configOptions = {
|
||||
SUBVOLUME = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
description = ''
|
||||
Path of the subvolume or mount point.
|
||||
This path is a subvolume and has to contain a subvolume named
|
||||
.snapshots.
|
||||
See also man:snapper(8) section PERMISSIONS.
|
||||
'';
|
||||
};
|
||||
|
||||
FSTYPE = lib.mkOption {
|
||||
type = lib.types.enum ["btrfs" "bcachefs"];
|
||||
default = "btrfs";
|
||||
description = ''
|
||||
Filesystem type. Only btrfs is stable and tested.
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_GROUPS = lib.mkOption {
|
||||
type = lib.types.listOf safeStr;
|
||||
default = [];
|
||||
description = ''
|
||||
List of groups allowed to operate with the config.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
ALLOW_USERS = lib.mkOption {
|
||||
type = lib.types.listOf safeStr;
|
||||
default = [];
|
||||
example = ["alice"];
|
||||
description = ''
|
||||
List of users allowed to operate with the config. "root" is always
|
||||
implicitly included.
|
||||
|
||||
Also see the PERMISSIONS section in man:snapper(8).
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CLEANUP = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Defines whether the timeline cleanup algorithm should be run for the config.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_CREATE = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Defines whether hourly snapshots should be created.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_HOURLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_DAILY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_WEEKLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 0;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_MONTHLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_QUARTERLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 0;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
|
||||
TIMELINE_LIMIT_YEARLY = lib.mkOption {
|
||||
type = intOrNumberOrRange;
|
||||
default = 10;
|
||||
description = ''
|
||||
Limits for timeline cleanup.
|
||||
'';
|
||||
};
|
||||
};
|
||||
in {
|
||||
options.services.snapper = {
|
||||
snapshotRootOnBoot = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to snapshot root on boot
|
||||
'';
|
||||
};
|
||||
|
||||
snapshotInterval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hourly";
|
||||
description = ''
|
||||
Snapshot interval.
|
||||
|
||||
The format is described in
|
||||
{manpage}`systemd.time(7)`.
|
||||
'';
|
||||
};
|
||||
|
||||
persistentTimer = lib.mkOption {
|
||||
default = false;
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Set the `Persistent` option for the
|
||||
{manpage}`systemd.timer(5)`
|
||||
which triggers the snapshot immediately if the last trigger
|
||||
was missed (e.g. if the system was powered down).
|
||||
'';
|
||||
};
|
||||
|
||||
cleanupInterval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "1d";
|
||||
description = ''
|
||||
Cleanup interval.
|
||||
|
||||
The format is described in
|
||||
{manpage}`systemd.time(7)`.
|
||||
'';
|
||||
};
|
||||
|
||||
filters = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = null;
|
||||
description = ''
|
||||
Global display difference filter. See man:snapper(8) for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
configs = lib.mkOption {
|
||||
default = {};
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
};
|
||||
}
|
||||
'';
|
||||
|
||||
description = ''
|
||||
Subvolume configuration. Any option mentioned in man:snapper-configs(5)
|
||||
is valid here, even if NixOS doesn't document it.
|
||||
'';
|
||||
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
freeformType = lib.types.attrsOf (
|
||||
lib.types.oneOf [
|
||||
(lib.types.listOf safeStr)
|
||||
lib.types.bool
|
||||
safeStr
|
||||
lib.types.number
|
||||
]
|
||||
);
|
||||
|
||||
options = configOptions;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.configs != {}) (
|
||||
let
|
||||
documentation = [
|
||||
"man:snapper(8)"
|
||||
"man:snapper-configs(5)"
|
||||
];
|
||||
in {
|
||||
environment = {
|
||||
systemPackages = [pkgs.snapper];
|
||||
|
||||
# Note: snapper/config-templates/default is only needed for create-config
|
||||
# which is not the NixOS way to configure.
|
||||
etc =
|
||||
{
|
||||
"sysconfig/snapper".text = ''
|
||||
SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
|
||||
options.services.snapper = {
|
||||
snapshotRootOnBoot = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to snapshot root on boot
|
||||
'';
|
||||
}
|
||||
// (lib.mapAttrs' (
|
||||
name: subvolume:
|
||||
lib.nameValuePair "snapper/configs/${name}" {
|
||||
text = lib.generators.toKeyValue {inherit mkKeyValue;} (
|
||||
lib.filterAttrs (k: v: v != defaultOf k) subvolume
|
||||
);
|
||||
};
|
||||
|
||||
snapshotInterval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hourly";
|
||||
description = ''
|
||||
Snapshot interval.
|
||||
|
||||
The format is described in
|
||||
{manpage}`systemd.time(7)`.
|
||||
'';
|
||||
};
|
||||
|
||||
persistentTimer = lib.mkOption {
|
||||
default = false;
|
||||
type = lib.types.bool;
|
||||
example = true;
|
||||
description = ''
|
||||
Set the `Persistent` option for the
|
||||
{manpage}`systemd.timer(5)`
|
||||
which triggers the snapshot immediately if the last trigger
|
||||
was missed (e.g. if the system was powered down).
|
||||
'';
|
||||
};
|
||||
|
||||
cleanupInterval = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "1d";
|
||||
description = ''
|
||||
Cleanup interval.
|
||||
|
||||
The format is described in
|
||||
{manpage}`systemd.time(7)`.
|
||||
'';
|
||||
};
|
||||
|
||||
filters = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = null;
|
||||
description = ''
|
||||
Global display difference filter. See man:snapper(8) for more details.
|
||||
'';
|
||||
};
|
||||
|
||||
configs = lib.mkOption {
|
||||
default = {};
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
home = {
|
||||
SUBVOLUME = "/home";
|
||||
ALLOW_USERS = [ "alice" ];
|
||||
TIMELINE_CREATE = true;
|
||||
TIMELINE_CLEANUP = true;
|
||||
};
|
||||
}
|
||||
)
|
||||
cfg.configs)
|
||||
// (lib.optionalAttrs (cfg.filters != null) {"snapper/filters/default.txt".text = cfg.filters;});
|
||||
};
|
||||
|
||||
services.dbus.packages = [pkgs.snapper];
|
||||
|
||||
systemd.services.snapperd = {
|
||||
description = "DBus interface for snapper";
|
||||
inherit documentation;
|
||||
serviceConfig = {
|
||||
Type = "dbus";
|
||||
BusName = "org.opensuse.Snapper";
|
||||
ExecStart = "${pkgs.snapper}/bin/snapperd";
|
||||
CapabilityBoundingSet = "CAP_DAC_OVERRIDE CAP_FOWNER CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SYS_ADMIN CAP_SYS_MODULE CAP_IPC_LOCK CAP_SYS_NICE";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = false;
|
||||
PrivateNetwork = true;
|
||||
ProtectHostname = true;
|
||||
RestrictAddressFamilies = "AF_UNIX";
|
||||
RestrictRealtime = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.snapper-timeline = {
|
||||
description = "Timeline of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
requires = ["local-fs.target"];
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
|
||||
};
|
||||
|
||||
systemd.timers.snapper-timeline = {
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
Persistent = cfg.persistentTimer;
|
||||
OnCalendar = cfg.snapshotInterval;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.snapper-cleanup = {
|
||||
description = "Cleanup of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
|
||||
};
|
||||
|
||||
systemd.timers.snapper-cleanup = {
|
||||
description = "Cleanup of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
wantedBy = ["timers.target"];
|
||||
requires = ["local-fs.target"];
|
||||
timerConfig.OnBootSec = "10m";
|
||||
timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
|
||||
};
|
||||
|
||||
systemd.services.snapper-boot = lib.mkIf cfg.snapshotRootOnBoot {
|
||||
description = "Take snapper snapshot of root on boot";
|
||||
inherit documentation;
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/bin/snapper --config root create --cleanup-algorithm number --description boot";
|
||||
serviceConfig.Type = "oneshot";
|
||||
requires = ["local-fs.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
|
||||
};
|
||||
|
||||
assertions = lib.concatMap (
|
||||
name: let
|
||||
sub = cfg.configs.${name};
|
||||
in
|
||||
[
|
||||
{
|
||||
assertion = !(sub ? extraConfig);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.extraConfig' no longer has any effect; please remove it.
|
||||
The contents of this option should be migrated to attributes on `services.snapper.configs.${name}'.
|
||||
'';
|
||||
}
|
||||
]
|
||||
++ map
|
||||
(attr: {
|
||||
assertion = !(lib.hasAttr attr sub);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.${attr}' has been renamed to `services.snapper.configs.${name}.${lib.toUpper attr}'.
|
||||
'';
|
||||
})
|
||||
[
|
||||
"fstype"
|
||||
"subvolume"
|
||||
]
|
||||
) (lib.attrNames cfg.configs);
|
||||
}
|
||||
);
|
||||
|
||||
meta.maintainers = with lib.maintainers; [Djabx];
|
||||
description = ''
|
||||
Subvolume configuration. Any option mentioned in man:snapper-configs(5)
|
||||
is valid here, even if NixOS doesn't document it.
|
||||
'';
|
||||
|
||||
type = lib.types.attrsOf (
|
||||
lib.types.submodule {
|
||||
freeformType = lib.types.attrsOf (
|
||||
lib.types.oneOf [
|
||||
(lib.types.listOf safeStr)
|
||||
lib.types.bool
|
||||
safeStr
|
||||
lib.types.number
|
||||
]
|
||||
);
|
||||
|
||||
options = configOptions;
|
||||
}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.configs != {}) (
|
||||
let
|
||||
documentation = [
|
||||
"man:snapper(8)"
|
||||
"man:snapper-configs(5)"
|
||||
];
|
||||
in {
|
||||
environment = {
|
||||
systemPackages = [pkgs.snapper];
|
||||
|
||||
# Note: snapper/config-templates/default is only needed for create-config
|
||||
# which is not the NixOS way to configure.
|
||||
etc =
|
||||
{
|
||||
"sysconfig/snapper".text = ''
|
||||
SNAPPER_CONFIGS="${lib.concatStringsSep " " (builtins.attrNames cfg.configs)}"
|
||||
'';
|
||||
}
|
||||
// (lib.mapAttrs' (
|
||||
name: subvolume:
|
||||
lib.nameValuePair "snapper/configs/${name}" {
|
||||
text = lib.generators.toKeyValue {inherit mkKeyValue;} (
|
||||
lib.filterAttrs (k: v: v != defaultOf k) subvolume
|
||||
);
|
||||
}
|
||||
)
|
||||
cfg.configs)
|
||||
// (lib.optionalAttrs (cfg.filters != null) {"snapper/filters/default.txt".text = cfg.filters;});
|
||||
};
|
||||
|
||||
services.dbus.packages = [pkgs.snapper];
|
||||
|
||||
systemd.services.snapperd = {
|
||||
description = "DBus interface for snapper";
|
||||
inherit documentation;
|
||||
serviceConfig = {
|
||||
Type = "dbus";
|
||||
BusName = "org.opensuse.Snapper";
|
||||
ExecStart = "${pkgs.snapper}/bin/snapperd";
|
||||
CapabilityBoundingSet = "CAP_DAC_OVERRIDE CAP_FOWNER CAP_CHOWN CAP_FSETID CAP_SETFCAP CAP_SYS_ADMIN CAP_SYS_MODULE CAP_IPC_LOCK CAP_SYS_NICE";
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = false;
|
||||
PrivateNetwork = true;
|
||||
ProtectHostname = true;
|
||||
RestrictAddressFamilies = "AF_UNIX";
|
||||
RestrictRealtime = true;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.snapper-timeline = {
|
||||
description = "Timeline of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
requires = ["local-fs.target"];
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --timeline";
|
||||
};
|
||||
|
||||
systemd.timers.snapper-timeline = {
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
Persistent = cfg.persistentTimer;
|
||||
OnCalendar = cfg.snapshotInterval;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.snapper-cleanup = {
|
||||
description = "Cleanup of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/lib/snapper/systemd-helper --cleanup";
|
||||
};
|
||||
|
||||
systemd.timers.snapper-cleanup = {
|
||||
description = "Cleanup of Snapper Snapshots";
|
||||
inherit documentation;
|
||||
wantedBy = ["timers.target"];
|
||||
requires = ["local-fs.target"];
|
||||
timerConfig.OnBootSec = "10m";
|
||||
timerConfig.OnUnitActiveSec = cfg.cleanupInterval;
|
||||
};
|
||||
|
||||
systemd.services.snapper-boot = lib.mkIf cfg.snapshotRootOnBoot {
|
||||
description = "Take snapper snapshot of root on boot";
|
||||
inherit documentation;
|
||||
serviceConfig.ExecStart = "${pkgs.snapper}/bin/snapper --config root create --cleanup-algorithm number --description boot";
|
||||
serviceConfig.Type = "oneshot";
|
||||
requires = ["local-fs.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
unitConfig.ConditionPathExists = "/etc/snapper/configs/root";
|
||||
};
|
||||
|
||||
assertions = lib.concatMap (
|
||||
name: let
|
||||
sub = cfg.configs.${name};
|
||||
in
|
||||
[
|
||||
{
|
||||
assertion = !(sub ? extraConfig);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.extraConfig' no longer has any effect; please remove it.
|
||||
The contents of this option should be migrated to attributes on `services.snapper.configs.${name}'.
|
||||
'';
|
||||
}
|
||||
]
|
||||
++ map
|
||||
(attr: {
|
||||
assertion = !(lib.hasAttr attr sub);
|
||||
message = ''
|
||||
The option definition `services.snapper.configs.${name}.${attr}' has been renamed to `services.snapper.configs.${name}.${lib.toUpper attr}'.
|
||||
'';
|
||||
})
|
||||
[
|
||||
"fstype"
|
||||
"subvolume"
|
||||
]
|
||||
) (lib.attrNames cfg.configs);
|
||||
}
|
||||
);
|
||||
|
||||
meta.maintainers = with lib.maintainers; [Djabx];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,48 +1,48 @@
|
|||
{pkgs, ...}: {
|
||||
users.users.tao.packages = with pkgs; [
|
||||
(python311Full.withPackages (ps:
|
||||
with ps; [
|
||||
# bokeh
|
||||
# datashader
|
||||
# hvplot
|
||||
# ipywidgets
|
||||
# ipywidgets
|
||||
# linkify-it-py
|
||||
# markdown-it-py
|
||||
# mdit-py-plugins
|
||||
# nbclient
|
||||
# numpy
|
||||
# pandas
|
||||
# panel
|
||||
# plotly
|
||||
# pyparsing
|
||||
# pyserial
|
||||
# scikit-learn
|
||||
# scipy
|
||||
# streamz
|
||||
# tkinter
|
||||
jupyter
|
||||
users.users.tao.packages = with pkgs; [
|
||||
(python311Full.withPackages (ps:
|
||||
with ps; [
|
||||
# bokeh
|
||||
# datashader
|
||||
# hvplot
|
||||
# ipywidgets
|
||||
# ipywidgets
|
||||
# linkify-it-py
|
||||
# markdown-it-py
|
||||
# mdit-py-plugins
|
||||
# nbclient
|
||||
# numpy
|
||||
# pandas
|
||||
# panel
|
||||
# plotly
|
||||
# pyparsing
|
||||
# pyserial
|
||||
# scikit-learn
|
||||
# scipy
|
||||
# streamz
|
||||
# tkinter
|
||||
jupyter
|
||||
|
||||
# pyserial
|
||||
bokeh
|
||||
datashader
|
||||
hvplot
|
||||
# ipython_blocking
|
||||
ipywidgets
|
||||
nbclient
|
||||
numpy
|
||||
pandas
|
||||
panel
|
||||
plotly
|
||||
pyparsing
|
||||
scikit-learn
|
||||
scipy
|
||||
streamz
|
||||
# pyserial
|
||||
bokeh
|
||||
datashader
|
||||
hvplot
|
||||
# ipython_blocking
|
||||
ipywidgets
|
||||
nbclient
|
||||
numpy
|
||||
pandas
|
||||
panel
|
||||
plotly
|
||||
pyparsing
|
||||
scikit-learn
|
||||
scipy
|
||||
streamz
|
||||
|
||||
tkinter
|
||||
linkify-it-py
|
||||
markdown-it-py
|
||||
mdit-py-plugins
|
||||
]))
|
||||
];
|
||||
tkinter
|
||||
linkify-it-py
|
||||
markdown-it-py
|
||||
mdit-py-plugins
|
||||
]))
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,62 +1,62 @@
|
|||
{config, ...}: {
|
||||
age.secrets.uwuraid.file = ../secrets/uwuraid.age;
|
||||
systemd.mounts = let
|
||||
opts = {
|
||||
type = "cifs";
|
||||
mountConfig = {Options = "noauto,noatime,async,users,rw,x-systemd.automount,credentials=${config.age.secrets.uwuraid.path},gid=users,file_mode=0770,dir_mode=0770";};
|
||||
};
|
||||
in [
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/anime";
|
||||
where = "/mnt/uwuraid/anime";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/backup";
|
||||
where = "/mnt/uwuraid/backup";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/everything";
|
||||
where = "/mnt/uwuraid/everything";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/media";
|
||||
where = "/mnt/uwuraid/media";
|
||||
})
|
||||
# (opts
|
||||
# // {
|
||||
# what = "//100.97.47.81/isos";
|
||||
# where = "/mnt/uwuraid/isos";
|
||||
# })
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/photos";
|
||||
where = "/mnt/uwuraid/photos";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/virginia";
|
||||
where = "/mnt/uwuraid/virginia";
|
||||
})
|
||||
];
|
||||
systemd.automounts = let
|
||||
opts = {
|
||||
wantedBy = ["multi-user.target"];
|
||||
automountConfig = {
|
||||
TimeoutIdleSec = "60";
|
||||
# DirectoryMode
|
||||
};
|
||||
};
|
||||
in [
|
||||
(opts // {where = "/mnt/uwuraid/anime";})
|
||||
(opts // {where = "/mnt/uwuraid/backup";})
|
||||
(opts // {where = "/mnt/uwuraid/everything";})
|
||||
(opts // {where = "/mnt/uwuraid/media";})
|
||||
# (opts // {where = "/mnt/uwuraid/isos";})
|
||||
(opts // {where = "/mnt/uwuraid/photos";})
|
||||
(opts // {where = "/mnt/uwuraid/virginia";})
|
||||
];
|
||||
age.secrets.uwuraid.file = ../secrets/uwuraid.age;
|
||||
systemd.mounts = let
|
||||
opts = {
|
||||
type = "cifs";
|
||||
mountConfig = {Options = "noauto,noatime,async,users,rw,x-systemd.automount,credentials=${config.age.secrets.uwuraid.path},gid=users,file_mode=0770,dir_mode=0770";};
|
||||
};
|
||||
in [
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/anime";
|
||||
where = "/mnt/uwuraid/anime";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/backup";
|
||||
where = "/mnt/uwuraid/backup";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/everything";
|
||||
where = "/mnt/uwuraid/everything";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/media";
|
||||
where = "/mnt/uwuraid/media";
|
||||
})
|
||||
# (opts
|
||||
# // {
|
||||
# what = "//100.97.47.81/isos";
|
||||
# where = "/mnt/uwuraid/isos";
|
||||
# })
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/photos";
|
||||
where = "/mnt/uwuraid/photos";
|
||||
})
|
||||
(opts
|
||||
// {
|
||||
what = "//100.97.47.81/virginia";
|
||||
where = "/mnt/uwuraid/virginia";
|
||||
})
|
||||
];
|
||||
systemd.automounts = let
|
||||
opts = {
|
||||
wantedBy = ["multi-user.target"];
|
||||
automountConfig = {
|
||||
TimeoutIdleSec = "60";
|
||||
# DirectoryMode
|
||||
};
|
||||
};
|
||||
in [
|
||||
(opts // {where = "/mnt/uwuraid/anime";})
|
||||
(opts // {where = "/mnt/uwuraid/backup";})
|
||||
(opts // {where = "/mnt/uwuraid/everything";})
|
||||
(opts // {where = "/mnt/uwuraid/media";})
|
||||
# (opts // {where = "/mnt/uwuraid/isos";})
|
||||
(opts // {where = "/mnt/uwuraid/photos";})
|
||||
(opts // {where = "/mnt/uwuraid/virginia";})
|
||||
];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue