WordPressの管理に疲れたので静的ページに落としてS3で公開した話

(追記 7/11)
qiitaの記事を転機し,動作テストとする.

(追記 7/10)
cloudfrontの設定を追記した.
意外と手間がかかっていて,wordpressを普通に運営した方がいいんじゃねーのってツッコミもありうる.

注意
ドメイン名を晒していますが,403 Forbiddenが返ってしまった方がいるかも知れません.
過去にアタック性のあるURLへのアクセスが検出されたアクセス元IPアドレスは,全て機械的に拒否設定しているため,そのリストに加えられている可能性があります.

遊び半分で「w00tw00t」なんて文字列の入ったパスにアクセスしちゃダメ,絶対!

疲れた…

私の運営するwebsiteは,wordpressがメインコンテンツになっている.
運用するのは結構大変で,

もう疲れたよ!

この記事の概略

https://wp.hadacchi.com がサンプル (なぜか wp_blog/index.html だけ,index.htmlまで指定しないと読んでくれない)

※スクリーンショットを何回にも分けて取ったので,ドメイン名がコロコロかわっている点はご留意いただきたい.

対策→構成変更

ということで,手間を少なくblogを運営する方法を模索することにした.
構成っぽく書くが,AWS構成はフルマネージドのサービスを使っているので,実際の構成とはきっと違うし雰囲気だけ掴めれば良いことにする.

構成(イメージ)

[the Internet]
       |
     [FW]
       |
       +-- [Server] (nginx + wordpress)
       |
       +-- [Object Storage]
 [the Internet]
        |
[AWS Cloud Front]
        |
   [Amazon S3] <--(awscli)-- [FW] -- [local machine] (nginx + wordpress)

要は,従来のクラウド上の機能をローカルの非公開NWに落として,静的コンテンツに変換したものをS3にアップロードする.で,CloudFront経由で公開する.
しかも,今のクラウド料金はVMとオブジェクトストレージを合わせて400円/月くらいだが,この構成なら200円/月くらいになるはず.
あーなんで,この方法に気付かなかったんだろ.

実は,この記事[1]で行けるんだけど,ハマりどころがあるのでもう少し細かく書いたものが,本記事である.
基本的には,素晴らしき先達のノウハウを活用されたい.

S3 webhostingの設定

S3でindex.htmlを公開する

簡単には,この記事の通りである→[2]
ただ,いくつか端折られてたりするので,もちょっとだけ詳しく書く.

なおAWSアカウントは,もうあるものとする.(既に持ってるので再現できない)

awscli導入

awscliを,まず導入してしまおう.
pipが使えるものとし,awscliをインストールする.

# user権限で入れると ~/.local/bin/ にインストールされる
pip install --user awscli
export PATH=${HOME}/.local/bin:${PATH}
aws --version

すると,こんな感じの結果が返ってくる.

aws-cli/1.15.49 Python/2.7.9 Linux/3.16.0-4-amd64 botocore/1.10.48

文献[2]の通りバケットを作成する

仮ドメインをtmp.hadacchi.comとすると,バケット名もtmp.hadacchi.comとする.
※他の設定を正しくしても,この名前が合ってないとs3 webhostingでは404が返るので注意.
※cloudfrontを設定した後はこの限りでない

indexesを.htmにしたい場合は,index.htmと書けば良い.
ただし,後述のstaticpressというwordpressをhtml化するプラグインはindex.htmlとして吐くので,あえてhtmにするメリットはない.

バケットポリシーは,Resourceのところを,「バケットポリシーエディター ARN: arn:aws:s3:::tmp.hadacchi.com」と編集画面で書かれているところからコピペして修正すること.

書くならこんな感じ.
Versionの値の"2012-10-17"は,このJSONの従うフォーマットのバージョンなので,この値で良いことに注意.

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

IAMの作成(権限作成)

