laravel + nginx でLet's encryptのSSL運用

# 前提
ドメインとDNSが正しく逆引きできていること。
設定は各々のドメイン管理のサイトなどで行う。
設定が適用されているかはdigコマンドで確認。
```
$ dig black.jp
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;black.jp.                IN      A

;; ANSWER SECTION:
black.jp. 3600    IN      A       x.x.x.x
```

# laravelのinstall
パスはどこでもいいが、nginxと管理ユーザー(仮にkanriuserとする)の両方で
読み書き可能な権限にする。

```
$ usermod -G nginx kanriuser
※複数に属する場合カンマ指定
$ usermod -G nginx,apache kanriuser
```
/var/www/htmlの配下にドメイン名のフォルダでinstallする。
```
$ cd /var/www/html
$ chown root:nginx .
$ chmod g+rw .

$ composer create-project laravel/laravel black.jp
```
ドキュメントルートの配下のgroupはnginxに変える。
```
$ cd black.jp
$ chown -R kanriuser:nginx .
```
# nginxの設定
初回は80ポートで確認。
後述のlet's encryptの更新用のrootを作成しておく
```
$ mkdir /var/www/html/letsencrypt
$ chown kanriuser:nginx /var/www/html/letsencrypt
$ chmod 775 /var/www/html/letsencrypt
```
nginx.confの設定は[こちら](https://readouble.com/laravel/11.x/ja/deployment.html)を参考にする。
let's EncryptのSSL化のために以下の個所を書き換える。
```conf:nginx.conf
server {
(略)
    location ^~ /.well-known/acme-challenge/ {
        root /var/www/html/letsencrypt;
    }

    location = /.well-known/acme-challenge/ {
        return 404;
    }
}
```
nginxを再起動してブラウザ等で[http://black.jp/]にアクセスしてlaravelの初期画面が表示されること。
```
$ vi /etc/nginx/conf.d/black.jp.conf
$ systemctl reload nginx
```

# let's Encryptの設定
## 初回のみ
### snapd版のcertbotの導入
詳しくは[こちら](https://certbot.eff.org/lets-encrypt)から
対象のプラットフォームとSoftwareを選んで手順を表示する。
大まかな流れは
1.snapdのインストール
2.snapdからcertbotインストール
3.シンボリックリンクを作成

※certbotコマンドは制限があり、週当たり実行回数に制限があり
失敗した回数を含めて何回以上か実行するとその週は更新できなくなります。
確実に成功するまでは--dry-runオプションをつけて実行すること。

```
$ certbot certonly --dry-run --webroot -w /var/www/html/letsencrypt -d black.jp
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Simulating a certificate request for black.jp
The dry run was successful.
```
successfulがでたら--dry-runを削って本番実行する。
成功すると以下のフォルダに証明書が生成されるのでnginxで指定する。
```
/etc/letsencrypt/live/black.jp/fullchain.pem;
/etc/letsencrypt/live/black.jp/privkey.pem;
```
```conf:nginx.conf
server {
    listen 80;
    listen [::]:80;
    server_name black.jp;
    root /var/www/html/black.jp/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_index index.php;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/html/letsencrypt;
    }

    location = /.well-known/acme-challenge/ {
        return 404;
    }
}

server {
    listen 443 ssl;
    server_name black.jp;
    root /var/www/html/black.jp/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers          'ECDH !aNULL !eNULL !SSLv2 !SSLv3';
    add_header           Strict-Transport-Security "max-age=31536000; includeSubdomains";
    ssl_session_cache    shared:SSL:10m;
    ssl_session_timeout  10m;
    ssl_certificate /etc/letsencrypt/live/black.jp/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/black.jp/privkey.pem;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_index index.php;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/html/letsencrypt;
    }

    location = /.well-known/acme-challenge/ {
        return 404;
    }
}
```
```
$ systemctl reload nginx
$ systemctl status nginx
```
### (補足)httpからのアクセスをhttpsにredirectする
nginx.confで80のセクションの最後で301でリダイレクトする。
```conf:nginx.conf

server {
    listen      80:
    listen      [::]:80;
    server_name black.jp;

    (略)
    return 301 https://$host$request_uri;
}

```
## Let’s Encryptの初回以降の更新処理
systemctlのtimerでcertbotの更新が行われる。
以下を参考。

https://qiita.com/woonotch/items/b1208dd792be00e6c447