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?

GoogleCloudのVMで立てたdockerのサーバー(Nginx)に最小コストでSSL/TLS証明書を適用する

Posted at

やろうとしたこと

GoogleCloudのVMにdockerでWebサーバーを立てて、HTTPSでアクセスできるようにしたかった。
HTTPS通信にするためにはロードバランサを使用しSSL/TLS証明書(以下、証明書と呼ぶ)を適用する必要がある。ロードバランサはどう頑張ってもコストがかかるので、できれば使わずに無料でHTTPS化したい。無料でHTTPSを使う、ここ大事!

前提

  • 使用するdocker関連ファイルはCTFdを流用
  • 使用するドメイン名は取得済み
  • HTTPを使ったWebサーバーからのレスポンスは正常なことを確認済み

手順

  1. Nginxの設定ファイルを修正する

    CTFdだと~/conf/nginx/http.confを修正することになる

    worker_processes 4;
    
    events {
    
      worker_connections 1024;
    }
    
    http {
    
      # Configuration containing list of application servers
      upstream app_servers {
    
        server ctfd:8000;
      }
    
        server {
            # HTTPからHTTPSへのリダイレクト
            listen 80;
            server_name <取得しているドメイン名>;  # ドメイン名を指定
    
            # リダイレクト設定
            return 301 https://$host$request_uri;
        }
    
        server {
            listen 443 ssl;  # SSLを有効にする
            server_name <取得しているドメイン名>;  # ドメイン名を指定
    
            # SSL証明書のパスを指定
            ssl_certificate /etc/letsencrypt/live/cyber-ctf.xyz/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/cyber-ctf.xyz/privkey.pem;
    
        gzip on;
    
        client_max_body_size 4G;
    
        # Handle Server Sent Events for Notifications
        location /events {
    
          proxy_pass http://app_servers;
          proxy_set_header Connection '';
          proxy_http_version 1.1;
          chunked_transfer_encoding off;
          proxy_buffering off;
          proxy_cache off;
          proxy_redirect off;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Host $server_name;
        }
    
        # Proxy connections to the application servers
        location / {
    
          proxy_pass http://app_servers;
          proxy_redirect off;
          proxy_set_header Host $host;
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Host $server_name;
        }
      }
    }
    
  2. docker-compose.yamlを修正する

    services:
      ctfd:
        build: .
        user: root
        restart: always
        ports:
          - "8000:8000"
        environment:
          - UPLOAD_FOLDER=/var/uploads
          - DATABASE_URL=mysql+pymysql://ctfd:ctfd@db/ctfd
          - REDIS_URL=redis://cache:6379
          - WORKERS=1
          - LOG_FOLDER=/var/log/CTFd
          - ACCESS_LOG=-
          - ERROR_LOG=-
          - REVERSE_PROXY=true
        volumes:
          - .data/CTFd/logs:/var/log/CTFd
          - .data/CTFd/uploads:/var/uploads
          - .:/opt/CTFd:ro
        depends_on:
          - db
        networks:
            default:
            internal:
    
      nginx:
        image: nginx:stable
        restart: always
        volumes:
          - ./conf/nginx/http.conf:/etc/nginx/nginx.conf
          - /etc/letsencrypt:/etc/letsencrypt # 証明書をマウントさせるため追記
        ports:
          - 443:443  # HTTPS接続させるため変更
    
    	# 証明書を使うためcertbotの記述を追加
      certbot:
        image: certbot/certbot
        volumes:
          - ./certs:/etc/letsencrypt
        entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
        depends_on:
          - ctfd
    
      db:
        image: mariadb:10.11
        restart: always
        environment:
          - MARIADB_ROOT_PASSWORD=ctfd
          - MARIADB_USER=ctfd
          - MARIADB_PASSWORD=ctfd
          - MARIADB_DATABASE=ctfd
          - MARIADB_AUTO_UPGRADE=1
        volumes:
          - .data/mysql:/var/lib/mysql
        networks:
            internal:
        # This command is required to set important mariadb defaults
        command: [mysqld, --character-set-server=utf8mb4, --collation-server=utf8mb4_unicode_ci, --wait_timeout=28800, --log-warnings=0]
    
      cache:
        image: redis:4
        restart: always
        volumes:
        - .data/redis:/data
        networks:
            internal:
    
    networks:
        default:
        internal:
            internal: true
    
  3. Certbotを使用して証明書を取得する

    sudo docker-compose run --rm certbot certonly --nginx -d <ドメイン名>
    又は
    sudo docker-compose run --rm certbot certonly --standalone -d <ドメイン名>
    
  4. dockerを起動する

    sudo docker compose up
    

これでdocker上のNginxとHTTPS通信が可能になる上、HTTP通信を試みるとHTTPSにリダイレクトされる!

補足(上手くいかない時)

自分の場合は手順3を実施した時に、証明書が何も取得できなかった。これはdockerに適用する前にVMでテストするため以下のコマンドで証明書を既に入手していたから。

sudo apt install python3-certbot-nginx
sudo certbot --nginx

証明書を既に持っているにも関わらずdocker compose upをすると証明書のエラーが出て起動できない状態が続いた。
この場合の原因はdocker-compose.yamlファイルにあった。当初はファイルの記述内容を下記のようにしていた

nginx:
    image: nginx:stable
    restart: always
    volumes:
      - ./conf/nginx/http.conf:/etc/nginx/nginx.conf
      - ./:/etc/letsencrypt # ここの記述がエラーの原因だった
    ports:
      - 443:443 

証明書が格納されているファイルを調べると/etc/letsencrypt/だった。
つまり、上記のコードだと、証明書がdocker上の/etc/letsencryptにマウントされず証明書エラーが出てしまう。
事前にVM上で証明書を取ったためにエラーが出てしまい時間を溶かしてしまった。

さいごに

思い返せばdockerで出るエラーはほとんどvolumesに関連してる。
他の人はどうなんだろう?
自分は今度からエラーが出たら真っ先にvolumesが正しいか確認することから始めようかな。

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?