Skip to content

Latest commit

 

History

29 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

google-drive-ocamlfuse - (ghcr.io/servercontainers/google-drive-ocamlfuse) [x86 + arm] on alpine

I've created this container to mount google drive shares on my host system, without the need of installing this ocaml stuff.

It's pretty easy to use: authorize once (see First authorization below), then just start the container and wait for the successful mount. The token is persisted, so this is a one-time step.

Make sure to mount the config directory /root/.gdfuse so the token and config will persisted.

After that, just mount your volume mountpoint to the gdrive mountpoint inside the container like this: /mnt/path/where/you/want/your/gdrive:/data:shared.

It's loosely based on https://github.com/Patricol/dockerfiles-public/tree/master/alpine/gdrive.

currently tested on: x86_64, arm64, arm

IMPORTANT!

In March 2023 - Docker informed me that they are going to remove my organizations servercontainers and desktopcontainers unless I'm upgrading to a pro plan.

I'm not going to do that. It's more of a professionally done hobby then a professional job I'm earning money with.

In order to avoid bad actors taking over my org. names and publishing potenial backdoored containers, I'd recommend to switch over to my new github registry: ghcr.io/servercontainers.

First authorization (required once)

Older versions shipped shared default OAuth client credentials, so you only had to open the authentication link from the logs. Google retired the copy-paste ("OOB") consent flow those relied on, and google-drive-ocamlfuse 0.9.x therefore ships no default credentials anymore — every user now brings their own OAuth client. Once authorized, the refresh token (and your client id/secret) are stored in the mounted /root/.gdfuse config and survive restarts and upgrades, exactly like before.

1. Create your OAuth client (Google Cloud console, ~5 minutes)

  1. Create a project (any name) and enable the Google Drive API (APIs & Services → Library).
  2. OAuth consent screen: type External, fill the mandatory fields, and set the app to "In production" (publish it). In "Testing" mode Google expires refresh tokens after 7 days — you would have to re-authorize every week. Publishing an unverified personal app is fine; the consent page just shows a warning you can click through (Advanced → continue).
  3. Credentials → Create credentials → OAuth client ID → type "Desktop app" — this gives you the xxxx.apps.googleusercontent.com id and the secret.

2. Authorize

Pass the credentials via the CLIENT_ID / CLIENT_SECRET environment variables (or -id/-secret below). A fresh Desktop client uses a loopback redirect: google-drive-ocamlfuse listens on 127.0.0.1:8080 and the consent page redirects there.

On a machine with a browser, simply start the container with the env variables set, open the URL from the logs, and grant access.

On a headless machine, tunnel your local browser to the container's loopback listener:

# terminal 1 - on your desktop
ssh -L 8080:127.0.0.1:8080 user@headless-host

# terminal 2 - on the headless host (one-shot; then start normally)
docker run --rm -p 127.0.0.1:8080:8080 \
  -v /path/to/config:/root/.gdfuse \
  --entrypoint google-drive-ocamlfuse \
  ghcr.io/servercontainers/google-drive-ocamlfuse \
  -id xxxx.apps.googleusercontent.com -secret your-secret -browser echo

-browser echo prints the consent URL instead of trying to open a browser — open it on your desktop, grant access, and the redirect flows through the tunnel back into the container, which stores the token and exits. Then start the container normally.

If Google answers with invalid_grant, the code expired — just run the authorization again.

Build & Versioning

You can specify DOCKER_REGISTRY environment variable (for example my.registry.tld) and use the build script to build the main container and it's variants for x86_64, arm64 and arm

You'll find all images tagged like a3.15.0-g0.7.23 which means a<alpine version>-g<google-drive-ocamlfuse version>. This way you can pin your installation/configuration to a certian version. or easily roll back if you experience any problems (don't forget to open a issue in that case ;D).

To build a latest tag run ./build.sh release

Changelogs

  • 2026-08-30
    • fixed startup crash-loop with google-drive-ocamlfuse 0.9.x (obsolete -f flag - the process stays in foreground by itself since the 0.8.0 dependency bump)
    • new CLIENT_ID / CLIENT_SECRET environment variables (0.9.x requires own OAuth client credentials for new setups)
    • entrypoint-level smoke test in CI that catches launcher/binary option drift
    • documented the new first-authorization flow (own OAuth client, loopback redirect, headless via ssh tunnel)
    • documented host prerequisites and mount propagation (:shared/:rslave) for consuming the mount from other containers with independent lifecycles
  • 2023-03-20
    • github action to build container
    • implemented ghcr.io as new registry
  • 2023-03-18
    • switched from docker hub to a build-yourself container
  • 2022-12-27
    • fixed broken build (opam depext etc.)
    • fixed url display problem in custom xdg-open
  • 2022-01-08
    • better build script
    • improved readme
    • version pinning
    • custom user / group creation - for better mapping
  • 2021-01-03
    • added bash to fix scripts and startup
  • 2020-11-20
    • removed unsupported arm 32 bit builds
  • 2020-11-18
    • initial creation
    • up-to-date build
    • multiarch support

