Luke Granger-Brown
829d179d37
In general, it's better for us to fail to pass credentials to the Nix daemon than it is for the Nix daemon to fail to start up entirely. We will restart the daemon once the secrets have been delivered anyway.
298 lines
10 KiB
Nix
298 lines
10 KiB
Nix
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
{ pkgs, config, depot, lib, rebuilder, ... }@args:
|
|
let
|
|
inherit (depot.ops) secrets;
|
|
|
|
switch-prebuilt = import ./switch-prebuilt.nix args;
|
|
|
|
# Default default priority is 1000; we use 900 here so we're higher priority,
|
|
# but lower priority than user-specified things. This is particularly
|
|
# important for our timezone setting, which otherwise conflicts with the one
|
|
# set by the Clickhouse module, which is used by e.g. bvm-logger.
|
|
mkDefault = lib.mkOverride 900;
|
|
in
|
|
{
|
|
imports = [
|
|
../../../third_party/home-manager/nixos
|
|
./vault-agent.nix
|
|
./vault-agent-secrets.nix
|
|
./secretsmgr.nix
|
|
./secretsmgr-acme.nix
|
|
./ssh-ca-vault.nix
|
|
];
|
|
|
|
options.my.specialisationName = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
};
|
|
|
|
options.my.rundeck.hostname = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = config.networking.fqdn;
|
|
};
|
|
options.my.rundeck.expectedOnline = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
options.my.rundeck.tags = lib.mkOption {
|
|
type = lib.types.listOf lib.types.str;
|
|
default = [ "nixos" ];
|
|
};
|
|
|
|
options.my.home-manager.imports = lib.mkOption {
|
|
type = lib.types.listOf lib.types.path;
|
|
default = [ ./home-manager/common.nix ];
|
|
};
|
|
options.my.home-manager.system = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.anything;
|
|
default = null;
|
|
};
|
|
options.my.prometheus.additionalExporterPorts = lib.mkOption {
|
|
type = lib.types.attrsOf lib.types.port;
|
|
default = {};
|
|
};
|
|
|
|
options.my.ip.tailscale = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
};
|
|
|
|
options.my.deploy.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
};
|
|
options.my.deploy.args = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "";
|
|
};
|
|
|
|
options.my.scrapeJournal.enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = config.my.scrapeJournal.addr != null;
|
|
};
|
|
options.my.scrapeJournal.addr = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = if config.my.ip.tailscale == null then null else "${config.my.ip.tailscale}:19531";
|
|
};
|
|
|
|
config = {
|
|
hardware.enableRedistributableFirmware = true;
|
|
|
|
networking.search = [
|
|
"int.as205479.net"
|
|
"as205479.net"
|
|
];
|
|
services.resolved = {
|
|
enable = true;
|
|
llmnr = "false"; # LLMNR breaks search domains.
|
|
dnssec = "false"; # DNSSEC support in systemd-resolved is just broken.
|
|
domains = config.networking.search;
|
|
extraConfig = ''
|
|
# For global search domains to work, we also need global DNS servers.
|
|
DNS=8.8.8.8#dns.google [2001:4860:4860::8888]#dns.google 1.1.1.1#cloudflare-dns.com [2606:4700:4700::1111]#cloudflare-dns.com
|
|
'';
|
|
fallbackDns = [
|
|
"8.8.8.8"
|
|
"2001:4860:4860::8888"
|
|
"1.1.1.1"
|
|
"2606:4700:4700::1111"
|
|
];
|
|
};
|
|
|
|
my.rundeck.tags = [ "nixos" ];
|
|
|
|
nix = {
|
|
package = pkgs.nix_2_3; # Use a working nix.
|
|
nixPath = [ "depot=/home/lukegb/depot/" "nixpkgs=/home/lukegb/depot/third_party/nixpkgs/" ];
|
|
settings = {
|
|
trusted-users = [ "root" "@wheel" "deployer" ];
|
|
substituters = lib.mkForce [ "https://cache.nixos.org/" "s3://lukegb-nix-cache?endpoint=storage.googleapis.com&trusted=1" ];
|
|
trusted-substituters = lib.mkForce [ "https://cache.nixos.org/" "s3://lukegb-nix-cache?endpoint=storage.googleapis.com&trusted=1" ];
|
|
};
|
|
};
|
|
nixpkgs.config = depot.third_party.nixpkgsConfig;
|
|
|
|
documentation.nixos.enable = false; # I just use the website.
|
|
|
|
i18n.defaultLocale = "en_GB.UTF-8";
|
|
console.keyMap = "us";
|
|
|
|
time.timeZone = mkDefault "Etc/UTC";
|
|
|
|
zramSwap = {
|
|
enable = true;
|
|
memoryMax = 4 * 1024 * 1024 * 1024;
|
|
};
|
|
|
|
environment.systemPackages = with pkgs; [
|
|
vim rxvt_unicode.terminfo tmux rebuilder tailscale rsync libarchive tcpdump restic
|
|
alacritty.terminfo kitty.terminfo
|
|
iftop htop jq
|
|
depot.nix.pkgs.mercurial
|
|
switch-prebuilt
|
|
];
|
|
|
|
networking.useDHCP = false;
|
|
networking.firewall = {
|
|
allowPing = true;
|
|
logRefusedConnections = false;
|
|
};
|
|
|
|
environment.homeBinInPath = true;
|
|
security.pam.enableSSHAgentAuth = true;
|
|
|
|
users.mutableUsers = false;
|
|
users.users = let secrets = depot.ops.secrets; in {
|
|
root.hashedPassword = secrets.passwordHashes.root;
|
|
lukegb = {
|
|
isNormalUser = true;
|
|
uid = 1000;
|
|
extraGroups = [ "wheel" "audio" ];
|
|
hashedPassword = secrets.passwordHashes.lukegb;
|
|
openssh.authorizedKeys.keyFiles = [
|
|
../../secrets/lukegb_totoro.pub
|
|
../../secrets/lukegb_termius.pub
|
|
../../secrets/lukegb_porcorosso_win.pub
|
|
../../secrets/lukegb_porcorosso_wsl.pub
|
|
../../secrets/lukegb_porcorosso_linux.pub
|
|
../../secrets/lukegb_red_solo.pub
|
|
];
|
|
};
|
|
deployer = {
|
|
isSystemUser = true;
|
|
uid = 1001;
|
|
group = "deployer";
|
|
hashedPassword = "!";
|
|
useDefaultShell = true;
|
|
home = "/var/lib/deployer";
|
|
createHome = true;
|
|
openssh.authorizedKeys.keyFiles = [
|
|
../../secrets/deployer_ed25519.pub
|
|
../../secrets/rundeck_deployer_rsa.pub
|
|
];
|
|
};
|
|
};
|
|
users.groups.deployer = {};
|
|
security.sudo.extraRules = [{
|
|
users = [ "deployer" ];
|
|
commands = [{
|
|
command = "${rebuilder}/bin/rebuilder";
|
|
options = [ "NOPASSWD" ];
|
|
} {
|
|
command = "${switch-prebuilt}/bin/switch-prebuilt";
|
|
options = [ "NOPASSWD" ];
|
|
}];
|
|
}];
|
|
security.sudo.extraConfig = ''
|
|
Defaults:deployer !requiretty
|
|
'';
|
|
|
|
programs.mtr.enable = true;
|
|
services.openssh.enable = true;
|
|
services.tailscale.enable = true;
|
|
networking.firewall.interfaces.tailscale0 = {
|
|
# Just allow anything in on tailscale0.
|
|
allowedTCPPortRanges = [{ from = 0; to = 65535; }];
|
|
allowedUDPPortRanges = [{ from = 0; to = 65535; }];
|
|
};
|
|
|
|
boot = {
|
|
kernelModules = [ "tcp_bbr" ];
|
|
kernel.sysctl."net.ipv4.tcp_congestion_control" = "bbr";
|
|
kernel.sysctl."net.core.default_qdisc" = "fq_codel";
|
|
};
|
|
|
|
# Clean up daily.
|
|
nix.gc = {
|
|
automatic = mkDefault true;
|
|
dates = "*-*-* 05:00:00";
|
|
options = "--delete-older-than 7d";
|
|
};
|
|
|
|
home-manager.useUserPackages = true;
|
|
home-manager.useGlobalPkgs = true;
|
|
|
|
systemd.services."home-manager-lukegb" = {
|
|
before = [ "display-manager.service" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
};
|
|
|
|
home-manager.users.lukegb = { pkgs, ... }: ({
|
|
imports = [ ({
|
|
_module.args = args // {
|
|
configName = null;
|
|
};
|
|
})] ++ config.my.home-manager.imports ++ (
|
|
lib.optional (config.my.home-manager.system != null) config.my.home-manager.system
|
|
);
|
|
});
|
|
|
|
services.prometheus.exporters.node = {
|
|
enable = true;
|
|
enabledCollectors = [ "systemd" "textfile" ];
|
|
extraFlags = [
|
|
"--collector.textfile.directory=/run/prometheus-textfile-exports"
|
|
];
|
|
};
|
|
system.activationScripts.node-exporter = {
|
|
text = ''
|
|
test -d /run/prometheus-textfile-exports || mkdir /run/prometheus-textfile-exports
|
|
my_version_string="$(cat "$systemConfig/nixos-version")"
|
|
my_hash_string="$(readlink -f "$systemConfig" | ${pkgs.gnugrep}/bin/grep -Eo '\b[0-9a-df-np-sv-z]{32}\b')"
|
|
my_specialisation="$(cat "$systemConfig/specialisation-name" 2>/dev/null || true)"
|
|
echo "nixos_running_system{version=\"$my_version_string\", hash=\"$my_hash_string\", specialisation=\"$my_specialisation\"} 1" > /run/prometheus-textfile-exports/running_system.prom
|
|
|
|
my_version_string="$(cat "/run/booted-system/nixos-version")"
|
|
my_hash_string="$(readlink -f "/run/booted-system" | ${pkgs.gnugrep}/bin/grep -Eo '\b[0-9a-df-np-sv-z]{32}\b')"
|
|
my_specialisation="$(cat "/run/booted-system/specialisation-name" 2>/dev/null || true)"
|
|
echo "nixos_booted_system{version=\"$my_version_string\", hash=\"$my_hash_string\", specialisation=\"$my_specialisation\"} 1" > /run/prometheus-textfile-exports/booted_system.prom
|
|
'';
|
|
};
|
|
boot.postBootCommands = lib.mkAfter ''
|
|
test -d /run/prometheus-textfile-exports || mkdir /run/prometheus-textfile-exports
|
|
my_version_string="$(cat "/run/booted-system/nixos-version")"
|
|
my_hash_string="$(readlink -f "/run/booted-system" | ${pkgs.gnugrep}/bin/grep -Eo '\b[0-9a-df-np-sv-z]{32}\b')"
|
|
my_specialisation="$(cat "/run/booted-system/specialisation-name" 2>/dev/null || true)"
|
|
echo "nixos_booted_system{version=\"$my_version_string\", hash=\"$my_hash_string\", specialisation=\"$my_specialisation\"} 1" > /run/prometheus-textfile-exports/booted_system.prom
|
|
'';
|
|
system.extraSystemBuilderCmds = lib.mkAfter ''
|
|
echo "${if config.my.specialisationName == null then "" else config.my.specialisationName}" > $out/specialisation-name
|
|
'';
|
|
|
|
system.nixos.tags = lib.mkBefore ([
|
|
depot.version
|
|
] ++ lib.optional (config.my.specialisationName != null) "specialisation-${config.my.specialisationName}");
|
|
|
|
services.nginx = {
|
|
recommendedTlsSettings = true;
|
|
recommendedOptimisation = true;
|
|
recommendedGzipSettings = true;
|
|
recommendedProxySettings = true;
|
|
};
|
|
|
|
my.vault.secrets.nix-daemon = {
|
|
template = ''
|
|
{{ with secret "kv/apps/nix-daemon" }}
|
|
AWS_ACCESS_KEY_ID={{ .Data.data.cacheAccessKeyID }}
|
|
AWS_SECRET_ACCESS_KEY={{ .Data.data.cacheSecretAccessKey }}
|
|
{{ end }}
|
|
'';
|
|
group = "root";
|
|
reloadOrRestartUnits = [ "nix-daemon.service" ];
|
|
};
|
|
# - prefix to make the file existing optional.
|
|
systemd.services.nix-daemon.serviceConfig.EnvironmentFile = "-${config.my.vault.secrets.nix-daemon.path}";
|
|
|
|
services.fwupd.enable = true;
|
|
|
|
# This is enabled independently of my.scrapeJournal.enable.
|
|
services.journald.enableHttpGateway = config.my.ip.tailscale != null;
|
|
systemd.sockets.systemd-journal-gatewayd.socketConfig = lib.optionalAttrs (config.my.ip.tailscale != null) {
|
|
ListenStream = [ "" "${config.my.ip.tailscale}:19531" ];
|
|
FreeBind = true;
|
|
};
|
|
};
|
|
}
|