diff --git a/templates/hetzner/1.sh b/templates/hetzner/1.sh new file mode 100755 index 0000000..a3813e3 --- /dev/null +++ b/templates/hetzner/1.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +set -ex + +mkdir -p tmp +pushd tmp +rm -rf * + +source vars.sh + +# Generate cold keys (not to be copied) +# cold.vkey, cold.skey and opcert.counter +cardano-cli latest node key-gen \ + --cold-verification-key-file cold.vkey \ + --cold-signing-key-file cold.skey \ + --operational-certificate-issue-counter-file opcert.counter + +# Generate payment keys +cardano-cli latest address key-gen \ + --verification-key-file payment.vkey \ + --signing-key-file payment.skey + +# Generate stake keys +cardano-cli latest stake-address key-gen \ + --verification-key-file stake.vkey \ + --signing-key-file stake.skey + +# Generate the payment address +cardano-cli latest address build \ + --payment-verification-key-file payment.vkey \ + --stake-verification-key-file stake.vkey \ + --testnet-magic 2 \ + --out-file payment.addr + +# Generate KES keys +# kes.vkey, kes.skey +cardano-cli latest node key-gen-KES \ + --verification-key-file kes.vkey \ + --signing-key-file kes.skey + +# Generate VRF keys +# vrf.vkey and vrf.skey +cardano-cli latest node key-gen-VRF \ + --verification-key-file vrf.vkey \ + --signing-key-file vrf.skey + +cardano-cli latest stake-pool registration-certificate \ + --cold-verification-key-file cold.vkey \ + --vrf-verification-key-file vrf.vkey \ + --pool-pledge $PLEDGE \ + --pool-cost $COST \ + --pool-margin $MARGIN \ + --pool-reward-account-verification-key-file stake.vkey \ + --pool-owner-stake-verification-key-file stake.vkey \ + --testnet-magic $TESTNET_MAGIC \ + --pool-relay-ipv4 $RELAY_IPV4 \ + --pool-relay-port $RELAY_PORT \ + --single-host-pool-relay $RELAY_HOST \ + --metadata-url $METADATA_FILE \ + --metadata-hash $METADATA_HASH \ + --out-file pool-registration.cert + +cardano-cli latest stake-address registration-certificate \ + --key-reg-deposit-amt $STAKE_DEPOSIT_AMOUNT \ + --stake-verification-key-file stake.vkey \ + --out-file registration.cert + +cardano-cli latest stake-address stake-delegation-certificate \ + --stake-verification-key-file stake.vkey \ + --cold-verification-key-file cold.vkey \ + --out-file stake-delegation.cert + +cardano-cli latest stake-pool id \ + + --output-format bech32 > pool_id.bech32 + +popd diff --git a/templates/hetzner/2.sh b/templates/hetzner/2.sh new file mode 100755 index 0000000..fd8909a --- /dev/null +++ b/templates/hetzner/2.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -xe + +TESTNET_MAGIC=${TESTNET_MAGIC:-2} + +cardano-cli latest transaction build \ + --testnet-magic $TESTNET_MAGIC \ + --witness-override 2 \ + --tx-in $(cardano-cli query utxo --address $(cat payment.addr) --testnet-magic $TESTNET_MAGIC --out-file /dev/stdout | jq -r 'keys[0]') \ + --change-address $(cat payment.addr) \ + --certificate-file registration.cert \ + --out-file tx.raw + +cardano-cli latest transaction sign \ + --tx-body-file tx.raw \ + --signing-key-file payment.skey \ + --signing-key-file stake.skey \ + --testnet-magic $TESTNET_MAGIC \ + --out-file tx.signed + +cardano-cli latest transaction submit \ + --testnet-magic 2 \ + --tx-file tx.signed + +# Wait a bit? + +cardano-cli latest transaction build \ + --testnet-magic $TESTNET_MAGIC \ + --witness-override 3 \ + --tx-in $(cardano-cli query utxo --address $(cat payment.addr) --testnet-magic $TESTNET_MAGIC --out-file /dev/stdout | jq -r 'keys[0]') \ + --change-address $(cat payment.addr) \ + --certificate-file pool-registration.cert \ + --certificate-file stake-delegation.cert \ + --out-file tx.raw + +cardano-cli latest transaction sign \ + --tx-body-file tx.raw \ + --signing-key-file payment.skey \ + --signing-key-file cold.skey \ + --signing-key-file stake.skey \ + --testnet-magic 2 \ + --out-file tx.signed + +cardano-cli latest transaction submit \ + --testnet-magic $TESTNET_MAGIC \ + --tx-file tx.signed diff --git a/templates/hetzner/3.sh b/templates/hetzner/3.sh new file mode 100755 index 0000000..93eaa50 --- /dev/null +++ b/templates/hetzner/3.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -xe + +source vars.sh + +cardano-cli node issue-op-cert --kes-verification-key-file tmp/kes.vkey \ + --cold-signing-key-file tmp/cold.skey \ + --operational-certificate-issue-counter-file tmp/opcert.counter \ + --kes-period $1 \ + --out-file tmp/opcert.cert diff --git a/templates/hetzner/README.md b/templates/hetzner/README.md new file mode 100644 index 0000000..77aa906 --- /dev/null +++ b/templates/hetzner/README.md @@ -0,0 +1,11 @@ +# SPO-Anywhere on Hetzner Cloud + +This Nix flake template installs a Stake Pool on Hetzner cloud using `spo-anywhere`. + +## Prerequisites + +To get started create an Hetzner cloud machine (tested with Ubuntu) and make sure you are able to connect as `root` with ssh. + +You also need to generate a set of stake pool keys, you can follow our documentation section on [generating keys](https://mlabs-haskell.github.io/spo-anywhere/usage/generate-keys/). + +https://mithril.network/explorer/?aggregator=https%3A%2F%2Faggregator.pre-release-preview.api.mithril.network%2Faggregator diff --git a/templates/hetzner/configuration.nix b/templates/hetzner/configuration.nix new file mode 100644 index 0000000..50116fa --- /dev/null +++ b/templates/hetzner/configuration.nix @@ -0,0 +1,24 @@ +{ + networking.hostName = "spo-node-hetzner"; + + system.stateVersion = "24.11"; + + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCzCmDCtlGscpesHuoiruVWD2IjYEFtaIl9Y2JZGiOAyf3V17KPx0MikcknfmxSHi399SxppiaXQHxo/1wjGxXkXNTTv6h1fBuqwhJE6C8+ZSV+gal81vEnXX+/9w2FQqtVgnG2/mO7oJ0e3FY+6kFpOsGEhYexoGt/UxIpAZoqIN+CWNhJIASUkneaZWtgwiL8Afb59kJQ2E7WbBu+PjYZ/s5lhPobhlkz6s8rkhItvYdiSHT0DPDKvp1oEbxsxd4E4cjJFbahyS8b089NJd9gF5gs0b74H/2lUUymnl63cV37Mp4iXB4rtE69MbjqsGEBKTPumLualmc8pOGBHqWIdhAqGdZQeBajcb6VK0E3hcU0wBB+GJgm7KUzlAHGdC3azY0KlHMrLaZN0pBrgCVR6zBNWtZz2B2qMBZ8Cw+K4vut8GuspdXZscID10U578GxQvJAB9CdxNUtrzSmKX2UtZPB1udWjjIAlejzba4MG73uXgQEdv0NcuHNwaLuCWxTUT5QQF18IwlJ23Mg8aPK8ojUW5A+kGHAu9wtgZVcX1nS5cmYKSgLzcP1LA1l9fTJ1vqBSuy38GTdUzfzz7AbnkRfGPj2ALDgyx17Rc5ommjc1k0gFoeIqiLaxEs5FzDcRyo7YvZXPsGeIqNCYwQWw3+U+yUEJby8bxGb2d/6YQ==" + ]; + + spo-anywhere = { + node = { + enable = true; + block-producer-key-path = "/var/lib/spo"; + }; + install-script = { + enable = true; + target = "root@188.245.227.87"; + }; + }; + + services.cardano-node = { + environment = "preview"; + }; +} diff --git a/templates/hetzner/disko.nix b/templates/hetzner/disko.nix new file mode 100644 index 0000000..384b7a6 --- /dev/null +++ b/templates/hetzner/disko.nix @@ -0,0 +1,40 @@ +{ + inputs = { + # spo-anywhere.url = "github:mlabs-haskell/spo-anywhere/aciceri/hetzner-template"; # TODO go back to `main` once merged + spo-anywhere.url = "../.."; + srvos.url = "github:nix-community/srvos"; + nixpkgs.follows = "srvos/nixpkgs"; + disko.follows = "spo-anywhere/disko"; + }; + outputs = inputs @ { + nixpkgs, + flake-parts, + spo-anywhere, + srvos, + disko, + ... + }: + flake-parts.lib.mkFlake { + inherit inputs; + } ({config, ...}: { + systems = [ + "x86_64-linux" + ]; + flake.nixosConfigurations.spo-node-hetzner = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + spo-anywhere.nixosModules.default + srvos.nixosModules.server + srvos.nixosModules.hardware-hetzner-cloud + disko.nixosModules.disko + ./configuration.nix + ./disko.nix + ]; + }; + perSystem = {...}: { + packages = { + install = config.flake.nixosConfigurations.spo-node-hetzner.config.system.build.spoInstallScript; + }; + }; + }); +} diff --git a/templates/hetzner/flake.nix b/templates/hetzner/flake.nix new file mode 100644 index 0000000..384b7a6 --- /dev/null +++ b/templates/hetzner/flake.nix @@ -0,0 +1,40 @@ +{ + inputs = { + # spo-anywhere.url = "github:mlabs-haskell/spo-anywhere/aciceri/hetzner-template"; # TODO go back to `main` once merged + spo-anywhere.url = "../.."; + srvos.url = "github:nix-community/srvos"; + nixpkgs.follows = "srvos/nixpkgs"; + disko.follows = "spo-anywhere/disko"; + }; + outputs = inputs @ { + nixpkgs, + flake-parts, + spo-anywhere, + srvos, + disko, + ... + }: + flake-parts.lib.mkFlake { + inherit inputs; + } ({config, ...}: { + systems = [ + "x86_64-linux" + ]; + flake.nixosConfigurations.spo-node-hetzner = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + spo-anywhere.nixosModules.default + srvos.nixosModules.server + srvos.nixosModules.hardware-hetzner-cloud + disko.nixosModules.disko + ./configuration.nix + ./disko.nix + ]; + }; + perSystem = {...}: { + packages = { + install = config.flake.nixosConfigurations.spo-node-hetzner.config.system.build.spoInstallScript; + }; + }; + }); +} diff --git a/templates/hetzner/pool-metadata.json b/templates/hetzner/pool-metadata.json new file mode 100644 index 0000000..5c3abc3 --- /dev/null +++ b/templates/hetzner/pool-metadata.json @@ -0,0 +1,6 @@ +{ + "name": "Test", + "description": "Test", + "ticker": "TEST", + "homepage": "https://mlabs-haskell.github.io/spo-anywhere" +} diff --git a/templates/hetzner/topology.json b/templates/hetzner/topology.json new file mode 100644 index 0000000..b310594 --- /dev/null +++ b/templates/hetzner/topology.json @@ -0,0 +1,23 @@ +{ + "localRoots":[ + { + "accessPoints":[ + { + "address":"preview-node.world.dev.cardano.org", + "port":30002 + } + ], + "advertise":false, + "valency":1 + } + ], + "publicRoots":[ + { + "accessPoints":[ + + ], + "advertise":false + } + ], + "useLedgerAfterSlot":-1 +} diff --git a/templates/hetzner/vars.sh b/templates/hetzner/vars.sh new file mode 100644 index 0000000..35c3038 --- /dev/null +++ b/templates/hetzner/vars.sh @@ -0,0 +1,21 @@ +# Pledge amount in Lovelace +PLEDGE=1000000 +# Pool cost per-epoch in Lovelace +COST=170000000 +# Pool cost per epoch in percentage +MARGIN=0.1 +# Preview network +TESTNET_MAGIC=2 +# Metadata +METADATA_FILE=pool-metadata.json +echo '{ + "name": "Test", + "description": "Test", + "ticker": "TEST", + "homepage": "https://mlabs-haskell.github.io/spo-anywhere" +}' > $METADATA_FILE +METADATA_HASH=`cardano-cli latest stake-pool metadata-hash --pool-metadata-file pool-metadata.json` +RELAY_IPV4="87.227.245.188" +RELAY_HOST="static.87.227.245.188.clients.your-server.de" +RELAY_PORT=3000 +STAKE_DEPOSIT_AMOUNT=2000000