Hatena::ブログ(Diary)

とあるプログラマの日記 @s025236 RSSフィード Twitter

2012-03-07

僕が考えた最強のサーバ設定

いつの間にかさくらのVPSの標準OSがCentOS6になってたので設定を見直してみました。
月額980円/月から利用でき、2週間のお試し期間もあるのでこれを機会にサーバ設定に足を踏み入れてみてはどうでしょう?
慣れると10分くらいでウェブサーバが立ち上げれるようになります。

すみません。こんなに多くの人が見てると思わなかったんです。
お一人様サーバ向けのつもりで書いてます。
タイトルもタグもネタだったのにツッコまれまくりで恥ずかしい…

公開鍵登録しよう

どうせ自分しか触らないなしrootで作業しちゃってもいいんじゃない?
リブート(またはsshのrestart)以降秘密鍵がないとsshでログイン出来なくなるので気をつけてください。

mkdir ~/.ssh/
touch ~/.ssh/authorized_keys
chmod 700 ~/.ssh/
chmod 600 ~/.ssh/authorized_keys
echo 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEA5BqkP+ToroYtzOhnZ2aOJj8WqUpRcQRy/D2ojlPsQutM9Pqfo3qI+75iLpTAAkt+X0RlSBNFLfLsDgfV45IWS/5jv7CKLF/AAIU8Ke5wKVXZrC1LkZ7HfnluALhepUkeB3ilrhFQS+qeS8LHw2s2C2Ig/bGj8lXuEyt93aSREIU= makoto@2ch.to' >> ~/.ssh/authorized_keys
echo 'OPTIONS="-o PermitRootLogin=without-password -o GSSAPIAuthentication=no -o PasswordAuthentication=no"' >> /etc/sysconfig/sshd

※公開鍵は自分のに書き変えてね

id:itochan315さんから
普段からrootで作業しないのには誤操作防止の意味もあるのに、必要な時にsudoすればいい話ですよ。。
と指摘を頂きました。
個人的にはお一人様サーバだとsudoは形骸化してしまってると思ってます。

やっぱ日本人だし日本語だよね

echo 'LANG="ja_JP.UTF-8"' >> /etc/sysconfig/i18n

いらない子

yum -y remove '*.i[3-6]86'
yum -y remove mlocate cups dhclient kudzu wireless-tools
chmod -x /etc/cron.daily/makewhatis.cron
chkconfig cpuspeed off

IPv6…なにそれ美味しいの?

echo 'IPV6_DEFAULTDEV=tun6to4' >> /etc/sysconfig/network
echo 'IPV6INIT=yes' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'IPV6TO4INIT=yes' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'IPV6TO4_RELAY=192.88.99.1' >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'tun6to4 2000::/3' >> /etc/sysconfig/static-routes-ipv6
echo 'IPV6TO4_IPV4ADDR='`/sbin/ifconfig eth0 |grep 'inet addr:' | awk '{print \$2}' | sed -e 's/addr://g'` >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo 'UseDNS no' >> /etc/ssh/sshd_config

アクセス時間なんかいらなくね?

(2012/03/07 16:10 修正)
HDD遅いしイジメ良くない。noatimeをつけよう。
id:sh2さんから、はてなブックマークで
RHEL 6系はrelatimeが導入されたのでnoatimeは設定しなくていいはず。」
という指摘を頂きました。(参考)
CentOS5からの惰性で書いててすみませんでした。

漏れまくりだけどファイアーウオール

どうせ不要なサービスとか動かさないしぃとかいわないで一応default dropで設定します。
/etc/sysconfig/iptablesと/etc/sysconfig/ip6tablesを書き換えます。
IP指定がなければ同じ内容で良いみたい。

