English | Русская версия
- user registration and authentication based on Django sessions and CSRF cookies
- administrative user management interface
- personal file storage with upload, preview, download, rename, comments, and share-link enable/disable flows
- Backend: Django + PostgreSQL
- Frontend: React (Vite) + Redux + React Router
- Deploy: Docker Compose + Nginx as a single entrypoint
The application is served under a single URL such as http://<SERVER_IP>/:
Nginxserves the built frontendNginxproxies/api/requests to the Django backendPostgreSQLruns inside the Docker network and is not exposed publicly- user files are stored in a Docker volume
- Ubuntu 24.04 LTS or a similar Linux VPS
- Docker Engine + Docker Compose plugin
- Port
80open for HTTP traffic - Git
File: backend/.env
Minimum example:
ADMIN_PASSWORD=change-me
SECRET_KEY=replace-with-a-strong-secret-key
DJANGO_ALLOWED_HOSTS=<SERVER_IP>,localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=http://<SERVER_IP>,http://localhost,http://127.0.0.1,http://localhost:5173,http://127.0.0.1:5173
POSTGRES_DB=my_cloud
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=db
POSTGRES_PORT=5432
STORAGE_ROOT=/data/storagessh deploy@<SERVER_IP>
sudo mkdir -p /opt/my_cloud
sudo chown -R deploy:deploy /opt/my_cloud
cd /opt/my_cloud
git clone <REPO_URL>
cd <REPO_DIR>
nano backend/.env
docker compose up --build -d
Open in a browser:
http://<SERVER_IP>/
curl http://127.0.0.1/api/auth/csrf/
A bootstrap superuser with login admin is created from migration on first database initialization.
The initial password is taken from ADMIN_PASSWORD in backend/.env.
Changing ADMIN_PASSWORD later does not automatically update the password of an already existing admin user.
Use a strong unique password before the first deployment.
This mode is intended for validating the integrated stack before deploying to a VPS.
Behavior is equivalent to the server deployment, but the application is accessed through localhost.
- Docker Desktop (WSL2) or Docker Engine
- Docker Compose plugin
- Git
From the monorepo root:
Create:
backend/.env
Example:
ADMIN_PASSWORD=change-me
SECRET_KEY=replace-with-a-strong-secret-key
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost,http://127.0.0.1,http://localhost:5173,http://127.0.0.1:5173
POSTGRES_DB=my_cloud
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=db
POSTGRES_PORT=5432
STORAGE_ROOT=/data/storagedocker compose up --build
Or in detached mode:
docker compose up --build -d
Open:
http://localhost/
API check:
curl http://localhost/api/auth/csrf/
docker compose down
All endpoints are available under the /api/ prefix.
-
GET
/api/auth/csrf/Issue a CSRF cookie. -
POST
/api/auth/register/Register a new user. JSON:{ "username": "user1", "full_name": "User One", "email": "user@example.com", "password": "Secret#1" } -
POST
/api/auth/login/Sign in. -
GET
/api/auth/logout/End the current session. -
GET
/api/auth/me/Return information about the current user.
-
GET
/api/admin/users/List users visible to the current administrator together with storage metadata. -
DELETE
/api/admin/users/<user_id>/?delete_files=1Delete a user.delete_files=1also removes the user's files and storage directory. -
PATCH
/api/admin/users/<user_id>/level/Change user level. JSON:{ "level": "user | admin | senior_admin | superuser" }
-
POST
/api/files/upload/Upload a file.multipart/form-datafields:filecommentoptional
-
GET
/api/files/List files of the current user. -
GET
/api/files/?user_id=<int>For administrators, list files of another user when permissions allow it. -
DELETE
/api/files/<file_id>/Delete a file. -
PATCH
/api/files/<file_id>/rename/Rename a file. JSON:{ "name": "new_name.txt" } -
PATCH
/api/files/<file_id>/comment/Update the file comment. Empty string is allowed. JSON:{ "comment": "new comment" } -
GET
/api/files/<file_id>/download/Download a file. Query:mode=previewopens inline when supported by the browser- otherwise the file is downloaded as an attachment
-
POST
/api/files/<file_id>/share/Create or enable a public share link. -
POST
/api/files/<file_id>/share/disable/Disable a public share link. -
GET
/api/share/<uuid>Download a file through a public share link.