Amazon Lightsailでdiscord.py製のBotを常時ホストする

# 注意
この記事は一端の情報工学生という素人が書いたものです。
細かい間違いなどあるかもしれませんがすべて許してください。

# 前置き
**無料のDiscordBot常時ホストがめんどくさい！！！！**
Herokuなど多くのサービスが有料化しており、無料で使えるものが限られてきています。
render.comに登録してみましたがデプロイが何故か尽く失敗し上手く行かず……。
やれDockerだの、やれFlaskだの、やれUptimerobotだの……。
**うるせえ！！もっとシンプルに動かしたいんじゃ！！**

また、intel N100を搭載したミニPCを簡易的なサーバーとして置いていました……が！
**先日のアップデート時に壊れました。**
色々やっても上手く行かないので、なんとかデータだけ引っ張り出して修理は後回しの状態です。

……そういえば、AWSとか触ってこなかったなぁ……。

というわけで、比較的安い中で安定性もあり、最低$3.5/月という[Amazon Lightsail](https://aws.amazon.com/jp/lightsail/)を使ってDiscordBotを常駐させてみました。
なお、同時にお名前.comで取ったドメインと紐づけてWebサーバーもホストしたいと思っています。

今回のプランは$5/月です。
**え、電気代も固定IPも入ってこの値段！？IPアドレスの固定化のためだけに毎月1000円くらい払ってたのに！？**
自分は今まで何をしていたんでしょうね……。

# この記事の対象
- discord.pyで作成したBotを常時起動させたい人
- DockerとかでなくシンプルにvenvでBotをホストしたい人
- AWS・VPSを知ってはいるが触ったことがない人
- Ubuntuを少しは触った経験がある人

# 用意したBot
今回はGeminiを使ったBotを作ってみました。
めちゃくちゃ個人的に使うだけですが、良かったら勝手に個人でクローンするなりして使ってください。
何も考えてないのでコミットの名前がクソ雑なのはお許しを。

https://github.com/DistNovelist/AutoEventer/tree/main


# 手順

## Amazon Lightsailのインスタンスの作成
AWSのアカウントを持っていない人は作成します。

https://aws.amazon.com/jp/lightsail/

アカウントを作成したらLightsailのダッシュボードから[+ Create instance]ボタンを押します。
ここで貸し出してくれる環境が選べるみたいです。
今回はRegionをTokyo (ap-northeast-1)、platformをLinux/Unix、blueprintをOprating System (OS) OnlyのUbuntu 24.04LTSにしました。
他のLinuxに慣れてる人はそちらを選ぶと良いと思いますが、自分はUbuntuを一番良く触っていたので慣れたUbuntuで行きます。
![chrome_WK1X9IIEp3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102419/c87ec3ef-8e6e-b94b-61e4-2a97c02f5333.png)

また、プランとしてはDual-stackの$5プランを選択します。最初の3ヶ月無料は嬉しいね。
![chrome_ixmO607zrh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102419/384241ce-7903-8bc8-d460-ce372aef6bae.png)

あとは適当なインスタンス名を入れてCreateInstanceで作成です。
かんたん。

## 静的IPアドレスの設定
IPアドレスを固定化しないと色々面倒です。
インスタンスの情報を開き、Networkingから静的IPの作成を押します。
あとは指示に従っているだけで、一瞬で静的IPを取得できます。
スクショを撮るのが大変なので、よくわからないという方は以下を参考にしてください。

https://qiita.com/tomokei5634/items/a5dfb8504989ed93c31b

## SSHの設定（任意）
SFTPを使う時、自分はWinSCPを利用しています。もちろん、FileZillaなど他のクライアントでも構いません。
とにかくこれらのソフトがあると、ローカルからファイルを送るのが圧倒的に楽になるので設定しておきましょう。
なお、LightsailでUbuntuを選択した場合、ユーザーネームはUbuntuで、パスワードでの認証はできず秘密鍵を使って認証するみたいです。

インスタンスのConnectメニューの、右下のDownload default keyを押すと秘密鍵が保存できるようです。
![chrome_CH2N4yO7jJ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102419/68aa9b3b-35a4-a46e-01e3-f7a453647d34.png)

あとはWinSCPに設定するだけです。
プロトコルはSFTP、ホスト名は固定化したIP、ユーザー名はubuntu、設定を開いてSSHの認証の秘密鍵にダウンロードした鍵を指定・形式の変換を行います。
![WinSCP_wAKKZiTg7f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102419/2296f787-a4b3-568b-19c9-bb946d29047a.png)
![WinSCP_qE0qaH9TEU.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102419/1f978e5b-25c4-d21f-04a7-915d93a5f439.png)
これでファイルをやり取りできるようになりました。

なお、VSCodeで接続すると一瞬で激重になるのでおすすめしません。
拡張機能や一部の設定のせいなのでしょうが、とにかくLightsailの安いプランはスペックが限られているのでシンプルなもので接続したほうが良いようです。
したがって自分は、ファイルを直接送る時はWinSCP経由、GitHub経由でのファイルのやり取りや一般的な編集にはブラウザのSSH経由で接続することにしました。

## パッケージのインストール・更新
Ubuntuのインスタンス作成直後はソフトの更新が適用されていない、venvが入ってないなどの問題が起きます。
いつも通りaptでインストールしましょう。
```bash
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install python3-venv
```

## GitHub経由でBotの中身をアップロード
今回は既にBotのプログラムをGitHubに公開しているので、それをクローンします。
WinSCPなどSFTPで飛ばしてもいいのですが、更新のたびにファイルを選んで送るのは面倒なので……。
```bash
$ git clone https://github.com/<ユーザー名>/<リポジトリ名>.git 
```

## venv環境整備
venvを作成し、`requirements.txt`にまとめたパッケージをインストールします。
```bash
$ cd <リポジトリ名>
$ python3 -m venv venv
$ source ./venv/bin/activate
(venv)$ pip install -r requirements.txt
```

## Bot起動確認
venvに入った状態でBotが正常に動作するか確認しましょう。
なお、環境変数を使用している場合はあらかじめ`export`で適切に設定してください。
```sh
(venv)$ python3 main.py
```
これでDiscordのBotが正しく動作していれば、とりあえずOKです。

## サービスとして登録、自動起動の設定
正直ここが今回初めての学びでした。
今の状態ではSSHを開いてPythonを動かさなければBotが動作しません。
試しにSSHを閉じると、Botは停止してしまいます。

自動起動・常駐させるには、サービスとして登録する必要があるようです。
裏でWebサーバーのApacheが常に動いているアレを自作するわけです。
難しそうに聞こえますが、蓋を開ければあっさりできました。

環境変数を設定している場合、まず設定ファイルを作成しておきましょう。
```bash
$ sudo mkdir /etc/sysconfig
$ sudo nano /etc/sysconfig/<環境変数設定ファイル名> 
```

ファイルの内容は以下の形式で書いていきます。
```
変数1=値1
変数2=値2
```

保存したら、サービスの中身を書きます。サービス名は任意です。
```bash
$ sudo nano /etc/systemd/system/<サービス名>.service
```

中身は次のようにします。
```<サービス名>.service
[Unit]
Description=<説明文>
After=network.target

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
WorkingDirectory=<Botのプログラムのあるディレクトリ>
ExecStart=<Botのプログラムのあるディレクトリ>/venv/bin/python3 <Botのプログラムのあるディレクトリ>/main.py
EnvironmentFile=/etc/sysconfig/<環境変数ファイル名>
```

保存したら次のコマンドで実行しましょう。

```bash
$ sudo systemctl start <サービス名>
```

再度、DiscordのBotが正しく動作しているか確認しましょう！

またよくわかっていませんが、次のコマンドで自動稼働・更新時の自動再起動ができるみたいです。

```bash
$ systemctl enable <サービス名>
$ sudo loginctl enable-linger
```
```bash
$ systemctl daemon-reload
$ systemctl restart <サービス名>
```
https://zenn.dev/sweetsoundstory/books/python-discord-bot/viewer/ubuntu

# 全体の参考記事

https://zenn.dev/sweetsoundstory/books/python-discord-bot/viewer/aws-lightsail

https://zenn.dev/sweetsoundstory/books/python-discord-bot/viewer/ubuntu

https://tech.mamezou00000.com/entry/service-env

https://qiita.com/aKuad/items/c702b508375a5d9c476b