diff --git a/DEPLOYMENT-NOTES.rst b/DEPLOYMENT-NOTES.rst index 5f1b15e933e9c2e98c364bf5969350a494987f61..fbde887b5ecfc5f1fa5b520df71a6a0ecc1980fe 100644 --- a/DEPLOYMENT-NOTES.rst +++ b/DEPLOYMENT-NOTES.rst @@ -1,6 +1,40 @@ Deployment notes ================ +- 2021-12-20 + + `https://whetstone.privatestorage.io/privatestorage/privatestorageops/-/issues/399`_ requires moving the PaymentServer database on the ``payments`` host onto a new dedicated filesystem. + + Follow these steps *before* deploying this version of PrivateStorageio: + + 0. Deploy the `PrivateStorageOps change <https://whetstone.privatestorage.io/privatestorage/privatestorageops/-/merge_requests/169>`_ that creates a new dedicated volume. + + 1. Put a disk label on the new dedicated volume :: + + nix-shell -p parted --run 'parted /dev/nvme1n1 mklabel msdos' + + 2. Put a properly aligned partition in the new disk label :: + + nix-shell -p parted --run 'parted /dev/nvme1n1 mkpart primary ext2 4096s 4G' + + 3. Create a labeled filesystem on the partition :: + + mkfs.ext4 -L zkapissuer-data /dev/nvme1n1p1 + + 4. Deploy the PrivateStorageio update. + + 5. Move the database file to the new location :: + + mv -iv /var/lib/zkapissuer/vouchers.sqlite3 /var/lib/zkapissuer-v2 + + 6. Clean up the old state directory :: + + rm -ir /var/lib/zkapissuer + + 7. Start the PaymentServer service (not running because its path assertions were not met earlier) :: + + systemctl start zkapissuer + - 2021-10-12 The secret in ``private-keys/grafana-slack-url`` needs to be changed to remove the ``SLACKURL=`` prefix. - 2021-09-30 `Enable alerting <https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/merge_requests/185>`_ needs a secret in ``private-keys/grafana-slack-url`` looking like the template in ``morph/grid/local/private-keys/grafana-slack-url`` and pointing to the secret API endpoint URL saved in `this 1Password entry <https://privatestorage.1password.com/vaults/7flqasy5hhhmlbtp5qozd3j4ga/allitems/cgznskz2oix2tyx5xyntwaos5i>`_ (or create a new secret URL at https://www.slack.com/apps/A0F7XDUAZ). @@ -15,4 +49,3 @@ Deployment notes chmod 750 /var/lib/zkapissuer chmod 640 /var/lib/zkapissuer/vouchers.sqlite3 - diff --git a/morph/lib/base.nix b/morph/lib/base.nix index f6a9a5f008681df23487f0f065ec4b9b8f982067..7390654ac167909149b0a6f4dfae897b8f3f43a3 100644 --- a/morph/lib/base.nix +++ b/morph/lib/base.nix @@ -20,8 +20,12 @@ }; }; + # Any extra NixOS modules to load on all our servers. Note that just + # because they're loaded doesn't *necessarily* mean they're turned on. imports = [ - ../../nixos/modules/packages.nix + # This brings in various other modules that define options for different + # areas of the service. + ../../nixos/modules/default.nix ]; config = { diff --git a/morph/lib/hardware-vagrant.nix b/morph/lib/hardware-vagrant.nix index 150944cd5b64b7a3eb620cd40ea39e00544779a7..6c41af4923861e89d144303d129d7babde494363 100644 --- a/morph/lib/hardware-vagrant.nix +++ b/morph/lib/hardware-vagrant.nix @@ -31,7 +31,21 @@ prefixLength = 24; }]; + # The issuer configuration wants to read the location of its database + # directory from the filesystem configuration. Since the Vagrant + # environment doesn't have separate volume-as-infrastructure management + # (maybe it could? but why bother?) we do a bind-mount here so there is a + # configured value readable. The database won't really have a dedicated + # volume but it will sort of appear as if it does. + services.private-storage-issuer.databaseFileSystem = { + device = "/var/lib/origin-zkapissuer-v2"; + options = ["bind"]; + }; + + # XXX This should be handled by the storage module like the zkap + # filesystem above is handled by the issuer module. fileSystems."/storage" = { fsType = "tmpfs"; }; + fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; diff --git a/morph/lib/issuer-aws.nix b/morph/lib/issuer-aws.nix index bf7de56cfb570857da32c34ebfcc9b21c91e702e..8ff172803eda784898aba2d96636df1afcee36e5 100644 --- a/morph/lib/issuer-aws.nix +++ b/morph/lib/issuer-aws.nix @@ -18,6 +18,14 @@ # <https://github.com/DBCDK/morph/issues/146>. networking.hostName = name; + # Mount a dedicated filesystem (ideally on a dedicated volume, but that's + # beyond control of this particular part of the system) for the + # PaymentServer voucher database. This makes it easier to manage for + # tasks like backup/recovery and encryption. + services.private-storage-issuer.databaseFileSystem = { + label = "zkapissuer-data"; + }; + # Clean up packages after a while nix.gc = { automatic = true; diff --git a/morph/lib/issuer.nix b/morph/lib/issuer.nix index d60af799888c97ec8f97a061d40b54d3f2db82a7..d3ee812e865f741b01eb811589262ae01ece824f 100644 --- a/morph/lib/issuer.nix +++ b/morph/lib/issuer.nix @@ -45,7 +45,6 @@ in { }; imports = [ - ../../nixos/modules/issuer.nix ../../nixos/modules/monitoring/vpn/client.nix ../../nixos/modules/monitoring/exporters/node.nix ]; @@ -56,6 +55,6 @@ in { ristrettoSigningKeyPath = config.deployment.secrets.ristretto-signing-key.destination; stripeSecretKeyPath = config.deployment.secrets.stripe-secret-key.destination; database = "SQLite3"; - databasePath = "/var/lib/zkapissuer/vouchers.sqlite3"; + databasePath = "${config.fileSystems."zkapissuer-data".mountPoint}/vouchers.sqlite3"; }; } diff --git a/nixos/modules/default.nix b/nixos/modules/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..1772d399639aa8b4ec2c9ac6a218c4dd8a6169da --- /dev/null +++ b/nixos/modules/default.nix @@ -0,0 +1,16 @@ +{ + # Load modules that are sometimes universally useful and other times useful + # only for a specific service. Where functionality is not universally + # useful, it needs to be enabled by a node's configuration. By loading more + # modules (and therefore defining more options) than is strictly necessary + # for any single node the logic for supplying conditional configuration + # elsewhere is much simplified. For example, a Vagrant module can + # unconditionally set up a filesystem for PaymentServer. If PaymentServer + # is running on that node then it will get a Vagrant-appropriate + # configuration. If PaymentServer hasn't been enabled then the + # configuration will just be ignored. + imports = [ + ./packages.nix + ./issuer.nix + ]; +} diff --git a/nixos/modules/issuer.nix b/nixos/modules/issuer.nix index e0d1f6560e48748854ab5bcd4613b50c2f24cbcd..67bc3c5029c290676a777115179b273b2e8851ef 100644 --- a/nixos/modules/issuer.nix +++ b/nixos/modules/issuer.nix @@ -81,6 +81,15 @@ in { The kind of voucher database to use. ''; }; + services.private-storage-issuer.databaseFileSystem = lib.mkOption { + # Logically, the type is the type of an entry in fileSystems - but we'll + # just let the type system enforce that when we pass the value on to + # fileSystems. + description = '' + Configuration for a filesystem to mount which will hold the issuer's + internal state database. + ''; + }; services.private-storage-issuer.databasePath = lib.mkOption { default = null; type = lib.types.str; @@ -114,7 +123,23 @@ in { # Payment server internal http port (arbitrary, non-priviledged): internalHttpPort = "1061"; + # The "-vN" suffix indicates that this Nth incompatible version of on + # disk state as managed by this deployment system. This does not have + # anything to do with what's inside the PaymentServer-managed state. + # Instead it's about things like the type of filesystem used or options + # having to do with the backing volume behind the filesystem. In + # general I expect that to get from "-vN" to "-v(N+1)" some manual + # upgrade steps will be required. + stateDirectory = "zkapissuer-v2"; + in lib.mkIf cfg.enable { + # Make sure the voucher database filesystem is mounted. + fileSystems = { + "zkapissuer-data" = cfg.databaseFileSystem // { + mountPoint = "/var/lib/${stateDirectory}"; + }; + }; + # Add a systemd service to run PaymentServer. systemd.services.zkapissuer = { enable = true; @@ -137,15 +162,30 @@ in { # Make systemd create a User/Group owned directory for PaymentServer # state. According to the docs at # https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RuntimeDirectory= - # "The specified directory names must be relative" ... this - # makes systemd create /var/lib/zkapissuer/ for us: - serviceConfig.StateDirectory = "zkapissuer"; + # "The specified directory names must be relative" ... this makes + # systemd create this directory in /var/lib/ for us. + serviceConfig.StateDirectory = stateDirectory; serviceConfig.StateDirectoryMode = "0750"; - # Bail if there is still an old (root-owned) DB file on this system. - # If you hit this, and this /var/db/ file is indeed current, move it to - # /var/lib/zkapissuer/vouchers.sqlite3 and chown it to zkapissuer:zkapissuer. - unitConfig.AssertPathExists = "!/var/db/vouchers.sqlite3"; + unitConfig.AssertPathExists = [ + # Bail if there is still an old (root-owned) DB file on this system. + # If you hit this, and this /var/db/ file is indeed current, move it + # to /var/lib/zkapissuer/vouchers.sqlite3 and chown it to + # zkapissuer:zkapissuer. + "!/var/db/vouchers.sqlite3" + + # Similarly, bail if the newer path you were just told to create -- + # /var/lib/zkapissuer/vouchers.sqlite3 -- exists. It needs to be + # moved /var/lib/zkapissuer-v2 where a dedicated filesystem has been + # created for it. + "!/var/lib/zkapissuer/vouchers.sqlite3" + ]; + + # Only start if the dedicated vouchers database filesystem is mounted so + # that we know we're going to find our vouchers database there (or that + # we will create it in the right place). + unitConfig.Requires = ["local-fs.target"]; + unitConfig.After = ["local-fs.target"]; script = let