"mounted" was true even when /data was the hidden anonymous volume Docker creates for the Dockerfile's VOLUME, so the app looked fine while the user's host folder stayed empty and the data was lost when the container was recreated. Read the mount source and report host folder, named volume or anonymous volume (flagged), in Settings and the startup log. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
NE Hub
One installable web app (PWA) for Seafile, OnlyOffice and your four webmail accounts. Mobile-first; bottom tabs on phones, side rail on iPad and desktop (tuned for 12.9" at 1024 and 1366 wide).
Configure
cp .env.example .env # set ONLYOFFICE_JWT_SECRET (same value as the Document Server) and PUBLIC_URL
PUBLIC_URL must be an address the OnlyOffice server can reach (not localhost): it posts saved edits back there.
Run
docker compose up -d --build # http://localhost:8080
# or: node server.js
Put it behind your reverse proxy with HTTPS (needed for "Add to Home Screen" and the service worker),
e.g. hub.necloud.us. Settings: SEAFILE_URL, ONLYOFFICE_URL env vars in docker-compose.yml.
What each part does
- Files: signs in with your Seafile account, browses libraries, uploads, creates folders, downloads, deletes.
The server proxies
/sf/*to Seafile because Seafile sends no CORS headers. Token lives in the browser only. Office files open in Seafile's own OnlyOffice integration. - Edit here: opens docs inside the app via OnlyOffice. The server signs each editor config with the JWT secret and saves edits back to Seafile.
- Sign-in: the whole app sits behind a passkey (WebAuthn). First run: open the site and enter the setup code (
HUB_SETUP_CODE, or the one printed in the server log) to create a passkey; add more devices from Settings. Passkeys and the session secret live in/data(a Docker volume). - Files: also rename, move, share links, image/PDF/video/audio preview, and New document/spreadsheet/presentation.
- Calendar: month grid and agenda. Add, edit and delete events:
- NE Hub calendar: events you create are stored in
/data/events.jsonand published as a private subscribe link (Manage calendars -> copy link) so Outlook, Google or Apple Calendar can show them (read-only there). - iCloud (two-way): connect with an Apple ID and an app-specific password (appleid.apple.com). Credentials are
encrypted in
/data/icloud.json; only*.icloud.comis contacted. Edits keep alarms and attendees intact. - ICS links (Google secret address, Outlook/M365 published calendar) are read-only.
- NE Hub calendar: events you create are stored in
- Tasks: to-do lists stored in NE Hub (
/data/tasks.json), with due dates, notes and completion. If the connected iCloud account exposes reminder lists over CalDAV they appear too and sync both ways. Apple hides Reminders lists that were upgraded for iOS 13+, so for most accounts only NE Hub lists are available. - Settings sync: your preferences (mail addresses, audiobooks sign-in (encrypted), Plex library, Office save location, calendar/task views, recent files) are saved on the server in
/data/settings.jsonand shared by every device. Per-device items (Seafile sign-in token, music queue) stay in the browser. - Search: libraries, file names (scans libraries if Seafile has no search index) and Plex artists/albums/tracks.
- Music: Plex player. Sign in goes through plex.tv (no password handled), the server proxies your Plex server and adds the token itself, and a mini player keeps playing as you move between tabs; the queue (play next / add to queue) and position are remembered.
- Audio: embeds audiobooks.necloud.us; sign-in details saved in Settings can be copied with one tap.
- Podcast and Podcast Admin: launchers that open
PODCAST_URL(a home-network address) andVERSE_URLin their own tabs. - Office: embeds onlyoffice.necloud.us in a frame, with an "open in new tab" fallback if it blocks framing.
- Mail: deep links to Gmail, Outlook.com, Microsoft 365 and iCloud webmail (inbox + compose). Providers forbid framing, and a real unified inbox would need Google/Azure app registrations.
Install on iPhone / iPad (PWA)
Open the site in Safari (it must be the https:// address), tap Share -> Add to Home Screen. The home-screen app has proper
icons (iPhone, iPad), a splash screen for each iPhone and iPad size (including iPad Pro 12.9"), and opens full screen without Safari's bars.
iOS keeps a separate sign-in for the home-screen app, so sign in once inside it with your passkey; it then stays signed in
(SESSION_DAYS, default 180, renewed whenever you use it). Regenerate the artwork with python3 tools/make-icons.py (needs Pillow).
Build and deploy with Gitea
.gitea/workflows/build.yml builds the container on every push to main (and v* tags) and pushes it to
git.necloud.us/nate/hub (tags: latest, short commit sha, git tag). amd64 (x86) only.
One-time setup in Gitea: create an access token with the write:package scope, then add it to the repo under
Settings -> Actions -> Secrets as REGISTRY_TOKEN (optionally REGISTRY_USER). The runner needs Docker.
On the server:
cp .env.example .env # fill in secrets, PUBLIC_URL, etc.
docker compose pull && docker compose up -d
docker compose logs hub | grep "Setup code" # first sign-in: create your passkey