How to Make Persistent System Changes (crontab, etc)

Many people have had trouble making persistent changes (crontab, etc) to their NAS. Various methods have been tried, with varying degrees of success, but the changes usually revert after some time has passed and/or the NAS is rebooted. This guide will show you how to access certain NAS system areas so that persistent changes can be made.

The config.xml file is used in many examples shown below. Changing other system files is beyond the scope of this guide.

WARNING: THE FOLLOWING PROCEDURES CAN VOID YOUR WARRANTY AND BRICK YOUR NAS - USE EXTREME CAUTION AT ALL TIMES

NOTE: BASIC LINUX SKILLS AND ROOT ACCESS VIA SSH ARE REQUIRED

Each of the Linux command examples shown below is preceeded with "# " (no quotes). This indicates a command prompt with root access. If copying/pasting a command, do not copy/paste the "# " portion of the example.

The following instructions are based on the WD My Cloud PR4100 NAS firmware, but they should be applicable to many other WD My Cloud models, possibly with minor variations applied as needed.

Most NAS options are stored in a file called config.xml and this file is stored in several locations. The contents of the file can be viewed by executing either of the following commands.

# cat /usr/local/modules/default/config.xml
# cat /etc/NAS_CFG/config.xml

Note the differences between the two files, where /usr/local/modules/default/config.xml appears to be a default basic configuration, possibly used as a fallback.

The config.xml file is also stored in a RAM database controlled by a Linux program called xmldbc.

# xmldbc -h

Usage: xmldbc version 2 [OPTIONS]
  -h                     show this help message.
  -H                     show version number.
  -v                     verbose mode.
  -i                     ignore external function (like runtime).
  -g {node path}         get value from {node path}.
  -s {node path} {value} set  {value} in {node path}.
  -d {node path}         delete {node path}.
  -l {XML file}          reload XML file to database.
  -D {XML file}          dump database to XML file.
  -S {unix socket}       specify unix socket name, default is /var/run/xmldb_sock
  -A {ephp file}         embeded php parse.
  -V {name=value}        variable for ephp.
  -x {command}           set extended get/set command.
  -t {tag:sec:command}   schedule a timer.
  -k {tag}               kill timers by tag.
  -X {node field}        sorting.
  -I {node field}        insert row.
  -p {node path} {file}  print node to file.
  -r {XML file}          read file and insert to XMLDB.

The contents of the xmldbc database can be dumped to an XML file by executing the following command. Any destination path and filename may be used, as long as they do not conflict with existing system files.

# xmldbc -D /tmp/xmldbc_test.xml

At first, I thought xmldbc may have been the actual source that was used to revert system changes, but a detailed examination of the source code revealed that it was not.

Further investigation revealed a number of “hidden” system partitions which are stored in eMMC flash memory. The partitions aren’t actually “hidden” per-se, but they are not easy to find unless you know what to look for. All things considered, I think this is a good thing because it prevents inexperienced users from accidentally bricking their NAS. A list of all active partitions can be viewed by executing the following command.

# cat /proc/partitions

Pay particular attention to the partitions with a mmcblk name prefix. These are eMMC flash partitions, and they are read/write, so USE EXTREME CAUTION at all times. A more detailed and meaningful list can be seen by executing the following command.

# blkid -o list

