🍏

Misskeyのfilesをs3にあげてurlを解決するメモ

2023/03/20に公開

Misskeyでは、ユーザがアップロードしたファイルをバックエンドの/files以下に保存するか、s3互換のオブジェクトストレージに乗せるか選ぶことができます。
しかし、/files以下にホストした場合、 https://misskey-url/files/{filename}のようなホストになり、s3に設定を変更して乗せ換えたところで、urlが一致しないので簡単には移行できません。DBをいじってreplaceとかもできますが、それだと連携先に配送されたリンクが解決できなくなります。
なので、以前のURLで移行先のs3にリンクする必要があります。
僕のインスタンスでは前段にnginxがいるので、そこの設定だけでなんとかしましたというメモです。 正しい保証はしません。

環境

  • Ubuntu 20.04
  • nginx (luaモジュール入り)
  • misskey 13.9.1

ファイル移動

移動に気を付ける点は、content-typecontent-dispositionをつけてs3にあげる必要があることです。データはmisskeyのDBのdrive_fileテーブルにありますが、僕はまだ1万ファイル程度だったので、すべてのファイルにGETを飛ばしてヘッダをそのままs3に付け替えました。

Nginxの設定変更

各々変更が必要な個所は {}で囲んであります。適宜変更してください。

server {
        listen 80;
        server_name {server_name};
        client_max_body_size 100M;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        location ~ ^/proxy/(.*)$ {
            rewrite_by_lua_block {
                local uri_args = ngx.req.get_uri_args()
                local modified = false

                local target_param = "url"
                local old_domain = "{昔のfilesの場所}" #例 "misskey.example/files"
                local new_domain = "{新しいs3のfilesの場所}" #例 "s3.example/files"

                if uri_args[target_param] then
                    local v = uri_args[target_param]
                    if type(v) == "table" then
                        for i, value in ipairs(v) do
                            local new_value = string.gsub(value, old_domain, new_domain)
                            if new_value ~= value then
                                uri_args[target_param][i] = new_value
                                modified = true
                            end
                        end
                    else
                        local new_value = string.gsub(v, old_domain, new_domain)
                        if new_value ~= v then
                            uri_args[target_param] = new_value
                            modified = true
                        end
                    end
                end
                if modified then
                    local new_args = ngx.encode_args(uri_args)
                    local new_uri = ngx.var.uri .. "?" .. new_args
                    return ngx.redirect(new_uri, ngx.HTTP_MOVED_PERMANENTLY)
                end
           }
                proxy_pass http://{misskeyのバックエンド};
        }

        location ~ ^/files/(.*)$ {
            return 302 https://{新しいs3の場所}/files/$1;
        }

        location / {
                proxy_pass http://{misskeyのバックエンド};
        }
}

Discussion