wordpressが動作しているAWS外のホストから,awscliで接続できるよう設定したい.
AWSのアクセス管理は,ユーザ(IAM)への権限付与で行なうので,まずIAMユーザを作る.

AWSコンソールの左上の「サービス」をクリックし「IAM」を選ぶ.

先にポリシーを作成する.

ビジュアルエディタでポチポチ選べば作成できる.
設定はS3を選んで,権限を選んで,対象リソースや対象オブジェクトを指定する.
具体的には,以下の通り.(ListAllMyBucketsにobjectの指定は不要なので,設定後にListAllMyBucketsだけ別グループに自動で切り出される)

サービス:S3
アクション(リスト):ListAllMyBuckets, ListBucket
アクション(読み込み):GetObject
アクション(書き込み):DeleteObject, PutObject
リソース(bucket):arn:aws:s3:::tmp.hadacchi.com
リソース(object):arn:aws:s3:::tmp.hadacchi.com/*

最後にReview policyを選んでからポリシーセットに名前をつけてcreate policyで作成できる.

IAMの作成(ユーザ作成)

今作ったポリシーを付与するユーザを作る.

とりあえずCLIからアクセスするキーさえあれば良い.

上で作成したポリシーをアタッチする.

で,スクロールして右下の確認→作成で完成.
次の画面のアクセスキーとシークレットアクセスキー(要はID/PW)はこの画面でしか確認できないので,ダウンロードしておく.
(もし確認を忘れたら,新しいキーを発行すれば良い.それは割愛する)

得たアクセスキーとシークレットキーにawscliに設定

~/.local/bin/awsへ設定を付与する.
Tokyo regionはap-northeast-1.

aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: ap-northeast-1
Default output format [None]: json

設定がうまくできていれば,バケット一覧(aws s3 ls)が見れるし,バケット内(aws s3 ls s3://BUCKETNAME)も見れる.
下の例はindex.htmlを置いてみた後の実行結果.

aws s3 ls
2018-07-01 15:42:56 tmp.hadacchi.com
aws s3 ls s3://tmp.hadacchi.com
2018-07-01 15:44:17       3417 index.html

コンテンツアップロード

サイト内コンテンツへのリンクを相対パスで書いていれば,今のpublic_html以下をそのまんまputすれば静的コンテンツだけは動く.
下のコマンドの例では,public_htmlというディレクトリは作成されない.(public_html/index.htmls3://tmp.hadacchi.com/index.htmlになる)
※注意: 以下のコマンドラインでアップロードしたところで,phpは動作しないので,当然ながらwordpressも動作しない.

aws s3 cp --recursive public_html s3://tmp.hadacchi.com

web公開設定の確認

文献[2]に記載の通りs3 website hostingのエンドポイントに書かれたURLへアクセスすれば,静的コンテンツであれば表示されるはず.
更に自分のDNSレコードをCNAMEでこのエンドポイントのFQDNに転送すれば,独自ドメインで引ける.この時,バケット名が独自ドメインと合致してないとエラーが出る.

wordpressの静的コンテンツ化

[1]の通りなんだけど,nginxを使っていると.htaccessを使ったrewriteが走らないためpermalinkの設定が反映されずハマる.

permalinkの設定反映

個人的にurlにはコンテンツに関する情報が入って欲しくないので,idで設定する.
%post_id%.html でOK

nginxの設定ファイルでrewriteを記述

[3]の方法でphp-fpmにpathを送ってあげれば良くて,重要なのは以下に改変して抜粋したこの部分.
なぜか我が家の環境では最後の1行だけで動作する.

    if (!-e $request_filename) {
        #rewrite ^.+?(/wp-.*) $1 last;  # ←なくても動く
        #rewrite ^.+?(/.*\.php)$ $1 last; # ←なくても動く
        rewrite ^ /wp_blog/index.php last;
    }

timeout値の変更

次の手順のstaticpressのrebuildでタイムアウトによりエラー停止することがあるので,事前に伸ばしておく.
だいたい500sで私はうまくいった.
設定場所は上のrewriteを追記したserverディレクティブの中で,php-fpmを呼び出しているところ.


     location ~ \.php$ {
         # With php5-fpm:
+        fastcgi_read_timeout 500s;
         fastcgi_pass unix:/var/run/php5-fpm.sock;
         fastcgi_index index.php;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

staticpressのbasic認証のところを改変

もし,wordpress本体側にBASIC認証をかける場合,staticpressのBASIC認証周りはバグ(?)で設定ページでどれだけBASIC認証情報を入れてもDBにその情報を記録してくれないので,ハードコードするかDBに書き込んでおくかしなければならない.
方法は文献[[4]](#cite4)を参照.
ハードコードするとすげー早くなったので,ハードコードオススメ.

--- class-static_press_admin.php.org
+++ class-static_press_admin.php
@@ -56,7 +56,8 @@
 	}
 
 	static public function basic_auth(){
-		return get_option(self::OPTION_STATIC_BASIC, false);
+		//return get_option(self::OPTION_STATIC_BASIC, false);
+		return "XXXXXXXXXXXXXXXXXXX";
 	}
 
 	static public function timeout() {

XXXXXXXXXXXは「ID:PW」なる文字列をbase64にかけたもの.
以下で得られる文字列である.(python2.Xの場合は,.encode('ascii')はいらない.)

>>> import base64
>>> print(base64.b64encode('hoge:fuga'.encode('ascii')))
b'aG9nZTpmdWdh'

staticpressでbuild

staticpress optionから設定.
Static URLはs3でアクセスするためのドメインtmp.hadacchi.comとしておく.その下のパス名は,s3にアップロードする時のディレクトリ名を指定すれば良いので,ルートに置く場合はなくても良い.
SaveDIRはstaticpressがdumpするhtmlの格納先のディレクトリ名で,ubuntuの場合はwww-dataに書き込み権限がないとエラーとなる.

あとは,staticpressのRebuildボタンで生成されるのを数分まつ.

アップロード

fromで指定したディレクトリの下のファイルを,toで指定したディレクトリの直下に置く,と覚えておく.

aws s3 cp --recursive /home/hoge/public_html/wp_blog/static/wp_blog s3://tmp.hadacchi.com/wp_blog

DNSの設定(S3を直接指定)

S3のwebhostingのエンドポイントを確認する.
エンドポイントのアドレスで,まずコンテンツが表示されるはず.(内部リンクはつながらないけど)

次に,DNSでこのエンドポイントに飛ぶよう CNAME を設定する.bindを例にすると,こんな感じ.
末尾のピリオドを忘れるとgTLDとか親レベルのドメイン名(ここではhadacchi.com)が勝手に補完されるので注意.

tmp   IN   CNAME tmp.hadacchi.com.s3-website-ap-northeast-1.amazonaws.com.

この時点で,DNSの設定をCNAMEでwebページは表示されるようになっているはず.

CloudFrontでSSL化と独自ドメインからの参照の設定

証明書の作成 (Certificate Manager)

CloudFrontの設定といいつつ,Certificate Managerで証明書を先に作る.

ここでのハマりポイントは認証.

DNSの認証の場合,レジストラのDNSサービスに乗っている人だと,レジストラの設定ページに依存するので各自で当該サービスに問い合わされたい.

ここで上の「DNSの認証」を選択すると,このようなCNAMEの設定をDNSに加えることが求められる.

これを設定しようと思うと,以下に相当する設定をレジストラのDNS設定ページから登録する必要がある.
各FQDNの最後のピリオドを忘れると,gLTD(ここではhadacchi.com)が補完されるので注意.

_15370fbba1c4b1cadb21f882e5078517.tmp	IN	CNAME	_39dc4142a943daade594b688b198dfc5.acm-validations.aws.
; または
_15370fbba1c4b1cadb21f882e5078517.tmp.hadacchi.com.	IN	CNAME	_39dc4142a943daade594b688b198dfc5.acm-validations.aws.

Eメールの場合,admin@,webmaster@,postmaster@などよくあるユーザ名にメールが送付されてくるので,それらメールで受け取った情報から認証する.
こちらの場合,MXレコードを設定しメールを受けられるようにしていないとうまくいかない.

いずれの方法を取るにせよ,ドメイン管理ができていれば大丈夫なはずなので,ここでは認証できたものとする.
Certificate Managerで認証が通って証明書が発行されると,CloudFrontの設定の途中で独自ドメインのSSLを参照できる.

CloudFrontの設定

CloudFrontのサービスページから「Create Distribution」をクリックしコンテンツ配信設定を作る.
続いて「Web」の方のGetStartedから開始する.

その次の画面で設定するのは,多分赤枠のところくらい.

「Origin Domain Name」に入力しようとするとドロップダウンリストでS3の公開設定されているリソースなどが表示されるので,該当のものを選ぶ.
「Viewer Protocol Policy」はお好みで.私は「Redirect HTTP to HTTPS」が好みだけど,今は実験的に「HTTP and HTTPS」にしている.

下へスクロールして続き.

「Alternate Domain Names」に独自ドメイン名を入れる.
「SSL Certificate」で「Custom SSL Certificate」を選択すると,その下の入力ボックスにお待ちかねの上(Certificate Managerの設定)で発行した証明書が入るので,Alternate Domain Namesと合うものを選択する.
すぐ下のCustom SSL Client SupportはSNIのみにしておかないと鬼のような請求が来るので注意.
世界各地のClourFrontのエッジの固定IPを占有するんだろうから,仕方ないけど.

更にスクロールして,設定するのはTSLやHTTPのバージョンくらいか.
Security Policyは,私の周りではTLSv1.2のみで何の問題も起きてないけど,古いブラウザや設定に対応したいならTLSv1.1とかv1でないとダメかも.
Supported HTTP Versionsは,もともと個人サイトでSSLを導入するモチベーションはHTTP/2による転送の高速化くらいだと思うんで,HTTP/2を選べば良いと思う.

DNSの設定(CloudFront)

CloudFrontのWebコンソールに「Domain Name」という列がある.これがCloudFrontのエッジを指定する時のSNIによるドメイン名(FQDN)であるので,自分の独自ドメインからCNAMEでこのFQDNを指すように設定してやれば良い.
設定の方法は,Certificate Managerの設定を参照されたい.

配信

以上を設定して「Create Distribution」を押せば完了だが,この設定をエッジに配布するのに15分くらいかかる.
また,15分経過するとAWSのコンソール上でStatusがProceedからDeployedになるが,実際にhttpアクセスが通るまでにもう少しかかる印象.
そのため,これまでの手順に漏れやミスがあってもCloudFrontの設定配信が切り分けのボトルネックになる.

以上のことから,まずはCloudFrontなしで全てのページが表示されることを確認した上で,CloudFrontの設定を行なうのが良い.

参考文献

[1] WordPress + StaticPress S3で静的WebサイトをS3でホストする - Qiita
[2] 独自ドメインを使ってAmazon S3で静的Webサイトをホストする - Qiita
[3] nginx で WordPress のパーマリンク設定を使用する - 暇人じゃない
[4] StaticPressとS3で爆速で激安な静的サイトを作ろう

確定申告メモ

書いた気になって忘れてたからここに書いておく

配当金の申告年度

  • 支払確定日の年の申告に含める

配当金の確定申告の種別

  • 確定申告しない(源泉徴収済の場合)
    • 20.315%
  • 確定申告する
    • 総合課税
      • 所得税率+住民税率
      • 配当控除が適用される
    • 申告分離課税
      • 損益通算の対象となる

UbuntuでCitrix Receiverを使ってVPN越しにRDPする時のtips

firefoxにCA証明書を登録してるのに,証明書がtrustedじゃないよって怒られる時のtips

前提

  • VPNを受けてRDPを受け付けるサーバ側は用意されているものとする.
    勤務先とか勤務先とか勤務先とか
  • 必要な証明書はcrtとかcerとかのファイルがあるものとする

手順

  1. firefoxをインストール.ubuntuのdesktopを入れてたら最初から入ってるかも
  2. Citrix Receiverをインストール.
  3. 証明書をインストール
    • 個人証明書
    • サーバ証明書
  4. 指定されたURLにアクセスして認証を通す
  5. ここで,Citrix Receiverに怒られる場合,firefoxのcertをCitrixが読めるようリンクを貼る
    sudo ln -s /usr/share/ca-certificates/mozilla/* /opt/Citrix/ICAClient/keystore/cacerts
  6. それでもダメな場合,firefoxに取り込めてない可能性があるので直接コピっちゃう
    sudo cp /path/to/cert.crt /opt/Citrix/ICAClient/keystore/cacerts

    1. 証明書がちゃんと入っていたら,ブラウザのセッションは維持したまま,icaを落とし直してreceiverを起こし直せば動く

updatedbのエラー回避

crontabで定期実行しているupdatedbが吐く/run/user/*/gvfsへのパーミッションエラーを避けたい

