ラベル nginx の投稿を表示しています。 すべての投稿を表示
ラベル nginx の投稿を表示しています。 すべての投稿を表示

2024年9月1日日曜日

Windows11 に nginx をインストールする方法

Windows11 に nginx をインストールする方法

概要

インストーラはないのでダウンロードして適切な場所に配置して設定ファイルを編集します

環境

  • Windows11
  • nginx 1.27.1

ダウンロード

https://nginx.org/en/download.html ここから zip ファイルをダウンロードします

展開し C 直下に配置

ダウンロードしたファイルを展開しディレクトリをリネームし C 直下に配置します
執筆時点では nginx-1.27.1 というディレクトリ名なのでこれを nginx に変えれば OK です

C:\nginx という感じで配置します

php cgi 連携

php で起動した cgi サーバと連携する場合は以下のように C:\nginx\conf\nginx.conf を修正します
php で起動した cgi サーバと連携する箇所がそもそもコメントされているのでそこをコメントアウトして使います

location / {
    root   html;
    index  index.html index.php;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000

location ~ \.php$ {
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

動作確認

コマンドプロンプトを起動して以下を実行しましょう

cd c:\nginx
start nginx

で localhost にアクセスできることを確認します

cgi の動作確認をしたい場合は php の cgi サーバを起動し C:\nginx\html\test.php を配置し

  • vim test.php
<?php phpinfo();

localhost/test.php にアクセスして php の情報が表示されることを確認しましょう

最後に

nginx と php の連携は連携というよりかは php で起動した fast-cgi サーバにプロキシしてその結果を nginx で表示するという感じです

参考サイト

2024年7月9日火曜日

Grafana を nginx 配下で動作させる方法

Grafana を nginx 配下で動作させる方法

概要

docker で動作している Grafana を nginx 配下で動作させる方法を紹介します

環境

  • Ubuntu 22.04
  • Grafana 10.26.0
  • nginx 1.27.0

Grafana の起動オプション変更

docker compose の場合は GF_SERVER_ROOT_URLGF_SERVER_SERVE_FROM_SUB_PATH を設定します
GF_SERVER_SERVE_FROM_SUB_PATH を true に設定しなければいけないので忘れずに設定しましょう

services:
  grafana:
    image: grafana/grafana-oss:9.5.20
    ports:
     - '3000:3000'
    environment:
      GF_SERVER_ROOT_URL: http://localhost:3000/grafana
      GF_SERVER_SERVE_FROM_SUB_PATH: true
    volumes:
      - type: volume
        source: grafana_data
        target: /var/lib/grafana
    restart: always
volumes:
  grafana_data:

nginx.conf

/prometheus で受けれるようにします

upstream grafana {
    server 192.168.1.100:3000;
}

server {
    listen 8080;
    server_name host01;

    location = /grafana {
        return 302 /grafana/;
    }

    location /grafana/ {
        proxy_set_header Host $host;
        proxy_pass http://grafana;
    }
}

動作確認

:8080/grafana にアクセスして問題なく動作することを確認しましょう

最後に

Grafana は環境変数を使うのが簡単です

参考サイト

2024年7月8日月曜日

Alertmanager を nginx 配下で動作させる方法

Alertmanager を nginx 配下で動作させる方法

概要

前回 Prometheus を nginx 配下で動作させました
今回は Alertmanager を動作させます

環境

  • Ubuntu 22.04
  • Alertmanager 0.26.0
  • nginx 1.27.0

Alertmanager の起動オプション変更

--web.external-url=http://localhost:9093/alertmanager/ を追加します
localhost の部分は listen したいホスト名や IP に変更してください

nginx.conf

/prometheus で受けれるようにします

upstream alertmanager {
    server 192.168.1.100:9093;
}

server {
    listen 8080;
    server_name host01;

    location = /alertmanager {
        return 302 /alertmanager/;
    }

    location /alertmanager/ {
        proxy_set_header Host $host;
        proxy_pass http://alertmanager;
    }
}

prometheus.yml の変更

Prometheus から Alertmanager を使っている場合は alerting 部分を変更します
具体的に path_prefix を追加し targets を nginx のアドレスに変更します

alerting:
  alertmanagers:
    - scheme: http
      path_prefix: "/alertmanager/"
      static_configs:
        - targets:
            - "192.168.1.200:8080"

動作確認

:8080/alertmanager にアクセスして問題なく動作することを確認しましょう
またアラートも届くことを確認しましょう

また Alertmanager のエンドポイントにアクセスしているツールが他にある場合はそちらのエンドポイントも修正する必要があります

最後に

Prometheus も Alertmanager も同じ起動オプションを変更することで nginx 配下で動作させることができます

2024年7月5日金曜日

Prometheus を nginx 配下で動作させる方法

Prometheus を nginx 配下で動作させる方法

概要

ポイントは --web.router-prefix は何も設定しない点です

環境

  • Ubuntu 22.04
  • Promethues 2.52.0
  • nginx 1.27.0

Prometheus の起動オプション変更

--web.external-url=http://localhost:9090/prometheus/ を追加します
localhost の部分は listen したいホスト名や IP に変更してください

nginx.conf

/prometheus で受けれるようにします

upstream prometheus {
    server 192.168.1.100:9090;
}

server {
    listen 8080;
    server_name host01;

    location = /prometheus {
        return 302 /prometheus/;
    }

    location /prometheus/ {
        proxy_set_header Host $host;
        proxy_pass http://prometheus;
    }
}

動作確認

:8080/prometheus にアクセスして問題なく動作することを確認しましょう

また Prometheus のエンドポイントにアクセスしているツール (grafana や sdk など) がある場合はそちらのエンドポイントも修正する必要があります

最後に

次回は Alertmanager を動作させます

参考サイト

2024年6月10日月曜日

OAuth2 Proxy と nginx を組み合わせる方法

OAuth2 Proxy と nginx を組み合わせる方法

概要

前回 oauth2-proxy を構築しました
今回はその構築したプロキシを使って nginx と組み合わせてみます

環境

  • Ubuntu 22.04
  • golang 1.22.3
  • oauth2-proxy 7.6
  • nginx 1.18.0

nginx.conf (default) の修正

  • vim /etc/nginx/sites-available/default

最低限設定が必要な箇所だけ紹介します
server ディレクティブを編集します

location /oauth2/location = /oauth2/auth は必須です
そして認証をかけたい部分 (今回だと location /) に auth_request と error_page お記載します

こうすることで / にアクセスされた際に oauth2-proxy に認証させることができます

server {
	listen 80 default_server;
	listen [::]:80 default_server;

	location /oauth2/ {
		proxy_pass       http://localhost:4180;
		proxy_set_header Host                    $host;
		proxy_set_header X-Real-IP               $remote_addr;
		proxy_set_header X-Auth-Request-Redirect $request_uri;
		# or, if you are handling multiple domains:
		# proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
	}
	location = /oauth2/auth {
		proxy_pass       http://localhost:4180;
		proxy_set_header Host             $host;
		proxy_set_header X-Real-IP        $remote_addr;
		proxy_set_header X-Forwarded-Uri  $request_uri;
	        # nginx auth_request includes headers but not body
	        proxy_set_header Content-Length   "";
		proxy_pass_request_body           off;
	}

	root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
	server_name _;

	location / {
		auth_request /oauth2/auth;
		error_page 401 =403 /oauth2/sign_in;
		try_files $uri $uri/ =404;
	}
}

oauth2-proxy 側は

前回の設定のままで OK です

動作確認

  • sudo systemctl restart nginx

で再起動し localhost にアクセスすると認証ページに移動することを確認します

Tips

nginx は当然アクセスできる必要があるのですが auth2-proxy にもクライアントからアクセスできる必要があります
これはリダイレクト先が auth2-proxy になっているためで auth2-proxy のリダイレクト URL にブラウザからアクセスできないと認証情報が受け取れないためです
なのでクライアントには 80 と 4180 の auth2-proxy のポートも開放する必要があります

最後に

oauth2-proxy と nginx を組み合わせてみました
認証後の情報がバックエンド側のアプリでほしい場合には nginx 側でスルーするヘッダなどを設定しましょう

参考サイト

2023年4月10日月曜日

docker + nginx でファイルを簡単に公開する

docker + nginx でファイルを簡単に公開する

概要

適当にファイルを公開したい場合に使えます

環境

  • Ubuntu 18.04
  • docker 20.10.7

コマンド

公開したいディレクトリに移動してから以下を実行します
ドキュメントルートにローカルのファイルをマウントして終了です

  • docker run -d -p 80:80 -v $(pwd):/usr/share/nginx/html --name web nginx

2021年5月5日水曜日

nginx-quic をビルドしてみた

nginx-quic をビルドしてみた

概要

nginx でも本格的に QUIC サポートが始まっており現在かなり使えるレベルにまでなっているので試してみました
Vagrant で構築した Ubuntu 18.04 上でビルドします

環境

  • Ubuntu 18.04
    • cmake 3.10
    • ninja 1.8.2
    • golang 1.10
  • Chrome 90.0.4430.85
  • nginx-quic 1.19.10
  • boringssl (revision: fe3b185e5d46e643727cbf3e7cb1edcb394f1317)

依存パッケージのインストール

  • sudo apt -y install mercurial ninja-build cmake build-essential g++ golang libpcre3 libpcre3-dev zlib1g-dev

自分の環境は上記で足りましたが他に足りないパッケージがある場合は適宜インストールしてください
OpenSSL のライブラリがないと言われる場合は後述する boringssl のビルドがうまくいっていない可能性があります

boringssl のビルド

nginx-quic のビルド

  • hg clone -b quic https://hg.nginx.org/nginx-quic
  • cd nginx-quic
  • ./auto/configure --with-debug --with-http_v3_module --with-cc-opt="-I../boringssl/include" --with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto"
  • make
  • sudo make install

nginx のバイナリは /usr/local/nginx/sbin/nginx に配置されます

(Optional) サーバ証明書の作成

動作確認用の自己証明書を作成します
すでに適当なサーバ SSL 証明書がある場合はそれで代用可能です

https://hawksnowlog.blogspot.com/2021/01/how-to-generate-client-certs-on-ubuntu.html#optional-サーバ証明書の作成

nginx 起動

QUIC をオンにした nginx の設定ファイルを作成し起動します

  • cat /usr/local/nginx/conf/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    log_format quic '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" "$quic" "$http3"';

    access_log logs/access.log quic;

    server {
        listen 8443 http3 reuseport;
        listen 8443 ssl;

        ssl_certificate     /etc/nginx/certificates/domain.com.crt;
        ssl_certificate_key /etc/nginx/certificates/domain.com.key;
        ssl_protocols       TLSv1.3;

        location / {
            add_header Alt-Svc '$http3=":8443"; ma=86400';
        }
    }
}
  • sudo /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

動作確認

http3 が使える curl クライアントを使います
QUIC が使えるクライアントはいろいろありますのでお好きなものを使ってください

これで「HTTP/3 200」と表示されれば OK です
ちなみに nginx のログを見るとちゃんと HTTP3 で通信しているのが確認できます

  • tail -f /usr/local/nginx/logs/access.log
172.17.0.2 - - [29/Apr/2021:12:04:56 +0000] "GET / HTTP/3.0" 200 790 "-" "curl/7.76.1-DEV" "quic" "h3-29"

以下の動作確認方法 ERR_QUIC_PROTOCOL_ERROR となりできません
おそらく自己証明書などの関係かなと思います

chrome を使って quic でレスポンスされているか確認してみましょう
Chrome で QUIC をオンにして再起動します

  • chrome://flags/#enable-quic

https://192.168.100.10:8443/

NET::ERR_CERT_INVALID で先に進めない場合は「thiisunsafe」をタイプしましょう

最後に

設定ファイルなどもそのまま流用できますし QUIC でないクライアントの場合は HTTP2/1.1 で返してくれるのでかなり使えそうです
ただ自分でバイナリをビルドする必要があるのでそこがまだ面倒かなと思います

docker などで公式がリリースしてくれる日も近いかもしれません

参考サイト

2021年1月28日木曜日

Ubuntu でクライアント証明書を発行する方法

概要

過去 に Mac で作成しました
今回は Ubuntu で作成してみたいと思います

環境

  • Ubuntu 18.04
  • openssl 1.1.1i

CA 用ディレクトリの作成

ここに鍵やクライアント証明書を作成していきます

  • sudo mkdir /CertificateAuthCA

ルートCAの作成

鍵を作成し鍵から証明書を作成します
CSR の情報は適当に入力します
今回の方法では鍵にパスフレーズの設定が必要になるので入力しましょう

  • sudo openssl genrsa -des3 -out ca.key 4096
  • sudo openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

クライアント証明書の作成

こちらもまずは鍵を作成します
次に CSR を先に作成してその CSR と先ほど作成してルートCA の鍵と証明書を使ってクライアント証明書を作成します

  • sudo openssl genrsa -des3 -out client.key 2048
  • sudo openssl req -new -key client.key -out client.csr
  • sudo openssl x509 -req -days 365 -in client.csr -CA myca.crt -CAkey myca.key -set_serial 01 -out client.crt

nginx で動作確認するので pem ファイルも作成しておきます

  • sudo openssl x509 -in client.crt -outform PEM -out client.pem

Optional: サーバ証明書の作成

nginx で動作確認します
クライアント証明書は https が必須なので https で nginx が動作するためにサーバ証明書も作成しておきます

  • sudo apt -y install nginx
  • sudo mkdir /etc/nginx/certificates
  • sudo chown -R www-data:www-data /etc/nginx/certificates
  • cd /etc/nginx/certificates

サーバ証明書配置ディレクトリを作成してそこに作成します
鍵、CSR、証明書を作成します

  • sudo openssl genrsa -out domain.com.key 2048
  • sudo openssl req -new -sha256 -key domain.com.key -out domain.com.csr
  • sudo openssl x509 -in domain.com.csr -out domain.com.crt -req -signkey domain.com.key -days 3650

あとは nginx の設定をします

  • cd /etc/nginx/sites-available
  • sudo touch proxy.conf
  • sudo vim proxy.conf
ssl_client_certificate /CertificateAuthCA/ca.pem;
ssl_verify_client on;
  • sudo ln -s /etc/nginx/sites-available/proxy.conf /etc/nginx/sites-enabled/proxy.conf
  • sudo systemctl restart nginx
  • systemctl status nginx

動作確認

curl で動作確認します
必要になるのはクライアント証明書と鍵になります
また curl の場合は --key で指定する鍵情報に証明書の情報も含まれている必要があるので注意してください

  • cat client.crt client.key > client_curl_key.pem
  • curl -k --cert ./client.crt --key ./client_curl_key.pem https://localhost

ちなみに Ruby では以下のスクリプトで動作します

  • vim test.rb
require 'net/https'

https = Net::HTTP.new('localhost', 443)
https.use_ssl = true
https.cert = OpenSSL::X509::Certificate.new(File.read('./client.crt'))
https.key = OpenSSL::PKey::RSA.new(File.read('./client.key'), 'pass')
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
https.verify_depth = 5
https.start {
  response = https.get('/')
  puts response.body
}
  • ruby test.rb

最後に

中間CA がある場合にはまた作業や挙動が異なると思います
証明書はクライアントごとに発行できるます
もし複数のクライアントで証明書を作成した場合は nginx 側では ca.pem の後ろに結合していけば OK です

参考サイト

2020年10月20日火曜日

nginx の server_names_hash_bucket_size の挙動を確認してみる

概要

server_names_hash_bucket_size ディレクティブは nginx で VirtualHost を使う場合に影響するディレクティブになります
VirtualHost として指定する server_name が長い場合などにエラーが発生することがあります
今回は server_names_hash_bucket_size の適切なサイズを見極めるために挙動を確認してみました

環境

  • macOS 10.15.7
  • nginx 1.19.3

まずは確認用のアプリを作成する

何でも OK です
今回は nginx 単体で動作確認します

nginx.conf

2 つの server ディレクティブを定義します
下が動作確認用で上は Host ヘッダが設定されていない場合のデフォルトで表示する server になります
server_names_hash_bucket_size はデフォルトの 32 で設定しています

  • vim /usr/local/etc/nginx/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server_names_hash_bucket_size  32;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html;
        }
    }

    server {
        listen       80;
        server_name  test-server.dev;

        location / {
            root   html;
            index  index2.html;
        }
    }
}

