経緯
何か業務で使う技術や新しい技術を試したいときにAWS上にWebサーバーを立ててAPIとかテストページとか用意して、ローカルのChromeやAndroid端末からhttpで繋いでごにょごにょやるってのを結構やる。
RestAPIの疎通確認ぐらいならそれでいいんだけど、WebRTCやWebSocketの検証で使いたい場合、SSL化されたサイトでないとエラーになって接続できないため動作確認が出来ない問題があった。
どうにかこうにか安価でオレオレ証明書じゃないWebサーバーを立てられないかなーと調べたところ、FreenomとLet's Encryptを使えばほぼ無料で独自ドメインのhttpsサーバーを立てられそうだと判明。
Freenomでのドメイン取得方法やLet's EncryptでのSSL証明書取得方法、それらをAWSで設定するやり方等は探せば断片的にはあるけど、全部まとまった記事は無かったので、備忘録もかねてここに残しておく。
やること
- 【無料】Freenomで無料ドメインを取得する
- 【条件付無料】AWS EC2インスタンスを作成してdockerをインストールする
- 【条件付無料】AWS Elastic IPで静的IPアドレスを発行してEC2インスタンスに関連付ける
- 【ほぼ無料】AWS Route53でDNS設定を行いドメイン名でEC2インスタンスに繋がるようにする
- 【無料】dockerでEC2インスタンスにnginxコンテナを立ち上げる
- 【無料】Let's Encryptで無料SSL証明書を取得してhttpsで繋がるようにする
無料の条件とほぼ無料の詳細
- AWS EC2インスタンスは無料利用枠を使用する
- 無料利用枠と記載のあるAmazonマシンイメージ(AMI)は月に750時間無料で使える。今回はそれを使うことで無料とする
- ElasticIPで割り当てたEC2インスタンスは起動したままにしておく
- ElasticIPで発行したIPアドレスがEC2インスタンスに関連付けされていない場合は課金が発生する。いくら課金されるかは調べていないがわずかであるらしい。こういう仕組みになっているのは無駄にIPアドレスを確保されるのを防ぐためだろう。
- AWS Route53では月に0.5$課金される
1. 【無料】Freenomで無料ドメインを取得する
早速やっていきます。ドメインはFreenomというサービスを使って取得します。Freenomとは、ドメインを無料で取得出来る海外のサービスです。ドメイン名は、XXXX.tkやXXXX.ml、XXXX.ga等が無料で取得できます。
https://www.freenom.com/ja/index.html
ドメインが使えることを確認し、チェックアウトする
好きなドメインを取得することが出来ますので、取得したいドメインを入力しましょう。利用可能か調べてくれて利用可能であれば以下のような画面になりますので「今すぐ入手!」を押下した後、「チェックアウト」を押下します。
使用期間を選択する
12ヵ月まで無料で使えるようですので、最大限使用させていただきましょう。Periodで「12 Months @ FREE」を選択して「Continue」を押下します。
ユーザー登録 or ログイン
金額が$0.00USD(無料)なのを確認します。問題なければ購入のためログインします。
私の場合は既に登録済みなので、普通にGoogleでログインします。
初回登録してないと、いろいろ登録しないといけないかもしれません。
規約に同意して購入
再度、金額が$0.00USD(無料)なのを確認してから、規約に同意のチェックを入れ、「Complete Order」を押下します。
これにてドメインの取得は完了しました。
2. 【条件付無料】AWS EC2インスタンスを作成してdockerをインストールする
こちらは私が書いた別の記事がそのまま使用できますので、こちら↓を参照ください。
AWS EC2インスタンスにdockerとdocker-composeをインストールして簡単なWEBサービスを立ち上げる方法
3. AWS Elastic IPで静的IPアドレスを発行してEC2インスタンスに関連付ける
静的IPアドレス(固定IPアドレス)を取得し、上記で起動したEC2インスタンスにそのIPアドレスを割り当てます。こうすることで、EC2を再起動したりしてもIPアドレスが変わることは無くなります。
静的IPアドレスを取得する
まずは画面操作して静的IPアドレスを取得します。
「Elastic IP」を押下し、
次の画面で「Elastic IP アドレスの割り当て」を押下します。
次の画面で「割り当て」を押下します。
静的IPアドレスが取得できました。
EC2インスタンスに静的IPアドレスを関連付ける
割り当てられたIPアドレスを選択状態にして「アクション」内の「Elastic IPアドレスの関連付け」を押下します。
インスタンスには、先ほど作成したEC2のインスタンスIDを入力します。
入力したら「関連付ける」を押下します。
EC2インスタンスと静的IPアドレスの関連付けが完了しました。
4. 【ほぼ無料】AWS Route53でDNS設定を行いドメイン名でEC2インスタンスに繋がるようにする
ドメイン名で繋がるようにDNS設定を行います。
ホストゾーン作成→Aレコード登録→FreenomでNameserver設定という手順になります。
ホストゾーンの作成
Route53の画面に行き、
「ホストゾーン」を押下します。
「ホストゾーンの作成」を押下します。
Freenomで取得したドメインを入力して「ホストゾーンの作成」を押下します。
ホストゾーンの作成が完了しました。
Aレコードの作成
「レコードの作成」を押下します。
シンプルルーティングがデフォルト選択されているのを確認して「次へ」を押下します。
「シンプルなレコードを定義」を押下します。
値/トラフィックのルーティング先で「レコードタイプに応じたIPアドレスまたは別の値」を選択した後、先ほど取得した静的IPアドレスを入力して、「シンプルなレコードを定義」を押下します。
レコードの作成を押下します。
レコードの作成が完了しました。
Nameserverの設定
今度はFreenomでNameserverの設定を行います。
「My Domains」を押下し、次の画面で「Manage Domain」を押下します。
「Management Tools」の「Nameservers」を押下します。
「Use custom nameservers(enter below)」を選択、Nameserver欄にはRoute53 ホストゾーンのNSレコードの値をコピペします。
入力したら「Change Nameservers」を押下します。
この時点で数分経過すると、DNSが浸透して行って「http://ドメイン名」でサイトが表示されるようになっているかと思います。
5. 【無料】dockerでEC2インスタンスにnginxコンテナを立ち上げる
6. 【無料】Let's Encryptで無料SSL証明書を取得してhttpsで繋がるようにする
5と6は一気にやっちゃいます。
いろいろやり方はあるかと思いますが、以下構成でdockerを使用してやってみます。
- reverse-proxyコンテナをインターネットに公開し、https通信を受け付けます。
- reverse-proxyコンテナからwebコンテナへ通信を転送、webコンテナではreverse-proxyからhttp通信を受け付けます。
全てのdockerを停止しておく
誤動作防止のため、作業前に一度全てのdockerコンテナを止めて、dockerオブジェクトも全部削除しておくといいでしょう。
docker stop $(docker ps -q)
docker system prune -a
webコンテナの作成と起動
homeディレクトリ配下にwebディレクトリを作成し、必要な構成ファイルを作成します。
cd
mkdir web
ディレクトリ配下とファイルの内容は以下のような構成にしました。
web
- html
- index.html # hogeとでも書いておく
- docker-compose.yml
version: '3'
services:
web:
image: nginx:latest
container_name: web
volumes:
- ./html:/usr/share/nginx/html
作成が終わったらdockerコンテナを起動します。
docker-compose up -d --build
起動したことを確認します。
docker-compose ps
Name Command State Ports
------------------------------------------------------
web /docker-entrypoint.sh ngin ... Up 80/tcp
reverse-proxyコンテナの作成と起動
homeディレクトリ配下にreverse-proxyディレクトリを作成し、必要な構成ファイルを作成します。
cd
mkdir reverse-proxy
ディレクトリ配下とファイルの内容は、悪戦苦闘の結果、以下のような構成にしました。
reverse-proxy
- reverse-proxy
- default.conf
- Dockerfile
- entrypoint.sh
- docker-compose.yml
server{
server_name y-do.tk;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://web/;
}
}
FROM nginx
COPY default.conf /etc/nginx/conf.d/default.conf
RUN cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
RUN apt-get update && apt-get install -y \
wget cron && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ADD https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh /usr/local/bin/wait-for-it.sh
RUN chmod +x /usr/local/bin/wait-for-it.sh
ADD https://dl.eff.org/certbot-auto /usr/local/bin/certbot-auto
RUN chmod a+x /usr/local/bin/certbot-auto
RUN certbot-auto --os-packages-only -n
COPY ./entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
#!/bin/bash
# hogehoge@example.comはメールアドレス
certbot-auto --nginx -d y-do.tk -m hogehoge@example.com --agree-tos -n
certbot-auto renew
# cron job settings
# Let's Encrypt automatic Renew
echo '0 8 * * * certbot-auto renew --post-hook "nginx -s reload"' >> /cron-tmpfile
crontab /cron-tmpfile
rm /cron-tmpfile
# cron start
/etc/init.d/cron start
/bin/bash
version: '3'
services:
reverse-proxy:
build: ./reverse-proxy
tty: true
container_name: reverse-proxy
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
ports:
- "80:80"
- "443:443"
volumes:
- '/srv/letsencrypt:/etc/letsencrypt'
command: ["wait-for-it.sh", "web:80"]
networks:
- default
- web_default
networks:
web_default:
external: true
作成が終わったらdockerコンテナを起動します。
docker-compose up -d --build
起動したことを確認します。
docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------------------------------
reverse-proxy entrypoint.sh wait-for-it. ... Up 0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp
インターネットからhttpsで繋がるようにAWSでセキュリティグループを更新する
FWで弾かれているため、まだインターネットからhttps通信を受け付けることが出来ません。
AWSのセキュリティグループのインバウンドルールを修正します。
ルールを追加して、タイプ「HTTPS」、ソースは「0.0.0.0/0」を入力します。
入力したら「ルールを保存」を押下します。
動作確認
ここまでやってやっとhttpsで通信が出来るようになっているはずです。アクセスしてみます。
アクセス出来た!!!
結果
月額0.5USDで独自ドメインのSSLサイトが運用できる。
ただし、ドメインは12ヵ月、SSL証明書は3か月で有効期限が切れる(無料だから文句は言えない)ので、今後は自動更新の仕組みを導入したい