package kopia import ( "context" "fmt" "log" "os" "os/exec" "path/filepath" ) // SFTPProvider implements the Provider interface for SFTP remote storage type SFTPProvider struct { Host string BasePath string Username string KeyFile string } // NewSFTPProvider creates a new SFTP provider func NewSFTPProvider(host, basePath, username, keyFile string) *SFTPProvider { return &SFTPProvider{ Host: host, BasePath: basePath, Username: username, KeyFile: keyFile, } } // kopia repository connect sftp \ // --path="/home/gevo/kopiatemp" \ // --host="maric.ro" \ // --username="gevo" \ // --keyfile="$(realpath ~/.ssh/kopia_key)" \ // --known-hosts="$(realpath ~/.ssh/known_hosts)" func (p *SFTPProvider) Connect(ctx context.Context, serviceName string, password string, configPath string) error { // Just use the path on the remote server, not the full URI repoPath := fmt.Sprintf("%s/%s", p.BasePath, serviceName) // Try to connect to existing repository with config file connectCmd := exec.CommandContext( ctx, "kopia", "--config-file", configPath, "repository", "connect", "sftp", "--path", repoPath, "--host", p.Host, "--username", p.Username, "--keyfile", p.KeyFile, "--known-hosts", filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"), "--password", password, ) err := connectCmd.Run() if err != nil { // Connection failed, create new repository log.Printf("Creating new SFTP repository for %s at %s", serviceName, repoPath) createCmd := exec.CommandContext( ctx, "kopia", "--config-file", configPath, "repository", "create", "sftp", "--path", repoPath, "--host", p.Host, "--username", p.Username, "--keyfile", p.KeyFile, "--known-hosts", filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"), "--password", password, ) createOutput, err := createCmd.CombinedOutput() if err != nil { return fmt.Errorf("failed to create repository: %w\nOutput: %s", err, createOutput) } } return nil } // GetRepositoryParams returns parameters for SFTP operations func (p *SFTPProvider) GetRepositoryParams(serviceName string) ([]string, error) { repoPath := fmt.Sprintf("%s@%s:%s/%s", p.Username, p.Host, p.BasePath, serviceName) return []string{ "sftp", "--path", repoPath, "--keyfile", p.KeyFile, "--known-hosts", filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"), }, nil } // GetBucketName returns the path for a service func (p *SFTPProvider) GetBucketName(serviceName string) string { return fmt.Sprintf("%s/%s", p.BasePath, serviceName) } // GetProviderType returns the provider type identifier func (p *SFTPProvider) GetProviderType() string { return "sftp" }