1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-29 02:11:15 +02:00

MountedSSHStore: stores on shared filesystems

This commit is contained in:
Matej Urbas 2023-04-15 11:02:41 +01:00 committed by John Ericson
parent 226b0f3956
commit 06b8902562
3 changed files with 164 additions and 1 deletions

View file

@ -3,9 +3,10 @@
#include "local-fs-store.hh"
#include "remote-store.hh"
#include "remote-store-connection.hh"
#include "remote-fs-accessor.hh"
#include "source-accessor.hh"
#include "archive.hh"
#include "worker-protocol.hh"
#include "worker-protocol-impl.hh"
#include "pool.hh"
#include "ssh.hh"
@ -78,6 +79,8 @@ protected:
std::string host;
std::vector<std::string> extraRemoteProgramArgs;
SSHMaster master;
void setOptions(RemoteStore::Connection & conn) override
@ -91,6 +94,121 @@ protected:
};
};
struct MountedSSHStoreConfig : virtual SSHStoreConfig, virtual LocalFSStoreConfig
{
using SSHStoreConfig::SSHStoreConfig;
using LocalFSStoreConfig::LocalFSStoreConfig;
MountedSSHStoreConfig(StringMap params)
: StoreConfig(params)
, RemoteStoreConfig(params)
, CommonSSHStoreConfig(params)
, SSHStoreConfig(params)
, LocalFSStoreConfig(params)
{
}
const std::string name() override { return "Experimental SSH Store with filesytem mounted"; }
std::string doc() override
{
return
#include "mounted-ssh-store.md"
;
}
std::optional<ExperimentalFeature> experimentalFeature() const override
{
return ExperimentalFeature::MountedSSHStore;
}
};
/**
* The mounted ssh store assumes that filesystems on the remote host are
* shared with the local host. This means that the remote nix store is
* available locally and is therefore treated as a local filesystem
* store.
*
* MountedSSHStore is very similar to UDSRemoteStore --- ignoring the
* superficial differnce of SSH vs Unix domain sockets, they both are
* accessing remote stores, and they both assume the store will be
* mounted in the local filesystem.
*
* The difference lies in how they manage GC roots. See addPermRoot
* below for details.
*/
class MountedSSHStore : public virtual MountedSSHStoreConfig, public virtual SSHStore, public virtual LocalFSStore
{
public:
MountedSSHStore(const std::string & scheme, const std::string & host, const Params & params)
: StoreConfig(params)
, RemoteStoreConfig(params)
, CommonSSHStoreConfig(params)
, SSHStoreConfig(params)
, LocalFSStoreConfig(params)
, MountedSSHStoreConfig(params)
, Store(params)
, RemoteStore(params)
, SSHStore(scheme, host, params)
, LocalFSStore(params)
{
extraRemoteProgramArgs = {
"--process-ops",
};
}
static std::set<std::string> uriSchemes()
{
return {"mounted-ssh-ng"};
}
std::string getUri() override
{
return *uriSchemes().begin() + "://" + host;
}
void narFromPath(const StorePath & path, Sink & sink) override
{
return LocalFSStore::narFromPath(path, sink);
}
ref<SourceAccessor> getFSAccessor(bool requireValidPath) override
{
return LocalFSStore::getFSAccessor(requireValidPath);
}
std::optional<std::string> getBuildLogExact(const StorePath & path) override
{
return LocalFSStore::getBuildLogExact(path);
}
/**
* This is the key difference from UDSRemoteStore: UDSRemote store
* has the client create the direct root, and the remote side create
* the indirect root.
*
* We could also do that, but the race conditions (will the remote
* side see the direct root the client made?) seems bigger.
*
* In addition, the remote-side will have a process associated with
* the authenticating user handling the connection (even if there
* is a system-wide daemon or similar). This process can safely make
* the direct and indirect roots without there being such a risk of
* privilege escalation / symlinks in directories owned by the
* originating requester that they cannot delete.
*/
Path addPermRoot(const StorePath & path, const Path & gcRoot) override
{
auto conn(getConnection());
conn->to << WorkerProto::Op::AddPermRoot;
WorkerProto::write(*this, *conn, path);
WorkerProto::write(*this, *conn, gcRoot);
conn.processStderr();
return readString(conn->from);
}
};
ref<RemoteStore::Connection> SSHStore::openConnection()
{
auto conn = make_ref<Connection>();
@ -98,6 +216,8 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
std::string command = remoteProgram + " --stdio";
if (remoteStore.get() != "")
command += " --store " + shellEscape(remoteStore.get());
for (auto & arg : extraRemoteProgramArgs)
command += " " + shellEscape(arg);
conn->sshConn = master.startCommand(command);
conn->to = FdSink(conn->sshConn->in.get());
@ -106,5 +226,6 @@ ref<RemoteStore::Connection> SSHStore::openConnection()
}
static RegisterStoreImplementation<SSHStore, SSHStoreConfig> regSSHStore;
static RegisterStoreImplementation<MountedSSHStore, MountedSSHStoreConfig> regMountedSSHStore;
}