diff --git a/CHANGELOG.md b/CHANGELOG.md index 900a8fa..9341c44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.4.0] +## [1.4.0] - 2021-10-30 + +### Added - Allow specify to specify a backend for location backup - Global restic flags +- Generic ENV support for backends + +### Changed + +- Install now only requires `wget` +- Env variable for the `KEY` has been renamed from `AUTORESTIC_[BACKEND NAME]_KEY` -> `AUTORESTIC_[BACKEND NAME]_RESTIC_PASSWORD` + +### Fixed + +- Error handling during upgrade & uninstall ## [1.3.0] - 2021-10-26 diff --git a/cmd/uninstall.go b/cmd/uninstall.go index 50f774c..e3e955f 100644 --- a/cmd/uninstall.go +++ b/cmd/uninstall.go @@ -9,12 +9,12 @@ var uninstallCmd = &cobra.Command{ Use: "uninstall", Short: "Uninstall restic and autorestic", Run: func(cmd *cobra.Command, args []string) { - noRestic, _ := cmd.Flags().GetBool("no-restic") - bins.Uninstall(!noRestic) + restic, _ := cmd.Flags().GetBool("restic") + bins.Uninstall(restic) }, } func init() { rootCmd.AddCommand(uninstallCmd) - uninstallCmd.Flags().Bool("no-restic", false, "do not uninstall restic.") + uninstallCmd.Flags().Bool("restic", false, "also uninstall restic.") } diff --git a/cmd/upgrade.go b/cmd/upgrade.go index f2a0dc7..b6bc15e 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -9,13 +9,13 @@ var upgradeCmd = &cobra.Command{ Use: "upgrade", Short: "Upgrade autorestic and restic", Run: func(cmd *cobra.Command, args []string) { - noRestic, _ := cmd.Flags().GetBool("no-restic") - err := bins.Upgrade(!noRestic) + restic, _ := cmd.Flags().GetBool("restic") + err := bins.Upgrade(restic) CheckErr(err) }, } func init() { rootCmd.AddCommand(upgradeCmd) - upgradeCmd.Flags().Bool("no-restic", false, "also update restic") + upgradeCmd.Flags().Bool("restic", true, "also update restic") } diff --git a/docs/markdown/backend/available.md b/docs/markdown/backend/available.md index 88bccf0..cf692c4 100644 --- a/docs/markdown/backend/available.md +++ b/docs/markdown/backend/available.md @@ -4,6 +4,8 @@ In theory [all the restic backends](https://restic.readthedocs.io/en/stable/030_ Those tested are the following: +> ℹ️ You can also [specify the `env` variables in a config file](/backend/env) to separate them from the config file. + ## Local ```yaml diff --git a/docs/markdown/backend/env.md b/docs/markdown/backend/env.md index 4831c13..f66784e 100644 --- a/docs/markdown/backend/env.md +++ b/docs/markdown/backend/env.md @@ -1,36 +1,67 @@ # Environment -> ⚠ Available since version `v1.3.0` +> ⚠ Available since version `v1.4.0` Sometimes it's favorable not having the encryption keys in the config files. -For that `autorestic` allows passing the backend keys as `ENV` variables, or through an env file. +For that `autorestic` allows passing the env variables to backend password as `ENV` variables, or through an env file. +You can also pass whatever `env` variable to restic by prefixing it with `AUTORESTIC_[BACKEND NAME]_`. -The syntax for the `ENV` variables is as follows: `AUTORESTIC_[BACKEND NAME]_KEY`. +> ℹ️ Env variables and file overwrite the config file in the following order: +> +> Env Variables > Env File (`.autorestic.env`) > Config file (`.autorestic.yaml`) + +## Env file + +Alternatively `autorestic` can load an env file, located next to `.autorestic.yml` called `.autorestic.env`. + +``` +AUTORESTIC_FOO_RESTIC_PASSWORD=secret123 +``` + +### Example with repository password + +The syntax for the `ENV` variables is as follows: `AUTORESTIC_[BACKEND NAME]_RESTIC_PASSWORD`. ```yaml | autorestic.yaml backend: foo: type: ... path: ... - key: secret123 # => AUTORESTIC_FOO_KEY=secret123 + key: secret123 # => AUTORESTIC_FOO_RESTIC_PASSWORD=secret123 ``` -## Example - This means we could remove `key: secret123` from `.autorestic.yaml` and execute as follows: ```bash -AUTORESTIC_FOO_KEY=secret123 autorestic backup ... +AUTORESTIC_FOO_RESTIC_PASSWORD=secret123 autorestic backup ... ``` -## Env file +### Example with Backblaze B2 -Alternatively `autorestic` can load an env file, located next to `autorestic.yml` called `.autorestic.env`. - -```| .autorestic.env -AUTORESTIC_FOO_KEY=secret123 +```yaml | autorestic.yaml +backends: + bb: + type: b2 + path: myBucket + key: myPassword + env: + B2_ACCOUNT_ID: 123 + B2_ACCOUNT_KEY: 456 ``` -after that you can simply use `autorestic` as your are used to. +You could create an `.autorestic.env` or pass the following `ENV` variables to autorestic: + +``` +AUTORESTIC_BB_RESTIC_PASSWORD=myPassword +AUTORESTIC_BB_B2_ACCOUNT_ID=123 +AUTORESTIC_BB_B2_ACCOUNT_KEY=456 +``` + +```yaml | autorestic.yaml +backends: + bb: + type: b2 + path: myBucket +``` > :ToCPrevNext diff --git a/docs/markdown/installation.md b/docs/markdown/installation.md index 7f7e3fc..a6a9a2a 100644 --- a/docs/markdown/installation.md +++ b/docs/markdown/installation.md @@ -2,10 +2,10 @@ Linux & macOS. Windows is not supported. If you have problems installing please open an issue :) -Autorestic requires `curl`, `wget` and `bzip2` to be installed. For most systems these should be already installed. +Autorestic requires `bash`, `wget` and `bzip2` to be installed. For most systems these should be already installed. ```bash -curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash +wget -qO - https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash ``` ## Alternatives diff --git a/docs/markdown/quick.md b/docs/markdown/quick.md index 231d184..574bc03 100644 --- a/docs/markdown/quick.md +++ b/docs/markdown/quick.md @@ -3,7 +3,7 @@ ## Installation ```bash -curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash +wget -qO - https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash ``` See [installation](/installation) for alternative options. diff --git a/install.sh b/install.sh index de473a4..2638498 100755 --- a/install.sh +++ b/install.sh @@ -31,7 +31,7 @@ else fi echo $ARCH -curl -s https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \ +wget -qO - https://api.github.com/repos/cupcakearmy/autorestic/releases/latest \ | grep "browser_download_url.*_${OS}_${ARCH}" \ | cut -d : -f 2,3 \ | tr -d \" \ diff --git a/internal/backend.go b/internal/backend.go index 8116d44..e60c709 100644 --- a/internal/backend.go +++ b/internal/backend.go @@ -58,20 +58,27 @@ func (b Backend) generateRepo() (string, error) { func (b Backend) getEnv() (map[string]string, error) { env := make(map[string]string) + // Key if b.Key != "" { env["RESTIC_PASSWORD"] = b.Key - } else { - key, err := b.getKey() - if err != nil { - return nil, err - } - env["RESTIC_PASSWORD"] = key } + + // From config file repo, err := b.generateRepo() env["RESTIC_REPOSITORY"] = repo for key, value := range b.Env { env[strings.ToUpper(key)] = value } + + // From Envfile and passed as env + var prefix = "AUTORESTIC_" + strings.ToUpper(b.name) + "_" + for _, variable := range os.Environ() { + var splitted = strings.SplitN(variable, "=", 2) + if strings.HasPrefix(splitted[0], prefix) { + env[strings.TrimPrefix(splitted[0], prefix)] = splitted[1] + } + } + return env, err } @@ -85,17 +92,6 @@ func generateRandomKey() string { return key } -func (b Backend) getKey() (string, error) { - if b.Key != "" { - return b.Key, nil - } - keyName := "AUTORESTIC_" + strings.ToUpper(b.name) + "_KEY" - if key, found := os.LookupEnv(keyName); found { - return key, nil - } - return "", fmt.Errorf("no key found for backend \"%s\"", b.name) -} - func (b Backend) validate() error { if b.Type == "" { return fmt.Errorf(`Backend "%s" has no "type"`, b.name) @@ -105,8 +101,9 @@ func (b Backend) validate() error { } if b.Key == "" { // Check if key is set in environment - if _, err := b.getKey(); err != nil { - // If not generate a new one + env, _ := b.getEnv() + if _, found := env["RESTIC_PASSWORD"]; !found { + // No key set in config file or env => generate random key and save file key := generateRandomKey() b.Key = key c := GetConfig() diff --git a/internal/bins/bins.go b/internal/bins/bins.go index 87e9488..27c640c 100644 --- a/internal/bins/bins.go +++ b/internal/bins/bins.go @@ -47,11 +47,11 @@ func dlJSON(url string) (GithubRelease, error) { func Uninstall(restic bool) error { if err := os.Remove(path.Join(INSTALL_PATH, "autorestic")); err != nil { - colors.Error.Println(err) + return err } if restic { if err := os.Remove(path.Join(INSTALL_PATH, "restic")); err != nil { - colors.Error.Println(err) + return err } } return nil @@ -79,11 +79,15 @@ func downloadAndInstallAsset(body GithubRelease, name string) error { return err } defer tmp.Close() - tmp.Chmod(0755) - io.Copy(tmp, bz) + if err := tmp.Chmod(0755); err != nil { + return err + } + if _, err := io.Copy(tmp, bz); err != nil { + return err + } to := path.Join(INSTALL_PATH, name) - os.Remove(to) // Delete if current, ignore error if file does not exits. + defer os.Remove(to) // Delete if current, ignore error if file does not exits. if err := os.Rename(tmp.Name(), to); err != nil { return nil } @@ -121,9 +125,11 @@ func Upgrade(restic bool) error { // Upgrade restic if restic { if err := InstallRestic(); err != nil { - colors.Error.Println(err) + return err + } + if err := upgradeRestic(); err != nil { + return err } - upgradeRestic() } // Upgrade self @@ -140,7 +146,9 @@ func Upgrade(restic bool) error { return err } if current.LT(latest) { - downloadAndInstallAsset(body, "autorestic") + if err := downloadAndInstallAsset(body, "autorestic"); err != nil { + return err + } colors.Success.Println("Updated autorestic") } else { colors.Body.Println("Already up to date")