From b14a690975aaeb2681dc0caf22f43f794f60d046 Mon Sep 17 00:00:00 2001 From: Emelie Date: Wed, 22 Sep 2021 10:16:11 +0200 Subject: [PATCH] wind 1.0 --- .gitignore | 2 + LICENSE | 21 +++ README.md | 1 + config/hosts/wind/configuration.nix | 78 +++++++++ config/hosts/wind/hardware-configuration.nix | 72 ++++++++ config/hosts/wind/services/acme.nix | 25 +++ config/hosts/wind/services/coturn.nix | 26 +++ config/hosts/wind/services/gitea.nix | 16 ++ config/hosts/wind/services/nginx.nix | 73 ++++++++ config/hosts/wind/services/postgres.nix | 27 +++ config/hosts/wind/services/restic.nix | 34 ++++ config/hosts/wind/services/sshguard.nix | 7 + config/hosts/wind/services/synapse.nix | 57 ++++++ config/hosts/wind/services/ttrss.nix | 10 ++ config/sources/default.nix | 11 ++ config/sources/nix/sources.json | 50 ++++++ config/sources/nix/sources.nix | 174 +++++++++++++++++++ deploy/default.nix | 23 +++ 18 files changed, 707 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config/hosts/wind/configuration.nix create mode 100644 config/hosts/wind/hardware-configuration.nix create mode 100644 config/hosts/wind/services/acme.nix create mode 100644 config/hosts/wind/services/coturn.nix create mode 100644 config/hosts/wind/services/gitea.nix create mode 100644 config/hosts/wind/services/nginx.nix create mode 100644 config/hosts/wind/services/postgres.nix create mode 100644 config/hosts/wind/services/restic.nix create mode 100644 config/hosts/wind/services/sshguard.nix create mode 100644 config/hosts/wind/services/synapse.nix create mode 100644 config/hosts/wind/services/ttrss.nix create mode 100644 config/sources/default.nix create mode 100644 config/sources/nix/sources.json create mode 100644 config/sources/nix/sources.nix create mode 100644 deploy/default.nix diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3bc6559 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +**/secrets/ +/result diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..942787e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Emelie Graven + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..885ac1b --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +NixOS deployments using [nixus](https://github.com/Infinisil/nixus). diff --git a/config/hosts/wind/configuration.nix b/config/hosts/wind/configuration.nix new file mode 100644 index 0000000..948d4fc --- /dev/null +++ b/config/hosts/wind/configuration.nix @@ -0,0 +1,78 @@ +{ config, pkgs, lib, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ./services/acme.nix + ./services/coturn.nix + ./services/nginx.nix + ./services/postgres.nix + ./services/synapse.nix + ./services/ttrss.nix + ./services/gitea.nix + ./services/restic.nix + ./services/sshguard.nix + ./data/secrets/secrets.nix + ]; + + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.device = "/dev/sda"; + boot.supportedFilesystems = ["zfs"]; + services.zfs.autoSnapshot.enable = true; + services.zfs.autoScrub.enable = true; + + networking.hostName = "wind"; + networking.hostId = "929e7fb7"; + time.timeZone = "Europe/Copenhagen"; + networking.useDHCP = false; + networking.interfaces.ens3.useDHCP = true; + networking.interfaces.ens3.ipv6.addresses = [ { address = "2a01:4f9:c010:34cb::1"; prefixLength = 64; } ]; + networking.defaultGateway6 = { address = "fe80::1"; interface = "ens3"; }; + + users.users.emelie = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICO4LyBsW1YuUA6i3EL/IZhchSvk7reO4qgRmR/tdQPU emelie@flap" + ]; + }; + + security.sudo.wheelNeedsPassword = false; + + environment.systemPackages = with pkgs; [ + vim + htop + iotop + ]; + + nix = { + autoOptimiseStore = true; + trustedUsers = [ + "root" + "@wheel" + ]; + }; + + services.openssh = { + enable = true; + passwordAuthentication = false; + permitRootLogin = "no"; + challengeResponseAuthentication = false; + }; + + # Use hetzner firewall instead + networking.firewall.enable = false; + # networking.firewall.allowedTCPPorts = [ 22 80 443 3478 5349 ]; + # networking.firewall.allowedUDPPorts = [ 3478 5349 ] + # networking.firewall.allowedUDPPortsRanges = [ { from = 49152; to = 49999; } ]; + + users.groups.acme.members = [ "nginx" "turnserver" "gitea" ]; + users.groups.postgres.members = [ "restic" ]; + users.groups.gitea.members = [ "restic" ]; + users.groups.matrix-synapse.members = [ "restic" ]; + + + system.stateVersion = "21.05"; + +} diff --git a/config/hosts/wind/hardware-configuration.nix b/config/hosts/wind/hardware-configuration.nix new file mode 100644 index 0000000..1e2ed9e --- /dev/null +++ b/config/hosts/wind/hardware-configuration.nix @@ -0,0 +1,72 @@ +# 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") + (modulesPath + "/profiles/minimal.nix") + #(modulesPath + "/profiles/hardened.nix") + ]; + + boot.initrd.availableKernelModules = [ "ata_piix" "virtio_pci" "virtio_scsi" "xhci_pci" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "rpool/safe/root"; + fsType = "zfs"; + }; + + fileSystems."/home" = + { device = "rpool/safe/home"; + fsType = "zfs"; + }; + + fileSystems."/nix" = + { device = "rpool/local/nix"; + fsType = "zfs"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/85B8-9142"; + fsType = "vfat"; + }; + + fileSystems."/var/lib/matrix-synapse" = + { device = "rpool/safe/synapse"; + fsType = "zfs"; + }; + + fileSystems."/var/lib/postgresql" = + { device = "rpool/safe/postgres"; + fsType = "zfs"; + }; + + fileSystems."/var/lib/acme" = + { device = "rpool/safe/acme"; + fsType = "zfs"; + }; + + fileSystems."/var/www" = + { device = "rpool/safe/webroot"; + fsType = "zfs"; + }; + + fileSystems."/var/lib/tt-rss" = + { device = "rpool/safe/tt-rss"; + fsType = "zfs"; + }; + + fileSystems."/var/lib/gitea" = + { device = "rpool/safe/gitea"; + fsType = "zfs"; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/e70cc088-a54e-4cd8-88ec-91944e5ff989"; } + ]; + +} diff --git a/config/hosts/wind/services/acme.nix b/config/hosts/wind/services/acme.nix new file mode 100644 index 0000000..4ff75ce --- /dev/null +++ b/config/hosts/wind/services/acme.nix @@ -0,0 +1,25 @@ +{ config, ... }: + +{ + security.acme = { + acceptTerms = true; + email = "admin+certs@graven.dev"; + certs."graven.dev" = { + dnsProvider = "hurricane"; + credentialsFile = config.secrets.files.acme_graven_dev.file; + }; + certs."turn.graven.dev" = { + dnsProvider = "hurricane"; + credentialsFile = config.secrets.files.acme_turn_graven_dev.file; + }; + certs."rss.graven.dev" = { + dnsProvider = "hurricane"; + credentialsFile = config.secrets.files.acme_rss_graven_dev.file; + }; + certs."git.graven.dev" = { + dnsProvider = "hurricane"; + credentialsFile = config.secrets.files.acme_git_graven_dev.file; + }; + }; +} + diff --git a/config/hosts/wind/services/coturn.nix b/config/hosts/wind/services/coturn.nix new file mode 100644 index 0000000..3094ebd --- /dev/null +++ b/config/hosts/wind/services/coturn.nix @@ -0,0 +1,26 @@ +{ + services.coturn = { + enable = true; + lt-cred-mech = true; + use-auth-secret = true; + #static-auth-secret = builtins.toString config.secrets.files.synapse_turn_shared_secret.file; + static-auth-secret = "a_long_string_that_i_will_be_changing"; + realm = "turn.graven.dev"; + relay-ips = [ + "65.21.58.38" + "2a01:4f9:c010:34cb::1" + ]; + no-tcp-relay = true; + extraConfig = " + cipher-list=\"HIGH\" + no-loopback-peers + no-multicast-peers + "; + secure-stun = true; + cert = "/var/lib/acme/turn.graven.dev/fullchain.pem"; + pkey = "/var/lib/acme/turn.graven.dev/key.pem"; + min-port = 49152; + max-port = 49999; + }; +} + diff --git a/config/hosts/wind/services/gitea.nix b/config/hosts/wind/services/gitea.nix new file mode 100644 index 0000000..58fc760 --- /dev/null +++ b/config/hosts/wind/services/gitea.nix @@ -0,0 +1,16 @@ +{ ... }: + +{ + services.gitea = { + enable = true; + domain = "git.graven.dev"; + rootUrl = "https://git.graven.dev"; + enableUnixSocket = true; + cookieSecure = true; + appName = "Graven Gitea"; + settings = { "ui" = { "DEFAULT_THEME" = "arc-green"; }; }; + database = { + type = "postgres"; + }; + }; +} diff --git a/config/hosts/wind/services/nginx.nix b/config/hosts/wind/services/nginx.nix new file mode 100644 index 0000000..459a3a7 --- /dev/null +++ b/config/hosts/wind/services/nginx.nix @@ -0,0 +1,73 @@ +{ + services.nginx = { + enable = true; + + # Use recommended settings + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + + # Only allow PFS-enabled ciphers with AES256 + sslCiphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; + + commonHttpConfig = '' + # Add HSTS header with preloading to HTTPS requests. + # Adding this header to HTTP requests is discouraged + map $scheme $hsts_header { + https "max-age=31536000; includeSubdomains; preload"; + } + add_header Strict-Transport-Security $hsts_header; + + # Enable CSP for your services. + #add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'none';" always; + + # Minimize information leaked to other domains + add_header 'Referrer-Policy' 'origin-when-cross-origin'; + + # Disable embedding as a frame + add_header X-Frame-Options DENY; + + # Prevent injection of code in other mime types (XSS Attacks) + add_header X-Content-Type-Options nosniff; + + # Enable XSS protection of the browser. + # May be unnecessary when CSP is configured properly (see above) + add_header X-XSS-Protection "1; mode=block"; + + # This might create errors + proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict"; + ''; + + virtualHosts = { + "graven.dev" = { + useACMEHost = "graven.dev"; + forceSSL = true; + locations."/".root = "/var/www/graven.dev/public"; + locations."/_matrix".proxyPass = "http://127.0.0.1:8008"; + locations."/_synapse".proxyPass = "http://127.0.0.1:8008"; + locations."/.well-known/matrix/" = { + root = "/var/www/matrix/public"; + extraConfig = '' + default_type application/json; + add_header Access-Control-Allow-Origin "*"; + add_header Strict-Transport-Security $hsts_header; + add_header Referrer-Policy "origin-when-cross-origin"; + add_header X-Frame-Options "DENY"; + add_header X-Content-Type-Options "nosniff"; + add_header X-XSS-Protection "1; mode=block"; + ''; + }; + }; + "rss.graven.dev" = { + useACMEHost = "rss.graven.dev"; + forceSSL = true; + }; + "git.graven.dev" = { + useACMEHost = "git.graven.dev"; + forceSSL = true; + locations."/".proxyPass = "http://unix:/run/gitea/gitea.sock:"; + }; + }; + }; +} diff --git a/config/hosts/wind/services/postgres.nix b/config/hosts/wind/services/postgres.nix new file mode 100644 index 0000000..be905b2 --- /dev/null +++ b/config/hosts/wind/services/postgres.nix @@ -0,0 +1,27 @@ +{ pkgs, ... }: +{ + services.postgresql = { + enable = true; + package = pkgs.postgresql_13; + initialScript = pkgs.writeText "synapse-init.sql" '' + CREATE ROLE synapse; + CREATE DATABASE synapse WITH OWNER synapse + TEMPLATE template0 + LC_COLLATE = "C" + LC_CTYPE = "C" + ENCODING = "UTF8"; + ''; + authentication = pkgs.lib.mkOverride 10 '' + local all all trust + host all all ::1/128 trust + ''; + }; + + services.postgresqlBackup = { + enable = true; + location = "/var/lib/postgresql/backup"; + databases = [ "gitea" "mogger" "synapse" "tt_rss" ]; + startAt = "02:30"; + compression = "none"; + }; +} diff --git a/config/hosts/wind/services/restic.nix b/config/hosts/wind/services/restic.nix new file mode 100644 index 0000000..07bbc39 --- /dev/null +++ b/config/hosts/wind/services/restic.nix @@ -0,0 +1,34 @@ +{ config, ... }: + +{ + + services.restic.backups = { + "gitea" = { + paths = [ "/var/lib/gitea" ]; + repository = "sftp:restic@despondos.nao.sh:/etheria/backup/wind/gitea"; + initialize = true; + pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12" "--keep-yearly 75" ]; + timerConfig = { "OnCalendar" = "02:15"; }; + extraOptions = [ "sftp.command='ssh restic@despondos.nao.sh -i ${config.secrets.files.ssh_private_key.file} -s sftp'" ]; + passwordFile = builtins.toString config.secrets.files.restic_pass.file; + }; + "postgres" = { + paths = [ "/var/lib/postgresql/backup" ]; + repository = "sftp:restic@despondos.nao.sh:/etheria/backup/wind/postgres"; + initialize = true; + pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12" "--keep-yearly 75" ]; + timerConfig = { "OnCalendar" = "03:00"; }; + extraOptions = [ "sftp.command='ssh restic@despondos.nao.sh -i ${config.secrets.files.ssh_private_key.file} -s sftp'" ]; + passwordFile = builtins.toString config.secrets.files.restic_pass.file; + }; + "synapse" = { + paths = [ "/var/lib/matrix-synapse" ]; + repository = "sftp:restic@despondos.nao.sh:/etheria/backup/wind/synapse"; + initialize = true; + pruneOpts = [ "--keep-daily 7" "--keep-weekly 5" "--keep-monthly 12" "--keep-yearly 75" ]; + timerConfig = { "OnCalendar" = "03:30"; }; + extraOptions = [ "sftp.command='ssh restic@despondos.nao.sh -i ${config.secrets.files.ssh_private_key.file} -s sftp'" ]; + passwordFile = builtins.toString config.secrets.files.restic_pass.file; + }; + }; +} diff --git a/config/hosts/wind/services/sshguard.nix b/config/hosts/wind/services/sshguard.nix new file mode 100644 index 0000000..a36708e --- /dev/null +++ b/config/hosts/wind/services/sshguard.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + services.sshguard = { + enable = true; + blocktime = 300; + }; +} diff --git a/config/hosts/wind/services/synapse.nix b/config/hosts/wind/services/synapse.nix new file mode 100644 index 0000000..3ae9a0c --- /dev/null +++ b/config/hosts/wind/services/synapse.nix @@ -0,0 +1,57 @@ +{ config, ... }: + +{ + services.matrix-synapse = { + enable = true; + server_name = "graven.dev"; + enable_registration = false; + # This causes infinite recursion for some reason. TODO: Investigate + #registration_shared_secret = builtins.toString config.secrets.files.synapse_registration_shared_secret.file; + #turn_shared_secret = builtins.toString config.secrets.files.synapse_turn_shared_secret.file; + turn_shared_secret = "a_long_string_that_i_will_be_changing"; + max_upload_size = "100M"; + database_type = "psycopg2"; + database_user = "synapse"; + database_name = "synapse"; + logConfig = '' + version: 1 + + formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + + handlers: + console: + class: logging.StreamHandler + formatter: precise + + loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: WARN + + root: + level: WARN + handlers: [console] + + disable_existing_loggers: false + ''; + listeners = [ + { + port = 8008; + bind_address = "127.0.0.1"; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ + { + names = [ "client" "federation" ]; + compress = false; + } + ]; + } + ]; + }; +} + diff --git a/config/hosts/wind/services/ttrss.nix b/config/hosts/wind/services/ttrss.nix new file mode 100644 index 0000000..3a30bee --- /dev/null +++ b/config/hosts/wind/services/ttrss.nix @@ -0,0 +1,10 @@ +{ config, ... }: + +{ + services.tt-rss = { + enable = true; + registration.enable = true; + virtualHost = "rss.graven.dev"; + selfUrlPath = "https://rss.graven.dev"; + }; +} diff --git a/config/sources/default.nix b/config/sources/default.nix new file mode 100644 index 0000000..ccd3ba8 --- /dev/null +++ b/config/sources/default.nix @@ -0,0 +1,11 @@ +let + sources = import ./nix/sources.nix; + + # just use standard pkgs from sources + # so that we have our applyPattches function + pkgs = import sources.nixpkgs {}; + +in { + nixus = sources.nixus; +} // sources + diff --git a/config/sources/nix/sources.json b/config/sources/nix/sources.json new file mode 100644 index 0000000..bd9d728 --- /dev/null +++ b/config/sources/nix/sources.json @@ -0,0 +1,50 @@ +{ + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "65a61b147f307d24bfd0a5cd56ce7d7b7cc61d2e", + "sha256": "17mirpsx5wyw262fpsd6n6m47jcgw8k2bwcp1iwdnrlzy4dhcgqh", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/65a61b147f307d24bfd0a5cd56ce7d7b7cc61d2e.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixos-hardware": { + "branch": "master", + "description": "A collection of NixOS modules covering hardware quirks.", + "homepage": "", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "16fca9df230408608846940981b4037762420b1b", + "sha256": "0nvak6dmlcgc4m5s6di82c06c95cmc4iys1ky14y5di27r7qnrma", + "type": "tarball", + "url": "https://github.com/NixOS/nixos-hardware/archive/16fca9df230408608846940981b4037762420b1b.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "nixos-unstable-small", + "description": "Nix Packages collection", + "homepage": "", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d6b683c0527a7f777b5f2b4db2555891cd5a85f5", + "sha256": "0mkinbg2s4mg1ngh773h7rqc898siyigwy2wfz8jaai8k9srpx1n", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/d6b683c0527a7f777b5f2b4db2555891cd5a85f5.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixus": { + "branch": "master", + "description": null, + "homepage": "", + "owner": "Infinisil", + "repo": "nixus", + "rev": "851b6b7480815afd0032fd15ebcf23e80e1d7e57", + "sha256": "1vr39sa7gldwkkhcq70ki878zgnj9z4gvwg85asi2mai0x47f3lb", + "type": "tarball", + "url": "https://github.com/Infinisil/nixus/archive/851b6b7480815afd0032fd15ebcf23e80e1d7e57.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/config/sources/nix/sources.nix b/config/sources/nix/sources.nix new file mode 100644 index 0000000..1938409 --- /dev/null +++ b/config/sources/nix/sources.nix @@ -0,0 +1,174 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; name = name'; } + else + pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; + + fetch_tarball = pkgs: name: spec: + let + name' = sanitizeName name + "-src"; + in + if spec.builtin or true then + builtins_fetchTarball { name = name'; inherit (spec) url sha256; } + else + pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; + + fetch_git = name: spec: + let + ref = + if spec ? ref then spec.ref else + if spec ? branch then "refs/heads/${spec.branch}" else + if spec ? tag then "refs/tags/${spec.tag}" else + abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; + in + builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; }; + + fetch_local = spec: spec.path; + + fetch_builtin-tarball = name: throw + ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=tarball -a builtin=true''; + + fetch_builtin-url = name: throw + ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. + $ niv modify ${name} -a type=file -a builtin=true''; + + # + # Various helpers + # + + # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 + sanitizeName = name: + ( + concatMapStrings (s: if builtins.isList s then "-" else s) + ( + builtins.split "[^[:alnum:]+._?=-]+" + ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) + ) + ); + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = sources: system: + let + sourcesNixpkgs = + import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = == ./.; + in + if builtins.hasAttr "nixpkgs" sources + then sourcesNixpkgs + else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + import {} + else + abort + '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs name spec + else if spec.type == "tarball" then fetch_tarball pkgs name spec + else if spec.type == "git" then fetch_git name spec + else if spec.type == "local" then fetch_local spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball name + else if spec.type == "builtin-url" then fetch_builtin-url name + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # If the environment variable NIV_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + replace = name: drv: + let + saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; + ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; + in + if ersatz == "" then drv else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 + optionalAttrs = cond: as: if cond then as else {}; + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, name ? null, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = replace name (fetch config.pkgs name spec); } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null + , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) + , system ? builtins.currentSystem + , pkgs ? mkPkgs sources system + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; + +in +mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/deploy/default.nix b/deploy/default.nix new file mode 100644 index 0000000..f46e893 --- /dev/null +++ b/deploy/default.nix @@ -0,0 +1,23 @@ +let + sources = import ../config/sources; +in import "${sources.nixus}" {} ({ config, ... }: { + + defaults = { name, ... }: { + configuration = { lib, ... }: { + networking.hostName = lib.mkDefault name; + }; + + # use our nixpkgs from niv + nixpkgs = sources.nixpkgs; + }; + + nodes = { + wind = { lib, config, ... }: { + host = "emelie@graven.dev"; + configuration = ../config/hosts/wind/configuration.nix; + switchTimeout = 300; + successTimeout = 300; + }; + }; +}) +