9Drive is a storage gateway web app for connecting multiple Google Drive accounts into one virtual storage dashboard. Users can connect Google Drive accounts, t
9Drive is a storage gateway web app for connecting multiple Google Drive accounts into one virtual storage dashboard. Users can connect Google Drive accounts, t
9Drive is a storage gateway web app for connecting multiple Google Drive accounts into one virtual storage dashboard. Users can register with email/password or Google, automatically connect their first Google Drive account during Google sign-in, track quota, upload files into a dedicated 9drive Drive folder, organize files with virtual folders, preview files, sync MySQL from Google Drive, and let the backend route uploads to the Drive account with enough free space.
Copyright 2026 Zenhosta
Licensed under the Apache License, Version 2.0. See LICENSE for details.
9drive folder.POST /api/v1/uploads.9drive folder back into MySQL.update.sh directly from the Settings UI (PM2 setup).Live preview: https://9drive.zenhosta.com
backend/ Express API, Prisma schema, Google Drive integration
frontend/ Vite React appDefault database used by this project:
host: localhost
port: 3306
database: 9drive
user: root
password: emptyThe easiest way to prepare the project is using the automated setup script. It generates local environment files with secure keys, installs dependencies, and generates the Prisma client. MySQL 8+ must already be running for local development; Docker setup includes MySQL.
Make sure to open PowerShell and navigate to the project directory first. For example, if you cloned the project to E:\AUTO KLIK\9Drive:
# 1. Switch to the drive where the project is located (if necessary)
E:
# 2. Navigate to the project folder
cd "E:\AUTO KLIK\9Drive"
# 3. Run the automated setup script
powershell -ExecutionPolicy Bypass -File .\setup.ps1bash ./setup.shEnter your MySQL connection URL when prompted. Google Client ID/Secret can be skipped and configured later.
Once setup is complete, apply migrations and start backend and frontend in separate terminals:
cd backend
npm run prisma:migrate
npm run devcd frontend
npm run devIf you prefer to configure the project manually:
Install backend dependencies:
cd backend
npm installInstall frontend dependencies:
cd ../frontend
npm installCreate a database:
CREATE DATABASE 9drive;If using MySQL CLI:
mysql -u root -e "CREATE DATABASE IF NOT EXISTS 9drive;"Create backend/.env:
DATABASE_URL="mysql://root@localhost:3306/9drive"
APP_PORT=4000
FRONTEND_URL="http://localhost:5173"
JWT_ACCESS_SECRET="change-this-jwt-secret-at-least-32-chars"
TOKEN_ENCRYPTION_KEY="change-this-encryption-key-32bytes!"
ACCESS_TOKEN_TTL_SECONDS=900
REFRESH_TOKEN_TTL_DAYS=30
MAX_UPLOAD_BYTES=5368709120
RECAPTCHA_SECRET_KEY=""
# Used only by `npm run seed:google-config`.
# These values are encrypted and stored in DB as global Google OAuth config.
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
GOOGLE_REDIRECT_URI="http://localhost:4000/connected-accounts/google/callback"Important:
JWT_ACCESS_SECRET should be long and random.TOKEN_ENCRYPTION_KEY should be long and random.backend/.env.Create or confirm frontend/.env:
VITE_API_URL=http://localhost:4000
VITE_RECAPTCHA_SITE_KEY=Captcha is disabled when VITE_RECAPTCHA_SITE_KEY or backend RECAPTCHA_SECRET_KEY is empty. Set both values to enable captcha on registration.
cd backend
npm run prisma:migrateIf Prisma client generation is blocked on Windows by a running Node process, stop running backend/frontend dev servers and run:
npx prisma generateGoogle setup is done in Google Cloud Console, not Google Search Console. Google Search Console is for website indexing/search ownership. OAuth and Drive API are managed in Google Cloud Console.
Open Google Cloud Console:
https://console.cloud.google.com/APIs & Services -> LibraryGoogle Drive APIGoogle Drive API.Enable.Direct URL pattern:
https://console.developers.google.com/apis/api/drive.googleapis.com/overview?project=YOUR_PROJECT_IDIf Google Drive API is disabled, you will see an error like:
Google Drive API has not been used in project ... before or it is disabled.APIs & Services -> OAuth consent screenExternalApp name
User support email
Developer contact emailhttps://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profileFull Drive access is required so Google sign-in can connect the first Drive account automatically and sync files manually added to the 9drive folder.
Testing, add test users.Add every Google account that will test the app:
OAuth consent screen -> Test users -> Add usersIf you do not add test users, Google may show:
Access blocked: app has not completed the Google verification process
Error 403: access_deniedAPIs & Services -> CredentialsCreate Credentials -> OAuth client IDWeb applicationhttp://localhost:5173http://localhost:4000/connected-accounts/google/callbackClient ID
Client SecretPut values into backend/.env:
GOOGLE_CLIENT_ID="your-client-id"
GOOGLE_CLIENT_SECRET="your-client-secret"
GOOGLE_REDIRECT_URI="http://localhost:4000/connected-accounts/google/callback"Then run:
cd backend
npm run seed:google-configThis stores the Google OAuth config as a global encrypted provider config in MySQL. Google sign-in uses the same config and automatically connects the first Drive account. Logged-in users can still click Connect Drive in Settings to add more Drive accounts.
Start backend:
cd backend
npm run devBackend runs at:
http://localhost:4000Start frontend:
cd frontend
npm run devFrontend runs at:
http://localhost:5173This repository includes Docker files for running MySQL, backend, and frontend together.
Files:
docker-compose.yml
.env.docker.example
backend/Dockerfile
frontend/Dockerfile
frontend/nginx.confCopy the example env file:
cp .env.docker.example .envOn Windows PowerShell:
Copy-Item .env.docker.example .envEdit .env:
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=9drive
FRONTEND_URL=http://localhost:5173
VITE_API_URL=http://localhost:4000
VITE_RECAPTCHA_SITE_KEY=
JWT_ACCESS_SECRET=replace-with-long-random-secret
TOKEN_ENCRYPTION_KEY=replace-with-long-random-secret
RECAPTCHA_SECRET_KEY=
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GOOGLE_REDIRECT_URI=http://localhost:4000/connected-accounts/google/callbackCaptcha is disabled when either VITE_RECAPTCHA_SITE_KEY or RECAPTCHA_SECRET_KEY is empty.
docker compose up -d --buildServices:
frontend: http://localhost:5173
backend: http://localhost:4000
mysql: localhost:3306The backend container runs Prisma migrations automatically on startup:
npm run db:migrate:deployThis applies pending migrations such as S3 storage support before the API starts, so deployments from an older database can update safely without dropping data.
It also seeds the global Google OAuth config automatically when GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are set to real values in .env. If those values are blank or still placeholders, the backend still starts and logs a warning. Google connect/sign-in will be unavailable until you set real Google OAuth credentials and restart the stack:
docker compose up -d --buildAutomatic Docker startup seeding is usually enough. If you update Google OAuth values while containers are already running, seed the global Google OAuth config manually:
docker compose exec backend npm run seed:google-configThis stores GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI from Docker env into MySQL as encrypted global config.
docker compose logs -f backend
docker compose logs -f frontend
docker compose logs -f mysqldocker compose downRemove database volume too:
docker compose down -vJWT_ACCESS_SECRET and TOKEN_ENCRYPTION_KEY.VITE_API_URL changes because Vite embeds env at build time.VITE_RECAPTCHA_SITE_KEY changes because Vite embeds env at build time.Follow these steps to deploy 9Drive to a VPS (such as Ubuntu/Debian) using Docker:
sudo apt update
sudo apt install -y docker.io docker-compose
sudo systemctl enable --now dockergit clone https://github.com/your-gitNo open issues yet, or sync has not completed.