updatedbはlocateでファイル検索する時のDB更新コマンド.用途から考えて/run/user配下は検索する必要がないので,crontabで呼び出す時に検索パスから外すオプションをつければ良い.

updatedb --prunepaths=/run/user

これはubuntuの場合.ディストリによっては=でつながないらしいので注意.複数パスを外す場合は

updatedb  --prunepaths='/run/user/110 /run/user/1000'

みたいにする.

threading.Threadの使い方

よく忘れるので.
docoptは入れて使ってくらはい.他のはanaconda3-4.4.0で入ったと思う.

この記事は次の記事を参考にしている.
実行中のスレッドに対し外から操作をする - Qiita
ただし,私はスクリプトの外から操作をしたかったので,イベントハンドラから呼んでみた.
あと終了処理を入れたかったので無駄に関数を作って呼び出し順などを確認できるようにしてみた.
withは使ってないからenterとexitはいらんかった.

__file__ を test.pid で一括置換した名残が何か残ってるけど気にせんとってください.(abspathとかdirnameとかbasenameとかんとこ)

# スレッドを3つ開始
# 1つはインスタンスで生成
# 2つはサブクラスで生成
# サブクラスの1つは自動的に3秒後に停止
$ python start.py
# SIGUSR1を送信してサブクラスのもう一つを停止
$ kill -USR1 $(cat test.pid)
# 停止スクリプトから停止
$ python stop.py

