Skip to main content

Aird

Aird

CI PyPI Python versions Quality gate License: BSL 1.1

Aird demo

Aird is a self-hosted file browser, editor, and sharing platform built on Python and Tornado. It targets fast local and LAN use: parallel HTTP transfers for large files, real-time log streaming, content search, secure shares, optional multi-user isolation, direct messages between users, and an admin console that applies settings without restarts.


Highlights

Area What you get
File manager Browse, upload, download, rename, move, copy, bulk ops, in-browser text edit, ZIP download
Large transfers Parallel HTTP Content-Range uploads/downloads (primary path for big files)
Search Super Search — glob + regex content search with live WebSocket progress
Direct messages Optional chat plugin — DMs, file/GIF attachments, realtime WebSocket, “From chat” on Shares
Streaming Tail log files over WebSocket with filters
Sharing Token-based public/private shares, static or live folder views
Security CSRF, CSP, path traversal checks, optional ABAC policies, WebAuthn, LDAP
Integrations Google Drive / OneDrive browse, P2P WebRTC rooms, optional embedded SMB & WebDAV
Ops SQLite-backed settings, audit log, feature flags, transfer rate limits, health endpoint

File transfers

Large uploads are designed for high-throughput links (e.g. gigabit LAN or VPN):

  1. Small files — single POST /upload.
  2. Large files — client opens a range session (POST /api/upload/range/session), then sends many parallel PUT requests with Content-Range. Each chunk is written in place at the correct byte offset on disk (no separate part files, no concat step at the end).
  3. Downloads — GET /files/...?download=1 with optional Range for parallel fetch.

Defaults (all adjustable in Admin → Upload settings):

Setting Default Notes
Max file size 10 240 MB (10 GiB) Hard cap per file
Single-request max 100 MB Files ≥ this use parallel HTTP ranges
HTTP chunk size 90 MB Per range PUT body
HTTP parallelism 16 Concurrent upload streams

Behind nginx/Caddy: set client_max_body_size (or equivalent) to at least your HTTP chunk size. If Single-request max is 0, Aird uses a 100 MB parallel threshold (proxy-safe), not a single POST for the entire max file size.

Optional WebSocket upload (/ws/file-transfer) remains for specialized paths; the browser UI uses HTTP parallel by default.

Transfer progress, cancel, and resume metadata are handled in the browser (transfer-tracker.js, transfer-engine/, service worker sw-transfer.js).


Quick start

Install

pip install aird

# Optional extras
pip install "aird[compress]"   # zstandard HTTP compression
pip install "aird[chat]"     # direct messages (bleach)
pip install "aird[all]"      # compress + native build tools + chat

# From source
git clone https://github.com/blinkerbit/aird.git
cd aird
pip install -e .
# With chat:
pip install -e ".[chat]"

Python: 3.10+ required. On Linux, free-threaded builds (3.13t / 3.14t) are supported and recommended for parallel disk I/O; the server detects nogil at startup and sizes the I/O thread pool accordingly.

Run

# Default: port 8000, current directory as root
python -m aird

# Custom root and port
python -m aird --root /data --port 8080

# Multi-user (per-user home directories under root)
python -m aird --root /data --multi-user

# TLS
python -m aird --ssl-cert /path/cert.pem --ssl-key /path/key.pem --port 443

# Worker processes (Linux; default is auto from CPU topology)
python -m aird --workers 4

On first start, random access and admin tokens are generated unless you set them via --token, --admin-token, config.json, or AIRD_ACCESS_TOKEN. Users log in with username/password; the access token is for API/CLI automation.

A port that is already taken stops the process. Set AIRD_PORT_RETRY=1 to try the next two ports.

Open http://localhost:8000/ → redirects to /files/.

CLI client

pip install aird   # includes aird-cli
aird-cli config set server https://your-host
aird-cli login
aird-cli ls /

Direct messages (optional)

Requires pip install "aird[chat]" and Admin → Direct messages enabled (feature flag direct_messages).

Feature Details
UI /chat — conversation list, rich-text composer, browse/upload/GIF attachments
Realtime WebSocket /ws/chat (messages, read receipts, notifications)
File shares Copies land in recipient {home}/.aird-shares/{sender}/ (hidden from browse root)
Shares page “From chat” section — grouped by sender, recipient can delete received files
Notifications Nav badge, in-app toasts, optional browser notifications (profile toggle)

Logged-in DB/LDAP users only (not token-only sessions).


GitLab (experimental)

