Compare commits

...

19 Commits
0.13 ... 0.16

Author SHA1 Message Date
7e577c439a notify user if config file was overwritten and make a copy of it as backup 2020-03-02 19:08:20 +01:00
bc36a39de4 Update README.md 2020-03-02 19:01:39 +01:00
9e6b393e62 Update README.md 2020-03-02 18:59:40 +01:00
de34396b93 Update README.md 2020-02-26 12:18:04 +01:00
ebbe10608a Update README.md 2020-02-26 12:13:46 +01:00
8a34270934 Update README.md 2020-02-26 12:12:40 +01:00
e459e393a9 Update README.md 2020-01-23 11:27:00 +01:00
b1a3074f33 changelog 2020-01-23 11:20:44 +01:00
ae63d8b12e protected drone file 2020-01-23 11:19:16 +01:00
7aa937dd41 automatic signing 2020-01-23 11:09:57 +01:00
cupcakearmy
37361727ba Merge remote-tracking branch 'origin/master' 2020-01-08 00:48:13 +01:00
f1874438e5 Update README.md 2020-01-08 00:46:36 +01:00
cupcakearmy
066342a7b7 changelog 2020-01-08 00:45:39 +01:00
cupcakearmy
f620bb1764 version bump and help command in addition to flag 2020-01-08 00:34:36 +01:00
cupcakearmy
e3506e44b5 enable sftp 2020-01-08 00:32:33 +01:00
cupcakearmy
f65a83991b Merge remote-tracking branch 'origin/master' 2020-01-08 00:30:16 +01:00
f10b8c7990 Update README.md 2020-01-08 00:29:12 +01:00
cupcakearmy
a8af085d9c dont' get stuck if backend is not supported 2020-01-08 00:22:49 +01:00
fa89d2941f Update README.md 2019-12-24 19:05:26 +01:00
7 changed files with 181 additions and 71 deletions

31
.drone.yml Normal file
View File

