File areas
File areas are the BBS's download library. Each area lives on disk
under a configurable storage path.
Creating an area
Admin → File Areas → Add Area:
| field | purpose |
|---|---|
tag |
unique key (e.g. FILES.GAMES) |
name |
display name |
description |
shown in the area listing |
storage_path |
absolute path on disk where files live |
upload_permission |
none / users / sysop |
is_sysop_only |
hide entirely from non-admins |
password |
optional — area lock |
min_access_level |
minimum access level to see/browse the area (default 10 = registered users; 0 = everyone, 50 = VIP, 100 = sysop) |
min_write_level |
minimum access level to upload, independent of upload_permission |
Where files live
Each area stores binaries in its storage_path. Sysop can drop files
in directly (e.g. via SFTP) or users can upload via the web or FTP.
Migrating an existing file collection that already has a classic
FILES.BBS / FILES.BSS index? tools/bbs-files-tool.py builds the
.descriptions.json cache ANetBBS reads for an area directly from
that index, without touching the original file. See
FILEBASE-MIGRATION.md for the full
walkthrough.
FTP access
When FTP_ENABLED=true in .env (or via Admin → Settings), the
ANetBBS FTP server publishes every active FileArea as a top-level
directory. Three views are served from the same port:
- Anonymous (
anonymous/ blank password) — read-only, sees only
active areas withis_sysop_only=false. Earns you the FTN nodelist
IFCflag once advertised. - Authenticated users — same login as web / telnet / SSH. Read
everything not sysop-only, upload subject to each area's
upload_permission(none/users/sysop). - Sysop — read + write everything, including
is_sysop_onlyareas.
Uploads via FTP create the same FileUpload row a web upload would,
so they show up in the web file-area browser as well. Per-area
upload_permission is enforced post-write: a denied upload is
deleted from disk and the violation is logged.
Ports to open on the firewall: 21/tcp (control) and the configured
FTP_PASV_PORTS range (default 40000-40050, data channels). See
docs/PORTS.md for the full table. Optional FTPS by setting
FTP_TLS_CERTFILE + FTP_TLS_KEYFILE (reuse your nginx
Let's Encrypt cert).
Daily download quota
Admin → File System → Download Quotas (/admin/file-quotas) caps
how much a user can download per day, scaled by access level — so one
user can't tag-leech the whole file base overnight.
Configure a list of (minimum access level, daily quota in MB) tiers.
A user gets whichever tier has the highest access level they still
qualify for — e.g. tiers at level 50 and 100 give a level-75 user the
level-50 quota, not the level-100 one. A level with no tier configured
at or below it downloads unlimited. Admins always bypass.
Enforced everywhere a file can be downloaded: the web file-area and
file-gallery routes, ANSI telnet/SSH (Zmodem/Ymodem/Xmodem, single and
batch), PETSCII (Xmodem), and FTP (RETR) — anonymous FTP logins and
QWK-node FTP sessions are exempt (no local account to attribute usage
to, or out of scope respectively). Usage resets at Eastern midnight.
Upload moderation queue
Set FILE_MOD_QUEUE_ENABLED=true in .env to require sysop approval
for non-admin uploads.
When on:
- User uploads → file lands in data/file-queue/, a
FileQueueEntry row marks it pending.
- Admin → File Queue (/admin/file-queue/) lets sysop approve
(moves to area storage_path) or reject (deletes).
Upload safety checks
Two checks run automatically on every upload, before it's accepted:
- Archive integrity test — zip/tar/7z/rar archives are opened and
verified; a corrupt archive is rejected outright instead of sitting
in the file base as a broken download. - Content-hash dedup check — a SHA-256 hash of the file's content
(not its filename) is compared against everything already in the
file base. A near-identical re-upload under a different name gets
flagged instead of silently duplicating storage.
File ratios
Mystic/Synchronet-style ratio control:
RATIO_MIN=0.05 # require uploads to be at least 5% of downloads
When set:
- Each download bumps bytes_downloaded on FileRatio per user.
- Each upload bumps bytes_uploaded.
- A new download is blocked if the user's projected ratio
(after the download) is below RATIO_MIN. Sysops always exempt.
Set RATIO_MIN=0 (default) to disable.
Hatched files (TIC)
TIC ("Ticket File") is FidoNet's file-echo distribution mechanism —
the file-area equivalent of echomail. It runs in both directions:
Inbound
If you've subscribed to file echos via FidoNet, the TIC processor
(anetbbs/echomail/tic.py) auto-files incoming .tic packets into the
matching area. Audit at Admin → TIC In Log (/admin/tic-log) — its
outbound counterpart, TIC Out Log (/admin/hatch-log), covers the
queue described below.
Outbound — automatic, no manual step
This is the part that's easy to miss: uploading a file to any file
area that has a network attached (network_id is not None) queues
that file for outbound distribution to every peer subscribed to that
file echo — automatically, with no extra action. This includes all
9 of the bundled ANN.FILES.* areas (see doc 6 —
Echomail for the full list) as well as any custom
file-echo area you attach to a network yourself.
Concretely: _hatch_if_network_area() in anetbbs/web/file_areas.py
runs after every successful upload — the regular Upload form, the
sysop's Manage → Upload, and Smart Upload all call it, as does
the moderation queue's Approve action in
anetbbs/web/file_queue.py (so a queued upload only hatches out once
a sysop actually approves it, not the moment a user submits it). It
calls hatch_local_file() in tic.py, which queues one HatchQueue
row per subscribed peer (FileEchoSubscription) with a fresh CRC32
and size — the same fan-out process_tic() does for a TIC that
arrived from elsewhere, except this file is the origin hop, so there's
no prior SEEN-BY/PATH to inherit.
In short: if you upload to a network-attached area, you are
broadcasting that file to every peer on that file echo, not just
filing it locally. Purely local file areas (network_id is None)
are unaffected — nothing is queued for those.
Delivery happens on the next BinkP poll per peer. A sysop running this
BBS as a network hub can see the outbound queue's current
pending/failed counts on the TIC / File Distribution tab of Admin
→ Echomail Networks → Hub Management (/admin/echomail/hub/), which
links through to the TIC Out Log (/admin/hatch-log) for the full
per-item detail (which file, which peer, retry count, last error) — see
doc 6 for the full Hub Management writeup. That
dashboard view is hub-operator-only (gated by REGISTRY_MODE_ENABLED);
the plain Admin → TIC In/Out Log audit pages above are available on
every install.
FileFix — subscription requests from peers
FileFix is the file-echo counterpart to AreaFix (see
doc 6 — Echomail) — it lets a downstream peer manage
their own file-echo subscriptions by sending a netmail instead of the
hub sysop doing it by hand. It lives in anetbbs/echomail/filefix.py
and reuses AreaFix's exact command grammar.
A peer addresses a netmail to FileFix (also recognized:
File Fix, FileMgr) at your hub address, with the AreaFix/FileFix
password in the Subject line (per FTS-0024 — NOT in the body, same
convention as AreaFix) and one command per line in the body:
+FILES.GAMES subscribe to a file echo
-FILES.GAMES unsubscribe from a file echo
+ALL / -ALL subscribe / unsubscribe to everything available
%LIST (or %QUERY) reply with current subscriptions
%HELP reply with a help/command summary
The bot replies with a netmail confirming what changed. If the
requester's FTN address matches a BinkPNode this BBS hosts as a hub
peer, the change is scoped to that peer's own FileEchoSubscription
rows (keyed by peer address, not a BinkPNode foreign key — a real
structural difference from AreaFix's EchoAreaNode) instead of the
global FileArea.is_subscribed flag.
Password: FileFix shares the same network-level password fields as
AreaFix — there's no separate filefix_password. Set areafix_password
(or leave it blank to fall back to binkp_password) on the network's
edit page; it covers both bots.
The sysop side of outbound FileFix requests (subscribe/unsubscribe
buttons on file-area management pages) queues the same kind of netmail
automatically — see send_areafix_request(..., robot_name='FileFix')
in areafix.py (FileFix reuses AreaFix's outbound sender directly).
Traffic is logged on the same Admin → Echomail Networks → AreaFix
Log page AreaFix uses (/admin/echomail/areafix_log) — a Bot
column and an AreaFix/FileFix filter distinguish the rows.
Shareable links
Any user can mint an expiring share link for a file in an area they
have access to. Tools → My File Shares.