Compare commits

...
Sign in to create a new pull request.

54 commits

Author SHA1 Message Date
e3cacda356 Update hdd encryption docs for lindberg
All checks were successful
CI / build (push) Successful in 5m30s
2025-04-04 18:07:10 +03:00
86a3ffc42d Add flags to deploy-qois
All checks were successful
CI / build (push) Successful in 1m38s
2025-03-31 15:02:18 +03:00
177cca2c53 Set dev-shell nixVersions to latest
All checks were successful
CI / build (push) Successful in 1m50s
2025-03-31 14:46:41 +03:00
d587df9fed chore(deps): lock file maintenance
Some checks failed
CI / build (push) Failing after 24s
2025-03-31 00:00:49 +02:00
c9cde808e2 Add note about clearing git-ci-runner caches
All checks were successful
CI / build (push) Successful in 2m13s
2025-03-26 16:00:05 +02:00
1badc42a60 Clean up subsitutors for builds 2025-03-26 15:53:34 +02:00
afd284a008 Disable backup and outgoing mail in module test
Some checks failed
CI / build (push) Has been cancelled
2025-03-25 23:59:22 +02:00
6818a9cea2 Move sops default file configuration to private submodule 2025-03-25 16:26:59 +02:00
a990c33299 Move shared secrets definition to private submodule 2025-03-25 16:22:02 +02:00
6734f07711 Fix bug in backplane-net module options 2025-03-25 16:12:57 +02:00
dfc4ef90c4 Make static-page test use something else than localhost 2025-03-25 16:05:29 +02:00
ed29aa354a Clean up module imports for future tests 2025-03-25 16:00:48 +02:00
5ff94e05b8 Remove unfree packages 2025-03-25 15:50:08 +02:00
85ea7fe030 Improve nixosModules checks to include all modules by default. 2025-03-25 15:46:08 +02:00
fc39e912ad Extend package set available in git-ci-runner
All checks were successful
CI / build (push) Successful in 1m49s
2025-03-25 15:23:40 +02:00
172e4c37a3 Update build process ci and docs
Some checks failed
CI / build (push) Failing after 15s
2025-03-25 15:04:59 +02:00
cad4f35ee9 Add pre-commit-hook with formatting
Some checks failed
CI / build (push) Failing after 47s
2025-03-25 14:32:57 +02:00
b2c240e87f Apply treefmt 2025-03-25 14:10:54 +02:00
b2395ce611 Add treefmt configuration 2025-03-25 14:09:20 +02:00
ff0ce9d94c Reorganize imports to prevent infinite recursions 2025-03-25 12:49:36 +02:00
ee6b756d3c chore(deps): lock file maintenance
All checks were successful
CI / build (push) Successful in 2m45s
2025-03-24 21:40:14 +01:00
7930f9191d Implement nixos-modules/static-page test
All checks were successful
CI / build (push) Successful in 2m40s
2025-03-24 22:26:50 +02:00
c3962b9738 Remove outdated hardware configurations
All checks were successful
CI / build (push) Successful in 2m48s
2025-03-21 20:22:43 +02:00
b4cd63afe8 Move defaults/base to nixos-modules/system/physical.nix 2025-03-21 20:19:29 +02:00
24b4b04df9 Move defaults/base-vm to nixos-modules/system/virtual-machine.nix 2025-03-21 20:16:31 +02:00
94510a8cd9 Move defaults/base-minimal to nixos-modules/system 2025-03-21 19:54:39 +02:00
0abeadc533 Move nextcloud to nixos-modules 2025-03-21 19:50:44 +02:00
d216ee6f3f Move vpn docs to nixos-module 2025-03-21 19:39:48 +02:00
97d1a30329 Move all nixos-modules out of qois subfolder 2025-03-21 19:23:53 +02:00
d49f58265f Move all nixos-modules to options.qois 2025-03-21 19:19:37 +02:00
9088ef8a04 chore(deps): lock file maintenance
All checks were successful
CI / build (push) Successful in 2m40s
2025-03-20 13:10:18 +01:00
d54febbb87 Enable forgejo email notifications
All checks were successful
CI / build (push) Successful in 2m40s
2025-03-20 13:50:14 +02:00
Raphael Zimmermann
1db545ebab Extend vpn user docs
All checks were successful
CI / build (push) Successful in 2m49s
Co-authored-by: Fabian Hauser <fabian@fh2.ch>
2025-03-18 16:38:56 +02:00
3a9454bd92 lindberg: Reinstate /boot-secondary
All checks were successful
CI / build (push) Successful in 2m58s
2025-03-06 10:28:24 +02:00
24edc73914 lindberg: Remove old md_data raid 2025-03-06 10:28:24 +02:00
Raphael Zimmermann
01e7baa452 Update issue ur to git.qo.is
All checks were successful
CI / build (push) Successful in 2m33s
2025-03-05 07:25:34 +01:00
8610aa5ac2 Remove submodule clone from ci pipeline
All checks were successful
CI / build (push) Successful in 2m32s
2025-03-03 21:13:34 +02:00
078e930143 Lock file maintenance
All checks were successful
CI / build (push) Successful in 2m42s
2025-03-03 18:46:06 +02:00
08368ec872 Upgrade attic max body size to 10G
All checks were successful
CI / build (push) Successful in 4m1s
2025-03-03 18:19:08 +02:00
c3fcdc9322 Upgrade attic max body size
All checks were successful
CI / build (push) Successful in 3m0s
2025-03-03 17:36:53 +02:00
26022cf3dd Switch mstmp password reader to coreutils for services
All checks were successful
CI / build (push) Successful in 2m46s
2025-02-25 22:17:58 +02:00
c503124425 Make loadbalancer domain mapping use exact matches
All checks were successful
CI / build (push) Successful in 2m53s
2025-02-25 20:32:50 +02:00
d18b40525c Add static qo.is landing page
All checks were successful
CI / build (push) Successful in 2m46s
2025-02-03 13:24:24 +02:00
8b6353d209 Lock file maintenance
All checks were successful
CI / build (push) Successful in 2m53s
2025-01-27 00:00:47 +01:00
23e4658e68 Lock file maintenance
All checks were successful
CI / build (push) Successful in 2m51s
2025-01-22 18:49:07 +01:00
8ecebda2b8 Fix renovate submodule cloning
All checks were successful
CI / build (push) Successful in 3m13s
2025-01-22 19:44:12 +02:00
3d04556637 Remove broken private submodule update check
All checks were successful
CI / build (push) Successful in 2m37s
2025-01-22 14:41:56 +02:00
83af6149f4 Add submodule to renovate
All checks were successful
CI / build (push) Successful in 2m38s
2025-01-22 14:37:26 +02:00
91b648889a Update renovate configuration
All checks were successful
CI / build (push) Successful in 2m38s
2025-01-22 14:19:09 +02:00
ed14197eb8 Add notes about changing secrets
All checks were successful
CI / build (push) Successful in 2m25s
2025-01-22 14:05:57 +02:00
9e5c3d5c05 Add renovate config 2025-01-22 14:01:59 +02:00
232e08801f Add git renovate module 2025-01-22 14:01:59 +02:00
627707fe67 Update secrets
All checks were successful
CI / build (push) Successful in 4m8s
2025-01-21 21:20:55 +02:00
529619647c Switch shell to mkShellNoCC
All checks were successful
CI / build (push) Successful in 6m19s
2025-01-14 20:38:39 +02:00
136 changed files with 1561 additions and 1315 deletions