fontconfigのエラー

ubuntuで突然,GUIプログラムを起動すると

Fontconfig warning: "/etc/fonts/conf.d/30-metric-aliases.conf", line 84: Having multiple  in  isn't supported and may not work as expected

みたいなエラーと

Unable to update the static FcBlanks: 0x0601

みたいなエラーが大量に出るようになって困った.

前者は該当ファイルを一つ一つ開いて,<alias>ディレクティブ内で複数の<family>をまとめて1つの<family>にエイリアスしているところを,別<alias>に展開することで解消.

具体的にはこんな感じ
Fixing Warning Messages About Font Configuration

後者はエラーの出てるコードだけ消せばいいのかもしんないけど,メンドクセーので/etc/fonts/fonts.confの<brank>ディレクティブを全消しで解消.

findでまとめてパーミッション変更

追記

ここ(ファイルやディレクトリのパーミッションを一括で置換したい - Qiita)のコメント欄の内容が神すぎたので自分でも忘れないよう転記.
この「X」しらんかった.

chmod -R a=rX,u+w path/to/dir

sambaでファイルサーバを運用している時に,別ユーザでのアクセスが問題になることがまれによくある
なのでディレクトリは755に,ファイルは644にしたい

基本

# まとめてchmodに渡す.数が多いとコマンドの上限文字数を越える
$ find . -type d -exec chmod 755 {} +
# 1つずつchmodに渡す.数が多いとえらい時間がかかる
$ find . -type d -exec chmod 755 {} \;

