raspberry pi によるsymbolノード構築

# はじめに

RaspberryPiでSymbolNodeを構築してみました。

非エンジニアが四苦八苦しながらなんとかノード起動まで漕ぎ着けました。
正直甘くみていました。
### 辿り着けたのも、先人の知恵やアドバイスのおかげです。
### ありがとうございます。
### 加えて、QUESTにて応援していただいた皆様にも感謝申し上げます。
### ありがとうございます。

参考にさせていただいたページ


https://qiita.com/panda_sonson

https://qiita.com/ishidad2


ちなみにXYMが全然足りないのでテストネットで稼働させています。
何がとは言いませんが、


        NACW73ZWAD6RGZPC3P64DN3KYK5XDLLMVGHW2KQ
私のsymbolアドレスです。

# 使ったもの
M1 Mac
RapberryPi 4B 8GB
1TB SSD(USBのやつ)
テキトーなSDカード
テキトーなモニタ
テキトーなキーボード

# １　OS起動まで

### 1-1 Raspberry Pi Imagerをインストール
[<<ここから>>](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwiJ-83ThP38AhVFM94KHQ3iCXgQFnoECA0QAQ&url=https%3A%2F%2Fwww.raspberrypi.com%2Fsoftware%2F&usg=AOvVaw1QDXlKGDU_22RHEvtotfgF)



### 1-2　USBブート、できるかな？

めんどければこの確認作業は飛ばして1-3から始めてもいい。で、うまくいかなければ戻ってきて確認とアップデートをするとか。

Raspberry Pi 4B からUSBブートに対応したらしい。
ただし、ブートローダが古いとダメなので、ブートローダを更新する必要がある。
確認は、一旦テキトーなSDカードにRaspbianというOSをインストールして


    sudo vcgencmd bootloader_version
をすると、


    update-time XXXXXXXX
とかいうのが出てくる。これはUNIXタイムなので、「UNIX TIME 変換」とか検索すれば変換サイトが出てくる。
2020年12月11日のアップデートでUSBブートに正式対応したのでそれ以降のバージョンであれば出来るとは思う。

### 1-3　OSイメージのダウンロード
[<＜ここから＞＞](https://ubuntu.com/download/raspberry-pi)

![スクリーンショット 2023-02-05 9.48.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125343/e2de2ef7-0f9c-9ce8-f5c3-18088ae304b6.png)
これの64-bit

### 1-4　書き込み
![スクリーンショット 2023-02-05 9.51.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125343/96089376-0bb4-9691-5b15-b2e36770e3ff.png)
「カスタムイメージを使う」で 1-3 でダウンロードしたイメージを選択

SSDをMacに挿し、
![スクリーンショット 2023-02-05 9.53.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3125343/813bc20d-b1ff-97b6-249b-974f363909ee.png)
「ストレージを選ぶ」で挿したSSDを選択。

歯車のマークで、ユーザー設定とかWi-Fi設定とかできるのでやっとく。一応ちゃんと反映されてた。

最後に「書き込む」を押して少し待てばOK。

### 1-5　起動

~~以下の作業をやらないとWiFiが繋がらなかった（なぜだ）。~~
~~・RaspberryPiにSSDを挿し、モニタとキーボードを接続。~~
~~・それから電源に繋ぐ。~~
~~・一旦ログインする。~~

ここまで来ればWiFiが繋がるのでssh接続で今後はいく。

    ssh ユーザ名@IPアドレス


# ２　セキュリティって大事だよね

### 2-1 アップデート

    sudo apt update
    sudo apt upgrade
アップデートの内容によっては設定ファイルを初期化するものもあるので、この段階でやっておくといい。


### 2-2 ルートにパスワードを設定
    sudo passwd root

### 2-3 新たなユーザーを作成
デフォルトユーザの場合は新たなユーザーを作る

    sudo su
このコマンドで一旦ルートユーザーになる

    adduser ユーザ名
このコマンドで新たなユーザーを作る。パスワードを設定した後、フルネームとかを聞かれるが、空白のままエンターでOK。

### 2-4 作ったユーザーをsudoグループに追加し、権限を持たせる

    gpasswd -a ユーザ名 sudo

### 2-5 データ移行と移動ログインの解除

省略

### 2-6 初期ユーザの削除

一旦ログアウトし、新たに作ったユーザでログインして、次のコマンドを実行。

    sudo userdel -r ユーザ名

### 2-7 ssh設定の変更

    sudo nano /etc/ssh/sshd_config
これでsshの設定を変える。（自分はnano派だが、viを使っても良い）


    #Port 22 -> Port 好きなポート番号
気休め程度だがポート番号を変える

    #PermitRootLogin prohibit-password -> PermitRootLogin no
ルートログインを禁止する
   
    #PermitEmptyPasswords no　-> PermitEmptyPasswords no
これもついでにやっとく

    sudo /etc/init.d/ssh restart
これでsshを再起動し、設定を反映させる


### 2-8 IPアドレスの制限
省略

### 2-9 公開鍵でログインする

    logout
一旦ログアウトする。ここからはMacでの作業。

    ssh-keygen -t rsa -b 4096
このコマンドで鍵ペアを作る。
サイトによっては2048で鍵ペアを作っているみたいだが、rsaの場合は強度的に4096がいいらしい。
パスフレーズ（この鍵を使う時に聞かれるパスワードという認識でとりあえずはいい）を聞かれるので、好きなものを設定する（忘れないようにする。）

    ls -al ~/.ssh
これで、「id_rsa」「id_rsa.pub」ができているのを確認。
id_rsaが秘密鍵
id_rsa.pubが公開鍵

    ssh-copy-id -i ~/.ssh/id_rsa.pub -p ポート番号 ユーザ名@IPアドレス
これでraspberry pi に公開鍵を送信・登録を行う。
うまくいかない時はsudoをつける。

    ssh -p ポート番号 -i id_rsa ユーザ名@IPアドレス
これでログインする。
うまくいかない時はsudoをつける。

ここからはraspberry piでの作業。

### 2-10 パスワードでログインできないようにする

    sudo nano /etc/ssh/sshd_config
もっかいこのファイルを操作し、

    #PasswordAuthentication yes -> PasswordAuthentication no
こんな感じに変更

# ３　インストール

    sudo apt-get install -y nodejs npm
    sudo npm install -g npm@latest
    sudo apt install -y docker.io
    sudo apt install -y docker-compose
    sudo usermod -aG docker ユーザ名
    su - ユーザ名
これらのコマンドを順に実行する。

    sudo reboot
自分は念のためここで一旦再起動させた。

### ここまでが準備運動。ここからが構築本番。


# ４　構築その１

めんどいので処理をシェルスクリプトにまとめた。

    nano ~/テキトーなファイル名.sh    
をやって、以下の内容を貼り付ける。


```shell
#!/bin/bash

baseFolderName="mysymbol"
check=""


echo "********** Symbolリポジトリのクローン"
rm -rf symbol
git clone https://github.com/symbol/symbol.git
cd symbol
git checkout -b 1.0.3.5  refs/tags/client/catapult/v1.0.3.5


echo "********** コンフィグファイルの作成"
echo "compiler: ../compilers/gcc-latest.yaml" > ./jenkins/catapult/configurations/gcc-12-aarch64.yaml
echo "architecture: armv8-a" >> ./jenkins/catapult/configurations/gcc-12-aarch64.yaml

check=`docker images | grep symbol-server-compiler`
while [ "$check" = "" ]
do

echo "********** ベースとなるDockerイメージの作成 1/2"
echo -e "\
FROM arm64v8/ubuntu:22.04 \n\
\n\
ARG DEBIAN_FRONTEND=noninteractive \n\
\n\
RUN apt-get update >/dev/null && \\ \n\
    apt-get install -y \\ \n\
    apt-utils \\ \n\
    build-essential \\ \n\
    gnupg2 \\ \n\
    curl \\ \n\
    xz-utils \\ \n\
    wget \\ \n\
    >/dev/null \n\
\n\
\n\
ARG COMPILER_VERSION=12 \n\
RUN apt-get update >/dev/null && \\ \n\
    apt-get install -y \\ \n\
    gcc-\${COMPILER_VERSION} g++-\${COMPILER_VERSION} >/dev/null && \\ \n\
    update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-\${COMPILER_VERSION} 100 && \\ \n\
    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-\${COMPILER_VERSION} 100 && \\ \n\
    update-alternatives --install /usr/bin/cc cc /usr/bin/gcc 100 && \\ \n\
    update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++ 100 && \\ \n\
    update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-\${COMPILER_VERSION} 100 && \\ \n\
    update-alternatives --install /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-\${COMPILER_VERSION} 100 && \\ \n\
    update-alternatives --install /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-\${COMPILER_VERSION} 100 && \\ \n\
    rm -rf /var/lib/apt/lists/* \
" > jenkins/catapult/compilers/ubuntu-gcc/Dockerfile-ubuntu-gcc-12


echo "********** ベースとなるDockerイメージの作成 2/2"
docker build -f jenkins/catapult/compilers/ubuntu-gcc/Dockerfile-ubuntu-gcc-12 -t $baseFolderName/symbol-server-compiler:ubuntu-gcc-12 .

check=`docker images | grep symbol-server-compiler`

done



echo "********** runDockerBuild.pyを修正"
sed -i -e s/symbolplatform/$baseFolderName/g \
 -e s/"--source-path=\/catapult-src\/client\/catapult"/"--source-path=\/catapult-src\/catapult"/g \
 -e s/"f'registry.hub.docker.com\/{prepare_replacements\[\"base_image_name\"\]}'"/"f'{prepare_replacements\[\"base_image_name\"\]}'"/g \
 -e s/"environment_manager.copy_tree_with_symlinks(source_path \/ 'client\/catapult' \/ folder_name, folder_name)"/\
"environment_manager.copy_tree_with_symlinks(source_path \/ 'catapult' \/ folder_name, folder_name)"/g \
 jenkins/catapult/runDockerBuild.py





echo "********** environment.pyの修正"
sed -i -e s/"for descriptor in \[('ubuntu', '\/usr\/lib\/x86_64-linux-gnu'), ('fedora', '\/usr\/lib64')\]:"/\
"for descriptor in \[('ubuntu', '\/usr\/lib\/aarch64-linux-gnu'), ('fedora', '\/usr\/lib64')\]:"/g \
 jenkins/catapult/environment.py





check=`docker images | grep preimage1`
while [ "$check" = "" ]
do

echo "********** 中間イメージ1 1/2"
python3 ./jenkins/catapult/baseImageDockerfileGenerator.py \
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml \
    --operating-system ubuntu \
    --versions ./jenkins/catapult/versions.properties \
    --layer os \
| sed -e s/symbolplatform/$baseFolderName/g \
 -e s/cmake-3.23.2-Linux-x86_64.sh/cmake-3.24.3-linux-aarch64.sh/g \
 -e s/v3.23.2/v3.24.3/g \
> Dockerfile-preimage1

echo "********** 中間イメージ1 2/2"
docker build -f Dockerfile-preimage1 -t $baseFolderName/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage1 .

check=`docker images | grep preimage1`

done



check=`docker images | grep preimage2`
while [ "$check" = "" ]
do

echo "********** 中間イメージ2 1/2"
python3 ./jenkins/catapult/baseImageDockerfileGenerator.py \
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml \
    --operating-system ubuntu \
    --versions ./jenkins/catapult/versions.properties \
    --layer boost \
| sed -e s/symbolplatform/$baseFolderName/g \
> Dockerfile-preimage2

echo "********** 中間イメージ2 1/2"
docker build -f Dockerfile-preimage2 -t $baseFolderName/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage2 .

check=`docker images | grep preimage2`

done



check=`docker images | grep preimage3`
while [ "$check" = "" ]
do

echo "********** 中間イメージ3 1/2"
python3 ./jenkins/catapult/baseImageDockerfileGenerator.py \
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml \
    --operating-system ubuntu \
    --versions ./jenkins/catapult/versions.properties \
    --layer deps \
| sed -e s/symbolplatform/$baseFolderName/g \
 -e s/"Configure linux-x86_64"/"Configure linux-aarch64"/g \
> Dockerfile-preimage3


echo "********** 中間イメージ3 2/2"
docker build -f Dockerfile-preimage3 -t $baseFolderName/symbol-server-build-base:ubuntu-gcc-12-armv8-a-preimage3 . --memory-swap -1

check=`docker images | grep preimage3`

done



check=`docker images | grep ubuntu-gcc-12-armv8-a$'\s'`
while [ "$check" = "" ]
do

echo "********** 最終レイヤー 1/2"
python3 ./jenkins/catapult/baseImageDockerfileGenerator.py \
    --compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml \
    --operating-system ubuntu \
    --versions ./jenkins/catapult/versions.properties \
    --layer test \
| sed -e s/symbolplatform/$baseFolderName/g \
 -e s/"Configure linux-x86_64"/"Configure linux-aarch64"/g \
> Dockerfile-preimage4

echo "最終レイヤー 2/2"
docker build -f Dockerfile-preimage4 -t $baseFolderName/symbol-server-build-base:ubuntu-gcc-12-armv8-a .

check=`docker images | grep ubuntu-gcc-12-armv8-a$'\s'`

done



check=`docker images | grep symbol-server-test-base`
while [ "$check" = "" ]
do

echo "********** symbol-server-test-baseイメージを作成 1/2"
echo -e "\
FROM arm64v8/ubuntu:22.04 \n\

CMD ["/bin/bash"] \n\
ARG DEBIAN_FRONTEND=noninteractive \n\
\n\
RUN apt-get -y update \ \n\
    && apt-get install -y bison gdb git flex python3 python3-ply python3-pip shellcheck inotify-tools libdw-dev libelf-dev libiberty-dev libslang2-dev \ \n\
    && rm -rf /var/lib/apt/lists/* \ \n\
    && pip3 install -U colorama cryptography gitpython pycodestyle pylint pylint-quotes PyYAML \ \n\
    && git config --global http.postBuffer 524288000 \ \n\
    && git config --global https.postBuffer 524288000 \ \n\
    && git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux.git \ \n\
    && cd linux.git/tools/perf \ \n\
    && make \ \n\
    && cp perf /usr/bin \ \n\
    && cd ../../.. \ \n\
    && rm -rf linux.git \
" > Docker-test-preimage

echo "********** symbol-server-test-baseイメージを作成 2/2"
docker build -f Docker-test-preimage -t $baseFolderName/symbol-server-test-base:ubuntu .

check=`docker images | grep symbol-server-test-base`

done


check=`docker images | grep symbol-server$'\s'`
while [ "$check" = "" ]
do

echo "********** クライアントのコンパイル"
sudo mkdir /jenkins_cache
sudo chown 1000:1000 /jenkins_cache

python3 jenkins/catapult/runDockerBuild.py \
--compiler-configuration jenkins/catapult/configurations/gcc-12-aarch64.yaml \
--build-configuration jenkins/catapult/configurations/release-private.yaml \
--operating-system ubuntu \
--user "$(id -u):$(id -g)" \
--source-path client \
--destination-image-label gcc-12-armv8-a-main-9273d6c5

# うまくいかなかったのでハードコーディング
docker tag mysymbol/symbol-server-private:gcc-12-armv8-a-main-9273d6c5 mysymbol/symbol-server:gcc-1.0.3.5

check=`docker images | grep symbol-server$'\s'`

done




echo "********** restイメージ 1/3"

cd ./client
mv ./rest ./rest_old
git clone https://github.com/symbol/symbol.git -b rest/v2.4.2
cp -r ./symbol/client/rest ./
rm -rf symbol



echo "********** restイメージ 2/3"
cd ./rest
cat ./Dockerfile | sed s/lts/16/g > ./Dockerfilev2

echo "********** restイメージ 3/3"
docker build -f ./Dockerfilev2 -t $baseFolderName/symbol-rest:2.4.2 .





echo "********** Node.js を最新バージョンにする"
sudo npm install -g n
sudo n latest


check=`symbol-bootstrap version | grep node`
while [ "$check" = "" ]
do

echo "********** symbol-bootstrapのインストール"
sudo npm install -g symbol-bootstrap

echo "コンテナイメージの変更"
sudo cp /usr/local/lib/node_modules/symbol-bootstrap/presets/shared.yml /usr/local/lib/node_modules/symbol-bootstrap/presets/shared_old.yml
sudo sed -i -e s/"symbolServerImage: symbolplatform"/"symbolServerImage: "$baseFolderName/g \
 -e s/"symbolRestImage: symbolplatform"/"symbolRestImage: "$baseFolderName/g \
 /usr/local/lib/node_modules/symbol-bootstrap/presets/shared.yml

check=`symbol-bootstrap version | grep node`
done

```

    bash テキトーなファイル名.sh
これで実行。
おそらく大丈夫なハズ。


    baseFolderName=
は好きな名前を入れられたい。

ネットワークが貧弱だとイメージ作成が失敗することがあるので上手くいくまでループさせている。
素人が書いたスクリプトなので、雑な部分は大いにある。

peerノードでいい人は


    echo "********** restイメージ 1/3"

から始まるrestイメージの部分は削除してもいい。

    docker images
スクリプト実行後はこれで作成済みのDockerのイメージが見られるので、全て作成されたか確認


# ５　DDNSの設定

https://yuki9431.hatenablog.com/entry/2019/03/09/122723

このサイトのとおりやった。感謝。

# ６　symbol-bootstrap

細かな設定は他サイトを参照されたい。


### 6-1 設定ファイルの作成１

    cd ~/symbol
で移動し、

    symbol-bootstrap wizerd
で設定ファイルを作る。

    ~/symbol/custom-preset.yml
があることを確認したら

    nano ~/symbol/custom-preset.yml
で、末尾に
    
    symbolServerImage: シェルスクリプトで設定した(baseFolderNameの)名前/symbol-server:gcc-1.0.3.4  
    symbolRestImage: シェルスクリプトで設定した(baseFolderNameの)名前/symbol-rest:2.4.2            #先程作成したイメージ名
を追加。


### 6-2 設定ファイルの作成２


    symbol-bootstrap config -p testnet -a dual -c custom-preset.yml 
を実行。メインネットがいい人は testnetをmainnetに変更すること。

    symbol-bootstrap compose
を実行。

### 6-3 起動

    symbol-bootstrap run -d
を実行し、ノードを起動。

    symbol-bootstrap healthCheck
で、正常に作動しているかが確認できる。

# 終わりに





        NACW73ZWAD6RGZPC3P64DN3KYK5XDLLMVGHW2KQ
しつこいようですが私のsymbolアドレスです。