Bring the Hugging Face Hub home.
Browse live models, choose exactly which files to keep, and build a clean local library on your PC or NAS.
Features · Screenshots · Quick start · NAS setup · Security
Live Hub discovery with practical metadata, storage-aware downloads, and no cloud dashboard in the middle.
Note
HuggingHack is an unofficial, local-first project. It is not affiliated with or endorsed by Hugging Face.
| 🔎 Discover Search the live model catalog and narrow it by task, format, local app, parameter count, or popularity. |
🎯 Download precisely Keep a full repository, SafeTensors, one GGUF, metadata only, or your own include and exclude patterns. |
🏠 Own the library Store models in a plain folder on your disk or NAS and index files you copied there yourself. |
- Familiar Hub-style model catalog with visual, metadata-driven model cards plus task, format, local-app, parameter, and sort filters
- Live Hugging Face metadata, repository file lists, richly rendered model cards, gated status, likes, and download counts
- On-demand GGUF metadata and tensor inspection with shard position, names, shapes, data types, and parameter totals
- Full repository, SafeTensors, GGUF, metadata-only, file/folder, weight-set, and custom-pattern download modes
- Background downloads with revision pinning, byte progress, speed, pause/resume, retained-data cleanup, and history
- Administrator-defined weekly download windows in the browser's IANA timezone
- Restart recovery: interrupted jobs resume through Hugging Face's local-dir metadata
- Automatic local-library indexing with model size, file count, config metadata, and unsafe serialization warnings
- Built-in local accounts or Pocket ID OIDC with per-user provisioning and group-based roles
- Per-account saved models, private notes, and project or rig collections
- Per-account My Hardware rigs with GGUF/MLX weight-fit estimates and 20% runtime headroom
- Private or locally shared user repositories with resumable, chunked model-folder uploads
- Optional S3-compatible durable storage with a local working cache, remote browsing, restore, and cache eviction
- Network runtime jobs: transfer models to Ollama or switch a remote vLLM rig through an authenticated manager
- Ownership-verified repository deletion with exact-name confirmation
- Optional read-only
HF_TOKENsupport for private and gated models - Light/dark themes and responsive desktop/mobile layouts
- One Docker Compose service with persistent model and application-data mounts
The catalog above is the main workspace. Open any model to inspect its repository, estimate storage, and choose the exact download mode without leaving the app. Local accounts add private shortlists, notes, collections, and repositories without turning HuggingHack into a hosted service.
|
|
| One-time local owner setup with no hosted identity service | Per-account model shortlists, collections, and private notes |
Resumable model-folder uploads into private or locally shared repositories on the mounted drive
|
|
| Repository details and file-aware download controls in dark mode | The same live catalog on mobile |
- Install and start Docker Desktop.
- Double-click Start HuggingHack.bat.
- Open http://localhost:7860.
The first launch builds the container. Later launches reuse the image unless the project changes. On the first browser visit, HuggingHack asks you to create the owner account. Use a unique password of at least 12 characters. The owner can add local member accounts from Settings.
Command-line equivalent:
Copy-Item .env.example .env
docker compose up --build -dStop it with Stop HuggingHack.bat or:
docker compose downModels and the default SQLite database are persistent and are not removed by
docker compose down.
SQLite remains the zero-configuration default. For a multi-user deployment or an external
database service, set DATABASE_URL to a PostgreSQL connection URL:
DATABASE_URL=postgresql://hugginghack:password@database-host:5432/hugginghackHuggingHack creates and upgrades its tables at startup. PostgreSQL credentials stay on the server and are not returned by the API.
An optional Compose overlay runs PostgreSQL 17 beside HuggingHack. Add a long URL-safe
password to .env, then start both services:
POSTGRES_PASSWORD=replace-with-a-long-random-passworddocker compose -f docker-compose.yml -f docker-compose.postgres.yml up --build -dThe overlay stores PostgreSQL data in the postgres-data named volume and waits for the
database health check before starting HuggingHack. Back it up separately from ./data.
Do not start HuggingHack against PostgreSQL until the migration is complete. Build the new image, start only PostgreSQL, stop the old application, and run the one-shot migration command:
docker compose -f docker-compose.yml -f docker-compose.postgres.yml build hugginghack
docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d postgres
docker compose -f docker-compose.yml -f docker-compose.postgres.yml stop hugginghack
docker compose -f docker-compose.yml -f docker-compose.postgres.yml run --rm --no-deps hugginghack python -m app.migrate_database --source /data/hugginghack.sqlite3 --backup /data/hugginghack.pre-postgres-20260731.sqlite3Use the actual cutover date in the backup filename. The command:
- uses SQLite's backup API so committed WAL data is included;
- never changes the source database or overwrites an existing backup;
- upgrades a temporary copy to the current schema;
- refuses a PostgreSQL target that already contains application data;
- copies stable IDs and foreign keys in one PostgreSQL transaction; and
- compares every persistent row before committing.
Sessions and unfinished OIDC login states are intentionally not copied, so users must sign in again. Keep the dated SQLite backup until PostgreSQL backups have been created and restored in a test environment. After a successful migration, start the application:
docker compose -f docker-compose.yml -f docker-compose.postgres.yml up -d hugginghackIf the existing installation used disabled authentication and will switch to Pocket ID, first follow the identity-linking note in the Pocket ID section so existing ownership is retained.
Local accounts stay inside this HuggingHack installation. Each member gets a separate saved-model library, private notes, collections, and download history. Local members can rotate their own password from Settings; doing so revokes their other active sessions. Pocket ID can instead be the only sign-in method, as described below.
Use the heart on a Hub model to save it without downloading. The Saved workspace can organize those models into multiple collections, such as a project shortlist or a target rig.
The Uploads workspace creates repositories under the signed-in owner name:
models/
your-username/
your-repository/
.hugginghack.json
config.json
model.safetensors
...
Choose a model folder in the browser and HuggingHack sends each file in bounded chunks. Interrupted uploads keep their progress and resume from the server's confirmed offset. Uploaded repositories are private by default; their owner can share them with every local account. Model files stay in the model mount rather than in the metadata database.
To preserve the original trusted-LAN behavior, set AUTH_MODE=disabled. This creates a single
local compatibility identity and skips sign-in. ACCOUNTS_ENABLED=false remains supported when
AUTH_MODE is blank. Do not use disabled mode on an untrusted network.
Pocket ID can authenticate every HuggingHack user through one confidential OIDC client. Local username/password forms are hidden while OIDC is enabled, and each Pocket ID subject gets its own saved models, collections, uploads, and history.
- In Pocket ID, create an OIDC client for HuggingHack and allow the user groups that should be able to sign in.
- Register
https://models.example.com/api/auth/oidc/callbackas the callback URL andhttps://models.example.com/as the logout callback, replacing the hostname with your public HuggingHack URL. - Configure
.envand restart HuggingHack:
AUTH_MODE=oidc
APP_BASE_URL=https://models.example.com
SECURE_COOKIES=true
OIDC_ISSUER=https://id.example.com
OIDC_CLIENT_ID=replace-with-pocket-id-client-id
OIDC_CLIENT_SECRET=replace-with-pocket-id-client-secret
OIDC_SCOPES=openid,profile,email,groups
OIDC_ALLOWED_GROUPS=model-users,model-admins
OIDC_ADMIN_GROUPS=model-admins
OIDC_SESSION_TTL_HOURS=12OIDC_ALLOWED_GROUPS is an optional second access check inside HuggingHack; Pocket ID's client
group restriction should remain the primary gate. OIDC_ADMIN_GROUPS maps matching group names
to the HuggingHack administrator role on every login. With no admin-group mapping, existing
linked roles are preserved and newly provisioned users are members.
HuggingHack uses Authorization Code flow with a client secret, PKCE S256, nonce validation, one-time server-side state, discovery/JWKS signature verification, and exact issuer and audience checks. If a Pocket ID preferred username exactly matches an unlinked local username after normalization, the identity is linked to that account so its existing data is retained. Later users with the same preferred username receive a unique suffix. Signing out revokes the local session and continues through Pocket ID's end-session endpoint when advertised.
Edit .env and set MODEL_STORAGE_PATH to the host folder that should contain models:
MODEL_STORAGE_PATH=./modelsThe container sees this folder as /models. Managed repositories are stored in a plain hierarchy:
models/
organization/
repository/
.hugginghack.json
config.json
model.safetensors
...
That layout is portable and works with vLLM, llama.cpp, Ollama import workflows, Transformers, Diffusers, and other tools that accept a local repository path.
Set MODEL_STORAGE_BACKEND=s3 to keep complete managed repositories in AWS S3 or an
S3-compatible service such as Garage or Ceph. /models remains a local working cache because
vLLM, llama.cpp, and similar runtimes require filesystem paths.
MODEL_STORAGE_BACKEND=s3
MODEL_STORAGE_PATH=./models
S3_BUCKET=my-model-bucket
S3_PREFIX=models
S3_REGION=us-east-1
AWS_ACCESS_KEY_ID=replace-me
AWS_SECRET_ACCESS_KEY=replace-meFor a generic custom endpoint:
S3_ENDPOINT_URL=https://s3.example.com
S3_ADDRESSING_STYLE=pathSet the Garage provider preset when the durable store is a Garage cluster:
MODEL_STORAGE_BACKEND=s3
S3_PROVIDER=garage
S3_BUCKET=hugginghack-models
S3_PREFIX=models
S3_ENDPOINT_URL=http://garage:3900
AWS_ACCESS_KEY_ID=GKreplace-me
AWS_SECRET_ACCESS_KEY=replace-me
S3_USE_SSL=falseThe preset defaults S3_REGION to garage, uses path-style SigV4 requests, and limits
SDK checksums to those required by the S3 operation. You can still override the region and
addressing style when your Garage deployment uses different values. Do not set
S3_STORAGE_CLASS; Garage does not implement S3 storage classes.
Create the bucket and an application key in Garage, then grant that key read, write, and owner access to the bucket:
garage bucket create hugginghack-models
garage key create hugginghack
garage bucket allow --read --write --owner hugginghack-models --key hugginghackWhen Garage runs in the same Compose project or Docker network, use the container service
name in S3_ENDPOINT_URL, as shown above. For a Garage server on another host, use its
TLS endpoint reachable from the HuggingHack container and leave S3_USE_SSL=true.
HuggingHack also supports boto3's normal credential chain, including attached IAM roles, so static keys are optional on AWS. Credentials stay server-side and are never returned by the API. Downloads and finalized browser uploads sync automatically. The manifest is published last, so partially transferred repositories are not indexed as complete. From the Local library you can remove a local cache copy while keeping its durable S3 copy, then restore it when an inference runtime needs the files.
On AWS, the bucket identity needs s3:ListBucket on the bucket and s3:GetObject,
s3:PutObject, and s3:DeleteObject on the configured prefix.
Keep the metadata database backed up too: private upload manifests fail closed unless their
matching ownership metadata is present.
HuggingHack can dispatch a cached model to another inference device on the same network. Destinations are configured server-side so endpoints and credentials never have to be entered in the browser. The owner can then choose Local library → model → Send to runtime, while automation can use the same API.
Add one or both target types to .env on a single line:
RUNTIME_TARGETS_JSON=[{"id":"ollama-rig","name":"Ollama GPU","kind":"ollama","base_url":"http://192.168.0.36:11434","keep_alive":"15m"},{"id":"vllm-rig","name":"vLLM GPU","kind":"vllm","base_url":"http://192.168.0.35:8090","remote_model_root":"/mnt/nas/models","token_env":"VLLM_AGENT_TOKEN"}]
RUNTIME_WORKERS=2
VLLM_AGENT_TOKEN=replace-with-the-same-long-random-secret-used-on-the-agentThe two adapters deliberately handle storage differently:
- Ollama uses its native blob and create APIs. HuggingHack hashes each required file, skips
blobs the remote server already has, transfers missing data over HTTP, creates the Ollama
model, and preloads it for the configured
keep_alive. A repository needs one selected GGUF or a root-level SafeTensors model supported by Ollama. - vLLM reads the existing NAS files instead of copying them. Mount the HuggingHack model
folder on the vLLM device, then set
remote_model_rootto that device's mount path. vLLM fixes its base model at process startup, so the authenticated agent stops the process it manages and startsvllm servewith the selected model. Active inference requests will be interrupted during a switch.
S3-only models must be restored to the local cache before either adapter can use them.
On the vLLM device, mount the same model share and run the small manager included in this repository. The token is mandatory and must match the environment variable forwarded to the HuggingHack container:
export VLLM_AGENT_TOKEN='replace-with-a-long-random-secret'
export VLLM_AGENT_MODEL_ROOT=/mnt/nas/models
export VLLM_AGENT_VLLM_PORT=8000
export VLLM_AGENT_EXTRA_ARGS_JSON='["--gpu-memory-utilization","0.9"]'
python -m uvicorn app.vllm_agent:app \
--app-dir backend \
--host 0.0.0.0 \
--port 8090The agent never accepts a shell command or arbitrary model path. It only starts vllm serve
for a directory inside VLLM_AGENT_MODEL_ROOT, with additional vLLM arguments fixed by the
agent administrator through VLLM_AGENT_EXTRA_ARGS_JSON. Do not run a separate vLLM server on
the configured vLLM port; the agent owns that process.
Set RUNTIME_API_TOKEN to enable bearer-token automation scoped to runtime targets, loads, and
job history:
RUNTIME_API_TOKEN=replace-with-another-long-random-secretQueue a load:
curl -X POST http://NAS-IP:7860/api/runtimes/ollama-rig/load \
-H "Authorization: Bearer $RUNTIME_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"repo_id":"bartowski/Qwen2.5-7B-Instruct-GGUF","runtime_model_name":"qwen-local","source_file":"Qwen2.5-7B-Instruct-Q4_K_M.gguf"}'The response is a persistent asynchronous job. Read it at
GET /api/runtime-jobs/{job_id}, list history at GET /api/runtime-jobs, and discover
configured destinations at GET /api/runtimes. The same endpoints also accept the owner's
normal browser session and CSRF token. Interactive API documentation is available at
http://NAS-IP:7860/api/docs.
Copy the entire HuggingHack directory to your NAS, then change only MODEL_STORAGE_PATH in .env.
The host model folder and the project's data folder must exist before the container starts. Synology Container Manager does not always create missing bind-mount sources. For a project stored at /volume1/docker/HuggingHack, create them in File Station or over SSH:
mkdir -p /volume1/docker/HuggingHack/models
mkdir -p /volume1/docker/HuggingHack/dataThen set MODEL_STORAGE_PATH=/volume1/docker/HuggingHack/models. If you choose another model location, create that exact path first.
Common examples:
# Synology
MODEL_STORAGE_PATH=/volume1/AI/models
# TrueNAS
MODEL_STORAGE_PATH=/mnt/tank/ai/models
# QNAP
MODEL_STORAGE_PATH=/share/Container/modelsIf your NAS enforces Unix ownership, set its user and group IDs:
PUID=1026
PGID=100Find them over SSH with id your-nas-user. Then launch from the project directory:
docker compose up --build -dOpen http://NAS-IP:7860 from another computer on the LAN.
- Sign in at Hugging Face and accept the repository's license or access terms in your browser.
- Create a read-only user access token.
- Put it in
.env:
HF_TOKEN=hf_your_read_token- Restart the service:
docker compose up -dThe token is read only by the backend container. It is never returned by the API or sent to the browser.
The model drawer offers six download modes plus detected weight-set shortcuts:
- Full repository downloads every file in the selected revision.
- SafeTensors selects safe weights plus configuration and tokenizer files.
- One GGUF lets you choose a specific quantization from the repository file list.
- Files & folders selects any combination of repository files and complete folders. Support metadata is included by default and can be switched off.
- Metadata only fetches configuration, tokenizer, and documentation files without weights.
- Custom accepts comma-separated include and exclude patterns.
When a repository publishes a sharded GGUF quantization or an MLX weight folder, the
Weight sets list selects the complete set in one click. For example, choosing
UD-Q8_K_XL includes all of that quantization's shards without selecting unrelated weights.
Custom pattern examples:
- Include only SafeTensors and config files:
*.safetensors, *.json, tokenizer* - Download one GGUF quantization:
*Q4_K_M.gguf, *.json, tokenizer* - Exclude legacy PyTorch weights:
*.bin, *.pt, *.pth
Patterns use Hugging Face's official snapshot_download filtering.
Open Settings → My hardware to add named machines and any combination of:
- CPU/system RAM
- one or more GPUs and their VRAM
- Apple silicon and its unified memory
The first rig becomes primary, and any rig can be marked primary later. Hardware profiles are private to the signed-in account. Open a model with detected GGUF quantizations or MLX weight folders to see a fit summary beside each complete weight set; selecting one shows the result for every saved rig.
HuggingHack reserves 20% above the published weight-file size for runtime overhead. Fits means that reserve is available, tight means the raw weights fit without the full reserve, and does not fit means the weight bytes exceed the applicable memory. GGUF checks Apple unified memory, aggregate GPU VRAM, and system RAM; MLX checks Apple unified memory. Missing or inapplicable component data is reported as unknown.
These are planning estimates, not runtime guarantees. Context length, KV cache, framework, offloading strategy, multimodal projectors, and other processes can materially change actual memory use.
Repositories containing GGUF files get a GGUF tab in the model drawer. Select a file or shard to inspect its metadata, tensor names, shapes, data types, quantization breakdown, and parameter count without downloading the model weights.
HuggingHack reads only bounded byte ranges from the selected file, caches the result for the
browser session, and leaves every other shard untouched until you select it. Private and gated
repositories use the backend's HF_TOKEN; the token is never exposed to the browser.
Downloads first write to a hidden staging area and only replace the managed model when the selected revision is complete. Pause stops an isolated worker while keeping the transferred files and Hugging Face local-directory metadata. Resume continues that job; Stop retains the same partial data in case it is useful later. A stopped, paused, or failed job exposes Delete data, which removes only its staging files and keeps the history record.
Administrators can enable one weekly download window in Settings, choose its weekdays and start/end times, and capture the current browser's IANA timezone. New jobs wait while the window is closed. Active transfers pause at closing and resume at the next opening; overnight ranges are supported.
Copy a model folder anywhere within the first few directory levels of the mounted model folder, then choose Local library → Scan folder. HuggingHack recognizes common configs and weight extensions such as:
config.json,model_index.json,tokenizer.json.safetensors,.gguf,.onnx,.bin,.pt,.pth, and.ckpt
Manually copied models are indexed but never modified.
- HuggingHack downloads files but does not execute repository code, import model modules, or deserialize weights.
- Model cards are rendered as sanitized Markdown with safe HTML, readable code, tables, lists, and math; embedded scripts, forms, and frames are discarded.
- Pickle-compatible formats can execute code when loaded by other applications. Prefer SafeTensors or GGUF and only load models from publishers you trust.
- Local passwords are salted and hashed with
scrypt; sessions use hashed random tokens in HTTP-only, SameSite cookies and state-changing requests require a per-session CSRF token. - OIDC uses authorization-code and PKCE protections, validates signed ID-token claims, stores login state server-side, and never sends the Pocket ID client secret to the browser.
- Built-in accounts protect application data, but public exposure still requires HTTPS. Put HuggingHack behind a TLS reverse proxy such as Caddy, Traefik, or Nginx Proxy Manager and set
SECURE_COOKIES=true. - Upload paths are confined to repositories owned by the signed-in account. Repository deletion verifies ownership and requires the exact repository name.
- Runtime dispatch is administrator-only in the UI. Optional bearer access is limited to runtime endpoints; use long random tokens and firewall Ollama and the vLLM agent to trusted LAN clients.
- The vLLM agent rejects paths outside its configured model root and launches a fixed argument vector without a shell.
- Use a read-only Hugging Face token.
Backend:
py -3.13 -m venv .venv
.venv\Scripts\pip install -r backend\requirements.txt
$env:MODEL_STORAGE="$PWD\models"
$env:DATA_DIR="$PWD\data"
.venv\Scripts\uvicorn app.main:app --app-dir backend --reload --port 7860Python 3.12 or 3.13 is recommended for local development. The Docker image uses Python 3.12, so Python is not required on the NAS.
Frontend:
Set-Location frontend
npm install
npm run devThe Vite development server proxies /api to port 7860.
Frontend development and production builds require Node.js 22 or newer. The lockfile is maintained with npm 10.9.8.
Tests and build:
$env:PYTHONPATH="$PWD\backend"
pytest backend\tests
Set-Location frontend
npm test
npm run build- Models: the host path configured by
MODEL_STORAGE_PATH - S3 mode: durable model objects in
S3_BUCKETand working copies inMODEL_STORAGE_PATH - Accounts, sessions, saved collections, repository ownership, download history, and local
index:
./data/hugginghack.sqlite3by default, or the database named byDATABASE_URL - Hub metadata cache:
./data/hub-cache
Back up the models folder and metadata database together. Keep backing up data for the Hub
cache and for SQLite deployments. The model index can be rebuilt from model files, but the
database preserves accounts, saved-model organization, ownership, and download history.
Store backups securely because it contains password hashes and active session hashes.





