目录

Running Synology Diskstation in an Alpine Linux chroot container

2020年1月11日

I have a Synology Diskstation DS115j. This NAS device has very limited resources, from today's perspective:

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

Screenshot DSM web interface

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@192.168.178.7'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 wand 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 "${CHROOTTARGET}/proc " /proc/mounts || mount -t proc proc ${CHROOTTARGET}/proc
        grep -q "${CHROOTTARGET}/sys " /proc/mounts || mount -t sysfs sys ${CHROOTTARGET}/sys
        grep -q "${CHROOTTARGET}/dev " /proc/mounts || mount -o bind /dev ${CHROOTTARGET}/dev
        grep -q "${CHROOTTARGET}/dev/pts " /proc/mounts || mount -o bind /dev/pts ${CHROOTTARGET}/dev/pts
        grep -q "${CHROOTTARGET}/media " /proc/mounts || mount -o bind /volume1/media ${CHROOTTARGET}/media
        grep -q "${CHROOTTARGET}/volume1 " /proc/mounts || mount -o bind /volume1 ${CHROOTTARGET}/volume1
        chroot ${CHROOTTARGET}/ /sbin/openrc
        chroot ${CHROOTTARGET}/ touch /run/openrc/softlevel
# start SSH
        chroot ${CHROOTTARGET}/ /etc/init.d/sshd start
# start Samba
        chroot ${CHROOTTARGET}/ /etc/init.d/samba start
# Start syslog
        chroot ${CHROOTTARGET}/ /sbin/syslogd
# Start cron
        chroot ${CHROOTTARGET}/ /usr/sbin/crond -b
}

stop_daemon ()
{

    # Unmount
    umount ${CHROOTTARGET}/dev/pts
    umount ${CHROOTTARGET}/dev
    umount ${CHROOTTARGET}/sys
    umount ${CHROOTTARGET}/proc
}

daemon_status ()
{
    `grep -q "${CHROOTTARGET}/proc " /proc/mounts` && `grep -q "${CHROOTTARGET}/sys " /proc/mounts` && `grep -q "${CHROOTTARGET}/dev " /proc/mounts` && `grep -q "${CHROOT
TARGET}/dev/pts " /proc/mounts`                                                                             
}

case $1 in
    start)
        if daemon_status; then
            echo ${DNAME} is already running
            exit 0
        else
            echo Starting ${DNAME} ...
            start_daemon
            exit $?
        fi
        ;;
    stop)
        if daemon_status; then
            echo Stopping ${DNAME} ...
            stop_daemon
            exit 0
        else
            echo ${DNAME} is not running
            exit 0
        fi
        ;;
    status)
        if daemon_status; then
            echo ${DNAME} is running
            exit 0
        else
            echo ${DNAME} is not running
            exit 1
        fi
        ;;
    chroot)
        chroot ${CHROOTTARGET}/ /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 mout the necessery 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.


参考链接:https://write.as/allgoodthings/running-synology-diskstation-in-an-alpine-linux-chroot-container