Compare commits

..

28 commits

Author SHA1 Message Date
ed285ba79d feat(scripts/liminix): fail HARD and support root prefixes
Now that we possess the levitation technology, it's necessary to support
root prefixes for rebuild otherwise we will just overwrite our RAM disk
configuration.

Also, to avoid any issue, let's fail hard and avoid rebooting while
being in levitation for nothing.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
d29deeae56 feat(ap01): use levitation for mass rebuilds
To deal with mass rebuild disk space requirements, we can just levitate.

In the future, we will use levitation as a general-purpose mechanism for
partition layout migration, etc.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
4ed0c435ba feat(ap01): write nixpkgs version in /etc
It's useful for debugging.
We should also track our own revisions at some point.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
c08d6c464f feat(ap01): re-enable 2GHz
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
46d07da404 fix(hive): misc fixes regarding the nixpkgs usage
Previously, we were using <nixpkgs> actually, we fixed liminix and this
file to ensure that we are instantiating the right nixpkgs.

This helps to deal with unexpected mass rebuilds.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:50:33 +02:00
99902d2bb8 chore: upgrade liminix
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-08 00:48:12 +02:00
c0ec57ef22 fix(ap01): bridge only once the WLAN is in operational state
It required a lot of technology, but hey, we now have it.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-07 21:14:27 +02:00
337a71a169 feat(scripts): add Android profile building via Nix
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 17:06:40 +02:00
9bf83a60fe fix(ap01): fix _one_ race condition when bridging the LAN
The remaining is hostapd notification that the WLAN interface is ready
to bridge.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:59:16 +02:00
994e593d3b chore(ap01): cleanup
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:58:44 +02:00
adb843dd8b feat(ap01): add ubus
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-05 14:58:38 +02:00
45b106190f feat(ap01): disable IPv6
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
0b94fb5ba7 feat(ap01): external RADIUS + DHCPv4 + jitterRNGd + stable bridge + default route
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
4fb39070bb fix(sources): update to the latest version of Liminix
With bridge fixes and many other things.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 18:08:41 +02:00
47231417cc feat(liminix-rebuild): support hive names directly
Thanks @catvayor, I'm so dumb.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-09-01 17:20:37 +02:00
afd92ab203 feat(devshell): add kanidm & freeradius
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:38:07 +02:00
270eb4b106 chore(ap01): cleanup
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:37:46 +02:00
04cb0a9f04 feat(scripts): add liminix-oriented scripts
- extraction for manual recovery via nandwrite
- liminix rebuild to interactively develop the AP

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:23:04 +02:00
c4d9d6d000 feat(ap01): enable fully RADIUS via internal RADIUS server
This adds two public keys.

For the private keys, heh…

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:23:04 +02:00
be1673c6aa feat(devshell): add liminix-related tools
serial console, deployment tools and TFTP tool

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-31 22:20:24 +02:00
8b66b2b7c3 feat: add access control for APs via our custom modules
It works!

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-22 18:45:40 +02:00
3ed6ecba31 feat: ensure that colmena repl can evaluate nodes.ap01
Bump to latest Liminix and use the new `defaults` function.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-08-22 15:28:34 +02:00
5a8fe24dce feat: achieve custom evaluation in the framework
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:13 +02:00
0a948e6148 feat: Specialize nixpkgs as a function of the system 2024-05-24 18:46:13 +02:00
41ca207b41 feat: wip! wip! wip! 2024-05-24 18:46:01 +02:00
aa6b082b81 feat: enable liminix-rebuild
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
17b2345a02 feat: add liminix-rebuild in the shell
Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
fde8f66ea7 feat: init Liminix evaluation system
Very rudimentary; undocumented, untested in production. This is for testing purposes.

Signed-off-by: Ryan Lahfa <ryan@dgnum.eu>
2024-05-24 18:46:01 +02:00
166 changed files with 1654 additions and 9410 deletions

View file

@ -9,192 +9,80 @@ on:
- main - main
jobs: jobs:
build_and_cache_krz01: build_compute01:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build compute01
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on compute01'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "krz01"
- uses: actions/upload-artifact@v3 build_storage01:
if: always()
with:
name: outputs_krz01
path: paths.txt
build_and_cache_compute01:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build storage01
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on storage01'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "compute01"
- uses: actions/upload-artifact@v3 build_vault01:
if: always()
with:
name: outputs_compute01
path: paths.txt
build_and_cache_storage01:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build vault01
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on vault01'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "storage01"
- uses: actions/upload-artifact@v3 build_web01:
if: always()
with:
name: outputs_storage01
path: paths.txt
build_and_cache_rescue01:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build web01
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on web01'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "rescue01"
- uses: actions/upload-artifact@v3 build_web02:
if: always()
with:
name: outputs_rescue01
path: paths.txt
build_and_cache_geo01:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build web02
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on web02'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "geo01"
- uses: actions/upload-artifact@v3 build_rescue01:
if: always()
with:
name: outputs_geo01
path: paths.txt
build_and_cache_geo02:
runs-on: nix runs-on: nix
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Build rescue01
run: nix-shell --run cache-node run: |
env: # Enter the shell
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" nix-shell --run 'colmena build --on rescue01'
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "geo02"
- uses: actions/upload-artifact@v3 push_to_cache:
if: always()
with:
name: outputs_geo02
path: paths.txt
build_and_cache_vault01:
runs-on: nix runs-on: nix
needs:
- build_compute01
- build_storage01
- build_vault01
- build_web01
- build_web02
- build_rescue01
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Build and cache the node - name: Push to cache
run: nix-shell --run cache-node run: nix-shell --run push-to-cache
env: env:
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/" ATTIC_ENDPOINT: "https://cachix.dgnum.eu"
STORE_USER: "admin" ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "vault01"
- uses: actions/upload-artifact@v3
if: always()
with:
name: outputs_vault01
path: paths.txt
build_and_cache_web01:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build and cache the node
run: nix-shell --run cache-node
env:
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/"
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "web01"
- uses: actions/upload-artifact@v3
if: always()
with:
name: outputs_web01
path: paths.txt
build_and_cache_web02:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build and cache the node
run: nix-shell --run cache-node
env:
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/"
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "web02"
- uses: actions/upload-artifact@v3
if: always()
with:
name: outputs_web02
path: paths.txt
build_and_cache_bridge01:
runs-on: nix
steps:
- uses: actions/checkout@v3
- name: Build and cache the node
run: nix-shell --run cache-node
env:
STORE_ENDPOINT: "https://tvix-store.dgnum.eu/infra-signing/"
STORE_USER: "admin"
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
BUILD_NODE: "bridge01"
- uses: actions/upload-artifact@v3
if: always()
with:
name: outputs_web02
path: paths.txt

View file

@ -1,5 +1,5 @@
name: lint name: lint
on: [push, pull_request] on: push
jobs: jobs:
check: check:
@ -8,4 +8,4 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Run pre-commit on all files - name: Run pre-commit on all files
run: nix-shell --run 'pre-commit run --all-files --hook-stage pre-push --show-diff-on-failure' -A shells.pre-commit ./. run: nix-shell --run 'pre-commit run --all-files --show-diff-on-failure' -A shells.pre-commit ./.

107
README.md
View file

@ -8,110 +8,3 @@ Some instruction on how to contribute are available (in french) in [/CONTRIBUTE.
You're expected to read this document before commiting to the repo. You're expected to read this document before commiting to the repo.
Some documentation for the development tools are provided in the aforementioned file. Some documentation for the development tools are provided in the aforementioned file.
# Using the binary cache
Add the following module to your configuration (and pin this repo using your favorite tool: npins, lon, etc...):
```
{ lib, ... }:
let
dgnum-infra = PINNED_PATH_TO_INFRA;
in {
nix.settings = (import dgnum-infra { }).mkCacheSettings {
caches = [ "infra" ];
};
}
```
# Adding a new machine
The first step is to create a minimal viable NixOS host, using tha means necessary.
The second step is to find a name for this host, it must be unique from the other hosts.
> [!TIP]
> For the rest of this part, we assume that the host is named `host02`
## Download the keys
The public SSH keys of `host02` have to be saved to `keys`, preferably only the `ssh-ed25519` one.
It can be retreived with :
```bash
ssh-keyscan address.of.host02 2>/dev/null | awk '/ssh-ed25519/ {print $2,$3}'
```
## Initialize the machine folder and configuration
- Create a folder `host02` under `machines/`
- Copy the hardware configuration file generated by `nixos-generate-config` to `machines/host02/_hardware-configuration.nix`
- Create a `machines/host02/_configuration.nix` file, it will contain the main configuration options, the basic content of this file should be the following
```nix
{ lib, ... }:
lib.extra.mkConfig {
enabledModules = [
# List of modules to enable
];
enabledServices = [
# List of services to enable
];
extraConfig = {
services.netbird.enable = true;
};
root = ./.;
}
```
## Fill in the metadata
### Network configuration
The network is declared in `meta/network.nix`, the necessary `hostId` value can be generated with :
```bash
head -c4 /dev/urandom | od -A none -t x4 | sed 's/ //'
```
### Other details
The general metadata is declared in `meta/nodes.nix`, the main values to declare are :
- `site`, where the node is physically located
- `stateVersion`
- `nixpkgs`, the nixpkgs version to use
## Initialize secrets
Create the directory `secrets` in the configuration folder, and add a `secrets.nix` file containing :
```nix
(import ../../../keys).mkSecrets [ "host02" ] [
# List of secrets for host02
]
```
This will be used for future secret management.
## Update encrypted files
Both the Arkheon, Netbox and notification modules have secrets that are deployed on all machines. To make those services work correctly, run in `modules/dgn-records`, `modules/dgn-netbox-agent` and `modules/dgn-notify` :
```bash
agenix -r
```
## Commit and create a PR
Once all of this is done, check that the configuration builds correctly :
```bash
colmena build --on host02
```
Apply it, and create a Pull Request.

View file

@ -34,36 +34,25 @@
termes. termes.
*/ */
{
sources ? import ./npins,
pkgs ? import sources.nixpkgs { },
nix-pkgs ? import sources.nix-pkgs { inherit pkgs; },
}:
let let
git-checks = (import (builtins.storePath sources.git-hooks)).run { sources = import ./npins;
pkgs = import sources.nixpkgs { };
pre-commit-check = (import sources.pre-commit-hooks).run {
src = ./.; src = ./.;
hooks = { hooks = {
statix = { # Nix Hooks
statix.enable = true;
deadnix.enable = true;
rfc101 = {
enable = true; enable = true;
stages = [ "pre-push" ];
settings.ignore = [ name = "RFC-101 formatting";
"**/lon.nix" entry = "${pkgs.lib.getExe pkgs.nixfmt-rfc-style}";
"**/npins" files = "\\.nix$";
];
};
deadnix = {
enable = true;
stages = [ "pre-push" ];
};
nixfmt-rfc-style = {
enable = true;
stages = [ "pre-push" ];
}; };
# Misc Hooks
commitizen.enable = true; commitizen.enable = true;
}; };
}; };
@ -76,27 +65,28 @@ in
dns = import ./meta/dns.nix; dns = import ./meta/dns.nix;
mkCacheSettings = import ./machines/storage01/tvix-cache/cache-settings.nix;
shells = { shells = {
default = pkgs.mkShell { default = pkgs.mkShell {
name = "dgnum-infra"; name = "dgnum-infra";
packages = [ packages =
(pkgs.nixos-generators.overrideAttrs (_: { (with pkgs; [
version = "1.8.0-unstable"; npins
src = builtins.storePath sources.nixos-generators; nixos-generators
})) attic-client
pkgs.npins picocom
kanidm # for remote SSO operations
(pkgs.callPackage ./lib/colmena { inherit (nix-pkgs) colmena; }) freeradius # for radtest
(pkgs.callPackage "${sources.agenix}/pkgs/agenix.nix" { }) (callPackage (sources.liminix + "/pkgs/min-copy-closure") { nix = pkgs.lix; })
(pkgs.callPackage "${sources.lon}/nix/packages/lon.nix" { }) (callPackage (sources.liminix + "/pkgs/min-collect-garbage") { nix = pkgs.lix; })
(callPackage (sources.liminix + "/pkgs/tufted") { })
] ++ (import ./scripts { inherit pkgs; }); (callPackage (sources.disko + "/package.nix") { })
(callPackage ./lib/colmena { colmena = import sources.colmena; })
])
++ (import ./scripts { inherit pkgs; });
shellHook = '' shellHook = ''
${git-checks.shellHook} ${pre-commit-check.shellHook}
''; '';
preferLocalBuild = true; preferLocalBuild = true;
@ -106,7 +96,7 @@ in
name = "pre-commit-shell"; name = "pre-commit-shell";
shellHook = '' shellHook = ''
${git-checks.shellHook} ${pre-commit-check.shellHook}
''; '';
}; };
}; };

147
hive.nix
View file

@ -1,47 +1,90 @@
let let
sources' = import ./npins; sources = import ./npins;
# Patch sources directly lib = import (sources.nix-lib + "/src/trivial.nix");
sources = builtins.mapAttrs (patch.base { pkgs = import sources'.nixos-unstable { }; }) lib' = (import sources.nixos-unstable { }).lib;
.applyPatches' sources';
nix-lib = import ./lib/nix-lib; patch = import sources.nix-patches { patchFile = ./patches; };
patch = import ./lib/nix-patches { patchFile = ./patches; };
nodes' = import ./meta/nodes.nix; nodes' = import ./meta/nodes.nix;
nodes = builtins.attrNames nodes'; nodes = builtins.attrNames nodes';
mkNode = node: { mkNode = node: {
# Import the base configuration for each node # Import the base configuration for each node
imports = [ ./machines/${node}/_configuration.nix ]; imports = builtins.map (lib.mkRel (./machines/${node})) [
"_configuration.nix"
"_hardware-configuration.nix"
];
deployment.systemType = systemType node;
}; };
nixpkgs' = import ./meta/nixpkgs.nix; nixpkgs' = import ./meta/nixpkgs.nix;
# All supported nixpkgs versions, instanciated # All supported nixpkgs versions, instanciated
nixpkgs = nix-lib.mapSingleFuse mkNixpkgs nixpkgs'.supported; nixpkgs = lib.mapSingleFuse (
s: lib.mapSingleFuse (mkSystemNixpkgs s) nixpkgs'.versions.supported
) nixpkgs'.systems.supported;
# Get the configured nixos version for the node, # Get the configured nixos version for the node,
# defaulting to the one defined in meta/nixpkgs # defaulting to the one defined in meta/nixpkgs
version = node: nodes'.${node}.nixpkgs or nixpkgs'.default; version = node: nodes'.${node}.nixpkgs or nixpkgs'.versions.default;
system = node: nodes'.${node}.system or nixpkgs'.systems.default;
systemType =
node:
nodes'.${node}.system
or (lib'.warn "Not specifying the `deployment.systemType` is deprecated!" "nixos");
# Builds a patched version of nixpkgs, only as the source # Builds a patched version of nixpkgs, only as the source
mkNixpkgs' = mkNixpkgs' =
v: v:
patch.mkNixpkgsSrc rec { let
src = sources'.${name}; version = "nixos-${v}";
name = "nixos-${v}"; in
patch.mkNixpkgsSrc {
src = sources.${version};
inherit version;
}; };
# Instanciates the required nixpkgs version mkNixpkgsConfigPerSystem =
mkNixpkgs = version: import (mkNixpkgs' version) { }; system: _:
if system == "nixos" then
{ }
else
(import "${sources.liminix}/devices/${system}").system
// {
overlays = [ (import "${sources.liminix}/overlay.nix") ];
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.8" # Python < 3 is needed for kernel backports.
];
};
};
# Instanciate a specialized version of nixpkgs
mkSystemNixpkgs =
system: version:
let
args = mkNixpkgsConfigPerSystem system version;
in
import (mkNixpkgs' version) args;
### ###
# Function to create arguments based on the node # Function to create arguments based on the node
# #
mkArgs = node: rec { mkArgs =
lib = nixpkgs.${version node}.lib // { node:
extra = nix-lib; let
pkgs = nixpkgs.${system node};
in
rec {
lib = import sources.nix-lib {
inherit (pkgs.${version node}) lib;
nixpkgs = pkgs;
keysRoot = ./keys;
}; };
meta = (import ./meta) lib; meta = (import ./meta) lib;
@ -51,37 +94,43 @@ let
in in
{ {
meta = { registry = {
nodeNixpkgs = nix-lib.mapSingleFuse (n: nixpkgs.${version n}) nodes; zyxel-nwa50ax = {
evalConfig = import "${sources.liminix}/lib/eval-config.nix" {
specialArgs = { nixpkgs = sources.nixos-unstable;
inherit nixpkgs sources;
dgn-keys = import ./keys;
}; };
nodeSpecialArgs = nix-lib.mapSingleFuse mkArgs nodes; defaults = _: {
nixpkgs = {
source = sources.nixos-unstable;
config = {
allowUnsupportedSystem = true; # mipsel
permittedInsecurePackages = [
"python-2.7.18.8" # Python < 3 is needed for kernel backports.
];
};
hostPlatform = {
config = "mipsel-unknown-linux-musl";
gcc = {
abi = "32";
arch = "mips32"; # mips32r2?
};
}; };
# It's impure, but who cares?
# Can Flakes do that?
buildPlatform = builtins.currentSystem;
};
};
};
nixos = {
evalConfig = import "${sources.nixos-unstable}/nixos/lib/eval-config.nix";
defaults = defaults =
{ { nodeMeta, name, ... }:
pkgs,
name,
nodeMeta,
...
}:
{ {
# Import the default modules # Import the default modules
imports = [ imports = [ ./modules ];
./modules
(import "${sources.lix-module}/module.nix" {
lix = pkgs.applyPatches {
name = "lix-2.90.patched";
src = sources.lix;
patches = [ ./patches/00-disable-installChecks-lix.patch ];
};
})
];
# Include default secrets # Include default secrets
age-secrets.sources = [ ./machines/${name}/secrets ]; age-secrets.sources = [ ./machines/${name}/secrets ];
@ -109,5 +158,17 @@ in
inherit (nodeMeta) stateVersion; inherit (nodeMeta) stateVersion;
}; };
}; };
};
};
meta = {
nodeNixpkgs = lib.mapSingleFuse (n: nixpkgs.${system n}.${version n}) nodes;
specialArgs = {
inherit sources;
};
nodeSpecialArgs = lib.mapSingleFuse mkArgs nodes;
};
} }
// (nix-lib.mapSingleFuse mkNode nodes) // (lib.mapSingleFuse mkNode nodes)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
NIXPKGS=$(nix-build --no-out-link nixpkgs.nix) NIXPKGS=$(nix-build nixpkgs.nix)
nixos-generate -c configuration.nix -I NIX_PATH="$NIXPKGS" -f install-iso nixos-generate -c configuration.nix -I NIX_PATH="$NIXPKGS" -f install-iso

View file

@ -1,9 +1,9 @@
{ lib, pkgs, ... }: { lib, pkgs, ... }:
let let
dgn-keys = import ../keys; dgn-lib = import ../lib { };
dgn-members = (import ../meta lib).organization.groups.root; dgn-members = (import ../meta lib).members.groups.root;
in in
{ {
@ -11,7 +11,7 @@ in
boot = { boot = {
blacklistedKernelModules = [ "snd_pcsp" ]; blacklistedKernelModules = [ "snd_pcsp" ];
kernelPackages = pkgs.linuxPackages_latest; kernelPackages = pkgs.linuxPackages_6_1;
tmp.cleanOnBoot = true; tmp.cleanOnBoot = true;
loader = { loader = {
@ -22,7 +22,6 @@ in
supportedFilesystems = [ supportedFilesystems = [
"exfat" "exfat"
"zfs" "zfs"
"bcachefs"
]; ];
swraid.enable = lib.mkForce false; swraid.enable = lib.mkForce false;
@ -34,5 +33,7 @@ in
openssh.enable = true; openssh.enable = true;
}; };
users.users.root.openssh.authorizedKeys.keys = dgn-keys.getKeys dgn-members; users.users.root.openssh.authorizedKeys.keyFiles = builtins.map (
m: dgn-lib.mkRel ../keys "${m}.keys"
) dgn-members;
} }

View file

@ -1,6 +1,5 @@
let let
version = (import ../meta/nixpkgs.nix).default; inherit (import ../npins) nixpkgs;
nixpkgs = (import ../npins)."nixos-${version}";
in in
(import nixpkgs { }).srcOnly { (import nixpkgs { }).srcOnly {

1
keys/catvayor.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAA16foz+XzwKwyIR4wFgNIAE3Y7AfXyEsUZFVVz8Rie catvayor@katvayor

View file

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC6TCCAdECFEbjeqNNzKWyfs2GJekipWK+yO4uMA0GCSqGSIb3DQEBCwUAMHMx
NDAyBgNVBAMMK0RHTnVtIFRlc3QgQVAgQ0EgLS0gRE8gTk9UIFVTRSBPUiBHRVQg
RklSRUQxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwGA1UEBwwFUGFy
aXMxDjAMBgNVBAoMBURHTnVtMB4XDTI0MDgyNjE5MDQxMFoXDTI2MDgyNjE5MDQx
MFowdzE4MDYGA1UEAwwvREdOdW0gVGVzdCBBUCBzZXJ2ZXIgLS0gRE8gTk9UIFVT
RSBPUiBHRVQgRklSRUQxCzAJBgNVBAYTAkZSMQ4wDAYDVQQIDAVQYXJpczEOMAwG
A1UEBwwFUGFyaXMxDjAMBgNVBAoMBURHTnVtMIGbMBAGByqGSM49AgEGBSuBBAAj
A4GGAAQBDrTf0SH/YOkOfvOSnB3BbICb80jSsxwQH50y4jylbXcrUZnegLYjW/lF
QknuMBzzE5fnE9lAeOxqsn0ec+sL3zEBrV0LSG2LgxhAkahZS9U4Spt9Qc84U7cG
AFQ3GXDMTEb/COHJSu7sIfV4gFRVesFez30gb94lMxckkq/6nkXXaEUwDQYJKoZI
hvcNAQELBQADggEBAEfPHMAXwftYQ0lDYPlr9b+GZDl7/JAavEfBXKzj1U8O0sJz
daNOHEX3a5ZOaQoean2zmBLROgQpDlwsjAFNA9dg0ef2f4RgJvr/l2fspHwG0Uaq
4JEOKTj3htd8aZX2i6AR02UC2oxCtf7ZVa+a6NOeeKl53QPzjduPO60ruz8tD2Xr
YnQwVinQX0fJo7TmyQKDIxwld/Q5pMoDMfVlS71M/vISFfQ/Rx1PqYvBQyG1dvIA
qn9cNNVnjEGrk7zXjCfehMYiCtDZ+D3VyXeZ6A7YZNpc6RUj8rbWcOtKLayRFlwf
DTjV3/nPqV0M2nU6jXFBMfQ47VSfB7ibINt94xo=
-----END CERTIFICATE-----

View file

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIIDxzCCAq+gAwIBAgIUPuHEZeZoCidp+w5ME2CrkZEn3T8wDQYJKoZIhvcNAQEL
BQAwczE0MDIGA1UEAwwrREdOdW0gVGVzdCBBUCBDQSAtLSBETyBOT1QgVVNFIE9S
IEdFVCBGSVJFRDELMAkGA1UEBhMCRlIxDjAMBgNVBAgMBVBhcmlzMQ4wDAYDVQQH
DAVQYXJpczEOMAwGA1UECgwFREdOdW0wHhcNMjQwODI2MTg1ODQ4WhcNMjkwODI2
MTg1ODQ4WjBzMTQwMgYDVQQDDCtER051bSBUZXN0IEFQIENBIC0tIERPIE5PVCBV
U0UgT1IgR0VUIEZJUkVEMQswCQYDVQQGEwJGUjEOMAwGA1UECAwFUGFyaXMxDjAM
BgNVBAcMBVBhcmlzMQ4wDAYDVQQKDAVER051bTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAKLgCNXLI6FQWJY5JQDqZcO1hmZpp0upT59/JvJXmEl4St1O
FF3frSAoFcgn2Bv3kYQQ6wEhD3S7JBxRmoDtx/7sqsXthNpBaymVdphb9XhnVOC2
NDBKV4WH06Hr06oKVfDSBhIldPJr1vfQLehOnz6uqK7walqPvid3tMv0lwt7mHZ9
qQpgC2C/tkHwD1kh1RszoIZKIQWDnSNXPhYnB3X/DMCUWIKiz6P/0rVANEDDZER6
b6eJRjv2l8jPlOt7CUTAOrsoJGCnSg2SV4lgr1u3mE/2AvmLdO0l5Dz0qCuQNbb3
uWqYUonooR8rox171On/Rd0zvtihycSDxofVJ+MCAwEAAaNTMFEwHQYDVR0OBBYE
FIPUT3v8AoeBS6VbcEvgVc1dC38hMB8GA1UdIwQYMBaAFIPUT3v8AoeBS6VbcEvg
Vc1dC38hMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBACX1aqYU
9PIwZ/dBS7cpsBsCm9M0ueInTlQpvv6xioKuPhIet40YgawTRakxniAr0WXHTBV5
a8ZQ4ff4uI+sdaxN7Ueufr4ltWVLuSc9DfIxjLVZ+41G6Ehy9Xc2zoDBfYURrXjd
ISvPSXIKjM0yuS/249C77HOdzwbliS65Io2zubQStGfSaZ3sLAfPJoig+QiVyOtG
sPoYzzrjXDBym+plfGTWqHv+gwo6DZarXrK4yaMn4hYkkf95NsY2ywwHzcy/4hsu
+bMm4IeCrB9uNOZtQrqW81/+4oxjGiKLbhnFPNQOg2pzb+iOJTPKVicAqKDSCnou
WXG5pjBKzojPvxU=
-----END CERTIFICATE-----

View file

@ -1,80 +0,0 @@
let
_sources = import ../npins;
meta = import ../meta (import _sources.nixpkgs { }).lib;
getAttr = flip builtins.getAttr;
inherit (import ../lib/nix-lib) flip setDefault unique;
in
rec {
# WARNING: When updating this list, make sure that the nodes and members are alphabetically sorted
# If not, you will face an angry maintainer
_keys = {
# SSH keys of the nodes
bridge01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP5bS3iBXz8wycBnTvI5Qi79WLu0h4IVv/EOdKYbP5y7" ];
compute01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE/YluSVS+4h3oV8CIUj0OmquyJXju8aEQy0Jz210vTu" ];
geo01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEl6Pubbau+usQkemymoSKrTBbrX8JU5m5qpZbhNx8p4" ];
geo02 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNXaCS0/Nsu5npqQk1TP6wMHCVIOaj4pblp2tIg6Ket" ];
krz01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP4o65gWOgNrxbSd3kiQIGZUM+YD6kuZOQtblvzUGsfB" ];
rescue01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJa02Annu8o7ggPjTH/9ttotdNGyghlWfU9E8pnuLUf" ];
storage01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0s+rPcEcfWCqZ4B2oJiWT/60awOI8ijL1rtDM2glXZ" ];
vault01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJA6VA7LENvTRlKdcrqt8DxDOPvX3bg3Gjy9mNkdFEW" ];
web01 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPR+lewuJ/zhCyizJGJOH1UaAB699ItNKEaeuoK57LY5" ];
web02 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID+QDE+GgZs6zONHvzRW15BzGJNW69k2BFZgB/Zh/tLX" ];
# SSH keys of the DGNum members
catvayor = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAA16foz+XzwKwyIR4wFgNIAE3Y7AfXyEsUZFVVz8Rie catvayor@katvayor"
];
ecoppens = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIGmU7yEOCGuGNt4PlQbzd0Cms1RePpo8yEA7Ij/+TdA" ];
gdd = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICE7TN5NQKGojNGIeTFiHjLHTDQGT8i05JFqX/zLW2zc"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFbkPWWZzOBaRdx4+7xQUgxDwuncSl2fxAeVuYfVUPZ"
];
jemagius = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOoxmou5OU74GgpIUkhVt6GiB+O9Jy4ge0TwK5MDFJ2F"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxQX0JLRah3GfIOkua4ZhEJhp5Ykv55RO0SPrSUwCBs5arnALg8gq12YLr09t4bzW/NA9/jn7flhh4S54l4RwBUhmV4JSQhGu71KGhfOj5ZBkDoSyYqzbu206DfZP5eQonSmjfP6XghcWOr/jlBzw9YAAQkFxsQgXEkr4kdn0ZXfZGz6b0t3YUjYIuDNbptFsGz2V9iQVy1vnxrjnLSfc25j4et8z729Vpy4M7oCaE6a6hgon4V1jhVbg43NAE5gu2eYFAPIzO3E7ZI8WjyLu1wtOBClk1f+HMen3Tr+SX2PXmpPGb+I2fAkbzu/C4X/M3+2bL1dYjxuvQhvvpAjxFwmdoXW4gWJ3J/FRiFrKsiAY0rYC+yi8SfacJWCv4EEcV/yQ4gYwpmU9xImLaro6w5cOHGCqrzYqjZc4Wi6AWFGeBSNzNs9PXLgMRWeUyiIDOFnSep2ebZeVjTB16m+o/YDEhE10uX9kCCx3Dy/41iJ1ps7V4JWGFsr0Fqaz8mu8="
];
luj = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMBW7rTtfZL9wtrpCVgariKdpN60/VeAzXkh9w3MwbO julien@enigma"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGa+7n7kNzb86pTqaMn554KiPrkHRGeTJ0asY1NjSbpr julien@tower"
];
mdebray = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpwF+XD3HgX64kqD42pcEZRNYAWoO4YNiOm5KO4tH6o maurice@polaris"
];
raito = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU"
];
thubrecht = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+EZXYziiaynJX99EW8KesnmRTZMof3BoIs3mdEl8L3"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHL4M4HKjs4cjRAYRk9pmmI8U0R4+T/jQh6Fxp/i1Eoy"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM1jpXR7BWQa7Sed7ii3SbvIPRRlKb3G91qC0vOwfJn"
];
};
getKeys = ls: builtins.concatLists (builtins.map (getAttr _keys) ls);
mkSecrets =
nodes: setDefault { publicKeys = unique (rootKeys ++ (builtins.concatMap getNodeKeys' nodes)); };
getNodeKeys' =
node:
let
names = builtins.foldl' (names: group: names ++ meta.organization.groups.${group}) (
meta.nodes.${node}.admins ++ [ node ]
) meta.nodes.${node}.adminGroups;
in
unique (getKeys names);
getNodeKeys = node: rootKeys ++ getNodeKeys' node;
# List of keys for the root group
rootKeys = getKeys meta.organization.groups.root;
# List of 'machine' keys
machineKeys = rootKeys ++ (getKeys (builtins.attrNames meta.nodes));
}

1
keys/ecoppens.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIGmU7yEOCGuGNt4PlQbzd0Cms1RePpo8yEA7Ij/+TdA

2
keys/gdd.keys Normal file
View file

@ -0,0 +1,2 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICE7TN5NQKGojNGIeTFiHjLHTDQGT8i05JFqX/zLW2zc
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIFbkPWWZzOBaRdx4+7xQUgxDwuncSl2fxAeVuYfVUPZ

2
keys/jemagius.keys Normal file
View file

@ -0,0 +1,2 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOoxmou5OU74GgpIUkhVt6GiB+O9Jy4ge0TwK5MDFJ2F
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCxQX0JLRah3GfIOkua4ZhEJhp5Ykv55RO0SPrSUwCBs5arnALg8gq12YLr09t4bzW/NA9/jn7flhh4S54l4RwBUhmV4JSQhGu71KGhfOj5ZBkDoSyYqzbu206DfZP5eQonSmjfP6XghcWOr/jlBzw9YAAQkFxsQgXEkr4kdn0ZXfZGz6b0t3YUjYIuDNbptFsGz2V9iQVy1vnxrjnLSfc25j4et8z729Vpy4M7oCaE6a6hgon4V1jhVbg43NAE5gu2eYFAPIzO3E7ZI8WjyLu1wtOBClk1f+HMen3Tr+SX2PXmpPGb+I2fAkbzu/C4X/M3+2bL1dYjxuvQhvvpAjxFwmdoXW4gWJ3J/FRiFrKsiAY0rYC+yi8SfacJWCv4EEcV/yQ4gYwpmU9xImLaro6w5cOHGCqrzYqjZc4Wi6AWFGeBSNzNs9PXLgMRWeUyiIDOFnSep2ebZeVjTB16m+o/YDEhE10uX9kCCx3Dy/41iJ1ps7V4JWGFsr0Fqaz8mu8=

2
keys/luj.keys Normal file
View file

@ -0,0 +1,2 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDMBW7rTtfZL9wtrpCVgariKdpN60/VeAzXkh9w3MwbO julien@enigma
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGa+7n7kNzb86pTqaMn554KiPrkHRGeTJ0asY1NjSbpr julien@tower

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE/YluSVS+4h3oV8CIUj0OmquyJXju8aEQy0Jz210vTu

1
keys/machines/geo01.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEl6Pubbau+usQkemymoSKrTBbrX8JU5m5qpZbhNx8p4

1
keys/machines/geo02.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFNXaCS0/Nsu5npqQk1TP6wMHCVIOaj4pblp2tIg6Ket

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJa02Annu8o7ggPjTH/9ttotdNGyghlWfU9E8pnuLUf

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA0s+rPcEcfWCqZ4B2oJiWT/60awOI8ijL1rtDM2glXZ

View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJA6VA7LENvTRlKdcrqt8DxDOPvX3bg3Gjy9mNkdFEW

1
keys/machines/web01.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPR+lewuJ/zhCyizJGJOH1UaAB699ItNKEaeuoK57LY5

1
keys/machines/web02.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE020zqMJTlJ73czVxWVNmRof6il+N9dS4Knm43bJSpm

1
keys/mdebray.keys Normal file
View file

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEpwF+XD3HgX64kqD42pcEZRNYAWoO4YNiOm5KO4tH6o maurice@polaris

3
keys/raito.keys Normal file
View file

@ -0,0 +1,3 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDcEkYM1r8QVNM/G5CxJInEdoBCWjEHHDdHlzDYNSUIdHHsn04QY+XI67AdMCm8w30GZnLUIj5RiJEWXREUApby0GrfxGGcy8otforygfgtmuUKAUEHdU2MMwrQI7RtTZ8oQ0USRGuqvmegxz3l5caVU7qGvBllJ4NUHXrkZSja2/51vq80RF4MKkDGiz7xUTixI2UcBwQBCA/kQedKV9G28EH+1XfvePqmMivZjl+7VyHsgUVj9eRGA1XWFw59UPZG8a7VkxO/Eb3K9NF297HUAcFMcbY6cPFi9AaBgu3VC4eetDnoN/+xT1owiHi7BReQhGAy/6cdf7C/my5ehZwD
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE0xMwWedkKosax9+7D2OlnMxFL/eV4CvFZLsbLptpXr
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU

3
keys/thubrecht.keys Normal file
View file

@ -0,0 +1,3 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL+EZXYziiaynJX99EW8KesnmRTZMof3BoIs3mdEl8L3
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHL4M4HKjs4cjRAYRk9pmmI8U0R4+T/jQh6Fxp/i1Eoy
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM1jpXR7BWQa7Sed7ii3SbvIPRRlKb3G91qC0vOwfJn

33
lib/default.nix Normal file
View file

@ -0,0 +1,33 @@
_:
let
sources = import ../npins;
lib = import sources.nix-lib {
inherit ((import sources.nixpkgs { })) lib;
keysRoot = ../keys;
};
meta = import ../meta lib;
inherit (lib.extra) getAllKeys;
in
lib.extra
// rec {
# Get publickeys associated to a node
getNodeKeys =
node:
let
names = builtins.foldl' (names: group: names ++ meta.organization.groups.${group}) (
meta.nodes.${node}.admins ++ [ "/machines/${node}" ]
) meta.nodes.${node}.adminGroups;
in
rootKeys ++ (getAllKeys names);
rootKeys = getAllKeys meta.organization.groups.root;
machineKeys =
rootKeys ++ (getAllKeys (builtins.map (n: "machines/${n}") (builtins.attrNames meta.nodes)));
}

View file

@ -1,197 +0,0 @@
# Copyright Tom Hubrecht, (2023)
#
# Tom Hubrecht <tom@hubrecht.ovh>
#
# This software is governed by the CeCILL license under French law and
# abiding by the rules of distribution of free software. You can use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
# "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
let
# Reimplement optional functions
_optional =
default: b: value:
if b then value else default;
in
rec {
inherit (import ./nixpkgs.nix)
flip
hasPrefix
recursiveUpdate
splitString
unique
;
/*
Fuses a list of attribute sets into a single attribute set.
Type: [attrs] -> attrs
Example:
x = [ { a = 1; } { b = 2; } ]
fuseAttrs x
=> { a = 1; b = 2; }
*/
fuseAttrs = builtins.foldl' (attrs: x: attrs // x) { };
fuseValueAttrs = attrs: fuseAttrs (builtins.attrValues attrs);
/*
Applies a function to `attrsList` before fusing the resulting list
of attribute sets.
Type: ('a -> attrs) -> ['a] -> attrs
Example:
x = [ "to" "ta" "ti" ]
f = s: { ${s} = s + s; }
mapFuse f x
=> { to = "toto"; ta = "tata"; ti = "titi"; }
*/
mapFuse =
# 'a -> attrs
f:
# ['a]
attrsList:
fuseAttrs (builtins.map f attrsList);
/*
Equivalent of lib.singleton but for an attribute set.
Type: str -> 'a -> attrs
Example:
singleAttr "a" 1
=> { a = 1; }
*/
singleAttr = name: value: { ${name} = value; };
# Enables a list of modules.
enableAttrs' =
enable:
mapFuse (m: {
${m}.${enable} = true;
});
enableModules = enableAttrs' "enable";
/*
Create an attribute set from a list of values, mapping those
values through the function `f`.
Example:
mapSingleFuse (x: "val-${x}") [ "a" "b" ]
=> { a = "val-a"; b = "val-b" }
*/
mapSingleFuse = f: mapFuse (x: singleAttr x (f x));
/*
Creates a relative path as a string
Type: path -> str -> path
Example:
mkRel /home/test/ "file.txt"
=> "/home/test/file.txt"
*/
mkRel = path: file: path + "/${file}";
setDefault =
default:
mapFuse (name: {
${name} = default;
});
mkBaseSecrets =
root:
mapFuse (secret: {
${secret}.file = mkRel root secret;
});
getSecrets = dir: builtins.attrNames (import (mkRel dir "secrets.nix"));
subAttr = attrs: name: attrs.${name};
subAttrs = attrs: builtins.map (subAttr attrs);
optionalList = _optional [ ];
optionalAttrs = _optional { };
optionalString = _optional "";
/*
Same as fuseAttrs but using `lib.recursiveUpdate` to merge attribute
sets together.
Type: [attrs] -> attrs
*/
recursiveFuse = builtins.foldl' recursiveUpdate { };
mkImport =
root: file:
let
path = mkRel root file;
in
path + (optionalString (!(builtins.pathExists path)) ".nix");
mkImports = root: builtins.map (mkImport root);
/*
Creates a confugiration by merging enabled modules,
services and extraConfig.
Example:
mkConfig {
enabledModules = [ "ht-defaults" ];
enabledServices = [ "toto" ];
extraConfig = { services.nginx.enable = true; };
root = ./.;
}
=>
{
imports = [ ./toto ];
ht-defaults.enable = true;
services.nginx.enable = true;
}
*/
mkConfig =
{
# List of modules to enable with `enableModules`
enabledModules,
# List of services to import
enabledServices,
# Extra configuration, defaults to `{ }`
extraConfig ? { },
# Path relative to which the enabled services will be imported
root,
}:
recursiveFuse [
(enableModules enabledModules)
{ imports = mkImports root ([ "_hardware-configuration" ] ++ enabledServices); }
extraConfig
];
}

View file

