From 88353f37274833448be6798fe22227e68668c0be Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Fri, 23 Jun 2023 23:52:31 +0100 Subject: [PATCH] feat: added backup config (currently temp server, will be using hardware soon) --- applications/restic.nix | 162 +++++++++++++++++++++++++++++++++++ flake.nix | 3 + machines/neuromancer.nix | 59 +++++++++++++ secrets/backup/restic.age | 33 +++++++ secrets/backup/restic_pw.age | Bin 0 -> 699 bytes secrets/secrets.nix | 25 ++++-- 6 files changed, 276 insertions(+), 6 deletions(-) create mode 100644 applications/restic.nix create mode 100644 machines/neuromancer.nix create mode 100644 secrets/backup/restic.age create mode 100644 secrets/backup/restic_pw.age diff --git a/applications/restic.nix b/applications/restic.nix new file mode 100644 index 0000000..e511534 --- /dev/null +++ b/applications/restic.nix @@ -0,0 +1,162 @@ + +# nodes is all the nodes +{ lib, config, nodes, ...}: with lib; + let + cfg = config.services.skynet_backup; + + + # since they should all have the same config we can do this + base = { + paths = cfg.normal.backups; + exclude = cfg.normal.exclude; + initialize = true; + passwordFile = config.age.secrets.restic.path; + + pruneOpts = [ + #"--keep-within 0y2m0d0h" + #"--keep-monthly 2" + ]; + + timerConfig = { + OnCalendar = "daily"; + Persistent = true; + RandomizedDelaySec = "5h"; + }; + }; + + # takes nodes, + # for each check if iut has teh abckup attribute, + # then if the server is enabled, + # then pull relevant dtails + ownServers = builtins.listToAttrs (builtins.concatLists ( + lib.attrsets.mapAttrsToList (key: value: + if ( + (builtins.hasAttr "skynet_backup" value.config.services) + && (value.config.services.skynet_backup.server.enable) + && (!value.config.services.skynet_backup.server.appendOnly) + ) + then [ + { + name = value.config.services.skynet_backup.host.name; + value = base // { + repository = "rest:http://${value.config.services.skynet_backup.host.ip}:${value.config.services.skynet_backup.server.port}/${cfg.host.name}"; + }; + } + ] + else [ ] + ) nodes + )); + + + + in { + + imports = [ + + ]; + + # using https://github.com/greaka/ops/blob/818be4c4dea9129abe0f086d738df4cb0bb38288/apps/restic/options.nix as a base + # will eb enabled on every server + options.services.skynet_backup = { + # backup is enabled by default + # enable = mkEnableOption "Skynet backup"; + + # what folders to backup + normal = { + backups = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.str; + description = '' + A list of paths to backup. + ''; + }; + + exclude = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.str; + description = '' + A list of paths to exclide . + ''; + }; + }; + + # append only data so space limited + secure = { + backups = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.str; + description = '' + A list of paths to backup. + ''; + }; + + exclude = lib.mkOption { + default = [ ]; + type = lib.types.listOf lib.types.str; + description = '' + A list of paths to exclide . + ''; + }; + }; + + host = { + ip = mkOption { + type = types.str; + }; + + name = mkOption { + type = types.str; + }; + }; + + server = { + enable = mkEnableOption "Skynet backup Server"; + + port = mkOption { + type = types.str; + default = "8765"; + }; + + appendOnly = mkOption { + type = types.bool; + default = false; + }; + }; + + }; + + + config = { + # these values are anabled for every client + age.secrets.restic.file = ../secrets/backup/restic.age; +# age.secrets.backblaze.file = ../secrets/backup/backblaze.age; + + services.restic.backups = ownServers // { + # merge teh two configs together +# backblaze = base // { +# # backupos for each server are stored in a folder under their name +# repository = "b2:NixOS-Main2:/${cfg.host.name}"; +# #environmentFile = config.age.secrets.backblaze.path; +# }; + + }; + + + #age.secrets.restic_pw.file = mkIf cfg.server.enable ../secrets/backup/restic_pw.age; + + services.restic.server = mkIf cfg.server.enable{ + enable = true; + listenAddress = "${cfg.host.ip}:${cfg.server.port}"; + appendOnly = cfg.server.appendOnly; + #privateRepos = true; + + extraFlags = ["--no-auth"]; + # + }; + + # https://git.hrnz.li/Ulli/nixos/src/commit/5edca2dfdab3ce52208e4dfd2b92951e500f8418/profiles/server/restic.nix + #systemd.tmpfiles.rules = mkIf cfg.server.enable [ + # "L+ ${config.services.restic.server.dataDir}/.htpasswd - - - - ${config.age.secrets.restic_pw.path}" + #]; + }; +} diff --git a/flake.nix b/flake.nix index 034456b..36398ee 100644 --- a/flake.nix +++ b/flake.nix @@ -82,6 +82,9 @@ # email gir.imports = [ ./machines/gir.nix simple-nixos-mailserver.nixosModule]; + # backup 1 + neuromancer = import ./machines/neuromancer.nix; + }; }; diff --git a/machines/neuromancer.nix b/machines/neuromancer.nix new file mode 100644 index 0000000..a397ae5 --- /dev/null +++ b/machines/neuromancer.nix @@ -0,0 +1,59 @@ +/* + + Name: https://williamgibson.fandom.com/wiki/Neuromancer_(AI) + Why: A sibling to Wintermute, stores and archives memories. + Type: VM + Hardware: - + From: 2023 + Role: Backup Server + Notes: + +*/ + +{ pkgs, lib, nodes, ... }: +let + # name of the server, sets teh hostname and record for it + name = "neuromancer"; + ip_pub = "193.1.99.80"; + ip_priv = "172.20.20.7"; + hostname = "${name}.skynet.ie"; + +in { + imports = [ + ../applications/restic.nix + ]; + + deployment = { + targetHost = hostname; + targetPort = 22; + targetUser = "root"; + + tags = [ "active" ]; + }; + + + skynet_dns.records = { + external = [ + "${name} A ${ip_pub}" + ]; + reverse = [ + "${builtins.substring 9 3 ip_pub} IN PTR ${hostname}." + ]; + }; + + services.skynet_backup = { + normal.backups = ["/etc/skynet"]; + + + host = { + ip = ip_pub; + name = name; + }; + + server = { + enable = true; + }; + + }; + +} \ No newline at end of file diff --git a/secrets/backup/restic.age b/secrets/backup/restic.age new file mode 100644 index 0000000..d2ee750 --- /dev/null +++ b/secrets/backup/restic.age @@ -0,0 +1,33 @@ +age-encryption.org/v1 +-> ssh-ed25519 V1pwNA T9gRXKpj/4ewIKWFTa/hIa4/bYVDSWy4buXoda9rSSg +g+JduPpaLSbaae8+SDzlcXRg6N4GNAkmp14QZ+pCb6I +-> ssh-ed25519 rIwlvw gpZihOLlGBfcQkdas8MLnmdNAnltuIl+5JKvgdglJzw +vYLsHxGgzLlZ1FqNQPX//4MgGs60+2YzE39eBS2R6UI +-> ssh-ed25519 q8eJgg DCvlQKK7tH5klfsDWG350EcWbrHuoPoqes0iducTQl4 +vNCjrOXnLyMmU7M4lZQ/e7PQZuBl2oD3Hx/tAUO68uA +-> ssh-ed25519 bPfq4g oWuG4M75YBLCFjOJma/IPFRpoaKPO4zoZ/y511WnbSM +0sJFaEI54NsHbi1xNgMKDRWr8ly9R88Tn80LXA6aOJE +-> ssh-ed25519 P1ilJQ pT4p9gp9LFMuMdJ0KiJJIspLK1Rz8cNgPK3ry1jyP3Q +2CHqMQLYGyFj00qO3JcmfRgLUtPBsAF7Yj5txko6JD4 +-> ssh-ed25519 pBdJmw 5Uo1Iy2iwPcOw7mvUSt/4aWJRUE8pevNQkvnM86lAxk +1znyqu9cbmyQNLUh+V5oMIfxE7jSgcVOfCsHOGRNj8o +-> ssh-ed25519 v2Y09A IvOSMVJgeo92DcKLtt9HjWvhr2D1ubyNk94aTzCWf1w +suSMLOa7y1RAOT/nHhBns1Dx6rrlVq8IFhQdGsmz/N8 +-> ssh-ed25519 XSrA6w n0dvD2rSRxnnSgAz0StT52trGYb/NuC7mrH3qbR5Ins +CFScfXXMacC+n/7akrPXXBoMpMznuYKU6n+ff7a3FVE +-> ssh-ed25519 DVzSig PUxmsjbpaAKHNK1crEdAZfv6GsuNE/ciOCsQ/Eg63jk +xB4/taoj9Bjtmp6vyq4cckNyTnJuvQXUWlv428rOv2Q +-> ssh-ed25519 uZzB3g HMn9ru7qX/7bg6zQ3e4OPWgtI8k4dl+P9EZqdPFU9FM +oIRlyF4cP4u/9tdvXqbnyQNVGJ5RXmEyK8r8j0MyOak +-> ssh-ed25519 yvS9bw Y1cWxbizUa4lWDeMD8d0zLSsVc/1aVqDHhccbqba6SE +X6om2Euh8YPGtCLPA2SWYbJ1CMXQYb+9IGzfVaJ3rNU +-> ssh-ed25519 IzAMqA cD6olEK5Q6vCkO97QofInoziHA61Q/P7PUyIK8K5P2o +IXmD0KDdKNpOLR+I1WrjQN+hS5OKErIHXrXDpMgb9Mg +-> ssh-ed25519 Hb0ipQ 9gSxP4CxZE0PgvRZ+UUPKxhQEJMVG03xVN/e5x1o6hY +84iQ4BGWxMeMa+39ggbs92Mj+L7asopVdjXNYc1xsos +-> ssh-ed25519 pgMpXg 2cm5IFCt30VnbKUy991lxTJRYNLfyu3WpQ7v4C/6OnQ +kQF2YW2Zw0afiJY+/TnhhKkDSS266ByGm2xt34zClo0 +-> `-grease +B3Sa9qAARZP5qG1lRyM8bqHz2jofMaKzfT1Z3Ng1PCHbCJ8rKdNmFYs3 +--- hMXGwWSFtjaEh8RMePM+gnvDF/sSea2n+uu9Hq7y1G0 +1_ H|̠B V6EGM`AtSQ RMI$EC y@ ZrvOPTpWPYT٢3e&U90F0G}mSiv#4U#&wyecǓ \ No newline at end of file diff --git a/secrets/backup/restic_pw.age b/secrets/backup/restic_pw.age new file mode 100644 index 0000000000000000000000000000000000000000..09724783b3bc0d882fd984eb16aa8ffd00e4660a GIT binary patch literal 699 zcmZY4yNlCs003Zdy9|dMs5qIu_R=K3w2gz1XPZaUq-k<#1ffmZ^pRK7JnJY3qJs!J zx`@lcfg-2~E-rH5aKmlRiVkkh;<=uG!N)iDruAv)BvqU)qHsS-JS0b<`Ym{~nb)T- zMi3|on`m4p6znQg?K2+HUY*wxq44tpmi)Me42=LaVhI>amBzD$n>TPP z^$)bQ7?M)8wlQI>bqvTPQ(R(4{I+T*a-ek92w+LXR@ByVA$VzKS{pxci*OA7)7I^& z=y~vfwpIt2sjF^4Dh;O_3fwp=@*a>4N8m(?a+b*1&F>bK6v?GSa_N${%~bGt zwUGO0o`8(#ZcN+=FuqlwJUD-gyE#>s~S)Z>BH} z&6@3TCmX$k@ z9)(d-l^91s^?Ds9r*!J}Z9y8i^9INV4SKa1#H63kmdH9?poy*YYz{0YXLIIh`lDMM zzu)`14_<$1{ATWbUw pbe|mU9$!{hpDw<2UOi0i&heu^Cp)Kyk1k#K_4v)_Q}4!7{0nNI>tz4{ literal 0 HcmV?d00001 diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 3380255..5d9de0f 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -11,6 +11,7 @@ let # change this when its properly set up agentjones = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAbqYQrdVHmGgXZJoMWWRDGVEIj775Zrf4PxB5hoth+k root@agentjones"; + ash = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGJDVQGjIwMQmkElGshgKDAlChM2xdNN6iI5Ap2IbAs5"; # dns servers vendetta = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINxTrUPZPqttuxfmmP8BTACTAkv1yY1nfzEd64hN4LT+ root@vendetta"; @@ -18,24 +19,29 @@ let galatea = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3Mke5YtaMkLvXJxJ3y7YAIEBesoJk3qJyJsnoLUWgW root@galatea"; - # for testing configs at home - silver_homelab = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCG1JzosOwS7oKjgm0+FlqMKrUbu+M5403un+VA7LwiGRQnneawuq6aqQsIoDqAlb9AzUdLTeBQb+rBf94kx7yVGdEIz1i34WdMK3kgl176jnDIR4TWeNKdj8Q6+4d7tn5mZrqmpXZ/+1KSauV9JHxytR+7A4NVexkhGX1Mq3efGBYsCKzUQh83lHs2baWUYuxaPCCR6vy6uklzQRQfg+NsxCCUKkbgJwv1ar5U1ccr4N89EWiR2Yu4XsPzXr0JJUQcUy587l+G7QYVoCwVgUKHevCRqtRlmnI6JrzWctQJPpAmWF4EF66QnWccdXUS+aVc0IKP0ORqmz8Nps4NWWVPjRRxeshl2XfFawWxGlgT4WJ0+qv/EDVPZQvNBrjFvY5QBAaU08Nnkg6QzehlwD4/zQQMFiDjMb7sUuhXdq0vOK235QMhS4jtX7Sm2ki6mJdXrlErq9dIaqcoYuw9EtfajaM/NnGYIy97JUOrfztQTAwiuPgrc4DijpdR0QtvYK7NvefiJYcW+osmcv+FYM03kMXK9uGtM6KI44i27ZdsUFWTIHeiR1yBGUfP1ObFLLaNx5E42jSA77RLF8BSUaPbGgRv3OciACNftIKhAJrV4AZGvBbaUvAlzC8CryFAcRDgQwIVlXBJzChc7Rh9/V8I5342Tq7xMmzBQ2WcQdqZ9Q== root@galatea"; - optimus = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIqYbbWy3WWtxvD96Hx+RfTx7fJPPirIEa5bOvUILi9r root@optimus"; glados = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ6go7ScvOga9vYqC5HglPfh2Nu8wQTpEKpvIZuMAZom root@glados"; - wheatly = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEehcrWqZbTr4+do1ONE9Il/SayP0xXMvhozm845tonN root@wheatly"; kitt = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPble6JA2O/Wwv0Fztl/kiV0qj+QMjS+jTTj1Sz8k9xK root@kitt"; gir = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINL2qk/e0QBqpTQ2xDjF7Cv4c92jJ53jW2fuu88hAF/u root@gir"; + neuromancer = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFozqR8f8DN7/DLUQV4o290n3UZ75fSEdgVlSwzyza/N root@neuromancer"; + systems = [ agentjones ash - - silver_homelab + vendetta + vigil + galatea + optimus + glados + wheatly + kitt + gir + neuromancer ]; dns = [ @@ -72,6 +78,9 @@ let ++ ldap ++ gitlab; + restic = [ + neuromancer + ]; in { # nix run github:ryantm/agenix -- -e secret1.age @@ -96,4 +105,8 @@ in "ldap/pw.age".publicKeys = users ++ ldap; "ldap/self_service.age".publicKeys = users ++ ldap; + # everyone has access to this + "backup/restic.age".publicKeys = users ++ systems; + "backup/restic_pw.age".publicKeys = users ++ restic; + } \ No newline at end of file