REST API for generating, storing, locating, and removing disk identifiers on a local machine. The service works with disk roots, writes a unique identifier file at the root of a drive, and keeps an in-memory cache so identifiers can be resolved back to their paths quickly.
This project provides a small Flask service for assigning a unique identifier to a disk root, looking that disk root up later, and forgetting the association when it is no longer needed. It stores persistent identifier records in resources/identifiers.json, writes the identifier file directly at the disk root, and refreshes the path-to-id cache on startup and every 30 seconds in the background. Every API request is also restricted to the local device itself.
DiskIdentifier is particularly useful for applications that need to:
- Track files across multiple drives: Maintain reliable references to files and directories regardless of how many storage volumes are connected to the system, without relying on potentially volatile absolute paths.
- Handle detachable storage: Work seamlessly with removable media (USB drives, external hard drives, SD cards) and network-mounted shares. The service automatically resolves disk identifiers back to current mount paths, even if a drive is unmounted and remounted.
- Decouple storage from paths: Store file references using disk identifiers instead of absolute paths, making your application resilient to drive reassignments, path changes, or different mount configurations.
This approach is essential for portable applications, backup systems, media management tools, and any software that needs to maintain file references across multiple, potentially detachable storage devices.
- REST API: Simple HTTP interface for registering, locating, and forgetting disk identifiers
- Disk-Root Registration: Create a unique identifier file at the root of a drive or mounted volume
- Persistent Identifier Store: Save registered disk/path associations in
resources/identifiers.json - Cached Lookups: Resolve identifiers from memory without rereading every file on each request
- Background Refresh: Rebuild the cache automatically at startup and on a repeating interval
- Local-Only Service: Bind to the host and port defined in
resources/configuration.json - Local Device Request Check: Reject API calls that do not originate from the machine running the service
DiskIdentifier/
├── deployment/
│ ├── com.service.plist # macOS launch agent example
│ ├── service.service # systemd service example
│ └── startup-windows.vbs # Windows startup helper
├── resources/
│ ├── configuration.json # Host, port, and universal identifier settings
│ └── identifiers.json # Persistent disk/path association store
├── scripts/
│ ├── run.bat # Windows launcher
│ ├── run.sh # macOS/Linux launcher
│ ├── setup.bat # Windows setup script
│ └── setup.sh # macOS/Linux setup script
├── src/
│ └── main.py # Flask application entry point
├── LICENSE
├── README.md
└── requirements.txt
The code is intentionally compact:
src/main.pycontains configuration loading, identifier generation, lookup logic, cache refreshes, and all API routes.resources/configuration.jsoncontrols the bind address, port, and universal identifier file name.resources/identifiers.jsonstores the registered disk-root associations.scripts/provides the quickest way to create the virtual environment, install dependencies, and start the server.- The API rejects any request that does not come from the local device.
- Python 3.10 or newer
- Permission to read and write the root of the disk you want to register
- Local access to the machine where the service will run
-
Clone the repository:
git clone <repository-url> cd DiskIdentifier
-
Configure the service: Edit resources/configuration.json and set the local bind address and port if needed. Leave
universalDiskIdentifierIDblank if you want the application to generate one automatically on first start. -
Install dependencies:
- Windows: run scripts/setup.bat
- macOS/Linux: run scripts/setup.sh
-
Start the server:
- Windows: run scripts/run.bat
- macOS/Linux: run scripts/run.sh
- Create and activate a virtual environment
- Install dependencies:
python -m pip install -r requirements.txt
- Run the application:
python src/main.py
ipandportin resources/configuration.json control where the server binds.universalDiskIdentifierIDis the filename used for the identifier file written to disk roots. If it is empty, the service generates and saves one automatically.resources/identifiers.jsonis the persistent store for registered disk/path associations.- The service runs locally only and refreshes the cache every 30 seconds in a daemon thread.
The API exposes four endpoints.
- Request type:
POST - Arguments: provide the disk root as a path parameter or in a JSON body with
path. - What it does: validates that the path is a disk root, generates a unique disk identifier, writes an identifier file at the disk root, and stores the association in
resources/identifiers.json. - How it answers: returns
201 Createdwith JSON like{"disk_identifier": "..."}. If the root already has an identifier file, the API returns409. Invalid paths return400.
- Request type:
GET - Arguments: provide the disk identifier as a path parameter or in a JSON body with
disk_identifier. - What it does: looks up the identifier in the in-memory cache and returns the matching disk root path.
- How it answers: returns
200 OKwith JSON like{"path": "..."}. Missing identifiers return400. Unknown identifiers return404.
- Request type:
GET - Arguments: provide the disk root as a path parameter or in a JSON body with
path. - What it does: returns the disk identifier currently loaded for the provided disk root (from the in-memory cache).
- How it answers: returns
200 OKwith JSON like{"disk_identifier": "...", "path": "..."}when an identifier is loaded. If the path is missing or invalid the endpoint returns400. If no identifier is loaded for the provided disk root, the endpoint returns404with a warning message.
- Request type:
GET - Arguments: none
- What it does: returns the installation's
universalDiskIdentifierIDvalue fromresources/configuration.json. - How it answers: returns
200 OKwith JSON like{"universaldiskidentifierid": "..."}.
- Request type:
DELETE - Arguments: provide the disk identifier as a path parameter or in a JSON body with
disk_identifier. - What it does: removes the identifier file from disk, deletes the persistent record from
resources/identifiers.json, and removes the association from the in-memory cache. - How it answers: returns
200 OKwith JSON like{"status": "forgotten", "disk_identifier": "...", "path": "..."}. Missing identifiers return400. Unknown identifiers return404.
- Request type:
GET - Arguments: none
- What it does: reports whether the service is running.
- How it answers: returns
200 OKwith JSON containing{"status": "ok"}.
POST /api/registerrequires a disk root, not an arbitrary subfolder.GET /api/locateandDELETE /api/forgetrequire a previously registered disk identifier.- The identifier file name comes from
universalDiskIdentifierIDin resources/configuration.json. - The service only recognizes identifiers that exist in
resources/identifiers.jsonand the current in-memory cache. - All API endpoints reject requests that do not originate from the local device.
- Language: Python 3.10+
- Web Framework: Flask
- Storage: JSON file for persistent identifier records
- Concurrency: Standard library threads for cache refresh
- Configuration: JSON file
This project is licensed under the terms specified in LICENSE.