ℹ️ GCE を使わずにサーバレスでもっと簡単に作る方法 も紹介しています。
manji602さんが Google Cloud Platform(GCP) 無料枠を使っておもしろそうなことをやっていたので私も何か作ってみようと思い、夫婦円満を願って家族のLINEグループに妻の好きな猫をLINE Botで導入することにしました。
私はGoogleクラウドはGAEが出た頃に少し触ったくらいで、当初は確かJavaとPythonしか使えず「AWSの方が自由度があって良いな」と思っていたのですが、今回初めてGCPを触ってみると、インターフェースがシンプルでわかりやすく使いやすいと感じました。
そこで、Googleクラウド初心者の私がGCP無料枠の範囲でLINE Botを動かすまでの要点をまとめておこうと思います。
下図は今回作ったシステムの構成です。
GCP
GCPの設定についてはGCPで無料枠のサーバを立るときに、初見でハマりそうなところがわかりやすく説明してくれています。
今回はSinatraを使うためRubyをインストールしました。おおまかには次のような手順です。
DNS設定
所有しているドメインから固定したGCEのIPアドレスが引けるように設定します。
GCPのDNSサービス (CLOUD DNS) を使うと、無料クレジットはあるものの本来有料であることと、AWS Route53で所有ドメインを管理していることがあり、今回はRoute53でAレコードを設定しました。
SSL証明書取得
Let's Encryptで証明書を発行します(無料)。
証明書の有効期間は90日と短めですが、証明書はCertbotと呼ばれるクライアントを使って簡単に取得・更新することができます。
さらにDebianだとCertbotインストール時に証明書更新のCRONジョブを自動で追加してくれるので便利です。
ただし、証明書の更新コマンド certbot renew
を実行すると、いくつかのディレクトリでパーミッションエラーになってしまったので、事前にパーミッションを付与して実行できることを確認しておくと良いでしょう。
私はこのあたりでハマりました。。
Nginx設定
NginxにSSL証明書を設定します。 セキュリティのためにNginxでSSLの評価をA+にする手順を参考に、SSLv3の無効化など対応しておくと良いでしょう。
下記は今回の設定例です。Unicornを使うためupstreamディレクティブでソケットファイルを指定しています。
/etc/nginx/conf.d/ssl.conf
upstream linebot { server unix:/tmp/linebot.sock; } server { listen 443; server_name example.com; ssl on; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers ECDHE+RSAGCM:ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:!aNULL!eNull:!EXPORT:!DES:!3DES:!MD5:!DSS; location / { root /usr/share/nginx/html; index index.html index.htm; } location /linebot/ { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://linebot; proxy_redirect http:// https://; } }
Unicorn & Sinatra
【Ruby】Sinatraで、速攻でWebサイトを公開するための環境構築にわかりやすくまとめられていますので、特に詰まる箇所はないと思います。
LINE Messaging APIの使い方はLINE Bot SDKに言語ごとにまとめられています。そのままで動くようになっているので、ここも詰まる箇所はないと思います。
参考までに、今回作ったLINE Botのコードの抜粋を掲載しておきます。
config.ru
require './app.rb' run Linebot
app.rb
class Linebot < Sinatra::Base def client @client ||= Line::Bot::Client.new do |config| config.channel_secret = ENV["LINE_CHANNEL_SECRET"] config.channel_token = ENV["LINE_CHANNEL_TOKEN"] end end post '/linebot/callback' do body = request.body.read signature = request.env['HTTP_X_LINE_SIGNATURE'] unless client.validate_signature(body, signature) error 400 do 'Bad Request' end end events = client.parse_events_from(body) events.each do |event| case event when Line::Bot::Event::Message case event.type when Line::Bot::Event::MessageType::Text reply_text = build_reply_text event.message['text'] if !reply_text.nil? && reply_text != "" client.reply_message(event['replyToken'], type: 'text', text: reply_text) end when Line::Bot::Event::MessageType::Image, Line::Bot::Event::MessageType::Video response = client.get_message_content(event.message['id']) tf = Tempfile.open("content") tf.write(response.body) end end end "OK" end end
猫ちゃん(LINE Bot)導入後の様子
実際にはTodoistというタスク管理アプリとも連携して、「ホイちゃん 今日の晩ごはん」みたいに話しかけるとTodoist REST APIから今日の晩ごはんを取ってきて教えてくれるといった機能も載せています。
そのためリポジトリを公開できないことについては悪しからずご了承ください🙏🙏
おわりに
今回LINE Botを作ってみて、将来的にはLINEを通じて自宅のエアコンや照明を操作できるようにしてみたくなりました。
ドメインの費用以外は無料でLINE Botが運用できるので、皆さんもぜひアイデアを膨らませて作ってみてくださいね。
宣伝
普段の業務ではCRE (Customer Reliability Engineering)という役割のエンジニアとして働いています。CREチームを設立しました!も良ければご覧ください😄