nix fmt
This commit is contained in:
@@ -257,7 +257,11 @@ else
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJJk3a190w/1TZkzVKORvz/kwyKmFY144lVeDFm80p17";
|
||||
};
|
||||
"rsync.net" = {
|
||||
extraHostNames = [ "rsn" "rsyncnet" "fm2382.rsync.net" ];
|
||||
extraHostNames = [
|
||||
"rsn"
|
||||
"rsyncnet"
|
||||
"fm2382.rsync.net"
|
||||
];
|
||||
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINdUkGe6kKn5ssz4WRZKjcws0InbQqZayenzk9obmP1z";
|
||||
};
|
||||
|
||||
|
@@ -87,7 +87,10 @@ lib.mkMerge [
|
||||
})
|
||||
{
|
||||
vacu.packages.ffmpeg-vacu-full.enable = config.vacu.systemKind == "desktop";
|
||||
vacu.packages.ffmpeg-vacu-headless.enable = config.vacu.systemKind != "minimal" && config.vacu.systemKind != "container" && config.vacu.systemKind != "desktop";
|
||||
vacu.packages.ffmpeg-vacu-headless.enable =
|
||||
config.vacu.systemKind != "minimal"
|
||||
&& config.vacu.systemKind != "container"
|
||||
&& config.vacu.systemKind != "desktop";
|
||||
}
|
||||
{
|
||||
vacu.packages = {
|
||||
@@ -122,63 +125,62 @@ lib.mkMerge [
|
||||
};
|
||||
}
|
||||
{
|
||||
vacu.packages =
|
||||
with pkgs; [
|
||||
bash
|
||||
bzip2
|
||||
curl
|
||||
ddrescue
|
||||
diffutils
|
||||
dig
|
||||
dnsutils
|
||||
ethtool
|
||||
file
|
||||
findutils
|
||||
gnugrep
|
||||
gnused
|
||||
gnutar
|
||||
gnutls
|
||||
gzip
|
||||
hostname
|
||||
htop
|
||||
inetutils
|
||||
iperf3
|
||||
iputils
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
mosh
|
||||
nano
|
||||
ncdu
|
||||
netcat-openbsd
|
||||
nixos-rebuild
|
||||
openssh
|
||||
"p7zip-unfree"
|
||||
pciutils
|
||||
progress
|
||||
psutils
|
||||
pv
|
||||
ripgrep
|
||||
rsync
|
||||
screen
|
||||
# sed => gnused
|
||||
sops
|
||||
sshfs
|
||||
ssh-to-age
|
||||
# tar => gnutar
|
||||
tmux
|
||||
tree
|
||||
tzdata
|
||||
# units => vacu-units
|
||||
unzip
|
||||
usbutils
|
||||
util-linux
|
||||
"vacu-units"
|
||||
vim
|
||||
wget
|
||||
which
|
||||
xz
|
||||
zip
|
||||
];
|
||||
vacu.packages = with pkgs; [
|
||||
bash
|
||||
bzip2
|
||||
curl
|
||||
ddrescue
|
||||
diffutils
|
||||
dig
|
||||
dnsutils
|
||||
ethtool
|
||||
file
|
||||
findutils
|
||||
gnugrep
|
||||
gnused
|
||||
gnutar
|
||||
gnutls
|
||||
gzip
|
||||
hostname
|
||||
htop
|
||||
inetutils
|
||||
iperf3
|
||||
iputils
|
||||
jq
|
||||
killall
|
||||
lsof
|
||||
mosh
|
||||
nano
|
||||
ncdu
|
||||
netcat-openbsd
|
||||
nixos-rebuild
|
||||
openssh
|
||||
"p7zip-unfree"
|
||||
pciutils
|
||||
progress
|
||||
psutils
|
||||
pv
|
||||
ripgrep
|
||||
rsync
|
||||
screen
|
||||
# sed => gnused
|
||||
sops
|
||||
sshfs
|
||||
ssh-to-age
|
||||
# tar => gnutar
|
||||
tmux
|
||||
tree
|
||||
tzdata
|
||||
# units => vacu-units
|
||||
unzip
|
||||
usbutils
|
||||
util-linux
|
||||
"vacu-units"
|
||||
vim
|
||||
wget
|
||||
which
|
||||
xz
|
||||
zip
|
||||
];
|
||||
}
|
||||
]
|
||||
|
@@ -33,7 +33,8 @@ let
|
||||
readOnly = true;
|
||||
};
|
||||
};
|
||||
config.finalPackage = if config.overrides == null then config.package else config.package.override config.overrides;
|
||||
config.finalPackage =
|
||||
if config.overrides == null then config.package else config.package.override config.overrides;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
@@ -47,7 +47,9 @@ in
|
||||
};
|
||||
config =
|
||||
{
|
||||
vacu.sourceTree = inputsOf inputs.self // { inherit inputs; };
|
||||
vacu.sourceTree = inputsOf inputs.self // {
|
||||
inherit inputs;
|
||||
};
|
||||
# vacu.sourceTree = pkgs.runCommand "inputs-tree" { } ''
|
||||
# mkdir -p $out
|
||||
# ln -s ${inputs.self} $out/self
|
||||
|
@@ -1,8 +1,4 @@
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{ pkgs, inputs, ... }:
|
||||
{
|
||||
imports = [
|
||||
inputs.jovian.nixosModules.jovian
|
||||
|
55
flake.nix
55
flake.nix
@@ -175,10 +175,11 @@
|
||||
map (name: lib.nameValuePair name inputs.${name + suffix}) inp'
|
||||
);
|
||||
in
|
||||
thisInputsA // {
|
||||
inherit nixpkgs;
|
||||
inherit (inputs) self;
|
||||
};
|
||||
thisInputsA
|
||||
// {
|
||||
inherit nixpkgs;
|
||||
inherit (inputs) self;
|
||||
};
|
||||
mkNixosConfig =
|
||||
{
|
||||
unstable ? false,
|
||||
@@ -210,7 +211,12 @@
|
||||
);
|
||||
|
||||
lib = {
|
||||
inherit mkPlain mkPkgs mkInputs mkNixosConfig;
|
||||
inherit
|
||||
mkPlain
|
||||
mkPkgs
|
||||
mkInputs
|
||||
mkNixosConfig
|
||||
;
|
||||
};
|
||||
|
||||
nixosConfigurations = {
|
||||
@@ -268,9 +274,7 @@
|
||||
inherit (inputs) dns;
|
||||
vacuModuleType = "nix-on-droid";
|
||||
};
|
||||
pkgs = mkPkgs {
|
||||
system = arm;
|
||||
};
|
||||
pkgs = mkPkgs { system = arm; };
|
||||
};
|
||||
|
||||
checks = nixpkgs.lib.genAttrs [ x86 ] (
|
||||
@@ -286,15 +290,15 @@
|
||||
node.specialArgs.selfPackages = self.packages.${system};
|
||||
node.specialArgs.vacuModuleType = "nixos";
|
||||
};
|
||||
mkTest = name:
|
||||
mkTest =
|
||||
name:
|
||||
nixpkgs.lib.nixos.runTest {
|
||||
imports = [
|
||||
commonTestModule
|
||||
./tests/${name}
|
||||
{ node.specialArgs.inputs = self.nixosConfigurations.${name}._module.specialArgs.inputs; }
|
||||
];
|
||||
}
|
||||
;
|
||||
};
|
||||
checksFromConfig = plain.config.vacu.checks;
|
||||
in
|
||||
assert !(checksFromConfig ? liam) && !(checksFromConfig ? trip);
|
||||
@@ -421,7 +425,8 @@
|
||||
// (inputs.flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
mkNixvim = unstable:
|
||||
mkNixvim =
|
||||
unstable:
|
||||
let
|
||||
nixvim-input = if unstable then inputs.nixvim-unstable else inputs.nixvim;
|
||||
in
|
||||
@@ -437,12 +442,8 @@
|
||||
config.allowUnfree = true;
|
||||
overlays = [ inputs.sm64baserom.overlays.default ];
|
||||
};
|
||||
pkgs-unstable = mkPkgs (nixpkgs-args // {
|
||||
useUnstable = true;
|
||||
});
|
||||
pkgs-stable = mkPkgs (nixpkgs-args // {
|
||||
useUnstable = false;
|
||||
});
|
||||
pkgs-unstable = mkPkgs (nixpkgs-args // { useUnstable = true; });
|
||||
pkgs-stable = mkPkgs (nixpkgs-args // { useUnstable = false; });
|
||||
_plain = mkPlain pkgs-unstable;
|
||||
plain = _plain.config.vacu.withAsserts _plain;
|
||||
treefmtEval = inputs.treefmt-nix.lib.evalModule pkgs-unstable ./treefmt.nix;
|
||||
@@ -473,14 +474,18 @@
|
||||
};
|
||||
generated = pkgs.linkFarm "generated" {
|
||||
nixpkgs = "${inputs.nixpkgs}";
|
||||
"liam-test/hints.py" = pkgs.writeText "hints.py" (import ./typesForTest.nix {
|
||||
name = "liam";
|
||||
inherit (pkgs-stable) lib;
|
||||
inherit self;
|
||||
inherit (inputs) nixpkgs;
|
||||
});
|
||||
"liam-test/hints.py" = pkgs.writeText "hints.py" (
|
||||
import ./typesForTest.nix {
|
||||
name = "liam";
|
||||
inherit (pkgs-stable) lib;
|
||||
inherit self;
|
||||
inherit (inputs) nixpkgs;
|
||||
}
|
||||
);
|
||||
"dns/python-env" = builtins.dirOf (builtins.dirOf dns.interpreter);
|
||||
"mailtest/python-env" = builtins.dirOf (builtins.dirOf self.checks.x86_64-linux.liam.nodes.checker.vacu.mailtest.smtp.interpreter);
|
||||
"mailtest/python-env" = builtins.dirOf (
|
||||
builtins.dirOf self.checks.x86_64-linux.liam.nodes.checker.vacu.mailtest.smtp.interpreter
|
||||
);
|
||||
};
|
||||
haproxy-auth-request = pkgs.callPackage ./packages/haproxy-auth-request.nix {
|
||||
inherit haproxy-lua-http;
|
||||
|
@@ -1,8 +1,11 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
vacu.packages = [ "tpm-fido" ];
|
||||
users.groups.uhid = {};
|
||||
users.users.shelvacu.extraGroups = [ config.security.tpm2.tssGroup config.users.groups.uhid.name ];
|
||||
users.groups.uhid = { };
|
||||
users.users.shelvacu.extraGroups = [
|
||||
config.security.tpm2.tssGroup
|
||||
config.users.groups.uhid.name
|
||||
];
|
||||
security.tpm2.enable = true;
|
||||
security.tpm2.applyUdevRules = true;
|
||||
services.udev.extraRules = ''
|
||||
|
@@ -13,8 +13,9 @@
|
||||
background: #eee;
|
||||
padding: 0 10px;
|
||||
}
|
||||
h1,h2,h3 { line-height: 1.2; }
|
||||
|
||||
h1, h2, h3 {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 5px;
|
||||
@@ -22,21 +23,34 @@
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
}
|
||||
form label { display: block; }
|
||||
form label {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Jobs info</h1>
|
||||
<p>Hi! I am currently looking to find a Software Engineering job. I am a professional developer specializing in Ruby on Rails and Rust, with over 10 years of experience.</p>
|
||||
<p>
|
||||
Hi! I am currently looking to find a Software Engineering job. I am a
|
||||
professional developer specializing in Ruby on Rails and Rust, with over
|
||||
10 years of experience.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
What I want in a job:
|
||||
|
||||
<ul>
|
||||
<li><b>Fully Remote</b> - that means 1 visit to an office per month or less. Strongly preferred; non-remote jobs will have to be very tempting in every other category.</li>
|
||||
<li>
|
||||
<b>Fully Remote</b> - that means 1 visit to an office per month or
|
||||
less. Strongly preferred; non-remote jobs will have to be very
|
||||
tempting in every other category.
|
||||
</li>
|
||||
<li>Prefer direct hire, but not required.</li>
|
||||
<li>W2 employment preferred, but also open to C2C/1099.</li>
|
||||
<li>While I could be productive in nearly any language, I would most like to work with Rust.</li>
|
||||
<li>
|
||||
While I could be productive in nearly any language, I would most like
|
||||
to work with Rust.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
@@ -44,41 +58,78 @@
|
||||
Things you probably want to know:
|
||||
|
||||
<ul>
|
||||
<li>I am a US citizen (USC), for work authorization purposes I can work anywhere in the US.</li>
|
||||
<li>
|
||||
I am a US citizen (USC), for work authorization purposes I can work
|
||||
anywhere in the US.
|
||||
</li>
|
||||
<li>Open to both contract and permanent positions.</li>
|
||||
<li>I can start within a week.</li>
|
||||
<li>I do not have a formal degree, but more than enough experience to make up for it.</li>
|
||||
<li>
|
||||
I do not have a formal degree, but more than enough experience to make
|
||||
up for it.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h2>Resume</h2>
|
||||
|
||||
<p>
|
||||
<a href="/shelvacu-resume.pdf">You can see my latest, up-to-date resume here</a>.
|
||||
<a href="/shelvacu-resume.pdf"
|
||||
>You can see my latest, up-to-date resume here</a>.
|
||||
</p>
|
||||
|
||||
<h2>To send me job offers</h2>
|
||||
|
||||
<p>Unfortunately I get a lot of bad job offers if I just give out my email to anyone. As such, I will only accept job offers sent using this form.</b>
|
||||
<p>
|
||||
Unfortunately I get a lot of bad job offers if I just give out my email to
|
||||
anyone. As such, I will only accept job offers sent using this form.
|
||||
</p>
|
||||
|
||||
<p>Each time you want to send me an email about a new job offer, you must return to this page. The process may change from time to time. If you have multiple jobs you think I am a good fit for, please combine them in one email.</p>
|
||||
<p>
|
||||
Each time you want to send me an email about a new job offer, you must
|
||||
return to this page. The process may change from time to time. If you have
|
||||
multiple jobs you think I am a good fit for, please combine them in one
|
||||
email.
|
||||
</p>
|
||||
|
||||
<form method="get" action="/email">
|
||||
<label>
|
||||
<input type="checkbox" name="confirm_fully_remote_or_exceptional" value="yes" required>
|
||||
<span>This is a fully remote job, or you will give an exceptional reason why the offer should be considered despite not being fully remote.</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="confirm_fully_remote_or_exceptional"
|
||||
value="yes"
|
||||
required
|
||||
>
|
||||
<span>This is a fully remote job, or you will give an exceptional reason
|
||||
why the offer should be considered despite not being fully
|
||||
remote.</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="confirm_i_read_the_above" value="yes" required>
|
||||
<span>You have read the above and will not ask about work authorization status, earliest date to start, or formal education because you already have that information.</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="confirm_i_read_the_above"
|
||||
value="yes"
|
||||
required
|
||||
>
|
||||
<span>You have read the above and will not ask about work authorization
|
||||
status, earliest date to start, or formal education because you
|
||||
already have that information.</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="confirm_include_pay" value="yes" required>
|
||||
<span>You will include an estimated pay range. No "depends on experience", my resume clearly shows how much experience I have.</span>
|
||||
<span>You will include an estimated pay range. No "depends on
|
||||
experience", my resume clearly shows how much experience I
|
||||
have.</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="confirm_no_ask_resume" value="yes" required>
|
||||
<span>You will not ask for an updated resume. The latest resume is always available on this page.</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="confirm_no_ask_resume"
|
||||
value="yes"
|
||||
required
|
||||
>
|
||||
<span>You will not ask for an updated resume. The latest resume is
|
||||
always available on this page.</span>
|
||||
</label>
|
||||
<label>
|
||||
<div>Your email:</div>
|
||||
@@ -87,6 +138,10 @@
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<p>I apologize for the hassle. I promise that if you follow everything here before sending a job offer to me, I <i>will</i> respond, and I will make every effort to respond within 1 week.</p>
|
||||
<p>
|
||||
I apologize for the hassle. I promise that if you follow everything here
|
||||
before sending a job offer to me, I <i>will</i> respond, and I will make
|
||||
every effort to respond within 1 week.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -57,16 +57,20 @@ in
|
||||
repo = mkOption { default = "${cfg.rsyncUser}@${cfg.rsyncHost}:borg-repos/liam-backup"; };
|
||||
package = mkOption { default = pkgs.borgbackup; };
|
||||
cmd = mkOption { default = lib.getExe cfg.package; };
|
||||
paths = mkOption { default = [
|
||||
"/var/lib/mail"
|
||||
"/var/lib/dovecot"
|
||||
"/var/log"
|
||||
]; };
|
||||
paths = mkOption {
|
||||
default = [
|
||||
"/var/lib/mail"
|
||||
"/var/lib/dovecot"
|
||||
"/var/log"
|
||||
];
|
||||
};
|
||||
keyPath = mkOption { default = config.sops.secrets.liam-borg-key.path; };
|
||||
};
|
||||
config = {
|
||||
vacu.assertions = lib.singleton {
|
||||
assertion = (lib.versionAtLeast cfg.package.version "1.4.0") && !(lib.versionAtLeast cfg.package.version "1.5.0");
|
||||
assertion =
|
||||
(lib.versionAtLeast cfg.package.version "1.4.0")
|
||||
&& !(lib.versionAtLeast cfg.package.version "1.5.0");
|
||||
message = "Only for version 1.4.x";
|
||||
fatal = true;
|
||||
};
|
||||
@@ -88,7 +92,7 @@ in
|
||||
group = cfg.user;
|
||||
home = "/var/lib/auto-borg";
|
||||
};
|
||||
users.groups.${cfg.user} = {};
|
||||
users.groups.${cfg.user} = { };
|
||||
systemd.services.auto-borg-gen-key = {
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
|
405
liam/sieve.nix
405
liam/sieve.nix
@@ -5,7 +5,17 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (builtins) isString isList length head all isInt isAttrs isFloat isBool;
|
||||
inherit (builtins)
|
||||
isString
|
||||
isList
|
||||
length
|
||||
head
|
||||
all
|
||||
isInt
|
||||
isAttrs
|
||||
isFloat
|
||||
isBool
|
||||
;
|
||||
inherit (lib)
|
||||
concatStrings
|
||||
concatStringsSep
|
||||
@@ -16,21 +26,13 @@ let
|
||||
elemAt
|
||||
mapAttrsToList
|
||||
;
|
||||
mapConcat = f: xs:
|
||||
concatStrings (map f xs)
|
||||
;
|
||||
mapConcatSep = sep: f: xs:
|
||||
concatStringsSep sep (map f xs)
|
||||
;
|
||||
mapConcatLines = f: xs:
|
||||
mapConcatSep "\n" f xs
|
||||
;
|
||||
isListWhere = xs: f:
|
||||
(isList xs) && (all f xs)
|
||||
;
|
||||
stringOrList = val: (isString val) || (
|
||||
(isListWhere val isString) && (length val) > 0
|
||||
);
|
||||
mapConcat = f: xs: concatStrings (map f xs);
|
||||
mapConcatSep =
|
||||
sep: f: xs:
|
||||
concatStringsSep sep (map f xs);
|
||||
mapConcatLines = f: xs: mapConcatSep "\n" f xs;
|
||||
isListWhere = xs: f: (isList xs) && (all f xs);
|
||||
stringOrList = val: (isString val) || ((isListWhere val isString) && (length val) > 0);
|
||||
listify = val: if isList val then val else [ val ];
|
||||
email_folders = [
|
||||
"24nm-domain@shelvacu.com"
|
||||
@@ -89,36 +91,47 @@ let
|
||||
is_match = regex: s: (match regex s) != null;
|
||||
is_not_match = regex: s: !(is_match regex s);
|
||||
only_printable_ascii = s: is_match "[ -~\r\n]*" s;
|
||||
has_vars = s: lib.hasInfix ("$"+"{") s;
|
||||
has_vars = s: lib.hasInfix ("$" + "{") s;
|
||||
# is_quoteable = s: (only_printable_ascii s) && (!lib.hasInfix ("$" + "{") s);
|
||||
sieve_raw_escape_string =
|
||||
s:
|
||||
if !only_printable_ascii s then
|
||||
builtins.trace s
|
||||
throw "s failed only_printable_ascii check"
|
||||
builtins.trace s throw "s failed only_printable_ascii check"
|
||||
else
|
||||
replaceStrings [ ''"'' ''\'' "\n" "\r" ] [ ''\"'' ''\\'' ''\n'' ''\r'' ] s
|
||||
;
|
||||
replaceStrings [ ''"'' ''\'' "\n" "\r" ] [ ''\"'' ''\\'' ''\n'' ''\r'' ] s;
|
||||
sieve_encode_string =
|
||||
{ allow_vars, for_debug_comment, with_quotes }: s:
|
||||
{
|
||||
allow_vars,
|
||||
for_debug_comment,
|
||||
with_quotes,
|
||||
}:
|
||||
s:
|
||||
assert isString s;
|
||||
assert allow_vars || for_debug_comment || (!has_vars s);
|
||||
assert allow_vars || for_debug_comment || (!has_vars s);
|
||||
let
|
||||
a = sieve_raw_escape_string s;
|
||||
b = if for_debug_comment then replaceStrings [ ''*/'' ] [ ''*\/'' ] a else a;
|
||||
res = if with_quotes then ''"${b}"'' else b;
|
||||
in res
|
||||
;
|
||||
sieve_quote_string = sieve_encode_string { allow_vars = false; for_debug_comment = false; with_quotes = true; };
|
||||
sieve_quote_string_with_interp = sieve_encode_string { allow_vars = true; for_debug_comment = false; with_quotes = true; };
|
||||
in
|
||||
res;
|
||||
sieve_quote_string = sieve_encode_string {
|
||||
allow_vars = false;
|
||||
for_debug_comment = false;
|
||||
with_quotes = true;
|
||||
};
|
||||
sieve_quote_string_with_interp = sieve_encode_string {
|
||||
allow_vars = true;
|
||||
for_debug_comment = false;
|
||||
with_quotes = true;
|
||||
};
|
||||
is_valid_long_ident = is_match "[a-z_][a-z0-9_]*";
|
||||
is_number_ident = is_match "[0-9]*";
|
||||
is_valid_ident = s: (is_valid_long_ident s) || (is_number_ident s);
|
||||
interp = ident:
|
||||
interp =
|
||||
ident:
|
||||
assert isString ident;
|
||||
assert is_valid_ident ident;
|
||||
"$" + "{${ident}}"
|
||||
;
|
||||
"$" + "{${ident}}";
|
||||
dest = "envelope_to";
|
||||
dest_domain = "envelope_to_domain";
|
||||
set_envelope = ''
|
||||
@@ -133,139 +146,155 @@ let
|
||||
'';
|
||||
envelope_is = key: ''string :is "${interp dest}" ${sieve_quote_string key}'';
|
||||
envelope_domain_is = key: ''string :is "${interp dest_domain}" ${sieve_quote_string key}'';
|
||||
sieve_encode_list = xs:
|
||||
sieve_encode_list =
|
||||
xs:
|
||||
assert isListWhere xs isString;
|
||||
"[ ${mapConcatSep ", " sieve_encode xs} ]"
|
||||
;
|
||||
sieve_encode = val:
|
||||
if isString val then sieve_quote_string val
|
||||
else if isList val then sieve_encode_list val
|
||||
else assert "dunno what to do with this"; null
|
||||
;
|
||||
"[ ${mapConcatSep ", " sieve_encode xs} ]";
|
||||
sieve_encode =
|
||||
val:
|
||||
if isString val then
|
||||
sieve_quote_string val
|
||||
else if isList val then
|
||||
sieve_encode_list val
|
||||
else
|
||||
assert "dunno what to do with this";
|
||||
null;
|
||||
sieve_debug_list = xs: "[ ${mapConcat (s: (sieve_debug s) + " ") xs}]";
|
||||
sieve_debug_attrs = attrs:
|
||||
let
|
||||
toPairStr = name: val: "${sieve_debug name} = ${sieve_debug val}; ";
|
||||
pairStrs = mapAttrsToList toPairStr attrs;
|
||||
pairsStr = concatStrings pairStrs;
|
||||
in
|
||||
"{ ${pairsStr}}"
|
||||
;
|
||||
sieve_debug = val:
|
||||
if isString val then sieve_encode_string { allow_vars = true; for_debug_comment = true; with_quotes = true; } val
|
||||
else if (isInt val) || (isFloat val) then toString val
|
||||
sieve_debug_attrs =
|
||||
attrs:
|
||||
let
|
||||
toPairStr = name: val: "${sieve_debug name} = ${sieve_debug val}; ";
|
||||
pairStrs = mapAttrsToList toPairStr attrs;
|
||||
pairsStr = concatStrings pairStrs;
|
||||
in
|
||||
"{ ${pairsStr}}";
|
||||
sieve_debug =
|
||||
val:
|
||||
if isString val then
|
||||
sieve_encode_string {
|
||||
allow_vars = true;
|
||||
for_debug_comment = true;
|
||||
with_quotes = true;
|
||||
} val
|
||||
else if (isInt val) || (isFloat val) then
|
||||
toString val
|
||||
else if (isBool val) then
|
||||
(if val then "true" else "false")
|
||||
else if isNull val then "null"
|
||||
else if isList val then sieve_debug_list val
|
||||
else if isAttrs val then sieve_debug_attrs val
|
||||
else assert "dunno what to do with this"; null
|
||||
;
|
||||
pure_flags_impl = flags: conditions:
|
||||
assert isListWhere flags isString;
|
||||
assert isListWhere conditions isString;
|
||||
assert (length flags) > 0;
|
||||
assert (length conditions) > 0;
|
||||
let
|
||||
argAttrs = { inherit flags conditions; };
|
||||
firstFlag = head flags;
|
||||
combined_condition = if (length conditions) == 1 then head conditions else (allof conditions);
|
||||
in
|
||||
''
|
||||
# pure_flags ${sieve_debug argAttrs};
|
||||
removeflag ${sieve_quote_string firstFlag};
|
||||
if ${combined_condition} {
|
||||
${record_action "pure_flags ${concatStringsSep " " flags}"}
|
||||
${concatStringsSep "\n" (map (flag: ''addflag ${sieve_quote_string flag};'') flags)}
|
||||
}
|
||||
# pure_flags end
|
||||
'';
|
||||
pure_flags = flags: conditions:
|
||||
else if isNull val then
|
||||
"null"
|
||||
else if isList val then
|
||||
sieve_debug_list val
|
||||
else if isAttrs val then
|
||||
sieve_debug_attrs val
|
||||
else
|
||||
assert "dunno what to do with this";
|
||||
null;
|
||||
pure_flags_impl =
|
||||
flags: conditions:
|
||||
assert isListWhere flags isString;
|
||||
assert isListWhere conditions isString;
|
||||
assert (length flags) > 0;
|
||||
assert (length conditions) > 0;
|
||||
let
|
||||
argAttrs = { inherit flags conditions; };
|
||||
firstFlag = head flags;
|
||||
combined_condition = if (length conditions) == 1 then head conditions else (allof conditions);
|
||||
in
|
||||
''
|
||||
# pure_flags ${sieve_debug argAttrs};
|
||||
removeflag ${sieve_quote_string firstFlag};
|
||||
if ${combined_condition} {
|
||||
${record_action "pure_flags ${concatStringsSep " " flags}"}
|
||||
${concatStringsSep "\n" (map (flag: ''addflag ${sieve_quote_string flag};'') flags)}
|
||||
}
|
||||
# pure_flags end
|
||||
'';
|
||||
pure_flags =
|
||||
flags: conditions:
|
||||
assert stringOrList flags;
|
||||
assert stringOrList conditions;
|
||||
pure_flags_impl (listify flags) (listify conditions)
|
||||
;
|
||||
exists_impl = headers:
|
||||
pure_flags_impl (listify flags) (listify conditions);
|
||||
exists_impl =
|
||||
headers:
|
||||
assert isListWhere headers isString;
|
||||
if headers == [] then
|
||||
if headers == [ ] then
|
||||
"/* exists START: called with empty array */ false /* exists END */"
|
||||
else
|
||||
"/* exists START */ exists ${sieve_encode_list headers} /* exists END */"
|
||||
;
|
||||
exists = headers:
|
||||
"/* exists START */ exists ${sieve_encode_list headers} /* exists END */";
|
||||
exists =
|
||||
headers:
|
||||
assert stringOrList headers;
|
||||
exists_impl (listify headers)
|
||||
;
|
||||
header_generic = match_kind: header_s: match_es:
|
||||
exists_impl (listify headers);
|
||||
header_generic =
|
||||
match_kind: header_s: match_es:
|
||||
assert stringOrList header_s;
|
||||
assert stringOrList match_es;
|
||||
''/* header_generic START */ header ${match_kind} ${sieve_encode header_s} ${sieve_encode match_es} /* header_generic END */''
|
||||
;
|
||||
''/* header_generic START */ header ${match_kind} ${sieve_encode header_s} ${sieve_encode match_es} /* header_generic END */'';
|
||||
header_matches = header_generic ":matches";
|
||||
header_is = header_generic ":is";
|
||||
subject_generic = match_kind: match_es: header_generic match_kind "Subject" match_es;
|
||||
subject_matches = subject_generic ":matches";
|
||||
subject_is = subject_generic ":is";
|
||||
environment_generic = match_kind: environment_name_s: match_es:
|
||||
environment_generic =
|
||||
match_kind: environment_name_s: match_es:
|
||||
assert stringOrList environment_name_s;
|
||||
assert stringOrList match_es;
|
||||
"environment ${match_kind} ${sieve_encode environment_name_s} ${sieve_encode match_es}"
|
||||
;
|
||||
"environment ${match_kind} ${sieve_encode environment_name_s} ${sieve_encode match_es}";
|
||||
environment_matches = environment_generic ":matches";
|
||||
environment_is = environment_generic ":is";
|
||||
from_is = addr_list:
|
||||
from_is =
|
||||
addr_list:
|
||||
assert stringOrList addr_list;
|
||||
''/* from_is START */ address :is :all "From" ${sieve_encode addr_list} /* from_is END */''
|
||||
;
|
||||
var_is = var_name: rhs:
|
||||
''/* from_is START */ address :is :all "From" ${sieve_encode addr_list} /* from_is END */'';
|
||||
var_is =
|
||||
var_name: rhs:
|
||||
assert isString var_name;
|
||||
assert stringOrList rhs;
|
||||
''string :is "''${${var_name}}" ${sieve_encode rhs}''
|
||||
;
|
||||
''string :is "''${${var_name}}" ${sieve_encode rhs}'';
|
||||
var_is_true = var_name: var_is var_name "1";
|
||||
var_is_false = var_name: not (var_is_true var_name);
|
||||
set_with_interp = var_name: new_val:
|
||||
set_with_interp =
|
||||
var_name: new_val:
|
||||
assert isString var_name;
|
||||
assert is_valid_ident var_name;
|
||||
assert isString new_val;
|
||||
"set ${sieve_encode var_name} ${sieve_quote_string_with_interp new_val};"
|
||||
;
|
||||
set = var_name: new_val:
|
||||
"set ${sieve_encode var_name} ${sieve_quote_string_with_interp new_val};";
|
||||
set =
|
||||
var_name: new_val:
|
||||
assert isString var_name;
|
||||
assert is_valid_ident var_name;
|
||||
assert isString new_val;
|
||||
"set ${sieve_encode var_name} ${sieve_encode new_val};"
|
||||
;
|
||||
set_bool_var = var_name: bool_val:
|
||||
"set ${sieve_encode var_name} ${sieve_encode new_val};";
|
||||
set_bool_var =
|
||||
var_name: bool_val:
|
||||
assert isBool bool_val;
|
||||
set var_name (if bool_val then "1" else "0")
|
||||
;
|
||||
over_test_list = name: test_list:
|
||||
set var_name (if bool_val then "1" else "0");
|
||||
over_test_list =
|
||||
name: test_list:
|
||||
assert isListWhere test_list isString;
|
||||
''
|
||||
${name}(
|
||||
${concatStringsSep ",\n" test_list}
|
||||
)
|
||||
''
|
||||
;
|
||||
'';
|
||||
anyof = over_test_list "anyof";
|
||||
allof = over_test_list "allof";
|
||||
not = test: "not ${test}";
|
||||
record_action = action_desc:
|
||||
record_action =
|
||||
action_desc:
|
||||
assert isString action_desc;
|
||||
''addheader "X-Vacu-Action" ${sieve_encode action_desc};''
|
||||
;
|
||||
fileinto = folder:
|
||||
''addheader "X-Vacu-Action" ${sieve_encode action_desc};'';
|
||||
fileinto =
|
||||
folder:
|
||||
assert isString folder;
|
||||
''
|
||||
${record_action "fileinto ${folder}"}
|
||||
fileinto :create ${sieve_encode folder};
|
||||
''
|
||||
;
|
||||
ihave = extension_name_s:
|
||||
'';
|
||||
ihave =
|
||||
extension_name_s:
|
||||
assert stringOrList extension_name_s;
|
||||
"ihave ${sieve_encode extension_name_s}"
|
||||
;
|
||||
"ihave ${sieve_encode extension_name_s}";
|
||||
email_filters = map (e: ''
|
||||
elsif ${envelope_is e} { # item of email_filters
|
||||
${record_action "email_filters fileinto ${mk_email_folder_name e}"}
|
||||
@@ -291,7 +320,9 @@ let
|
||||
${set_with_interp var (interp "1")}
|
||||
}
|
||||
else {
|
||||
${lib.optionalString warn_if_unset (maybe_debug "info: Could not set ${var} from condition ${condition}, setting to default(${default})")}
|
||||
${lib.optionalString warn_if_unset (
|
||||
maybe_debug "info: Could not set ${var} from condition ${condition}, setting to default(${default})"
|
||||
)}
|
||||
${set var default}
|
||||
}
|
||||
# set_from END
|
||||
@@ -305,13 +336,11 @@ let
|
||||
condition = ''environment :matches ${sieve_quote_string item} "*"'';
|
||||
inherit var;
|
||||
};
|
||||
maybe_debug = msg:
|
||||
''
|
||||
if ${ihave "vnd.dovecot.debug"} {
|
||||
debug_log ${sieve_quote_string_with_interp msg};
|
||||
}
|
||||
''
|
||||
;
|
||||
maybe_debug = msg: ''
|
||||
if ${ihave "vnd.dovecot.debug"} {
|
||||
debug_log ${sieve_quote_string_with_interp msg};
|
||||
}
|
||||
'';
|
||||
sieve_text = ''
|
||||
require [
|
||||
"fileinto",
|
||||
@@ -325,22 +354,33 @@ let
|
||||
"ihave"
|
||||
];
|
||||
|
||||
if ${allof [
|
||||
(ihave "imapsieve")
|
||||
(environment_matches "imap.user" "*")
|
||||
(environment_matches "location" "MS")
|
||||
(environment_matches "phase" "post")
|
||||
]} {
|
||||
if ${
|
||||
allof [
|
||||
(ihave "imapsieve")
|
||||
(environment_matches "imap.user" "*")
|
||||
(environment_matches "location" "MS")
|
||||
(environment_matches "phase" "post")
|
||||
]
|
||||
} {
|
||||
${set_bool_var "in_imap" true}
|
||||
} else {
|
||||
${set_bool_var "in_imap" false}
|
||||
}
|
||||
|
||||
if ${var_is_true "in_imap"} {
|
||||
if ${not (allof [
|
||||
(environment_is "imap.cause" ["APPEND" "COPY" ""])
|
||||
(environment_is "imap.mailbox" ["MagicRefilter" ""])
|
||||
])} {
|
||||
if ${
|
||||
not (allof [
|
||||
(environment_is "imap.cause" [
|
||||
"APPEND"
|
||||
"COPY"
|
||||
""
|
||||
])
|
||||
(environment_is "imap.mailbox" [
|
||||
"MagicRefilter"
|
||||
""
|
||||
])
|
||||
])
|
||||
} {
|
||||
${maybe_debug "NOT doing anything cuz imap.cause and/or imap.mailbox isn't right"}
|
||||
stop;
|
||||
}
|
||||
@@ -358,9 +398,7 @@ let
|
||||
condition = ''currentdate :matches "iso8601" "*"'';
|
||||
var = "datetime";
|
||||
}}
|
||||
${set_with_interp "sieved_message"
|
||||
''at ''${datetime} by ${config.vacu.versionId} loc ''${env_location} phase ''${env_phase} user ''${env_imap_user} email ''${env_imap_email} cause ''${env_imap_cause} mailbox ''${env_imap_mailbox} changedflags ''${env_imap_changedflags} envelope ''${dest}''
|
||||
}
|
||||
${set_with_interp "sieved_message" ''at ''${datetime} by ${config.vacu.versionId} loc ''${env_location} phase ''${env_phase} user ''${env_imap_user} email ''${env_imap_email} cause ''${env_imap_cause} mailbox ''${env_imap_mailbox} changedflags ''${env_imap_changedflags} envelope ''${dest}''}
|
||||
${maybe_debug ''X-Vacu-Sieved: ''${sieved_message}''}
|
||||
|
||||
if ${ihave "envelope"} {
|
||||
@@ -382,43 +420,76 @@ let
|
||||
removeflag "ignore";
|
||||
removeflag "not-spamish";
|
||||
|
||||
${pure_flags ["amazon-ignore" "ignore"] [
|
||||
(envelope_is "amznbsns@shelvacu.com")
|
||||
(subject_matches [ "Your Amazon.com order has shipped*" "Your Amazon.com order of * has shipped!" ])
|
||||
]}
|
||||
${pure_flags ["bandcamp-ignore" "ignore"] [
|
||||
(envelope_is "bandcamp@shelvacu.com")
|
||||
(subject_matches [ "* just announced a listening party on Bandcamp" "New items from *" "Starting in *" "New from *" ])
|
||||
]}
|
||||
${pure_flags ["ika-ignore" "ignore"] (envelope_is "ika@dis8.net")}
|
||||
${pure_flags ["ally-statement" "ignore"] [
|
||||
(envelope_is "ally@shelvacu.com")
|
||||
(subject_is "Your latest statement is ready to view.")
|
||||
]}
|
||||
${pure_flags
|
||||
[ "amazon-ignore" "ignore" ]
|
||||
[
|
||||
(envelope_is "amznbsns@shelvacu.com")
|
||||
(subject_matches [
|
||||
"Your Amazon.com order has shipped*"
|
||||
"Your Amazon.com order of * has shipped!"
|
||||
])
|
||||
]
|
||||
}
|
||||
${pure_flags
|
||||
[ "bandcamp-ignore" "ignore" ]
|
||||
[
|
||||
(envelope_is "bandcamp@shelvacu.com")
|
||||
(subject_matches [
|
||||
"* just announced a listening party on Bandcamp"
|
||||
"New items from *"
|
||||
"Starting in *"
|
||||
"New from *"
|
||||
])
|
||||
]
|
||||
}
|
||||
${pure_flags [ "ika-ignore" "ignore" ] (envelope_is "ika@dis8.net")}
|
||||
${pure_flags
|
||||
[ "ally-statement" "ignore" ]
|
||||
[
|
||||
(envelope_is "ally@shelvacu.com")
|
||||
(subject_is "Your latest statement is ready to view.")
|
||||
]
|
||||
}
|
||||
|
||||
${pure_flags "bloomberg" (envelope_is "bloomberg@shelvacu.com")}
|
||||
|
||||
${pure_flags ["money-stuff" "not-spamish"] [
|
||||
(envelope_is "bloomberg@shelvacu.com")
|
||||
''header :matches "From" "\"Matt Levine\" *"''
|
||||
]}
|
||||
${pure_flags
|
||||
[ "money-stuff" "not-spamish" ]
|
||||
[
|
||||
(envelope_is "bloomberg@shelvacu.com")
|
||||
''header :matches "From" "\"Matt Levine\" *"''
|
||||
]
|
||||
}
|
||||
|
||||
${pure_flags ["git" "not-spamish"] (exists ["X-GitHub-Reason" "X-GitLab-Project"])}
|
||||
${pure_flags ["git-uninsane" "git" "not-spamish"] (envelope_is "git-uninsane@shelvacu.com")}
|
||||
${pure_flags [ "git" "not-spamish" ] (exists [
|
||||
"X-GitHub-Reason"
|
||||
"X-GitLab-Project"
|
||||
])}
|
||||
${pure_flags [ "git-uninsane" "git" "not-spamish" ] (envelope_is "git-uninsane@shelvacu.com")}
|
||||
|
||||
${pure_flags ["discourse" "not-spamish"] (exists "X-Discourse-Post-Id")}
|
||||
${pure_flags ["agora" "not-spamish"] (envelope_is "agora@shelvacu.com")}
|
||||
${pure_flags ["postgres-list" "not-spamish"] (header_matches "List-Id" "<*.lists.postgresql.org>")}
|
||||
${pure_flags ["secureaccesswa" "not-spamish"] (from_is "help@secureaccess.wa.gov")}
|
||||
${pure_flags ["letsencrypt-mailing-list" "not-spamish"] (envelope_is "lets-encrypt-mailing-list@shelvacu.com")}
|
||||
${pure_flags ["jmp-news" "not-spamish"] (header_matches "List-Id" "*<jmp-news.soprani.ca>")}
|
||||
${pure_flags ["tf2wiki" "not-spamish"] [
|
||||
(envelope_is "tf2wiki@shelvacu.com")
|
||||
(from_is "noreply@wiki.teamfortress.com")
|
||||
]}
|
||||
${pure_flags [ "discourse" "not-spamish" ] (exists "X-Discourse-Post-Id")}
|
||||
${pure_flags [ "agora" "not-spamish" ] (envelope_is "agora@shelvacu.com")}
|
||||
${pure_flags [ "postgres-list" "not-spamish" ] (
|
||||
header_matches "List-Id" "<*.lists.postgresql.org>"
|
||||
)}
|
||||
${pure_flags [ "secureaccesswa" "not-spamish" ] (from_is "help@secureaccess.wa.gov")}
|
||||
${pure_flags [ "letsencrypt-mailing-list" "not-spamish" ] (
|
||||
envelope_is "lets-encrypt-mailing-list@shelvacu.com"
|
||||
)}
|
||||
${pure_flags [ "jmp-news" "not-spamish" ] (header_matches "List-Id" "*<jmp-news.soprani.ca>")}
|
||||
${pure_flags
|
||||
[ "tf2wiki" "not-spamish" ]
|
||||
[
|
||||
(envelope_is "tf2wiki@shelvacu.com")
|
||||
(from_is "noreply@wiki.teamfortress.com")
|
||||
]
|
||||
}
|
||||
|
||||
${pure_flags "gmail-fwd" (envelope_is "gmailfwd-fc2e10bec8b2@shelvacu.com")}
|
||||
${pure_flags "aliexpress" (from_is ["transaction@notice.aliexpress.com" "aliexpress@notice.aliexpress.com"])}
|
||||
${pure_flags "aliexpress" (from_is [
|
||||
"transaction@notice.aliexpress.com"
|
||||
"aliexpress@notice.aliexpress.com"
|
||||
])}
|
||||
|
||||
removeflag "auto-marked-read";
|
||||
if hasflag "ignore" {
|
||||
|
@@ -31,6 +31,6 @@
|
||||
vacu.packages = [
|
||||
"yt-dlp"
|
||||
"radicle-node"
|
||||
"ncurses" #want this everywhere for clear/reset commands, but its included by default in nixos so only need ta specify here
|
||||
"ncurses" # want this everywhere for clear/reset commands, but its included by default in nixos so only need ta specify here
|
||||
];
|
||||
}
|
||||
|
@@ -1,8 +1,4 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{ config, lib, ... }:
|
||||
{
|
||||
imports = [ ./lean.nix ];
|
||||
opts = {
|
||||
@@ -23,7 +19,10 @@
|
||||
lua_ls.enable = true;
|
||||
nixd = {
|
||||
enable = true;
|
||||
cmd = [ (lib.getExe config.plugins.lsp.servers.nixd.package) "--log=error" ];
|
||||
cmd = [
|
||||
(lib.getExe config.plugins.lsp.servers.nixd.package)
|
||||
"--log=error"
|
||||
];
|
||||
};
|
||||
pyright.enable = true;
|
||||
rust_analyzer = {
|
||||
|
@@ -9,7 +9,8 @@ let
|
||||
lean = inputs.self.packages.${system}.leanLatest;
|
||||
in
|
||||
{
|
||||
imports = []
|
||||
imports =
|
||||
[ ]
|
||||
++ (lib.optional (!unstable) {
|
||||
plugins.lean.leanPackage = lean;
|
||||
plugins.lean.mappings = true;
|
||||
@@ -17,7 +18,6 @@ in
|
||||
++ (lib.optional unstable {
|
||||
dependencies.lean.enable = false;
|
||||
plugins.lean.settings.mappings = true;
|
||||
})
|
||||
;
|
||||
});
|
||||
plugins.lean.enable = true;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
git,
|
||||
libdbusmenu,
|
||||
|
||||
# options passed to the thunderbird builder, but with betterbird defaults
|
||||
# options passed to the thunderbird builder, but with betterbird defaults
|
||||
privacySupport ? true,
|
||||
requireSigning ? false,
|
||||
allowAddonSideload ? true,
|
||||
@@ -33,25 +33,28 @@ let
|
||||
tag = version;
|
||||
hash = "sha256-9UG1juN/vKHY3LRuryjMDdaFapd6y7ySu0Fn3GTeN2w=";
|
||||
};
|
||||
patchesFromThunderbird = runCommandNoCC "betterbird-patches-from-network" {
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-4OD7OckIA/qB0jI9dNk1Q6cTZZrKVufDNvPKSeEWYBY=";
|
||||
} ''
|
||||
set -xev
|
||||
mkdir -p $out
|
||||
fetchFromSeries() {
|
||||
local seriesFile="$1"
|
||||
shift
|
||||
filteredSeries="$(mktemp)"
|
||||
cat "$seriesFile" | grep " # " | grep -v "^#" | sed 's/ # / /' | sed 's:/rev/:/raw-rev/:' > "$filteredSeries"
|
||||
while IFS=" " read -r filename url; do
|
||||
${lib.getExe curl} -v -k "$url" --output "$out/$filename"
|
||||
done < "$filteredSeries"
|
||||
}
|
||||
fetchFromSeries ${betterbirdPatches}/${majorVersion}/series${stuff.MOZU}
|
||||
fetchFromSeries ${betterbirdPatches}/${majorVersion}/series
|
||||
'';
|
||||
patchesFromThunderbird =
|
||||
runCommandNoCC "betterbird-patches-from-network"
|
||||
{
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
outputHash = "sha256-4OD7OckIA/qB0jI9dNk1Q6cTZZrKVufDNvPKSeEWYBY=";
|
||||
}
|
||||
''
|
||||
set -xev
|
||||
mkdir -p $out
|
||||
fetchFromSeries() {
|
||||
local seriesFile="$1"
|
||||
shift
|
||||
filteredSeries="$(mktemp)"
|
||||
cat "$seriesFile" | grep " # " | grep -v "^#" | sed 's/ # / /' | sed 's:/rev/:/raw-rev/:' > "$filteredSeries"
|
||||
while IFS=" " read -r filename url; do
|
||||
${lib.getExe curl} -v -k "$url" --output "$out/$filename"
|
||||
done < "$filteredSeries"
|
||||
}
|
||||
fetchFromSeries ${betterbirdPatches}/${majorVersion}/series${stuff.MOZU}
|
||||
fetchFromSeries ${betterbirdPatches}/${majorVersion}/series
|
||||
'';
|
||||
mozilla_src = fetchhg {
|
||||
name = "mozilla--mozilla";
|
||||
url = stuff.MOZILLA_REPO;
|
||||
@@ -95,54 +98,64 @@ let
|
||||
applySeries ${betterbirdPatches}/${majorVersion}/series $out/comm
|
||||
'';
|
||||
in
|
||||
(thunderbird-128-unwrapped.override {
|
||||
inherit privacySupport requireSigning allowAddonSideload;
|
||||
}).overrideAttrs (old: rec {
|
||||
pname = "betterbird";
|
||||
inherit version;
|
||||
name = "${pname}-${version}";
|
||||
(thunderbird-128-unwrapped.override { inherit privacySupport requireSigning allowAddonSideload; })
|
||||
.overrideAttrs
|
||||
(old: rec {
|
||||
pname = "betterbird";
|
||||
inherit version;
|
||||
name = "${pname}-${version}";
|
||||
|
||||
buildInputs = (old.buildInputs or []) ++ [ libdbusmenu ];
|
||||
buildInputs = (old.buildInputs or [ ]) ++ [ libdbusmenu ];
|
||||
|
||||
src = replacement_src;
|
||||
src = replacement_src;
|
||||
|
||||
configureFlags = (old.configureFlags or []) ++ [
|
||||
# "--enable-application=comm/mail"
|
||||
"--with-branding=comm/mail/branding/betterbird"
|
||||
# "--disable-updater"
|
||||
# "--disable-crashreporter"
|
||||
# "--enable-tests"
|
||||
# "--without-wasm-sandboxed-libraries"
|
||||
# "--with-unsigned-addon-scopes=app,system"
|
||||
# "--allow-addon-sideload"
|
||||
# "--enable-default-toolkit=cairo-gtk3-wayland"
|
||||
# "--enable-official-branding"
|
||||
];
|
||||
configureFlags = (old.configureFlags or [ ]) ++ [
|
||||
# "--enable-application=comm/mail"
|
||||
"--with-branding=comm/mail/branding/betterbird"
|
||||
# "--disable-updater"
|
||||
# "--disable-crashreporter"
|
||||
# "--enable-tests"
|
||||
# "--without-wasm-sandboxed-libraries"
|
||||
# "--with-unsigned-addon-scopes=app,system"
|
||||
# "--allow-addon-sideload"
|
||||
# "--enable-default-toolkit=cairo-gtk3-wayland"
|
||||
# "--enable-official-branding"
|
||||
];
|
||||
|
||||
preConfigure = (old.preConfigure or "") + ''
|
||||
# Disable enforcing that add-ons are signed.
|
||||
export MOZ_REQUIRE_SIGNING=
|
||||
export MOZ_REQUIRE_ADDON_SIGNING=0
|
||||
preConfigure =
|
||||
(old.preConfigure or "")
|
||||
+ ''
|
||||
# Disable enforcing that add-ons are signed.
|
||||
export MOZ_REQUIRE_SIGNING=
|
||||
export MOZ_REQUIRE_ADDON_SIGNING=0
|
||||
|
||||
# For NSS symbols
|
||||
export MOZ_DEBUG_SYMBOLS=1
|
||||
# For NSS symbols
|
||||
export MOZ_DEBUG_SYMBOLS=1
|
||||
|
||||
# Set the WM_CLASS referenced in the .desktop file.
|
||||
export MOZ_APP_REMOTINGNAME=eu.betterbird.Betterbird
|
||||
# Set the WM_CLASS referenced in the .desktop file.
|
||||
export MOZ_APP_REMOTINGNAME=eu.betterbird.Betterbird
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
# The preceding comment appears all over the Mozilla repos, however it is misleading.
|
||||
# "Official" (server) builds, as opposed to local builds, should have nothing to do
|
||||
# with "breakpad" (https://chromium.googlesource.com/breakpad/) crash reporting.
|
||||
# In any case, we don't want a local build.
|
||||
export MOZILLA_OFFICIAL=1
|
||||
# Needed to enable breakpad in application.ini
|
||||
# The preceding comment appears all over the Mozilla repos, however it is misleading.
|
||||
# "Official" (server) builds, as opposed to local builds, should have nothing to do
|
||||
# with "breakpad" (https://chromium.googlesource.com/breakpad/) crash reporting.
|
||||
# In any case, we don't want a local build.
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
||||
export MOZ_TELEMETRY_REPORTING= # No telemetry.
|
||||
export MOZ_TELEMETRY_REPORTING= # No telemetry.
|
||||
|
||||
# Used for Linux to create small launcher executable for file browsers.
|
||||
# See https://hg.mozilla.org/mozilla-central/rev/3cbbfc5127e4 for details.
|
||||
export MOZ_NO_PIE_COMPAT=1
|
||||
'';
|
||||
# Used for Linux to create small launcher executable for file browsers.
|
||||
# See https://hg.mozilla.org/mozilla-central/rev/3cbbfc5127e4 for details.
|
||||
export MOZ_NO_PIE_COMPAT=1
|
||||
'';
|
||||
|
||||
passthru = (old.passthru or {}) // { inherit betterbirdPatches mozilla_src comm_src replacement_src patchesFromThunderbird; };
|
||||
})
|
||||
passthru = (old.passthru or { }) // {
|
||||
inherit
|
||||
betterbirdPatches
|
||||
mozilla_src
|
||||
comm_src
|
||||
replacement_src
|
||||
patchesFromThunderbird
|
||||
;
|
||||
};
|
||||
})
|
||||
|
@@ -1,14 +1,15 @@
|
||||
# shellcheck shell=bash
|
||||
translateWetransferLinks() {
|
||||
local old_urlsArray=("${urls[*]}")
|
||||
local new_urlsArray=()
|
||||
for this_url in "${old_urlsArray[@]}"; do
|
||||
if [[ "$this_url" = https://we.tl/* ]] || [[ "$this_url" = https://wetransfer.com/downloads/* ]]; then
|
||||
local new_url
|
||||
new_url="$("$transferweeBin" -v -g download "$this_url")"
|
||||
new_urlsArray+=("$new_url")
|
||||
else
|
||||
new_urlsArray+=("$this_url")
|
||||
fi
|
||||
if [[ $this_url == https://we.tl/* ]] || [[ $this_url == https://wetransfer.com/downloads/* ]]; then
|
||||
local new_url
|
||||
new_url="$("${transferweeBin:?}" -v -g download "$this_url")"
|
||||
new_urlsArray+=("$new_url")
|
||||
else
|
||||
new_urlsArray+=("$this_url")
|
||||
fi
|
||||
done
|
||||
urls="${new_urlsArray[*]}"
|
||||
}
|
||||
|
@@ -1,7 +1,9 @@
|
||||
self: _super: {
|
||||
fetchurlWithWetransfer = args: (self.fetchurl args).overrideAttrs (old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ ./convert-wetransfer-links.sh ];
|
||||
env.transferweeBin = self.lib.getExe self.transferwee;
|
||||
env.NIX_DEBUG = "6";
|
||||
});
|
||||
fetchurlWithWetransfer =
|
||||
args:
|
||||
(self.fetchurl args).overrideAttrs (old: {
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ ./convert-wetransfer-links.sh ];
|
||||
env.transferweeBin = self.lib.getExe self.transferwee;
|
||||
env.NIX_DEBUG = "6";
|
||||
});
|
||||
}
|
||||
|
@@ -1,15 +1,13 @@
|
||||
{
|
||||
lean4,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
lean4.overrideAttrs (final: prev: {
|
||||
version = "4.19.0-rc3";
|
||||
src = fetchFromGitHub {
|
||||
owner = "leanprover";
|
||||
repo = "lean4";
|
||||
tag = "v4.19.0-rc3";
|
||||
hash = "sha256-3a+zMGr1JnjxCm9sx8ikTpPXUoaOxmO6o5I0akip+kU=";
|
||||
};
|
||||
cmakeFlags = (prev.cmakeFlags or []) ++ [ "-DUSE_MIMALLOC=OFF" ];
|
||||
})
|
||||
|
||||
{ lean4, fetchFromGitHub }:
|
||||
lean4.overrideAttrs (
|
||||
final: prev: {
|
||||
version = "4.19.0-rc3";
|
||||
src = fetchFromGitHub {
|
||||
owner = "leanprover";
|
||||
repo = "lean4";
|
||||
tag = "v4.19.0-rc3";
|
||||
hash = "sha256-3a+zMGr1JnjxCm9sx8ikTpPXUoaOxmO6o5I0akip+kU=";
|
||||
};
|
||||
cmakeFlags = (prev.cmakeFlags or [ ]) ++ [ "-DUSE_MIMALLOC=OFF" ];
|
||||
}
|
||||
)
|
||||
|
@@ -17,8 +17,9 @@ let
|
||||
];
|
||||
python = pkgs.python312.withPackages (_: libraries);
|
||||
in
|
||||
(pkgs.writers.writePython3Bin "dns-update" {
|
||||
inherit libraries;
|
||||
} pythonScript).overrideAttrs (old: {
|
||||
passthru = (old.passthru or {}) // { inherit libraries python; };
|
||||
})
|
||||
(pkgs.writers.writePython3Bin "dns-update" { inherit libraries; } pythonScript).overrideAttrs
|
||||
(old: {
|
||||
passthru = (old.passthru or { }) // {
|
||||
inherit libraries python;
|
||||
};
|
||||
})
|
||||
|
@@ -4,98 +4,98 @@ dkim_key: ENC[AES256_GCM,data:CZC/1U1cJUIyNhXAWp+YFJd0pZZKvZClJxOh3uZ3YyfEQBiK9n
|
||||
dkim_pub: ENC[AES256_GCM,data:XLYRTAviK+r6DnRU4+lc58elI3FJ+FPsB1A5sQOk+pb+fNu7zFCiZdz/MwTVkE9izDP1Onv+VhV8sRgmxacTv4nW5GcukCrm3FmCp2jm6QF1/40/WRv6Lkbek0tV1bMOQPy9Zj8wdO9M05XCXUVXk4x17rj+lw8ApwJS2pJMoultMFx34tx2pNEnmO3MFtuBOxzeU2yP+NhF2sJNA62to78AiH5EblkoF0a6sUYk553U+sv3Ob0lo1nSv6c8zwl7y1WSNQnLK+/3WxSVGfePHVsVM8Zze1KFTVLQQggIzWTdcr7AgcTGbk3kaYCeucfQ60pVlqOyPnkJoUJ8HR1RSajFk6Ylzw0xBpY85qAXNT2YIRiq0HTUc1s5lD0luXLQEP+g+XUwZfzFRZgt1nWBlPmpbj2Ylj1FfrA7EXsIK9nyo+rf0qRn/4HusJATr9ddYmZdxwazl1FXkOKLHPyu1NlzwoTNSQQgMHlzxzUvrrv7+mI2nQvXRx82TSRytqrMvoBTF1NFX+pRjhNg9fcq0oPJ2ORqOVQsxzhLhB+tw7Cg+UHGWlnKnkqaKH1JDmOFyJDB96aPUnSQT2J8qkyb+hMBXz9mme8rZopkHrA4WyDXv3zpEi0P5Sj0DDwdRxKMdDdZ4hw79YQIrd63cIorN8XG6Icevb25LfekLEq/C2FS8+kADagyOM0uzCw2p/qacNz37ZNGqPK6gYkjnyoAfSm14zbgoLX/5dnf7eCuMatevTm4AcE53RawQfzz0YNJuEv5uqD/WUy+UIKHIwxPYY9FWBBPmH+8eaPC1mMPh54I444b39FwpnPU8GwxEPsjRg8TSnohawNmmhEWEpmlawEKw+C+BE6A2DmVJzyeBvVRwe/W6CPgyYxgSGWUuvfZFm1GrzwZDjCOEMRn7qMwMBxh1nr2BOAiNxA38UtsymaZO5ZOknClWlKIkIFl8NJdVITNNsI48KMuSY20o1puzkxMaAUH3OrGEhtoHrEOeIq+KCFzH2gZo6L5hbv9CHM7QgCYsbtVIMwL+cRZZaSNubS3K48OmWJnHNuqkcrSI4lqfjLhz1DbnQ==,iv:/cNMmlpq9LSOk0MwVq8NaWvp47q68lKWTx4s5nkwF5c=,tag:ZNX+yZsSxdhFsavDpX380g==,type:str]
|
||||
relay_creds: ENC[AES256_GCM,data:o0FIKyqYHo1mndY+TC6TopipDlZMoyePPPRF62+WVegWjnz+dG83WTzIduJ6qdzlkBH0tgYfau7aIzYaDWZAd935efxvwTMl8lot0xTa8SqAYxQKDkTcpUhaHtu9wlpaqv31vzPdGUJbI17e9ZPdMEPRNaEYQkYqP2YoagO17WRbzIOax+XTP08pyVJChDG++aYlkuScOXQyM830hDy2xCYA9OHN4BeyU5mh6W0BiXLYIp9oOh0y1We59CUKeo0S,iv:JHgLeQO6XE5VYsoPU4YrI+LIaWSETvfnnwjrlTc1n0g=,tag:cWafuECJy2Gv5BMGKG1NOw==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1hkve3khk7fthyrwxjqdf4r37lrqpmnkz6mke7psuphvu2ykynqaq9g6ja5
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvNDFQQ3lMbGtBVjdBR0t2
|
||||
MjJvcmpjQmtYR1VkSVYzTzJFZDZibmFKc1dNCkZpWUsvcEM2MnA2OWdOdXVsZzJi
|
||||
VjFDOVNjdkVIZDgwWE5pQmpKWkxSb3MKLS0tIDlSbXZFY1R0dkl3NHdvSTlWYTZ6
|
||||
bDV6UGVHd2RVKzVycHJUWllTMk1HU2MKkDag+K62PydC3jcvLaIxy0vOuANbA65P
|
||||
hzaTNzv8iotafjFDYLWim7PLnxv+IeywKoL+Pnn4o3+e0617omx1mA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnbWUrNTN0Y2lzSjR1ckc1
|
||||
cW03WXZFVzBSUzdpUzVLMWJzRjhqaWRFODFBClJGSno0QUpQaGpVSzJ0Y3h5eXFj
|
||||
aGpoNGIycG80NkxhWEFGeU9IMk1tWFEKLS0tIDI3Q3lHNGI1VWJBcFZDRDBqNGpD
|
||||
RDFNajdSSWQ1ZWNNcXl0T3lLcm1YUWMKm7w5OXFeuk7Sby68ODrk9EC8SbvCTxoO
|
||||
oQueOepqeeh4wip3SQpHACvtUp4s85M6ZXE96uYioRlzy3zg39tIpQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1rz75dqzfd6gulwh270ukmt5amcau6j8dpxgzx8fm6u8sjkyx9usq69y4s2
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsMUVLVWpHaksvZkJIb0U4
|
||||
RnVTZ0k0L0VlMjFNNFg4RVZjTmk1OHEwbGpnCkIxTXN5aWMwTlZEWERYRXV5dHEx
|
||||
UVFVVEczRFhWRDJPN3g0QVh2NXlZUjAKLS0tIGNRbkk3R1RYVCs2Y2x4UmZhTXdx
|
||||
UVUrQStXTU9yUWJ0SnlIbDBIRUdSb00K9oPKVn1RzK0DVtaeXnfURea9k1lNzpor
|
||||
3ex6hSyrfzNazFlInCuptIFIpf5o1eeiiV2PL85w9wvpMh4MEG7peg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age13x0f3glnz4jvqty2v92cxrrnjcna6ed4qegrhulw9jjy08zuy3aqzvrfc6
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1MHUxcU9tR3JKSjk5TGRm
|
||||
c2I3S0lrV1RJZHFkN1JyNHlqc2hXbGtPVlVzCk9pMmVRdC92bld6SW0rNFVyRmJs
|
||||
QmVOMXRrb3FvVUNUYnVuczg5MklEL1kKLS0tIEE2YkRmeWFONVpDTk02S3kwSWNI
|
||||
Ty9PdGYxUnRNSUIxN21RWWJUQnVqWjAKp1KybOk5/5xHHggBwE7zyuOw17GwxPCw
|
||||
UR2R5wuc0d1Uyb/z/QvRI4lbpjAhjb749JgLE2IYTYLfPsJv59K8BA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age13j6l33g0ghk4vezn0qwfal2qmcgqwkv89ejwezpe3n47mw8yxyuslj6y7d
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2c2cyOWh3bEtBMUF6a3hx
|
||||
UjVIYkN5cE1ZcWNZM1V3Y3lhR05JYUt4Q3djCk9XNWF1dnhveVlLNWxJSVcxcVRK
|
||||
V2d2aWx5ZXdrYUw0TFN3VGVZTE5RTTAKLS0tIDNnWm5nbDZUbmh3QTBCWXp6aUE0
|
||||
ZFhoeXRTOEhDT2NpOXM2L3NCdVNEQmMKBp4e23mcqrJdlcqbf6mUjitYq7MxkeoX
|
||||
jX8LQTucw9dhLu/SCxymRxg9/Q2+PfhUvDR2L51tdlbr77dRhic3/A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1vla9w33lsp03s46p9p6gc2mvr844vthdqhc2hzau2ph6h60gmyqqh9sf57
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoeWltSkV6aGJ1WkJOVTBp
|
||||
Q24wMEFuWlVQYXMrKzRrSHN2THB3TWtYQ0VvCldHUmlpUGdNTlp4QkluZjRzK0J3
|
||||
U0ZGYWM2eFZyZHhuT2dWSnBJdzA0dmMKLS0tIHg0citENmY1QkpXNURzY2x4QkZM
|
||||
bG9DUTFkd2t3YXFXVElKK3JsK216Rm8KGvXixYViOUwrVarBMZeUI5HlCBtoL5bp
|
||||
7uZ9JFKQMh9EtiUk+Pr2xr4r9Mah0Gk3AmmVKWvaQaC/bkEIhe30Eg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1jy8mxcndkw6zd6q99tjgz3gsynn78x2lwtrff85u6ud9g9y9z5mspvhufl
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnYmhVb0FsdUc5RjdPWnA5
|
||||
ZmpaMi9Rek5WM1AvSVl3Nk1maG1YanJaS0RzCjM3VEJKM3dVclZxK2FSMENKTUUz
|
||||
d0dleUU2Rk5namdUdFl4ZjNSM05xdnMKLS0tIHRzYldRM0I4MytMcGFMUnZ3QXA0
|
||||
MGtKcDMyejNFNktCL2I4RUI3Qkk1TWMKsxjqBw5J91f3T9TDHNAKFI2cTT4i7zJw
|
||||
N33KbrskOaOXjCsoENnqdRl9Y7v/JbOh5YQ2/oPwZEfuwgHG9lcXqw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age148huz6rc3q9xx5t873ncx75sja2sazlescwspxl7lsmxsqkz0apsy8cldp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWdWRCdnNybjdzSFpacjNj
|
||||
eFNJNjBzYmpsRkw4czN2aWJzSnBDeFYweDM4CmZCcnZCTEJQTGtoSlo3VW45T0ZJ
|
||||
bmpUMHhFMy9mSUxaTWVCcFBnQlAramsKLS0tIGV3eHcxRlJZc3BxQUU3TUhsRVAr
|
||||
VXdheGpVRFF2UFBKQTF0OFMrVzdYcjQKaEs1irVwO0OoXbBhYd1AgCCPPF3sFH3a
|
||||
go3jAHOCnwkYQMVRd24FGZx28XuEgeXQALk7JqEEy5eCS6nKDEVqcg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age197a33mlf5294amjx59hycctu6wm4l3cu3w7n9rv3fs9340ql64rqjzpr7s
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHcWZxa3NHR0Z4TmlNNHVU
|
||||
aFNvN2tycVd2THhFMGtMckhGOXBuZXNMSkFFCm1VR1ZwUHdabFdBWmUxUXVxTVR5
|
||||
eFVvakFDZUV2WHByU2pRU3hrWXVaMGcKLS0tIHRjbElYOU8xaW1lVFlrL0YwMDlQ
|
||||
MEwvd1RQd1hlNVNZL3VveUkydVNjVE0KFsyjr38WdXu4R0038Dum0VeVw+LNcI6q
|
||||
4R0ft0KsfLLmPgoNIdK5Dq5hUxyGVe8Ej/9KaN0UrqIRsLHCHimYyQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1sqj8z3feqm2dk3gj8mxpfn5dpqnsmus862e8ayd0d4cdresqffdswcf9ru
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4QW9yVk9zN2RrZkpTWXZU
|
||||
U080M1pDdzV1bDFSR2UrY0o2dnoyYlpNZXc0CmJCSE84L1ZRdUVZc21GbWc3cG9t
|
||||
NHRGQUFVS3U1TjFVYWl1Q1FyODY3UjgKLS0tIGhrY1dMa251R1hCc0F5eDhtWnc2
|
||||
bXpqNkVobzgwMHJIdHBFZ0xDZ2RzcmcK0m4awMUrdwYvXO14L1hvhcaGgLOW3FCq
|
||||
UU1Vc/vX32Lsu1BN4aXlTZ1jHD6R6CnV5TbUTcM/jxFRKoRzDwdJig==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-04-16T00:39:52Z"
|
||||
mac: ENC[AES256_GCM,data:5rVkhMPb+gpB1fCCvRbillDO4MXl6TbKQar+hjRqy6bYjFejZgaAtAObbGL0n05/1XKpc3ULUXq7kQEOyjic6qhLx+o6biwkJFEjoF+0CePtTS9zRHXYDK1hnpgqMzVlVUH6KHipDJL9DAnDoJks3wc7gQaj4WjoGSlydDIcFPA=,iv:4JD9s2zkZjMoWRut9aawQjRhPo3q4FZrzoSTB6qyWgY=,tag:ZLzlb9TSP1agyPbWtP/mkA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.10.1
|
||||
age:
|
||||
- recipient: age1hkve3khk7fthyrwxjqdf4r37lrqpmnkz6mke7psuphvu2ykynqaq9g6ja5
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvNDFQQ3lMbGtBVjdBR0t2
|
||||
MjJvcmpjQmtYR1VkSVYzTzJFZDZibmFKc1dNCkZpWUsvcEM2MnA2OWdOdXVsZzJi
|
||||
VjFDOVNjdkVIZDgwWE5pQmpKWkxSb3MKLS0tIDlSbXZFY1R0dkl3NHdvSTlWYTZ6
|
||||
bDV6UGVHd2RVKzVycHJUWllTMk1HU2MKkDag+K62PydC3jcvLaIxy0vOuANbA65P
|
||||
hzaTNzv8iotafjFDYLWim7PLnxv+IeywKoL+Pnn4o3+e0617omx1mA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnbWUrNTN0Y2lzSjR1ckc1
|
||||
cW03WXZFVzBSUzdpUzVLMWJzRjhqaWRFODFBClJGSno0QUpQaGpVSzJ0Y3h5eXFj
|
||||
aGpoNGIycG80NkxhWEFGeU9IMk1tWFEKLS0tIDI3Q3lHNGI1VWJBcFZDRDBqNGpD
|
||||
RDFNajdSSWQ1ZWNNcXl0T3lLcm1YUWMKm7w5OXFeuk7Sby68ODrk9EC8SbvCTxoO
|
||||
oQueOepqeeh4wip3SQpHACvtUp4s85M6ZXE96uYioRlzy3zg39tIpQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1rz75dqzfd6gulwh270ukmt5amcau6j8dpxgzx8fm6u8sjkyx9usq69y4s2
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsMUVLVWpHaksvZkJIb0U4
|
||||
RnVTZ0k0L0VlMjFNNFg4RVZjTmk1OHEwbGpnCkIxTXN5aWMwTlZEWERYRXV5dHEx
|
||||
UVFVVEczRFhWRDJPN3g0QVh2NXlZUjAKLS0tIGNRbkk3R1RYVCs2Y2x4UmZhTXdx
|
||||
UVUrQStXTU9yUWJ0SnlIbDBIRUdSb00K9oPKVn1RzK0DVtaeXnfURea9k1lNzpor
|
||||
3ex6hSyrfzNazFlInCuptIFIpf5o1eeiiV2PL85w9wvpMh4MEG7peg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age13x0f3glnz4jvqty2v92cxrrnjcna6ed4qegrhulw9jjy08zuy3aqzvrfc6
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA1MHUxcU9tR3JKSjk5TGRm
|
||||
c2I3S0lrV1RJZHFkN1JyNHlqc2hXbGtPVlVzCk9pMmVRdC92bld6SW0rNFVyRmJs
|
||||
QmVOMXRrb3FvVUNUYnVuczg5MklEL1kKLS0tIEE2YkRmeWFONVpDTk02S3kwSWNI
|
||||
Ty9PdGYxUnRNSUIxN21RWWJUQnVqWjAKp1KybOk5/5xHHggBwE7zyuOw17GwxPCw
|
||||
UR2R5wuc0d1Uyb/z/QvRI4lbpjAhjb749JgLE2IYTYLfPsJv59K8BA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age13j6l33g0ghk4vezn0qwfal2qmcgqwkv89ejwezpe3n47mw8yxyuslj6y7d
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2c2cyOWh3bEtBMUF6a3hx
|
||||
UjVIYkN5cE1ZcWNZM1V3Y3lhR05JYUt4Q3djCk9XNWF1dnhveVlLNWxJSVcxcVRK
|
||||
V2d2aWx5ZXdrYUw0TFN3VGVZTE5RTTAKLS0tIDNnWm5nbDZUbmh3QTBCWXp6aUE0
|
||||
ZFhoeXRTOEhDT2NpOXM2L3NCdVNEQmMKBp4e23mcqrJdlcqbf6mUjitYq7MxkeoX
|
||||
jX8LQTucw9dhLu/SCxymRxg9/Q2+PfhUvDR2L51tdlbr77dRhic3/A==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1vla9w33lsp03s46p9p6gc2mvr844vthdqhc2hzau2ph6h60gmyqqh9sf57
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoeWltSkV6aGJ1WkJOVTBp
|
||||
Q24wMEFuWlVQYXMrKzRrSHN2THB3TWtYQ0VvCldHUmlpUGdNTlp4QkluZjRzK0J3
|
||||
U0ZGYWM2eFZyZHhuT2dWSnBJdzA0dmMKLS0tIHg0citENmY1QkpXNURzY2x4QkZM
|
||||
bG9DUTFkd2t3YXFXVElKK3JsK216Rm8KGvXixYViOUwrVarBMZeUI5HlCBtoL5bp
|
||||
7uZ9JFKQMh9EtiUk+Pr2xr4r9Mah0Gk3AmmVKWvaQaC/bkEIhe30Eg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1jy8mxcndkw6zd6q99tjgz3gsynn78x2lwtrff85u6ud9g9y9z5mspvhufl
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnYmhVb0FsdUc5RjdPWnA5
|
||||
ZmpaMi9Rek5WM1AvSVl3Nk1maG1YanJaS0RzCjM3VEJKM3dVclZxK2FSMENKTUUz
|
||||
d0dleUU2Rk5namdUdFl4ZjNSM05xdnMKLS0tIHRzYldRM0I4MytMcGFMUnZ3QXA0
|
||||
MGtKcDMyejNFNktCL2I4RUI3Qkk1TWMKsxjqBw5J91f3T9TDHNAKFI2cTT4i7zJw
|
||||
N33KbrskOaOXjCsoENnqdRl9Y7v/JbOh5YQ2/oPwZEfuwgHG9lcXqw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age148huz6rc3q9xx5t873ncx75sja2sazlescwspxl7lsmxsqkz0apsy8cldp
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWdWRCdnNybjdzSFpacjNj
|
||||
eFNJNjBzYmpsRkw4czN2aWJzSnBDeFYweDM4CmZCcnZCTEJQTGtoSlo3VW45T0ZJ
|
||||
bmpUMHhFMy9mSUxaTWVCcFBnQlAramsKLS0tIGV3eHcxRlJZc3BxQUU3TUhsRVAr
|
||||
VXdheGpVRFF2UFBKQTF0OFMrVzdYcjQKaEs1irVwO0OoXbBhYd1AgCCPPF3sFH3a
|
||||
go3jAHOCnwkYQMVRd24FGZx28XuEgeXQALk7JqEEy5eCS6nKDEVqcg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age197a33mlf5294amjx59hycctu6wm4l3cu3w7n9rv3fs9340ql64rqjzpr7s
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHcWZxa3NHR0Z4TmlNNHVU
|
||||
aFNvN2tycVd2THhFMGtMckhGOXBuZXNMSkFFCm1VR1ZwUHdabFdBWmUxUXVxTVR5
|
||||
eFVvakFDZUV2WHByU2pRU3hrWXVaMGcKLS0tIHRjbElYOU8xaW1lVFlrL0YwMDlQ
|
||||
MEwvd1RQd1hlNVNZL3VveUkydVNjVE0KFsyjr38WdXu4R0038Dum0VeVw+LNcI6q
|
||||
4R0ft0KsfLLmPgoNIdK5Dq5hUxyGVe8Ej/9KaN0UrqIRsLHCHimYyQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
- recipient: age1sqj8z3feqm2dk3gj8mxpfn5dpqnsmus862e8ayd0d4cdresqffdswcf9ru
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4QW9yVk9zN2RrZkpTWXZU
|
||||
U080M1pDdzV1bDFSR2UrY0o2dnoyYlpNZXc0CmJCSE84L1ZRdUVZc21GbWc3cG9t
|
||||
NHRGQUFVS3U1TjFVYWl1Q1FyODY3UjgKLS0tIGhrY1dMa251R1hCc0F5eDhtWnc2
|
||||
bXpqNkVobzgwMHJIdHBFZ0xDZ2RzcmcK0m4awMUrdwYvXO14L1hvhcaGgLOW3FCq
|
||||
UU1Vc/vX32Lsu1BN4aXlTZ1jHD6R6CnV5TbUTcM/jxFRKoRzDwdJig==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-04-16T00:39:52Z"
|
||||
mac: ENC[AES256_GCM,data:5rVkhMPb+gpB1fCCvRbillDO4MXl6TbKQar+hjRqy6bYjFejZgaAtAObbGL0n05/1XKpc3ULUXq7kQEOyjic6qhLx+o6biwkJFEjoF+0CePtTS9zRHXYDK1hnpgqMzVlVUH6KHipDJL9DAnDoJks3wc7gQaj4WjoGSlydDIcFPA=,iv:4JD9s2zkZjMoWRut9aawQjRhPo3q4FZrzoSTB6qyWgY=,tag:ZLzlb9TSP1agyPbWtP/mkA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.10.1
|
||||
|
@@ -71,31 +71,34 @@ let
|
||||
mkdir -p $out/liam
|
||||
SOPS_AGE_KEY="${testAgeSecret}" ${pkgs.sops}/bin/sops --verbose -e --age "$(echo "${testAgeSecret}" | ${pkgs.age}/bin/age-keygen -y)" ${sopsTestSecretsYaml} --output-type yaml > $out/liam/main.yaml
|
||||
'';
|
||||
mailtestModule = {
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
libraries = with pkgs.python3Packages; [
|
||||
imap-tools
|
||||
requests
|
||||
];
|
||||
mkPkg = name: pkgs.writers.writePython3Bin "mailtest-${name}" { inherit libraries; } ''
|
||||
# flake8: noqa
|
||||
${builtins.readFile ./mailtest/${name}.py}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.vacu.mailtest = lib.mkOption { readOnly = true; };
|
||||
config.vacu.mailtest = {
|
||||
smtp = mkPkg "smtp";
|
||||
imap = mkPkg "imap";
|
||||
mailpit = mkPkg "mailpit";
|
||||
mailtestModule =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
libraries = with pkgs.python3Packages; [
|
||||
imap-tools
|
||||
requests
|
||||
];
|
||||
mkPkg =
|
||||
name:
|
||||
pkgs.writers.writePython3Bin "mailtest-${name}" { inherit libraries; } ''
|
||||
# flake8: noqa
|
||||
${builtins.readFile ./mailtest/${name}.py}
|
||||
'';
|
||||
in
|
||||
{
|
||||
options.vacu.mailtest = lib.mkOption { readOnly = true; };
|
||||
config.vacu.mailtest = {
|
||||
smtp = mkPkg "smtp";
|
||||
imap = mkPkg "imap";
|
||||
mailpit = mkPkg "mailpit";
|
||||
};
|
||||
config.environment.systemPackages = builtins.attrValues config.vacu.mailtest;
|
||||
};
|
||||
config.environment.systemPackages = builtins.attrValues config.vacu.mailtest;
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "liam-receives-mail";
|
||||
@@ -168,7 +171,12 @@ in
|
||||
};
|
||||
|
||||
nodes.liam =
|
||||
{ lib, inputs, config, ... }:
|
||||
{
|
||||
lib,
|
||||
inputs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
"${inputs.self}/common"
|
||||
@@ -209,8 +217,10 @@ in
|
||||
security.pki.certificateFiles = [ rootCA.certificatePath ];
|
||||
|
||||
vacu.liam.backup.keyPath = pkgs.writeText "test-borg-key" testBorgKey;
|
||||
vacu.ssh.knownHosts."rsync.net".enable = lib.mkForce false; #remove known key so i can do a trust-on-first-use in the test
|
||||
networking.hosts."${nodes.rsyncnet.networking.primaryIPAddress}" = [ config.vacu.liam.backup.rsyncHost ];
|
||||
vacu.ssh.knownHosts."rsync.net".enable = lib.mkForce false; # remove known key so i can do a trust-on-first-use in the test
|
||||
networking.hosts."${nodes.rsyncnet.networking.primaryIPAddress}" = [
|
||||
config.vacu.liam.backup.rsyncHost
|
||||
];
|
||||
};
|
||||
|
||||
nodes.rsyncnet =
|
||||
@@ -218,7 +228,7 @@ in
|
||||
let
|
||||
borgCfg = nodes.liam.vacu.liam.backup;
|
||||
user = borgCfg.rsyncUser;
|
||||
loginCommand = pkgs.writers.writeBashBin "special-rsync-login" {} ''
|
||||
loginCommand = pkgs.writers.writeBashBin "special-rsync-login" { } ''
|
||||
set -euo pipefail
|
||||
if [ -n "$SSH_ORIGINAL_COMMAND" ]; then
|
||||
echo "hi there"
|
||||
@@ -255,7 +265,7 @@ in
|
||||
};
|
||||
environment.systemPackages = [
|
||||
pkgs.borgbackup
|
||||
(pkgs.writers.writeBashBin "borg-init" {} ''
|
||||
(pkgs.writers.writeBashBin "borg-init" { } ''
|
||||
set -euo pipefail
|
||||
export BORG_PASSPHRASE=${lib.escapeShellArg testBorgKey}
|
||||
export BORG_NEW_PASSPHRASE=${lib.escapeShellArg testBorgKey}
|
||||
@@ -268,27 +278,26 @@ in
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
imports = [ mailtestModule ];
|
||||
environment.systemPackages = [
|
||||
pkgs.wget
|
||||
];
|
||||
environment.systemPackages = [ pkgs.wget ];
|
||||
networking.nameservers = lib.mkForce (lib.singleton nodes.ns.networking.primaryIPAddress);
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
rawFile = builtins.readFile ./testScript/main.py;
|
||||
data = {
|
||||
checkSieve = lib.getExe nodes.liam.vacu.checkSieve;
|
||||
acmeTest = pkgs.writeText "acme-test" "test";
|
||||
acmeTestDest = nodes.liam.security.acme.defaults.webroot + "/.well-known/acme-challenge/test";
|
||||
relayIP = nodes.relay.networking.primaryIPAddress;
|
||||
liamIP = nodes.liam.networking.primaryIPAddress;
|
||||
inherit testBorgKey;
|
||||
borgExe = lib.getExe pkgs.borgbackup;
|
||||
};
|
||||
dataJson = builtins.toJSON data;
|
||||
res = builtins.replaceStrings [ "@data@" ] [ dataJson ] rawFile;
|
||||
in res;
|
||||
let
|
||||
rawFile = builtins.readFile ./testScript/main.py;
|
||||
data = {
|
||||
checkSieve = lib.getExe nodes.liam.vacu.checkSieve;
|
||||
acmeTest = pkgs.writeText "acme-test" "test";
|
||||
acmeTestDest = nodes.liam.security.acme.defaults.webroot + "/.well-known/acme-challenge/test";
|
||||
relayIP = nodes.relay.networking.primaryIPAddress;
|
||||
liamIP = nodes.liam.networking.primaryIPAddress;
|
||||
inherit testBorgKey;
|
||||
borgExe = lib.getExe pkgs.borgbackup;
|
||||
};
|
||||
dataJson = builtins.toJSON data;
|
||||
res = builtins.replaceStrings [ "@data@" ] [ dataJson ] rawFile;
|
||||
in
|
||||
res;
|
||||
|
||||
skipTypeCheck = true;
|
||||
skipLint = true;
|
||||
|
@@ -6,18 +6,22 @@ import ssl
|
||||
import json
|
||||
from typing import NamedTuple
|
||||
|
||||
|
||||
def info(msg: str):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
|
||||
def mk_ctx():
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
return ctx
|
||||
|
||||
|
||||
def print_json(**kwargs):
|
||||
print(json.dumps(kwargs))
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--host", type=str)
|
||||
parser.add_argument("--insecure", default=False, action="store_true")
|
||||
@@ -45,6 +49,7 @@ info(f"looking for {msg_magic}")
|
||||
result: bool
|
||||
matching_messages = []
|
||||
try:
|
||||
|
||||
def connection() -> imap_tools.BaseMailBox:
|
||||
return imap_tools.MailBox(args.host, ssl_context=mk_ctx()).login(
|
||||
username, password
|
||||
@@ -87,7 +92,7 @@ try:
|
||||
assert uid is not None
|
||||
info(f"about to move {uid} to {args.move_to}")
|
||||
res = mailbox.move(uid, args.move_to)
|
||||
assert res[1][1][1] is not None, "failed to move" # type: ignore
|
||||
assert res[1][1][1] is not None, "failed to move" # type: ignore
|
||||
info(f"done moving, res {res!r}")
|
||||
|
||||
with connection() as mailbox:
|
||||
@@ -99,6 +104,7 @@ except imaplib.IMAP4.error as e:
|
||||
else:
|
||||
result = True
|
||||
|
||||
|
||||
def mail_to_jsonish(m: MessageInFolder) -> dict:
|
||||
return {
|
||||
"folder": m.folder,
|
||||
@@ -106,7 +112,8 @@ def mail_to_jsonish(m: MessageInFolder) -> dict:
|
||||
"body": m.message.text.strip(),
|
||||
}
|
||||
|
||||
|
||||
print_json(
|
||||
result = result,
|
||||
messages = [mail_to_jsonish(m) for m in matching_messages],
|
||||
result=result,
|
||||
messages=[mail_to_jsonish(m) for m in matching_messages],
|
||||
)
|
||||
|
@@ -3,9 +3,11 @@ import requests
|
||||
import sys
|
||||
import json
|
||||
|
||||
|
||||
def info(msg: str):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
|
||||
def print_json(**kwargs):
|
||||
print(json.dumps(kwargs))
|
||||
|
||||
@@ -37,4 +39,4 @@ for message_data in mails["messages"]:
|
||||
found_message = True
|
||||
break
|
||||
|
||||
print_json(found_message = found_message)
|
||||
print_json(found_message=found_message)
|
||||
|
@@ -4,18 +4,22 @@ import sys
|
||||
import ssl
|
||||
import json
|
||||
|
||||
|
||||
def info(msg: str):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
|
||||
def mk_ctx():
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
return ctx
|
||||
|
||||
|
||||
def print_json(**kwargs):
|
||||
print(json.dumps(kwargs))
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--host", type=str)
|
||||
parser.add_argument("--mailfrom", default="foo@example.com")
|
||||
@@ -64,4 +68,4 @@ except smtplib.SMTPSenderRefused:
|
||||
else:
|
||||
result = True
|
||||
|
||||
print_json(result = result)
|
||||
print_json(result=result)
|
||||
|
@@ -2,14 +2,17 @@ import sys
|
||||
import ssl
|
||||
import json
|
||||
|
||||
|
||||
def info(msg: str):
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
|
||||
def mk_ctx():
|
||||
ctx = ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = ssl.CERT_NONE
|
||||
return ctx
|
||||
|
||||
|
||||
def print_json(**kwargs):
|
||||
print(json.dumps(kwargs))
|
||||
|
@@ -6,7 +6,7 @@ DATA_JSON = """
|
||||
"""
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from hints import * # type: ignore
|
||||
from hints import * # type: ignore
|
||||
|
||||
import json
|
||||
import shlex
|
||||
@@ -32,7 +32,7 @@ liam.wait_for_unit("dovecot2.service")
|
||||
relay.wait_for_unit("mailpit.service")
|
||||
|
||||
# generate and exchange keys so they can talk to eachother
|
||||
rsyncnet.wait_for_open_port(22);
|
||||
rsyncnet.wait_for_open_port(22)
|
||||
# liam.succeed("install -d --owner=autoborger --group=autoborger --mode=0770 /var/lib/auto-borg")
|
||||
# # not succeed, it will fail because not authorized but that's okay
|
||||
# liam.execute("sudo -u autoborger ssh -oBatchMode=yes -oStrictHostKeyChecking=accept-new fm2382.rsync.net")
|
||||
@@ -40,7 +40,9 @@ liam.succeed("systemctl start auto-borg-gen-key.service")
|
||||
# liam.wait_for_unit("auto-borg-gen-key.service")
|
||||
liam_autoborger_key = liam.succeed("cat /var/lib/auto-borg/id_ed25519.pub").strip()
|
||||
rsyncnet.succeed("install -d --owner=fm2382 --mode=0700 /home/fm2382/.ssh")
|
||||
rsyncnet.succeed(f"install --owner=fm2382 --mode=0600 -T <(echo 'command=\"borg serve --restrict-to-repository /home/fm2382/borg-repos/liam-backup --append-only\",restrict {liam_autoborger_key}') /home/fm2382/.ssh/authorized_keys")
|
||||
rsyncnet.succeed(
|
||||
f"install --owner=fm2382 --mode=0600 -T <(echo 'command=\"borg serve --restrict-to-repository /home/fm2382/borg-repos/liam-backup --append-only\",restrict {liam_autoborger_key}') /home/fm2382/.ssh/authorized_keys"
|
||||
)
|
||||
rsyncnet.succeed("sudo -u fm2382 borg-init")
|
||||
liam.succeed("systemctl start auto-borg.service")
|
||||
# liam.wait_for_unit("auto-borg.service")
|
||||
@@ -51,21 +53,25 @@ class ImapMessage(TypedDict):
|
||||
flags: list[str]
|
||||
body: str
|
||||
|
||||
|
||||
class ImapResult(TypedDict):
|
||||
result: bool
|
||||
messages: list[ImapMessage]
|
||||
|
||||
|
||||
def make_command(args: list) -> str:
|
||||
return " ".join(map(shlex.quote, (map(str, args))))
|
||||
|
||||
Arg = str|bool|int
|
||||
|
||||
Arg = str | bool | int
|
||||
|
||||
Args = dict[str, Arg]
|
||||
|
||||
|
||||
def dict_args_to_list(dict_args: Args) -> list[str]:
|
||||
args:list[str] = []
|
||||
args: list[str] = []
|
||||
for k, v in dict_args.items():
|
||||
dashed = k.replace("_","-")
|
||||
dashed = k.replace("_", "-")
|
||||
if isinstance(v, int) and not isinstance(v, bool):
|
||||
v = str(v)
|
||||
if isinstance(v, str) or (isinstance(v, bool) and v):
|
||||
@@ -74,15 +80,17 @@ def dict_args_to_list(dict_args: Args) -> list[str]:
|
||||
args.append(v)
|
||||
return args
|
||||
|
||||
|
||||
class LogEntry(TypedDict):
|
||||
__CURSOR: str
|
||||
_SYSTEMD_UNIT: str
|
||||
MESSAGE: str
|
||||
pass
|
||||
|
||||
|
||||
DEFAULT_JOURNALCTL_OPTS: Args = {
|
||||
"all": True,
|
||||
"output": "json",
|
||||
"all": True,
|
||||
"output": "json",
|
||||
}
|
||||
|
||||
# --json
|
||||
@@ -94,22 +102,27 @@ DEFAULT_JOURNALCTL_OPTS: Args = {
|
||||
#
|
||||
# 3. Fields containing non-printable or non-UTF8 bytes are encoded as arrays containing the raw bytes individually formatted as unsigned numbers.
|
||||
|
||||
def journalctl_log_entries(machine: Machine = liam, **kwargs: Arg) -> Generator[LogEntry, None, None]:
|
||||
|
||||
def journalctl_log_entries(
|
||||
machine: Machine = liam, **kwargs: Arg
|
||||
) -> Generator[LogEntry, None, None]:
|
||||
with_defaults = {**kwargs, **DEFAULT_JOURNALCTL_OPTS}
|
||||
args = ["journalctl", *dict_args_to_list(with_defaults)]
|
||||
res = machine.succeed(make_command(args))
|
||||
for line in res.splitlines():
|
||||
data:LogEntry = json.loads(line)
|
||||
data: LogEntry = json.loads(line)
|
||||
assert isinstance(data, dict)
|
||||
for _, v in data.items():
|
||||
assert isinstance(v, str)
|
||||
yield data
|
||||
|
||||
|
||||
class ProcessingWaiter(contextlib.AbstractContextManager):
|
||||
cursor: str = ""
|
||||
timeout: int = 60
|
||||
_postfix_smtpd_connections: set[str] = set()
|
||||
_postfix_queue: set[str] = set()
|
||||
|
||||
def __init__(self, timeout=60):
|
||||
most_recent_entry = list(journalctl_log_entries(lines=1))[0]
|
||||
self.cursor = most_recent_entry["__CURSOR"]
|
||||
@@ -128,7 +141,9 @@ class ProcessingWaiter(contextlib.AbstractContextManager):
|
||||
assert sl_pid is not None
|
||||
if message.startswith("connect from"):
|
||||
self._postfix_smtpd_connections.add(sl_pid)
|
||||
if message.startswith("disconnect from") or message.startswith("lost connection"):
|
||||
if message.startswith("disconnect from") or message.startswith(
|
||||
"lost connection"
|
||||
):
|
||||
self._postfix_smtpd_connections.discard(sl_pid)
|
||||
if unit == "postfix.service" and sl_ident == "postfix/qmgr":
|
||||
queue_id = message.split(":")[0]
|
||||
@@ -136,7 +151,10 @@ class ProcessingWaiter(contextlib.AbstractContextManager):
|
||||
self._postfix_queue.add(queue_id)
|
||||
if message.endswith("removed"):
|
||||
self._postfix_queue.discard(queue_id)
|
||||
if len(self._postfix_smtpd_connections) == 0 and len(self._postfix_queue) == 0:
|
||||
if (
|
||||
len(self._postfix_smtpd_connections) == 0
|
||||
and len(self._postfix_queue) == 0
|
||||
):
|
||||
return
|
||||
else:
|
||||
liam.sleep(1)
|
||||
@@ -144,32 +162,28 @@ class ProcessingWaiter(contextlib.AbstractContextManager):
|
||||
def __exit__(self, _a, _b, _c):
|
||||
self.wait_until_finished()
|
||||
|
||||
class TesterThing():
|
||||
|
||||
class TesterThing:
|
||||
uuid: str = ""
|
||||
default_smtp: Args = {}
|
||||
default_imap: Args = {}
|
||||
default_mailpit: Args = {}
|
||||
|
||||
def __init__(self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: Arg):
|
||||
def __init__(
|
||||
self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: Arg
|
||||
):
|
||||
self.uuid = str(uuid.uuid4())
|
||||
self.default_smtp = {
|
||||
"rcptto": "someone@example.com",
|
||||
"host": f"{liam_ip}",
|
||||
**common,
|
||||
**smtp
|
||||
}
|
||||
self.default_imap = {
|
||||
"host": f"{liam_ip}",
|
||||
**common,
|
||||
**imap
|
||||
}
|
||||
self.default_mailpit = {
|
||||
"mailpit-url": f"http://{relay_ip}:8025",
|
||||
**mailpit
|
||||
**smtp,
|
||||
}
|
||||
self.default_imap = {"host": f"{liam_ip}", **common, **imap}
|
||||
self.default_mailpit = {"mailpit-url": f"http://{relay_ip}:8025", **mailpit}
|
||||
|
||||
def run_expecting_json(self, name: str, **kwargs: Arg) -> dict[str, Any]:
|
||||
args:list[str] = [name, *dict_args_to_list(kwargs)]
|
||||
args: list[str] = [name, *dict_args_to_list(kwargs)]
|
||||
print(f"running {args!r}")
|
||||
with ProcessingWaiter():
|
||||
res = checker.succeed(make_command(args))
|
||||
@@ -195,35 +209,37 @@ class TesterThing():
|
||||
def run_imap(self, **kwargs: Arg) -> ImapResult:
|
||||
args = {"message_magic": self.uuid, **self.default_imap, **kwargs}
|
||||
res_unty = self.run_expecting_json("mailtest-imap", **args)
|
||||
res_ty: ImapResult = res_unty # type: ignore
|
||||
res_ty: ImapResult = res_unty # type: ignore
|
||||
return res_ty
|
||||
|
||||
def imap_expect(self, mailbox: str|None = None, flags: list[str] = [], **kwargs: Arg) -> Self:
|
||||
def imap_expect(
|
||||
self, mailbox: str | None = None, flags: list[str] = [], **kwargs: Arg
|
||||
) -> Self:
|
||||
res = self.run_imap(**kwargs)
|
||||
assert res['result']
|
||||
assert len(res['messages']) == 1
|
||||
message = res['messages'][0]
|
||||
assert res["result"]
|
||||
assert len(res["messages"]) == 1
|
||||
message = res["messages"][0]
|
||||
if mailbox is not None:
|
||||
assert message['folder'] == mailbox
|
||||
assert message["folder"] == mailbox
|
||||
for flag in flags:
|
||||
assert flag in message['flags']
|
||||
assert flag in message["flags"]
|
||||
return self
|
||||
|
||||
def imap_found(self, **kwargs: Arg) -> Self:
|
||||
return self.imap_expect(mailbox = None, flags = [], **kwargs)
|
||||
return self.imap_expect(mailbox=None, flags=[], **kwargs)
|
||||
|
||||
def imap_found_in(self, mailbox: str, **kwargs: Arg) -> Self:
|
||||
return self.imap_expect(mailbox = mailbox, flags = [], **kwargs)
|
||||
return self.imap_expect(mailbox=mailbox, flags=[], **kwargs)
|
||||
|
||||
def imap_move_to(self, dest: str, **kwargs: Arg) -> Self:
|
||||
res = self.run_imap(move_to=dest, **kwargs)
|
||||
assert res['result']
|
||||
assert res["result"]
|
||||
return self
|
||||
|
||||
def run_mailpit(self, **kwargs: Arg) -> bool:
|
||||
args = {"message_magic": self.uuid, **self.default_mailpit, **kwargs}
|
||||
res = self.run_expecting_json("mailtest-mailpit", **args)
|
||||
return res['found_message']
|
||||
return res["found_message"]
|
||||
|
||||
def mailpit_not_received(self, **kwargs: Arg) -> Self:
|
||||
received = self.run_mailpit(**kwargs)
|
||||
@@ -235,57 +251,78 @@ class TesterThing():
|
||||
assert received
|
||||
return self
|
||||
|
||||
class Defaults():
|
||||
|
||||
class Defaults:
|
||||
default_smtp: Args = {}
|
||||
default_imap: Args = {}
|
||||
default_mailpit: Args = {}
|
||||
|
||||
def __init__(self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: str|bool):
|
||||
self.default_smtp = {
|
||||
**common,
|
||||
**smtp
|
||||
}
|
||||
self.default_imap = {
|
||||
**common,
|
||||
**imap
|
||||
}
|
||||
self.default_mailpit = {
|
||||
**mailpit
|
||||
}
|
||||
def __init__(
|
||||
self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: str | bool
|
||||
):
|
||||
self.default_smtp = {**common, **smtp}
|
||||
self.default_imap = {**common, **imap}
|
||||
self.default_mailpit = {**mailpit}
|
||||
|
||||
def make_tester(self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: str|bool) -> TesterThing:
|
||||
def make_tester(
|
||||
self, smtp: Args = {}, imap: Args = {}, mailpit: Args = {}, **common: str | bool
|
||||
) -> TesterThing:
|
||||
return TesterThing(
|
||||
smtp = {**self.default_smtp, **common, **smtp},
|
||||
imap = {**self.default_imap, **common, **imap},
|
||||
mailpit = {**self.default_mailpit, **common, **mailpit},
|
||||
smtp={**self.default_smtp, **common, **smtp},
|
||||
imap={**self.default_imap, **common, **imap},
|
||||
mailpit={**self.default_mailpit, **common, **mailpit},
|
||||
)
|
||||
|
||||
# The order of these shouldn't matter, other than what fails first. Whatever is at the top is probably whatever I was working on most recently.
|
||||
d = Defaults(smtp = {"submission": True, "rcptto": "someone@example.com"}, username = "vacustore")
|
||||
d.make_tester(smtp = {"mailfrom": "robot@vacu.store"}).smtp_accepted().mailpit_received()
|
||||
d.make_tester(smtp = {"mailfrom": "foobar@vacu.store"}).smtp_rejected()
|
||||
d.make_tester(smtp = {"mailfrom": "abc@shelvacu.com"}).smtp_rejected()
|
||||
|
||||
d = Defaults(smtp = {"mailfrom": "whoeve2@example.com", "rcptto": "sieve2est@shelvacu.com"}, username = "shelvacu")
|
||||
# The order of these shouldn't matter, other than what fails first. Whatever is at the top is probably whatever I was working on most recently.
|
||||
d = Defaults(
|
||||
smtp={"submission": True, "rcptto": "someone@example.com"}, username="vacustore"
|
||||
)
|
||||
d.make_tester(smtp={"mailfrom": "robot@vacu.store"}).smtp_accepted().mailpit_received()
|
||||
d.make_tester(smtp={"mailfrom": "foobar@vacu.store"}).smtp_rejected()
|
||||
d.make_tester(smtp={"mailfrom": "abc@shelvacu.com"}).smtp_rejected()
|
||||
|
||||
d = Defaults(
|
||||
smtp={"mailfrom": "whoeve2@example.com", "rcptto": "sieve2est@shelvacu.com"},
|
||||
username="shelvacu",
|
||||
)
|
||||
# test refilter
|
||||
d.make_tester().smtp_accepted().imap_move_to("MagicRefilter").imap_found_in("com.shelvacu")
|
||||
d.make_tester().smtp_accepted().imap_move_to("MagicRefilter").imap_found_in(
|
||||
"com.shelvacu"
|
||||
)
|
||||
# refilter doesnt activate on other folders
|
||||
d.make_tester().smtp_accepted().imap_move_to("testFolder").imap_found_in("testFolder")
|
||||
d.make_tester().smtp_accepted().imap_move_to("INBOX").imap_found_in("INBOX")
|
||||
# test the sieve script is working
|
||||
d.make_tester().smtp_accepted().imap_found_in("com.shelvacu")
|
||||
# refilter doesnt activate on julie's
|
||||
d.make_tester(username="julie").smtp_accepted(rcptto="julie@shelvacu.com").imap_move_to("MagicRefilter").imap_found_in("MagicRefilter")
|
||||
d.make_tester(username="julie").smtp_accepted(rcptto="julie@shelvacu.com").imap_move_to(
|
||||
"MagicRefilter"
|
||||
).imap_found_in("MagicRefilter")
|
||||
|
||||
d = Defaults(username = "shelvacu")
|
||||
d.make_tester().smtp_accepted(mailfrom="asshole-spammer@example.com", rcptto="whatever@shelvacu.com", header="List-unsubscribe: whatever").imap_expect(mailbox="com.shelvacu.#spamish", flags=["spamish"])
|
||||
d.make_tester().smtp_accepted(mailfrom="shipment-tracking@amazon.com", rcptto="amznbsns@shelvacu.com", subject="Your Amazon.com order has shipped (#123-1234)").imap_expect(mailbox="com.shelvacu", flags=["\\Seen","auto-marked-read","amazon-ignore"])
|
||||
d = Defaults(username="shelvacu")
|
||||
d.make_tester().smtp_accepted(
|
||||
mailfrom="asshole-spammer@example.com",
|
||||
rcptto="whatever@shelvacu.com",
|
||||
header="List-unsubscribe: whatever",
|
||||
).imap_expect(mailbox="com.shelvacu.#spamish", flags=["spamish"])
|
||||
d.make_tester().smtp_accepted(
|
||||
mailfrom="shipment-tracking@amazon.com",
|
||||
rcptto="amznbsns@shelvacu.com",
|
||||
subject="Your Amazon.com order has shipped (#123-1234)",
|
||||
).imap_expect(
|
||||
mailbox="com.shelvacu", flags=["\\Seen", "auto-marked-read", "amazon-ignore"]
|
||||
)
|
||||
|
||||
TesterThing().smtp_accepted(rcptto="shelvacu@shelvacu.com", username="shelvacu", smtp_starttls=True)
|
||||
TesterThing().smtp_accepted(
|
||||
rcptto="shelvacu@shelvacu.com", username="shelvacu", smtp_starttls=True
|
||||
)
|
||||
|
||||
d = Defaults(smtp = {"submission": True, "rcptto": "foo@example.com"}, username="shelvacu")
|
||||
d = Defaults(
|
||||
smtp={"submission": True, "rcptto": "foo@example.com"}, username="shelvacu"
|
||||
)
|
||||
d.make_tester().smtp_accepted(mailfrom="me@shelvacu.com").mailpit_received()
|
||||
d.make_tester().smtp_accepted(mailfrom="me@dis8.net" ).mailpit_not_received()
|
||||
d.make_tester().smtp_accepted(mailfrom="me@dis8.net").mailpit_not_received()
|
||||
|
||||
# julie's emails should NOT get sieve'd like mine
|
||||
d = Defaults(username="julie")
|
||||
@@ -302,7 +339,7 @@ d.make_tester().smtp_accepted(rcptto="julie@shelvacu.com").imap_found()
|
||||
d.make_tester().smtp_accepted(rcptto="sales@theviolincase.com").imap_found()
|
||||
d.make_tester().smtp_accepted(rcptto="superwow@theviolincase.com").imap_found()
|
||||
|
||||
#incoming mail cant be from known domains
|
||||
# incoming mail cant be from known domains
|
||||
TesterThing().smtp_rejected(mailfrom="bob@vacu.store")
|
||||
TesterThing().smtp_rejected(mailfrom="shelvacu@shelvacu.com")
|
||||
TesterThing().smtp_rejected(mailfrom="julie@shelvacu.com")
|
||||
@@ -310,19 +347,27 @@ TesterThing().smtp_rejected(mailfrom="@vacu.store")
|
||||
|
||||
TesterThing().smtp_rejected(mailfrom="reject-spam-test@example.com")
|
||||
|
||||
#people cant send as the wrong person
|
||||
d = Defaults(smtp = {"submission": True})
|
||||
# people cant send as the wrong person
|
||||
d = Defaults(smtp={"submission": True})
|
||||
d.make_tester().smtp_rejected(mailfrom="julie@shelvacu.com", username="shelvacu")
|
||||
d.make_tester().smtp_rejected(mailfrom="fubar@theviolincase.com", username="shelvacu")
|
||||
d.make_tester().smtp_rejected(mailfrom="fubar@vacu.store", username="julie")
|
||||
|
||||
d = Defaults(smtp = {"submission": True, "rcptto": "foo@example.com"})
|
||||
d = Defaults(smtp={"submission": True, "rcptto": "foo@example.com"})
|
||||
d.make_tester().smtp_accepted(mailfrom="shelvacu@shelvacu.com", username="shelvacu")
|
||||
d.make_tester().smtp_accepted(mailfrom="shelvacu@shelvacu.com", username="shelvacu@shelvacu.com", password="shelvacu")
|
||||
d.make_tester().smtp_accepted(
|
||||
mailfrom="shelvacu@shelvacu.com",
|
||||
username="shelvacu@shelvacu.com",
|
||||
password="shelvacu",
|
||||
)
|
||||
d.make_tester().smtp_accepted(mailfrom="foo@vacu.store", username="shelvacu")
|
||||
d.make_tester().smtp_accepted(mailfrom="foo@vacu.store", username="shelvacu@shelvacu.com", password="shelvacu")
|
||||
d.make_tester().smtp_accepted(
|
||||
mailfrom="foo@vacu.store", username="shelvacu@shelvacu.com", password="shelvacu"
|
||||
)
|
||||
d.make_tester().smtp_accepted(mailfrom="foo@violingifts.com", username="julie")
|
||||
d.make_tester().smtp_accepted(mailfrom="foo@violingifts.com", username="julie@shelvacu.com", password="julie")
|
||||
d.make_tester().smtp_accepted(
|
||||
mailfrom="foo@violingifts.com", username="julie@shelvacu.com", password="julie"
|
||||
)
|
||||
|
||||
# now that there's a bunch of mail and logs and stuff, we can still run a borg backup, right?
|
||||
liam.succeed("systemctl start auto-borg.service")
|
||||
|
@@ -1,6 +1,4 @@
|
||||
{
|
||||
...
|
||||
}:
|
||||
{ ... }:
|
||||
{
|
||||
# systemd.services.dovecot-backup-sftp-server = {
|
||||
# enable = true;
|
||||
|
@@ -22,7 +22,12 @@ in
|
||||
restartIfChanged = true;
|
||||
|
||||
config =
|
||||
{ lib, config, pkgs, ... }:
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
secrets_folder = "/var/lib/vaultwarden/secrets";
|
||||
services = [ "vaultwarden.service" ];
|
||||
|
@@ -9,9 +9,9 @@
|
||||
let
|
||||
config = self.checks.x86_64-linux.${name}.config;
|
||||
|
||||
vlans = map (m: (
|
||||
m.virtualisation.vlans ++
|
||||
(lib.mapAttrsToList (_: v: v.vlan) m.virtualisation.interfaces))) (lib.attrValues config.nodes);
|
||||
vlans = map (
|
||||
m: (m.virtualisation.vlans ++ (lib.mapAttrsToList (_: v: v.vlan) m.virtualisation.interfaces))
|
||||
) (lib.attrValues config.nodes);
|
||||
|
||||
nodeHostNames =
|
||||
let
|
||||
@@ -19,13 +19,14 @@ let
|
||||
in
|
||||
nodesList ++ lib.optional (lib.length nodesList == 1 && !lib.elem "machine" nodesList) "machine";
|
||||
|
||||
pythonizeName = name:
|
||||
pythonizeName =
|
||||
name:
|
||||
let
|
||||
head = lib.substring 0 1 name;
|
||||
tail = lib.substring 1 (-1) name;
|
||||
in
|
||||
(if builtins.match "[A-z_]" head == null then "_" else head) +
|
||||
lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
|
||||
(if builtins.match "[A-z_]" head == null then "_" else head)
|
||||
+ lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
|
||||
|
||||
uniqueVlans = lib.unique (builtins.concatLists vlans);
|
||||
vlanNames = map (i: "vlan${toString i}: VLan;") uniqueVlans;
|
||||
|
Reference in New Issue
Block a user