Compare commits

..

1 commit

Author SHA1 Message Date
2152d863c0 Add caral documentation
All checks were successful
CI / build (push) Successful in 3m26s
2025-01-06 16:31:13 +02:00
137 changed files with 1364 additions and 1562 deletions

View file

@ -1,12 +1,11 @@
name: CI name: CI
on: on:
push: push:
defaults:
run:
shell: nix develop --command bash -c "{0}"
env: env:
CACHE_NAME: qois ATTIC_AUTH_TOKEN: ${{ secrets.ATTIC_AUTH_TOKEN }}
CACHE_REPOSITORY: qois:qois-infrastructure
jobs: jobs:
build: build:
runs-on: nix runs-on: nix
@ -16,20 +15,31 @@ jobs:
with: with:
token: ${{ secrets.CI_TOKEN }} token: ${{ secrets.CI_TOKEN }}
lfs: false lfs: false
- name: Setup Attic Cache
env: - name: Add submodules to nix store to circumvent another nix bug
SERVER: https://attic.qo.is/
ATTIC_AUTH_TOKEN: ${{ secrets.ATTIC_AUTH_TOKEN }}
run: | run: |
attic login "$CACHE_NAME" "$SERVER" "$ATTIC_AUTH_TOKEN" git clone https://git.qo.is/qo.is/infrastructure-private.git /tmp/private
attic use "$CACHE_REPOSITORY" cd /tmp/private
- name: Run Builds and Checks nix flake prefetch
run: nix-fast-build --no-nom --max-jobs 6 --skip-cached --attic-cache "$CACHE_REPOSITORY"
- name: Use attic cache
run: nix run .#cache use
- name: Build
run: |
nix build --max-jobs 12 --cores 12
nix run .#cache push
- name: Run Checks
run: nix flake check
- name: Deploy Docs - name: Deploy Docs
if: success() && github.ref == 'refs/heads/main' if: success() && github.ref == 'refs/heads/main'
run: | run: |
mkdir ~/.ssh/ mkdir ~/.ssh/
echo -e "Host lindberg-webapps.backplane.net.qo.is\n StrictHostKeyChecking no" >> ~/.ssh/config echo -e "Host lindberg-webapps.backplane.net.qo.is\n StrictHostKeyChecking no" >> ~/.ssh/config
(umask 0077 && printf "%s\n" "${{ secrets.SSH_DEPLOY_KEY }}" > ~/.ssh/id_ed25519) (umask 0077 && printf "%s\n" "${{ secrets.SSH_DEPLOY_KEY }}" > ~/.ssh/id_ed25519)
deploy --skip-checks --remote-build .#lindberg-webapps.\"docs-ops.qo.is\" # Remote build might be neccessary due to non-wheel nix users signing restrictions.
# Remote build is neccessary due to non-wheel nix users signing restrictions. However, the build should come from the cache anyway. # However, the build should come from the cache anyway.
nix develop --command deploy --skip-checks --remote-build .#lindberg-webapps.\"docs-ops.qo.is\"

2
.gitignore vendored
View file

@ -5,5 +5,3 @@ result*
/.direnv /.direnv
/book /book
/.sops.yaml /.sops.yaml
/.nixos-test-history
/.pre-commit-config.yaml

View file

@ -1,21 +1,18 @@
{ {
"eval": { "eval": {
"target": { "target": {
"args": [ "args": ["-f", "default.nix"],
"-f", "installable": ""
"default.nix" }
], },
"installable": "" "formatting": {
"command": "nixfmt"
},
"options": {
"enable": true,
"target": {
"args": [],
"installable": ""
}
} }
},
"formatting": {
"command": "nixfmt"
},
"options": {
"enable": true,
"target": {
"args": [],
"installable": ""
}
}
} }

View file

@ -1,5 +1,5 @@
{ {
"recommendations": [ "recommendations": [
"jnoortheen.nix-ide" "jnoortheen.nix-ide"
] ]
} }

View file

@ -6,65 +6,63 @@ Check out the current [rendered documentation](https://docs-ops.qo.is).
## Structure ## Structure
`nixos-configurations`: Main nixos configuration for every host.\ `nixos-configurations`: Main nixos configuration for every host.
`defaults`: Configuration defaults\ `defaults`: Configuration defaults
`nixos-modules`: Custom modules (e.g. for vpn and routers)\ `nixos-modules`: Custom modules (e.g. for vpn and routers)
`private`: Private configuration values (like users, sops-encrypted secrets and keys) `private`: Private configuration values (like users, sops-encrypted secrets and keys)
## Development ## Building
This repository requires [nix flakes](https://nixos.wiki/wiki/Flakes) This repository requires [nix flakes](https://nixos.wiki/wiki/Flakes)
- `nix flake check`\ - `nix build`
Execute the project's checks, which includes building all configurations and packages. See [Tests](./checks/README.md). Build all host configurations and docs
- `nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel`
Build a single host configuration with
- `nix build .#docs`
Build the documentation website
- `nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel`\ ## Development
Build a single host configuration.
- `nix build .#docs`\ - `nix develop`
Build the documentation website.
- `nix develop`\
Development environment Development environment
- `nix flake check`
- `nix fmt`\ Execute the project's checks
- `nix fmt`
Autofix formatting Autofix formatting
### Secrets and `private` Submodule ### Working with the private submodule
Secret management is done with [nix-sops](https://github.com/Mic92/sops-nix) and a git submodule in `private`.\ To clone with submodules (if you have access):
Make sure you have the submodule correctly available. To clone with submodules (if you have access):
```bash ```bash
git clone --recurse-submodules https://git.qo.is/qo.is/infrastructure.git git clone --recurse-submodules https://git.qo.is/qo.is/infrastructure.git
# See below for how to commit changes.
``` ```
On changes:
```bash
git add private
nix flake lock --update-input private
```
## Deployment
`nix run .#deploy-qois`
See [Deployment](deploy/README.md) for details.
## Secrets
Secret management is done with [nix-sops](https://github.com/Mic92/sops-nix).
Secrets are stored in `private/passwords.sops.yaml` (sysadmin passwords), Secrets are stored in `private/passwords.sops.yaml` (sysadmin passwords),
`private/nixos-modules/shared-secrets/default.sops.yaml` (shared secrets for all hosts) and `private/nixos-configurations/secrets.sops.yaml` (shared secrets for all hosts) and
`private/nixos-configurations/<hostname>/secrets.sops.yaml` (host specific secrets). `private/nixos-configurations/<hostname>/secrets.sops.yaml` (host specific secrets).
To modify secrets: Usage:
```bash ```bash
sops $file # To edit a file sops $file # To edit a file
sops-rekey # To rekey all secrets, e.g. after a key rollover or new host sops-rekey # To rekey all secrets, e.g. after a key rollover or new host
``` ```
After changing secrets:
```bash
# Commit changes in subrepo
pushd private
git commit
git push
nix flake prefetch . # Make subrepo available in nix store. Required until nix 2.27.
popd
git add private
nix flake lock --update-input private
```
## Deployment
See [Deployment](deploy/README.md) for details.

View file

@ -1,10 +1,9 @@
# Summary # Summary
- [Repository README](README.md) - [Repository README](README.md)
- [Testing](checks/README.md)
- [Deployment](deploy/README.md) - [Deployment](deploy/README.md)
______________________________________________________________________ ---
- [Network Topology](defaults/meta/network.md) - [Network Topology](defaults/meta/network.md)
- [Hardware (generic)](defaults/hardware/README.md) - [Hardware (generic)](defaults/hardware/README.md)
@ -12,15 +11,16 @@ ______________________________________________________________________
- [Updates](updates.md) - [Updates](updates.md)
- [New Host Setup](nixos-configurations/setup.md) - [New Host Setup](nixos-configurations/setup.md)
# Services # Services
- [E-mail](email.md) - [E-mail](email.md)
- [Git CI Runner](nixos-modules/git-ci-runner/README.md) - [Git CI Runner](nixos-modules/qois/git-ci-runner/README.md)
- [Git Hosting](nixos-modules/git/README.md) - [Git Hosting](nixos-modules/qois/git/README.md)
- [Nextcloud](nixos-modules/cloud/README.md) - [Nextcloud](defaults/nextcloud/README.md)
- [Nix Caches](nixos-configurations/lindberg-build/applications/README.md) - [Nix Caches](nixos-configurations/lindberg-build/applications/README.md)
- [Static Pages](nixos-modules/static-page/README.md) - [Static Pages](nixos-modules/qois/static-page/README.md)
- [VPN](nixos-modules/vpn-server/README.md) - [VPN](defaults/vpn/README.md)
- [Vaultwarden](nixos-modules/vault/README.md) - [Vaultwarden](nixos-modules/vault/README.md)
# Nixos Configurations # Nixos Configurations
@ -29,3 +29,4 @@ ______________________________________________________________________
- [cyprianspitz](nixos-configurations/cyprianspitz/README.md) - [cyprianspitz](nixos-configurations/cyprianspitz/README.md)
- [lindberg](nixos-configurations/lindberg/README.md) - [lindberg](nixos-configurations/lindberg/README.md)
- [stompert](nixos-configurations/stompert/README.md) - [stompert](nixos-configurations/stompert/README.md)

View file

@ -1,25 +0,0 @@
# Tests
`nix flake check` currently:
- builds all nixos-configurations
- builds all packages
- runs all [nixos-module tests](#module-tests)
- checks all deployment configurations
- checks repository formatting.
## Module Tests
We test our nixos modules with [NixOS tests](https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests).
Running nixos tests requires QEMU virtualisation, so make sure you have KVM virtualisation support enabled.
Run all: `nix build .#checks.x86_64-linux.nixos-modules`\
Run single test: `nix build .#checks.x86_64-linux.nixos-modules.entries.vm-test-run-testNameAsInDerivationName`
### Run Test Interactively
```bash
nix run .#checks.x86_64-linux.nixos-modules.entries.vm-test-run-testNameAsInDerivationName.driverInteractive
```
See [upstream documentation](https://nixos.org/manual/nixos/stable/#sec-running-nixos-tests-interactively) for more details.

View file

@ -1,22 +1,22 @@
{ {
self, self,
flakeSelf,
system, system,
pkgs, pkgs,
deployPkgs, deployPkgs,
treefmtEval,
... ...
}@inputs: }@inputs:
{ {
${system} = { ${system} = {
formatting = treefmtEval.config.build.check flakeSelf;
nixos-modules = pkgs.callPackage ./nixos-modules { # Check project formatting
defaultModule = self.nixosModules.default; format = pkgs.runCommand "nixfmt-check" { } ''
inherit (self.lib) getSubDirs isFolderWithFile; set -euo pipefail
}; cd ${self}
${self.formatter.${system}}/bin/formatter . --check
mkdir $out
'';
nixos-configurations = import ./nixos-configurations inputs; #TODO(#29): Integration/System tests
# Import deploy-rs tests # Import deploy-rs tests
} // (deployPkgs.deploy-rs.lib.deployChecks self.deploy); } // (deployPkgs.deploy-rs.lib.deployChecks self.deploy);

View file

@ -1,4 +0,0 @@
{ self, pkgs, ... }:
pkgs.linkFarmFromDrvs "all" (
pkgs.lib.mapAttrsToList (_n: v: v.config.system.build.toplevel) self.nixosConfigurations
)

View file

@ -1,68 +0,0 @@
{
linkFarmFromDrvs,
isFolderWithFile,
getSubDirs,
lib,
testers,
defaultModule,
}:
let
inherit (lib)
filter
path
mkDefault
mkForce
readFile
attrNames
concatStringsSep
pipe
;
modulesBaseDir = ../../nixos-modules;
mkTest =
name:
let
getFilePath = file: path.append modulesBaseDir "./${name}/${file}";
in
testers.runNixOSTest {
inherit name;
imports = [
(import (getFilePath "test.nix") {
inherit name;
inherit lib;
})
];
defaults = {
imports = [ defaultModule ];
qois.outgoing-server-mail.enable = mkForce false;
qois.backup-client.enable = mkForce false;
};
# Calls a `test(...)` python function in the test's python file with the list of nodes and helper functions.
# Helper symbols may be added as function args when needed and can be found in:
# https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/test-driver/src/test_driver/driver.py#L121
testScript = mkDefault (
{ nodes, ... }:
let
script = readFile (getFilePath "test.py");
nodeArgs = pipe nodes [
attrNames
(map (val: "${val}=${val}"))
(concatStringsSep ", ")
];
in
''
${script}
test(${nodeArgs}, subtest=subtest)
''
);
};
in
pipe modulesBaseDir [
getSubDirs
(filter (isFolderWithFile "test.nix" modulesBaseDir))
(map mkTest)
(linkFarmFromDrvs "nixos-modules")
]

View file

@ -1,5 +0,0 @@
{ self, pkgs, ... }:
let
inherit (pkgs.lib) attrValues;
in
pkgs.linkFarmFromDrvs "all" (attrValues self.packages)

View file

@ -1,4 +1,6 @@
{ {
config,
lib,
pkgs, pkgs,
... ...
}: }:

View file

@ -2,15 +2,15 @@
config, config,
lib, lib,
pkgs, pkgs,
inputs,
... ...
}: }:
{ {
imports = [ imports = [
./unfree.nix
./applications.nix ./applications.nix
./overlays.nix ./overlays.nix
./physical.nix
./security.nix ./security.nix
./virtual-machine.nix
]; ];
boot.loader.timeout = 2; boot.loader.timeout = 2;
@ -55,9 +55,9 @@
settings = settings =
let let
substituters = [ substituters = [
"https://${config.qois.nixpkgs-cache.hostname}?priority=30" "https://${inputs.self.nixosConfigurations.lindberg-build.config.qois.nixpkgs-cache.hostname}?priority=39"
"https://attic.qo.is/qois-infrastructure?priority=32"
"https://cache.nixos.org?priority=40" "https://cache.nixos.org?priority=40"
"https://attic.qo.is/qois-infrastructure"
]; ];
in in
{ {
@ -69,7 +69,7 @@
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE=" "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE="
]; ];
trusted-substituters = substituters; trusted-substituters = substituters; # For hosts that limit the subst list
inherit substituters; inherit substituters;
}; };
gc = { gc = {
@ -111,6 +111,12 @@
defaultEditor = true; defaultEditor = true;
}; };
sops.defaultSopsFile =
let
defaultSopsPath = "${inputs.private}/nixos-configurations/${config.networking.hostName}/secrets.sops.yaml";
in
lib.mkIf (builtins.pathExists defaultSopsPath) defaultSopsPath;
services.fstrim.enable = true; services.fstrim.enable = true;
qois.outgoing-server-mail.enable = true; qois.outgoing-server-mail.enable = true;

View file

@ -0,0 +1,12 @@
{
config,
lib,
pkgs,
options,
...
}:
{
nixpkgs.overlays = [ (import ../../overlays) ];
nix.nixPath = options.nix.nixPath.default;
}

View file

@ -1,5 +1,7 @@
{ {
config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;

View file

@ -0,0 +1,22 @@
{
config,
lib,
pkgs,
...
}:
{
nixpkgs.config.allowUnfreePredicate =
pkg:
builtins.elem (lib.getName pkg) [
"corefonts"
"camingo-code"
"helvetica-neue-lt-std"
#"kochi-substitute-naga10"
"ttf-envy-code-r"
"vista-fonts"
"vista-fonts-chs"
"xkcd-font-unstable"
"ricty"
];
}

View file

@ -0,0 +1,39 @@
{
config,
lib,
modulesPath,
pkgs,
...
}:
{
imports = [
../base-minimal
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.loader.grub.enable = true;
system.autoUpgrade.allowReboot = true;
services.qemuGuest.enable = true;
boot.initrd.availableKernelModules = [
"ahci"
"xhci_pci"
"sr_mod"
];
# Taken from https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/profiles/minimal.nix
documentation.enable = lib.mkDefault false;
documentation.doc.enable = lib.mkDefault false;
documentation.info.enable = lib.mkDefault false;
documentation.man.enable = lib.mkDefault false;
documentation.nixos.enable = lib.mkDefault false;
}

View file

@ -0,0 +1,32 @@
{
config,
lib,
pkgs,
...
}:
{
environment.systemPackages =
with pkgs;
[
pciutils
dmidecode
smartmontools
iw
efibootmgr
efitools
efivar
pwgen
powertop
lm_sensors
]
++ [
# Filesystem & Disk Utilities
hdparm
smartmontools
]
++ [
# Networking Utilities
tcpdump
];
}

25
defaults/base/default.nix Normal file
View file

@ -0,0 +1,25 @@
{
config,
lib,
pkgs,
...
}:
{
imports = [
../base-minimal
./applications.nix
];
# System Services
services.fwupd.enable = true;
services.smartd = {
enable = true;
notifications.mail = {
enable = true;
mailer = "${pkgs.msmtp}/bin/sendmail";
sender = "system@qo.is";
recipient = "sysadmin@qo.is";
};
};
}

View file

@ -1,3 +1,4 @@
# APU # APU
## Setup ## Setup
@ -6,5 +7,9 @@ To boot the nixos installer with the console port, add `console=ttyS0,115200n8`
# ASROCK Mainboards # ASROCK Mainboards
`F2`: Boot into BIOS\ `F2`: Boot into BIOS
`F11`: Select boot device `F11`: Select boot device
# NUC
- [Boot Keybindings](https://www.intel.com/content/www/us/en/support/articles/000005672/boards-and-kits/desktop-boards.html)

View file

@ -2,7 +2,9 @@
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ {
config,
lib, lib,
pkgs,
modulesPath, modulesPath,
... ...
}: }:

View file

@ -2,7 +2,9 @@
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ {
config,
lib, lib,
pkgs,
modulesPath, modulesPath,
... ...
}: }:

View file

@ -2,7 +2,9 @@
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ {
config,
lib, lib,
pkgs,
modulesPath, modulesPath,
... ...
}: }:

View file

@ -1,5 +1,7 @@
{ {
config,
lib, lib,
pkgs,
modulesPath, modulesPath,
... ...
}: }:

33
defaults/hardware/nuc.nix Normal file
View file

@ -0,0 +1,33 @@
# 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.
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
"e1000e"
"virtio-pci"
];
boot.initrd.kernelModules = [ ];
# boot.kernelModules = [ "kvm-intel" "virtio" "tun" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
# boot.kernelParams = [ "console=ttyS0,115200n8" ];
hardware.cpu.intel.updateMicrocode = true;
powerManagement.cpuFreqGovernor = "ondemand";
nix.settings.max-jobs = lib.mkDefault 8;
}

View file

@ -0,0 +1,40 @@
diff --unified --recursive --text archlinux-linux/drivers/net/wireless/ath/regd.c archlinux-linux-patched/drivers/net/wireless/ath/regd.c
--- a/drivers/net/wireless/ath/regd.c 2019-08-29 18:31:52.749909030 +0200
+++ b/drivers/net/wireless/ath/regd.c 2019-08-29 18:33:33.318773763 +0200
@@ -345,6 +345,8 @@
struct ieee80211_channel *ch;
unsigned int i;
+ return;
+
for (band = 0; band < NUM_NL80211_BANDS; band++) {
if (!wiphy->bands[band])
continue;
@@ -378,6 +380,8 @@
{
struct ieee80211_supported_band *sband;
+ return;
+
sband = wiphy->bands[NL80211_BAND_2GHZ];
if (!sband)
return;
@@ -407,6 +411,8 @@
struct ieee80211_channel *ch;
unsigned int i;
+ return;
+
if (!wiphy->bands[NL80211_BAND_5GHZ])
return;
@@ -639,6 +645,9 @@
const struct ieee80211_regdomain *regd;
wiphy->reg_notifier = reg_notifier;
+
+ return 0;
+
wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
REGULATORY_CUSTOM_REG;

View file

@ -0,0 +1,23 @@
{
config,
lib,
pkgs,
...
}:
{
boot.kernelPatches = [
{
name = "ath10k-override-eeprom-regulatory-domain";
patch = ./ath10k-override-eeprom-regulatory-domain.patch;
extraConfig = ''
EXPERT y
CFG80211_CERTIFICATION_ONUS y
ATH_REG_DYNAMIC_USER_REG_HINTS y
ATH_REG_DYNAMIC_USER_CERT_TESTING y
ATH_REG_DYNAMIC_USER_CERT_TESTING y
ATH9K_DFS_CERTIFIED y
ATH10K_DFS_CERTIFIED y
'';
}
];
}

View file

@ -0,0 +1,11 @@
{
config,
lib,
pkgs,
...
}:
{
services.hostapd.extraConfig = ''
ht_capab=[HT40-][HT40+][SHORT-GI-40][TX-STBC][RX-STBC1][DSSS_CCK-40]
'';
}

View file

@ -1,4 +1,7 @@
{ {
config,
lib,
pkgs,
... ...
}: }:
{ {

View file

@ -1,4 +1,7 @@
{ {
config,
lib,
pkgs,
... ...
}: }:
{ {

View file

@ -1,5 +1,7 @@
{ {
config, config,
lib,
pkgs,
... ...
}: }:
{ {

View file

@ -74,6 +74,7 @@ All Services are published under the *qo.is* domain name. Following services are
## Contacts ## Contacts
### Init7 ### Init7
- [Status Netzwerkdienste](https://www.init7.net/status/) - [Status Netzwerkdienste](https://www.init7.net/status/)

View file

@ -11,7 +11,7 @@ For user documentation, refer to the [upstream Nextcloud docs](https://docs.next
## Backup / Restore ## Backup / Restore
1. Stop all related services: nextcloud, php-fpm, redis etc. 1. Stop all related services: nextcloud, php-fpm, redis etc.
1. (mabe dump redis data?) 2. (mabe dump redis data?)
1. Import Database Backup 3. Import Database Backup
1. Restore `/var/lib/nextcloud`, which is currently a bind mount on `lindberg`'s `/mnt/data` volume 4. Restore `/var/lib/nextcloud`, which is currently a bind mount on `lindberg`'s `/mnt/data` volume
1. Resync nextcloud files and database, see [nextcloud docs](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html) 5. Resync nextcloud files and database, see [nextcloud docs](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html)

View file

@ -0,0 +1,99 @@
# Default configuration for hosts
{
config,
lib,
pkgs,
...
}:
{
sops.secrets."nextcloud/admin" = with config.users.users.nextcloud; {
inherit group;
owner = name;
};
services.postgresql.enable = true;
qois.backup-client.includePaths = [ config.services.nextcloud.home ];
services.nextcloud = {
enable = true;
https = true;
webfinger = true;
maxUploadSize = "10G";
database.createLocally = true;
config = {
adminpassFile = config.sops.secrets."nextcloud/admin".path;
adminuser = "root";
dbtype = "pgsql";
};
appstoreEnable = false;
extraApps = {
inherit (config.services.nextcloud.package.passthru.packages.apps)
calendar
contacts
deck
groupfolders
maps
memories
music
news
notes
notify_push
tasks
twofactor_webauthn
;
};
phpOptions = {
"opcache.interned_strings_buffer" = "23";
};
poolSettings = {
"pm" = "dynamic";
"pm.max_children" = "256";
"pm.max_requests" = "500";
"pm.max_spare_servers" = "16";
"pm.min_spare_servers" = "2";
"pm.start_servers" = "8";
};
configureRedis = true;
caching.redis = true;
notify_push = {
enable = true;
bendDomainToLocalhost = true;
};
settings = {
log_type = "syslog";
syslog_tag = "nextcloud";
"memories.exiftool" = "${lib.getExe pkgs.exiftool}";
"memories.vod.ffmpeg" = "${lib.getExe pkgs.ffmpeg-headless}";
"memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe";
preview_ffmpeg_path = "${lib.getExe pkgs.ffmpeg-headless}";
mail_smtpmode = "sendmail";
mail_domain = "qo.is";
};
};
services.phpfpm.pools.nextcloud.settings = {
"pm.max_children" = lib.mkForce "256";
"pm.max_spare_servers" = lib.mkForce "16";
"pm.start_servers" = lib.mkForce "8";
};
users.users.nextcloud.extraGroups = [ "postdrop" ];
systemd.services.nextcloud-cron = {
path = [ pkgs.perl ];
};
environment.systemPackages = with pkgs; [
nodejs # required for Recognize
];
}

122
defaults/vpn/README.md Normal file
View file

@ -0,0 +1,122 @@
# VPN
On [vpn.qo.is](https://vpn.qo.is) we run a [Tailscale](https://tailscale.com) compatible VPN service. To use the service, you can use a normal Tailscale client with following additional configuration:
| Option | Recommended value | Description |
|--------|-------------------|-------------|
| `accept-routes` | enabled (flag) | Accept direct routes to internal services |
| `exit-node` | `100.64.0.5` (lindberg) or `100.64.0.6` (cypriaspitz) | Use host as [exit node](#exit-nodes) |
| `login-server` | `https://vpn.qo.is` | Use our own VPN service and not tailscale's upstream one |
⚠️ Currently, if the client is in an IPv6 network, the transport is broken. See [#51](https://gitlab.com/qo.is/infrastructure/-/issues/51) for progress on this.
## Exit nodes
- `100.64.0.5`: lindberg (riedbach-net)
- `100.64.0.6`: cyprianspitz (plessur-net)
Currently, name resolution for these do not work reliably on first starts, hence the IP must be used. This hould be fixed in the future.
## User and Client Management
To register a new client, you can generate a pre-auth key and insert it in the client:
```bash
headscale preauthkeys create --user marlene.mayer
```
Or alternatively use the register command shown when configuring the VPN client.
## ACL
At this time, there are a few ACL rules to isolate a users host but do not expect them to be expected to be enforced - expect your client to be accessible by the whole network.
## Exit Nodes
To add an exit node, create a preauth secret on the `vpn.qo.is` host:
```bash
headscale preauthkeys create --user srv --reusable
```
and configure the host as follows:
```nix
# TODO: This should not be a snipped but a module
{config, ...}: {
# Use this node as vpn exit node
services.tailscale = let meta = config.qois.meta; in {
enable = true;
openFirewall = true;
useRoutingFeatures = "server";
authKeyFile = "/secrets/wireguard/tailscale-key"; # The preauth secret. TODO: Should be in sops.
extraUpFlags = [
"--login-server=https://vpn.qo.is"
"--advertise-exit-node"
(
with meta.network.virtual.backplane.v4; "--advertise-routes=${id}/${builtins.toString prefixLength}"
)
"--advertise-tags=tag:srv"
];
};
}
```
and register it in Headscale with:
```bash
headscale nodes register -u srv -k nodekey:xyzxyzxyzxyzxyzxyzxyzxyz
```
With using the `srv` user, exit nodes and routes get automatically accepted as trusted.
## Clients
### NixOS
Sample config:
```nix
{ config, pkgs, ... }: {
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "client";
authKeyFile = "/secrets/wireguard/tailscale-key"; # This is the pre-auth secret. Make sure it's only accessible by root.
extraUpFlags = [
"--operator"
"yourUserNameChangePlease"
"--accept-routes"
"--exit-node=100.64.0.5"
"--login-server=https://vpn.qo.is"
];
};
}
```
### Mobile App
> Android App: Tip 5 times on the tooltip dots to reveal server config option
See [this Headscale documentation for more](https://headscale.net/android-client/#configuring-the-headscale-url) on how to configure the mobile app. Note that on restarts, sometimes you have to reopen/save the config dialog. If the Tailscale login site is shown, just close the browser with the ❌.
## Backup and Restore
### Server
1. `systemctl stop headscale`
2. Replace `/var/lib/headscale`
3. `systemctl start headscale`
4. Monitor logs for errors
Note: `/var/lib/headscale` contains a sqlite database.
### Clients
1. `systemctl stop tailscaled`
2. Replace `/var/lib/tailscale`
3. `systemctl start tailscaled`
4. Monitor logs for errors

View file

@ -4,6 +4,7 @@ Note that you have to be connected to the `vpn.qo.is`
(or execute the deployment from a host that is in the `backplane.net.qo.is` overlay network) (or execute the deployment from a host that is in the `backplane.net.qo.is` overlay network)
and that you need to have SSH root access to the target machines. and that you need to have SSH root access to the target machines.
## Deploy to selected target hosts ## Deploy to selected target hosts
```bash ```bash

View file

@ -1,4 +1,5 @@
{ {
deployPkgs,
pkgs, pkgs,
self, self,
... ...

View file

@ -1,5 +1,6 @@
{ {
deployPkgs, deployPkgs,
pkgs,
self, self,
system, system,
... ...

View file

@ -1,23 +1,11 @@
{ {
pkgs, pkgs,
git-hooks-nix,
treefmtEval,
system, system,
self, self,
... ...
}: }:
let
pre-commit-check = git-hooks-nix.lib.${system}.run {
src = ../.;
hooks.treefmt = {
enable = true;
package = treefmtEval.config.build.wrapper;
always_run = true;
};
};
in
{ {
${system}.default = pkgs.mkShellNoCC { ${system}.default = pkgs.mkShell {
name = "qois-infrastructure-shell"; name = "qois-infrastructure-shell";
buildInputs = buildInputs =
let let
@ -26,9 +14,9 @@ in
vscode = pkgs.vscodium; vscode = pkgs.vscodium;
}; };
in in
pre-commit-check.enabledPackages [ vscodium-with-extensions ]
++ [ vscodium-with-extensions ]
++ (with self.packages.${system}; [ ++ (with self.packages.${system}; [
cache
deploy-qois deploy-qois
sops sops
sops-rekey sops-rekey
@ -36,15 +24,13 @@ in
++ (with pkgs; [ ++ (with pkgs; [
attic-client attic-client
deploy-rs deploy-rs
jq
nix-fast-build
nixVersions.latest
nixd nixd
nixfmt-rfc-style nixfmt-rfc-style
nixos-anywhere nixos-anywhere
pssh
ssh-to-age ssh-to-age
pssh
yq yq
jq
]); ]);
LANG = "C.UTF-8"; LANG = "C.UTF-8";
LC_ALL = "C.UTF-8"; LC_ALL = "C.UTF-8";
@ -60,7 +46,11 @@ in
done done
export XDG_DATA_DIRS export XDG_DATA_DIRS
${pre-commit-check.shellHook} # Make sure we support the pure case as well as non nixos cases
# where dynamic bash completions were not sourced.
#if ! type _completion_loader > /dev/null; then
# . ${pkgs.bash-completion}/etc/profile.d/bash_completion.sh
#fi
''; '';
}; };
} }

View file

@ -9,6 +9,7 @@ E-Mail accounts should be created in a `first.lastname@qo.is` fashion.
Alias/forwarding Domains may be added on an best effort basis. Alias/forwarding Domains may be added on an best effort basis.
Bills for these domains should go directly to the respective owner (i.e. should be registered with own accounts). Bills for these domains should go directly to the respective owner (i.e. should be registered with own accounts).
## System E-mails ## System E-mails
For groups, systems, services that require e-mail access, other accounts may be created. For groups, systems, services that require e-mail access, other accounts may be created.

126
flake.lock generated
View file

@ -27,11 +27,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1741786315, "lastModified": 1736165297,
"narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=", "narHash": "sha256-OT+sF4eNDFN/OdyUfIQwyp28+CFQL7PAdWn0wGU7F0U=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de", "rev": "76816af65d5294761636a838917e335992a52e0c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -56,65 +56,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"git-hooks-nix": {
"inputs": {
"flake-compat": "flake-compat_2",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1742649964,
"narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1702272962, "lastModified": 1702272962,
@ -133,11 +74,11 @@
}, },
"nixpkgs-nixos-stable": { "nixpkgs-nixos-stable": {
"locked": { "locked": {
"lastModified": 1743231893, "lastModified": 1736061677,
"narHash": "sha256-tpJsHMUPEhEnzySoQxx7+kA+KUtgWqvlcUBqROYNNt0=", "narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "c570c1f5304493cafe133b8d843c7c1c4a10d3a6", "rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -147,13 +88,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_2": { "nixpkgs-nixos-unstable": {
"locked": { "locked": {
"lastModified": 1743095683, "lastModified": 1736012469,
"narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=", "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6", "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -165,16 +106,15 @@
}, },
"private": { "private": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs-nixos-unstable": [
"nixpkgs" "nixpkgs-nixos-unstable"
] ]
}, },
"locked": { "locked": {
"lastModified": 1743779182, "lastModified": 1734984619,
"narHash": "sha256-0wQ+22g6dfnIBIvw2Mji37R7OmCMrmqcp/4zSLQRKSQ=", "narHash": "sha256-D9awD3ArJ+8jCPr96HruGS4xpkJ7h2+V0Yiaay/9pyE=",
"ref": "refs/heads/main", "rev": "18d3b3b703a6139b9ebd5ec64311717cf2a6f9bc",
"rev": "8e7ec0d7f4a571a55d0e6b99fcd6f85fea474f1e", "revCount": 7,
"revCount": 16,
"type": "git", "type": "git",
"url": "file:./private" "url": "file:./private"
}, },
@ -187,26 +127,24 @@
"inputs": { "inputs": {
"deploy-rs": "deploy-rs", "deploy-rs": "deploy-rs",
"disko": "disko", "disko": "disko",
"git-hooks-nix": "git-hooks-nix",
"nixpkgs": "nixpkgs_2",
"nixpkgs-nixos-stable": "nixpkgs-nixos-stable", "nixpkgs-nixos-stable": "nixpkgs-nixos-stable",
"nixpkgs-nixos-unstable": "nixpkgs-nixos-unstable",
"private": "private", "private": "private",
"sops-nix": "sops-nix", "sops-nix": "sops-nix"
"treefmt-nix": "treefmt-nix"
} }
}, },
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs-nixos-unstable"
] ]
}, },
"locked": { "locked": {
"lastModified": 1743305778, "lastModified": 1736064798,
"narHash": "sha256-Ux/UohNtnM5mn9SFjaHp6IZe2aAnUCzklMluNtV6zFo=", "narHash": "sha256-xJRN0FmX9QJ6+w8eIIIxzBU1AyQcLKJ1M/Gp6lnSD20=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "8e873886bbfc32163fe027b8676c75637b7da114", "rev": "5dc08f9cc77f03b43aacffdfbc8316807773c930",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -230,26 +168,6 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1743081648,
"narHash": "sha256-WRAylyYptt6OX5eCEBWyTwOEqEtD6zt33rlUkr6u3cE=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "29a3d7b768c70addce17af0869f6e2bd8f5be4b7",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"utils": { "utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"

132
flake.nix
View file

@ -5,48 +5,34 @@
extra-trusted-public-keys = "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE="; extra-trusted-public-keys = "qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE=";
}; };
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.11";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
git-hooks-nix = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
sops-nix = {
url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.url = "github:serokell/deploy-rs";
disko = { disko = {
url = "github:nix-community/disko"; url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs-nixos-stable"; inputs.nixpkgs.follows = "nixpkgs-nixos-stable";
}; };
nixpkgs-nixos-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-nixos-stable.url = "github:NixOS/nixpkgs/nixos-24.11";
sops-nix = {
url = "github:Mic92/sops-nix";
inputs = {
nixpkgs.follows = "nixpkgs-nixos-unstable";
};
};
private.url = "git+file:./private"; private.url = "git+file:./private";
private.inputs.nixpkgs.follows = "nixpkgs"; private.inputs.nixpkgs-nixos-unstable.follows = "nixpkgs-nixos-unstable";
}; };
outputs = outputs =
{ { nixpkgs-nixos-unstable, deploy-rs, ... }@inputs:
self,
nixpkgs,
deploy-rs,
treefmt-nix,
...
}@inputs:
let let
system = "x86_64-linux"; system = "x86_64-linux";
# Packages for development and build process # Packages for development and build process
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs-nixos-unstable { inherit system; };
deployPkgs = import nixpkgs { deployPkgs = import nixpkgs-nixos-unstable {
inherit system; inherit system;
overlays = [ overlays = [
deploy-rs.overlay deploy-rs.overlay
(_self: super: { (self: super: {
deploy-rs = { deploy-rs = {
inherit (pkgs) deploy-rs; inherit (pkgs) deploy-rs;
lib = super.deploy-rs.lib; lib = super.deploy-rs.lib;
@ -54,86 +40,22 @@
}) })
]; ];
}; };
treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix; importParams = inputs // {
importParams = { inherit pkgs;
inherit (inputs) inherit deployPkgs;
deploy-rs inherit system;
disko
nixpkgs-nixos-stable
sops-nix
private
git-hooks-nix
;
inherit
deployPkgs
pkgs
system
treefmtEval
;
flakeSelf = self;
}; };
in in
{ {
checks = import ./checks/default.nix ( checks = import ./checks/default.nix importParams;
importParams deploy = import ./deploy/default.nix importParams;
// { devShells = import ./dev-shells/default.nix importParams;
self = { formatter.${system} = pkgs.writeShellScriptBin "formatter" ''
inherit (self) ${pkgs.findutils}/bin/find $1 -type f -name '*.nix' -exec ${pkgs.nixfmt-rfc-style}/bin/nixfmt ''${@:2} {} +
lib '';
packages nixosConfigurations = import ./nixos-configurations/default.nix importParams;
nixosModules nixosModules = import ./nixos-modules/default.nix importParams;
nixosConfigurations packages = import ./packages/default.nix importParams;
deploy lib = import ./lib/default.nix importParams;
;
};
}
);
deploy = import ./deploy/default.nix (
importParams
// {
self = {
inherit (self)
lib
packages
nixosModules
nixosConfigurations
;
};
}
);
devShells = import ./dev-shells/default.nix (
importParams
// {
self = {
inherit (self) lib packages;
};
}
);
formatter.${system} = treefmtEval.config.build.wrapper;
nixosConfigurations = import ./nixos-configurations/default.nix (
importParams
// {
self = {
inherit (self) lib packages nixosModules;
};
}
);
nixosModules = import ./nixos-modules/default.nix (
importParams
// {
self = {
inherit (self) lib packages;
};
}
);
packages = import ./packages/default.nix (
importParams
// {
self = {
inherit (self) lib packages;
};
}
);
lib = import ./lib/default.nix { inherit pkgs; };
}; };
} }

View file

@ -1,26 +1,18 @@
{ pkgs, ... }: { pkgs, ... }:
let let
inherit (pkgs.lib) lib = pkgs.lib;
attrNames foldersWithNix =
filterAttrs path:
filter let
pathExists folders = lib.attrNames (lib.filterAttrs (n: t: t == "directory") (builtins.readDir path));
path isFolderWithDefaultNix = folder: lib.pathExists (lib.path.append path "./${folder}/default.nix");
; in
# Get a list of all subdirectories of a directory. lib.filter isFolderWithDefaultNix folders;
getSubDirs = base: attrNames (filterAttrs (_n: t: t == "directory") (builtins.readDir base));
# Check if a folder with a base path and folder name contains a file with a specific name
isFolderWithFile =
fileName: basePath: folderName:
(pathExists (path.append basePath "./${folderName}/${fileName}"));
# Get a list of subfolders that contain a default.nix file.
foldersWithNix = base: filter (isFolderWithFile "default.nix" base) (getSubDirs base);
in in
{ {
inherit getSubDirs isFolderWithFile foldersWithNix; inherit foldersWithNix;
# Get a list of default.nix files that are nix submodules of the current folder.
loadSubmodulesFrom = loadSubmodulesFrom =
basePath: map (folder: path.append basePath "./${folder}/default.nix") (foldersWithNix basePath); path: map (folder: lib.path.append path "./${folder}/default.nix") (foldersWithNix path);
} }

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
@ -6,9 +6,10 @@
./filesystems.nix ./filesystems.nix
../../defaults/hardware/apu.nix ../../defaults/hardware/apu.nix
];
qois.system.physical.enable = true; ../../defaults/base
../../defaults/meta
];
# This value determines the NixOS release from which the default # This value determines the NixOS release from which the default
# settings for stateful data, like fi:le locations and database versions # settings for stateful data, like fi:le locations and database versions

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
fileSystems."/" = { fileSystems."/" = {

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;
@ -32,7 +32,7 @@ in
qois.backplane-net.enable = true; qois.backplane-net.enable = true;
# TODO: Metaize ips # TODO: Metaize ips
qois.router = { services.qois.router = {
enable = true; enable = true;
wanInterface = "enp4s0"; wanInterface = "enp4s0";
wirelessInterfaces = [ "wlp5s0" ]; wirelessInterfaces = [ "wlp5s0" ];

View file

@ -1,16 +1,17 @@
# Host: Cyprianspitz # Host: Cyprianspitz (+Router: Caral)
## Operations {#\_operations} ## Operations {#_operations}
Reboot requires passphrase. Reboot requires passphrase.
```bash ``` bash
# Get HDD Password: # Get HDD Password:
sops decrypt --extract '["system"]["hdd"]' private/nixos-configurations/cyprianspitz/secrets.sops.yaml sops decrypt --extract '["system"]["hdd"]' private/nixos-configurations/cyprianspitz/secrets.sops.yaml
ssh -p 8223 root@calanda.plessur-ext.net.qo.is ssh -p 8223 root@calanda.plessur-ext.net.qo.is
``` ```
Direct remote ssh access: Direct remote ssh access:
``` ```
@ -23,6 +24,40 @@ TODO
- [Mainboard Manual](docs/z790m-itx-wifi.pdf) - [Mainboard Manual](docs/z790m-itx-wifi.pdf)
### Networking: Caral Internet Router
A [MikroTik `CCR2004-1G-2XS-PCIe`](https://mikrotik.com/product/ccr2004_1g_2xs_pcie#fndtn-downloads) is used for internet access.
It's a fiber card with build in router, supporting 2x 25Gbit SFP28 cages and 1Gbit RJ45 eth.
- [RouterOS Docs](https://help.mikrotik.com/docs/spaces/ROS/pages/328059/RouterOS)
[The manual](docs/CCR2004-1G-2XS-PCIe_241138.pdf) states:
> This form-factor does come with certain limitations that you should keep in mind.
> The CCR NIC card needs some time to boot up compared to ASIC-based setups.
> If the host system is up before the CCR card, it will not appear among the available devices.
> You should add a PCIe device initialization delay after power-up in the BIOS.
> Or you will need to re-initialize the PCIe devices from the HOST system.
In our case, since networking is reinitialized after the LUKS password promt, this should not be a issue in practice. However, if networking would not be available, contact someone for a physical reboot and wait longer before entering the HDD password.
To reload the card's virtual interfaces on a running system:
```bash
echo "1" > /sys/bus/pci/devices/0000\:01\:00.0/remove
sleep 2
echo "1" > /sys/bus/pci/rescan
```
To restart the card on a running system:
```bash
echo "1" > /sys/bus/pci/devices/0000\:01\:00.0/reset
sleep 2m # Wait for reboot
echo "1" > /sys/bus/pci/rescan
```
### Top Overview ### Top Overview
![](docs/top-view.jpg) ![](docs/top-view.jpg)

View file

@ -1,4 +1,4 @@
{ config, ... }: { pkgs, config, ... }:
{ {
qois.backup-server = { qois.backup-server = {

View file

@ -1,4 +1,6 @@
{ {
config,
pkgs,
lib, lib,
... ...
}: }:

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
qois.vpn-server.enable = true; qois.vpn-server.enable = true;
} }

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
@ -10,9 +10,10 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock-z790m.nix ../../defaults/hardware/asrock-z790m.nix
];
qois.system.physical.enable = true; ../../defaults/base
../../defaults/meta
];
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;
@ -14,9 +14,25 @@ in
networking.nameservers = [ calandaIp ]; networking.nameservers = [ calandaIp ];
networking.useDHCP = false; networking.useDHCP = false;
networking.interfaces.enp0s31f6.ipv4.addresses = [ networking.interfaces = {
(getNetV4Ip meta.network.physical.plessur-lan) # enp0s31f6: 1 Gbit mainboard interface
]; enp0s31f6.ipv4.addresses = [
(getNetV4Ip meta.network.physical.plessur-lan)
];
# wlp0s20f3: Mainboard Wireless interface
# enp3s0: 2.5 Gbit mainboard interface: Connected to ether1
#enp3s0.useDHCP = true;
# enp1s0f0: mikrotik sfp28-1: ether-pcie1 passthrough
enp1s0f0.useDHCP = true;
# enp1s0f1: mikrotik sfp28-2: ether-pcie2 passthrough
enp1s0f1.useDHCP = true;
# enp1s0f2: mikrotik ether1/bridge1: ether-pcie3 bridge \
enp1s0f2.useDHCP = true;
# enp1s0f3: mikrotik ether1/bridge1: ether-pcie4 bridge > connected to enp3s0
enp1s0f3.useDHCP = true;
};
networking.defaultGateway = { networking.defaultGateway = {
address = calandaIp; address = calandaIp;
@ -73,7 +89,7 @@ in
}; };
# Boot # Boot
qois.luks-ssh = { services.qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";

View file

@ -1,4 +1,4 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
virtualisation.libvirtd = { virtualisation.libvirtd = {
enable = true; enable = true;

View file

@ -2,16 +2,16 @@
self, self,
pkgs, pkgs,
nixpkgs-nixos-stable, nixpkgs-nixos-stable,
disko,
sops-nix,
... ...
}@inputs: }@inputs:
let let
inherit (pkgs.lib) genAttrs;
inherit (nixpkgs-nixos-stable.lib) nixosSystem;
configs = self.lib.foldersWithNix ./.; configs = self.lib.foldersWithNix ./.;
in in
genAttrs configs ( pkgs.lib.genAttrs configs (
config: config:
nixosSystem { nixpkgs-nixos-stable.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = { specialArgs = {
inherit inputs; inherit inputs;
@ -19,6 +19,15 @@ genAttrs configs (
modules = [ modules = [
self.nixosModules.default self.nixosModules.default
./${config}/default.nix ./${config}/default.nix
disko.nixosModules.disko
sops-nix.nixosModules.sops
(
{ ... }:
{
system.extraSystemBuilderCmds = "ln -s ${self} $out/nixos-configuration";
imports = [ ./secrets.nix ];
}
)
]; ];
} }
) )

View file

@ -1,4 +1,5 @@
{ {
config,
pkgs, pkgs,
lib, lib,
... ...
@ -12,7 +13,6 @@
qois.git-ci-runner.enable = true; qois.git-ci-runner.enable = true;
qois.attic.enable = true; qois.attic.enable = true;
qois.postgresql.package = pkgs.postgresql_15; qois.postgresql.package = pkgs.postgresql_15;
qois.renovate.enable = true;
# Remove substituters that are hosted on this node, to prevent lockups # Remove substituters that are hosted on this node, to prevent lockups
# since the current nix implementation is not forgiving with unavailable subsituters. # since the current nix implementation is not forgiving with unavailable subsituters.

View file

@ -1,7 +1,8 @@
{ config, ... }: { config, pkgs, ... }:
{ {
qois.nixpkgs-cache = { qois.nixpkgs-cache = {
enable = true; enable = true;
hostname = "nixpkgs-cache.qo.is";
dnsResolvers = [ config.qois.meta.network.virtual.lindberg-vms-nat.hosts.lindberg.v4.ip ]; dnsResolvers = [ config.qois.meta.network.virtual.lindberg-vms-nat.hosts.lindberg.v4.ip ];
}; };
} }

View file

@ -1,14 +1,15 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
../../defaults/base-vm
../../defaults/meta
./applications ./applications
./disko-config.nix ./disko-config.nix
./networking.nix ./networking.nix
./secrets.nix ./secrets.nix
]; ];
qois.system.virtual-machine.enable = true;
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
{ {

View file

@ -0,0 +1,21 @@
{ config, pkgs, ... }:
let
host = "cloud.qo.is";
in
{
imports = [ ../../../defaults/nextcloud ];
services.postgresql.enable = true;
services.nextcloud = {
hostName = host;
package = pkgs.nextcloud30;
settings.default_phone_region = "CH";
};
services.nginx.virtualHosts."${host}" = {
forceSSL = true;
enableACME = true;
kTLS = true;
};
}

View file

@ -1,9 +1,7 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
qois.postgresql.package = pkgs.postgresql_14;
qois.cloud = { imports = [ ./cloud.nix ];
enable = true;
package = pkgs.nextcloud30; qois.postgresql.package = pkgs.postgresql_14;
};
} }

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {

View file

@ -1,14 +1,14 @@
{ config, ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
../../defaults/base-vm
../../defaults/meta
./applications ./applications
./backup.nix ./backup.nix
./secrets.nix ./secrets.nix
]; ];
qois.system.virtual-machine.enable = true;
boot.loader.grub.device = "/dev/vda"; boot.loader.grub.device = "/dev/vda";
fileSystems."/" = { fileSystems."/" = {
device = "/dev/disk/by-uuid/5b6823ec-921f-400a-a7c0-3fe34d56ae12"; device = "/dev/disk/by-uuid/5b6823ec-921f-400a-a7c0-3fe34d56ae12";

View file

@ -1,16 +1,3 @@
# Web Apps # Web Apps
## Setting up new static sites ## fabianhauser.ch
Generate ssh key for deployment:
```bash
export SSH_KEYFILE=$(mktemp --dry-run -- /dev/shm/key-XXXXXXXXX)
mkfifo -m 600 $SSH_KEYFILE
ssh-keygen -q -t ed25519 -C "ci@git.qo.is" -N "" -f $SSH_KEYFILE <<< "y\ny\n" &
wl-copy --trim-newline --foreground --paste-once < $SSH_KEYFILE
# Paste private key in CI secret "SSH_DEPLOY_KEY" now
# Configure public key:
wl-copy --trim-newline < ${SSH_KEYFILE}.pub
```

View file

@ -1,4 +1,4 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
imports = [ ]; imports = [ ];

View file

@ -1,15 +1,16 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
../../defaults/base-vm
../../defaults/meta
./applications ./applications
./disko-config.nix ./disko-config.nix
./networking.nix ./networking.nix
./secrets.nix ./secrets.nix
]; ];
qois.system.virtual-machine.enable = true;
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
{ {

View file

@ -1,14 +1,10 @@
# Host: Lindberg # Host: Lindberg
## Operations {#\_operations} ## Operations {#_operations}
Reboot requires passphrase: Reboot requires passphrase (see pass `host/lindberg/hdd_luks`)
```bash ``` bash
# Get passphrase
sops decrypt --extract '["system"]["hdd"]' private/nixos-configurations/lindberg/secrets.sops.yaml
# Insert passphrase:
ssh -p 2222 root@lindberg.riedbach-ext.net.qo.is ssh -p 2222 root@lindberg.riedbach-ext.net.qo.is
``` ```
@ -16,6 +12,7 @@ ssh -p 2222 root@lindberg.riedbach-ext.net.qo.is
- [Mainboard Manual](docs/X570Pro4-mainboard-manual.pdf) - [Mainboard Manual](docs/X570Pro4-mainboard-manual.pdf)
### Front / Back ### Front / Back
#### Front Overview #### Front Overview

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ ./loadbalancer.nix ]; imports = [ ./loadbalancer.nix ];

View file

@ -1,4 +1,7 @@
{ {
config,
pkgs,
lib,
... ...
}: }:

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
qois.backup-client.includePaths = [ "/mnt/data" ]; qois.backup-client.includePaths = [ "/mnt/data" ];

View file

@ -1,4 +1,4 @@
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
@ -11,9 +11,10 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock.nix ../../defaults/hardware/asrock.nix
];
qois.system.physical.enable = true; ../../defaults/base
../../defaults/meta
];
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";

View file

@ -9,8 +9,12 @@
MAILADDR root MAILADDR root
ARRAY /dev/md/raid_system metadata=1.2 name=any:raid_system UUID=1becc692:aeb83b67:1c65da45:b8bd4b93 ARRAY /dev/md/raid_system metadata=1.2 name=any:raid_system UUID=1becc692:aeb83b67:1c65da45:b8bd4b93
ARRAY /dev/md/raid_data metadata=1.2 name=any:raid_data UUID=576eabb1:0722bc27:84d9314f:d0145000 ARRAY /dev/md/raid_data metadata=1.2 name=any:raid_data UUID=576eabb1:0722bc27:84d9314f:d0145000
INACTIVE-ARRAY /dev/md125 metadata=1.2 name=nixos:md_data UUID=b9c36b6d:a2e0fa86:f6dbfe57:857cd0d2
''; '';
# TODO: RAID Monitoring
# TODO: Set spin-down time of physical disks
services.fwupd.daemonSettings.EspLocation = pkgs.lib.mkForce config.disko.devices.disk.system-1.content.partitions.boot.content.mountpoint; services.fwupd.daemonSettings.EspLocation = pkgs.lib.mkForce config.disko.devices.disk.system-1.content.partitions.boot.content.mountpoint;
# Use the systemd-boot EFI boot loader. # Use the systemd-boot EFI boot loader.
@ -24,11 +28,11 @@
path = "/boot-primary"; path = "/boot-primary";
efiBootloaderId = "NixOS primary"; efiBootloaderId = "NixOS primary";
} }
{ #{
devices = [ "nodev" ]; # devices = [ "nodev" ];
path = "/boot-secondary"; # path = "/boot-secondary";
efiBootloaderId = "NixOS secondary"; # efiBootloaderId = "NixOS secondary";
} #}
]; ];
}; };
} }

View file

@ -1,4 +1,4 @@
{ config, ... }: { config, pkgs, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;
@ -73,7 +73,7 @@ in
# Boot # Boot
boot.initrd.network.udhcpc.enable = true; boot.initrd.network.udhcpc.enable = true;
qois.luks-ssh = { services.qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";
sshPort = 2222; sshPort = 2222;

View file

@ -1,4 +1,4 @@
{ pkgs, ... }: { config, pkgs, ... }:
{ {
virtualisation.libvirtd = { virtualisation.libvirtd = {
enable = true; enable = true;

View file

@ -0,0 +1,11 @@
{ inputs, ... }:
{
sops.secrets =
let
allHostsSecretsFile = "${inputs.private}/nixos-configurations/secrets.sops.yaml";
in
{
"msmtp/password".sopsFile = allHostsSecretsFile;
"wgautomesh/gossip-secret".sopsFile = allHostsSecretsFile;
};
}

View file

@ -3,8 +3,8 @@
## Prepare Remote Machine ## Prepare Remote Machine
1. Boot nixos installer image 1. Boot nixos installer image
1. Set a root password: `sudo passwd root` 2. Set a root password: `sudo passwd root`
1. Get host ip to connect to ssh with `ip a` 3. Get host ip to connect to ssh with `ip a`
## Verify configuration ## Verify configuration
@ -12,7 +12,7 @@
## Installation ## Installation
````bash ```bash
nix develop nix develop
# Set according to what we want # Set according to what we want
@ -60,11 +60,11 @@ sops exec-file --no-fifo --filename secret.key private/nixos-configurations/$REM
--disk-encryption-keys /run/secrets/system/hdd.key <(yq --raw-output '.system.hdd' {}) \ --disk-encryption-keys /run/secrets/system/hdd.key <(yq --raw-output '.system.hdd' {}) \
--disk-encryption-keys /run/secrets/system/initrd-ssh-key <(yq --raw-output '.system.\"initrd-ssh-key\"' {}) --disk-encryption-keys /run/secrets/system/initrd-ssh-key <(yq --raw-output '.system.\"initrd-ssh-key\"' {})
" "
```` ```
## Post-Setup ## Post-Setup
- Add backplane-vpn pubkey to `network-virtual.nix` configuration with * Add backplane-vpn pubkey to `network-virtual.nix` configuration with
```bash ```bash
wg pubkey < /secrets/wireguard/private/backplane wg pubkey < /secrets/wireguard/private/backplane
``` ```

View file

@ -1,7 +1,7 @@
# Operations {#\_operations} # Operations {#_operations}
Reboot requires passphrase (see pass `host/stompert/hdd_luks`) Reboot requires passphrase (see pass `host/stompert/hdd_luks`)
```bash ``` bash
ssh -p 2222 root@stompert.eem-ext.net.qo.is ssh -p 2222 root@stompert.eem-ext.net.qo.is
``` ```

View file

@ -2,15 +2,15 @@
# your system. Help is available in the configuration.nix(5) man page # your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help). # and in the NixOS manual (accessible by running nixos-help).
{ ... }: { config, pkgs, ... }:
{ {
imports = [ imports = [
../../defaults/hardware/apu.nix ../../defaults/hardware/apu.nix
../../defaults/base
../../defaults/meta
]; ];
qois.system.physical.enable = true;
boot.initrd.luks.devices."systems".device = boot.initrd.luks.devices."systems".device =
"/dev/disk/by-uuid/5718bd19-cb7a-4728-9ec4-6b2be48215fc"; "/dev/disk/by-uuid/5718bd19-cb7a-4728-9ec4-6b2be48215fc";
@ -35,7 +35,7 @@
# Define on which hard drive you want to install Grub. # Define on which hard drive you want to install Grub.
boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
qois.luks-ssh = { services.qois.luks-ssh = {
enable = true; enable = true;
interface = "eth1"; interface = "eth1";
sshPort = 2222; sshPort = 2222;

View file

@ -1,80 +0,0 @@
{
config,
lib,
...
}:
with lib;
let
cfg = config.qois.backplane-net;
in
{
options.qois.backplane-net = {
enable = mkEnableOption "Enable backplane server services";
netName = mkOption {
description = "Network Name";
type = types.str;
default = "backplane";
};
port = mkOption {
description = "Wireguard Default Port";
type = types.number;
default = 51825;
};
};
config = lib.mkIf cfg.enable (
let
hostName = config.networking.hostName;
netConfig = config.qois.meta.network.virtual.${cfg.netName};
hostNetConfig = netConfig.hosts.${hostName};
interface = "wg-${cfg.netName}";
wgService = [ "wireguard-${interface}.service" ];
in
{
sops.secrets."wgautomesh/gossip-secret".restartUnits = [ "wgautomesh.service" ];
networking.wireguard.enable = true;
networking.wireguard.interfaces."wg-${cfg.netName}" = {
ips = [ "${hostNetConfig.v4.ip}/${toString netConfig.v4.prefixLength}" ];
listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else cfg.port;
privateKeyFile = "/secrets/wireguard/private/${cfg.netName}";
generatePrivateKeyFile = true;
};
systemd.network.wait-online.ignoredInterfaces = [ interface ];
networking.firewall.allowedUDPPorts =
if hostNetConfig.endpoint != null then [ hostNetConfig.endpoint.port ] else [ cfg.port ];
# Configure wgautomesh to setup peers. Make sure that the name is not used in the VPN module
services.wgautomesh = {
enable = true;
gossipSecretFile = config.sops.secrets."wgautomesh/gossip-secret".path;
openFirewall = true;
settings = {
inherit interface;
# Map meta network configuration to the format of wgautomesh and filter out peers with endpoints
peers = pipe netConfig.hosts [
(filterAttrs (peerHostName: _: peerHostName != hostName)) # Not this host
(mapAttrsToList (
_: peerConfig: {
address = peerConfig.v4.ip;
endpoint =
if (peerConfig.endpoint != null) then
with peerConfig.endpoint; "${fqdn}:${toString port}"
else
null;
pubkey = peerConfig.publicKey;
}
))
];
};
};
systemd.services.wgautomesh = {
requires = wgService;
after = wgService;
};
}
);
}

View file

@ -1,135 +0,0 @@
# Default configuration for hosts
{
config,
lib,
pkgs,
...
}:
let
cfg = config.qois.cloud;
in
with lib;
{
options.qois.cloud = {
enable = mkEnableOption "Enable qois cloud service";
domain = mkOption {
type = types.str;
default = "cloud.qo.is";
description = "Domain, under which the service is served.";
};
package = mkOption {
type = types.package;
description = "Which package to use for the Nextcloud instance.";
relatedPackages = [
"nextcloud28"
"nextcloud29"
"nextcloud30"
];
};
};
config = mkIf cfg.enable {
services.nginx.virtualHosts."${cfg.domain}" = {
forceSSL = true;
enableACME = true;
kTLS = true;
};
sops.secrets."nextcloud/admin" = with config.users.users.nextcloud; {
inherit group;
owner = name;
};
services.postgresql.enable = true;
qois.backup-client.includePaths = [ config.services.nextcloud.home ];
services.nextcloud = {
inherit (cfg) package;
enable = true;
hostName = cfg.domain;
https = true;
webfinger = true;
maxUploadSize = "10G";
database.createLocally = true;
config = {
adminpassFile = config.sops.secrets."nextcloud/admin".path;
adminuser = "root";
dbtype = "pgsql";
};
appstoreEnable = false;
extraApps = {
inherit (config.services.nextcloud.package.passthru.packages.apps)
calendar
contacts
deck
groupfolders
maps
memories
music
news
notes
notify_push
tasks
twofactor_webauthn
;
};
phpOptions = {
"opcache.interned_strings_buffer" = "23";
};
poolSettings = {
"pm" = "dynamic";
"pm.max_children" = "256";
"pm.max_requests" = "500";
"pm.max_spare_servers" = "16";
"pm.min_spare_servers" = "2";
"pm.start_servers" = "8";
};
configureRedis = true;
caching.redis = true;
notify_push = {
enable = true;
bendDomainToLocalhost = true;
};
settings = {
log_type = "syslog";
syslog_tag = "nextcloud";
"memories.exiftool" = "${lib.getExe pkgs.exiftool}";
"memories.vod.ffmpeg" = "${lib.getExe pkgs.ffmpeg-headless}";
"memories.vod.ffprobe" = "${pkgs.ffmpeg-headless}/bin/ffprobe";
preview_ffmpeg_path = "${lib.getExe pkgs.ffmpeg-headless}";
mail_smtpmode = "sendmail";
mail_domain = "qo.is";
default_phone_region = "CH";
};
};
services.phpfpm.pools.nextcloud.settings = {
"pm.max_children" = lib.mkForce "256";
"pm.max_spare_servers" = lib.mkForce "16";
"pm.start_servers" = lib.mkForce "8";
};
users.users.nextcloud.extraGroups = [ "postdrop" ];
systemd.services.nextcloud-cron = {
path = [ pkgs.perl ];
};
environment.systemPackages = with pkgs; [
nodejs # required for Recognize
];
};
}

View file

@ -1,20 +1,8 @@
{ inputs: {
private,
self,
disko,
sops-nix,
...
}:
{
default = default =
{ ... }: { config, pkgs, ... }:
{ {
imports = (self.lib.loadSubmodulesFrom ./.) ++ [ imports = (inputs.self.lib.loadSubmodulesFrom ./.) ++ [ inputs.private.nixosModules.default ];
../defaults/meta
disko.nixosModules.disko
sops-nix.nixosModules.sops
private.nixosModules.default
];
}; };
} }

View file

@ -1,16 +1,17 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
let let
cfg = config.qois.luks-ssh; cfg = config.services.qois.luks-ssh;
in in
{ {
options.qois.luks-ssh = { options.services.qois.luks-ssh = {
enable = mkEnableOption "luks-ssh service"; enable = mkEnableOption "luks-ssh service";
interface = mkOption { interface = mkOption {
@ -82,7 +83,7 @@ in
with lib; with lib;
concatLists ( concatLists (
mapAttrsToList ( mapAttrsToList (
_name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else [ ] name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else [ ]
) config.users.users ) config.users.users
); );
hostKeys = [ cfg.sshHostKey ]; hostKeys = [ cfg.sshHostKey ];

View file

@ -1,4 +1,8 @@
{ {
config,
lib,
pkgs,
options,
... ...
}: }:
{ {

View file

@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
pkgs,
options, options,
... ...
}: }:
@ -42,10 +43,10 @@ in
}; };
config = config =
let let
hostsWithSshKey = lib.filterAttrs (_name: hostCfg: hostCfg.sshKey != null) cfg; hostsWithSshKey = lib.filterAttrs (name: hostCfg: hostCfg.sshKey != null) cfg;
in in
{ {
programs.ssh.knownHosts = lib.mapAttrs (_name: hostCfg: { programs.ssh.knownHosts = lib.mapAttrs (name: hostCfg: {
publicKey = hostCfg.sshKey; publicKey = hostCfg.sshKey;
}) hostsWithSshKey; }) hostsWithSshKey;
}; };

View file

@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
pkgs,
options, options,
... ...
}: }:
@ -16,6 +17,13 @@ let
type = str; type = str;
inherit description; inherit description;
}); });
mkOptStr =
description:
(mkOption {
type = nullOr str;
default = null;
inherit description;
});
mkNetworkIdOpts = mkNetworkIdOpts =
v: v:
@ -217,10 +225,10 @@ in
(getHostNamesForNetworks hostname cfg.virtual) ++ (getHostNamesForNetworks hostname cfg.physical); (getHostNamesForNetworks hostname cfg.virtual) ++ (getHostNamesForNetworks hostname cfg.physical);
hostsWithPublicKey = lib.filterAttrs ( hostsWithPublicKey = lib.filterAttrs (
_hostName: hostConfig: hostConfig.sshKey != null hostName: hostConfig: hostConfig.sshKey != null
) config.qois.meta.hosts; ) config.qois.meta.hosts;
in in
mapAttrs (name: _hostCfg: { extraHostNames = getHostNames name; }) hostsWithPublicKey; mapAttrs (name: hostCfg: { extraHostNames = getHostNames name; }) hostsWithPublicKey;
}; };
} }

View file

@ -1,5 +1,6 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -15,7 +16,6 @@ with lib;
hostname = mkOption { hostname = mkOption {
type = types.str; type = types.str;
example = "mycache.myhost.org"; example = "mycache.myhost.org";
default = "nixpkgs-cache.qo.is";
description = "Hostname, under which the cache is served"; description = "Hostname, under which the cache is served";
}; };

View file

@ -40,7 +40,7 @@ with lib;
host = "mail.cyon.ch"; host = "mail.cyon.ch";
user = "system@qo.is"; user = "system@qo.is";
from = "no-reply@qo.is"; from = "no-reply@qo.is";
passwordeval = "${pkgs.coreutils}/bin/cat ${config.sops.secrets."msmtp/password".path}"; passwordeval = "${pkgs.busybox}/bin/cat ${config.sops.secrets."msmtp/password".path}";
}; };
}; };
}; };

View file

@ -1,5 +1,6 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -84,7 +85,7 @@ in
services.nginx = { services.nginx = {
enable = true; enable = true;
clientMaxBodySize = "10G"; clientMaxBodySize = "1g";
virtualHosts.${cfg.domain} = { virtualHosts.${cfg.domain} = {
kTLS = true; kTLS = true;
forceSSL = true; forceSSL = true;

View file

@ -1,5 +1,6 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -34,7 +35,7 @@ in
networking.hosts = pipe cfg.loadbalancers [ networking.hosts = pipe cfg.loadbalancers [
(map (hostname: config.qois.meta.network.virtual.backplane.hosts.${hostname}.v4.ip)) (map (hostname: config.qois.meta.network.virtual.backplane.hosts.${hostname}.v4.ip))
(flip genAttrs (_lb: cfg.domains)) (flip genAttrs (lb: cfg.domains))
]; ];
}; };

View file

@ -0,0 +1,83 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.qois.backplane-net;
hostName = config.networking.hostName;
netConfig = config.qois.meta.network.virtual.${cfg.netName};
hostNetConfig = netConfig.hosts.${hostName};
interface = "wg-${cfg.netName}";
wgService = [ "wireguard-${interface}.service" ];
in
{
options.qois.backplane-net = {
enable = mkEnableOption "Enable backplane server services";
netName = mkOption {
description = "Network Name";
type = types.str;
default = "backplane";
};
domain = mkOption {
description = "Domain";
type = types.str;
default = hostNetConfig;
};
port = mkOption {
description = "Wireguard Default Port";
type = types.number;
default = 51825;
};
};
config = {
sops.secrets."wgautomesh/gossip-secret".restartUnits = [ "wgautomesh.service" ];
networking.wireguard.enable = true;
networking.wireguard.interfaces."wg-${cfg.netName}" = {
ips = [ "${hostNetConfig.v4.ip}/${toString netConfig.v4.prefixLength}" ];
listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else cfg.port;
privateKeyFile = "/secrets/wireguard/private/${cfg.netName}";
generatePrivateKeyFile = true;
};
systemd.network.wait-online.ignoredInterfaces = [ interface ];
networking.firewall.allowedUDPPorts =
if hostNetConfig.endpoint != null then [ hostNetConfig.endpoint.port ] else [ cfg.port ];
# Configure wgautomesh to setup peers. Make sure that the name is not used in the VPN module
services.wgautomesh = {
enable = true;
gossipSecretFile = config.sops.secrets."wgautomesh/gossip-secret".path;
openFirewall = true;
settings = {
inherit interface;
# Map meta network configuration to the format of wgautomesh and filter out peers with endpoints
peers = pipe netConfig.hosts [
(filterAttrs (peerHostName: _: peerHostName != hostName)) # Not this host
(mapAttrsToList (
_: peerConfig: {
address = peerConfig.v4.ip;
endpoint =
if (peerConfig.endpoint != null) then
with peerConfig.endpoint; "${fqdn}:${toString port}"
else
null;
pubkey = peerConfig.publicKey;
}
))
];
};
};
systemd.services.wgautomesh = {
requires = wgService;
after = wgService;
};
};
}

View file

@ -2,6 +2,8 @@
config, config,
lib, lib,
options, options,
pkgs,
self,
... ...
}: }:

View file

@ -2,6 +2,8 @@
config, config,
lib, lib,
options, options,
pkgs,
self,
... ...
}: }:

View file

@ -0,0 +1,10 @@
{
config,
pkgs,
inputs,
...
}:
{
imports = inputs.self.lib.loadSubmodulesFrom ./.;
}

View file

@ -2,6 +2,7 @@
Runner for the [Forgejo git instance](../git/README.md). Runner for the [Forgejo git instance](../git/README.md).
## Default docker/ubuntu Runner ## Default docker/ubuntu Runner
Registers a default runner with ubuntu OS or executes user's OCI container with podman. Registers a default runner with ubuntu OS or executes user's OCI container with podman.
@ -18,14 +19,3 @@ Consequentially, don't use to build nix things that should stay secret (which is
## Create Secret Token ## Create Secret Token
To create a new token for registration, follow the steps outlined in the [Forgejo documentation](https://forgejo.org/docs/latest/user/actions/#forgejo-runner). To create a new token for registration, follow the steps outlined in the [Forgejo documentation](https://forgejo.org/docs/latest/user/actions/#forgejo-runner).
## Clear Runner Caches
Under some circumstances, runner caches need to be cleared. This can be done with:
```bash
cd /var/lib/private/gitea-runner/
systemctl stop --all gitea-runner-*
rm -r */.cache/
systemctl start --all gitea-runner-*
```

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