Quickstart
Run with Docker
This starts two services:
- api – PutFS on a unix socket (internal, not exposed)
- nginx – reverse proxy on port 8000 (exposed)
The storage root defaults to ./data and is configured via the PUTFS_ROOT environment variable.
Set up a key
Create a keys file at ./keys/keys.conf:
map "$http_x_api_key:$http_x_api_secret" $key_ok {
default 0;
"putfs_demo:demo" 1;
}
map "$http_x_api_key:$request_method:$request_uri" $auth_ok {
default 0;
"~^putfs_demo:[^:]+:/.+" 1;
}
Then reload nginx: docker compose exec nginx nginx -s reload
See Auth for key scoping by path and method.
Usage
Upload a file:
curl -X PUT \
-H "X-Api-Key: putfs_demo" \
-H "X-Api-Secret: demo" \
http://localhost:8000/my-dataset/hello.txt \
-d "hello world"
Download it:
curl \
-H "X-Api-Key: putfs_demo" \
-H "X-Api-Secret: demo" \
http://localhost:8000/my-dataset/hello.txt
List objects in a path prefix (trailing slash):
Delete it:
curl -X DELETE \
-H "X-Api-Key: putfs_demo" \
-H "X-Api-Secret: demo" \
http://localhost:8000/my-dataset/hello.txt
How requests flow
Nginx serves files directly from the data volume for reads. Writes, deletes, and listing go through the PutFS API upstream.
client -> nginx
|-- GET static file -> serve from /data (fast path)
`-- PUT/DELETE/LIST -> proxy to PutFS API
API endpoints
| Method | Pattern | Action |
|---|---|---|
| PUT | /:path | Upload an object |
| GET | /:path | Download an object |
| HEAD | /:path | Check if an object exists |
| DELETE | /:path | Delete an object |
| GET | /:path/ | List objects in path prefix |
Install from PyPI
If you prefer running without Docker:
Then run with granian: