Skip to content
mattlol85Public

About

A collection of software that runs the Fitz-Net

Resources

Stars

2 stars

Watchers

1 watching

Forks

Repository files navigation

Contributors Forks Stargazers Issues MIT License LinkedIn


Logo

Fitz-Net

A self-hosted platform for @mattlol85's ideas — running on bare metal, served to the internet.
Explore the docs »

Live Site · Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Architecture
  3. Repositories
  4. Service Details
  5. Built With
  6. Getting Started
  7. Roadmap
  8. Contributing
  9. License
  10. Contact

About The Project

Product Name Screen Shot

Fitz-Net is a self-hosted, full-stack personal platform running on a home server — exposed to the internet via dynamic DNS. It's a place to build and ship real ideas, backed by real infrastructure: a Proxmox hypervisor, Docker containers, a Caddy reverse proxy, physical ESP32 hardware that talks to the backend over WebSockets, a self-hosted email server for fitznet.org, a Discord bot (Fitz-Bot) that manages a Minecraft server, and a full observability stack (Grafana, Loki, Prometheus, Promtail, cAdvisor).

(back to top)

Architecture

Infrastructure

Traffic arrives at fitznet.org, which is fronted by an external reverse proxy that forwards to fitznet.doomdns.org (dynamic DNS on the home router). From there it reaches a Proxmox server where the active Ubuntu VM runs Docker, hosting all services behind a Caddy reverse proxy. A second Ubuntu VM is kept idle as a spare/staging target.

graph TD
    Internet(["🌐 Internet"])
    FitznetOrg["fitznet.org\nReverse Proxy"]
    DNS["fitznet.doomdns.org\nDynamic DNS"]
    Router["🏠 Home Router\nPort Forwarding"]

    subgraph Proxmox["Proxmox Server · 192.168.1.225"]
        VM1["Ubuntu VM 1\n⏸ Idle"]

        subgraph VM2["Ubuntu VM 2 · 192.168.1.59 — Docker"]
            Caddy["Caddy\nReverse Proxy"]

            subgraph Core["fitznet-core"]
                Website["fitz-net-website\nReact SPA"]
                API["fitz-net-api\nSpring Boot REST"]
                Bell["GamerBell\nWebSocket + OTA"]
                Mongo["MongoDB"]
            end

            subgraph Mail["mail/"]
                MailServer["mailserver\nSMTP + IMAP"]
                Roundcube["Roundcube\nWebmail"]
            end

            subgraph Obs["observability/"]
                Grafana["Grafana\nlogs.fitznet.org"]
                Prometheus["Prometheus\n:9090"]
                Loki["Loki\n:3100"]
                Promtail["Promtail"]
                CAdvisor["cAdvisor\n:8081"]
                NodeExp["node-exporter\n:9100"]
            end
        end

        FitzBot["🤖 Fitz-Bot\nDiscord bot · Spring Boot"]

        subgraph VM3["Ubuntu VM · Minecraft Server"]
            MC["Minecraft Server\nRCON :25575 · whitelist"]
        end
    end

    ESP32["📟 ESP32 Bell\nEsp32FitznetBell"]
    Discord(["💬 Discord"])

    Internet --> FitznetOrg --> DNS --> Router
    Router -->|"80/443"| Caddy
    Router -->|"25/587/993"| MailServer
    Caddy --> Website
    Caddy --> API
    Caddy --> Bell
    Caddy --> Roundcube
    Caddy --> Grafana
    API --> Mongo
    MailServer --> Roundcube
    ESP32 -->|"wss"| Bell
    Discord <-->|"slash commands"| FitzBot
    FitzBot -->|"RCON · whitelist add"| MC

    Promtail -->|"logs"| Loki
    CAdvisor -->|"metrics"| Prometheus
    NodeExp -->|"metrics"| Prometheus
    Loki --> Grafana
    Prometheus --> Grafana
Loading

Services

The services and how they interact at the application layer:

