How to create automatic backups of hub database

Thanks @john.hart3706, I modified your PowerShell script to make it little bit more secure, configurable and added a retention policy, it will keep the last X backups and delete the rest, if less than X it will not delete any file...

$HubitatHost = "IP or Hostname"
$BackupPath = "Drive:\BackupFolder\SubFolder"
$RetentionPolicy = 30
$Protocol = "HTTPS"
$DisableCertificateValidation = $true


# Get Backup User Credentials
$BackupCredentials = "$BackupPath\BackupCredentials.xml"
If (!(Test-Path $BackupCredentials)) {
    $Credentials =  Get-Credential
    $Credentials | Export-CliXml -Path $BackupCredentials
} Else {
    Try {
        $Credentials = Import-CliXml -Path $BackupCredentials
    } Catch {
        Throw "Error reading credentials file, it may have been generatd with a diferent computer/account, try deleting the file and recreating it."
    }
}

# Sets Security Protocol to TLS 1.2 and certificate validation preference.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
If ($DisableCertificateValidation) { [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } }

# Request Login Session
$Body = @{
    username = $Credentials.UserName
    password  = ([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credentials.Password)))
}

$url = "$Protocol`://$HubitatHost/hub/backupDB?fileName=latest"
$output = "$BackupPath\HubitatBackup_$(get-date -f yyyy-MM-dd-HHmmss).lzf"
$LoginResponse = Invoke-WebRequest "$Protocol`://$HubitatHost/login" -SessionVariable 'Session' -Body $Body -Method 'POST'

# Check if Login was successful
If ($LoginResponse.BaseResponse.ResponseUri -eq "$Protocol`://$HubitatHost/login") {
    Throw "Error Logging In to Hubitat, please check credentials."
}

# Download the Backup file
$ProfileResponse = Invoke-WebRequest $url -OutFile $output -WebSession $Session

# Apply Retention Policy
gci $BackupPath -Recurse| where {$_.extension -eq ".lzf" -and -not $_.PsIsContainer} | sort CreationTime -desc | select -Skip $RetentionPolicy | Remove-Item -Force

First time it runs it will ask for credentials and save them in an encrypted file with the backups. To change the credentials just delete the "BackupCredentials.xml" file and run manually again.

It will also check that it is able to login successfully or otherwise you'll end with a bunch of useless backup files containing the login page error.

Please note: The credentials file can only be used in the computer it was generated by the user who generated it. This will not stop anybody who knows what theyโ€™re doing from decrypting your password or from reusing your encrypted password if they are able to compromise your login. The whole point of converting your password to a SecureString and storing it in a file is to keep it out of plain text in your scripts so that itโ€™s not as easily discovered.

Furthermore, because of the login mechanism currently implemented and the fact that Hubitat does not currently implement SSL, the password is still sent in plain text...

EDIT: Added support for HTTPS that was added to HE Firmware 2.0.5 but as the certificate is Self-Siged and does not include a host name, the script disables certificate validation. This is not ideal but much better as the password is not sent in clear text.

10 Likes