Raspberry Piをリフレッシュする（環境再構築）

ネットワーク関連で弄り回してるラズパイ(Raspberry Pi 3B+)の設定とかパッケージ管理とかがぐちゃぐちゃになってしまって把握できなくなったので、しっかり計画性を持って永続的に稼働させられ続けるよう一旦オールリセットして再稼働しようと思いました。この記事はそのときの手順書兼備忘録です。


#システム情報
###Raspberry Pi 3B+（移行前）
<ul>
  <h4>OS</h4>
  Raspberry Pi OS (Raspbian)
  
  
</ul>

###Raspberry Pi 3B+（移行後）
<ul>
  <h4>OS</h4>
  Raspberry Pi OS (Raspbian)
</ul>

###条件
<ul>
  - モニターは繋がない（ヘッドレス）<br>
  - 管理はSSH,xRDPのどちらかを使う<br>
  - sudo権限有り
</ul>

#移行前の準備
移行しようと思ってすぐ作業に入ってもまたよくわからんことになるので、しっかり移行前に計画を立てます。

##移行するファイル、設定等の洗い出し
まず、移行すべきファイルや設定などをまとめ、書き出すことにしました。

###移行前の環境で稼働させていたサービス

- __SoftEther VPN Server__<br>
 — LAN内へのVPN接続に使用
- __Node.js__<br>
 — Webアプリのホスティングに使用
- __PM2__<br>
 — Node.jsアプリの常時稼働用に使用
- __Nginx HTTP Server__<br>
 — Node.jsサーバーのリバースプロキシ、HTTPプロキシサーバーのホスティングに使用
- __ISC-DHCP-Server__<br>
 — LAN内でのDHCPサーバーとして使用
- __BIND9__<br>
 — LAN内でのDNSサーバーとして使用
- __Cockpit__<br>
 — ラズパイのリソース使用量監視に使用
- __xrdp__<br>
 — 他マシンからのリモートデスクトップ接続のために使用
- __ufw__<br>
 — 外部からの不要・悪意あるネットワークトラフィックを遮断するために使用

###移行後の環境に引き継ぐもの
- __SoftEther VPN Server__
  - 仮想HUBやサーバーの設定
- __Node.js__
  - インストールしたモジュール
- __PM2__
- __Nginx HTTP Server__
  - サーバーの設定ファイル
- __ISC-DHCP-Server__
  - サーバーの設定ファイル
- __BIND9__
  - DNSのデータベース、設定ファイル
- __Cockpit__
  - SSL/TLSの証明書
- __xrdp__
- __ufw__
  - 許可・拒否リスト

- Crontabのコマンド

##移行の手順を整理
どのような手順でデータをバックアップし、移行して復元するかをGoogleドキュメントへ書き出しました。



#移行作業
本番の移行作業です。手順を整理したGoogleドキュメントに従いながら、進めていきます。


##リセット前の作業

###BIND9の設定ファイルのコピー
BIND9の各種設定ファイルは（`apt`でインストールしていれば）`/etc/bind/`内にあります。

- `named.conf`（下記設定ファイル読み込み用）
- `named.conf.options`（設定の受付）<br>
（これより下のファイルは人によって名称が異なります）
- `named.conf.internal-zones`（正引き・逆引き要求の参照先の指定）
- `[domain-name].db`（正引き用データベース）
- `1.168.192.db`（逆引き用データベース）

をコピーして別PCなどに保存します。

###Nginxの設定ファイル・コンパイル用ファイルのコピー
Nginxの各種設定ファイルは（`apt`でインストールしていれば）`/etc/nginx/`内にあります。
（私は諸事情で（フォワードプロキシを運用する関係上）ソースからコンパイルしていたので、`/usr/local/nginx/`内でした。）

- `nginx.conf`（下記サーバー設定ファイル類の読み込み）
- `conf.d/*.conf`（稼働させているサーバーの設定ファイル類）<br>
（`*`には任意の名前が入ります）

をコピーします。

###SoftEther VPN Server Configrationファイルのコピー
SoftEtherは人によって保存する場所が違ってくるのですが、私は`/usr/local/vpnserver`内に保存していました。

- `vpn_server.config`（サーバー設定全般）

をコピーします。

###ISC-DHCP-Serverの設定ファイルのコピー
ISC-DHCP-Serverの各種設定ファイルは（`apt`でインストールしていれば）`/etc/dhcp/`内にあります。

- `dhcpd.conf`（サーバー設定全般）

をコピーします。

###Let’s Encrypt 証明書フォルダのコピー
`Certbot`を使用して証明書を取得した場合、`/etc/letsencrypt/`内にさまざまな証明書関係のファイルが保存されます。

- `letsencrypt`フォルダー

フォルダごとそのままコピーします。

##リセット作業
コピー作業が終わったら、ラズパイをリセットします。
__コピーし忘れたファイルはありませんか？よく確認してください。__

今回はラズパイはリモートでしか管理できないので、microSDカードにイメージを書込み直すという方法でリセットします。
ラズパイにディスプレイとキーボードがつなげられる場合、起動時に`Shift`キーを押すことでも初期化できるそうです。

###ラズパイのシャットダウン
`sudo shutdown`でOSをシャットダウンした後、緑色のLEDが点滅しなくなったことを確認してから電源コードを抜き、microSDカードを取り出します。

###microSDカードのイメージ書き直し
今回は公式がリリースしている「Raspberry Pi Imager」を使います。

  1. `Erase`を選択し一旦フォーマット
  1. `Raspberry Pi OS (32bit)`を選択しインストール

###SSHの事前有効化
そのまま起動してしまうとSSHが無効化されていてリモート接続できないので、microSDカード内にファイルを追加します。
microSDカードの`Boot`パーティションのルートディレクトリに`ssh`（中身空）を作成します。
ラズパイを無線LANに繋げてリモート接続する場合は、別途設定するとヘッドレスでWi-Fiにつなげられるそうです。

###ラズパイ起動
書き込み直したmicroSDカードをラズパイに差し込み、起動します。
別のデバイスから`ssh pi@raspberrypi.local`でログインします。
ログインできたらまず

```shell
$ sudo apt update
$ sudo apt full-upgrade
$ sudo apt dist-upgrade
```

を実行し、OSを最新版へアップデートしておきます。

- - -

###初期設定・セキュリティ対策
ラズパイの初期設定と不正ログインなどの対策を行います。以下の記事を参考にしました。

