Quantcast
Channel: apache – softelメモ
Viewing all 68 articles
Browse latest View live

【apache】CacheLock On の効果は?

$
0
0

問題

CacheLock On にしたら、いいことあるんですか?

cache-lock-on

答え

キャッシュを有効にしているとき、キャッシュ作成中や、キャッシュ有効期限切れでキャッシュを再作成する必要があるタイミングで問題が発生する可能性があります。

キャッシュがまだないコンテンツ、キャッシュの有効期限切れのコンテンツにリクエストがあると、キャッシュが作成されますが、そのキャッシュ作成中にさらに立て続けにリクエストがあると、バックエンドに対して複数のリクエストが届いてしまうという問題が発生します。

その対策として、キャッシュを作成中であることを示すロックファイルを使って、後続のリクエストがバックエンドにアクセスするのを防ぐようにすることができます。

CacheLock の設定は、Apacheの設定ファイルでは、以下の3つで制御します。

CacheLock [ On | Off ]
CacheLockMaxAge [秒数]
CacheLockPath [/path/to/lock/directory]

設定例 キャッシュロック有効、待ち行列のタイムアウト15秒、ロックファイル置き場 /tmp/mod_cache-lock

CacheLock On
CacheLockMaxAge 15
CacheLockPath /tmp/mod_cache-lock

CacheLock は、デフォルトがOffなので、有効にする場合はOnを明示する。

CacheLockMaxAge は、バックエンドの処理が通常以上に遅いときなどに、接続したままいつまでも待たないように設定。

CacheLockPath のディレクトリは、手で作らなくても自動的に作られる。その中にディレクトリはたくさん作られるが、キャッシュのようにファイルは溜まらず、用が済むと通常は消えていく。


Windows環境でApacheが起動しなくなった

$
0
0

問題

突然、Windows環境のApacheが起動しなくなりました。

サービスで起動しようとしているのですが、イベントログに以下のエラーがありました。

Apache2.2 サービスは、サービス固有エラー ファンクションが間違っています。 で終了しました。

答え

他のソフトに80番ポートを先に使われている可能性がある。

80番ポートを使っているプロセスを確認すると、以下のように出てくれば、何かが起動して80番ポートをLISTENしていると見られる。管理者権限がなかったら、コマンドは netstat -ano でもよい。

>netstat -anob

アクティブな接続

  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:80             0.0.0.0:0              LISTENING       4
 所有者情報を取得できません
(略)
  TCP         [::]:80                [::]:0                 LISTENING       4
 所有者情報を取得できません
(略)

ついでに、この状況であれば、telnetで80番ポートに話しかけてみると、何か返ってくるでしょう。

>telnet localhost 80
(レスポンスがあるかどうか確認したいだけなので、aaa など適当に入力して、Enter、Enter 入力)

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 21 Dec 2015 02:57:01 GMT
Connection: close
Content-Length: 326

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
<HTML><HEAD><TITLE>Bad Request</TITLE>
<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>
<BODY><h2>Bad Request - Invalid Verb</h2>
<hr><p>HTTP Error 400. The request verb is invalid.</p>
</BODY></HTML>

なんだか Microsoft の仕業っぽいレスポンスです。

その線で調べていくと、IISを有効化したつもりはなくても、Windows10にアップグレードしたら有効化されていたり、WebMatrix など何かと一緒に有効化されて稼働していることがあるらしいです。

IIS(インターネットインフォメーションサービス)っぽいということまで分かれば、あとは、サービスを停止するなりWindowsの機能の有効化で無効にしたり、IIS管理マネージャーもインストールして停止するなどの対応となります。

80番ポートを使っている他のソフトがなくなれば、80番ポートを使うApacheが起動できます。

【WordPress】Apacheのmod_cacheで高速化する

$
0
0

問題

mod_cacheを使って、WordPressを高速化したいです。

できますか。

wordpress

答え

利用することは可能。

mod_cacheを使うと、運用時にいろいろと気を遣う必要は出てくる。

  • 投稿を編集しても、キャッシュが更新されるまで、即座に反映されない。
  • 編集中に、うっかり記事のパーマリンクにアクセスすると、キャッシュが作成される。
  • 編集中の内容を確認するときは必ずプレビューで。

など。

そのあたり承知の上で適用するのなら、かなり高速化するのでとても良い。

1、WordPress側の対応(重要)

WordPressが作成するパーマリンクの設定(.htaccessのrewriteの設定)は、mod_cacheに適していない。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

mod_cache は、rewrite後のURLでキャッシュを作るので、すべてのリクエストが /index.php にrewriteされると、リクエストされたURLごとにキャッシュを作れない。(最初にアクセスされたページのキャッシュが /index.php のキャッシュとなり、すべてのページの表示がこの内容になる)

URLペースのキャッシュであるmod_cacheをを利用するなら、以下のように、rewrite後のURLがすべて同じにはならないようにする。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>

2、Apache側の設定

mod_cacheの設定は特に難しくない。VirtualHostの中などに、以下の記述を追加する。

CacheIgnoreCacheControl On
CacheIgnoreNoLastMod On
CacheIgnoreHeaders Set-Cookie
CacheEnable disk /
CacheRoot /var/cache/mod_cache
#CacheLock On
#CacheLockMaxAge 15
#CacheLockPath /tmp/mod_cache

WordPressが一番上の階層に設置してあるなど、Webサイト全体でキャッシュが有効でよかったら、CacheEnable disk / で。WordPressがあるディレクトリの下に設置してあるなどの場合は、CacheEnable disk /blog など、パスを指定。

CacheRoot はキャッシュが作られる場所。Apache実行ユーザーが書き込める場所を用意してあげる。

CacheLock On は、意味が分かるなら、必要なら、コメントを外して有効にする。

設定に問題ないことを確認して、

# apachectl -t
Syntax OK

Apache再起動。

# service httpd restart

もしくは

# service httpd graceful

3、キャッシュの定期的な削除

キャッシュの削除は htcacheclean。

cronで削除するなら以下のような設定で。

# 毎時0分に、100MB以下になるように、キャッシュ削除を実行
0 * * * * /usr/sbin/htcacheclean -r -l 100M -p /var/cache/mod_cache

※htcacheclean を常駐させる方法もある。

Apacheを別ポートで起動して、php7を使えるようにする

$
0
0

問題

既存のApacheを流用して別ポートで起動して、php7を使えるようにしたいです。

http://192.0.2.123/ → php5(モジュール版)
http://192.0.2.123:8000/ → php7(モジュール版)

答え

ポートを変えてしまえば、片方はfastcgi版などしなくてよいのがいいですね。

以下、CentOSにて。

1.Apacheインストール

apache、php5は、標準のリポジトリからのRPMでインストールしてあるものとする。

yum install httpd php

2.Apacheを別ポートで起動する設定

1) ServerRootをコピー

cp -pr /etc/httpd /etc/httpd-php7

2) logs(ログファイル置き場), run(pidファイルなどが入る)のディレクトリ作成

mkdir /var/log/httpd-php7
mkdir /var/run/httpd-php7

3) シンボリックリンクを修正

cd /etc/httpd-php7
rm logs
rm run
ln -s ../../var/log/httpd-php7 logs
ln -s ../../var/run/httpd-php7 run

4) httpd.conf を修正

Listen 80 → 8000
ServerName 192.0.2.123:80 → 192.0.2.123:8000
ServerRoot /etc/httpd → /etc/httpd-php7
(PidFile は run/httpd.pid と指定されていたら、シンボリックリンクを修正してあるのでそのままでよい。)

3.php7(モジュール版)を用意

–with-apxs2 付きで自前でコンパイル。