xargsとの組合せ

# まとめてchmodに渡す.数が多いとコマンドの上限文字数を越える
$ find . -type d -print0 | xargs -0 chmod 755
# 20ずつまとめてchmodに渡す.上3つと比べるとマシ
$ find . -type d -print0 | xargs -0 -n 20 chmod 755

オブジェクトストレージでownCloud

バケットを作成する

.s3cfg がある場合,そこに記載のAPIユーザでバケットを作成してしまう.
ownCloudのユーザを分けたい場合,まずAPIユーザの作成から行なう.

APIユーザを作成したら,APIユーザのAccess KeyとSecret Keyが発行されているはずなので,コピーする.
.s3cfgの他に設定ファイルを作成して-cオプションで読み込ませても良いし,s3cmdのコマンドラインオプションに与えても良い.

で,APIユーザのアクセスキーをもってmb (バケット作成)すればバケットの準備完了.

ownCloudに外部ストレージを使用させる

ownCloudのアプリ追加から External Storage Supportを有効化する.
続いて管理画面の外部ストレージからS3を選択し,オブジェクトストレージの設定を入れる.

バケットに作成したバケット名を入れる.
ホストには,s3cfgで言うところのhost_baseを入れる.
アクセスキーとシークレットキーも指定する.
ポートは不要(?)

