# Setting up FreeBSD with Auto ZFS snapshots



## churchi (Jul 8, 2010)

Well after issues with having some important files on my ZFS pool with out any backups or snapshots, i was wondering how i would go about setting up auto ZFS snapshots in FreeBSD?

What i would like to achieve is to enable a snapshot once a day and have 30 copies (1 month) then delete the oldest after one month to rotate the snapshots. Is this possible in FreeBSD? If so would someone be so kind as to share this with me and how i would achieve this.

I will be setting up another machine to mirror my current server for backups, however i am really interested in the snapshots that ZFS can provide for my file system.

If anyone has some setups that i could try to implement to automate this, then i would be really appreciative if you could share

thank you.


----------



## User23 (Jul 8, 2010)

http://www.solarisinternals.com/wik...ces_Guide#Recommendations_for_Saving_ZFS_Data

np


----------



## lme@ (Jul 8, 2010)

sysutils/zfs-snapshot-mgmt


----------



## jalla (Jul 8, 2010)

This gives me an opportunity to recommend Ralf Engelschall's exellent snapshot utility sysutils/freebsd-snapshot. It integrates nicely with periodic(8) for scheduling and amd(8) for on-demand mounting of snaps. Works both with zfs and ufs.

It's saved my ass more than once, like when I overwrote my kernel with one that was unbootable


----------



## DutchDaemon (Jul 8, 2010)

Look into the [port][/port] posting tag, people  Very nice!
http://forums.freebsd.org/misc.php?do=bbcode#port


----------



## graudeejs (Jul 8, 2010)

lme@ said:
			
		

> sysutils/zfs-snapshot-mgmt



ruby.... come on....
Wrote this in few minutes:
http://hg.bsdroot.lv/aldis/zfSnap

it's designed to be used with cron.
By default (age value) is set to keep snapshots for 30 days
you pass zfs filesystem names as args, that you want to make snapshots
if arg1 is *-r* then zfSnap will make recursive snapshots

snapshots will be save like:

```
a/home@2010-07-08_20:04:02
```
%Y-%m-%d_%T

how do you like it?
I haven't fully tested it yet.... but for now it looks good


----------



## jalla (Jul 8, 2010)

killasmurf86 said:
			
		

> how do you like it?
> I haven't fully tested it yet.... but for now it looks good



What it's lacking IMO (apart from UFS support of course) is the ability to keep a various number of snaps depending on age. IE, what I want from an automated setup is to take snapshots every couple of hours and keep them for a couple of days, then keep one daily snapshot up to a week and one weekly snapshot for, let's say, one month.

