0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Webアプリを作って自宅のサーバーでインターネットに公開してみた(インターネット公開編)

Last updated at Posted at 2024-10-19

はじめに

普段は主にクラウドサービスを使っているのですが、「ローカル環境のマシンをインターネットに公開する場合どうするんだろう」と思ったので勉強を兼ねてやってみました。

長くなったので

  • インターネット公開編
  • アプリ編

の2つに分けて書きました。これはインターネット公開編です。
アプリ編はこちらです。

アプリ紹介

ボタンを押すと曲(のキック)がランダムに1秒流れるアプリです。

全体構成

system_architecture_1.png

全体の構成は上記のような形です。
今記事では主に黄色枠部分について記載します。

環境

  • サーバー : Raspberry Pi 5 8GB
    • OS : Debian 12
  • ルーター : TP-Link Archer AX55
  • フロント&バックエンドライブラリ : Reflex
  • DB : MariaDB
  • CRUD API : Flask
  • Webサーバーアプリ : Apache2
  • クラウドストレージ : Amazon S3
  • SSL証明書 : Let's Encrypt
  • DNS : Lightsail DNS

設定

ルーター設定

TP-Linkルーターの管理画面から設定を行います。

アドレス予約

DHCPサーバーが有効になっており、サーバーが再起動するとローカルIPアドレスが変更される可能性があるので、MACアドレスを指定しローカルIPアドレスの予約設定をします。

20241019.png

ポートフォワーディング設定

3つのポートを使用したいので、以下のように設定しました。

image.png

これにより、グローバルIPの特定ポートにアクセスが来た時、先ほど設定したローカルIPアドレスの特定ポートに転送されます。

DNS設定

私は数年前からドメインをお名前.comで購入し所有しています。
それをLightsail DNSに登録して管理しています。

グローバルIPを以下コマンドで確認し、

$ curl -4 ifconfig.co
xxx.xxx.xxx.xxx

AレコードにドメインとグローバルIPを記載して登録します。

image.png

動的グローバルIPアドレスへの対処

グローバルIPアドレスですが、個人契約の場合基本的には動的になっており、ある程度期間が立つと変わるようです。

Lightsail DNSにはcliが提供されているので、cronでグローバルIPアドレスをフェッチし、DNSをUpdateするスクリプトを作成・実行します。

update_grobal_ip.sh
#!/bin/bash

dns_setting_json=`/usr/local/bin/aws lightsail get-domain --domain-name "${MY_DOMAIN}" --region us-east-1 | /usr/bin/jq '.domain.domainEntries[] | select(.name == "home.'"${MY_DOMAIN}"'" and .type == "A")'`
ip=`/usr/bin/curl -4 -s ifconfig.co`
updated_dns_setting_json=$(echo "$dns_setting_json" | /usr/bin/jq --arg new_ip "$ip" '.target = $new_ip')

/usr/local/bin/aws lightsail update-domain-entry --domain-name "${MY_DOMAIN}" --region us-east-1 --domain-entry "$updated_dns_setting_json"
crontab
*/10 * * * * /home/xxx/update_grobal_ip.sh >> /home/xxx/update_grobal_ip.log 2>&1

数分のダウンタイムはありますが、これでグローバルIPアドレスが変わっても大丈夫です。

これで指定のドメインからアクセスできるようになります。

# 諸々設定済みの為301が返ってきていますが、本来は200が返ってきます。
# 尚、完成してから記事を書いているので、本来はアプリサーバー側ポートもLISTENしていないと通信成功しません。
$ curl -I curl -I  http://home.quark-hardcore.com/kick-preview/
curl: (6) Could not resolve host: curl
HTTP/1.1 301 Moved Permanently
Date: Sat, 19 Oct 2024 06:34:53 GMT
Server: Apache/2.4.62 (Debian)
Location: https://home.quark-hardcore.com/kick-preview/
Content-Type: text/html; charset=iso-8859-1

TP-Link DDNS設定について

TP-LinkにはDDNS機能があります。これを使えば動的なグローバルIPアドレスであっても、TP-Linkが提供するドメインでインターネットから接続できるのですが、ルーターにSSL証明書のインポート機能がなく、httpsの接続は対応していません

httpsでの通信とDDNSは全く違う話ですが、TP-LinkがDDNSで提供する*.tplinkdns.comについては

「ルーターにSSL証明書がインポートできない→TP-LinkからDDNS機能により提供されるドメインではhttps通信ができない」

という認識です。間違っていたら教えていただきたいです。

ということで、TP-LinkのDDNSは使っていないです。

SSL証明書

ルーターの設定により特定のドメインから自宅のサーバーへアクセスさせることが可能になりました。
自宅のサーバーにSSL証明書をインポートし、https通信ができるようにします。

Let's Encrypt証明書を作成

無料でSSL証明書を作成できるLet's Encryptを使います。

手順はこちらが分かりやすいです。

また、事前にnginx or apache2どちらかを先にインストールします。
Lightsailインスタンスに入っているBitnamiで使ったことがあるApache2を選択しました。

Certbotインストール
$ sudo apt update
$ sudo apt install apache2
$ sudo apt install python3 python3-venv libaugeas0
$ sudo python3 -m venv /opt/certbot/
$ sudo /opt/certbot/bin/pip install --upgrade pip
$ sudo /opt/certbot/bin/pip install certbot certbot-apache
$ sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
CertbotでSSL証明書を作成
$ sudo certbot --apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Please enter the domain name(s) you would like on your certificate (comma and/or
space separated) (Enter 'c' to cancel): home.quark-hardcore.com
Requesting a certificate for home.quark-hardcore.com
                                                                                                      Successfully received certificate.
This certificate expires on 2024-12-30.
These files will be updated when the certificate renews.

Deploying certificate
Successfully deployed certificate for home.quark-hardcore.com to 
Congratulations! You have successfully enabled HTTPS on https://home.quark-hardcore.com

NEXT STEPS:
- The certificate will need to be renewed before it expires. Certbot can automatically renew the certificate in the background, but you may need to take steps to enable that functionality. See https://certbot.org/renewal-setup for instructions.
                                                                                                      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Let's Encryptは有効期間が90日と短いので、定期的に更新するようcronで設定しておきます。

0 3 1 * * /usr/bin/certbot renew --quiet

これでhttpsでの通信が可能になりました

image.png

通信成功です!

$ curl -I  https://home.quark-hardcore.com/kick-preview/
HTTP/1.1 200 OK
Date: Sat, 19 Oct 2024 06:35:22 GMT
Server: Apache/2.4.62 (Debian)
Cache-Control: no-store, must-revalidate
X-Powered-By: Next.js
ETag: "14m1wwi91dj5y7"
Content-Type: text/html; charset=utf-8
Content-Length: 7745
Vary: Accept-Encoding
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?