さくらの VPS の Ubuntu 24.04 + nginx で HTTPS ファイル転送システムを作ってみた
前書き
この投稿では、さくらの VPS にある Ubuntu サーバー上に nginx をセットアップして、HTTPS ファイル転送システムを構築する手順を説明します。
このシステムでは、ファイル転送を実行するクライアントは Base64 でエンコードされたユーザー ID とパスワードを使用した認証 (ベーシック認証) を使って、インターネットを介してファイルを転送することができます。
このシステムは、僕が個人的に進めている Spresense でトレイルカメラを作るプロジェクトと関連していて、ゆくゆくは Spresense が撮った写真を送信する先のサーバーとして利用することを意図しています。
前提条件
以下に前提条件と、参考にしていただける記事を記します。
- Ubuntu サーバー (僕が使うのは 24.04) がセットアップされていること
- Ubuntu サーバーがインターネット側からドメイン名 (FQDN) でアクセス可能となっていること
- Ubuntu サーバーにサーバー証明書 (TLS 証明書) が作成済みであること
さくらの VPS の Ubuntu 24.04 に Certbot (Let’s Encrypt) で証明書を発行してみた
セットアップする流れ
- Ubuntu サーバーにファイル転送用の新しいユーザーを作成
- nginx のインストールと設定
- nginx の設定ファイルの作成と有効化
- ファイルアップロード用ディレクトリの作成
- Basic 認証用のユーザーとパスワードの設定
セットアップ手順
1. ファイル転送用ユーザーの作成
クライアントがインターネット側から Ubuntu サーバーにアクセスしてログインするときのユーザー ID (アカウント) を作成します。
spresense-iot-test というユーザーを作ることにしました。
$ sudo adduser spresense-iot-test [sudo] hoge のパスワード: info: ユーザ `spresense-iot-test' を追加しています... info: Selecting UID/GID from range 1000 to 59999 ... info: 新しいグループ `spresense-iot-test' (1002) を追加しています... info: Adding new user `spresense-iot-test' (1002) with group `spresense-iot-test (1002)' ... info: ホームディレクトリ `/home/spresense-iot-test' を作成しています... info: `/etc/skel' からファイルをコピーしています... 新しいパスワード: 新しいパスワードを再入力してください: passwd: パスワードは正しく更新されました spresense-iot-test のユーザ情報を変更中 新しい値を入力してください。標準設定値を使うならリターンを押してください フルネーム []: 部屋番号 []: 職場電話番号 []: 自宅電話番号 []: その他 []: 以上で正しいですか? [Y/n] y info: Adding new user `spresense-iot-test' to supplemental / extra groups `users' ... info: ユーザ `spresense-iot-test' をグループ `users' に追加しています... $
対話的にパスワードも聞いてくるので adduser コマンド 1 つでアカウントが作成できました。
次に作ったアカウントを www-data グループに追加します。
$ sudo usermod -aG www-data spresense-iot-test $ getent group www-data www-data:x:33:spresense-iot-test $
www-data グループは、ウェブサーバー (通常は Apache や Nginx など) が動作している環境で使用する専用のグループです。、ウェブサーバーによって提供されるファイルやリソースに対してアクセスできるようになります。
2. nginx のインストールと設定
次に Ubuntu に nginx をインストールします。
$ sudo apt update ヒット:1 http://security.ubuntu.com/ubuntu noble-security InRelease ヒット:2 http://archive.ubuntu.com/ubuntu noble InRelease 取得:3 http://archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB] ヒット:4 http://archive.ubuntu.com/ubuntu noble-backports InRelease 取得:5 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages [475 kB] 取得:6 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages [351 kB] 953 kB を 3秒 で取得しました (317 kB/s) パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています... 完了 状態情報を読み取っています... 完了 アップグレードできるパッケージが 124 個あります。表示するには 'apt list --upgradable' を実行してください。 $ sudo apt install nginx パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています... 完了 状態情報を読み取っています... 完了 以下の追加パッケージがインストールされます: nginx-common 提案パッケージ: fcgiwrap nginx-doc ssl-cert 以下のパッケージが新たにインストールされます: nginx nginx-common アップグレード: 0 個、新規インストール: 2 個、削除: 0 個、保留: 124 個。 552 kB のアーカイブを取得する必要があります。 この操作後に追加で 1,596 kB のディスク容量が消費されます。 続行しますか? [Y/n] y 取得:1 http://archive.ubuntu.com/ubuntu noble/main amd64 nginx-common all 1.24.0-2ubuntu7 [31.2 kB] 取得:2 http://archive.ubuntu.com/ubuntu noble/main amd64 nginx amd64 1.24.0-2ubuntu7 [521 kB] 552 kB を 2秒 で取得しました (259 kB/s) パッケージを事前設定しています ... 以前に未選択のパッケージ nginx-common を選択しています。 (データベースを読み込んでいます ... 現在 125302 個のファイルとディレクトリがインストールされています。) .../nginx-common_1.24.0-2ubuntu7_all.deb を展開する準備をしています ... nginx-common (1.24.0-2ubuntu7) を展開しています... 以前に未選択のパッケージ nginx を選択しています。 .../nginx_1.24.0-2ubuntu7_amd64.deb を展開する準備をしています ... nginx (1.24.0-2ubuntu7) を展開しています... nginx (1.24.0-2ubuntu7) を設定しています ... nginx-common (1.24.0-2ubuntu7) を設定しています ... Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service. ufw (0.36.2-6) のトリガを処理しています ... man-db (2.12.0-4build2) のトリガを処理しています ... Scanning processes... Scanning candidates... Scanning linux images... Pending kernel upgrade! Running kernel version: 6.8.0-35-generic Diagnostics: The currently running kernel version is not the expected kernel version 6.8.0-41-generic. Restarting the system to load the new kernel will not be handled automatically, so you should consider rebooting. Restarting services... Service restarts being deferred: /etc/needrestart/restart.d/dbus.service systemctl restart getty@tty1.service systemctl restart serial-getty@ttyS0.service systemctl restart systemd-logind.service systemctl restart unattended-upgrades.service No containers need to be restarted. User sessions running outdated binaries: nobi @ session #1: java[935] nobi @ session #2410: java[281638] nobi @ user manager service: systemd[732] No VM guests are running outdated hypervisor (qemu) binaries on this host. $ which nginx /usr/sbin/nginx $ nginx -v nginx version: nginx/1.24.0 (Ubuntu) $
nginx がインストールできました。
3. nginx 設定ファイルの作成
touch コマンドで spresense-transfer という空の設定ファイルを作成します。
$ ls -l /etc/nginx/sites-available 合計 4 -rw-r--r-- 1 root root 2412 12月 1 2023 default $ sudo touch /etc/nginx/sites-available/spresense-transfer $ ls -l !$ ls -l /etc/nginx/sites-available/spresense-transfer -rw-r--r-- 1 root root 0 9月 8 13:27 /etc/nginx/sites-available/spresense-transfer $
このファイルに vi エディターで以下のように記載しました。
$ cat /etc/nginx/sites-available/spresense-transfer
server {
listen 443 ssl;
server_name test-spresense.gadgets-today.net;
ssl_certificate /etc/letsencrypt/live/test-spresense.gadgets-today.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/test-spresense.gadgets-today.net/privkey.pem;
client_max_body_size 10M;
location /tests {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
root /home/spresense-iot-test;
dav_methods PUT;
dav_access user:rw group:rw all:r;
create_full_put_path on;
client_body_temp_path /tmp;
limit_except PUT {
deny all;
}
}
}
sites-enabled ディレクトリにシンボリックリンクを作ることでこの設定ファイルを有効にします。
$ sudo ln -s /etc/nginx/sites-available/spresense-transfer /etc/nginx/sites-enabled/ $ ls -l /etc/nginx/sites-enabled/spresense-transfer lrwxrwxrwx 1 root root 45 9月 8 14:28 /etc/nginx/sites-enabled/spresense-transfer -> /etc/nginx/sites-available/spresense-transfer $
4. ファイルアップロード用ディレクトリの作成
クライアントからアップロードする先のディレクトリを作っておきます。
$ sudo mkdir /home/spresense-iot-test/tests
クライアントから Ubuntu サーバーにアクセスするとき、spresense-iot-test ユーザーの ID とパスワードを使用しますが、サーバー側では nginx が www-data ユーザーとして処理を実行します。
このため、www-data ユーザーとして実行します。そして www-data ユーザーは www-data グループに属していますので、www-data グループにアクセス付与する形の設定にしました。
具体的には、/home/spresense-iot-test/tests ディレクトリと /home/spresense-iot-test ディレクトリの両方に、www-data グループに write と execute の設定を付与する必要がありました。このあたりのパーミッション設定が間違っていると nginx 側のログ (/var/log/nginx/error.log) に 500 エラーが記録されます。
$ sudo chown www-data:www-data /home/spresense-iot-test/tests $ sudo chmod 770 /home/spresense-iot-test/tests $ sudo chown www-data:www-data /home/spresense-iot-test $ sudo chmod 770 /home/spresense-iot-test
ファイルのオーナー・グループとパーミッションを確認します。
$ sudo ls -ld /home/spresense-iot-test/tests drwxrwx--- 2 spresense-iot-test www-data 4096 9月 8 15:50 /home/spresense-iot-test/tests $ sudo ls -ld /home/spresense-iot-test drwxrwx--- 3 spresense-iot-test www-data 4096 9月 8 15:12 /home/spresense-iot-test $
5. ベーシック認証用のユーザーとパスワードの設定
クライアントが Ubuntu にアクセスしてファイル転送するための認証方式はユーザー ID とパスワードのためベーシック認証を使用することになります。
対象のユーザー (spresense-iot-test) がアクセスできるように nginx のベーシック認証で使用されるファイル (/etc/nginx/.htpasswd) を設定します。
以下のようにユーザー名 (spresense-iot-test) とそのパスワードのハッシュ値が .htpasswd ファイルに保存されます。2 つ目のコマンドを実行した後に入力を求められているのは、このユーザーのパスワードです。ここで入力したパスワードがハッシュされて .htpasswd に保存されます。
$ sudo sh -c "echo -n 'spresense-iot-test:' >> /etc/nginx/.htpasswd" $ sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd" Password: Verifying - Password: $
.htpasswd ファイルのオーナー・グループと、ファイルパーミッションを変更します。
$ ls -l /etc/nginx/.htpasswd -rw-r--r-- 1 root root 53 9月 8 14:52 /etc/nginx/.htpasswd $ sudo chown root:www-data /etc/nginx/.htpasswd $ sudo chmod 640 !$ sudo chmod 640 /etc/nginx/.htpasswd $ ls -l /etc/nginx/.htpasswd -rw-r----- 1 root www-data 53 9月 8 14:52 /etc/nginx/.htpasswd $
ここまでできたらngiinx を再起動します。
$ sudo systemctl restart nginx
クライアント側から適当なファイルをアップロードしてみる
クライアント側からアクセスするために認証情報を Base64 形式で準備します。
$ echo -n "spresense-iot-test:passwordstring" | base64
aCyWXdlboNlPXSlc3e5VpVzIC0mOTL4QFqlbG6jZQ==
$
この文字列を添えて、curl で適当なファイル (tmp.txt) を PUT でアップロードしてみます。
$ curl -X PUT -H "Authorization: Basic aCyWXdlboNlPXSlc3e5VpVzIC0mOTL4QFqlbG6jZQ==" -T ./tmp.txt https://test-spresense.gadgets-today.net/tests/tmp.txt
$
nginx のアクセスログ (/var/log/nginx/access.log) を確認します。
130.62.xx.xx – spresense-iot-test [08/Sep/2024:18:51:47 +0900] “PUT /tests/tmp.txt HTTP/1.1” 201 0 “-” “curl/8.5.0”
このようなログが記録されます。
もちろん、指定したディレクトリにはファイルが保存されています。
$ sudo ls -l /home/spresense-iot-test/tests/tmp.txt
-rw-rw-r-- 1 www-data www-data 43 9月 8 18:51 /home/spresense-test/uploads/tmp.txt
$