さくらのレンタルサーバにgit-ftp

git-ftpについて簡単な説明

git-ftpは、gitのサブコマンドとして作られたFTPクライアントです。

git-ftpではサーバー側に .git-ftp.log ファイルを設置し、その中に現在サーバー上にアップされているコミットIDを保存しています。
それによりコミットIDでサーバーとリポジトリの差分が比較可能となり、必要なファイルのみアップされる仕組みになっています。

git-ftp でファイルをアップロード

git-ftpを使用する場合、初回アップロードは基本的に init サブコマンドを使用します。

git ftp init -u <ユーザー名> -p <パスワード> --force --syncroot public ftp://<ホスト名><アップ先のパス>

init コマンドによって、 .git-ftp.log ファイルの生成と、ファイルのアップロードが行われます。
この際、既に同名ファイルが存在する場合は上書き保存されてしまうため、アップ先のパスが正しいか不安という場合は catchup サブコマンドを使いましょう。

git ftp catchup -u <ユーザー名> -p <パスワード> ftp://<ホスト名><アップ先のパス>

catchup サブコマンドでは .git-ftp.log ファイルの生成のみ行われます。
意図したパスに .git-ftp.log が生成されていることが確認できたのち、一度 .git-ftp.log を削除し、再度 init サブコマンドを実行すれば確実です。(.git-ftp.log を削除しない場合、サーバーとリポジトリのコミットIDが同じになるためリポジトリ側で改めてコミットする必要がある)

さくらのレンタルサーバに git-ftp でアップロード

アップロード先がさくらのレンタルサーバの場合でもgit-ftpを使用できます。

国外IPアドレスフィルタ

まず、git-ftpに直接関係しませんが、さくらのレンタルサーバには国外IPアドレスフィルタという機能が存在します。

GitHub Actionsなどの自動デプロイでgit-ftpを使用する場合はこちらの設定を変更する必要があるでしょう。

ホワイトリストで許可するIPアドレスを指定する方法があるみたいですが、ざっと調べた感じだとGitHub Actionsの場合はIPアドレスが頻繁に変わるようなので無効にするしかないかもしれません。

オプションの設定

git ftp init -u <ユーザー名> -p <パスワード> --force --syncroot <ローカル側のパス> ftp://<ホスト名><アップ先のパス>
<ユーザー名>FTPユーザー
<パスワード>FTPパスワード
<ローカル側のパス>リポジトリ内のアップロードするファイルのパス(dist など)
<ホスト名>FTPホスト名(おそらく、<ユーザー名>.sakura.ne.jp)
<アップ先のパス>ユーザー用のディレクトリからのパス(/wwwなど)

基本的に難しい設定はありませんが、アップ先のパスだけちょっと引っかかるかもしれません。

GUIのFTPクライアントで接続すると /home/ユーザー名/www/ に接続されるようですが、git-ftpで設定するアップロード先のパスには /home/ユーザー名 は必要ないので注意が必要です。

また、--force を使って対話的な質問を無効にしています。こちらも自動デプロイからgit-ftpを使う場合は設定しておいたほうがよいでしょう。

初回以降のアップロード

初回以降のアップロードには push サブコマンドを使用します。

git ftp push -u <ユーザー名> -p <パスワード> --force --syncroot <ローカル側のパス> ftp://<ホスト名><アップ先のパス>

オプションは init と全く同じなので迷うことはないかと思います。

SVGファイルをサーバ側で圧縮する

SVGファイルの実態はシンプルなXMLなので、HTMLやCSSと同じようにサーバ側での圧縮が可能です。方法としては以下の3つが考えられるでしょう。

  1. mod_deflate を使って圧縮する方法
  2. 事前に圧縮し、SVGZファイルとして配信する方法
  3. 2の方法にgzip非対応ブラウザ用のフォールバックを追加した方法

以下の動作確認は全て Apache 2.4.34 で行なっています。

mod_deflate を使って圧縮する方法

mod_deflate は HTTPリクエストの Accept-Encoding ヘッダーをもとに、ブラウザが gzip に対応している場合のみ圧縮を行います。

gzip に対応していないブラウザでも(圧縮はされないものの)、画像が表示されなくなるといったことはありません。しかし、リクエストのたびに圧縮を行うため、サーバの負担が大きくなるというデメリットがあります。

設定方法

まず、mod_deflate が有効になっていない場合は httpd.conf を修正して有効化する必要があります。

LoadModule deflate_module modules/mod_deflate.so

次に .htaccess (またはhttpd.conf)で SVGファイルが圧縮されるように AddOutputFilterByTypeディレクティブを指定します。

AddOutputFilterByType DEFLATE image/svg+xml

デモ(圧縮無し)
デモ(mod_deflate での圧縮)

SVGZファイルとして配信する方法

SVGファイルを gzip で圧縮したものを SVGZファイルと呼びます。

事前にファイルを圧縮しておくことでサーバの負担を減らすことができます。そのかわり常に gzip で圧縮したファイルを返すため、gzip に対応しないブラウザではファイルを正常に扱えず、表示できなくなります。

設定方法

まず SVGファイルを gzip コマンドで SVGZファイルに変換します。

$ gzip ebi.svg
$ mv ebi.svg.gz ebi.svgz

そして .htaccess で、SVGZファイルが gzip で圧縮されていることをクライアントに知らせるために AddEncoding ディレクティブを使用します。

AddEncoding x-gzip .svgz

デモ(SVGZ での圧縮)

SVG、SVGZ の両ファイルを用意して配信する方法

上記で紹介した方法の『gzip非対応ブラウザで表示されなくなる』というデメリットを補う方法です。あらかじめ SVGファイル、SVGZファイルの両方を用意しておき、gzip 対応ブラウザには SVGZファイルを、非対応ブラウザには SVGファイルを返します。

設定方法

SVGファイルのリクエスト時にSVGZファイルを返す処理を行うには mod_rewrite を使います。そのため、まず mod_rewrite が有効になっていない場合は httpd.conf で有効化する必要があります。

LoadModule rewrite_module modules/mod_rewrite.so

そして .htaccess で以下の設定をします。

AddEncoding x-gzip .svgz

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} \.svg$
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME}z -s
RewriteRule .+ %{REQUEST_URI}z [L]

AddEncoding ディレクティブは上記の方法と同じように SVGZファイルが gzip 圧縮されていることを示しています。

次の段落のリライトルールでは、『リクエストされたファイルがSVGファイルかどうか』、『リクエストの Accept-Encoding ヘッダに gzip が含まれるか』、『対応するSVGZファイルが存在するか』を一つずつ検査し、全てに該当するリクエストの場合にのみ SVGZファイルを返すよう指定しています。

これによってサーバの負担を減らし、なおかつ gzip 非対応ブラウザでも表示できるようになります。

デモ(SVGとSVGZをリクエストによって切り替え)

おわり

.htaccess の編集や gzip コマンドでの圧縮など、手間はかかりますが、SVGファイルをサーバ側で圧縮する場合は3つめの方法が一番良いと思います。

『gzip に対応していないブラウザ』と何度か書きましたが、実際のところそんなものは今の時代使われてないでしょう。そのため2つ目の方法でも動作しないということはほぼないと思います。

重要なのはリクエストの Accept-Encoding を見て、適切なレスポンスを返すことです。ちゃんと Accept-Encoding を見ることで、仮に宗教上の理由で gzip が使えなかったり、あるいは gzip に重大な脆弱性が見つかり gzip を完全廃止する世界がやってきた場合でも、gzip を使用するかどうかの判断をユーザに委ねることができます。

どこまでクライアント側の事情に対応するかが難しいところですが、HTTP自体の仕様にAccept-Encoding がある以上はそれに準拠した動作の方が望ましいでしょう。

.htaccessによるIPアドレスでのアクセス制御

Apache2.4以前まではDenyAllowといったディレクティブを使用していましたが、Apache2.4以降それらは非推奨となり、代わりにRequireディレクティブを使用するよう変更されました。

全てのアクセスを拒否

Require all denied

特定のIPアドレスからのアクセスのみ許可

Require ip 192.168.0.1

複数指定

Require ip 192.168.0.1 192.168.0.2

前方一致での指定

Require ip 192.168

ネットワーク指定

Require ip 192.168.0.0/255.255.0.0

CIDRでのネットワーク指定

Require ip 192.168.0.0/16

参考URL

mod_authz_host のドキュメント
https://httpd.apache.org/docs/2.4/mod/mod_authz_host.html

.htaccessによるHTTPSへのリダイレクト

.htaccess を使用して、http://***.com へのアクセスを https://***.com へリダイレクトします。

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

リダイレクトにはmod_rewriteモジュールを使用します。

簡単な解説

mod_rewriteモジュールはルールベースの書き換えエンジンであり、まずリクエストされたURLを見て、ルールに従ってURLを書き換え、そして必要であれば書き換え後のURLへリダイレクトを促すという仕組みになっています。

RewriteEngine

そのためまず1行目で書き換えエンジンを有効化しています。デフォルトはOffなので、必ず必要になります。

RewriteEngine On

RewriteCond

2,3行目で書き換えのルールを記述しています。RewriteCondはどのURLを書き換えるかという条件を示す部分です。今回のケースでは「httpアクセスの場合」という条件であるため、以下のように記述しています。

RewriteCond %{HTTPS} off

.htaccess では多くの変数を使えます。上の%{HTTPS}もその一つです。%{HTTPS}にはリクエストがhttpsの場合はon、それ以外の場合はoffが格納されています。

RewriteCond の構文は以下のようになっており、

RewriteCond TestString CondPattern

TestStringCondPatternと一致するURLのみが、次のRewriteRuleにて書き換えられます。CondPatternは、今回は単純な文字列ですが、正規表現を使用することもできます。

RewriteRule

RewriteRuleは、どのように書き換えるかを示す部分です。今回は「URLのスキームをhttpsに書き換える」というルールなので、以下のように記述します。

RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

構文は以下のようになっており、

RewriteRule Pattern Substitution [flags]

基本的に正規表現を使って書き換えを行います。

今回はシンプルに、URL全体をhttps://%{HTTP_HOST}%{REQUEST_URI}に変換するようなルールになっています。%{HTTP_HOST}にはHTTPリクエストのHOSTヘッダの値、%{REQUEST_URI}にはリクエストのパスが入っています。

フラグには[R=301,L]を指定しています。まずR=301では、クライアントに対しリダイレクトを促し、その際のHTTPステータスコードを301にすることを記述しています。リダイレクトに使用されるステータスコードはいくつかありますが、恒久的な移動を示す301で良いと思われます。

もう一つのフラグLでは、このルール以降の書き換えルールは適用しないということを示します。今回のケースではこれ以降にルールはないため省略可能ですが、今後の追加などで他の設定とかち合う可能性もあるので書いておいてデメリットはないでしょう。

補足

この書き換えルールではURLの?以降にあるクエリ文字列も消えてしまうように見えますが、mod_rewriteでは特に指定がない限りクエリ文字列はそのまま残すようになっています。そのため、http://***.com?name=taro は https://***.com?name=taro のように、クエリ文字列の情報を残したまま、httpsに変換されます。

参考URL

mod_rewrite のドキュメント
https://httpd.apache.org/docs/current/mod/mod_rewrite.html

.htaccess で使用できる変数一覧
https://httpd.apache.org/docs/current/expr.html