NASQuay gives you a web interface, scheduled routines and an MCP endpoint for AI tools — all behind one set of users, roles and per-action permissions, with every action recorded.
It drives QNAP’s own MCP Assistant, which runs on each NAS, and uses SSH only for the few readings it has no tool for. Nothing extra is installed on a NAS.
Storage, shares and files, NAS accounts, logs, security and system — every area built from the actions your role allows. An action you may not run is not offered.
Every action the app can perform is switched on or off per role, with optional per-NAS overrides. An admin can only be disabled if another admin remains.
The pages, the embedded assistant, routines and the MCP endpoint all call the same actions, so one permission check and one audit record cover every route in.
Volumes and shares watched from several independent angles, to catch divergence between what a NAS reports and what is actually there.
Destructive actions need confirmation from a person, and unattended callers cannot perform them unless explicitly allowed.
Installed on your own host. Every NAS, credential, AI provider, schedule and threshold is a setting — nothing about a particular network is built in.
Everything NASQuay can do is an action: a stable name, a schema for its
parameters, and a classification of read, write or
destructive. Whoever is asking — a person at the page, the embedded assistant,
a scheduled routine, an outside AI tool over MCP — the call goes the same way.
the page ──────────────────┐
the embedded assistant ────┤
a routine ─────────────────┤
an outside AI tool ────────┘
│
▼
┌───────────────────────────────────────┐
│ authenticate │
│ permission gate one check per call │
│ audit record one row per call │
└───────────────────┬───────────────────┘
▼
action registry
┌─────────┴─────────┐
▼ ▼
QNAP MCP client SSH runner
│ │
▼ ▼
MCP Assistant df · du · find
A request the caller’s role does not allow is refused before anything is sent to a NAS. Every attempt is recorded either way — when, who, through what, which action, which NAS, the parameters with secrets redacted, the decision and why, the outcome and how long it took.
| Caller | Acts as | Notes |
|---|---|---|
| The embedded assistant | the signed-in user | calls arrive through that user’s browser session, so their role applies exactly as if they had clicked |
| A routine | its run-as user | set by an admin per routine; a routine can never do more than that user can |
| The MCP endpoint | the owner of the API token | tokens are per user, revocable, and hashed at rest |
NASQuay talks to QNAP’s MCP Assistant, the app QNAP ships for its own NAS units, and falls back to a fixed, allow-listed set of SSH commands for the few readings MCP Assistant does not provide. There is no agent to install, no package to sideload and no free-form shell.
Pools, volumes and disks — status, capacity and free space, with usage history backfilled from the NAS on first connection.
Shared folders and their permissions; list, search and share links. Paths are validated and confined to their share.
The users and groups defined on the NAS itself, kept distinct from the people who sign in to NASQuay.
System logs, malware and security scans and their reports, system info and load, installed apps, firmware checks, the power schedule.
QNAP’s tool annotations carry no information — on the firmware examined, every tool including plain reads reports itself destructive. NASQuay ships its own reviewed catalogue instead, and a tool it has not seen before is hidden until an admin classifies it. Cached figures are labelled as cached and never used to trigger a rule; the usage-history units, which the NAS returns mislabelled, are converted and marked rounded.
A NAS that quietly loses data usually still reports itself healthy. NASQuay reads the same
volumes and shares from several independent angles — the NAS’s own MCP figures,
df and du over SSH, and optionally a client machine’s view of
its mount — and raises a flag when they stop agreeing.
| Rule | Fires when |
|---|---|
volume_drop | used space on a volume falls sharply within a window |
file_count_drop | a share’s live file count falls between readings |
df_vs_du | du across a volume’s shares and df disagree beyond a calibrated margin |
client_vs_nas | a client’s view of a mount differs from the NAS’s view |
mcp_vs_df | MCP free space and df disagree beyond the margin |
mount_missing | a configured client mount is absent |
pool_status_change | a pool’s status changes — and it stays badged while degraded |
worker_stale | the worker has not completed a collection run on time |
Collection runs in tiers — cheap readings every few minutes, file counts and
du less often — and every interval and threshold is a setting. Flags appear on
the dashboard, and can be sent on by email or push.
A scheduled piece of work, on an interval or a cron expression, running as a user you choose. A fixed routine is an ordered list of actions with parameters and no AI involved. An AI routine is a prompt, a provider, and the subset of actions the model may call — the worker loops until it answers or hits the routine’s step limit. Every run is recorded: start, end, status, each action called, final output.
NASQuay embeds the suite’s assistant and publishes its actions to it. The assistant’s calls travel through the signed-in user’s own browser session, so your role applies exactly as if you had clicked — and writes still need your confirmation.
For AI tools outside NASQuay. Streamable HTTP, authenticated by a per-user API token, with the tool list filtered to the actions that user’s role allows. Long-running actions return a job id and a tool to check it.
Any OpenAI-compatible server — including a local Ollama, LM Studio or vLLM — or the Anthropic API. Nothing assumes a particular model size, and a routine that needs tool calling can require a provider that does it properly.
BatchMode, a pinned host key and allow-listed commands only.
There is no free-form shell action, and there is not going to be one.git clone https://github.com/bsnwgit/nasquay.git
cd nasquay
bash install.sh
The installer asks for the install directory, the listen address and port, and the first
admin account. It creates the virtual environment, writes config.yaml with
freshly generated keys, and installs the nasquay-web service.
127.0.0.1. Put a TLS reverse proxy in front of it
before using it from other machines.
bash uninstall.sh # service, environment and all data
bash uninstall.sh --keep-data # keeps config.yaml, the database, secrets and logs