libstore: allow specifying port for ssh[-ng] stores
This also adds documentation for it in distributed-builds.md as that's possibly the most common use-case for remote ssh stores Support for `std::optional<uint16_t>` in Setting is also added since setting a port is optional. The line `#include "lix/libutil/strings.hh"` fixes that templates instanciations in lix/libutil/config-impl.hh were using string utils without including the header (why are they even there btw) Change-Id: Id806c117c48cdf158d9d1cb1e639b0df31d9bf11
This commit is contained in:
@@ -153,6 +153,9 @@ roberth:
|
||||
display_name: Robert Hensing
|
||||
github: roberth
|
||||
|
||||
seppel3210:
|
||||
github: Seppel3210
|
||||
|
||||
teofilc:
|
||||
forgejo: teofilc
|
||||
github: TeofilC
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
synopsis: 'Allow specifying ports for remote ssh[-ng] stores'
|
||||
issues: []
|
||||
cls: [2432]
|
||||
category: Improvements
|
||||
credits: [seppel3210]
|
||||
---
|
||||
|
||||
You can now specify which port should be used for a remote ssh store (e.g. for remote/distributed builds) through a uri parameter.
|
||||
E.g., when a remote builder `foo` is listening on port `1234` instead of the default, it can be specified like this `ssh://foo?port=1234`.
|
||||
@@ -75,7 +75,9 @@ by spaces. Only the first element is required. To leave a field at its
|
||||
default, set it to `-`.
|
||||
|
||||
1. The URI of the remote store in the format
|
||||
`ssh://[username@]hostname`, e.g. `ssh://nix@mac` or `ssh://mac`.
|
||||
`ssh://[username@]hostname[?port=<port>]`, e.g. `ssh://nix@mac` or `ssh://mac`.
|
||||
If the ssh server is not listening on port 22 (e.g. port 1337 in this case)
|
||||
the URI would be `ssh://nix@mac?port=1337`
|
||||
For backward compatibility, `ssh://` may be omitted. The hostname
|
||||
may be an alias defined in your `~/.ssh/config`.
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "lix/libutil/result.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
#include "lix/libstore/derivations.hh"
|
||||
#include "lix/libutil/config-impl.hh"
|
||||
#include "lix/libutil/abstract-setting-to-json.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -113,6 +115,7 @@ struct LegacySSHStore final : public Store
|
||||
))
|
||||
, master(
|
||||
host,
|
||||
config_.port,
|
||||
config_.sshKey,
|
||||
config_.sshPublicHostKey,
|
||||
// Use SSH master only if using more than 1 connection.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
R"(
|
||||
|
||||
**Store URL format**: `ssh://[username@]hostname`
|
||||
**Store URL format**: `ssh://[username@]hostname[?port=42069]`
|
||||
|
||||
This store type allows limited access to a remote store on another
|
||||
machine via SSH.
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
, host(host)
|
||||
, master(
|
||||
host,
|
||||
config_.port,
|
||||
config_.sshKey,
|
||||
config_.sshPublicHostKey,
|
||||
// Use SSH master only if using more than 1 connection.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
///@file
|
||||
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include <cstdint>
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -9,6 +10,9 @@ struct CommonSSHStoreConfig : virtual StoreConfig
|
||||
{
|
||||
using StoreConfig::StoreConfig;
|
||||
|
||||
const Setting<std::optional<uint16_t>> port{this, std::nullopt, "port",
|
||||
"Port that should be used instead of the default on the remote machine."};
|
||||
|
||||
const Setting<Path> sshKey{this, "", "ssh-key",
|
||||
"Path to the SSH private key used to authenticate to the remote machine."};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
R"(
|
||||
|
||||
**Store URL format**: `ssh-ng://[username@]hostname`
|
||||
**Store URL format**: `ssh-ng://[username@]hostname[?port=42069]`
|
||||
|
||||
Experimental store type that allows full access to a Nix store on a
|
||||
remote machine.
|
||||
|
||||
+4
-1
@@ -8,8 +8,9 @@
|
||||
|
||||
namespace nix {
|
||||
|
||||
SSHMaster::SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD)
|
||||
SSHMaster::SSHMaster(const std::string & host, const std::optional<uint16_t> port, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD)
|
||||
: host(host)
|
||||
, port(port)
|
||||
, fakeSSH(host == "localhost")
|
||||
, keyFile(keyFile)
|
||||
, sshPublicHostKey(sshPublicHostKey)
|
||||
@@ -28,6 +29,8 @@ void SSHMaster::addCommonSSHOpts(Strings & args)
|
||||
{
|
||||
auto state(state_.lock());
|
||||
|
||||
if (port.has_value())
|
||||
args.insert(args.end(), {"-p", std::to_string(*port)});
|
||||
for (auto & i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS").value_or("")))
|
||||
args.push_back(i);
|
||||
if (!keyFile.empty())
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@
|
||||
#include "lix/libutil/file-system.hh"
|
||||
#include "lix/libutil/processes.hh"
|
||||
#include "lix/libutil/sync.hh"
|
||||
#include <cstdint>
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -12,6 +13,7 @@ class SSHMaster
|
||||
private:
|
||||
|
||||
const std::string host;
|
||||
const std::optional<uint16_t> port;
|
||||
bool fakeSSH;
|
||||
const std::string keyFile;
|
||||
const std::string sshPublicHostKey;
|
||||
@@ -33,7 +35,7 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
SSHMaster(const std::string & host, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD = -1);
|
||||
SSHMaster(const std::string & host, const std::optional<uint16_t> port, const std::string & keyFile, const std::string & sshPublicHostKey, bool useMaster, bool compress, int logFD = -1);
|
||||
|
||||
struct Connection
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "lix/libutil/args.hh"
|
||||
#include "lix/libutil/config.hh"
|
||||
#include "lix/libutil/logging.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -123,6 +124,7 @@ void BaseSetting<T>::convertToArg(Args & args, const std::string & category)
|
||||
|
||||
DECLARE_CONFIG_SERIALISER(std::string)
|
||||
DECLARE_CONFIG_SERIALISER(std::optional<std::string>)
|
||||
DECLARE_CONFIG_SERIALISER(std::optional<uint16_t>)
|
||||
DECLARE_CONFIG_SERIALISER(bool)
|
||||
DECLARE_CONFIG_SERIALISER(Strings)
|
||||
DECLARE_CONFIG_SERIALISER(StringSet)
|
||||
|
||||
@@ -270,6 +270,21 @@ template<> std::string BaseSetting<std::optional<std::string>>::to_string() cons
|
||||
return value ? *value : "";
|
||||
}
|
||||
|
||||
template<> std::optional<uint16_t> BaseSetting<std::optional<uint16_t>>::parse(const std::string & str, const ApplyConfigOptions & options) const
|
||||
{
|
||||
if (str == "")
|
||||
return std::nullopt;
|
||||
else if (auto n = string2Int<uint16_t>(str))
|
||||
return n;
|
||||
else
|
||||
throw UsageError("setting '%s' has invalid value '%s'", name, str);
|
||||
}
|
||||
|
||||
template<> std::string BaseSetting<std::optional<uint16_t>>::to_string() const
|
||||
{
|
||||
return value ? std::to_string(*value) : "";
|
||||
}
|
||||
|
||||
template<> bool BaseSetting<bool>::parse(const std::string & str, const ApplyConfigOptions & options) const
|
||||
{
|
||||
if (str == "true" || str == "yes" || str == "1")
|
||||
|
||||
Reference in New Issue
Block a user