mirror of
https://cgit.krebsco.de/krops
synced 2024-11-23 03:29:48 +01:00
Merge pull request #35 from erikarvstedt/fix-ssh-port
target: use default port from SSH config
This commit is contained in:
commit
13ae434b14
6 changed files with 78 additions and 55 deletions
14
README.md
14
README.md
|
@ -6,7 +6,7 @@ krops is a lightweight toolkit to deploy NixOS systems, remotely or locally.
|
||||||
## Some Features
|
## Some Features
|
||||||
|
|
||||||
- store your secrets in [password store](https://www.passwordstore.org/)
|
- store your secrets in [password store](https://www.passwordstore.org/)
|
||||||
- build your system remotely
|
- build your systems remotely
|
||||||
- minimal overhead (it's basically just `nixos-rebuild switch`!)
|
- minimal overhead (it's basically just `nixos-rebuild switch`!)
|
||||||
- run from custom nixpkgs branch/checkout/fork
|
- run from custom nixpkgs branch/checkout/fork
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ Create a file named `krops.nix` (name doesn't matter) with following content:
|
||||||
let
|
let
|
||||||
krops = (import <nixpkgs> {}).fetchgit {
|
krops = (import <nixpkgs> {}).fetchgit {
|
||||||
url = https://cgit.krebsco.de/krops/;
|
url = https://cgit.krebsco.de/krops/;
|
||||||
rev = "v1.17.0";
|
rev = "v1.25.0";
|
||||||
sha256 = "150jlz0hlb3ngf9a1c9xgcwzz1zz8v2lfgnzw08l3ajlaaai8smd";
|
sha256 = "07mg3iaqjf1w49vmwfchi7b1w55bh7rvsbgicp2m47gnj9alwdb6";
|
||||||
};
|
};
|
||||||
|
|
||||||
lib = import "${krops}/lib";
|
lib = import "${krops}/lib";
|
||||||
|
@ -185,6 +185,10 @@ pkgs.krops.writeCommand "deploy-with-swap" {
|
||||||
|
|
||||||
[see `writeDeploy`](#writeDeploy)
|
[see `writeDeploy`](#writeDeploy)
|
||||||
|
|
||||||
|
### `allocateTTY` (optional, defaults to false)
|
||||||
|
|
||||||
|
whether the ssh session should do a pseudo-terminal allocation.
|
||||||
|
sets `-t` on the ssh command.
|
||||||
|
|
||||||
## Source Types
|
## Source Types
|
||||||
|
|
||||||
|
@ -206,13 +210,15 @@ using [`rsync`](https://rsync.samba.org/).
|
||||||
Supported attributes:
|
Supported attributes:
|
||||||
|
|
||||||
* `path` -
|
* `path` -
|
||||||
absolute path to files that should by transfered
|
absolute path to files that should by transferred.
|
||||||
|
|
||||||
* `useChecksum` (optional) -
|
* `useChecksum` (optional) -
|
||||||
boolean that controls whether file contents should be checked to decide
|
boolean that controls whether file contents should be checked to decide
|
||||||
whether a file has changed. This is useful when `path` points at files
|
whether a file has changed. This is useful when `path` points at files
|
||||||
with mangled timestamps, e.g. the Nix store.
|
with mangled timestamps, e.g. the Nix store.
|
||||||
|
|
||||||
|
The default value is `true` if `path` is a derivation, and `false` otherwise.
|
||||||
|
|
||||||
* `filters` (optional)
|
* `filters` (optional)
|
||||||
List of filters that should be passed to [`rsync`](https://rsync.samba.org/).
|
List of filters that should be passed to [`rsync`](https://rsync.samba.org/).
|
||||||
Filters are specified as attribute sets with the attributes `type` and
|
Filters are specified as attribute sets with the attributes `type` and
|
||||||
|
|
4
ci.nix
4
ci.nix
|
@ -5,7 +5,7 @@ let
|
||||||
pkgs = import "${krops}/pkgs" {};
|
pkgs = import "${krops}/pkgs" {};
|
||||||
|
|
||||||
source = lib.evalSource [{
|
source = lib.evalSource [{
|
||||||
nixos-config.file = toString (pkgs.writeText "nixos-config" ''
|
nixos-config.file = pkgs.writeText "nixos-config" ''
|
||||||
{ pkgs, ... }: {
|
{ pkgs, ... }: {
|
||||||
|
|
||||||
fileSystems."/" = { device = "/dev/sda1"; };
|
fileSystems."/" = { device = "/dev/sda1"; };
|
||||||
|
@ -13,7 +13,7 @@ let
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
environment.systemPackages = [ pkgs.git ];
|
environment.systemPackages = [ pkgs.git ];
|
||||||
}
|
}
|
||||||
'');
|
'';
|
||||||
nixpkgs.symlink = toString <nixpkgs>;
|
nixpkgs.symlink = toString <nixpkgs>;
|
||||||
}];
|
}];
|
||||||
in {
|
in {
|
||||||
|
|
|
@ -57,9 +57,9 @@ let {
|
||||||
elemAt' = xs: i: if lib.length xs > i then lib.elemAt xs i else null;
|
elemAt' = xs: i: if lib.length xs > i then lib.elemAt xs i else null;
|
||||||
filterNull = lib.filterAttrs (n: v: v != null);
|
filterNull = lib.filterAttrs (n: v: v != null);
|
||||||
in {
|
in {
|
||||||
user = lib.getEnv "LOGNAME";
|
user = lib.maybeEnv "LOGNAME" null;
|
||||||
host = lib.maybeEnv "HOSTNAME" (lib.maybeHostName "localhost");
|
host = lib.maybeEnv "HOSTNAME" (lib.maybeHostName "localhost");
|
||||||
port = "22";
|
port = null;
|
||||||
path = "/var/src";
|
path = "/var/src";
|
||||||
sudo = false;
|
sudo = false;
|
||||||
extraOptions = [];
|
extraOptions = [];
|
||||||
|
@ -70,6 +70,10 @@ let {
|
||||||
path = elemAt' parse 6;
|
path = elemAt' parse 6;
|
||||||
} else s);
|
} else s);
|
||||||
|
|
||||||
|
mkUserPortSSHOpts = target:
|
||||||
|
(lib.optionals (target.user != null) ["-l" target.user]) ++
|
||||||
|
(lib.optionals (target.port != null) ["-p" target.port]);
|
||||||
|
|
||||||
shell = let
|
shell = let
|
||||||
isSafeChar = lib.testString "[-+./0-9:=A-Z_a-z]";
|
isSafeChar = lib.testString "[-+./0-9:=A-Z_a-z]";
|
||||||
quoteChar = c:
|
quoteChar = c:
|
||||||
|
|
|
@ -21,11 +21,15 @@
|
||||||
};
|
};
|
||||||
file = lib.mkOption {
|
file = lib.mkOption {
|
||||||
apply = x:
|
apply = x:
|
||||||
if lib.types.absolute-pathname.check x
|
if lib.types.absolute-pathname.check x || lib.types.package.check x
|
||||||
then { path = x; }
|
then { path = x; }
|
||||||
else x;
|
else x;
|
||||||
default = null;
|
default = null;
|
||||||
type = lib.types.nullOr (lib.types.either lib.types.absolute-pathname source-types.file);
|
type = lib.types.nullOr (lib.types.oneOf [
|
||||||
|
lib.types.absolute-pathname
|
||||||
|
lib.types.package
|
||||||
|
source-types.file
|
||||||
|
]);
|
||||||
};
|
};
|
||||||
git = lib.mkOption {
|
git = lib.mkOption {
|
||||||
default = null;
|
default = null;
|
||||||
|
|
|
@ -4,20 +4,14 @@ in
|
||||||
|
|
||||||
{ nix, openssh, populate, writers }: rec {
|
{ nix, openssh, populate, writers }: rec {
|
||||||
|
|
||||||
build = target:
|
|
||||||
runShell target (lib.concatStringsSep " " [
|
|
||||||
"nix build"
|
|
||||||
"-I ${lib.escapeShellArg target.path}"
|
|
||||||
"--no-link -f '<nixpkgs/nixos>'"
|
|
||||||
"config.system.build.toplevel"
|
|
||||||
]);
|
|
||||||
|
|
||||||
rebuild = args: target:
|
rebuild = args: target:
|
||||||
runShell target "nixos-rebuild -I ${lib.escapeShellArg target.path} ${
|
runShell target {} "nixos-rebuild -I ${lib.escapeShellArg target.path} ${
|
||||||
lib.concatMapStringsSep " " lib.escapeShellArg args
|
lib.concatMapStringsSep " " lib.escapeShellArg args
|
||||||
}";
|
}";
|
||||||
|
|
||||||
runShell = target: command:
|
runShell = target: {
|
||||||
|
allocateTTY ? false
|
||||||
|
}: command:
|
||||||
let
|
let
|
||||||
command' = if target.sudo then "sudo ${command}" else command;
|
command' = if target.sudo then "sudo ${command}" else command;
|
||||||
in
|
in
|
||||||
|
@ -26,9 +20,8 @@ in
|
||||||
else
|
else
|
||||||
writers.writeDash "krops.${target.host}.${lib.firstWord command}" ''
|
writers.writeDash "krops.${target.host}.${lib.firstWord command}" ''
|
||||||
exec ${openssh}/bin/ssh ${lib.escapeShellArgs (lib.flatten [
|
exec ${openssh}/bin/ssh ${lib.escapeShellArgs (lib.flatten [
|
||||||
(lib.optionals (target.user != "") ["-l" target.user])
|
(lib.mkUserPortSSHOpts target)
|
||||||
"-p" target.port
|
(if allocateTTY then "-t" else "-T")
|
||||||
"-T"
|
|
||||||
target.extraOptions
|
target.extraOptions
|
||||||
target.host
|
target.host
|
||||||
command'])}
|
command'])}
|
||||||
|
@ -38,6 +31,7 @@ in
|
||||||
command ? (targetPath: "echo ${targetPath}"),
|
command ? (targetPath: "echo ${targetPath}"),
|
||||||
backup ? false,
|
backup ? false,
|
||||||
force ? false,
|
force ? false,
|
||||||
|
allocateTTY ? false,
|
||||||
source,
|
source,
|
||||||
target
|
target
|
||||||
}: let
|
}: let
|
||||||
|
@ -46,14 +40,14 @@ in
|
||||||
writers.writeDash name ''
|
writers.writeDash name ''
|
||||||
set -efu
|
set -efu
|
||||||
${populate { inherit backup force source; target = target'; }}
|
${populate { inherit backup force source; target = target'; }}
|
||||||
${runShell target' (command target'.path)}
|
${runShell target' { inherit allocateTTY; } (command target'.path)}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
writeDeploy = name: {
|
writeDeploy = name: {
|
||||||
backup ? false,
|
backup ? false,
|
||||||
buildTarget ? null,
|
buildTarget ? null,
|
||||||
crossDeploy ? false,
|
crossDeploy ? false,
|
||||||
fast ? false,
|
fast ? null,
|
||||||
force ? false,
|
force ? false,
|
||||||
source,
|
source,
|
||||||
target
|
target
|
||||||
|
@ -64,26 +58,24 @@ in
|
||||||
else lib.mkTarget buildTarget;
|
else lib.mkTarget buildTarget;
|
||||||
target' = lib.mkTarget target;
|
target' = lib.mkTarget target;
|
||||||
in
|
in
|
||||||
writers.writeDash name ''
|
lib.traceIf (fast != null) "writeDeploy: it's now always fast, setting the `fast` attribute is deprecated and will be removed in future" (
|
||||||
set -efu
|
writers.writeDash name ''
|
||||||
${lib.optionalString (buildTarget' != target')
|
set -efu
|
||||||
(populate { inherit backup force source; target = buildTarget'; })}
|
${lib.optionalString (buildTarget' != target')
|
||||||
${populate { inherit backup force source; target = target'; }}
|
(populate { inherit backup force source; target = buildTarget'; })}
|
||||||
${lib.optionalString (! fast) ''
|
${populate { inherit backup force source; target = target'; }}
|
||||||
${rebuild ["dry-build"] buildTarget'}
|
${rebuild ([
|
||||||
${build buildTarget'}
|
"switch"
|
||||||
''}
|
] ++ lib.optionals crossDeploy [
|
||||||
${rebuild ([
|
"--no-build-nix"
|
||||||
"switch"
|
] ++ lib.optionals (buildTarget' != target') [
|
||||||
] ++ lib.optionals crossDeploy [
|
"--build-host" "${buildTarget'.user}@${buildTarget'.host}"
|
||||||
"--no-build-nix"
|
"--target-host" "${target'.user}@${target'.host}"
|
||||||
] ++ lib.optionals (buildTarget' != target') [
|
] ++ lib.optionals target'.sudo [
|
||||||
"--build-host" "${buildTarget'.user}@${buildTarget'.host}"
|
"--use-remote-sudo"
|
||||||
"--target-host" "${target'.user}@${target'.host}"
|
]) buildTarget'}
|
||||||
] ++ lib.optionals target'.sudo [
|
''
|
||||||
"--use-remote-sudo"
|
);
|
||||||
]) buildTarget'}
|
|
||||||
'';
|
|
||||||
|
|
||||||
writeTest = name: {
|
writeTest = name: {
|
||||||
backup ? false,
|
backup ? false,
|
||||||
|
|
|
@ -45,10 +45,21 @@ let
|
||||||
'';
|
'';
|
||||||
|
|
||||||
pop.file = target: source: let
|
pop.file = target: source: let
|
||||||
configAttrs = ["useChecksum" "exclude" "filters" "deleteExcluded"];
|
config = rsyncDefaultConfig // derivedConfig // sourceConfig;
|
||||||
config = filterAttrs (name: _: elem name configAttrs) source;
|
derivedConfig = {
|
||||||
|
useChecksum =
|
||||||
|
if isStorePath source.path
|
||||||
|
then true
|
||||||
|
else rsyncDefaultConfig.useChecksum;
|
||||||
|
};
|
||||||
|
sourceConfig =
|
||||||
|
filterAttrs (name: _: elem name (attrNames rsyncDefaultConfig)) source;
|
||||||
|
sourcePath =
|
||||||
|
if isStorePath source.path
|
||||||
|
then quote (toString source.path)
|
||||||
|
else quote source.path;
|
||||||
in
|
in
|
||||||
rsync' target config (quote source.path);
|
rsync' target config sourcePath;
|
||||||
|
|
||||||
pop.git = target: source: runShell target /* sh */ ''
|
pop.git = target: source: runShell target /* sh */ ''
|
||||||
set -efu
|
set -efu
|
||||||
|
@ -144,7 +155,7 @@ let
|
||||||
echo "$local_pass_info" > "$tmp_dir"/.pass_info
|
echo "$local_pass_info" > "$tmp_dir"/.pass_info
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${rsync' target {} /* sh */ "$tmp_dir"}
|
${rsync' target rsyncDefaultConfig /* sh */ "$tmp_dir"}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
pop.pipe = target: source: /* sh */ ''
|
pop.pipe = target: source: /* sh */ ''
|
||||||
|
@ -172,17 +183,17 @@ let
|
||||||
source_path=$source_path/
|
source_path=$source_path/
|
||||||
fi
|
fi
|
||||||
${rsync}/bin/rsync \
|
${rsync}/bin/rsync \
|
||||||
${optionalString (config.useChecksum or false) /* sh */ "--checksum"} \
|
${optionalString config.useChecksum /* sh */ "--checksum"} \
|
||||||
${optionalString target.sudo /* sh */ "--rsync-path=\"sudo rsync\""} \
|
${optionalString target.sudo /* sh */ "--rsync-path=\"sudo rsync\""} \
|
||||||
${concatMapStringsSep " "
|
${concatMapStringsSep " "
|
||||||
(pattern: /* sh */ "--exclude ${quote pattern}")
|
(pattern: /* sh */ "--exclude ${quote pattern}")
|
||||||
(config.exclude or [])} \
|
config.exclude} \
|
||||||
${concatMapStringsSep " "
|
${concatMapStringsSep " "
|
||||||
(filter: /* sh */ "--${filter.type} ${quote filter.pattern}")
|
(filter: /* sh */ "--${filter.type} ${quote filter.pattern}")
|
||||||
(config.filters or [])} \
|
config.filters} \
|
||||||
-e ${quote (ssh' target)} \
|
-e ${quote (ssh' target)} \
|
||||||
-vFrlptD \
|
-vFrlptD \
|
||||||
${optionalString (config.deleteExcluded or true) /* sh */ "--delete-excluded"} \
|
${optionalString config.deleteExcluded /* sh */ "--delete-excluded"} \
|
||||||
"$source_path" \
|
"$source_path" \
|
||||||
${quote (
|
${quote (
|
||||||
optionalString (!isLocalTarget target) (
|
optionalString (!isLocalTarget target) (
|
||||||
|
@ -194,6 +205,13 @@ let
|
||||||
>&2
|
>&2
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
rsyncDefaultConfig = {
|
||||||
|
useChecksum = false;
|
||||||
|
exclude = [];
|
||||||
|
filters = [];
|
||||||
|
deleteExcluded = true;
|
||||||
|
};
|
||||||
|
|
||||||
runShell = target: command:
|
runShell = target: command:
|
||||||
if isLocalTarget target
|
if isLocalTarget target
|
||||||
then command
|
then command
|
||||||
|
@ -206,8 +224,7 @@ let
|
||||||
|
|
||||||
ssh' = target: concatMapStringsSep " " quote (flatten [
|
ssh' = target: concatMapStringsSep " " quote (flatten [
|
||||||
"${openssh}/bin/ssh"
|
"${openssh}/bin/ssh"
|
||||||
(optionals (target.user != "") ["-l" target.user])
|
(mkUserPortSSHOpts target)
|
||||||
"-p" target.port
|
|
||||||
"-T"
|
"-T"
|
||||||
target.extraOptions
|
target.extraOptions
|
||||||
]);
|
]);
|
||||||
|
|
Loading…
Reference in a new issue