wget http://jp2.php.net/get/php-7.0.4.tar.xz/from/this/mirror -O php-7.0.4.tar.xz
xz -d php-7.0.4.tar.xz
tar -xf php-7.0.4.tar
cd php-7.0.4
./configure --with-apxs2 --prefix=/usr/local/php/7.0.4 --以下-オプションは-お好みで
make
make install

make install すると、最初にインストールしてある方の /etc/httpd/conf/httpd.conf が書き換えられてしまうので、LoadModule が追加されていたらコメントアウトする。

LoadModule php7_module        /usr/lib64/httpd/modules/libphp7.so
↓
#LoadModule php7_module        /usr/lib64/httpd/modules/libphp7.so

4.別ポートで起動するApacheでphp7を実行できるようにする

別ポート用に用意した /etc/httpd-php7 の方で、設定変更。

yum install php していたら、php5 の設定が conf.d/php.conf に書かれていると思うので、conf.d/php.conf の内容を削除して、php7 の LoadModule を追加する。

LoadModule php7_module modules/libphp7.so
<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

5.別ポートでApache起動

とりあえずは以下のようにconfファイルを指定して起動すればOK。

/usr/sbin/httpd -f /etc/httpd-php7/conf/httpd.conf -k start

サービスに登録したり、自動起動スクリプトをいじったりをしてもよい。

【apache】特定のディレクトリを除外してリダイレクトしたい

$
0
0

問題

Webサイトを移転したので、基本的には example.com → example.jp のリダイレクトでよいのだけど、
特定のディレクトリ(URL)の場合は、旧ドメインの旧URLのままアクセス可能にしたい。

答え

よくあるドメイン変更の移転の場合は、.htaccess や httpd.conf にて、以下のように設定すると思う

Redirect permanent / https://example.jp/

Redirect を使うと、Redirect 設定の優先順位が高いために、除外のための他の追加設定ができないので、

特定のURLは除外したい場合などには、Rewrite を使うとよい。

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !(^/ex/)
RewriteRule ^(.*)$ https://example.jp/$1 [R=301,L]

Let’s encrypt を使う(debianの場合)

$
0
0

問題

Let’s encrypt でサーバー証明書取得、簡単ですか。

le-logo-standard

答え

簡単でした。

以下、Debianの場合。

1、backports を有効にする

/etc/apt/sources.list に、以下を追記

deb http://ftp.debian.org/debian jessie-backports main

2、certbot をインストール

apt-get install python-certbot-apache -t jessie-backports

3、さっそく証明書取得

certbot --apache

設定は自分でおこなう場合は、

certbot --apache certonly

certbot --apache では、apacheの設定が自動的に書き換えられたりするので、初めての場合は、期待した通りになっているか実行後要確認。

4、90日の更新を自動化

certbot renew --dry-run でうまく動けば、crontab -e で以下を追加。1日2回実行が良いらしい。

0 0,12 * * * /usr/bin/certbot renew --quiet

数分で証明書導入まで完了、その後の自動化も可能で、ドメイン認証だけあればよければ、とても簡単だった。

【apache】 ProxyPreserveHost を On にするとはまる(こともある)

$
0
0

問題

リバースプロキシを設定していて、以下のようにしているのですが、

ServerName example.com
ProxyPreserveHost On
ProxyPass /xxxx/ http://192.168.123.123/
ProxyPassReverse /xxxx/ http://192.168.123.123/

末尾スラッシュなしでディレクトリへのアクセスがあったときなどに、どうも想定外のURL(上の階層)にリダイレクトされます。

https://example.com/xxxx/images
↓
http://example.com/images/

答え

ProxyPreserveHost は、デフォルト Off で、公式ドキュメントには以下の記述があります。

このオプションは通常は Off に設定してください。 ほとんどの場合、これは大量の名前ベースのバーチャルホスティングを行なっていて、 元々の Host ヘッダをバックエンドサーバが解釈する必要のあるときのような、 特別な設定が必要な場合にのみ有用です。

ProxyPreserveHost On が有用なのは特別な場合と書かれている通り、安易に「アクセスされた時のホスト名をバックエンドに渡したいな…」と思って On にすると、困った問題が発生する場合があります。

問題の設定例だと、バックエンドにホスト名が伝わり、バックエンドがUseCanonicalName Off(デフォルト)であれば、以下のように、バックエンドから返ってくるリダイレクト先URLがバックエンドに伝えたホスト名になり、ProxyPassReverse の設定にもマッチせず、変換がかからないままブラウザに返されることになる。https:// が http:// に変わってしまっているのも問題でしょう。

proxy-preserve-host-on

ProxyPreserveHost Off であれば、素直な動きで、設定どおり変換が入り、特に問題ないと思う。

proxy-preserve-host-off

問題があるとすれば、バックエンド側がホスト名を期待しているとか、IPアドレスでは困るといった場合だが、調整可能な問題だと思います。

まとめ

本当に必要でない限りは ProxyPreserveHost Off で何とかするのが、素直な動きをする。

【Apache】LDAP連携のベーシック認証

$
0
0

問題

LDAP(ActiveDirectory)連携のベーシック認証ってできますか?

答え

httpd.conf か .htaccess にちょっと設定を書くだけでできる。簡単。

● LDAPのみ

AuthName "User/Password"
AuthType Basic
AuthBasicProvider ldap
AuthzLDAPAuthoritative off
AuthLDAPURL ldaps://ldap.example.jp/ou=staff,dc=example,dc=jp?uid
AuthLDAPBindDN "cn=admin,dc=example,dc=jp"
AuthLDAPBindPassword "bind_password"
require valid-user

● LDAPして、ダメだったときは.htpasswdする場合(ActiveDirectory使用時)

AuthName "Please enter your ID and password"
AuthType Basic
AuthBasicProvider ldap file
AuthLDAPBindAuthoritative on
AuthLDAPUrl "ldap://192.168.xxx.xxx:389/ou=softel,dc=softel,dc=local?sAMAccountName?sub?(objectClass=*)"
AuthLDAPBindDN xxxxxxxx@softel-domain
AuthLDAPBindPassword "xxxxxxxx"
Require ldap-attribute objectClass=person
AuthUserFile /home/www/xxxx/yyyy/.htpasswd
AuthGroupFile /dev/null
Require valid-user

● LDAPして、ダメだったときは.htpasswdするけど社内IPはベーシック認証不要にする場合

AuthName "Please enter your ID and password"
AuthType Basic
AuthBasicProvider ldap file
AuthLDAPBindAuthoritative on
AuthLDAPUrl "ldap://192.168.xxx.xxx:389/ou=softel,dc=softel,dc=local?sAMAccountName?sub?(objectClass=*)"
AuthLDAPBindDN xxxxxxxx@softel-domain
AuthLDAPBindPassword "xxxxxxxx"
Require ldap-attribute objectClass=person
AuthUserFile /home/www/xxxx/yyyy/.htpasswd
AuthGroupFile /dev/null
Require valid-user
Satisfy Any
Order Allow,Deny
Allow from 123.456.789.000

● ユーザーが入力したID、パスワードでbindする方式もあるらしい

省略

以下のモジュールが有効なこと。

LoadModule ldap_module modules/mod_ldap.so
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so

他に使える設定項目。

LDAPVerifyServerCert Off   #オレオレ証明書でエラーにしない
LDAPOpCacheTTL 600         #LDAP問い合わせをキャッシュする

さくらのレンタルサーバーのSNI SSLで常時SSL化するときの WordPressの.htaccess

$
0
0

問題

さくらのレンタルサーバーでWordPressを稼働させていまして、SNI SSLで、常時SSL化したいです。

http → https のリダイレクトはどうしたらよいですか。

さくらのレンタルサーバーでWordPressの常時SSL化(SNI版)

答え

最初は以下のような状態だとしたら、

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

以下のように追記。


SetEnvIf REDIRECT_HTTPS (.*) HTTPS=$1

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{ENV:HTTPS} !on
RewriteCond %{REQUEST_URI} !^/wp-cron.php$
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>


# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

メモ

SNIではないときは、上に追記する内容は、これでよいらしい。

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

参考: さくらのレンタルサーバ 簡単SSL化プラグイン

【Apache】PUTリクエストが 405 Method Not Allowed になる

$
0
0

問題

HTMLファイルや画像ファイルのURLに、PUTリクエストを送ると、405 Method Not Allowed になるのですが、そういうものなのですか?

$ curl http://localhost/test/index.html -X PUT
$ curl http://localhost/readme.txt -X DELETE

→ 405 Method Not Allowed

apache HTTP method

答え

特に指定がない場合、デフォルトのハンドラー(default_handler())が処理しますが、apacheのソースを見ると、default_handler()は、GETメソッドとPOSTメソッド(とOPTIONS)以外は、HTTP_METHOD_NOT_ALLOWED(405 Method Not Allowed)か HTTP_NOT_IMPLEMENTED(501 Not Implemented)を返しています。

phpのハンドラーなど、PUTメソッドでもHOGEメソッドでも受け付けるハンドラーに処理させる設定になっていればまた結果が違いますが、デフォルトのハンドラーが処理すれば 405 Method Not Allowed などになります。

$ curl http://localhost/test/index.php -X HOGEHOGE

→ 200 OK でレスポンスが返ってくるし、php側でHOGEHOGEメソッドだった場合の処理を書くこともできる

PUTやDELEETで 405 Method Not Allowed にしたくない、どこかしらで処理をしたいのであれば、
Scriptディレクティブで設定するのが簡単です。

&glt;Directory /var/www/test>
    Script PUT /put.php
    Script DELETE /delete.php
    Script HOGE /hoge.php
&glt;/Directory>

Apache mod_proxy_fcgiで複数のバージョンのphpを動かす

$
0
0

問題

Apache1つで複数のバージョンのphpを動作させたいです。

答え

CentOS6で、php-fpmでたくさん動かす例。

yumで一通り入れる。apacheは2.2が入る。

yum install httpd php (など)

epelなどからもしくはRPMを持ってくるもしくは自分でコンパイルして mod_proxy_fcgi を追加する。

yum install mod_proxy_fcgi
自分でコンパイル → https://github.com/ceph/mod-proxy-fcgi

phpをコンパイルする。

# ./configure --prefix=/usr/local/php/7.2.6 --enable-fpm (+ その他オプション)
# make
# make install

php-fpmの設定。複数稼働させるならポートを変えること。9000、9001、9002…。

# cp /usr/local/php/7.2.6/etc/php-fpm.conf.default /usr/local/php/7.2.6/etc/php-fpm.conf
# cp /usr/local/php/7.2.6/etc/php-fpm.d/www.conf.default /usr/local/php/7.2.6/etc/php-fpm.d/www.conf

# vi /usr/local/php/7.2.6/etc/php-fpm.d/www.conf
[www]
...
listen = 127.0.0.1:9000 ← これ
...

php-fpm 起動。

# /usr/local/php/7.2.6/sbin/php-fpm
# /usr/local/php/5.6.36/sbin/php-fpm
# /usr/local/php/5.5.30/sbin/php-fpm

apacheのVirtualHostなどに設定追加

<VirtualHost *:80>
ProxyPassMatch ^/php7/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9072/home/apache/vhosts/default/www/php7/$1
ProxyPassMatch ^/php56/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9056/home/apache/vhosts/default/www/php56/$1
ProxyPassMatch ^/php55/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9055/home/apache/vhosts/default/www/php55/$1
ProxyPassMatch ^/php54/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9054/home/apache/vhosts/default/www/php54/$1
</VirtualHost>

ポート番号を変える方式も便利。

<VirtualHost *:8072>
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9072/home/apache/vhosts/default/www/$1
</VirtualHost>
<VirtualHost *:8056>
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9056/home/apache/vhosts/default/www/$1
</VirtualHost>
<VirtualHost *:8055>
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9055/home/apache/vhosts/default/www/$1
</VirtualHost>

メモ

Apache2.4.10以降は以下の書き方ができる。可能ならこちらがおすすめ。

<FilesMatch \.php$>
    SetHandler "proxy:fcgi://127.0.0.1:9000"
</FilesMatch>

証明書取得時のファイル認証で wwwあり、なし、両方に対応する

$
0
0

問題

サーバー証明書取得でファイル認証したいのですが、常時SSLのWebサイトのため、wwwあり / なし、http / https、何でアクセスしても httpsのwwwありにリダイレクトされます。

FujiSSLなどよくあるパターンでは、www.example.com で申請すると、 www.example.com と example.com どちらでも使えるようにしてくれるのですが、そのためには、www.example.com と example.com の両方で認証用のファイルにアクセス可能である必要があります。

リダイレクト設定をどのように変更するとよいでしょうか。

答え

ファイル認証は、対象のドメインのWebbサイトに /.well-known/pki-validation/fileauth.txt を置いて、外部から確認可能かどうかで認証する方式ですね。

Rewriteで以下のようにしている場合は、

RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www.example.com)(.*)$
RewriteRule ^/(.*) https://www.example.com/$1 [NE,L,R=301]

/.well-known/pki-validation/ へのアクセスは対象外にすると、Rewriteによるリダイレクトを回避できます。

RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www.example.com)(.*)$
RewriteCond %{REQUEST_URI} !^/.well-known/pki-validation/
RewriteRule ^/(.*) https://www.example.com/$1 [NE,L,R=301]

【Apache】LocationMatchで否定条件

$
0
0

問題

LocationMatchで「URLがマッチしないとき」の条件を作りたいです。

答え

/hoge のときは、以下の書き方でできる。

<LocaitonMatch /(?!hoge)>
  # xxxxxx
</LocationMatch>

条件に / スラッシュが含まれるときはこちら。

<LocaitonMatch ^(?!(/hoge/fuga)$)>
  # xxxxxx
</LocationMatch>

リダイレクトしたいだけの時などなら、Rewriteを使ってもいいと思います。

【WordPress】キャッシュ有効期限を記事と記事一覧で切り替える

$
0
0

問題

WordPressの記事にExpireヘッダ、Cache-Controlヘッダを付与したい。

その際、記事ページは長めの有効期限、トップページや記事一覧ページは短めの有効期限にしたい。

答え

Apacheに以下のような設定をしておくと、普段はそちらが適用される。

例)画像などは1週間キャッシュしてよい。HTMLは1日キャッシュしてよい。

        ExpiresActive On
        ExpiresByType text/html "access plus 1 days"
        ExpiresDefault "access plus 1 weeks"

そのうえで、WordPressから必要な時だけヘッダを出力する。

コンテンツの種類に応じてヘッダを出し分けたい場合は、’template_redirect’フックがちょうどよかった。

/**
 * 一覧系(単体記事以外)のキャッシュ時間を短くする
 */
function my_header_cache_control() {
    if (is_home() || is_front_page() || is_archive()) {
        header('Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 600 ) . ' GMT');
        header('Cache-Control: max-age=600, public');
age=0');
    }
}
add_action('template_redirect', 'my_header_cache_control');

「600」と書いている箇所は、希望の時間(秒数)に応じて書き換える。

Cache-Controlだけだと Apacheも Cache-Controlを出力してくるので、Expireとセットで出力する。そうすると、Apacheは Cache-Control: max-age=~ を出力してこない。

【Apache】FollowSymLinks は有効にしたほうがパフォーマンスが上がる

$
0
0

問題

FollowSymLinks って有効にしておいたほうがいいんですか?

答え

こちらに書いてある

http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks

FollowSymLinks and SymLinksIfOwnerMatch

Options FollowSymLinks を設定していない場合、または Options SymLinksIfOwnerMatch いる場合、Apacheはシンボリックリンクを調査するためにシステムコールを必要とする。(ディレクトリ、ファイルごとに1回発生する)

例えば、以下の設定の場合

DocumentRoot "/www/htdocs"
<Directory "/">
  Options SymLinksIfOwnerMatch
</Directory>

/index.html にリクエストがあると、Apache は lstat(2) を /www, /www/htdocs,  /www/htdocs/index.html に対して実行する。これらのlstatsの結果はキャッシュされない。そのためこの処理はリクエストの都度発生する。

もしシンボリックリンクのチェックを本当に必要としているならば、以下のようにするとよい:

DocumentRoot "/www/htdocs"
<Directory "/">
  Options FollowSymLinks
</Directory>

<Directory "/www/htdocs">
  Options -FollowSymLinks +SymLinksIfOwnerMatch
</Directory>

これで少なくともDocumentRootまではシンボリックリンクのチェックを回避できる。DocumentRoot外への Alias や RewriteRule があれば、同様の設定を追加すること。

シンボリックリンクのチェックをなくして、最大の性能を得るには、あらゆるディレクトリに FollowSymLinks を設定し、SymLinksIfOwnerMatch は設定しないこと。


【Apache2.2】起動時にapr_sockaddr_info_get() failed が発生する

$
0
0

問題

apache をrestart したり configtest したりすると、以下のエラーが発生します。

$ apachectl -t
httpd: apr_sockaddr_info_get() failed for xxxxxxxx
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
Syntax OK

答え

ServerName が設定されていないため。

httpd.conf などで、以下のように適当な名前を付けると出なくなる。

$vi /etc/httpd/conf/httpd.conf
ServerName localhost:80

Apache2.4のアクセス制御はRequireに統一するといい

$
0
0

問題

Apache2.2から2.4への移転で、元の .htaccess のIP制限やベーシック認証を持ってきたのですが、なんだか思ったように設定しづらいです。

答え

古い .htaccess だと、Order、Allow、Deny、Satisfy などを使って書かれていると思う。

Order Deny,Allow
Deny from all
Allow from xxx.xxx.xxx

AuthType Basic
AuthUserFile /var/www/example.com/.htpasswd
AuthName "auth"
require valid-user

Satisfy any

Apache2.4 でこれらがまだ使えるのは、互換性のために用意された mod_access_compat モジュールのおかげ。

# apache2ctl -M
Loaded Modules:
 core_module (static)
 ...
 ...
 access_compat_module (shared) ← これ
 ...
 ...

上の階層に .htaccess で Satisfy any など書かれていると、影響を受けて思ったような設定が難しくなる場合がある。

互換性モジュールのおかげで古い書き方がまだ使えるが、廃止していくとよい。

また、Apache2.4 のRequireは、より具体的なDirectoryや.htaccessでの設定があるとデフォルトではそちらで上書きされていくので、完全に Require で書き直したほうがすっきりする。

例)
/ は制限なし
/test/ はIP制限したい
/test/private/ はベーシック認証したい
→ それぞれの階層で Require で設定するだけ

# httpd.conf か / の .htaccess
Require all granted
# /test/ の .htaccess
Require ip xxx.xxx.xxx.xxx
# /test/private/ の .htaccess
AuthType Basic
AuthUserFile /var/www/example.com/.htpasswd
AuthName "auth"
Require valid-user

Apache2.4 のRequireは、いろんな表現もできるようになっているので、今まで複雑に書いていた設定が簡単に書ける。

例)プロキシ経由するので X-Forwarded-For を見たい。 SetEnvIf して環境変数をセットしてどうのこうの……

Require expr "%{HTTP:X-Forwarded-For} in { 'xxx.xxx.xxx.xxx', 'yyy.yyy.yyy.yyy' }"

もちろん SetEnvIf もできる。

SetEnvIf X-Forwarded-For xxx.xxx.xxx.xxx allowed_ip
SetEnvIf X-Forwarded-For yyy.yyy.yyy.yyy allowed_ip
Require env allowed_ip

でも Require expr だと IP を CIDR で書けたり、複数キーワードを in で列挙したりできるので便利。

https://httpd.apache.org/docs/2.4/ja/expr.html → ipmatch

AND条件は <RequireAll></RequireAll> で囲む。

例)IP制限なおかつベーシック認証

<RequireAll>
  Require ip xxx.xxx.xxx.xxx
  Require valid-user
</RequireAll>

デフォルトは OR扱いなので以下はどちらも「~~ または ~~」

Require ip xxx.xxx.xxx.xxx
Require valid-user
<RequireAny>
  Require ip xxx.xxx.xxx.xxx
  Require valid-user
</RequireAny>

古い書き方(Allow、Denyなど)を混ぜなければ、単純に下の階層の Require で上書きしていけるので、とても分かりやすくなる。

【Apache】プロキシで特定のパスだけ除外

$
0
0

問題

全体的に / をプロキシしていいのですが、特定のパスだけしないでほしいです。

例) /.well-known/ だけ除外

答え

よくあるプロキシ設定

<VirtualHost *:443>
    # 略
    ProxyPass / http://192.0.2.123/
    ProxyPassReverse / http://192.0.2.123/
    # 略    
</VirtualHost>

特定のパスを除外する例

<VirtualHost *:443>
    # 略
    ProxyPass /.well-known !

    ProxyPass / http://192.0.2.123/
    ProxyPassReverse / http://192.0.2.123/
    # 略    
</VirtualHost>

proxyしないで別の場所に置いたファイルを見せるようAlias設定する例

<VirtualHost *:443>
    # 略
    ProxyPass /.well-known !
    Alias /.well-known /var/www/html/.well-known

    ProxyPass / http://192.0.2.123/
    ProxyPassReverse / http://192.0.2.123/
    # 略    
</VirtualHost>

CentOS9のapacheで Let’s Encrypt 使いたい

$
0
0

問題

CentOS 9 Stream で Let’s Encrypt 使おうとしたら certbotコマンドでエラーになりました。

# certbot certonly --apache
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Error in checking parameter list:
The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError('Apache is unable to check whether or not the module is loaded because Apache is misconfigured.')
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

答え

–apache するとダメだが、自分でオプションを指定すれば実行できて、サーバー証明書を取得できる。

certbot certonly --webroot -w /ドキュメントルート -d ドメイン名

取得後は、certbot renew もできた。

メモ

certbotのオプション

Options:
-n: Not interactive
--webroot: Place files in the document root of an already running server
-w: The document root (where to place the files)
-d: The domain
-d: Another domain

opensslコマンドで秘密鍵と証明書の組み合わせの検証をする

$
0
0

問題

サーバー証明書を更新するとき、

秘密鍵作成 → CSR作成 → 証明書取得 の流れとなりますが、

複数のドメインで並行して作業しているときに取り違えたりしないように、秘密鍵と証明書のペアが間違っていないか確認方法はありますか?

答え

下記のコマンドを実行し、それぞれで出力される[Modules]部分が一致することを確認します。

md5ハッシュにすると確認しやすい。

証明書(CRT)

openssl x509 -noout -modulus -in xxxxxxxxxx.crt | openssl md5

署名要求(CSR)

openssl req -noout -modulus -in xxxxxxxxxx.csr | openssl md5

秘密鍵(KEY)

openssl rsa -noout -modulus -in xxxxxxxxxx.key | openssl md5

同じハッシュが得られれば組み合わせは合っている。

Viewing all 68 articles
Browse latest View live