確認用 html

どちらが表示されているか確認できるないようであれば何でも OK です

  • vim /usr/local/var/www/index.html
<html>
<head>
</head>
<body>
index
</body>
</html>
  • vim /usr/local/var/www/index2.html
<html>
<head>
</head>
<body>
index2
</body>
</html>

テストしてみる

  • brew services start nginx

で起動し curl で Host ヘッダを設定し異なるコンテンツが返ってくるか確認しましょう

  • curl localhost

=> index

  • curl -H 'Host: test-server.dev' localhost

=> index2

が返ってくることを確認します

server_name を長くしてエラーが発生するか確認する

まずは could not build server_names_hash, you should increase server_names_hash_bucket_size: 64 というエラーが発生するか確認します
想定では server_name を長くすれば発生するはずです
例えば以下のように長くしてみましょう

  • vim /usr/local/etc/nginx/nginx.conf
server_name  test-server.aaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbcccccccccc.dev;

76 文字あります
これで nginx を再起動してみるとうまく起動していないことが確認できます

  • brew services restart nginx

またログを見ると該当のログが表示されているのも確認できると思います

  • less /usr/local/var/log/nginx/error.log
2020/10/20 14:37:05 [emerg] 22865#0: could not build server_names_hash, you should increase server_names_hash_bucket_size: 64