@ -1,416 +0,0 @@
###
# Collection of nixpkgs library functions, those are necessary for defining our own lib
#
# They have been simplified and builtins are used in some places, instead of lib shims.
rec {
/**
Does the same as the update operator '//' except that attributes are
merged until the given predicate is verified. The predicate should
accept 3 arguments which are the path to reach the attribute, a part of
the first attribute set and a part of the second attribute set. When
the predicate is satisfied, the value of the first attribute set is
replaced by the value of the second attribute set.
# Inputs
`pred`
: Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
`lhs`
: Left attribute set of the merge.
`rhs`
: Right attribute set of the merge.
# Type
```
recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.recursiveUpdateUntil` usage example
```nix
recursiveUpdateUntil (path: l: r: path == ["foo"]) {
# first attribute set
foo.bar = 1;
foo.baz = 2;
bar = 3;
} {
#second attribute set
foo.bar = 1;
foo.quz = 2;
baz = 4;
}
=> {
foo.bar = 1; # 'foo.*' from the second set
foo.quz = 2; #
bar = 3; # 'bar' from the first set
baz = 4; # 'baz' from the second set
}
```
:::
*/
recursiveUpdateUntil =
pred: lhs: rhs:
let
f =
attrPath:
builtins.zipAttrsWith (
n: values:
let
here = attrPath ++ [ n ];
in
if builtins.length values == 1 || pred here (builtins.elemAt values 1) (builtins.head values) then
builtins.head values
else
f here values
);
in
f [ ] [
rhs
lhs
];
/**
A recursive variant of the update operator //. The recursion
stops when one of the attribute values is not an attribute set,
in which case the right hand side value takes precedence over the
left hand side value.
# Inputs
`lhs`
: Left attribute set of the merge.
`rhs`
: Right attribute set of the merge.
# Type
```
recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
```
# Examples
:::{.example}
## `lib.attrsets.recursiveUpdate` usage example
```nix
recursiveUpdate {
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/hda";
} {
boot.loader.grub.device = "";
}
returns: {
boot.loader.grub.enable = true;
boot.loader.grub.device = "";
}
```
:::
*/
recursiveUpdate =
lhs: rhs:
recursiveUpdateUntil (
_: lhs: rhs:
!(builtins.isAttrs lhs && builtins.isAttrs rhs)
) lhs rhs;
/**
Determine whether a string has given prefix.
# Inputs
`pref`
: Prefix to check for
`str`
: Input string
# Type
```
hasPrefix :: string -> string -> bool
```
# Examples
:::{.example}
## `lib.strings.hasPrefix` usage example
```nix
hasPrefix "foo" "foobar"
=> true
hasPrefix "foo" "barfoo"
=> false
```
:::
*/
hasPrefix = pref: str: (builtins.substring 0 (builtins.stringLength pref) str == pref);
/**
Escape occurrence of the elements of `list` in `string` by
prefixing it with a backslash.
# Inputs
`list`
: 1\. Function argument
`string`
: 2\. Function argument
# Type
```
escape :: [string] -> string -> string
```
# Examples
:::{.example}
## `lib.strings.escape` usage example
```nix
escape ["(" ")"] "(foo)"
=> "\\(foo\\)"
```
:::
*/
escape = list: builtins.replaceStrings list (builtins.map (c: "\\${c}") list);
/**
Convert a string `s` to a list of characters (i.e. singleton strings).
This allows you to, e.g., map a function over each character. However,
note that this will likely be horribly inefficient; Nix is not a
general purpose programming language. Complex string manipulations
should, if appropriate, be done in a derivation.
Also note that Nix treats strings as a list of bytes and thus doesn't
handle unicode.
# Inputs
`s`
: 1\. Function argument
# Type
```
stringToCharacters :: string -> [string]
```
# Examples
:::{.example}
## `lib.strings.stringToCharacters` usage example
```nix
stringToCharacters ""
=> [ ]
stringToCharacters "abc"
=> [ "a" "b" "c" ]
stringToCharacters "🦄"
=> [ "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" "<EFBFBD>" ]
```
:::
*/
stringToCharacters = s: builtins.genList (p: builtins.substring p 1 s) (builtins.stringLength s);
/**
Turn a string `s` into an exact regular expression
# Inputs
`s`
: 1\. Function argument
# Type
```
escapeRegex :: string -> string
```
# Examples
:::{.example}
## `lib.strings.escapeRegex` usage example
```nix
escapeRegex "[^a-z]*"
=> "\\[\\^a-z]\\*"
```
:::
*/
escapeRegex = escape (stringToCharacters "\\[{()^$?*+|.");
/**
Appends string context from string like object `src` to `target`.
:::{.warning}
This is an implementation
detail of Nix and should be used carefully.
:::
Strings in Nix carry an invisible `context` which is a list of strings
representing store paths. If the string is later used in a derivation
attribute, the derivation will properly populate the inputDrvs and
inputSrcs.
# Inputs
`src`
: The string to take the context from. If the argument is not a string,
it will be implicitly converted to a string.
`target`
: The string to append the context to. If the argument is not a string,
it will be implicitly converted to a string.
# Type
```
addContextFrom :: string -> string -> string
```
# Examples
:::{.example}
## `lib.strings.addContextFrom` usage example
```nix
pkgs = import <nixpkgs> { };
addContextFrom pkgs.coreutils "bar"
=> "bar"
```
The context can be displayed using the `toString` function:
```nix
nix-repl> builtins.getContext (lib.strings.addContextFrom pkgs.coreutils "bar")
{
"/nix/store/m1s1d2dk2dqqlw3j90jl3cjy2cykbdxz-coreutils-9.5.drv" = { ... };
}
```
:::
*/
addContextFrom = src: target: builtins.substring 0 0 src + target;
/**
Cut a string with a separator and produces a list of strings which
were separated by this separator.
# Inputs
`sep`
: 1\. Function argument
`s`
: 2\. Function argument
# Type
```
splitString :: string -> string -> [string]
```
# Examples
:::{.example}
## `lib.strings.splitString` usage example
```nix
splitString "." "foo.bar.baz"
=> [ "foo" "bar" "baz" ]
splitString "/" "/usr/local/bin"
=> [ "" "usr" "local" "bin" ]
```
:::
*/
splitString =
sep: s:
let
splits = builtins.filter builtins.isString (
builtins.split (escapeRegex (builtins.toString sep)) (builtins.toString s)
);
in
builtins.map (addContextFrom s) splits;
/**
Remove duplicate elements from the `list`. O(n^2) complexity.
# Inputs
`list`
: Input list
# Type
```
unique :: [a] -> [a]
```
# Examples
:::{.example}
## `lib.lists.unique` usage example
```nix
unique [ 3 2 3 4 ]
=> [ 3 2 4 ]
```
:::
*/
unique = builtins.foldl' (acc: e: if builtins.elem e acc then acc else acc ++ [ e ]) [ ];
/**
Flip the order of the arguments of a binary function.
# Inputs
`f`
: 1\. Function argument
`a`
: 2\. Function argument
`b`
: 3\. Function argument
# Type
```
flip :: (a -> b -> c) -> (b -> a -> c)
```
# Examples
:::{.example}
## `lib.trivial.flip` usage example
```nix
flip concat [1] [2]
=> [ 2 1 ]
```
:::
*/
flip =
f: a: b:
f b a;
}

View file

@ -1,110 +0,0 @@
# Copyright Tom Hubrecht, (2023-2024)
#
# Tom Hubrecht <tom@hubrecht.ovh>
#
# This software is governed by the CeCILL license under French law and
# abiding by the rules of distribution of free software. You can use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
# "http://www.cecill.info".
#
# As a counterpart to the access to the source code and rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty and the software's author, the holder of the
# economic rights, and the successive licensors have only limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading, using, modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean that it is complicated to manipulate, and that also
# therefore means that it is reserved for developers and experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and, more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
{
patchFile,
excludeGitHubManual ? true,
fetchers ? { },
}:
rec {
base =
{ pkgs }:
rec {
mkUrlPatch =
attrs:
pkgs.fetchpatch (
{
hash = pkgs.lib.fakeHash;
}
// attrs
// (pkgs.lib.optionalAttrs (excludeGitHubManual && !(builtins.hasAttr "includes" attrs)) {
excludes = (attrs.excludes or [ ]) ++ [ "nixos/doc/manual/*" ];
})
);
mkGitHubPatch =
{ id, ... }@attrs:
mkUrlPatch (
(builtins.removeAttrs attrs [ "id" ])
// {
url = "https://github.com/NixOS/nixpkgs/pull/${builtins.toString id}.diff";
}
);
mkCommitPatch =
{ sha, ... }@attrs:
mkUrlPatch (
(builtins.removeAttrs attrs [ "sha" ])
// {
url = "https://github.com/NixOS/nixpkgs/commit/${builtins.toString sha}.diff";
}
);
patchFunctions = {
commit = mkCommitPatch;
github = mkGitHubPatch;
remote = pkgs.fetchpatch;
static = attrs: attrs.path;
url = mkUrlPatch;
} // fetchers;
mkPatch =
{
_type ? "github",
...
}@attrs:
if builtins.hasAttr _type patchFunctions then
patchFunctions.${_type} (builtins.removeAttrs attrs [ "_type" ])
else
throw "Unknown patch type: ${builtins.toString _type}.";
mkPatches = v: builtins.map mkPatch ((import patchFile).${v} or [ ]);
applyPatches =
{
src,
name,
patches ? mkPatches name,
}:
if patches == [ ] then
src
else
pkgs.applyPatches {
inherit patches src;
name = "${name}-patched";
};
applyPatches' = name: src: applyPatches { inherit name src; };
};
mkNixpkgsSrc = { src, name }: (base { pkgs = import src { }; }).applyPatches { inherit src name; };
}

1
liminix-rebuild.nix Normal file
View file

@ -0,0 +1 @@
{ liminix-system }: (import ./liminix-hive.nix { }).${liminix-system}.primary

View file

@ -0,0 +1,259 @@
{
config,
pkgs,
modulesPath,
...
}:
let
inherit (pkgs.liminix.services) oneshot;
inherit (pkgs.pseudofile) symlink dir;
inherit (pkgs) serviceFns;
svc = config.system.service;
secrets-1 = {
ssid = "DGNum 2G prototype (N)";
};
secrets-2 = {
ssid = "DGNum 5G prototype (AX)";
};
baseParams = {
country_code = "FR";
hw_mode = "g";
channel = 6;
wmm_enabled = 1;
ieee80211n = 1;
ht_capab = "[LDPC][GF][HT40-][HT40+][SHORT-GI-40][MAX-AMSDU-7935][TX-STBC]";
auth_algs = 1;
wpa = 2;
wpa_pairwise = "TKIP CCMP";
rsn_pairwise = "CCMP";
};
radiusKeyMgmt = {
wpa_key_mgmt = "WPA-EAP";
};
modernParams = {
hw_mode = "a";
he_su_beamformer = 1;
he_su_beamformee = 1;
he_mu_beamformer = 1;
preamble = 1;
# Allow radar detection.
ieee80211d = 1;
ieee80211h = 1;
ieee80211ac = 1;
ieee80211ax = 1;
vht_capab = "[MAX-MPDU-7991][SU-BEAMFORMEE][SU-BEAMFORMER][RXLDPC][SHORT-GI-80][MAX-A-MPDU-LEN-EXP3][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][TX-STBC-2BY1][RX-STBC-1][MU-BEAMFORMER]";
vht_oper_chwidth = 1;
he_oper_chwidth = 1;
channel = 36;
vht_oper_centr_freq_seg0_idx = 42;
he_oper_centr_freq_seg0_idx = 42;
require_vht = 1;
};
clientRadius = {
ieee8021x = 1;
eapol_version = 2;
use_pae_group_addr = 1;
dynamic_vlan = 0;
vlan_tagged_interface = "lan";
};
externalRadius = {
# TODO: when we have proper IPAM, set the right value here.
own_ip_addr = "127.0.0.1";
nas_identifier = "ap01.dgnum.eu";
# No DNS here, hostapd do not support this mode.
auth_server_addr = "129.199.195.129";
auth_server_port = 1812;
auth_server_shared_secret = "read it online";
};
mkWifiSta =
params: interface: secrets:
svc.hostapd.build {
inherit interface;
package = pkgs.hostapd-radius;
params = params // secrets;
dependencies = [ config.services.jitter ];
};
in
rec {
imports = [
"${modulesPath}/wlan.nix"
"${modulesPath}/network"
"${modulesPath}/dhcp6c"
"${modulesPath}/hostapd"
"${modulesPath}/ssh"
"${modulesPath}/ntp"
"${modulesPath}/vlan"
"${modulesPath}/bridge"
"${modulesPath}/jitter-rng"
"${modulesPath}/pki"
"${modulesPath}/ubus"
../../modules/dgn-access-control.nix
# TODO: god that's so a fucking hack.
(import "${modulesPath}/../devices/zyxel-nwa50ax").module
];
hostname = "ap01-prototype";
# Get moar random please
services.jitter = svc.jitter-rng.build { };
services.ubus = svc.ubus.build { };
# SSH keys are handled by the access control module.
dgn-access-control.enable = true;
users.root = {
passwd = "$6$jVXFFOp8HBYmgINR$lutB4kvw.W1jlXRby9ZYAgBitQ32RxQdYAGN.s2x4ris8J07vM6tzlRBQoeLELOIEMClDzbciQV0itfHQnTqd1";
};
services.int = svc.bridge.primary.build {
ifname = "int";
macAddressFromInterface = config.hardware.networkInterfaces.lan;
};
services.bridge = svc.bridge.members.build {
primary = services.int;
members = {
lan.member = config.hardware.networkInterfaces.lan;
wlan0 = {
member = config.hardware.networkInterfaces.wlan0;
# Bridge only once hostapd is ready.
dependencies = [ config.services.hostap-1-ready ];
};
wlan1 = {
member = config.hardware.networkInterfaces.wlan1;
# Bridge only once hostapd is ready.
dependencies = [ config.services.hostap-2-ready ];
};
};
};
services.resolvconf = oneshot rec {
name = "resolvconf";
up = ''
. ${serviceFns}
( in_outputs ${name}
for i in $(output ${services.dhcpv4} dns); do
echo "nameserver $i" >> resolv.conf
done
)
'';
dependencies = [
config.services.dhcpv4
];
};
filesystem = dir {
etc = dir {
"resolv.conf" = symlink "${config.services.resolvconf}/.outputs/resolv.conf";
"nixpkgs.version" = {
type = "f";
file = "${pkgs.lib.version}";
mode = "0444";
};
};
};
services.dhcpv4 = svc.network.dhcp.client.build {
interface = config.services.int;
dependencies = [
config.services.hostname
config.services.bridge.components.lan
];
};
# TODO(raito): these won't work with RAs
# fix them in Liminix directly and re-enable.
# services.dhcpv6 = svc.dhcp6c.client.build {
# interface = config.services.int;
# dependencies = [
# config.services.hostname
# config.services.bridge
# ];
# };
# services.ipv6 = svc.dhcp6c.address.build {
# interface = config.services.int;
# client = config.services.dhcpv6;
# dependencies = [ config.services.hostname ];
# };
services.defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} router)";
target = "default";
dependencies = [ services.dhcpv4 ];
};
services.packet_forwarding = svc.network.forward.build { };
services.sshd = svc.ssh.build { allowRoot = true; };
services.ntp = config.system.service.ntp.build {
pools = {
"pool.ntp.org" = [ "iburst" ];
};
dependencies = [ config.services.jitter ];
};
boot.tftp = {
serverip = "192.0.2.10";
ipaddr = "192.0.2.12";
};
# wlan0 is the 2.4GHz interface.
services.hostap-1 = mkWifiSta (
baseParams // radiusKeyMgmt
) config.hardware.networkInterfaces.wlan0 secrets-1;
services.hostap-1-ready = svc.hostapd-ready.build {
interface = config.hardware.networkInterfaces.wlan0;
};
# wlan1 is the 5GHz interface, e.g. AX capable.
services.hostap-2 = mkWifiSta (
baseParams // clientRadius // externalRadius // radiusKeyMgmt // modernParams
) config.hardware.networkInterfaces.wlan1 secrets-2;
# Oneshot that waits until the hostapd has set the interface in operational state.
services.hostap-2-ready = svc.hostapd-ready.build {
interface = config.hardware.networkInterfaces.wlan1;
};
defaultProfile.packages = with pkgs; [
zyxel-bootconfig
min-collect-garbage
iwinfo
ifwait
# Levitate enable us to mass-reinstall the system on the fly.
(levitate.override {
config = {
imports = [
"${modulesPath}/network"
"${modulesPath}/ssh"
"${modulesPath}/hardware.nix"
"${modulesPath}/kernel"
"${modulesPath}/outputs/tftpboot.nix"
"${modulesPath}/outputs.nix"
];
services = {
# Simplest DHCPv4 we can find.
dhcpv4 = svc.network.dhcp.client.build {
interface = config.hardware.networkInterfaces.lan;
};
inherit (config.services) sshd;
defaultroute4 = svc.network.route.build {
via = "$(output ${services.dhcpv4} router)";
target = "default";
dependencies = [ config.services.dhcpv4 ];
};
};
defaultProfile.packages = [ mtdutils ];
# Only keep root, which should inherit from DGN access control's root permissions.
users.root = config.users.root;
};
})
];
}

View file

@ -0,0 +1 @@
{ }

View file

@ -1,20 +0,0 @@
{ lib, pkgs, ... }:
lib.extra.mkConfig {
enabledModules = [
# List of modules to enable
];
enabledServices = [
# List of services to enable
"network"
];
extraConfig = {
services.netbird.enable = true;
environment.systemPackages = [ pkgs.bcachefs-tools ];
};
root = ./.;
}

View file

@ -1,53 +0,0 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ modulesPath, pkgs, ... }:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"xhci_pci"
"ehci_pci"
"ahci"
"sd_mod"
"sr_mod"
];
};
kernelModules = [ "kvm-intel" ];
kernelPackages = pkgs.linuxPackages_latest;
supportedFilesystems.bcachefs = true;
};
fileSystems = {
"/" = {
device = "UUID=3da58b64-a2fd-428d-bde8-3a185e2f73fd";
fsType = "bcachefs";
options = [ "compression=zstd" ];
};
"/boot" = {
device = "/dev/disk/by-uuid/4D0A-AF11";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
};
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
# networking.interfaces.eno1.useDHCP = lib.mkDefault true;
# networking.interfaces.vlan-admin.useDHCP = lib.mkDefault true;
# networking.interfaces.vlan-uplink-oob.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = "x86_64-linux";
hardware.cpu.intel.updateMicrocode = true;
}

View file

@ -1,79 +0,0 @@
_:
{
networking = {
useNetworkd = true;
useDHCP = false;
nftables.enable = true;
firewall.allowedUDPPorts = [ 67 ];
};
systemd.network = {
networks = {
"10-eno1" = {
name = "eno1";
networkConfig = {
VLAN = [
"vlan-admin"
"vlan-uplink-oob"
];
LinkLocalAddressing = false;
LLDP = false;
EmitLLDP = false;
IPv6AcceptRA = false;
IPv6SendRA = false;
};
# address = [ "192.168.222.1/24" ];
};
"10-vlan-admin" = {
name = "vlan-admin";
# DHCP for the BMC
networkConfig.DHCPServer = "yes";
dhcpServerConfig = {
PoolOffset = 128;
EmitDNS = false;
EmitNTP = false;
EmitSIP = false;
EmitPOP3 = false;
EmitSMTP = false;
EmitLPR = false;
UplinkInterface = ":none";
};
address = [
"fd26:baf9:d250:8000::ffff/64"
"192.168.222.1/24"
];
};
"10-vlan-uplink-oob" = {
name = "vlan-uplink-oob";
networkConfig.DHCP = "ipv4";
};
};
netdevs = {
"10-vlan-admin" = {
netdevConfig = {
Name = "vlan-admin";
Kind = "vlan";
};
vlanConfig.Id = 3000;
};
"10-vlan-uplink-oob" = {
netdevConfig = {
Name = "vlan-uplink-oob";
Kind = "vlan";
};
vlanConfig.Id = 500;
};
};
};
}

View file

@ -1,3 +0,0 @@
(import ../../../keys).mkSecrets [ "bridg01" ] [
# List of secrets for bridge01
]

View file

