271 lines
5.5 KiB
Markdown
271 lines
5.5 KiB
Markdown
# CloudSave
|
|
|
|
CloudSave is a small client/server tool to keep save folders in sync across multiple computers.
|
|
It is aimed at games that do not provide their own cloud sync, such as emulators, old games, or any title that stores progress in a local directory.
|
|
|
|
The project is still in alpha.
|
|
|
|
## What Is In The Repository
|
|
|
|
This repository currently contains three Go binaries:
|
|
|
|
- `cmd/cli`: the end-user CLI (`cloudsave`)
|
|
- `cmd/server`: the HTTP API server
|
|
- `cmd/web`: a small read-only web UI that talks to the API server
|
|
|
|
## Build
|
|
|
|
The module targets Go `1.24` in [go.mod](/home/aurelie/src/cloudsave/go.mod), while the container image builds with Go `1.26.3` from [dockerfile](/home/aurelie/src/cloudsave/dockerfile). In practice, using a recent Go toolchain is recommended.
|
|
|
|
To build all binaries for the platforms configured in the project:
|
|
|
|
```bash
|
|
./build.sh
|
|
```
|
|
|
|
Artifacts are written to `./build`.
|
|
|
|
If you only want one binary, you can also build it directly:
|
|
|
|
```bash
|
|
go build -o cloudsave ./cmd/cli
|
|
go build -o cloudsave_server ./cmd/server
|
|
go build -o cloudsave_web ./cmd/web
|
|
```
|
|
|
|
## Server
|
|
|
|
The server exposes an authenticated HTTP API on port `8080` by default.
|
|
|
|
### Data Directory
|
|
|
|
By default, the server uses:
|
|
|
|
```text
|
|
/var/lib/cloudsave
|
|
```
|
|
|
|
You can override it with:
|
|
|
|
```bash
|
|
cloudsave_server -document-root /path/to/cloudsave-data
|
|
```
|
|
|
|
Inside this directory, the server expects:
|
|
|
|
- `.htpasswd`: credentials file
|
|
- `data/`: stored save archives and metadata
|
|
|
|
### Authentication
|
|
|
|
The API uses HTTP Basic Auth. Credentials are read from `.htpasswd`.
|
|
|
|
Example:
|
|
|
|
```text
|
|
test:$2y$10$uULsuyROe3LVdTzFoBH7HO0zhvyKp6CX2FDNl7quXMFYqzitU0kc.
|
|
```
|
|
|
|
The code currently expects bcrypt hashes when validating passwords.
|
|
|
|
### Start The Server
|
|
|
|
```bash
|
|
cloudsave_server
|
|
```
|
|
|
|
Useful flags from [cmd/server/runner.go](/home/aurelie/src/cloudsave/cmd/server/runner.go):
|
|
|
|
- `-document-root`: change the storage directory
|
|
- `-port`: change the listening port
|
|
- `-no-cache`: use the lazy repository instead of the eager cache
|
|
- `-verbose`: enable more logs
|
|
|
|
On non-Windows systems, sending `SIGHUP` reloads the eager cache and the `.htpasswd` file.
|
|
|
|
## Docker
|
|
|
|
The repository contains a server-only container setup:
|
|
|
|
- [dockerfile](/home/aurelie/src/cloudsave/dockerfile)
|
|
- [docker-compose.yml](/home/aurelie/src/cloudsave/docker-compose.yml)
|
|
|
|
Run it with:
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
This maps:
|
|
|
|
- port `8080`
|
|
- local `./data` to `/var/lib/cloudsave`
|
|
|
|
Before starting the container, you still need to create `./data/.htpasswd`.
|
|
|
|
## Client
|
|
|
|
The CLI stores its local database in the user config directory under `cloudsave/data`.
|
|
|
|
It keeps:
|
|
|
|
- per-game metadata
|
|
- current local archive
|
|
- backup archives
|
|
- `remote.json` per game when a remote is configured
|
|
|
|
Saved credentials are stored separately in `credential.json`.
|
|
|
|
Important: the `login` command stores credentials in plain text. This is also stated in the code.
|
|
|
|
## Typical Workflow
|
|
|
|
### 1. Register a game
|
|
|
|
```bash
|
|
cloudsave add /home/user/gamedata
|
|
```
|
|
|
|
You can override the displayed name:
|
|
|
|
```bash
|
|
cloudsave add -name "My Game" /home/user/gamedata
|
|
```
|
|
|
|
Note: the `-remote` flag exists on `add`, but the current implementation does not persist it. Use `cloudsave remote -set` after `add`.
|
|
|
|
### 2. List registered games
|
|
|
|
```bash
|
|
cloudsave list
|
|
```
|
|
|
|
To include local backup IDs:
|
|
|
|
```bash
|
|
cloudsave list -include-backup
|
|
```
|
|
|
|
### 3. Create or refresh the local archive
|
|
|
|
```bash
|
|
cloudsave scan
|
|
```
|
|
|
|
This scans all registered folders. If a folder changed since the last scan, the current archive is moved to the backup history and a new `data.tar.gz` archive is created.
|
|
|
|
### 4. Configure the remote server for a game
|
|
|
|
```bash
|
|
cloudsave remote -set GAME_ID http://localhost:8080
|
|
```
|
|
|
|
To list configured remotes:
|
|
|
|
```bash
|
|
cloudsave remote -list
|
|
```
|
|
|
|
### 5. Save credentials locally
|
|
|
|
```bash
|
|
cloudsave login http://localhost:8080
|
|
```
|
|
|
|
This verifies the credentials against the server and then stores them locally in plain text.
|
|
|
|
### 6. Synchronize with the server
|
|
|
|
```bash
|
|
cloudsave sync
|
|
```
|
|
|
|
The sync command:
|
|
|
|
- groups games by remote URL
|
|
- authenticates once per remote
|
|
- compares local and remote metadata
|
|
- pushes or pulls as needed
|
|
- asks for a resolution if versions conflict
|
|
|
|
### 7. Restore a save locally
|
|
|
|
Apply the latest local archive for a game:
|
|
|
|
```bash
|
|
cloudsave apply GAME_ID
|
|
```
|
|
|
|
Apply a specific backup:
|
|
|
|
```bash
|
|
cloudsave apply GAME_ID BACKUP_ID
|
|
```
|
|
|
|
## Other CLI Commands
|
|
|
|
Show metadata for one game:
|
|
|
|
```bash
|
|
cloudsave show GAME_ID
|
|
```
|
|
|
|
Pull one game and its backups from a remote into a local path:
|
|
|
|
```bash
|
|
cloudsave pull http://localhost:8080 GAME_ID /path/to/restore
|
|
```
|
|
|
|
Show local version information:
|
|
|
|
```bash
|
|
cloudsave version
|
|
```
|
|
|
|
Show remote version information:
|
|
|
|
```bash
|
|
cloudsave version -a http://localhost:8080
|
|
```
|
|
|
|
Remove a registered game and its local backups:
|
|
|
|
```bash
|
|
cloudsave remove GAME_ID
|
|
```
|
|
|
|
## Web UI
|
|
|
|
The repository also contains a small web frontend in `cmd/web`.
|
|
|
|
It uses a JSON config file, for example:
|
|
|
|
```json
|
|
{
|
|
"server": {
|
|
"port": 8081
|
|
},
|
|
"remote": {
|
|
"url": "http://localhost:8080"
|
|
}
|
|
}
|
|
```
|
|
|
|
Then start it with:
|
|
|
|
```bash
|
|
cloudsave_web -config /path/to/config.json
|
|
```
|
|
|
|
The web UI itself does not manage users. It forwards HTTP Basic Auth credentials to the configured API server.
|
|
|
|
## Current Caveats
|
|
|
|
These points are worth knowing in the current state of the project:
|
|
|
|
- the software is still alpha
|
|
- credentials saved by `cloudsave login` are stored in plain text
|
|
- the Docker setup only runs the API server, not the web UI
|
|
- `add -remote` is exposed by the CLI but is not currently persisted by the service layer
|
|
|