Browse Google Drive or your own storage from a Nintendo Switch.
Features · Get started · Home Storage · Controls · Self-host · Build
Switch Drive is a Nintendo Switch homebrew app for accessing Google Drive and self-hosted Home Storage providers. Browse remote folders, save files directly to the microSD card, and optionally install supported packages from the console.
Warning
Currently under active development. Core features are stable and functional, though you may still encounter minor bugs or UX issues while the project moves toward its first fully validated end-to-end release.
Important
NSP and NSZ operations require an Atmosphère console running Switch Drive in application mode. Only install packages you trust and are authorized to use.
- Phone-based Google OAuth pairing with a QR code or short URL and six-digit code—no Google credentials are entered on the Switch.
- Self-hosted Home Storage providers with LAN discovery, manual addresses, optional authentication, and a read-only host library.
- Direct downloads from the selected provider to
sd:/switch-drive/downloads/<task-id>/<filename>; file contents never pass through the pairing service. - Safe resume after interruption, guarded by provider identity, revision, ETag, HTTP range, expected size, and MD5 or SHA-256 metadata.
- Files of 4 GiB or more stored as native HOS concatenated files, avoiding the FAT32 per-file limit while preserving one logical filename on the Switch.
- Standalone NRO installation and transactional NSP/NSZ installation for one base game, update, or DLC per package.
- Downgrade protection, selectable SD/internal installation storage, interrupted-install recovery, and managed component removal that preserves save data.
- Local download library with optional package cleanup after installation.
- Controller and touch navigation in English (US), Portuguese (Brazil), and Spanish.
- Two interchangeable self-hosted pairing services: Node.js/Docker or Cloudflare Workers.
| Type | Download | Install | Notes |
|---|---|---|---|
.nro |
Yes | Yes | Standalone app in sd:/switch/<app-name>/ |
.nsp |
Yes | Yes | One base game, update, or DLC through NCM |
.nsz |
Yes | Yes | Streams NCZ into NCM; no intermediate NSP |
.xci, .zip, and other files |
Yes | No | Stored as regular downloads |
| Native Google documents | No | No | Metadata only; no export |
Note
Large-file support requires HOS 4.0.0 or later. On a FAT32 card viewed outside HOS, a concatenated file appears as a directory containing numbered segments. Keep that directory intact.
flowchart LR
S[Nintendo Switch] -->|start and poll pairing| P[Pairing service]
P -->|session and short-lived token| S
M[Phone browser] -->|Google OAuth approval| P
P -->|encrypted refresh token| DB[(PostgreSQL)]
P <-->|OAuth exchange| G[Google OAuth]
S -->|browse and download directly| D[Google Drive API]
S <-->|catalog and direct downloads| H[Home Storage]
H -->|read-only mount| L[(Host library)]
The pairing service holds the Google refresh token and returns a short-lived Drive access token to the console. Google Drive and Home Storage file data flows directly to the console; Home Storage does not depend on the pairing service.
- A Nintendo Switch capable of running homebrew with Atmosphère.
- A FAT32 or exFAT microSD card. FAT32 is recommended for homebrew setups.
- A built
switch-drive.nro, or the devkitPro toolchain to create it. - For Google Drive: a public HTTPS hostname and a Google Cloud OAuth 2.0 web client with the Drive API enabled.
- For Home Storage: Docker on the computer that hosts the library.
-
Enable the Google Drive API in a Google Cloud project.
-
Configure the OAuth consent screen. While the app is in testing mode, add each user as a test user.
-
Create an OAuth 2.0 Web application client.
-
Register this exact redirect URI, replacing the hostname:
https://drive.example.com/oauth/google/callback
Note
External OAuth apps in testing mode are limited to approved test users, and
their refresh tokens expire after seven days. The requested drive.readonly
scope is restricted, so review Google's
OAuth production requirements
and Drive scope guidance
before distributing a public deployment.
The quickest local-server deployment uses Docker Compose with PostgreSQL and Caddy:
cp server/.env.example server/.env
# Edit server/.env with the public hostname, OAuth client, and random secrets.
docker compose --env-file server/.env up --build -dSet PUBLIC_ORIGIN to the HTTPS origin used in Google Cloud and PUBLIC_HOST
to the hostname only. Generate TOKEN_ENCRYPTION_KEY and COOKIE_SECRET as
shown in server/.env.example, and choose a separate long random PostgreSQL
password. Caddy obtains and renews the TLS certificate.
Confirm the public endpoint before configuring the console:
curl https://drive.example.com/healthFor the serverless alternative, follow the Cloudflare Worker deployment guide.
Copy the NRO and create the service configuration:
sd:/
├── switch/
│ └── switch-drive/
│ └── switch-drive.nro
└── switch-drive/
└── config.json
config.json must contain the public HTTPS origin in this compact form:
{"service_url":"https://drive.example.com"}Launch Switch Drive from Sphaira or hbmenu. Use a title override—hold R while opening a game—for NSP/NSZ installation and removal. Browsing and regular downloads remain available in applet mode, where the app displays a warning.
- Choose Connect Drive.
- Scan the QR code, or open the displayed URL and enter its six-digit code.
- Approve read-only Drive access, return to the Switch, and press A to check the pairing.
- Open Files, select a file, then press X to download or Y to download and install.
Pairing requests expire after ten minutes. Connecting another account makes it the active account; a full account switcher is not implemented yet.
Home Storage is an optional .NET 10 service that exposes a private computer folder through the same browse, download, resume, and install workflow. The library is mounted read-only; SQLite stores its catalog and credentials.
cd home-storage
Copy-Item .env.example .env
# Set HOST_LIBRARY_PATH and replace SETUP_TOKEN in .env.
docker compose up -dOpen http://localhost:8080/setup, enter SETUP_TOKEN, and create the
administrator and Switch-library credentials. On the Switch, open Settings →
Home Storage, then detect the service on the LAN or enter its address
manually.
LAN discovery uses UDP port 8080 and may be blocked by wireless client isolation. Plain HTTP is appropriate only on a trusted LAN; use HTTPS and Home Storage authentication for remote access. See the complete Home Storage guide, including the optional Cloudflare Tunnel setup.
The client never stores Google refresh tokens or a Home Storage password. It
stores the console session credential, account IDs, and revocable Home Storage
bearer tokens in sd:/switch-drive/state.json. The pairing server encrypts
refresh tokens using TOKEN_ENCRYPTION_KEY before writing them to PostgreSQL.
Home Storage hashes passwords and bearer tokens, mounts the host library
read-only, and hides catalog entries only in SQLite. Do not commit .env,
console state, logs, OAuth credentials, or tunnel tokens.
| Input | Action |
|---|---|
| D-pad or either stick | Move the selection; hold to repeat |
| A | Activate; open a folder; install a Library NSP/NSZ |
| B | Go back; pause/cancel an active network operation |
| X in Files | Download the selected file |
| Y in Files | Download and install the selected file |
| X in Library | Confirm uninstall of a managed NSP component |
| Y in Library | Delete the package or offer managed uninstall |
| L/R | Change the main section |
| L while browsing | Toggle My Drive and Shared with me |
| Y in Settings | Cycle en-US → pt-BR → es-ES |
| ZL in Settings | Add a Home Storage provider |
| ZL in Home Storage | Hide an entry when catalog management is allowed |
| + | Exit |
| Touch | Select tabs, cards, and rows; tap again to activate; swipe to scroll |
The service requests only drive.readonly and identity scopes. It provides:
- ten-minute, attempt-limited pairings with one-time claims;
- 180-day console sessions stored as hashes;
- AES-256-GCM encryption for Google refresh tokens at rest;
- short-lived Drive access tokens for linked consoles;
- per-route and global rate limiting; and
- automatic PostgreSQL schema creation.
The REST contract is documented in the OpenAPI specification.
Warning
Never commit server/.env, OAuth credentials, state.json, or boot.log.
Do not expose the Docker PostgreSQL port directly to the internet. Use the
included Caddy service or a managed PostgreSQL database with the Worker.
Install devkitPro with switch-dev, switch-curl, switch-mbedtls,
switch-zstd, switch-jansson, switch-sdl2, and switch-sdl2_ttf, then run:
make
python3 tests/check_nro.py switch-drive.nroThe packaging check verifies the NRO header and its embedded icon, NACP, and RomFS assets.
The host suite covers state migration and atomic persistence, resumable logical files, safe package removal, PFS0/CNMT/NCZ parsing, download range validation, localization, QR generation, and UI navigation models.
cmake -S tests -B build/tests
cmake --build build/tests
ctest --test-dir build/tests --output-on-failureThe host needs CMake 3.24+, a C++20 compiler, zstd, and mbedTLS crypto headers and libraries.
Install host SDL2, SDL2_ttf, and pkg-config, then configure either option:
cmake -S tests -B build/preview \
-DSWITCHDRIVE_UI_PREVIEW=ON \
-DSWITCHDRIVE_UI_RUNTIME_TESTS=ON
cmake --build build/preview
SWITCHDRIVE_PREVIEW_FONT=/path/to/font.ttf ctest --test-dir build/preview --output-on-failure
SWITCHDRIVE_PREVIEW_FONT=/path/to/font.ttf build/preview/switch_drive_ui_previewPreview images are written to build/ui-preview/. These tests exercise the
real renderer with host or simulated services; they do not emulate Switch HID,
the compositor, memory limits, or NCM permissions.
The Docker service requires Node.js 24 or later. The Worker uses Wrangler 4.
cd server
npm ci
npm run build
cd ../worker
npm ci
npm run checkRun the .NET test target in Docker:
cd home-storage
docker build --target test -t switch-drive-home-storage-tests .- State writes use temporary files, backups, and atomic replacement.
- Downloads checkpoint committed data and reject unsafe HTTP range responses or changed Drive revisions before resuming.
- NSP/NSZ mutations are journaled before NCM changes. On the next launch, the app checks live metadata and either completes or rolls back recovery.
- Existing content remains registered until replacement metadata commits.
- Managed removal deletes only the selected base, update, or DLC component after orphan checks. Switch Drive never calls save-data deletion APIs.
- Package cleanup happens only after a confirmed installation.
- Home Storage mounts the host library read-only. Hiding an entry changes only its SQLite catalog and never deletes the host file.
Package signature verification is not implemented yet. Atmosphère and the appropriate FS patches remain the operator's responsibility.
- Configuration missing: verify that
sd:/switch-drive/config.jsonuses the exact compact JSON shown above and an HTTPS origin without an API path. - Install controls unavailable: relaunch through a full title override by holding R while opening a game.
- Pairing stops working after several days: reconnect the account and check whether the Google consent screen is still in testing mode.
- Interrupted download: select the same Drive file again. Switch Drive will offer Resume only when its saved identity and partial data are consistent.
- Home Storage is not discovered: check UDP port 8080 and wireless client isolation, or enter the HTTP/HTTPS address manually.
- Startup or input problem: preserve
sd:/switch-drive/boot.logimmediately after the failed attempt; each launch replaces it. Include Switch firmware, Atmosphère, Sphaira/hbmenu, launch mode, and microSD filesystem in the report.
| Path | Purpose |
|---|---|
switch/ |
C++20 client, UI, networking, downloader, and installers |
server/ |
Fastify pairing/OAuth service for Docker deployments |
worker/ |
Cloudflare Worker implementation of the same pairing API |
home-storage/ |
.NET 10 service for a private, read-only host library |
tests/ |
Portable core, UI model, renderer, and NRO packaging checks |
docs/openapi.yaml |
Pairing service API contract |
deploy/ |
Caddy reverse-proxy configuration |
third_party/Goldleaf/ |
Pinned Goldleaf reference for NCM integration |
The NSP/NSZ installer follows the NCM approach from Goldleaf. NCZ streaming implements the public NSZ format with zstd and AES-CTR; this project does not ship console keys or copyrighted content.