A simple, internal-use file server with Azure AD authentication and per-user bucket-based access control.
Ideal for internal homepages, admin panels, or internal tools that need secure file upload/download functionality without full cloud complexity.
- Bucket + file system storage
- Per-user access control (
read
,write
,admin
) - Microsoft Azure AD (Entra ID) token authentication
- Simple local file locking for safe concurrent writes
- Max file size limits via environment variable
- Extremely low operational overhead
Requirement | Description |
---|---|
Python | 3.8+ |
Flask | Flask web server |
Azure Tenant ID | Obtained via Entra |
Azure Client ID | Obtained via Entra |
FILE_STORAGE_LOCATION | Local folder path for storage |
DEFAULT_ADMIN | Initial system admin username (UPN) |
Recommended: run behind nginx (or similar) in production.
- Clone this repo
- Install dependencies:
pip install -r requirements.txt
- Create a
.env
file:
MSAL_TENANT_ID=<Azure Tenant ID>
MSAL_CLIENT_ID=<Azure Client ID>
FILE_STORAGE_LOCATION=/path/to/files
DEFAULT_ADMIN=<admin user UPN (email)>
MAX_FILE_SIZE_MB=100 # optional, defaults to 100
- Run the server:
python app.py
This will create:
FILESERVER_BUCKETS.fsconfig
FILESERVER_PERMISSIONS.fsconfig
By default, app.py
enables CORS only for http://localhost:*
.
If deploying behind nginx, or accessing from non-local clients, update:
CORS(
app,
supports_credentials=True,
origins=["http://your-frontend-url.com"],
allow_headers=["Authorization", "Content-Type"]
)
Also modify app.run()
to bind to 0.0.0.0
if you want to expose it:
app.run(debug=True, host="0.0.0.0", port=5000)
This server does not issue tokens.
Clients must acquire an Azure AD token using MSAL (Microsoft Authentication Library) for their platform.
Supply the token on every request:
Authorization: Bearer <your_token>
All tokens must be acquired on company-managed compliant devices (if Conditional Access applies).
Level | Description |
---|---|
admin | Full control of system or bucket |
write | Can upload or delete files |
read | Can download or list files |
remove | Used to remove user access |
DEFAULT_ADMIN
automatically has admin
on SYSTEM
and all buckets.
All routes require:
Authorization: Bearer <Azure Token>
Get list of user-accessible buckets.
[
{
"bucket_id": "uuid",
"bucket_name": "Reports",
"created_by": "user@example.com",
"created_at": "ISO8601"
}
]
Create a bucket.
{ "bucket_name": "MyBucket" }
Returns:
{ "bucket_id": "uuid" }
Delete a bucket.
{ "success": true }
List files in a bucket.
[
{
"file_id": "uuid",
"file_name": "report.pdf",
"file_size": 1.2,
"created_by": "user@example.com",
"created_at": "ISO8601"
}
]
Upload a file (multipart/form-data
):
file = <binary file>
Returns:
{ "file_id": "uuid" }
Download a file.
Returns file as attachment.
Delete a file.
{ "success": true }
Set or remove a userβs permission:
{
"user": "user@example.com",
"permission": "admin" // or "read", "write", "remove"
}
Returns:
{ "success": true }
Grant SYSTEM
admin rights:
{ "admin": "user@example.com" }
Revoke SYSTEM
admin rights:
{ "admin": "user@example.com" }
curl -H "Authorization: Bearer <your_token>" http://localhost:5000/buckets
curl -X POST -H "Authorization: Bearer <your_token>" -H "Content-Type: application/json" -d '{"bucket_name": "MyNewBucket"}' http://localhost:5000/buckets
curl -X POST -H "Authorization: Bearer <your_token>" -F "file=@/path/to/your/file.pdf" http://localhost:5000/buckets/<bucket_id>/files
This system is designed to:
- Replace internal app file storage systems using base64 blobs
- Provide internal tools with simple secure file uploads
- Be easily auditable and fully controlled by developers
This is NOT designed for:
- Internet-scale workloads
- Unmanaged public access
- Extreme file sizes (>2GB)
- Multi-server high availability
Think: internal team utility, not production cloud file service.
This system is meant for internal environments only.
Do not expose directly to the public internet.
Deploy behind internal reverse proxies and firewalls for safety.
Production stable for small to medium internal use cases.
Actively used in practice projects and prototype tooling.
This system is minimal by design and provides just enough features to be powerful without complexity.
Use it, customize it, improve it!