Skip to content

Repository files navigation

Nimbus S3 Portal

A self-hosted customer portal that lets MinIO IAM users securely browse their buckets, view storage usage, and manage their own service accounts (access keys) — without exposing the native MinIO console.

Built with SvelteKit 2 + Svelte 5, deployed as a standalone Node.js server via @sveltejs/adapter-node.


Features

  • Secure login — MinIO IAM credentials (access key + secret key) verified directly against the MinIO S3 API; nothing stored except an encrypted session token
  • Dashboard — bucket cards showing used storage, quota bar, object count, last upload date, and tags
  • Bucket explorer — breadcrumb navigation, object listing, one-click presigned downloads
  • Service accounts — create and delete your own child access keys; secret shown once on creation, never again
  • Portal admin — local admin account (no MinIO IAM required) with a full cluster management UI
  • Multi-cluster — configure any number of MinIO clusters; users are automatically routed to the correct one after a user sync
  • Dark / light theme — system preference detected, toggle in navbar
  • Security hardened — AES-256-GCM credentials at rest, rate-limited login, CSP / security headers, HttpOnly SameSite cookies, per-cluster TLS control

Quick Start

Prerequisites

  • Node.js 20+
  • mc (MinIO Client) installed and on PATH (or set MC_PATH)
  • A MinIO cluster with at least one IAM user

1. Clone and install

git clone https://github.com/nimbustech-lab/s3-portal.git
cd s3-portal
npm install

2. Configure

cp .env.example .env

Edit .env — the minimum required fields:

# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
SESSION_ENCRYPTION_KEY=<64 hex chars>

PORTAL_ADMIN_USER=admin
PORTAL_ADMIN_PASSWORD=<strong password>

S3 cluster credentials can be added via the Admin UI after first login, or pre-seeded in .env:

CLUSTER_1_ID=silo
CLUSTER_1_LABEL=SILO Cluster
CLUSTER_1_ENDPOINT=s3.example.com:9000
CLUSTER_1_SECURE=true
CLUSTER_1_ADMIN_ACCESS=<admin access key>
CLUSTER_1_ADMIN_SECRET=<admin secret key>

3. Build and run

npm run build
node build/index.js

The server listens on http://0.0.0.0:8900 by default (override with PORT and HOST env vars).


First Login

  1. Open the portal URL and log in with PORTAL_ADMIN_USER / PORTAL_ADMIN_PASSWORD
  2. Go to AdminAdd Cluster and enter your MinIO cluster details
  3. Click Sync Users to pull IAM accounts from MinIO into the portal DB
  4. MinIO users can now log in — the portal auto-routes them to the correct cluster

Architecture

src/
├── lib/server/
│   ├── clusterStore.ts   # cluster CRUD (DB + .env merged), user sync, login resolution
│   ├── config.ts         # .env cluster parsing (CLUSTER_N_* variables)
│   ├── crypto.ts         # AES-256-GCM encrypt/decrypt for credentials at rest
│   ├── db.ts             # SQLite via better-sqlite3 (WAL mode)
│   ├── mc.ts             # mc CLI wrapper — admin ops, user/SA listing
│   ├── portalAdmin.ts    # portal admin local auth (separate from MinIO IAM)
│   ├── ratelimit.ts      # in-memory IP rate limiter (10 req / 15 min)
│   ├── s3.ts             # MinIO SDK — bucket list, object list, presigned URLs
│   └── session.ts        # session create/get/delete with encrypted credential storage
└── routes/
    ├── login/            # S3 credential login + portal admin login
    ├── logout/           # cookie clear
    ├── (protected)/
    │   ├── +layout.server.ts   # session guard — redirects to /login if unauthenticated
    │   ├── admin/              # cluster CRUD + user sync (portal admin only)
    │   ├── dashboard/          # bucket overview cards
    │   ├── explorer/[bucket]/  # object browser
    │   └── service-accounts/   # access key management
    └── api/download/[bucket]/  # presigned URL redirect

Database tables (SQLite)

Table Purpose
sessions Active sessions — encrypted access key + secret key
db_clusters Clusters created via Admin UI — encrypted admin credentials
cluster_users IAM users synced from each cluster
service_accounts_sync Service account access keys per user (secret keys never stored)

Environment Variables

Variable Required Default Description
SESSION_ENCRYPTION_KEY Yes 64 hex chars (32 bytes) for AES-256-GCM
PORTAL_ADMIN_USER Yes Portal admin username
PORTAL_ADMIN_PASSWORD Yes Portal admin password
CLUSTER_N_ID No Cluster identifier (slug)
CLUSTER_N_LABEL No Display name
CLUSTER_N_ENDPOINT No host:port
CLUSTER_N_SECURE No true Use HTTPS
CLUSTER_N_INSECURE No false Allow self-signed TLS cert
CLUSTER_N_ADMIN_ACCESS No Admin access key
CLUSTER_N_ADMIN_SECRET No Admin secret key
CLUSTER_MAX No 10 Max number of CLUSTER_N_* entries to scan
DB_PATH No ./data/portal.db SQLite database path
MC_PATH No /usr/local/bin/mc Path to mc binary
PORT No 8900 HTTP listen port
HOST No 0.0.0.0 HTTP listen address

Deployment (systemd)

# /etc/systemd/system/s3portal.service
[Unit]
Description=Nimbus S3 Customer Portal
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/s3portal
EnvironmentFile=/opt/s3portal/.env
ExecStart=/usr/bin/node build/index.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now s3portal

Expose via nginx or HAProxy with SSL termination on port 443.


Security Notes

  • Admin credentials live only in server-side env vars and encrypted DB; never sent to the browser
  • Session data island contains only { id, username, cluster_id } — no access key or secret key
  • Service account secrets are returned once at creation and never stored in the portal
  • Per-cluster TLSCLUSTER_N_INSECURE=true applies a custom https.Agent only to that cluster; the global NODE_TLS_REJECT_UNAUTHORIZED is never modified
  • Rate limiting — 10 failed login attempts per IP per 15-minute window
  • CSPContent-Security-Policy, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin applied via SvelteKit handle hook

Development

cp .env.example .env   # fill in SESSION_ENCRYPTION_KEY and admin creds
npm run dev            # starts on http://localhost:8900 with HMR

License

MIT

About

Nimbus S3 Portal

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages