- C++ 96.1%
- C 3.9%
- Add /admin/login POST handler with session token and 4-hour expiry - Add /admin/logout GET handler to clear session - Strip monolithic function duplicates from icons.cpp (broken linker) - Remove duplicate JS, QR_JS, rmRecursive, and upload state from pages.cpp - Fix SP upload slot check (was checking stale globals instead of queue pos) - Add rate limiting (10 attempts/5min, 5min lockout) on login and SP code entry - Upgrade randToken to use esp_random() HW RNG with [a-z0-9] charset - Add SameSite=Strict to cookies, session expiry tracking - Change static const char* to constexpr in config.h - Remove dead isAdminHost() code, fix duplicate CFG_UPLOAD_SLOTS assignment |
||
|---|---|---|
| src | ||
| .gitignore | ||
| platformio.ini | ||
| README.md | ||
PocketNAS
A portable offline file-sharing device built on the AI Thinker ESP32-CAM. Creates its own WiFi network and serves a web-based file manager over SD card storage.
Hardware
- AI Thinker ESP32-CAM
- MicroSD card (FAT32)
(Could not test it on a normal ESP32 since i don't have one.)
Building
Requires PlatformIO.
pio run --target upload
Dependencies (resolved automatically by PlatformIO):
ESP32Async/AsyncTCP @ ^3.3.2ESP32Async/ESPAsyncWebServer @ ^3.7.0
Partition scheme: huge_app (3MB code / 1MB SPIFFS) - set in platformio.ini, required due to the size of the embedded HTML/CSS/JS.
First Boot
On first boot (or if the SD card has no config), the device starts in setup mode. Connect to the WiFi network PocketNAS (open, no password) and navigate to http://storage.local or http://192.168.4.1. A three-step wizard will walk you through:
- Network name - the SSID the device broadcasts
- Sharepoint - enable or disable the guest sharing feature
- Passwords and settings - admin password, and either a WiFi password (if sharepoint is disabled) or upload slot count and code lifetime (if enabled)
The device reboots after saving. Config is stored at /.pnas/nas.conf on the SD card.
Interfaces
PocketNAS exposes two separate web interfaces, distinguished by the Host: header. Both run on the same IP (192.168.4.1).
| Interface | URL | Fallback IP | Purpose |
|---|---|---|---|
| Admin | storage.local |
192.168.4.1 |
Full file manager, protected by admin password |
| Sharepoint | sharepoint.local |
192.168.4.2 |
Guest access, protected by time-limited code |
If mDNS isn't resolving (common on some devices), the fallback IPs work identically.
Admin Interface
Log in with the admin password set during setup. From here you can:
- Browse, upload, download files and folders
- Create and delete folders
- Rename files and folders
- View files inline (images, video, audio, PDF, text) or download anything
- Manage sharepoints and generate guest access codes
- View the QR code for easy connection sharing
All per-item actions (rename, delete, sharepoint, download) are behind a ⋮ menu on each row.
Sharepoint
Sharepoint lets you expose specific files or folders to guests without giving them access to the rest of the SD card.
Setting up a sharepoint
- In the admin file manager, open the
⋮menu on any file or folder - Click Sharepoint
- Choose an access mode:
- Read Only - guests can browse and download, no uploads
- Write Only - guests can upload files, but cannot see or download anything (suitable for collecting submissions privately)
- Read + Write - guests can both upload and download
- Go to Sharepoint in the header to generate an access code
Guest access
Guests connect to the same WiFi network and navigate to sharepoint.local (or 192.168.4.2). They enter the 6-digit code and immediately land in the shared folder or file. They see it as their root - no other paths on the SD are visible or accessible.
Codes expire after the configured TTL (default 1 hour). Multiple codes for different paths can be active simultaneously. Codes can be revoked early from the Sharepoint admin page.
Upload slots
To prevent the ESP32 from being overwhelmed when multiple guests upload simultaneously, uploads are queued. The slot count (set during setup, default 3) controls how many uploads can proceed at once. Waiting guests see their position in the queue and are notified when a slot opens.
Configuration
/.pnas/nas.conf on the SD card, key=value format. Lines starting with # are comments. The setup wizard generates this file - you can also edit it by hand.
| Key | Default | Description |
|---|---|---|
ap_ssid |
PocketNAS |
WiFi network name |
admin_password |
- | Password for storage.local |
sp_disabled |
false |
Set true to disable all sharepoint features |
ap_password |
- | WiFi password, only used when sp_disabled=true |
upload_slots |
3 |
Max concurrent uploads (sharepoint only, 1–10) |
code_ttl |
3600 |
Guest code lifetime in seconds |
When sp_disabled=true, the WiFi network uses WPA2 with ap_password, the sharepoint interface is completely removed, and the device behaves as a simple private file server.
The /.pnas/ directory is hidden from the browser interface and cannot be browsed, downloaded, or modified through the web UI.
Source layout
src/
├── PocketNAS.ino hardware init, WiFi, DNS, entry point
├── config.h/.cpp config file, sharepoint map
├── auth.h/.cpp admin session, guest codes, upload queue
├── files.h/.cpp SD operations, upload handler
├── icons.h/.cpp SVG icon strings
├── assets.h/.cpp CSS, JS, QR encoder (flash-stored)
├── pages.h/.cpp HTML page builders
├── routes.h/.cpp HTTP route registration, request dispatch
└── util.h/.cpp string, path, and MIME helpers
Known limitations
- Single WiFi radio - only one network at a time. Sharepoint guests and admin share the same AP; the Host header distinguishes which interface to serve.
- mDNS reliability varies by OS. Some devices may need the IP fallback.
- SD card writes are not atomic. If power is lost mid-upload, the partial file will remain on the card.
- The upload queue is in-memory and resets on reboot. Guests in a queue will need to rejoin after a power cycle.
© 2026 CrystalSky | Code AI Assisted