This is an old revision of the document!
/volume2. The name is optional but must be a directory outside of the encrypted /volume1 and also outside of any operating system or Synology created directory so that these 2 files are kept intact when DSM get's updated, they must be treated as user files. In my setup Synology created /volume2 automatically when I created the fully encrypted /volume1./bin/sh or /bin/bash. They regularly check existence of /volume1/homes, and if the script detects the homes directory is not accessible it restarts the SSH daemon with password login enabled. To further safeguard it against misuse my DSM first contacts an external (cloud) server and requests the 2-factor-login key for my user account, which I activated with 2FA served through google authenticator. Without the 6 digit login key served from my cloud server, which serves it only if the request originates from my own fixed IP NAS, password login is not enabled.enablepwd and queryotp reside on my NAS under /volume2/rescue/batch/, the third one synology.php serves the OTP and resides on my cloud server.enablepwd:#!/bin/sh
#
# This script checks availability of a fully encrypted volume1 and enables password authentication for SSH in case the volume is locked
# After restarting the SSH daemon it allows to login even though the homes directory is not accessible
# It requires script 'queryotp' to provide a valid google authenticator code without which it will do nothing
# Must be run as root, place it in the task scheduler with regular execution
# (c) Bernard Condrau
# 2026-08-31: initial
#
VOLUME="/volume1/homes"
SSHD_CONFIG="/etc/ssh/sshd_config"
PWD_AUTH_STR="PasswordAuthentication yes"
BASE_PATH=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
QUERY_OTP=$BASE_PATH"/queryotp"
LOG_FILE=$BASE_PATH"/../logs/enablepwd.log"
#
# check whether password authentication is enabled
head -n 1 $SSHD_CONFIG | grep -q "$PWD_AUTH_STR" && ENABLED="yes" || ENABLED=""
echo "$(date +'%Y-%m-%d %H.%M'): enablepwd task run" | tee -a $LOG_FILE
#
# check whether homes exists (e.g. volume1 is decrypted)
if [ -d "$VOLUME" ]; then
echo "homes exists."
if [[ -n "$ENABLED" ]]; then
# disable password authentication
$QUERY_OTP
if [ $? -eq 0 ]; then
sed -i "1d" $SSHD_CONFIG
synosystemctl restart sshd
echo "$(date +'%Y-%m-%d %H.%M'): \"$PWD_AUTH_STR\" removed" | tee -a $LOG_FILE
exit 0
fi
fi
else
echo "homes does not exist."
if [[ -z "$ENABLED" ]]; then
# enable password authentication
$QUERY_OTP
if [ $? -eq 0 ]; then
sed -i "1i $PWD_AUTH_STR" $SSHD_CONFIG
synosystemctl restart sshd
echo "$(date +'%Y-%m-%d %H.%M'): \"$PWD_AUTH_STR\" added" | tee -a $LOG_FILE
exit 0
fi
fi
fi
exit 1
queryotp:#!/bin/sh # # Query OTP # must be run as root # (c) Bernard Condrau # 2026-08-31: initial # OTPQ="https://your.cloud.tld/html/synology.php?share=merkur-otp&auth=your-safe-authentication-password-which-should-have-24-or-more-characters" AUTH=0; CODE="`wget -qO - $OTPQ`" SYNO=$(sudo synootp username=bco code=$CODE) if [[ $SYNO == 'auth ok' ]]; then echo 'authenticated' exit 0 else sleep 35 CODE="`wget -qO - $OTPQ`" SYNO=$(sudo synootp username=bco code=$CODE) if [[ $SYNO == 'auth ok' ]]; then echo 'authenticated' exit 0 fi fi echo 'not authenticated' exit 1
synology.php:<?php
/*
* php to deliver encryption key to remote NAS
*
* (c) 2026, Bernard Condrau
*
*/
// Build an array of trusted IP addresses...
$trusted=array('nas.server1.ip.addr', 'nas.server2.ip.addr');
// check if request is made from valid ip address
if (in_array($_SERVER['REMOTE_ADDR'], $trusted) && isset($_SERVER['QUERY_STRING'])) {
$password = array(
'merkur-otp' => ['your-safe-authentication-password-which-should-have-24-or-more-characters',
shell_exec('/home/user/html/merkur-otp.sh') // generate OTP
],
);
// get the share name from the request
$share = $_GET['share'];
if (isset($password[$share]) && ($password[$share][0] == $_GET['auth'])) {
echo $password[$share][1]; // echo the password, this will be grabbed by wget
exit(0);
}
}
echo '';
?>
merkur-otp.sh:#!/bin/bash source /home/bco/html/pyotp-env/bin/activate python3 /home/bco/html/pyotp-env/merkur-otp.py deactivate exit 0
reboot shutdown -r now
sudo /usr/syno/sbin/synoencvolume --auto-unlock-get-keys
.rkey recovery file. The system will prompt you to enter a new vault password to recreate and repair the local key vault.sudo lvdisplay
LV Path /dev/vg1/volume_1sudo cryptsetup luksOpen /dev/vg1/volume_1 mapped_volume
.rkey file saved on a USB drive or transferred via SSH to /tmp/volume1.rkey, use:sudo cryptsetup luksOpen /dev/vg1/volume_1 mapped_volume --key-file /tmp/volume1.rkey
sudo mkdir -p /mnt/recovery mount /dev/mapper/mapped_volume /mnt/recovery
/mnt/recovery. You can use command-line tools like cp, rsync, or tar to copy your files off to an external drive or another server..rkey) will download automatically to your computer's default download folder