ちなみにこの指示通りに server_names_hash_bucket_size: 64 に変更してもなぜかエラーは止まりませんでした
更に上の 128 を指定したところ上記の設定でも動作するを確認しています
なぜ 64 ではダメで 128 で動作するのかは謎です

ギリギリのラインを確認する

先程は 76 文字の適当な server_name を設定しました
今度はエラーになるギリギリの文字数を見つけてみます

  • vim /usr/local/etc/nginx/nginx.conf
server_name  test-server.aaaaaaaaaabbbbbbbbbbcccccccccc.dev;

上記のように 46 文字を指定したところでエラーが止まりました
これならば server_names_hash_bucket_size: 32 でも動作します
しかし一文字増やすだけで 64 でなく 128 が必要になります

別の server ディレクティブの影響を受けるのか確認する

server_name の情報をマッピングするハッシュを生成している可能性があるので別の server ディレクティブを追加してみます
まずは以下のようにしましょう

  • vim /usr/local/etc/nginx/nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout  65;
    server_names_hash_bucket_size 32;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html;
        }
    }

    server {
        listen       80;
        server_name  test-server.aaaaaaaaaabbbbbbbbbbcccccccccc.dev;

        location / {
            root   html;
            index  index2.html;
        }
    }

    server {
        listen       80;
        server_name  new.test-server.dev;

        location / {
            root   html;
            index  index3.html;
        }
    }
}

