mirror of
https://git.pvv.ntnu.no/Drift/pvv-nixos-config.git
synced 2025-12-12 21:27:15 +01:00
Compare commits
23 Commits
spotifyd
...
ce2f6a4546
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce2f6a4546 | ||
|
|
ed13e49ba7 | ||
|
|
d64d8edd68 | ||
|
|
4de7bd09bd | ||
|
|
0f5c48902b | ||
|
|
36a8868f94 | ||
|
|
fe3e5d6a3d | ||
|
|
2f3bcaf124 | ||
|
|
c6684d5146 | ||
|
|
f6cb934ffb | ||
|
|
9625258942 | ||
|
|
34637e383a | ||
|
|
0bfa6ac329 | ||
|
|
2c3261de74 | ||
|
|
c2e6f294ea | ||
|
|
41e94695f0 | ||
|
|
c6b4ea9929 | ||
|
|
9dbf5d56f5 | ||
|
|
64b5bb548b | ||
|
|
261c8e0811 | ||
|
|
4476cdcbbc | ||
|
|
1714681532 | ||
|
|
314c7960d1 |
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@@ -0,0 +1,10 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.nix]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
1
.git-blame-ignore-revs
Normal file
1
.git-blame-ignore-revs
Normal file
@@ -0,0 +1 @@
|
||||
e00008da1afe0d760badd34bbeddff36bb08c475
|
||||
@@ -30,7 +30,7 @@ creation_rules:
|
||||
- *user_oysteikt
|
||||
|
||||
# Host specific secrets
|
||||
|
||||
|
||||
- path_regex: secrets/bekkalokk/[^/]+\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
@@ -66,7 +66,7 @@ creation_rules:
|
||||
- *user_pederbs_bjarte
|
||||
pgp:
|
||||
- *user_oysteikt
|
||||
|
||||
|
||||
- path_regex: secrets/bicep/[^/]+\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
|
||||
9
base.nix
9
base.nix
@@ -76,10 +76,19 @@
|
||||
# Trusted users on the nix builder machines
|
||||
users.groups."nix-builder-users".name = "nix-builder-users";
|
||||
|
||||
# Let's not thermal throttle
|
||||
services.thermald.enable = lib.mkIf (lib.all (x: x) [
|
||||
(config.nixpkgs.system == "x86_64-linux")
|
||||
(!config.boot.isContainer or false)
|
||||
]) true;
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
extraConfig = ''
|
||||
PubkeyAcceptedAlgorithms=+ssh-rsa
|
||||
Match Group wheel
|
||||
PasswordAuthentication no
|
||||
Match All
|
||||
'';
|
||||
settings.PermitRootLogin = "yes";
|
||||
};
|
||||
|
||||
11
flake.nix
11
flake.nix
@@ -37,8 +37,8 @@
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forAllSystems = f: nixlib.genAttrs systems (system: f system);
|
||||
allMachines = nixlib.mapAttrsToList (name: _: name) self.nixosConfigurations;
|
||||
forAllSystems = f: nixlib.genAttrs systems f;
|
||||
allMachines = builtins.attrNames self.nixosConfigurations;
|
||||
importantMachines = [
|
||||
"bekkalokk"
|
||||
"bicep"
|
||||
@@ -47,6 +47,8 @@
|
||||
"ildkule"
|
||||
];
|
||||
in {
|
||||
inherit inputs;
|
||||
|
||||
nixosConfigurations = let
|
||||
unstablePkgs = nixpkgs-unstable.legacyPackages.x86_64-linux;
|
||||
nixosConfig = nixpkgs: name: config: nixpkgs.lib.nixosSystem (nixpkgs.lib.recursiveUpdate
|
||||
@@ -124,6 +126,11 @@
|
||||
buskerud = stableNixosConfig "buskerud" { };
|
||||
};
|
||||
|
||||
nixosModules = {
|
||||
snakeoil-certs = ./modules/snakeoil-certs.nix;
|
||||
snappymail = ./modules/snappymail.nix;
|
||||
};
|
||||
|
||||
devShells = forAllSystems (system: {
|
||||
default = nixpkgs.legacyPackages.${system}.callPackage ./shell.nix { };
|
||||
});
|
||||
|
||||
@@ -15,9 +15,9 @@ let
|
||||
enable = true;
|
||||
name = "git-runner-${name}"; url = "https://git.pvv.ntnu.no";
|
||||
labels = [
|
||||
"debian-latest:docker://node:18-bullseye"
|
||||
"ubuntu-latest:docker://node:18-bullseye"
|
||||
];
|
||||
"debian-latest:docker://node:18-bullseye"
|
||||
"ubuntu-latest:docker://node:18-bullseye"
|
||||
];
|
||||
tokenFile = config.sops.secrets."gitea/runners/${name}".path;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,7 +6,8 @@ let
|
||||
in {
|
||||
imports = [
|
||||
./ci.nix
|
||||
./import-users.nix
|
||||
./import-users
|
||||
./web-secret-provider
|
||||
];
|
||||
|
||||
sops.secrets = {
|
||||
@@ -135,10 +136,16 @@ in {
|
||||
script = let
|
||||
logo-svg = ../../../../assets/logo_blue_regular.svg;
|
||||
logo-png = ../../../../assets/logo_blue_regular.png;
|
||||
extraLinks = pkgs.writeText "gitea-extra-links.tmpl" ''
|
||||
<a class="item" href="https://www.pvv.ntnu.no/">PVV</a>
|
||||
<a class="item" href="https://wiki.pvv.ntnu.no/">Wiki</a>
|
||||
<a class="item" href="https://git.pvv.ntnu.no/Drift/-/projects/4">Tokyo Drift Issues</a>
|
||||
'';
|
||||
in ''
|
||||
install -Dm444 ${logo-svg} ${cfg.customDir}/public/assets/img/logo.svg
|
||||
install -Dm444 ${logo-png} ${cfg.customDir}/public/assets/img/logo.png
|
||||
install -Dm444 ${./loading.apng} ${cfg.customDir}/public/assets/img/loading.png
|
||||
install -Dm444 ${extraLinks} ${cfg.customDir}/templates/custom/extra_links.tmpl
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
||||
153
hosts/bekkalokk/services/gitea/web-secret-provider/default.nix
Normal file
153
hosts/bekkalokk/services/gitea/web-secret-provider/default.nix
Normal file
@@ -0,0 +1,153 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
organizations = [
|
||||
"Drift"
|
||||
"Projects"
|
||||
"Kurs"
|
||||
];
|
||||
|
||||
cfg = config.services.gitea;
|
||||
|
||||
program = pkgs.writers.writePython3 "gitea-web-secret-provider" {
|
||||
libraries = with pkgs.python3Packages; [ requests ];
|
||||
flakeIgnore = [
|
||||
"E501" # Line over 80 chars lol
|
||||
"E201" # "whitespace after {"
|
||||
"E202" # "whitespace after }"
|
||||
"E251" # unexpected spaces around keyword / parameter equals
|
||||
"W391" # Newline at end of file
|
||||
];
|
||||
makeWrapperArgs = [
|
||||
"--prefix PATH : ${(lib.makeBinPath [ pkgs.openssh ])}"
|
||||
];
|
||||
} (lib.pipe ./gitea-web-secret-provider.py [
|
||||
builtins.readFile
|
||||
(lib.splitString "\n")
|
||||
(lib.drop 2)
|
||||
lib.concatLines
|
||||
]);
|
||||
|
||||
commonHardening = {
|
||||
NoNewPrivileges = true;
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
ProtectSystem = true;
|
||||
ProtectHome = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
LockPersonality = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
sops.secrets."gitea/web-secret-provider/token" = {
|
||||
owner = "gitea";
|
||||
group = "gitea";
|
||||
restartUnits = [
|
||||
"gitea-web-secret-provider@"
|
||||
] ++ (map (org: "gitea-web-secret-provider@${org}") organizations);
|
||||
};
|
||||
|
||||
systemd.tmpfiles.settings."10-gitea-web-secret-provider"."/var/lib/gitea-web/authorized_keys.d".d = {
|
||||
user = "gitea";
|
||||
group = "gitea";
|
||||
mode = "700";
|
||||
};
|
||||
|
||||
systemd.slices.system-giteaweb = {
|
||||
description = "Gitea web directories";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
# https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Specifiers
|
||||
# %i - instance name (after the @)
|
||||
# %d - secrets directory
|
||||
# %S - /var/lib
|
||||
systemd.services = {
|
||||
"gitea-web-secret-provider@" = {
|
||||
description = "Ensure all repos in %i has an SSH key to push web content";
|
||||
requires = [ "gitea.service" "network.target" ];
|
||||
serviceConfig = {
|
||||
Slice = "system-giteaweb.slice";
|
||||
Type = "oneshot";
|
||||
ExecStart = let
|
||||
args = lib.cli.toGNUCommandLineShell { } {
|
||||
org = "%i";
|
||||
token-path = "%d/token";
|
||||
api-url = "${cfg.settings.server.ROOT_URL}api/v1";
|
||||
key-dir = "%S/%i/keys";
|
||||
authorized-keys-path = "%S/gitea-web/authorized_keys.d/%i";
|
||||
rrsync-path = "${pkgs.rrsync}/bin/rrsync";
|
||||
web-dir = "%S/gitea-web/web";
|
||||
};
|
||||
in "${program} ${args}";
|
||||
User = "gitea";
|
||||
Group = "gitea";
|
||||
StateDirectory = "%i";
|
||||
LoadCredential = [
|
||||
"token:${config.sops.secrets."gitea/web-secret-provider/token".path}"
|
||||
];
|
||||
} // commonHardening;
|
||||
};
|
||||
|
||||
"gitea-web-chown@" = {
|
||||
description = "Ensure all gitea-web content is owned by the gitea user";
|
||||
serviceConfig = {
|
||||
Slice = "system-giteaweb.slice";
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.coreutils}/bin/chown -R gitea:gitea '%S/gitea-web'";
|
||||
|
||||
StateDirectory = "%i";
|
||||
|
||||
LoadCredential = [
|
||||
"token:${config.sops.secrets."gitea/web-secret-provider/token".path}"
|
||||
];
|
||||
|
||||
PrivateNetwork = true;
|
||||
} // commonHardening;
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers = {
|
||||
"gitea-web-secret-provider@" = {
|
||||
description = "Ensure all repos in %i has an SSH key to push web content";
|
||||
timerConfig = {
|
||||
RandomizedDelaySec = "1h";
|
||||
Persistent = true;
|
||||
Unit = "gitea-web-secret-provider@%i.service";
|
||||
OnCalendar = "daily";
|
||||
};
|
||||
};
|
||||
|
||||
"gitea-web-chown@" = {
|
||||
description = "Ensure all gitea-web content is owned by the gitea user";
|
||||
timerConfig = {
|
||||
RandomizedDelaySec = "10m";
|
||||
Persistent = true;
|
||||
Unit = "gitea-web-chown@%i.service";
|
||||
OnCalendar = "hourly";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.targets.timers.wants = lib.mapCartesianProduct ({ timer, org }: "${timer}@${org}.timer") {
|
||||
timer = [
|
||||
"gitea-web-secret-provider"
|
||||
"gitea-web-chown"
|
||||
];
|
||||
org = organizations;
|
||||
};
|
||||
|
||||
services.openssh.authorizedKeysFiles = map (org: "/var/lib/gitea-web/authorized_keys.d/${org}") organizations;
|
||||
|
||||
services.nginx.virtualHosts."pages.pvv.ntnu.no" = {
|
||||
kTLS = true;
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = "/var/lib/gitea-web/web";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ requests ])" openssh
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import os
|
||||
import requests
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description="Generate SSH keys for Gitea repositories and add them as secrets")
|
||||
parser.add_argument("--org", required=True, help="The organization to generate keys for")
|
||||
parser.add_argument("--token-path", metavar='PATH', required=True, help="Path to a file containing the Gitea API token")
|
||||
parser.add_argument("--api-url", metavar='URL', help="The URL of the Gitea API", default="https://git.pvv.ntnu.no/api/v1")
|
||||
parser.add_argument("--key-dir", metavar='PATH', help="The directory to store the generated keys in", default="/run/gitea-web-secret-provider")
|
||||
parser.add_argument("--authorized-keys-path", metavar='PATH', help="The path to the resulting authorized_keys file", default="/etc/ssh/authorized_keys.d/gitea-web-secret-provider")
|
||||
parser.add_argument("--rrsync-path", metavar='PATH', help="The path to the rrsync binary", default="/run/current-system/sw/bin/rrsync")
|
||||
parser.add_argument("--web-dir", metavar='PATH', help="The directory to sync the repositories to", default="/var/www")
|
||||
parser.add_argument("--force", action="store_true", help="Overwrite existing keys")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def add_secret(args, token, repo, name, secret):
|
||||
result = requests.put(
|
||||
f"{args.api_url}/repos/{args.org}/{repo}/actions/secrets/{name}",
|
||||
json = { 'data': secret },
|
||||
headers = { 'Authorization': 'token ' + token },
|
||||
)
|
||||
if result.status_code not in (201, 204):
|
||||
raise Exception(f"Failed to add secret: {result.json()}")
|
||||
|
||||
|
||||
def get_org_repo_list(args, token):
|
||||
result = requests.get(
|
||||
f"{args.api_url}/orgs/{args.org}/repos",
|
||||
headers = { 'Authorization': 'token ' + token },
|
||||
)
|
||||
return [repo["name"] for repo in result.json()]
|
||||
|
||||
|
||||
def generate_ssh_key(args, repository: str):
|
||||
keyname = hashlib.sha256(args.org.encode() + repository.encode()).hexdigest()
|
||||
|
||||
if not os.path.exists(os.path.join(args.key_dir, keyname)) or args.force:
|
||||
subprocess.run(
|
||||
[
|
||||
"ssh-keygen",
|
||||
*("-t", "ed25519"),
|
||||
*("-b", "4096"),
|
||||
*("-f", os.path.join(args.key_dir, keyname)),
|
||||
*("-N", ""),
|
||||
*("-C", f"{args.org}/{repository}"),
|
||||
],
|
||||
check=True,
|
||||
stdin=subprocess.DEVNULL,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL
|
||||
)
|
||||
print(f"Generated SSH key for `{args.org}/{repository}`")
|
||||
|
||||
with open(os.path.join(args.key_dir, keyname), "r") as f:
|
||||
private_key = f.read()
|
||||
|
||||
with open(os.path.join(args.key_dir, keyname + ".pub"), "r") as f:
|
||||
public_key = f.read()
|
||||
|
||||
return private_key, public_key
|
||||
|
||||
|
||||
def generate_authorized_keys(args, repo_public_keys: list[tuple[str, str]]):
|
||||
result = ""
|
||||
for repo, public_key in repo_public_keys:
|
||||
result += f"""
|
||||
command="{args.rrsync_path} -wo {args.web_dir}/{args.org}/{repo}",restrict,no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding {public_key}
|
||||
""".strip() + "\n"
|
||||
|
||||
with open(args.authorized_keys_path, "w") as f:
|
||||
f.write(result)
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
with open(args.token_path, "r") as f:
|
||||
token = f.read().strip()
|
||||
|
||||
os.makedirs(args.key_dir, 0o700, exist_ok=True)
|
||||
os.makedirs(Path(args.authorized_keys_path).parent, 0o700, exist_ok=True)
|
||||
|
||||
repos = get_org_repo_list(args, token)
|
||||
print(f'Found {len(repos)} repositories in `{args.org}`')
|
||||
|
||||
repo_public_keys = []
|
||||
for repo in repos:
|
||||
print(f"Locating key for `{args.org}/{repo}`")
|
||||
private_key, public_key = generate_ssh_key(args, repo)
|
||||
add_secret(args, token, repo, "WEB_SYNC_SSH_KEY", private_key)
|
||||
repo_public_keys.append((repo, public_key))
|
||||
|
||||
generate_authorized_keys(args, repo_public_keys)
|
||||
print(f"Wrote authorized_keys file to `{args.authorized_keys_path}`")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -112,7 +112,7 @@ class PwAuth extends \SimpleSAML\Module\core\Auth\UserPassBase
|
||||
array_shift($groups);
|
||||
array_shift($groups);
|
||||
array_pop($groups);
|
||||
|
||||
|
||||
$info = posix_getpwnam($uid);
|
||||
$group = $info['gid'];
|
||||
if (!in_array($group, $groups)) {
|
||||
|
||||
@@ -58,7 +58,7 @@ $config = [
|
||||
/*
|
||||
* The following settings are *filesystem paths* which define where
|
||||
* SimpleSAMLphp can find or write the following things:
|
||||
* - 'cachedir': Where SimpleSAMLphp can write its cache.
|
||||
* - 'cachedir': Where SimpleSAMLphp can write its cache.
|
||||
* - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging
|
||||
* handler other than `file`.
|
||||
* - 'datadir': Storage of general data.
|
||||
|
||||
@@ -22,62 +22,62 @@ let
|
||||
# openssl req -newkey rsa:4096 -new -x509 -days 365 -nodes -out idp.crt -keyout idp.pem
|
||||
"metadata/saml20-idp-hosted.php" = pkgs.writeText "saml20-idp-remote.php" ''
|
||||
<?php
|
||||
$metadata['https://idp.pvv.ntnu.no/'] = array(
|
||||
'host' => '__DEFAULT__',
|
||||
'privatekey' => '${config.sops.secrets."idp/privatekey".path}',
|
||||
'certificate' => '${./idp.crt}',
|
||||
'auth' => 'pwauth',
|
||||
);
|
||||
?>
|
||||
$metadata['https://idp.pvv.ntnu.no/'] = array(
|
||||
'host' => '__DEFAULT__',
|
||||
'privatekey' => '${config.sops.secrets."idp/privatekey".path}',
|
||||
'certificate' => '${./idp.crt}',
|
||||
'auth' => 'pwauth',
|
||||
);
|
||||
?>
|
||||
'';
|
||||
|
||||
"metadata/saml20-sp-remote.php" = pkgs.writeText "saml20-sp-remote.php" ''
|
||||
<?php
|
||||
${ lib.pipe config.services.idp.sp-remote-metadata [
|
||||
(map (url: ''
|
||||
$metadata['${url}'] = [
|
||||
'SingleLogoutService' => [
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
|
||||
],
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
|
||||
],
|
||||
],
|
||||
'AssertionConsumerService' => [
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
|
||||
'index' => 0,
|
||||
],
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
|
||||
'index' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
''))
|
||||
(lib.concatStringsSep "\n")
|
||||
]}
|
||||
?>
|
||||
${ lib.pipe config.services.idp.sp-remote-metadata [
|
||||
(map (url: ''
|
||||
$metadata['${url}'] = [
|
||||
'SingleLogoutService' => [
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
|
||||
],
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-logout.php/default-sp',
|
||||
],
|
||||
],
|
||||
'AssertionConsumerService' => [
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
|
||||
'index' => 0,
|
||||
],
|
||||
[
|
||||
'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
|
||||
'Location' => '${url}module.php/saml/sp/saml2-acs.php/default-sp',
|
||||
'index' => 1,
|
||||
],
|
||||
],
|
||||
];
|
||||
''))
|
||||
(lib.concatStringsSep "\n")
|
||||
]}
|
||||
?>
|
||||
'';
|
||||
|
||||
"config/authsources.php" = pkgs.writeText "idp-authsources.php" ''
|
||||
<?php
|
||||
$config = array(
|
||||
'admin' => array(
|
||||
'core:AdminPassword'
|
||||
),
|
||||
'admin' => array(
|
||||
'core:AdminPassword'
|
||||
),
|
||||
'pwauth' => array(
|
||||
'authpwauth:PwAuth',
|
||||
'pwauth_bin_path' => '${lib.getExe pwAuthScript}',
|
||||
'mail_domain' => '@pvv.ntnu.no',
|
||||
'authpwauth:PwAuth',
|
||||
'pwauth_bin_path' => '${lib.getExe pwAuthScript}',
|
||||
'mail_domain' => '@pvv.ntnu.no',
|
||||
),
|
||||
);
|
||||
?>
|
||||
?>
|
||||
'';
|
||||
|
||||
"config/config.php" = pkgs.runCommandLocal "simplesamlphp-config.php" { } ''
|
||||
@@ -108,7 +108,7 @@ in
|
||||
List of urls point to (simplesamlphp) service profiders, which the idp should trust.
|
||||
|
||||
:::{.note}
|
||||
Make sure the url ends with a `/`
|
||||
Make sure the url ends with a `/`
|
||||
:::
|
||||
'';
|
||||
};
|
||||
@@ -132,7 +132,7 @@ in
|
||||
owner = "idp";
|
||||
group = "idp";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.groups."idp" = { };
|
||||
users.users."idp" = {
|
||||
@@ -199,9 +199,9 @@ in
|
||||
'';
|
||||
};
|
||||
"^~ /simplesaml/".extraConfig = ''
|
||||
rewrite ^/simplesaml/(.*)$ /$1 redirect;
|
||||
return 404;
|
||||
'';
|
||||
rewrite ^/simplesaml/(.*)$ /$1 redirect;
|
||||
return 404;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -879,15 +879,15 @@ let
|
||||
|
||||
inherit (pkgs) pam_krb5 pam_ccreds;
|
||||
|
||||
use_ldap = (config.users.ldap.enable && config.users.ldap.loginPam);
|
||||
use_ldap = config.users.ldap.enable && config.users.ldap.loginPam;
|
||||
pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap;
|
||||
|
||||
# Create a limits.conf(5) file.
|
||||
makeLimitsConf = limits:
|
||||
pkgs.writeText "limits.conf"
|
||||
(concatMapStrings ({ domain, type, item, value }:
|
||||
"${domain} ${type} ${item} ${toString value}\n")
|
||||
limits);
|
||||
(concatMapStrings ({ domain, type, item, value }:
|
||||
"${domain} ${type} ${item} ${toString value}\n")
|
||||
limits);
|
||||
|
||||
limitsType = with lib.types; listOf (submodule ({ ... }: {
|
||||
options = {
|
||||
@@ -935,8 +935,8 @@ let
|
||||
}));
|
||||
|
||||
motd = if config.users.motdFile == null
|
||||
then pkgs.writeText "motd" config.users.motd
|
||||
else config.users.motdFile;
|
||||
then pkgs.writeText "motd" config.users.motd
|
||||
else config.users.motdFile;
|
||||
|
||||
makePAMService = name: service:
|
||||
{ name = "pam.d/${name}";
|
||||
@@ -976,20 +976,20 @@ in
|
||||
item = "maxlogins";
|
||||
value = "4";
|
||||
}
|
||||
];
|
||||
];
|
||||
|
||||
description = lib.mdDoc ''
|
||||
Define resource limits that should apply to users or groups.
|
||||
Each item in the list should be an attribute set with a
|
||||
{var}`domain`, {var}`type`,
|
||||
{var}`item`, and {var}`value`
|
||||
attribute. The syntax and semantics of these attributes
|
||||
must be that described in {manpage}`limits.conf(5)`.
|
||||
description = lib.mdDoc ''
|
||||
Define resource limits that should apply to users or groups.
|
||||
Each item in the list should be an attribute set with a
|
||||
{var}`domain`, {var}`type`,
|
||||
{var}`item`, and {var}`value`
|
||||
attribute. The syntax and semantics of these attributes
|
||||
must be that described in {manpage}`limits.conf(5)`.
|
||||
|
||||
Note that these limits do not apply to systemd services,
|
||||
whose limits can be changed via {option}`systemd.extraConfig`
|
||||
instead.
|
||||
'';
|
||||
Note that these limits do not apply to systemd services,
|
||||
whose limits can be changed via {option}`systemd.extraConfig`
|
||||
instead.
|
||||
'';
|
||||
};
|
||||
|
||||
security.pam.services = mkOption {
|
||||
@@ -1507,10 +1507,10 @@ in
|
||||
runuser = { rootOK = true; unixAuth = false; setEnvironment = false; };
|
||||
|
||||
/* FIXME: should runuser -l start a systemd session? Currently
|
||||
it complains "Cannot create session: Already running in a
|
||||
session". */
|
||||
it complains "Cannot create session: Already running in a
|
||||
session". */
|
||||
runuser-l = { rootOK = true; unixAuth = false; };
|
||||
} // optionalAttrs (config.security.pam.enableFscrypt) {
|
||||
} // optionalAttrs config.security.pam.enableFscrypt {
|
||||
# Allow fscrypt to verify login passphrase
|
||||
fscrypt = {};
|
||||
};
|
||||
|
||||
@@ -199,7 +199,7 @@ in {
|
||||
extraConfig = ''
|
||||
location ~ ^/simplesaml/(?<phpfile>.+?\.php)(?<pathinfo>/.*)?$ {
|
||||
include ${pkgs.nginx}/conf/fastcgi_params;
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
|
||||
fastcgi_pass unix:${config.services.phpfpm.pools.mediawiki.socket};
|
||||
fastcgi_param SCRIPT_FILENAME ${simplesamlphp}/share/php/simplesamlphp/public/$phpfile;
|
||||
|
||||
# Must be prepended with the baseurlpath
|
||||
|
||||
@@ -58,7 +58,7 @@ $config = [
|
||||
/*
|
||||
* The following settings are *filesystem paths* which define where
|
||||
* SimpleSAMLphp can find or write the following things:
|
||||
* - 'cachedir': Where SimpleSAMLphp can write its cache.
|
||||
* - 'cachedir': Where SimpleSAMLphp can write its cache.
|
||||
* - 'loggingdir': Where to write logs. MUST be set to NULL when using a logging
|
||||
* handler other than `file`.
|
||||
* - 'datadir': Storage of general data.
|
||||
|
||||
@@ -4,7 +4,7 @@ with lib;
|
||||
let
|
||||
cfg = config.services.roundcube;
|
||||
domain = "webmail.pvv.ntnu.no";
|
||||
in
|
||||
in
|
||||
{
|
||||
services.roundcube = {
|
||||
enable = true;
|
||||
|
||||
@@ -21,8 +21,8 @@ in {
|
||||
services.idp.sp-remote-metadata = [
|
||||
"https://www.pvv.ntnu.no/simplesaml/"
|
||||
"https://pvv.ntnu.no/simplesaml/"
|
||||
"https://www.pvv.org/simplesaml/"
|
||||
"https://pvv.org/simplesaml/"
|
||||
"https://www.pvv.org/simplesaml/"
|
||||
"https://pvv.org/simplesaml/"
|
||||
];
|
||||
|
||||
services.pvv-nettsiden = {
|
||||
@@ -43,7 +43,7 @@ in {
|
||||
'idp' => 'https://idp.pvv.ntnu.no/',
|
||||
),
|
||||
);
|
||||
'';
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ in {
|
||||
while IFS= read fname; do
|
||||
# Skip this file if an up-to-date thumbnail already exists
|
||||
if [ -f ".thumbnails/$fname.png" ] && \
|
||||
[ "$(date -R -r "$fname")" == "$(date -R -r ".thumbnails/$fname.png")" ]
|
||||
[ "$(date -R -r "$fname")" == "$(date -R -r ".thumbnails/$fname.png")" ]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
@@ -54,7 +54,7 @@ in {
|
||||
echo "Creating thumbnail for $fname"
|
||||
mkdir -p $(dirname ".thumbnails/$fname")
|
||||
convert -define jpeg:size=200x200 "$fname" -thumbnail 300 -auto-orient ".thumbnails/$fname.png" ||:
|
||||
touch -m -d "$(date -R -r "$fname")" ".thumbnails/$fname.png"
|
||||
touch -m -d "$(date -R -r "$fname")" ".thumbnails/$fname.png"
|
||||
done <<< "$images"
|
||||
'';
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
"turns:turn.pvv.ntnu.no:5349?transport=tcp"
|
||||
"turns:turn.pvv.ntnu.no:5349?transport=udp"
|
||||
|
||||
|
||||
"turns:turn.pvv.ntnu.no:3478?transport=udp"
|
||||
"turns:turn.pvv.ntnu.no:3478?transport=tcp"
|
||||
"turn:turn.pvv.ntnu.no:3478?transport=udp"
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
tls-listening-port = 443;
|
||||
alt-tls-listening-port = 5349;
|
||||
|
||||
|
||||
listening-port = 3478;
|
||||
|
||||
min-port = 49000;
|
||||
@@ -116,7 +116,7 @@
|
||||
#total-quota=1200
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
networking.firewall = {
|
||||
interfaces.enp6s0f0 = let
|
||||
range = with config.services.coturn; [ {
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
./discord.nix
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
services.mjolnir = {
|
||||
enable = true;
|
||||
pantalaimon.enable = false;
|
||||
homeserverUrl = http://127.0.0.1:8008;
|
||||
homeserverUrl = "http://127.0.0.1:8008";
|
||||
accessTokenFile = config.sops.secrets."matrix/mjolnir/access_token".path;
|
||||
managementRoom = "!gsdeCoWjvYRBrzuiRq:pvv.ntnu.no";
|
||||
protectedRooms = map (a: "https://matrix.to/#/${a}") [
|
||||
|
||||
@@ -141,12 +141,12 @@ in {
|
||||
|
||||
|
||||
services.redis.servers."".enable = true;
|
||||
|
||||
|
||||
services.nginx.virtualHosts."matrix.pvv.ntnu.no" = lib.mkMerge [
|
||||
({
|
||||
{
|
||||
kTLS = true;
|
||||
})
|
||||
({
|
||||
}
|
||||
{
|
||||
locations."/.well-known/matrix/server" = {
|
||||
return = ''
|
||||
200 '{"m.server": "matrix.pvv.ntnu.no:443"}'
|
||||
@@ -156,16 +156,16 @@ in {
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
'';
|
||||
};
|
||||
})
|
||||
({
|
||||
}
|
||||
{
|
||||
locations = let
|
||||
connectionInfo = w: matrix-lib.workerConnectionResource "metrics" w;
|
||||
socketAddress = w: let c = connectionInfo w; in "${c.host}:${toString (c.port)}";
|
||||
socketAddress = w: let c = connectionInfo w; in "${c.host}:${toString c.port}";
|
||||
|
||||
metricsPath = w: "/metrics/${w.type}/${toString w.index}";
|
||||
proxyPath = w: "http://${socketAddress w}/_synapse/metrics";
|
||||
in lib.mapAttrs' (n: v: lib.nameValuePair
|
||||
(metricsPath v) ({
|
||||
(metricsPath v) {
|
||||
proxyPass = proxyPath v;
|
||||
extraConfig = ''
|
||||
allow ${values.hosts.ildkule.ipv4};
|
||||
@@ -174,10 +174,10 @@ in {
|
||||
allow ${values.hosts.ildkule.ipv6_global};
|
||||
deny all;
|
||||
'';
|
||||
}))
|
||||
})
|
||||
cfg.workers.instances;
|
||||
})
|
||||
({
|
||||
}
|
||||
{
|
||||
locations."/metrics/master/1" = {
|
||||
proxyPass = "http://127.0.0.1:9000/_synapse/metrics";
|
||||
extraConfig = ''
|
||||
@@ -202,5 +202,5 @@ in {
|
||||
labels = { };
|
||||
}]) + "/";
|
||||
};
|
||||
})];
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
mysqld = {
|
||||
# PVV allows a lot of connections at the same time
|
||||
max_connect_errors = 10000;
|
||||
bind-address = values.services.mysql.ipv4;
|
||||
skip-networking = 0;
|
||||
bind-address = values.services.mysql.ipv4;
|
||||
skip-networking = 0;
|
||||
|
||||
# This was needed in order to be able to use all of the old users
|
||||
# during migration from knakelibrak to bicep in Sep. 2023
|
||||
secure_auth = 0;
|
||||
# This was needed in order to be able to use all of the old users
|
||||
# during migration from knakelibrak to bicep in Sep. 2023
|
||||
secure_auth = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = mkForce false;
|
||||
};
|
||||
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
services.resolved.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
../../misc/metrics-exporters.nix
|
||||
|
||||
../../modules/grzegorz.nix
|
||||
../../modules/spotifyd.nix
|
||||
];
|
||||
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
|
||||
@@ -23187,4 +23187,4 @@
|
||||
"uid": "rYdddlPWk",
|
||||
"version": 9,
|
||||
"weekStart": ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3164,4 +3164,4 @@
|
||||
"title": "PostgreSQL Database",
|
||||
"uid": "000000039",
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,13 +34,13 @@ in {
|
||||
{
|
||||
name = "Ildkule Prometheus";
|
||||
type = "prometheus";
|
||||
url = ("http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}");
|
||||
isDefault = true;
|
||||
url = "http://${config.services.prometheus.listenAddress}:${toString config.services.prometheus.port}";
|
||||
isDefault = true;
|
||||
}
|
||||
{
|
||||
name = "Ildkule loki";
|
||||
type = "loki";
|
||||
url = ("http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port}");
|
||||
url = "http://${config.services.loki.configuration.server.http_listen_address}:${toString config.services.loki.configuration.server.http_listen_port}";
|
||||
}
|
||||
];
|
||||
dashboards.settings.providers = [
|
||||
@@ -56,13 +56,13 @@ in {
|
||||
url = "https://raw.githubusercontent.com/matrix-org/synapse/develop/contrib/grafana/synapse.json";
|
||||
options.path = dashboards/synapse.json;
|
||||
}
|
||||
# TODO: enable once https://github.com/NixOS/nixpkgs/pull/242365 gets merged
|
||||
# {
|
||||
# name = "MySQL";
|
||||
# type = "file";
|
||||
# url = "https://raw.githubusercontent.com/prometheus/mysqld_exporter/main/mysqld-mixin/dashboards/mysql-overview.json";
|
||||
# options.path = dashboards/mysql.json;
|
||||
# }
|
||||
# TODO: enable once https://github.com/NixOS/nixpkgs/pull/242365 gets merged
|
||||
# {
|
||||
# name = "MySQL";
|
||||
# type = "file";
|
||||
# url = "https://raw.githubusercontent.com/prometheus/mysqld_exporter/main/mysqld-mixin/dashboards/mysql-overview.json";
|
||||
# options.path = dashboards/mysql.json;
|
||||
# }
|
||||
{
|
||||
name = "Postgresql";
|
||||
type = "file";
|
||||
|
||||
@@ -58,7 +58,7 @@ in {
|
||||
};
|
||||
|
||||
limits_config = {
|
||||
allow_structured_metadata = false;
|
||||
allow_structured_metadata = false;
|
||||
reject_old_samples = true;
|
||||
reject_old_samples_max_age = "72h";
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ in {
|
||||
};
|
||||
|
||||
systemd.services.prometheus-postgres-exporter-knakelibrak.serviceConfig = let
|
||||
localCfg = config.services.prometheus.exporters.postgres;
|
||||
localCfg = config.services.prometheus.exporters.postgres;
|
||||
in lib.recursiveUpdate config.systemd.services.prometheus-postgres-exporter.serviceConfig {
|
||||
EnvironmentFile = config.sops.secrets."keys/postgres/postgres_exporter_knakelibrak_env".path;
|
||||
ExecStart = ''
|
||||
|
||||
21
justfile
Normal file
21
justfile
Normal file
@@ -0,0 +1,21 @@
|
||||
export GUM_FILTER_HEIGHT := "15"
|
||||
nom := `if command -v nom >/dev/null; then echo nom; else echo nix; fi`
|
||||
|
||||
@_default:
|
||||
just "$(gum choose --ordered --header "Pick a recipie..." $(just --summary --unsorted))"
|
||||
|
||||
check:
|
||||
nix flake check --keep-going
|
||||
|
||||
build-machine machine=`just _a_machine`:
|
||||
{{nom}} build .#nixosConfigurations.{{ machine }}.config.system.build.toplevel
|
||||
|
||||
@update-inputs:
|
||||
nix eval .#inputs --apply builtins.attrNames --json \
|
||||
| jq '.[]' -r \
|
||||
| gum choose --no-limit --height=15 \
|
||||
| xargs nix flake update --commit-lock-file
|
||||
|
||||
|
||||
_a_machine:
|
||||
nix eval .#nixosConfigurations --apply builtins.attrNames --json | jq .[] -r | gum filter
|
||||
@@ -32,7 +32,7 @@
|
||||
color = "red";
|
||||
command = "hostname | ${pkgs.toilet}/bin/toilet -f mono9";
|
||||
};
|
||||
|
||||
|
||||
service_status = {
|
||||
Accounts = "accounts-daemon";
|
||||
Cron = "cron";
|
||||
@@ -40,16 +40,16 @@
|
||||
Matrix = "matrix-synapse";
|
||||
sshd = "sshd";
|
||||
};
|
||||
|
||||
|
||||
uptime = {
|
||||
prefix = "Uptime: ";
|
||||
};
|
||||
|
||||
|
||||
# Not relevant for server
|
||||
# user_service_status = {
|
||||
# Gpg-agent = "gpg-agent";
|
||||
# };
|
||||
|
||||
|
||||
filesystems = let
|
||||
inherit (lib.attrsets) attrNames listToAttrs nameValuePair;
|
||||
inherit (lib.lists) imap1;
|
||||
@@ -61,7 +61,7 @@
|
||||
getName = i: v: if (v.label != null) then v.label else "<? ${toString i}>";
|
||||
in
|
||||
imap1Attrs' (i: n: v: nameValuePair (getName i v) n) fileSystems;
|
||||
|
||||
|
||||
memory = {
|
||||
swap_pos = "beside"; # or "below" or "none"
|
||||
};
|
||||
@@ -70,14 +70,14 @@
|
||||
inherit (lib.lists) imap1;
|
||||
inherit (lib.attrsets) filterAttrs nameValuePair attrValues listToAttrs;
|
||||
inherit (config.users) users;
|
||||
|
||||
|
||||
normalUsers = filterAttrs (n: v: v.isNormalUser || n == "root") users;
|
||||
userNPVs = imap1 (index: user: nameValuePair user.name index) (attrValues normalUsers);
|
||||
in listToAttrs userNPVs;
|
||||
|
||||
last_run = {};
|
||||
};
|
||||
|
||||
|
||||
toml = pkgs.formats.toml {};
|
||||
|
||||
in toml.generate "rust-motd.toml" cfg;
|
||||
|
||||
@@ -36,10 +36,10 @@ in
|
||||
type = lib.types.str;
|
||||
default = "${name}.key";
|
||||
};
|
||||
subject = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/C=NO/O=Programvareverkstedet/CN=*.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
|
||||
};
|
||||
subject = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/C=NO/O=Programvareverkstedet/CN=*.pvv.ntnu.no/emailAddress=drift@pvv.ntnu.no";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
@@ -54,16 +54,16 @@ in
|
||||
mkdir -p $(dirname "${value.certificate}") $(dirname "${value.certificateKey}")
|
||||
if ! ${openssl} x509 -checkend 86400 -noout -in ${value.certificate}
|
||||
then
|
||||
echo "Regenerating '${value.certificate}'"
|
||||
${openssl} req \
|
||||
-newkey rsa:4096 \
|
||||
-new -x509 \
|
||||
-days "${toString value.daysValid}" \
|
||||
-nodes \
|
||||
-subj "${value.subject}" \
|
||||
-out "${value.certificate}" \
|
||||
-keyout "${value.certificateKey}" \
|
||||
${lib.escapeShellArgs value.extraOpenSSLArgs}
|
||||
echo "Regenerating '${value.certificate}'"
|
||||
${openssl} req \
|
||||
-newkey rsa:4096 \
|
||||
-new -x509 \
|
||||
-days "${toString value.daysValid}" \
|
||||
-nodes \
|
||||
-subj "${value.subject}" \
|
||||
-out "${value.certificate}" \
|
||||
-keyout "${value.certificateKey}" \
|
||||
${lib.escapeShellArgs value.extraOpenSSLArgs}
|
||||
fi
|
||||
chown "${value.owner}:${value.group}" "${value.certificate}"
|
||||
chown "${value.owner}:${value.group}" "${value.certificateKey}"
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
{ lib, config, ... }:
|
||||
|
||||
{
|
||||
|
||||
services.spotifyd.enable = true;
|
||||
# https://docs.spotifyd.rs/config/File.html
|
||||
services.spotifyd.settings = {
|
||||
device_name = "${config.networking.hostName}-spotifyd";
|
||||
device_type = "t_v"; # in ["unknown" "computer" "tablet" "smartphone" "speaker" "t_v"],
|
||||
bitrate = 160; # in [96 160 320]
|
||||
volume_normalisation = true;
|
||||
zeroconf_port = 44677; # instead of user/password
|
||||
|
||||
# this is the place you add blinkenlights
|
||||
#on_song_change_hook = "rm -rf / --no-preserve-root";
|
||||
};
|
||||
|
||||
systemd.services.spotifyd.serviceConfig = {
|
||||
SupplementaryGroups = [
|
||||
"audio"
|
||||
"pipewire"
|
||||
];
|
||||
};
|
||||
|
||||
services.avahi.enable = true;
|
||||
services.avahi.publish.enable = true;
|
||||
services.avahi.publish.addresses = true;
|
||||
services.avahi.publish.domain = true;
|
||||
services.avahi.extraServiceFiles.spotifyd = ''
|
||||
<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
|
||||
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
|
||||
<service-group>
|
||||
<name replace-wildcards="yes">%h</name>
|
||||
<service>
|
||||
<type>_spotify-connect._tcp</type>
|
||||
<port>${builtins.toString config.services.spotifyd.settings.zeroconf_port}</port>
|
||||
</service>
|
||||
</service-group>
|
||||
'';
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ config.services.spotifyd.settings.zeroconf_port ];
|
||||
networking.firewall.allowedUDPPorts = [ 5353 ]; # mDNS
|
||||
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
gitea:
|
||||
web-secret-provider:
|
||||
token: ENC[AES256_GCM,data:pHmBKxrNcLifl4sjR44AGEElfdachja35Tl/InsqvBWturaeTv4R0w==,iv:emBWfXQs2VNqtpDp5iA5swNC+24AWDYYXo6nvN+Fwx4=,tag:lkhSVSs6IqhHpfDPOX0wQA==,type:str]
|
||||
password: ENC[AES256_GCM,data:hlNzdU1ope0t50/3aztyLeXjMHd2vFPpwURX+Iu8f49DOqgSnEMtV+KtLA==,iv:qljRnSnchL5cFmaUAfCH9GQYQxcy5cyWejgk1x6bFgI=,tag:tIhboFU5kZsj5oAQR3hLbw==,type:str]
|
||||
database: ENC[AES256_GCM,data:UlS33IdCEyeSvT6ngpmnkBWHuSEqsB//DT+3b7C+UwbD8UXWJlsLf1X8/w==,iv:mPRW5ldyZaHP+y/0vC2JGSLZmlkhgmkvXPk4LazkSDs=,tag:gGk6Z/nbPvzE1zG+tJC8Sw==,type:str]
|
||||
email-password: ENC[AES256_GCM,data:KRwC+aL1aPvJuXt91Oq1ttATMnFTnuUy,iv:ats8TygB/2pORkaTZzPOLufZ9UmvVAKoRcWNvYF1z6w=,tag:Do0fA+4cZ3+l7JJyu8hjBg==,type:str]
|
||||
@@ -90,8 +92,8 @@ sops:
|
||||
UHpLRkdQTnhkeGlWVG9VS1hkWktyckEKAdwnA9URLYZ50lMtXrU9Q09d0L3Zfsyr
|
||||
4UsvjjdnFtsXwEZ9ZzOQrpiN0Oz24s3csw5KckDni6kslaloJZsLGg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2024-05-26T02:07:41Z"
|
||||
mac: ENC[AES256_GCM,data:CRaJefV1zcJc6eyzyjTLgd0+Wv46VT8o4iz2YAGU+c2b/Cr97Tj290LoEO6UXTI3uFwVfzii2yZ2l+4FK3nVVriD4Cx1O/9qWcnLa5gfK30U0zof6AsJx8qtGu1t6oiPlGUCF7sT0BW9Wp8cPumrY6cZp9QbhmIDV0o0aJNUNN4=,iv:8OSYV1eG6kYlJD4ovZZhcD1GaYnmy7vHPa/+7egM1nE=,tag:OPI13rpDh2l1ViFj8TBFWg==,type:str]
|
||||
lastmodified: "2024-08-13T19:49:24Z"
|
||||
mac: ENC[AES256_GCM,data:AeJ53D+8A8mHYRmVHdqhcS1ZTbqVe5gQqJsJjMk4T/ZlNX8/V4M9mqAW2FB9m/JSdj234gDu+PBHcW70ZrCqeVsoUW/ETVgUX3W2gBmBgYJiRETp8I7/eks/5YEV6vIIxQsZNP/9dZTNX4T2wD74ELl23NSTXA/6k2tyzBlTMYo=,iv:DABafHvw+5w0PHCKqLgpwmQnv0uHOTyj+s8gdnHFTZ4=,tag:SNZ7W+6zdyuuv2AB9ir8eg==,type:str]
|
||||
pgp:
|
||||
- created_at: "2024-08-04T00:03:28Z"
|
||||
enc: |-
|
||||
@@ -114,4 +116,4 @@ sops:
|
||||
-----END PGP MESSAGE-----
|
||||
fp: F7D37890228A907440E1FD4846B9228E814A2AAC
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.8.1
|
||||
version: 3.9.0
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
pkgs.mkShellNoCC {
|
||||
packages = with pkgs; [
|
||||
just
|
||||
jq
|
||||
gum
|
||||
sops
|
||||
gnupg
|
||||
statix
|
||||
openstackclient
|
||||
editorconfig-checker
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
|
||||
24
statix.toml
Normal file
24
statix.toml
Normal file
@@ -0,0 +1,24 @@
|
||||
ignore = [".direnv"]
|
||||
nix_version = '2.18' # '2.4'
|
||||
disabled = [
|
||||
# "bool_comparison", # W01
|
||||
# "empty_let_in", # W02
|
||||
"manual_inherit", # W03
|
||||
"manual_inherit_from", # W04
|
||||
# "legacy_let_syntax", # W05
|
||||
"collapsible_let_in", # W06
|
||||
# "eta_reduction", # W07
|
||||
# "useless_parens", # W08
|
||||
"empty_pattern", # W10
|
||||
# "redundant_pattern_bind", # W11
|
||||
# "unquoted_uri", # W12
|
||||
# "deprecated_is_null", # W13
|
||||
# "empty_inherit", # W14
|
||||
# "faster_groupby", # W15
|
||||
# "faster_zipattrswith", # W16
|
||||
# "deprecated_to_path", # W17
|
||||
# "bool_simplification", # W18
|
||||
# "useless_has_attr", # W19
|
||||
"repeated_keys", # W20
|
||||
"empty_list_concat", # W23
|
||||
]
|
||||
@@ -3,10 +3,10 @@
|
||||
{
|
||||
users.users.amalieem = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
extraGroups = [ "wheel" ];
|
||||
shell = pkgs.zsh;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPsMtFIj4Dem/onwMoWYbosOcU4y7A5nTjVwqWaU33E1 amalieem@matey-aug22"
|
||||
];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{
|
||||
users.users.jonmro = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" "drift" "nix-builder-users" ];
|
||||
extraGroups = [ "wheel" "drift" "nix-builder-users" ];
|
||||
shell = pkgs.zsh;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEm5PfYmfl/0fnAP/3coVlvTw3/TYNLT6r/NwJHZbLAK jonrodtang@gmail.com"
|
||||
|
||||
Reference in New Issue
Block a user