Many small structural improvements (treefmt, no cyclic imports, git-pre-commit-hook, faster CI) #50

Merged
fabianhauser merged 16 commits from update-imports into main 2025-03-26 15:10:42 +01:00
106 changed files with 864 additions and 780 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,25 +16,20 @@ jobs:
with: with:
token: ${{ secrets.CI_TOKEN }} token: ${{ secrets.CI_TOKEN }}
lfs: false lfs: false
- name: Setup Attic Cache
- name: Use attic cache env:
run: nix run .#cache use SERVER: https://attic.qo.is/
ATTIC_AUTH_TOKEN: ${{ secrets.ATTIC_AUTH_TOKEN }}
- name: Build
run: | run: |
nix build --max-jobs 12 --cores 12 attic login "$CACHE_NAME" "$SERVER" "$ATTIC_AUTH_TOKEN"
nix run .#cache push attic use "$CACHE_REPOSITORY"
- name: Run Builds and Checks
- name: Run Checks run: nix-fast-build --no-nom --max-jobs 6 --skip-cached --attic-cache "$CACHE_REPOSITORY"
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\"

1
.gitignore vendored
View file

@ -6,3 +6,4 @@ result*
/book /book
/.sops.yaml /.sops.yaml
/.nixos-test-history /.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,66 +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, don't forget to push the sub-repository and run After changing secrets:
`nix flake update private` in the infrastructure repository to use the changes in builds.
```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

@ -4,7 +4,7 @@
- [Testing](checks/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,7 +12,6 @@
- [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)

View file

@ -1,11 +1,19 @@
# Tests # 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 ## Module Tests
We test our nixos modules with [NixOS tests](https://nixos.org/manual/nixos/stable/index.html#sec-nixos-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. 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 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 single test: `nix build .#checks.x86_64-linux.nixos-modules.entries.vm-test-run-testNameAsInDerivationName`
### Run Test Interactively ### Run Test Interactively

View file