It would definitely take more than a few minutes to write, at least for me, but then fortunately such tools already exist in ports. Even in plain sh(1) if you're so inclined.
(I'll refrain from applying my newly learned knowledge of the port tag here, but I guess you catch my drift)


----------



## graudeejs (Jul 8, 2010)

jalla said:
			
		

> What it's lacking IMO (apart from UFS support of course) is the ability to keep a various number of snaps depending on age. IE, what I want from an automated setup is to take snapshots every couple of hours and keep them for a couple of days, then keep one daily snapshot up to a week and one weekly snapshot for, let's say, one month.
> 
> It would definitely take more than a few minutes to write, at least for me, but then fortunately such tools already exist in ports. Even in plain sh(1) if you're so inclined.
> (I'll refrain from applying my newly learned knowledge of the port tag here, but I guess you catch my drift)



simply add to your cron job either small script that will take snapshots with different pattern, or simply add entry per fs that you want to make snapshot for
for example
/etc/crontab

```
# zfs snapshots 2x a day
45      6,18    *       *       *       root    /usr/local/bin/zfSnap.sh -r tank
10      30      *       *       1       root    zfs snapshot -r tank/home@keep_`date +%Y-%m-%d_%T`
```

This will make snapshots of all file systems 2x a day
and 1 snapshot of /home and all it's sub-file-systems every Monday


----------



## churchi (Jul 9, 2010)

Firstly thank you all very much for the replies. I am hopeful from all of these replies that i can put in place a snapshot system that will save me from what happened yesterday.



			
				jalla said:
			
		

> This gives me an opportunity to recommend Ralf Engelschall's exellent snapshot utility sysutils/freebsd-snapshot. It integrates nicely with periodic(8) for scheduling and amd(8) for on-demand mounting of snaps. Works both with zfs and ufs.
> 
> It's saved my ass more than once, like when I overwrote my kernel with one that was unbootable



I am liking this port. A few questions on this:
1. Can this be configured to take a snapshot once a day, and just keep for 30 days only?
2. if the above can be done, can the utility auto delete once the 30 days has been up for the oldest snapshot?
3. can the snapshots be recursive if using the above way (deleting the oldest from 30 days ago) or would they have to be full snapshots every day if doing it this way?


>>lme@  	 sysutils/zfs-snapshot-mgmt

I have also looked into this script however i cant see a way for the script to delete the oldest snapshot after the period i select? if there is a way can someone show me please?


----------



## graudeejs (Jul 9, 2010)

try my script  it will auto delete snapshots older than, 30 days [those, that this script created or match pattern mentioned above]


----------



## churchi (Jul 9, 2010)

sweet, let me set it up and give it ago.

Do i need to schedule the weekly full snapshot, or this scrip will keep all needed snapshots for 30 days to recover files, then auto delete them after 30 days?


----------



## graudeejs (Jul 9, 2010)

churchi said:
			
		

> sweet, let me set it up and give it ago.
> 
> Do i need to schedule the weekly full snapshot, or this scrip will keep all needed snapshots for 30 days to recover files, then auto delete them after 30 days?



I'm not sure I understand you...
This script will create snapshots, if it's called with arguments (it will make recursive snapshots if first argument is -r).

after snapshots are made, it will check zfs snapshots, that match pattern.
From each snapshot that match pattern it will calculate creating time in seconds from Eposh
It will then compare this time to current time (in seconds from Eposh) minus age seconds.
If snapshot is older, than age seconds, then snapshot will be deleted

If you want some snapshots to remain you need to set crom, or somehow otherwise create zfs snapshots, that won't match patter used to identify zfs snapshots created with zfSnap.sh

Does this answer your question?


----------



## jalla (Jul 9, 2010)

killasmurf86 said:
			
		

> simply add to your cron job either small script that will take snapshots with different pattern, or simply add entry per fs that you want to make snapshot for
> for example
> /etc/crontab
> 
> ...



I'm not convinced

1) Time to keep snapshots is still hardcoded in your script
2) The weekly snapshots aren't rotated automatically
3) You've not deviced any practical method of differentiating hourly/daily/weekly snapshots, except by adding crontab entries to handle every special case

Instead of a shitload of crontab entries, I find it infinitely more flexible (and elegant) with one simple entry in /etc/periodic.conf


```
snapshot_schedule="/:4:7:3@11,14"
```

That's it


----------



## jalla (Jul 9, 2010)

churchi said:
			
		

> Firstly thank you all very much for the replies. I am hopeful from all of these replies that i can put in place a snapshot system that will save me from what happened yesterday.
> 
> 
> 
> ...



With freebsd-snapshot you just put your shedule in /etc/periodic.conf, something like

```
snapshot_schedule="/fs:0:30:0"
```
which means "take a snapshot every day (at midnight), and keep the last 30". Older snaps just "fall off the end".

If you ever find you want to checkpoint your system a few times during the day, just change the schedule

```
snapshot_schedule="/fs:0:30:8@10:12:14:16"
```

Not sure what you mean with 3. but any snapshot is by design "full" in the sense that it represents the complete filesystem at the time it's taken. The actual size of a snapshot though is the difference between that and the live fs.

ps. As many people seem to think snapshots were invented with zfs, I keep stressing the point that they're available with UFS as well (and equally useful).
I should note however that there's a hard limit of 20 snaps per filesystem in UFS.


----------



## graudeejs (Jul 9, 2010)

jalla said:
			
		

> I'm not convinced
> 
> 1) Time to keep snapshots is still hardcoded in your script
> 2) The weekly snapshots aren't rotated automatically
> ...



*You can adjust the script* to your needs, can't you? and it's really simple to extend it...

and instead of shitload of contab entries, write simple sh script, where you set, how and which zfs file systems you want to backup and exec it as many times as you want...

K.I.S.S.

P.S.
maybe I'll improve things that you noted


----------



## jalla (Jul 9, 2010)

