Initial commit

main
n0emis 2 years ago
commit 0dd7fb7ac0
Signed by: n0emis
GPG Key ID: 00FAF748B777CF10

@ -0,0 +1,21 @@
# Colmena NixOS Config Template
* user gpg-keys (for them to be able to decrypt the secrets): `secrets/.gpg-id`
* collect/generate host gpg-keys: `./lib/create-keys.sh`
* edit stuff in password store: `./lib/pass.sh`
## How to deploy
```
./deploy.sh apply switch --on vpn7
```
or to deploy all gateways (all hosts with the gateway-tag):
```
./deploy.sh apply switch --on gateway
```
There is a special case for the nixdeploy-host:
```
./deploy.sh apply-local --node nixdeploy
```

@ -0,0 +1,44 @@
{ pkgs, lib, ... }:
{
nix = {
package = pkgs.nixFlakes;
extraOptions = ''
experimental-features = nix-command flakes
'';
trustedUsers = [ "root" "@wheel" ];
};
services.openssh.enable = true;
services.openssh.permitRootLogin = "without-password";
security.sudo.wheelNeedsPassword = false;
time.timeZone = "Europe/Berlin";
networking.firewall.logRefusedConnections = false;
programs.mtr.enable = true;
environment.systemPackages = with pkgs; [
bind.dnsutils
colmena
git
gnupg
htop
rsync
tmux
wget
];
programs.vim.defaultEditor = true;
users.users.root = {
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcOPtW5FWNIdlMQFoqeyA1vHw+cA8ft8oXSbXPzQNL9 n0emis@n0emis.eu"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC8xqVakxJ+AwcIrS/wyL03N++pE09epwMFlIMXWvlpwwEp1J/0H7nygwxk/9LIZdabs/ETWn0s8oHAkc7YR1c6ajSTCDiZEYATAWt7t8t4Gw/80c8u8T50lIqmiDEEVbOVv3Vta/pAN4hAUp9U5DpYCkQbvF+NKKcK3Yp8d9usNC6ohqgTK+IGAEdMhvpbbNppDMXoWHuynBzUX7TS6ST6yEr0tD+CBbCpbfcMuwTI3lNtfywEVpuFaeHqDZx2QDrEX4bg0dRKgQstbXYdqmBfnOiBpUr8Wyl8U1J24rN+E07pBw/8KDGWbVg19/Ex8o4ht/p5voUfKVjD/DwWXTLntBirjfAgQAm4GH/qP4x3zNiTtlYlQFbXSk6VEVrTrxCB5rTWvGnhg31tk5P3YwvagDmGABazY5s/8tlttSc1yWBctWQJCjxSqcCLekxG4D1rVuGKCKOZgflQ9QFdQlKycInPBek3zi0i3GYkE1YnNFye5ggOnxT8qGuKjfdtZI9qvMJQO8lbEDzbYQvNns1V/k4ZobiihYwrG5TJUzZFEpMYetDK6tI8BRU11d+ja0jWzguj5/7wc0nrr/BiZ8FkAr2fZ60j2aI5kG0s3qjbrQbB/RXaGP9hRU0+480+IokNJJIcjv5iwH5ophdrjC8GH4So2kPPt0NXob1yNysdjw== simeon@noemis.me (OLD)"
];
};
environment.noXlibs = lib.mkForce false;
}

@ -0,0 +1,6 @@
#!/usr/bin/env bash
DEPLOY_HOST="nixdeploy.neo.cccgoe.de"
rsync -r . root@${DEPLOY_HOST}:/root/nixfiles/
ssh -tA root@${DEPLOY_HOST} "cd /root/nixfiles && colmena $@"

@ -0,0 +1,65 @@
{
"nodes": {
"ffnix": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1649686725,
"narHash": "sha256-t2ByQJ52I67nxdocQRtYOvBD7ZHNt6wRcWqq79EZmGw=",
"owner": "n0emis",
"repo": "ffnix",
"rev": "bdf5dfb77cd474d7fbddc1297526dc1ce339fdb2",
"type": "github"
},
"original": {
"owner": "n0emis",
"ref": "main",
"repo": "ffnix",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1647992509,
"narHash": "sha256-AG40Nt5OWz0LBs5p457emOuwLKOvTtcv/2fUdnEN3Ws=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d2caa9377539e3b5ff1272ac3aa2d15f3081069f",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "release-21.11",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"ffnix": "ffnix",
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

@ -0,0 +1,48 @@
{
description = "FFGoe NixOS Config";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/release-21.11";
ffnix = {
url = "github:n0emis/ffnix/main";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, ffnix }: {
colmena = {
meta = {
nixpkgs = import nixpkgs {
system = "x86_64-linux";
overlays = [
ffnix.overlay
];
};
};
defaults = { config, lib, name, ... }: {
deployment.targetHost = lib.mkDefault (config.networking.hostName + "." + config.networking.domain);
imports = [
(./. + "/hosts/${name}")
./common
./modules
ffnix.nixosModule
];
};
vpn7 = {
deployment.tags = [ "gateway" "legacy" ];
};
nixdeploy = {
deployment.allowLocalDeployment = true;
};
testhost = {
deployment.targetHost = "10.152.32.1";
};
dfz-el = {};
};
};
}

@ -0,0 +1,37 @@
{ config, pkgs, modulesPath, lib, ... }:
{
imports = [
(modulesPath + "/virtualisation/lxc-container.nix")
];
networking.hostName = "nixdeploy";
networking.domain = "neo.cccgoe.de";
networking.useNetworkd = true;
networking.useDHCP = false;
networking.firewall.enable = false;
networking.useHostResolvConf = false;
systemd.suppressedSystemUnits = [
"dev-mqueue.mount"
"sys-kernel-debug.mount"
"sys-fs-fuse-connections.mount"
];
systemd.network = {
links."10-eth0" = {
matchConfig.MACAddress = "02:a6:13:d1:e4:0b";
linkConfig.Name = "eth0";
};
networks."10-eth0" = {
name = "eth0";
address = [ "192.168.42.101/24" "2a01:4f8:10b:7e1::1:101/64" ];
gateway = [ "192.168.42.1" "2a01:4f8:10b:7e1::1:1" ];
};
};
services.resolved.dnssec = "false";
system.stateVersion = "21.11";
}

@ -0,0 +1,62 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, pkgs, ... }:
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Use the GRUB 2 boot loader.
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
# boot.loader.grub.efiSupport = true;
# boot.loader.grub.efiInstallAsRemovable = true;
# boot.loader.efi.efiSysMountPoint = "/boot/efi";
# Define on which hard drive you want to install Grub.
boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
networking.hostName = "vpn7";
networking.domain = "cccgoe.de";
# The global useDHCP flag is deprecated, therefore explicitly set to false here.
# Per-interface useDHCP will be mandatory in the future, so this generated config
# replicates the default behaviour.
networking.useDHCP = false;
networking.useNetworkd = true;
systemd.network = {
links."10-eth0" = {
matchConfig.MACAddress = "f6:ac:c8:5c:f5:ce";
linkConfig.Name = "eth0";
};
networks."10-eth0" = {
matchConfig = {
Name = "eth0";
};
addresses = [
{
addressConfig = {
Address = "88.99.250.3/32";
Peer = "88.99.250.30/32";
};
}
];
gateway = [ "88.99.250.30"];
dns = [ "5.1.66.255" "185.150.99.255" "2001:678:e68:f000::" "2001:678:ed0:f000::" ];
};
};
# This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions
# on your system were taken. Its perfectly fine and recommended to leave
# this value at the release version of the first install of this system.
# Before changing this value read the documentation for this option
# (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
system.stateVersion = "21.11"; # Did you read the comment?
}

@ -0,0 +1,24 @@
# 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 + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{ device = "/dev/disk/by-uuid/49598cf8-8b50-46cf-b4dc-67dfa5fdfde8";
fsType = "ext4";
};
swapDevices = [ ];
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

@ -0,0 +1,43 @@
#!/usr/bin/env bash
cd $(dirname $0)/..
read -r -a HOSTS <<< "$(colmena eval lib/get-hosts.nix | jq -r 'to_entries | map("\(.key) \(.value)") | @tsv')"
p=0
while [ "${HOSTS[$p]}" ]
do
hostname=${HOSTS[$p]}
ssh_host=root@${HOSTS[$p+1]}
echo
echo "##### $hostname - $ssh_host"
ssh -o ConnectTimeout=10 $ssh_host "echo > /dev/null"
rc=$?
if [ $rc = 0 ]; then
echo "$hostname is online, checking gpg-key"
ssh $ssh_host "sudo -u root gpg --fingerprint --with-colons | grep '^fpr' | grep $(cat secrets/$hostname/.gpg-id | tail -n1) > /dev/null"
rc=$?
else
echo "$hostname is offline"
rc=0
fi
if ! [ $rc = 0 ]; then
echo "generating gpg-key"
mkdir -p secrets/$hostname
ssh $ssh_host "sudo rm -rf /root/.gnupg"
cat lib/keygen | sed "s/NAME/${hostname}/" | ssh -o RequestTTY=yes $ssh_host "sudo -u root gpg --generate-key --pinentry-mode loopback --batch /dev/stdin"
cp secrets/.gpg-id secrets/$hostname/.gpg-id
ssh $ssh_host "sudo -u root gpg --fingerprint --with-colons | grep '^fpr' | head -n1 | cut -d: -f10" >> secrets/$hostname/.gpg-id
ssh $ssh_host "sudo -u root gpg --fingerprint --with-colons | grep '^fpr' | head -n1 | cut -d: -f10" >> secrets/all/.gpg-id
ssh $ssh_host "sudo -u root gpg --export --armor" > secrets/.public-keys/$hostname
lib/pass.sh init -p $hostname $(cat secrets/$hostname/.gpg-id);
lib/pass.sh init -p all $(cat secrets/all/.gpg-id);
else
echo "key does already exist..."
fi
let p=p+2
done