これは server_names_hash_bucket_size: 32 でも動作しました
これだけ見ると server ディレクティブの数には影響しないように見えます
一応更に動作確認として new2, new3, new4 まで作りましたが特に問題なく動作しました

ただドキュメントを見ると server_name を大量に定義した場合は server_names_hash_max_size ディレクティブのチューニングが必要とあったのでもしかすると 50 とか 100 ほど server ディレクティブを定義すればエラーが発生するかもしれません

結論

結論としては数字と server_name の相関関係ははっきりとわかりませんでした
nginx のコードを読めばハッシュの生成方法がわかると思いますがそこまでは追っていません
なので現状は自分もとりあえずエラーが発生したら値を増やせという雑な対応しかできないところです
使用している CPU のラインキャッシュが影響するようなのでマシンによっては大きな値は設定できないという可能性もでてきそうです

参考サイト

2020年7月28日火曜日

Vue で作成したコードをプロダクション用として nginx にデプロイする方法

概要

vue cli で作成したプロジェクトであれば yarn build コマンド一発でプロダクション用の html, js, css を出力できます
今回は出力したファイルをデプロイする方法を紹介します

環境

  • macOS 10.15.6
  • nginx 1.19.1
  • yarn 1.22.4
  • vue cli 4.4.6

ビルド

  • yarn build

これだけで OK です
完了すると dist ディレクトリ配下に作成されるので基本はそれらを DocumentRoot に配置すれば OK です

デプロイ

例えば macOS 上の nginx であれば以下のような感じでできます
デフォルトの DocumentRoot は /usr/local/var/www になります
また nginx が起動するポートは 8080 になっています

  • mv /path/to/dist/* /usr/local/var/www
  • nginx

これで localhost:8080 にアクセスすると Vue で作成した Single Page Application が表示されます

VueRouter を使っている場合の注意点

VueRouter を使っている場合 VueRouter が生成する URI に再度アクセスすると 404 エラーになってしまいます
これは nginx 側で VueRouter が生成した URL を受ける設定をしていないためです

server ディレクティブに 404 時にリダイレクトする設定を入れましょう
そして reload します

  • vim /usr/local/etc/nginx/nginx.conf
error_page  404 /;
  • nginx -s reload

これで再度確認すると以下のように nginx のデフォルトの 404 ページが表示されずに現在のページにあたかもリダイレクトされているような挙動になります

ただコンソールを見るとわかりますが一度 nginx が 404 を返すことには変わりないのでエラーは表示されてしまうことには注意しましょう
もしかするともっと良い方法があるのかもしれませんがとりあえず手っ取り早く対応するならこれが簡単です

最後に

Vue で作成したアプリをビルドしてデプロイするところまでやってみました
vue cli で作成していればコマンド一つでビルドできるように設定してくれるので簡単です
が、内部で何をやっているのかはさっぱりなので詳しく知りたい方には向いていない方法かなとも思います

VueRouter を使っている場合には注意が必要だということもわかりました (VueRouter に関わらず angular などの SAP でも同様の現象になります)
今回は nginx にデプロイしてみましたが他の web サーバでも同様の対処が必要になると思います

参考サイト

2020年3月3日火曜日

nginx の upstream_response_time を使う場合は map を設定しておこう

理由

upstream_response_time は 499 などでクライアントからの接続エラーの場合には「- (ハイフン)」が設定されます
ElasticSearch 側の型が Integer の場合にはエラーになるのでハイフンの場合には適当な数値が入るように map を使って設定しておきましょう

設定方法

map $upstream_response_time $u_r_t {
  default $upstream_response_time;
  "-"     0;
}

上記を設定したあとで参照する場合は $u_r_t を使いましょう

2019年12月28日土曜日

nginx でクライアント証明書認証してみる (キーチェーンアクセス編)

概要

クライアント証明書認証は https のサイトにアクセスするのに指定の証明書がないとアクセスできない認証です
IP だけではアクセス制御できない場合に使えます
今回は証明書の発行をキーチェーンアクセスで行い、そこで発行した証明書を使って nginx でクライアント証明書認証を試してみました

環境

  • macOS 10.15.2
  • nginx 1.15.2

認証局の作成

まずはキーチェーンアクセスを使って認証局を作成します
証明書は認証局がないと発行できません

ユーザ証明書を「SSL クライアント」にします
名前は好きな名前にしましょう

以下のように認証局が作成できれば OK です

キーチェーンアクセスの一覧にも認証局が存在することを確認します

クライアント証明書の発行

次に作成した認証局からクライアント証明書を書き出します

作成した認証局を右クリックし書き出しを選択します

鍵は p12 形式で書き出します

鍵にはパスワードを設定することもできます
今回はテストなのでパスワードなしにします

鍵が書き出せたら同様に認証局を右クリックして書き出しを選択します
そして .cer 形式で証明書を書き出します

証明書と鍵の変換

nginx で使うためには証明書と鍵ファイルをそれぞれ「.crt」「.key 」形式に変換する必要があります

  • openssl x509 -in ca.cer -inform DER -out ca.crt -outform PEM
  • openssl pkcs12 -in ca.p12 -nocerts -nodes -out ca.key

鍵を変換する際にパスワードを求められますが今回は設定していないので空で OK です

nginx の設定

あとは作成したクライアント証明書を nginx に設定して起動します
クライアント証明書認証は https でなければ動作しないのでサーバ証明書を適当に用意します
また以下の設定は最低限の設定のみになっています

  • cd /usr/local/etc/nginx/
  • vim nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       443 ssl;
        server_name  localhost;

        ssl_certificate      /etc/letsencrypt/live/hoge.fuga.com/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/hoge.fuga.com/privkey.pem;
        ssl_verify_client on;
        ssl_client_certificate /path/to/ca.crt;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
    }

    include servers/*;
}

ssl_verify_client on;ssl_client_certificate /path/to/ca.crt; がクライアント証明書認証を有効にしている部分です
それ以外のディレクティブは SSL に関する設定になります

/path/to/ca.crt は先程変換した証明書のパスをフルパスで指定しましょう
鍵は nginx には指定せずクライアントがアクセスする際に指定します

動作確認

nginx を再起動しましょう

  • sudo nginx -s stop
  • sudo nginx

まずは curl を使って確認してみます
クライアント証明書を指定するオプションは --cert でクライアント証明書の鍵を指定するオプションは --key になります

  • curl -k --cert ./ca.crt --key ./ca.key https://localhost

これでアクセスできると思います
もしクライアント証明書と鍵が指定されていない場合は nginx が「400 No required SSL certificate was sent」というエラーを返します
またクライアント証明書と鍵の指定が誤っている場合は「400 The SSL certificate error」が返ります

こんな感じでクライアント証明書と鍵の指定が合っていないと正常にアクセスできないのでこの仕組を使ってアクセス制御を実現できるます

ちなみに Chrome などのブラウザでアクセスしたい場合はキーチェーンアクセスなどの証明書を管理するアプリに鍵をインポートしましょう
基本は p12 ファイルをそのまま配布してダブルクリックなどすれば各 OS に付属の証明書管理アプリが立ち上がってインポートできると思います

今回は curl とブラウザのクライアント証明書を使ったアクセス方法を紹介しましたがクライアントのソフトウェアによって証明書の設定は様々なのでそれぞれに合った設定をしてください

最後に

nginx でクライアント証明書認証を試してみました
クライアント証明書の発行は MacOS 付属のキーチェーンアクセスで行いました
キーチェーンアクセスに慣れている人はこの方法でも良いと思います
クライアント証明書の管理も簡単になります

openssl コマンドを使ってすべての作業をクライアント証明書の発行を行うことも可能です
openssl の手順はネットを検索すればいろいろ出てくると思います

また混乱しそうなので説明しておくとサーバ証明書とクライアント証明書は全くの別物です
同じ認証局から発行されている必要もないのでご注意ください

2019年7月20日土曜日

nginx で error.log にログ意図的に出力させる方法

概要

nginx の error.log をテストで意図的に出力させたい場合はあると思います
そんなときにてっとり早くエラーログを出力させる方法を紹介します
なお今回は nginx コンテナを使っています

環境

  • macOS 10.14.5
  • docker 18.09.2

default.conf の編集

CGI 用の URI を活用します
.php でアクセスが来たらそのままバックエンドのアプリに流しますが実際はないのでこれでエラーログが出ます

  • vim default.conf
location ~ \.php$ {
    proxy_pass   http://127.0.0.1;
}

途中他の設定もありますが省略しています
なお default.conf はコンテナ内から cp しても OK です

  • docker -d run nginx
  • docker cp 403876658f4e:/etc/nginx/conf.d/default.conf .

default.conf を使って nginx コンテナを起動

作成した default.conf を使ってコンテナを起動します

  • docker run -d -p 80:80 -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf nginx

動作確認

docker logs には標準出力と標準エラーのどちらも流れてきます
標準出力のみを表示する場合は

  • docker logs -f 403876658f4e 2> /dev/null

標準エラーのみを表示する場合は

  • docker logs -f 403876658f4e > /dev/null

という感じで表示を制限できます
今回はエラーログを表示させたいので下を使います
そして curl を使って以下のようにアクセスしてみましょう

  • curl localhost/index.php

すると以下のようにエラーログが出力されると思います

2019/07/17 01:37:16 [alert] 7#7: 1024 worker_connections are not enough 2019/07/17 01:37:16 [error] 7#7: *1021 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET /index.php HTTP/1.0", upstream: "http://127.0.0.1:80/index.php", host: "127.0.0.1"

最後に

nginx の error.log のテストをしたい場合に意図的にエラーログを出力する方法を紹介しました
これ以外にも方法はあると思いますが思いつかない場合には使ってみてください

2018年6月8日金曜日

nginx for windows で簡単ファイルホスティング

概要

Windows から別のマシンにファイルを送るのが非常に面倒です
そんな場合に nginx を立ててファイルを配布すると簡単です

環境

  • Windows7 64bit HomeEdition
  • nginx for Windows 1.15.0

インストール

ここから最新版の zip ファイルをダウンロードしましょう
執筆時点では「nginx-1.15.0.zip」というファイルが最新版でした
ダウンロードしたら解凍して適当なフォルダに配置してください

基本はこれだけで OK です
いらなくなったらフォルダごと捨ててください

サーバを起動する

コマンドプロンプトを立ち上げましょう
あとは配置したディレクトリに移動して start するだけです

  • cd nginx-1.15.0
  • start nginx.exe
  • tasklist /fi "imagename eq nginx.exe"

tasklist コマンドでプロセスが起動しているか確認できます

ファイルをホスティングする

ドキュメントルートに配置してみましょう
デフォルトだと配置した nginx-1.15.0 配下の html というディレクトリが root になっています
ここに適当にテキスト (hoge.txt) を配置してください
nginx_win1.jpg

あとはブラウザで localhost/hoge.txt にアクセスするとファイルが表示できると思います
Mac などからダウンロードしたい場合は wget コマンドを使っても良いと思います

停止する

  • nginx.exe -s stop

で OK です

最後に

Windows で nginx を動かしてみました
Windows で生成したファイルをほかで共有したい場合に一時的に nginx を起動するだけで簡単に共有できるかなと思います

Mac と Windows, Linux と Windows でファイルを共有する場合にはいろいろな方法がありますがファイル共有機能などを使うといろいろと躓くポイントが多いのでとりあえずってことであればこの方法をお勧めします

参考サイト

2018年4月30日月曜日

docker-compose を使って Sinatra を nginx 配下で動かす方法

概要

nginx を挟んでいたほうが何かと便利なので試してみました
最終的には docker-compose で nginx と Sinatra が上がってきます

$ tree . -I vendor
.
├── Dockerfile.web
├── Gemfile
├── Gemfile.lock
├── app.rb
├── config.ru
├── docker-compose.yml
└── nginx.conf

環境

  • macOS 10.13.4
  • docker-compose 18.04.0-ce

Sinatra アプリの作成

  • vim config.ru
require './app.rb'
run MyApp
  • vim app.rb
require 'sinatra/base'

class MyApp < Sinatra::Base
  get '/' do
    request.host
  end
end

アプリはリクエストのホストヘッダを返すだけです

  • vim Dockerfile
FROM ruby

ADD . /home
WORKDIR /home
RUN bundle install --path vendor

CMD ["bundle", "exec", "rackup", "config.ru", "-o", "0.0.0.0"]

nginx.conf の作成

今回の肝の部分かと思います

  • vim nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    upstream app {
        server web:9292; 
    }

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass http://app;
            proxy_set_header Host $host;
        }
    }
    include servers/*;
}

ポイントは proxy_set_header Host $host; です
これがないと Sinatra で 404 エラーが発生した際に正常に表示されません
Sinatra はリクエストされた Host ヘッダを見て画像などの情報を取得します
もし上記の nginx.conf の設定がない場合 Host 情報が app となってしまい画像などを取得しにいくサーバも http://app となり正常に取得できません

なので Host ヘッダをちゃんと設定することで Sinatra が正常に画像などを取得できるようにします

docker-compose.yml の作成

  • vim docker-compose.yml
version: '2'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.web
    expose:
      - "9292"
  proxy:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    links:
      - "web"

作成した nginx.conf を volumes を使って nginx コンテナ内の nginx.conf に上書きします
web 側のポート解放はホスト側の解放は不要なので expose を使っています
直接ホストから Sinatra にアクセスしたいのであれば ports を使うと良いと思います

動作確認

  • docker-compose up -d

で起動しましょう
nginx と Sinatra が上がってきます
nginx 側にアクセスすれば良いのです http://localhost にアクセスしましょう
するとそのまあプロキシして Sinatra アプリの情報が表示されると思います
また、http://localhost/hoge などにアクセスしてもちゃんと Sinatra のエラー画面が表示されることが確認できると思います

最後に

nginx + Sinatra を docker-compose で動かしてみました
今回 upstream を使っていますがなくても大丈夫です
将来的にアプリをポート分散などさせたい場合は upstream を定義したほうが良いかと思います

nginx を入れた理由としては同一マシン内で別アプリを動かした際に nginx でルーティングすることができるのと、同一マシンに別のドメインを振って VirtualHost の server_name でバランシングできることかなと思います
単一ホストだけで動作させている場合などには必須の構成かなと思います

ただこの構成にすることで nginx の管理、チューニングをする必要が出てくるのでそれはそれで面倒かなとも思います

2017年10月2日月曜日

nginx の location に対してベーシック認証をかける

概要

nginx にベーシック認証をかけてみました
指定した location のパスにアクセスした場合にベーシック認証が発動するようにしてみます

環境

  • Ubuntu 16.04
  • nginx 1.10.3

パスワードファイル生成

  • echo "username:$(openssl passwd -apr1 password)" > /etc/nginx/basic_auth_password
  • chmod 400 /etc/nginx/basic_auth_password

username と password の部分がベーシック認証に使われる ID/PW です

設定ファイル変更

  • vim /etc/nginx/sites-available/ssl
location /hoge {
    auth_basic "closed site";
    auth_basic_user_file /etc/nginx/basic_auth_password;
    proxy_pass http://localhost:4567/optin;
    proxy_redirect default;
}

location の部分だけ抜粋しています
auth_basic と auth_basic_user_file を追記すれば基本的には OK です

再起動

  • systemctl restart nginx

これでベーシック認証が location の部分にだけ発生するようになっていると思います

最後に

nginx の location にベーシック認証をかけてみました
server ディレクティブにも設定できるのでパスではなくサイト全体でかけることもできます

2017年8月5日土曜日

nginx のエラーレスポンスで json レスポンスを返却してみる

概要

前回 nginx に IP 制限をしてみました
今回は IP 制限した際にデフォルトのエラーページではなく json レスポンスを返却するようにしてみたいと思います

環境

  • Ubuntu 16.04
  • nginx 1.10.3

設定ファイル編集

前回の設定から以下のように編集します

  • vim /etc/nginx/sites-available/ssl
server {
        error_page 403 /403.json;
        location /403.json {
            default_type application/json;
            return 403 '{"error": {"status_code": 403,"status": "Forbidden"}}';
        }
        allow 192.168.100.110;
        deny all;
        listen       443;
        server_name  your.site.domain.com;

        ssl                  on;
        ssl_certificate      /etc/ssl/certs/chain_server.crt;
        ssl_certificate_key  /etc/ssl/certs/server.key;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;

        location / {
            proxy_pass http://localhost:9292/;
            proxy_redirect default;
        }
}

先頭の error_page とエラー用の location を追記しています

error_page 403 /403.json;
location /403.json {
    default_type application/json;
    return 403 '{"error": {"status_code": 403,"status": "Forbidden"}}';
}

403 エラーが発生した場合は /403.json という場所にアクセスします
そして /403.json は Content-Type application/json で {"error": {"status_code": 403,"status": "Forbidden"}} という文字列を返却するように定義しています

こうすることで 403 のエラーページをデフォルトの HTML ではなく json 文字列を返却できるようになります

ポイントは 2 つで 403.html とせずに 403.json として点と default_type ディレクティブを使用して Content-Type を application/json に設定してる点です
これをしないと text/html で返却されてしまいブラウザなどのクライアントなどでは HTML として判断して処理してしまうことになります

最後に

nginx の 403 ページを json 文字列が返るようにカスタマイズしてみました
別途エラーページ専用のファイルを用意しなくてもできるのは嬉しい点かなと思います

うまく application/json で返却されない場合は /etc/nginx/mime.types というファイルに以下の設定が入っているか確認してみてください

application/json                      json;

参考サイト

2017年8月3日木曜日

nginx にIP 制限を入れる方法

概要

前回 nginx に証明書を設置して SSL を有効にしました
今回は nginx にアクセスする IP を制限したかったので試してみました

環境

  • Ubuntu 16.04
  • nginx 1.10.3

設定ファイル編集

前回の設定から以下のように編集します

  • vim /etc/nginx/sites-available/ssl
server {
        allow 192.168.100.110;
        deny all;
        listen       443;
        server_name  your.site.domain.com;

        ssl                  on;
        ssl_certificate      /etc/ssl/certs/chain_server.crt;
        ssl_certificate_key  /etc/ssl/certs/server.key;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;

        location / {
            proxy_pass http://localhost:9292/;
            proxy_redirect default;
        }
}

追記しているのは先頭の allow と deny の部分です
これだけで IP 制御ができます
今回は IP を直書きしていますが CIDR 形式でも記載することができます

設定を反映するには nginx を再起動します

  • systemctl restart nginx

上記の設定の場合 192.168.100.104 だけを許可していてそれ以外はすべて拒否する設定になります
先に deny を書いてしまうとすべて拒否して終了になってしまうので先に allow を記載するようにしてください

deny された場合には nginx が用意しているデフォルトの HTML が返却されます

<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

最後に

nginx に IP 制限をしてみました

このあたりの設定方法は Web 上にゴロゴロ転がっていると思います
このままだとデフォルトの HTML が返却されてしまうので次回はレスポンスをカスタマイズしてみたいと思います

2017年7月15日土曜日

Ubuntu16.04 の nginx で SSL 通信を有効にする方法

概要

Ubuntu16.04 で apt install できる nginx に SSL 証明書を設定して https 通信させてみました
Web 上に他にもいろいろと nginx + ssl の記事はありますが自分の備忘録として残しておきます

環境

  • Ubuntu 16.04
  • nginx 1.10.3

nginx のインストール

  • apt -y install nginx

今回は apt でインストールします
執筆時点での nginx の最新版は 1.13.3 なのでバージョン的にはかなり古いものになります

SSL の有効化

ディレクトリ構成などは apt install できたものをそのまま採用してます

設定ファイルの作成

まず SSL 用の設定ファイルがないので作成します

  • touch /etc/nginx/sites-available/ssl
  • vim /etc/nginx/sites-available/ssl
server {
        listen       443;
        server_name  your.site.domain.com;

        ssl                  on;
        ssl_certificate      /etc/ssl/certs/chain_server.crt;
        ssl_certificate_key  /etc/ssl/certs/server.key;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;

        location / {
            proxy_pass http://localhost:9292/;
            proxy_redirect default;
        }
}

server_name には 443 で受けるサーバまたはロードバランサのドメイン名を指定してください
ポイントとしては ssl_certificate の項目で nginx の場合 CA 証明書を設定する欄はなく ssl_certificate でサーバ証明書と CA 証明書を設定します
つまりどういうことかというと 2 つのファイルを結合して配置します

連結証明書の作成

  • scp server.crt server.key ca.crt server001:/etc/ssl/certs

ローカルからサーバに証明書を転送します、すでにサーバに証明書一式がある場合はこの作業は不要です
パスは「/etc/ssl/certs」に配置します

  • cd /etc/ssl/certs
  • cat server.crt ca.crt >> chain_server.crt

単純に cat で結合すれば大丈夫です

設定ファイルを有効化

Ubuntu + apt install の場合 sites-enabled に使いたい設定ファイルのシンボリックリンクを作成することで設定を追加することができます
Apache とかもこの方式を採用しています

  • cd /etc/nginx/sites-enabled
  • ln -s /etc/nginx/sites-available/ssl ssl
  • rm default
  • systemctl restart nginx

作成した ssl を sites-enabled にリンクして終了です
あとは nginx を再起動してあげましょう

動作確認

ブラウザや curl で適当にドメインにアクセスして localhost:9292 で動作してるアプリにアクセスできるか確認してください
もちろんローカルで動作しているアプリは別のものに変更して大丈夫です

最後に

Ubuntu16.04 の nginx で https 通信を設定してみました
Web 上に膨大な情報があるので簡単にセットアップできると思います

この後の Tips でも紹介していますが、地味に ufw の設定などでハマるかもしれません

Tips

もし key ファイルにパスが設定されている場合は以下のコマンドでパスフレーズがない key ファイルを作成してください
パスフレーズがあっても問題ないのは問題ないですが、systemctl で自動起動などができなくなります

  • openssl rsa -in server.key -out nopass_server.key

パスフレーズがわからない場合はさすがに証明書の管理者に聞くしかないと思います

Ubuntu の場合 ufw が効いているので 443 をオープンしましょう

  • ufw allow 443

あと curl で以下のようなエラーが出た場合は CA 証明書が適切に連結されているか確認してみてください

curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

証明書によっては CA ファイルが不要な証明書もあるのでその場合は特にエラーも出ないと思います