@ -1,19 +1,17 @@
{ lib, ... }: { lib, ... }:
lib.extra.mkConfig { lib.extra.mkConfig {
# List of modules to enable
enabledModules = [ enabledModules = [
# INFO: This list needs to stay sorted alphabetically # List of modules to enable
"dgn-backups" "dgn-backups"
"dgn-chatops" "dgn-fail2ban"
"dgn-web" "dgn-web"
]; ];
# List of services to enable
enabledServices = [ enabledServices = [
# INFO: This list needs to stay sorted alphabetically # List of services to enable
"arkheon" "arkheon"
"dgsi" "signal-irc-bridge"
"ds-fr" "ds-fr"
"grafana" "grafana"
"hedgedoc" "hedgedoc"
@ -21,22 +19,24 @@ lib.extra.mkConfig {
"librenms" "librenms"
"mastodon" "mastodon"
"nextcloud" "nextcloud"
"ollama-proxy"
"outline" "outline"
"plausible" "plausible"
"postgresql" "postgresql"
"rstudio-server" "rstudio-server"
"satosa" "satosa"
"signal-irc-bridge"
"signald" "signald"
"stirling-pdf" "stirling-pdf"
"takumi"
"telegraf" "telegraf"
"vaultwarden" "vaultwarden"
"zammad" "zammad"
]; ];
extraConfig = { extraConfig = {
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
"sshd-bruteforce"
"sshd-timeout"
];
dgn-hardware.useZfs = true; dgn-hardware.useZfs = true;
services.netbird.enable = true; services.netbird.enable = true;

View file

@ -1,222 +0,0 @@
{
config,
lib,
pkgs,
utils,
sources,
...
}:
let
inherit (lib) toLower;
python =
let
python3 = pkgs.python312;
nix-pkgs = import sources.nix-pkgs { inherit pkgs python3; };
in
python3.override {
packageOverrides = _: _: {
inherit (nix-pkgs)
django-allauth
django-allauth-cas
django-browser-reload
django-bulma-forms
django-sass-processor
django-sass-processor-dart-sass
django-unfold
pykanidm
python-cas
loadcredential
xlwt
;
};
};
pythonEnv = python.withPackages (
ps:
[
ps.django
ps.gunicorn
ps.psycopg
ps.django-compressor
ps.django-import-export
# Local packages
ps.django-allauth
ps.django-allauth-cas
ps.django-browser-reload
ps.django-bulma-forms
ps.django-sass-processor
ps.django-sass-processor-dart-sass
ps.django-unfold
ps.loadcredential
ps.pykanidm
ps.python-cas
]
++ ps.django-allauth.optional-dependencies.saml
);
staticDrv = pkgs.stdenv.mkDerivation {
name = "dgsi-static";
src = sources.dgsi;
sourceRoot = "source/src";
nativeBuildInputs = [
pkgs.dart-sass
pythonEnv
];
configurePhase = ''
export DGSI_STATIC_ROOT=$out/static
export CREDENTIALS_DIRECTORY=$(pwd)/../.credentials
export DGSI_KANIDM_CLIENT="dgsi_test"
export DGSI_KANIDM_AUTH_TOKEN="fake.token"
export DGSI_X509_KEY=""
export DGSI_X509_CERT=""
'';
doBuild = false;
installPhase = ''
mkdir -p $out/static
python3 manage.py compilescss
python3 manage.py collectstatic
'';
};
in
{
users = {
users.nginx.extraGroups = [ "django-apps" ];
groups.django-apps = { };
};
systemd = {
services = {
dj-dgsi = {
description = "DGSI web app";
requires = [ "dj-dgsi.socket" ];
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"postgresql.service"
];
serviceConfig = {
DynamicUser = true;
LoadCredential = map (name: "${name}:${config.age.secrets."dgsi-${toLower name}_file".path}") [
"EMAIL_HOST_PASSWORD"
"KANIDM_AUTH_TOKEN"
"KANIDM_SECRET"
"SECRET_KEY"
"X509_CERT"
"X509_KEY"
];
RuntimeDirectory = "django-apps/dgsi";
StateDirectory = "django-apps/dgsi";
UMask = "0027";
User = "dj-dgsi";
Group = "django-apps";
WorkingDirectory = sources.dgsi;
ExecReload = "${lib.getExe' pkgs.coreutils "kill"} -s HUP $MAINPID";
KillMode = "mixed";
Type = "notify";
ExecStart = utils.escapeSystemdExecArgs [
(lib.getExe' pythonEnv "gunicorn")
"--workers"
4
"--bind"
"unix:/run/django-apps/dgsi.sock"
"--pythonpath"
"src"
"app.wsgi"
];
};
environment = {
DGSI_ALLOWED_HOSTS = builtins.toJSON [
"profil.dgnum.eu"
"dgsi.dgnum.eu"
];
DGSI_EMAIL_HOST = "kurisu.lahfa.xyz";
DGSI_EMAIL_HOST_USER = "web-services@infra.dgnum.eu";
DGSI_EMAIL_USE_SSL = builtins.toJSON true;
DGSI_FROM_EMAIL = "La Délégation Générale Numérique <noreply@infra.dgnum.eu>";
DGSI_SERVER_EMAIL = "dgsi@infra.dgnum.eu";
DGSI_KANIDM_CLIENT = "dgsi";
DGSI_KANIDM_URI = "https://sso.dgnum.eu";
DGSI_MEDIA_ROOT = "/var/lib/django-apps/dgsi/media";
DGSI_STATIC_ROOT = "${staticDrv}/static";
DGSI_DATABASES = builtins.toJSON {
default = {
ENGINE = "django.db.backends.postgresql";
NAME = "dj-dgsi";
};
};
DJANGO_SETTINGS_MODULE = "app.settings";
};
path = [ pythonEnv ];
preStart = ''
python3 src/manage.py migrate --no-input
'';
};
};
sockets."dj-dgsi" = {
description = "Socket for the DGSI Django Application";
wantedBy = [ "sockets.target" ];
socketConfig = {
ListenStream = "/run/django-apps/dgsi.sock";
SocketMode = "600";
SocketUser = config.services.nginx.user;
};
};
mounts = [
{
where = "/run/django-apps/dgsi/media";
what = "/var/lib/django-apps/dgsi/media";
options = "bind";
after = [ "dj-dgsi.service" ];
partOf = [ "dj-dgsi.service" ];
upheldBy = [ "dj-dgsi.service" ];
}
];
};
dgn-redirections.permanent."dgsi.dgnum.eu" = "profil.dgnum.eu";
services = {
postgresql = {
ensureDatabases = [ "dj-dgsi" ];
ensureUsers = [
{
name = "dj-dgsi";
ensureDBOwnership = true;
}
];
};
nginx.virtualHosts."profil.dgnum.eu" = {
enableACME = true;
forceSSL = true;
locations = {
"/".proxyPass = "http://unix:/run/django-apps/dgsi.sock";
"/static/".root = staticDrv;
"/media/".root = "/run/django-apps/dgsi";
};
};
};
}

View file

@ -1,4 +1,9 @@
(import ../../../../keys).mkSecrets [ "compute01" ] [ let
lib = import ../../../../lib { };
publicKeys = lib.getNodeKeys "compute01";
in
lib.setDefault { inherit publicKeys; } [
"kanidm-password_admin" "kanidm-password_admin"
"kanidm-password_idm_admin" "kanidm-password_idm_admin"
] ]

View file

@ -9,16 +9,22 @@ in
enable = true; enable = true;
hostName = host; hostName = host;
package = pkgs.nextcloud29; package = pkgs.nextcloud28;
https = true; https = true;
config = { config = {
overwriteProtocol = "https";
dbtype = "pgsql"; dbtype = "pgsql";
adminpassFile = config.age.secrets."nextcloud-adminpass_file".path; adminpassFile = config.age.secrets."nextcloud-adminpass_file".path;
adminuser = "thubrecht"; adminuser = "thubrecht";
defaultPhoneRegion = "FR";
trustedProxies = [ "::1" ];
objectstore.s3 = { objectstore.s3 = {
enable = true; enable = true;
@ -55,7 +61,7 @@ in
"opcache.max_accelerated_files" = "10000"; "opcache.max_accelerated_files" = "10000";
"opcache.memory_consumption" = "128"; "opcache.memory_consumption" = "128";
"opcache.revalidate_freq" = "1"; "opcache.revalidate_freq" = "1";
"opcache.fast_shutdown" = "0"; "opcache.fast_shutdown" = "1";
"openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt"; "openssl.cafile" = "/etc/ssl/certs/ca-certificates.crt";
catch_workers_output = "yes"; catch_workers_output = "yes";
}; };
@ -65,17 +71,11 @@ in
autoUpdateApps.enable = true; autoUpdateApps.enable = true;
settings = { extraOptions = {
overwriteprotocol = "https";
overwritehost = host; overwritehost = host;
"overwrite.cli.url" = "https://${host}"; "overwrite.cli.url" = "https://${host}";
updatechecker = false; updatechecker = false;
default_phone_region = "FR";
trusted_proxies = [ "::1" ];
allow_local_remote_servers = true; allow_local_remote_servers = true;
maintenance_window_start = 1; maintenance_window_start = 1;
@ -97,12 +97,15 @@ in
}; };
virtualisation.oci-containers = { virtualisation.oci-containers = {
# # Since 22.05, the default driver is podman but it doesn't work
# # with podman. It would however be nice to switch to podman.
# backend = "docker";
containers.collabora = { containers.collabora = {
image = "collabora/code"; image = "collabora/code";
imageFile = pkgs.dockerTools.pullImage { imageFile = pkgs.dockerTools.pullImage {
imageName = "collabora/code"; imageName = "collabora/code";
imageDigest = "sha256:07da8a191b37058514dfdf921ea8c2270c6634fa659acee774cf8594f86950e4"; imageDigest = "sha256:a8cce07c949aa59cea0a7f1f220266a1a6d886c717c3b5005782baf6f384d645";
sha256 = "sha256-5oaz07NQScHUVN/HznzZGQ2bGrU/V1GhI+9btXHz0GM="; sha256 = "sha256-lN6skv62x+x7G7SNOUyZ8W6S/uScrkqE1nbBwwSEWXQ=";
}; };
ports = [ "9980:9980" ]; ports = [ "9980:9980" ];
environment = { environment = {
@ -110,7 +113,6 @@ in
extra_params = "--o:ssl.enable=false --o:ssl.termination=true --o:remote_font_config.url=https://cloud.dgnum.eu/apps/richdocuments/settings/fonts.json"; extra_params = "--o:ssl.enable=false --o:ssl.termination=true --o:remote_font_config.url=https://cloud.dgnum.eu/apps/richdocuments/settings/fonts.json";
}; };
extraOptions = [ extraOptions = [
"--network=host"
"--cap-add" "--cap-add"
"MKNOD" "MKNOD"
"--cap-add" "--cap-add"

View file

@ -1,27 +0,0 @@
{
pkgs,
nodes,
meta,
...
}:
{
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts."ollama01.beta.dgnum.eu" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://${meta.network.krz01.netbirdIp}:${toString nodes.krz01.config.services.ollama.port}";
basicAuthFile = pkgs.writeText "ollama-htpasswd" ''
raito:$y$j9T$UDEHpLtM52hRGK0I4qT6M0$N75AhENLqgtJnTGaPzq51imhjZvuPr.ow81Co1ZTcX2
'';
};
};
};
networking.firewall.allowedTCPPorts = [
80
443
];
}

View file

@ -1,28 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA CQffZYaxexZ2f+HeNj+SHeSak0kzNPiq6ExW7tUyCBs
oJQhtMFD9KSnXSPGRb3zLwCB2/KEXo8cgxHN5ML83Qw
-> ssh-ed25519 QlRB9Q V1PnEYJvFCdBRzN4z3iDtIzHLxxCimejdkqRS4zMCG8
bVc87bxPmhofmoscGFBgQ+ffRlo216RiRkkV1MNoQyY
-> ssh-ed25519 r+nK/Q YI+1MYnCvSq5/QfA2y01IQlJeMGF0AfNs91QlrVaVGs
HSB8Gai96mjRbM68G3iRmXNkI4kqyJAWTMxWc8UOPr8
-> ssh-rsa krWCLQ
k2mssz4C9p8K+rJ6Jbbm+w7uLTqoUOiOKvlt2btEyw2Lup8PQNfyTNFSBvuBMmfj
re1zuAufH0HIw3B0xWYauBSD4pasc7EFTr/OLoM8BRFMEb11IM5ZKJrO+hnWy0Sk
eIs6cpkoBVi4GZmkRfbvaitk42i9JzjrKU0OeqLCWQbHmHkTb3acsGXCc6A6JSbF
AVb+Eaak6EIdX1dP4PWyCxU2PkcBtYBcLoGH74r1o0i3SzvmuzKvlBntx5IzsAvY
+QNGJLNZl0+NePafAkvVY8UOrlzxj+tCgfunAGXIXlZlVfNcjZX9Wv30sJOtwpbw
DdkJAqSrNkHianC5MEGgpA
-> ssh-ed25519 /vwQcQ yxGAMhwDcoDjw5MJudEE95PakhZvNpYfmfWiM6wbQBg
C1o3mNO2YFnBXamCcpAW0aQVGrNNcUpDtSn8+VLobmE
-> ssh-ed25519 0R97PA XRWbcwt3wXR3AYg0rhzc6OUuAA+blVTf3SHERYy3MkA
iCBd0E1NrV7tv3/0pD0FYWgUfGmB4M+VWfiixvVGv68
-> ssh-ed25519 JGx7Ng R47xTx4IGC/qf/v6WOXvJTd20MbeTdZ/8ovAA6d0iyQ
uBxcQVztpW4QaAR5rKfEVgtmrPk6l51+tY3brNjsTV4
-> ssh-ed25519 5SY7Kg LNtU+/1YlPX6T6gO2lb/wEei7hsy2oud8cTQXFQy0HY
xxPvBAIpFyCUqExjseerz6WlwWQEmw9fltzQBx51KI0
-> ssh-ed25519 p/Mg4Q uWIz5shMnsLXsh160cCW8E6kh9v4LPunOonugjWdSEY
5aRrIB5gxIplVWDGeMQ6g09togku6LxWRxBP7FbRNU0
-> ssh-ed25519 tDqJRg G8rNpeGY29czDVMvvt4LZ7nffZ/JAHDzxuIs7C/0SEM
HowgAvrQQcvUx93ZdK5q2bSsJDqaOxFf+x/lwTRss4I
--- ktcSPCC1TpguyYJ2ua7IuGcEw+Z9YuqjzcmH18abjo4
<EFBFBD><20><>ゥ煩 ネ9<1猤カワ簒<EFBE9C>pWJSWpsV/ム#<23>ウリ9タ{タ゚cHB<><42><EFBFBD>5<EFBFBD>ャ^ァ

View file

@ -1,30 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA zSfj75mxEod8RszD4XGaFIeMvcLnBgUHShIW5yFPdiE
YXaCFZ07BMzehG/PCUFDEzRy+y4c+IESO9kcLx+eG8M
-> ssh-ed25519 QlRB9Q 39DPdLnRMs5YSQOr/rY2nXO/8s/oCnYDkRex51tZayw
W3GbNP7qbgW2b0RoZmcWH0kLtQaIV50APGcntjMfn8o
-> ssh-ed25519 r+nK/Q dnX8kPKvyHS5U1N52QTDwonaHbBh8sv2DPBL1PoBO2E
mxduSFeWB4tJlrHDEthNKGv/vxzeWUtNwq1b2nDP6Z0
-> ssh-rsa krWCLQ
QN1OOmCREY2LljXm0+TAsOSkjIQ0RXyX8w5TVOOus5QAt1WTJan/mm4X1SviWqmn
UFDIeCoG2l5tBSyZr4VpnDeq7koWRA2eC7WnwWW47PQIRFSyjf+sy00rGR9kxVuL
1M9gsAGa5sud/PvmgSPSLsGhhrPsH/ZxN9beyIXIwmssmjN34KygUz9+u4T8IkVz
oxdq75LMzE2o0gcgC1EZ5+rDq0NSPQ9+1KgqwJuKlLKRXGdudgaVEUxX60g2ZnkX
8fNEgxqEkQ5MNnPfwbVumF6SWmMWyZSJ0rwHC94O1RdRNDcD3yKimuBmNSv2X+3L
cS3kE9LfNst2zBKHBGBOHQ
-> ssh-ed25519 /vwQcQ ZD8aiyO6fWEM9zG0iPP1/lftRPNl+mmFLHvGxVpSWzg
ZcTmN8zSHz8iLQmCLTZCdaqX5En/KrciR8KHwoXl8t0
-> ssh-ed25519 0R97PA xLQYBS5ozP1e4NWVa9yahN2OQB0Luw7mm3nBYdoHyRI
SKTRzLfGNFQ9fSX8ZFkKIYPZ4If5QrxcmSoBoGVG2Xk
-> ssh-ed25519 JGx7Ng XPo1QJ8OS/ShEAaXWwzZCS1p5/C6mLNlk4Us63YTVQ8
HGbfr8WBfCDKnIlATAeiE6JcLWCbn64vn1Cg7i9QGbA
-> ssh-ed25519 5SY7Kg CFpRcZmZ7DTspxkmdD8x7dRh1mqOHpTF7GzW5xBtLxw
n1n6/Ciwwo4rb3Cb6Yv/b1dHSvVAbCuDZ52maNpCexg
-> ssh-ed25519 p/Mg4Q km6ZjasKtOlaQL8rdVXkjRP4sooql15PrW0lz6YZaDg
Yrpi65IC3RJS3YSAChKjVyvowGxxmSPFkwa6CXUYVZ4
-> ssh-ed25519 tDqJRg au3x6e4L1os7OH4WXbdST74LhMsHPjP6KYrTWKUc1i8
zxKFk51MteTETWEu8peSH/lninM3zZkQi+Xjx5OQMTU
-> l$R6Y:c1-grease
MY0HS+ErZAtAhg
--- w+3gxmkrZ+xxSAQHbERgvsqur0v6k2/U0KUsfegRGcI
7Ú”gpò7šæ«¹Š\ŠE„àø~Â$±\¹Ä”Q„™H˜Èî¼¼2'k4Ž¥zÿqȦì'ÍNò!{@qxÎ,ƒ+iTû

View file

@ -1,31 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA xQaZW42vwq7pndbRqiATFVgl1QM3LbD5Sqzz61yinUY
7N4GIIAnzwTPA2IgOPWLtE03kCZPihKu8ZAG9e7Bv7k
-> ssh-ed25519 QlRB9Q mfs9SndrSY1meTEYiVxXLbS7Ecf0rjaQ3vX4626+9CI
BDdh3a02EqMeO5jPlz6kjmjuLMldf/s9V7hDkIef+g4
-> ssh-ed25519 r+nK/Q HqduuibujATQyp2TUswgrFyTdcdmPsNsZJ2pOLZ+MTc
WjFm95dxVYKA2ekOgKzMrMmk1nxfuurmDyMXtUIGnIo
-> ssh-rsa krWCLQ
GzznBXY+5RpGFJKli2rOdzO5bun6REyjA78nV8RviQdAN/mGXEZfGFq4HFuQZM0e
fYADtpZxOZ3vyY/9DqCguay3R02DcyTpAhdb6A3kdzApUVR/3ZKJXy0+l5qRqKD7
j/cMfIxk/WpsHKHDWKXkG+FiTnF+V+ZtUom9W1aYFc1506OdDbjBVfTnBFs/+WVf
MWd+Y0ANCFiNH+kjzvALRazkmJgt9SvYWBG6suym6YZ2073GFu85jUJB2juSDmBN
tp0OJvNrjH5F/CcJXLMVrJz4Azin+2iM+re78cSVmZ1aqLf72RIrg/VhuuNy2MVn
gU32t9qy5EvTbzliWpAvxw
-> ssh-ed25519 /vwQcQ rVT/tH4fZ49hwxJTaZMZhzMgkS0MJILZmuL/J1CCPGY
mW3BNdXsylo0Yhg2KYpGNLoDkd7DYX+NEGF8a7j5R5g
-> ssh-ed25519 0R97PA vnXhW5pn1XgOJcMcD1cu7hQLlnIrJyp2Bu3TbThBIik
QFQFocftqwsPS1AbGykbDkIWqaAdZ7I9njS2ZUXz+4w
-> ssh-ed25519 JGx7Ng ljVNZ4AdZ3DLow2m3mf+6bf9zj6+t9RP7w8Bi7aMlAI
E5Q9yEA3d2nPTZO2jFkGnsHyo3W19P/lSG6yl3RL6Vo
-> ssh-ed25519 5SY7Kg 2LcgbYRROFSGfq0L5XBQMl6p62DreGceGqRFzKGi4X8
x4V+gnzdm1HgjYwhBnYAldkchX4YCsUhqoq1iCaOZ6s
-> ssh-ed25519 p/Mg4Q Y+o5nrSvL+xL43OHjEnesKV+9gCl4H4gBmBBjbqDABA
TvGky1wSVanvpq2Xj2FUmRtJ205iq92g6PVDASAfyaE
-> ssh-ed25519 tDqJRg X0Y8YCi5qOy3Du1/DIMMc4W7P6zQNTlwF4+QrisHCwM
SzJPH+h5847WSl9CrJatqIf9CSnKGUQZDK6ROD5LqXU
-> `--grease N]PH
fdR7jONsDC5Fj/FU++dDsFJSa4sLmvnTzPbt3X96zJDHVQypmV+JMhQNudQGrq9K
7oPr3+cA61qtqUv6v519zFLtRXkpY6FMiB2euGJufVZqGh9jDzfi0jNu6dUO7A
--- a0TP8YPal5jgd3BSIm0THbaMHgLOiOgMqdlwQwUGzWk
:È/ Àn ž±Ý§¦p=fu²hãT¶ÅêF—ÙêÂ¥nh¢„¾•œ¹ÀU2#„éµÆ©“ºôâ>Û“<4.<2E>uŸ‰…m3Ü&<26>g¤(ö<>5 Û¶Ã

View file

@ -1,16 +1,14 @@
(import ../../../keys).mkSecrets [ "compute01" ] [ let
# List of secrets for compute01 lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "compute01";
in
lib.setDefault { inherit publicKeys; } [
"arkheon-env_file" "arkheon-env_file"
"bupstash-put_key" "bupstash-put_key"
"dgsi-email_host_password_file"
"dgsi-kanidm_auth_token_file"
"dgsi-kanidm_secret_file"
"dgsi-secret_key_file"
"dgsi-x509_cert_file"
"dgsi-x509_key_file"
"ds-fr-secret_file" "ds-fr-secret_file"
"grafana-oauth_client_secret_file"
"grafana-smtp_password_file" "grafana-smtp_password_file"
"grafana-oauth_client_secret_file"
"hedgedoc-environment_file" "hedgedoc-environment_file"
"librenms-database_password_file" "librenms-database_password_file"
"librenms-environment_file" "librenms-environment_file"

View file

@ -1,29 +1,29 @@
age-encryption.org/v1 age-encryption.org/v1
-> ssh-ed25519 jIXfPA Io/zqmrxU05V3yhgyGySW5f2hlQdBOqzXzv2I5x+nVs -> ssh-ed25519 jIXfPA amum6RbXOklYVgw9LbePC/FlJPJHLRT1peBvcD7+3xE
O5szAc5hiv4Kw+Xo90mhst3vGLqhtqSuaKxPTkCQCJw xB0z2R0gERJNMQnuuWlMZBvwBLD/0Cb70rFrnYg7Xm0
-> ssh-ed25519 QlRB9Q 9gQ+5aCcW+gi30S20om5+Zign9zXfgKlG9/59a2rdl4 -> ssh-ed25519 QlRB9Q 3+JuXBQQWcQbC2HsfO5FY+MQrSIpXJ1DBOpp9vHH7GY
nXyckLZ6zNdG096GAPlK/gyold3XxOqeKB1Kiy/BCmI 7IcedTCLy1clAfhlhfkkMcLLq1FNM1kugRgdnAkXeCY
-> ssh-ed25519 r+nK/Q nctFMke6IvbEII3/Mq7wq9Cb30GO1yBqePJXdOFjExs -> ssh-ed25519 r+nK/Q fS289K4zpwTlcXaI1TrfmUTdatunytf3I/Yjh33PHQQ
fMEbZoSsvMiFS2wHD0RCcSqbigmFHCnhEagXDTYBIW8 4n05isyZbYWQyyASL3FRiaL4IrliW+l5uxorfKgs1Es
-> ssh-rsa krWCLQ -> ssh-rsa krWCLQ
i7lgxs2DFU6OYdR0wC9NBJAUrYOarTpIBu8JiQKKTymkGauTtpCkOgakEF7N/TLd dk+PWx2abIh09/6BNshqi6X7P4uqdlO8ofsBebYlQW8j7hwFTJ89ivERMq35h/6A
1KFX6ww2lhmGwgi/4qYK5R21geqbLaogm5LsSrWgwI+nAqzAasD30i4MYWSfd1PS 6JT8R2QRpqT8HLYK21Wi3kDaiHF0H7KhHdXotTqCi4zFAqUFRKHs96dZsSgOePoL
kewXfRmMOUc2feMN/FiLDlyxxdg3DQImEwwAUq3k4F7W7/ggi4qPKzqzGhlOG1kB iJA7a/YHofpgjzZmNvc1ewLdmDD6+SnHXIzHfdHrFINUu2iRVDPwlyidOvRzJuGu
Ma05hLsOhTVwbyRQzf9MFDUypYJ8KRsV5/rdxnGzTaJLlYbNoQpIG3lQZelggGpS OJv+KChAZ0l2RhQCH+dw5uzJZP6WKfoNhsupTtxLRlfb/gEWSUfahA85rWc5JvT4
N6f5kz0fHRkTqCrINJpmLVkvQDbNNDslsDcr86O0LEI7NPrBry5fUSxI+YOzCJCu udw/oW3C7/hjiwKa8sd5XmxWz8BYut7OwTAFEXZCDSVuABjfUOKCF9IduTO3C8hP
3xnkIiYlcua2WGEXNd6vPQ 9fxCaztbhnCicDbTseP3rQ
-> ssh-ed25519 /vwQcQ L9OynFtsmYWQBB/PKHsJ4B2mdUFk8wkuPzaKBmvKERc -> ssh-ed25519 /vwQcQ 3NrE1YovFZCAdBv2jjGLkj07Auqyt1gBxP5zn0vXNkc
LPHLANWrv90EFdF+cXEOFnOf1XaLWeyEDij+DYVrDJM hYIWVsJNiKIbMl7zg7Qlf/HqwZ49eQsFs/3pFH809K8
-> ssh-ed25519 0R97PA 49YuJOzGjfLe8RixCtw8Z/EEngEGyNRQjb6sDXESQyM -> ssh-ed25519 0R97PA aw0rnvI6F3l/XA9SmK6I/mxDuVU7SD3jVcliix4u91Y
ICCw8XFpzJjZpOayDR6uoHqdv0vuEVg1uQyNrNONj8s TR+cZbyrengvbKF2jjhF42N+Iq7F3PMO71tc8e/Dy6s
-> ssh-ed25519 JGx7Ng fESc17fhVuC9dfNvDZKLq5EheYw+ufw0hpJqeDffxSE -> ssh-ed25519 JGx7Ng k+FsCk0FCgwsIOICmyOwJhrbTgleVoiqopv4cY5fmHQ
CWRV2wnZYh/bK5xgCDUASUmYMWSLbTXqnD1TFcbEHUU ZNCkfdStH2LqTiDTZ4VZIomsPw+S8PeSZpz/r088iAM
-> ssh-ed25519 5SY7Kg DgOrBwnV6Uxc5dMcNSR57HSgTW5DsG9Y9kcNYNevMGw -> ssh-ed25519 5SY7Kg bN3Yr4E+74hi46Zn6eLknIxbhW7E+XGPGuF1I07h7EU
W0HtwhGJ2jiU9jrfvGoEXthZ3ewxAL8ERNOUYSgWI1A UgX/w4B5iyJKXPcG4DCcM+vsZS/iGM8NFRS3F5qbif8
-> ssh-ed25519 p/Mg4Q doo+f6eD3s2uoMwekzHcUFCsls8gNZjiI0Nyyd1sClA -> ssh-ed25519 p/Mg4Q U1UZZaCOZ/gpLC0wc+ltv6Gx0GsYucydBmlHwnZT00k
NZnBQy9PJeabIwp6N7D85sI/UbCIcC7FzQALoNOD5h0 Dod7IsbtLnX89ekJGoRevH5OLd/ztLD4bsz3mUiuoHU
-> ssh-ed25519 tDqJRg tVVtvHVf/l4k+vr5A81tKTff49Rn1L1lrONq1DaGxDk -> ssh-ed25519 tDqJRg ydfBlrMl0PiStKGgxM48S2SFOQ+TdCU7WVkKoEne6W0
vskCx+/l45iAtB8Mn6S9T7I0rKEGgesDfqBrrT0wewU WNRZAx3aKOq+/Cz7TGI6Eu1QN+hqZlPuscGBNkOJBhg
--- HQzVXwtwdHyjKCBSbBOTiytzpLVc1eBCZZgW7sIgFEI --- E6Fp2JAT9jd8jYWOtMWkH0BNqrafOxBzyRLdK5H1/CI
9˜†%}/JÞ„U»cMä<38>ç™`®=%¿ÝîN} è9tñœÇ§‰¡¨‰rŒ}ˆ½KÿøžqøëO5GlùÑct#" Ò[Yw½e‰<65>_ûtˆ)f3Çòª´ÕGÊ2¹j„Wý^ìr¹ôYa=ESÓ ýØ,<2C>²Ú“rÐ_„£ ý8E ªª Ž¬1çî•íŇ“sÂ<73>ü–¼<”µŸ‚£ 0QMU"Œ±Ú’Åõ õˆ¬wSúœ4º=ï‰G(ˆ’º<<3C>?iZSW]Œ. pP93±zžl¸OSd·êS¯šçI­8Äeײ·Ú7ÃUMù¯< ªº<C2AA>Ýžóì<>?îOc2Z¬Uº Ä•èc²àԗ×7@ÄýôóŠòZæ™ihCžXß”QŸcɹ[èo=kÏòñËÞL"Z Í/uê´q ÛGäçó Ú[<5B>ú,£«i×Ãäs<C3A4>Jÿ•=GBç~^€Ù'Aý´èÕ±©¹í*giÝ|Ý*ùN·ÿŠË‘a]º˜áäši|áÔŽP'_(½±ÂQLŽØl„O ÈÛ´ |®<Û([Û‡ÐUå¥-ÙŽ‘`/ú:z õÀ§aØ2çu<C3A7>d"òB íÀ•°<E280A2> Gž»ŒžJÈô$ë¼=ÿ£Eé&Î4tè<74>€¶§<C2B6>â¶÷v?g -º¦0!PCé¹S¹ból½nWf|:ørm^麕ÎÊ\nOƒEc<45>Zé?‹° 4ŒÎ+W©X; û=7j6!Å@«Ãœ)oœ­¸Ì<C2B8>4Ø+ÞÑ÷/¯ 3òʤ-…;$aeµÛˆ¶jß¹²:=åféت§ÀcŽJnžèÁû4Eø/_¬L€9³`Úò<C39A>Æðä ³Ë:^:O<>ìp H(Ð÷ <20>Ä邃àÄ ¢~ÔÛû×,iùºÎk~ùpм0ìÜçÖèòG¢­e`Å<>Ï•Õq"šè!™r<72>Ͳs
P94ϨäÛF½]³¡È{Öºeç4ý[McQuÎÞî« ¥Jwȃ¼Ê“÷•ÁÛX@RÙÑÛŒú‰5M•Ý£V<E280B9>rjÇ—ó<E28094>„—½¢Ÿó7<C3B3>[¨8qÐb þô*«­ýÖ®þ5 ‰P¿ºB¥.Ï\{wW<_E•)Rh

View file

@ -7,16 +7,12 @@
{ {
imports = [ (import (sources.signal-irc-bridge.outPath + "/module.nix")) ]; imports = [ (import (sources.signal-irc-bridge.outPath + "/module.nix")) ];
systemd.services.signal-irc-bridge.serviceConfig = {
Group = "nginx";
};
services.signal-irc-bridge = { services.signal-irc-bridge = {
enable = true; enable = true;
package = nixpkgs.unstable.callPackage (sources.signal-irc-bridge.outPath + "/package.nix") { }; package = nixpkgs.unstable.callPackage (sources.signal-irc-bridge.outPath + "/package.nix") { };
configFile = config.age.secrets."signal-irc-bridge-config".path; configFile = config.age.secrets."signal-irc-bridge-config".path;
}; };
services.nginx.virtualHosts."bridge.dgnum.eu" = {
forceSSL = true;
enableACME = true;
locations."/files/".alias = "/var/lib/signal-irc/hermes-media/";
};
users.users.nginx.extraGroups = [ "signal-irc" ];
} }

View file

@ -1,16 +1,7 @@
{ nixpkgs, ... }: { nixpkgs, ... }:
let let
### dgn-id = "57ac2e06a00384772bf63f055874ce2fefe4eb0a";
# How to update:
# - clone https://git.dgnum.eu/DGNum/Stirling-PDF
# - switch to the branch dgn-v0.X.Y where X.Y is the version in production
# - fetch upstream changes up to the tagged release in nixos-unstable
# - rebase onto the upstream branch, so that the last commit is "feat: Add DGNum customization"
# - push to a new branch dgn-v0.A.B where A.B is the new version
# - finally, update the commit hash of the customization patch
dgn-id = "8f19cb1c9623f8da71f6512c1528d83acc35db57";
in in
{ {

View file

@ -1,35 +0,0 @@
diff --git a/build.gradle b/build.gradle
index 78901d8e..3a14ceee 100644
--- a/build.gradle
+++ b/build.gradle
@@ -70,20 +70,6 @@ launch4j {
messagesInstanceAlreadyExists="Stirling-PDF is already running."
}
-spotless {
- java {
- target project.fileTree('src/main/java')
-
- googleJavaFormat('1.19.1').aosp().reorderImports(false)
-
- importOrder('java', 'javax', 'org', 'com', 'net', 'io')
- toggleOffOn()
- trimTrailingWhitespace()
- indentWithSpaces()
- endWithNewline()
- }
-}
-
dependencies {
//security updates
implementation 'ch.qos.logback:logback-classic:1.5.3'
@@ -171,9 +157,6 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}
-tasks.withType(JavaCompile).configureEach {
- dependsOn 'spotlessApply'
-}
compileJava {
options.compilerArgs << '-parameters'
}

View file

@ -1,12 +0,0 @@
diff --git a/build.gradle b/build.gradle
index 78901d8e..2e7ff96b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -166,6 +166,7 @@ task writeVersion {
def props = new Properties()
props.setProperty('version', version)
props.store(propsFile.newWriter(), null)
+ propsFile.text = propsFile.readLines().tail().join('\n')
}
swaggerhubUpload {

View file

@ -1,16 +0,0 @@
diff --git a/build.gradle b/build.gradle
index 2e7ff96b..f3a4a15c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,6 +21,11 @@ repositories {
mavenCentral()
}
+tasks.withType(AbstractArchiveTask) {
+ preserveFileTimestamps = false
+ reproducibleFileOrder = true
+}
+
licenseReport {
renderers = [new JsonReportRenderer()]
}

View file

@ -1,25 +0,0 @@
diff --git a/build.gradle b/build.gradle
index f3a4a15c..61fbd74e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,7 +18,7 @@ version = '0.26.1'
sourceCompatibility = '17'
repositories {
- mavenCentral()
+ maven { url '@deps@' }
}
tasks.withType(AbstractArchiveTask) {
diff --git a/settings.gradle b/settings.gradle
index f8139930..2c87f3cc 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,7 @@
+pluginManagement {
+ repositories {
+ maven { url '@deps@' }
+ }
+}
+
rootProject.name = 'Stirling-PDF'

View file

@ -1,22 +0,0 @@
diff --git a/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java b/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
index cab78313..192922f3 100644
--- a/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
+++ b/src/test/java/stirling/software/SPDF/utils/ProcessExecutorTest.java
@@ -19,7 +19,7 @@ public class ProcessExecutorTest {
processExecutor = ProcessExecutor.getInstance(ProcessExecutor.Processes.LIBRE_OFFICE);
}
- @Test
+ /* @Test
public void testRunCommandWithOutputHandling() throws IOException, InterruptedException {
// Mock the command to execute
List<String> command = new ArrayList<>();
@@ -32,7 +32,7 @@ public class ProcessExecutorTest {
// Check the exit code and output messages
assertEquals(0, result.getRc());
assertNotNull(result.getMessages()); // Check if messages are not null
- }
+ } */
@Test
public void testRunCommandWithOutputHandling_Error() {

View file

@ -1 +0,0 @@
_: { dgn-chatops.enable = true; }

View file

@ -1,3 +1,5 @@
(import ../../../keys).mkSecrets [ "geo01" ] [ let
# List of secrets for geo01 lib = import ../../../lib { };
] publicKeys = lib.getNodeKeys "geo01";
in
lib.setDefault { inherit publicKeys; } [ ]

View file

@ -1,3 +1,5 @@
(import ../../../keys).mkSecrets [ "geo02" ] [ let
# List of secrets for geo02 lib = import ../../../lib { };
] publicKeys = lib.getNodeKeys "geo02";
in
lib.setDefault { inherit publicKeys; } [ ]

View file

@ -1,179 +0,0 @@
From 2abd226ff3093c5a9e18a618fba466853e7ebaf7 Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Tue, 8 Oct 2024 18:27:41 +0200
Subject: [PATCH] K80 support
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
---
docs/development.md | 6 +++-
docs/gpu.md | 1 +
gpu/amd_linux.go | 6 +++-
gpu/gpu.go | 63 ++++++++++++++++++++++++++++++++++++-----
scripts/build_docker.sh | 2 +-
scripts/build_linux.sh | 2 +-
6 files changed, 69 insertions(+), 11 deletions(-)
diff --git a/docs/development.md b/docs/development.md
index 2f7b9ecf..9da35931 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -51,7 +51,11 @@ Typically the build scripts will auto-detect CUDA, however, if your Linux distro
or installation approach uses unusual paths, you can specify the location by
specifying an environment variable `CUDA_LIB_DIR` to the location of the shared
libraries, and `CUDACXX` to the location of the nvcc compiler. You can customize
-a set of target CUDA architectures by setting `CMAKE_CUDA_ARCHITECTURES` (e.g. "50;60;70")
+a set of target CUDA architectures by setting `CMAKE_CUDA_ARCHITECTURES` (e.g. "35;37;50;60;70")
+
+To support GPUs older than Compute Capability 5.0, you will need to use an older version of
+the Driver from [Unix Driver Archive](https://www.nvidia.com/en-us/drivers/unix/) (tested with 470) and [CUDA Toolkit Archive](https://developer.nvidia.com/cuda-toolkit-archive) (tested with cuda V11). When you build Ollama, you will need to set two environment variable to adjust the minimum compute capability Ollama supports via `export GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/gpu.CudaComputeMajorMin=3\" \"-X=github.com/ollama/ollama/gpu.CudaComputeMinorMin=5\"'"` and the `CMAKE_CUDA_ARCHITECTURES`. To find the Compute Capability of your older GPU, refer to [GPU Compute Capability](https://developer.nvidia.com/cuda-gpus).
+
Then generate dependencies:
diff --git a/docs/gpu.md b/docs/gpu.md
index a6b559f0..66627611 100644
--- a/docs/gpu.md
+++ b/docs/gpu.md
@@ -28,6 +28,7 @@ Check your compute compatibility to see if your card is supported:
| 5.0 | GeForce GTX | `GTX 750 Ti` `GTX 750` `NVS 810` |
| | Quadro | `K2200` `K1200` `K620` `M1200` `M520` `M5000M` `M4000M` `M3000M` `M2000M` `M1000M` `K620M` `M600M` `M500M` |
+For building locally to support older GPUs, see [developer.md](./development.md#linux-cuda-nvidia)
### GPU Selection
diff --git a/gpu/amd_linux.go b/gpu/amd_linux.go
index 6b08ac2e..768fb97a 100644
--- a/gpu/amd_linux.go
+++ b/gpu/amd_linux.go
@@ -159,7 +159,11 @@ func AMDGetGPUInfo() []GpuInfo {
return []GpuInfo{}
}
- if int(major) < RocmComputeMin {
+ minVer, err := strconv.Atoi(RocmComputeMajorMin)
+ if err != nil {
+ slog.Error("invalid RocmComputeMajorMin setting", "value", RocmComputeMajorMin, "error", err)
+ }
+ if int(major) < minVer {
slog.Warn(fmt.Sprintf("amdgpu too old gfx%d%x%x", major, minor, patch), "gpu", gpuID)
continue
}
diff --git a/gpu/gpu.go b/gpu/gpu.go
index 781e23df..60d68c33 100644
--- a/gpu/gpu.go
+++ b/gpu/gpu.go
@@ -16,6 +16,7 @@ import (
"os"
"path/filepath"
"runtime"
+ "strconv"
"strings"
"sync"
"unsafe"
@@ -38,9 +39,11 @@ const (
var gpuMutex sync.Mutex
// With our current CUDA compile flags, older than 5.0 will not work properly
-var CudaComputeMin = [2]C.int{5, 0}
+// (string values used to allow ldflags overrides at build time)
+var CudaComputeMajorMin = "5"
+var CudaComputeMinorMin = "0"
-var RocmComputeMin = 9
+var RocmComputeMajorMin = "9"
// TODO find a better way to detect iGPU instead of minimum memory
const IGPUMemLimit = 1 * format.GibiByte // 512G is what they typically report, so anything less than 1G must be iGPU
@@ -175,11 +178,57 @@ func GetGPUInfo() GpuInfoList {
var memInfo C.mem_info_t
resp := []GpuInfo{}
- // NVIDIA first
- for i := 0; i < gpuHandles.deviceCount; i++ {
- // TODO once we support CPU compilation variants of GPU libraries refine this...
- if cpuVariant == "" && runtime.GOARCH == "amd64" {
- continue
+ // Load ALL libraries
+ cHandles = initCudaHandles()
+ minMajorVer, err := strconv.Atoi(CudaComputeMajorMin)
+ if err != nil {
+ slog.Error("invalid CudaComputeMajorMin setting", "value", CudaComputeMajorMin, "error", err)
+ }
+ minMinorVer, err := strconv.Atoi(CudaComputeMinorMin)
+ if err != nil {
+ slog.Error("invalid CudaComputeMinorMin setting", "value", CudaComputeMinorMin, "error", err)
+ }
+
+ // NVIDIA
+ for i := range cHandles.deviceCount {
+ if cHandles.cudart != nil || cHandles.nvcuda != nil {
+ gpuInfo := CudaGPUInfo{
+ GpuInfo: GpuInfo{
+ Library: "cuda",
+ },
+ index: i,
+ }
+ var driverMajor int
+ var driverMinor int
+ if cHandles.cudart != nil {
+ C.cudart_bootstrap(*cHandles.cudart, C.int(i), &memInfo)
+ } else {
+ C.nvcuda_bootstrap(*cHandles.nvcuda, C.int(i), &memInfo)
+ driverMajor = int(cHandles.nvcuda.driver_major)
+ driverMinor = int(cHandles.nvcuda.driver_minor)
+ }
+ if memInfo.err != nil {
+ slog.Info("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err))
+ C.free(unsafe.Pointer(memInfo.err))
+ continue
+ }
+
+ if int(memInfo.major) < minMajorVer || (int(memInfo.major) == minMajorVer && int(memInfo.minor) < minMinorVer) {
+ slog.Info(fmt.Sprintf("[%d] CUDA GPU is too old. Compute Capability detected: %d.%d", i, memInfo.major, memInfo.minor))
+ continue
+ }
+ gpuInfo.TotalMemory = uint64(memInfo.total)
+ gpuInfo.FreeMemory = uint64(memInfo.free)
+ gpuInfo.ID = C.GoString(&memInfo.gpu_id[0])
+ gpuInfo.Compute = fmt.Sprintf("%d.%d", memInfo.major, memInfo.minor)
+ gpuInfo.MinimumMemory = cudaMinimumMemory
+ gpuInfo.DependencyPath = depPath
+ gpuInfo.Name = C.GoString(&memInfo.gpu_name[0])
+ gpuInfo.DriverMajor = driverMajor
+ gpuInfo.DriverMinor = driverMinor
+
+ // TODO potentially sort on our own algorithm instead of what the underlying GPU library does...
+ cudaGPUs = append(cudaGPUs, gpuInfo)
}
gpuInfo := GpuInfo{
Library: "cuda",
diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh
index e91c56ed..c03bc25f 100755
--- a/scripts/build_docker.sh
+++ b/scripts/build_docker.sh
@@ -3,7 +3,7 @@
set -eu
export VERSION=${VERSION:-$(git describe --tags --first-parent --abbrev=7 --long --dirty --always | sed -e "s/^v//g")}
-export GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=$VERSION\" \"-X=github.com/ollama/ollama/server.mode=release\"'"
+export GOFLAGS=${GOFLAGS:-"'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=$VERSION\" \"-X=github.com/ollama/ollama/server.mode=release\"'"}
# We use 2 different image repositories to handle combining architecture images into multiarch manifest
# (The ROCm image is x86 only and is not a multiarch manifest)
diff --git a/scripts/build_linux.sh b/scripts/build_linux.sh
index 27c4ff1f..e7e6d0dd 100755
--- a/scripts/build_linux.sh
+++ b/scripts/build_linux.sh
@@ -3,7 +3,7 @@
set -eu
export VERSION=${VERSION:-$(git describe --tags --first-parent --abbrev=7 --long --dirty --always | sed -e "s/^v//g")}
-export GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=$VERSION\" \"-X=github.com/ollama/ollama/server.mode=release\"'"
+export GOFLAGS=${GOFLAGS:-"'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=$VERSION\" \"-X=github.com/ollama/ollama/server.mode=release\"'"}
BUILD_ARCH=${BUILD_ARCH:-"amd64 arm64"}
export AMDGPU_TARGETS=${AMDGPU_TARGETS:=""}
--
2.46.0

View file

@ -1,79 +0,0 @@
{
config,
lib,
pkgs,
meta,
name,
...
}:
lib.extra.mkConfig {
enabledModules = [
# INFO: This list needs to stay sorted alphabetically
];
enabledServices = [
# INFO: This list needs to stay sorted alphabetically
# Machine learning API machine
"microvm-ml01"
"microvm-router01"
"nvidia-tesla-k80"
"proxmox"
];
extraConfig = {
microvm = {
host.enable = true;
};
dgn-hardware = {
useZfs = true;
zfsPools = [
"dpool"
"ppool0"
];
};
services.netbird.enable = true;
# We are going to use CUDA here.
nixpkgs.config.cudaSupport = true;
hardware.graphics.enable = true;
environment.systemPackages = [
((pkgs.openai-whisper-cpp.override { cudaPackages = pkgs.cudaPackages_11; }).overrideAttrs (old: {
src = pkgs.fetchFromGitHub {
owner = "ggerganov";
repo = "whisper.cpp";
rev = "v1.7.1";
hash = "sha256-EDFUVjud79ZRCzGbOh9L9NcXfN3ikvsqkVSOME9F9oo=";
};
env = {
WHISPER_CUBLAS = "";
GGML_CUDA = "1";
};
# We only need Compute Capability 3.7.
CUDA_ARCH_FLAGS = [ "sm_37" ];
# We are GPU-only anyway.
patches = (old.patches or [ ]) ++ [
./no-weird-microarch.patch
./all-nvcc-arch.patch
];
}))
];
services = {
ollama = {
enable = true;
host = meta.network.${name}.netbirdIp;
package = pkgs.callPackage ./ollama.nix {
cudaPackages = pkgs.cudaPackages_11;
# We need to thread our nvidia x11 driver for CUDA.
extraLibraries = [ config.hardware.nvidia.package ];
};
};
};
networking.firewall.interfaces.wt0.allowedTCPPorts = [ config.services.ollama.port ];
};
root = ./.;
}

View file

@ -1,50 +0,0 @@
{
config,
lib,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot = {
initrd = {
availableKernelModules = [
"ehci_pci"
"ahci"
"mpt3sas"
"usbhid"
"sd_mod"
];
kernelModules = [ ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/92bf4d66-2693-4eca-9b26-f86ae09d468d";
fsType = "ext4";
};
boot.initrd.luks.devices."mainfs" = {
device = "/dev/disk/by-uuid/26f9737b-28aa-4c3f-bd3b-b028283cef88";
keyFileSize = 1;
keyFile = "/dev/zero";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/280C-8844";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,26 +0,0 @@
From 2278389ef9ac9231349440aa68f9544ddc69cdc7 Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Wed, 9 Oct 2024 13:37:08 +0200
Subject: [PATCH] fix: sm_37 for nvcc
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
---
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 2ccb750..70dfd9b 100644
--- a/Makefile
+++ b/Makefile
@@ -537,7 +537,7 @@ endif #GGML_CUDA_NVCC
ifdef CUDA_DOCKER_ARCH
MK_NVCCFLAGS += -Wno-deprecated-gpu-targets -arch=$(CUDA_DOCKER_ARCH)
else ifndef CUDA_POWER_ARCH
- MK_NVCCFLAGS += -arch=native
+ MK_NVCCFLAGS += -arch=sm_37
endif # CUDA_DOCKER_ARCH
ifdef GGML_CUDA_FORCE_DMMV
--
2.46.0

View file

@ -1,20 +0,0 @@
diff --git c/llm/generate/gen_common.sh i/llm/generate/gen_common.sh
index 3825c155..238a74a7 100644
--- c/llm/generate/gen_common.sh
+++ i/llm/generate/gen_common.sh
@@ -69,6 +69,7 @@ git_module_setup() {
}
apply_patches() {
+ return
# apply temporary patches until fix is upstream
for patch in ../patches/*.patch; do
git -c 'user.name=nobody' -c 'user.email=<>' -C ${LLAMACPP_DIR} am ${patch}
@@ -133,6 +134,7 @@ install() {
# Keep the local tree clean after we're done with the build
cleanup() {
+ return
(cd ${LLAMACPP_DIR}/ && git checkout CMakeLists.txt)
if [ -n "$(ls -A ../patches/*.diff)" ]; then

View file

@ -1,22 +0,0 @@
_: {
microvm.autostart = [ "ml01" ];
microvm.vms.ml01 = {
config = {
networking.hostName = "ml01";
microvm = {
hypervisor = "cloud-hypervisor";
vcpu = 4;
mem = 4096;
balloonMem = 2048;
shares = [
{
source = "/nix/store";
mountPoint = "/nix/.ro-store";
tag = "ro-store";
proto = "virtiofs";
}
];
};
};
};
}

View file

@ -1,16 +0,0 @@
_: {
microvm.autostart = [ "router01" ];
microvm.vms.router01 = {
config = {
networking.hostName = "router01";
microvm.shares = [
{
source = "/nix/store";
mountPoint = "/nix/.ro-store";
tag = "ro-store";
proto = "virtiofs";
}
];
};
};
}

View file

@ -1,34 +0,0 @@
From 51568b61ef63ecd97867562571411082c32751d3 Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
Date: Wed, 9 Oct 2024 13:36:51 +0200
Subject: [PATCH] fix: avx & f16c in Makefile
Signed-off-by: Raito Bezarius <masterancpp@gmail.com>
---
Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index 32b7cbb..2ccb750 100644
--- a/Makefile
+++ b/Makefile
@@ -361,12 +361,12 @@ ifndef RISCV
ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 i686 amd64))
# Use all CPU extensions that are available:
- MK_CFLAGS += -march=native -mtune=native
- HOST_CXXFLAGS += -march=native -mtune=native
+ # MK_CFLAGS += -march=native -mtune=native
+ # HOST_CXXFLAGS += -march=native -mtune=native
# Usage AVX-only
- #MK_CFLAGS += -mfma -mf16c -mavx
- #MK_CXXFLAGS += -mfma -mf16c -mavx
+ MK_CFLAGS += -mf16c -mavx
+ MK_CXXFLAGS += -mf16c -mavx
# Usage SSSE3-only (Not is SSE3!)
#MK_CFLAGS += -mssse3
--
2.46.0

View file

@ -1,8 +0,0 @@
{ config, ... }:
{
nixpkgs.config.nvidia.acceptLicense = true;
# Tesla K80 is not supported by the latest driver.
hardware.nvidia.package = config.boot.kernelPackages.nvidia_x11_legacy470;
# Don't ask.
services.xserver.videoDrivers = [ "nvidia" ];
}

View file

@ -1,243 +0,0 @@
{
lib,
buildGoModule,
fetchFromGitHub,
buildEnv,
linkFarm,
overrideCC,
makeWrapper,
stdenv,
addDriverRunpath,
nix-update-script,
cmake,
gcc11,
clblast,
libdrm,
rocmPackages,
cudaPackages,
darwin,
autoAddDriverRunpath,
extraLibraries ? [ ],
nixosTests,
testers,
ollama,
ollama-rocm,
ollama-cuda,
config,
# one of `[ null false "rocm" "cuda" ]`
acceleration ? null,
}:
assert builtins.elem acceleration [
null
false
"rocm"
"cuda"
];
let
pname = "ollama";
version = "2024-09-10-cc35";
src = fetchFromGitHub {
owner = "aliotard";
repo = "ollama";
rev = "34827c01f7723c7f5f9f5e392fe85f5a4a5d5fc0";
hash = "sha256-xFNuqcW7YWeyCyw5QLBnCHHTSMITR6LJkJT0CXZC+Y8=";
fetchSubmodules = true;
};
vendorHash = "sha256-hSxcREAujhvzHVNwnRTfhi0MKI3s8HNavER2VLz6SYk=";
validateFallback = lib.warnIf (config.rocmSupport && config.cudaSupport) (lib.concatStrings [
"both `nixpkgs.config.rocmSupport` and `nixpkgs.config.cudaSupport` are enabled, "
"but they are mutually exclusive; falling back to cpu"
]) (!(config.rocmSupport && config.cudaSupport));
shouldEnable =
mode: fallback: (acceleration == mode) || (fallback && acceleration == null && validateFallback);
rocmRequested = shouldEnable "rocm" config.rocmSupport;
cudaRequested = shouldEnable "cuda" config.cudaSupport;
enableRocm = rocmRequested && stdenv.isLinux;
enableCuda = cudaRequested && stdenv.isLinux;
rocmLibs = [
rocmPackages.clr
rocmPackages.hipblas
rocmPackages.rocblas
rocmPackages.rocsolver
rocmPackages.rocsparse
rocmPackages.rocm-device-libs
rocmPackages.rocm-smi
];
rocmClang = linkFarm "rocm-clang" { llvm = rocmPackages.llvm.clang; };
rocmPath = buildEnv {
name = "rocm-path";
paths = rocmLibs ++ [ rocmClang ];
};
cudaLibs = [
cudaPackages.cuda_cudart
cudaPackages.libcublas
cudaPackages.cuda_cccl
];
cudaToolkit = buildEnv {
name = "cuda-merged";
paths = map lib.getLib cudaLibs ++ [
(lib.getOutput "static" cudaPackages.cuda_cudart)
(lib.getBin (cudaPackages.cuda_nvcc.__spliced.buildHost or cudaPackages.cuda_nvcc))
];
};
metalFrameworks = with darwin.apple_sdk_11_0.frameworks; [
Accelerate
Metal
MetalKit
MetalPerformanceShaders
];
wrapperOptions =
[
# ollama embeds llama-cpp binaries which actually run the ai models
# these llama-cpp binaries are unaffected by the ollama binary's DT_RUNPATH
# LD_LIBRARY_PATH is temporarily required to use the gpu
# until these llama-cpp binaries can have their runpath patched
"--suffix LD_LIBRARY_PATH : '${addDriverRunpath.driverLink}/lib'"
"--suffix LD_LIBRARY_PATH : '${lib.makeLibraryPath (map lib.getLib extraLibraries)}'"
]
++ lib.optionals enableRocm [
"--suffix LD_LIBRARY_PATH : '${rocmPath}/lib'"
"--set-default HIP_PATH '${rocmPath}'"
]
++ lib.optionals enableCuda [
"--suffix LD_LIBRARY_PATH : '${lib.makeLibraryPath (map lib.getLib cudaLibs)}'"
];
wrapperArgs = builtins.concatStringsSep " " wrapperOptions;
goBuild =
if enableCuda then buildGoModule.override { stdenv = overrideCC stdenv gcc11; } else buildGoModule;
inherit (lib) licenses platforms maintainers;
in
goBuild {
inherit
pname
version
src
vendorHash
;
env =
lib.optionalAttrs enableRocm {
ROCM_PATH = rocmPath;
CLBlast_DIR = "${clblast}/lib/cmake/CLBlast";
}
// lib.optionalAttrs enableCuda { CUDA_LIB_DIR = "${cudaToolkit}/lib"; }
// {
CMAKE_CUDA_ARCHITECTURES = "35;37";
};
nativeBuildInputs =
[ cmake ]
++ lib.optionals enableRocm [ rocmPackages.llvm.bintools ]
++ lib.optionals enableCuda [ cudaPackages.cuda_nvcc ]
++ lib.optionals (enableRocm || enableCuda) [
makeWrapper
autoAddDriverRunpath
]
++ lib.optionals stdenv.isDarwin metalFrameworks;
buildInputs =
lib.optionals enableRocm (rocmLibs ++ [ libdrm ])
++ lib.optionals enableCuda cudaLibs
++ lib.optionals stdenv.isDarwin metalFrameworks;
patches = [
# disable uses of `git` in the `go generate` script
# ollama's build script assumes the source is a git repo, but nix removes the git directory
# this also disables necessary patches contained in `ollama/llm/patches/`
# those patches are applied in `postPatch`
./disable-git.patch
];
postPatch = ''
# replace inaccurate version number with actual release version
substituteInPlace version/version.go --replace-fail 0.0.0 '${version}'
# apply ollama's patches to `llama.cpp` submodule
for diff in llm/patches/*; do
patch -p1 -d llm/llama.cpp < $diff
done
'';
overrideModAttrs = _: _: {
# don't run llama.cpp build in the module fetch phase
preBuild = "";
};
preBuild = ''
# disable uses of `git`, since nix removes the git directory
export OLLAMA_SKIP_PATCHING=true
# build llama.cpp libraries for ollama
go generate ./...
'';
postFixup =
''
# the app doesn't appear functional at the moment, so hide it
mv "$out/bin/app" "$out/bin/.ollama-app"
''
+ lib.optionalString (enableRocm || enableCuda) ''
# expose runtime libraries necessary to use the gpu
wrapProgram "$out/bin/ollama" ${wrapperArgs}
'';
ldflags = [
"-s"
"-w"
"-X=github.com/ollama/ollama/version.Version=${version}"
"-X=github.com/ollama/ollama/server.mode=release"
"-X=github.com/ollama/ollama/gpu.CudaComputeMajorMin=3"
"-X=github.com/ollama/ollama/gpu.CudaComputeMinorMin=5"
];
passthru = {
tests =
{
inherit ollama;
version = testers.testVersion {
inherit version;
package = ollama;
};
}
// lib.optionalAttrs stdenv.isLinux {
inherit ollama-rocm ollama-cuda;
service = nixosTests.ollama;
service-cuda = nixosTests.ollama-cuda;
service-rocm = nixosTests.ollama-rocm;
};
updateScript = nix-update-script { };
};
meta = {
description =
"Get up and running with large language models locally"
+ lib.optionalString rocmRequested ", using ROCm for AMD GPU acceleration"
+ lib.optionalString cudaRequested ", using CUDA for NVIDIA GPU acceleration";
homepage = "https://github.com/ollama/ollama";
changelog = "https://github.com/ollama/ollama/releases/tag/v${version}";
license = licenses.mit;
platforms = if (rocmRequested || cudaRequested) then platforms.linux else platforms.unix;
mainProgram = "ollama";
maintainers = with maintainers; [
abysssol
dit7ya
elohmeier
roydubnium
];
};
}

View file

@ -1,14 +0,0 @@
{ sources, lib, ... }:
let
proxmox-nixos = import sources.proxmox-nixos;
in
{
imports = [ proxmox-nixos.nixosModules.proxmox-ve ];
services.proxmox-ve.enable = true;
nixpkgs.overlays = [ proxmox-nixos.overlays.x86_64-linux ];
networking.firewall = {
trustedInterfaces = [ "wt0" ];
allowedTCPPorts = lib.mkForce [ 22 ];
};
}

View file

@ -1,3 +0,0 @@
(import ../../../keys).mkSecrets [ "krz01" ] [
# List of secrets for krz01
]

View file

@ -3,6 +3,7 @@
lib.extra.mkConfig { lib.extra.mkConfig {
enabledModules = [ enabledModules = [
# List of modules to enable # List of modules to enable
"dgn-fail2ban"
]; ];
enabledServices = [ enabledServices = [
@ -11,6 +12,11 @@ lib.extra.mkConfig {
]; ];
extraConfig = { extraConfig = {
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
"sshd-bruteforce"
"sshd-timeout"
];
services.netbird.enable = true; services.netbird.enable = true;
}; };

View file

@ -1,4 +1,5 @@
(import ../../../keys).mkSecrets [ "rescue01" ] [ let
# List of secrets for rescue01 lib = import ../../../lib { };
"stateless-uptime-kuma-password" publicKeys = lib.getNodeKeys "rescue01";
] in
lib.setDefault { inherit publicKeys; } [ "stateless-uptime-kuma-password" ]

View file

@ -36,7 +36,6 @@ let
"cdn.dgnum.eu" "cdn.dgnum.eu"
"saml-idp.dgnum.eu" "saml-idp.dgnum.eu"
"status.dgnum.eu" "status.dgnum.eu"
"radius.dgnum.eu"
] ++ (concatLists (mapAttrsToList (_: { config, ... }: config.dgn-redirections.retired) nodes)); ] ++ (concatLists (mapAttrsToList (_: { config, ... }: config.dgn-redirections.retired) nodes));
extraProbes = { extraProbes = {

View file

@ -4,12 +4,13 @@ lib.extra.mkConfig {
enabledModules = [ enabledModules = [
# List of modules to enable # List of modules to enable
"dgn-backups" "dgn-backups"
"dgn-fail2ban"
"dgn-web" "dgn-web"
]; ];
enabledServices = [ enabledServices = [
# List of services to enable # List of services to enable
"tvix-cache" "atticd"
"forgejo" "forgejo"
"forgejo-runners" "forgejo-runners"
"garage" "garage"
@ -17,10 +18,11 @@ lib.extra.mkConfig {
"netbird" "netbird"
"peertube" "peertube"
"prometheus" "prometheus"
"redirections"
]; ];
extraConfig = { extraConfig = {
dgn-fail2ban.jails.sshd-preauth.enabled = true;
dgn-hardware.useZfs = true; dgn-hardware.useZfs = true;
services.netbird.enable = true; services.netbird.enable = true;

View file

@ -0,0 +1,82 @@
{ config, nixpkgs, ... }:
let
host = "cachix.dgnum.eu";
in
{
services = {
atticd = {
enable = true;
credentialsFile = config.age.secrets."atticd-credentials_file".path;
settings = {
listen = "127.0.0.1:9090";
api-endpoint = "https://${host}/";
allowed-hosts = [ host ];
chunking = {
# The minimum NAR size to trigger chunking
#
# If 0, chunking is disabled entirely for newly-uploaded NARs.
# If 1, all NARs are chunked.
nar-size-threshold = 0; # 64 KiB
# The preferred minimum size of a chunk, in bytes
min-size = 16 * 1024; # 16 KiB
# The preferred average size of a chunk, in bytes
avg-size = 64 * 1024; # 64 KiB
# The preferred maximum size of a chunk, in bytes
max-size = 256 * 1024; # 256 KiB
};
database.url = "postgresql://atticd?host=/run/postgresql";
storage = {
type = "s3";
region = "garage";
bucket = "attic-dgnum";
endpoint = "https://s3.dgnum.eu";
};
};
useFlakeCompatOverlay = false;
package = nixpkgs.unstable.attic-server;
};
nginx = {
enable = true;
virtualHosts.${host} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:9090";
extraConfig = ''
client_max_body_size 10G;
'';
};
};
};
postgresql = {
enable = true;
ensureDatabases = [ "atticd" ];
ensureUsers = [
{
name = "atticd";
ensureDBOwnership = true;
}
];
};
};
systemd.services.atticd.environment.RUST_LOG = "warn";
}

View file

@ -2,7 +2,6 @@
config, config,
pkgs, pkgs,
nixpkgs, nixpkgs,
sources,
... ...
}: }:
@ -30,8 +29,6 @@ let
options = "--cpus=4"; options = "--cpus=4";
}; };
}; };
nix-pkgs = import sources.nix-pkgs { inherit pkgs; };
in in
{ {
services.forgejo-nix-runners = { services.forgejo-nix-runners = {
@ -43,7 +40,7 @@ in
tokenFile = config.age.secrets."forgejo_runners-token_file".path; tokenFile = config.age.secrets."forgejo_runners-token_file".path;
dependencies = [ dependencies = [
nix-pkgs.colmena pkgs.colmena
pkgs.npins pkgs.npins
pkgs.tea pkgs.tea
nixpkgs.unstable.nixfmt-rfc-style nixpkgs.unstable.nixfmt-rfc-style

View file

@ -50,7 +50,6 @@ in
HTTP_ADDRESS = "127.0.0.1"; HTTP_ADDRESS = "127.0.0.1";
HTTP_PORT = port; HTTP_PORT = port;
APP_DATA_PATH = "/var/lib/git/data"; APP_DATA_PATH = "/var/lib/git/data";
OFFLINE_MODE = false;
}; };
service = { service = {
@ -62,11 +61,6 @@ in
}; };
ui.THEMES = "forgejo-auto,forgejo-light,forgejo-dark"; ui.THEMES = "forgejo-auto,forgejo-light,forgejo-dark";
"cron.cleanup_actions".ENABLED = true;
"cron.delete_old_actions".ENABLED = true;
"cron.git_gc_repos".ENABLED = true;
"cron.update_checker".ENABLED = false;
}; };
mailerPasswordFile = config.age.secrets."forgejo-mailer_password_file".path; mailerPasswordFile = config.age.secrets."forgejo-mailer_password_file".path;

View file

@ -8,20 +8,14 @@ let
metadata_dir = "/data/fast/garage/meta"; metadata_dir = "/data/fast/garage/meta";
domains = [ domains = [
"bandarretdurgence.ens.fr"
"boussole-sante.normalesup.eu" "boussole-sante.normalesup.eu"
"lanuit.ens.fr"
"simi.normalesup.eu" "simi.normalesup.eu"
]; ];
buckets = [ buckets = [
"monorepo-terraform-state"
"banda-website"
"castopod-dgnum" "castopod-dgnum"
"hackens-website"
"nuit-website"
"peertube-videos-dgnum" "peertube-videos-dgnum"
"banda-website"
] ++ domains; ] ++ domains;
mkHosted = host: builtins.map (b: "${b}.${host}"); mkHosted = host: builtins.map (b: "${b}.${host}");
@ -30,14 +24,14 @@ in
services.garage = { services.garage = {
enable = true; enable = true;
package = pkgs.garage_1_0_1; package = pkgs.garage_0_9;
settings = { settings = {
inherit data_dir metadata_dir; inherit data_dir metadata_dir;
db_engine = "lmdb"; db_engine = "lmdb";
replication_mode = "none"; # TODO: deprecated replication_mode = "none";
compression_level = 7; compression_level = 7;
rpc_bind_addr = "[::]:3901"; rpc_bind_addr = "[::]:3901";
@ -69,7 +63,7 @@ in
data_dir data_dir
metadata_dir metadata_dir
]; ];
TimeoutSec = 600; TimeoutSec = 3000;
}; };
users.users.garage = { users.users.garage = {
@ -79,17 +73,6 @@ in
users.groups.garage = { }; users.groups.garage = { };
services.nginx.virtualHosts = { services.nginx.virtualHosts = {
"s3-admin.dgnum.eu" = {
enableACME = true;
forceSSL = true;
locations."/".extraConfig = ''
proxy_pass http://127.0.0.1:3903;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
'';
};
${host} = { ${host} = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;

View file

@ -1,9 +0,0 @@
{
dgn-redirections = {
permanent = {
"www.lanuit.ens.fr" = "lanuit.ens.fr";
"lanuit.ens.psl.eu" = "lanuit.ens.fr";
"www.lanuit.ens.psl.eu" = "lanuit.ens.fr";
};
};
}

View file

@ -0,0 +1,30 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA HECtxDO0OV6To/Qs3A+2N8+3xqsHp6pz6d4ArgsgXS4
mnmDwWZ6d1aW5Qejzv2Jo112ee78wKVx90R7r5wQbYo
-> ssh-ed25519 QlRB9Q Rx3bV/DkoCCvQCMwJGOfibG8Rif5Ap+W6EqWlFOhUQc
jxEFUWqxedwIK3mNyOG+5dyFFZbJZ3XNFXnk0fe0vyw
-> ssh-ed25519 r+nK/Q J591Cg/4oP26LT7Tl/wrdDipR/gpg1WMsiKJN0ygbjw
WToE5xtuF2FOqtvRgz1SZStYGjTsKRxguIioan+vluU
-> ssh-rsa krWCLQ
hhp33AzK6wYWM6k7ZroV0J5i8C5MQXjQY9sksPQdABRQUd6XTmYOIOdA0ste0EA9
hqbbHQwbFy0oE/QKfnUZWbgJo5Us1DWKxip55L875CPfVcmxvC2ADRO5JKKNkQa/
P4zBALPqf+BXrafcGN4hT8D9gywIWdQ2zPSpKbJE+OdPcUrBVH/ndMUVoLfTEKL9
B3XgqRvLNkgsdu7FMEPnelWT3WrxkBME7AathdXcEYXSxiTmaKqxDzRtcNLdh+y2
6XfQU6lLMT+WWPD/Ro7UzLrWUnFJMYK0SinkOuX+PKxMq95lCc5kI3tZ7JL7bC5E
vBGnX9w0unyR//LLqrOPWA
-> ssh-ed25519 /vwQcQ eYSTWAYs/L+cYt/16TrKaIqoc9TFJQncM02Vd8hOg3A
lWalXa1ZBtrjXOB+sznWCjStFHF4ulLaBilEc3b7qWc
-> ssh-ed25519 0R97PA 78K7uF/mXT4pgTbnmfpyxY2czgs+DNueusuatUx7MCQ
C/pWPdVCWZuHFuM5fzJHdGZomM3Wbt22iwfLbLSznh0
-> ssh-ed25519 JGx7Ng xFzEGNVIiC0cXCbcSKUfmVLAdRBH7xu6/2E7nVoRwjI
+TgvIl03KGm5N55+jGc7UcyRHjMvAFm3Kbvx5Ma4HQ4
-> ssh-ed25519 5SY7Kg 7YO/crKVWSsr3Hy5HPr0/R3oPdCA2kWduZYeSlcxGnI
N0IpdylU+3ybInseGSKPONxeNr8mh/ZlBGCvY2c0WTA
-> ssh-ed25519 p/Mg4Q y1ekwzz3sSHGrLmb0NqF6VWfalARy+PykE77hVqD7Xc
0s9QrDsLH6XdzetyIXJEB2MrwwUi8CDpu7SEemm8zJ4
-> ssh-ed25519 rHotTw 7SMzV/pEmDISPL/fMjafXM3URZpbUPTg+9AngZ0GZTc
eIi1+i9JVBLvfQMkmMv5S0N8qgwVtyklX/J+6MdtlSc
--- Gjl7lNWG9gyMlg256Oa5i5bFLm1Cup1upjsEDVurgDo
uÂ;.ÿñË>pÔïÑ<C391>òh¸<68>2ÎŒ}£PJ4èú‘©‰Ñ×íè==#¯¾Úÿ¹8e¤UÊÉŠÇ$ 1»!z<E28093>jlA‡[@;òs®<>ŒÉáAB±á-§Rå=È0Ò·d“ðµú†Ê¢þ{«ÒF¹—hòà ù@%ˆŠä´›|×{ ¢åeÚÝÛ¯âøsbë«]Óèå¨ø.m8 8Bn"(Ûæ¤âïW½í!zxn\Ã(5:ïíÒÞ-ZDËÇÃ)}HŠü˜¦×ál}Sƒ˜ëFrn
øL¦-wÉÑ—¼j)ê â¶èÐ&:¥îÓCÞÆ2ÝÒÅÀÏB»ÛzïàŽŸt•WÍ!£8|lïí0
¾¸y8óÃkñbÔy×ËäÏ臃¹·k¤¨ÉÍ™ê°n/-'ÃZ<C383>ÅŸ ¾îƾ\Ûâê‰ù†uŸÍeu®"E ±/d

View file

@ -1,28 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA hiozo++fCkzjrvUQRLnAh4uwlmIXcTwkVbjkYbcH4mQ
boST8EzrWdNAuyOylbBX//DnWtO7RL2W++Wnm40w2MA
-> ssh-ed25519 QlRB9Q i0StXRfRRlTsN7MNZmlfBQdacHQlmTmriyiRcJu74g0
dhkD9ZfW+mkkryHBu+2fHe76hXrWVGKl+orxkPJD6gU
-> ssh-ed25519 r+nK/Q Ekn/Bz+c+G+KwgZEOCdk58lV9XN12d7/f+wi8ZEysgU
QdvnL+HtpHnxUbKD06WZDAi55q3xOYn3OiHViNdFt+I
-> ssh-rsa krWCLQ
ijGL8v8Otp59VvF0tDIReazFzchihsutr+zbcQuB6m3JZ6SAWyoKwhFdwiaLOfUd
DMAo2FOKfCbWS+M1VpdSJfu9LKroMCkeW+FOK81h6ywEYSAw/vt2FJP2TLiljZou
d7hiqNv0u/yiIoQiTs9hwOAPtLofiWcX//18TNTCgqm9Ttn0mKlfBjTkUQJdkZVM
j1rofzgHDdkyZDdr1op3sc4iURJ98dVN7ic035Fz+Ggs0yBh9T7qtVsUe7swuoH9
b9yxOSHdV3b4BYg75UrfiRNTOeQq8pxsga1DIs2x7oHkeVb8Ypmr1tXuAtWi20eg
1cYP5+BxY8ry6uaYNLYpKw
-> ssh-ed25519 /vwQcQ ZuVSKV4sI53zDaTOHIkk6ntPy9IxSBNIN/JEDPfT71Y
C5UgzlDJCcA8CP5D0kppqJKti76qe5IVFFnNirRtl/s
-> ssh-ed25519 0R97PA bNQCB3PAp5Ka2drYm74R7nuGM7NFUsKluPo6EEEyiVA
1/NFavNSG1pdMiWr2q2z9XwHs6iqhh5+3KIlr8ToPOo
-> ssh-ed25519 JGx7Ng 6X2a/FNvglr8ZSWvgEb37B67JJpJV0x1+fdlo6K6pzo
8AxYhMJ5+XGKNnpRBTSUM4GSbRj8s7amMQa8sp+tQWM
-> ssh-ed25519 5SY7Kg xw7EQG3mz6gQZXSh2LpY5zFRyMZOqEypvnOorRLBBHQ
WTcl4rLfg/siaGFmk/Odc6fsX+C6OPRWTHFQ0eENwgY
-> ssh-ed25519 p/Mg4Q hSz69OeCJyLJIpnI1tJqGNRErbDF2v6OdxWxi/pfF3k
nM6aJWcuzXEqRarkkAQx4636bALK3g0AwCsSfc8fXrk
-> ssh-ed25519 rHotTw xyrUv1xRQGG+CyL7Ftdw50S8LtN3Bd07f+8JInmBdGg
ehZkeby649QdiSyCDP4wTplLU7mtXac9QzILFIkIX/8
--- xWjuc/9B2UAHi7vuOjdvwJ2K3MEeDeTon5XDU1zi6rw
i«(rçfJ!G$<24>e)¤ê ý¡é•%)„‚9<>KÙ®UK¿Ëé]oǹË@Âv<C382>ŒÀ2I­pè\<12>ˆ^©9ä]¿ÂL,Ÿ•5æö/wvYŽÒ<C5BD>Í«‡³ ¬¼

View file

@ -1,5 +1,9 @@
(import ../../../keys).mkSecrets [ "storage01" ] [ let
# List of secrets for storage01 lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "storage01";
in
lib.setDefault { inherit publicKeys; } [
"atticd-credentials_file"
"bupstash-put_key" "bupstash-put_key"
"forgejo-mailer_password_file" "forgejo-mailer_password_file"
"forgejo_runners-token_file" "forgejo_runners-token_file"
@ -9,13 +13,10 @@
"influxdb2-initial_token_file" "influxdb2-initial_token_file"
"influxdb2-telegraf_token_file" "influxdb2-telegraf_token_file"
"netbird-auth_client_secret_file" "netbird-auth_client_secret_file"
"nginx-tvix-store-password"
"nginx-tvix-store-password-ci"
"peertube-secrets_file" "peertube-secrets_file"
"peertube-service_environment_file" "peertube-service_environment_file"
"peertube-smtp_password_file" "peertube-smtp_password_file"
"prometheus-web_config_file"
"prometheus-garage_api" "prometheus-garage_api"
"prometheus-uptime-kuma-apikey" "prometheus-uptime-kuma-apikey"
"prometheus-web_config_file"
"tvix-store-infra-signing-key"
] ]

View file

@ -1,29 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA /4nTbCIrufpN0Jho+8ZqTdZpc8mzSQrpG78flq+b9lM
x6Pg9oMGzboBg4WSAHxPwtNKcJUIG007Wx1ZjlzneLc
-> ssh-ed25519 QlRB9Q LsPsxbx6zvcLNf/EC3yFRP7Gr5tLYcg+8WGx6n0S724
4cyAHEdVBR885G4nfJSvUPqKWr/0abAtDTHmwksADp8
-> ssh-ed25519 r+nK/Q 9MisKxWalh0oubQFjwm2SDggxrj/fhdXGCYuYaP99jA
18o9juckqPtR4gh2MTXdmonxV9oZymyhCUqW3sOVltQ
-> ssh-rsa krWCLQ
j6AIypswOisUPlL538E3dpIWsHU/7H1c3+bEXXDFarP3Y5tjWltMRgKoPZUFlcRk
2yoVpOjDVkDvMTTu62Yn+Le6oYqoYQYzZ4e5incAR/v7sI76yPo1w+JN3BWBKPab
DN6h7Bdr8uzMISvxrRpCNDaU9n9GwA6ylJWvtFKjQZ6IDORVsa1tP44cndm6zAt6
Oq11bUDFSJLHiDtxjp0vJFa/4mq5Ay0G10xM/EI8Wf+Tiam/r3ytoBGnNYj1ENp8
AQkSxVF4cCORjQAokg+eUYCOzErJqpOx0ACx1SvuRvG4qcQ55ChYxs9zjnlCII2x
7JeUM/gjy0FnalxWWDX+cQ
-> ssh-ed25519 /vwQcQ bdzz3o+erI4c7ReafjhMYBgpebcJVcdB5vWK7cQ05Cs
3rVELKWfeiBksMzmm9XLmEgzdEASxSKcYJOpDQd7A+w
-> ssh-ed25519 0R97PA 4k2mZBQJTYhbjdzpxDuNw405iNxd96hVSMwzas/D3nU
neRy8ca2SguOJJQxalbPaq5SUH4taH+XxzkU/o/GVig
-> ssh-ed25519 JGx7Ng BlMr9FS9vuC1wnvDBAqEMJWzyuqoMqoU7YiFC9633xo
Xhvn+luDLE7AFbvgJs6V9cyRh8aJ2JrZfpVvXJhclu4
-> ssh-ed25519 5SY7Kg NkkDnN0z+2EzqpEdypnM7AROjjGVzoEvHfzaVbsyDiE
qbFUDBx4ghp9TG9YfjGjDXt35go0pMq0HH9GE+WT4v8
-> ssh-ed25519 p/Mg4Q rC/DrdXDUDWhbM7LMfQR203JClF/12o4rxJeGs+4rXY
Aj3P3skTbMvt2qN/FPSq97D1QwtHlKvFd4CsoujV2JI
-> ssh-ed25519 rHotTw 5IBV+q7+F7vNs5Tsx0S+ZEstiqoAaH1x78i/vAwrwDw
f729cEfMo/ozygHiRcNXmn8G+M+B68cM48ji7N6VgmY
--- TWScQDjdR4g/2v5oirYJgQw4zhhuMnmfvXtrigwmZC4
é°1ØLÅÄßán`Îq^ˆîÚ<C3AE>ï³Q²,ðT«Ó)Lñ aü„22 6M•¿Éú½Ü~4<E280BA>(~e±Y"´M·×!Žp!ÊU<ÖÜŒ<C592>Â;mn§`,öP6*&}HPM‡I¶ºòïH
Ûôï× Ãmõ<6D>‡ m£<6D>dGΠ߆ß÷T¥?G<>É»/

View file

@ -1,14 +0,0 @@
let
cache-info = {
infra = {
public-key = "infra.tvix-store.dgnum.eu-1:8CAY64o3rKjyw2uA5mzr/aTzstnc+Uj4g8OC6ClG1m8=";
url = "https://tvix-store.dgnum.eu/infra";
};
};
in
{ caches }:
{
trusted-substituters = builtins.map (cache: cache-info.${cache}.url) caches;
trusted-public-keys = builtins.map (cache: cache-info.${cache}.public-key) caches;
}

View file

@ -1,154 +0,0 @@
{ pkgs, config, ... }:
let
# How to add a cache:
# - Add the relevant services (likely only a pathinfoservice) to the
# composition config (store-config.composition).
# - Add an endpoint (store-config.endpoints).
# - Append a proxy configuration to nginx in order to make the store
# accessible.
# - Update cache-info.nix so users can add the cache to their configuration
store-config = {
composition = {
blobservices.default = {
type = "objectstore";
object_store_url = "file://${dataDir}/blob.objectstore";
object_store_options = { };
};
directoryservices = {
redb = {
type = "redb";
is_temporary = false;
path = "${dataDir}/directory.redb";
};
};
pathinfoservices = {
infra = {
type = "redb";
is_temporary = false;
path = "${dataDir}/pathinfo.redb";
};
infra-signing = {
type = "keyfile-signing";
inner = "infra";
keyfile = config.age.secrets."tvix-store-infra-signing-key".path;
};
};
};
endpoints = {
"127.0.0.1:8056" = {
endpoint_type = "Http";
blob_service = "default";
directory_service = "redb";
path_info_service = "infra";
};
"127.0.0.1:8058" = {
endpoint_type = "Http";
blob_service = "default";
directory_service = "redb";
path_info_service = "infra-signing";
};
# Add grpc for management and because it is nice
"127.0.0.1:8057" = {
endpoint_type = "Grpc";
blob_service = "default";
directory_service = "redb";
path_info_service = "infra";
};
};
};
settingsFormat = pkgs.formats.toml { };
webHost = "tvix-store.dgnum.eu";
dataDir = "/data/slow/tvix-store";
systemdHardening = {
PrivateDevices = true;
PrivateTmp = true;
ProtectControlGroups = true;
ProtectKernelTunables = true;
RestrictSUIDSGID = true;
ProtectSystem = "strict";
ProtectKernelLogs = true;
ProtectProc = "invisible";
PrivateUsers = true;
ProtectHome = true;
UMask = "0077";
RuntimeDirectoryMode = "0750";
StateDirectoryMode = "0750";
};
toml = {
composition = settingsFormat.generate "composition.toml" store-config.composition;
endpoints = settingsFormat.generate "endpoints.toml" store-config.endpoints;
};
package = pkgs.callPackage ./package { };
in
{
age-secrets.autoMatch = [
"tvix-store"
"nginx"
];
services.nginx.virtualHosts.${webHost} = {
enableACME = true;
forceSSL = true;
locations = {
"/infra/" = {
proxyPass = "http://127.0.0.1:8056/";
extraConfig = ''
client_max_body_size 50G;
limit_except GET {
auth_basic "Password required";
auth_basic_user_file ${config.age.secrets."nginx-tvix-store-password".path};
}
'';
};
"/infra-signing/" = {
proxyPass = "http://127.0.0.1:8058/";
extraConfig = ''
client_max_body_size 50G;
auth_basic "Password required";
auth_basic_user_file ${config.age.secrets."nginx-tvix-store-password-ci".path};
'';
};
};
};
# TODO add tvix-store cli here
# environment.systemPackages = [ ];
users.users.tvix-store = {
isSystemUser = true;
group = "tvix-store";
};
users.groups.tvix-store = { };
systemd.tmpfiles.rules = [ "d ${dataDir} 770 tvix-castore tvix-castore -" ];
systemd.services."tvix-store" = {
wantedBy = [ "multi-user.target" ];
environment = {
RUST_LOG = "debug";
};
serviceConfig = {
UMask = "007";
ExecStart = "${package}/bin/multitier-tvix-cache --endpoints-config ${toml.endpoints} --store-composition ${toml.composition}";
StateDirectory = "tvix-store";
RuntimeDirectory = "tvix-store";
User = "tvix-store";
Group = "tvix-store";
ReadWritePaths = [ dataDir ];
} // systemdHardening;
};
networking.firewall.allowedTCPPorts = [
80
443
];
}

File diff suppressed because it is too large Load diff

View file

@ -1,46 +0,0 @@
{
fetchgit,
rustPlatform,
protobuf,
runCommand,
}:
let
tvix-hash = "sha256-It3brj6SX+9OIGyKsITnNLjzDnB7CBCZDS+S7arRiWY=";
tvix-src = fetchgit {
name = "tvix";
url = "https://git.dgnum.eu/mdebray/tvl-depot";
rev = "3389c550b92d8b631f75e5a77e244fe698e4b4b2";
hash = tvix-hash;
};
protos = runCommand "tvix-protos" { } ''
mkdir $out
cd ${tvix-src}/tvix #remove tvix maybe
find . -name '*.proto' -exec install -D {} $out/{} \;
'';
in
rustPlatform.buildRustPackage rec {
pname = "multitenant-binary-cache";
version = "0.1.0";
src = fetchgit {
url = "https://git.lix.systems/sinavir/multitenant-tvix-binary-cache.git";
rev = "0d4c5ca8f75e156f9485fc085e93e85260e2e843";
hash = "sha256-OmXud+MhF2M02ofqDOnmazf190vu91i6RZ2y0NdA8oU=";
};
PROTO_ROOT = protos;
nativeBuildInputs = [ protobuf ];
cargoLock = {
lockFile = ./Cargo.lock;
outputHashes = {
"bigtable_rs-0.2.10" = "sha256-2NC3rHbS2rdD0Rnovymn1xaR22KaR6yzWr298wOPxlY=";
"nar-bridge-0.1.0" = tvix-hash;
};
};
cargoHash = "";
meta = { };
}

View file

@ -3,6 +3,7 @@
lib.extra.mkConfig { lib.extra.mkConfig {
enabledModules = [ enabledModules = [
# List of modules to enable # List of modules to enable
"dgn-fail2ban"
]; ];
enabledServices = [ enabledServices = [
@ -10,13 +11,15 @@ lib.extra.mkConfig {
"k-radius" "k-radius"
"networking" "networking"
"ups" "ups"
"ulogd"
]; ];
extraConfig = { extraConfig = {
dgn-fail2ban.jails = lib.extra.enableAttrs' "enabled" [
"sshd-bruteforce"
"sshd-timeout"
];
services.netbird.enable = true; services.netbird.enable = true;
services.nginx.enable = true;
networking.firewall.allowedTCPPorts = [ 80 ];
}; };
root = ./.; root = ./.;

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, lib, ... }:
{ {
imports = [ ./module.nix ]; imports = [ ./module.nix ];
@ -6,15 +6,6 @@
services.k-radius = { services.k-radius = {
enable = true; enable = true;
domain = "radius.dgnum.eu";
radiusClients = {
ap = {
ipaddr = "0.0.0.0/0";
secret = config.age.secrets."radius-ap-radius-secret_file".path;
};
};
settings = { settings = {
# URL to the Kanidm server # URL to the Kanidm server
uri = "https://sso.dgnum.eu"; uri = "https://sso.dgnum.eu";
@ -49,6 +40,18 @@
}; };
authTokenFile = config.age.secrets."radius-auth_token_file".path; authTokenFile = config.age.secrets."radius-auth_token_file".path;
privateKeyPasswordFile = config.age.secrets."radius-private_key_password_file".path;
certs = builtins.listToAttrs (
builtins.map (name: lib.nameValuePair name config.age.secrets."radius-${name}_pem_file".path) [
"ca"
"cert"
"dh"
"key"
]
);
radiusClients = { };
}; };
age-secrets.autoMatch = [ "radius" ]; age-secrets.autoMatch = [ "radius" ];

View file

@ -7,24 +7,10 @@
let let
inherit (lib) inherit (lib)
attrsToList
getExe'
imap0
mapAttrsToList
mkEnableOption mkEnableOption
mkIf mkIf
mkOption mkOption
optionalString types
;
inherit (lib.types)
attrsOf
bool
enum
package
path
str
submodule
; ;
settingsFormat = pkgs.formats.toml { }; settingsFormat = pkgs.formats.toml { };
@ -33,94 +19,67 @@ let
rlm_python = pkgs.callPackage ./packages/rlm_python.nix { inherit pykanidm; }; rlm_python = pkgs.callPackage ./packages/rlm_python.nix { inherit pykanidm; };
cfg = config.services.k-radius; cfg = config.services.k-radius;
acmeDirectory = config.security.acme.certs.${cfg.domain}.directory;
in in
{ {
options.services.k-radius = { options.services.k-radius = {
enable = mkEnableOption "a freeradius service linked to kanidm."; enable = mkEnableOption "a freeradius service linked to kanidm.";
domain = mkOption {
type = str;
description = "The domain used for the RADIUS server.";
};
raddb = mkOption {
type = path;
default = "/var/lib/radius/raddb/";
description = "The location of the raddb directory.";
};
settings = mkOption { inherit (settingsFormat) type; }; settings = mkOption { inherit (settingsFormat) type; };
freeradius = mkOption { freeradius = mkOption {
type = package; type = types.package;
default = pkgs.freeradius.overrideAttrs (old: { default = pkgs.freeradius.overrideAttrs (old: {
buildInputs = (old.buildInputs or [ ]) ++ [ (pkgs.python3.withPackages (ps: [ ps.kanidm ])) ]; buildInputs = (old.buildInputs or [ ]) ++ [ (pkgs.python3.withPackages (ps: [ ps.kanidm ])) ];
}); });
}; };
configDir = mkOption { configDir = mkOption {
type = path; type = types.path;
default = "/var/lib/radius/raddb"; default = "/var/lib/radius/raddb";
description = "The path of the freeradius server configuration directory."; description = "The path of the freeradius server configuration directory.";
}; };
authTokenFile = mkOption { authTokenFile = mkOption {
type = path; type = types.path;
description = "File to the auth token for the service account."; description = "File to the auth token for the service account.";
}; };
extra-mods = mkOption {
type = attrsOf path;
default = { };
description = "Additional files to be linked in mods-enabled.";
};
extra-sites = mkOption {
type = attrsOf path;
default = { };
description = "Additional files to be linked in sites-enabled.";
};
dictionary = mkOption {
type = attrsOf (enum [
"abinary"
"date"
"ipaddr"
"integer"
"string"
]);
default = { };
description = "Declare additionnal attributes to be listed in the dictionary.";
};
radiusClients = mkOption { radiusClients = mkOption {
type = attrsOf (submodule { type = types.attrsOf (
types.submodule {
options = { options = {
secret = mkOption { type = path; }; secret = mkOption { type = types.path; };
ipaddr = mkOption { type = str; }; ipaddr = mkOption { type = types.str; };
}; };
}); }
);
default = { }; default = { };
description = "A mapping of clients and their authentication tokens."; description = "A mapping of clients and their authentication tokens.";
}; };
checkConfiguration = mkOption { certs = {
type = bool; ca = mkOption {
description = "Check the configuration before starting the deamon. Useful for debugging."; type = types.str;
default = false; description = "The signing CA of the RADIUS certificate.";
}; };
dh = mkOption {
type = types.str;
description = "The output of `openssl dhparam -in ca.pem -out dh.pem 2048`.";
};
cert = mkOption {
type = types.str;
description = "The certificate for the RADIUS server.";
};
key = mkOption {
type = types.str;
description = "The signing key for the RADIUS certificate.";
};
};
privateKeyPasswordFile = mkOption { type = types.path; };
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
# Certificate setup
services.nginx.virtualHosts.${cfg.domain} = {
http2 = false;
enableACME = true;
forceSSL = true;
};
users = { users = {
users.radius = { users.radius = {
group = "radius"; group = "radius";
@ -131,45 +90,46 @@ in
groups.radius = { }; groups.radius = { };
}; };
services.k-radius.settings = {
ca_path = cfg.certs.ca;
radius_cert_path = cfg.certs.cert;
radius_key_path = cfg.certs.key;
radius_dh_path = cfg.certs.dh;
radius_ca_path = cfg.certs.ca;
};
systemd.services.radius = { systemd.services.radius = {
description = "FreeRadius server"; description = "FreeRadius server";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ after = [ "network.target" ];
"network.target"
"acme-finished-${cfg.domain}.target"
];
wants = [ "network.target" ]; wants = [ "network.target" ];
startLimitIntervalSec = 20;
startLimitBurst = 5;
preStart = '' preStart = ''
raddb=${cfg.raddb} mkdir -p ${cfg.configDir}
# Recreate the configuration directory cp -R --no-preserve=mode ${cfg.freeradius}/etc/raddb/* ${cfg.configDir}
rm -rf $raddb && mkdir -p $raddb cp -R --no-preserve=mode ${rlm_python}/etc/raddb/* ${cfg.configDir}
cp -R --no-preserve=mode ${cfg.freeradius}/etc/raddb/* $raddb chmod -R u+w ${cfg.configDir}
cp -R --no-preserve=mode ${rlm_python}/etc/raddb/* $raddb
chmod -R u+w $raddb
# disable auth via methods kanidm doesn't support # disable auth via methods kanidm doesn't support
rm $raddb/mods-available/sql rm ${cfg.configDir}/mods-available/sql
rm $raddb/mods-enabled/{passwd,totp} rm ${cfg.configDir}/mods-enabled/{passwd,totp}
# enable the python and cache modules # enable the python and cache modules
ln -nsf $raddb/mods-available/python3 $raddb/mods-enabled/python3 ln -nsf ${cfg.configDir}/mods-available/python3 ${cfg.configDir}/mods-enabled/python3
ln -nsf $raddb/sites-available/check-eap-tls $raddb/sites-enabled/check-eap-tls ln -nsf ${cfg.configDir}/sites-available/check-eap-tls ${cfg.configDir}/sites-enabled/check-eap-tls
# write the clients configuration # write the clients configuration
> $raddb/clients.conf rm ${cfg.configDir}/clients.conf && touch ${cfg.configDir}/clients.conf
${builtins.concatStringsSep "\n" ( ${builtins.concatStringsSep "\n" (
builtins.attrValues ( builtins.attrValues (
builtins.mapAttrs ( builtins.mapAttrs (
name: name:
{ secret, ipaddr }: { secret, ipaddr }:
'' ''
cat <<EOF >> $raddb/clients.conf cat <<EOF >> ${cfg.configDir}/clients.conf
client ${name} { client ${name} {
ipaddr = ${ipaddr} ipaddr = ${ipaddr}
secret = $(cat "${secret}") secret = $(cat "${secret}")
@ -190,40 +150,22 @@ in
chmod u+w /var/lib/radius/kanidm.toml chmod u+w /var/lib/radius/kanidm.toml
# Copy the certificates to the correct directory # Copy the certificates to the correct directory
rm -rf $raddb/certs && mkdir -p $raddb/certs rm -rf ${cfg.configDir}/certs && mkdir -p ${cfg.configDir}/certs
cp ${acmeDirectory}/chain.pem $raddb/certs/ca.pem cp ${cfg.certs.ca} ${cfg.configDir}/certs/ca.pem
${lib.getExe pkgs.openssl} rehash $raddb/certs ${pkgs.openssl}/bin/openssl rehash ${cfg.configDir}/certs
# Recreate the dh.pem file cp ${cfg.certs.dh} ${cfg.configDir}/certs/dh.pem
${lib.getExe pkgs.openssl} dhparam -in $raddb/certs/ca.pem -out $raddb/certs/dh.pem 2048
cp ${acmeDirectory}/full.pem $raddb/certs/server.pem cat ${cfg.certs.cert} ${cfg.certs.key} > ${cfg.configDir}/certs/server.pem
# Link the dictionary # Write the password of the private_key in the eap module
ln -nsf ${ sed -i ${cfg.configDir}/mods-available/eap \
pkgs.writeText "radius-dictionary" ( -e "s/whatever/$(cat "${cfg.privateKeyPasswordFile}")/"
builtins.concatStringsSep "\n" (
imap0 (i: { name, value }: "ATTRIBUTE ${name} ${builtins.toString (3000 + i)} ${value}") (
attrsToList cfg.dictionary
)
)
)
} $raddb/dictionary
# Link extra-mods
${builtins.concatStringsSep "\n" (
mapAttrsToList (name: path: "ln -nsf ${path} $raddb/mods-enabled/${name}") cfg.extra-mods
)}
# Link extra-sites
${builtins.concatStringsSep "\n" (
mapAttrsToList (name: path: "ln -nsf ${path} $raddb/sites-enabled/${name}") cfg.extra-sites
)}
# Check the configuration # Check the configuration
${optionalString cfg.checkConfiguration "${getExe' pkgs.freeradius "radiusd"} -C -d $raddb -l stdout"} # ${pkgs.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout
''; '';
path = [ path = [
@ -231,28 +173,24 @@ in
pkgs.gnused pkgs.gnused
]; ];
environment = {
KANIDM_RLM_CONFIG = "/var/lib/radius/kanidm.toml";
PYTHONPATH = rlm_python.pythonPath;
};
serviceConfig = { serviceConfig = {
ExecStart = "${cfg.freeradius}/bin/radiusd -X -f -d /var/lib/radius/raddb -l stdout"; ExecStart = "${cfg.freeradius}/bin/radiusd -X -f -d ${cfg.configDir} -l stdout";
ExecReload = [ ExecReload = [
"${cfg.freeradius}/bin/radiusd -C -d /var/lib/radius/raddb -l stdout" "${cfg.freeradius}/bin/radiusd -C -d ${cfg.configDir} -l stdout"
"${pkgs.coreutils}/bin/kill -HUP $MAINPID" "${pkgs.coreutils}/bin/kill -HUP $MAINPID"
]; ];
AmbientCapabilities = "CAP_NET_BIND_SERVICE"; User = "radius";
DynamicUser = true;
Group = "radius"; Group = "radius";
LogsDirectory = "radius"; DynamicUser = true;
ReadOnlyPaths = [ acmeDirectory ];
Restart = "on-failure"; Restart = "on-failure";
RestartSec = 2; RestartSec = 2;
RuntimeDirectory = "radius"; LogsDirectory = "radius";
StateDirectory = "radius"; StateDirectory = "radius";
SupplementaryGroups = [ "nginx" ]; RuntimeDirectory = "radius";
User = "radius"; Environment = [
"KANIDM_RLM_CONFIG=/var/lib/radius/kanidm.toml"
"PYTHONPATH=${rlm_python.pythonPath}"
];
}; };
}; };
}; };

View file

@ -1,5 +1,4 @@
{ {
pkgs,
lib, lib,
meta, meta,
name, name,
@ -19,7 +18,7 @@ let
mkNetwork = mkNetwork =
name: name:
{ {
address ? [ ], address,
extraNetwork ? { }, extraNetwork ? { },
... ...
}: }:
@ -37,61 +36,19 @@ let
}; };
mkUserVlan = mkUserVlan =
id:
let
vlan = 3245 + id;
prefix24nb = id / 32;
prefix29nb = (id - prefix24nb * 32) * 8;
in
{ {
vlan, name = "vlan-user-${builtins.toString vlan}";
netIP,
servIP,
interfaceName,
...
}:
{
name = interfaceName;
value = { value = {
Id = vlan; Id = vlan;
extraNetwork = { address = [ "10.0.${builtins.toString prefix24nb}.${builtins.toString (prefix29nb + 1)}/29" ];
networkConfig = {
LinkLocalAddressing = "no";
DHCPServer = "yes";
};
linkConfig.Promiscuous = true;
addresses = [
{
addressConfig = {
Address = "${servIP}/27";
AddPrefixRoute = false;
};
}
];
routes = [
{
routeConfig = {
Destination = "${netIP}/27";
Table = "user";
};
}
];
routingPolicyRules = [
{
routingPolicyRuleConfig = {
From = "${netIP}/27";
To = "10.0.0.0/27";
IncomingInterface = interfaceName;
Table = "user";
};
}
];
}; };
}; };
};
userVlans = builtins.genList (id: rec {
vlan = 4094 - id;
prefix24nb = (id + 1) / 8;
prefix27nb = (id + 1 - prefix24nb * 8) * 32;
netIP = "10.0.${toString prefix24nb}.${toString prefix27nb}";
servIP = "10.0.${toString prefix24nb}.${toString (prefix27nb + 1)}";
interfaceName = "vlan-user-${toString vlan}";
}) 850;
vlans = { vlans = {
vlan-uplink-cri = { vlan-uplink-cri = {
@ -116,16 +73,7 @@ let
vlan-admin-ap = { vlan-admin-ap = {
Id = 3001; Id = 3001;
address = [ "fd26:baf9:d250:8001::1/64" ]; address = [ "fd26:baf9:d250:8010::1/60" ];
extraNetwork.ipv6Prefixes = [
{
ipv6PrefixConfig = {
AddressAutoconfiguration = false;
OnLink = false;
Prefix = "fd26:baf9:d250:8001::/64";
};
}
];
}; };
vlan-apro = { vlan-apro = {
@ -134,41 +82,14 @@ let
extraNetwork.networkConfig.DHCPServer = "yes"; extraNetwork.networkConfig.DHCPServer = "yes";
}; };
} // builtins.listToAttrs (map mkUserVlan userVlans); } // builtins.listToAttrs (builtins.genList mkUserVlan 300); # 850 when we can
in in
{ {
systemd = { systemd.network = {
network = {
config.routeTables."user" = 1000;
networks = { networks = {
"10-lo" = {
name = "lo";
address = [
"::1/128"
"127.0.0.1/8"
"10.0.0.1/27"
];
routes = [
{
routeConfig = {
Destination = "10.0.0.0/27";
Table = "user";
};
}
];
routingPolicyRules = [
{
routingPolicyRuleConfig = {
IncomingInterface = "lo";
Table = "user";
};
}
];
};
"10-enp67s0f0np0" = { "10-enp67s0f0np0" = {
name = "enp67s0f0np0"; name = "enp67s0f0np0";
linkConfig.Promiscuous = true;
networkConfig = { networkConfig = {
VLAN = builtins.attrNames vlans; VLAN = builtins.attrNames vlans;
@ -184,74 +105,5 @@ in
netdevs = mapAttrs' mkNetdev vlans; netdevs = mapAttrs' mkNetdev vlans;
}; };
services = { networking.firewall.allowedUDPPorts = [ 67 ];
ethtoolConfig = {
wantedBy = [ "systemd-networkd.service" ];
after = [ "sys-subsystem-net-devices-enp67s0f0np0.device" ];
bindsTo = [ "sys-subsystem-net-devices-enp67s0f0np0.device" ];
script = builtins.concatStringsSep "\n" (
builtins.map (name: "${lib.getExe pkgs.ethtool} -K enp67s0f0np0 ${name} off") [
"rxvlan"
"txvlan"
"rx-vlan-filter"
"rx-vlan-offload"
"tx-vlan-offload"
"tx-vlan-stag-hw-insert"
]
);
};
systemd-networkd.serviceConfig.LimitNOFILE = 4096;
net-checker = {
path = [
pkgs.iputils
pkgs.systemd
];
script = ''
if ping -c 1 8.8.8.8 > /dev/null || ping -c 1 1.1.1.1 > /dev/null; then
${
lib.concatMapStringsSep "\n " ({ interfaceName, ... }: "networkctl up ${interfaceName}") userVlans
}
else
${
lib.concatMapStringsSep "\n " (
{ interfaceName, ... }: "networkctl down ${interfaceName}"
) userVlans
}
fi
'';
};
};
timers.net-checker = {
wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = "*-*-* *:*:42";
};
};
networking = {
nftables = {
enable = true;
tables.nat = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority 100;
ip saddr 10.0.0.0/16 ip saddr != 10.0.255.0/24 snat ip to 129.199.195.130-129.199.195.158
ether saddr e0:2b:e9:b5:b4:cc snat to 129.199.195.130 comment "Elias"
ether saddr { 1c:1b:b5:14:9c:e5, e6:ce:e2:b6:e3:82 } snat to 129.199.195.131 comment "Lubin"
ether saddr d0:49:7c:46:f6:39 snat to 129.199.195.132 comment "Jean-Marc"
ether saddr { 5c:64:8e:f4:09:06 } snat to 129.199.195.158 comment "APs"
}
'';
};
};
firewall = {
allowedUDPPorts = [ 67 ];
checkReversePath = false;
};
};
boot.kernel.sysctl."net.ipv4.ip_forward" = true;
} }

View file

@ -1,32 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 jIXfPA 2nFaxyP7O4GWU7U3wmET5sNrnFq72b9DEhiKEgWVrFk
l8uXfCBkTHogzVoUY0WOYhA99fodoT+N0HunacULydI
-> ssh-ed25519 QlRB9Q qDalihZE404oPOVHYQR5GIvozXNh4wNxhUa5Zwfz2DU
X8qvWf7qprbh0xu/uOHGsNLTQc8efYsgveH9R9kZZZw
-> ssh-ed25519 r+nK/Q mksHDhPoKKxQpk4sQPHapdq87EaJmgdmoVxMYjsAang
FTYHyxLp4nGOWJu1135yN/lQkGgAD9Jy4JJpMKFktrk
-> ssh-rsa krWCLQ
jEPt5eWP6NmpOikLhs1uPVo7kxHgg1y7WwdOPyR0z2vpFD2BWGlIi/BvnlE3OO5n
jtvDjAauWU0X2JarfdY9mY8MoPjT9qQ/ukxuVAHi5CoL/I1JCqcbuftssYY0B7Ab
SMfbyxjK8aIT1/4EQhMoWm0tuIylvgTBagL03Lw5mbyRqDkbpI/6YC9401YjT7Ts
dCDGIFAYM2BA7TuJiZr881ypUdU9rlm5rss1ZLMj90jyJPJC4SDYbzE0BoBat9l0
dYUrYGhGgZ1cDd6D6mPf6H95muiGHIhxaE8c+LdK/rKCSH9Rf6mfn/Ab/xvnaDNn
GW/WD0EpmdzpWVPby68+KA
-> ssh-ed25519 /vwQcQ 5DoMxdoK+KiHXKwwOpb7/1FZIEzAa/2/1l8yyxey6iw
RzmUkqZQLM5/jDXG9fxhZmfAywgVMjH9Y3O66BnhCSQ
-> ssh-ed25519 0R97PA g+uW/jfwHB3m0AdWxb9vPRjeaowhEx1Uoc2R0CVStlA
m5XvSEVQ8DiA7BSTsxVn6S1zv92CpbyZxSgUI3ObE4c
-> ssh-ed25519 JGx7Ng BtdJpskbfPyywYeFbmQw3HGPTLv5ri6x4bFocr9l6H8
88aFw+MCJLqMU/W/ikYDUZEAi0ImaPVbSc7cAZPbs/I
-> ssh-ed25519 5SY7Kg +JUMQfaxl7Orym43LVeqUyno0JfUbVnB+xv7smpdRhE
6K+Ewq1FhrXB2eYdljlsYpIfmVv49E4jSBsphgDpRJk
-> ssh-ed25519 p/Mg4Q AITnEN+Q41fEA2tkvVOKGCDZiuCXanG+qaiF5X4ukiA
NvP/HXOliNvi8tngH9PU90E616CPlh/QgkZ052H8wtk
-> ssh-ed25519 +mFdtQ RuaXIQNZ3s9C27XtpVTExJlAhYDYXRQni+Hwot0wrzU
WctqqoGS2hVfOZSU3ihCg5eI7PnxM7dkOJKM9DJ90Wk
-> ssh-ed25519 5rrg4g cAqJQ8z6T46YwzahtcTJxXZHklCGrupVCja5U/g+ZmM
wERu5T6rOi5/0qPSXeOnfA0Szg7/pbYFTW0Ys1yWq40
-> ssh-ed25519 oRtTqQ NF73c0d1qM4nVt2bEdWTEDjDcz/ZMCObn/7cDZfkVGA
Mivm+WWVqAfNs5pLwGmINIsmxlEZi7m7bQIRxGkf3/Q
--- 8R1h+xsovrLq+5QI1CoTXc9TBTQugnROZpOAHWBwG1w
G“Þ"û¤‡ã8ƒÈî&NF}x£ksyÖ\£.i§<69>קF¢¯}ê-ÍÁÓšLbì;{

View file

@ -1,5 +1,8 @@
(import ../../../keys).mkSecrets [ "vault01" ] [ let
# List of secrets for vault01 lib = import ../../../lib { };
publicKeys = lib.getNodeKeys "vault01";
in
lib.setDefault { inherit publicKeys; } [
"radius-auth_token_file" "radius-auth_token_file"
"radius-ca_pem_file" "radius-ca_pem_file"
"radius-cert_pem_file" "radius-cert_pem_file"
@ -7,5 +10,4 @@
"radius-key_pem_file" "radius-key_pem_file"
"radius-private_key_password_file" "radius-private_key_password_file"
"eatonmon-password_file" "eatonmon-password_file"
"radius-ap-radius-secret_file"
] ]

View file

@ -1,56 +0,0 @@
{
config,
lib,
pkgs,
...
}:
{
services = {
ulogd = {
enable = true;
logLevel = 5;
settings = {
global = {
logfile = "/var/log/ulogd.log";
stack = [ "ct1:NFCT,ip2str1:IP2STR,pgsql1:PGSQL" ];
};
ct1 = { };
pgsql1 = {
db = "ulogd";
user = "ulogd";
table = "ulog2_ct";
procedure = "INSERT_CT";
};
};
};
postgresql = {
enable = true;
identMap = ''
ulogd-map root ulogd
'';
authentication = ''
local ulogd ulogd peer map=ulogd-map
'';
ensureUsers = [
{
name = "ulogd";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "ulogd" ];
};
};
systemd.services.ulogd = {
serviceConfig.StateDirectory = "ulogd";
requires = [ "postgresql.service" ];
after = [ "postgresql.service" ];
path = [ config.services.postgresql.package ];
preStart = lib.mkAfter ''
if ! test -e "/var/lib/ulogd/.initialized"; then
psql -f "${pkgs.ulogd.doc}/share/doc/ulogd-pgsql/pgsql-ulogd2.sql" -d ulogd -U ulogd
touch "/var/lib/ulogd/.initialized"
fi
'';
};
}

View file

@ -3,6 +3,7 @@
lib.extra.mkConfig { lib.extra.mkConfig {
enabledModules = [ enabledModules = [
# List of modules to enable # List of modules to enable
"dgn-fail2ban"
"dgn-web" "dgn-web"
]; ];

View file

@ -0,0 +1,33 @@
{ config, lib, ... }:
let
cfg = config.services.castopod;
fpm = config.services.phpfpm.pools.castopod;
in
{
services.nginx = {
resolver.addresses = [ "127.0.0.53" ];
virtualHosts."${cfg.localDomain}" = {
locations."@force_get" = {
extraConfig = lib.mkForce ''
recursive_error_pages on;
proxy_method GET;
proxy_pass https://podcasts.dgnum.eu/$request_uri;
'';
};
locations."~ .php$" = {
extraConfig = lib.mkForce ''
error_page 550 = @force_get;
if ($request_method = HEAD) { return 550; }
fastcgi_intercept_errors on;
fastcgi_index index.php;
fastcgi_pass unix:${fpm.socket};
try_files $uri =404;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
'';
};
};
};
}

Some files were not shown because too many files have changed in this diff Show more