Hoodik is a free, open source file management & sync project written in Rust and released under a custom open-source licence. It has 1,475 GitHub stars, 68 forks and 11 open issues, and was last pushed 19 days ago. On this registry it ranks #9 of 12 tracked projects in File Management & Sync, with 5 head-to-head comparisons available. It gained 6 stars over the last 6 tracked days.

What is Hoodik?

What it is

Hoodik is a self-hosted, end-to-end encrypted cloud storage server. It lives in the Rust and Vue ecosystem, using Actix-web on the backend and Vue 3 on the frontend, and it is packaged as a Docker-first service with SQLite or PostgreSQL and S3-compatible storage options.

The project stores files, notes, and backups in a cloud service without giving the server access to plaintext content. Encryption and decryption happen in the browser, while the server stores encrypted chunks, wrapped file keys, metadata tags, and account records. This gives users a private storage drive, secure search, encrypted notes, and sharing links without relying on a third-party cloud provider to read the data.

Key capabilities

  • Hoodik encrypts files in the browser with AEGIS-128L, then wraps file keys with a hybrid X25519 and ML-KEM-768 scheme, with RSA support for legacy accounts.
  • It provides secure search by tokenizing names and note contents in the browser and storing HMAC tags that let the server match queries without reading the index.
  • It includes encrypted rich markdown notes with a WYSIWYG editor, auto-save, and searchability.
  • It supports public sharing links whose key travels in the URL fragment, so the recipient’s browser decrypts the file and the server never decrypts a public link.
  • It offers optional TOTP-based two-factor authentication, an admin dashboard, chunked transfers, SQLite or PostgreSQL, and S3-compatible storage.

Who uses it and how

  • Self-hosters deploy it as a private cloud drive for files and encrypted notes, using Docker and choosing SQLite or PostgreSQL.
  • Users upload files from a browser, where Hoodik splits them into encrypted chunks and sends them through chunked or tar-bundled HTTP endpoints for fewer round-trips.
  • Users can share files through public links, with the key contained in the URL fragment and decryption performed by the recipient’s browser.
  • Android, iOS, and macOS applications connect to the self-hosted service or the hosted Hoodik Cloud option.

Getting started

The README points to a self-hosting guide, a Docker-first single-container deployment, multi-arch Docker images, and a hosted Hoodik Cloud option. Android, iOS, and macOS apps are linked from the homepage.

When to use it — and when not to

Hoodik is useful when a user wants a browser-based, end-to-end encrypted storage server and is willing to operate the database, storage backend, and container themselves. It is less suitable for people who need a mature, clearly licensed, or large contributor base, because the repository is young, lists zero contributors, has open issues, and shows NOASSERTION for its license. The private-key recovery warning is important: if a user forgets the password and has not stored the private key, recovery and decryption can become impossible.

project readme (upstream, from github) — read inline

Hoodik

CI Docker Hub CC BY-NC 4.0 License

Hoodik is a lightweight, self-hosted, end-to-end encrypted cloud storage server. All encryption and decryption happens in your browser — the server never sees your plaintext data. Built with Rust (Actix-web) on the backend and Vue 3 on the frontend.

🌐 hoodik.io — Website  |  ☁️ Hoodik Cloud  |  📱 Android App  |  🍎 iOS & macOS App  |  ⚡ Self-Hosting Guide


Features

  • End-to-end encryption — files are encrypted in the browser with AEGIS-128L before upload and decrypted after download; file keys are wrapped with a quantum-resistant X25519 + ML-KEM-768 hybrid (RSA on legacy accounts)
  • Secure search — file metadata is tokenized and tagged with a key the server never sees, so it can match a query without being able to read the index
  • Encrypted notes — create and edit rich markdown notes with a WYSIWYG editor; content is encrypted, auto-saved, and searchable just like uploaded files
  • Public sharing links — share files via a link; the recipient decrypts everything in their browser with the key in the URL fragment, and the server never decrypts a public link
  • Two-factor authentication — optional TOTP-based 2FA per user
  • Admin dashboard — manage users, sessions, invitations, and application settings
  • Chunked transfers — files are split into encrypted chunks for concurrent upload/download
  • SQLite or PostgreSQL — SQLite out of the box, PostgreSQL via a single environment variable
  • S3-compatible storage — store encrypted chunks on any S3-compatible service (AWS, MinIO, Backblaze B2, Wasabi) instead of local disk
  • Docker-first — single container deployment; multi-arch images (amd64, armv6, armv7, arm64)

How encryption works

File storage

Each user gets an Ed25519 identity key pair (for signing) and an X25519 + ML-KEM-768 wrapping key pair (for wrapping file keys) on registration. File keys are wrapped under both algorithms at once — a hybrid that stays secure even if a future quantum computer breaks the elliptic-curve half. Login uses OPAQUE, so your password never leaves the device; the private keys are stored envelope-encrypted under a key derived from the OPAQUE export_key, which only your password can produce — the server cannot read them. Accounts created before this scheme used an RSA-2048 key pair and are still supported; they migrate to the new keys automatically on the next login.

⚠️ Store your private key somewhere safe (e.g. a password manager). If you forget your password, the private key is the only way to recover your account and decrypt your files.

When you upload a file:

  1. A random symmetric key is generated for the file (key size depends on the cipher).
  2. The file is encrypted chunk-by-chunk with that key using the file's cipher (AEGIS-128L unless the admin picks a different default in the settings).
  3. The cipher identifier and the encrypted key are stored in the database alongside the file, so old files can always be decrypted with the correct algorithm even after the default cipher changes.

Chunks move over one of two HTTP endpoints, both client-side encrypted:

  • POST /api/storage/{file_id}?chunk=N&checksum=... — upload one encrypted chunk; the server verifies the CRC16 per chunk and stores it.
  • POST /api/storage/{file_id}?format=tar — upload many chunks in one request as an uncompressed tar archive whose entries are named {index:06}.enc. Fewer HTTP round-trips on slow networks; the per-chunk integrity check is skipped (TLS + the file-level hash still cover transport and content).

Download mirrors the same split: GET /api/storage/{file_id}?chunk=N streams a single chunk, while GET /api/storage/{file_id}?format=tar streams every chunk as a single tar archive.

Search

Searchable metadata (file names, and the contents of notes) is tokenized in the browser and each token is tagged with HMAC under a key derived from your private key. Only those tags are stored. When you search, the same tagging is applied to your query and the tags are matched server-side. No plaintext leaves the browser, and the key never does either, so the index cannot be read back into words by anyone holding the database.

Public links

When you share a file:

  1. A random link key is generated.
  2. The file metadata and file key are encrypted with the link key.
  3. The link key itself is wrapped under your own current key type (the X25519 + ML-KEM-768 hybrid on current accounts, RSA on legacy accounts) so only you can recover it.
  4. The link key is appended to the share URL as a fragment: https://…/links/{id}#link-key.

The recipient's browser uses the fragment to decrypt the metadata and file key locally and does all decryption itself — the link key in the fragment never reaches the server. The server only ever serves encrypted bytes and never decrypts anything for a public link.

Cryptographic primitives

Primitive Algorithm
Identity / signing Ed25519 (legacy accounts: RSA-2048 PKCS#1)
Key wrapping hybrid X25519 + ML-KEM-768 (post-quantum) — HKDF-SHA256 combiner, AEGIS-256 wrap AEAD (legacy accounts: RSA-2048)
Symmetric (default) AEGIS-128L — hardware-accelerated AEAD via WASM SIMD128/relaxed-simd
Symmetric (supported) AEGIS-256, Ascon-128a, ChaCha20-Poly1305
Login OPAQUE (RFC 9807, ristretto255-SHA512), Argon2id KSF — password never crosses the wire
Private-key wrap envelope encryption under a KEK derived (HKDF-SHA512) from the OPAQUE export_key

The cipher used to encrypt each file is stored in the database (files.cipher), so the correct algorithm is always used for decryption regardless of what the current default is.


Hoodik Cloud

If you'd rather not run a server, Hoodik Cloud is the managed version, run by us on the same publicly auditable code. The encryption is identical — files are encrypted in the browser and the server only ever stores ciphertext. There is no lock-in: you can export your whole instance at any time and get a runnable copy of Hoodik with your encrypted data inside, ready to self-host with Docker.


Getting started

Docker (quickstart)

docker run --name hoodik -d \
  -e DATA_DIR='/data' \
  -e APP_URL='https://my-app.example.com' \
  --volume "$(pwd)/data:/data" \
  -p 5443:5443 \
  hudik/hoodik:latest

This runs with a self-signed TLS certificate generated automatically in DATA_DIR. For production, provide your own certificate (see Configuration) or put Hoodik behind a reverse proxy such as Nginx Proxy Manager.

Docker with email and custom TLS

docker run --name hoodik -d \
  -e DATA_DIR='/data' \
  -e APP_URL='https://my-app.example.com' \
  -e SSL_CERT_FILE='/data/my-cert.crt.pem' \
  -e SSL_KEY_FILE='/data/my-key.key.pem' \
  -e MAILER_TYPE='smtp' \
  -e SMTP_ADDRESS='smtp.gmail.com' \
  -e SMTP_USERNAME='[email protected]' \
  -e SMTP_PASSWORD='your-app-password' \
  -e SMTP_PORT='465' \
  -e SMTP_DEFAULT_FROM_EMAIL='[email protected]' \
  -e SMTP_DEFAULT_FROM_NAME='Hoodik Drive' \
  --volume "$(pwd)/data:/data" \
  -p 5443:5443 \
  hudik/hoodik:latest

Tip: Set JWT_SECRET to a stable random string so sessions survive container restarts.


Configuration

All configuration is done through environment variables. A full reference is in .env.example.

Core

Variable Default Description
DATA_DIR (required) Directory for the database and stored files
DATABASE_URL (SQLite) PostgreSQL connection string — omit to use SQLite
APP_URL https://localhost:5443 Public URL of the application
APP_CLIENT_URL APP_URL URL of the frontend (set to Vite dev server during development)
HTTP_PORT 5443 Port the server listens on
HTTP_ADDRESS localhost Bind address (0.0.0.0 in Docker)

Database note: SQLite and PostgreSQL databases are not interchangeable. Switching after data has been writt

readme truncated — read the full docs on github

Frequently asked questions

Is Hoodik free to use?

Hoodik is open source. There is no licence fee and no seat count — you can self-host it or, where the project offers one, pay a vendor for a managed version instead.

What does Hoodik do?

Secure self-hosted cloud storage with end-to-end encryption

What is Hoodik written in?

Hoodik is primarily written in Rust. Its source is publicly available at https://github.com/hudikhq/hoodik, and it has 1,475 GitHub stars.