View file

@ -1,11 +1,12 @@
name: CI name: CI
on: on:
push: push:
defaults:
run:
shell: nix develop --command bash -c "{0}"
env: env:
ATTIC_AUTH_TOKEN: ${{ secrets.ATTIC_AUTH_TOKEN }} CACHE_NAME: qois
CACHE_REPOSITORY: qois:qois-infrastructure
jobs: jobs:
build: build:
runs-on: nix runs-on: nix
@ -15,31 +16,20 @@ jobs:
with: with:
token: ${{ secrets.CI_TOKEN }} token: ${{ secrets.CI_TOKEN }}
lfs: false lfs: false
- name: Setup Attic Cache
- name: Add submodules to nix store to circumvent another nix bug env:
SERVER: https://attic.qo.is/
ATTIC_AUTH_TOKEN: ${{ secrets.ATTIC_AUTH_TOKEN }}
run: | run: |
git clone https://git.qo.is/qo.is/infrastructure-private.git /tmp/private attic login "$CACHE_NAME" "$SERVER" "$ATTIC_AUTH_TOKEN"
cd /tmp/private attic use "$CACHE_REPOSITORY"
nix flake prefetch - name: Run Builds and Checks
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)
# Remote build might be neccessary due to non-wheel nix users signing restrictions. deploy --skip-checks --remote-build .#lindberg-webapps.\"docs-ops.qo.is\"
# However, the build should come from the cache anyway. # Remote build is neccessary due to non-wheel nix users signing restrictions. 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,3 +5,5 @@ result*
/.direnv /.direnv
/book /book
/.sops.yaml /.sops.yaml
/.nixos-test-history
/.pre-commit-config.yaml

