Windows上にサーバー作成 Nginx/PHP/MariaDB/WordPress

以前は必要になるとXamppを使ってたけど、今回はNginx環境を手動で作ってみる。

Nginx

Windows用のzipファイルをダウンロードし解凍する。設定ファイルはもともとのコメント部を消して、とりあえずこんな感じ。

nginx-1.19.2/conf/nginx.conf

Nginxフォルダのパスに日本語があると起動しない場合があるので注意。

PHP

ダウンロードして解凍したら、phpというフォルダでnginxの中に入れる。
(nginx-1.19.2/php)

php.ini-development
をコピーしてphp.iniにし、
extension_dir=”ext”
extension=php_mysqli.dll
を追記する。

MariaDB

ダウンロードして解凍したら、mariadbというフォルダでnginxの中に入れる。
(nginx-1.19.2/mariadb)

nginx-1.19.2/mariadb/bin
の中にある、mysql_install_db.exeを実行すると、
nginx-1.19.2/mariadb/data
が作成され、my.iniも入っている。
(Nginxフォルダを移動したらmy.iniを修正しないと起動しない)

手動でDB作成等に使う場合、まずbinの中のmysqld.exeを起動。次にコマンドプロンプトからmysql -u root のような感じでログインできる。

・設定
nginx-1.19.2/mariadb/bin
に移動しmysqldを起動後、
mysql -u root
とするとログインできる。

mysql> set password = password(“1234”);

・データベース作成
mysql> create database wpd character set utf8;
(utf8を指定しないとWPのインストールでエラー)

起動・終了バッチ

start.bat

my.iniを自動で書き換える場合このような感じ

stop.bat

あるいは全て強制終了
(こうしないとプロセスが残る場合あり)

mysql.bat

mysqlのディレクトリに移動するためだけのバッチ

WordPress

nginx-1.19.2\html\wp
にWordPressを解凍したので、ブラウザから、
http://localhost/wp

にアクセス。

DBの情報を入れて送信したところ、
サイトに重大なエラーがありました。
と表示されエラーになった。
(1度目のインストール)

・DBをリセット
フォルダを手動で削除せず、mysqlのコマンドからdrop databaseする。
そして再度create databaseする。

・wp-config.phpを削除
wp-config-sample.phpを複写し、名前をwp-config.phpに変更する。

wp-config.phpが存在しないと自動でwp-config.phpは作成されるが、ここでは手動でwp-config.phpを設定する。

wp-config.phpの以下の部分をtrueに変更する。
define( ‘WP_DEBUG’, true);

以下の部分にDB情報を記入する。
define( ‘DB_NAME’, ‘wpd’ );
define( ‘DB_USER’, ‘root’ );
define( ‘DB_PASSWORD’, ‘1234’ );

再度挑戦するが、
サイトに重大なエラーがありました。
と表示されるだけで、特にエラー内容は表示されない。
(2度目のインストール)

Nginxのログ(logs/error.log)
を確認すると、
Fatal error: Maximum execution time of 30 seconds exceeded
とあるので、
php.iniで下記の部分を30から120に変更
max_execution_time = 120
(3度目のインストール)

これでインストールできた。

LAN経由(外部)から見る場合、ファイアーウォールに新しい規則を追加する。
もしCSSが適用されていない場合は、
設定>一般>アドレス
をIPアドレスに変更してみる。

NginxとgolangでAPIサーバー

golangもNginxも始めたばかりなので、他のブログの記事を参考にしつつ試験中

Nginxのconfにlocation追加

golang

ちょっと違う書き方

サーバーの開始

func http.ListenAndServe(addr string, handler Handler) err
http.ListenAndServe(“:81”, nil)

第1引数にTCPアドレス
第2引数にHandlerを引数に受け取りサーバーを起動する。

Handlerというのは、http.Handlerインターフェースを実装していればいい。

ちなみに、内部でhttp.server.ListenAndServeを呼んでいる。http.server.ListenAndServeは内部でhttp.Server.Serveを呼んでいる。http.Server.Serveはforループでリクエストごとにgoroutineを立ち上げる。

http.Handle(r)とは

ServeHTTPメソッドを持つインターフェース。
ServeHTTPはリクエストとレスポンスが記述される。
type Handler interface { ServeHTTP(ResponseWriter, *Request) }

http.Handleとは

func Handle(pattern string, handler Handler)
URLとhttp.Handerを実装した構造体を受け取り、ルータに登録。

http.HandleFuncとは

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
URLとhttp.Handerを受け取り、ルータに登録。

HandleだとServeHTTPを定義しHandlerを実装した構造体を渡す必要があるが、HandleFuncの場合Funcのまま受け取れる。

http.HandleとHandleFuncについて

http内でDefaultServeMux(ServeMux)が定義されており、DefaultServeMux.Handler、DefaultServeMux.HandleFuncが呼ばれている。

http.ServerMuxとは

ServerMuxはURLとhandlerを登録しておく構造体。
ServeMux自体、ServeHTTPメソッドを実装している→Handler
mux := http.NewServeMux()
mux.Handle(“/echo”, echoHandler)

http.Handle(r)Funcとは

type HandlerFunc func(ResponseWriter, *Request)
func(ResponseWriter, *Request)の別名でServerHTTPが定義(実装)されている。

Handle(r)FuncとHandleFuncについて

そっくりで混乱するが、HandleFuncはURLとHandlerをServerMuxに登録する。Handle(r)Funcの方は、func(ResponseWriter, *Request)の別名でhttp.Handlerとして使える。

http.ServeMux.HandleFuncとは

URLとfunc(ResponseWriter, *Request)を受け取りルータに登録している

内部でfunc(ResponseWriter, *Request)をHandle(r)FuncにキャストしているHandleに登録している。

http.ServerMux.Handleとは

ServeMuxにURLとHandlerを登録する。

出力関係

Print
標準出力へ

Fprint
出力先を指定

Sprint
文字列で返す。

接尾のfはフォーマット

Apache設定

Ubuntuのインストール記事からApacheの箇所だけ抜出し。

インストール

sudo apt-get update
sudo apt-get install apache2

・起動
sudo /etc/init.d/apache2 start

・ファイアーウォール(ufw)の設定が必要なら、
sudo ufw app list (名前確認)
sudo ufw allow apache

設定関連

バージョン
apache2 -v

パス確認
apachectl -S

ロードモジュール
apachectl -M

設定ファイル

設定ファイルは、
/etc/apache2
の中にあるファイル。

***-enabled内の.confや.loadファイルを読み込む。
***-enabledは***-availableへのシンボリックリンクが基本。

/etc/apache2/apache2.conf
基本設定ファイル

/etc/apache2/mods-enabled/
/etc/apache2/mods-available/
モジュール(a2enmod, a2dismod)

/etc/apache2/sites-enabled/
/etc/apache2/sites-available/
サイト設定(a2ensite, a2dissite)

/etc/apache2/ports.conf
ポート番号

/etc/apache2/conf-enabled/
/etc/apache2/conf-available/
設定(a2enconf, a2disconf)

***

モジュールのテストをしてみる。

必要なモジュールをインストールすると、 設定ファイルは
/etc/apache2/mods-available
に書き込まれる。

書き込まれるのは、
モジュール名.load、モジュール名.conf
の2つ。

使えるモジュール一覧
apt search libapache2-mod
(apt-cache search libapache2-mod)

モジュールのインストール
sudo apt install libapache2-mod-xxx

インストール後、使いたいモジュールは、
sudo /usr/sbin/a2enmod xxx
/etc/apache2/mods-enabled に、mods-available への
シンボリックリンクを作ってくれる。

試しにPHPでテストしてみる。
sudo apt install libapache2-mod-php

/etc/apache2/mods-available
の中に
php7.2.conf
php7.2.load
が書き込まれた。
/etc/apache2/mods-enabled
の中にもavailableへの
php7.2.conf
php7.2.load
2つのリンクが作成された。

無効化
sudo /usr/sbin/a2dismod php7.2

ls /etc/apache2/mods-enabled | grep php
出力なし

有効化
sudo /usr/sbin/a2enmod php7.2

ls /etc/apache2/mods-enabled | grep php
php7.2.conf
php7.2.load

再起動
sudo /etc/init.d/apache2 restart

apache2.confについて

・DefaultRuntimeDir ${APACHE_RUN_DIR}
Base directory for the server run-time files

・PidFile ${APACHE_PID_FILE}
デーモンのプロセス ID をサーバが記録するためのファイル

・Timeout 300
各イベントについて、リクエストを失敗させるまでにサーバが 待つ時間を設定

・KeepAlive On
HTTP の持続的な接続を有効にする

・MaxKeepAliveRequests 100
持続的な接続上で許可されるリクエストの数

・KeepAliveTimeout 5
持続的な接続で次のリクエストが来るまでサーバが待つ時間

・User ${APACHE_RUN_USER}
The userid under which the server will answer requests

・Group ${APACHE_RUN_GROUP}
Group under which the server will answer requests

・HostnameLookups Off
クライアントの IP アドレスの DNS ルックアップを 有効にする

・ErrorLog ${APACHE_LOG_DIR}/error.log
サーバがエラーをログ収集する場所

・LogLevel warn
ErrorLog の冗長性を制御する

・IncludeOptional mods-enabled/*.load
・IncludeOptional mods-enabled/*.conf
Includes other configuration files from within the server configuration files

・Include ports.conf
サーバ設定ファイル中から他の設定ファイルを取り込む

<Directory /> … </Directory>
指定のファイルシステムのディレクトリとサブディレクトリとのみに 適用されるディレクティブを囲む

以下Directoryの中について。

・Options FollowSymLinks

Options xxx
ディレクトリに対して使用可能な機能を設定する

xxxの部分については以下。

None:何もなし。
All:MultiViews以外の機能が有効。Optionsを設定しない場合と同じ。
ExecCGI:cgiの実行を許可。
FollowSymLinks:シンボリックリンクをたどれる。
Includes:SSI の使用を許可。
IncludesNOEXEC:SSIを許可。SSIから外部cgiを呼び出すのは禁止。
Indexes:DirectoryIndexで指定したファイルが存在しない場合、一覧を表示する。
MultiViews:コンテントネゴシエーションを有効。
SymLinksIfOwnerMatch:シンボリックリンクのリンク先がシンボリックリンクと同じオーナーのある場合、みたどれる。

・AllowOverride None

AllowOverRide xxx
.htaccessで使用できるディレクティブを指定。

xxxの部分については以下。

None:.htaccess では何も設定できない。
All:.htaccess で設定可能なものは全て有効。
AuthConfig:認証関連のディレクティブの使用を許可。
FileInfo:ドキュメントタイプやドキュメントのメタデータを制御するディレクティブの使用を許可。
Indexes:ディレクトリインデックス関連のディレクティブの使用を許可。
Limit:アクセス制御関連のディレクティブの使用を許可。
Options:Optionsディレクティブの使用を許可。

・Require xxx

xxxの部分については以下。

Require all granted:全てのアクセスを許可。
Require all denied:全てのアクセスを拒否。
Require [not] env env-var [env-var]:指定した環境変数が定義されていれば(not指定時は環境変数が定義されていなければ)アクセスを許可。
Require method http-method [http-method]:Pメソッドが指定されたものである場合はアクセスを許可。
Require valid-user:有効なユーザーの場合はアクセスを許可。
Require ip xxx.xxxx.xxx.xxx:クライアントのIPアドレスが指定されたものである場合はアクセスを許可。

ここまでDirectoryの中について。

・AccessFileName .htaccess
リクエストを処理するとき、サーバはディレクトリに対して分散設定ファイルが有効になっていれば、そのドキュメントへのパス上にある全てのディレクトリから、ここで指定された名前の一覧の中で最初に見つかったファイルをそれぞれ設定ファイルとして読み込みます。

・<FilesMatch> … </FilesMatch>
正規表現にマッチするファイル名に適用される ディレクティブを囲む。

・LogFormat “%h %l %u %t \”%r\” %>s %O” common
LogFormat “フォーマット” “フォーマット名”

サイトの設定

正しく処理の流れとして、
sites-available/000-default.conf
がテンプレートなので、それをコピーして編集する。

000-default.conf
が有効になっているので以下で無効化。
sudo a2dissite 000-default.conf

コピーしたファイルを有効化。
sudo a2ensite xxx.conf

sites-available/xxx.confについて

<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
これが初期設定となっていた。

ちなみに、バーチャルホストの設定はなくてもOKなので、
apache2.conf
の中の、
IncludeOptional sites-enabled/*.conf
をコメントアウトして、apache2.confの中にDocumentRootを記入してもOK。

VirtualHost使う場合、
DocumentRoot,ServerNameが必須。

ここでは使っていないけど、複数のドメインを運用する場合、
ドメイン分のVirtualHostを作成し、ServerNameで指定する。
<VirtualHost *:80>
DocumentRoot /var/www/xxx
ServerName domain.com
ServerAlias www.domain.com
(ServerAliasでアクセスしてきたらServerNameへリダイレクトという感じ)

</VirtualHost>

アクセスの振り分けとしては、
・IPアドレス
・ポート番号
・ドメイン名(ServerName)
で振り分けることができる。
<VirtualHost addr:[port]></VirtualHost>

サブドメインを指定する場合、
<VirtualHost *:80>
DocumentRoot /var/www/xxx
ServerName sub.domain.com
ServerAlias www.sub.domain.com
</VirtualHost>

セキュリティ関連

/etc/apache2/conf-available/security.conf
には、もともと
ServerTokens OS
ServerSignature On
TraceEnable Off
とあった。

もともとのsecurity.confをバックアップし以下を追加。

バージョン情報を隠す(変更)
ServerTokens Prod
ServerSignature Off

トレースメソッドを無効化(そのままでOK)
TraceEnable Off

PHPのバージョンを隠す
Header unset X-Powered-By

ファイルの一覧を表示しない(/etc/apache2/apache2.confを更新)
<Directory /var/www/html>
Options -Indexes
</Directory>

リクエストを制限する(/etc/apache2/apache2.confを更新)
<Directory xxx>
Require method GET POST
</Directory>

他のサイトにframeで埋め込まれないように
Header append X-Frame-Options DENY

ダミーのVirtualHost(先頭に書く)
<VirtualHost *:80>
ServerName dummy
Redirect 404 /
</VirtualHost>

conf-availableの方がsites-availableより先に読み込まれるが、sites-availableにある<VirtualHost>…</VirtualHost>にはServerNameがなかったので、ダミーを作る場合、sites-availableにServerNameが必要。

HTTP_PROXYの書換え禁止
RequestHeader unset Proxy

ブラウザがXSSをブロック
Header set X-XSS-Protection “1; mode=block”

ブラウザがContent-Typeを無視することを禁止
Header set X-Content-Type-Options nosniff

リクエストボディのサイズ指定 (10MB)
LimitRequestBody 10485760

***

設定ファイルのエラーチェック
apachectl configtest

Invalid command ‘Header’, perhaps misspelled or defined by a module not included in the server configuration
というエラーがでたら。
sudo a2enmod headers
sudo /etc/init.d/apache2 restart

PHP関連

・MPM

apachectl -V
worker, preforkがあり基本preforkとなっている。
mod_phpはpreforkなので、workerにしたい場合、PHPはFastCGIで利用。

 

Apache+PassengerでRailsを動かす

passengerインストール(gem)

sudo gem install passenger

sudo /usr/local/bin/passenger-install-apache2-module
を実行する。(該当ファイルが見つからない場合。sudo find / -name “*passenger*” -type f)

最後に必要な追加が表示される。
sudo apt-get install libcurl4-openssl-dev
sudo apt-get install libcurl4-gnutls-dev
sudo apt-get install apache2-dev
sudo apt-get install libapr1-dev
sudo apt-get install libaprutil1-dev

表示されたとおり不足の機能をインストールして、もう一回以下を実行。
sudo /usr/local/bin/passenger-install-apache2-module

All goodと表示されるまで繰り返せばOKのハズだけど、今回は、
fatal error: openssl/pem.h: そのようなファイ ルやディレクトリはありません
と表示されてしまう。

必要な追加では表示されないが、opensshでエラーなので、
以下をインストールしてみる。
sudo apt-get install libssl-dev

インストールが無事終了すると、
LoadModule passenger_module /var/lib/gems/2.3.0/gems/passenger-5.1.2/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /var/lib/gems/2.3.0/gems/passenger-5.1.2
PassengerDefaultRuby /usr/bin/ruby2.3
</IfModule>
のように表示されるので、apacheの設定に追加する。

基本設定

もともとのDocumentRootは
/home/okamura/www
だったので、そこで
rails new test_app
を実行して新しいrailsのフォルダを作成してみた。

実体としては
/home/okamura/www/test_app
がrailsのプロジェクトフォルダとなる。

VirtualHostの項目で
DocumentRoot /home/okamura/www/test_app/public
として、開発なので以下を追加しておく。
RailsEnv development

これで問題なく動いた。

サブディレクトリで複数動かす場合

railsのpublicの実体が
/home/okamura/www/test_app/public
apacheのconfでのdocumentrootが
/home/okamura/www/test_app/public
とするのが基本。

サブディレクトリで複数のアプリを動かしたい場合。
apacheのconfでdocumentrootを
/home/okamura/www
にする。

RailsBaseURI /app1
RailsBaseURI /app2
を追加する。

railsのpublicの実体のシンボリックを作る。
sudo ln -s /home/okamura/ruby/asagao/public /home/okamura/www/app1
sudo ln -s /home/okamura/ruby/pico_planner/public /home/okamura/www/app2

apacheのconfはこんな感じ。
DocumentRoot /home/okamura/www
RailsBaseURI /app1
RailsBaseURI /app2
RailsEnv development

ApacheのCGIでRubyを呼び出す。

Apacheの設定

sudo find / -name 000-default.conf
で検索かけると2箇所ある。

/etc/apache2/sites-enabled/000-default.conf
/etc/apache2/sites-available/000-default.conf

設定を読み込まれているのは、enabledで、availableの
設定ファイルへシンボリックしている。

mods-enabledの中でシンボリックしているのは、
cgid.conf
cgid.load
だけ。

mods-availableの中にcgi関連は、
authnz_fcgi.load
cgi.load
cgid.conf
cgid.load
proxy_fcgi.load
proxy_scgi.load
だけ。

sites-availableを以下のように変更。
<Directory /home/okamura/www/>
Require all granted
AllowOverride All
Options +ExecCGI
AddHandler cgi-script .rb
</Directory>

CGI側(Ruby)

rubyのファイルに以下のように記述し、
chmod +x で実行権限をつければOK。

エラーの場合、
改行コードが違っていてハマッた。Winで作ってLinuxに転送の場合注意。

GETを受取たい場合

送信側(Form)

CGI(Ruby)

Apacheの設定、htaccessなど

Basic認証

.htaccessファイルを作成し、以下を記述。

AuthUserFile /home/okamura/.pwd

AuthName “please enter”

AuthType Basic

Require valid-user

.pwdの名称はなんでもいいが指定はフルパスにする。

一般的には.htpasswdとする。

htpasswd -c /home/okamura/.pwd taro

New password:xxx

Re-type new password:xxx

-cオプションがなくhtpasswdコマンドだけだと、追加、変更。-dオプションを付けるとと削除となる。

apache2ctl -M

有効なモジュールを確認できる。

sudo a2enmod rewrite

rewriteを有効化する。

/etc/apache2/apache2.conf

で、該当するDirectoryにAllowOverride allを追加する。

sudo /etc/init.d/apache2 restart

転送

301は恒久的(元のキャッシュが消える)な転送302(元のキャッシュが残る)は一時的な転送。

外部サイトに転送している設定。Rに数字をいれないと302転送。

RewriteEngine On

RewriteRule ^ http://start-affiliate-life.com [R,L]

メインディレクトリをサブに飛ばす設定。

RewriteEngine On

RewriteCond %{REQUEST_URI} !/w

RewriteRule ^(.*)$ /w/ [R,L]

RewriteCond が true の時 RewriteRuleが実行される。

RewriteCond %変数名(テスト文字列) 条件パターン(正規表現) [フラグ]。

PHP関連

変数登録の優先順位

variables_order = “EGPCS”

外部ホストへのアクセス

allow_url_fopen = off

エラーレポート

error_reporting = E_ALL & ~E_NOTICE & E_STRICT

E_NOTICEとE_STRICT以外は全てという意味 ~ は否定の意味

画面へエラーを表示

display_errors = off

エラーのログを出力(Windowsの場合はイベントログにエラーがいくらしい)

log_errors = On

error_log = file name

セーフモード

safe_mode_gid = On

セーフモードはファイルオープンはスクリプトと同じ所有者のファイルのみになる。

重要なのはセーフモードを使うときはスクリプトの所有者を一般ユーザーにしておくこと。

セーフモードはdlや()やshell_execが使えない。

exec,system,passthru,popenはsafe_mode_exec_dirで指定したディレクトリに制限される。

open_base_dir ファイル操作できるフォルダを限定。

disable_functions 使える関数を制限。