Enable under Admin → Plugins (experimental). Flag gitlab_integration.

  • Bind a folder to a code project (CI, MRs) and a possibly different issues project (board, tickets).
  • Folder owner: save a PAT on the machine ({home}/.aird/secrets/gitlab_token) or use GITLAB_TOKEN / glab. Aird calls GitLab on the server.
  • Share viewers: their PAT stays in the browser (localStorage). Aird never uses the owner token for them.
  • File comments are stored in Aird and visible to anyone who can see the file. Promote a comment onto a GitLab issue.
  • Copilot MCP: aird-gitlab-mcp (stdio). Set AIRD_URL and AIRD_TOKEN. Optional CORS helper: aird-gitlab-mcp --bridge on 127.0.0.1:8765.
{
  "mcpServers": {
    "aird-gitlab": {
      "command": "aird-gitlab-mcp",
      "env": { "AIRD_URL": "http://127.0.0.1:8000", "AIRD_TOKEN": "…" }
    }
  }
}

Configuration

config.json

{
  "port": 8000,
  "root": "/srv/files",
  "hostname": "files.example.com",
  "token": "your-access-token",
  "admin_token": "your-admin-token",
  "multi_user": false,
  "workers": 2,
  "ldap": false,
  "ldap_server": "ldaps://directory.example.com:636",
  "ldap_base_dn": "dc=example,dc=com",
  "feature_flags": {
    "file_upload": true,
    "super_search": true,
    "direct_messages": false,
    "gitlab_integration": false,
    "abac_engine": false
  }
}
python -m aird --config /etc/aird/config.json

Environment variables (common)

Variable Purpose
AIRD_ACCESS_TOKEN Login / API token (required in multi-user mode)
AIRD_COOKIE_SECRET Persistent session signing (set in production)
AIRD_LDAP_CA_FILE PEM CA for LDAPS when the directory certificate is private
AIRD_CORPORATE_IP_CIDRS Comma-separated CIDRs for ABAC / WAN compression rules
AIRD_GDRIVE_ACCESS_TOKEN / AIRD_ONEDRIVE_ACCESS_TOKEN Cloud providers

Admin console

GET /admin — feature flags, upload limits, extension allow-list, WebSocket pool limits, LDAP, network shares, ABAC policies/tags, users, audit. Changes persist to SQLite and apply without restart (feature-flag subscribers refresh over /features WebSocket).


Production deployment

Reverse proxy

Aird listens on one port (default 8000). Terminate TLS at Caddy, nginx, or similar.

nginx example (adjust chunk size to match Admin → HTTP chunk):

client_max_body_size 128m;

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

WebSocket routes (/stream/, /search/ws, /features, /ws/chat, /ws/…) need Upgrade and Connection headers if you proxy them.

Ubuntu deploy script

deploy_local.ps1 (run from Windows) syncs source or a wheel to a remote host, creates a uv venv with Python 3.14t, and installs the package. See docs/wireguard-deploy.md for VPN-only TLS layouts.

LDAP

LDAP login is optional (--ldap or "ldap": true in config.json). The directory URL is ldap_server / --ldap-server.

Production binds should use LDAPS so the password is not on the wire:

python -m aird --ldap \
  --ldap-server ldaps://directory.example.com:636 \
  --ldap-base-dn "dc=example,dc=com" \
  --ldap-user-template "uid={username},ou=users,dc=example,dc=com"

ldaps:// turns on TLS and certificate checks (ssl.CERT_REQUIRED, including the hostname). Trust comes from the host store, or from AIRD_LDAP_CA_FILE when the directory uses a private CA. ldap:// is cleartext and is only appropriate on a network you already trust. Proxy TLS in front of Aird does not cover the LDAP connection.

Config keys: ldap, ldap_server, ldap_base_dn, ldap_user_template, ldap_filter_template, ldap_attributes, ldap_attribute_map. Admin group sync uses the same ldaps:// URL. Details: docs/admin-ldap.md.

Systemd

Run python -m aird (or the venv equivalent) as a service user with --config pointing at your JSON file. Logs go to the data directory (aird.log under the platform app data path).


API

Swagger UI is served by the running server at /api/docs. The OpenAPI document is /api/openapi.json. That document is the contract a native client (including a future Android app) uses against this same process. Browser pages call those routes today.

POST /api/auth/login with {"username","password"} returns a token. Send it as Authorization: Bearer. That call, and later bearer calls, do not use the _xsrf cookie. Cookie sessions still do. Send Accept: application/json so file-change errors are JSON.