@ -0,0 +1,3 @@
{ nodes, pkgs, lib, ... }:
# Feels like a NixOS module - But you can return any JSON-serializable value
lib.attrsets.mapAttrs (k: v: v.config.deployment.targetHost) nodes

@ -0,0 +1,11 @@
%echo Generating ed25519 primary and cv25519 subkey
Key-Type: eddsa
Key-Curve: Ed25519
Key-Usage: sign
Name-Real: NAME
Subkey-Type: ecdh
Subkey-Curve: Curve25519
Expire-Date: 0
%no-protection
%commit
%echo done

@ -0,0 +1,13 @@
#!/usr/bin/env bash
cd $(dirname $0)/..
for key in secrets/.public-keys/*
do
gpg --import "$key" 2>/dev/null
done
export PASSWORD_STORE_GPG_OPTS="--trust-model always"
export PASSWORD_STORE_DIR="$PWD/secrets"
pass $@

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./secrets
];
}

@ -0,0 +1,98 @@
{ config, lib, pkgs, ... }:
with lib;
let
secret-file = types.submodule ({ ... }@moduleAttrs: {
options = {
name = mkOption {
type = types.str;
default = moduleAttrs.config._module.args.name;
};
path = mkOption {
type = types.str;
readOnly = true;
default = "/run/secrets/${removeSuffix ".gpg" (baseNameOf moduleAttrs.config.source-path)}";
};
mode = mkOption {
type = types.str;
default = "0400";
};
owner = mkOption {
type = types.str;
default = "root";
};
group-name = mkOption {
type = types.str;
default = "root";
};
source-path = mkOption {
type = types.str;
default = pkgs.copyPathToStore "${toString ../../secrets}/${config.networking.hostName}/${moduleAttrs.config.name}.gpg";
};
encrypted = mkOption {
type = types.bool;
default = true;
};
enable = mkOption {
type = types.bool;
default = true;
};
};
});
enabledFiles = filterAttrs (n: file: file.enable) config.petabyte.secrets;
mkDecryptSecret = file: pkgs.writeScript "decrypt-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
#!${pkgs.runtimeShell}
set -eu pipefail
if [ ! -f "${file.path}" ]; then
umask 0077
echo "${file.source-path} -> ${file.path}"
${if file.encrypted then ''
${pkgs.gnupg}/bin/gpg --decrypt ${escapeShellArg file.source-path} > ${file.path}
'' else ''
cat ${escapeShellArg file.source-path} > ${file.path}
''}
fi
'';
mkSetupSecret = file: pkgs.writeScript "setup-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
#!${pkgs.runtimeShell}
set -eu pipefail
chown ${escapeShellArg file.owner}:${escapeShellArg file.group-name} ${escapeShellArg file.path}
chmod ${escapeShellArg file.mode} ${escapeShellArg file.path}
'';
in {
options.petabyte.secrets = mkOption {
type = with types; attrsOf secret-file;
default = {};
};
config = mkIf (enabledFiles != {}) {
system.activationScripts = let
files = unique (map (flip removeAttrs ["_module"]) (attrValues enabledFiles));
decrypt = ''
function fail() {
rm $1
echo "failed to decrypt $1"
}
echo setting up secrets...
mkdir -p /run/secrets
chown 0:0 /run/secrets
chmod 0755 /run/secrets
${concatMapStringsSep "\n" (file: ''
${mkDecryptSecret file} || fail ${file.path}
'') files}
'';
setup = ''
echo setting up secrets...
${concatMapStringsSep "\n" (file: ''
${mkSetupSecret file} || echo "failed to set up ${file.path}"
'') files}
'';
in {
decrypt-secrets.text = "source ${pkgs.writeText "setup-secrets.sh" decrypt}";
setup-secrets = stringAfter [ "users" "groups" ] "source ${pkgs.writeText "setup-secrets.sh" setup}";
users.deps = [ "decrypt-secrets" ];
};
};
}

@ -0,0 +1 @@
6E10217E3187069E057DF5ABE0262A773B824745

@ -0,0 +1,13 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYiyiyxYJKwYBBAHaRw8BAQdAPsPSocI7hwg1Ll+MQtAkXB97Fs4wS6jAgHJy
4tIV6Yq0CW5peGRlcGxveYiQBBMWCAA4FiEERpX3ufdo1Ms5XHiPp9zPzW66SHsF
AmIsossCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQp9zPzW66SHvCUQEA
wDc+ifC0KX1diclphsmr379u1zIyCgQnzo1CZfzbfksBAMGHrPrGC01Yhijvp8Op
97rCKi5Tc9o3pzIGaQhxheMGuDgEYiyiyxIKKwYBBAGXVQEFAQEHQNBwRBfv1C/n
Kj7Zwa4tW/oDO/CofWpZc/rBLW2DTQVnAwEIB4h4BBgWCAAgFiEERpX3ufdo1Ms5
XHiPp9zPzW66SHsFAmIsossCGwwACgkQp9zPzW66SHtIvgEAm3V0VlCWh3vAu2sS
3kolo3C3O8VNljTZpjyHX9uZb0sA/0kjj9ySpLWg9ct1w9Xq1rx8NAqg3717QfEV
Eu93PqIH
=sw4f
-----END PGP PUBLIC KEY BLOCK-----

@ -0,0 +1,13 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYiyjMBYJKwYBBAHaRw8BAQdA6Eqvi71nq1N0YXSv2H7bQPuNhRN71OrMDCav
hcuHz9i0BHZwbjeIkAQTFggAOBYhBIkqg13mIq22arDfh8nOp4wJbO8QBQJiLKMw
AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEMnOp4wJbO8Q+YQBAPka4X71
eeJ+fOLgE2JlyqXRcGzKtEz5YzAFP74oC2vBAP9w0MrbRVtzwQPa4Omyy1SMtwoP
a2QmPB52aJ6nhfBlArg4BGIsozASCisGAQQBl1UBBQEBB0C+DsCLXf4vApdVZ71N
wjQUGQp9nd6zyMXXsl7oPfGvDQMBCAeIeAQYFggAIBYhBIkqg13mIq22arDfh8nO
p4wJbO8QBQJiLKMwAhsMAAoJEMnOp4wJbO8QrhMBAKcljw2BYS05IPev6kKdrlZ4
0H3l4So/GlaI/bkhyEdHAQDytHkdN4TK4QF/p6i/6+F0pClZJINm9aOlCksq3thv
AQ==
=qCbs
-----END PGP PUBLIC KEY BLOCK-----

@ -0,0 +1,4 @@
6E10217E3187069E057DF5ABE0262A773B824745
F1D6AA729DE5DDF5F94CEEE2D764341778B42777
4695F7B9F768D4CB395C788FA7DCCFCD6EBA487B
892A835DE622ADB66AB0DF87C9CEA78C096CEF10

@ -0,0 +1,2 @@
6E10217E3187069E057DF5ABE0262A773B824745
4695F7B9F768D4CB395C788FA7DCCFCD6EBA487B

@ -0,0 +1,2 @@
6E10217E3187069E057DF5ABE0262A773B824745
892A835DE622ADB66AB0DF87C9CEA78C096CEF10

@ -0,0 +1 @@
„Nê!]ë<%@$÷&€$9åÿqM-;&AIc£¾<>¿$µ¯è ‰ºð) &z5­«Ü¡e<C2A1>ÌëÏ¡Fxâ·D• V=×ìV“µ<E2809C>§3Û„NűZª1ró@80_1#ÁkæžÝ<C5BE>óUÕm<W<>Å@¤ëÝ×¢G# wZ>næf[±°ÎÃr4ÈÚѪ²ò„q¦™ü(¸Ò‘uƒ+ ¬>.hœ4—Eö5 ‡÷ŸkX#Ó›°Ã‰ºñú1Ñu2„<32>ÞÊe¼”zéÈ=9ÓZ°öi<>µ»ìb"ÂCEÀÕè—Öv†Î',kâ bìyi¼©jzõ¦u¸ª=i(Á©‡¬8D/Igps̳(©MVZ¼&¡Çâ7# žBj­‰ýª
Loading…
Cancel
Save