Compare commits

...

2 Commits

Author SHA1 Message Date
959305c93c format 2025-12-23 15:41:12 +00:00
203a3f9b71 fix depreciation again 2025-12-23 15:41:12 +00:00
6 changed files with 259 additions and 228 deletions

View File

@@ -102,7 +102,7 @@
flake.colmena = flake.colmena =
{ {
meta = { meta = {
nixpkgs = import inputs.nixpkgs {system = "x86_64-linux";}; nixpkgs = import inputs.nixpkgs {localSystem = "x86_64-linux";};
specialArgs = {inherit inputs user constants;}; specialArgs = {inherit inputs user constants;};
}; };
} }
@@ -115,6 +115,7 @@
imports = [ imports = [
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
{ {
nixpkgs.hostPlatform = "x86_64-linux";
nixpkgs.overlays = overlays; nixpkgs.overlays = overlays;
_module.args.hostname = hostname; _module.args.hostname = hostname;
} }

View File

@@ -7,8 +7,9 @@
in { in {
sops.age.keyFile = "/Users/${user}/.config/sops/age/keys.txt"; sops.age.keyFile = "/Users/${user}/.config/sops/age/keys.txt";
sops.secrets = secrets.mkSyncthingSecrets { sops.secrets =
inherit hostname user; secrets.mkSyncthingSecrets {
isDarwin = true; inherit hostname user;
}; isDarwin = true;
};
} }

View File

@@ -9,8 +9,9 @@ in {
sops.age.sshKeyPaths = []; sops.age.sshKeyPaths = [];
sops.gnupg.sshKeyPaths = []; sops.gnupg.sshKeyPaths = [];
sops.secrets = secrets.mkSyncthingSecrets { sops.secrets =
inherit hostname user; secrets.mkSyncthingSecrets {
isDarwin = true; inherit hostname user;
}; isDarwin = true;
};
} }

View File

@@ -1,4 +1,8 @@
{config, hostname, ...}: { {
config,
hostname,
...
}: {
networking = { networking = {
hostName = hostname; hostName = hostname;
useDHCP = false; useDHCP = false;

View File

@@ -10,231 +10,254 @@ in {
options.my.pgbackrest = { options.my.pgbackrest = {
enable = mkEnableOption "pgBackRest PostgreSQL backup"; enable = mkEnableOption "pgBackRest PostgreSQL backup";
stanza = mkOption { stanza =
type = types.str; mkOption {
default = "main"; type = types.str;
description = "Name of the pgBackRest stanza"; default = "main";
}; description = "Name of the pgBackRest stanza";
secretFile = mkOption {
type = types.path;
description = "Path to the environment file containing S3 credentials and cipher passphrase";
};
s3 = mkOption {
type = types.submodule {
options = {
endpoint = mkOption {
type = types.str;
default = "s3.eu-central-003.backblazeb2.com";
description = "S3 endpoint URL";
};
bucket = mkOption {
type = types.str;
description = "S3 bucket name";
};
region = mkOption {
type = types.str;
default = "eu-central-003";
description = "S3 region";
};
path = mkOption {
type = types.str;
default = "/backups";
description = "Path within the S3 bucket";
};
};
}; };
default = {};
description = "S3 storage configuration";
};
retention = mkOption { secretFile =
type = types.submodule { mkOption {
options = { type = types.path;
full = mkOption { description = "Path to the environment file containing S3 credentials and cipher passphrase";
type = types.int;
default = 7;
description = "Number of full backups to retain";
};
diff = mkOption {
type = types.int;
default = 7;
description = "Number of differential backups to retain";
};
};
}; };
default = {};
description = "Backup retention configuration";
};
compression = mkOption { s3 =
type = types.submodule { mkOption {
options = { type =
type = mkOption { types.submodule {
type = types.str; options = {
default = "zst"; endpoint =
description = "Compression algorithm (none, gz, lz4, zst)"; mkOption {
}; type = types.str;
default = "s3.eu-central-003.backblazeb2.com";
description = "S3 endpoint URL";
};
level = mkOption { bucket =
type = types.int; mkOption {
default = 3; type = types.str;
description = "Compression level"; description = "S3 bucket name";
};
region =
mkOption {
type = types.str;
default = "eu-central-003";
description = "S3 region";
};
path =
mkOption {
type = types.str;
default = "/backups";
description = "Path within the S3 bucket";
};
};
}; };
}; default = {};
description = "S3 storage configuration";
}; };
default = {};
description = "Compression configuration";
};
processMax = mkOption { retention =
type = types.int; mkOption {
default = 2; type =
description = "Maximum number of processes for parallel operations"; types.submodule {
}; options = {
full =
mkOption {
type = types.int;
default = 7;
description = "Number of full backups to retain";
};
schedule = mkOption { diff =
type = types.submodule { mkOption {
options = { type = types.int;
full = mkOption { default = 7;
type = types.str; description = "Number of differential backups to retain";
default = "daily"; };
description = "OnCalendar expression for full backups"; };
}; };
default = {};
diff = mkOption { description = "Backup retention configuration";
type = types.str; };
default = "hourly";
description = "OnCalendar expression for differential backups"; compression =
}; mkOption {
}; type =
types.submodule {
options = {
type =
mkOption {
type = types.str;
default = "zst";
description = "Compression algorithm (none, gz, lz4, zst)";
};
level =
mkOption {
type = types.int;
default = 3;
description = "Compression level";
};
};
};
default = {};
description = "Compression configuration";
};
processMax =
mkOption {
type = types.int;
default = 2;
description = "Maximum number of processes for parallel operations";
};
schedule =
mkOption {
type =
types.submodule {
options = {
full =
mkOption {
type = types.str;
default = "daily";
description = "OnCalendar expression for full backups";
};
diff =
mkOption {
type = types.str;
default = "hourly";
description = "OnCalendar expression for differential backups";
};
};
};
default = {};
description = "Backup schedule configuration";
}; };
default = {};
description = "Backup schedule configuration";
};
}; };
config = mkIf cfg.enable (let config =
archivePushScript = pkgs.writeShellScript "pgbackrest-archive-push" '' mkIf cfg.enable (let
set -a archivePushScript =
source ${cfg.secretFile} pkgs.writeShellScript "pgbackrest-archive-push" ''
set +a set -a
exec ${pkgs.pgbackrest}/bin/pgbackrest --stanza=${cfg.stanza} archive-push "$1" source ${cfg.secretFile}
''; set +a
in { exec ${pkgs.pgbackrest}/bin/pgbackrest --stanza=${cfg.stanza} archive-push "$1"
environment.systemPackages = [ '';
pkgs.pgbackrest in {
(pkgs.writeShellScriptBin "pgbackrest-wrapper" '' environment.systemPackages = [
set -a pkgs.pgbackrest
source ${cfg.secretFile} (pkgs.writeShellScriptBin "pgbackrest-wrapper" ''
set +a set -a
exec ${pkgs.pgbackrest}/bin/pgbackrest "$@" source ${cfg.secretFile}
'') set +a
]; exec ${pkgs.pgbackrest}/bin/pgbackrest "$@"
'')
];
services.postgresql.settings = { services.postgresql.settings = {
archive_mode = "on"; archive_mode = "on";
archive_command = "${archivePushScript} %p"; archive_command = "${archivePushScript} %p";
};
environment.etc."pgbackrest/pgbackrest.conf".text = ''
[global]
repo1-type=s3
repo1-s3-endpoint=${cfg.s3.endpoint}
repo1-s3-bucket=${cfg.s3.bucket}
repo1-s3-region=${cfg.s3.region}
repo1-path=${cfg.s3.path}
repo1-retention-full=${toString cfg.retention.full}
repo1-retention-diff=${toString cfg.retention.diff}
repo1-cipher-type=aes-256-cbc
compress-type=${cfg.compression.type}
compress-level=${toString cfg.compression.level}
process-max=${toString cfg.processMax}
log-level-console=info
log-level-file=detail
log-path=/var/log/pgbackrest
spool-path=/var/spool/pgbackrest
[${cfg.stanza}]
pg1-path=/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}
pg1-user=postgres
'';
systemd.services.pgbackrest-stanza-create = {
description = "pgBackRest Stanza Create";
after = ["postgresql.service"];
requires = ["postgresql.service"];
path = [pkgs.pgbackrest];
serviceConfig = {
Type = "oneshot";
User = "postgres";
EnvironmentFile = cfg.secretFile;
RemainAfterExit = true;
}; };
script = ''
pgbackrest --stanza=${cfg.stanza} stanza-create || true environment.etc."pgbackrest/pgbackrest.conf".text = ''
[global]
repo1-type=s3
repo1-s3-endpoint=${cfg.s3.endpoint}
repo1-s3-bucket=${cfg.s3.bucket}
repo1-s3-region=${cfg.s3.region}
repo1-path=${cfg.s3.path}
repo1-retention-full=${toString cfg.retention.full}
repo1-retention-diff=${toString cfg.retention.diff}
repo1-cipher-type=aes-256-cbc
compress-type=${cfg.compression.type}
compress-level=${toString cfg.compression.level}
process-max=${toString cfg.processMax}
log-level-console=info
log-level-file=detail
log-path=/var/log/pgbackrest
spool-path=/var/spool/pgbackrest
[${cfg.stanza}]
pg1-path=/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}
pg1-user=postgres
''; '';
};
systemd.services.pgbackrest-backup = { systemd.services.pgbackrest-stanza-create = {
description = "pgBackRest Full Backup"; description = "pgBackRest Stanza Create";
after = ["postgresql.service" "pgbackrest-stanza-create.service"]; after = ["postgresql.service"];
requires = ["postgresql.service"]; requires = ["postgresql.service"];
wants = ["pgbackrest-stanza-create.service"]; path = [pkgs.pgbackrest];
path = [pkgs.pgbackrest]; serviceConfig = {
serviceConfig = { Type = "oneshot";
Type = "oneshot"; User = "postgres";
User = "postgres"; EnvironmentFile = cfg.secretFile;
EnvironmentFile = cfg.secretFile; RemainAfterExit = true;
};
script = ''
pgbackrest --stanza=${cfg.stanza} stanza-create || true
'';
}; };
script = ''
pgbackrest --stanza=${cfg.stanza} backup --type=full
'';
};
systemd.timers.pgbackrest-backup = { systemd.services.pgbackrest-backup = {
wantedBy = ["timers.target"]; description = "pgBackRest Full Backup";
timerConfig = { after = ["postgresql.service" "pgbackrest-stanza-create.service"];
OnCalendar = cfg.schedule.full; requires = ["postgresql.service"];
Persistent = true; wants = ["pgbackrest-stanza-create.service"];
RandomizedDelaySec = "1h"; path = [pkgs.pgbackrest];
serviceConfig = {
Type = "oneshot";
User = "postgres";
EnvironmentFile = cfg.secretFile;
};
script = ''
pgbackrest --stanza=${cfg.stanza} backup --type=full
'';
}; };
};
systemd.services.pgbackrest-backup-diff = { systemd.timers.pgbackrest-backup = {
description = "pgBackRest Differential Backup"; wantedBy = ["timers.target"];
after = ["postgresql.service" "pgbackrest-stanza-create.service"]; timerConfig = {
requires = ["postgresql.service"]; OnCalendar = cfg.schedule.full;
wants = ["pgbackrest-stanza-create.service"]; Persistent = true;
path = [pkgs.pgbackrest]; RandomizedDelaySec = "1h";
serviceConfig = { };
Type = "oneshot";
User = "postgres";
EnvironmentFile = cfg.secretFile;
}; };
script = ''
pgbackrest --stanza=${cfg.stanza} backup --type=diff
'';
};
systemd.timers.pgbackrest-backup-diff = { systemd.services.pgbackrest-backup-diff = {
wantedBy = ["timers.target"]; description = "pgBackRest Differential Backup";
timerConfig = { after = ["postgresql.service" "pgbackrest-stanza-create.service"];
OnCalendar = cfg.schedule.diff; requires = ["postgresql.service"];
Persistent = true; wants = ["pgbackrest-stanza-create.service"];
RandomizedDelaySec = "5m"; path = [pkgs.pgbackrest];
serviceConfig = {
Type = "oneshot";
User = "postgres";
EnvironmentFile = cfg.secretFile;
};
script = ''
pgbackrest --stanza=${cfg.stanza} backup --type=diff
'';
}; };
};
systemd.tmpfiles.rules = [ systemd.timers.pgbackrest-backup-diff = {
"d /var/lib/pgbackrest 0750 postgres postgres -" wantedBy = ["timers.target"];
"d /var/log/pgbackrest 0750 postgres postgres -" timerConfig = {
"d /var/spool/pgbackrest 0750 postgres postgres -" OnCalendar = cfg.schedule.diff;
]; Persistent = true;
}); RandomizedDelaySec = "5m";
};
};
systemd.tmpfiles.rules = [
"d /var/lib/pgbackrest 0750 postgres postgres -"
"d /var/log/pgbackrest 0750 postgres postgres -"
"d /var/spool/pgbackrest 0750 postgres postgres -"
];
});
} }

View File

@@ -127,24 +127,25 @@
}; };
}; };
home.file.".config/opencode/oh-my-opencode.json".text = builtins.toJSON { home.file.".config/opencode/oh-my-opencode.json".text =
"$schema" = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json"; builtins.toJSON {
google_auth = false; "$schema" = "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json";
agents = { google_auth = false;
oracle = { agents = {
model = "opencode/gpt-5.2"; oracle = {
}; model = "opencode/gpt-5.2";
frontend-ui-ux-engineer = { };
model = "google/gemini-3-pro-high"; frontend-ui-ux-engineer = {
}; model = "google/gemini-3-pro-high";
document-writer = { };
model = "google/gemini-3-flash"; document-writer = {
}; model = "google/gemini-3-flash";
multimodal-looker = { };
model = "google/gemini-3-flash"; multimodal-looker = {
model = "google/gemini-3-flash";
};
}; };
}; };
};
home.sessionVariables = { home.sessionVariables = {
OPENCODE_EXPERIMENTAL_EXA = "true"; OPENCODE_EXPERIMENTAL_EXA = "true";