device                                   fs_type         label            mount point            UUID
-------------------------------------------------------------------------------------------------------------------------------------
/dev/loop0                               squashfs                         (in use)
/dev/loop1                               ext4                             (in use)               94c1bc4e-98f8-4aa6-b699-9d02c4c8f43d
/dev/loop3                               squashfs                         /usr/local/modules
/dev/sda1                                linux_raid_member                (in use)               1bd71974-bf36-f39b-bb4b-d7932c0a2b97
/dev/sda2                                ext4                             /mnt/HD/HD_a2          27bd93dd-a6b4-49d7-af45-9cfc6a1eef61
/dev/sda4                                ext4                             /mnt/HD_a4             da63156e-198b-43bb-8b37-beac6d94f44b
/dev/sdb1                                linux_raid_member                (in use)               1bd71974-bf36-f39b-bb4b-d7932c0a2b97
/dev/sdb2                                ext4                             /mnt/HD/HD_b2          d23c5cac-b202-465a-ba32-325e99672a1f
/dev/sdb4                                ext4                             /mnt/HD_b4             9fad9dd3-ddff-4e4d-9149-fe61787cdb50
/dev/sdc1                                linux_raid_member                (in use)               1bd71974-bf36-f39b-bb4b-d7932c0a2b97
/dev/sdc2                                ext4                             /mnt/HD/HD_c2          c4669438-f2df-4a99-a29b-17e772e7ceaa
/dev/sdc4                                ext4                             /mnt/HD_c4             ed1be8c5-d51f-4c35-b115-53676f2def74
/dev/mmcblk0                                                              (not mounted)
/dev/mmcblk0p1                           vfat            wdnas_efi        (not mounted)          9FE2-0840
/dev/mmcblk0p2                           ext4            wdnas_kernel     (not mounted)          c5d6e030-df55-4731-99e4-cbb2e5b771e2
/dev/mmcblk0p3                           ext4            wdnas_initramfs  (not mounted)          6bab9bea-2650-4944-84ea-a6fc4ba3fdd0
/dev/mmcblk0p4                           ext4            wdnas_image.cfs  (not mounted)          00035529-6b69-4fca-a0fd-cde0cd805a00
/dev/mmcblk0p5                           ext4            wdnas_rescue_fw  (not mounted)          8c54a8c2-9055-407c-bab1-5985d107fb3a
/dev/mmcblk0p6                           ext4            wdnas_config     (not mounted)          43eafe4c-2503-401e-b288-6cba67952ac9
/dev/mmcblk0p9                           ext4            wdnas_backup     (not mounted)          46330f66-5c9f-4862-9053-6ba3461685be
/dev/md0                                 swap                             <swap>                 b66719fa-c34d-44c1-9f1d-98e48a95ce05
/dev/mapper/docker-8:2-81788934-pool     ext4                             (not mounted)          94c1bc4e-98f8-4aa6-b699-9d02c4c8f43d

The following is a list of named system (mmcblk) eMMC flash partitions, preceded by descriptions.

GRUB Bootloader           wdnas_efi
Linux Kernel              wdnas_kernel
Initial RAM Filesystem    wdnas_initramfs
Squashfs Filesystem       wdnas_image.cfs
Rescue Firmware           wdnas_rescue_fw
Configuration Files       wdnas_config
Backup Files              wdnas_backup

Note that the mount point for each of the mmcblk partitions indicates if they are mounted. A list of mounted partitions can be viewed by executing the following command.

# cat /proc/mounts

Before one can interact with a partition, it must be mounted. If a partition is already mounted, one simply needs to change to the directory it’s mounted to. To mount one of the mmcblk partitions, execute the following sequence of commands, one at a time. Note that a temporary directory named /tmp/eMMC_flash is used to prevent conflicts with existing system directories. In the following example the /dev/mmcblk0p9 eMMC flash partition is mounted, where the path corresponding to any partition of interest can be used instead.

# cd /
# mkdir /tmp/eMMC_flash
# mount /dev/mmcblk0p9 /tmp/eMMC_flash
# cd /tmp/eMMC_flash
# ls -l

Too make persistent changes (adding cron jobs, etc) to the config.xml file, first mount the appropriate partitions (if required), then make two copies of the file. One copy (config_backup.xml) is simply a backup in case changes need to be reverted, and the second copy (config_edit.xml) will be used for making changes. Note: On my WD PR4100 NAS /usr/local/tmp_wdnas_config is mounted to the /dev/mmcblk0p6 device on system startup, and the system configuration files are stored in a subfolder named config. Mount points and paths may vary, depending on the NAS model and firmware version.

# cp -f /usr/local/tmp_wdnas_config/config/config.xml /shares/Public/config_backup.xml
# cp -f /usr/local/tmp_wdnas_config/config/config.xml /shares/Public/config_edit.xml

In the example shown below, note that I’ve added a new cron job named cron_test. Within the config.xml file is a <crond></crond> section, which contains all cron jobs which are added to the crontab at system startup.

<crond>
	<list>
		<count>9</count>
		<name id="1">stime</name>
		<name id="2">wd_crontab</name>
		<name id="3">app_get_info</name>
		<name id="4">recycle_bin_clear</name>
		<name id="5">chk_wfs_download</name>
		<name id="6">random_check</name>
		<name id="7">user_expire_chk</name>
		<name id="8">fw_available</name>
		<name id="9">cron_test</name>
	</list>
	<stime>
		<count>1</count>
		<item id="1">
			<method>3</method>
			<1>30</1>
			<2>2</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>/usr/sbin/stime&amp;</run>
		</item>
	</stime>
	<wd_crontab>
		<count>1</count>
		<item id="1">
			<method>3</method>
			<1>0</1>
			<2>3</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>wd_crontab.sh&amp;</run>
		</item>
	</wd_crontab>
	<app_get_info>
		<count>1</count>
		<item id="1">
			<method>3</method>
			<1>0</1>
			<2>4</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>auto_fw -a -c&amp;</run>
		</item>
	</app_get_info>
	<recycle_bin_clear>
		<count>1</count>
		<item id="1">
			<method>3</method>
			<1>0</1>
			<2>0</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>auto_clear_recycle_bin.sh &amp;</run>
		</item>
	</recycle_bin_clear>
	<chk_wfs_download>
		<count>1</count>
		<item id="1">
			<method>3</method>
			<1>30</1>
			<2>3</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>/usr/sbin/chk_wfs_download&amp;</run>
		</item>
	</chk_wfs_download>
	<random_check>
		<item id="1">
			<method>3</method>
			<1>0</1>
			<2>0</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>random_check -s &amp;</run>
		</item>
	</random_check>
	<user_expire_chk>
		<item id="1">
			<method>3</method>
			<1>0</1>
			<2>0</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>expire.sh</run>
		</item>
	</user_expire_chk>
	<fw_available>
		<item id="1">
			<method>3</method>
			<1>52</1>
			<2>18</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>auto_fw -c 1 &amp;</run>
		</item>
	</fw_available>
	<cron_test>
		<item id="1">
			<method>3</method>
			<1>*</1>
			<2>*</2>
			<3>*</3>
			<4>*</4>
			<5>*</5>
			<run>date >> /shares/Public/test.txt &amp;</run>
		</item>
	</cron_test>
</crond>

To add a new cron job, first edit the <list></list> section as follows, using any name you want for the new cron job, as long as it’s unique. Note that the id="" attributes can only contain numbers, and each number must be unique. Also, the number within the <count></count> element should be changed to reflect the number of cron jobs contained in the <list></list> section. In this case, there are 9 cron jobs, so the count is 9.

<list>
	<count>9</count>
	<name id="1">stime</name>
	<name id="2">wd_crontab</name>
	<name id="3">app_get_info</name>
	<name id="4">recycle_bin_clear</name>
	<name id="5">chk_wfs_download</name>
	<name id="6">random_check</name>
	<name id="7">user_expire_chk</name>
	<name id="8">fw_available</name>
	<name id="9">cron_test</name>
</list>

Next, add a new section to the end of the <crond></crond> section as follows. Note that the outer element name must EXACTLY match the name element value used in the <list></list> section. In this case, the outer element name is <cron_test></cron_test>.

<cron_test>
	<item id="1">
		<method>3</method>
		<1>*</1>
		<2>*</2>
		<3>*</3>
		<4>*</4>
		<5>*</5>
		<run>date >> /shares/Public/test.txt &amp;</run>
	</item>
</cron_test>

The exact purpose of the <method></method> element is currently unknown. The numbered elements (<1></1>, <2></2>. etc) represent the 5 fields used by crontab for specifying time intervals. For more information about crontab time intervals, see: [GUIDE] Crontab Demystified

In the examples shown above, the text within the <run></run> element is the command or script to be executed. The & (ampersand) character at the end of a shell command is known as job control. The & (ampersand) character informs the shell to put the command in the background, allowing parallel commands to be run. The & (ampersand) character is reserved as a special character in XML files, so it must be represented by &amp; at all times.

For example, the following command will append the current date to a text file in the “Public” share folder. The & (ampersand) character at the end of the line isn’t strictly necessary, but I’ve included it so I could explain it’s purpose and how to use it within XML files.

# date >> /shares/Public/test.txt &

Shell scripts contained in text files, or even binary programs can also be executed by a cron job. However, they must be saved in a location which is not periodically refreshed along with the root filesystem. eMMC flash partitions can be used for this purpose, but one must be EXTREMELY CAREFUL to not overwrite any existing files.

For example, if the shell command in the examples shown above were contained in a text file, the resulting <cron_test></cron_test> XML <run></run> command line might resemble the following.

<run>/usr/local/tmp_wdnas_config/config/cron_test.sh &amp;</run>

