Content is based on this article on yubico documentation found here:


  • OpenSSH  (v9.4+) found here
  • Git (v2.42+) found here
  • Gitlab account configured (no matter if or if you have CE (community edition) , I used it for proprietary CE  and it worked so it should work with not problem with online version)


On existing reporsitory you need to adjust that SSH will be used instead of PGP

git config gpg.format ssh

Generate new key that supports Yubikey (ECDSA key). During process you will be asked to select device for signing and confirm generation of key with touch on your Yubikey.

ssh-keygen -t ecdsa-sk -f c:\users\yourusername\.ssh\id_ecdsa_sk

Setup to use key for signing

git config user.signingKey c:\users\yourusername\.ssh\id_ecdsa_sk

If you have more ssh keys you should aready have config file here c:\users\yourusername\.ssh\config, add for destination Gitlab server newly created private key, this ensures that our new key will be used.

Copy content of  c:\users\yourusername\.ssh\ to c:\users\yourusername\.ssh\allowed_signers,

Run command to define allowd_signers

git config gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers

Paste public part also to Gitlab account.

And that’s it! If i did not forget on anything, this should be enough and

Powershell commands for fixing WSUS on clients

net stop wuauserv
net stop cryptSvc
net stop bits
net stop msiserver
Ren C:\Windows\SoftwareDistribution SoftwareDistribution.old
Ren C:\Windows\System32\catroot2 Catroot2.old
net start wuauserv
net start cryptSvc
net start bits
net start msiserver


Batch file for fixing  WSUS on client:

@echo off

:: Created by: Shawn Brink
:: Created on: October 1, 2015
:: Updated on: March 8, 2021
:: Tutorial:

:: Prompt to Run as administrator
Set "Variable=0" & if exist "%temp%\getadmin.vbs" del "%temp%\getadmin.vbs"
fsutil dirty query %systemdrive%  >nul 2>&1 && goto :(Privileges_got)
If "%1"=="%Variable%" (echo. &echo. Please right-click on the file and select &echo. "Run as administrator". &echo. Press any key to exit. &pause>nul 2>&1& exit)
cmd /u /c echo Set UAC = CreateObject^("Shell.Application"^) : UAC.ShellExecute "%~0", "%Variable%", "", "runas", 1 > "%temp%\getadmin.vbs"&cscript //nologo "%temp%\getadmin.vbs" & exit

:: Checking and Stopping the Windows Update services
set b=0

