Sftp strategy work
This commit is contained in:
parent
1d06437fe9
commit
3d1a9f5438
34
config.yml
34
config.yml
@ -7,6 +7,16 @@ defaults:
|
||||
keep_monthly: 12
|
||||
keep_yearly: 3
|
||||
|
||||
common:
|
||||
sftp_raid_strategy: &sftp_raid_strategy
|
||||
type: "kopia"
|
||||
provider: "sftp"
|
||||
destination:
|
||||
username: "gevo"
|
||||
host: "maric.ro"
|
||||
path: "/raid/backups/"
|
||||
ssh_key: "/home/gevo/.ssh/kopia_key"
|
||||
|
||||
services:
|
||||
backealocal:
|
||||
source:
|
||||
@ -28,7 +38,27 @@ services:
|
||||
provider: "local"
|
||||
destination:
|
||||
path: "/home/gevo/backup/images2"
|
||||
|
||||
3:
|
||||
backup_strategy:
|
||||
type: "kopia"
|
||||
provider: "sftp"
|
||||
destination:
|
||||
username: "gevo"
|
||||
host: "maric.ro"
|
||||
path: "/home/gevo/backups/backealocal"
|
||||
ssh_key: "/home/gevo/.ssh/kopia_key"
|
||||
4:
|
||||
backup_strategy: *sftp_raid_strategy
|
||||
backeaworking:
|
||||
source:
|
||||
host: "local"
|
||||
path: "/home/gevo/Images"
|
||||
hooks:
|
||||
before_hook: "ls"
|
||||
after_hook: ""
|
||||
backup_config:
|
||||
1:
|
||||
backup_strategy: *sftp_raid_strategy
|
||||
imageslocal:
|
||||
source:
|
||||
host: "local"
|
||||
@ -42,4 +72,4 @@ services:
|
||||
type: "kopia"
|
||||
provider: "local"
|
||||
destination:
|
||||
host: "local"
|
||||
host: "local"
|
@ -65,9 +65,10 @@ type RetentionConfig struct {
|
||||
|
||||
// DestConfig represents destination configuration for remote backups
|
||||
type DestConfig struct {
|
||||
Host string `mapstructure:"host,omitempty"`
|
||||
Path string `mapstructure:"path"`
|
||||
SSHKey string `mapstructure:"ssh_key,omitempty"`
|
||||
Host string `mapstructure:"host,omitempty"`
|
||||
Path string `mapstructure:"path"`
|
||||
SSHKey string `mapstructure:"ssh_key,omitempty"`
|
||||
Username string `mapstructure:"username"`
|
||||
}
|
||||
|
||||
// LoadConfig loads the application configuration from a file
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -64,30 +63,17 @@ func (f *Factory) createKopiaProvider(strategyConfig models.StrategyConfig) (kop
|
||||
return kopia.NewLocalProvider(getDefaultPath(strategyConfig.Destination.Path)), nil
|
||||
case "b2", "backblaze":
|
||||
return kopia.NewB2Provider(), nil
|
||||
// case "sftp":
|
||||
// return createSFTPProvider(strategyConfig.Destination)
|
||||
case "sftp":
|
||||
host := strategyConfig.Destination.Host
|
||||
basepath := strategyConfig.Destination.Path
|
||||
username := strategyConfig.Destination.Username
|
||||
keyFile := strategyConfig.Destination.SSHKey
|
||||
return kopia.NewSFTPProvider(host, basepath, username, keyFile), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown kopia provider type: %s", strategyConfig.Provider)
|
||||
}
|
||||
}
|
||||
|
||||
// createSFTPProvider handles SFTP provider creation
|
||||
func createSFTPProvider(dest DestinationConfig) (kopia.Provider, error) {
|
||||
host, username := parseSFTPHost(dest.Host)
|
||||
if host == "" {
|
||||
return nil, fmt.Errorf("SFTP host not specified")
|
||||
}
|
||||
return kopia.NewSFTPProvider(host, getDefaultPath(dest.Path), username, getSSHKeyPath(dest.SSHKey)), nil
|
||||
}
|
||||
|
||||
// parseSFTPHost extracts the username and host from "user@host"
|
||||
func parseSFTPHost(host string) (string, string) {
|
||||
if atIndex := strings.Index(host, "@"); atIndex > 0 {
|
||||
return host[atIndex+1:], host[:atIndex]
|
||||
}
|
||||
return host, getEnvUser()
|
||||
}
|
||||
|
||||
// getDefaultPath returns the given path or a default
|
||||
func getDefaultPath(path string) string {
|
||||
if path != "" {
|
||||
@ -97,23 +83,6 @@ func getDefaultPath(path string) string {
|
||||
return filepath.Join(home, ".backea", "repos")
|
||||
}
|
||||
|
||||
// getEnvUser returns the system username
|
||||
func getEnvUser() string {
|
||||
if user := os.Getenv("USER"); user != "" {
|
||||
return user
|
||||
}
|
||||
return "root"
|
||||
}
|
||||
|
||||
// getSSHKeyPath returns the SSH key path
|
||||
func getSSHKeyPath(key string) string {
|
||||
if key != "" {
|
||||
return key
|
||||
}
|
||||
home, _ := os.UserHomeDir()
|
||||
return filepath.Join(home, ".ssh", "id_rsa")
|
||||
}
|
||||
|
||||
// getServicePath returns a service's path
|
||||
func (f *Factory) getServicePath(groupName string) (string, error) {
|
||||
if serviceGroup, exists := f.Config.Services[groupName]; exists {
|
||||
|
@ -27,9 +27,15 @@ func NewSFTPProvider(host, basePath, username, keyFile string) *SFTPProvider {
|
||||
}
|
||||
}
|
||||
|
||||
// Connect connects to an SFTP repository
|
||||
// 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 {
|
||||
repoPath := fmt.Sprintf("%s@%s:%s/%s", p.Username, p.Host, p.BasePath, serviceName)
|
||||
// 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(
|
||||
@ -38,10 +44,13 @@ func (p *SFTPProvider) Connect(ctx context.Context, serviceName string, password
|
||||
"--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
|
||||
@ -52,10 +61,13 @@ func (p *SFTPProvider) Connect(ctx context.Context, serviceName string, password
|
||||
"--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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user