When finished making changes, simply save the config.xml file, then copy it to the appropriate location, replacing the existing config.xml file.

# cp -f /shares/Public/config_flash.xml /usr/local/tmp_wdnas_config/config/config.xml

One should be ABSOLUTELY CERTAIN that the config.xml file does not contain any typos or errors BEFORE replacing the existing config.xml file. Note that standard XML parsers or validation services may report the config.xml XML file as being malformed because the developers chose to use element names (<1></1>, <2></2>. etc) which violate the XML syntax rules. The NAS must be rebooted from the dashboard for changes to take effect.

After the NAS is finished rebooting, verify that the new cron job has been added to the crontab by executing the following command.

# crontab -l

When finished, ALWAYS UNMOUNT eMMC FLASH PARTITIONS, as shown in the following example. Either the partition or the mount point may be used to unmount a partition. Note: Partitions mounted by the system should NOT be unmounted.

# umount /tmp/eMMC_flash

Again, USE EXTREME CAUTION because making changes to any of the system files stored in the eMMC flash partitions can very easily BRICK YOUR NAS. You have been warned… multiple times.

5 Likes

We appreciate you taking the time to provide this guide.

Hi,

When making changes as you mention, this will be override with a future firmware upgrade?

If for instance the changed config.xml is invalid (some mistake while closing a tag) what is the side effect, it is possible to recover without losing the precious disk content?

Changing this config.xml void the warranty, but after a software update it is possible to detect those changes?

Sorry for many questions but it seems that you have good knowledge not this :grin:

Thanks

So using your method are you able to save the modified config.xml back to the NAND flash - BECAUSE THAT IS how you can make changes persistent. And after reading this I am unsure if your method accomplishes that.

Actually, I had analyzed and custom-compiled the firmware code of EX2 3 years ago…so I do know a bit more than basic Linux facts. I asked my earlier question because I did not see in your original post any mention of the NAND partitions being read/write - but I now see that it’s mentioned there…not sure if that added in of your 5 edits to the original post, or it was there from the beginning…I don’t recall seeing it there earlier when I asked my question, but it’s possible I missed it.

Anyway, good to see that you figured out what seems to be an alternate way to get the keys to the kingdom…I felt the same way 3 years ago when within a week I had hacked EX2’s code…and took the bold but risky step to custom compile it and load it on my EX2.

Hi @dswv42, Thank you for the outstanding insight! I’m really pissed off by not being able to add to cron simple rsync jobs for backing up the NAS to USB. As extensively explored other threads the built it solution on the dashboard never completes the task. Maybe you could show us how to do such thing by pointing out how to edit the config.xml file in the nand partition.

Thanks!

Hi @dswv42. I own a EX4 instead of the 4100. Check out the partitions and blkid commands output:

# cat /proc/partitions

rootfs / rootfs rw 0 0
/dev/root / ext2 rw,relatime,errors=continue,user_xattr 0 0
sysfs /sys sysfs rw,relatime 0 0
mdev /dev tmpfs rw,relatime 0 0
proc /proc proc rw,relatime 0 0
cgroup_root /cgroup tmpfs rw,nosuid,nodev,noexec,relatime 0 0
memory /cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0
ubi0:config /usr/local/config ubifs rw,relatime 0 0
squash /usr/local/tmp ramfs rw,relatime,size=105m 0 0
/dev/loop0 /usr/local/modules squashfs ro,relatime 0 0
tmpfs /mnt tmpfs rw,relatime,size=1024k,nr_inodes=0 0 0
tmpfs /var/log tmpfs rw,relatime,size=40960k,nr_inodes=0 0 0
tmpfs /tmp tmpfs rw,relatime,size=102400k,nr_inodes=20000 0 0
/dev/sda4 /mnt/HD_a4 ext4 rw,relatime,user_xattr,barrier=1,stripe=128,data=ordered 0 0
/dev/sdb4 /mnt/HD_b4 ext4 rw,relatime,user_xattr,barrier=1,stripe=128,data=ordered 0 0
/dev/sdd4 /mnt/HD_d4 ext4 rw,relatime,user_xattr,barrier=1,stripe=128,data=ordered 0 0
/dev/sde4 /mnt/HD_e4 ext4 rw,relatime,user_xattr,barrier=1,stripe=128,data=ordered 0 0
/dev/md1 /mnt/HD/HD_a2 ext4 rw,noatime,nodiratime,user_xattr,barrier=1,stripe=48,data=ordered,usrquota,grpquota 0 0
none /proc/bus/usb usbfs rw,relatime 0 0
/dev/sdc1 /mnt/USB/USB1_c1 ufsd rw,relatime,nls=utf8,fmask=0,dmask=0,force,user_xattr 0 0

# blkid -o list

device     fs_type label    mount point    UUID
-------------------------------------------------------------------------------
/dev/ubi0_0
           ubifs            (not mounted)  d6ecd034-8f8e-4d50-9dfd-222f985013c7
/dev/loop0 squashfs         /usr/local/modules 
/dev/sda1  linux_raid_member  (in use)     8d1319bb-64ff-3aff-ef17-b15d5db656ea
/dev/sda2  linux_raid_member 1 (in use)    79a7190c-6a6f-abfc-22ee-3092feec0922
/dev/sda4  ext4             /mnt/HD_a4     d9c223e2-0cb4-474c-9f59-69d5844e0115
/dev/sdb1  linux_raid_member  (in use)     8d1319bb-64ff-3aff-ef17-b15d5db656ea
/dev/sdb2  linux_raid_member 1 (in use)    79a7190c-6a6f-abfc-22ee-3092feec0922
/dev/sdb4  ext4             /mnt/HD_b4     809d7737-5fd4-4562-aa84-d5f0b22e31b5
/dev/sdd1  linux_raid_member  (in use)     8d1319bb-64ff-3aff-ef17-b15d5db656ea
/dev/sdd2  linux_raid_member 1 (in use)    79a7190c-6a6f-abfc-22ee-3092feec0922
/dev/sdd4  ext4             /mnt/HD_d4     2f953ec9-408d-4b00-bc4d-4a703195e699
/dev/sdc1  ntfs    Backup_RR /mnt/USB/USB1_c1 D8268EA9268E8868
/dev/sde1  linux_raid_member  (in use)     8d1319bb-64ff-3aff-ef17-b15d5db656ea
/dev/sde2  linux_raid_member 1 (in use)    79a7190c-6a6f-abfc-22ee-3092feec0922
/dev/sde4  ext4             /mnt/HD_e4     fc28f557-be9d-420f-a16f-2e12d25eb16b
/dev/md0   swap             <swap>         227ffad2-1b31-4134-9591-d60efb4d9c70
/dev/md1   ext4             /mnt/HD/HD_a2  cbbf678d-82a6-4790-b8c8-74081b801ffb

