Add project scaffolding and documentation
Add .env.example with configuration for database, Redis, security, SMTP, workers, and plugins. Add .gitignore for Python, Node.js, Next.js, Docker volumes, and IDE files. Add MIT License. Update README.md with feature overview, quick start guide, architecture description, plugin system documentation, security details, backup/restore instructions, and developer setup. Add Alembic configuration files and placeholder directories for API, web, worker, and plugin components
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# NexaDash Admin Guide
|
||||
|
||||
## Initial Setup
|
||||
|
||||
After starting the Docker Compose stack, open the web UI and create the owner account. The setup wizard is only available while no user exists.
|
||||
|
||||
## User Management
|
||||
|
||||
- Roles: Owner, Admin, Editor, Viewer.
|
||||
- Invite users via email or create them directly.
|
||||
- Users can change their own password and profile settings.
|
||||
|
||||
## Plugin Management
|
||||
|
||||
1. Install built-in plugins automatically from the plugin registry.
|
||||
2. Upload custom plugins as ZIP files.
|
||||
3. Activate/deactivate plugins per environment.
|
||||
4. Configure service connections for each plugin.
|
||||
|
||||
## Service Connections
|
||||
|
||||
Each plugin instance needs a service connection with:
|
||||
|
||||
- Base URL
|
||||
- TLS verification option
|
||||
- Encrypted credentials
|
||||
- Timeout
|
||||
|
||||
Always test the connection before saving.
|
||||
|
||||
## Dashboards
|
||||
|
||||
- Create dashboards per user or team.
|
||||
- Use the editor to drag, drop and resize widgets.
|
||||
- Save layouts per breakpoint.
|
||||
- Set auto-refresh intervals.
|
||||
|
||||
## Monitoring
|
||||
|
||||
- View audit logs for security-relevant actions.
|
||||
- Check plugin health and logs.
|
||||
- Monitor background job status.
|
||||
|
||||
## Mail Settings
|
||||
|
||||
Configure SMTP in the UI to send invitation and password reset emails.
|
||||
|
||||
## Backup
|
||||
|
||||
Use the database dump command documented in `docs/deployment/README.md` or automate it with a cron job.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Check API logs: `docker compose logs api`
|
||||
- Check worker logs: `docker compose logs worker`
|
||||
- Check plugin logs in the UI or database.
|
||||
@@ -0,0 +1,76 @@
|
||||
# NexaDash Deployment Guide
|
||||
|
||||
## Quick Start with Docker Compose
|
||||
|
||||
1. Copy the example environment:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
2. Edit `.env` and set strong passwords and secrets.
|
||||
|
||||
3. Start the stack:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
4. Open `http://localhost:3000` and complete the setup wizard.
|
||||
|
||||
## Services
|
||||
|
||||
- `web` — Next.js frontend (port 3000).
|
||||
- `api` — FastAPI backend (port 8000).
|
||||
- `worker` — Celery background worker.
|
||||
- `postgres` — PostgreSQL database.
|
||||
- `redis` — Redis for cache, jobs and sessions.
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
Set `NEXADASH_WEB_URL` and `NEXADASH_API_URL` to your public URLs. Use a reverse proxy with HTTPS. The API expects the web origin in its CORS allowlist.
|
||||
|
||||
## Healthchecks
|
||||
|
||||
- API: `GET /health`
|
||||
- Web: built-in Docker healthcheck
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Database Backup
|
||||
|
||||
```bash
|
||||
docker compose exec postgres pg_dump -U nexadash nexadash > backup.sql
|
||||
```
|
||||
|
||||
### Restore
|
||||
|
||||
```bash
|
||||
docker compose exec -T postgres psql -U nexadash nexadash < backup.sql
|
||||
```
|
||||
|
||||
### Volumes
|
||||
|
||||
Important Docker volumes:
|
||||
|
||||
- `postgres_data` — database files.
|
||||
- `redis_data` — Redis persistence.
|
||||
- `plugin_data` — uploaded plugin files.
|
||||
|
||||
## Updates
|
||||
|
||||
```bash
|
||||
git pull
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Run migrations after updates:
|
||||
|
||||
```bash
|
||||
docker compose exec api alembic upgrade head
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
See `README.md` for developer setup.
|
||||
@@ -0,0 +1,177 @@
|
||||
# NexaDash Plugin Developer Documentation
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [What is a NexaDash Plugin?](#what-is-a-nexadash-plugin)
|
||||
2. [Plugin Structure](#plugin-structure)
|
||||
3. [Manifest](#manifest)
|
||||
4. [Settings & Credentials Schema](#settings--credentials-schema)
|
||||
5. [Widget Schema](#widget-schema)
|
||||
6. [Backend Connector](#backend-connector)
|
||||
7. [Frontend Widget](#frontend-widget)
|
||||
8. [Permissions](#permissions)
|
||||
9. [Secrets Handling](#secrets-handling)
|
||||
10. [Background Jobs](#background-jobs)
|
||||
11. [Error Handling](#error-handling)
|
||||
12. [Versioning](#versioning)
|
||||
13. [Testing](#testing)
|
||||
14. [Security Rules](#security-rules)
|
||||
15. [Example: Creating a Plugin](#example-creating-a-plugin)
|
||||
16. [Packaging](#packaging)
|
||||
17. [Upload](#upload)
|
||||
18. [Best Practices](#best-practices)
|
||||
|
||||
## What is a NexaDash Plugin?
|
||||
|
||||
A NexaDash plugin is a declarative package that connects an external service to the dashboard. It defines:
|
||||
|
||||
- A `plugin.manifest.json` describing metadata, schemas and widgets.
|
||||
- A backend connector (declarative or built-in Python class) that fetches data from the service.
|
||||
- Optional frontend widget components that render the data.
|
||||
|
||||
Plugins never execute arbitrary code in the main API process. Connectors are loaded from a known registry and run in a sandboxed layer.
|
||||
|
||||
## Plugin Structure
|
||||
|
||||
```text
|
||||
my-plugin/
|
||||
plugin.manifest.json
|
||||
README.md
|
||||
widgets/
|
||||
MyWidget.tsx
|
||||
connector/
|
||||
connector.py (optional, for custom Python connectors)
|
||||
```
|
||||
|
||||
## Manifest
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "my-plugin",
|
||||
"name": "My Plugin",
|
||||
"version": "1.0.0",
|
||||
"nexadashPluginApi": "1.0",
|
||||
"description": "Short description",
|
||||
"author": "Your Name",
|
||||
"category": "Infrastructure",
|
||||
"permissions": ["network:outbound", "secrets:read"],
|
||||
"settingsSchema": {},
|
||||
"credentialsSchema": {},
|
||||
"widgets": [],
|
||||
"apiRoutes": [],
|
||||
"hasFrontend": true,
|
||||
"healthcheck": {
|
||||
"method": "GET",
|
||||
"intervalSeconds": 60,
|
||||
"timeoutSeconds": 30
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Settings & Credentials Schema
|
||||
|
||||
Schemas follow JSON Schema with a few conventions:
|
||||
|
||||
- `format: "password"` hides the value in the UI.
|
||||
- `enum` renders as a select dropdown.
|
||||
- Credentials are stored encrypted and never returned to the frontend.
|
||||
|
||||
## Widget Schema
|
||||
|
||||
Each widget needs:
|
||||
|
||||
- `id`: unique widget type identifier.
|
||||
- `name`: human-readable label.
|
||||
- `description`: short help text.
|
||||
- `defaultWidth`, `defaultHeight`: default grid size.
|
||||
- `settingsSchema`: per-widget settings.
|
||||
|
||||
## Backend Connector
|
||||
|
||||
Built-in connectors cover many services. For custom services, you can provide a Python class that extends `PluginConnector`:
|
||||
|
||||
```python
|
||||
from apps.api.src.plugins.base import PluginConnector
|
||||
|
||||
class MyConnector(PluginConnector):
|
||||
id = "my-plugin"
|
||||
name = "My Plugin"
|
||||
|
||||
async def healthcheck(self):
|
||||
return {"status": "ok"}
|
||||
|
||||
async def fetch_widget_data(self, widget_type, settings):
|
||||
return {"value": 42}
|
||||
```
|
||||
|
||||
Register it in `apps/api/src/plugins/registry.py`.
|
||||
|
||||
## Frontend Widget
|
||||
|
||||
Frontend widgets are React components that receive `data` and `settings` props. They are rendered by the dashboard editor.
|
||||
|
||||
## Permissions
|
||||
|
||||
Common permissions:
|
||||
|
||||
- `network:outbound` — plugin may make HTTP requests.
|
||||
- `secrets:read` — plugin may decrypt its own credentials.
|
||||
- `jobs:schedule` — plugin may schedule background jobs.
|
||||
|
||||
## Secrets Handling
|
||||
|
||||
Never log or return secrets. The backend decrypts credentials only when executing a connector and passes them to the connector instance.
|
||||
|
||||
## Background Jobs
|
||||
|
||||
Use the Celery worker for long-running sync tasks. Schedule via the `background_jobs` API or from a connector.
|
||||
|
||||
## Error Handling
|
||||
|
||||
Return `{status: "error", message: "..."}` on failures. The dashboard shows a user-friendly error card.
|
||||
|
||||
## Versioning
|
||||
|
||||
Use semantic versioning. The plugin registry tracks versions in `plugin_versions`.
|
||||
|
||||
## Testing
|
||||
|
||||
- Validate the manifest with `@nexadash/plugin-sdk`.
|
||||
- Test connectors with mocked HTTP clients.
|
||||
- Add API tests for custom endpoints.
|
||||
|
||||
## Security Rules
|
||||
|
||||
- Only `http`/`https` URLs are allowed (SSRF protection).
|
||||
- No credentials in frontend code.
|
||||
- No dynamic code execution (`eval`, `exec`).
|
||||
- Use least-privilege API tokens.
|
||||
- Validate all inputs with schemas.
|
||||
|
||||
## Example: Creating a Plugin
|
||||
|
||||
See `plugins/example-plugin/` for a complete working example.
|
||||
|
||||
## Packaging
|
||||
|
||||
Zip the plugin directory with the manifest at the root:
|
||||
|
||||
```bash
|
||||
zip -r my-plugin.zip my-plugin/
|
||||
```
|
||||
|
||||
## Upload
|
||||
|
||||
Upload the ZIP in the UI under **Plugins → Upload Plugin** or via the API:
|
||||
|
||||
```bash
|
||||
curl -F "file=@my-plugin.zip" https://nexadash.local/api/v1/plugins/upload
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
- Keep widgets focused on one metric.
|
||||
- Use pagination for large lists.
|
||||
- Cache expensive requests in the connector.
|
||||
- Provide clear error messages.
|
||||
- Document required credentials.
|
||||
@@ -0,0 +1,81 @@
|
||||
# NexaDash Security Documentation
|
||||
|
||||
This document describes the security architecture and configuration recommendations for NexaDash.
|
||||
|
||||
## Authentication
|
||||
|
||||
- Passwords are hashed with **Argon2id**.
|
||||
- Sessions use short-lived JWT access tokens (15 minutes) and long-lived refresh tokens (7 days) stored in HTTP-only cookies.
|
||||
- Failed logins are rate-limited and accounts are locked after repeated failures.
|
||||
|
||||
## Authorization
|
||||
|
||||
- Role-based access control (RBAC) with system roles: Owner, Admin, Editor, Viewer.
|
||||
- Permissions are enforced on every API endpoint.
|
||||
- Owners bypass permission checks but their actions are still audit-logged.
|
||||
|
||||
## Secrets
|
||||
|
||||
- All service credentials are encrypted with Fernet (AES-128-CBC + HMAC) before storage.
|
||||
- Secrets are only decrypted by the backend connector layer.
|
||||
- The encryption key must be set via `NEXADASH_ENCRYPTION_KEY` and never exposed to the frontend.
|
||||
|
||||
## Input Validation
|
||||
|
||||
- All API inputs are validated with Pydantic schemas.
|
||||
- SQLAlchemy ORM prevents SQL injection.
|
||||
- Service URLs are validated against SSRF blocklists.
|
||||
|
||||
## Network Security
|
||||
|
||||
- Only `http` and `https` schemes are allowed for service URLs.
|
||||
- Private IP ranges (10.0.0.0/8, 127.0.0.0/8, 192.168.0.0/16, 169.254.169.254) are blocked.
|
||||
- Redirect following is disabled for outbound requests.
|
||||
|
||||
## Plugin Sandboxing
|
||||
|
||||
- Plugins are declarative JSON manifests.
|
||||
- Custom connectors are loaded from a known registry; arbitrary Python code is not executed.
|
||||
- Uploaded plugins are validated before installation.
|
||||
- The plugin process runs with the same container restrictions but no direct filesystem access beyond the plugin directory.
|
||||
|
||||
## Security Headers
|
||||
|
||||
The API sets:
|
||||
|
||||
- `X-Content-Type-Options: nosniff`
|
||||
- `X-Frame-Options: DENY`
|
||||
- `Referrer-Policy: strict-origin-when-cross-origin`
|
||||
- `Permissions-Policy`
|
||||
- `Content-Security-Policy`
|
||||
|
||||
## Audit Logging
|
||||
|
||||
All critical actions are recorded in `audit_logs`:
|
||||
|
||||
- login/logout
|
||||
- user create/update/delete
|
||||
- role changes
|
||||
- plugin install/activate/delete
|
||||
- dashboard modifications
|
||||
- connection changes
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- Default: 100 requests per minute.
|
||||
- Login: 10 requests per minute.
|
||||
- Configurable via environment variables.
|
||||
|
||||
## Recommendations
|
||||
|
||||
1. Change all default secrets in `.env` before deployment.
|
||||
2. Use HTTPS in production.
|
||||
3. Keep the app and dependencies updated.
|
||||
4. Run container scans with Trivy or Docker Scout.
|
||||
5. Restrict database and Redis access with Docker networks.
|
||||
6. Enable database backups and test restores.
|
||||
7. Use strong, unique API tokens for each service.
|
||||
|
||||
## Vulnerability Reporting
|
||||
|
||||
Report security issues privately to the maintainers.
|
||||
Reference in New Issue
Block a user