View file

@ -1,18 +1,21 @@
{ {
"eval": { "eval": {
"target": { "target": {
"args": ["-f", "default.nix"], "args": [
"installable": "" "-f",
} "default.nix"
}, ],
"formatting": { "installable": ""
"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,63 +6,65 @@ 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)
## Building
This repository requires [nix flakes](https://nixos.wiki/wiki/Flakes)
- `nix build`
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
## Development ## Development
- `nix develop` This repository requires [nix flakes](https://nixos.wiki/wiki/Flakes)
- `nix flake check`\
Execute the project's checks, which includes building all configurations and packages. See [Tests](./checks/README.md).
- `nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel`\
Build a single host configuration.
- `nix build .#docs`\
Build the documentation website.
- `nix develop`\
Development environment Development environment
- `nix flake check`
Execute the project's checks - `nix fmt`\
- `nix fmt`
Autofix formatting Autofix formatting
### Working with the private submodule ### Secrets and `private` Submodule
To clone with submodules (if you have access): Secret management is done with [nix-sops](https://github.com/Mic92/sops-nix) and a git submodule in `private`.\
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-configurations/secrets.sops.yaml` (shared secrets for all hosts) and `private/nixos-modules/shared-secrets/default.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).
Usage: To modify secrets:
```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,9 +1,10 @@
# 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)
@ -11,16 +12,15 @@
- [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/qois/git-ci-runner/README.md) - [Git CI Runner](nixos-modules/git-ci-runner/README.md)
- [Git Hosting](nixos-modules/qois/git/README.md) - [Git Hosting](nixos-modules/git/README.md)
- [Nextcloud](defaults/nextcloud/README.md) - [Nextcloud](nixos-modules/cloud/README.md)
- [Nix Caches](nixos-configurations/lindberg-build/applications/README.md) - [Nix Caches](nixos-configurations/lindberg-build/applications/README.md)
- [Static Pages](nixos-modules/qois/static-page/README.md) - [Static Pages](nixos-modules/static-page/README.md)
- [VPN](defaults/vpn/README.md) - [VPN](nixos-modules/vpn-server/README.md)
- [Vaultwarden](nixos-modules/vault/README.md) - [Vaultwarden](nixos-modules/vault/README.md)
# Nixos Configurations # Nixos Configurations
@ -29,4 +29,3 @@
- [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)

25
checks/README.md Normal file
View file

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

View file

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

View file

@ -0,0 +1,68 @@
{
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

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

View file

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

View file

@ -1,22 +0,0 @@
{
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

@ -1,39 +0,0 @@
{
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

@ -1,32 +0,0 @@
{
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
];
}

View file

@ -1,25 +0,0 @@
{
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,4 +1,3 @@
# APU # APU
## Setup ## Setup
@ -7,9 +6,5 @@ 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,9 +2,7 @@
# 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,9 +2,7 @@
# 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,9 +2,7 @@
# 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,7 +1,5 @@
{ {
config,
lib, lib,
pkgs,
modulesPath, modulesPath,
... ...
}: }:

View file

@ -1,33 +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.
{
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

@ -1,40 +0,0 @@
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

@ -1,23 +0,0 @@
{
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

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

View file

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

View file

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

View file

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

View file

@ -74,7 +74,6 @@ 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

@ -1,99 +0,0 @@
# 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
];
}

View file

@ -1,122 +0,0 @@
# 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,7 +4,6 @@ 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,5 +1,4 @@
{ {
deployPkgs,
pkgs, pkgs,
self, self,
... ...

View file

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

View file

@ -1,11 +1,23 @@
{ {
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.mkShell { ${system}.default = pkgs.mkShellNoCC {
name = "qois-infrastructure-shell"; name = "qois-infrastructure-shell";
buildInputs = buildInputs =
let let
@ -14,9 +26,9 @@
vscode = pkgs.vscodium; vscode = pkgs.vscodium;
}; };
in in
[ vscodium-with-extensions ] pre-commit-check.enabledPackages
++ [ vscodium-with-extensions ]
++ (with self.packages.${system}; [ ++ (with self.packages.${system}; [
cache
deploy-qois deploy-qois
sops sops
sops-rekey sops-rekey
@ -24,13 +36,15 @@
++ (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
ssh-to-age
pssh pssh
ssh-to-age
yq yq
jq
]); ]);
LANG = "C.UTF-8"; LANG = "C.UTF-8";
LC_ALL = "C.UTF-8"; LC_ALL = "C.UTF-8";
@ -46,11 +60,7 @@
done done
export XDG_DATA_DIRS export XDG_DATA_DIRS
# Make sure we support the pure case as well as non nixos cases ${pre-commit-check.shellHook}
# 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,7 +9,6 @@ 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": 1736165297, "lastModified": 1741786315,
"narHash": "sha256-OT+sF4eNDFN/OdyUfIQwyp28+CFQL7PAdWn0wGU7F0U=", "narHash": "sha256-VT65AE2syHVj6v/DGB496bqBnu1PXrrzwlw07/Zpllc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "76816af65d5294761636a838917e335992a52e0c", "rev": "0d8c6ad4a43906d14abd5c60e0ffe7b587b213de",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -56,6 +56,65 @@
"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,
@ -74,11 +133,11 @@
}, },
"nixpkgs-nixos-stable": { "nixpkgs-nixos-stable": {
"locked": { "locked": {
"lastModified": 1736061677, "lastModified": 1743231893,
"narHash": "sha256-DjkQPnkAfd7eB522PwnkGhOMuT9QVCZspDpJJYyOj60=", "narHash": "sha256-tpJsHMUPEhEnzySoQxx7+kA+KUtgWqvlcUBqROYNNt0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "cbd8ec4de4469333c82ff40d057350c30e9f7d36", "rev": "c570c1f5304493cafe133b8d843c7c1c4a10d3a6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -88,13 +147,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-nixos-unstable": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1736012469, "lastModified": 1743095683,
"narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=", "narHash": "sha256-gWd4urRoLRe8GLVC/3rYRae1h+xfQzt09xOfb0PaHSk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d", "rev": "5e5402ecbcb27af32284d4a62553c019a3a49ea6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -106,15 +165,16 @@
}, },
"private": { "private": {
"inputs": { "inputs": {
"nixpkgs-nixos-unstable": [ "nixpkgs": [
"nixpkgs-nixos-unstable" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1734984619, "lastModified": 1743779182,
"narHash": "sha256-D9awD3ArJ+8jCPr96HruGS4xpkJ7h2+V0Yiaay/9pyE=", "narHash": "sha256-0wQ+22g6dfnIBIvw2Mji37R7OmCMrmqcp/4zSLQRKSQ=",
"rev": "18d3b3b703a6139b9ebd5ec64311717cf2a6f9bc", "ref": "refs/heads/main",
"revCount": 7, "rev": "8e7ec0d7f4a571a55d0e6b99fcd6f85fea474f1e",
"revCount": 16,
"type": "git", "type": "git",
"url": "file:./private" "url": "file:./private"
}, },
@ -127,24 +187,26 @@
"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-nixos-unstable" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1736064798, "lastModified": 1743305778,
"narHash": "sha256-xJRN0FmX9QJ6+w8eIIIxzBU1AyQcLKJ1M/Gp6lnSD20=", "narHash": "sha256-Ux/UohNtnM5mn9SFjaHp6IZe2aAnUCzklMluNtV6zFo=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "5dc08f9cc77f03b43aacffdfbc8316807773c930", "rev": "8e873886bbfc32163fe027b8676c75637b7da114",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -168,6 +230,26 @@
"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,34 +5,48 @@
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-nixos-unstable.follows = "nixpkgs-nixos-unstable"; private.inputs.nixpkgs.follows = "nixpkgs";
}; };
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-nixos-unstable { inherit system; }; pkgs = import nixpkgs { inherit system; };
deployPkgs = import nixpkgs-nixos-unstable { deployPkgs = import nixpkgs {
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;
@ -40,22 +54,86 @@
}) })
]; ];
}; };
importParams = inputs // { treefmtEval = treefmt-nix.lib.evalModule pkgs ./treefmt.nix;
inherit pkgs; importParams = {
inherit deployPkgs; inherit (inputs)
inherit system; deploy-rs
disko
nixpkgs-nixos-stable
sops-nix
private
git-hooks-nix
;
inherit
deployPkgs
pkgs
system
treefmtEval
;
flakeSelf = self;
}; };
in in
{ {
checks = import ./checks/default.nix importParams; checks = import ./checks/default.nix (
deploy = import ./deploy/default.nix importParams; importParams
devShells = import ./dev-shells/default.nix importParams; // {
formatter.${system} = pkgs.writeShellScriptBin "formatter" '' self = {
${pkgs.findutils}/bin/find $1 -type f -name '*.nix' -exec ${pkgs.nixfmt-rfc-style}/bin/nixfmt ''${@:2} {} + inherit (self)
''; lib
nixosConfigurations = import ./nixos-configurations/default.nix importParams; packages
nixosModules = import ./nixos-modules/default.nix importParams; nixosModules
packages = import ./packages/default.nix importParams; nixosConfigurations
lib = import ./lib/default.nix importParams; deploy
;
};
}
);
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,18 +1,26 @@
{ pkgs, ... }: { pkgs, ... }:
let let
lib = pkgs.lib; inherit (pkgs.lib)
foldersWithNix = attrNames
path: filterAttrs
let filter
folders = lib.attrNames (lib.filterAttrs (n: t: t == "directory") (builtins.readDir path)); pathExists
isFolderWithDefaultNix = folder: lib.pathExists (lib.path.append path "./${folder}/default.nix"); path
in ;
lib.filter isFolderWithDefaultNix folders; # Get a list of all subdirectories of a directory.
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 foldersWithNix; inherit getSubDirs isFolderWithFile foldersWithNix;
# Get a list of default.nix files that are nix submodules of the current folder.
loadSubmodulesFrom = loadSubmodulesFrom =
path: map (folder: lib.path.append path "./${folder}/default.nix") (foldersWithNix path); basePath: map (folder: path.append basePath "./${folder}/default.nix") (foldersWithNix basePath);
} }

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { ... }:
{ {
imports = [ imports = [
@ -6,11 +6,10 @@
./filesystems.nix ./filesystems.nix
../../defaults/hardware/apu.nix ../../defaults/hardware/apu.nix
../../defaults/base
../../defaults/meta
]; ];
qois.system.physical.enable = true;
# 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
# on your system were taken. Its perfectly fine and recommended to leave # on your system were taken. Its perfectly fine and recommended to leave

View file

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

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { config, ... }:
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
services.qois.router = { qois.router = {
enable = true; enable = true;
wanInterface = "enp4s0"; wanInterface = "enp4s0";
wirelessInterfaces = [ "wlp5s0" ]; wirelessInterfaces = [ "wlp5s0" ];

View file

@ -1,17 +1,16 @@
# Host: Cyprianspitz # Host: Cyprianspitz
## 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:
``` ```
@ -24,8 +23,6 @@ TODO
- [Mainboard Manual](docs/z790m-itx-wifi.pdf) - [Mainboard Manual](docs/z790m-itx-wifi.pdf)
### Top Overview ### Top Overview
![](docs/top-view.jpg) ![](docs/top-view.jpg)

View file

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

View file

@ -1,6 +1,4 @@
{ {
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,11 +10,10 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock-z790m.nix ../../defaults/hardware/asrock-z790m.nix
../../defaults/base
../../defaults/meta
]; ];
qois.system.physical.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, pkgs, ... }: { config, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;
@ -73,7 +73,7 @@ in
}; };
# Boot # Boot
services.qois.luks-ssh = { qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { 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
pkgs.lib.genAttrs configs ( genAttrs configs (
config: config:
nixpkgs-nixos-stable.lib.nixosSystem { nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
specialArgs = { specialArgs = {
inherit inputs; inherit inputs;
@ -19,15 +19,6 @@ pkgs.lib.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,5 +1,4 @@
{ {
config,
pkgs, pkgs,
lib, lib,
... ...
@ -13,6 +12,7 @@
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,8 +1,7 @@
{ config, pkgs, ... }: { config, ... }:
{ {
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,15 +1,14 @@
{ 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, pkgs, ... }: { config, ... }:
{ {

View file

@ -1,21 +0,0 @@
{ 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,7 +1,9 @@
{ config, pkgs, ... }: { pkgs, ... }:
{ {
imports = [ ./cloud.nix ];
qois.postgresql.package = pkgs.postgresql_14; qois.postgresql.package = pkgs.postgresql_14;
qois.cloud = {
enable = true;
package = pkgs.nextcloud30;
};
} }

View file

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

View file

@ -1,14 +1,14 @@
{ config, pkgs, ... }: { config, ... }:
{ {
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,3 +1,16 @@
# Web Apps # Web Apps
## fabianhauser.ch ## Setting up new static sites
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 @@
{ config, pkgs, ... }: { pkgs, ... }:
{ {
imports = [ ]; imports = [ ];

View file

@ -1,16 +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, pkgs, ... }: { config, ... }:
{ {

View file

@ -1,10 +1,14 @@
# Host: Lindberg # Host: Lindberg
## Operations {#_operations} ## Operations {#\_operations}
Reboot requires passphrase (see pass `host/lindberg/hdd_luks`) Reboot requires passphrase:
``` 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
``` ```
@ -12,7 +16,6 @@ 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,7 +1,4 @@
{ {
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,11 +11,10 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock.nix ../../defaults/hardware/asrock.nix
../../defaults/base
../../defaults/meta
]; ];
qois.system.physical.enable = true;
# Set your time zone. # Set your time zone.
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";

View file

@ -9,12 +9,8 @@
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.
@ -28,11 +24,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, pkgs, ... }: { config, ... }:
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;
services.qois.luks-ssh = { qois.luks-ssh = {
enable = true; enable = true;
interface = "eth0"; interface = "eth0";
sshPort = 2222; sshPort = 2222;

View file

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

View file

@ -1,11 +0,0 @@
{ 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
2. Set a root password: `sudo passwd root` 1. Set a root password: `sudo passwd root`
3. Get host ip to connect to ssh with `ip a` 1. 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
services.qois.luks-ssh = { qois.luks-ssh = {
enable = true; enable = true;
interface = "eth1"; interface = "eth1";
sshPort = 2222; sshPort = 2222;

View file

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

View file

@ -1,6 +1,5 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -35,7 +34,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,80 @@
{
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

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

View file

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

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.
2. (mabe dump redis data?) 1. (mabe dump redis data?)
3. Import Database Backup 1. Import Database Backup
4. Restore `/var/lib/nextcloud`, which is currently a bind mount on `lindberg`'s `/mnt/data` volume 1. Restore `/var/lib/nextcloud`, which is currently a bind mount on `lindberg`'s `/mnt/data` volume
5. Resync nextcloud files and database, see [nextcloud docs](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html) 1. Resync nextcloud files and database, see [nextcloud docs](https://docs.nextcloud.com/server/latest/admin_manual/maintenance/restore.html)

View file

@ -0,0 +1,135 @@
# 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,8 +1,20 @@
inputs: { {
private,
self,
disko,
sops-nix,
...
}:
{
default = default =
{ config, pkgs, ... }: { ... }:
{ {
imports = (inputs.self.lib.loadSubmodulesFrom ./.) ++ [ inputs.private.nixosModules.default ]; imports = (self.lib.loadSubmodulesFrom ./.) ++ [
../defaults/meta
disko.nixosModules.disko
sops-nix.nixosModules.sops
private.nixosModules.default
];
}; };
} }

View file

@ -2,7 +2,6 @@
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.
@ -19,3 +18,14 @@ 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-*
```

View file

@ -25,6 +25,35 @@ with lib;
default = 10; default = 10;
description = "How many nix runner instances to start"; description = "How many nix runner instances to start";
}; };
trustedSubstituters = mkOption {
type = types.listOf types.str;
default = [
# General substitutors (also elsewhere defined defaults, but without priority params)
"https://cache.nixos.org"
"https://${config.qois.nixpkgs-cache.hostname}"
"https://cache.garnix.io"
# Project builds
"https://attic.qo.is/qois-infrastructure" # https://git.qo.is/qo.is/infrastructure
"https://attic.qo.is/dotfiles" # https://git.qo.is/fabianhauser/dotfiles
];
description = "Substitutors that are trusted by the host.";
};
trustedPublicKeys = mkOption {
type = types.listOf types.str;
default = [
# General subsitutors
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g="
# Project builds
"qois-infrastructure:lh35ymN7Aoxm5Hz0S6JusxE+cYzMU+x9OMKjDVIpfuE=" # https://git.qo.is/qo.is/infrastructure
"dotfiles:KpLi0qe5O5rb8E8N8vntZWBDqFwG3Ksx4AFGizYCLoU=" # https://git.qo.is/fabianhauser/dotfiles
];
description = "Substitutor public keys that are trusted by the host.";
};
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
@ -34,6 +63,12 @@ with lib;
"gitea-runner-${defaultInstanceName}.service" "gitea-runner-${defaultInstanceName}.service"
] ++ (genList (n: "gitea-runner-nix${builtins.toString n}.service") cfg.nixInstances); ] ++ (genList (n: "gitea-runner-nix${builtins.toString n}.service") cfg.nixInstances);
nix.settings = {
trusted-substituters = cfg.trustedSubstituters;
trusted-public-keys = cfg.trustedPublicKeys;
};
virtualisation.podman = { virtualisation.podman = {
enable = true; enable = true;
dockerCompat = true; dockerCompat = true;
@ -146,7 +181,7 @@ with lib;
{ {
systemd.services = systemd.services =
genAttrs (genList (n: "gitea-runner-nix${builtins.toString n}") cfg.nixInstances) genAttrs (genList (n: "gitea-runner-nix${builtins.toString n}") cfg.nixInstances)
(name: { (_name: {
after = [ after = [
"gitea-runner-nix-image.service" "gitea-runner-nix-image.service"
]; ];
@ -237,7 +272,9 @@ with lib;
pkgs.findutils pkgs.findutils
pkgs.gawk pkgs.gawk
pkgs.git pkgs.git
pkgs.git-lfs
pkgs.gnugrep pkgs.gnugrep
pkgs.gnused
pkgs.jq pkgs.jq
pkgs.nix pkgs.nix
pkgs.nodejs pkgs.nodejs

View file

@ -38,7 +38,6 @@ sudo -u forgejo 'nix run nixpkgs#forgejo -- admin user create --config ~custom/c
## Backup / Restore ## Backup / Restore
1. `systemctl stop forgejo.service` 1. `systemctl stop forgejo.service`
2. Import Postgresql Database Backup 1. Import Postgresql Database Backup
3. Restore `/var/lib/forgejo` 1. Restore `/var/lib/forgejo`
4. `systemctl start forgejo.service` 1. `systemctl start forgejo.service`

View file

@ -40,7 +40,11 @@ with lib;
}; };
"ssh.minimum_key_sizes".RSA = 2047; "ssh.minimum_key_sizes".RSA = 2047;
session.COOKIE_SECURE = true; session.COOKIE_SECURE = true;
service.DISABLE_REGISTRATION = true; service = {
DISABLE_REGISTRATION = true;
ENABLE_NOTIFY_MAIL = true;
DEFAULT_KEEP_EMAIL_PRIVATE = true;
};
mailer = { mailer = {
ENABLED = true; ENABLED = true;
PROTOCOL = "sendmail"; PROTOCOL = "sendmail";

View file

@ -9,7 +9,7 @@ with lib;
let let
# We assume that all static pages are hosted on lindberg-webapps # We assume that all static pages are hosted on lindberg-webapps
staticPages = pipe config.qois.static-page.pages [ staticPages = pipe config.qois.static-page.pages [
(mapAttrsToList (name: { domain, domainAliases, ... }: [ domain ] ++ domainAliases)) (mapAttrsToList (_name: { domain, domainAliases, ... }: [ domain ] ++ domainAliases))
flatten flatten
(map (name: { (map (name: {
inherit name; inherit name;
@ -148,7 +148,7 @@ in
frontend http frontend http
mode http mode http
bind *:80 bind *:80
use_backend %[req.hdr(host),lower,map_dom(${domainMappingFile})]-http use_backend %[req.hdr(host),lower,map(${domainMappingFile})]-http
frontend https frontend https
bind *:443 bind *:443
@ -156,7 +156,7 @@ in
tcp-request inspect-delay 5s tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 } tcp-request content accept if { req_ssl_hello_type 1 }
use_backend %[req.ssl_sni,lower,map_dom(${domainMappingFile})]-https use_backend %[req.ssl_sni,lower,map(${domainMappingFile})]-https
## Generated Backends: ## Generated Backends:
${httpBackends} ${httpBackends}

View file

@ -1,17 +1,16 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
let let
cfg = config.services.qois.luks-ssh; cfg = config.qois.luks-ssh;
in in
{ {
options.services.qois.luks-ssh = { options.qois.luks-ssh = {
enable = mkEnableOption "luks-ssh service"; enable = mkEnableOption "luks-ssh service";
interface = mkOption { interface = mkOption {
@ -83,7 +82,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,8 +1,4 @@
{ {
config,
lib,
pkgs,
options,
... ...
}: }:
{ {

View file

@ -1,7 +1,6 @@
{ {
config, config,
lib, lib,
pkgs,
options, options,
... ...
}: }:
@ -43,10 +42,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,7 +1,6 @@
{ {
config, config,
lib, lib,
pkgs,
options, options,
... ...
}: }:
@ -17,13 +16,6 @@ let
type = str; type = str;
inherit description; inherit description;
}); });
mkOptStr =
description:
(mkOption {
type = nullOr str;
default = null;
inherit description;
});
mkNetworkIdOpts = mkNetworkIdOpts =
v: v:
@ -225,10 +217,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,6 +1,5 @@
{ {
config, config,
pkgs,
lib, lib,
... ...
}: }:
@ -16,6 +15,7 @@ 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.busybox}/bin/cat ${config.sops.secrets."msmtp/password".path}"; passwordeval = "${pkgs.coreutils}/bin/cat ${config.sops.secrets."msmtp/password".path}";
}; };
}; };
}; };

View file

@ -1,83 +0,0 @@
{
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

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

View file

@ -0,0 +1,58 @@
{
config,
pkgs,
lib,
inputs,
...
}:
with lib;
let
cfg = config.qois.renovate;
in
{
options.qois.renovate = {
enable = mkEnableOption "Enable renovate service";
gitServer = mkOption {
description = "Gitea/Forgejo server that should be accessed";
type = types.str;
default = "git.qo.is";
};
gitAuthor = mkOption {
description = "Author of commit messages";
type = types.str;
default = "Renovate Bot <sysadmin+renovate@qo.is>";
};
};
config = mkIf cfg.enable {
sops.secrets."renovate/token".restartUnits = [ "renovate.service" ];
sops.secrets."renovate/host_rules".restartUnits = [ "renovate.service" ];
systemd.services.renovate.environment.LOG_LEVEL = "debug";
services.renovate = {
enable = true;
credentials = {
RENOVATE_TOKEN = config.sops.secrets."renovate/token".path;
RENOVATE_HOST_RULES = config.sops.secrets."renovate/host_rules".path;
};
runtimePackages = with pkgs; [
nix
];
settings = {
inherit (cfg) gitAuthor;
endpoint = "https://${cfg.gitServer}/api/v1";
platform = "gitea";
autodiscover = true;
optimizeForDisabled = true;
};
schedule = "*:0/10";
};
systemd.services.renovate = {
path = mkBefore [ inputs.pkgs.nixVersions.latest ]; # Circumvent submodule bug - remove after >=2.26 is the default.
script = mkBefore ''
echo -e "machine ${cfg.gitServer}\n login $(systemd-creds cat 'SECRET-RENOVATE_TOKEN')\n password x-oauth-basic" > ~/.netrc
'';
};
};
}

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