さくらのレンタルサーバーでminioのデータを読みたい（misskeyのデータ置き場にしたい)

## 前提

* どっかに[minio](https://min.io/)が立ち上がってる前提です
* [なるべく安く定額でS3互換ストレージを立ち上げたい](https://qiita.com/ityuki/items/c844c72fade65d9c50d2)の続編？です
* キャッシュのみ
* アドレスのIDをほぼ再利用しないmisskeyとかで使えるかも
* 今回も[さくらのレンタルサーバー スタンダード](https://rs.sakura.ad.jp/standard.html)を使います

## 解決案

CGIでminioのデータをキャッシュして使おうぜ！

## そもそものきっかけ

* [なるべく安く定額でS3互換ストレージを立ち上げたい](https://qiita.com/ityuki/items/c844c72fade65d9c50d2)の方法だと、ネットワーク使いすぎでは？
* CGIでminioのデータ吐きたい
* minio-clientってのがあるらしい　←　New!!

## 前準備

### minio-client (mc) 入れなきゃ

* さくらのレンタルサーバーはLinuxではなくFreeBSD！
* pkgもってきてバイナリだけ使う方向で（笑）

```sh
mkdir src
cd src
wget https://pkg.freebsd.org/FreeBSD:13:amd64/latest/All/minio-client-2024.01.31.08.59.40_1.pkg
tar xvf minio-client-2024.01.31.08.59.40_1.pkg
cd ..
mkdir bin
cp src/usr/local/bin/minio-client bin/mc
```

* これでbin/mcできた！

### mc初期設定

* 適当なalias名（今回は`media`を採用）で設定

```sh
bin/mc alias set media https://エンドポイント アクセスキー トークン
```

## CGI登録

* `www/` で作業

```conf:.htaccess
Options +ExecCGI
<Files "media">
SetHandler cgi-script
</Files>
```

```ruby:media
#!/usr/local/bin/ruby

ROOT="/home/アカウント名/キャッシュを置くディレクトリ名"

require 'cgi'

@cgi= CGI.new

path = @cgi.path_info

def error
  puts "Status: 403 Forbidden"
  puts ""
  puts "Forbidden"
  exit 1
end

error if path.nil? or path == ""

path = "/media" + path

if path =~ /^(\/[A-Za-z0-9_-]+)+\.[A-Za-z0-9_-]+$/
  # do nothing
else
  error
end

file = ROOT + path
dir = File.dirname(file)
if not File.file?(file)
  `mkdir -p '#{dir}' > /dev/null 2> /dev/null`
   l=0
   while (l < 3) do
     `/home/アカウント名/bin/mc --quiet cp 'media/#{path}' '#{file}' 2> /dev/null`
     l += 1
     break if File.file?(file) and not File.zero?(file)
     sleep 0.1
   end
end

if File.zero?(file)
  File.delete(file)
end

error if not File.file?(file)

print "Content-Type: "
print `file -i '#{file}' | cut -d ' ' -f 2`
puts ""
print `cat '#{file}'`
```

* mediaファイルに拡張子は付けないこと
* media以外のバケット名を使うときは、.htaccessのファイル名、`path = "/media" + path`の`media`文字列とファイル名を置き換えること

* 以下のコマンドでCGI有効化

```sh
chmod 700 media
```

* これで、`https://さくらのレンタルサーバーのアドレス/media/ほげほげ`が、元のエンドポイントのコピーを指すようになる

## 定期的に削除

`crontab -e`に、例えば以下のように書いておく

```conf
0 5 * * * find /home/アカウント名/キャッシュを置くディレクトリ名 -type f -atime +30 -exec rm -f {} \;
```

* これで、30日間アクセスされていないファイルは削除される(はず）

## misskeyに反映

* コントロールパネル　→　オブジェクトストレージから、Base URLを`https://さくらのレンタルサーバーのアドレス/media/`に設定

* これ以降のファイルはさくらのレンタルサーバー経由に

## ちなみに

見てわかるとおり、削除・更新やIDのコンフリクトには対応していません

がまぁ、misskeyのオブジェクトストレージとしてなら良いんじゃないかな。

## 結果

2回目以降のアクセスが早くなったよー！

## おまけ

さらなる高速化を目指した結果、こうなった！

1. mediaという名前のファイルをmedia.loadにリネーム
1. 新たなmediaという名前のファイルを以下の内容で記述

```php:media
<?php

//ob_start();
//ini_set('display_errors', "On");

function error(){
  header("HTTP/1.1 503 Service Unavailable");
  header("Content-Type: text/plain; charset=utf-8");
  header("Cache-control: no-store");
  header("Pragma: no-cache");
  header("Expires: -1");
  echo "Service Unavailable";
  exit;
}

$ROOT="/home/アカウント名/キャッシュを置くディレクトリ名";
$path = $_SERVER['PATH_INFO'];

if (preg_match('/^(\\/[A-Za-z0-9_-]+)+(\\.[A-Za-z0-9_-]+)?$/',$path) == 1){
 // OK
}else{
  error();
}

$file = $ROOT . "/media" . $path;

if (file_exists($file)){
  $finfo = new finfo(FILEINFO_MIME_TYPE);
  $mime_type = $finfo->file($file);
  if ($mime_type == "") {
    $mime_type = "binary/octet-stream";
  }
  header("Content-Type: " . $mime_type);
  header('Content-Length: ' . filesize($file));
  readfile($file);
}else{
  header("Location: " . $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['SERVER_NAME'] . "/media.load" . $path);
}

?>
```

.htaccessを次のように書き換える

```conf:.htaccess
Options +ExecCGI
<Files "media">
ForceType application/x-httpd-php
</Files>
<Files "media.load">
SetHandler cgi-script
</Files>
```

これでキャッシュがあるときはクソ早いphpを、そうじゃないときはruby-cgiを使って処理するようになりました