以上をうまく設定できれば,外部ストレージの一覧の画面で名前の左の赤い四角が緑の丸になるはず.
その状態で接続成功しているのでownCloudのホームに戻ると,ルートに設定したオブジェクトストレージ名のディレクトリが作成されているはず.
あとはファイルを移して気長に待つ.

vim+previm+MathJaxでmarkdownに数式を書く

必要なもの

  • vim
  • vim-markdown
  • previm
  • open-browser

前提

NeoBundleは設定済とする

設定

NeoBundle 'plasticboy/vim-markdown'
NeoBundle 'kannokanno/previm'
NeoBundle 'tyru/open-browser.vim'

NeoBundleLazy 'kannokanno/previm', {
\    'depends':   'open-browser.vim',
\    'filetypes': 'markdown',}

MathJax対応

~/.vim/bundle/previm/にprevimがある場合.

MathJaxの読み込みをテンプレートに追記.

@@ -5,6 +5,13 @@
         Preview
         
         
+        
+        
     
     
         

previmの処理後にMathJaxを呼び出すらしい.
ついでに$でインライン数式モードを使えるようにする.
これにより,$$で数式ブロックを,$でインライン数式を書けるようになる.

@@ -84,6 +84,10 @@
       Array.prototype.forEach.call(_doc.querySelectorAll('pre code'), hljs.highlightBlock);
       autoScroll('body', beforePageYOffset);
       style_header();
+
+      // for MathJax
+      MathJax.Hub.Config({ tex2jax: { inlineMath: [['$','$'], ["\\(","\\)"]] } });
+      MathJax.Hub.Typeset(document.getElementById("preview"));
     }
   }

使い方

markdown を書いて,:PrevimOpen でプレビューする.
好きにコマンドを割り当てても良いと思う.

xmonad on ubuntu 16.04 でバックライトを調整

経緯

VAIO Pro 13 に入れていた 14.04 を 16.04 に変えたら,xbacklight が動かなくなったので自分でコマンドを作ってみた.

使い方

下のコードをbglightという名前でPATHの通ったところに置いたとすると

sudo chmod 666 /sys/class/backlight/{バックライト名}|/brightness  # 一般ユーザに書き込み権限を与える
$ bglight  # 現在の照度を表示する
30
$ bglight +  # 最大値まで10ずつ照度を増加させる
$ bglight -  # 0まで10ずつ照度を減少させる

コード

これは,バックライト名がintel_backlightの場合.