@ -1,26 +1,22 @@
{ {
self, self,
flakeSelf,
system, system,
pkgs, pkgs,
deployPkgs, deployPkgs,
treefmtEval,
... ...
}: }@inputs:
{ {
${system} = { ${system} = {
formatting = treefmtEval.config.build.check flakeSelf;
# Check project formatting
format = pkgs.runCommand "nixfmt-check" { } ''
set -euo pipefail
cd ${self}
${self.formatter.${system}}/bin/formatter . --check
mkdir $out
'';
nixos-modules = pkgs.callPackage ./nixos-modules { nixos-modules = pkgs.callPackage ./nixos-modules {
defaultModule = self.nixosModules.default;
inherit (self.lib) getSubDirs isFolderWithFile; inherit (self.lib) getSubDirs isFolderWithFile;
}; };
#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

@ -4,12 +4,14 @@
getSubDirs, getSubDirs,
lib, lib,
testers, testers,
defaultModule,
}: }:
let let
inherit (lib) inherit (lib)
filter filter
path path
mkDefault mkDefault
mkForce
readFile readFile
attrNames attrNames
concatStringsSep concatStringsSep
@ -23,6 +25,7 @@ let
in in
testers.runNixOSTest { testers.runNixOSTest {
inherit name; inherit name;
imports = [ imports = [
(import (getFilePath "test.nix") { (import (getFilePath "test.nix") {
inherit name; inherit name;
@ -30,7 +33,12 @@ let
}) })
]; ];
defaults.imports = [ (getFilePath "default.nix") ]; 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. # 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: # Helper symbols may be added as function args when needed and can be found in:

View file

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

View file

@ -1,4 +1,3 @@
# APU # APU
## Setup ## Setup
@ -7,5 +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

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,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

@ -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,9 +1,21 @@
{ {
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.mkShellNoCC {
name = "qois-infrastructure-shell"; name = "qois-infrastructure-shell";
@ -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,14 +36,15 @@
++ (with pkgs; [ ++ (with pkgs; [
attic-client attic-client
deploy-rs deploy-rs
jq
nix-fast-build
nixVersions.git nixVersions.git
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";
@ -47,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.

110
flake.lock generated
View file

@ -56,18 +56,77 @@
"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": 1742669843,
"narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=", "narHash": "sha256-G5n+FOXLXcRx+3hCJ6Rt6ZQyF1zqQ0DL0sWAMn2Nk0w=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d", "rev": "1e5b653dff12029333a6546c11e108ede13052eb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixpkgs-unstable", "ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -88,7 +147,7 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-nixos-unstable": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1742669843, "lastModified": 1742669843,
"narHash": "sha256-G5n+FOXLXcRx+3hCJ6Rt6ZQyF1zqQ0DL0sWAMn2Nk0w=", "narHash": "sha256-G5n+FOXLXcRx+3hCJ6Rt6ZQyF1zqQ0DL0sWAMn2Nk0w=",
@ -106,15 +165,16 @@
}, },
"private": { "private": {
"inputs": { "inputs": {
"nixpkgs-nixos-unstable": [ "nixpkgs": [
"nixpkgs-nixos-unstable" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1737552783, "lastModified": 1742912717,
"narHash": "sha256-pJ2lp36L3++a5HtdN7ULcVpdB4j7yo90TDayWuAO+T8=", "narHash": "sha256-jKDVM4hLzNwYpg1/at53B2LZIEEvey1UUIi5cR8wNVQ=",
"rev": "33cf80043c64ddd6882268430454e3cbe98b692b", "ref": "refs/heads/main",
"revCount": 11, "rev": "80b04cd406adc46357888614ecc3f467b85ab8fa",
"revCount": 15,
"type": "git", "type": "git",
"url": "file:./private" "url": "file:./private"
}, },
@ -127,16 +187,18 @@
"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": {
@ -168,6 +230,26 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1742370146,
"narHash": "sha256-XRE8hL4vKIQyVMDXykFh4ceo3KSpuJF3ts8GKwh5bIU=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "adc195eef5da3606891cedf80c0d9ce2d3190808",
"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

@ -8,7 +8,7 @@ let
path path
; ;
# Get a list of all subdirectories of a directory. # Get a list of all subdirectories of a directory.
getSubDirs = base: attrNames (filterAttrs (n: t: t == "directory") (builtins.readDir base)); 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 # Check if a folder with a base path and folder name contains a file with a specific name
isFolderWithFile = isFolderWithFile =
fileName: basePath: folderName: fileName: basePath: folderName:

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { ... }:
{ {
imports = [ imports = [
@ -6,8 +6,6 @@
./filesystems.nix ./filesystems.nix
../../defaults/hardware/apu.nix ../../defaults/hardware/apu.nix
../../defaults/meta
]; ];
qois.system.physical.enable = true; qois.system.physical.enable = true;

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;

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,8 +10,6 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock-z790m.nix ../../defaults/hardware/asrock-z790m.nix
../../defaults/meta
]; ];
qois.system.physical.enable = true; qois.system.physical.enable = true;

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { config, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;

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,
... ...

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,8 +1,7 @@
{ config, pkgs, ... }: { ... }:
{ {
imports = [ imports = [
../../defaults/meta
./applications ./applications
./disko-config.nix ./disko-config.nix

View file

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

View file

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

View file

@ -1,8 +1,7 @@
{ config, pkgs, ... }: { config, ... }:
{ {
imports = [ imports = [
../../defaults/meta
./applications ./applications
./backup.nix ./backup.nix
./secrets.nix ./secrets.nix

View file

@ -2,7 +2,6 @@
## Setting up new static sites ## Setting up new static sites
Generate ssh key for deployment: Generate ssh key for deployment:
```bash ```bash

View file

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

View file

@ -1,9 +1,7 @@
{ config, pkgs, ... }: { ... }:
{ {
imports = [ imports = [
../../defaults/meta
./applications ./applications
./disko-config.nix ./disko-config.nix
./networking.nix ./networking.nix

View file

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

View file

@ -1,10 +1,10 @@
# Host: Lindberg # Host: Lindberg
## Operations {#_operations} ## Operations {#\_operations}
Reboot requires passphrase (see pass `host/lindberg/hdd_luks`) Reboot requires passphrase (see pass `host/lindberg/hdd_luks`)
``` bash ```bash
ssh -p 2222 root@lindberg.riedbach-ext.net.qo.is ssh -p 2222 root@lindberg.riedbach-ext.net.qo.is
``` ```
@ -12,7 +12,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,8 +11,6 @@
./virtualisation.nix ./virtualisation.nix
../../defaults/hardware/asrock.nix ../../defaults/hardware/asrock.nix
../../defaults/meta
]; ];
qois.system.physical.enable = true; qois.system.physical.enable = true;

View file

@ -1,4 +1,4 @@
{ config, pkgs, ... }: { config, ... }:
let let
meta = config.qois.meta; meta = config.qois.meta;

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,13 +2,11 @@
# 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/meta
]; ];
qois.system.physical.enable = true; qois.system.physical.enable = true;

View file

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

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

@ -1,19 +1,12 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
let let
cfg = config.qois.backplane-net; 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 in
{ {
options.qois.backplane-net = { options.qois.backplane-net = {
enable = mkEnableOption "Enable backplane server services"; enable = mkEnableOption "Enable backplane server services";
@ -22,11 +15,6 @@ in
type = types.str; type = types.str;
default = "backplane"; default = "backplane";
}; };
domain = mkOption {
description = "Domain";
type = types.str;
default = hostNetConfig;
};
port = mkOption { port = mkOption {
description = "Wireguard Default Port"; description = "Wireguard Default Port";
type = types.number; type = types.number;
@ -34,50 +22,59 @@ in
}; };
}; };
config = { config = lib.mkIf cfg.enable (
sops.secrets."wgautomesh/gossip-secret".restartUnits = [ "wgautomesh.service" ]; 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.enable = true;
networking.wireguard.interfaces."wg-${cfg.netName}" = { networking.wireguard.interfaces."wg-${cfg.netName}" = {
ips = [ "${hostNetConfig.v4.ip}/${toString netConfig.v4.prefixLength}" ]; ips = [ "${hostNetConfig.v4.ip}/${toString netConfig.v4.prefixLength}" ];
listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else cfg.port; listenPort = if hostNetConfig.endpoint != null then hostNetConfig.endpoint.port else cfg.port;
privateKeyFile = "/secrets/wireguard/private/${cfg.netName}"; privateKeyFile = "/secrets/wireguard/private/${cfg.netName}";
generatePrivateKeyFile = true; 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 = { systemd.network.wait-online.ignoredInterfaces = [ interface ];
requires = wgService;
after = wgService; 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

@ -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

@ -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;

View file

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

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

View file

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

View file

@ -1,14 +1,12 @@
{ {
config, config,
lib, lib,
pkgs,
... ...
}: }:
with lib; with lib;
let let
routerCfg = config.qois.router;
cfg = config.qois.router.wireless; cfg = config.qois.router.wireless;
in in
{ {

View file

@ -1,4 +1,4 @@
# Router Role {#_router_role} # Router Role {#\_router_role}
The `router` role set is applied on hosts which serve the rule of a SOHO The `router` role set is applied on hosts which serve the rule of a SOHO
router. router.

View file

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

View file

@ -3,4 +3,3 @@
This module enables static nginx sites, with data served from "/var/lib/nginx/$domain/root". This module enables static nginx sites, with data served from "/var/lib/nginx/$domain/root".
To deploy the site, a user `nginx-$domain` is added, of which a `root` profile in the home folder can be deployed, e.g. with deploy-rs. To deploy the site, a user `nginx-$domain` is added, of which a `root` profile in the home folder can be deployed, e.g. with deploy-rs.

View file

@ -53,7 +53,7 @@ with lib;
config = mkIf cfg.enable ( config = mkIf cfg.enable (
let let
pageConfigs = concatMapAttrs ( pageConfigs = concatMapAttrs (
name: page: _name: page:
let let
home = "/var/lib/nginx-${page.domain}"; home = "/var/lib/nginx-${page.domain}";
in in
@ -76,7 +76,7 @@ with lib;
users = { users = {
groups = concatMapAttrs ( groups = concatMapAttrs (
name: _name:
{ user, ... }: { user, ... }:
{ {
"${user}" = { }; "${user}" = { };
@ -84,10 +84,10 @@ with lib;
) pageConfigs; ) pageConfigs;
users = users =
{ {
${config.services.nginx.user}.extraGroups = mapAttrsToList (domain: getAttr "user") pageConfigs; ${config.services.nginx.user}.extraGroups = mapAttrsToList (_domain: getAttr "user") pageConfigs;
} }
// (concatMapAttrs ( // (concatMapAttrs (
name: _name:
{ {
user, user,
home, home,
@ -134,10 +134,10 @@ with lib;
globalRedirect = domain; globalRedirect = domain;
}; };
}); });
aliasVhosts = concatMapAttrs (name: mkAliasVhost) pageConfigs; aliasVhosts = concatMapAttrs (_name: mkAliasVhost) pageConfigs;
in in
aliasVhosts // (mapAttrs (name: mkVhost) pageConfigs); aliasVhosts // (mapAttrs (_name: mkVhost) pageConfigs);
}; };
} }
); );

View file

@ -10,14 +10,14 @@
inherit (lib) mkForce genAttrs const; inherit (lib) mkForce genAttrs const;
in in
{ {
# Setup simple localhost page with an example.com redirect # Setup simple docs.example.com page with an example.com redirect
qois.static-page = { qois.static-page = {
enable = true; enable = true;
pages."localhost".domainAliases = [ "example.com" ]; pages."docs.example.com".domainAliases = [ "example.com" ];
}; };
# Disable TLS services # Disable TLS services
services.nginx.virtualHosts = genAttrs [ "localhost" "example.com" ] (const { services.nginx.virtualHosts = genAttrs [ "docs.example.com" "example.com" ] (const {
forceSSL = mkForce false; forceSSL = mkForce false;
enableACME = mkForce false; enableACME = mkForce false;
}); });

View file

@ -3,18 +3,20 @@ def test(subtest, webserver):
webserver.wait_for_open_port(80) webserver.wait_for_open_port(80)
# Preparations # Preparations
webserverRoot = "/var/lib/nginx-localhost/root" webserverRoot = "/var/lib/nginx-docs.example.com/root"
indexContent = "It works!" indexContent = "It works!"
webserver.succeed(f"mkdir {webserverRoot}") webserver.succeed(f"mkdir {webserverRoot}")
webserver.succeed(f"echo '{indexContent}' > {webserverRoot}/index.html") webserver.succeed(f"echo '{indexContent}' > {webserverRoot}/index.html")
webserver.succeed(f"chown -R nginx-localhost\: {webserverRoot}") webserver.succeed(f"chown -R nginx-docs.example.com\: {webserverRoot}")
# Helpers # Helpers
def curl_variable_test(node, variable, expected, url): def curl_variable_test(node, variable, expected, url):
value = node.succeed( value = node.succeed(
f"curl -s --no-location -o /dev/null -w '%{{{variable}}}' '{url}'") f"curl -s --no-location -o /dev/null -w '%{{{variable}}}' '{url}'"
assert value == expected, \ )
assert value == expected, (
f"expected {variable} to be '{expected}' but got '{value}'" f"expected {variable} to be '{expected}' but got '{value}'"
)
def expect_http_code(node, code, url): def expect_http_code(node, code, url):
curl_variable_test(node, "http_code", code, url) curl_variable_test(node, "http_code", code, url)
@ -24,23 +26,24 @@ def test(subtest, webserver):
def expect_http_content(node, expectedContent, url): def expect_http_content(node, expectedContent, url):
content = node.succeed(f"curl --no-location --silent '{url}'") content = node.succeed(f"curl --no-location --silent '{url}'")
assert content.strip() == expectedContent.strip(), f''' assert content.strip() == expectedContent.strip(), f"""
expected content: expected content:
{expectedContent} {expectedContent}
at {url} but got following content: at {url} but got following content:
{content} {content}
''' """
# Tests # Tests
with subtest("website is successfully served on localhost"): with subtest("website is successfully served on docs.example.com"):
expect_http_code(webserver, "200", "http://localhost/index.html") webserver.succeed("grep docs.example.com /etc/hosts")
expect_http_content(webserver, indexContent, expect_http_code(webserver, "200", "http://docs.example.com/index.html")
"http://localhost/index.html") expect_http_content(
webserver, indexContent, "http://docs.example.com/index.html"
)
with subtest("example.com is in hosts file and a redirect to localhost"): with subtest("example.com is a redirect to docs.example.com"):
webserver.succeed("grep example.com /etc/hosts") webserver.succeed("grep -e '[^\.]example.com' /etc/hosts")
url = "http://example.com/index.html" url = "http://example.com/index.html"
expect_http_code(webserver, "301", url) expect_http_code(webserver, "301", url)
expect_http_location( expect_http_location(webserver, "http://docs.example.com/index.html", url)
webserver, "http://localhost/index.html", url)

View file

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

View file

@ -2,7 +2,6 @@
config, config,
lib, lib,
pkgs, pkgs,
inputs,
... ...
}: }:
{ {
@ -11,7 +10,6 @@
./overlays.nix ./overlays.nix
./physical.nix ./physical.nix
./security.nix ./security.nix
./unfree.nix
./virtual-machine.nix ./virtual-machine.nix
]; ];
@ -57,9 +55,9 @@
settings = settings =
let let
substituters = [ substituters = [
"https://${inputs.self.nixosConfigurations.lindberg-build.config.qois.nixpkgs-cache.hostname}?priority=39" "https://${config.qois.nixpkgs-cache.hostname}?priority=30"
"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
{ {
@ -71,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; # For hosts that limit the subst list trusted-substituters = substituters;
inherit substituters; inherit substituters;
}; };
gc = { gc = {
@ -113,12 +111,6 @@
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

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

View file

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

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

@ -3,7 +3,7 @@
To use our Vaultwarden instance, you can use the regular To use our Vaultwarden instance, you can use the regular
[Bitwarden apps](https://bitwarden.com/download/) with our custom server when logging in: [Bitwarden apps](https://bitwarden.com/download/) with our custom server when logging in:
Username: `first.lastname@qo.is` Username: `first.lastname@qo.is`\
Server Name: `https://vault.qo.is` Server Name: `https://vault.qo.is`
## Create Accounts ## Create Accounts
@ -17,7 +17,6 @@ Please instruct users to:
- the password cannot be reset without loosing all the passwords. - the password cannot be reset without loosing all the passwords.
Use of [Emergency Contacts](https://bitwarden.com/help/emergency-access/) or Organizations may be advisable. Use of [Emergency Contacts](https://bitwarden.com/help/emergency-access/) or Organizations may be advisable.
## Administration ## Administration
An admin panel is available under [vault.qo.is/admin](https://vault.qo.is/admin). An admin panel is available under [vault.qo.is/admin](https://vault.qo.is/admin).
@ -26,12 +25,10 @@ The password is saved in the pass database under `vaultwarden-admin`.
In the administration panel, users and organizations may be managed. In the administration panel, users and organizations may be managed.
Instance settings should be changed with the nixos module in the infrastructure repository only. Instance settings should be changed with the nixos module in the infrastructure repository only.
## Backup / Restore ## Backup / Restore
1. `systemctl stop vaultwarden.service` 1. `systemctl stop vaultwarden.service`
2. Import Postgresql Database Backup 1. Import Postgresql Database Backup
3. Restore `/var/lib/bitwarden_rs` 1. Restore `/var/lib/bitwarden_rs`
4. `systemctl start vaultwarden.service` 1. `systemctl start vaultwarden.service`
5. Click `Force clients to resync` in the [Administration interface under _Users_](https://vault.qo.is/admin/users/overview) 1. Click `Force clients to resync` in the [Administration interface under _Users_](https://vault.qo.is/admin/users/overview)

View file

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

View file

@ -29,14 +29,13 @@ These nodes allow access to the internet for clients connected to the VPN:
> ⚠️ 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. > ⚠️ 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.
### Add exit nodes: ### Add exit nodes:
1. Create a preauth secret on the `vpn.qo.is` host: 1. Create a preauth secret on the `vpn.qo.is` host:
```bash ```bash
headscale preauthkeys create --user srv --reusable headscale preauthkeys create --user srv --reusable
``` ```
2. Configure the new exit-node host with the `qois.vpn-exit-node` module. 1. Configure the new exit-node host with the `qois.vpn-exit-node` module.
When using the `srv` user, exit nodes and routes are automatically accepted as trusted. When using the `srv` user, exit nodes and routes are automatically accepted as trusted.
@ -50,11 +49,9 @@ To use the service, you can use a normal Tailscale client with following additio
| `exit-node` | `100.64.0.5` (lindberg) or `100.64.0.6` (cypriaspitz) | Use host as [exit node](#exit-nodes) | | `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. | | `login-server` | `https://vpn.qo.is` | Use our own VPN service. |
> ⚠️ Currently, if the client is in an IPv6 network, the transport is broken. > ⚠️ Currently, if the client is in an IPv6 network, the transport is broken.
> Disable IPv6 connectivity to use the VPN. > Disable IPv6 connectivity to use the VPN.
> See [#4](https://git.qo.is/qo.is/infrastructure/issues/4) for details. > See [#4](https://git.qo.is/qo.is/infrastructure/issues/4) for details.
### NixOS ### NixOS
@ -90,15 +87,15 @@ See [this Headscale documentation for more](https://headscale.net/stable/usage/c
### Server ### Server
1. `systemctl stop headscale` 1. `systemctl stop headscale`
2. Replace `/var/lib/headscale` 1. Replace `/var/lib/headscale`
3. `systemctl start headscale` 1. `systemctl start headscale`
4. Monitor logs for errors 1. Monitor logs for errors
Note: `/var/lib/headscale` contains a sqlite database. Note: `/var/lib/headscale` contains a sqlite database.
### Clients ### Clients
1. `systemctl stop tailscaled` 1. `systemctl stop tailscaled`
2. Replace `/var/lib/tailscale` 1. Replace `/var/lib/tailscale`
3. `systemctl start tailscaled` 1. `systemctl start tailscaled`
4. Monitor logs for errors 1. Monitor logs for errors

View file

@ -10,7 +10,7 @@ let
cfgLoadbalancer = config.qois.loadbalancer; cfgLoadbalancer = config.qois.loadbalancer;
defaultDnsRecords = defaultDnsRecords =
(mapAttrs ( (mapAttrs (
name: value: mkIf (cfgLoadbalancer.hostmap ? ${value}) cfgLoadbalancer.hostmap.${value} _name: value: mkIf (cfgLoadbalancer.hostmap ? ${value}) cfgLoadbalancer.hostmap.${value}
) cfgLoadbalancer.domains) ) cfgLoadbalancer.domains)
// { // {
"vpn.qo.is" = config.services.headscale.address; "vpn.qo.is" = config.services.headscale.address;

View file

@ -1,8 +1,8 @@
# WWAN Module {#_wwan_module} # WWAN Module {#\_wwan_module}
This module configures WWAN adapters that support MBIM This module configures WWAN adapters that support MBIM
## Current limitations {#_current_limitations} ## Current limitations {#\_current_limitations}
- IPv4 tested only - IPv4 tested only
- Currently, it is not simple to get network failures or address - Currently, it is not simple to get network failures or address

View file

@ -6,11 +6,11 @@ MODE=$1
DEV=$2 DEV=$2
if [ "$DEBUG" == "" ]; then if [ "$DEBUG" == "" ]; then
DEBUG="false" DEBUG="false"
fi fi
if [ "$MBIM_INTERFACE" == "" ]; then if [ "$MBIM_INTERFACE" == "" ]; then
MBIM_INTERFACE="/dev/cdc-wdm0" MBIM_INTERFACE="/dev/cdc-wdm0"
fi fi
############################################################################### ###############################################################################
@ -29,274 +29,273 @@ ipv6_dns=()
ipv6_mtu="" ipv6_mtu=""
export previous_state state skip_line \ export previous_state state skip_line \
ipv4_addresses ipv4_gateway ipv4_dns ipv4_mtu \ ipv4_addresses ipv4_gateway ipv4_dns ipv4_mtu \
ipv6_addresses ipv6_gateway ipv6_dns ipv6_mtu ipv6_addresses ipv6_gateway ipv6_dns ipv6_mtu
############################################################################### ###############################################################################
# Function # Function
############################################################################### ###############################################################################
function print_debug { function print_debug {
if [ "$DEBUG" != "false" ]; then if [ "$DEBUG" != "false" ]; then
echo "[State: $state] $1" >&2 echo "[State: $state] $1" >&2
fi fi
} }
function print_full_configuration { function print_full_configuration {
if [[ "${#ipv4_addresses[@]}" > 0 ]]; then if [[ ${#ipv4_addresses[@]} > 0 ]]; then
printf "IPv4: " printf "IPv4: "
printf '%s, ' "${ipv4_addresses[@]}" printf '%s, ' "${ipv4_addresses[@]}"
printf "\n" printf "\n"
printf "GW: $ipv4_gateway\n" printf "GW: $ipv4_gateway\n"
printf "DNS: " printf "DNS: "
printf '%s, ' "${ipv4_dns[@]}" printf '%s, ' "${ipv4_dns[@]}"
printf "\n" printf "\n"
printf "MTU: $ipv4_mtu\n" printf "MTU: $ipv4_mtu\n"
fi fi
if [[ "${#ipv6_addresses[@]}" > 0 ]]; then if [[ ${#ipv6_addresses[@]} > 0 ]]; then
echo echo
printf "IPv6: " printf "IPv6: "
printf '%s, ' "${ipv6_addresses[@]}" printf '%s, ' "${ipv6_addresses[@]}"
printf "\n" printf "\n"
printf "GW: $ipv6_gateway\n" printf "GW: $ipv6_gateway\n"
printf "DNS: " printf "DNS: "
printf '%s, ' "${ipv6_dns[@]}" printf '%s, ' "${ipv6_dns[@]}"
printf "\n" printf "\n"
printf "MTU: $ipv6_mtu\n" printf "MTU: $ipv6_mtu\n"
fi fi
} }
function next_state { function next_state {
previous_state="$state" previous_state="$state"
state="$1" state="$1"
} }
function parse_ip { function parse_ip {
# IP [0]: '10.134.203.177/30' # IP [0]: '10.134.203.177/30'
local line_re="IP \[([0-9]+)\]: '(.+)'" local line_re="IP \[([0-9]+)\]: '(.+)'"
local input=$1 local input=$1
if [[ $input =~ $line_re ]]; then if [[ $input =~ $line_re ]]; then
local ip_cnt=${BASH_REMATCH[1]} local ip_cnt=${BASH_REMATCH[1]}
local ip=${BASH_REMATCH[2]} local ip=${BASH_REMATCH[2]}
fi fi
echo "$ip" echo "$ip"
} }
function parse_dns { function parse_dns {
# IP [0]: '10.134.203.177/30' # IP [0]: '10.134.203.177/30'
local line_re="DNS \[([0-9]+)\]: '(.+)'" local line_re="DNS \[([0-9]+)\]: '(.+)'"
local input=$1 local input=$1
if [[ $input =~ $line_re ]]; then if [[ $input =~ $line_re ]]; then
local dns_cnt=${BASH_REMATCH[1]} local dns_cnt=${BASH_REMATCH[1]}
local dns=${BASH_REMATCH[2]} local dns=${BASH_REMATCH[2]}
fi fi
echo "$dns" echo "$dns"
} }
function parse_gateway { function parse_gateway {
# Gateway: '10.134.203.178' # Gateway: '10.134.203.178'
local line_re="Gateway: '(.+)'" local line_re="Gateway: '(.+)'"
local input=$1 local input=$1
if [[ $input =~ $line_re ]]; then if [[ $input =~ $line_re ]]; then
local gw=${BASH_REMATCH[1]} local gw=${BASH_REMATCH[1]}
fi fi
echo "$gw" echo "$gw"
} }
function parse_mtu { function parse_mtu {
# MTU: '1500' # MTU: '1500'
local line_re="MTU: '([0-9]+)'" local line_re="MTU: '([0-9]+)'"
local input=$1 local input=$1
if [[ $input =~ $line_re ]]; then if [[ $input =~ $line_re ]]; then
local mtu=${BASH_REMATCH[1]} local mtu=${BASH_REMATCH[1]}
fi fi
echo "$mtu" echo "$mtu"
} }
function parse_input_state_machine { function parse_input_state_machine {
state="start" state="start"
while true; do while true; do
if [[ "$skip_line" == 0 ]]; then if [[ $skip_line == 0 ]]; then
read line || break # TODO: Clean up read line || break # TODO: Clean up
else else
skip_line=0 skip_line=0
fi fi
case "$state" in case "$state" in
"start") "start")
read line || break # first line is empty, read a new one #TODO: This is not very clean... read line || break # first line is empty, read a new one #TODO: This is not very clean...
case "$line" in case "$line" in
*"configuration available: 'none'"*) *"configuration available: 'none'"*)
# Skip none state # Skip none state
# TODO: This is a workaround of the original parser's shortcomming # TODO: This is a workaround of the original parser's shortcomming
continue continue
;; ;;
*"IPv4 configuration available"*) *"IPv4 configuration available"*)
next_state "ipv4_ip" next_state "ipv4_ip"
continue continue
;; ;;
*"IPv6 configuration available"*) *"IPv6 configuration available"*)
next_state "ipv6_ip" next_state "ipv6_ip"
continue continue
;; ;;
*) *)
next_state "exit" next_state "exit"
continue continue
;; ;;
esac esac
;; ;;
"error") "error")
echo "Error in pattern matchin of state $previous_state. Exiting." >&2 echo "Error in pattern matchin of state $previous_state. Exiting." >&2
exit 2 exit 2
;; ;;
"exit") "exit")
break break
;; ;;
"ipv4_ip") "ipv4_ip")
ipv4=$(parse_ip "$line") ipv4=$(parse_ip "$line")
if [ -z "$ipv4" ]; then if [ -z "$ipv4" ]; then
if [[ "${#ipv4_addresses[@]}" < 1 ]]; then if [[ ${#ipv4_addresses[@]} < 1 ]]; then
next_state "error" next_state "error"
continue continue
else else
next_state "ipv4_gateway" next_state "ipv4_gateway"
skip_line=1 skip_line=1
continue continue
fi fi
fi fi
print_debug "$ipv4" print_debug "$ipv4"
ipv4_addresses+=("$ipv4") ipv4_addresses+=("$ipv4")
;; ;;
"ipv4_gateway") "ipv4_gateway")
gw=$(parse_gateway "$line") gw=$(parse_gateway "$line")
if [ -z "$gw" ]; then if [ -z "$gw" ]; then
next_state "error" next_state "error"
continue continue
fi fi
print_debug "$gw" print_debug "$gw"
ipv4_gateway="$gw" ipv4_gateway="$gw"
next_state "ipv4_dns" next_state "ipv4_dns"
;; ;;
"ipv4_dns") "ipv4_dns")
ipv4=$(parse_dns "$line") ipv4=$(parse_dns "$line")
if [ -z "$ipv4" ]; then if [ -z "$ipv4" ]; then
if [[ "${#ipv4_dns[@]}" < 1 ]]; then if [[ ${#ipv4_dns[@]} < 1 ]]; then
next_state "error" next_state "error"
continue continue
else else
next_state "ipv4_mtu" next_state "ipv4_mtu"
skip_line=1 skip_line=1
continue continue
fi fi
fi fi
print_debug "$ipv4" print_debug "$ipv4"
ipv4_dns+=("$ipv4") ipv4_dns+=("$ipv4")
;; ;;
"ipv4_mtu") "ipv4_mtu")
mtu=$(parse_mtu "$line") mtu=$(parse_mtu "$line")
if [ -z "$mtu" ]; then if [ -z "$mtu" ]; then
next_state "error" next_state "error"
continue continue
fi fi
print_debug "$mtu" print_debug "$mtu"
ipv4_mtu="$mtu" ipv4_mtu="$mtu"
next_state "start" next_state "start"
;; ;;
"ipv6_ip") "ipv6_ip")
ipv6=$(parse_ip "$line") ipv6=$(parse_ip "$line")
if [ -z "$ipv6" ]; then if [ -z "$ipv6" ]; then
if [[ "${#ipv6_addresses[@]}" < 1 ]]; then if [[ ${#ipv6_addresses[@]} < 1 ]]; then
next_state "error" next_state "error"
continue continue
else else
next_state "ipv6_gateway" next_state "ipv6_gateway"
skip_line=1 skip_line=1
continue continue
fi fi
fi fi
print_debug "$ipv6" print_debug "$ipv6"
ipv6_addresses+=("$ipv6") ipv6_addresses+=("$ipv6")
;; ;;
"ipv6_gateway") "ipv6_gateway")
gw=$(parse_gateway "$line") gw=$(parse_gateway "$line")
if [ -z "$gw" ]; then if [ -z "$gw" ]; then
next_state "error" next_state "error"
continue continue
fi fi
print_debug "$gw" print_debug "$gw"
ipv6_gateway="$gw" ipv6_gateway="$gw"
next_state "ipv6_dns" next_state "ipv6_dns"
;; ;;
"ipv6_dns") "ipv6_dns")
ipv6=$(parse_dns "$line") ipv6=$(parse_dns "$line")
if [ -z "$ipv6" ]; then if [ -z "$ipv6" ]; then
if [[ "${#ipv6_dns[@]}" < 1 ]]; then if [[ ${#ipv6_dns[@]} < 1 ]]; then
next_state "error" next_state "error"
continue continue
else else
next_state "ipv6_mtu" next_state "ipv6_mtu"
skip_line=1 skip_line=1
continue continue
fi fi
fi fi
print_debug "$ipv6" print_debug "$ipv6"
ipv6_dns+=("$ipv6") ipv6_dns+=("$ipv6")
;; ;;
"ipv6_mtu") "ipv6_mtu")
mtu=$(parse_mtu "$line") mtu=$(parse_mtu "$line")
if [ -z "$mtu" ]; then if [ -z "$mtu" ]; then
next_state "error" next_state "error"
continue continue
fi fi
print_debug "$mtu" print_debug "$mtu"
ipv6_mtu="$mtu" ipv6_mtu="$mtu"
next_state "start" next_state "start"
;; ;;
*) *)
print_debug "Invalid state (came from $previous_state). Exiting." print_debug "Invalid state (came from $previous_state). Exiting."
exit 0 exit 0
;; ;;
esac esac
done done
} }
interface_stop() {
ip addr flush dev $DEV
ip route flush dev $DEV
interface_stop(){ ip -6 addr flush dev $DEV
ip addr flush dev $DEV ip -6 route flush dev $DEV
ip route flush dev $DEV
ip -6 addr flush dev $DEV #TODO: Nameserver?
ip -6 route flush dev $DEV
#TODO: Nameserver?
} }
interface_start() { interface_start() {
ip link set $DEV up ip link set $DEV up
if [[ "${#ipv4_addresses[@]}" > 0 ]]; then if [[ ${#ipv4_addresses[@]} > 0 ]]; then
ip addr add ${ipv4_addresses[@]} dev $DEV broadcast + #TODO: Works for multiple addresses? ip addr add ${ipv4_addresses[@]} dev $DEV broadcast + #TODO: Works for multiple addresses?
ip link set $DEV mtu $ipv4_mtu ip link set $DEV mtu $ipv4_mtu
ip route add default via $ipv4_gateway dev $DEV ip route add default via $ipv4_gateway dev $DEV
#TODO: nameserver ${ipv4_dns[@]} #TODO: nameserver ${ipv4_dns[@]}
else else
echo "No IPv4 address, skipping v4 configuration..." echo "No IPv4 address, skipping v4 configuration..."
fi fi
if [[ "${#ipv6_addresses[@]}" > 0 ]]; then if [[ ${#ipv6_addresses[@]} > 0 ]]; then
ip -6 addr add ${ipv6_addresses[@]} dev $DEV #TODO: Works for multiple addresses? ip -6 addr add ${ipv6_addresses[@]} dev $DEV #TODO: Works for multiple addresses?
ip -6 route add default via $ipv6_gateway dev $DEV ip -6 route add default via $ipv6_gateway dev $DEV
ip -6 link set $DEV mtu $ipv6_mtu ip -6 link set $DEV mtu $ipv6_mtu
#TODO: nameserver ${ipv6_dns[@]}" #TODO: nameserver ${ipv6_dns[@]}"
else else
echo "No IPv6 address, skipping v6 configuration..." echo "No IPv6 address, skipping v6 configuration..."
fi fi
} }
############################################################################### ###############################################################################
@ -307,23 +306,23 @@ set -e
echo "NOTE: This script does not yet support nameserver configuration." echo "NOTE: This script does not yet support nameserver configuration."
case "$MODE" in case "$MODE" in
"start") "start")
mbim-network $MBIM_INTERFACE start mbim-network $MBIM_INTERFACE start
sleep 1 sleep 1
mbimcli -d $MBIM_INTERFACE -p --query-ip-configuration=0 | { mbimcli -d $MBIM_INTERFACE -p --query-ip-configuration=0 | {
parse_input_state_machine parse_input_state_machine
print_full_configuration print_full_configuration
interface_stop interface_stop
interface_start interface_start
} }
;; ;;
"stop") "stop")
mbim-network $MBIM_INTERFACE stop mbim-network $MBIM_INTERFACE stop
interface_stop interface_stop
;; ;;
*) *)
echo "USAGE: $0 start|stop INTERFACE" >&2 echo "USAGE: $0 start|stop INTERFACE" >&2
echo "You can set an env variable DEBUG to gather debugging output." >&2 echo "You can set an env variable DEBUG to gather debugging output." >&2
exit 1 exit 1
;; ;;
esac esac

View file

@ -1,5 +0,0 @@
self: super: {
lib = (super.lib or { }) // {
qois = import ../lib { lib = self.lib; };
};
}

View file

@ -1,42 +0,0 @@
{
attic-client,
findutils,
gnugrep,
writeShellApplication,
...
}:
writeShellApplication {
name = "cache";
meta.description = "Access the infrastructure's attic cache. Mostly used in CI.";
runtimeInputs = [
attic-client
findutils
gnugrep
];
text = ''
SERVER="https://attic.qo.is/"
CACHE_NAME="qois"
CACHE_REPO="$CACHE_NAME:qois-infrastructure"
if [ -z "$ATTIC_AUTH_TOKEN" ]; then
echo "Please set the \$ATTIC_AUTH_TOKEN environment variable to access the cache."
exit 3
fi
attic login "$CACHE_NAME" "$SERVER" "$ATTIC_AUTH_TOKEN"
case "$1" in
use)
attic use "$CACHE_REPO"
;;
watch)
attic watch-store "$CACHE_REPO"
;;
push)
RESULT_PATH="./result"
# Add build dependencies as well
nix-store -qR --include-outputs "$(nix-store -qd $RESULT_PATH)" | grep -v '\.drv$' \
| xargs attic push "$CACHE_REPO" "$RESULT_PATH"
;;
esac
'';
}

View file

@ -1,37 +1,28 @@
{ {
self, self,
flakeSelf,
system, system,
private,
pkgs, pkgs,
... ...
}: }:
with pkgs.lib; let
inherit (self.lib) foldersWithNix;
inherit (pkgs.lib)
path
genAttrs
;
in
{ {
${system} = ${system} = genAttrs (foldersWithNix ./.) (
let name:
packages = pipe (self.lib.foldersWithNix ./.) [ pkgs.callPackage (path.append ./. "./${name}/default.nix") {
(map (name: { inherit
inherit name; self
path = path.append ./. "./${name}/default.nix"; flakeSelf
})) system
(map ( private
{ name, path }: ;
{ }
inherit name; );
value = pkgs.callPackage path {
inherit self;
inherit system;
};
}
))
listToAttrs
];
in
packages
// {
default =
let
nixosConfigs = mapAttrsToList (n: v: v.config.system.build.toplevel) self.nixosConfigurations;
in
pkgs.linkFarmFromDrvs "all" (nixosConfigs ++ (attrValues packages));
};
} }

View file

@ -1,6 +1,6 @@
{ {
deploy-rs, deploy-rs,
self, flakeSelf,
writeShellApplication, writeShellApplication,
... ...
}: }:
@ -9,6 +9,6 @@ writeShellApplication {
meta.description = "Deploy configuration to specificed targets."; meta.description = "Deploy configuration to specificed targets.";
runtimeInputs = [ deploy-rs ]; runtimeInputs = [ deploy-rs ];
text = '' text = ''
deploy --interactive --targets "''${@:-${self}}" deploy --interactive --targets "''${@:-${flakeSelf}}"
''; '';
} }

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