SSH接続・CUI操作のLinux(Debian)にgoogle-drive-ocamlfuseをつかってGoogleDriveをマウントする

今日は、SSH接続・CUI操作のLinuxに[google-drive-ocamlfuse](https://github.com/astrada/google-drive-ocamlfuse)を使ってGoogleDriveをマウントする方法を書きます。

https://github.com/astrada/google-drive-ocamlfuse

## なぜやろうと思ったのか

最近、[GCPのSpot Virtual Machines](https://cloud.google.com/spot-vms?hl=ja)からGoogleDriveにファイルを移動させることが多々ありました。
その度に、
「VMから手元のPCにSSHでファイルをダウンロードする → GoogleDriveにアップロードする」
という方法を取っており、かなり工数がかかっていました。

今回は、この操作を楽にしたいと思い、直接VMからGoogleDriveにアップロードする方法として、GoogleDriveをVMをマウントさせました。

これにより、GoogleDriveの中身が、VMのディレクトリとしてみれるようになり、cpコマンドやmvコマンドが利用できるようになりました！

## 前提条件

- マシンスペック: Linux: Debian 11
- GoogleCloudPlatformのGoogleDriveAPIを有効にしてあること
- VMとは別に、ブラウザが利用できる端末をもっていること

## 設定方法

### 1. google-drive-ocamlfuseをインストールする

後述しますが、[公式](https://github.com/astrada/google-drive-ocamlfuse#getting-started)に書かれているPPA経由やDEBファイルからインストールする方法はうまくいきませんでした。

そこで、[こちら](https://linuxhint.com/install-google-drive-debian-11/)を参考に、opam経由でインストールしました。

```shell
sudo apt install opam -y
opam init # プロファイルの設定など不要なところはNを選択
opam install google-drive-ocamlfuse
```

インストールしたら、`~/.bashrc`に下記のパスを追加します。

```
PATH="$PATH:$HOME/.opam/default/bin"
```

これで、`source ~/.bashrc`をすれば、`google-drive-ocamlfuse`コマンドが使えるようになりました。


#### （失敗した方法その1）PPA経由でgoogle-drive-ocamlfuseをインストールした場合

[公式](https://github.com/astrada/google-drive-ocamlfuse#getting-started)のコマンドを入力してみたところ、

```shell
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:alessandro-strada/ppa
$ sudo apt update
```

下記のようなエラーになりました。

```shell
$ sudo apt update
Hit:1 http://deb.debian.org/debian bullseye InRelease
Hit:2 http://deb.debian.org/debian bullseye-updates InRelease
Hit:3 http://security.debian.org/debian-security bullseye-security InRelease
Hit:4 http://deb.debian.org/debian bullseye-backports InRelease
Hit:5 http://packages.cloud.google.com/apt cloud-sdk-bullseye InRelease
Hit:6 http://packages.cloud.google.com/apt google-cloud-packages-archive-keyring-bullseye InRelease
Hit:7 http://packages.cloud.google.com/apt google-compute-engine-bullseye-stable InRelease
Ign:8 http://ppa.launchpad.net/alessandro-strada/ppa/ubuntu mantic InRelease
Err:9 http://ppa.launchpad.net/alessandro-strada/ppa/ubuntu mantic Release
  404  Not Found [IP: 185.125.190.52 80]
Reading package lists... Done
E: The repository 'http://ppa.launchpad.net/alessandro-strada/ppa/ubuntu mantic Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
```

これは、[公式Wiki](https://github.com/astrada/google-drive-ocamlfuse/wiki/Installation#ppas-down)にも書かれているとおり、2020年以降使用できなくなっているようです。

#### （失敗した方法その2）DEBファイルからgoogle-drive-ocamlfuseをインストールした場合

[公式Wiki](https://github.com/astrada/google-drive-ocamlfuse/wiki/Installation#ppas-down)に書かれている手順に沿って、DEBファイルからのインストールも試しました。

```shell
$ sudo apt-get update
$ sudo apt-get install wget
$ wget https://launchpad.net/~alessandro-strada/+archive/ubuntu/ppa/+files/google-drive-ocamlfuse_0.7.30-1ubuntu1_amd64.deb
$ sudo dpkg -i ~/google-drive-ocamlfuse_0.7.30-1ubuntu1_amd64.deb
```

ここで下記のようなエラーになりました。

```shell
dpkg-deb: error: archive '/home/xxx/google-drive-ocamlfuse_0.7.30-1ubuntu1_amd64.deb' uses unknown compression for member 'control.tar.zst', giving up
dpkg: error processing archive /home/xxx/google-drive-ocamlfuse_0.7.30-1ubuntu1_amd64.deb (--install):
 dpkg-deb --control subprocess returned error exit status 2
Errors were encountered while processing:
 /home/xxx/google-drive-ocamlfuse_0.7.30-1ubuntu1_amd64.deb
```

ChatGPTに聞きならが調べましたが、[Debian11では.tar.zstをサポートしていない](https://unix.stackexchange.com/a/669008)ようでした。

### 2. GoogleDriveのOAuth認証をする

GUI操作が可能であれば、ブラウザを利用して認証が簡単にできますが、今回はCUIのみで操作していきます。

後述しますが、[公式Wiki](https://github.com/astrada/google-drive-ocamlfuse/wiki/Authorization#alternative-authorization-mode)にはデスクトップアプリの認証情報を利用するようにあります。ただ、これは現在利用できなくなっています。

幸い[issue](https://github.com/astrada/google-drive-ocamlfuse/issues/756)にある通り、すでにウェブアプリケーションで認証する方法は実装されており、今回はこちらを利用します。

https://github.com/astrada/google-drive-ocamlfuse/issues/756

#### GoogleDriveのAPIを有効にする

GCP上でGoogleDriveのAPIを有効にしておきます。

#### 認証情報を作成する

GCPの認証情報から、下記を追加します

![Screenshot 2023-05-25 at 16.11.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627146/6105989d-7184-4706-9f98-734e791778fb.png)

- 「OAuthクライアントID」
- アプリケーションの種類: ウェブアプリケーション
- 名前: 任意の表示名
- 承認済みのリダイレクト URI: http://127.0.0.1:8080/oauth2callback

作成すると、クライアントIDとクライアントシークレットが作成されます。

#### VMのgoogle-drive-ocamlfuseの設定を変更する

google-drive-ocamlfuseの接続設定は`~/.gdfuse/default/config`にあります。（後述しますが、defaultとあることから分かるように、ラベルをつけて複数の接続を管理することも可能です）

認証時に、リダイレクトできるように、vim等でVMの~/.gdfuse/default/configを下記のように書き換えます。

```diff
- oauth2_loopback=false
+ oauth2_loopback=true
```

これで認証する準備が整いました。

#### 作成した認証情報を使ってVMから認証する

作成した認証情報を使って、VMで下記コマンドを打ちます。

ヘッドレスで、認証情報を付与して認証します。

```shell
google-drive-ocamlfuse -headless -id トークンID -secret クライアントシークレットシークレット
```

このようにURLが表示されます。

```shell
Please, open the following URL in a web browser: https://accounts.google.com/o/oauth2/auth?XXXXX
Please enter the verification code: 
```

手元のMacなど任意のブラウザで上記のURLにアクセスし、GoogleDriveを使用したいGoogleアカウントで認証を行います。

認証が完了すると、ページが遷移しますので、その遷移したURLを参照します。
このURLの`code`パラメーターがVMに渡すべきコードになります。

例: URLが`http://127.0.0.1:8080/oauth2callback?code=1234&scope=https://www.googleapis.com/auth/drive`のとき、`1234`が認証コード


このコードを先ほどのVMのターミナルに入力します。


```shell
Please enter the verification code: 1234
```

これで、ターミナルで、`Access token retrieved correctly.`と表示されれば認証成功です。

#### (失敗した方法) デスクトップアプリの認証情報で認証する

[公式Wiki](https://github.com/astrada/google-drive-ocamlfuse/wiki/Authorization#alternative-authorization-mode)には、

> When creating a new client ID, you must select "Desktop app" as Application type

とあり、最初はデスクトップアプリの認証情報を作成して接続しました。

すると、ホストでの認証で、下記のようなエラーが発生しました。

![Screenshot 2023-05-24 at 15.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627146/66d2b1bd-49f0-63e9-97bd-98ca1717f954.png)

> Error 400: invalid_request The out-of-band (OOB) flow has been blocked in order to keep users secure. Follow the Out-of-Band (OOB) flow Migration Guide linked in the developer docs below to migrate your app to an alternative method. Request details: redirect_uri=urn:ietf:wg:oauth:2.0:oob

リンクを参照すると、リダイレクトを持たない手動コピー・貼り付けによる認証は2022年にサポートが終了したとのことです。

[https://developers.google.com/identity/protocols/oauth2/resources/oob-migration?hl=ja:title]

## 3. GoogleDriveのマイライブをマウント・アンマウントする

デフォルトでは、認証したGoogleアカウントのマイドライブにマウントします。
初回に、VM上でマウントさせるディレクトリを作成します。

```shell
mkdir ~/GoogleDrive
```

指定したディレクトリにマウントします

```shell
google-drive-ocamlfuse GoogleDrive/
```

ディレクトリをアンマウントします

```shell
google-drive-ocamlfuse -u GoogleDrive/
```

## 共有ドライブにマウント・アンマウントする

今回は共有ドライブにもマウントしてみました。

[公式のWiki](https://github.com/astrada/google-drive-ocamlfuse/wiki/Team-Drives)にも手順は載っています。

### 共有ドライブにマウント・アンマウントする方法

マウントしたい共有ドライブのチームIDを取得します。

マウントさせたいGoogleDriveのURLを表示し、URLのfolders以下がチームIDです。

例: `https://drive.google.com/drive/folders/XXX` -> チームID: `XXX`

これを、VMのgoogle-drive-ocamlfuseの設定ファイル`~/.gdfuse/default/config`に設定します。

```diff
- team_drive_id=
+ team_drive_id=XXX
```

すでに別のドライブにマウントしていた場合は、キャッシュを削除します。

```shell
fusermount -cc
```

これで、再度マウントすれば、ドライブの内容が見れるようになっているはずです。

### 複数のドライブを利用する

なお、複数のドライブを持つ場合や、共有ドライブを持つ場合、それぞれにラベルをつけることもできます。
これにより、設定ファイルもそれぞれ`~/.gdfuse/{label}/config`を持つことになります。
```shell
$ google-drive-ocamlfuse -label ラベル名
```

以上です。
これでファイル転送作業がグッと楽になりそうです！

## 参考サイト

公式Github。WikiやIssueを読み漁りました。

https://github.com/astrada/google-drive-ocamlfuse

Debianにgoogle-drive-ocamlfuseをインストールするときに参考にしました。

https://linuxhint.com/install-google-drive-debian-11


AWS内の仮想マシンに接続されたブログでした。デスクトップアプリ認証なので少しが異なりますが、認証周りで参考になりました。

https://www.servernote.net/article.cgi?id=use-google-drive-on-ssh-cui-only