うっかりエンジニアのメモ

未来の自分に宛てたメモ

S3上の静的サイトにさくらで管理中のドメインのサブドメインでアクセス

今日、さくらのレンタルサーバから、さくらのVPS+さくらのメールボックスへのお引越しが完了しました。はじめはすべてVPSで済ませようと考えていたものの、メールサーバの構築難易度(セキュリティ面含む)の高さに恐れおののき、このような変則構成になりました。

その引っ越しの最中に、中学時代に書いてたオリジナルガンダム小説発表サイトなど、暗黒時代の産物が多数発掘されて、面白くなってきてこれはこれで公開しとこうと思い立ちました。でも普通にVPSのwebサーバ上に置くのも技術的に面白く無いなぁということで、そういえば昔AWSのS3に月額10円でサイトをホストうんちゃらというような広告を見たことがあったような気がして、ちょうどいい機会だと思って試してみました。

公開したいガンダム小説サイトはこちら http://0322.entropia.jp

条件

  • さくらのドメインentropia.jpを管理している
  • デプロイしたいサイトは静的サイト

ゴール

0322.entropia.jpで、S3上にデプロイした静的サイトにアクセスできる

手順

AWSでの設定

バケットの作成

[Create Bucket]から0322.entropia.jpという名前のバケットを作成します。

静的サイト公開設定

バケットを静的サイトのデプロイ先として利用できるように設定します。 Static Website Hosting > Enable website hostingを選択
Index Documentにindex.htmlError Documentにerror.htmlと入力します。

ファイルアップロード

普通にFTPする感覚で左上のUploadからファイルをアップロードします。
バケットのルートディレクトリがURLのルートと対応することに注意します。

パーミッション設定

Permission > edit bucket policyで開いたウィンドウに以下をコピペしてsaveします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::0322.entropia.jp/*"
        }
    ]
}

この時点でAWSドメインで静的サイトにアクセスすることができます。もう一息です。 http://0322.entropia.jp.s3-website-ap-northeast-1.amazonaws.com

さくらでの設定

会員メニュー > ドメイン > ドメイン名一覧 から所望のドメインのゾーン編集をクリックして、下記のCNAMEレコードを追加します。
0322 CNAME 0322.entropia.jp.s3-website-ap-northeast-1.amazonaws.com.
最後のドットが非常に重要です。

以上です。お疲れ様でした。

nginx上でサブディレクトリのCakePHPアプリを動作させる

もう本当に大変で、1週間潰れました。
同じように貴重な土日を潰してしまう人が一人でも減ることを願って。

環境

目標

サブディレクトリにあるCakePHPアプリを動作させたい。

いいかえるとhttp://example.com/subdir/ にアクセスして、サーバー上の/usr/shared/nginx/example.com/subdirにあるCakePHPアプリにアクセスしたい。

stackoverflowなどに同様の質問は沢山挙がっているのですが、どのベストアンサーも私の環境では正常に動作しませんでした。

CakePHP公式サイトのnginx設定例じゃダメなの?

ダメなんです。。。

server {
    listen   80;
    server_name www.example.com;
    rewrite ^(.*) http://example.com$1 permanent;
}

server {
    listen   80;
    server_name example.com;

    # root directive should be global
    root   /var/www/example.com/public/app/webroot/;
    index  index.php;

    access_log /var/www/example.com/log/access.log;
    error_log /var/www/example.com/log/error.log;

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

残念ながら、これはサーバのルートディレクトリにCakePHPを設置した場合の設定例なのです。
サブディレクトリにCakePHPを配置した場合の設定を一から考える必要があります。

CakePHP公式サイトのnginx設定例は何をやっているのか

公式サイトの設定例はそのまま利用できないものの、nginxでどう設定すればよいのかヒントになるので、詳しく見ていきます。

まず、最初のserverコンテキストで設定されているものです。

server {
    listen   80;
    server_name www.example.com;
    rewrite ^(.*) http://example.com$1 permanent;
}

これはwww.有りでアクセスがあった際に、www.なしのhttp://example.com/にリダイレクトする設定です。これはCakePHPと関係がないので、以後無視します。

後半のserverコンテキストを見ます。

server {
    listen   80;
    server_name example.com;

    # root directive should be global
    root   /var/www/example.com/public/app/webroot/;
    index  index.php;

    access_log /var/www/example.com/log/access.log;
    error_log /var/www/example.com/log/error.log;

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

server_name example.com;
Hostがexample.comであるアクセスは、このコンテキストの設定で処理されることを宣言しています。

root /var/www/example.com/public/app/webroot/;
URL上のルートパスに対応するサーバ上のフルパスが設定されます。apacheにおけるDocumentRootと同じ。

locationコンテキストその1

    location / {
        try_files $uri $uri/ /index.php?$uri&$args;
    }

(先ほどのrootディレクティブの設定は{}の内側全域で有効であることに注意)
ここのlocationコンテキストの動作はやや複雑。

  1. /var/www/example.com/public/app/webroot/$uriという静的ファイルを探す
  2. (無ければ)/var/www/example.com/public/app/webroot/$uri/というディレクトリを探す
  3. (それも無ければ)/var/www/example.com/public/app/webroot/index.php?$uri&$argsに内部リダイレクトする

  4. $uriにはクライアントから要求のあったURLから、server_nameを取り除いた文字列が入る

    • 例: http://www.example.com/xxx/yyyにアクセスがあった場合、$uri = xxx/yyy
  5. $argsはURLパラメータを保持したまま内部リダイレクトするための変数

locationコンテキストその2

    location ~ \.php$ {
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

locationコンテキストに~をつけると、設定を適用したいアクセスを正規表現で指定できます。
この場合、末尾が.phpで終わるファイルへのアクセスは、このlocationコンテキストの設定が適用されます。

nginx設定例

以上を踏まえて、こうなりました。

server {
    listen       80;
    server_name  example.com;

    root   /usr/share/nginx/example.com;

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

    location ~ ^/subdir/(img|css|js|files)/(.+)$ {
        root /usr/share/nginx/example.com/subdir/app/webroot;
        try_files /$1/$2 =404;
    }

    location ~ ^/subdir/(.+\.php) {
        fastcgi_pass    127.0.0.1:9000;
        fastcgi_index   index.php;
        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include         fastcgi_params;
    }

    location ~ ^/subdir/(.*)$ {
        index  index.php index.html;
        try_files /subdir/$1 /subdir/$1/ /subdir/index.php?$1&$args;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

参考資料

Nginx Community
http://wiki.nginx.org/

Nginx はどのようにリクエストを処理するか
http://nginx.org/ja/docs/http/request_processing.html

Nginx で location の判定方法と優先順位を調べる
http://server-setting.info/centos/nginx-location-check.html

nginx連載5回目: nginxの設定、その3 - locationディレクティブ
http://heartbeats.jp/hbblog/2012/04/nginx05.html

新卒2年目がAWSソリューションアーキテクト アソシエイトレベルに合格するまで

2014年5月に受験して合格しました。

例によって、受験時の規約により問題内容などについて言及することができないので、おすすめの教材などをまとめます。

受験者について

  • SIer新卒2年目エンジニア
  • 担当業務は脆弱性検査、コーディング(Java)
  • AWSは無料利用枠で触ってるくらい
  • 大学は情報系専攻

倒すべき敵を知る

公式サイトと受験体験記から、どんな試験なのかあたりをつけます。

眺めた受験記

http://drawing-hisa.seesaa.net/article/384974315.html http://qiita.com/inouet/items/02e8ba866a30f0316eeb http://humangas.hatenablog.jp/entry/2014/03/31/174247 http://www.seeds-std.co.jp/seedsblog/1055.html http://pc-concierge.net/blogs/blog/archives/70

おすすめ教材

サンプル問題
http://aws.amazon.com/jp/certification/certification-levels/certified-solutions-architect-associate/
公式に公開されています。

AWS 認定ソリューションアーキテクト – アソシエイト レベル試験に合格する方法
http://dev.classmethod.jp/etc/how-to-get-a-certification-aws-architect-associate-level/
クラスメソッドさんのブログにはいろいろ助けられました。

Amazon Web Services クラウドデザインパターン 設計ガイド

Amazon Web Services クラウドデザインパターン 設計ガイド

AWSエバンジェリスト玉川憲氏らが執筆した、AWSデザインパターンのカタログのような本です。1つのデザインパターンを数ページにまとめているので、さくさく読みやすいです。

AWS クラウドサービス活用資料集 特に「AWS マイスターシリーズ」と題した一連のプレゼン資料は、よくある要件をもとにAWSの各種サービス適用例を説明しているので理解しやすいです。

サンプル問題にもあるように、暗記すれば解ける類の問題よりも、ある状況設定のもとで最善の方法を選ばせる問題に対応できると良いと思います(精一杯の言い方)

ひとこと

CCNAのような暗記ゲーでも無ければ、Oracleの白本(※)のようなチート本もないので、なかなかしんどい試験だと思います。 「実戦経験がない人は受けない方が良い」という意見も見かけましたが、AWSを使ったアーキテクチャ設計が未経験だったり、AWSの管理画面をばりばり利用したことがなくても、ドキュメントベースでAWSへの理解があれば合格できるように感じました。 実務に裏打ちされた深い技術理解の証明には、今ならソリューションアーキテクト – プロフェッショナルレベルが適していると思います。

【オラクル認定資格試験対策書】ORACLE MASTER Bronze[12c SQL基礎](試験番号:1Z0-061)完全詳解+精選問題集(オラクルマスタースタディガイド)

【オラクル認定資格試験対策書】ORACLE MASTER Bronze[12c SQL基礎](試験番号:1Z0-061)完全詳解+精選問題集(オラクルマスタースタディガイド)

  • 作者: エディフィストラーニング株式会社,西昭彦,飯室美紀,鈴木佐和,岡野友紀,矢島祐子
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2014/03/27
  • メディア: 単行本
  • この商品を含むブログを見る

CakePHPでやたら遅いSELECTクエリの改善

プライベートで作ったWebアプリで、一画面だけブラウザに表示されるまで3秒かかる激重画面があります。 この画面ではCakePHPが自動的にいろんなテーブルをjoinしたSQLを生成しているので、その辺りが原因だろうとは感づきました。 それにしても、たかだか20行程度のselectなので、なんか変だ。。。 ちょっとだけ分析と改善をしました。(はじめてのパフォーマンスチューニング…ドキドキ)

結論としては、1000倍早くなりました。 CakePHPのクエリ自動生成は楽ですが、パフォーマンス上の問題が発生した時にはやはりSQLを知らないとダメだなぁ…

環境

VirtualBoxVM(メモリ613MB)上に下記の環境があります。

テーブル構造

テーブル 内容 外部キー
orders 注文データ shipping_method_id, payment_method_id, prefecture_id, tracking_code_id
shipping_methods 発送手段データ なし
payment_methods 入金方法データ なし
prefectures 都道府県データ なし
tracking_codes 追跡番号データ order_id(この追跡番号に対応した注文のid)

全てのテーブルはid列を主キーとして持つ。

恐ろしく時間がかかるクエリは、ordersテーブルを基点に他の4つのテーブルをleft joinして、注文が新しい順にソートして上位20件だけselectするようなクエリです。

改善前

CakePHPが発行したクエリ

SELECT *
FROM
  orders 
LEFT JOIN shipping_methods ON orders.shipping_method_id = shipping_methods.id
LEFT JOIN payment_methods ON orders.payment_method_id = payment_methods.id
LEFT JOIN prefectures ON orders.prefecture_id = prefectures.id
LEFT JOIN tracking_codes ON orders.id = tracking_codes.order_id
  WHERE 1 = 1
  ORDER BY orders.created DESC
  LIMIT 20;

※見やすさのために手を加えています

WHERE 1 = 1が気になりますが速度に影響しません。
CakePHPが挿入するこのWHERE 1 = 1の意味はこちらの解説がわかりやすいです。
CROSSOVER SEplus : where 1 = 1

実行速度(5回実行平均)

1826ms
くっそ遅い

クエリのexplain結果

id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE orders ALL NULL NULL NULL NULL 2604 Using temporary; Using filesort
1 SIMPLE shipping_methods eq_ref PRIMARY PRIMARY 4 ordersys.orders.shipping_method_id 1
1 SIMPLE payment_methods eq_ref PRIMARY PRIMARY 4 ordersys.orders.payment_method_id 1
1 SIMPLE prefectures eq_ref PRIMARY PRIMARY 1 ordersys.orders.prefecture_id 1
1 SIMPLE tracking_codes ALL NULL NULL NULL NULL 2233

で、でた〜ww
Using temporary; Using filesortはアカン。
なぜアカンのかはイケメンな漢さんの記事が大変参考になります。
漢(オトコ)のコンピュータ道: Using filesort

分析

怪しいのは2箇所。

  • LEFT JOIN tracking_codes ON orders.id = tracking_codes.order_idだけ、join先の列がidではなくorder_id
  • ORDER BY orders.created DESCでは、indexが生成されていないcreated列を使ってソートしている

それぞれ修正していきます。

CakePHPのテーブル関係定義

生成されるSQLの違いはCakePHPでの設定の違いから生まれるのは間違いないので、Orderモデルの定義をみていきます。

<?
class Order extends AppModel {
    public $hasMany = array(
        'ItemOrder'
    );
    
    public $hasOne = array(
        'TrackingCode',
    );

    public $belongsTo = array(
        'ShippingMethod',
        'PaymentMethod',
        'Prefecture'
    );
    ?>

SQLが怪しいTrackingCodeモデルだけ、関係がhasOneなのが気になります。

設計時に「OrderはひとつのTrackingCodeを持つ」という考えだったけれど、エンティティの主従関係を踏まえると、OrderがあろうがなかろうがTrackingCodeは存在するのだから、「OrderTrackingCodeに紐づく」(つまりOrder belongs to TrackingCode)としたほうが自然。

したがってOrderモデルを以下のように修正しました。

<?
class Order extends AppModel {
    public $hasMany = array(
        'ItemOrder'
    );

    public $belongsTo = array(
        'ShippingMethod',
        'PaymentMethod',
        'Prefecture',
        'TrackingCode'
    );

    // 中略
    ?>

ソート

これまで、注文日時が新しい順にデータが欲しかったのでorders.created(レコードの挿入日時)をもとにソートしていましたが

  • orders.created列にはindexが作成されていない
  • orders.id列で降順ソートしても注文日時順にデータが取得できる

ということで、orders.idをもとにソートするように修正します。

ORDER BY orders.id DESC

改善後

CakePHPが発行したクエリ

SELECT *
FROM
  orders 
LEFT JOIN shipping_methods ON orders.shipping_method_id = shipping_methods.id
LEFT JOIN payment_methods ON orders.payment_method_id = payment_methods.id
LEFT JOIN prefectures ON orders.prefecture_id = prefectures.id
LEFT JOIN tracking_codes ON orders.tracking_code_id = tracking_codes.id
  WHERE 1 = 1
  ORDER BY orders.id DESC
  LIMIT 20;

実行速度(5回実行平均)

1.3ms!!
当社比1400倍。くっそ速い(前が遅すぎた)

クエリのexplain結果

id select_type table type possible_keys key key_len ref row Extra
1 SIMPLE Order index NULL PRIMARY 4 NULL 20
1 SIMPLE ShippingMethod eq_ref PRIMARY PRIMARY 4 ordersys.Order.shipping_method_id 1
1 SIMPLE PaymentMethod eq_ref PRIMARY PRIMARY 4 ordersys.Order.payment_method_id 1
1 SIMPLE Prefecture eq_ref PRIMARY PRIMARY 1 ordersys.Order.prefecture_id 1
1 SIMPLE TrackingCode eq_ref PRIMARY PRIMARY 4 ordersys.Order.tracking_code_id 1

Using temporary; Using filesortが消えてる

まとめ

  • CakePHPhasOneアソシエーションを設定する場合は生成されるクエリに注意
  • ソート列にindexが作成されているか注意
  • クエリが遅かったらexplainで手がかりをつかむ

さくらVPSにowncloudをインストール

owncloudとは

owncloudは自分のサーバ上にdropboxのようなクラウドファイル同期環境を実現するオープンソースソフトウェアです。

クラウドストレージサービスはすでにDropboxなどが定番でしょうか。しかし、デフォルトの容量が2GBと少なく、いろいろ頑張って無料範囲内で増量しても、せいぜい10GB。ですので

  • メジャーなクラウドストレージサービスでは足りない人
  • 諸事情でDropboxにはつなげられないけどクラウドでファイル同期したい人

に、おすすめです。

今回はowncloud6.0.1をさくらのVPSに入れてみました。

環境

LAMP環境をすでに構築してあるものとします。

さくらVPSLAMP環境を構築する手順は過去記事を参考にどうぞ。

準備

MySQL

owncloudは管理のためにDBを利用します。v6.0.1ではMySQLSQLiteを選択できるので、ここではMySQLを選択します。

owncloud用のDBを作成し、owncloud用のユーザを作成します。

mysql> create database owncloud character set utf8;
mysql> grant all privileges on owncloud.* to 'owncloud'@'localhost' identified by '【パスワード】' with grant option;
mysql> flush previleges;

Apache

/etc/httpd/conf.d/owncloud.confを新規作成し、

<Directory /var/www/html/owncloud/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
</Directory>

と入力して保存。

owncloudインストール

cd /etc/yum.repos.d/
wget http://download.opensuse.org/repositories/isv:ownCloud:community/CentOS_CentOS-6/isv:ownCloud:community.repo
yum install owncloud

デフォルトでowncloudは/var/www/html/owncloudにインストールされます。rootユーザでファイルが生成されているとあかんので、apacheユーザにしておきます。

chown -R apache:apache /var/www/html/owncloud

Apacheを再起動します。

service httpd restart

owncloudへのアクセス

http://host.your.domain/owncloud

初期設定画面が表示されたら、インストールは完了です。


トラブルシューティング

手元のマシンからMySQL DBへ接続できない

リモート(たとえば手元のMacBook Pro)から、すべてのDBにアクセスできるDBユーザを作成済みで、正しいユーザ名とパスワードであるにもかかわらず、接続できない。

原因

ファイアウォールMySQLのポートへの接続が制限されているかも。

解決策

iptablesに下記を追加します。

-A INPUT -p tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp --sport 3306 -j ACCEPT

iptablesを再起動します。

service iptables restart

owncloudにログインしようとするとリダイレクトループでログインできない

解決策

セッションファイルの所有者を確認します。 CentOS 6.5の場合、PHPのセッションファイルはデフォルトで/var/lib/php/session下に保存されるので、所有者をapacheの実行ユーザに変更する。

chown -R apache:apache /var/lib/php/session

原因

たぶんこのハマり方したのは自分だけのような気が…。 owncloud redirect loopググると、海外のフォーラムはよくひっかかる。それぞれ原因は異なるように見え、解決策を見つけることはできず。

うーん…と悩みつつ、あらためてコマンド履歴を振り返ると、owncloudのアクセス中にhttpd.confを編集した形跡が…! 思い出しました。owncloudインストール後に、Apacheの実行ユーザとグループをhogeに変えていたことを。

つまりこんなことが起きてました。

  • Apacheの実行ユーザがapacheの状態で、owncloudにログイン
  • /var/lib/php/session下に、所有者apacheでセッションファイルが生成される
  • owncloudにログイン中(=セッション有効中)にhttpd.confを開き、Apacheの実行ユーザをhogeに変更
  • Apache再起動
  • ブラウザからowncloud利用しようとするとログイン画面へ飛ばされる
  • ログイン画面で正しいユーザID/パスワードを入力する
  • ログイン情報は正しいのでログインしようとするが、セッションファイルを生成するディレクトリの所有者がapacheなので、生成できない
  • ここでリダイレクトループ発生?

完全におばかさんでした。 Apacheの実行ユーザはよく考えて、最初に決めましょう。

さくらVPSで複数の独自ドメインを運用する

さくらのVPSで、もともとサーバに付与されているipアドレスを生かしたまま、複数の独自ドメインを運用する手順を説明します。

環境

LAMP環境をすでに構築してあるものとします。

さくらVPSLAMP環境を構築する手順は過去記事を参考にどうぞ。

手順

ここでは例として、追加したいドメインは下記の2つとします。

DNSレコード設定

上記のドメインはさくらで取得していたので、さくらの管理画面からAレコードの指すipアドレスVPSサーバに付与されているものに変更するだけでした。5分程度で反映されました。

NameVirtualHost

Apacheが同じサーバ上で別々のドメインのサイトを運用する方法の一つが名前ベースのバーチャルホストです。Apacheは、クライアント(ブラウザ)から送られてくるHTTPHostヘッダを頼りに、どの独自ドメイン宛のリクエストなのかを判別します。

NameVirtualHostの有効化

/etc/httpd/conf/httpd.confを開き

#NameVirtualHost *:80

先頭の#を外します。

ドメインとの対応付け

ドメインに対するアクセスを、どのディレクトリに対応付けるかを設定します。 /etc/httpd/conf/httpd.confに書いてもよいのですが、ここで、/etc/httpd/conf.d/下にある.confで終わるファイルが、apacheの起動時にhttpd.confと同様に読み込まれることを利用します。

/etc/httpd/conf.d/moiranographia.com.confを新規作成し、下記を書きます。

<VirtualHost *:80>
  ServerName moiranographia.com
  DocumentRoot "/var/www/moiranographia.com/public_html"
  DirectoryIndex index.html index.php
  ErrorLog /var/log/httpd/moiranographia.com_error_log
  CustomLog /var/log/httpd/moiranographia.com_access_log combined
  AddDefaultCharset UTF-8
  <Directory "/var/www/moiranographia.com/public_html">
    AllowOverride All
  </Directory>
</VirtualHost>

独自ドメインが複数ある場合、同様にファイルの作成を繰り返します。

もともとサーバに付与されているipアドレスを生かす

Apacheの公式ドキュメントにもある通り、VirtualHostを有効にすると、もともとサーバに付与されているipアドレスの直打ちではアクセスできなくなります。

メインホストはなくなります

既にあるウェブサーバにバーチャルホストを追加する場合、 既存のウェブサーバに対しても ブロックを作らなければなりません。このバーチャルホストの ServerName と DocumentRoot は、グローバルな ServerName と DocumentRoot と同じものにします。また、このバーチャルホストを設定ファイルの中で先頭に置いて、デフォルトホストとして動作するようにします。

http://httpd.apache.org/docs/current/ja/vhosts/name-based.html より引用

ですので、httpd.confを編集します。

/etc/httpd/conf/httpd.confを開き、NameVirtualHost *:80の下あたりに、下記を追加します。

<VirtualHost *:80>
  ServerName xxx.xxx.xxx.xxx
  DocumentRoot "/var/www/html"
  DirectoryIndex index.html index.php
  ErrorLog /var/log/httpd/error_log
  CustomLog /var/log/httpd/access_log combined
  AddDefaultCharset UTF-8
  <Directory "/var/www/html">
    AllowOverride All
  </Directory>
</VirtualHost>

xxx.xxx.xxx.xxx: もともとVPSに割り当てられていたipアドレス

この設定により、たとえばxxx.xxx.xxx.xxx/example.htmlへのリクエストに対して、apache/var/www/html/example.htmlをレスポンスとして返します。

apacheを再起動します。

service httpd restart

さくらVPSにLAMP環境構築

さくらのVPSを契約してから、LAMP環境を構築するまでの手順を記録しておきます。

OSはCentOS 6.5 x86_64です。

事前準備

何はともあれ、まずはyum update

yum update

OSの言語を日本語にします。etc/sysconfig/i18nを開き

LANG="ja_JP.UTF-8"

に変更して保存。

SELinuxはオフにします。vi/selinux/configを開き

SELINUX=disabled

に変更して保存。

epel,remiレポジトリの追加

標準レポジトリPHPMySQLのバージョンが古いので、新しいバージョンをインストールするためにepel,remiレポジトリを追加します。

wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
rpm -ivh epel-release-6-8.noarch.rpm 
rpm -ivh remi-release-6.rpm 

作業用ユーザ設定

rootでずっと作業したくないので、作業用ユーザhogeを追加します。

useradd hoge
passwd hoge
<ユーザhogeに設定したいパスワードを入力>

ユーザhogeをwheelグループに追加

usermod -G wheel hoge

ユーザhogeがsudoを実行できるように設定を変更します。

visudo

開いたテキストファイル中の

#%wheel        ALL=(ALL)       ALL

の先頭の#を削除する。

公開鍵認証

hogeユーザで実行します。

mkdir ~/.ssh
chmod 700 ~/.ssh

手元のPCで実行します。

ssh-keygen -t rsa -v
chmod 600 .ssh/id_rsa.pub
scp ~/.ssh/id_rsa.pub hoge@IP.ADD.RE.SS:~/.ssh/authorized_keys
ssh -i ~/.ssh/id_rsa hoge@IP.ADD.RE.SS

完了したら、ssh hoge@IP.ADD.RE.SSで、パスワードを聞かれることなくサーバにログインできることを確認。

SSH

サーバのセキュリティを高めます。

  • SSHポート番号変更
  • パスワード認証を禁止
  • rootユーザのログインを禁止

/etc/ssh/sshd_configを開き

Port 【10000以降で適当なポート番号】
PasswordAuthentication no
PermitRootLogin no

SSHDを再起動します。

service sshd restart

iptables

こちらの記事が非常に参考になりました。ありがとうございますm(__)m 「さくらのVPS」CentOS の初期設定の作業のまとめ&解説(iptablesによるファイアウォール編)「さくらのVPS」CentOS の初期設定の作業のまとめ&解説(iptablesによるファイアウォール編)

外部からMySQLへのアクセスを許可するために以下を追加します。

-A INPUT -p tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp --sport 3306 -j ACCEPT

サーバーから外部へのHTTPS接続を許可するために以下を追加します。

-A INPUT -p tcp --sport 443 -j ACCEPT
-A OUTPUT -p tcp --dport 443 -j ACCEPT

Apache

インストール

OS起動時の自動起動設定も合わせて。

yum install httpd
chkconfig httpd on

DocumentRootの所有者がrootになっているので、apacheの実行ユーザに修正する。

chown -R apache:apache /var/www/html/

httpd.confの編集

/etc/httpd/conf/httpd.conf

ServerTokens Prod
ServerSignature Off
Options -Indexes FollowSymLinks

PHP

インストール

yum --enablerepo=remi install php php-devel php-mysql php-gd php-mbstring

php.iniの編集

error_log = /var/log/php.log
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = auto
mbstring.detect_order = auto
expose_php = Off
date.timezone = Asia/Tokyo

apacheの再起動

service httpd restart

MySQL

インストール

yum --enablerepo=remi install mysql-server

my.cnfの編集

/etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

character_set_server=utf8
default-storage-engine=InnoDB
innodb_file_per_table

# Settings user and group are ignored when systemd is used (fedora >= 15).
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
user=mysql

# Semisynchronous Replication
# http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html
# uncomment next line on MASTER
;plugin-load=rpl_semi_sync_master=semisync_master.so
# uncomment next line on SLAVE
;plugin-load=rpl_semi_sync_slave=semisync_slave.so

# Others options for Semisynchronous Replication
;rpl_semi_sync_master_enabled=1
;rpl_semi_sync_master_timeout=10
;rpl_semi_sync_slave_enabled=1

# http://dev.mysql.com/doc/refman/5.5/en/performance-schema.html
;performance_schema


[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

[mysql]
default-character-set=utf8
[mysqldump]
default-character-set=utf8

mysql起動

OS起動時の自動起動設定も合わせて。

service mysqld start
chkconfig mysqld on

mysql初期設定

mysql_secure_installation