API overview

Authentication: session cookie after /login, bearer token, or Authorization header where supported. Mutating requests require the _xsrf cookie + X-XSRFToken header.

Operation Method / path
List directory GET /api/files/{path}
Upload (small) POST /upload
Upload (large) POST /api/upload/range/session then PUT /api/upload/range/{id}
Upload status GET /api/upload/range/{id}/status
Download GET /files/{path}?download=1
Edit GET /edit/{path}, POST /edit
Delete / rename / mkdir POST /delete, POST /rename, POST /mkdir
Search UI GET /search
Search (live) WebSocket /search/ws
Log stream WebSocket /stream/{path}
Shares POST /share/create, GET /share/list, …
Chat (optional) GET /chat, GET/POST /api/chat/conversations, WebSocket /ws/chat
GitLab (optional) /api/gitlab/*, WebSocket /ws/file-comments
Health GET /health

Page-level UI contracts and routes are documented under docs/.


Architecture notes

  • Async I/O: Tornado event loop; on Linux optionally uvloop.
  • Free-threaded Python: SQLite access is wrapped (aird/db/sync.py); upload chunk writes use asyncio.to_thread / os.pwrite so parallel range PUTs do not block the loop.
  • HTTP compression: gzip by default; optional zstandard via pip install aird[compress] (loaded only on builds where the extension is nogil-safe).
  • Security headers: COOP/COEP/CORP for transfer workers; strict CSP on HTML pages.
  • ABAC: Optional policy engine (abac_engine flag) with admin-defined policies, tags, and user attributes.
  • Plugins: Optional features (e.g. chat) live under aird/plugins/ and register routes from main.py. An alternate microservices layout exists under aird/ms/ for split deployment behind Caddy (not used by default python -m aird).

Development

Frontend assets

npm install
npm run css:build          # Tailwind → aird/static/css/app.css
npm run js:share           # Bundle share UI → aird/static/js/share/app.js
npm run vendor:fflate      # Compression worker dependency

Tests

python -m pytest tests/

Project layout

aird/
  handlers/       # HTTP & WebSocket handlers (monolith)
  plugins/        # Optional features (e.g. chat)
  ms/             # Starlette microservices (split deploy)
  services/       # Config, quota, share, audit, …
  static/js/      # Browser UI & transfer engine
  templates/      # Jinja2 pages
  core/           # Compression, mmap, rate limits, …
docs/             # Per-page UI & admin documentation

Security

  • Path traversal and symlink checks on file access
  • Argon2 password hashing for local users
  • CSRF on state-changing requests
  • Upload extension allow-list (or allow-all) with max size enforced server-side
  • Optional storage quotas (multi-user)
  • Audit trail and live policy-decision stream for ABAC

For production, set AIRD_COOKIE_SECRET, use TLS, and restrict admin routes. Report vulnerabilities through SECURITY.md.

Contributing

Local setup, tests, and the dev → pre-release → main flow are in CONTRIBUTING.md. Issues labeled good first issue are a starting point.


License

Business Source License 1.1 (BSL) — see LICENSE. Converts to Apache 2.0 after the change date in the license file.

Commercial File-Management-as-a-Service use requires a separate license. Contact Viswanatha Srinivas P.



Made by Viswanatha Srinivas P

Metadata

Release files for aird 0.5.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aird 0.5.7
File Size Uploaded Provenance
aird-0.5.7.tar.gz 3.0 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for aird 0.5.7
File Interpreter ABI Platform
aird-0.5.7-py3-none-any.whl Python 3 none any Details

Total release size: 6.2 MB

Release files / aird-0.5.7.tar.gz

Download URL aird-0.5.7.tar.gz
Size 3.0 MB
Tags Source
SHA-256 checksum
How to use checksums
fea27554c3dcb2d514bd62ae29966450962288e5950627163a3a78b9ac11b31d
BLAKE2b-256 checksum
How to use checksums
0bfc91948fcb41e331e4fcd888fd9dd75511530d5df99b6559b675076d63e5d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Release files / aird-0.5.7-py3-none-any.whl

Download URL aird-0.5.7-py3-none-any.whl
Size 3.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3a9a275e48e9e2b1f3c7ffebc10440ab1d7805b13ac11c1e2108ace888364f44
BLAKE2b-256 checksum
How to use checksums
5fc9e86ab38563645efb3448f99d592883943aa7c53a082a18b6e9b04651c795
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.6

Security for aird 0.5.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.5.7 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page