Hardcoding this stuff in the script is not the way to go. You should factor out all the variables and keep the script itself generic IMO. As to simplicity, a single line in a config file to control all periodic snapshots, which filesystems, what time to snapshot, how many to keep, that's what I call simple.

When you deside to reinvent the wheel you should opt to improve it. No offense, but your "wheel" in this case looks distinctly square to me.


----------



## graudeejs (Jul 9, 2010)

jalla said:
			
		

> Hardcoding this stuff in the script is not the way to go. You should factor out all the variables and keep the script itself generic IMO. As to simplicity, a single line in a config file to control all periodic snapshots, which filesystems, what time to snapshot, how many to keep, that's what I call simple.
> 
> When you deside to reinvent the wheel you should opt to improve it. No offense, but your "wheel" in this case looks distinctly square to me.



The wheel that I made was especially for particular road.... enough talks....
Check updates, when I improve it


----------



## tdb@ (Jul 13, 2010)

Take a look at this thread:

http://forums.freebsd.org/showthread.php?t=15004


----------



## churchi (Jul 15, 2010)

jalla said:
			
		

> With freebsd-snapshot you just put your shedule in /etc/periodic.conf, something like
> 
> ```
> snapshot_schedule="/fs:0:30:0"
> ...




Cheers thanks guys for all the help. I have decided to give freebsd-snapshot a quick go.

So i have edited my /etc/periodic.conf
and i have the following in there:

```
monthly_statistics_enable="YES"
monthly_statistics_report_devices="YES"
monthly_statistics_report_ports="YES"

snapshot_enable="YES"
snapshot_schedule="/storage1:0:30:0"
```

Do i have to edit anything else in the /etc/crontab for example? or will everything be taken care of by adding in these lines into periodic.conf

```
snapshot_enable="YES"
snapshot_schedule="/storage1:0:30:0"
```

cheers


----------



## churchi (Jul 21, 2010)

Hi All,

i have setup the above and still can't seem to find any snapshots being taken daily.



```
[root@server-01 /home/churchi]# zfs list -r -t snapshot
no datasets available
```

Is there a better way like adding the above (freebsd-snapshot) to cron? at least i know that cron works on my system.

Thanks.


----------



## jalla (Jul 21, 2010)

You need an addition to /etc/crontab as well


```
0 * * * *       root    /usr/local/sbin/periodic-snapshot hourly
0 0 * * *       root    /usr/local/sbin/periodic-snapshot daily
0 0 * * 0       root    /usr/local/sbin/periodic-snapshot weekly
```


----------



## churchi (Jul 21, 2010)

cheers thanks jalla,

so with just adding: 

```
snapshot_enable="YES"
snapshot_schedule="/storage1:0:30:0"
```
to /etc/periodic.conf

and adding the above lines:

```
0 * * * *       root    /usr/local/sbin/periodic-snapshot hourly
0 0 * * *       root    /usr/local/sbin/periodic-snapshot daily
0 0 * * 0       root    /usr/local/sbin/periodic-snapshot weekly
```
to /etc/crontab

Setting up this will allow for backup of my ZFS pool of /storage1/

Is that all i need to complete and setup for this to be taking snapshots?

Thanks.


----------



## jalla (Jul 21, 2010)

In principle, yes. But you must specify the datasets you want to snapshot, not the pool


```
snapshot_schedule="/storage1/data1:0:30:0 /storage1/data2:0:30:0"
```


----------



## churchi (Jul 21, 2010)

awesome mate. thanks for clearing that up.

so this is my zfs list

```
[root@server-01 /etc]# zfs list
NAME                   USED  AVAIL  REFER  MOUNTPOINT
storage1              2.23T  8.46T  45.4K  /storage1
storage1/data         2.23T  8.46T  1.46T  /storage1/data
storage1/data/photos   787G  8.46T   787G  /storage1/data/photos
[root@server-01 /etc]# ls /storage1/data/
```

If i snapshot /storage1/data
will that snapshot /storage1/data/photos
as well?


cheers


----------



## jalla (Jul 21, 2010)

No, snapshots taken this way are not recursive. To change that you can modify /usr/local/sbin/snapshot

```
gnome:/usr/local/sbin# diff snapshot.orig snapshot
292c292
<                 system zfs destroy "$fs_name@$fs_tag.$i"
---
>                 system zfs destroy -r "$fs_name@$fs_tag.$i"
301c301
<                 system zfs destroy "$fs_name@$fs_tag.$i"
---
>                 system zfs destroy -r "$fs_name@$fs_tag.$i"
307c307
<                     system zfs rename "$fs_name@$fs_tag.$i" "$fs_name@$fs_tag.$j"
---
>                     system zfs rename -r "$fs_name@$fs_tag.$i" "$fs_name@$fs_tag.$j"
313c313
<             system zfs snapshot "$fs_name@$fs_tag.$fs_gen"
---
>             system zfs snapshot -r "$fs_name@$fs_tag.$fs_gen"
```

This is fine for my usage as I don't want to to do anything but recursive snapshots. Unfortunaly there's no simple way to have the script support both recursive an non-recursive snapshots


----------



## graudeejs (Aug 1, 2010)

jalla said:
			
		

> Hardcoding this stuff in the script is not the way to go. You should factor out all the variables and keep the script itself generic IMO. As to simplicity, a single line in a config file to control all periodic snapshots, which filesystems, what time to snapshot, how many to keep, that's what I call simple.
> 
> When you deside to reinvent the wheel you should opt to improve it. No offense, but your "wheel" in this case looks distinctly square to me.



check out latest version in git repo
http://hg.bsdroot.lv/aldis/zfSnap/


----------



## jalla (Aug 1, 2010)

Well, with my currnet setup I keep 4 weekly snapshots (taken sunday night), 7 nightly snapshots (taken at midnight), and a number of houly snaps (@10,@14,@16)
Tell me how  can use you're script to do something similar.


----------



## graudeejs (Aug 2, 2010)

jalla said:
			
		

> Well, with my currnet setup I keep 4 weekly snapshots (taken sunday night), 7 nightly snapshots (taken at midnight), and a number of houly snaps (@10,@14,@16)
> Tell me how  can use you're script to do something similar.



oh... yesterday, at night a good idea hit my head  I will finish it today, and then I will tell you [zfSnap.sh will be quite rewritten]


----------



## graudeejs (Aug 2, 2010)

finished rewriting my script



			
				jalla said:
			
		

> Well, with my currnet setup I keep 4 weekly snapshots (taken sunday night), 7 nightly snapshots (taken at midnight), and a number of houly snaps (@10,@14,@16)
> Tell me how  can use you're script to do something similar.



every 2 hours take recursive snapshots of zpool/zfs1 zpool/zfs2, and not recursive snapshots of zpool/zfs3 andzpool/zfs4. keep these snapshots for 1 week

```
0 */2 * * * root /usr/local/bin/zfSnap.sh -a 1w -r zpool/zfs1 zpool/zfs2 -R zpool/zfs3 zpool/zfs4
```

same as above exept make montly snapshots, and keep zpool/zfs1 zpool/zfs2 zpool/zfs3 snapshots for one and half year. Keep zpool/zfs4 for year

```
0 0 1 * * root /usr/local/bin/zfSnap.sh -a 1y6m -r zpool/zfs1 zpool/zfs2 -R zpool/zfs3 -a 1y zpool/zfs4
```

Delete old snapshots every night at 2:00 am

```
0 2 * * * root /usr/local/bin/zfSnap.sh -d
```
I think making 1 entry for deleting old snapshots is better, than adding -d to entries above, because deleting snapshots is slower, than creating them.... and who cares is some snapshots will stay available few hours longer 

So what do you think?

P.S.
for more info on how to use /etc/crontab see crontab(5)


----------



## jalla (Aug 3, 2010)

Haven't tested the script, but as far as I can tell it should work as advertised. With a number of crontab entries it seems to support differing hourly/daily/weekly/whatever schedules. The idea of coding the ttl into the snapshot name and use that for recycling is smart.

Personally I use snapshots both for ufs and zfs so sysutils/freebsd-snapshot still works better for me.


----------



## graudeejs (Aug 3, 2010)

jalla said:
			
		

> Haven't tested the script, but as far as I can tell it should work as advertised. With a number of crontab entries it seems to support differing hourly/daily/weekly/whatever schedules. The idea of coding the ttl into the snapshot name and use that for recycling is smart.
> 
> Personally I use snapshots both for ufs and zfs so sysutils/freebsd-snapshot still works better for me.



Thanks for feedback.... 

P.S.
I've submitted port http://www.freebsd.org/cgi/query-pr.cgi?pr=149188
Also writing wiki page now http://wiki.bsdroot.lv/zfsnap


----------



## tdb@ (Aug 3, 2010)

killasmurf86 said:
			
		

> P.S. I've submitted port http://www.freebsd.org/cgi/query-pr.cgi?pr=149188



Committed 

Tim.


----------



## tdb@ (Aug 3, 2010)

Feature suggestion: a -n flag to say what it would do but without actually doing it.


----------



## graudeejs (Aug 3, 2010)

tdb@ said:
			
		

> Feature suggestion: a -n flag to say what it would do but without actually doing it.



committed to HEAD. Check if you like it, and how to improve it (Then I will submit update PR. lol)


----------



## tdb@ (Aug 3, 2010)

killasmurf86 said:
			
		

> committed to HEAD. Check if you like it, and how to improve it (Then I will submit update PR. lol)
> http://aldis.git.bsdroot.lv/zfSnap/tree/zfSnap.sh



It works 

But, I'd probably have implemented it a bit differently. By having the command in the dry_run block and in the non-dry_run block you run the risk of changing one but not the other. Maybe use a variable so they set in one place? Minor niggle though.

The other thing is your check for a valid ZFS filesystem. Would running "zfs list -H $1" and checking the output be more efficient? I have quite a few filesystems and snapshots, so "zfs list -H" takes a while to run. Again, a minor niggle since it only happens when doing a dry run.

Tim.


----------



## graudeejs (Aug 3, 2010)

tdb@ said:
			
		

> But, I'd probably have implemented it a bit differently. By having the command in the dry_run block and in the non-dry_run block you run the risk of changing one but not the other. Maybe use a variable so they set in one place? Minor niggle though.


commited to HEAD (won't make it to v1.1.7 Thanks for tip



			
				tdb@ said:
			
		

> The other thing is your check for a valid ZFS filesystem. Would running "zfs list -H $1" and checking the output be more efficient? I have quite a few filesystems and snapshots, so "zfs list -H" takes a while to run. Again, a minor niggle since it only happens when doing a dry run.



hmm I think if you have many zfs files systems (for example on some advanced server) doing zfs list -H once will be much faster

P.S.
Mod... do you think last few posts should be split into new thread?


----------



## tdb@ (Aug 3, 2010)

killasmurf86 said:
			
		

> hmm I think if you have many zfs files ystems (for example on some advanced server) doing zfs list -H once will be much faster




```
# /usr/bin/time zfs list -H
pool0   92.5G   39.4G   18K     legacy
...
        2.62 real         0.02 user         0.02 sys
```


```
# /usr/bin/time zfs list -H pool0
pool0   92.5G   39.4G   18K     legacy
        0.09 real         0.00 user         0.00 sys
```

Given you're only actually checking those given on the command line it seems like it'd be quicker to check individually.

But, I'd not worry since it's only done on a dry run, which you only do once or twice to test.


----------



## tdb@ (Aug 5, 2010)

I've been running this script for a couple of days now and it's working great for me.

But I wonder, is there any way to back the deletes recursive? It takes some time to walk over all my filesystems deleting snapshots when they were all made quickly using recursion at the top level.

The only way I can think of to do it is by adding optional arguments to the delete flag which work the same as the normal usage. So I could run:


```
zfSnap -d -r pool
```

What do you think? Maybe you have a better idea?


----------



## graudeejs (Aug 5, 2010)

tdb@ said:
			
		

> I've been running this script for a couple of days now and it's working great for me.
> 
> But I wonder, is there any way to back the deletes recursive? It takes some time to walk over all my filesystems deleting snapshots when they were all made quickly using recursion at the top level.
> 
> ...



Good idea.... I will try it


----------



## graudeejs (Aug 5, 2010)

implemented
anyone who is interested in testing

```
$ git clone -b zfs-destroy-recursive-snapshots http://aldis.git.bsdroot.lv/zfSnap
```

EDIT:
branch deleted
port (sysutils/zfsnap) updated to latest version


----------

