mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 18:40:40 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
7aa937dd41 | |||
|
37361727ba | ||
f1874438e5 | |||
|
066342a7b7 | ||
|
f620bb1764 | ||
|
e3506e44b5 | ||
|
f65a83991b | ||
f10b8c7990 | |||
|
a8af085d9c | ||
fa89d2941f |
25
.drone.yml
Normal file
25
.drone.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
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
|
@@ -1,5 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.14
|
||||||
|
|
||||||
|
- Fixed #17 enable sftp
|
||||||
|
- Fixed #18 help command
|
||||||
|
|
||||||
## 0.13
|
## 0.13
|
||||||
|
|
||||||
- Restored files are now without the prefix path.
|
- Restored files are now without the prefix path.
|
||||||
|
95
README.md
95
README.md
@@ -13,6 +13,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,6 +21,7 @@ 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)
|
||||||
@@ -190,6 +192,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 +275,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 +295,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)
|
||||||
|
@@ -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",
|
||||||
|
@@ -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.14'
|
||||||
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)
|
||||||
|
@@ -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,6 +43,7 @@ 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... ⏳')
|
||||||
|
try {
|
||||||
const env = getEnvFromBackend(backend)
|
const env = getEnvFromBackend(backend)
|
||||||
|
|
||||||
const { out, err } = exec('restic', ['init'], { env })
|
const { out, err } = exec('restic', ['init'], { env })
|
||||||
@@ -53,6 +54,9 @@ export const checkAndConfigureBackend = (name: string, backend: Backend) => {
|
|||||||
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) => {
|
||||||
|
Reference in New Issue
Block a user