This post is an evolution of my prior post here.
So I got a Synology NAS. Set up a rest-server
docker container, and created a user profile backup script to be pushed out via group policy.
WINDOWS USER PROFILE BACKUP SCRIPT
@ECHO OFF
REM The following is the command to call this batch file from Task Scheduler for the "lock screen" or "login" event.
rem %COMSPEC% /c IF EXIST \\domain.local\netlogon\* ( start "Backup Agent" /min "\\domain.local\netlogon\restic-backup.bat" ) ^& exit
ECHO Setting environment variables, please wait...
SET RESTIC_REPOSITORY=rest:http://san:8000/repo
SET RESTIC_PASSWORD=ABCDEFGHIJKLMNOPQRSTUVWXYZ
REM Skip backup for administrators
IF /I %USERNAME% == administrator exit
REM Delete stale script lock file in case of prior interruption
del /f /s /q /a \\mss.ramlaw.local\ram-backup\.restic\logs\~%USERNAME%-%COMPUTERNAME%.LOCK
REM Determine if 32-bit or 64-bit OS
reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set RESTIC_BIN=restic_x86.exe || set RESTIC_BIN=restic.exe
:START
REM Count .lock files created by current backups
FOR /f %%i in ('dir /b \\san\data\.restic\logs\*.lock ^| find /v /c "::"') do set LOCKS=%%i
CLS
ECHO Restic Backup Agent by Akrabu
ECHO.
REM Check for too many concurrent backups
IF %LOCKS% GEQ 6 (
ECHO Too many concurrent backups; waiting...
REM Generate random number from 1 to 300 and wait that many seconds
SET /A _RAND=%RANDOM% %% 300 + 1
TIMEOUT %_RAND%
GOTO START
)
REM Placeholder for a mandatory pause
rem PING localhost -n 10 >NUL
REM Create lock file
ECHO. > \\san\data\.restic\logs\~%USERNAME%-%COMPUTERNAME%.LOCK
REM Write log header
ECHO. >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO ------------------------------------------------------- >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO. >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO STARTED: %DATE% %TIME% >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
REM Check if repository is locked and write to log
IF NOT EXIST \\san\data\.restic\unlocked (
ECHO. >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO REPOSITORY LOCKED OR UNAVAILABLE >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
)
REM Check for low bandwidth users
IF /I %USERNAME% == slowusername GOTO SLOW
REM Run backup, write output to log
ECHO Backing up user profile, please wait...
IF EXIST \\san\data\.restic\unlocked (
\\san\data\.restic\%RESTIC_BIN% backup --cleanup-cache %USERPROFILE% %PROGRAMDATA% --tag USER_PROFILE --exclude-file=\\san\data\.restic\excludes.txt >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
GOTO DONE
)
:SLOW
REM Run SLOW backup, write output to log
ECHO Backing up user profile, please wait...
IF EXIST \\san\data\.restic\unlocked (
ECHO SLOW RUN: >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
\\san\data\.restic\%RESTIC_BIN% backup --cleanup-cache %USERPROFILE% %PROGRAMDATA% --tag USER_PROFILE --exclude-file=\\san\data\.restic\excludes.txt --limit-upload=1024 >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO. >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
GOTO DONE
)
:DONE
REM Write log footer
ECHO. >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
ECHO STOPPED: %DATE% %TIME% >>\\san\data\.restic\logs\%USERNAME%-%COMPUTERNAME%.LOG
REM Delete lock file
del /f /s /q /a \\san\data\.restic\logs\~%USERNAME%-%COMPUTERNAME%.LOCK
:END
REM Done!
CLS
ECHO Restic Backup Agent by Akrabu
ECHO.
ECHO Backup complete!
ECHO.
ECHO ---
REM Loop commands
rem TIMEOUT 3600
rem GOTO START
EXIT
This will set the repo and password variables. IF the file “unlocked” exists and is accessible via the SAN, it will start restic in idle priority mode, backup the user profile, excluding a bunch of stuff (mostly browser caches), tag it with USER_PROFILE, clean up the cache if necessary, and append to a log file with their username. It also creates empty “STARTED” and “STOPPED” files in the LOG directory, to quickly see what times the script started and stopped. It will then wait one hour (3600 seconds), and do it all over again. If the “unlocked” file isn’t available, it will wait one hour and try again.
I have this script set to run as a GPO for all my domain users. The specific policy is under User Profile Backup Script (what I named it) > User Configuration > Policies > Administrative Templates > System > Logon > Run these programs at user logon. The specific command I use is cmd /c start "Backup Agent" /low /min "\\domain.local\netlogon\restic-backup.bat"
LOG FILE OUTPUT
-------------------------------------------------------
STARTED: Mon 07/15/2019 17:57:34.00
Files: 252 new, 387 changed, 9607 unmodified
Dirs: 0 new, 2 changed, 0 unmodified
Added to the repo: 120.910 MiB
processed 10246 files, 3.495 GiB in 0:53
snapshot d21c99df saved
STOPPED: Mon 07/15/2019 17:58:32.13
-------------------------------------------------------
STARTED: Tue 07/16/2019 11:50:20.12
Files: 230 new, 430 changed, 9769 unmodified
Dirs: 0 new, 2 changed, 0 unmodified
Added to the repo: 121.821 MiB
processed 10429 files, 3.552 GiB in 0:35
snapshot 5aa9911e saved
STOPPED: Tue 07/16/2019 11:50:58.58
SERVER BACKUP SCRIPT
@ECHO OFF
ECHO Starting SERVER_NAME backup...
paexec \\SERVER_NAME -u domain\administrator -p PASSWORD -e -c -f -d -background -csrc "\\san\data\.restic\restic.exe" restic.exe -r rest:http://san:8000/repo --password-file \\san\data\.restic\password.txt backup --cleanup-cache --exclude-file=\\san\data\.restic\excludes.txt --tag SERVER "E:\Shares" >>\\san\data\.restic\logs\!SERVER_NAME.LOG
Unfortunately I have not figured out how to log PAEXEC command output.
EXCLUDES FILE
AppData\Local\Microsoft\Windows\INetCookies\**
.ost
.tmp
AppData\Local\Microsoft\Windows\INetCache\
AppData\Local\Microsoft\Internet Explorer\DOMStore\**
AppData\Local\Microsoft\Internet Explorer\imagestore\**
AppData\Local\Microsoft\Internet Explorer\imagestore\**
C:\Users\admin
C:\Users\administrator
Cache\**
Code Cache\**
Copitrak\LOGGING\**
CryptnetUrlCache\**
GPUCache\**
IconCache*.db
Media Cache\**
Temp\**
Temporary Internet Files\**
WER\ReportQueue\**
WebCache\**
cache\**
iconcache*.db
temp\**
MAINTENANCE SCRIPT (WORK-IN-PROGRESS)
@ECHO OFF
SET RESTIC_REPOSITORY=rest:http://san:8000/repo
SET RESTIC_PASSWORD=ABCDEFGHIJKLMNOPQRSTUVWXYZ
:START
IF EXIST \\san\data\.restic\unlocked (
ECHO Waiting for backups to finish, please wait...
del /f /s /q /a \\san\data\.restic\unlocked
TIMEOUT 60
GOTO START
)
TIMEOUT 28800
ECHO.
( dir /b /a "\\path\to\repository\LOCKS" | findstr . ) > nul && (
ECHO Unlocking repository, please wait...
ECHO.
restic unlock
GOTO START
ECHO.
)
ECHO Cleaning stale script locks, please wait...
del /f /s /a /q \\san\data\.restic\logs\*.lock
ECHO.
REM EXTRA COMMANDS GO HERE
rem restic tag --set
rem restic forget
ECHO Rebuilding index, please wait...
restic rebuild-index
ECHO Cleaning repository, please wait...
ECHO.
restic forget --keep-within 336h --keep-hourly 672 --keep-daily 90 --keep-weekly 26 --keep-monthly 12 --group-by host --cleanup-cache --prune
ECHO.
ECHO Checking repository integrity, please wait...
ECHO.
restic check
ECHO.
ECHO. > \\san\data\.restic\unlocked
pause
Right now I have it waiting 8 hours after removing the “unlocked” file and 15 minutes after running restic unlock
. I have the repo shared mainly as a REST-SERVER, but have a READ-ONLY SMB share for syncing the repo to off-site storage, and for the IF EXIST \\path\to\repository\locks\*
statement. I did that to protect against cryptolocker viruses. As with everything here, use at your own risk!
Ps. Using rest-server
instead of a SMB share is WAY faster. Highly recommend it!
Pps. I was almost swayed by Synology’s “Active Backup” software - but ultimately it just didn’t give me the fine-grain control that restic does. If you need bare-metal recovery for all users, it’s worth looking into. I just want the user profiles, myself.