Needed Options

  • device

    • /dev/fuse
  • cap-add

    • mknod
    • sys_admin
  • security-opt

    • apparmor:unconfined

Environment variables and defaults

  • PUID

    • optional
    • user id to map the google drive directory and files
    • default value: 0 (root)
  • PGID

    • optional
    • group id to map the google drive directory and files
    • default value: 0 (root)
  • MOUNT_OPTS

    • optional
    • additional mount opts
    • no default value
  • CLIENT_ID / CLIENT_SECRET

    • required for NEW setups (empty config volume) since google-drive-ocamlfuse 0.9.x - it no longer ships default OAuth client credentials
    • create your own OAuth client (Desktop app) in the Google Cloud console and pass id + secret here for the first authorization
    • existing config volumes keep working without these - the values are stored in the config after the first authorization

User Accounts (for usage with custom UID/GID)

  • GROUP_groupname

    • optional
    • value will be gid
    • example: GROUP_devops=1500 will create group devops with id 1500
  • ACCOUNT_username

    • optional
    • multiple variables/accounts possible
    • adds a new user account with the given username and the user id the env value
      • example ACCOUNT_foo: 1001 will create user foo with uid 1001
      • see docker-compose.yml user foo for an example how it's used/configured.
  • GROUPS_username

    • optional
    • additional groups for the user
    • to create groups look at GROUP_groupname or mount/inject /etc/groups file (can cause problems)
    • the username part must match to a specified ACCOUNT_username environment variable
    • one or more groups to add seperated by a ,
    • example: GROUPS_foo=musican,devops

Using the mount from other containers (mount propagation)

The whole point of mounting to a host path (:shared) is that other containers — a samba server, a media server, a backup job — can consume the Google Drive mount by binding the same host path. For that to work reliably, and for both containers to keep independent lifecycles (start / stop / restart either one without touching the other), three things must be true:

  1. The host must have the fuse module loaded (modprobe fuse, and make it persistent for boot — a missing module fails container creation with error gathering device information ... /dev/fuse).
  2. The host path's parent mount must allow propagation. Docker rejects :shared/:rslave binds with ... is not a shared or slave mount when the underlying filesystem is mounted private. Most systemd distros mount / shared by default; minimal/init-based systems often don't — fix with mount --make-rshared /your/mountpoint (and persist it in your boot sequence, before containers start).
  3. This container binds :shared, consumers bind :rslave.
    • :shared (here) pushes the FUSE mount out to the host.
    • :rslave (consumer) makes the consumer follow mount and unmount events on that path. That's what buys the independence: restart this container and the fresh mount propagates into the running consumer automatically; while it's down, the consumer just sees an empty directory instead of a stale or broken mount. A plain bind (no propagation flag) only sees whatever was mounted when the consumer started — after a gdrive restart it silently serves an empty dir until you restart the consumer too.
# this container
volumes:
  - /srv/gdrive:/data:shared

# any consumer container
volumes:
  - /srv/gdrive:/consumed/path:rslave

Samba integration

Since it was difficult to integrate with my samba system (permissions problem) I've enforced the user root. After that it worked nicely.

You can use the folder also inside your Samba configuration (servercontainers/samba)

Examples

If you want to share the folder using samba, make sure your user has the same UID/GID. Default is set to root which has UID: 0 and GID: 0.

In order to use it properly with samba, you can enforce user and group root or use the UID/GID of the user you want to use it with.

docker env for: servercontainers/samba

SAMBA_VOLUME_CONFIG_gdrive: "[GDrive]; path = /shares/gdrive; valid users = alice; guest ok = no; read only = no; browseable = yes; force user = root; force group = root"

and bind the host path with propagation (see the section above), so samba survives gdrive restarts without a restart of its own:

volumes:
  - /srv/gdrive:/shares/gdrive:rslave

plain stanza for: smb.conf

[GDrive]
 path = /shares/gdrive
 valid users = alice
 guest ok = no
 read only = no
 browseable = yes
 force user = root
 force group = root

About

google-drive-ocamlfuse - (ghcr.io/servercontainers/google-drive-ocamlfuse) on alpine [x86 + arm]

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages