AWS for WordPress の CloudFront をエラーなく使う設定方法

WordPress の AWS for WordPress プラグインに CloudFront を設定できる画面がありますが、画面の指示通りにやってもエラーが出ます。
この画面でエラーなく設定する方法は以下の通りです。

origin も dest も普通の WordPress サイトとして表示できるようにする。

origin も (取りあえず)dest も EC2 の IP アドレスを指すように、DNS サーバの設定で A レコードの設定をします。

Apache の httpd.conf で、origin も dest も同じサイトを指すように設定します。

<VirtualHost *:80>
  DocumentRoot "/home/{your-home-directory}/wordpress"
  Servername "orgin.bass-world.net"
  ServerAlias "origin.bass-world.net"
  ServerAlias "dest.bass-world.net"
  (以下略)
</VirtualHost>

origin と dest の両方を含む SSL 認証書を取得する

# certbot certonly --webroot -w /home/{your-home-directory}/wordpress
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Please enter in your domain name(s) (comma and/or space separated)  (Enter 'c' to cancel): 
origin.bass-world.net dest.bass-world.net
(以下略)

取得したら、origin/dest の両方でウェブサイトが表示できるか確認する。

確認したら、dest の A レコードを DNS 設定から削除する。

AWS for WordPress の CloudFront を実行する

origin の WordPress の AWS 設定画面で、CloudFront の設定をする。(画面に書かれてある 3 ステップ)

CloudFront のディストリビューションアドレスを dest の CNAME に設定する。

WordPress のサイトアドレスを dest に変更する

WordPress 設定画面の「設定」→「一般」で、「WordPress アドレス (URL)」「サイトアドレス (URL)」を、dest の URL に変更する。

追記・マルチサイト化

サブディレクトリ型のマルチサイト化は無理。

CloudFront の設定が終わってからマルチサイト化すると、サブドメイン型しか選択できなくなる。

先にサブドメイン型のマルチサイトを作っておいて CloudFront を設定すると、一見できたように思えるが、色々バグってる。

CloudFront の設定 (php ファイル対応編)

AWS CloudFront の Behavior の設定。サイトに php ファイルがある場合。