graph LR
    Browser(["🖥 Browser"])
    ESP32(["📟 ESP32 Device"])

    subgraph Website["fitz-net-website · React 19 + Vite"]
        React["App"]
        AuthCtx["AuthContext\nJWT · localStorage"]
        ApiSvc["api.js\nfetch wrapper"]
        WSClient["STOMP WebSocket\nClient"]
    end

    subgraph API["fitz-net-api · Spring Boot 3.4"]
        SecFilter["JWT Auth Filter"]
        Controllers["Controllers"]
        Services["Services"]
        Repos["Repositories"]
        MailSvc["EmailService\nSpring Mail"]
    end

    subgraph Bell["GamerBell · Spring Boot 3.4"]
        WSHandler["ButtonWebSocket\nHandler"]
        BellSvc["ButtonService\nSession Pool"]
        FirmSvc["FirmwareService\nOTA Cache"]
    end

    Mongo[("MongoDB")]
    GitHub(["GitHub Releases\nOTA Firmware"])
    MailServer(["mail.fitznet.org\ndocker-mailserver"])

    Browser --> React
    React --> AuthCtx --> ApiSvc
    ApiSvc -->|"REST / HTTPS"| SecFilter
    SecFilter --> Controllers --> Services --> Repos --> Mongo
    Services --> MailSvc -->|"SMTP"| MailServer

    React --> WSClient
    WSClient -->|"wss"| WSHandler
    WSHandler --> BellSvc -->|"broadcast"| WSClient

    ESP32 -->|"wss"| WSHandler
    ESP32 -->|"GET /api/firmware/latest"| FirmSvc
    FirmSvc -->|"fetch .bin"| GitHub
Loading

(back to top)

Repositories

Repo Description
Fitz-Net This repo — orchestration hub, architecture docs
fitz-net-api Spring Boot 3.4 REST API — user management, auth, encryption, email
fitz-net-website React 19 SPA — dashboard, live board, game stats, auth, password reset
GamerBell Spring Boot WebSocket relay + OTA firmware server for ESP32 bells
Esp32FitznetBell C++ / PlatformIO firmware for the physical ESP32 bell button
Fitz-Bot Discord bot — voice-join milestones, media downloads (Radarr/Sonarr), Minecraft whitelist management
Fitz-Net-Agent-Sandbox AI agent workspace + mail server Docker Compose config

(back to top)

Service Details

fitz-net-website

Repo: mattlol85/fitz-net-website
Live: https://fitznet.org

React 19 frontend served via Caddy. Features:

  • Homepage with animated Fitz-Net branding
  • Overwatch 2 tracker — competitive leaderboard, history charts, player avatars
  • LiveBoard — real-time collaborative canvas via STOMP WebSocket
  • GamerBell widget — live status of physical ESP32 button devices
  • Status Dashboard — monitors all service health via Spring Actuator
  • User auth (JWT), profile editing, forgot-password / reset-password flow

Stack: React 19 · Vite 6 · React Router 7 · Vanilla CSS Modules · Docker


fitz-net-api

Repo: mattlol85/fitz-net-api
Live: https://api.fitznet.org

Spring Boot 3.4 REST API and WebSocket backend. Features:

  • User management (register, login, JWT auth, profile update)
  • Overwatch 2 integration via OverFast API (player stats, ratings, history snapshots)
  • LiveBoard STOMP WebSocket for shared canvas state
  • AES encryption endpoints
  • Password reset via email — generates secure tokens, sends reset links via noreply@fitznet.org

Stack: Java 21 · Spring Boot 3.4 · MongoDB · Spring Security (JWT/BCrypt) · Spring Mail · Gradle · Docker

Key environment variables:

Variable Purpose
JWT_SECRET HS256 signing key
ADMIN_API_KEY Optional. Enables the X-Admin-Key header for managing user permissions (see below); unset disables it
MONGO_HOST / MONGO_PORT MongoDB connection
MONGO_USERNAME / MONGO_PASSWORD MongoDB app-user credentials
MAIL_HOST SMTP host (mail.fitznet.org)
MAIL_USERNAME SMTP user (noreply@fitznet.org)
MAIL_PASSWORD SMTP password
APP_BASE_URL Base URL for reset links (https://fitznet.org)

GamerBell

Repo: mattlol85/GamerBell
Live: https://gamerbell.fitznet.org

Spring Boot WebSocket relay service bridging physical ESP32 button devices with the Fitz-Net web UI. Also handles over-the-air (OTA) firmware updates for ESP32s via the GitHub Releases API.

Stack: Java 21 · Spring Boot 3.4 · Spring WebSocket · Docker


Esp32FitznetBell

Repo: mattlol85/Esp32FitznetBell

C++ / PlatformIO firmware for the physical ESP32 bell button. The device connects to GamerBell over a WebSocket to broadcast button press/release events and shows the currently active users on a local 0.96" OLED screen. WiFi credentials and the user's display name are configured at first boot through the FitzNetBell-Setup WiFiManager captive portal — nothing is hardcoded. New firmware is published as GitHub Releases and pushed to devices over the air via GamerBell's GET /api/firmware/latest.

Hardware: ESP32 DevKit · SSD1306 OLED (I2C — SDA GPIO 21, SCL GPIO 22) · push button on GPIO 13.

Stack: C++ · PlatformIO · Arduino framework · WebSockets · Adafruit SSD1306/GFX · ArduinoJson · WiFiManager · FastLED


Fitz-Bot

Repo: mattlol85/Fitz-Bot

Discord bot for the Fitz-Net community. Built on JDA, it tracks voice-channel activity and posts milestone celebrations, exposes media-download commands backed by Radarr/Sonarr, and manages the Minecraft server that runs on a separate VM adjacent to the Docker host.

The /whitelist <username> command lets trusted members (gated by a configurable Discord role) add players to the Minecraft whitelist over RCON. Together with white-list=true + online-mode=true on the server, this keeps anonymous crawlers/bots out.

Slash commands:

Command Purpose
/whitelist <username> Add a player to the Minecraft whitelist (role-gated)
/setwhitelistrole <role> Choose which Discord role may use /whitelist (admin)
/setbotchannel · /getbotchannel Configure where milestone messages post
/joenet download · /joenet status Search/queue movies & TV (Radarr/Sonarr)

Stack: Java 21 · Spring Boot 3.2 · JDA 5 · Gradle

Key environment variables:

Variable Purpose
DISCORD_BOT_TOKEN Discord bot token
MINECRAFT_RCON_HOST / MINECRAFT_RCON_PORT Minecraft server RCON endpoint
MINECRAFT_RCON_PASSWORD RCON password (matches rcon.password in server.properties)
JOENET_HOST · JOENET_RADARR_APIKEY · JOENET_SONARR_APIKEY Media download integration

See docs/fitz-bot.md for the Minecraft topology and whitelist/RCON setup guide.


Mail Server

Config: Fitz-Net-Agent-Sandbox/mail/
Live: https://mail.fitznet.org (webmail) · mail.fitznet.org:993 (IMAP) · mail.fitznet.org:587 (SMTP)

Self-hosted email for fitznet.org running via Docker Compose alongside the other services.

Container Image Role
mailserver ghcr.io/docker-mailserver/docker-mailserver SMTP (Postfix) + IMAP (Dovecot) + rspamd spam filter + DKIM
roundcube roundcube/roundcubemail Browser-based webmail, proxied through Caddy

DNS records required:

Type Name Value
A mail <public IP>
MX @ mail.fitznet.org (priority 10)
TXT @ v=spf1 mx ~all
TXT _dmarc v=DMARC1; p=quarantine; rua=mailto:admin@fitznet.org
TXT dkim._domainkey (generated by docker-mailserver)

DMARC: start at p=none only long enough to confirm from the rua aggregate reports that all legitimate mail (including the Resend relay) passes SPF/DKIM alignment, then publish p=quarantine as above. Move to p=reject once quarantine has been clean for a few weeks.

See docs/mail-server.md for the full step-by-step setup guide.

(back to top)

User permissions: users carry a set of permissions that the website uses to show/hide tabs and that the API enforces. Permissions are defined at runtime in MongoDB (permissions collection) — only ADMIN is built in and cannot be deleted. Create them first, then grant them. Manage them from the website /admin page (needs ADMIN) or the API, using either an admin user's JWT or the X-Admin-Key header:

curl -H "X-Admin-Key: $ADMIN_API_KEY" https://<api>/admin/permissions
curl -H "X-Admin-Key: $ADMIN_API_KEY" -H 'Content-Type: application/json' -X POST \
     -d '{"name":"RADARR","description":"Radarr tab"}' https://<api>/admin/permissions
curl -H "X-Admin-Key: $ADMIN_API_KEY" -X DELETE https://<api>/admin/permissions/RADARR   # also revokes from all users
curl -H "X-Admin-Key: $ADMIN_API_KEY" https://<api>/admin/users
curl -H "X-Admin-Key: $ADMIN_API_KEY" -X POST   https://<api>/admin/users/<user>/permissions/RADARR
curl -H "X-Admin-Key: $ADMIN_API_KEY" -X DELETE https://<api>/admin/users/<user>/permissions/RADARR
curl -H "X-Admin-Key: $ADMIN_API_KEY" -H 'Content-Type: application/json' -X PUT \
     -d '{"permissions":["RADARR","SONARR"]}' https://<api>/admin/users/<user>/permissions

There is no seeded admin; grant ADMIN to the first user with the API key.

Built With

  • React
  • Spring
  • Java
  • Node
  • MongoDB
  • Docker
  • Caddy
  • Grafana

(back to top)

Getting Started

Each component lives in its own repository. Clone the ones you need:

git clone https://github.com/mattlol85/fitz-net-api.git
git clone https://github.com/mattlol85/fitz-net-website.git
git clone https://github.com/mattlol85/GamerBell.git
git clone https://github.com/mattlol85/Esp32FitznetBell.git

fitz-net-api — requires Java 21 and MongoDB:

cd fitz-net-api
./gradlew bootRun

fitz-net-website — requires Node.js:

cd fitz-net-website
npm install
npm run dev

GamerBell — requires Java 21:

cd GamerBell
./gradlew bootRun --args='--spring.profiles.active=dev'

Esp32FitznetBell — requires PlatformIO and an ESP32 board:

cd Esp32FitznetBell
pio run                 # Compile firmware
pio run --target upload  # Flash to a connected ESP32 over USB
pio device monitor       # Serial logs (115200 baud)
# First boot: connect to the "FitzNetBell-Setup" WiFi AP to set WiFi + display name

Mail stack — run on the Proxmox Docker host:

cd Fitz-Net-Agent-Sandbox/mail
docker compose up -d
# First time: create mailboxes and generate DKIM
docker exec -ti mailserver setup email add matt@fitznet.org
docker exec -ti mailserver setup email add noreply@fitznet.org
docker exec -ti mailserver setup config dkim

Observability stack — run on the Docker host:

cd observability
cp .env.example .env   # then set GRAFANA_ADMIN_PASSWORD to a strong value
docker compose up -d
# Grafana UI available at https://logs.fitznet.org (login: admin / $GRAFANA_ADMIN_PASSWORD)
# GRAFANA_ADMIN_PASSWORD only applies on first start; on an existing install rotate it with:
#   docker exec -it grafana grafana cli admin reset-admin-password '<new password>'

See each repo's .github/agents.md for full conventions, build commands, and architecture details.
See docs/mail-server.md for the complete mail server setup guide.

(back to top)

Roadmap

  • React frontend + Spring Boot API
  • JWT authentication and user management
  • Overwatch 2 stats tracker and leaderboard
  • LiveBoard — real-time collaborative canvas
  • ESP32 physical bell button with WebSocket integration (GamerBell + Esp32FitznetBell)
  • OTA firmware updates for ESP32 devices via GitHub Releases
  • Self-hosted on Proxmox + Docker behind Caddy reverse proxy
  • Observability stack — Grafana, Loki, Prometheus, Promtail, cAdvisor, node-exporter
  • Self-hosted email at fitznet.org (docker-mailserver + Roundcube)
  • Password reset via email
  • Raspberry Pi remote client with hardware buttons
    • 3D print enclosure and upload files to GitHub
  • Complete a 1.0 release

See the open issues for a full list of proposed features and known issues.

(back to top)

Contributing

  1. Fork the relevant repo
  2. Create a feature branch: git checkout -b feature/your-feature
  3. Commit using conventional commits:
    feat(scope): what you added
    fix(scope): what you fixed
    chore(scope): maintenance change
    
  4. Push and open a Pull Request against main

(back to top)

Claude Code agents & skills

This hub ships custom Claude Code agents and skills for the cross-repo orchestration work this repo exists to do. They live in .claude/.

Agents (.claude/agents/):

Agent What it does
repo-sweeper Read-only sweep of all six sibling repos — pulls each, lists open issues, returns a ranked table clustered by repo/theme/effort
pr-triage Scores every open PR across the six repos for merge confidence (diff size, CI, contract surfaces touched) and lists what is safe to auto-merge + tag
cross-repo-feature Implements a multi-repo feature per the numbered workflow in .github/agents.md — matching branches, API contract first, backend before frontend, linked PRs
release-conductor The merge → tag → deploy → handoff tail: verifies CI, merges, cuts semver tags, triggers Deploy to Proxmox, writes a prod handoff
java-spring-agent Java 21 / Spring Boot specialist for fitz-net-api, GamerBell, Fitz-Bot
react-frontend-agent React 19 / Vite specialist for fitz-net-website
esp32-cpp-agent C++ / PlatformIO specialist for Esp32FitznetBell

Skills (.claude/skills/):

Skill What it does
sync-siblings Runs the mandatory six-repo git pull and prints a per-repo branch/ahead-behind/dirty summary
prod-handoff Template + checklist for the docs/*-handoff.md runbooks that live on the prod Proxmox VM
deploy-to-proxmox Documents the web-triggered deploy workflow, its tag/latest input, and post-deploy /actuator/health checks
local-fitznet Spin up / tear down the full local stack via docker-compose.yml, with the URLs to check
arch-visualize How the website's 3D architecture graph is built and updated — data model, node/link conventions, live preview
vulnScan Language-agnostic CVE scan (Gradle, npm, PlatformIO): upgrades vulnerable packages, verifies build + tests, leaves changes uncommitted. --report-only to just scan

(back to top)

License

Distributed under the MIT License. See LICENSE for more information.

(back to top)

Contact

Matt - @mattylol85 - mattlol85@gmail.com

Project Link: https://github.com/mattlol85/Fitz-Net

(back to top)

About

A collection of software that runs the Fitz-Net

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages