mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 10:30:39 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2f0092befe | ||
|
1026e68b68 | ||
2389c59aa9 | |||
087aeaf578 | |||
3b7062f733 | |||
|
96b63c744b | ||
|
9669b70e20 | ||
|
bcb081234c | ||
|
336f44e9dc | ||
|
d0cda7f1d5 |
58
README.md
58
README.md
@@ -54,13 +54,11 @@ backends:
|
|||||||
|
|
||||||
Then we check if everything is correct by running the `check` command. We will pass the `-a` (or `--all`) to tell autorestic to check all the locations.
|
Then we check if everything is correct by running the `check` command. We will pass the `-a` (or `--all`) to tell autorestic to check all the locations.
|
||||||
|
|
||||||
Lets see a more realistic example (from the config above)
|
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
|
||||||
autorestic check -l important
|
|
||||||
```
|
|
||||||
|
|
||||||
If we would check only one location we could run the following: `autorestic -l home check`.
|
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
|
||||||
|
|
||||||
@@ -76,6 +74,7 @@ autorestic restore -a --to /path/where/to/restore
|
|||||||
|
|
||||||
This will restore all the locations to the selected target. If for one location there are more than one backends specified autorestic will take the first one.
|
This will restore all the locations to the selected target. If for one location there are more than one backends specified autorestic will take the first one.
|
||||||
|
|
||||||
|
Lets see a more realistic example (from the config above)
|
||||||
```
|
```
|
||||||
autorestic restore -l home --from hdd --to /path/where/to/restore
|
autorestic restore -l home --from hdd --to /path/where/to/restore
|
||||||
```
|
```
|
||||||
@@ -132,7 +131,7 @@ backends:
|
|||||||
B2_ACCOUNT_KEY: backblaze_account_key
|
B2_ACCOUNT_KEY: backblaze_account_key
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pruning and snapshot policies
|
### Pruning and snapshot policies
|
||||||
|
|
||||||
Autorestic supports declaring snapshot policies for location to avoid keeping old snapshot around if you don't need them.
|
Autorestic supports declaring snapshot policies for location to avoid keeping old snapshot around if you don't need them.
|
||||||
|
|
||||||
@@ -143,24 +142,20 @@ locations:
|
|||||||
etc:
|
etc:
|
||||||
from: /etc
|
from: /etc
|
||||||
to: local
|
to: local
|
||||||
keep:
|
options:
|
||||||
# options matches the --keep-* options used in the restic forget CLI
|
forget:
|
||||||
# cf https://restic.readthedocs.io/en/latest/060_forget.html#removing-snapshots-according-to-a-policy
|
keep-last: 5 # always keep at least 5 snapshots
|
||||||
last: 5 # always keep at least 5 snapshots
|
keep-hourly: 3 # keep 3 last hourly shapshots
|
||||||
hourly: 3 # keep 3 last hourly shapshots
|
keep-daily: 4 # keep 4 last daily shapshots
|
||||||
daily: 4 # keep 4 last daily shapshots
|
keep-weekly: 1 # keep 1 last weekly shapshots
|
||||||
weekly: 1 # keep 1 last weekly shapshots
|
keep-monthly: 12 # keep 12 last monthly shapshots
|
||||||
monthly: 12 # keep 12 last monthly shapshots
|
keep-yearly: 7 # keep 7 last yearly shapshots
|
||||||
yearly: 7 # keep 7 last yearly shapshots
|
keep-within: "2w" # keep snapshots from the last 2 weeks
|
||||||
within: "2w" # keep snapshots from the last 2 weeks
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Pruning can be triggered using `autorestic forget -a`, for all locations, or selectively with `autorestic forget -l <location>`. **please note that contrary to the restic CLI, `restic forget` will call `restic prune` internally.**
|
Pruning can be triggered using `autorestic forget -a`, for all locations, or selectively with `autorestic forget -l <location>`. **please note that contrary to the restic CLI, `restic forget` will call `restic prune` internally.**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Run with the `--dry-run` flag to only print information about the process without actually pruning the snapshots. This is especially useful for debugging or testing policies:
|
Run with the `--dry-run` flag to only print information about the process without actually pruning the snapshots. This is especially useful for debugging or testing policies:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ autorestic forget -a --dry-run --verbose
|
$ autorestic forget -a --dry-run --verbose
|
||||||
|
|
||||||
@@ -181,9 +176,30 @@ f8f8f976 2019-12-02 12:11:08 computer within 2w /etc
|
|||||||
3 snapshots
|
3 snapshots
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Note
|
### Excluding files/folders
|
||||||
|
|
||||||
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!
|
If you want to exclude certain files or folders it done easily by specifiyng the right flags in the location you desire to filter. The flags are taken straight from the [restic cli exclude rules](https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
locations:
|
||||||
|
my-location:
|
||||||
|
from: /data
|
||||||
|
to:
|
||||||
|
- local
|
||||||
|
- remote
|
||||||
|
options:
|
||||||
|
backup:
|
||||||
|
exclude:
|
||||||
|
- '*.nope'
|
||||||
|
- '*.abc'
|
||||||
|
exclude-file: .gitignore
|
||||||
|
|
||||||
|
backends:
|
||||||
|
local:
|
||||||
|
...
|
||||||
|
remote:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
"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": "npm run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin"
|
"bin": "yarn run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-yaml": "^3.12.1",
|
"@types/js-yaml": "^3.12.1",
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"@types/node": "^12.11.7",
|
"@types/node": "^12.11.7",
|
||||||
"pkg": "^4.4.0",
|
"pkg": "^4.4.0",
|
||||||
"ts-node-dev": "^1.0.0-pre.40",
|
"ts-node-dev": "^1.0.0-pre.40",
|
||||||
"typescript": "^3.5.1"
|
"typescript": "^3.7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
|
@@ -26,7 +26,7 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
|
|||||||
string: ['l', 'b'],
|
string: ['l', 'b'],
|
||||||
})
|
})
|
||||||
|
|
||||||
export const VERSION = '0.7'
|
export const VERSION = '0.8'
|
||||||
export const INSTALL_DIR = '/usr/local/bin'
|
export const INSTALL_DIR = '/usr/local/bin'
|
||||||
export const VERBOSE = flags.verbose
|
export const VERBOSE = flags.verbose
|
||||||
|
|
||||||
|
@@ -10,8 +10,8 @@ import { exec, ConfigError, pathRelativeToConfigFile, getFlagsFromLocation } fro
|
|||||||
export const backupSingle = (name: string, to: string, location: Location) => {
|
export const backupSingle = (name: string, to: string, location: Location) => {
|
||||||
if (!config) throw ConfigError
|
if (!config) throw ConfigError
|
||||||
const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳')
|
const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳')
|
||||||
const backend = config.backends[to]
|
|
||||||
|
|
||||||
|
const backend = config.backends[to]
|
||||||
const path = pathRelativeToConfigFile(location.from)
|
const path = pathRelativeToConfigFile(location.from)
|
||||||
|
|
||||||
const cmd = exec(
|
const cmd = exec(
|
||||||
@@ -27,13 +27,12 @@ export const backupSingle = (name: string, to: string, location: Location) => {
|
|||||||
export const backupLocation = (name: string, location: Location) => {
|
export const backupLocation = (name: string, location: Location) => {
|
||||||
const display = name.yellow + ' ▶ '
|
const display = name.yellow + ' ▶ '
|
||||||
const filler = new Array(name.length + 3).fill(' ').join('')
|
const filler = new Array(name.length + 3).fill(' ').join('')
|
||||||
if (Array.isArray(location.to)) {
|
let first = true
|
||||||
let first = true
|
|
||||||
for (const t of location.to) {
|
for (const t of Array.isArray(location.to) ? location.to : [location.to]) {
|
||||||
backupSingle(first ? display : filler, t, location)
|
backupSingle(first ? display : filler, t, location)
|
||||||
if (first) first = false
|
if (first) first = false
|
||||||
}
|
}
|
||||||
} else backupSingle(display, location.from, location)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const backupAll = (locations?: Locations) => {
|
export const backupAll = (locations?: Locations) => {
|
||||||
|
@@ -2,46 +2,46 @@ import { Writer } from 'clitastic'
|
|||||||
|
|
||||||
import { config, VERBOSE } from './autorestic'
|
import { config, VERBOSE } from './autorestic'
|
||||||
import { getEnvFromBackend } from './backend'
|
import { getEnvFromBackend } from './backend'
|
||||||
import { Locations, Location, ForgetPolicy, Flags } from './types'
|
import { Locations, Location, Flags } from './types'
|
||||||
import { exec, ConfigError } from './utils'
|
import { exec, ConfigError, pathRelativeToConfigFile, getFlagsFromLocation } from './utils'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const forgetSingle = (dryRun: boolean, name: string, from: string, to: string, policy: ForgetPolicy) => {
|
export const forgetSingle = (name: string, to: string, location: Location, dryRun: boolean) => {
|
||||||
if (!config) throw ConfigError
|
if (!config) throw ConfigError
|
||||||
const writer = new Writer(name + to.blue + ' : ' + 'Removing old spnapshots… ⏳')
|
const base = name + to.blue + ' : '
|
||||||
|
const writer = new Writer(base + 'Removing old snapshots… ⏳')
|
||||||
|
|
||||||
const backend = config.backends[to]
|
const backend = config.backends[to]
|
||||||
const flags = [] as any[]
|
const path = pathRelativeToConfigFile(location.from)
|
||||||
for (const [name, value] of Object.entries(policy)) {
|
const flags = getFlagsFromLocation(location, 'forget')
|
||||||
flags.push(`--keep-${name}`)
|
|
||||||
flags.push(value)
|
if (flags.length == 0) {
|
||||||
|
writer.done(base + 'skipping, no policy declared')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if (dryRun) {
|
if (dryRun) flags.push('--dry-run')
|
||||||
flags.push('--dry-run')
|
|
||||||
}
|
writer.replaceLn(base + 'Forgetting old snapshots… ⏳')
|
||||||
const env = getEnvFromBackend(backend)
|
const cmd = exec(
|
||||||
writer.replaceLn(name + to.blue + ' : ' + 'Forgeting old snapshots… ⏳')
|
'restic',
|
||||||
const cmd = exec('restic', ['forget', '--path', from, '--prune', ...flags], { env })
|
['forget', '--path', path, '--prune', ...flags],
|
||||||
|
{ env: getEnvFromBackend(backend) },
|
||||||
|
)
|
||||||
|
|
||||||
if (VERBOSE) console.log(cmd.out, cmd.err)
|
if (VERBOSE) console.log(cmd.out, cmd.err)
|
||||||
writer.done(name + to.blue + ' : ' + 'Done ✓'.green)
|
writer.done(base + 'Done ✓'.green)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const forgetLocation = (dryRun: boolean, name: string, backup: Location, policy?: ForgetPolicy) => {
|
export const forgetLocation = (name: string, backup: Location, dryRun: boolean) => {
|
||||||
const display = name.yellow + ' ▶ '
|
const display = name.yellow + ' ▶ '
|
||||||
if (!policy) {
|
const filler = new Array(name.length + 3).fill(' ').join('')
|
||||||
console.log(display + 'skipping, no policy declared')
|
let first = true
|
||||||
} else {
|
|
||||||
if (Array.isArray(backup.to)) {
|
for (const t of Array.isArray(backup.to) ? backup.to : [backup.to]) {
|
||||||
let first = true
|
const nameOrBlankSpaces: string = first ? display : filler
|
||||||
for (const t of backup.to) {
|
forgetSingle(nameOrBlankSpaces, t, backup, dryRun)
|
||||||
const nameOrBlankSpaces: string = first
|
if (first) first = false
|
||||||
? display
|
|
||||||
: new Array(name.length + 3).fill(' ').join('')
|
|
||||||
forgetSingle(dryRun, nameOrBlankSpaces, backup.from, t, policy)
|
|
||||||
if (first) first = false
|
|
||||||
}
|
|
||||||
} else forgetSingle(dryRun, display, backup.from, backup.to, policy)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,12 +51,10 @@ export const forgetAll = (backups?: Locations, flags?: Flags) => {
|
|||||||
backups = config.locations
|
backups = config.locations
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('\nRemoving old shapshots according to policy'.underline.grey)
|
console.log('\nRemoving old snapshots according to policy'.underline.grey)
|
||||||
const dryRun = flags ? flags['dry-run'] : false
|
const dryRun = flags ? flags['dry-run'] : false
|
||||||
if (dryRun) console.log('Running in dry-run mode, not touching data\n'.yellow)
|
if (dryRun) console.log('Running in dry-run mode, not touching data\n'.yellow)
|
||||||
|
|
||||||
for (const [name, backup] of Object.entries(backups)) {
|
for (const [name, backup] of Object.entries(backups))
|
||||||
const policy = config.locations[name].keep
|
forgetLocation(name, backup, dryRun)
|
||||||
forgetLocation(dryRun, name, backup, policy)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -215,8 +215,7 @@ const handlers: Handlers = {
|
|||||||
darwin: 'macos',
|
darwin: 'macos',
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = `autorestic_${platformMap[process.platform] ||
|
const name = `autorestic_${platformMap[process.platform] || process.platform}_${process.arch}`
|
||||||
process.platform}_${process.arch}`
|
|
||||||
const dl = json.assets.find((asset: any) => asset.name === name)
|
const dl = json.assets.find((asset: any) => asset.name === name)
|
||||||
|
|
||||||
const to = INSTALL_DIR + '/autorestic'
|
const to = INSTALL_DIR + '/autorestic'
|
||||||
|
@@ -103,7 +103,7 @@ export const getFlagsFromLocation = (location: Location, command?: string): stri
|
|||||||
values = [values]
|
values = [values]
|
||||||
|
|
||||||
for (const value of values)
|
for (const value of values)
|
||||||
flags = [...flags, `--${flag}`, value]
|
flags = [...flags, `--${String(flag)}`, String(value)]
|
||||||
}
|
}
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user