Live self-hosted platform

The Stack Behind
mynuggets.dev

A privacy-first, self-hosted platform built with modern tooling. Next.js, FastAPI, Docker, and PostgreSQL — deployed to an Unraid home-lab with security hardening and automated pipelines.

10Applications
15+Technologies
100%Self-Hosted
03rd-Party Trackers

Why This Stack

Built for privacy & speed

Every architectural decision centres on protecting user data while maintaining developer experience and operational simplicity.

🧩

Unified Platform

10 isolated services — Main, Tech, Analytics, FitNuggys, Mental Health, Support, Admin, the Discord bot, and a Fastify middleware gateway, alongside the Diabetes CGM service — all on one shared Docker network.

🛡️

Privacy by Design

No third-party analytics, ever. Every service is self-hosted on this stack — what each one stores server-side, and for how long, is listed per service below.

🔐

Security Hardened

HSTS, CSP, XFO, nosniff, CORS/CSRF protection, timing-safe auth. LibreLinkUp usernames and passwords are not logged; the password itself is encrypted at rest. Other services handle credentials per their own architecture — see below.

🚀

One-Command Deploy

Node-based deployer pushes to Unraid via SSH. Supports full or per-service incremental deploys with health checks.

Architecture

System Overview

A layered architecture designed for separation of concerns, security boundaries, and operational simplicity.

Frontend Layer

Next.js 15React 18TypeScriptTailwind CSS

App Router, static + dynamic rendering, strict typing across all apps.

Backend Services

FastAPINode.jsLibreLinkUp Client (Nuggy)

Python microservice bridges LibreLinkUp API. Next.js API routes handle proxying and sanitization.

Data Layer

PostgreSQL 15pg (node-postgres)asyncpg

Postgres stores contact submissions, admin auth, diabetes users/accounts/readings, and the Analytics demo schema (seeded mock business data). No third‑party tracking; data stays self‑hosted.

Infrastructure

DockerDocker ComposeFastify GatewayUnraid

Multi-stage builds, unified stack, an internal Fastify gateway proxying service-to-service traffic with a constant-time-compared shared secret, self-hosted.

Security

Defense in Depth

Multiple layers of protection at every level — from transport to storage, with privacy as the default, not an afterthought.

🔑

Encrypted Credential Storage

LibreLinkUp credentials are encrypted at rest and used only for periodic re-authentication with LibreLinkUp’s own API — never logged, never sent anywhere else.

🔒

Transport Security

HSTS max-age 1 year, strict CSP, X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin.

🛡️

CORS & CSRF

No wildcard origins with credentials. Same-origin enforcement for admin APIs. Proper preflight handling.

🧹

Data Sanitization

Responses from LibreLinkUp stripped of device metadata, internal IDs, and PII before reaching the client.

📦

Per-Service Data Handling

What each service stores, and for how long, differs by service — see the table below rather than one blanket claim for the whole platform.

🐳

Container Isolation

Multi-stage builds, non-root runtime users, standalone Next.js output, service-level network isolation.

Services

What each service actually stores

10 deployed applications — 7 public, 1 internal admin tool, 2 backend services with no web interface. Status and data handling per service, not one blanket claim for the whole platform.

ServiceStatusStored server-sideRetentionEncryption
Main siteLiveContact form submissionsUntil manually clearedNone beyond standard DB access controls
Tech Stack (this page)LiveNothing — informational onlyn/an/a
Diabetes ManagerLiveAccount metadata, CGM readings, LibreLinkUp passwordUntil account deletedLibreLinkUp password: AES-128 (Fernet), column-level. Readings: standard DB storage, not separately encrypted.
Mental Health DirectoryLivePublic service-directory data only — no personal or user dataOngoing (directory content)n/a — not personal data
Support HubLiveTickets, contact messages, community stories. IP hash (indefinite, rate-limiting); raw IP/user-agent on tickets only (welfare-check use)Ticket raw IP/UA: 90 days, auto-purged. Everything else: until deleted on request.None beyond standard DB access controls
FitNuggysLiveFitbit OAuth tokens, linked-account settingsUntil disconnectedNone beyond standard DB access controls
AnalyticsDemoSeeded mock business data (payroll, GST, accounts) — no real user or financial dataDemo dataset, reset periodicallyn/a — not real data
AdminInternalManages the data above; own data is one operator account + security event logsOperator account: ongoing. Security logs: no scheduled purge (audit trail).Password: bcrypt (12 rounds)
Discord botInternalNo independent storage — relays to/from the services aboven/an/a
Middleware gatewayInternalNo independent storage — internal request routing onlyn/an/a

“Live” means real users and real data. “Demo” means seeded/mock data only. “Internal” means not intended for public use, regardless of whether it has its own domain.

Technologies

The Full Stack

Every tool chosen for a reason — performance, security, developer experience, or operational simplicity.

No entries match this filter.

Interested in a similar stack?

Whether you need a privacy-focused application, a self-hosted solution, or help with Docker and DevOps — let's chat.