# 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