UbuntuでNginxサーバーを立ててBlazorWebアプリを公開する

Blazor WebアプリをUbuntuのNginxサーバーで公開しようと思います。

前提
- Ubuntu 24.04
- Nginx
- Blazor Web Appは用意できてる
- ドメインを取得済み
- SSL/TLS証明書をLet's Encryptで取得

# 1, システムを最新にしておく
```console
$ sudo apt update
$ sudo apt upgrade
```

# 2, [必要ならば] DDNS（独自ドメイン）のIP自動更新機能をインストール
お名前.com限定ですが、固定IPを使えない人のために、IPアドレスが変わるのを定期的にチェックして、自動的に更新してくれるツールがあります。

https://qiita.com/NZTD/items/4ffb6f71fb96ac75a743

インストール時のコマンド`dnf`を`apt`に置き換えてご利用ください。

# 3, Nginxのインストール
```console
$ sudo apt -y install nginx
```

# 4, Nginxの設定
`/etc/nginx/sites-available/default`ファイルを編集します。
```console
$ sudo nano /etc/nginx/sites-available/default
```
`www.example.com`のところは各自のドメイン等を入力してください。
スペース区切りで複数を指定可能です。また、`*.example.com`のような指定方法も可能です。
```diff_conf:default
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

-        root /var/www/html;
+       #root /var/www/html;

        # Add index.php to the list if you are using PHP
-        index index.html index.htm index.nginx-debian.html;
+        #index index.html index.htm index.nginx-debian.html;

-        server_name _;
+        server_name www.example.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
-                try_files $uri $uri/ =404;
+                #try_files $uri $uri/ =404;

+                proxy_pass    http://localhost:5000;
+                proxy_redirect  off;
+                proxy_http_version  1.1;
+                proxy_set_header  Upgrade $http_upgrade;
+                proxy_set_header  Connection keep-alive;
+                proxy_set_header  Host $host;
+                proxy_cache_bypass  $http_upgrade;
+                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
+                proxy_set_header  X-Forwarded-Proto $scheme;
        }

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}
```

# 5, .NET8 のSDKをインストール
### Microsoftのリポジトリ設定ファイルをインストール
```console
$ wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
$ rm packages-microsoft-prod.deb
```
### パッケージのダウンロードにhttpsを使えるように
```console
$ sudo apt update && sudo apt install -y apt-transport-https
``` 
### .Net8.0 SDKのインストール
ランタイムでも良さそうな気がするのに、ランタイム入れてもうまくいきませんでした。
ランタイム版のバージョンがSDK版と違っているのに原因があるかもしれませんが、細かいことを調査するのは別の機会にし、今回はSDKをインストールします。
```console
$ sudo apt update && sudo apt-get install -y dotnet-sdk-8.0
```

# 6, SSL/TLS証明書を自動化
Let's Encrypt に証明書を発行してもらいます。
### 既存のCertbotがあればアンインストールしておく
トラブル防止です。
```console
$ sudo apt remove certbot
```

### Certbotインストール
```console
$ sudo snap install --classic certbot
```
### Certbotコマンドパスのへのリンクを作成
```console
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
```
### Nginxに証明書をインストール
`www.example.com`は各自のドメイン等に変更してください。
```console
$ sudo certbot --nginx -d www.example.com
```
メールアドレスを聞かれます。入力してください。
```conf
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): 
```
利用規約等読むように言われます。**Y**で。
```conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: 
```
Certbotを開発している非営利団体であるElectronic Frontier Foundationとメールアドレスを共有してもよろしいですか？ **N**でも良いです。
```conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: 
```

### Nginxの再起動
無事にインストールが終わったらNginxを再起動します。
```console
$ sudo systemctl restart nginx
```
### 証明書更新サービスを作成
```console
$ sudo nano /etc/systemd/system/certbot.service
```
以下の内容を貼り付けてください。
```conf:certbot.service
[Unit]
Description=certbotでSSL/TLS証明書を更新

[Service]
Type=oneshot
User=root
ExecStart=certbot renew --pre-hook "service httpd stop" --post-hook "service httpd start"

[Install]
WantedBy=multi-user.target
```
### 更新サービスの定期実行ファイルを作成
```console
$ sudo nano /etc/systemd/system/certbot.timer
```
以下の内容を貼り付けてください。
```conf:certbot.timer
[Unit]
Description=certbotを定期実行します

[Timer]
OnCalendar=*-1,3,5,7,9,11-1 1:00:00
Persistent=true

[Install]
WantedBy=timers.target
```
これはcertbot.serviceを毎年1,3,5,7,9,11月の1日 AM1時に実行するという内容です。
Let's Encrypt の証明書は有効期限が3か月であるため、2か月毎に更新すれば安心というわけです。

### 定期実行ファイルの有効化
```console
$ sudo systemctl enable certbot.timer
$ sudo systemctl start certbot.timer
```

# 7, BlazorWebアプリのデプロイ
今回は`/var`ディレクトリの直下に配置用のディレクトリを作成します。
`wwwexample`は各自のプロジェクト名などにしてもらったら良いと思います。
ディレクトリを作ったら、公開用のファイルをそこにコピーしてください。
### 配置先のディレクトリを準備する
```console
$ sudo mkdir /var/wwwexample
```
:::note
### [必要なら] ディレクトリの所有権とアクセス許可を設定
サーバーをリモート先に設置する時など、`RLogin`や`Tera Term`などのソフトを使ってSFTPでファイルを配置するのが楽です。しかし、`/ver`ディレクトリはユーザーに書き込み等の権限が与えられていないために、ソフトからファイルを配置できないことがあります。その為、配置先のディレクトリに対しユーザーにも権限を持たせてソフトを使った配置が可能なようにします。
##### 配置先ディレクトリとそのコンテンツのファイル所有権とグループ所有権を設定します。
`ユーザー名`にはUbuntuへログインしているユーザー名を入れてください。
`ユーザーグループ`にも同じユーザー名を入れてください。
```console
$ sudo chown -R ユーザー名:ユーザーグループ /var/wwwexample
```
##### グループに対し配置先とサブディレクトリへのディレクトリ許可を変更します。
```console
$ sudo chmod 2775 /var/wwwexample && find /var/wwwexample -type d -exec sudo chmod 2775 {} \;
```
##### グループに対し配置先とサブディレクトリへのファイル許可を再帰的に変更します。
```console
$ find /var/wwwexample -type f -exec sudo chmod 0664 {} \;
```
:::
### 配置したBlazorWebアプリをサービス化します。
systemctlコマンドから起動や再起動、停止などが行えるようにします。
`/lib/systemd/system`フォルダにserviceファイルを新規作成します。
```console
$ sudo nano /lib/systemd/system/wwwexample.service
```
以下の内容を貼り付けます。`wwwexample`がたくさんあるので、全て書き換えましょう。
```conf:wwwexample.service
[Unit]
Description=wwwexampleを実行します。

[Service]
WorkingDirectory=/var/wwwexample
ExecStart=/usr/bin/dotnet /var/wwwexample/wwwexample.dll
Restart=always

# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=wwwexample
#User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target
```
### サービスを有効化します。
```console
$ sudo systemctl enable wwwexample
```
### サービスを起動します。
```console
$ sudo systemctl start wwwexample
```
### サービスの起動を確認します。
```console
$ sudo systemctl status wwwexample
```

<br>

以上で、公開完了しているはずです。
ブラウザで`http://www.example.com`を開いてみてください。