######################################################################
# makoto@2ch.to
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
######################################################################
# ループバック/ICMP/確立済みの接続
-A INPUT   -i lo   -j ACCEPT
-A OUTPUT  -o lo   -j ACCEPT
-A INPUT   -p icmp -j ACCEPT
-A OUTPUT  -p icmp -j ACCEPT
-A INPUT   -p ipv6 -j ACCEPT
-A OUTPUT  -p ipv6 -j ACCEPT
-A INPUT   -p ipv6-icmp -j ACCEPT
-A OUTPUT  -p ipv6-icmp -j ACCEPT
-A INPUT   -m state --state RELATED,ESTABLISHED -j ACCEPT
-A OUTPUT  -m state --state RELATED,ESTABLISHED -j ACCEPT
######################################################################
# OUTPUT
-A OUTPUT -m state --state NEW -p tcp --dport ssh           -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport smtp          -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport domain        -j ACCEPT
-A OUTPUT -m state --state NEW -p udp --dport domain        -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport http          -j ACCEPT
-A OUTPUT -m state --state NEW -p udp --dport ntp           -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport https         -j ACCEPT
-A OUTPUT -m state --state NEW -p tcp --dport mysql         -j ACCEPT
#↓memcached
#-A OUTPUT -m state --state NEW -p tcp --dport 11211         -j ACCEPT
######################################################################
# 公開ポート 必要なこだけコメントを外すこと
#-A INPUT -m state --state NEW -p tcp --dport smtp          -j ACCEPT
#-A INPUT -m state --state NEW -p tcp --dport domain        -j ACCEPT
#-A INPUT -m state --state NEW -p udp --dport domain        -j ACCEPT
 -A INPUT -m state --state NEW -p tcp --dport http          -j ACCEPT
#-A INPUT -m state --state NEW -p tcp --dport https         -j ACCEPT
#↓可能ならSAFTYを利用する
#-A INPUT -m state --state NEW -p tcp --dport ssh    -j ACCEPT
######################################################################
# 信頼できるIP
-N SAFETY
-A SAFETY -m state --state NEW -p tcp --dport ssh           -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport smtp          -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport http          -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport https         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport mysql         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport 11211         -j ACCEPT
-A SAFETY -m state --state NEW -p tcp --dport postgres      -j ACCEPT
-A INPUT -s 自分ちの固定IP -j SAFETY
COMMIT

※CentOS5系だとip6tablesでRELATED,ESTABLISHEDが使えないので注意が必要です。

nginxさんは早くてかっこいい

SSLv2有効にしてるサイトが多くてビビる。
静的コンテンツならnginxで返してそれ以外はバックエンドに送る設定が多いけどちょっとひねってみた。
ファイルがあればnginxが返すけど特定の拡張子はバックエンドへ送る。not foundも裏に送る。

yum -y install nginx
chkconfig nginx on
cat > /etc/nginx/nginx.conf

######################################################################
# (c)makoto@2ch.to
user nginx;
worker_processes  2;
pid /var/run/nginx.pid;
error_log  /var/log/nginx/error.log;
events { worker_connections 1024; }
######################################################################
#
http {
  ####################################################################
  # 上位サーバの設定
  upstream backend {
    server 127.0.0.1:8080;
  }
  ####################################################################
  # 基本設定
  include           mime.types;
  sendfile          on;
  tcp_nopush        off;
  server_tokens     off;
  keepalive_timeout 1;
  ####################################################################
  # 不要ならoff
  ssi on;
  ssi_types text/x-server-parsed-html;
  ####################################################################
  #圧縮しないならoff
  gzip on;
  gzip_vary off;
  gzip_disable “MSIE [1-6]\.”;
  gzip_disable “Mozilla/4;
  gzip_types
    text/plain
    text/xml
    text/css
    application/xml
    application/xhtml+xml
    application/rss+xml
    application/javascript
    application/x-javascript
  ;
  ####################################################################
  # SSLの設定
  ssl_certificate           /etc/pki/tls/certs/localhost.crt;
  ssl_certificate_key       /etc/pki/tls/private/localhost.key;
  ssl_protocols             TLSv1.2 TLSv1.1 TLSv1; #SSLv2,SSLv3は脆弱性がある
  ssl_ciphers               HIGH:!ADH:!MD5:!SSLv3; # openssl ciphers -v 'HIGH:!ADH:!MD5:!SSLv3'
  #nginxのversionによってssl_ciphersがエラーになる場合がある
  #ssl_ciphers               HIGH:!ADH:!MD5; 
  ssl_prefer_server_ciphers on;
  ssl_session_cache         shared:SSL:10m;
  ssl_session_timeout       10m;
  ####################################################################
  # 80,443ポート
  server {
    index index.php index.html;
    root    /var/www/html;
    listen  80;
    listen  443 ssl; #不要な場合はコメントアウト
    ##################################################################
    # backendでSSLか判定するのに必要
    set $ssl 0;
    if ($scheme = 'https') { set $ssl 1; }
    proxy_set_header X-SSL $ssl;
    proxy_redirect   off;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    ##################################################################
    # 静的コンテンツはブラウキャッシュ
    location ~ \.(gif|jpg|png|swf|css|js|txt|ico|css|html|xml)$ {
      expires 1d;
    }
    ##################################################################
    # not foundやcgi,php,plはバックエンドに渡す
    error_page 404 = @fallback;
    location ~ \.(cgi|php|pl)$ {proxy_pass http://backend;}
    location @fallback         {proxy_pass http://backend;}
  }
}

error_pageのエラーコードの後に=を追記しました。
POODLE対策の為SSLv3を禁止にしました

バックエンドはapacheが楽だよね

今までのknow howもあるし、rewrite使いたいし余計なこと考えたくない!
ZendFrameworkに興味がない人やそもそもphpに興味がない人は不要なとこは消して実行してね。

yum -y install php-ZendFramework-Cache-Backend-Memcached php-ZendFramework-Cache-Backend-Apc php-ZendFramework-Db-Adapter-Mysqli php-mbstring mod_extract_forwarded mod_ssl
echo 'date.timezone = Asia/Tokyo' >> /etc/php.d/local.ini
chkconfig httpd on
cat > /etc/httpd/conf/httpd.conf

# (C) makoto <makoto@2ch.to>
######################################################################
# 基本設定
ServerRoot /etc/httpd
PidFile run/httpd.pid

User apache
Group apache

# 接続関係
Timeout 3
KeepAlive off
KeepAliveTimeout 1
MaxKeepAliveRequests 20
#Listen 0.0.0.0:80
Listen 127.0.0.1:8080

# 起動設定
<IfModule prefork.c>
  StartServers       3
  MinSpareServers    5
  MaxSpareServers   10
  MaxClients        100
  MaxRequestsPerChild  0
</IfModule>

# 起動設定
<IfModule worker.c>
StartServers         2
MaxClients         150
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

# その他
ServerTokens Prod
ServerSignature Off
TraceEnable Off
######################################################################
# ディレクトリの設定
AccessFileName .htaccess
DocumentRoot /var/www/html/
######################################################################
# MIME/言語設定
LoadModule mime_module       modules/mod_mime.so
LoadModule mime_magic_module modules/mod_mime_magic.so
TypesConfig /etc/mime.types
MIMEMagicFile conf/magic
DefaultType text/plain
######################################################################
# LOG設定
ErrorLog logs/error_log
LogLevel warn
#LogLevel error
#LoadModule log_config_module modules/mod_log_config.so
#LogFormat "%h %v %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %X%D" combined
#CustomLog logs/access_log combined env=!nolog
######################################################################
# php
<IfModule prefork.c>
 LoadModule php5_module modules/libphp5.so
</IfModule>
<IfModule worker.c>
 LoadModule php5_module modules/libphp5-zts.so
</IfModule>
AddHandler php5-script .php
######################################################################
# server-status
LoadModule status_module modules/mod_status.so
ExtendedStatus On
<Location /server-status>
    SetHandler server-status
</Location>
#####################################################################
#
LoadModule dir_module modules/mod_dir.so
DirectoryIndex index.php index.html
#####################################################################
#
#LoadModule rewrite_module    modules/mod_rewrite.so
#LoadModule auth_basic_module modules/mod_auth_basic.so
#LoadModule authn_file_module modules/mod_authn_file.so
#LoadModule authz_user_module modules/mod_authz_user.so
<Directory /var/www/html>
#  AllowOverride FileInfo Options AuthConfig
  AllowOverride None
  Options FollowSymLinks
</Directory>
#####################################################################
# expiresの設定
LoadModule expires_module modules/mod_expires.so
ExpiresActive On
#ExpiresActive Off
ExpiresByType text/css "access plus 1 day"
ExpiresByType application/x-javascript "access plus 1 days"
ExpiresByType application/javascript "access plus 1 days"
ExpiresByType text/javascript "access plus 1 days"
ExpiresByType text/plain "access plus 1 days"
ExpiresByType image/gif "access plus 1 days"
ExpiresByType image/jpeg "access plus 1 days"
ExpiresByType image/jpg "access plus 1 days"
ExpiresByType image/png "access plus 1 days"
ExpiresByType image/ico "access plus 1 days"
ExpiresByType image/icon "access plus 1 days"
ExpiresByType text/ico "access plus 1 days"
ExpiresByType application/ico "access plus 1 days"
ExpiresByType image/x-icon "access plus 1 days"
#####################################################################
# mod_extract_forwarded
LoadModule proxy_module modules/mod_proxy.so
LoadModule extract_forwarded_module modules/mod_extract_forwarded.so
MEForder refuse,accept
MEFrefuse all
MEFaccept 127.0.0.1
MEFaddenv on
MEFdebug off

以下の指摘を受けて修正しました。


最新版大切

ついでに設定反映させるのにrebootもしちゃえ

yum -y update
reboot

関連リンク

携帯とかスマートフォンでコンテンツを切り替える魔法の設定もお役に立つと思いますので是非はてなブックマークをお願いします。

最後に

こういう話出来る人が周りにすくないので是非twitterで語り合いましょう。

clonekocloneko 2012/03/08 09:47 twitterからきました。

Iptablesのところで設定しているMySQL、memcached、PostgreSQLへの接続はSSHポートフォワーディングにしたほうがよりセキュアだと思います。
開けるポート減らせるし、暗号化されるし、おすすめです。

s025236s025236 2012/03/08 16:56 clonekoさん
MySQLやpostgreSQL等、暗号化通信する方法が提供されてるのに
わざわざポートフォワード使うのはCPU的にもネットワーク的にも無駄使いだと思います。
それに、ポートフォワードって切断されたときに(なんらかの別の仕組みを使わずに)自動的に再接続する仕組みも無いですよね。
あえて障害の発生箇所や手間を増やす必要あるのでしょうか?

memcachedは内容次第では必要かもしれませんがSSHのオーバーヘッドでmemcacheの利点はどこに…

iwaimiwaim 2012/03/08 19:28 > memcachedは内容次第では必要かもしれませんがSSHのオーバーヘッドでmemcacheの利点はどこに…

ディスクI/Oがボトルネックになったりすることも多いから十分に利点があるケースは想像できます。

s025236s025236 2012/03/09 02:35 iwaimさん
すみません、あんまりフィードバックもらった事が無いので過剰反応かもしれません。

ひとつ前の回答は一般化した環境のipatblesの設定でそれらのOUTPUTを許可(INPUTは部分許可)してる事に対しての回答です。(と思って回答してます)
そもそもmemcachedというより、なんでもポートフォワーディングに頼ろうとしていてそれを"おすすめ"してる事に対して反対しています。

ケースがあるかないか?という意味では個別案件で「そういうのもできるよねー」というつっこみであればおっしゃる通りかと思います。

ただ、他にもソリューションがあり出されたものがひとつの方法でベストでも無い(しかも十分にオーバーヘッドがあるのを知ってる)のでまったく"十分に"ではないと思いますしその前の部分でデメリットも述べてます。(ベストな方法は提示できないので書きませんでした)

ここで討論してもしょうがないので、この日記の中で"おすすめ"されるのであれば(ベストは提示できないので)"おすすめ"しない理由を書くしかないのです。(間違いだと思えば日記自体を訂正しています)

この日記自体ある程度以上の人からは突っ込まれるのを覚悟してますし、最低限(でも実用に耐えれるハズ)のレベルで書いてますしこの日記みて突っ込み出来る人はこの日記鵜呑みにしないと思うんですよ。
(というよりこれに反応してもっと良い記事書いたり補完記事を書いてくれるハズ)

うまくまとめられずすみません。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。