@@ -0,0 +1,31 @@
---
kind: pipeline
name: default
steps:
- name: build
image: node
pull: always
commands:
- yarn
- yarn run bin
when:
event: tag
- name: publish
image: plugins/github-release
pull: always
settings:
api_key:
from_secret: github
files: bin/*
checksum:
- sha512
note: CHANGELOG.md
when:
event: tag
---
kind: signature
hmac: 3b1f235f6a6f0ee1aa3f572d0833c4f0eec931dbe0378f31b9efa336a7462912
...

View File

@@ -1,53 +1,3 @@
# Changelog ## 0.16
## 0.13 - notify user if config file was overwritten and make a copy of it as backup
- Restored files are now without the prefix path.
- Support for making backups of docker volumes and restoring them (not incremental).
- Show error to user during backup
## 0.12
- fix self update on linux (Fix #15)
## 0.11
- tilde in arguments (Fix #14)
## 0.10
- Show elapsed time (Fix #12)
- Remove some code duplication
- New info command to quickly show an overview of your config (Fix #11)
## 0.9
- Hooks
- Cleanup
## 0.8
- Support for native flags in the backup and forget commands.
- Forget cleanup
## 0.7
- Cleanup
- Support for excluding files
- Ability to prune keeping the last x snapshots according to restic policy rules
## 0.6
- support for absolute paths
## 0.5
- config optional if not required for current operation
## 0.4
- show version number
## 0.3
- test autoupdate function

119
README.md
View File

@@ -5,6 +5,10 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
![Sketch](./docs/Sketch.png) ![Sketch](./docs/Sketch.png)
## ✈️ Roadmap
I would like to make the official `1.0` release in the coming months. Until then please feel free to file issues or feature requests so that the tool is as flexible as possible :)
## 🌈 Features ## 🌈 Features
- Config files, no CLI - Config files, no CLI
@@ -13,6 +17,7 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
- Snapshot policies and pruning - Snapshot policies and pruning
- Simple interface - Simple interface
- Fully encrypted - Fully encrypted
- Backup & Restore docker volumes
### 📒 Docs ### 📒 Docs
@@ -20,13 +25,15 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
* [Pruning & Deleting old files](#pruning-and-snapshot-policies) * [Pruning & Deleting old files](#pruning-and-snapshot-policies)
* [Excluding files](#excluding-filesfolders) * [Excluding files](#excluding-filesfolders)
* [Hooks](#before--after-hooks) * [Hooks](#before--after-hooks)
* [Docker volumes](#-Docker-volumes)
* [Backends](#-backends) * [Backends](#-backends)
* [Commands](#-commands) * [Commands](#-commands)
* [Examples](#-examples) * [Examples](#-examples)
* [QA](#-qa)
## 🛳 Installation ## 🛳 Installation
Linux & macOS. Windows is not supported. Linux & macOS. Windows is not supported. If you have problems installing please open an issue :)
``` ```
curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.sh | bash
@@ -34,6 +41,12 @@ curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.
## 🚀 Quickstart ## 🚀 Quickstart
##### ⚠️ Note ⚠️
Note that the data is automatically encrypted on the server. The key will be generated and added to your config file. Every backend will have a separate key. **You should keep a copy of the keys or config file somewhere in case your server dies**. Otherwise DATA IS LOST!
Also, currently comments in the config file will be deleted, due how the yaml parsing library works. I will fix this soon :)
### Setup ### Setup
First we need to configure our locations and backends. Simply create a `.autorestic.yml` either in your home directory of in the folder from which you will execute `autorestic`. First we need to configure our locations and backends. Simply create a `.autorestic.yml` either in your home directory of in the folder from which you will execute `autorestic`.
@@ -68,10 +81,6 @@ Then we check if everything is correct by running the `check` command. We will p
If we would check only one location we could run the following: `autorestic check -l home`. Otherwise simpply check all locations with `autorestic check -a` If we would check only one location we could run the following: `autorestic check -l home`. Otherwise simpply check all locations with `autorestic check -a`
##### Note
Note that the data is automatically encrypted on the server. The key will be generated and added to your config file. Every backend will have a separate key. You should keep a copy of the keys somewhere in case your server dies. Otherwise DATA IS LOST!
### 📦 Backup ### 📦 Backup
``` ```
@@ -190,6 +199,64 @@ locations:
- echo "kthxbye" - echo "kthxbye"
``` ```
#### 🐳 Docker volumes
Since version 0.13 autorestic supports docker volumes directly, without needing them to be mounted to the host filesystem.
Let see an example.
###### docker-compose.yml
```yaml
version: '3.7'
volumes:
data:
name: my-data
services:
api:
image: alpine
volumes:
- data:/foo/bar
```
###### .autorestic.yml
```yaml
locations:
hello:
from: 'volume:my-data'
to:
- remote
options:
forget:
keep-last: 2
backends:
remote:
...
```
Now you can backup and restore as always.
```sh
autorestic -l hello backup
```
```sh
autorestic -l hello restore
```
If the volume does not exist on restore, autorestic will create it for you and then fill it with the data.
### Limitations
Unfortunately there are some limitations when backing up directly from a docker volume without mounting the volume to the host. If you are curious or have ideas how to improve this, please [read more here](https://github.com/cupcakearmy/autorestic/issues/4#issuecomment-568771951). Any help is welcomed 🙂
1. Incremental updates are not possible right now due to how the current docker mounting works.
2. Exclude patterns and files also do not work as restic only sees a compressed tarball as source and not the actual data.
## 💽 Backends ## 💽 Backends
Backends are the place where you data will be saved. Backups are incremental and encrypted. Backends are the place where you data will be saved. Backups are incremental and encrypted.
@@ -215,7 +282,16 @@ For each backend you need to specify the right variables as shown in the example
The path on the remote server. The path on the remote server.
For object storages as For object storages as
##### Example ##### Example Local
```yaml
backends:
name-of-backend:
type: local
path: /data/my/backups
```
##### Example Backblaze
```yaml ```yaml
backends: backends:
@@ -226,6 +302,30 @@ backends:
B2_ACCOUNT_KEY: backblaze_account_key B2_ACCOUNT_KEY: backblaze_account_key
``` ```
##### Example S3 / Minio
```yaml
backends:
name-of-backend:
type: s3
path: s3.amazonaws.com/bucket_name
# Minio
# path: http://localhost:9000/bucket_name
AWS_ACCESS_KEY_ID: my_key
AWS_SECRET_ACCESS_KEY: my_secret
```
##### Example SFTP
For SFTP to work you need to use configure your host inside of `~/.ssh/config` as password prompt is not supported. For more information on this topic please see the [official docs on the matter](https://restic.readthedocs.io/en/stable/030_preparing_a_new_repo.html#sftp).
```yaml
backends:
name-of-backend:
type: sftp
path: my-host:/remote/path/on/the/server
```
## 👉 Commands ## 👉 Commands
* [info](#info) * [info](#info)
@@ -334,6 +434,13 @@ autorestic -a exec snapshots
autorestic -b my-backend exec unlock autorestic -b my-backend exec unlock
``` ```
## ❓ QA
### My config file was moved?
This happens when autorestic needs to write to the config file. This happend e.g. when we are generating a key for you.
Unforunately during this process formatting and comments are lost. That is why autorestic will place a copy of your old config next to the one we are writing to.
## Contributors ## Contributors
This amazing people helped the project! This amazing people helped the project!

View File

@@ -4,7 +4,8 @@
"build": "tsc", "build": "tsc",
"build:watch": "tsc -w", "build:watch": "tsc -w",
"dev": "tsnd --no-notify --respawn ./src/autorestic.ts", "dev": "tsnd --no-notify --respawn ./src/autorestic.ts",
"bin": "yarn run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin" "move": "mv bin/autorestic-linux bin/autorestic_linux_x64 && mv bin/autorestic-macos bin/autorestic_macos_x64",
"bin": "yarn run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin && yarn run move"
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^3.12.1", "@types/js-yaml": "^3.12.1",
@@ -22,4 +23,4 @@
"minimist": "^1.2.0", "minimist": "^1.2.0",
"uhrwerk": "^1.0.0" "uhrwerk": "^1.0.0"
} }
} }

View File

@@ -25,7 +25,7 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
string: ['l', 'b'], string: ['l', 'b'],
}) })
export const VERSION = '0.13' export const VERSION = '0.16'
export const INSTALL_DIR = '/usr/local/bin' export const INSTALL_DIR = '/usr/local/bin'
export const VERBOSE = flags.verbose export const VERBOSE = flags.verbose
@@ -33,7 +33,7 @@ export const config = init()
async function main() { async function main() {
if (commands.length < 1) return help() if (commands.length < 1 || commands[0] === 'help') return help()
const command: string = commands[0] const command: string = commands[0]
const args: string[] = commands.slice(1) const args: string[] = commands.slice(1)

View File

@@ -16,8 +16,8 @@ export const getPathFromBackend = (backend: Backend): string => {
case 'azure': case 'azure':
case 'gs': case 'gs':
case 's3': case 's3':
return `${backend.type}:${backend.path}`
case 'sftp': case 'sftp':
return `${backend.type}:${backend.path}`
case 'rest': case 'rest':
throw new Error(`Unsupported backend type: "${backend.type}"`) throw new Error(`Unsupported backend type: "${backend.type}"`)
default: default:
@@ -43,16 +43,20 @@ export const getBackendsFromLocations = (locations: Locations): string[] => {
export const checkAndConfigureBackend = (name: string, backend: Backend) => { export const checkAndConfigureBackend = (name: string, backend: Backend) => {
const writer = new Writer(name.blue + ' : ' + 'Configuring... ⏳') const writer = new Writer(name.blue + ' : ' + 'Configuring... ⏳')
const env = getEnvFromBackend(backend) try {
const env = getEnvFromBackend(backend)
const { out, err } = exec('restic', ['init'], { env }) const { out, err } = exec('restic', ['init'], { env })
if (err.length > 0 && !ALREADY_EXISTS.test(err)) if (err.length > 0 && !ALREADY_EXISTS.test(err))
throw new Error(`Could not load the backend "${name}": ${err}`) throw new Error(`Could not load the backend "${name}": ${err}`)
if (VERBOSE && out.length > 0) console.log(out) if (VERBOSE && out.length > 0) console.log(out)
writer.done(name.blue + ' : ' + 'Done ✓'.green) writer.done(name.blue + ' : ' + 'Done ✓'.green)
} catch (e) {
writer.done(name.blue + ' : ' + 'Error ⚠️ ' + e.message.red)
}
} }
export const checkAndConfigureBackends = (backends?: Backends) => { export const checkAndConfigureBackends = (backends?: Backends) => {

View File

@@ -1,4 +1,4 @@
import { readFileSync, writeFileSync, statSync } from 'fs' import { readFileSync, writeFileSync, statSync, copyFileSync } from 'fs'
import { resolve } from 'path' import { resolve } from 'path'
import { homedir } from 'os' import { homedir } from 'os'
@@ -88,10 +88,27 @@ export const init = (): Config | undefined => {
yaml.safeLoad(readFileSync(CONFIG_FILE).toString()), yaml.safeLoad(readFileSync(CONFIG_FILE).toString()),
) )
const current = JSON.stringify(raw)
normalizeAndCheckBackends(raw) normalizeAndCheckBackends(raw)
normalizeAndCheckBackups(raw) normalizeAndCheckBackups(raw)
writeFileSync(CONFIG_FILE, yaml.safeDump(raw)) const changed = JSON.stringify(raw) !== current
if (changed) {
const OLD_CONFIG_FILE = CONFIG_FILE + '.old'
copyFileSync(CONFIG_FILE, OLD_CONFIG_FILE)
writeFileSync(CONFIG_FILE, yaml.safeDump(raw))
console.log(
'\n' +
'⚠️ MOVED OLD CONFIG FILE TO: ⚠️'.red.underline.bold +
'\n' +
OLD_CONFIG_FILE +
'\n' +
'What? Why? '.grey + 'https://git.io/Jv2D0'.underline.grey +
'\n'
)
}
return raw return raw
} }