Running Synology Diskstation in an Alpine Linux chroot container
senioradminRunning Synology Diskstation in an Alpine Linux chroot container
I have a Synology Diskstation DS115j. This NAS device has very limited resources, from today’s perspective:
- 256 MB RAM
- CPU Marvell Armada-370 @800Mhz
- USB 2.0 only
However, it is a neat little device which consumes not too much power.
Unfortunately, the operating system which comes with it, the Linux based DSM 6.2, feels always a little too sluggish. As per default DSM runs several services, among them Nginx and PostgreSQL.
As a Unix/Linux professional I don’t really need the web interface or other fancy stuff. I want only exactly one reliable file service and shell access through ssh - nothing more.
Step one: settings in the web interface
- Go to “Control Panel” -> “File Services”
- Disable all File Services (SMB/AFP/NFS, TFP, rsync)
- Scroll down to “Terminal & SNMP”
- Check “Enable SSH sevice” and use a non-standard port
Step two: Prepare the Alpine chroot
Now, that we setup ssh we will not return to the webinterface. Login to you diskstation over ssh.
user@desktop:~$ ssh diskstation -p 9022
user@diskstations's password:
Could not chdir to home directory /var/services/homes/user: No such file or directory
user@diskstation:/$ sudo -i
Password:
root@diskstation:~#
Then we prepare our Alpine chroot. Go to https://alpinelinux.org/downloads/ and download the “Mini Root Filesystem” for armv7.
At your Diskstation root shell prepare the chroot directory.
root@diskstation:~# mkdir -p /volume1/chroots/alpine/
root@diskstation:~# cd /volume1/chroots/alpine/
Copy the Alpine rootfs to the diskstation:
scp -P 9022 alpine-minirootfs-3.11.2-armv7.tar.gz user@diskstation:/tmp
At the diskstation, extract it:
root@diskstation:/volume1/chroots/alpine# tar xvzf /tmp/alpine-minirootfs-3.11.2-armv7.tar.gz
Create a directory for the data volume:
# mkdir /volume1/chroots/alpine/volume1
Now, we must copy over the kernel modules from the DSM system to the alpine chroot. This is important or kernel related tasks we want to do later in the chroot.
# mkdir /volume1/chroots/alpine/lib/modules/`uname -r`
# cp -a /lib/modules/* /volume1/chroots/alpine/lib/modules/`uname -r`/
Now it is time to make some bind mounts end enter the chroot:
# CR=/volume1/chroots/alpine
# mount --bind /proc $CR/proc
# mount --bind /sys $CR/sys
# mount --bind /dev $CR/dev
# mount --bind /dev/pts $CR/dev/pts
# chroot $CR /bin/ash -l
We are now inside the Alpine chroot and can do further configuration. At first, we want to setup a user:
diskstation:/# adduser user
Then we update the system and add openssh
# apk update
# apk upgrade
# apk add openssh
# vi /etc/ssh/sshd_config
In the SSH config choose a non-standard port
Port 7022
Add sudo and add the user:
# apk add sudo
# visudo
user ALL=(ALL) ALL
Add openrc:
apk add openrc
For file services I chose samba:
# apk add samba-server
# vi /etc/samba/smb.conf
# .... Add following lines at the bottom
[media]
writeable=yes
guest ok=yes
path=/volume1/media
skip smb perm=yes
comment="media"
Add the user to samba:
# smbpasswd -a user
Step three: Disable DSM services and start chroot
Now that our Alpine chroot is ready to go we want to disable the unnecessary DSM services.
Exit the Alpine chroot and return to the DSM command line envvironment .
At first we want to disable the thumbd service
cd /var/packages/FileStation/target/etc/conf
mv thumbd.conf thumbd.conf.orig
Now it depends heavily on what services are running at your diskstation. You can find out what services are enabled with the command synoservicecfg --status
In order to disable the services we have to utilize the script /etc/rc.local. Because DSM is very picky about the services and may even refuse to start, it is important that we disable the services only temporarily every time the device is booted. The synoservicectl command makes disabling services permanent. Since DSM uses the Upstart system, like earlier versions of Ubuntu, it does so by creating override files. In order to revert this, we have to delete these files.
So, my /etc/rc.local
script looks like this:
#!/bin/sh
synoservice --disable pkgctl-SynoFinder
synoservicecfg -stop pgsql
synoservicectl --stop synosnmpcd
synoservicectl --stop snmpd
synoservicectl --stop syslog-ng
rm /usr/share/init/syslog-ng.override
synoservicectl --stop synobackupd
synoservicectl --stop synocgid
synoservicectl --stop hotplugd
synoservicectl --stop nginx
synoservicectl --stop pgsql
synoservicectl --stop synologaccd
synoservicectl --stop synoconfd
synoservicectl --stop synonetd
synoservicectl --stop synologrotated
synoservicectl --stop synologand
synoservicectl --stop synocrond
synoservicectl --stop synostoraged
synoservicectl --stop findhostd
synoservicectl --stop synoscgi
synoservicectl --stop syslog-acc
synoservicectl --stop s2s_daemon
rm /usr/share/init/synobackupd.override
rm /usr/share/init/synocgid.override
rm /usr/share/init/hotplugd.override
rm /usr/share/init/nginx.override
rm /usr/share/init/pgsql.override
rm /usr/share/init/synologaccd.override
rm /usr/share/init/synoconfd.override
rm /usr/share/init/synonetd.override
rm /usr/share/init/synologrotated.override
rm /usr/share/init/synologand.override
rm /usr/share/init/synocrond.override
rm /usr/share/init/synostoraged.override
rm /usr/share/init/findhostd.override
rm /usr/share/init/synoscgi.override
rm /usr/share/init/syslog-acc.override
rm /usr/share/init/s2s_daemon.override
Create this file, but do not reboot just yet. We must prepare the autostart of out Alpine chroot. Create a second file with name /etc/rc.alpine
#!/bin/sh
# Package
PACKAGE="alpine"
DNAME="Alpine Chroot"
# Others
CHROOTTARGET="/volume1/chroots/alpine"
start_daemon ()
{
# Make sure we don't mount twice
grep -q "/proc " /proc/mounts || mount -t proc proc /proc
grep -q "/sys " /proc/mounts || mount -t sysfs sys /sys
grep -q "/dev " /proc/mounts || mount -o bind /dev /dev
grep -q "/dev/pts " /proc/mounts || mount -o bind /dev/pts /dev/pts
grep -q "/media " /proc/mounts || mount -o bind /volume1/media /media
grep -q "/volume1 " /proc/mounts || mount -o bind /volume1 /volume1
chroot / /sbin/openrc
chroot / touch /run/openrc/softlevel
# start SSH
chroot / /etc/init.d/sshd start
# start Samba
chroot / /etc/init.d/samba start
# Start syslog
chroot / /sbin/syslogd
# Start cron
chroot / /usr/sbin/crond -b
}
stop_daemon ()
{
# Unmount
umount /dev/pts
umount /dev
umount /sys
umount /proc
}
daemon_status ()
{
`grep -q "/proc " /proc/mounts` && `grep -q "/sys " /proc/mounts` && `grep -q "/dev " /proc/mounts` && `grep -q "/dev/pts " /proc/mounts`
}
case $1 in
start)
if daemon_status; then
echo is already running
exit 0
else
echo Starting ...
start_daemon
exit $?
fi
;;
stop)
if daemon_status; then
echo Stopping ...
stop_daemon
exit 0
else
echo is not running
exit 0
fi
;;
status)
if daemon_status; then
echo is running
exit 0
else
echo is not running
exit 1
fi
;;
chroot)
chroot / /bin/ash -l
;;
*)
exit 1
;;
esac
Now, at the bottom of /etc/rc.local
add the line
[ -x /etc/rc.alpine ] && /etc/rc.alpine start
Now we are ready. The rc.alpine script mounts the necessary directories and starts 4 services inside the chroot “container”: SSH, Samba, Syslog and cron.
Cross your fingers and type reboot
.
It may take a while and longer than ususal (remember: all services must be started and hut down again). But then you should hear the well-known beep from your Diskstation.
Then try to login to your diskstation th the port of your Alpine chroot: ssh user@diskstation -p 7022
Check what processes are running, excluding kernel processes. The output should look like this.
diskstation:~$ ps ax|grep -v \\[
PID TTY STAT TIME COMMAND
1 ? Ss 0:13 /sbin/init
1362 ? Ss 0:00 udevd --daemon
2661 ? Ssl 0:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u ntp:ntp
2666 ? Ss 0:00 /usr/bin/sshd
3614 ? S 0:00 /usr/sbin/sshd
3695 ? Ss 0:00 /usr/sbin/smbd -D
3701 ? S 0:00 /usr/sbin/smbd -D
3702 ? S 0:00 /usr/sbin/smbd -D
3708 ? S 0:00 /usr/sbin/smbd -D
3728 ? Ss 0:00 /sbin/syslogd
3730 ? Ss 0:00 /usr/sbin/crond -b
3748 ttyS0 Ss+ 0:00 /sbin/getty 115200 console
4662 ? Ss 0:00 /usr/sbin/crond
4691 ? Ssl 0:01 /usr/syno/bin/scemd
5153 ? Ss 0:01 /usr/bin/nmbd -F
You will notice that the Synology service scemd
is still running. This is the “Synology Command Execution Management Daemon”.
It is necessary to run it in order to be able to switch off the Diskstation with a long press on the hardware button. Otherwise the Diskstation will fail to switch off.
The alternative is to log on via SSH in the DSM environment and type poweroff
.
If you can live with that (or if you don’t ever want to switch off your NAS anyway) you can disable scemd as well.
Conclusion
I showed you how to run your diskstation almost entirely in a minimal Alpine Linux chroot container. On my box this saves almost 30 MB of RAM. My Diskstation is now fast and snappy again. It should also be possible to run almost any service on the box, thanks to the vast Alpine Linux repository.