It seems that the NAND memory is mapped in ubifs by /dev/ubi0 (which is actually mounted to /usr/local/config and contains many .xml and .log files, as well as /dev/ubi0_0 which isn’t mounted.

# ls /usr/local/config/

CacheVolume
GAnalytics.xml-backup
access_lm.log
adjustTime
alert.xml
alert_email.conf
analytics_missed
certificate_https_all.pem
config.xml
dhcp6c.conf
dhcp6c.conf.bond0
dhcp6c.conf.egiga0
dhcp6c.conf.egiga1
dynamicconfig_config.ini
dynamicconfig_tmp.ini
ftp_download.xml
ga_default_flag
ganalytics
gid
gogoc.conf
group
hd_info.xml
hd_list.xml
hdd_white_list.xml
hosts
iconv_table
mail_event_conf.xml
mt-daapd.conf
mycl_id
mycloud.log
mycloud.log.1
onbrd.ini
orion.db
orion_cm.log
orion_cm.log.1
p2psettings.xml
passwd
passwd.webdav
power_schedule_info.xml
power_status
record_burn_in_fw_time
resolv.conf
routeap.conf
rtc-mfg-date.log
s3.conf
server.ca-bundle
server.crt
server.key
shadow
smbpasswd
sms_conf.xml
snmpd.conf
ssh_host_dsa_key
ssh_host_dsa_key.pub
syslog.conf
system.conf
tzmap.table
udhcpd.conf
udhcpd.conf.def
uid
usb_backup.xml
user.log
user.log.old
version.update
version_info
volume_encrypt.xml
wd_serial.txt
wdlog.conf
wdlog.filters
wdmcserver.log
wdmcserver.log.1
wdnas-rest-api.conf

I tried to mount /dev/ubi0_0 to check its contents but it yields:

# mount: /dev/ubi0_0 is not a block device

Which is as far as my superficial unix skills go :slight_smile:

Would you be interested in coaching me poke arround and dump some commands output here so we could maybe find a similar method to EX4 owners?

Regards

Rafael

Thanks for the orientation @dswv42 !

It did mount using:

# mount -t ubifs /dev/ubi0_0 /tmp/ubifs_flash

Here is the directory listing:

CacheVolume
GAnalytics.xml-backup
access_lm.log
adjustTime
alert.xml
alert_email.conf
analytics_missed
certificate_https_all.pem
config.xml
dhcp6c.conf
dhcp6c.conf.bond0
dhcp6c.conf.egiga0
dhcp6c.conf.egiga1
dynamicconfig_config.ini
dynamicconfig_tmp.ini
ftp_download.xml
ga_default_flag
ganalytics
gid
gogoc.conf
group
hd_info.xml
hd_list.xml
hdd_white_list.xml
hosts
iconv_table
mail_event_conf.xml
mt-daapd.conf
mycl_id
mycloud.log
mycloud.log.1
onbrd.ini
orion.db
orion_cm.log
orion_cm.log.1
p2psettings.xml
passwd
passwd.webdav
power_schedule_info.xml
power_status
record_burn_in_fw_time
resolv.conf
routeap.conf
rtc-mfg-date.log
s3.conf
server.ca-bundle
server.crt
server.key
shadow
smbpasswd
sms_conf.xml
snmpd.conf
ssh_host_dsa_key
ssh_host_dsa_key.pub
syslog.conf
system.conf
tzmap.table
udhcpd.conf
udhcpd.conf.def
uid
usb_backup.xml
user.log
user.log.old
version.update
version_info
volume_encrypt.xml
wd_serial.txt
wdlog.conf
wdlog.filters
wdmcserver.log
wdmcserver.log.1
wdnas-rest-api.conf

Which seems to be exactly the same contents of:

> ubi0:config /usr/local/config ubifs rw,relatime 0 0

I wonder if the OS loads content from that partition on boot, which would be logically similar to the PR4100 or if it has some different behavior considering that ubi0 is permanently mounted during normal operation.

Would you like me to check some file contents within that directory, or maybe devise a test by adding a basic edit to the config.xml files in those partitions and performing reboots?

Timestamps:

root@WDMyCloudEX4 root # ls -lh /usr/local/config/config.xml
-rwxr-xr-x    1 root     root       11.6K Apr 10 00:00 /usr/local/config/config.xml
root@WDMyCloudEX4 root # mount -t ubifs /dev/ubi0_0 /tmp/nand
root@WDMyCloudEX4 root # ls -lh /tmp/nand/config.xml
-rwxr-xr-x    1 root     root       11.6K Apr 10 00:00 /tmp/nand/config.xml
root@WDMyCloudEX4 root # ls -lh /usr/local/modules/default/config.xml
-rwxrwxr-x    1 root     root       10.6K Mar 21 07:30 /usr/local/modules/default/config.xml
root@WDMyCloudEX4 root # ls -lh /etc/NAS_CFG/config.xml
-rwxr-xr-x    1 root     root       11.6K Apr 10 00:00 /etc/NAS_CFG/config.xml
root@WDMyCloudEX4 root #

By the way, the <crond></crond> section in config.xml file structure in EX4 is exactly the same as your example extracted from PR4100. You won’t need to make any observations in the main guide on that regard.What is odd is that the <list> structure has 11 entries and the <count> number is 6, which seems a bit strange.

Except for the supposedly failback config.xml file you mentioned, they are all the same date / time. I wonder which one is the main partition and which one is the backup file. So I added slightly different cron jobs to each file and rebooted to find out.

:grimacing: tension :grimacing:

It did not brick! :relieved:

And the winner is…

/dev/ubi0_0 :astonished:

As it turns out the persistent config.xml file comes from the unmounted partition, similar behavior to PR4100 except it is far more simple since it only has one partition for that purpose.

With this I guess we can affirm that for EX4, and maybe EX2 and similar, in order to make persistent system changes you have to edit config.xml inside /dev/ubi0_0

Thank you for your help @dswv42 :clap: :+1:

As a follow up test, maybe someone who owns EX2 and other hardware versions could verify if the information we provided for PR4100 and EX4 covers all possible variations.

Gentlemen, pardon the intrusion in this thread, but I am really at a loss here, with my MyCloud Mirror and this thread is the only thing that was suggested to me, for help (and it might very well help me).

The problem I am facing with my NAS, is that all shares created have permissions of 777. In other words, open widely to the public. Obviously, I can change the permissions, after the shares are created, but every file copied to them will get 777 permissions. If I manually edit /etc/netatalk/afp.conf, and restart the corresponding processes, files copied to the shares do get the proper permissions I want, but the file /etc/netatalk/afp.conf, gets rewritten whenever the NAS is rebooted.

I followed this thread and mounted /dev/ubi0_0 and went through it, but I can’t find anything related to netatalk and afp, either in config.xml or any other .xml file in there.

Do you guys have any idea where I can intervene to change the afp.conf file, permanently?

Many thanks!

MANY THANKS for your reply, really appreciated!

One question, which perhaps can help me, without the need to access the SquashFS.

After the system is booted, can I just copy a modified afp.conf file to /etc/netatalk? The reason I am asking, is because if I manually change afp.conf file, after the system is booted, but before I mount the shares on my Mac, the system uses whatever permissions I have defined in the modified afp.conf. So I could -theoretically- save a modified afp.conf in one of my shares and copy that to /etc/netatalk before mounting the shares and have the proper permissions used.

Again, thanks!

Now I have to figure a way to do it. Maybe using a cron entry? hmmm time to think!

Update: I’ve managed to create a crontab entry, which copies a modified version of afp.conf to /etc/netatalk every 5 minutes (I wish I could just copy it once and be done with it, but I am not sure how to instract crontab to run the copy only once).

However, I strongly believe that this is a very serious issue, that Western Digital should address. It is crazy, for a consumer device, to need you to ssh to it, change the permissions manually, change the afp.conf file manually, and change ubi0_0 manually in order to set the NAS up, so that it sets safe permissions to whatever you copy to it. I have been using afp to mount disks from several different systems (including an Apple Server, a Centos-based server, an ancient Synology Cube station etc) all these afp implementations maintain the permissions of files copied, as they were in the original disk. So I have to assume that WD’s afp implementation is faulty.

Thanks are due to the participants of this discussion, for offering me the guidance to -somehow- fix a sever security issue affecting my MyCloudMirror device.

Thanks for some interesting concepts!

A while ago I posted some instructions how to run a user boot script. It’s also based on crontab hack.

You will find it here: How to run a user boot script at MyCloud Gen2 (2.11.xx) devices

Thank you dswv42 for this excellent guide!

Quick question: Is there any way to add a @reboot entry to the crontab?

Thanks.

What should be the best way to add a cronjob using @reboot?

Also, how can I add a ssh key persistently?

Thanks in advance.

If you have any app installed from the WD app store, you can modify the init / clean scripts to get persistent changes.

Example: persistent home directory (including .ssh dir with authorized_keys)

Go to the app directory.

cd /shares/Volume_1/Nas_Prog
ls

Pick an app, I’m using my entware package but you can use any dir that doesn’t start with an underscore.

cd entware

Prepare the home dir backup directory

mkdir -p home

Edit init.sh

vi init.sh

On app start (e.g. on boot), you want to restore your home directory to /home/root. Add this somewhere in the script. Press i to enter edit mode.

# the first argument is this application's directory
APPDIR=$1

# restore the home directory
rsync -a "${APPDIR}/home/" /home/root

Press escape to exit edit mode. Type :wq to write changes and exit.
Then edit clean.sh

vi clean.sh

On shutdown you want to backup your current home directory to {APPDIR}/home.
Press i for edit mode.

APPDIR=$1

# remove old backup
rm -rf "${APPDIR}/home"
# backup current home directory
rsync -a /home/root/ "${APPDIR}/home"

Press escape to exit edit mode. Type :wq to write changes and exit.

Now test the changes. We’ll check our if our .ash_history gets backed up. Use -a to show hidden files.

ls -a home            # nothing backed up yet
sh clean.sh .         # note the dot!
ls -a home            # tadaaaa!
2 Likes

You say you looked at the source for xmldbc. Where did you find it?

Is there absolutely no other option for scheduling jobs?

S3 backups from the GUI do not do what I need, crontab edits don’t stick, and I would rather not void the warranty. This is frustrating.

this worked for me.

edited init.sh of transmission

added

echo “* * * * * myscript.sh” >> /var/spool/cron/crontabs/root

my cron job get edited at reboot