WIP: feat/automated-account-deletion #174

Draft
b12f wants to merge 34 commits from feat/automated-account-deletion into main
54 changed files with 6056 additions and 232 deletions

View file

@ -18,7 +18,7 @@ jobs:
# Prevent cache garbage collection by creating GC roots
mkdir -p /var/lib/gitea-runner/tankstelle/.local/state/nix/results
sed -i 's/virtualisation.cores .*/virtualisation.cores = 16;/' tests/keycloak.nix
sed -i 's/virtualisation.memorySize .*/virtualisation.memorySize = 16384;/' tests/keycloak.nix
sed -i 's/virtualisation.cores .*/virtualisation.cores = 16;/' tests/**/*.nix
sed -i 's/virtualisation.memorySize .*/virtualisation.memorySize = 16384;/' tests/**/*.nix
# 1 eval-worker needs about 13GB of memory
nix --accept-flake-config --access-tokens '' develop --command nix-fast-build --no-nom --skip-cached --systems "x86_64-linux" --max-jobs 10 --eval-workers 2 --out-link /var/lib/gitea-runner/tankstelle/.local/state/nix/results/nix-fast-build

2
.gitignore vendored
View file

@ -5,3 +5,5 @@
*.plan
result
results
.nixos-test-history
/*.png

View file

@ -0,0 +1,14 @@
# Automated account deletion
Per GDPR legislation, accounts should be automatically deleted after a period of inactivity. We discern between two different types of accounts:
1. Without verified email: should be deleted after 30 days without being activated
2. With verified email: should be deleted after 2 years of inactivity
Some services hold on to a session for a very long time. We'll have to query their APIs to see if the account is still in use:
- Matrix via the admin api: https://matrix-org.github.io/synapse/v1.48/admin_api/user_admin_api.html#query-current-sessions-for-a-user
- Mastodon via the admin api: https://docs.joinmastodon.org/methods/admin/accounts/#200-ok
- Nextcloud only gives the last login, not the last active time like a sync via `nextcloud-occ user:lastseen`
- Keycloak
- We can ignore Forgejo, since the sessions there are valid for a maximum of one year, regardless of how they got created

164
flake.lock generated
View file

@ -68,6 +68,25 @@
"devshell": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1713532798,
"narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=",
"owner": "numtide",
"repo": "devshell",
"rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"devshell_2": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": [
"keycloak-theme-pub-solar",
"nixpkgs"
@ -94,11 +113,11 @@
]
},
"locked": {
"lastModified": 1738148035,
"narHash": "sha256-KYOATYEwaKysL3HdHdS5kbQMXvzS4iPJzJrML+3TKAo=",
"lastModified": 1738765162,
"narHash": "sha256-3Z40qHaFScWUCVQrGc4Y+RdoPsh1R/wIh+AN4cTXP0I=",
"owner": "nix-community",
"repo": "disko",
"rev": "18d0a984cc2bc82cf61df19523a34ad463aa7f54",
"rev": "ff3568858c54bd306e9e1f2886f0f781df307dff",
"type": "github"
},
"original": {
@ -198,6 +217,24 @@
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_2"
},
"locked": {
"lastModified": 1712014858,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_3"
@ -220,6 +257,24 @@
"inputs": {
"systems": "systems_4"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_5"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
@ -271,10 +326,33 @@
"type": "github"
}
},
"keycloak-theme-pub-solar": {
"keycloak-event-listener": {
"inputs": {
"devshell": "devshell",
"flake-utils": "flake-utils_2",
"flake-parts": "flake-parts_2",
"nixpkgs": [
"unstable"
]
},
"locked": {
"lastModified": 1738364013,
"narHash": "sha256-GAg9RaSThTW8+nL/rTsb12i4EHWl5uBqtq8Sp2jEoVg=",
"ref": "main",
"rev": "1b6c4dda9361bcc108a283e2c38867983474da17",
"revCount": 8,
"type": "git",
"url": "https://git.pub.solar/pub-solar/keycloak-event-listener"
},
"original": {
"ref": "main",
"type": "git",
"url": "https://git.pub.solar/pub-solar/keycloak-event-listener"
}
},
"keycloak-theme-pub-solar": {
"inputs": {
"devshell": "devshell_2",
"flake-utils": "flake-utils_3",
"nixpkgs": [
"nixpkgs"
]
@ -320,11 +398,11 @@
]
},
"locked": {
"lastModified": 1738277753,
"narHash": "sha256-iyFcCOk0mmDiv4ut9mBEuMxMZIym3++0qN1rQBg8FW0=",
"lastModified": 1739034224,
"narHash": "sha256-Mj/8jDzh1KNmUhWqEeVlW3hO9MZkxqioJGnmR7rivaE=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "49b807fa7c37568d7fbe2aeaafb9255c185412f9",
"rev": "0b6f96a6b9efcfa8d3cc8023008bcbcd1b9bc1a4",
"type": "github"
},
"original": {
@ -336,16 +414,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1738574474,
"narHash": "sha256-rvyfF49e/k6vkrRTV4ILrWd92W+nmBDfRYZgctOyolQ=",
"owner": "nixos",
"lastModified": 1704161960,
"narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fecfeb86328381268e29e998ddd3ebc70bbd7f7c",
"rev": "63143ac2c9186be6d9da6035fa22620018c85932",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.11",
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
@ -362,6 +440,40 @@
"url": "https://github.com/NixOS/nixpkgs/archive/072a6db25e947df2f31aab9eccd0ab75d5b2da11.tar.gz"
}
},
"nixpkgs-lib_2": {
"locked": {
"dir": "lib",
"lastModified": 1711703276,
"narHash": "sha256-iMUFArF0WCatKK6RzfUJknjem0H9m4KgorO/p3Dopkk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d8fe5e6c92d0d190646fb9f1056741a229980089",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1738843498,
"narHash": "sha256-7x+Q4xgFj9UxZZO9aUDCR8h4vyYut4zPUvfj3i+jBHE=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "f5a32fa27df91dfc4b762671a0e0a859a8a0058f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
@ -372,10 +484,11 @@
"flake-parts": "flake-parts",
"fork": "fork",
"home-manager": "home-manager",
"keycloak-event-listener": "keycloak-event-listener",
"keycloak-theme-pub-solar": "keycloak-theme-pub-solar",
"maunium-stickerpicker": "maunium-stickerpicker",
"nix-darwin": "nix-darwin",
"nixpkgs": "nixpkgs",
"nixpkgs": "nixpkgs_2",
"simple-nixos-mailserver": "simple-nixos-mailserver",
"unstable": "unstable"
}
@ -466,13 +579,28 @@
"type": "github"
}
},
"systems_5": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"unstable": {
"locked": {
"lastModified": 1738546358,
"narHash": "sha256-nLivjIygCiqLp5QcL7l56Tca/elVqM9FG1hGd9ZSsrg=",
"lastModified": 1739020877,
"narHash": "sha256-mIvECo/NNdJJ/bXjNqIh8yeoSjVLAuDuTUzAo7dzs8Y=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "c6e957d81b96751a3d5967a0fd73694f303cc914",
"rev": "a79cfe0ebd24952b580b1cf08cd906354996d547",
"type": "github"
},
"original": {

View file

@ -27,6 +27,9 @@
keycloak-theme-pub-solar.url = "git+https://git.pub.solar/pub-solar/keycloak-theme?ref=main";
keycloak-theme-pub-solar.inputs.nixpkgs.follows = "nixpkgs";
keycloak-event-listener.url = "git+https://git.pub.solar/pub-solar/keycloak-event-listener?ref=main";
keycloak-event-listener.inputs.nixpkgs.follows = "unstable";
element-themes.url = "github:aaronraimist/element-themes/master";
element-themes.flake = false;
@ -58,7 +61,7 @@
];
perSystem =
{
args@{
system,
pkgs,
config,
@ -133,6 +136,11 @@
terraform-backend-git
terraform-ls
jq
# For the tests puppeteer-socket pkg
nodejs
nodePackages.typescript
nodePackages.typescript-language-server
];
};

View file

@ -22,7 +22,7 @@ in
"${wireguardIPv6}/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# trinkgenossin.pub.solar
publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";

View file

@ -32,10 +32,10 @@
modules = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
./nachtigall
self.nixosModules.overlays
self.nixosModules.unlock-zfs-on-boot
self.nixosModules.core
self.nixosModules.docker
self.nixosModules.backups
@ -78,10 +78,10 @@
modules = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
./metronom
self.nixosModules.overlays
self.nixosModules.unlock-zfs-on-boot
self.nixosModules.core
self.nixosModules.backups
self.nixosModules.mail
self.nixosModules.prometheus-exporters
@ -100,9 +100,9 @@
modules = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
./tankstelle
self.nixosModules.overlays
self.nixosModules.core
self.nixosModules.backups
self.nixosModules.prometheus-exporters
self.nixosModules.promtail
@ -118,11 +118,11 @@
modules = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
./trinkgenossin
self.nixosModules.backups
self.nixosModules.overlays
self.nixosModules.unlock-luks-on-boot
self.nixosModules.core
self.nixosModules.garage
self.nixosModules.nginx
@ -145,10 +145,10 @@
self.inputs.agenix.nixosModules.default
self.inputs.disko.nixosModules.disko
self.nixosModules.home-manager
self.nixosModules.core
./delite
self.nixosModules.overlays
self.nixosModules.unlock-luks-on-boot
self.nixosModules.core
self.nixosModules.prometheus-exporters
self.nixosModules.promtail
@ -167,10 +167,10 @@
self.inputs.agenix.nixosModules.default
self.inputs.disko.nixosModules.disko
self.nixosModules.home-manager
self.nixosModules.core
./blue-shell
self.nixosModules.overlays
self.nixosModules.unlock-luks-on-boot
self.nixosModules.core
self.nixosModules.prometheus-exporters
self.nixosModules.promtail
@ -188,10 +188,10 @@
modules = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
./underground
self.nixosModules.overlays
self.nixosModules.unlock-luks-on-boot
self.nixosModules.core
self.nixosModules.backups
self.nixosModules.keycloak

View file

@ -22,7 +22,7 @@ in
"${wireguardIPv6}/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# trinkgenossin.pub.solar
publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";

View file

@ -7,6 +7,7 @@
./networking.nix
./wireguard.nix
./email.nix
./backups.nix
];
}

46
hosts/metronom/email.nix Normal file
View file

@ -0,0 +1,46 @@
{ config, flake, ... }:
{
age.secrets.mail-hensoko.file = "${flake.self}/secrets/mail/hensoko.age";
age.secrets.mail-teutat3s.file = "${flake.self}/secrets/mail/teutat3s.age";
age.secrets.mail-admins.file = "${flake.self}/secrets/mail/admins.age";
age.secrets.mail-bot.file = "${flake.self}/secrets/mail/bot.age";
age.secrets.mail-crew.file = "${flake.self}/secrets/mail/crew.age";
age.secrets.mail-erpnext.file = "${flake.self}/secrets/mail/erpnext.age";
age.secrets.mail-hakkonaut.file = "${flake.self}/secrets/mail/hakkonaut.age";
mailserver = {
# A list of all login accounts. To create the password hashes, use
# nix-shell -p mkpasswd --run 'mkpasswd -R11 -m bcrypt'
loginAccounts = {
"admins@${config.pub-solar-os.networking.domain}" = {
hashedPasswordFile = config.age.secrets.mail-admins.path;
};
"hakkonaut@${config.pub-solar-os.networking.domain}" = {
hashedPasswordFile = config.age.secrets.mail-hakkonaut.path;
};
"hensoko@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-hensoko.path;
quota = "2G";
};
"teutat3s@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-teutat3s.path;
quota = "2G";
};
"bot@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-bot.path;
quota = "2G";
aliases = [ "hackernews-bot@pub.solar" ];
};
"crew@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-crew.path;
quota = "2G";
aliases = [ "moderation@pub.solar" ];
};
"erpnext@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-erpnext.path;
quota = "2G";
};
};
};
}

View file

@ -18,7 +18,7 @@
"fd00:fae:fae:fae:fae:3::/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# nachtigall.pub.solar
endpoint = "138.201.80.102:51820";

View file

@ -18,7 +18,7 @@
"fd00:fae:fae:fae:fae:1::/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# tankstelle.pub.solar
endpoint = "80.244.242.5:51820";

View file

@ -8,6 +8,5 @@
./networking.nix
./forgejo-actions-runner.nix
./wireguard.nix
#./backups.nix
];
}

View file

@ -1,6 +1,6 @@
{
lib,
config,
pkgs,
flake,
...
}:
@ -18,7 +18,7 @@
"fd00:fae:fae:fae:fae:4::/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# nachtigall.pub.solar
endpoint = "138.201.80.102:51820";

View file

@ -22,7 +22,7 @@ in
"${wireguardIPv6}/96"
];
privateKeyFile = config.age.secrets.wg-private-key.path;
peers = flake.self.logins.wireguardDevices ++ [
peers = (flake.self.lib.wireguardDevicesForUsers config.pub-solar-os.authentication.users) ++ [
{
# nachtigall.pub.solar
endpoint = "138.201.80.102:51820";

View file

@ -1,5 +1,4 @@
{
self,
lib,
inputs,
...
@ -19,6 +18,7 @@
## In configs, they can be used under "lib.our"
deploy = import ./deploy.nix { inherit inputs lib; };
wireguardDevicesForUsers = callLibs ./wireguardDevicesForUsers.nix;
};
};
}

View file

@ -0,0 +1,6 @@
{ lib }:
users:
lib.lists.foldl (
wireguardDevices: userConfig:
wireguardDevices ++ (if userConfig ? "wireguardDevices" then userConfig.wireguardDevices else [ ])
) [ ] (lib.attrsets.attrValues users)

View file

@ -7,15 +7,6 @@ in
flake = {
logins = {
admins = admins;
wireguardDevices = lib.lists.foldl (
wireguardDevices: adminConfig:
wireguardDevices ++ (if adminConfig ? "wireguardDevices" then adminConfig.wireguardDevices else [ ])
) [ ] (lib.attrsets.attrValues admins);
sshPubKeys = lib.lists.foldl (
sshPubKeys: adminConfig:
sshPubKeys
++ (if adminConfig ? "sshPubKeys" then lib.attrsets.attrValues adminConfig.sshPubKeys else [ ])
) [ ] (lib.attrsets.attrValues admins);
robots.sshPubKeys = lib.attrsets.attrValues robots;
};
};

View file

@ -7,10 +7,10 @@
}:
{
imports = [
./users.nix
./nix.nix
./networking.nix
./terminal-tooling.nix
./users.nix
];
options.pub-solar-os =

View file

@ -1,4 +1,9 @@
{ flake, lib, ... }:
{
flake,
lib,
config,
...
}:
{
home-manager.users = (
lib.attrsets.foldlAttrs (
@ -28,6 +33,6 @@
};
};
}
) { } flake.self.logins.admins
) { } config.pub-solar-os.authentication.users
);
}

View file

@ -11,6 +11,44 @@
inherit (lib) mkOption types;
in
{
users = mkOption {
description = "Administrative users to add";
type = types.attrsOf (
types.submodule {
options = {
sshPubKeys = mkOption {
type = types.attrsOf types.str;
default = { };
};
secretEncryptionKeys = mkOption {
type = types.attrsOf types.str;
default = { };
};
wireguardDevices = mkOption {
type = types.listOf (
types.submodule {
options = {
publicKey = mkOption { type = types.str; };
allowedIPs = mkOption { type = types.listOf types.str; };
};
}
);
default = { };
};
};
}
);
default = flake.self.logins.admins;
};
robot.sshPubKeys = mkOption {
description = "SSH Keys to use for the robot user";
type = types.listOf types.str;
default = flake.self.logins.robots.sshPubKeys;
};
root.initialHashedPassword = mkOption {
description = "Hashed password of the root account";
type = types.str;
@ -22,12 +60,6 @@
type = types.str;
default = "hakkonaut";
};
robot.sshPubKeys = mkOption {
description = "SSH Keys to use for the robot user";
type = types.listOf types.str;
default = flake.self.logins.robots.sshPubKeys;
};
};
config = {
@ -47,10 +79,8 @@
openssh.authorizedKeys.keys = lib.attrsets.attrValues value.sshPubKeys;
};
}
) { } flake.self.logins.admins)
) { } config.pub-solar-os.authentication.users)
// {
# TODO: Remove when we stop locking ourselves out.
root.openssh.authorizedKeys.keys = flake.self.logins.sshPubKeys;
root.initialHashedPassword = config.pub-solar-os.authentication.root.initialHashedPassword;
${config.pub-solar-os.authentication.robot.username} = {
@ -74,14 +104,14 @@
home.stateVersion = "23.05";
};
}
) { } flake.self.logins.admins
) { } config.pub-solar-os.authentication.users
);
users.groups =
(lib.attrsets.foldlAttrs (
acc: name: value:
acc // { "${name}" = { }; }
) { } flake.self.logins.admins)
) { } config.pub-solar-os.authentication.users)
// {
${config.pub-solar-os.authentication.robot.username} = { };
};

View file

@ -0,0 +1 @@
node_modules

View file

@ -0,0 +1,75 @@
#!/usr/bin/env zx
import { add, sub, isEqual, isAfter } from "date-fns";
const realm = argv.realm;
const clientId = argv.clientId;
const server = argv.server;
/*
* You'll have to set KC_CLI_CLIENT_SECRET
*/
let users = JSON.parse(await $`kcadm.sh get users -r ${realm} --server ${server} --client ${clientId} --no-config"`);
// Set a last-login value to today for any accounts that do not have one
const noLastLogin = users.filter(user => !user.attributes?.["last-login"]?.length);
const now = new Date();
const todayString = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${now.getDate()}`;
await Promise.all(noLastLogin.map((user) => {
const attributes = {
"last-login": [todayString],
...user.attributes,
};
$`kcadm.sh update users/${user.id} -s 'attributes=${JSON.stringify(attributes)}' -r ${realm} --server ${server} --client ${clientId} --no-config"`;
}));
users = JSON.parse(await $`kcadm.sh get users -r ${realm} --server ${server} --client ${clientId} --no-config"`);
// Handle non-validated users
const nonValidated = users.filter(user => !user.emailVerified);
await Promise.all(nonValidated.map((user) => {
const lastLogin = new Date(user.attributes?.["last-login"]);
const deletionDate = add(lastLogin, { months: 1 });
if (isEqual(now, sub(deletionDate, { weeks: 1 })) {
// send reminder
}
if (isEqual(now, sub(deletionDate, { days: 1 })) {
// send reminder
}
if (isAfter(now, deletionDate)) {
// delete
}
}).filter(n => !!n));
const validated = users.filter(user => user.emailVerified);
await Promise.all(validated.map((user) => {
const lastLogin = new Date(user.attributes?.["last-login"]);
const deletionDate = add(lastLogin, { years: 2 });
if (isEqual(now, sub(deletionDate, { months: 1 })) {
// Send reminder to validated accounts that have not logged in for 2 years - 1 month
}
if (isEqual(now, sub(deletionDate, { weeks: 1 })) {
// Send reminder to validated accounts that have not logged in for 2 years - 1 week
}
if (isEqual(now, sub(deletionDate, { days: 1 })) {
// Send reminder to validated accounts that have not logged in for 2 years - 1 day
}
if (isEqual(now, deletionDate)) {
// Delete validated that have not logged in for more than 2 years
}
}).filter(n => !!n));

View file

@ -0,0 +1,26 @@
{
"name": "auto-delete-accounts",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "auto-delete-accounts",
"version": "1.0.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"date-fns": "^4.1.0"
}
},
"node_modules/date-fns": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
}
}
}

View file

@ -0,0 +1,14 @@
{
"name": "auto-delete-accounts",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "AGPL-3.0-or-later",
"description": "",
"dependencies": {
"date-fns": "^4.1.0"
}
}

View file

@ -0,0 +1,10 @@
{
writeShellScriptBin,
keycloak,
jq,
}:
writeShellScriptBin "autodelete-accounts" ''
set -e
USERS=$(${keycloak}/bin/kcadm.sh get users -r test.pub.solar --server http://localhost:8080 --realm master --user admin --password password --no-config")
''

View file

@ -57,6 +57,7 @@
"pub.solar" =
flake.inputs.keycloak-theme-pub-solar.legacyPackages.${pkgs.system}.keycloak-theme-pub-solar;
};
plugins = [ flake.inputs.keycloak-event-listener.packages.${pkgs.system}.keycloak-event-listener ];
};
pub-solar-os.backups.restic.keycloak = {

View file

@ -1,62 +1,29 @@
{ config, flake, ... }:
{ config, ... }:
{
age.secrets.mail-hensoko.file = "${flake.self}/secrets/mail/hensoko.age";
age.secrets.mail-teutat3s.file = "${flake.self}/secrets/mail/teutat3s.age";
age.secrets.mail-admins.file = "${flake.self}/secrets/mail/admins.age";
age.secrets.mail-bot.file = "${flake.self}/secrets/mail/bot.age";
age.secrets.mail-crew.file = "${flake.self}/secrets/mail/crew.age";
age.secrets.mail-erpnext.file = "${flake.self}/secrets/mail/erpnext.age";
age.secrets.mail-hakkonaut.file = "${flake.self}/secrets/mail/hakkonaut.age";
mailserver = {
enable = true;
fqdn = "mail.pub.solar";
domains = [ "pub.solar" ];
fqdn = "mail.${config.pub-solar-os.networking.domain}";
domains = [ config.pub-solar-os.networking.domain ];
# A list of all login accounts. To create the password hashes, use
# nix-shell -p mkpasswd --run 'mkpasswd -R11 -m bcrypt'
loginAccounts = {
"hensoko@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-hensoko.path;
quota = "2G";
};
"teutat3s@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-teutat3s.path;
quota = "2G";
};
"admins@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-admins.path;
"admins@${config.pub-solar-os.networking.domain}" = {
quota = "2G";
aliases = [
"abuse@pub.solar"
"alerts@pub.solar"
"forgejo@pub.solar"
"keycloak@pub.solar"
"mastodon-notifications@pub.solar"
"matrix@pub.solar"
"postmaster@pub.solar"
"nextcloud@pub.solar"
"no-reply@pub.solar"
"security@pub.solar"
"abuse@${config.pub-solar-os.networking.domain}"
"alerts@${config.pub-solar-os.networking.domain}"
"forgejo@${config.pub-solar-os.networking.domain}"
"keycloak@${config.pub-solar-os.networking.domain}"
"mastodon-notifications@${config.pub-solar-os.networking.domain}"
"matrix@${config.pub-solar-os.networking.domain}"
"postmaster@${config.pub-solar-os.networking.domain}"
"nextcloud@${config.pub-solar-os.networking.domain}"
"no-reply@${config.pub-solar-os.networking.domain}"
"security@${config.pub-solar-os.networking.domain}"
];
};
"bot@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-bot.path;
quota = "2G";
aliases = [ "hackernews-bot@pub.solar" ];
};
"crew@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-crew.path;
quota = "2G";
aliases = [ "moderation@pub.solar" ];
};
"erpnext@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-erpnext.path;
quota = "2G";
};
"hakkonaut@pub.solar" = {
hashedPasswordFile = config.age.secrets.mail-hakkonaut.path;
"hakkonaut@${config.pub-solar-os.networking.domain}" = {
quota = "2G";
};
};
@ -66,7 +33,7 @@
certificateScheme = "acme-nginx";
};
security.acme.acceptTerms = true;
security.acme.defaults.email = "security@pub.solar";
security.acme.defaults.email = "security@${config.pub-solar-os.networking.domain}";
pub-solar-os.backups.restic.mail = {
paths = [

5
modules/test-vm.nix Normal file
View file

@ -0,0 +1,5 @@
{ ... }:
{
security.acme.defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory";
security.acme.preliminarySelfsigned = true;
}

View file

@ -1,4 +1,4 @@
{ flake, config, ... }:
{ lib, config, ... }:
{
boot.initrd.network = {
enable = true;
@ -10,7 +10,11 @@
# Please create this manually the first time.
hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
authorizedKeys = flake.self.logins.sshPubKeys;
authorizedKeys = lib.lists.foldl (
sshPubKeys: userConfig:
sshPubKeys
++ (if userConfig ? "sshPubKeys" then lib.attrsets.attrValues userConfig.sshPubKeys else [ ])
) [ ] (lib.attrsets.attrValues config.pub-solar-os.authentication.users);
};
postCommands = ''
# Automatically ask for the password on SSH login

View file

@ -1,4 +1,4 @@
{ flake, config, ... }:
{ lib, config, ... }:
{
# From https://nixos.wiki/wiki/ZFS#Unlock_encrypted_zfs_via_ssh_on_boot
boot.initrd.network = {
@ -11,7 +11,11 @@
# Please create this manually the first time.
hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
authorizedKeys = flake.self.logins.sshPubKeys;
authorizedKeys = lib.lists.foldl (
sshPubKeys: userConfig:
sshPubKeys
++ (if userConfig ? "sshPubKeys" then lib.attrsets.attrValues userConfig.sshPubKeys else [ ])
) [ ] (lib.attrsets.attrValues config.pub-solar-os.authentication.users);
};
# this will automatically load the zfs password prompt on login
# and kill the other prompt so boot can continue

26
tests/default.nix Normal file
View file

@ -0,0 +1,26 @@
args@{
self,
lib,
system,
pkgs,
inputs,
...
}:
let
nixos-lib = import (inputs.nixpkgs + "/nixos/lib") { };
loadTestFiles =
with lib;
dir:
mapAttrs' (
name: _:
let
test = ((import (dir + "/${name}")) args);
in
{
name = "test-" + (lib.strings.removeSuffix ".nix" name);
value = nixos-lib.runTest test;
}
) (filterAttrs (name: _: (hasSuffix ".nix" name) && name != "default.nix") (builtins.readDir dir));
in
loadTestFiles ./.

View file

@ -1,11 +1,16 @@
{
self,
system,
pkgs,
lib,
config,
...
}:
let
realm-export = pkgs.writeTextFile {
name = "realm-export.json";
text = builtins.readFile ./support/keycloak-realm-export/realm-export.json;
};
in
{
name = "keycloak";
@ -16,58 +21,17 @@ in
node.specialArgs = self.outputs.nixosConfigurations.nachtigall._module.specialArgs;
nodes = {
acme-server = {
imports = [
self.nixosModules.home-manager
self.nixosModules.core
./support/ca.nix
];
};
client = {
imports = [
self.nixosModules.home-manager
self.nixosModules.core
./support/client.nix
];
};
nachtigall = {
imports = [
self.inputs.agenix.nixosModules.default
self.nixosModules.home-manager
self.nixosModules.core
self.nixosModules.backups
self.nixosModules.nginx
self.nixosModules.keycloak
self.nixosModules.postgresql
./support/global.nix
];
systemd.tmpfiles.rules = [ "f /tmp/dbf 1777 root root 10d password" ];
virtualisation.cores = 1;
virtualisation.memorySize = 4096;
pub-solar-os.auth = {
enable = true;
database-password-file = "/tmp/dbf";
};
services.keycloak.database.createLocally = true;
networking.interfaces.eth0.ipv4.addresses = [
{
address = "192.168.1.3";
prefixLength = 32;
}
];
};
dns-server.imports = [ ./support/dns-server.nix ];
acme-server.imports = [ ./support/acme-server.nix ];
mail-server.imports = [ ./support/mail-server.nix ];
auth-server.imports = [ ./support/auth-server.nix ];
client.imports = [ ./support/client.nix ];
};
testScript =
{ nodes, ... }:
let
user = nodes.client.users.users.b12f;
user = nodes.client.users.users.test-user;
#uid = toString user.uid;
bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u ${user.name})/bus";
gdbus = "${bus} gdbus";
@ -76,20 +40,188 @@ in
wmClass = su "${gdbus} ${gseval} global.display.focus_window.wm_class";
in
''
import time
import re
import sys
def puppeteer_succeed(cmd):
return client.succeed(f'puppeteer-run \'{cmd}\' ')
def puppeteer_execute(cmd):
return client.execute(f'puppeteer-run \'{cmd}\' ')
def puppeteer_scroll_into_view(selector):
return puppeteer_succeed(f'(async () => {{ const el = await page.$(`{selector}`); console.log(el); return el.scrollIntoView(); }})()')
start_all()
nachtigall.wait_for_unit("system.slice")
nachtigall.succeed("ping 127.0.0.1 -c 2")
nachtigall.wait_for_unit("nginx.service")
nachtigall.wait_for_unit("keycloak.service")
nachtigall.wait_for_open_port(8080)
nachtigall.wait_for_open_port(443)
nachtigall.wait_until_succeeds("curl http://127.0.0.1:8080/")
nachtigall.wait_until_succeeds("curl https://auth.test.pub.solar/")
acme_server.wait_for_unit("system.slice")
auth_server.wait_for_unit("system.slice")
auth_server.succeed("ping 127.0.0.1 -c 2")
auth_server.wait_for_unit("nginx.service")
auth_server.wait_for_unit("keycloak.service")
auth_server.wait_until_succeeds("curl http://127.0.0.1:8080/")
auth_server.succeed("${pkgs.keycloak}/bin/kcadm.sh create realms -f ${realm-export} --server http://localhost:8080 --realm master --user admin --password password --no-config")
auth_server.wait_until_succeeds("curl https://auth.test.pub.solar/")
client.wait_for_file("/tmp/puppeteer.sock")
####### Registration #######
puppeteer_succeed('page.goto("https://auth.test.pub.solar")')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("initial")
puppeteer_succeed('page.locator("::-p-text(Sign in)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("sign-in")
puppeteer_succeed('page.locator("::-p-text(Register)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("register")
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
puppeteer_succeed('page.locator("[name=email]").fill("test-user@test.pub.solar")')
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
puppeteer_succeed('page.locator("[name=password-confirm]").fill("Password1234")')
client.screenshot("register-filled-in")
# Make sure the mail server is ready to send
mail_server.wait_for_unit("dovecot2.service")
mail_server.wait_for_unit("postfix.service")
mail_server.wait_until_succeeds("curl http://mail.test.pub.solar/")
puppeteer_succeed('page.locator("input[type=submit][value=Register]").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("before-email-confirm")
# Sometimes offlineimap errors out
# ERROR: [Errno 2] No such file or directory: '/home/test-user/.local/share/offlineimap'
client.succeed("${su "mkdir -p ~/.local/share/offlineimap"}")
client.succeed("${su "offlineimap"}")
client.succeed("${su "[ $(messages -s ~/Maildir/test-user@test.pub.solar/INBOX) -eq 1 ]"}")
puppeteer_succeed('page.locator("a::-p-text(Click here)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.succeed("${su "offlineimap"}")
client.succeed("${su "[ $(messages -s ~/Maildir/test-user@test.pub.solar/INBOX) -eq 2 ]"}")
mail_text = client.execute("${su "echo p | mail -Nf ~/Maildir/test-user@test.pub.solar/INBOX"}")[1]
boundary_match = re.search('boundary="(.*)"', mail_text, flags=re.M)
if not boundary_match:
sys.exit(1)
splits = mail_text.split(f'--{boundary_match.group(1)}')
clean_plaintext = splits[1].replace("=\n", "").replace("=3D", "=")
url_match = re.search('(https://auth.test.pub.solar.*)', clean_plaintext, flags=re.M)
print(url_match)
if not url_match:
sys.exit(1)
puppeteer_succeed(f'page.goto("{url_match.group(1)}")')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("registration-complete")
####### Logout #######
puppeteer_succeed('page.locator("[data-testid=options-toggle]").click()')
puppeteer_succeed('page.locator("::-p-text(Sign out)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("logged-out")
####### Login plain #######
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.locator("::-p-text(Restart login)").click()')
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("logged-in")
####### Add TOTP #######
puppeteer_succeed('page.locator("::-p-text(Account security)").click()')
puppeteer_succeed('page.locator("::-p-text(Signing in)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("signing-in-settings")
puppeteer_succeed('page.locator(`[data-testid="otp/create"]`).click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("TOTP-setup-qr")
puppeteer_succeed('page.locator("::-p-text(Unable to scan?)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("TOTP-setup-manual")
totp_secret_key = puppeteer_execute('(async () => { const el = await page.waitForSelector("#kc-totp-secret-key"); return el.evaluate(e => e.textContent); })()')[1]
totp = client.execute(f'oathtool --totp -b "{totp_secret_key}"')[1].replace("\n", "")
puppeteer_succeed(f'page.locator("[name=totp]").fill("{totp}")')
puppeteer_succeed('page.locator("[name=userLabel]").fill("My TOTP")')
client.screenshot("TOTP-form-filled")
puppeteer_succeed('page.locator("input[type=submit][value=Submit]").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("TOTP-added")
####### Login w/ TOTP #######
puppeteer_succeed('page.locator("[data-testid=options-toggle]").click()')
puppeteer_succeed('page.locator("::-p-text(Sign out)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("logged-out")
auth_server.wait_for_file('/tmp/continue', 3600)
auth_server.execute('rm /tmp/continue')
puppeteer_succeed('page.locator("[name=username]").fill("test-user")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.locator("[name=password]").fill("Password1234")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("TOTP-login-form")
print('Setting all system clocks 30 seconds ahead for next TOTP token')
client.execute("date --set='+30 seconds'");
auth_server.execute("date --set='+30 seconds'");
dns_server.execute("date --set='+30 seconds'");
acme_server.execute("date --set='+30 seconds'");
mail_server.execute("date --set='+30 seconds'");
totp = client.execute(f'oathtool --totp -b "{totp_secret_key}"')[1].replace("\n", "")
puppeteer_succeed(f'page.locator("[name=otp]").fill("{totp}")')
puppeteer_succeed('page.locator("::-p-text(Sign In)").click()')
puppeteer_succeed('page.waitForNetworkIdle()')
client.screenshot("TOTP-signed-in")
auth_server.wait_for_file('/tmp/continue', 600)
auth_server.execute('rm /tmp/continue')
####### Delete TOTP #######
puppeteer_scroll_into_view('[data-testid="otp/credential-list"]')
time.sleep(0.2)
client.screenshot("TOTP-before-delete")
# puppeteer_succeed('page.locator(`[data-testid="otp/credential-list"] button::-p-text(Delete)`).click()')
# client.screenshot("TOTP-deleted")
####### Automated account deletion #######
auth_server.succeed("${pkgs.keycloak}/bin/kcadm.sh get users -r test.pub.solar --server http://localhost:8080 --realm master --user admin --password password --no-config")
client.wait_for_unit("system.slice")
client.sleep(30)
# client.wait_until_succeeds("${wmClass} | grep -q 'firefox'")
client.screenshot("screen")
'';
}

View file

@ -1,21 +1,19 @@
{
flake,
pkgs,
lib,
config,
...
}:
{
imports = [ ./global.nix ];
imports = [
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
./global.nix
];
systemd.tmpfiles.rules = [ "f /tmp/step-ca-intermediate-pw 1777 root root 10d password" ];
networking.interfaces.eth0.ipv4.addresses = [
{
address = "192.168.1.1";
prefixLength = 32;
}
];
services.step-ca =
let
certificates = pkgs.stdenv.mkDerivation {

View file

@ -0,0 +1,38 @@
{
pkgs,
flake,
...
}:
let
ca-cert = pkgs.writeTextFile {
name = "ca-cert";
text = builtins.readFile ./step/certs/root_ca.crt;
};
in
{
imports = [
flake.self.inputs.agenix.nixosModules.default
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
flake.self.nixosModules.backups
flake.self.nixosModules.nginx
flake.self.nixosModules.keycloak
flake.self.nixosModules.postgresql
./global.nix
];
systemd.tmpfiles.rules = [
"f /tmp/dbf 1777 root root 10d password"
];
virtualisation.cores = 1;
virtualisation.memorySize = 4096;
pub-solar-os.auth = {
enable = true;
database-password-file = "/tmp/dbf";
};
services.keycloak.database.createLocally = true;
services.keycloak.initialAdminPassword = "password";
services.keycloak.settings.truststore-paths = "${ca-cert}";
}

View file

@ -1,35 +1,78 @@
{
flake,
pkgs,
lib,
config,
...
}:
let
puppeteer-socket = (pkgs.callPackage (import ./puppeteer-socket/puppeteer-socket.nix) { });
puppeteer-run = (pkgs.callPackage (import ./puppeteer-socket/puppeteer-run.nix) { });
in
{
imports = [ ./global.nix ];
imports = [
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
./global.nix
];
services.xserver.enable = true;
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
services.xserver.displayManager.autoLogin.enable = true;
services.xserver.displayManager.autoLogin.user = "b12f";
security.polkit.enable = true;
systemd.user.services = {
"org.gnome.Shell@wayland" = {
serviceConfig = {
ExecStart = [
# Clear the list before overriding it.
""
# Eval API is now internal so Shell needs to run in unsafe mode.
"${pkgs.gnome.gnome-shell}/bin/gnome-shell --unsafe-mode"
environment.systemPackages = [
puppeteer-run
pkgs.alacritty
pkgs.mailutils
pkgs.oath-toolkit
pkgs.firefox
];
services.getty.autologinUser = "test-user";
virtualisation.cores = 1;
virtualisation.memorySize = 4096;
virtualisation.qemu.options = [ "-vga std" ];
home-manager.users.test-user = {
programs.bash.profileExtra = ''
[ "$(tty)" = "/dev/tty1" ] && exec systemd-cat --identifier=sway ${pkgs.sway}/bin/sway
'';
wayland.windowManager.sway = {
enable = true;
systemd.enable = true;
extraSessionCommands = ''
export WLR_RENDERER=pixman
'';
config = {
modifier = "Mod4";
terminal = "${pkgs.alacritty}/bin/alacritty";
startup = [
{ command = "EXECUTABLE=${pkgs.firefox}/bin/firefox ${puppeteer-socket}/bin/puppeteer-socket"; }
];
};
};
};
networking.interfaces.eth0.ipv4.addresses = [
{
address = "192.168.1.2";
prefixLength = 32;
}
];
programs.offlineimap.enable = true;
accounts.email.accounts."test-user@${config.pub-solar-os.networking.domain}" = {
primary = true;
address = "test-user@${config.pub-solar-os.networking.domain}";
userName = "test-user@${config.pub-solar-os.networking.domain}";
passwordCommand = "echo password";
realName = "Test User";
imap = {
host = "mail.${config.pub-solar-os.networking.domain}";
port = 993;
};
smtp = {
host = "mail.${config.pub-solar-os.networking.domain}";
port = 587;
tls.useStartTls = true;
};
getmail.enable = true;
getmail.mailboxes = [ "ALL" ];
msmtp.enable = true;
offlineimap.enable = true;
};
};
}

View file

@ -0,0 +1,70 @@
{
config,
flake,
lib,
...
}:
{
imports = [
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
./global.nix
];
networking.nameservers = lib.mkForce [
"193.110.81.0" # dns0.eu
"2a0f:fc80::" # dns0.eu
"185.253.5.0" # dns0.eu
"2a0f:fc81::" # dns0.eu
];
services.resolved.enable = lib.mkForce false;
networking.firewall.allowedUDPPorts = [ 53 ];
networking.firewall.allowedTCPPorts = [ 53 ];
networking.interfaces.eth1.ipv4.addresses = [
{
address = "192.168.1.254";
prefixLength = 32;
}
];
services.unbound = {
enable = true;
settings = {
server = {
interface = [
"192.168.1.254"
];
access-control = [
"0.0.0.0/0 allow"
];
local-zone = [
"\"pub.solar\" transparent"
];
local-data = [
"\"mail.${config.pub-solar-os.networking.domain}. 10800 IN CNAME mail-server\""
"\"ca.${config.pub-solar-os.networking.domain}. 10800 IN CNAME acme-server\""
"\"www.${config.pub-solar-os.networking.domain}. 10800 IN CNAME auth-server\""
"\"auth.${config.pub-solar-os.networking.domain}. 10800 IN CNAME auth-server\""
];
tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt";
};
forward-zone = [
{
name = ".";
forward-addr = [
"193.110.81.0#dns0.eu"
"2a0f:fc80::#dns0.eu"
"185.253.5.0#dns0.eu"
"2a0f:fc81::#dns0.eu"
];
forward-tls-upstream = "yes";
}
];
};
};
}

View file

@ -5,6 +5,8 @@
...
}:
{
pub-solar-os.authentication.users.test-user = { };
pub-solar-os.networking.domain = "test.pub.solar";
security.acme.defaults.server = "https://ca.${config.pub-solar-os.networking.domain}/acme/acme/directory";
@ -23,28 +25,12 @@
security.pam.services.sshd.allowNullPassword = true;
virtualisation.forwardPorts =
let
address = (builtins.elemAt config.networking.interfaces.eth0.ipv4.addresses 0).address;
lastAddressPart = builtins.elemAt (lib.strings.splitString "." address) 3;
in
[
{
from = "host";
host.port = 2000 + (lib.strings.toInt lastAddressPart);
guest.port = 22;
}
];
services.resolved.extraConfig = lib.mkForce ''
DNS=192.168.1.254
Domains=~.
'';
networking.interfaces.eth0.useDHCP = false;
networking.hosts = {
"192.168.1.1" = [ "ca.${config.pub-solar-os.networking.domain}" ];
"192.168.1.2" = [ "client.${config.pub-solar-os.networking.domain}" ];
"192.168.1.3" = [
"${config.pub-solar-os.networking.domain}"
"www.${config.pub-solar-os.networking.domain}"
"auth.${config.pub-solar-os.networking.domain}"
environment.systemPackages = [
pkgs.dig
];
};
}

View file

@ -0,0 +1 @@
node_modules

View file

@ -0,0 +1 @@
*.nix

View file

@ -0,0 +1,5 @@
# Keycloak realm export anonymizer
1. Export realm settings from keycloak, you'll get a file called `realm-export.json`.
2. Install dependencies for this package: `npm ci`
3. Clean the exported file: `node src/index.mjs $downloadedExportJSON > realm-export.json

View file

@ -0,0 +1,942 @@
{
"name": "keycloak-realm-export",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keycloak-realm-export",
"version": "1.0.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"puppeteer-core": "^23.1.1",
"uuid": "^10.0.0"
},
"bin": {
"puppeteer-socket": "src/index.mjs"
}
},
"node_modules/@puppeteer/browsers": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz",
"integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==",
"dependencies": {
"debug": "^4.3.6",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.4.0",
"semver": "^7.6.3",
"tar-fs": "^3.0.6",
"unbzip2-stream": "^1.4.3",
"yargs": "^17.7.2"
},
"bin": {
"browsers": "lib/cjs/main-cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@tootallnate/quickjs-emscripten": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
},
"node_modules/@types/node": {
"version": "22.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz",
"integrity": "sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==",
"optional": true,
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/ast-types": {
"version": "0.13.4",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
"integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
"dependencies": {
"tslib": "^2.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/b4a": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz",
"integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg=="
},
"node_modules/bare-events": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz",
"integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==",
"optional": true
},
"node_modules/bare-fs": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz",
"integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==",
"optional": true,
"dependencies": {
"bare-events": "^2.0.0",
"bare-path": "^2.0.0",
"bare-stream": "^2.0.0"
}
},
"node_modules/bare-os": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz",
"integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==",
"optional": true
},
"node_modules/bare-path": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
"integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
"optional": true,
"dependencies": {
"bare-os": "^2.1.0"
}
},
"node_modules/bare-stream": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz",
"integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==",
"optional": true,
"dependencies": {
"streamx": "^2.18.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/basic-ftp": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
"integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"engines": {
"node": "*"
}
},
"node_modules/chromium-bidi": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz",
"integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==",
"dependencies": {
"mitt": "3.0.1",
"urlpattern-polyfill": "10.0.0",
"zod": "3.23.8"
},
"peerDependencies": {
"devtools-protocol": "*"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/data-uri-to-buffer": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
"engines": {
"node": ">= 14"
}
},
"node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/degenerator": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
"integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
"dependencies": {
"ast-types": "^0.13.4",
"escodegen": "^2.1.0",
"esprima": "^4.0.1"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/devtools-protocol": {
"version": "0.0.1312386",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
"integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"engines": {
"node": ">=6"
}
},
"node_modules/escodegen": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^5.2.0",
"esutils": "^2.0.2"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=6.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/fs-extra": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
"integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/get-uri": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
"integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
"dependencies": {
"basic-ftp": "^5.0.2",
"data-uri-to-buffer": "^6.0.2",
"debug": "^4.3.4",
"fs-extra": "^11.2.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
"integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
"engines": {
"node": ">=12"
}
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/pac-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
"integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
"dependencies": {
"@tootallnate/quickjs-emscripten": "^0.23.0",
"agent-base": "^7.0.2",
"debug": "^4.3.4",
"get-uri": "^6.0.1",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.5",
"pac-resolver": "^7.0.1",
"socks-proxy-agent": "^8.0.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/pac-resolver": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
"dependencies": {
"degenerator": "^5.0.0",
"netmask": "^2.0.2"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/proxy-agent": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
"integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "^4.3.4",
"http-proxy-agent": "^7.0.1",
"https-proxy-agent": "^7.0.3",
"lru-cache": "^7.14.1",
"pac-proxy-agent": "^7.0.1",
"proxy-from-env": "^1.1.0",
"socks-proxy-agent": "^8.0.2"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/puppeteer-core": {
"version": "23.1.1",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.1.tgz",
"integrity": "sha512-OeTqNiYGF9qZtwZU4Yc88DDqFJs4TJ4rnK81jkillh6MwDeQodyisM9xe5lBmPhwiDy92s5J5DQtQLjCKHFQ3g==",
"dependencies": {
"@puppeteer/browsers": "2.3.1",
"chromium-bidi": "0.6.4",
"debug": "^4.3.6",
"devtools-protocol": "0.0.1312386",
"typed-query-selector": "^2.12.0",
"ws": "^8.18.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/queue-tick": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
"integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks-proxy-agent": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
"integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
"dependencies": {
"agent-base": "^7.1.1",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
},
"node_modules/streamx": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.19.0.tgz",
"integrity": "sha512-5z6CNR4gtkPbwlxyEqoDGDmWIzoNJqCBt4Eac1ICP9YaIT08ct712cFj0u1rx4F8luAuL+3Qc+RFIdI4OX00kg==",
"dependencies": {
"fast-fifo": "^1.3.2",
"queue-tick": "^1.0.1",
"text-decoder": "^1.1.0"
},
"optionalDependencies": {
"bare-events": "^2.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/tar-fs": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
"integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
"dependencies": {
"pump": "^3.0.0",
"tar-stream": "^3.1.5"
},
"optionalDependencies": {
"bare-fs": "^2.1.1",
"bare-path": "^2.1.0"
}
},
"node_modules/tar-stream": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
"integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
"dependencies": {
"b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
},
"node_modules/text-decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz",
"integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==",
"dependencies": {
"b4a": "^1.6.4"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
},
"node_modules/typed-query-selector": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
"integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg=="
},
"node_modules/unbzip2-stream": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
"dependencies": {
"buffer": "^5.2.1",
"through": "^2.3.8"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"optional": true
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/urlpattern-polyfill": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
"integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg=="
},
"node_modules/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"node_modules/zod": {
"version": "3.23.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}

View file

@ -0,0 +1,18 @@
{
"name": "keycloak-realm-export",
"version": "1.0.0",
"main": "src/index.mjs",
"scripts": {
"start": "node src/index.mjs"
},
"bin": {
"puppeteer-socket": "src/index.mjs"
},
"author": "",
"license": "AGPL-3.0-or-later",
"description": "",
"dependencies": {
"puppeteer-core": "^23.1.1",
"uuid": "^10.0.0"
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,82 @@
#!/usr/bin/env node
import { readFile } from 'node:fs/promises';
import { v4 } from 'uuid';
const filePath = process.argv[2];
const newIds = {};
const ID_KEYS = [
'id',
'containerId',
'_id',
];
const renameDomain = (s) => s.replace(/pub.solar/g, 'test.pub.solar');
const cleanClients = (data) => ({
...data,
clients: data.clients.map(c => ({
...c,
authorizationSettings: undefined,
...(c.secret ? {
secret: 'secret',
attributes: {
...c.attributes,
"client.secret.creation.time": +(new Date()),
},
} : {}),
})),
});
const shouldChangeId = (node, key) => ID_KEYS.find(name => name === key) && typeof node[key] === "string";
const changeIds = (node) => {
if (!node) {
return node;
}
if (Array.isArray(node)) {
return node.map(n => changeIds(n));
}
if (typeof node === "object") {
return Object.keys(node).reduce((acc, key) => ({
...acc,
[key]: shouldChangeId(node, key)
? (() => {
const oldId = node[key];
if (newIds[oldId]) {
return newIds[oldId];
}
newIds[oldId] = v4();
return newIds[oldId];
})()
: changeIds(node[key]),
}), {});
}
return node;
};
const setExtra = (data) => ({
...data,
loginTheme: "pub.solar",
accountTheme: "pub.solar",
adminTheme: "pub.solar",
emailTheme: "pub.solar",
smtpServer: {
...data.smtpServer,
password: "password",
},
});
(async () => {
const fileContents = await readFile(filePath, { encoding: 'utf8' });
const data = JSON.parse(renameDomain(fileContents));
const newData = setExtra(changeIds(cleanClients(data)));
console.log(JSON.stringify(newData, null, 2));
})();

View file

@ -0,0 +1,35 @@
{
config,
flake,
...
}:
{
imports = [
flake.inputs.simple-nixos-mailserver.nixosModule
flake.self.nixosModules.home-manager
flake.self.nixosModules.core
flake.self.nixosModules.backups
flake.self.nixosModules.mail
./global.nix
];
# password is password
systemd.tmpfiles.rules = [
"f /tmp/emailpw 1777 root root 10d $2b$11$NV75HGZzMcIwrnVUZKXtxexX9DN52HayDW4eKrD1A8O3uIPnCquQ2"
];
mailserver = {
loginAccounts = {
"admins@${config.pub-solar-os.networking.domain}" = {
hashedPasswordFile = "/tmp/emailpw";
};
"hakkonaut@${config.pub-solar-os.networking.domain}" = {
hashedPasswordFile = "/tmp/emailpw";
};
"test-user@${config.pub-solar-os.networking.domain}" = {
quota = "1G";
hashedPasswordFile = "/tmp/emailpw";
};
};
};
}

View file

@ -0,0 +1 @@
node_modules

View file

@ -0,0 +1 @@
*.nix

View file

@ -0,0 +1,926 @@
{
"name": "puppeteer-socket",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "puppeteer-socket",
"version": "1.0.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"puppeteer-core": "^23.1.1"
}
},
"node_modules/@puppeteer/browsers": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.3.1.tgz",
"integrity": "sha512-uK7o3hHkK+naEobMSJ+2ySYyXtQkBxIH8Gn4MK9ciePjNV+Pf+PgY/W7iPzn2MTjl3stcYB5AlcTmPYw7AXDwA==",
"dependencies": {
"debug": "^4.3.6",
"extract-zip": "^2.0.1",
"progress": "^2.0.3",
"proxy-agent": "^6.4.0",
"semver": "^7.6.3",
"tar-fs": "^3.0.6",
"unbzip2-stream": "^1.4.3",
"yargs": "^17.7.2"
},
"bin": {
"browsers": "lib/cjs/main-cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@tootallnate/quickjs-emscripten": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
},
"node_modules/@types/node": {
"version": "22.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz",
"integrity": "sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==",
"optional": true,
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/@types/yauzl": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
"integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
"optional": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/agent-base": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
"integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
"dependencies": {
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/ast-types": {
"version": "0.13.4",
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
"integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
"dependencies": {
"tslib": "^2.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/b4a": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz",
"integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg=="
},
"node_modules/bare-events": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.4.2.tgz",
"integrity": "sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==",
"optional": true
},
"node_modules/bare-fs": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.1.tgz",
"integrity": "sha512-W/Hfxc/6VehXlsgFtbB5B4xFcsCl+pAh30cYhoFyXErf6oGrwjh8SwiPAdHgpmWonKuYpZgGywN0SXt7dgsADA==",
"optional": true,
"dependencies": {
"bare-events": "^2.0.0",
"bare-path": "^2.0.0",
"bare-stream": "^2.0.0"
}
},
"node_modules/bare-os": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.0.tgz",
"integrity": "sha512-v8DTT08AS/G0F9xrhyLtepoo9EJBJ85FRSMbu1pQUlAf6A8T0tEEQGMVObWeqpjhSPXsE0VGlluFBJu2fdoTNg==",
"optional": true
},
"node_modules/bare-path": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
"integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
"optional": true,
"dependencies": {
"bare-os": "^2.1.0"
}
},
"node_modules/bare-stream": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.1.3.tgz",
"integrity": "sha512-tiDAH9H/kP+tvNO5sczyn9ZAA7utrSMobyDchsnyyXBuUe2FSQWbxhtuHB8jwpHYYevVo2UJpcmvvjrbHboUUQ==",
"optional": true,
"dependencies": {
"streamx": "^2.18.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/basic-ftp": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
"integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"engines": {
"node": "*"
}
},
"node_modules/chromium-bidi": {
"version": "0.6.4",
"resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.6.4.tgz",
"integrity": "sha512-8zoq6ogmhQQkAKZVKO2ObFTl4uOkqoX1PlKQX3hZQ5E9cbUotcAb7h4pTNVAGGv8Z36PF3CtdOriEp/Rz82JqQ==",
"dependencies": {
"mitt": "3.0.1",
"urlpattern-polyfill": "10.0.0",
"zod": "3.23.8"
},
"peerDependencies": {
"devtools-protocol": "*"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/data-uri-to-buffer": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
"engines": {
"node": ">= 14"
}
},
"node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/degenerator": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
"integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
"dependencies": {
"ast-types": "^0.13.4",
"escodegen": "^2.1.0",
"esprima": "^4.0.1"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/devtools-protocol": {
"version": "0.0.1312386",
"resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1312386.tgz",
"integrity": "sha512-DPnhUXvmvKT2dFA/j7B+riVLUt9Q6RKJlcppojL5CoRywJJKLDYnRlw0gTFKfgDPHP5E04UoB71SxoJlVZy8FA=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"engines": {
"node": ">=6"
}
},
"node_modules/escodegen": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^5.2.0",
"esutils": "^2.0.2"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=6.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/extract-zip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
"integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
"dependencies": {
"debug": "^4.1.1",
"get-stream": "^5.1.0",
"yauzl": "^2.10.0"
},
"bin": {
"extract-zip": "cli.js"
},
"engines": {
"node": ">= 10.17.0"
},
"optionalDependencies": {
"@types/yauzl": "^2.9.1"
}
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/fs-extra": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
"integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/get-uri": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
"integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
"dependencies": {
"basic-ftp": "^5.0.2",
"data-uri-to-buffer": "^6.0.2",
"debug": "^4.3.4",
"fs-extra": "^11.2.0"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/http-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
"dependencies": {
"agent-base": "^7.1.0",
"debug": "^4.3.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/https-proxy-agent": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
"integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ip-address": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/lru-cache": {
"version": "7.18.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
"engines": {
"node": ">=12"
}
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/netmask": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/pac-proxy-agent": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
"integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
"dependencies": {
"@tootallnate/quickjs-emscripten": "^0.23.0",
"agent-base": "^7.0.2",
"debug": "^4.3.4",
"get-uri": "^6.0.1",
"http-proxy-agent": "^7.0.0",
"https-proxy-agent": "^7.0.5",
"pac-resolver": "^7.0.1",
"socks-proxy-agent": "^8.0.4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/pac-resolver": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
"dependencies": {
"degenerator": "^5.0.0",
"netmask": "^2.0.2"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/proxy-agent": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
"integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
"dependencies": {
"agent-base": "^7.0.2",
"debug": "^4.3.4",
"http-proxy-agent": "^7.0.1",
"https-proxy-agent": "^7.0.3",
"lru-cache": "^7.14.1",
"pac-proxy-agent": "^7.0.1",
"proxy-from-env": "^1.1.0",
"socks-proxy-agent": "^8.0.2"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/puppeteer-core": {
"version": "23.1.1",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.1.1.tgz",
"integrity": "sha512-OeTqNiYGF9qZtwZU4Yc88DDqFJs4TJ4rnK81jkillh6MwDeQodyisM9xe5lBmPhwiDy92s5J5DQtQLjCKHFQ3g==",
"dependencies": {
"@puppeteer/browsers": "2.3.1",
"chromium-bidi": "0.6.4",
"debug": "^4.3.6",
"devtools-protocol": "0.0.1312386",
"typed-query-selector": "^2.12.0",
"ws": "^8.18.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/queue-tick": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
"integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
"dependencies": {
"ip-address": "^9.0.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks-proxy-agent": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
"integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
"dependencies": {
"agent-base": "^7.1.1",
"debug": "^4.3.4",
"socks": "^2.8.3"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
},
"node_modules/streamx": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.19.0.tgz",
"integrity": "sha512-5z6CNR4gtkPbwlxyEqoDGDmWIzoNJqCBt4Eac1ICP9YaIT08ct712cFj0u1rx4F8luAuL+3Qc+RFIdI4OX00kg==",
"dependencies": {
"fast-fifo": "^1.3.2",
"queue-tick": "^1.0.1",
"text-decoder": "^1.1.0"
},
"optionalDependencies": {
"bare-events": "^2.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/tar-fs": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
"integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
"dependencies": {
"pump": "^3.0.0",
"tar-stream": "^3.1.5"
},
"optionalDependencies": {
"bare-fs": "^2.1.1",
"bare-path": "^2.1.0"
}
},
"node_modules/tar-stream": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
"integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
"dependencies": {
"b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
},
"node_modules/text-decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.1.1.tgz",
"integrity": "sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==",
"dependencies": {
"b4a": "^1.6.4"
}
},
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="
},
"node_modules/typed-query-selector": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
"integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg=="
},
"node_modules/unbzip2-stream": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
"dependencies": {
"buffer": "^5.2.1",
"through": "^2.3.8"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"optional": true
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/urlpattern-polyfill": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
"integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg=="
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/wrap-ansi/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/wrap-ansi/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.18.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"node_modules/zod": {
"version": "3.23.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
"integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}

View file

@ -0,0 +1,17 @@
{
"name": "puppeteer-socket",
"version": "1.0.0",
"main": "src/index.mjs",
"scripts": {
"start": "node src/index.mjs"
},
"bin": {
"puppeteer-socket": "src/index.mjs"
},
"author": "",
"license": "AGPL-3.0-or-later",
"description": "",
"dependencies": {
"puppeteer-core": "^23.1.1"
}
}

View file

@ -0,0 +1,6 @@
{ writeShellScriptBin, curl }:
writeShellScriptBin "puppeteer-run" ''
set -e
exec ${curl}/bin/curl --fail-with-body -X POST -d "$@" -s --unix-socket "/tmp/puppeteer.sock" http://puppeteer-socket
''

View file

@ -0,0 +1,8 @@
{ buildNpmPackage, nodejs }:
buildNpmPackage rec {
src = ./.;
name = "puppeteer-socket";
nativeBuildInputs = [ nodejs ];
npmDepsHash = "sha256-d+mbHdwt9V5JIBUw/2NyTMBlZ3D5UNE8TpVXJm8rcnU=";
dontNpmBuild = true;
}

View file

@ -0,0 +1,59 @@
#!/usr/bin/env node
import http from 'node:http';
import puppeteer from 'puppeteer-core';
const PUPPETEER_SOCKET = '/tmp/puppeteer.sock';
const EXECUTABLE = process.env.EXECUTABLE || 'firefox';
(async () => {
const firefoxBrowser = await puppeteer.launch({
executablePath: EXECUTABLE,
headless: false,
devtools: true,
browser: 'firefox',
extraPrefsFirefox: {},
});
const page = await firefoxBrowser.newPage();
await page.setViewport({
width: 1200,
height: 600,
deviceScaleFactor: 1,
});
const server = http.createServer({});
server.on('request', (req, res) => {
const chunks = [];
req.on('data', (chunk) => {
chunks.push(chunk);
});
req.on('end', async () => {
try {
const content = chunks.join('');
const val = await eval(content);
const responseText = (() => {
try {
return val.toString();
} catch (err) {
return val;
}
})();
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(responseText);
} catch (err) {
console.error(err);
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: err.toString() }));
}
});
});
server.listen(PUPPETEER_SOCKET, () => {
console.log('[puppeteer-socket] Listening!');
});
})();

View file

@ -14,13 +14,7 @@
node.specialArgs = self.outputs.nixosConfigurations.nachtigall._module.specialArgs;
nodes = {
acme-server = {
imports = [
self.nixosModules.home-manager
self.nixosModules.core
./support/ca.nix
];
};
acme-server.imports = [ ./support/acme-server.nix ];
nachtigall = {
imports = [
@ -31,7 +25,7 @@
./support/global.nix
];
virtualisation.cores = 1;
virtualisation.cores = 16;
virtualisation.memorySize = 4096;
networking.interfaces.eth0.ipv4.addresses = [