にわかプログラマの技術ブログ

C#しかまともに読めないにわか技術者。何かを作りたいわけじゃない。新しい技術を触りたいだけです。

Raspberry Pi にVirtualenvでPythonの仮想環境を構築する

(Raspberry Pi に限った話ではないのですけどね)

pipのインストール

Python3の開発用パッケージをインストール

$ sudo apt-get -y install python3-dev

Python3のpipをインストール

$ sudo apt-get -y install python3-pip

Virtualenv のインストール

# pipのアップグレード
$ pip3 install --upgrade pip

# Virtualenv のインストール
$ pip3 install virtualenv

仮想環境の作成

# 仮想環境の作成
$ python3 -m venv 〇〇

# 仮想環境のディレクトリが作成される
$ ls
〇〇

# 仮想環境のアクティブ化
$ source 〇〇/bin/activate

# 端末に ( ) で使用している仮想環境の名前が表示される
(〇〇) $

# 仮想環境のディアクティブ
(〇〇) $ deactivate

# 仮想環境の削除
# (プロジェクト直下に生成されたフォルダを、まるごと削除でOKです。)
$ rm -rf 〇〇

Raspberry Pi のネットワーク設定

ネットワーク設定ファイルの種類

OSによって使用する設定ファイルが異なるようです。以下はラズパイ(Raspberry Pi OS)の場合はのリストです。

パス メモ
wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf ルーターの指定はここ
dhcpcd.conf /etc/dhcpcd.conf IPの指定はここ
interfaces /etc/network/interfaces 昔はね、DHCPなのか静的IPかはここだったのよ
NetworkManager /etc/NetworkManager/system-connections/ Desktop版に入っているが...?
Netplan /etc/netplan/01-network-manager-all.yaml Ubuntuとかはこゆのもありました

wpa_supplicant

ラズパイではルーターの指定をするファイルです。ただしraspi-configから設定できるのでそちらを使うのがよろしいかと思います。

$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

# 追加
network={
  ssid="{myssid}"
  psk="{mypassphrase}"
}

dhcpcd.conf

ラズパイでのIPアドレスを設定するファイルです。

$ sudo nano /etc/dhcpcd.conf 
# Example static IP configuration:
interface eth0 # ネットワークインターフェースを指定します (無線LANの場合は wlan0)
static ip_address=192.168.0.212/24 # IPアドレスとサブネットを指定します
static routers=192.168.0.1 # ゲートウェイを指定します
static domain_name_servers=192.168.0.1 # DNSを指定します

# デスクトップ版のGUIから設定すると↓みたいになるので、SSIDも指定可能みたいです
SSID {myssid}
static ip_address=192.168.0.212/24 # IPアドレスとサブネットを指定します
static routers=192.168.0.1 # ゲートウェイを指定します
static domain_name_servers=192.168.0.1 # DNSを指定します
static domain_search=
noipv6

interfaces

最新のラズパイOSでは未使用であり、設定するとネットワークエラーとなるため注意してください。昔のラズパイではネットワークインターフェースがDHCPなのか静的IPなのか、また使用するネットワークインターフェースを指定するファイルだったみたいです。

$ sudo nano /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

# Ethernet port
auto eth0
iface eth0 inet static

# wifi port
auto wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Raspberry Pi の環境構築手順メモ

前提条件

Raspberry Pi OS (Raspbian) を使用します。でもUbuntuであっても設定方法は違いますが、やりたいことは同じだと思います。

OSのイメージのSDカードへの書き込む

EtcherRaspberry Pi ImagerでOSのイメージのSDカードへの書き込みます。

環境設定

環境設定コマンドがあるので有難く使わせてもらいましょう。

$ sudo raspi-config

パスワードの変更

1 Change User Password を選択してデフォルトパスワードを変更します。

ホスト名の変更

2 Network Options > N1 Hostname を選択してホスト名を変更します。

Wi-Fiの設定

  1. 2 Network Options > N2 Wireless LAN を選択
  2. 初回は WLAN Country の選択が促されるので Japan を選択
  3. 4 Localisation Options > I4 Change WLAN Country から再設定できます
  4. 無線LANSSIDとパスワードを設定

ロケールの設定

日本語で使いたい場合は設定してください。テラタームなどで日本語になります。しかしraspi本体は文字化けします。

  1. 4 Localisation Options > I1 Change Locale を選択
  2. ja_JP.UTF-8 UTF-8 をスペースキーでチェックしてエンター
  3. システム全体のデフォルトロケールを尋ねられるので ja_JP.UTF-8 を選択

タイムゾーン

  1. 4 Localisation Options > I2 Change Timezone を選択
  2. Asia > Tokyo を選択

SSH serverの有効化/無効化

  1. 5 Interfacing Options - P2 SSH を選択

Would you like the SSH Server to be enabled?

  1. と聞かれるのでYesを選択
    • Noを選択した場合は無効となります

セキュリティ対策

1. デフォルトユーザーの「pi」を削除する

初期状態では、デフォルトユーザーの「pi」とパスワード「raspberry」が準備されています。がこれはインターネットに出回っているため外部公開する場合は危険です。よってオンリーワンなユーザーを作成してデフォルトユーザーの「pi」を削除します。

1-1. rootのパスワードを設定

初期状態では、スーパーユーザーのrootがパスワードで保護されていません。この状態では全ての操作がパスワード無しで実行可能となってしまいます。よってrootにパスワードを設定します。

$ sudo passwd root
Enter new UNIX password: #rootのパスワードを設定
Retype new UNIX password: #パスワードを再入力
passwd: password updated successfully

1-2. ユーザーの追加

$ sudo adduser 〇〇 # 〇〇というユーザーを追加
:
Enter new UNIX password: #新しく作成するユーザーのパスワードを設定
Retype new UNIX password: #パスワードの再入力
passwd: password updated successfully
Changing the user information for 〇〇
Enter the new value, or press ENTER for the default
    Full Name []: #入力の必要なければそのままEnter
    Room Number []: #同上
    Work Phone []: #同上
    Home Phone []: #同上
    Other []: #同上
Is the information correct? [Y/n] Y #「Y」と入力してEnter

1-3. 管理者権限の付与

piユーザーが属するグループを確認して同じグループに新規ユーザーを登録します。

 # piユーザーが属するグループを表示
$ groups pi
pi : pi adm dialout cdrom sudo audio video plugdev games users input netdev spi i2c gpio

# 同じグループに新規ユーザーを登録
$ sudo usermod -G pi,adm,dialout,cdrom,sudo,audio,video,plugdev,games,users,input,netdev,spi,i2c,gpio 〇〇

# ラズパイからログアウトして新規ユーザーでログインできることを確認してください
$ exit

1-4. 新規ユーザーがパスワードなしでsudoを実行できるようにする

sudo 設定ファイルを以下のコマンドで開きます。

$ sudo visudo

以下を挿入して保存します

#includedir /etc/sudoers.d
〇〇  ALL=(ALL) NOPASSWD: ALL # 挿入

piユーザをsudoグループから外します

$ sudo gpasswd -d pi sudo
Removing user pi from group sudo

piユーザを削除します

# ユーザーを確認
$ id -a pi
uid=1000(pi) gid=1000(pi) groups=1000(pi),4(adm),20(dialout),24(cdrom),29(audio),44(video),46(plugdev),60(games),100(users),101(input),108(netdev),999(spi),998(i2c),997(gpio)

# 削除
$ sudo userdel -r pi
userdel: group pi not removed because it has other members.
userdel: pi mail spool (/var/mail/pi) not found

# 削除されていることを確認
$ id -a pi
id: ‘pi’: no such user 

2. ログイン方式を公開鍵暗号方式にする

2-1. 鍵の作成

作成方法は色々ありますが、私はテラタームで作成しました。ラズパイではなく別のマシンでの作業なので省略しますが、作成した公開鍵id_rsa.pub秘密鍵id_rsaは決まったディレクトリに配置しないといけません。(Windowsマシンであろうとラズパイであろうと)

Windowsの場合はC:\Users\{ユーザー名}\.sshですし、ラズパイの場合は~/.sshです。

2-2. ラズパイに公開鍵を送信

公開鍵の転送先ディレクトリを作成します。

# ラズパイのホームディレクトリに.sshディレクトリを作成
$ mkdir ~/.ssh

そこに2-1. 鍵の作成で作成した公開鍵id_rsa.pubを配置します。私はテラタームを使って転送しました。

2-3. 公開鍵のパーミッションを変更

# パーミッションを700に変更
$ chmod 700 ~/.ssh

# id_rsa.pubの内容をauthorized_keysに書き込み
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

# パーミッションを600に変更
$ chmod 600 ~/.ssh/authorized_keys

# 不要となったid_rsa.pubを削除
$ rm ~/.ssh/id_rsa.pub

2-4. SSHの設定ファイルを変更

# SSHの設定ファイル
$ sudo nano /etc/ssh/sshd_config

下記の5カ所を変更します

#Port 22
Port 61234 # SSHポート番号を変更#PermitRootLogin prohibit-password
PermitRootLogin no # rootでログインできないようにする#PubkeyAuthentication yes
PubkeyAuthentication yes # 公開鍵でログインできるようにする (デフォルトでなっているのでしょうけど)#PasswordAuthentication yes
PasswordAuthentication no # パスワードでログインできないようにする
#PermitEmptyPasswords no
PermitEmptyPasswords no # パスワードなしのログインを禁止する

2-5. SSHの再起動

sudo systemctl restart sshdSSHを再起動します

ステップアップ:SSH接続をスムーズに

.ssh(Windowsの場合はC:\Users\{ユーザー名}\.ssh)配下にconfigファイルを作成します。内容は以下

Host raspi
    HostName 192.168.XXX.XXX (場合によってはHostName.localとすることも)
    User {ラズパイのユーザー名}
    port {SSHのポート}
    IdentityFile {秘密鍵のパス}

コマンドプロンプトであれば以下のコマンドによりSSH接続することができます。

> ssh raspi

ステップアップ:ログを監視/通知する (Slackと連携) ※準備中...

ログファイルを監視し、SSH接続時にSlackへ通知を飛ばします。

Slack側の準備

SlackというチャットツールのIncoming Webhookを使用します。

監視プログラムを作成 (Python)

テスト実行

以下のコマンドで実行します

$ python3 run.py

SSHで接続すると通知がくることを確認します

ログアウト後も実行状態を継続させる

以下のコマンドで実行します

$ nohup python3 run.py > /dev/null 2>&1 &

プロセスの終了はkillコマンドからプロセスIDを指定して強制終了させます

# プロセスID確認
$ ps aux | grep run.py
# プロセス強制終了
$ kill 444

起動時に自動実行させる

# サービスの作成
$ sudo nano /etc/systemd/system/logmonitors.service
[Unit]
Description=Log Monitors

[Service]
ExecStart=/usr/bin/python3 /home/xxx

[Install]
WantedBy=multi-user.target
# systemdに登録
$ sudo systemctl enable logmonitors.service
# systemdに登録
$ sudo systemctl start logmonitors.service