On-prem storage for Controlled Unclassified Information (CUI) at CMMC Level 2 / NIST SP 800-171 Rev 2. A hardened fork of filebrowser/filebrowser (Apache-2.0) that runs as a single Go binary on RHEL 9 or AlmaLinux 9 with FIPS mode enabled.
Authentication is externalized to OIDC (Keycloak, Entra GCC High, Okta Gov, Ping). Files are encrypted at rest (AES-256-GCM envelope), scanned on upload (ClamAV fail-closed), and every action emits a tamper-evident audit event.
Why now: CMMC Program Final Rule is in effect (32 CFR 170); Phase 2 begins 2026-11-10 and requires a C3PAO assessment for Level 2 contracts. FIPS posture inherits OpenSSL CMVP #4774 via RHEL / Alma
go-toolsetβ appliances ship audit-ready.
- Architecture
- NIST control mapping
- SSP base
- Installation
- Operator guides
- Wazuh β additional CMMC coverage
- Supported IdPs
- Project status
- License
- Appendix A: Gap analysis (pre-fork baseline)
Full architecture: docs/architecture.md β topology, components, data + audit flows, firewall rules, key management, TLS profile.
Turnkey shape: one VM, one command, the whole CUI enclave β cmmc-filebrowser plus a bundled Keycloak-FIPS OIDC IdP. Monitoring (Wazuh) and external auth / SIEM integrations are optional add-ons layered on top.
ββββ CUI enclave Β· single VM Β· RHEL 9 / Alma 9 FIPS ββββββββββββββββββββ
β β
β cmmc-filebrowser βββ OIDC + MFA βββΊ cmmc-keycloak β
β Go Β· TLS 1.3 FIPS (bundled OIDC IdP) β
β β β
β β JSON audit β
β βΌ β
β journald βββΊ rsyslog (mTLS) β
β β
β Files: AES-256-GCM envelope per object Β· KEK in TPM / HSM β
β BoltDB: envelope-encrypted rows Β· HMAC audit chain β
β β
β β (optional) Wazuh agent + manager + indexer + dashboard β β
β β enable with: install.sh deploy --with-wazuh β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Auth (optional federation) ββΊ Entra GCC-H Β· Okta Gov Β· Ping
SIEM (optional forward) ββΊ Splunk Β· Sentinel Β· Elastic
Deploy shapes:
- Turnkey all-in-one (default) β bundled Keycloak + Wazuh,
install.sh deploy --with-wazuhon a fresh RHEL/Alma 9 VM - Federated IdP + bundled SIEM β customer's Entra GCC-H / Okta Gov / Ping for auth, bundled Wazuh for monitoring
- Bundled IdP + federated SIEM β bundled Keycloak, forward audit to customer Splunk / Sentinel / Elastic
- Fully federated β customer's IdP + SIEM; appliance runs only the filebrowser core
- Behind Trout Access Gate β Gate fronts TLS + x509/PIV + egress allow-list, stacks on any of the above
Why do all control IDs start with
3.? NIST SP 800-171 Rev 2 is organized as Section 1 (purpose), Section 2 (scope), and Section 3: The Requirements. All 110 controls live in Section 3, so they're numbered3.X.YwhereXis the family (1β14) andYis the control within that family. The leading3.isn't meaningful β it's just the chapter number in the document.
Full per-control coverage: docs/compliance-posture.md (positive posture, installed) or docs/gap-analysis.md (pre-fork baseline). Family-level summary below.
CUI marking UI (NIST 3.8.4) β admin + fresh MFA required; every change emits an audit event.
Legend: β Open-CMMC directly Β· π’ Wazuh extends Β· π Customer SSP Β· π’ Host / facility
| Family | Coverage | Scope | Where Open-CMMC addresses it |
|---|---|---|---|
| 3.1 Access Control (22) | β 18 Β· π’ 3 Β· π 1 | OIDC + per-folder ACL + session mgmt | cmmc/auth/oidc/, cmmc/authz/folderacl/, http/cmmc_session_idle.go |
| 3.2 Awareness & Training (3) | π 3 | Policy / procedure | Customer SSP β not product-scope |
| 3.3 Audit & Accountability (9) | β 6 Β· π’ 3 | Structured events, HMAC chain, correlation IDs | cmmc/audit/, config/rsyslog/, config/wazuh/ |
| 3.4 Configuration Mgmt (9) | β 6 Β· π’ 3 | Config-change audit, CM baselines | http/cmmc_enforcement.go, SSP procedures |
| 3.5 Identification & Auth (11) | β 11 | MFA, replay-resistant, FIPS crypto, passkeys | cmmc/auth/oidc/, cmmc/auth/session/, WebAuthn policy |
| 3.6 Incident Response (3) | β 1 Β· π’ 2 | Audit forwarder + SIEM decoders | config/wazuh/rules/, audit-forwarder.md |
| 3.7 Maintenance (6) | β 2 Β· π’ 4 | Privileged-access audit, NOREMAUTH | SSP + Access Gate step-up |
| 3.8 Media Protection (9) | β 9 | CUI marking, envelope encryption, move/copy rules | cmmc/marking/, cmmc/crypto/envelope/, http/cmmc_enforcement.go |
| 3.9 Personnel Security (2) | π 2 | Policy | Customer SSP |
| 3.10 Physical Protection (6) | π’ 6 | Policy / host-layer | Customer facility + host SSP |
| 3.11 Risk Assessment (3) | π’ 3 | SBOM, vulnerability mgmt | CI workflow, govulncheck + trivy in release pipeline |
| 3.12 Security Assessment (4) | β 2 Β· π 2 | SSP, POA&M | This repo + customer SSP |
| 3.13 System & Comms Protection (16) | β 14 Β· π’ 2 | FIPS TLS, egress deny, FIPS crypto | cmmc/crypto/tlsprofile/, cmmc/crypto/fips/, firewalld |
| 3.14 System & Info Integrity (7) | β 3 Β· π’ 4 | Scan-on-upload, malware-sig currency | cmmc/scan/clamav/, update-ca-trust |
| Total | β 72 Β· π’ 18 Β· π 8 Β· π’ 12 (= 110) |
Open-CMMC is the product + evidence base for a System Security Plan. It doesn't replace the customer's SSP, but it supplies every artifact an assessor needs:
| Artifact | Path |
|---|---|
| Compliance posture (per-control coverage, installed) | docs/compliance-posture.md |
| Gap analysis (pre-fork baseline, per-control statements) | docs/gap-analysis.md |
| Architecture (data-flow diagrams, boundaries, inheritance) | docs/architecture.md |
| IdP setup (Entra GCC-H / Keycloak / Okta Gov) | docs/oidc-providers.md |
| Audit pipeline (rsyslog-ossl mTLS) | docs/audit-forwarder.md |
| Wazuh integration | docs/wazuh-integration.md |
| Operator 2FA + passkey walkthrough | docs/operator-2fa.md |
| Deployment (RHEL/Alma 9, FIPS) | docs/almalinux9-setup.md |
| Keycloak realm (policy + PKCE + amr) | docs/keycloak-setup.md |
Typical SSP workflow: the customer's compliance team copies per-control statements from gap-analysis.md, documents ODPs (organizationally-defined parameters), adds site-specific evidence (retention, ticketing), and produces the SSP + POA&M for C3PAO review.
No build toolchain needed on the target. Pick the arch that matches uname -m:
# On the target RHEL 9 / AlmaLinux 9 / Rocky 9 host β enable FIPS first
sudo fips-mode-setup --enable && sudo reboot
# After reboot
sudo dnf install -y podman jq curl iproute firewalld openssl policycoreutils-python-utils
sudo systemctl enable --now firewalld
# Download the release (pick amd64 or arm64 to match uname -m)
ARCH=amd64 # or arm64
VER=v1.0.0
TAR=cmmc-filebrowser-$VER-linux-$ARCH.tar.gz
curl -LO https://github.com/TroutSoftware/Open-CMMC/releases/download/$VER/$TAR
curl -LO https://github.com/TroutSoftware/Open-CMMC/releases/download/$VER/$TAR.sha256
sha256sum --check $TAR.sha256
# Extract + deploy
tar -xzf $TAR
sudo cmmc-filebrowser-$VER-linux-$ARCH/config/install.sh deploy --from-release "$(realpath $TAR)"In ~3 minutes: TLS-enabled filebrowser on https://<host>:8443, Keycloak OIDC on https://<host>:8081, systemd units, firewalld rules, self-signed CA + leaf cert (replaceable with customer PKI for prod), audit stream to journald, and envelope encryption (AES-256-GCM per-file) on by default with an auto-generated KEK at /etc/cmmc-filebrowser/kek.bin.
Air-gap: same commands, just download the tarball on an internet-connected host and scp it to the target before the tar -xzf step. install.sh --from-release skips the build phases entirely β no Go, Node, or pnpm needed on the target.
For development or when you want to patch before installing:
git clone https://github.com/TroutSoftware/Open-CMMC.git open-cmmc
cd open-cmmc
sudo config/install.sh deployNeeds Go 1.25, Node β₯18.12, and pnpm on the host. Same end state as Option 1.
sudo config/install.sh deploy --with-wazuh # baseline + bundled Wazuh SIEM
sudo config/install.sh status # health check
sudo config/install.sh uninstall # stop + disable (state preserved)
sudo config/install.sh uninstall --wipe-state # full clean slateFull deployment guide: docs/almalinux9-setup.md.
- 2FA + passkey enrollment β TOTP (default) and FIDO2 security keys (passwordless peer). Includes DNS prerequisites for passkey flows.
- Wazuh SIEM integration β agent install, decoder + rule drop-in, bundled-mode podman-compose.
- Wazuh endpoint agents β Windows / Linux / macOS agents for CMMC 3.14 coverage.
- Audit forwarder β rsyslog-ossl mTLS for Splunk / Sentinel / Elastic.
Per-user activity view (NIST 3.3.1 / 3.3.2) β every CUI mark change, preview, and admin action is stamped with a correlation id and emitted to the audit stream.
Wazuh is the default recommended SIEM + endpoint-monitoring stack for Open-CMMC (architecture decision D5). Running without Wazuh is valid β audit still lands in journald locally β but Wazuh extends coverage into families the filebrowser process alone can't satisfy.
Open-CMMC alone covers ~55 of 110 controls directly in product code (3.1, most of 3.3, 3.5, 3.8, 3.13).
Wazuh adds ~20 more, taking the deployed stack to ~75 of 110:
| Family | Controls | How Wazuh covers it |
|---|---|---|
| 3.3 Audit | 3.3.4, 3.3.7, 3.3.8 | Central log retention + tamper protection; audit-failure alerting |
| 3.4 CM | 3.4.1, 3.4.3, 3.4.7 | FIM on binary, /etc/cmmc-filebrowser/, systemd units |
| 3.6 Incident Response | 3.6.1, 3.6.2, 3.6.3 | Correlation rules turn audit events into SOC-actionable incidents |
| 3.11 Risk Assessment | 3.11.2, 3.11.3 | Daily vulnerability scan of host packages |
| 3.14 System & Info Integrity | 3.14.1β3.14.7 | Host antimalware, signature auto-update, rootcheck, anomaly detection |
| 3.1 AC (cross-system) | 3.1.1, 3.1.12, 3.1.20 | Endpoint agents on operator workstations catch lateral access |
The remaining ~35 controls are personnel / physical / policy β customer SSP domain by design.
Deployment shapes:
- Agent-only β customer's own Wazuh manager; appliance runs agent + our filebrowser decoder/rules (
docs/wazuh-integration.md) - Bundled β
sudo config/install.sh deploy --with-wazuhbrings up manager + indexer + dashboard
Other SIEMs β Splunk / Sentinel / Elastic connect via rsyslog-ossl (docs/audit-forwarder.md); the 3.4 / 3.14 coverage reverts to a customer-tool integration in those deployments.
| IdP | Use case | Docs |
|---|---|---|
| Keycloak (bundled) | Air-gap, sovereignty, single-appliance | keycloak-setup.md |
| Entra ID (Microsoft GCC High) | Customers on M365 GCC-H | oidc-providers.md |
| Okta Gov / Okta Fed | Okta-centric shops | oidc-providers.md |
| Ping Identity | PingFederate deployments | oidc-providers.md |
Prototype targeting C3PAO assessment readiness 2026 Q3. Phase 2 hard deadline: 2026-11-10. Work plan + decision log (D1βD13) in docs/architecture.md Β§11.
Trout Software is the primary maintainer. Community contributions welcome via PR. For commercial support / customer deployments, contact hello@trout.software.
Apache-2.0 β same as upstream filebrowser.
Open-CMMC started from filebrowser/filebrowser v2.63.2 (commit dd53644, 2026-04-17). CMMC-specific hardening lives under:
cmmc/β new Go packages (auth/oidc, auth/session, authz, audit, marking, crypto, scan, cabinet)config/β installer + systemd units + Keycloak bootstrap + rsyslog + Wazuh integration assetsdocs/β architecture, gap analysis, operator + deployment guidesscripts/build-release.shβ air-gap-friendly release packager
Upstream filebrowser functionality is preserved where it doesn't conflict with CMMC requirements; removed / hardened where it did (e.g., the default no-auth mode refuses to boot; public shares are rejected for CUI-marked items). Bug reports for upstream-derived code belong upstream first; Open-CMMC-specific bugs + features in this repo's issues.
This appendix describes filebrowser v2.63.2 as it existed at commit dd53644 (2026-04-17) β BEFORE Open-CMMC forked it. The gaps below are what motivated the fork: vanilla filebrowser is a capable file-sharing server but it ships without the controls a CMMC L2 assessment needs. Open-CMMC addresses every blocker in the table; this baseline is preserved as the evidence trail an assessor walks when asking "why is this product different from the one on GitHub's homepage?"
The full per-control baseline with file:line citations is at docs/gap-analysis.md β 110 controls across 14 families with severity (Blocker / Major / Minor / N/A-Infra / N/A-Policy / Inherited-AG) and remediation theme (replace-auth, add-module, config, host-control, siem, doc-only, inherit-idp, inherit-ag).
Top 10 ship-blockers the baseline carried, and how Open-CMMC addresses each:
| # | Baseline blocker (filebrowser v2.63.2) | Controls | Open-CMMC status |
|---|---|---|---|
| 1 | No FIPS-validated cryptography | 3.13.11, 3.13.8, 3.5.10, 3.13.16 | β Built with GOFIPS140=v1.0.0 on RHEL go-toolset (CMVP #4774) |
| 2 | No MFA / OIDC / SAML (only JSON + hook auth) | 3.5.3, 3.5.4, 3.5.1 | β OIDC backend (Keycloak/Entra/Okta) + step-up MFA + passkey peer |
| 3 | No lockout / session revocation / idle lock | 3.1.8, 3.5.4, 3.1.10, 3.1.11 | β Failed-attempt lockout, session-idle lock, JTI tracking |
| 4 | No encryption at rest | 3.13.16, 3.8.9, 3.8.1 | β Per-file envelope (AES-256-GCM, HKDF subkey), LUKS host layer |
| 5 | Audit trail insufficient (stdlib log + rotation only) |
3.3.1β3.3.9 | β Structured JSON events, HMAC chain, rsyslog-ossl / Wazuh |
| 6 | TLS not FIPS-profiled (Go default cipher list) | 3.13.8, 3.13.11, 3.13.15 | β Explicit FIPS cipher list, TLS 1.3 preferred, security headers |
| 7 | No malware scan on upload | 3.14.2, 3.14.5, 3.14.6 | β ClamAV integration fail-closed, internal signature mirror |
| 8 | No CUI marking model (plain file paths) | 3.8.4, 3.1.3, 3.1.22 | β Per-folder + per-file CUI marks, UI banners, declassify audit |
| 9 | Public shares bypass auth for any file | 3.1.3, 3.1.22, 3.13.5 | β Public share refused for CUI-marked items (out-of-scope for MVP) |
| 10 | No SBOM / reproducible builds | 3.14.1, 3.11.2, 3.14.3 | β -trimpath + -ldflags in release builds; SBOM via CI (WIP) |


