From 518f7f5b4f1db83cab61941ab8887b0df76ce8d8 Mon Sep 17 00:00:00 2001 From: notgne2 Date: Thu, 8 Oct 2020 18:13:26 -0700 Subject: Update documentation --- README.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++---- interface/README.md | 4 +-- src/main.rs | 14 --------- src/utils/mod.rs | 25 --------------- 4 files changed, 84 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 15877d1..e622250 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,93 @@ SPDX-License-Identifier: MPL-2.0 # deploy-rs -A Simple multi-profile Nix-flake deploy tool. +A Simple, multi-profile Nix-flake deploy tool. -**This is very early development software, you should expect to find issues** +**This is very early development software, you should expect to find issues, and things will change** ## Usage +Basic usage: `deploy [options] `. -- `nix run github:serokell/deploy-rs your-flake#node.profile` -- `nix run github:serokell/deploy-rs your-flake#node` +The given flake can be just a source `my-flake`, specify the node to deploy `my-flake#my-node`, or specify a profile too `my-flake#my-node.my-profile`. + +You can try out this tool easily with `nix run`: - `nix run github:serokell/deploy-rs your-flake` +If your require a signing key to push closures to your server, specify the path to it in the `LOCAL_KEY` environment variable. + +Check out `deploy --help` for CLI flags! Remember to check there before making one-time changes to things like hostnames. + ## API -Example Nix expressions/configurations are in the [examples folder](./examples). +### Profile + +This is the core of how `deploy-rs` was designed, any number of these can run on a node, as any user (see further down for specifying user information). If you want to mimick the behaviour of traditional tools like NixOps or Morph, try just defining one `profile` called `system`, as root, containing a nixosSystem. + +```nix +{ + # ...generic options... (see below) + + # The command to bootstrap your profile, this is optional + bootstrap = "mkdir xyz"; + + # A derivation containing your required software, and a script to activate it in `${path}/activate` + # For ease of use, `deploy-rs` provides a function to easy all this required activation script to any derivation + path = deploy-rs.lib.x86_64-linux.setActivate pkgs.hello "./bin/hello"; +} +``` + +### Node + +This defines a single node/server, and the profiles you intend it to run. + +```nix +{ + # ...generic options... (see below) + + # The hostname of your server, don't worry, this can be overridden at runtime if needed + hostname = "my.server.gov"; + + # An optional list containing the order you want profiles to be deployed. + profilesOrder = [ "something" "system" ]; + + profiles = { + system = {}; # Definition shown above + something = {}; # Definition shown above + }; +} +``` + +### Deploy + +This is the top level attribute containing all of the options for this tool + +```nix +{ + # ...generic options... (see below) + + nodes = { + my-node = {}; # Definition shown above + another-node = {}; # Definition shown above + }; +} +``` + +#### Generic options + +This is a set of options that can be put in any of the above definitions, with the priority being `profile > node > deploy` + +```nix +{ + sshUser = "admin"; # This is the user that deploy-rs will use when connecting + user = "root"; # This is the user that the profile will be deployed to (will use sudo if not the same as above) + sshOpts = [ "-p" "2121" ]; # These are arguments that will be passed to SSH + fastConnection = false; # Fast connection to the node. If this is true, copy the whole closure instead of letting the node substitute + autoRollback = true; # If the previous profile should be re-activated if activation fails +} +``` + +A stronger definition of the schema is in the [interface directory](./interface), and full working examples Nix expressions/configurations are in the [examples folder](./examples). ## Idea @@ -30,8 +103,11 @@ This type of design (as opposed to more traditional tools like NixOps or morph) ## Things to work on - ~~Ordered profiles~~ -- Automatic rollbacks if one profile on node failed to deploy (partially implemented) +- ~~Automatic rollbacks~~ - UI (?) +- automatic kexec lustration of servers (maybe) +- Remote health checks +- Rollback on reconnection failure (technically, rollback if not reconnected to) ## About Serokell diff --git a/interface/README.md b/interface/README.md index c6b52bd..bfca01e 100644 --- a/interface/README.md +++ b/interface/README.md @@ -7,6 +7,7 @@ deploy ├── │   ├── │   ├── hostname + │   ├── profilesOrder │   └── profiles │   ├── │   │   ├── @@ -14,7 +15,6 @@ deploy │   │   └── path │   └── ... └── ... - ``` Where `` are all optional and can be one or multiple of: @@ -29,4 +29,4 @@ A formal definition for the structure can be found in [the JSON schema](./deploy For every profile of every node, arguments are merged with `` taking precedence over `` and `` taking precedence over top-level. -Values can be overridden for all the profiles deployed by setting environment variables with the same names as the profile, for example `sshUser=foobar nix run github:serokell/deploy .` will connect to all nodes as `foobar@.hostname`. +Certain read values can be overridden by supplying flags to the deploy binary, for example `deploy --auto-rollback true .` will enable automatic rollback for all nodes being deployed to, regardless of settings. \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 04d7868..b28a520 100644 --- a/src/main.rs +++ b/src/main.rs @@ -349,20 +349,6 @@ async fn main() -> Result<(), Box> { hostname: opts.hostname, }; - match (cmd_overrides.purity(), deploy_flake.node, deploy_flake.profile) { - (utils::OverridePurity::ErrorProfile, _, None) => good_panic!( - "You have specified an override not suitible for deploying to multiple profiles, please specify your target profile explicitly" - ), - (utils::OverridePurity::Error, None, _) => good_panic!( - "You have specified an override not suitible for deploying to multiple nodes, please specify your target node explicitly" - ), - - (utils::OverridePurity::Warn, None, _) => warn!( - "Certain overrides you have provided might be dangerous when used on multiple nodes or profiles, be cautious" - ), - _ => (), - }; - let supports_flakes = test_flake_support().await?; let data = diff --git a/src/utils/mod.rs b/src/utils/mod.rs index bfdbc5e..97e4550 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -28,31 +28,6 @@ pub struct CmdOverrides { pub hostname: Option, } -pub enum OverridePurity { - ErrorProfile, - Error, - Warn, - Pure, -} - -impl CmdOverrides { - pub fn purity(&self) -> OverridePurity { - if self.profile_user.is_some() { - return OverridePurity::ErrorProfile; - } - - if self.hostname.is_some() || self.ssh_user.is_some() { - return OverridePurity::Error; - } - - if self.ssh_opts.is_some() || self.fast_connection.is_some() { - return OverridePurity::Warn; - } - - OverridePurity::Pure - } -} - #[derive(PartialEq, Debug)] pub struct DeployFlake<'a> { pub repo: &'a str, -- cgit v1.2.3 From 219d55e99e792a093c12dbc045bed88a4bfe1916 Mon Sep 17 00:00:00 2001 From: notgne2 Date: Thu, 8 Oct 2020 20:01:01 -0700 Subject: Minor flake and documentation fixes --- README.md | 22 +++++++++++----------- default.nix | 13 +++++++++++++ flake.lock | 37 +++++++++++++++++++++---------------- flake.nix | 50 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 default.nix diff --git a/README.md b/README.md index e622250..2710183 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,12 @@ A Simple, multi-profile Nix-flake deploy tool. Basic usage: `deploy [options] `. -The given flake can be just a source `my-flake`, specify the node to deploy `my-flake#my-node`, or specify a profile too `my-flake#my-node.my-profile`. +The given flake can be just a source `my-flake`, or optionally specify the node to deploy `my-flake#my-node`, or specify a profile too `my-flake#my-node.my-profile`. You can try out this tool easily with `nix run`: - `nix run github:serokell/deploy-rs your-flake` -If your require a signing key to push closures to your server, specify the path to it in the `LOCAL_KEY` environment variable. +If you require a signing key to push closures to your server, specify the path to it in the `LOCAL_KEY` environment variable. Check out `deploy --help` for CLI flags! Remember to check there before making one-time changes to things like hostnames. @@ -27,18 +27,18 @@ Check out `deploy --help` for CLI flags! Remember to check there before making o ### Profile -This is the core of how `deploy-rs` was designed, any number of these can run on a node, as any user (see further down for specifying user information). If you want to mimick the behaviour of traditional tools like NixOps or Morph, try just defining one `profile` called `system`, as root, containing a nixosSystem. +This is the core of how `deploy-rs` was designed, any number of these can run on a node, as any user (see further down for specifying user information). If you want to mimick the behaviour of traditional tools like NixOps or Morph, try just defining one `profile` called `system`, as root, containing a nixosSystem, and you can even similarly use [home-manager](https://github.com/nix-community/home-manager) on any non-privileged user. ```nix { - # ...generic options... (see below) - # The command to bootstrap your profile, this is optional bootstrap = "mkdir xyz"; # A derivation containing your required software, and a script to activate it in `${path}/activate` # For ease of use, `deploy-rs` provides a function to easy all this required activation script to any derivation path = deploy-rs.lib.x86_64-linux.setActivate pkgs.hello "./bin/hello"; + + # ...generic options... (see lower section) } ``` @@ -48,8 +48,6 @@ This defines a single node/server, and the profiles you intend it to run. ```nix { - # ...generic options... (see below) - # The hostname of your server, don't worry, this can be overridden at runtime if needed hostname = "my.server.gov"; @@ -60,6 +58,8 @@ This defines a single node/server, and the profiles you intend it to run. system = {}; # Definition shown above something = {}; # Definition shown above }; + + # ...generic options... (see lower section) } ``` @@ -69,16 +69,16 @@ This is the top level attribute containing all of the options for this tool ```nix { - # ...generic options... (see below) - nodes = { my-node = {}; # Definition shown above another-node = {}; # Definition shown above }; + + # ...generic options... (see lower section) } ``` -#### Generic options +### Generic options This is a set of options that can be put in any of the above definitions, with the priority being `profile > node > deploy` @@ -96,7 +96,7 @@ A stronger definition of the schema is in the [interface directory](./interface) ## Idea -`deploy-rs` is a simple Rust program that will take a Nix flake and use it to deploy any of your defined profiles to your nodes. This is _strongly_ based off of [serokell/deploy](https://github.com/serokell/deploy), with the intention of eventually replacing it. +`deploy-rs` is a simple Rust program that will take a Nix flake and use it to deploy any of your defined profiles to your nodes. This is _strongly_ based off of [serokell/deploy](https://github.com/serokell/deploy), designed to replace it and expand upon it. This type of design (as opposed to more traditional tools like NixOps or morph) allows for lesser-privileged deployments, and the ability to update different things independently of eachother. diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..873ece4 --- /dev/null +++ b/default.nix @@ -0,0 +1,13 @@ +(import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { + src = ./.; + }).defaultNix diff --git a/flake.lock b/flake.lock index 0a41d47..cbcd1bc 100644 --- a/flake.lock +++ b/flake.lock @@ -1,8 +1,26 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1600853454, + "narHash": "sha256-EgsgbcJNZ9AQLVhjhfiegGjLbO+StBY9hfKsCwc8Hw8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "94cf59784c73ecec461eaa291918eff0bfb538ac", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "naersk": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { "lastModified": 1597138680, @@ -20,20 +38,6 @@ } }, "nixpkgs": { - "locked": { - "lastModified": 1601091160, - "narHash": "sha256-26UI9LGjRO8Sv253zJZkoapP260QkJPQ2+vRyC1i+kI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "2768436826543af2b1540e4fe6b5afa15850e155", - "type": "github" - }, - "original": { - "id": "nixpkgs", - "type": "indirect" - } - }, - "nixpkgs_2": { "locked": { "lastModified": 1600387253, "narHash": "sha256-WtdpHuiunPF9QMlcXrWJkESuIjSSjP9WMOKvYQS/D7M=", @@ -51,8 +55,9 @@ }, "root": { "inputs": { + "flake-compat": "flake-compat", "naersk": "naersk", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "utils": "utils" } }, diff --git a/flake.nix b/flake.nix index 9cfaa49..81603e4 100644 --- a/flake.nix +++ b/flake.nix @@ -3,43 +3,53 @@ # SPDX-License-Identifier: MPL-2.0 { + description = "A Simple multi-profile Nix-flake deploy tool."; + inputs = { - naersk.url = "github:nmattia/naersk/master"; nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + naersk = { + url = "github:nmattia/naersk/master"; + inputs.nixpkgs.follows = "nixpkgs"; + }; utils.url = "github:numtide/flake-utils"; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; }; - outputs = { self, nixpkgs, utils, naersk }: + outputs = { self, nixpkgs, utils, naersk, ... }: utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; naersk-lib = pkgs.callPackage naersk { }; - setActivate = base: activate: pkgs.symlinkJoin { - name = ("activatable-" + base.name); - paths = [ - base - (pkgs.writeTextFile { - name = base.name + "-activate-path"; - text = '' - #!${pkgs.runtimeShell} - ${activate} - ''; - executable = true; - destination = "/activate"; - }) - ]; - }; in { - defaultPackage = naersk-lib.buildPackage ./.; + defaultPackage = self.packages."${system}".deploy-rs; + packages.deploy-rs = naersk-lib.buildPackage ./.; - defaultApp = { + defaultApp = self.apps."${system}".deploy-rs; + apps.deploy-rs = { type = "app"; program = "${self.defaultPackage."${system}"}/bin/deploy"; }; lib = { - inherit setActivate; + setActivate = base: activate: pkgs.symlinkJoin { + name = ("activatable-" + base.name); + paths = [ + base + (pkgs.writeTextFile { + name = base.name + "-activate-path"; + text = '' + #!${pkgs.runtimeShell} + ${activate} + ''; + executable = true; + destination = "/activate"; + }) + ]; + }; checkSchema = deploy: pkgs.runCommandNoCC "jsonschema-deploy-system" { } "${pkgs.python3.pkgs.jsonschema}/bin/jsonschema -i ${pkgs.writeText "deploy.json" (builtins.toJSON deploy)} ${./interface/deploy.json} && touch $out"; -- cgit v1.2.3