LibreELECでDebianを動かす

LibreELECはとてもコンパクトにまとまってて、プログラムを動かしたい場合リポジトリからインストールすることになります。ただ全て良い結果になるわけでありません。たとえばDockerをインストールしてDebianを動かしたい時、s905xではカーネルバージョンが3.14であるためoverlayfsが使えません。その結果、一見動いているようにみえますが、書き込みできないために再度立ち上げた時にエラーが起こります。

Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"bash\": executable file not found in $PATH" 
Error: failed to start containers: mydebian

そこで苦肉の策としてchrootを使ってみます。LibreELECではaptが使えないのでPCのデスクトップでイメージを作ります。s905xはarm64なのでそのアーキティチャーにあったアーカイブを使います。

$ sudo mkdir -p $HOME/srv/chroot/stretch
$ sudo debootstrap --arch=armhf stretch mkdir -p $/HOME/srv/chroot/stretch http://ftp.debian.org/debian/
$ cd $HOME
$ sudo tar czvf $HOME/strech.tar.gz ./srv/chroot/stretch

scp等でTV BOXに移して展開します。

# cd /storage
# tar xzvf strech.tar.gz

Debianのレポジトリを編集します。

/storage/srv/chroot/stretch/etc/apt/sources.list

deb http://ftp.jp.debian.org/debian/ stretch main contrib non-free 
deb-src http://ftp.jp.debian.org/debian/ stretch main contrib non-free

chroot用のスクリプトを作ります。

chroot.sh

#!/usr/bin/sh 
 
CHROOT=/storage/srv/chroot/stretch 
 
mount -o bind /proc $CHROOT/proc 
mount -o bind /sys $CHROOT/sys 
mount -o bind /dev $CHROOT/dev 
mount -o bind /dev/shm $CHROOT/dev/shm 
mount -o bind /dev/pts $CHROOT/dev/pts 
mount -o bind /sys/kernel/debug $CHROOT/sys/kernel/debug 
mount -o bind /sys/kernel/config $CHROOT/sys/kernel/config 
mount -o bind /dev/mqueue $CHROOT/dev/mqueue 

chroot $CHROOT /usr/bin/env -i \ 
    HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \ 
    PATH=/bin:/usr/bin:/sbin:/usr/sbin \ 
    /bin/bash --login +h 
 
umount $CHROOT/dev/mqueue 
umount $CHROOT/sys/kernel/config 
umount $CHROOT/sys/kernel/debug 
umount $CHROOT/dev/pts 
umount $CHROOT/dev/shm 
umount $CHROOT/dev 
umount $CHROOT/sys 
umount $CHROOT/proc

exit 0

実行形式にします。

chmod +x chroot.sh

実行します。

# ./chroot.sh
# apt update
# apt upgrade

これでDebianが使えるようになります。

Nginxをインストールする

Debianが使えるようになったところで、Nginxをインストールしてみます。目的はLibreELECをインターネットからアクセス出来るようにするためです。

aptでnginxとcronをインストールします。

/etc/nginx/sites-enabled/example.mydns.net

server { 
    listen       80; 
    server_name   example.mydns.net; 
    return 301    https://$host$request_uri; 
} 
 
server { 
    listen       443 ssl; 
    server_name example.mydns.net;

    proxy_set_header    X-Real-IP       $remote_addr; 
    proxy_set_header    Host            $http_host; 
    proxy_set_header    X-Forwarded-Proto $scheme; 
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header    X-Forwarded-Host $http_host; 
    proxy_set_header    X-Forwarded-Server $host; 
 
#    listen 443 ssl; # managed by Certbot 
ssl_certificate /etc/letsencrypt/live/example.mydns.net/fullchain.pem; # managed by Certbot 
ssl_certificate_key /etc/letsencrypt/live/example.mydns.net/privkey.pem; # managed by Certbot 
ssl_session_cache shared:le_nginx_SSL:1m; # managed by Certbot 
ssl_session_timeout 1440m; # managed by Certbot 
 
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # managed by Certbot 
ssl_prefer_server_ciphers on; # managed by Certbot 
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-SHA ECDHE-ECDSA-AES256-SHA ECDHE
-ECDSA-AES128-SHA256 ECDHE-ECDSA-AES256-SHA384 ECDHE-RSA-AES128-GCM-SHA256 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-RSA-AES128-SHA 
ECDHE-RSA-AES128-SHA256 ECDHE-RSA-AES256-SHA384 DHE-RSA-AES128-GCM-SHA256 DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES128-SHA DHE-R
SA-AES256-SHA DHE-RSA-AES128-SHA256 DHE-RSA-AES256-SHA256 EDH-RSA-DES-CBC3-SHA"; # managed by Certbot 
 
    location / { 
        return 301 http://$host/emby; 
    } 
    location /emby/ { 
        proxy_pass http://localhost:8096/; 
 
        error_log /var/log/nginx/emby.error; 
        access_log /var/log/nginx/emby.access; 
 
        proxy_read_timeout  240; 
        proxy_buffering off;
        proxy_redirect off; 
    } 
    location /kodi/ { 
        proxy_pass http://localhost:8080/; 
 
        error_log /var/log/nginx/kodi.error; 
        access_log /var/log/nginx/kodi.access; 
 
        proxy_read_timeout 240; 
        proxy_redirect off; 
        proxy_buffering off;  
    }
#   location /plex/ { 
#       proxy_pass http://192.168.1.9:32400/; 
#
#      error_log /var/log/nginx/plex.error; 
#       access_log /var/log/nginx/plex.access; 
#
#       proxy_read_timeout  90; 
#       proxy_redirect default; 
#   } 
    location ~ /.well-known/acme-challenge { 
        allow all; 
    } 
}