[Raspberry Piのセキュリティを真剣に考える](https://qiita.com/Kazuya_Murakami/items/b0ec7e65a7fe39cfd746)

https://qiita.com/Kazuya_Murakami/items/b0ec7e65a7fe39cfd746

[買ったらまず実施！RaspberryPiのセキュリティ対策](https://qiita.com/c60evaporator/items/ebe9c6e8a445fed859dc)

https://qiita.com/c60evaporator/items/ebe9c6e8a445fed859dc

- - -

###Crontabの復元
前環境のCrontabに登録されていた定期タスクを新Crontabに書き込みます。
（前環境では証明書の更新・DDNSの更新をCrontabで行っていました。）

- DDNSの更新


次のCertbotでの証明書更新の際にドメイン名を使うので、このタイミングでDDNSのIPアドレスを更新しておきます。
私はDDNSサービスに[DDNS Now](https://ddns.kuku.lu/)を使用しているので、公式のヘルプに従って設定しました。

[更新方法の解説 - DDNS Now](https://ddns.kuku.lu/setupinfo.php)

https://ddns.kuku.lu/setupinfo.php

```shell
$ sudo crontab -e
# Crontabの書き込み用ファイルが開いたら、末尾に下のコマンドを追加

# IPv4用
0-59 * * * * wget -O DDNSNow_update.log "https://f5.si/update.php?domain=ユーザ名&password=パスワード"
# IPv6用
0-59 * * * * wget -O DDNSNow_update.log "https://v6.f5.si/update.php?domain=ユーザ名&password=パスワード"
```

- 証明書の更新

次に行うCertbotでの証明書の自動更新タスクを先にCrontabに書き込んでおきます。
下の記事を参考に設定しました。

[Let’s EncryptのSSL証明書を更新する(手動とcronによる自動更新)](https://it-jog.com/khow/serv/renewletsencrypt)

https://it-jog.com/khow/serv/renewletsencrypt

```shell
$ sudo crontab -e
# Crontabの書き込み用ファイルが開いたら、末尾に下のコマンドを追加

# 毎月1日と15日、0時0分に証明書更新を要求し、更新後はNginxを再起動させる
0 0 1,15 * * sudo certbot renew --post-hook "systemctl restart nginx"
```

- - -

###Certbotのインストール・Let's Encrypt証明書ディレクトリの復元
今後の復元作業において証明書ファイルが必要になる場面が多々あるので、先に証明書が使える環境を作っておきます。

```terminal
$ sudo apt install certbot
# コピーしておいた “letsencrypt” フォルダーを /etc/ に配置
$ sudo cp -r [コピー元] /etc/

# お試し環境 (dry-run) で証明書が正常に更新されるのを確認する
$ sudo certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/[domain-name].conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not due for renewal, but simulating renewal for dry run
Plugins selected: Authenticator standalone, Installer None

Renewing an existing certificate
Performing the following challenges:
http-01 challenge for [domain-name]
Waiting for verification...
Cleaning up challenges

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed without reload, fullchain is
/etc/letsencrypt/live/[domain-name]/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/[domain-name]/fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```
Congratulations, ...と表示されれば成功しているので、次に進みます。

- - -

###必要パッケージのインストール・再設定
前環境に入っていたパッケージなどをインストールし直し、復元していきます。
参考にしたWeb上の記事を貼っておきます。

####ufw
[iptablesが難しいためufwでWEBサーバーのファイアウォール設定](https://qiita.com/shimakaze_soft/items/c3cce2bfb7d584e1fbce)

https://qiita.com/shimakaze_soft/items/c3cce2bfb7d584e1fbce

[ufwでIPv6のポートだけを開くには？](https://linuxfan.info/post-7961)

https://linuxfan.info/post-7961

```shell
# ufwをインストール
$ sudo apt install ufw

# ufwの状態を確認
$ sudo ufw status
Status: inactive # 現在は無効化されている

# いったんすべての通信を拒否する設定にする（ufw自体は無効なのでSSHは切断されない）
$ sudo ufw default DENY
Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)

# 192.168.1.0/24 (LAN内) からのSSH接続を許可する
$ sudo ufw allow from 192.168.1.0/24 to any port ssh
Rules updated

# この段階でufwを有効化させる
$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

$ sudo ufw status
Status: active # 有効化されている

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW       192.168.1.0/24

# 以降、必要なポートの開放作業を行う

# 指定したポート番号へのIPv4/IPv6 TCP/UDP接続を許可
$ sudo ufw allow [ポート番号]

# 指定したポート番号へのIPv4/IPv6 UDP接続を許可
$ sudo ufw allow [ポート番号]/udp

# 指定したポート番号へのIPv6 TCP/UDP接続を許可
$ sudo ufw allow to ::/0 port [ポート番号]

# 指定したネットワークアドレスからのIPv4 TCP/UDP接続を許可
$ sudo ufw allow from [ネットワークアドレス/サブネット長] to any port [ポート番号]


```

- - -

####xRDP
[Raspberry Piにリモートデスクトップ接続する(xrdpのインストール)](https://raspi.taneyats.com/entry/install-xrdp)

https://raspi.taneyats.com/entry/install-xrdp

```shell
$ sudo apt install xrdp

# このままだとリモートデスクトップしても操作できないので、
# 設定をいじって操作できるようにする
$ sudo raspi-config

[2 Display Options] -> [D4 Screen Blanking] -> [Yes]

# ufwも忘れずに
```

- - -

####Cockpit
[Raspberry Piに管理ツール"Cockpit"を入れてみる](https://qiita.com/nil0nil/items/f5d72dadba2da292e1d9)

https://qiita.com/nil0nil/items/f5d72dadba2da292e1d9

```shell
# 上記記事のdirmngrインストールやパッケージリスト追加は不要
$ sudo apt install cockpit

# curlでアクセスして応答があればOK
$ curl localhost:9090

# ufwも忘れずに
```

- Let’s Encrypt証明書の使用方法

[Use Let’s Encrypt certificates with Cockpit（英語）](https://ryan.lovelett.me/posts/letsencrypt-cockpit/)

https://ryan.lovelett.me/posts/letsencrypt-cockpit/

[Cockpit with LetsEncrypt（英語）](https://github.com/cockpit-project/cockpit/wiki/Cockpit-with-LetsEncrypt)

https://github.com/cockpit-project/cockpit/wiki/Cockpit-with-LetsEncrypt

```shell
# Cockpitの証明書は /etc/cockpit/ws-certs.d/ に置く
# /etc/letsencrypt/live/[domain-name]/ から証明書をとってきて
# fullchain.pemとprivkey.pemを1-my-cert.certに統合するスクリプトを書く
$ nano cockpit-cert.sh
```
```shell:cockpit-cert.sh
cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem > /etc/cockpit/ws-certs.d/1-my-cert.cert
cat /etc/letsencrypt/live/$DOMAIN/privkey.pem >> /etc/cockpit/ws-certs.d/1-my-cert.cert
systemctl daemon-reload && systemctl restart cockpit.socket
```
```shell
# Crontabにスクリプトを登録する
$ sudo crontab -e
# Crontabの書き込み用ファイルが開いたら、末尾に下のコマンドを追加

# 毎月1日と15日、0時30分にスクリプトを実行
30 0 1,15 * * sudo [cockpit-cert.shへのパス]
```

- - -

####SoftEther VPN Server

[Raspberry Pi 上にSoftetherをつかってVPNを構築する](https://qiita.com/sigma7641/items/6b253703efe5f8f06de2)

https://qiita.com/sigma7641/items/6b253703efe5f8f06de2

[ラズベリーパイでのVPNサーバー構築](https://qiita.com/ryo0916/items/9fe094dce7e0d9e2e222)

https://qiita.com/ryo0916/items/9fe094dce7e0d9e2e222

[SpftEtheVPNサーバーの別サーバー機への移行方法を教えてください](https://forum.vpngate.net/viewtopic.php?t=64328)
<font color="lightgray">~~誤字がすごい~~</font>

https://forum.vpngate.net/viewtopic.php?t=64328

- - -

####ISC-DHCP-Server
[ラズパイ(RaspberryPi3)をDHCPサーバーにしてみた](https://qiita.com/homines22/items/cccd711c9a77680d1e2c)

https://qiita.com/homines22/items/cccd711c9a77680d1e2c

```shell
$ sudo apt install isc-dhcp-server
```

- - -

####BIND9

[raspberry piでローカルDNSサーバを作る](https://anpontan382.hatenablog.com/entry/2018/06/20/222803)

https://anpontan382.hatenablog.com/entry/2018/06/20/222803

[【Raspberry Pi Zero】宅内専用　DNSサーバー(BIND9)構築](http://kykyblog.air-nifty.com/blog/2020/10/post-156219.html)

http://kykyblog.air-nifty.com/blog/2020/10/post-156219.html

```shell
$ sudo apt install bind9

# ufwも忘れずに
```

- - -

####Node.js
[ラズパイにNodejs を入れてWebサーバにする](https://note.com/agw/n/n3d41dc352b14)

https://note.com/agw/n/n3d41dc352b14

```shell
# 普通のaptで取得するNode.jsのバージョンは若干古いので、新しいバージョンのNode.jsの取得先を設定する
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -

# 新しいバージョンのNode.jsとnpm（パッケージ管理ツール、aptのようなもの）をインストールする
# Node.jsをインストールするとnpmも自動でインストールされる
$ sudo apt install nodejs

# aptで取得するnpmもバージョンが古いので、npm自身でnpmを更新する
$ sudo npm install npm -g
```

- - -

####PM2
[インスタンスが起動したら自動的にNode.jsアプリが起動するようにする](https://qiita.com/kuryus/items/fbdc373f23d3236ebb04)

https://qiita.com/kuryus/items/fbdc373f23d3236ebb04

```shell
$ sudo npm install pm2 -g

# PM2のデーモン化
$ pm2 startup
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u [ユーザー名] --hp /home/[ユーザー名]

# 表示されたコマンドを実行する
$ sudo env PATH=$PATH:/usr/local/bin /usr/local/lib/node_modules/pm2/bin/pm2 startup systemd -u [ユーザー名] --hp /home/[ユーザー名]
```

- - -

####Nginx
- ソースからのコンパイル方法・フォワードプロキシ構築

[HTTPS通信をNginxでフォワードプロキシ](https://blog.motikan2010.com/entry/2020/03/18/HTTPS%E9%80%9A%E4%BF%A1%E3%82%92Nginx%E3%81%A7%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7)

https://blog.motikan2010.com/entry/2020/03/18/HTTPS%E9%80%9A%E4%BF%A1%E3%82%92Nginx%E3%81%A7%E3%83%95%E3%82%A9%E3%83%AF%E3%83%BC%E3%83%89%E3%83%97%E3%83%AD%E3%82%AD%E3%82%B7

[NginxでHTTPS対応のフォワードプロキシを構築](https://fujiu.hatenablog.com/entry/2020/03/15/010353)

https://fujiu.hatenablog.com/entry/2020/03/15/010353

[Nginxをソースからビルドしてインストールする方法](https://www.task-notes.com/entry/20170510/1494385200)

https://www.task-notes.com/entry/20170510/1494385200



```shell
# この後必要になるパッケージをインストールしておく
$ sudo apt install libpcre3-dev libxml2 libxslt-dev libgd-dev google-perftools libgoogle-perftools-dev

# いきなりNginxをビルドするとOpenSSL関係で怒られるので、OpenSSLもソースからビルドする
$ mkdir openssl-build
$ cd openssl-build
# ダウンロードするのは一番上ではなく、バージョン番号の一番後ろにアルファベットがついたもの
$ wget https://www.openssl.org/source/openssl-x.x.x.tar.gz
$ tar zxvf openssl-x.x.x.tar.gz
$ cd openssl-x.x.x
# sudo make installした時のインストール先などを設定
$ ./config --prefix=/usr/local --openssldir=/usr/local/ssl shared
# makeにはそこそこ時間がかかるので待つ
$ make
$ sudo make install

# Nginxのビルドをする
$ mkdir Nginx-build
$ cd Nginx-build
# フォワードプロキシ用のモジュールをダウンロードする
$ git clone https://github.com/chobits/ngx_http_proxy_connect_module.git -b v0.0.1
# Stableの欄にあるVerをダウンロードする
$ wget https://nginx.org/download/nginx-x.x.x.tar.gz
$ tar zxvf nginx-x.x.x.tar.gz
$ cd nginx-x.x.x
# ビルドする目的であるフォワードプロキシ用のパッチを適用する
$ patch -p1 < ../ngx_http_proxy_connect_module/patch/proxy_connect_rewrite_101504.patch
$ ./configure --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module --with-http_image_filter_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-google_perftools_module --with-cpp_test_module --add-module=../ngx_http_proxy_connect_module
$ make
$ sudo make install
```

- リバースプロキシ構築・HTTPS対応・リダイレクト

[SSLに対応したNGINXリバースプロキシを構築する手順](https://qiita.com/tnoce/items/ded6d3d298da5972ab63)

https://qiita.com/tnoce/items/ded6d3d298da5972ab63

[NginxでSSLを設定する方法を基本から学ぶ](https://katsusand.dev/posts/nginx-ssl/)

https://katsusand.dev/posts/nginx-ssl/

[nginx で http でのアクセスを https にリダイレクト](https://qiita.com/kga/items/e30d668ec1ac5e30025b)

https://qiita.com/kga/items/e30d668ec1ac5e30025b

- - -

以上で移行は終了です。

#おまけ（後日追加）
##Samba

[Raspberry PIにSambaをインストール](https://qiita.com/neomi/items/645e2c7184210f989828)

https://qiita.com/neomi/items/645e2c7184210f989828

```shell
$ sudo apt install samba

# Sambaの設定ファイルを編集
$ sudo nano /etc/samba/smb.conf

# Sambaのユーザーの作成・パスワード設定
$ sudo smbpasswd -a [ユーザー名]

# Sambaを再起動
$ sudo systemctl restart smbd
```
#おわりに
__ufwは忘れずに。__時間が溶けます。