Path PatternDefault (*)*.php
Viewer Protocol PolicyRedirect HTTP to HTTPSRedirect HTTP to HTTPS
Allowed HTTP MethodsGET, HEADGET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cached HTTP MethodsGET, HEADGET, HEAD
Cache Based on
Selected
Request Headers
None (Imrpoves Caching)None (Improves Caching)
Object CachingUse Origin Cache HeadersUse Origin Cache Headers
Minimum TTL00
Maximum TTL3153600031536000
Default TTL8640086400
Forward CookiesNone (Improves Caching)All
Query String
Forwarding
and Caching
None (Improves CachingForward all, cache based on all

Amazon Linux 2 で Segmentation Fault

GMO クラウドで動かしていた、ツイートを一覧表示するプログラム、AWS の Amazon Lunux 2 に持って行って動かすと 10 回ぐらい動かすと「Segmentation Fault」でエラーになる。
それでもリスタートしないでおくと、順に

  1. WordPress がエラー画面
  2. Apache が落ちる
  3. SSH も繋がらなくなる

GMO クラウドでは1年間リスタートなしで動いているのに、Amazon Linux 2 では1週間と経たずに落ちる。メモリリークかと思って色々調べていたんだけど、原因は PHP のプログラムにあるっぽい。

PHP のガベージコレクションを信じるな。

使い終わったオブジェクトを unset するようにプログラムを書き換えたら、2 日経った今のところ、大丈夫そう。

WordPressの引っ越し

WordPress を CentOS7.6 + PHP7.2.9 + MySQL8.0.16 から AWS(EC2 + RDS) PHP7.2.27 + MariaDB10.2.21 に引っ越しました。
そこでの引っ越し方法とつまづきポイントを書きます。

データベースのエクスポート

mysqldump -u pocolog -p -h localhost -A -n > pocolog.sql

エクスポートしたデータで、旧URLから新URLに変換

エクスポートした SQL で、’https://{今までのブログのURL}’ を ‘https://{新しいブログのURL}’ にひたすら置換。

新サーバに上記データをコピー

mysql -h maria.xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -P 3306 -u admin -p < pocolog.sql

Access denied エラーをひたすら潰す

ERROR 1227 (42000) at line xx: Access denied; you need (at least one of) the SUPER privilege(s) for this operation をひたすら潰す。

新しいURLに変更

mysql コンソール上で update wp_blogs set domain = ‘{新しいブログのURL}’;

Twitter API で特定のアカウントのツイートを取得する方法、修正版

Twitter API で特定のアカウントのツイートを取得する方法」ですが、タイムアウトして情報が取れないことがあり、その辺りを改良しました。

<?php
require_once 'TwistOAuth.phar';

$consumer_key = '{your-consumer-key}';
$consumer_secret = '{your-consumer-secret}';
$access_token = '{your-access-token}';
$access_token_secret = '{your-access-token-secret}';

$connection = new TwistOAuth($consumer_key, $consumer_secret, $access_token, $access_token_secret);
$count = 3;
$max_length = 25;

function get_tweet($screen_name){
  global $connection, $count, $max_length;
  $ret = "";

	// connect
	try{
		$user = $connection->get('statuses/user_timeline',
    array('screen_name' => $screen_name,
      'count' => $count,
      'exclude_replies' => 'false',
      'include_rts' => 'false',)
    );
	} catch (TwistException $e) {
		fputs(STDERR, "Error : $screen_name , " . date("Y/m/d H:i:s") . "\n");
		$text = '<h4><a href = "https://twitter.com/@' . $screen_name . '">@' . $screen_name . '</a></h4>';
		$text .= '<ul class = "tweet"><li>取得失敗</li></ul>' . "\n";
		return $text;
	}

	// get user names.
	$screen_name = htmlspecialchars($user[0]->user->screen_name, ENT_QUOTES, 'UTF-8', false);
  $names = "<h4>" . htmlspecialchars($user[0]->user->name, ENT_QUOTES, 'UTF-8', false) 
      . ' <a href = "https://twitter.com/@' . $screen_name . '">@' . $screen_name . "</a></h4>\n";
  $ret .= $names;

  $ret .= '<ul class = "tweet">';

  // get tweets.
  foreach ($user as $value){
    $screen_name = htmlspecialchars($value->user->screen_name, ENT_QUOTES, 'UTF-8', false);
    $post_date_utc = htmlspecialchars($value->created_at, ENT_QUOTES, 'UTF-8', false);
    $post_date = timezone_change_ja($post_date_utc);
    $text = htmlspecialchars(mb_substr($value->text, 0, $max_length, 'UTF-8'), ENT_QUOTES, 'UTF-8', false);
    $link = '<a href = "https://twitter.com/' . $screen_name . '/status/' . $value->id_str . '">';
    $ret .= "<li>" . $post_date . " " . $link . $text . "</a></li>\n";
  }

  $ret .= "</ul>\n";
  return $ret;
}

/*
	Twitterからのタイムゾーンを日本時間(東京)に変換するq
         $time = timezone_change('Tue Jul 12 06:27:46 +0000 2011');
         echo $time{"tm_year"};
         
*/

function timezone_change_ja($timezone = null){

	$year = $month = $day = $hour = $minute = $second = null;
	if(!empty($timezone)){

		$date_arr = explode(" ", $timezone);
		$year = intval($date_arr[5]);
		
		if($date_arr[1] == "Jan"){
			$month = 1;
		}else if($date_arr[1] == "Feb"){
			$month = 2;
		}else if($date_arr[1] == "Mar"){
			$month = 3;
		}else if($date_arr[1] == "Apr"){
			$month = 4;
		}else if($date_arr[1] == "May"){
			$month = 5;
		}else if($date_arr[1] == "Jun"){
			$month = 6;
		}else if($date_arr[1] == "Jul"){
			$month = 7;
		}else if($date_arr[1] == "Aug"){
			$month = 8;
		}else if($date_arr[1] == "Sep"){
			$month = 9;
		}else if($date_arr[1] == "Oct"){
			$month = 10;
		}else if($date_arr[1] == "Nov"){
			$month = 11;
		}else if($date_arr[1] == "Dec"){
			$month = 12;
		}

		$day = intval(sprintf("%d", $date_arr[2]));

		$arr = explode(":", $date_arr[3]);
		
		$hour = intval(sprintf("%d", $arr[0]));
		$minute = intval(sprintf("%d", $arr[1]));
		$second = intval(sprintf("%d", $arr[2]));

		$time = mktime($hour, $minute, $second, $month, $day, $year);
		$time = $time + 60 * 60 * 9; # 9時間進める
    //$date = localtime($time, true);
    return date("Y-m-d H:i", $time);
		//return $date;
	}else{
                  return false;
         }
}

?>

取得失敗の例外発生時に、スクリーンネームと「取得失敗」を戻り値にして返して、標準エラー出力にエラー内容を出力するようにしました。

このため PHP の実行文も変わります。
エラー内容を itawoerror.log に追記していきます。

php ./itawotweet/itwt_cjpn.php > ./www/itawotweet/itwt_cjpn.html 2>> itawoerror.log

ログは定期的に自分のメールアドレスに送るようにシェルスクリプトを書きました。

#!/bin/sh
if [ -s ./itawoerror.log ]; then
	cat -v ./itawoerror.log | mail -s "itawotweet error log" {your-mail-address}
	rm -f itawoerror.log
fi

これを cron に登録します。

AWS の CloudFront で WordPress を稼働してて、かつ ec2 間に SSL 通信をしている場合

Amazon Web Service で ec2 と CloudFront で WordPress を稼働している、かつ Let’s Encrypt で CloudFront – ec2 間を SSL 通信している場合。

これはハマる気がした。
certbot renew が失敗する。
WordPress が勝手にリダイレクトするから。

3ヶ月に1回、ダミーの静的ウェブサイトに接続先変えて証明書を取得するもの面倒くさいなー。

AWS CloudFront で WordPress を立ち上げる大日程

  1. http で静的なオリジンサイトを立ち上げる。
  2. Let’s Encrypt で オリジンサイトに SSL 導入。
  3. https なオリジンサイトに WordPress インストール。
  4. CloudFront 導入。詳しくは
  5. 表側サイトの動作確認。
  6. WordPress の設定。管理画面で「一般」→「WordPress アドレス」「サイトアドレス」を表側の URL に変更。
  7. ec2 の方の httpd.conf にも表側サイトの設定を書く。←なぜ?
  8. マルチサイト作成。

AWS で ec2 + RDS で WordPress 作る時の備忘録

  • amazon-linux-extras で PHP7.2 と MariaDB をインストールする。
  • データベースもユーザも「localhost」で作らない。
  • Amazon Polly + WordPress のアマゾン公式ドキュメントはポリシーの JSON が間違っている。
  • 同じく、プラグインの設定がちょっとおかしい。一周遅れで来る感じ。日英中に翻訳させたいなら、一度日英中で保存した後、日英だけにして保存すると、投稿が日英中になる。

Amazon Polly の英語読み上げテスト

あー、Amazon Polly、設定画面で指定した言語でしか読み上げできないのかー。
試しに Japanese – Mizuki で読み上げてみたけど、典型的なジャパニーズイングリッシュかつイントネーションがヘン。
残念。
The train came out of the long tunnel into the snow country. The earth lay white under the night sky. The train pulled up at a signal stop.
A girl who had been sitting on the other side of the car came over and opened the window in front of Shimamura. The snowy cold poured in. Leaning far out the window, the girl called to the station master as though he were a great distance away.
The station master walked slowly over the snow, a lantern in his hand. His face was buried to the nose in a muffler, and the flaps of his cap were turned down over his face.

Amazon Polly で WordPress を音声読み上げをテストしてみた。流ちょう度は…?

AWS の Amazon polly で WordPress のブログ投稿を読み上げるよう設定してみました。

元記事はこれ。

んー、まだ機械音声みたいな感じ。Alexa と同等?
以下、読み上げているテキスト。
“Amazon Polly で WordPress を音声読み上げをテストしてみた。流ちょう度は…?” の続きを読む