Nginxが無事動いたらいったんchroot環境から抜けます。

スクリプトを作成します。

chroot-start-daemon.sh

#!/usr/bin/sh 
 
CHROOT=/storage/srv/chroot/stretch 
PKGS="nginx cron" 
 
mount -o bind /proc $CHROOT/proc 
mount -o bind /sys $CHROOT/sys 
mount -o bind /dev $CHROOT/dev 
mount -o bind /dev/shm $CHROOT/dev/shm 
mount -o bind /dev/pts $CHROOT/dev/pts 
mount -o bind /sys/kernel/debug $CHROOT/sys/kernel/debug 
mount -o bind /sys/kernel/config $CHROOT/sys/kernel/config 
mount -o bind /dev/mqueue $CHROOT/dev/mqueue 
 
sleep 3 
 
for i in $PKGS; do 
    chroot $CHROOT /usr/bin/env -i \ 
        HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \ 
        PATH=/bin:/usr/bin:/sbin:/usr/sbin \  
        /bin/bash /etc/init.d/$i start 
done     
 
exit 0

chroot-stop-daemon.sh

#!/usr/bin/sh 
 
CHROOT=/storage/srv/chroot/stretch 
PKGS="nginx cron" 
 
for i in $PKGS; do 
    chroot $CHROOT /usr/bin/env -i \ 
        HOME=/root TERM="$TERM" PS1='\u:\w\$ ' \ 
        PATH=/bin:/usr/bin:/sbin:/usr/sbin \ 
        /bin/bash /etc/init.d/$i stop 
done 
sleep 3 
 
exit 0

chroot-stop-env.sh

#!/usr/bin/sh 
 
CHROOT=/storage/srv/chroot/stretch 

umount $CHROOT/dev/mqueue 
umount $CHROOT/sys/kernel/config 
umount $CHROOT/sys/kernel/debug 
umount $CHROOT/dev/pts 
umount $CHROOT/dev/shm 
umount $CHROOT/dev 
umount $CHROOT/sys 
umount $CHROOT/proc 
 
exit 0

設定用のディレクトリに移動します。

# cd /storage/.config

autostart.sh

( 
    /storage/chroot-start-daemon.sh 
) &

shutdown.sh

case "$1" in 
  halt) 
    /storage/chroot-stop-daemon.sh 
    ;; 
  poweroff) 
    /storage/chroot-stop-daemon.sh 
    ;; 
  reboot) 
    /storage/chroot-stop-daemon.sh      
;; 
  *) 
    /storage/chroot-stop-daemon.sh 
    ;; 
esac

Armbianを使う方法

Armbianを使う場合はすこし簡単です。イメージファイルを次のサイトからダウンロードします。

https://yadi.sk/d/pHxaRAs-tZiei

イメージのファイルを調べます。

file Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img

Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img: DOS/MBR boot sector; partition 1 : ID=0xe, start-CHS (0x40,0,1), end-CHS (0x3ff,3,32), startsector 8192, 262144 sectors; partition 2 : ID=0x83, start-CHS (0x3ff,3,32), end-CHS (0x3ff,3,32), startsector 270336, 3563520 sectors

HDDイメージであることが分かります。さらにfdiskを使ってみます。

fdisk Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img

Command (m for help): p

Disk Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img: 1.8 GiB, 1962934272 bytes, 3833856 sectors
 Units: sectors of 1 * 512 = 512 bytes
 Sector size (logical/physical): 512 bytes / 512 bytes
 I/O size (minimum/optimal): 512 bytes / 512 bytes
 Disklabel type: dos
 Disk identifier: 0x1a9b4ccd

Device                                                         Boot  Start     End Sectors  Size Id Type
 Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img1        8192  270335 262144  128M  e W95 FAT16 (LBA)
 Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img2      270336 3833855 3563520  1.7G 83 Linux

Command (m for help): q

イメージファイルの始まりが270336で終わりが3833855なので、これの情報を元にイメージを切り取ります。

$ dd if=Armbian_5.34_S9xxx_Debian_stretch_3.14.29_server_20171104.img of=Armbian_5.34_roofs.img skip=270336 bs=512

マウントしてエラーがでなければ正しく切り取れています。

$ sudo mount Armbian_5.34_roofs.img mnt

この新しいイメージファイルをLibreELECに移します。

# mkdir -p srv/chroot/armbian
# mkdir -p srv/chroot/armbian
# mount -o loop Armbian_5.34_rootfs.img ./srv/chroot/armbian
# mount -o loop Armbian_5.34_rootfs.img ./srv/chroot/armbian

これでマウント出来ました。

あとは同じようにchrootするだけです。

chroot環境ではsystemdが使えません。そのためcgroupと整合性がとれずシステムが若干不安定になるかも知れません。

追記:それでもDockerを使いたい

カーネルがoverlayfsに対応していないのでDockerが起動に失敗するのですが、やはり使ってみたいという場合、方法がないわけではありません。Dockerのファイルシステムを無視して上層レイヤに下層レイヤの情報をコピーするだけです。起動してみます。

# docker start mydebian
# docker attach mydebian
root@421c2c3c636e:/# ls 
bin  boot  dev  etc  home  lib  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

References: