Self-hosted cloud save sync for PS Vita, PPSSPP, and RetroArch, across all your devices
Play anywhere · Upload your save · Restore on any device
Forked from Save Cloud Vita. Baidu Cloud replaced with a self-hosted HTTP API. All strings translated to English.
One server, multiple clients. All saves go to the same place.
PS Vita app:
- Backs up native PS Vita saves, PSP/Adrenaline saves, and RetroArch saves
- Uploads to your server as a zip, downloads and restores on another Vita
- Shows per-game sync status on the Cloud tab with one-tap Sync All
Note on native Vita saves: PSP and RetroArch saves transfer reliably between devices. Native PS Vita saves are encrypted with a mix of your PSN account and hardware keys, so results vary. Same PSN account on both Vitas works for many titles but is not guaranteed for all. If a save does not load after restoring, use a tool like Apollo Save Tool to resign it.
Save Sync Hub (Desktop / Android):
- Syncs PPSSPP and RetroArch saves from macOS, Windows, Linux, and Android
- Detects default save locations automatically per platform
- Upload to server, download to local, or restore directly from cloud
- Connects to the same server and same API as the Vita app
| Client | Runs on | Emu lators / saves |
|---|---|---|
| Save Sync (Vita app) | PS Vita, PSTV | Native Vita · PSP (Adrenaline) · RetroArch |
| Save Sync Hub | macOS · Windows · Linux · Android | PPSSPP · RetroArch · Custom path |
The Vita app requires HENkaku + iTLS-Enso. Save Sync Hub is a standard desktop/Android app (no jailbreak needed on the other end).
The server is a small Node.js app. It stores save files on disk and exposes a REST API. You need to keep it running while you sync, it does not need to be on 24/7.
Pick the option that fits your situation.
Option A | Docker
If you have Docker installed (Docker Desktop for macOS/Windows, or apt install docker.io on Linux), create two files and run one command:
# docker-compose.yml
services:
vita-save-sync:
image: ghcr.io/unveroleone/vita-save-sync-server:latest
container_name: vita-save-sync
restart: unless-stopped
ports:
- "3099:3000"
environment:
- USER_TOKEN=${USER_TOKEN:?set a strong token}
- DATA_DIR=/data
volumes:
- vita-save-data:/data
volumes:
vita-save-data:
driver: local# .env
USER_TOKEN=change-me-to-a-long-random-stringdocker compose up -dTo update later: docker compose pull && docker compose up -d
Note:
docker compose restartreuses the cached environment. If you change.env, rundocker compose up -dinstead.
Put the server behind Nginx Proxy Manager or Cloudflare Tunnel for HTTPS. The Vita needs HTTPS with a valid certificate; iTLS-Enso provides the modern TLS roots.
Option B | Node.js directly (quickest to get started)
You need Node.js 20 or newer. Works on macOS, Windows, and Linux.
git clone https://github.com/unveroleone/vita-save-sync.git
cd vita-save-sync/server
npm install
npm run build
USER_TOKEN=your-secret-token DATA_DIR=./data node dist/index.jsThe server listens on port 3000. Add PORT=3099 to the command if you need a different port.
Option C | Raspberry Pi (always-on home server)
Start from a fresh Raspberry Pi OS (Bookworm or newer). Ethernet is recommended for reliability, but Wi-Fi works too.
Install Node.js (LTS):
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs gitClone and start:
git clone https://github.com/unveroleone/vita-save-sync.git
cd vita-save-sync/server
npm install
npm run build
USER_TOKEN=your-secret-token DATA_DIR=./data node dist/index.jsAuto-start on boot with systemd:
Replace pi with your actual username if it differs (run whoami to check).
sudo tee /etc/systemd/system/vita-save-sync.service << 'EOF'
[Unit]
Description=Save Sync server
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/vita-save-sync/server
Environment=USER_TOKEN=your-secret-token
Environment=DATA_DIR=/home/pi/vita-save-sync/server/data
Environment=PORT=3000
ExecStart=/usr/bin/node dist/index.js
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now vita-save-syncCheck status: sudo systemctl status vita-save-sync
Option D | Background service on your laptop (macOS / Linux / Windows)
macOS: create a launchd plist so the server starts automatically at login.
First find your Node.js path: which node (commonly /usr/local/bin/node on Intel, /opt/homebrew/bin/node on Apple Silicon).
Save this as ~/Library/LaunchAgents/com.vita-save-sync.plist, replacing the paths and token:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.vita-save-sync</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/Users/you/vita-save-sync/server/dist/index.js</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>USER_TOKEN</key>
<string>your-secret-token</string>
<key>DATA_DIR</key>
<string>/Users/you/vita-save-sync/server/data</string>
<key>PORT</key>
<string>3000</string>
</dict>
<key>WorkingDirectory</key>
<string>/Users/you/vita-save-sync/server</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>Load it: launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.vita-save-sync.plist
Linux: use the systemd unit from Option C. Same file, same commands.
Windows: run a terminal on login and keep it open, or use Task Scheduler to launch node dist/index.js at boot with USER_TOKEN and DATA_DIR set as environment variables.
The Vita requires HTTPS with a valid certificate. The easiest option is Cloudflare Quick Tunnel (no account or domain needed). Install and run:
| Platform | Install command |
|---|---|
| macOS | brew install cloudflared |
| Linux | curl -L https://pkg.cloudflare.com/install.sh | sudo bash && sudo apt install cloudflared |
| Windows | winget install -e --id Cloudflare.cloudflared |
While your server is running:
cloudflared tunnel --url http://localhost:3000It prints a *.trycloudflare.com address. Use that as the server URL on the Vita. The tunnel closes when you close the terminal, which is fine for occasional sync sessions.
For a permanent setup with your own domain, Cloudflare Tunnel with a named tunnel is also free.
Install the VPK via VitaDB Downloader (search "Save Sync") or download it from GitHub Releases and install manually via VitaShell.
- Install the VPK
- Open Save Sync
- Press R to switch to the Cloud tab
- Press Triangle to open Settings
- Fill in Server URL (e.g.
https://vita-sync.example.com), API Token, and Device Name - Select Test Connection (checks both reachability and your token)
- Press o to go back, or select Save && Back
Save Sync Hub is the companion app for PC and Android. It syncs PPSSPP and RetroArch saves using the same server and API token as the Vita app.
Download the latest release from GitHub Releases for your platform (.dmg for macOS, .exe for Windows, .AppImage for Linux, .apk for Android).
- Open Save Sync Hub
- In the sidebar, enter your Server URL, API Token, and Device Name (same values as on the Vita)
- Click Save Config
- Select your platform (PSP / RetroArch / Custom path)
- The app auto-fills the default save folder for your OS, or browse to a custom path
- Click Scan Saves to list your save directories
| Platform | PPSSPP | RetroArch |
|---|---|---|
| macOS | ~/Documents/PPSSPP/PSP/SAVEDATA |
~/Library/Application Support/RetroArch |
| Windows | %USERPROFILE%\Documents\PPSSPP\PSP\SAVEDATA |
%APPDATA%\RetroArch |
| Linux | ~/.config/ppsspp/PSP/SAVEDATA |
~/.config/retroarch |
| Android | /storage/emulated/0/PSP/SAVEDATA |
/storage/emulated/0/RetroArch |
These are the most common defaults. PPSSPP varies by install method — if your saves are not found, use Browse to point to the right folder. For RetroArch, the app scans for
saves/andstates/subdirectories inside the path above.
- Upload: zips the save folder and sends it to the server
- Download: fetches the latest backup from the server to a local zip
- Restore: downloads from the server and extracts directly into the save folder
Save IDs on the server use the folder name as the title ID, prefixed with PSP_ or RA_ to avoid collisions with native Vita saves.
Press R to switch to the Cloud tab. Every game shows a sync status badge:
| Badge | Meaning |
|---|---|
| Synced | In sync with server |
| Not Uploaded | Never uploaded to server |
| Upload | Local is newer |
| Download | Server has a newer version |
| Cloud Only | On server, not on this Vita |
| Conflict | Both sides changed |
X on a game uploads (if marked Upload) or downloads and restores directly (if marked Download or Cloud Only). One step.
Square runs Sync All. It uploads everything marked Upload and downloads everything marked Download. Conflicts are reported but not touched.
Triangle opens Settings.
Press L to see your local saves. Select a game and press X to open the save drawer:
- Local Backup tab (press L in the drawer) manages save slots on the Vita itself, independent of the server. Use it to keep manual snapshots or restore a previous local slot.
- Server Backup tab (press R in the drawer) has manual Upload, Download, and Download & Restore options.
For daily use, the Cloud tab is faster. The drawer is there for the manual actions.
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/status |
No | Health check, server version |
GET |
/api/manifest |
Bearer | Cloud manifest for all games |
PUT |
/api/save/:titleId |
Bearer | Upload save zip |
GET |
/api/save/:titleId |
Bearer | Download save zip |
Upload sends X-Save-Hash (SHA-256), X-Save-Timestamp, and X-Device-Id headers. The server verifies the hash before writing.
Forked from Save Cloud Vita by iamcco. Vita app uses VitaShell SQLite VFS and kernel modules, vita-rust, VitaSDK. Save Sync Hub built with Tauri v2 and Svelte 5.
Built with the help of AI