set /a b=%b%+1
if %b% equ 3 (
   goto end1
net stop bits
echo Checking the bits service status.
sc query bits | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto bits 
goto loop2

echo Cannot reset Windows Update since "Background Intelligent Transfer Service" (bits) service failed to stop. Please restart the computer, and try again.
goto Start

set w=0

set /a w=%w%+1
if %w% equ 3 (
   goto end2
net stop wuauserv
echo Checking the wuauserv service status.
sc query wuauserv | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto wuauserv 
goto loop3

echo Cannot reset Windows Update since "Windows Update" (wuauserv) service failed to stop. Please restart the computer, and try again.
goto Start

set app=0

set /a app=%app%+1
if %app% equ 3 (
   goto end3
net stop appidsvc
echo Checking the appidsvc service status.
sc query appidsvc | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto appidsvc 
goto loop4

echo Cannot reset Windows Update since "Application Identity" (appidsvc) service failed to stop. Please restart the computer, and try again.
goto Start

set c=0

set /a c=%c%+1
if %c% equ 3 (
   goto end4
net stop cryptsvc
echo Checking the cryptsvc service status.
sc query cryptsvc | findstr /I /C:"STOPPED" 
if not %errorlevel%==0 ( 
    goto cryptsvc 
goto Reset

echo Cannot reset Windows Update since "Cryptographic Services" (cryptsvc) service failed to stop. Please restart the computer, and try again.
goto Start

Ipconfig /flushdns
del /s /q /f "%ALLUSERSPROFILE%\Application Data\Microsoft\Network\Downloader\qmgr*.dat" 
del /s /q /f "%ALLUSERSPROFILE%\Microsoft\Network\Downloader\qmgr*.dat"
del /s /q /f "%SYSTEMROOT%\Logs\WindowsUpdate\*"

if exist "%SYSTEMROOT%\winsxs\pending.xml.bak" del /s /q /f "%SYSTEMROOT%\winsxs\pending.xml.bak" 
if exist "%SYSTEMROOT%\winsxs\pending.xml" ( 
    takeown /f "%SYSTEMROOT%\winsxs\pending.xml" 
    attrib -r -s -h /s /d "%SYSTEMROOT%\winsxs\pending.xml" 
    ren "%SYSTEMROOT%\winsxs\pending.xml" pending.xml.bak 
if exist "%SYSTEMROOT%\SoftwareDistribution.bak" rmdir /s /q "%SYSTEMROOT%\SoftwareDistribution.bak"
if exist "%SYSTEMROOT%\SoftwareDistribution" ( 
    attrib -r -s -h /s /d "%SYSTEMROOT%\SoftwareDistribution" 
    ren "%SYSTEMROOT%\SoftwareDistribution" SoftwareDistribution.bak 
if exist "%SYSTEMROOT%\system32\Catroot2.bak" rmdir /s /q "%SYSTEMROOT%\system32\Catroot2.bak" 
if exist "%SYSTEMROOT%\system32\Catroot2" ( 
    attrib -r -s -h /s /d "%SYSTEMROOT%\system32\Catroot2" 
    ren "%SYSTEMROOT%\system32\Catroot2" Catroot2.bak 

:: Reset Windows Update policies
reg delete "HKCU\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f
reg delete "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate" /f
reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" /f
reg delete "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\WindowsUpdate" /f
gpupdate /force

:: Reset the BITS service and the Windows Update service to the default security descriptor


:: Reregister the BITS files and the Windows Update files
cd /d %windir%\system32
regsvr32.exe /s atl.dll 
regsvr32.exe /s urlmon.dll 
regsvr32.exe /s mshtml.dll 
regsvr32.exe /s shdocvw.dll 
regsvr32.exe /s browseui.dll 
regsvr32.exe /s jscript.dll 
regsvr32.exe /s vbscript.dll 
regsvr32.exe /s scrrun.dll 
regsvr32.exe /s msxml.dll 
regsvr32.exe /s msxml3.dll 
regsvr32.exe /s msxml6.dll 
regsvr32.exe /s actxprxy.dll 
regsvr32.exe /s softpub.dll 
regsvr32.exe /s wintrust.dll 
regsvr32.exe /s dssenh.dll 
regsvr32.exe /s rsaenh.dll 
regsvr32.exe /s gpkcsp.dll 
regsvr32.exe /s sccbase.dll 
regsvr32.exe /s slbcsp.dll 
regsvr32.exe /s cryptdlg.dll 
regsvr32.exe /s oleaut32.dll 
regsvr32.exe /s ole32.dll 
regsvr32.exe /s shell32.dll 
regsvr32.exe /s initpki.dll 
regsvr32.exe /s wuapi.dll 
regsvr32.exe /s wuaueng.dll 
regsvr32.exe /s wuaueng1.dll 
regsvr32.exe /s wucltui.dll 
regsvr32.exe /s wups.dll 
regsvr32.exe /s wups2.dll 
regsvr32.exe /s wuweb.dll 
regsvr32.exe /s qmgr.dll 
regsvr32.exe /s qmgrprxy.dll 
regsvr32.exe /s wucltux.dll 
regsvr32.exe /s muweb.dll 
regsvr32.exe /s wuwebv.dll
regsvr32.exe /s wudriver.dll
netsh winsock reset
netsh winsock reset proxy

:: Set the startup type as automatic
sc config wuauserv start= auto
sc config bits start= auto 
sc config DcomLaunch start= auto 

net start bits
net start wuauserv
net start appidsvc
net start cryptsvc

:: Restart computer

Umbrel – notes and hints

I’m starting to research what can be done with Umrel service. I initially start to deal with it due to configuration of Bitcoin node and eventually learn how to deal with Lightning node. It was a big suprise, how much thigs can be installed as docker image over Umrel. I think that this servie worth to research so here is link to the project:

How install umbrel app over command line

Sometimes, installation of umbrel app might failed and the reason cannot be found on the first seen. To get over it you might try to find app over shell, as result you might see an error message.


cd umbrel

sudo ./scripts/app install pi-hole


Redirect Bitcoin Node with addional storage

Even Umrel can be configured over Raspberry 4. Due to lack of such hardware i rather decide to use my proxmox server and use Ubuntu to get it work. Everything was quite straightforward. The only issue i found is that Bitcon app does not have explicitly customizable storage that is used for Bitcon Node app data. Blockchain size is at time of writing this article about 500 GB. Therfore i have prepared separated virtual storage just for this purpose.

Prepare disk

Let´s assume that disk is physically connected to your Ubuntu system. You would need to logon to console with root or use sudo su to switch to root.

For easir setup i would suggest to install gparted and open it with following command:


apt install gparted


Once you open gparted, swith in right combo box device you want to adjust. In my case it was /dev/sdb with 1TB  size. You would need to create new partition table with selecting Device-> Create Partition Table and  on newly attached disk and create ext4 filesystem. After selecting everything to desired state click on Apply All Operation (green circle with check mark) for apply changes.


Gparted steps

It is very helpful to get UUID of partition that can be used for automatic mount of disk to filesystem. So right-click partition and select Information option to find out this number.

gparted information

Now just copy this UUID to you notes, you will need it in next steps!


Now we can configure mount file to allow automatic mount of newly created partition. Let´s create mount folder and set ownership of user where Umbrel is used.

Replace:johndoe with real name of user!!!

Note:Not sure if it is neded but i rather changed ownership of folder itsel as well as  mounted disk. chown might not be needed but since i did not try it i rather writing it here to be sure that guide is working for sure. 

Suppose the mount folder will be /media/data

mkdir /media/data

chown -R johndoe:johndoe /media/data

Edit fstab with your favouring editor.

nano /etc/fstab

Add there line for mounting for me working this (please adjust UUID to yours copied from gparted:


UUID=5b7fe1b3-93c8-4399-8a05-ef8653b2d13b /media/data ext4 defaults 0 2

After saving the file exit editor and perform following steps, mounting of partition and ensuring that disk is owned by user used for Umbrel.

mount /media/data

chown -R martin:martin /media/data

Adjust docker of Bitcon Node app

Installation of Umbrel is usually in the User Home foder. Once you install Bitcoin Node app you would need to adjust yaml file for Bitcoin Node app. In home folder you should have umbrel folder, you shoudl successfully with this commands that perform stop of docker service and open yaml file where path need to be adjusted. Please ensure that you have console opened in context of user under which you have installed umbrel otherwise command cd will swithc to actively used profile!!!

Please back your yml file before edit it!


cd umbrel/



cd umbrel/

cd app-data/

cd bitcoin/

nano docker-compose.yml

Adjust in cocker-compose.yml file locations regarding to service (here I´m not user if it was needed but rather check it).

docker-compose.yml service

What i definelty need to adjust is bitcoinid section where i modified path in volumes from ${PWD}:/data/.bitcoin  to /media/data:/data/.bitcoin. And added line with /dev/sdb1:/dev/sdb1 to ensure that docker can find this device.


After saving docker-compose.yml file swithc back to umbrel folder and start docker service.



cd umbrel/



If all goes well you should see that Bitcoin Node docker was started sucessfully. If something went wrong you should see it in console.



This docker implementation does not work once you move db to different location.



Electrs dashboard writes still  „waiting for bitcoin node to finish syncing“

When you run command:

~/umbrel/scripts/app compose electrs logs”

you get error:

failed to open bitcoind cookie file: /data/.bitcoin/.cookie

electrs_1 | 1: No such file or directory (os error 2)

electrs_1 | [2023-05-24T18:20:54.900Z INFO electrs::db] "/data/db/bitcoin": 17 SST files, 0.000013685 GB, 0.000000017 Grows


Adjust Line in docker-compose.yml for Electrs app:

Under volumes:


– „${APP_BITCOIN_DATA_DIR}:/data/.bitcoin:ro“


– „/media/data:/data/.bitcoin:ro“


Add (device name depends on where you have external drive for bitcoin app db)

– /dev/sdb1:/dev/sdb1

I found this solution here:


This hint if very straightforward but migt be helpful if you don’t have any tool for full text search in files.

In this case i was looking for string „JoeDoe“ in folder C:\Test

get-childitem -Path "C:\Test" | Select-String "JoeDoe"

Result is:

get-childitem -Path "C:\Test" | Select-String "JoeDoe"



As you can see it will show file where was text found .

Graph API script for get lastpasswordset.
$cert = Get-ChildItem -Path Cert:LocalMachine\MY | ?{$_.Thumbprint -eq "B5****3" }
$token = Get-MsalToken -ClientId 12345678-1234-1234-1234-12344567489 -ClientCertificate $cert -TenantId 1234567-1234-1234-1234-123456789156
$users = Invoke-RestMethod -Headers @{Authorization = "Bearer $($token.AccessToken)" } -Uri '$select=userPrincipalName,mail,lastPasswordChangeDateTime' -Method Get
$allusers = $allusers + $users.value
while($users.'@odata.nextLink' -ne $null)
$users = Invoke-RestMethod -Headers @{Authorization = "Bearer $($token.AccessToken)" } -Uri $users.'@odata.nextLink' -Method Get
$allusers = $allusers + $users.value
#Returns users from aggregated varriable

Here is example how handle situation when limit is reached (I had limit on 100 objects in Get response). Following code shows how process each response and use @odata.nextLink to get another set of results. This article is not big deal, it is rather my note for next learning of Graph API :).



$users = Invoke-RestMethod -Headers @{Authorization = "Bearer $($token.AccessToken)" } -Uri '' -Method Get

$allusers = $allusers + $users.value

while($users.'@odata.nextLink' -ne $null)
$users = Invoke-RestMethod -Headers @{Authorization = "Bearer $($token.AccessToken)" } -Uri $users.'@odata.nextLink' -Method Get
$allusers = $allusers + $users.value 

#Returns users from aggregated varriable 


This article continues based on prevous article where application principle was used for authentication to AzureAD over powershell module AzureAD.

In order to get it work, module need to be installed. If application was created and working in mentioned article, following set of commands should provide you possibility to use Graph API. In this case list users:

  • replace string YourCertThumprint with the thumbprint of your certificate
  • replace string YourApplicationID with ID of you application used in mentioned article
  • replace string YourTenantID with ID of your tenantID



$cert = Get-ChildItem -Path Cert:LocalMachine\MY | ?{$_.Thumbprint -eq „YourCertThumbprint“ }

$token = Get-MsalToken -ClientId YourApplicationID -ClientCertificate $cert -TenantId YourTenantID

Invoke-RestMethod -Headers @{Authorization = „Bearer $($token.AccessToken)“ } `
-Uri ‚‘ `
-Method Get


This article is just note, but it might be helpful if somebody tries to find the way how to do it. In case that application is not Global Administrators API might need additional permissions in API permissions of your application.

Here is useful commandlet which generates report of scheduled tasks:


schtasks.exe /query /s localhost  /V /FO CSV | ConvertFrom-Csv | Where { $_.TaskName -ne "TaskName" } | select TaskName,"Next Run Time",Status,"Logon Mode","Last Run Time","Last Result",Author,"Task To Run","Start In",Comment,"Scheduled Task State","Run As User" | Export-Csv -Encoding UTF8 -Path C:\pathtocsv\file.csv -NoTypeInformation


Note: Just modify Path variable to valid path, where csv file will be written.

The main reason of doing this is fact that GA users has by default enabled MFA which basically blocks automations initated from onpremise to AzureAD. There are few workarounds how to do that and this article just describes one workaround. I would like to point out that I just tried already existing article so I´m not author of this. Be aware that loose control of certificate will cause security breach and attacker can use assigned role!

Before continue run Powershel ISE with elevated credentials (rather becase we will do activities with certificates and local disc modification and you might get stucked in the middle of action due to insufficient permissions.

You would need to connect to Azure AD. You can do it also with Powershell Module AzureADPreview. Wheather you use defulat AzureAD or AzureADPreview you would need to connect to AzureAD with following command.

import-module azuread 
# or import-module azureadpreview
connect-azuread -tenantID IDoftenant

Then define $pwd variable which contains password for pfx container where will be stored pfx certificate.

$pwd = "plaintext password"

Create foder where will be certificate stored (in below code i used C:\temp ).

Now let´s create certificate, plese define -DnsName value with your registered tenant domain

$notAfter = (Get-Date).AddMonths(6) # Valid for 6 months
$thumb = (New-SelfSignedCertificate -DnsName "" -CertStoreLocation "cert:\LocalMachine\My" -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $notAfter).Thumbprint
$pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText
Export-PfxCertificate -cert "cert:\localmachine\my\$thumb" -FilePath c:\temp\examplecert.pfx -Password $pwd


Load certificate to be able to use it in AzureAD.

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("C:\temp\examplecert.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())


Please modify parameter IdentifierUris to reflect your tenant name. Adjust Displaynema and CuctomeKeyIdentifier if you want.

$application = New-AzureADApplication -DisplayName "test123" -IdentifierUris ""
New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "Test123" -Type AsymmetricX509Cert -Usage Verify -Value $keyValue -EndDate $notAfter


Prepare service principal for new application.

$sp=New-AzureADServicePrincipal -AppId $application.AppId


Now let´s add role to our new application. You can select whatever role you want, you can list roles with following command. In my case i needed GA permisisons so what i was looking for is role named „Global Adminis“.




Here is command to add desired role.


Add-AzureADDirectoryRoleMember -ObjectId (Get-AzureADDirectoryRole | where-object {$_.DisplayName -eq "Global Administrator"}).Objectid -RefObjectId $sp.ObjectId


Now you can use following command to connect to tenant. You need to replace your values here:

  • YourTenantID (just your tenant ID you can find in Azure Portal)
  • YourApplicationID (in my case i could use following command to get it Get-AzureADApplication -SearchString „test123“)
  • YourCertThumbprint (you can find it in computer Personal – Certificates, doubleclick on the certificate, click on tab Details and get thumbprint in Field Thumbprint)



Connect-AzureAD -TenantId YourTenantID -ApplicationId YourApplicationID -CertificateThumbprint YourCertThumbprint





Backup and Restore


From Windows 10 OS, you can do backup with wbadmin command. This is example how perform backup to UNC path  however TargetBackup can be even local USB attached disk.


wbadmin start backup -backupTarget:\\wds1\winback\win10_2 -include:C: -allcritical -quiet


Note: recovery worked only in situation that identical disk has been used, when I used the new one disk it did not work and i tried to use wbadmin start sysrecovery but this did not work either. When i start recovery the error 0x80042308 object not found…So I endup to use WinRE (recovery from original installation media in order do recover system to new disk), where I could use backup from Backup section in this article.

For recovery (clonning) just boot from Windows installation media (important is to have the same installation media architecture and OS to ensure that recovery is possible). In my case i used WinPE if you have (be aware of that backup feature is not possible over WinPE, only partition recovery is possible)

For list of available backup versions run:

wbadmin get versions -backuptarget:\\wds1\winback\win10_2 -machine:DESKTOP-9CL3JDP

Output will show version parameter which needs to be added for recovery:

In this case Version is 07/31/22-08:37 so command for recovery will be:

wbadmin start recovery -version:07/31/2022-08:37 -itemtype:Volume -items:C: -BackupTarget:\\wds1\winback\win10_2 -machine:DESKTOP-9CL3JDP -quiet

After authentication resovery process should b started .


Details about WBAdmin backup and restore are here: