diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 7c231785..a8bdca88 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -74,6 +74,13 @@ - Use clear cross-references between related documentation files - Update the main architecture document when workflow structure changes +### Database Schema Documentation +- **Keep it current**: When adding or modifying Sequelize models, update `mie-opensource-landing/docs/developers/database-schema.md` +- **Update the ER diagram**: Add new entities and relationships to the Mermaid diagram +- **Document all fields**: Include field names, types, constraints, and purpose +- **Document relationships**: Specify all foreign keys and associations (hasMany, belongsTo, etc.) +- **Explain patterns**: If using special patterns (STI, polymorphism, etc.), document the reasoning + ## Working with GitHub Actions Workflows ### Development Philosophy diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml new file mode 100644 index 00000000..9db13405 --- /dev/null +++ b/.github/workflows/docker-build-push.yml @@ -0,0 +1,60 @@ +name: Build and Push Docker Image + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + REGISTRY: ghcr.io + IMAGE_NAME: mieweb/opensource-server + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract branch name + id: branch + run: echo "name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + OPENSOURCE_SERVER_BRANCH=${{ steps.branch.outputs.name }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Makefile b/Makefile index ff6a948e..376c0564 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install install-create-container install-pull-config help +.PHONY: install install-create-container install-pull-config install-docs help help: @echo "opensource-server installation" @@ -7,17 +7,26 @@ help: @echo " make install - Install all components" @echo " make install-create-container - Install create-a-container web application" @echo " make install-pull-config - Install pull-config system" + @echo " make install-docs - Install documentation server" @echo "" -install: install-create-container install-pull-config +install: install-create-container install-pull-config install-docs install-create-container: cd create-a-container && npm install --production cd create-a-container && npm run db:migrate - install -m644 -oroot -groot create-a-container/container-creator.service /etc/systemd/system/container-creator.service + install -m644 -oroot -groot create-a-container/systemd/container-creator.service /etc/systemd/system/container-creator.service systemctl daemon-reload || true systemctl enable container-creator.service systemctl start container-creator.service || true install-pull-config: cd pull-config && bash install.sh + +install-docs: + cd mie-opensource-landing && npm install --production + cd mie-opensource-landing && npm run build + install -m644 -oroot -groot mie-opensource-landing/systemd/opensource-docs.service /etc/systemd/system/opensource-docs.service + systemctl daemon-reload || true + systemctl enable opensource-docs.service + systemctl start opensource-docs.service || true diff --git a/create-a-container/views/nginx-conf.ejs b/create-a-container/views/nginx-conf.ejs index 518ac7c0..b4dbe4fc 100644 --- a/create-a-container/views/nginx-conf.ejs +++ b/create-a-container/views/nginx-conf.ejs @@ -201,6 +201,69 @@ http { # Return 404 for all requests return 404; } + + # Bare domain <%= domain.name %> - proxies to docs site + server { + listen 443 ssl; + listen [::]:443 ssl; + listen 443 quic; + listen [::]:443 quic; + http2 on; + http3 on; + + server_name <%= domain.name %>; + + # SSL certificates from lego + ssl_certificate /opt/opensource-server/create-a-container/certs/certificates/<%= domain.name %>.crt; + ssl_certificate_key /opt/opensource-server/create-a-container/certs/certificates/<%= domain.name %>.key; + + # Modern TLS configuration + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'; + ssl_prefer_server_ciphers off; + + # SSL session optimization + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_session_tickets off; + + # Security headers + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Alt-Svc 'h3=":443"; ma=86400' always; + + # Proxy to documentation site + location / { + proxy_pass http://localhost:2998; + proxy_http_version 1.1; + + # Proxy headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Port $server_port; + + # WebSocket support + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + + # Timeouts + proxy_connect_timeout 60s; + proxy_send_timeout 60s; + proxy_read_timeout 60s; + + # Buffering (disable for SSE/streaming) + proxy_buffering off; + proxy_request_buffering off; + + # Allow large uploads + client_max_body_size 100M; + } + } <%_ }) _%> } diff --git a/mie-opensource-landing/.env.example b/mie-opensource-landing/.env.example new file mode 100644 index 00000000..5121611b --- /dev/null +++ b/mie-opensource-landing/.env.example @@ -0,0 +1,7 @@ +# Proxmox Web GUI URL +# Example: https://your-proxmox-server:8006 +PROXMOX_URL=https://opensource.mieweb.org:8006 + +# Container Creation Web GUI URL +# Example: https://create-container.your-domain.com +CONTAINER_CREATION_URL=https://create-a-container.opensource.mieweb.org diff --git a/mie-opensource-landing/.gitignore b/mie-opensource-landing/.gitignore index b2d6de30..b083ed4f 100644 --- a/mie-opensource-landing/.gitignore +++ b/mie-opensource-landing/.gitignore @@ -10,6 +10,7 @@ # Misc .DS_Store +.env .env.local .env.development.local .env.test.local diff --git a/mie-opensource-landing/README.md b/mie-opensource-landing/README.md index 3bc522eb..d9f6a8cb 100644 --- a/mie-opensource-landing/README.md +++ b/mie-opensource-landing/README.md @@ -1,3 +1,27 @@ # MIE Open Source Landing Page -A modern, responsive landing page showcasing MIE's open source initiatives, built with [Docusaurus](https://docusaurus.io/). Features container management tools, Proxmox Launchpad CI/CD integration, and comprehensive documentation. \ No newline at end of file +A modern, responsive landing page showcasing MIE's open source initiatives, built with [Docusaurus](https://docusaurus.io/). Features container management tools, Proxmox Launchpad CI/CD integration, and comprehensive documentation. + +## Configuration for Self-Hosted Deployments + +This documentation site is designed to work for both MIE's hosted deployment and self-hosted instances. URLs for Proxmox and container creation services are parameterized. + +### Environment Variables + +Copy `.env.example` to `.env` and update the URLs for your deployment: + +```bash +cp .env.example .env +``` + +Then edit `.env` with your instance URLs: + +```env +# Your Proxmox Web GUI URL +PROXMOX_URL=https://your-proxmox-server:8006 + +# Your Container Creation Web GUI URL +CONTAINER_CREATION_URL=https://your-container-creation-url.com +``` + +These URLs will be used throughout the documentation and site interface automatically. \ No newline at end of file diff --git a/mie-opensource-landing/docs/admins/_category_.json b/mie-opensource-landing/docs/admins/_category_.json new file mode 100644 index 00000000..f63d90cb --- /dev/null +++ b/mie-opensource-landing/docs/admins/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Admins", + "position": 3, + "collapsed": false +} diff --git a/mie-opensource-landing/docs/admins/concepts.md b/mie-opensource-landing/docs/admins/concepts.md new file mode 100644 index 00000000..dc8a2eb2 --- /dev/null +++ b/mie-opensource-landing/docs/admins/concepts.md @@ -0,0 +1,51 @@ +--- +sidebar_position: 2 +--- + +# Core Concepts + +Understanding the data model and organizational structure is essential for effectively administering the MIE Opensource Proxmox Cluster. This section covers the key concepts you'll work with daily. + +## Organizational Hierarchy + +The cluster management system is organized hierarchically: + +**Sites** → **Nodes** → **Containers** + +Each level serves a specific purpose in managing your infrastructure. + +## Key Concepts + +### [Users & Groups →](users-and-groups) + +User accounts and group-based permissions for access control and LDAP authentication. + +### [Sites →](sites) + +Top-level organization units that define network configuration and house nodes and containers. + +### [External Domains →](external-domains) + +Domain configuration for exposing HTTP services with automatic SSL/TLS certificate management. + +### [Nodes →](nodes) + +Individual Proxmox VE servers within a site that host containers. + +### [Containers →](containers) + +Linux containers (LXC) running on nodes - see the [User Documentation](/docs/users/creating-containers/web-gui) for creation guides. + +--- + +## Getting Started + +New administrators should configure these elements in order: + +1. **Users & Groups**: Set up your team's accounts and permissions +2. **Sites**: Create your first site with network configuration +3. **External Domains**: Configure domains for service exposure (optional) +4. **Nodes**: Import or add your Proxmox nodes +5. **Containers**: Begin deploying containers for your users + +Each concept page includes detailed explanations and step-by-step guides for using the web interface. diff --git a/mie-opensource-landing/docs/admins/containers.md b/mie-opensource-landing/docs/admins/containers.md new file mode 100644 index 00000000..75372db3 --- /dev/null +++ b/mie-opensource-landing/docs/admins/containers.md @@ -0,0 +1,223 @@ +--- +sidebar_position: 7 +--- + +# Containers + +Containers are Linux containers (LXC) that run on Proxmox nodes within your site. This section provides an administrative overview of container management. + +## Container Overview + +From an administrator's perspective, containers are: +- Lightweight virtualized environments running on Proxmox nodes +- Assigned IP addresses from the site's DHCP range +- Accessible via the built-in LDAP authentication system +- Exposed to the internet via external domains (optional) + +## User Documentation + +Most container operations are performed by end users through the web interface or command line. + +### Creating Containers + +For detailed guides on creating and managing containers, see the User Documentation: + +- **[Web GUI Guide →](/docs/users/creating-containers/web-gui)**: Step-by-step container creation via web interface +- **[Command Line Guide →](/docs/users/creating-containers/command-line)**: Creating containers via API with curl + +## Administrative Tasks + +As an administrator, you'll manage containers at a higher level: + +### Container Lifecycle + +- **Creation**: Users create containers, which are assigned IPs and configured automatically +- **Running**: Containers run on assigned nodes with allocated resources +- **Monitoring**: Track container resource usage and health +- **Deletion**: Users or admins can delete containers to free resources + +### Resource Management + +Containers consume resources from their host node: +- **CPU**: Virtual cores allocated to the container +- **Memory**: RAM assigned from the node's available memory +- **Storage**: Disk space from the node's storage pools +- **Network**: IP addresses from the site's DHCP range + +:::tip Resource Monitoring +Use the Proxmox web interface to monitor node resource usage and identify which containers are consuming the most resources. +::: + +### Network Management + +Each container receives: +- **IP Address**: Automatically assigned from the site's DHCP range +- **DNS Name**: `container-name.INTERNAL_DOMAIN` +- **Gateway**: Site's configured gateway +- **DNS Servers**: Site's configured DNS forwarders + +### LDAP Authentication + +The built-in LDAP server provides authentication to all containers: +- Users in the **ldapusers** group can SSH into any container +- Credentials are synchronized automatically +- Group memberships are reflected in container access + +## Container States + +Containers can be in various states: + +| State | Description | User Access | +|-------|-------------|-------------| +| **Running** | Container is active and accessible | Full access via SSH/web | +| **Stopped** | Container is stopped but not deleted | No access | +| **Creating** | Container is being provisioned | No access yet | +| **Failed** | Creation or startup failed | No access | + +## Troubleshooting Containers + +### Container Won't Start + +Common causes: +- Insufficient resources on the host node +- Corrupted container filesystem +- Network configuration issues +- Storage pool problems + +**Check Proxmox logs:** +```bash +# On the Proxmox node +pct list # List all containers +journalctl -u pve-container@CTID.service # Check container logs +``` + +### User Can't Access Container + +Verify: +- User status is **Active** (not Pending or Suspended) +- User is member of **ldapusers** group +- LDAP service is running on the management container +- Container is running and network is configured correctly + +**Test LDAP authentication:** +```bash +# From the management container +ldapsearch -x -H ldap://localhost -b "dc=cluster,dc=internal" +``` + +### Container Has No Network Connectivity + +Check: +- Container has an IP address: `pct config CTID` +- IP is within the site's DHCP range +- Gateway is reachable from the container +- DNS servers are configured correctly + +**Test from within the container:** +```bash +# SSH into the container +ip addr # Check IP address +ip route # Check gateway +ping GATEWAY_IP # Test gateway connectivity +ping 8.8.8.8 # Test internet connectivity +``` + +### Container Using Too Many Resources + +To limit container resources: + +1. Open the Proxmox web interface +2. Navigate to the container +3. Go to **Resources** tab +4. Adjust limits: + - CPU Cores + - CPU Limit + - Memory + - Swap + +Changes typically require restarting the container. + +## Service Exposure + +Users can expose HTTP services from containers using external domains: + +- Services are automatically configured with SSL/TLS certificates +- Reverse proxy routes traffic from external domains to container services +- DNS records are created automatically in Cloudflare + +See [External Domains](external-domains) for configuration details. + +## Backup and Recovery + +:::note Backup Strategies +Container backup functionality depends on your Proxmox configuration. Refer to Proxmox documentation for setting up automated backups using: +- Proxmox Backup Server +- vzdump (built-in backup tool) +- Storage replication +::: + +### Manual Backup + +To manually backup a container: + +```bash +# On the Proxmox node +vzdump CTID --compress zstd --mode snapshot --dumpdir /path/to/backup +``` + +### Restoring a Container + +```bash +# On the Proxmox node +pct restore CTID /path/to/backup/vzdump-lxc-CTID-*.tar.zst +``` + +## Security Considerations + +### Container Isolation + +- Containers share the host kernel but are isolated from each other +- Use LXC security features (AppArmor, seccomp) for additional isolation +- Privileged containers should be avoided unless absolutely necessary + +### Access Control + +- Review user group memberships regularly +- Audit LDAP access logs for unauthorized attempts +- Suspend users immediately upon termination or security concerns + +### Network Security + +- Containers within a site can communicate with each other +- Use Proxmox firewall rules to restrict inter-container traffic if needed +- External services are exposed only when explicitly configured + +## Performance Optimization + +### Node Selection + +Distribute containers across nodes based on: +- Current resource utilization +- Workload characteristics (CPU-intensive vs. I/O-intensive) +- Network proximity requirements + +### Resource Allocation + +- Allocate CPU and memory based on actual usage patterns +- Use memory limits to prevent runaway processes +- Monitor and adjust allocations over time + +### Storage Performance + +- Use faster storage (SSD/NVMe) for I/O-intensive containers +- Consider separate storage pools for different workload types +- Enable compression on storage to save space (if CPU allows) + +## Next Steps + +For more detailed container management: + +- Review [User Documentation](/docs/users/creating-containers/web-gui) for creation workflows +- Set up monitoring for container health and resource usage +- Configure automated backups in Proxmox +- Review Proxmox documentation for advanced LXC features diff --git a/mie-opensource-landing/docs/admins/external-domains.md b/mie-opensource-landing/docs/admins/external-domains.md new file mode 100644 index 00000000..2e85ff50 --- /dev/null +++ b/mie-opensource-landing/docs/admins/external-domains.md @@ -0,0 +1,211 @@ +--- +sidebar_position: 5 +--- + +# External Domains + +External domains enable you to expose HTTP/HTTPS services running in containers to the internet with automatic SSL/TLS certificate management. + +## What is an External Domain? + +An external domain is a public domain name (e.g., `example.com`) configured to: +- Route traffic to services running in containers +- Automatically obtain and renew SSL/TLS certificates via ACME (Let's Encrypt, etc.) +- Support multiple services on subdomains + +External domains are associated with a specific site and can be used by any container within that site. + +## Prerequisites + +Before configuring an external domain, you need: + +- **A registered domain**: Ownership of a public domain name +- **Cloudflare account**: Currently the only supported DNS provider for automatic certificate validation +- **Cloudflare API credentials**: Token or API key for DNS-01 challenge authentication + +:::note DNS Provider Support +Only Cloudflare is currently supported for automatic certificate management. If you use another DNS provider, you'll need to manage SSL certificates manually. +::: + +## Domain Properties + +An external domain requires: + +### Basic Configuration + +- **Domain**: The top-level domain (e.g., `example.com` or `example.org`) +- **Site**: The site this domain is associated with + +### ACME (Certificate Management) + +- **ACME Email**: Email address for certificate expiration notifications +- **ACME Directory**: The certificate authority endpoint + - Let's Encrypt Production (recommended for live services) + - Let's Encrypt Staging (for testing) + - Other ACME-compatible providers + +- **Cloudflare API Token**: API credentials for DNS-01 challenge + - Can use either an API Token (recommended) or API Key + +:::tip ACME Directory Selection +Use Let's Encrypt **Staging** initially to test your configuration. Staging has higher rate limits and won't count against production quotas. Switch to **Production** once verified. +::: + +## Creating an External Domain + +### 1. Prepare Cloudflare + +Before adding the domain to the cluster: + +1. Add your domain to Cloudflare +2. Update your domain registrar's nameservers to Cloudflare's nameservers +3. Create a Cloudflare API token with **Zone:DNS:Edit** permissions for the domain + +:::important API Token Permissions +The API token must have permission to create and delete DNS TXT records for the domain. This is required for the DNS-01 ACME challenge. +::: + +### 2. Add Domain to Site + +1. Log in to the administration interface +2. Navigate to **External Domains** +3. Click **Create New External Domain** + +### 3. Configure Domain Settings + +Enter the configuration: + +**Example:** +``` +Domain: example.com +ACME Email: admin@example.com +ACME Directory: Let's Encrypt Production +Cloudflare API Token: [your-api-token] +Site: Production Cluster +``` + +### 4. Save and Test + +1. Click **Save** to create the external domain +2. The system will validate Cloudflare API access +3. Certificates will be requested automatically when services are exposed + +## How Certificate Management Works + +When a container exposes an HTTP service using the external domain: + +1. The service is configured (e.g., `app.example.com`) +2. The system initiates an ACME certificate request +3. A DNS-01 challenge is created via Cloudflare API +4. The certificate authority validates ownership via DNS +5. Certificate is issued and automatically installed +6. Certificate auto-renews before expiration (typically every 60 days) + +:::tip DNS-01 vs HTTP-01 +DNS-01 challenges work even when the service isn't publicly accessible yet, making them ideal for clustered environments. They also support wildcard certificates. +::: + +## Using External Domains with Services + +When creating a service in a container, users can: + +1. Select the external domain from a dropdown +2. Specify a subdomain (e.g., `app` for `app.example.com`) +3. The system automatically: + - Creates DNS records in Cloudflare + - Requests SSL certificate via ACME + - Configures reverse proxy routing + +See the [User Documentation](/docs/users/creating-containers/web-gui) for details on exposing services. + +## Multiple External Domains + +You can configure multiple external domains per site: + +- Different top-level domains (e.g., `example.com` and `example.org`) +- Development vs. production domains +- Customer-specific domains in multi-tenant setups + +Each domain manages its own certificates and DNS configuration. + +## Supported ACME Directories + +Common ACME certificate authorities: + +| Provider | Directory URL | Rate Limits | Notes | +|----------|--------------|-------------|-------| +| **Let's Encrypt Production** | `https://acme-v02.api.letsencrypt.org/directory` | 50 certs/week per domain | Recommended for production | +| **Let's Encrypt Staging** | `https://acme-staging-v02.api.letsencrypt.org/directory` | Higher limits | For testing only | +| **ZeroSSL** | `https://acme.zerossl.com/v2/DV90` | Varies | Alternative CA | + +:::warning Rate Limits +Let's Encrypt production has rate limits. Use staging for testing to avoid hitting limits during setup and debugging. +::: + +## Security Considerations + +### API Token Security + +- Store Cloudflare API tokens securely +- Use tokens with minimal required permissions (Zone:DNS:Edit only) +- Rotate tokens periodically +- Revoke tokens immediately if compromised + +### Certificate Management + +- Certificates are stored securely on the management container +- Private keys never leave the cluster +- Automatic renewal prevents expiration +- Expiration notifications sent to ACME email address + +### DNS Security + +- Enable DNSSEC in Cloudflare for additional security +- Monitor DNS changes for unauthorized modifications +- Use Cloudflare's security features (WAF, DDoS protection) + +## Troubleshooting + +### Certificate Request Fails + +**Check Cloudflare API token:** +```bash +# Test API token access +curl -X GET "https://api.cloudflare.com/client/v4/zones" \ + -H "Authorization: Bearer YOUR_TOKEN" +``` + +**Common issues:** +- Invalid or expired API token +- Insufficient token permissions +- Cloudflare nameservers not yet active for domain +- Domain not added to Cloudflare account + +### DNS-01 Challenge Fails + +- Verify DNS propagation: `dig TXT _acme-challenge.example.com` +- Check Cloudflare proxy status (should be DNS only for validation) +- Ensure no conflicting DNS records exist +- Wait for DNS propagation (can take minutes to hours) + +### Rate Limit Exceeded + +If you hit Let's Encrypt rate limits: +- Switch to staging directory for testing +- Wait for rate limit window to reset (weekly for most limits) +- Consider using a different subdomain for testing + +### Certificate Not Renewing + +- Check ACME email for renewal failure notifications +- Verify Cloudflare API token is still valid +- Check system logs for renewal errors +- Manually trigger renewal if needed + +## Next Steps + +After configuring external domains: + +1. **[Nodes](nodes)**: Import your Proxmox nodes +2. **[Containers](containers)**: Deploy containers and expose services +3. Review the [User Documentation](/docs/users/creating-containers/web-gui) for service exposure guides diff --git a/mie-opensource-landing/docs/admins/index.md b/mie-opensource-landing/docs/admins/index.md new file mode 100644 index 00000000..f1490644 --- /dev/null +++ b/mie-opensource-landing/docs/admins/index.md @@ -0,0 +1,45 @@ +--- +sidebar_position: 1 +--- + +# Administrator Documentation + +Welcome to the administrator documentation for the MIE Opensource Proxmox Cluster management system. + +## Getting Started + +New to managing this cluster? Start here: + +### [Installation Guide →](installation) + +Complete step-by-step instructions for: +- Setting up Proxmox VE 13+ +- Deploying the management container +- Configuring network access +- Creating your first administrator account + +### [Core Concepts →](concepts) + +Understanding the architecture and key concepts: +- Cluster organization and nodes +- User roles and permissions +- Container lifecycle management +- Service exposure strategies + +## What You'll Find Here + +This section provides comprehensive guides for: + +- **Installation & Setup**: Deploy and configure the cluster management system +- **Node Management**: Add, configure, and maintain Proxmox nodes +- **User Administration**: Manage accounts, permissions, and access control +- **Network Configuration**: Set up networking, ports, and service exposure +- **Monitoring & Maintenance**: Keep your cluster healthy and performant +- **Security**: Best practices for securing your infrastructure +- **Troubleshooting**: Diagnose and resolve common issues + +--- + +:::tip First Time Here? +Follow the [Installation Guide](installation) to get your cluster management system up and running. +::: diff --git a/mie-opensource-landing/docs/admins/installation.md b/mie-opensource-landing/docs/admins/installation.md new file mode 100644 index 00000000..c1dfe91f --- /dev/null +++ b/mie-opensource-landing/docs/admins/installation.md @@ -0,0 +1,150 @@ +--- +sidebar_position: 1 +--- + +# Installation Guide + +This guide walks you through installing and configuring the MIE Opensource Proxmox Cluster management system on your Proxmox VE infrastructure. + +## Prerequisites + +### System Requirements + +- **Proxmox VE 13 or higher**: Required for OCI (Open Container Initiative) image support +- **Isolated Network**: A network segment dedicated to the Proxmox cluster with no existing DHCP infrastructure +- **Network Access**: Ability to connect to the Proxmox host via: + - SSH (typically port-forwarded) + - Web UI on 8006/tcp (typically port-forwarded) + +### Before You Begin + +Ensure you have: +- Administrative access to your Proxmox VE cluster +- Network connectivity to reach the Proxmox management interface +- A subnet range allocated for the cluster (the management container will need a static IP in this range) + +## Installation Steps + +### 1. Pull the OCI Image + +Connect to your Proxmox VE host via SSH and pull the container image from the GitHub Container Registry. + +Proxmox uses `skopeo` to pull OCI images. First, ensure skopeo is installed: + +```bash +# Install skopeo if not already present +apt update && apt install -y skopeo +``` + +Then pull the image to your template storage: + +```bash +# Pull the OCI image to Proxmox template cache +skopeo copy docker://ghcr.io/mieweb/opensource-server:latest \ + oci-archive:/var/lib/vz/template/cache/opensource-server.tar +``` + +:::tip Using the Web UI +You can also pull OCI images through the Proxmox web interface: +1. Navigate to your storage location (e.g., `local`) +2. Click **CT Templates** +3. Use the **Download from URL** option with the OCI registry reference +::: + +This downloads the pre-built container image to your Proxmox host's template storage. + +### 2. Create the Management Container + +Launch a new container based on the pulled image: + +1. Navigate to the Proxmox web interface at `https://your-proxmox-host:8006` +2. Select your node in the left sidebar +3. Click **Create CT** to open the container creation wizard +4. Configure the container: + - **Template**: Select the `opensource-server:latest` image from OCI registry + - **Hostname**: Choose a meaningful hostname (e.g., `cluster-admin`) + - **Network**: Configure with a **static IP address** in the same subnet as your Proxmox VE server(s) + - **Resources**: Allocate appropriate CPU, memory, and storage based on expected usage + +:::important Static IP Required +The management container must have a static IP address. The container comes with a DNSMasq instance to manage DHCP within the network. +::: + +### 3. Configure Network Access + +Set up port forwarding to make the management interface accessible, exact steps will depend on your firewall platform. The specific port forwarding configuration depends on your network setup. At minimum, forward: +- **443/tcp**: HTTPS access to the web-based administration GUI + +:::tip Additional Ports +Depending on your deployment needs, you may also want to forward: +- **22/tcp**: SSH access to the management container +- **80/tcp**: HTTP access (will redirect to HTTPS) +::: + +### 4. Start the Container + +Once configured, start the management container: + +```bash +pct start +``` + +The container will initialize and start the cluster management services. + +### 5. Initial Account Setup + +Navigate to the management GUI via the forwarded HTTPS port: + +``` +https://your-external-address:443 +``` + +:::important First Account Registration +Register a new account through the web interface. The **first account registered** will be: +- Automatically approved (no manual approval required) +- Granted full administrative privileges +- Able to manage all cluster resources and user accounts +::: + +**Important**: Ensure you register the intended administrator account first, as it will receive elevated privileges automatically. + +## Next Steps + +Once logged in with your administrative account, proceed to the [Concepts](/docs/admins/concepts) guide to understand the architecture and key concepts of the cluster management system. + +You'll learn about: +- Cluster organization and node management +- User roles and permissions +- Container lifecycle management +- Service exposure and networking +- Monitoring and maintenance + +## Troubleshooting + +### Cannot Access the Management GUI + +- Verify port forwarding is correctly configured +- Check that the container is running: `pct status ` +- Ensure the static IP address is reachable from your location +- Review container logs: `pct logs ` + +### OCI Image Pull Fails + +- Verify internet connectivity from the Proxmox host +- Ensure Proxmox VE is version 13 or higher: `pveversion` +- Check that the container registry is accessible +- Try pulling the image manually with verbose output + +### Container Won't Start + +- Check container configuration: `pct config ` +- Review system logs for errors +- Verify sufficient resources are available on the host +- Ensure no IP address conflicts exist on the network + +## Getting Help + +For installation issues or questions: +- Review the detailed error messages in Proxmox logs +- Check the [GitHub repository](https://github.com/mieweb/opensource-server) for known issues +- Contact the MIE team for assistance diff --git a/mie-opensource-landing/docs/admins/nodes.md b/mie-opensource-landing/docs/admins/nodes.md new file mode 100644 index 00000000..98d56733 --- /dev/null +++ b/mie-opensource-landing/docs/admins/nodes.md @@ -0,0 +1,260 @@ +--- +sidebar_position: 6 +--- + +# Nodes + +Nodes represent individual Proxmox VE servers within a site. Each node can host multiple containers and must be registered with the cluster management system before use. + +## What is a Node? + +A node is a physical or virtual server running Proxmox VE that: +- Hosts Linux containers (LXC) +- Provides compute, memory, and storage resources +- Connects to the cluster management system via the Proxmox API +- Participates in the site's network infrastructure + +Multiple nodes within a site form a Proxmox cluster, enabling high availability and resource distribution. + +## Node Properties + +Each node requires the following configuration: + +- **Name**: The node name as it appears in the Proxmox cluster (must match exactly) +- **IP Address**: Used for internal DNS resolution +- **API URL**: The Proxmox API endpoint (e.g., `https://192.168.1.10:8006/api2/json`) +- **Authentication**: Either username/password or API token + - **Username**: Typically `root@pam` for full access + - **Password**: The user's password + - **Token ID**: Alternative to username (e.g., `root@pam!mytoken`) + - **Token Secret**: The token's secret value +- **TLS Verification**: Enable or disable certificate validation (optional) + +## Adding Nodes + +There are two methods for adding nodes to a site: + +### Method 1: Import Nodes (Recommended) + +The Import Nodes function automatically discovers all nodes in a Proxmox cluster: + +1. Navigate to **Nodes** in the administration interface +2. Select your site +3. Click **Import Nodes** +4. Enter the connection details: + - **API URL**: Any node in the cluster (e.g., `https://192.168.1.10:8006/api2/json`) + - **Username**: `root@pam` (recommended) + - **Password**: The root password + - **Disable TLS Verification**: Check if using self-signed certificates + +5. Click **Import** + +The system will: +- Connect to the Proxmox cluster +- Discover all nodes automatically +- Import each node with correct names and IP addresses +- Verify API connectivity + +:::tip Cluster Discovery +Import Nodes only needs credentials for one node. It will automatically discover and import all other nodes in the same Proxmox cluster. +::: + +### Method 2: Manual Node Creation + +For individual nodes or custom configurations: + +1. Navigate to **Nodes** in the administration interface +2. Select your site +3. Click **Create New Node** +4. Fill in all required fields: + - **Name**: Must exactly match the node name in Proxmox + - **IP Address**: The node's network IP + - **API URL**: `https://NODE_IP:8006/api2/json` + - **Username**: `root@pam` + - **Password**: The root password + +5. Click **Save** + +:::important Name Matching +The node name must **exactly match** the hostname shown in the Proxmox web interface. Mismatches will cause API communication failures. +::: + +## Authentication Methods + +### Username & Password + +The traditional authentication method: + +- **Pros**: Simple to configure, no token management +- **Cons**: Less secure, password changes require updating configuration +- **Recommended for**: Initial setup, testing + +**Example:** +``` +Username: root@pam +Password: your-root-password +``` + +### API Token (Recommended for Production) + +A more secure alternative using Proxmox API tokens: + +- **Pros**: More secure, can be revoked independently, fine-grained permissions +- **Cons**: Requires creating tokens in Proxmox first +- **Recommended for**: Production deployments + +**Creating an API Token in Proxmox:** + +1. Log in to Proxmox web interface +2. Navigate to **Datacenter** → **Permissions** → **API Tokens** +3. Click **Add** to create a new token +4. Configure the token: + - **User**: `root@pam` + - **Token ID**: A descriptive name (e.g., `cluster-mgmt`) + - **Privilege Separation**: Uncheck (for full root access) +5. Save and copy the token secret (shown only once) + +**Using the Token:** +``` +Token ID: root@pam!cluster-mgmt +Token Secret: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +``` + +## TLS Certificate Verification + +Proxmox uses self-signed certificates by default, which causes TLS verification to fail. + +### Options: + +**Disable TLS Verification** (Easiest) +- Check the "Disable TLS Verification" option when adding nodes +- ⚠️ Less secure (vulnerable to MITM attacks) +- ✅ Works immediately with self-signed certificates +- Recommended for: Isolated networks, internal deployments + +**Install Valid Certificates** (Most Secure) +- Configure Proxmox to use certificates from a trusted CA +- Leave TLS verification enabled +- ✅ Maximum security +- Recommended for: Production, internet-facing deployments + +:::tip Development vs Production +For isolated development clusters, disabling TLS verification is acceptable. For production environments exposed to untrusted networks, install valid certificates. +::: + +## Verifying Node Configuration + +After adding a node, verify it's working correctly: + +1. Check the node status in the **Nodes** list +2. Verify the green checkmark or "Online" indicator appears +3. Test creating a container on the node + +If the node shows as offline or unreachable: +- Verify the API URL is correct +- Check network connectivity from the management container +- Verify authentication credentials +- Review system logs for detailed error messages + +## Node Management + +### Updating Node Configuration + +To modify a node's settings: + +1. Navigate to the node's detail page +2. Update the necessary fields +3. Save changes +4. The system will test connectivity with the new configuration + +### Removing Nodes + +To remove a node from management: + +1. Ensure no active containers are running on the node +2. Navigate to the node's detail page +3. Click **Delete** or **Remove** +4. Confirm the action + +:::warning Container Dependencies +You cannot remove a node that has active containers. Migrate or delete containers first. +::: + +## Multi-Node Considerations + +### Load Distribution + +The cluster management system can distribute containers across nodes based on: +- Available resources (CPU, memory, storage) +- Node health and availability +- Administrator preferences + +### High Availability + +Proxmox supports HA clustering features: +- Live migration of containers between nodes +- Automatic failover if a node fails +- Shared storage for container data + +:::note HA Configuration +High availability features are configured in Proxmox itself, not in the cluster management system. Refer to Proxmox documentation for HA setup. +::: + +## Troubleshooting + +### Node Shows as Offline + +**Check network connectivity:** +```bash +# From the management container +ping NODE_IP +curl -k https://NODE_IP:8006/api2/json +``` + +**Verify Proxmox API is running:** +```bash +# On the Proxmox node +systemctl status pveproxy +``` + +**Common issues:** +- Firewall blocking port 8006 +- Proxmox API service not running +- Incorrect IP address or API URL +- Network routing issues + +### Authentication Failures + +**Check credentials:** +- Verify username/password or token/secret are correct +- Ensure the user has sufficient permissions +- Check if the API token hasn't been deleted or revoked + +**Test authentication manually:** +```bash +curl -k -u "root@pam:PASSWORD" \ + https://NODE_IP:8006/api2/json/nodes +``` + +### Name Mismatch Errors + +If you see "node name doesn't match" errors: + +1. Check the node name in Proxmox: `hostname` +2. Update the node name in cluster management to match exactly +3. Node names are case-sensitive + +### TLS Verification Errors + +If seeing SSL certificate errors: +- Enable "Disable TLS Verification" option +- Or install valid certificates on Proxmox nodes +- Ensure the certificate hostname matches the API URL + +## Next Steps + +After adding nodes to your site: + +1. **[Containers](containers)**: Learn about container deployment +2. Review the [User Documentation](/docs/users/creating-containers/web-gui) for creating containers +3. Set up monitoring and maintenance procedures diff --git a/mie-opensource-landing/docs/admins/sites.md b/mie-opensource-landing/docs/admins/sites.md new file mode 100644 index 00000000..485ea597 --- /dev/null +++ b/mie-opensource-landing/docs/admins/sites.md @@ -0,0 +1,155 @@ +--- +sidebar_position: 4 +--- + +# Sites + +A site is the top-level organizational unit that groups Proxmox nodes, defines network configuration, and manages container networking. You must create at least one site before adding nodes or deploying containers. + +## What is a Site? + +A site represents a physical or logical cluster location with its own: +- Network subnet and DHCP configuration +- Proxmox node(s) +- Container deployments +- External domain mappings + +Sites enable you to manage multiple independent Proxmox clusters from a single management interface. + +## Site Properties + +When creating a site, you must configure: + +### Basic Information + +- **Display Name**: A human-readable name for the site (e.g., "Production Cluster", "Development Lab") + +### Network Configuration + +- **Internal Domain Name**: The DNS domain for the cluster's internal network + - Recommended: `cluster.yourdomain.tld` + - If you don't own a domain, use IANA-defined local domains like `.internal`, `.local`, or `.home.arpa` + +- **DHCP Range**: The IP address range for automatic container assignment + - Must be within the site's subnet + - Format: `192.168.1.100-192.168.1.200` + +- **Subnet Mask**: The network subnet mask (e.g., `255.255.255.0` or `/24`) + +- **Gateway IP**: The default gateway for the network (typically your router) + +- **DNS Forwarders**: Upstream DNS servers for resolving external domains + - Can specify multiple servers separated by commas + - Example: `8.8.8.8,1.1.1.1` + +## Creating a Site + +Follow these steps to create your first site: + +### 1. Access Site Management + +1. Log in to the administration interface +2. Navigate to **Sites** in the main menu +3. Click **Create New Site** + +### 2. Configure Basic Settings + +1. Enter a descriptive **Display Name** +2. Set your **Internal Domain Name** (e.g., `cluster.example.internal`) + +:::tip Domain Selection +If you own a domain, using a subdomain like `cluster.yourdomain.tld` allows you to create valid SSL certificates. For purely internal deployments, `.internal` is recommended per RFC 8375. +::: + +### 3. Configure Networking + +Configure the network settings based on your infrastructure: + +**Example Configuration:** +``` +DHCP Range: 192.168.100.100-192.168.100.200 +Subnet Mask: 255.255.255.0 (or /24) +Gateway IP: 192.168.100.1 +DNS Forwarders: 8.8.8.8,1.1.1.1 +``` + +:::important Network Isolation +Ensure the DHCP range does not conflict with: +- Static IPs assigned to Proxmox nodes +- The management container's IP address +- Any other static infrastructure devices +::: + +### 4. Save and Verify + +1. Click **Save** to create the site +2. Verify the site appears in the sites list +3. Check that network settings are correct + +## DHCP and IP Management + +The cluster management system handles DHCP for containers automatically: + +- When a user creates a container, an IP is automatically assigned from the DHCP range +- IP assignments are tracked to prevent conflicts +- Containers receive DNS configuration pointing to the internal DNS server +- The gateway and subnet mask are automatically applied + +### Static IP Addresses + +While containers typically use DHCP, you can configure static IPs outside the DHCP range for: +- Load balancers +- Database servers +- Other infrastructure components requiring fixed addresses + +## DNS Configuration + +The internal DNS server provides: + +- Name resolution for containers within the site: `container-name.cluster.example.internal` +- Forwarding for external domains to the configured DNS forwarders +- Automatic DNS record creation when containers are deployed + +## Multiple Sites + +You can create multiple sites to manage separate clusters: + +- **Geographical separation**: Different physical locations +- **Environment separation**: Production vs. Development vs. Testing +- **Network isolation**: Different security zones or network segments + +Each site operates independently with its own: +- Network configuration +- Nodes and containers +- External domain mappings + +## Next Steps + +After creating a site: + +1. **[External Domains](external-domains)**: Configure domains for exposing HTTP services (optional) +2. **[Nodes](nodes)**: Import your Proxmox nodes into the site +3. **[Containers](containers)**: Begin deploying containers on your nodes + +## Troubleshooting + +### DHCP Range Exhausted + +If you run out of DHCP addresses: +1. Edit the site configuration +2. Expand the DHCP range (ensure no conflicts) +3. Save changes + +### DNS Resolution Issues + +If containers can't resolve external domains: +- Verify DNS forwarders are reachable from the Proxmox nodes +- Test DNS resolution: `dig @8.8.8.8 google.com` +- Check that the internal DNS server is running + +### Gateway Unreachable + +If containers can't reach the internet: +- Verify the gateway IP is correct +- Ensure Proxmox nodes can reach the gateway +- Check firewall rules on the gateway device diff --git a/mie-opensource-landing/docs/admins/users-and-groups.md b/mie-opensource-landing/docs/admins/users-and-groups.md new file mode 100644 index 00000000..86232185 --- /dev/null +++ b/mie-opensource-landing/docs/admins/users-and-groups.md @@ -0,0 +1,144 @@ +--- +sidebar_position: 3 +--- + +# Users & Groups + +User accounts and groups form the foundation of access control in the cluster management system. Groups determine permissions and provide LDAP authentication for container access. + +## Groups + +Groups organize users and define their permissions within the cluster. + +### Default Groups + +The system includes two built-in groups: + +- **ldapusers**: Members can authenticate via LDAP to all containers in the cluster +- **sysadmins**: Members receive full administrative access to both Proxmox nodes and the cluster management software + +### Group Properties + +When creating a new group, you must configure: + +- **Name**: The LDAP common name (CN) used for authentication +- **GID**: A unique numeric Group ID used by the LDAP server +- **Administrator**: Toggle to grant members full Proxmox and software administration privileges + +:::important GID Uniqueness +Each group must have a unique numeric GID. The LDAP server uses this identifier, so conflicts will cause authentication issues. +::: + +### Creating a Group + +1. Navigate to **Groups** in the administration interface +2. Click **Create New Group** +3. Enter a descriptive name (will be used as LDAP CN) +4. Assign a unique numeric GID +5. Enable **Administrator** if members should have full cluster access +6. Save the group + +## Users + +User accounts allow individuals to authenticate and access cluster resources. + +### User Registration + +Users typically register themselves through the web interface by providing: + +- Username +- First name +- Last name +- Email address +- Password + +Newly registered users are automatically: +- Set to **Pending** status +- Added to the **ldapusers** group + +:::tip Manual User Creation +Administrators can also create user accounts manually through the admin interface, skipping the registration process. +::: + +### User Statuses + +Users can have one of three statuses: + +- **Pending**: Newly registered, awaiting administrator approval +- **Active**: Approved and able to authenticate to all cluster services +- **Suspended**: Access revoked, cannot authenticate anywhere + +:::important Authentication Requirement +Only users with **Active** status can log in to the management interface, Proxmox, or any containers. +::: + +### Approving Users + +To approve a pending user: + +1. Navigate to **Users** in the administration interface +2. Find the pending user +3. Change their status to **Active** +4. Optionally add them to additional groups beyond **ldapusers** +5. Save the changes + +### Managing Group Membership + +To modify a user's group memberships: + +1. Navigate to the user's detail page +2. In the **Groups** section, add or remove group assignments +3. Save changes + +Group membership changes take effect immediately for new authentication attempts. + +## LDAP Integration + +The built-in LDAP server uses group and user information to provide authentication services to all containers in the cluster. + +### How It Works + +- Users in the **ldapusers** group can SSH into any container using their cluster credentials +- Group IDs (GIDs) and user IDs (UIDs) are synchronized across all containers +- Password changes in the management interface propagate to LDAP immediately + +### Best Practices + +- Keep the **ldapusers** group for general container access +- Create additional groups for team-based or project-based access control +- Use the **Administrator** flag sparingly - only for trusted cluster administrators +- Regularly review and approve pending user registrations +- Suspend rather than delete users who leave the organization (preserves audit trails) + +## Security Considerations + +### Password Management + +- Enforce strong password policies during registration +- Passwords are hashed and never stored in plaintext +- Users can reset their own passwords through the web interface + +### Administrator Access + +Users in administrator groups have extensive privileges: +- Full Proxmox API access on all nodes +- Ability to create, modify, and delete any resource +- Access to all user data and configurations + +Only grant administrator status to trusted individuals. + +### Audit Trail + +All user actions are logged, including: +- Login attempts (successful and failed) +- Status changes (pending → active, active → suspended) +- Group membership modifications +- Resource creation and deletion + +Review logs regularly to detect unauthorized access attempts. + +## Next Steps + +Once you've configured users and groups, proceed to: +- [**Sites**](sites): Set up your network infrastructure +- [**Nodes**](nodes): Connect your Proxmox servers diff --git a/mie-opensource-landing/docs/creating-containers/advanced-containers/_category_.json b/mie-opensource-landing/docs/creating-containers/advanced-containers/_category_.json deleted file mode 100644 index b0c2c772..00000000 --- a/mie-opensource-landing/docs/creating-containers/advanced-containers/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Creating Advanced Containers", - "position": 2, - "link": { - "type": "generated-index", - "description": "Learn how to create and set up deployment-ready LXC Containers from the command line." - } -} diff --git a/mie-opensource-landing/docs/creating-containers/advanced-containers/deploying-containers-overview.md b/mie-opensource-landing/docs/creating-containers/advanced-containers/deploying-containers-overview.md deleted file mode 100644 index 62a742f1..00000000 --- a/mie-opensource-landing/docs/creating-containers/advanced-containers/deploying-containers-overview.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Deploying Containers Overview - -The MIE Opensource Proxmox Cluster provides automated container deployment capabilities, allowing you to deploy applications directly from GitHub repositories without manual setup. This automation eliminates the need to SSH into containers, manually install dependencies, configure services, and start applications. - -:::note Note -As of writing (8/14/25), automatic deploy only supports components that run on either a `nodejs` or `python` runtime environment. -::: - -## Single vs Multi-Component Applications - -### Single Component Applications - -A **single component application** consists of one independent service or process that requires: -- One set of installation commands (e.g., `npm install`) -- One start command (e.g., `npm start`) -- One runtime environment (e.g., Node.js, Python) -- One package list or dependency file - -**Examples:** -- A React frontend application -- A simple Express.js server -- A Flask API server -- A Meteor application - -:::tip Tip -See the documentation for deploying single-component applications [here](/docs/creating-containers/advanced-containers/single-component). -::: - -### Multi-Component Applications - -A **multi-component application** consists of multiple independent services that each require: -- Their own installation commands -- Their own start commands -- Their own runtime environments -- Their own dependency files and environment variables - -**Examples:** -- React frontend + Flask backend -- Vue.js frontend + Express.js API + MongoDB -- Angular frontend + Django backend + PostgreSQL -- Multiple microservices working together - -:::tip Tip -See the documentation for deploying multi-component applications [here](/docs/creating-containers/advanced-containers/multi-component). -::: - -### Key Differences - -| Aspect | Single Component | Multi-Component | -|--------|------------------|-----------------| -| **Services** | One service/process | Multiple independent services | -| **Dependencies** | One package file | Multiple package files per component | -| **Runtime** | One runtime environment | Multiple runtime environments (although each runtime environment could be the same) | -| **Start Commands** | One start command | Multiple start commands | -| **Environment Variables** | One .env file | Multiple .env files per component | - -## Benefits of Automated Deployment - -### Eliminates Manual Setup -- **No SSH Required**: Deploy without manually connecting to containers -- **Automatic Dependencies**: Dependencies are installed automatically from package files -- **Service Configuration**: Required services (MongoDB, PostgreSQL, etc.) are installed and configured automatically -- **Environment Setup**: Environment variables are configured in the correct locations - -### Reduces Deployment Time -- **Instant Deployment**: Applications are ready immediately after container creation -- **Consistent Environment**: Same deployment process every time, reducing errors -- **Parallel Processing**: Multiple components are set up simultaneously - -### Simplifies Development Workflow -- **GitHub Integration**: Deploy directly from your repository with Proxmox Launchpad - -:::note Note -It is recommended to deploy your application on a test container via the command line first before working with [Proxmox Launchpad](/docs/category/proxmox-launchpad). -::: - - -## When to Use Each Method - -**Choose Single Component Deployment when:** -- Your application runs as one process -- All dependencies are in one package file -- You have one entry point/start command - -**Choose Multi-Component Deployment when:** -- Your application has separate frontend and backend -- Different parts use different runtime enviornments -- Components have different dependency requirements -- You need different environment variables for different services - ---- - -Ready to deploy? Choose your deployment method: -- [Single Component Deployment Guide](/docs/creating-containers/advanced-containers/single-component) -- [Multi-Component Deployment Guide](/docs/creating-containers/advanced-containers/multi-component) - diff --git a/mie-opensource-landing/docs/creating-containers/advanced-containers/multi-component.md b/mie-opensource-landing/docs/creating-containers/advanced-containers/multi-component.md deleted file mode 100644 index 514395ab..00000000 --- a/mie-opensource-landing/docs/creating-containers/advanced-containers/multi-component.md +++ /dev/null @@ -1,415 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Multi-Component Deployment - -This guide walks you through deploying a multi-component application automatically during container creation. A multi-component application consists of multiple independent services (e.g., frontend + backend) that each require their own installation commands, start commands, and runtime environments. - -:::note Prerequisites -- Valid Proxmox account on the MIE cluster -- Public GitHub repository with your application code -- Application with separate components in different directories -- Basic understanding of each component's requirements -::: - -## Getting Started - -Follow the [basic container creation steps](/docs/creating-containers/basic-containers/command-line) until you reach the automatic deployment prompt: - -``` -Do you want to deploy your project automatically? (y/n) → -``` - -Answer `y` to begin the deployment configuration process. - -## 1: Repository Information - -### Project Repository -``` -Paste the link to your project repository → -``` - -**Requirements:** -- Must be a valid, accessible GitHub repository URL -- Repository must be public -- Examples: `https://github.com/username/my-fullstack-app` - -**Validation:** The script checks if the repository exists and is accessible. - -### Project Branch -``` -Enter the project branch to deploy from (leave blank for "main") → -``` - -**Options:** -- Leave blank to use the default `main` branch -- Enter specific branch name (e.g., `develop`, `staging`) -- If your default branch is `master`, you must type `master` - -**Validation:** The script verifies the branch exists in your repository. - -### Project Root Directory -``` -Enter the project root directory (relative to repository root directory, or leave blank for root directory) → -``` - -**Options:** -- Leave blank to deploy from repository root (most common) -- Enter relative path if your application is in a subdirectory - -**Validation:** The script confirms the directory exists in your repository. - -## 2: Component Configuration - -### Multi-Component Check -``` -Does your app consist of multiple components that run independently, i.e. separate frontend and backend (y/n) → -``` - -**For multi-component applications, answer `y`.** - -## 3: Environment Variables (Optional) - -``` -Does your application require environment variables? (y/n) → -``` - -If you answer `y`, you'll configure environment variables **per component**: - -### Component Path Selection -``` -Enter the path of your component to enter environment variables → -``` - -**Examples:** -- `frontend/` for React/Vue/Angular frontend -- `backend/` for Express/Flask/Django backend -- `api/` for API services -- `client/` for client applications - -**Important:** Paths are relative to your project root directory. - -### Environment Variable Entry -For each component, you'll be prompted: -``` -Enter Environment Variable Key → -Enter Environment Variable Value → -Do you want to enter another Environment Variable? (y/n) → -``` - -**Examples:** -- Frontend: `REACT_APP_API_URL` → `http://localhost:5000/api` -- Backend: `DATABASE_URL` → `mongodb://localhost:27017/myapp` -- Backend: `SECRET_KEY` → `your-secret-key` - -### Multiple Components -After finishing one component's environment variables: -``` -Enter the path of your component to enter environment variables → -``` - -**Process:** -- Enter next component path (e.g., `backend/`) -- Configure its environment variables -- Repeat for all components that need environment variables -- Press Enter (leave blank) when finished - -**Notes:** -- Each component gets its own `.env` file in its directory -- Environment variables are isolated per component - -## 4: Build Commands (Optional) - -### Component Build Commands -``` -Enter the path of your component to enter the build command → -``` - -Then for each component: -``` -Enter the build command (leave blank if no build command) → -``` - -**Examples:** -- Frontend: `npm run build` (React, Angular, Vue) -- Backend: Usually no build command needed -- TypeScript projects: `npm run build` or `tsc` - -**Process:** -- Enter component path (e.g., `frontend/`) -- Enter build command for that component -- Repeat for all components requiring build steps -- Press Enter (leave blank) when finished - -## 5: Install Commands (Required) - -### Component Install Commands -``` -Enter the path of your component to enter the install command → -``` - -Then for each component: -``` -Enter the install command (e.g., 'npm install') → -``` - -**Examples:** -- Frontend (Node.js): `npm install` -- Backend (Node.js): `npm install` -- Backend (Python): `pip install -r requirements.txt` -- Backend (Python with path): `pip install -r ../requirements.txt` - -**Process:** -- Enter component path (e.g., `frontend/`) -- Enter install command for that component -- Repeat for all components -- Press Enter when finished - -:::important Important -- Commands run from within each component directory -- If your `requirements.txt` is in the project root, use relative paths like `../requirements.txt` -- Ensure dependency files are accessible from component directories -::: - - -## 6: Start Commands (Required) - -### Component Start Commands -``` -Enter the path of your component to enter the start command → -``` - -Then for each component: -``` -Enter the start command (e.g., 'npm start', 'python app.py') → -``` - -**Examples:** -- Frontend: `npm run dev` (Vite), `npm start` (React) -- Backend (Node.js): `npm start`, `node server.js` -- Backend (Flask): `FLASK_ENV=production flask run` -- Backend (Django): `python manage.py runserver 0.0.0.0:5000` - -**Process:** -- Enter component path for each component -- Enter start command for that component -- Repeat for all components -- Press Enter when finished - -:::important Important -Many applications, by default, run HTTP/HTTPS services on 127.0.0.1 (localhost). Make sure your service is running on 0.0.0.0 instead (all IPv4 addresses on the machine). -::: - -:::note Using Meteor? -If your application is a meteor application, you must include the flag --allow-superuser to run your application. -::: - -### Root Directory Commands (Optional) -``` -Do you want to run a command from the root directory? (e.g., 'docker-compose up') (Enter to skip) → -``` - -**Use cases:** -- Docker Compose: `docker-compose up` -- Docker Build: `docker build . && docker run -p 3000:3000 myapp` -- Makefile commands: `make start` -- Shell scripts: `./start.sh` - -**Leave blank if:** You don't need root-level commands. - -## 7: Runtime Environment (Required) - -For each component you've configured, specify its runtime: - -``` -Enter the underlying runtime environment for "frontend/" (e.g., 'nodejs', 'python') → -Enter the underlying runtime environment for "backend/" (e.g., 'nodejs', 'python') → -``` - -**Supported runtimes:** -- `nodejs` - For Node.js, React, Angular, Vue, Express applications -- `python` - For Python, Flask, Django, FastAPI applications - -**Examples:** -- React frontend → `nodejs` -- Flask backend → `python` -- Express backend → `nodejs` -- Vue frontend → `nodejs` - -:::note Note -Only `nodejs` and `python` are currently supported. -::: - -## 8: Services (Optional) - -``` -Does your application require special services (i.e. Docker, MongoDB, etc.) to run on the container? (y/n) → -``` - -Services are shared across all components in your application. - -If you answer `y`: -``` -Enter the name of a service to add to your container or type "C" to set up a custom service installation (Enter to exit) → -``` - -### Available Services -Common services for multi-component apps: -- `meteor` - Meteor framework -- `apache` - Apache web server -- `rabbitmq` - Message broker -- `memcached` - Caching service -- `mariadb` - MariaDB database -- `mongodb` - MongoDB database -- `postgresql` - PostgreSQL database -- `redis` - Redis cache -- `docker` - Docker container runtime -- `nginx` - NGINX web server - -:::note Note -Some services, like meteor, come pre-packaged with other services, like MongoDB. Installing the pre-packaged services like these separately is not necessary. -::: - -### Custom Services -Type `C` to install a service not in the master list and follow the prompts for custom installation commands. - -``` -Configuring Custom Service Installation. For each prompt, enter a command that is a part of the installation process for your service on Debian Bookworm. Do not forget to enable and start the service at the end. Once you have entered all of your commands, press enter to continue - -Enter Command 1: -Enter Command 2: -... -``` - -**Example custom service installation (NGINX):** -``` -sudo apt update -y -sudo apt install nginx -y -sudo systemctl enable nginx -sudo systemctl start nginx -``` - -:::important Important -Make sure you enable and start your service using the systemctl service manager CLI. -::: - -## 9: Automatic Deployment - -After providing all information, the system automatically: - -1. **Clones your repository** from the specified branch -2. **Allocates resources** (IP address, ports) via DHCP -3. **Configures LDAP**: Connects your container to an LDAP server -4. **Configures Wazuh**: Enables security monitoring on your container -5. **Installs services** (MongoDB, PostgreSQL, etc.) -6. **For each component:** - - Navigates to component directory - - Installs dependencies using install command - - Builds if build command provided - - Starts using start command in background -7. **Runs root commands** (if specified) -8. **Configures networking** (DNS, reverse proxy) - -This process typically takes 3-7 minutes depending on the number of components and their complexity. - -## Understanding the Output - -Once deployment completes, you'll receive output similar to: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -🔔 COPY THESE PORTS DOWN — For External Access -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📌 Note: Your container listens on SSH Port 22 internally, - but EXTERNAL traffic must use the SSH port listed below: -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -✅ Hostname Registration: my-fullstack-app → 10.15.19.182 -🔐 SSH Port : 2377 -🌐 HTTP Port : 3000 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📦 Container ID : 117 -🌐 Internal IP : 10.15.19.182 -🔗 Domain Name : https://my-fullstack-app.opensource.mieweb.org -🛠️ SSH Access : ssh -p 2377 myusername@my-fullstack-app.opensource.mieweb.org -🔑 Container Password : Your proxmox account password -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -NOTE: Additional background scripts are being ran in detached terminal sessions. -Wait up to two minutes for all processes to complete. -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -### Output Explanation - -| Field | Description | -|-------|-------------| -| **Hostname Registration** | Your application name mapped to the internal container IP | -| **SSH Port** | External port for SSH access (internal port 22 is mapped to this) | -| **HTTP Port** | Primary port your application is listening on (usually frontend) | -| **Container ID** | Unique identifier for your container in Proxmox | -| **Internal IP** | Private IP address assigned to your container | -| **Domain Name** | Public URL where your application is accessible | -| **SSH Access** | Complete SSH command to access your container | -| **Container Password** | Same as your Proxmox account password | - -:::important Important Notes -- Your application is accessible at the provided domain name -- All components run simultaneously in the background -- Wait 1-2 minutes for all background processes to complete -- Even-numbered containers are automatically migrated to PVE2 for load balancing -::: - -## Verifying Multi-Component Deployment - -After deployment, you can SSH into your container to verify all components are running: - -```bash -ssh -p 2377 myusername@my-fullstack-app.opensource.mieweb.org -``` - -Check running processes: -```bash -ss -tlnp | grep LISTEN -``` - -You should see your components listening on their respective ports. - -Check environment variables: -```bash -# Frontend environment variables -cat frontend/.env - -# Backend environment variables -cat backend/.env -``` - -## Troubleshooting - -**Component path errors:** -- Ensure component paths are relative to your project root -- Check that directories exist in your repository - -**Dependency installation fails:** -- For Python: Ensure `requirements.txt` path is correct relative to component directory -- For Node.js: Ensure `package.json` exists in component directory -- Check that dependency files are committed to your repository - -**Services not communicating:** -- Ensure backend services bind to `0.0.0.0` not `localhost` -- Check that frontend API URLs point to correct backend port -- Verify environment variables are correctly set - -**Runtime environment error:** -- Only `nodejs` and `python` are supported -- Ensure you're typing the runtime exactly as shown -- Each component can have different runtimes - -**Application not Accessible:** -- Wait 2-5 minutes for all background scripts to complete -- Check that your start commands are correct -- Verify your application listens on the specified HTTP port -- Run `tmux attach -t 0` inside your container to see any errors with you start/build command(s) - ---- - -**Next Steps:** Once your multi-component application is deployed, you can monitor each component, check logs via SSH, or explore using [Proxmox Launchpad](/docs/category/proxmox-launchpad) for automated CI/CD deployment. \ No newline at end of file diff --git a/mie-opensource-landing/docs/creating-containers/advanced-containers/single-component.md b/mie-opensource-landing/docs/creating-containers/advanced-containers/single-component.md deleted file mode 100644 index 9e9e5b36..00000000 --- a/mie-opensource-landing/docs/creating-containers/advanced-containers/single-component.md +++ /dev/null @@ -1,296 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Single-Component Deployment - -This guide walks you through deploying a single-component application automatically during container creation. A single-component application runs as one service with unified dependencies, build commands, and start commands. - -:::note Prerequisites -- Valid Proxmox account on the MIE cluster -- Public GitHub repository with your application code -- Basic understanding of your application's requirements -::: - -## Getting Started - -Follow the [basic container creation steps](/docs/creating-containers/basic-containers/command-line) until you reach the automatic deployment prompt: - -``` -Do you want to deploy your project automatically? (y/n) → -``` - -Answer `y` to begin the deployment configuration process. - -## 1: Repository Information - -### Project Repository -``` -Paste the link to your project repository → -``` - -**Requirements:** -- Must be a valid, accessible GitHub repository URL -- Repository must be public -- Examples: `https://github.com/username/my-app` or `https://github.com/username/my-app.git` - -**Validation:** The script checks if the repository exists and is accessible. - -### Project Branch -``` -Enter the project branch to deploy from (leave blank for "main") → -``` - -**Options:** -- Leave blank to use the default `main` branch -- Enter specific branch name (e.g., `develop`, `staging`) -- If your default branch is `master`, you must type `master` - -**Validation:** The script verifies the branch exists in your repository. - -### Project Root Directory -``` -Enter the project root directory (relative to repository root directory, or leave blank for root directory) → -``` - -**Options:** -- Leave blank to deploy from repository root (most common) -- Enter relative path if your application is in a subdirectory (e.g., `app/`, `src/backend/`) - -**Validation:** The script confirms the directory exists in your repository. - -## 2: Component Configuration - -### Multi-Component Check -``` -Does your app consist of multiple components that run independently, i.e. separate frontend and backend (y/n) → -``` - -**For single-component applications, answer `n` or leave blank.** - -## 3: Environment Variables (Optional) - -``` -Does your application require environment variables? (y/n) → -``` - -If you answer `y`, you'll be prompted for key-value pairs: - -``` -Enter Environment Variable Key → -Enter Environment Variable Value → -Do you want to enter another Environment Variable? (y/n) → -``` - -**Examples:** -- `API_KEY` → `your-api-key-value` -- `DATABASE_URL` → `mongodb://localhost:27017/myapp` -- `NODE_ENV` → `production` - -**Notes:** -- Environment variables are stored in a `.env` file in your project root -- Both key and value are required (cannot be empty) -- Continue adding variables or press Enter when finished - -## 4: Build Commands (Optional) - -``` -Enter the build command (leave blank if no build command) → -``` - -**Examples:** -- `npm run build` (React, Angular, Vue applications) -- `python setup.py build` (Python applications) -- `make build` (Applications with Makefiles) - -**Leave blank if:** Your application doesn't require a build step. - -## 5: Install Commands (Required) - -``` -Enter the install command (e.g., 'npm install') → -``` - -**Examples:** -- `npm install` (Node.js applications) -- `pip install -r requirements.txt` (Python applications) - -:::important Important -If you are deploying a component that is made in Python, and you have a `requirements.txt` file, make sure the requirements.txt file is in your project's root directory, or enter the path to the `requirements.txt` relatve to your project's root directory. -::: - -**This step is required** - your application must have an install command. - -## 6: Start Commands (Required) - -``` -Enter the start command (e.g., 'npm start', 'python app.py') → -``` - -**Examples:** -- `npm start` (Node.js applications) -- `python app.py` (Python Flask/Django applications) -- `node server.js` (Node.js servers) - -**Additional flags:** Include any necessary flags like hostname, port, or environment settings. - -:::important Important -Many applications, by default, run HTTP/HTTPS services on 127.0.0.1 (localhost). Make sure your service is running on 0.0.0.0 instead (all IPv4 addresses on the machine). -::: - -:::note Using Meteor? -If your application is a meteor application, you must include the flag --allow-superuser to run your application. -::: - -## 7: Runtime Environment (Required) - -``` -Enter the underlying runtime environment for your project (e.g., 'nodejs', 'python') → -``` - -**Supported runtimes:** -- `nodejs` - For Node.js, React, Angular, Vue, Express applications -- `python` - For Python, Flask, Django, FastAPI applications - -:::note Note -Only `nodejs` and `python` are currently supported. -::: - -## 8: Services (Optional) - -``` -Does your application require special services (i.e. Docker, MongoDB, etc.) to run on the container? (y/n) → -``` - -If you answer `y`: - -``` -Enter the name of a service to add to your container or type "C" to set up a custom service installation (Enter to exit) → -``` - -### Available Services -Common services include: -- `meteor` - Meteor framework -- `apache` - Apache web server -- `rabbitmq` - Message broker -- `memcached` - Caching service -- `mariadb` - MariaDB database -- `mongodb` - MongoDB database -- `postgresql` - PostgreSQL database -- `redis` - Redis cache -- `docker` - Docker container runtime -- `nginx` - NGINX web server - -:::note Note -Some services, like meteor, come pre-packaged with other services, like MongoDB. Installing the pre-packaged services like these separately is not necessary. -::: - -### Custom Services -Type `C` to install a service not in the master list: - -``` -Configuring Custom Service Installation. For each prompt, enter a command that is a part of the installation process for your service on Debian Bookworm. Do not forget to enable and start the service at the end. Once you have entered all of your commands, press enter to continue - -Enter Command 1: -Enter Command 2: -... -``` - -**Example custom service installation (NGINX):** -``` -sudo apt update -y -sudo apt install nginx -y -sudo systemctl enable nginx -sudo systemctl start nginx -``` - -:::important Important -Make sure you enable and start your service using the systemctl service manager CLI. -::: - -## 9: Automatic Deployment - -After providing all information, the system automatically: - -1. **Clones your repository** from the specified branch -2. **Allocates resources** (IP address, ports) via DHCP -3. **Configures LDAP**: Connects your container to an LDAP server -4. **Configures Wazuh**: Enables security monitoring on your container -5. **Installs services** (MongoDB, PostgreSQL, etc.) -6. **Installs dependencies** using your install command -7. **Builds the application** (if build command provided) -8. **Starts the application** using your start command -9. **Configures networking** (DNS, reverse proxy) - -This process typically takes 2-5 minutes depending on your application's complexity. - -## Understanding the Output - -Once deployment completes, you'll receive output similar to: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -🔔 COPY THESE PORTS DOWN — For External Access -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📌 Note: Your container listens on SSH Port 22 internally, - but EXTERNAL traffic must use the SSH port listed below: -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -✅ Hostname Registration: my-app → 10.15.19.181 -🔐 SSH Port : 2376 -🌐 HTTP Port : 3000 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📦 Container ID : 116 -🌐 Internal IP : 10.15.19.181 -🔗 Domain Name : https://my-app.opensource.mieweb.org -🛠️ SSH Access : ssh -p 2376 myusername@my-app.opensource.mieweb.org -🔑 Container Password : Your proxmox account password -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -NOTE: Additional background scripts are being ran in detached terminal sessions. -Wait up to two minutes for all processes to complete. -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -### Output Explanation - -| Field | Description | -|-------|-------------| -| **Hostname Registration** | Your application name mapped to the internal container IP | -| **SSH Port** | External port for SSH access (internal port 22 is mapped to this) | -| **HTTP Port** | Port your application is listening on | -| **Container ID** | Unique identifier for your container in Proxmox | -| **Internal IP** | Private IP address assigned to your container | -| **Domain Name** | Public URL where your application is accessible | -| **SSH Access** | Complete SSH command to access your container | -| **Container Password** | Same as your Proxmox account password | - -:::important Important Notes -- Your application is accessible at the provided domain name -- Wait 1-2 minutes for all background processes to complete -- Even-numbered containers are automatically migrated to PVE2 for load balancing -- Your container password is the same as your Proxmox account password -::: - -## Troubleshooting - -**Repository validation fails:** -- Ensure the repository URL is correct and publicly accessible -- Check that the branch name exists -- Verify the project root directory path - -**Runtime environment error:** -- Only `nodejs` and `python` are supported -- Ensure you're typing the runtime exactly as shown - -**Service installation fails:** -- Check that service names are spelled correctly -- For custom services, ensure all commands are valid for Debian Bookworm - -**Application not accessible:** -- Wait 2-5 minutes for all background scripts to complete -- Check that your start command is correct -- Verify your application listens on the specified HTTP port -- Run `tmux attach -t 0` inside your container to see any errors with you start/build command(s) - ---- - -**Next Steps:** Once your single-component application is deployed, you can SSH into your container, view logs, or explore [multi-component deployment](/docs/creating-containers/advanced-containers/multi-component) for more complex applications. \ No newline at end of file diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/_category_.json b/mie-opensource-landing/docs/creating-containers/basic-containers/_category_.json deleted file mode 100644 index 0f47b13c..00000000 --- a/mie-opensource-landing/docs/creating-containers/basic-containers/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Creating Basic Containers", - "position": 1, - "link": { - "type": "generated-index", - "description": "Learn how to create and set up basic LXCs (non-deployment ready) from both the web and the command line." - } -} diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/command-line.md b/mie-opensource-landing/docs/creating-containers/basic-containers/command-line.md deleted file mode 100644 index 91b0d8ed..00000000 --- a/mie-opensource-landing/docs/creating-containers/basic-containers/command-line.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Using The Command Line - -:::note Note -This walkthrough assumes that you already have a registered proxmox account in the cluster. If not, see [Introduction](/docs/intro.md). -::: - -This guide shows you how to set up a basic LXC container on the MIE Opensource Proxmox Cluster using the command line. We will walk you through several configuration steps, with exact prompts shown below. - -## 1. Authenticate Your Proxmox Account - -You'll be prompted for your credentials: - -``` -Enter Proxmox Username → -Enter Proxmox Password → -``` - -**Options:** -- Enter your valid Proxmox username and password -- If authentication fails, you'll see a "Authentication Failed. Try Again" message and be prompted again - -## 2. Choose a Container Hostname - -This will be your container's subdomain: - -``` -Enter Application Name (One-Word) → -``` - -**Options:** -- Use a single word containing only letters, numbers, and hyphens (e.g., `myapp`, `test-api`) -- The hostname will be available at `your-hostname.opensource.mieweb.org` -- If the name is already taken or contains invalid characters, you'll be asked to choose another - -## 3. Select a Linux Distribution - -The script presents available distributions: - -``` -Available Linux Distributions: -1. Debian 12 (Bookworm) -2. Rocky 9 -Choose a Linux Distribution (debian/rocky) → -``` - -**Options:** -- Type `debian` for Debian 12 (Bookworm) -- Type `rocky` for Rocky Linux 9 -- Any invalid input defaults to Debian - -## 4. Configure SSH Access - -The script attempts to detect your SSH public key: - -``` -Attempting to Detect SSH Public Key... -``` - -If no key is detected: -``` -Could not detect Public Key -Enter Public Key (Allows Easy Access to Container) [OPTIONAL - LEAVE BLANK TO SKIP] → -``` - -**Options:** -- Enter your SSH public key (starts with `ssh-rsa`, `ssh-ed25519`, etc.) -- Leave blank to skip SSH key configuration -- Invalid keys will prompt for a valid key or blank entry - -:::important Important -Entering a public key is highly recommended. It will allow you to access the create-container command line setup without entering a password. Additionally, it will allow you to SSH to your container without having to input your proxmox password, making the connection process faster and more secure. - -To create a private/public key pair on your machine, reference [this guide](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key). -::: - -## 5. Set the HTTP Port - -Specify which port your application will listen on: - -``` -Enter HTTP Port for your container to listen on (80-60000) → -``` - -**Options:** -- Any number between 80 and 60,000 -- Common choices: 80, 3000, 8080, 5000, 8000 -- Invalid entries will prompt you to try again - -## 6. Add Additional Protocols (Optional) - -Configure additional protocols beyond SSH and HTTP: - -``` -Does your Container require any protocols other than SSH and HTTP? (y/n) → -``` - -If you answer `y`: -``` -Enter the protocol abbreviation (e.g, LDAP for Lightweight Directory Access Protocol). Type "e" to exit → -``` - -**Options:** -- Answer `y` (yes) or `n` (no) -- If yes, enter protocol abbreviations one at a time (e.g., `LDAP`, `FTP`, `SMTP`) -- Type `e` when finished adding protocols -- The system validates each protocol against a master list -- Duplicate protocols are not allowed - -:::note Note -To see a full list of protocols supported by our cluster, see the [Protocol Master List](/docs/intro.md). -::: - - -## 7. Automatic Project Deployment (Optional) - -Choose whether to deploy your project when the container starts: - -``` -Do you want to deploy your project automatically? (y/n) → -``` - -**Options:** -- `y` - Yes, deploy automatically (opens additional configuration options) -- `n` - No, I'll deploy manually later - -:::note Note -If you choose to deploy automatically, see the documentation for doing so [here](/docs/intro.md). -::: - -## 8. Container Creation Process - -After providing all required information, the system will: -1. Transfer your configuration to the hypervisor -2. Begin the container creation process -3. Set up networking, DNS, and reverse proxy -4. Configure the container with your specified settings -5. Deploy your application if requested - -Once the container creation process is complete, your container will be accessible via an ssh command in the form of: - -``` -ssh -p @opensource.mieweb.org -``` - -## 9. Understanding the Output - -Once your container is created, you will receieve an output that looks somthing like this: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -🔔 COPY THESE PORTS DOWN — For External Access -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📌 Note: Your container listens on SSH Port 22 internally, - but EXTERNAL traffic must use the SSH port listed below: -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -✅ Hostname Registration: max-demo-container → 10.15.19.181 -🔐 SSH Port : 2376 -🌐 HTTP Port : 3000 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📦 Container ID : 116 -🌐 Internal IP : 10.15.19.181 -🔗 Domain Name : https://max-demo-container.opensource.mieweb.org -🛠️ SSH Access : ssh -p 2376 demouser@max-demo-container.opensource.mieweb.org -🔑 Container Password : Your proxmox account password -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -NOTE: Additional background scripts are being ran in detached terminal sessions. -Wait up to two minutes for all processes to complete. -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Still not working? Contact Max K. at maxklema@gmail.com -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -:::important Important -Your container password is the same as your Proxmox Account Password. -::: - -The first block will list all of the ports that your container uses. By default, it will display an SSH Port and an HTTP Port. If you added any other special protocols, they will appear there as well. - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -✅ Hostname Registration: max-demo-container → 10.15.19.181 -🔐 SSH Port : 2376 -🌐 HTTP Port : 3000 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -The second block contains network information about your container specifically, including its IP address, public domain name, and ssh command: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📦 Container ID : 116 -🌐 Internal IP : 10.15.19.181 -🔗 Domain Name : https://max-demo-container.opensource.mieweb.org -🛠️ SSH Access : ssh -p 2376 demouser@max-demo-container.opensource.mieweb.org -🔑 Container Password : Your proxmox account password -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -:::note Note -The IP that is given is an **internal IP** allocated by our local DHCP server. It is not public. Additionally, since we are setting up a basic container, nothing will be deployed yet, so navigating to the domain will return a 502 bad gateway error from our nginx server. This is expected. -::: - -:::warning Warning -Save your SSH port number, as well as any port numbers, because you will not be able to see them again. This will be fixed at a later time. -::: - -## 10. Viewing your Container on Proxmox - -To see your container on the Proxmox GUI, navigate to [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006). Once signed in, on the summary view, you should see the name of your container. If you double click on it, you will be able to access details, like the shell, metrics, and other network/filesystem information. - -![Hostname](img/proxmox-lxc.jpg) - -:::note Note -As of writing, you are able to reboot, start, and shutdown your container as you please. However, you must reach out to a cluster admin to delete your container. -::: - ---- - -**Advanced Options**: For multi-component deployments, custom environment variables, or specific service configurations, refer to the [Advanced Container Configuration](/docs/category/creating-advanced-containers) documentation or contact the MIE team. diff --git a/mie-opensource-landing/docs/creating-containers/protocol-list.md b/mie-opensource-landing/docs/creating-containers/protocol-list.md deleted file mode 100644 index 991bdf78..00000000 --- a/mie-opensource-landing/docs/creating-containers/protocol-list.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Protocol List - -Below is a list of all protocols supported by the MIE Proxmox cluster. - -:::note Note -You must specify any additional protocols that you want to use during the container creation process in the command line. If you need to, you can reference that documentation [here](/docs/creating-containers/basic-containers/command-line). -::: - -:::important Important -Protocols in your container should listen on their default port. However, traffic for that protocol coming into our cluster will come in on a randomly-generated port number assigned to you, before being forwarded to your container on the default port. Therefore, traffic for that service using that protocol should be sent on that randomly-generated port assigned to you. -::: - -| Protocol | Default Port | Type | -|----------|------|------| -| TCPM | 1 | tcp | -| RJE | 5 | tcp | -| ECHO | 7 | tcp | -| DISCARD | 9 | tcp | -| DAYTIME | 13 | tcp | -| QOTD | 17 | tcp | -| MSP | 18 | tcp | -| CHARGEN | 19 | tcp | -| FTP | 20 | tcp | -| FTP | 21 | tcp | -| SSH | 22 | tcp | -| TELNET | 23 | tcp | -| SMTP | 25 | tcp | -| TIME | 37 | tcp | -| HNS | 42 | tcp | -| WHOIS | 43 | tcp | -| TACACS | 49 | tcp | -| DNS | 53 | tcp | -| BOOTPS | 67 | udp | -| BOOTPC | 68 | udp | -| TFTP | 69 | udp | -| GOPHER | 70 | tcp | -| FINGER | 79 | tcp | -| HTTP | 80 | tcp | -| KERBEROS | 88 | tcp | -| HNS | 101 | tcp | -| ISO-TSAP | 102 | tcp | -| POP2 | 109 | tcp | -| POP3 | 110 | tcp | -| RPC | 111 | tcp | -| AUTH | 113 | tcp | -| SFTP | 115 | tcp | -| UUCP-PATH | 117 | tcp | -| NNTP | 119 | tcp | -| NTP | 123 | udp | -| EPMAP | 135 | tcp | -| NETBIOS-NS | 137 | tcp | -| NETBIOS-DGM | 138 | udp | -| NETBIOS-SSN | 139 | tcp | -| IMAP | 143 | tcp | -| SQL-SRV | 156 | tcp | -| SNMP | 161 | udp | -| SNMPTRAP | 162 | udp | -| XDMCP | 177 | tcp | -| BGP | 179 | tcp | -| IRC | 194 | tcp | -| LDAP | 389 | tcp | -| NIP | 396 | tcp | -| HTTPS | 443 | tcp | -| SNPP | 444 | tcp | -| SMB | 445 | tcp | -| KPASSWD | 464 | tcp | -| SMTPS | 465 | tcp | -| ISAKMP | 500 | udp | -| EXEC | 512 | tcp | -| LOGIN | 513 | tcp | -| SYSLOG | 514 | udp | -| LPD | 515 | tcp | -| TALK | 517 | udp | -| NTALK | 518 | udp | -| RIP | 520 | udp | -| RIPNG | 521 | udp | -| RPC | 530 | tcp | -| UUCP | 540 | tcp | -| KLOGIN | 543 | tcp | -| KSHELL | 544 | tcp | -| DHCPV6-C | 546 | tcp | -| DHCPV6-S | 547 | tcp | -| AFP | 548 | tcp | -| RTSP | 554 | tcp | -| NNTPS | 563 | tcp | -| SUBMISSION | 587 | tcp | -| IPP | 631 | tcp | -| LDAPS | 636 | tcp | -| LDP | 646 | tcp | -| LINUX-HA | 694 | tcp | -| ISCSI | 860 | tcp | -| RSYNC | 873 | tcp | -| VMWARE | 902 | tcp | -| FTPS-DATA | 989 | tcp | -| FTPS | 990 | tcp | -| TELNETS | 992 | tcp | -| IMAPS | 993 | tcp | -| POP3S | 995 | tcp | -| SOCKS | 1080 | tcp | -| OPENVPN | 1194 | udp | -| OMGR | 1311 | tcp | -| MS-SQL-S | 1433 | tcp | -| MS-SQL-M | 1434 | udp | -| WINS | 1512 | tcp | -| ORACLE-SQL | 1521 | tcp | -| RADIUS | 1645 | tcp | -| RADIUS-ACCT | 1646 | tcp | -| L2TP | 1701 | udp | -| PPTP | 1723 | tcp | -| CISCO-ISL | 1741 | tcp | -| RADIUS | 1812 | udp | -| RADIUS-ACCT | 1813 | udp | -| NFS | 2049 | tcp | -| CPANEL | 2082 | tcp | -| CPANEL-SSL | 2083 | tcp | -| WHM | 2086 | tcp | -| WHM-SSL | 2087 | tcp | -| DA | 2222 | tcp | -| ORACLE-DB | 2483 | tcp | -| ORACLE-DBS | 2484 | tcp | -| XBOX | 3074 | tcp | -| HTTP-PROXY | 3128 | tcp | -| MYSQL | 3306 | tcp | -| RDP | 3389 | tcp | -| NDPS-PA | 3396 | tcp | -| SVN | 3690 | tcp | -| MSQL | 4333 | udp | -| METASPLOIT | 4444 | tcp | -| EMULE | 4662 | tcp | -| EMULE | 4672 | udp | -| RADMIN | 4899 | tcp | -| UPNP | 5000 | tcp | -| YMSG | 5050 | tcp | -| SIP | 5060 | tcp | -| SIP-TLS | 5061 | tcp | -| AIM | 5190 | tcp | -| XMPP-CLIENT | 5222 | tcp | -| XMPP-CLIENTS | 5223 | tcp | -| XMPP-SERVER | 5269 | tcp | -| POSTGRES | 5432 | tcp | -| VNC | 5500 | tcp | -| VNC-HTTP | 5800 | tcp | -| VNC | 5900 | tcp | -| X11 | 6000 | tcp | -| BNET | 6112 | tcp | -| GNUTELLA | 6346 | tcp | -| SANE | 6566 | tcp | -| IRC | 6667 | tcp | -| IRCS | 6697 | tcp | -| BT | 6881 | tcp | -| HTTP-ALT | 8000 | tcp | -| HTTP-ALT | 8008 | tcp | -| HTTP-ALT | 8080 | tcp | -| HTTPS-ALT | 8443 | tcp | -| PDL-DS | 9100 | tcp | -| BACNET | 9101 | tcp | -| WEBMIN | 10000 | udp | -| MONGO | 27017 | tcp | -| TRACEROUTE | 33434 | udp | diff --git a/mie-opensource-landing/docs/developers/_category_.json b/mie-opensource-landing/docs/developers/_category_.json new file mode 100644 index 00000000..3e85382a --- /dev/null +++ b/mie-opensource-landing/docs/developers/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Developers", + "position": 4, + "collapsed": false +} diff --git a/mie-opensource-landing/docs/developers/contributing.md b/mie-opensource-landing/docs/developers/contributing.md new file mode 100644 index 00000000..7bc7df78 --- /dev/null +++ b/mie-opensource-landing/docs/developers/contributing.md @@ -0,0 +1,168 @@ +--- +sidebar_position: 4 +--- + +# Contributing + +We welcome contributions to the MIE Opensource Proxmox Cluster project! This guide will help you get started. + +## Areas for Contribution + +- **Frontend Development**: Improve the web UI, add new features +- **API Development**: Extend REST endpoints, optimize queries +- **Database Optimization**: Improve schema design, add indexes +- **DNS/NGINX Integration**: Enhance service exposure capabilities +- **LDAP Gateway**: Improve authentication mechanisms +- **Documentation**: Expand guides, add examples + +## Getting Started + +1. Review the [GitHub repository](https://github.com/mieweb/opensource-server) +2. Check open issues for contribution opportunities +3. Set up a local development environment using the [Development Workflow](development-workflow) guide +4. Fork the repository and create a feature branch +5. Make your changes and test thoroughly +6. Submit a pull request with a clear description + +## Pull Request Guidelines + +### Before Submitting + +- Ensure all tests pass: `npm test` +- Check for linting errors: `npm run lint` +- Test your changes in a local environment +- Update documentation if needed +- Add tests for new features + +### PR Description + +Include in your pull request: + +- **Summary**: Brief description of what changed and why +- **Related Issues**: Link to any related GitHub issues +- **Testing**: How you tested the changes +- **Screenshots**: If UI changes are involved +- **Breaking Changes**: Note any breaking changes + +### Code Review Process + +1. Submit your pull request +2. Automated tests will run +3. Maintainers will review your code +4. Address any feedback or requested changes +5. Once approved, your PR will be merged + +## Coding Standards + +### General Guidelines + +- Follow existing code style and conventions +- Write clear, descriptive commit messages +- Keep commits focused on a single change +- Add comments for complex logic + +### Commit Messages + +Follow the conventional commits format: + +``` +type(scope): subject + +body (optional) + +footer (optional) +``` + +**Types:** +- `feat`: New feature +- `fix`: Bug fix +- `docs`: Documentation changes +- `refactor`: Code refactoring +- `test`: Test additions or modifications +- `chore`: Maintenance tasks + +**Examples:** +``` +feat(containers): add support for custom CPU limits + +fix(auth): resolve LDAP authentication timeout issue + +docs(admin): add troubleshooting section for node setup +``` + +## Testing Requirements + +### Unit Tests + +- Write tests for new functions and modules +- Maintain or improve code coverage +- Use descriptive test names + +### Integration Tests + +- Test API endpoints end-to-end +- Verify database operations +- Test container creation workflows + +### Manual Testing + +Before submitting: +- Test container creation and deletion +- Verify DNS resolution works correctly +- Check NGINX routing for services +- Ensure LDAP authentication functions +- Test with different database backends (if applicable) + +## Documentation + +### Code Documentation + +- Add JSDoc comments for functions and classes +- Document function parameters and return values +- Explain non-obvious code behavior + +### User Documentation + +If your changes affect users: +- Update relevant documentation pages +- Add examples and screenshots +- Update the changelog + +## Community Guidelines + +### Communication + +- Be respectful and professional +- Ask questions if you're unsure +- Provide constructive feedback +- Help others when you can + +### Issue Reporting + +When reporting issues: +- Use a clear, descriptive title +- Provide steps to reproduce +- Include error messages and logs +- Specify your environment (OS, Node version, etc.) + +## License + +By contributing, you agree that your contributions will be licensed under the same license as the project. + +## Getting Help + +- Check existing documentation and issues first +- Ask questions in GitHub issues or discussions +- Reach out to maintainers for guidance + +## Resources + +- [Development Workflow](development-workflow): Setup and development guide +- [System Architecture](system-architecture): Understand the system design +- [GitHub Repository](https://github.com/mieweb/opensource-server): View code and issues +- [Administrator Documentation](/docs/admins/): Learn about cluster management +- [User Documentation](/docs/users/creating-containers/web-gui): Understand user workflows + +--- + +Thank you for contributing to the MIE Opensource Proxmox Cluster project! diff --git a/mie-opensource-landing/docs/developers/core-technologies.md b/mie-opensource-landing/docs/developers/core-technologies.md new file mode 100644 index 00000000..6746b45a --- /dev/null +++ b/mie-opensource-landing/docs/developers/core-technologies.md @@ -0,0 +1,153 @@ +--- +sidebar_position: 5 +--- + +# Core Technologies + +The MIE Opensource Proxmox Cluster is built on several key open-source technologies. This page provides links to external documentation for the core components. + +## Backend Framework + +### Express.js + +**Express** is a minimal and flexible Node.js web application framework that provides the foundation for our API server. + +- **Official Documentation**: [expressjs.com](https://expressjs.com/) +- **Getting Started**: [Express Guide](https://expressjs.com/en/guide/routing.html) +- **API Reference**: [Express API](https://expressjs.com/en/4x/api.html) + +**Used For:** +- REST API endpoints +- Request routing and middleware +- Session management +- Server-side rendering + +### Sequelize ORM + +**Sequelize** is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite, and more. + +- **Official Documentation**: [sequelize.org](https://sequelize.org/) +- **Models Guide**: [Sequelize Models](https://sequelize.org/docs/v6/core-concepts/model-basics/) +- **Migrations**: [Sequelize Migrations](https://sequelize.org/docs/v6/other-topics/migrations/) +- **Querying**: [Sequelize Querying](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/) + +**Used For:** +- Database abstraction layer +- Schema migrations +- Model definitions +- Query building + +## Frontend Templating + +### EJS (Embedded JavaScript) + +**EJS** is a simple templating language that lets you generate HTML markup with plain JavaScript. + +- **Official Documentation**: [ejs.co](https://ejs.co/) +- **Syntax Reference**: [EJS Tags](https://ejs.co/#docs) +- **GitHub Repository**: [github.com/mde/ejs](https://github.com/mde/ejs) + +**Used For:** +- Server-side rendering of HTML pages +- Dynamic content generation +- User interface templates +- Admin panel views + +## Infrastructure + +### Proxmox VE API + +**Proxmox Virtual Environment** provides a RESTful API for managing virtual machines and containers. + +- **API Documentation**: [pve.proxmox.com/pve-docs/api-viewer](https://pve.proxmox.com/pve-docs/api-viewer/) +- **API Guide**: [Proxmox VE API](https://pve.proxmox.com/wiki/Proxmox_VE_API) +- **Authentication**: [API Tokens](https://pve.proxmox.com/wiki/User_Management#pveum_tokens) + +**Used For:** +- Container (LXC) creation and management +- Node information retrieval +- Resource allocation +- Cluster status monitoring + +### LDAP Gateway + +**LDAPServer** is a custom Node.js-based LDAP server that integrates with our database for authentication. + +- **GitHub Repository**: [github.com/mieweb/LDAPServer](https://github.com/mieweb/LDAPServer) +- **SSSD Documentation**: [sssd.io/docs](https://sssd.io/docs/) + +**Used For:** +- Centralized authentication for all containers +- User credential management +- Group membership resolution +- PAM/NSS integration via SSSD + +## Supporting Libraries + +### DNSMasq + +**DNSMasq** provides network infrastructure services including DHCP and DNS. + +- **Official Documentation**: [thekelleys.org.uk/dnsmasq/doc.html](http://www.thekelleys.org.uk/dnsmasq/doc.html) +- **Man Page**: [dnsmasq(8)](https://linux.die.net/man/8/dnsmasq) + +**Used For:** +- DHCP server for container IP assignment +- DNS resolution for internal domain names +- DNS forwarding for external queries + +### NGINX + +**NGINX** is a high-performance HTTP server and reverse proxy. + +- **Official Documentation**: [nginx.org/en/docs](https://nginx.org/en/docs/) +- **Reverse Proxy Guide**: [NGINX Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) +- **SSL/TLS**: [NGINX SSL Configuration](https://nginx.org/en/docs/http/configuring_https_servers.html) + +**Used For:** +- HTTP/HTTPS reverse proxy +- TLS termination +- Layer 4 TCP proxying +- Load balancing + +## Development Tools + +### Node.js + +**Node.js** is the JavaScript runtime that powers the entire application stack. + +- **Official Documentation**: [nodejs.org/docs](https://nodejs.org/docs/) +- **API Reference**: [Node.js API](https://nodejs.org/api/) +- **Recommended Version**: 18+ LTS + +### npm + +**npm** is the package manager for Node.js. + +- **Official Documentation**: [docs.npmjs.com](https://docs.npmjs.com/) +- **CLI Commands**: [npm CLI](https://docs.npmjs.com/cli/v10/commands) + +## Related Resources + +- [System Architecture](system-architecture): Understand how these technologies work together +- [Development Workflow](development-workflow): Set up your development environment +- [Contributing](contributing): Contribute to the project +- [GitHub Repository](https://github.com/mieweb/opensource-server): View the source code + +## Version Requirements + +| Technology | Minimum Version | Recommended | +|------------|----------------|-------------| +| Node.js | 18.x | 20.x LTS | +| Proxmox VE | 13.0 | Latest stable | +| PostgreSQL | 12.x | 15.x+ | +| MySQL | 8.0 | 8.0+ | +| NGINX | 1.18 | Latest stable | + +## Additional Documentation + +For implementation-specific details, refer to: +- Code comments in the repository +- README files in individual directories +- Migration files for database schema changes +- Environment variable documentation in `.env.example` diff --git a/mie-opensource-landing/docs/developers/database-schema.md b/mie-opensource-landing/docs/developers/database-schema.md new file mode 100644 index 00000000..4e0d931b --- /dev/null +++ b/mie-opensource-landing/docs/developers/database-schema.md @@ -0,0 +1,404 @@ +--- +sidebar_position: 6 +--- + +# Database Schema + +The cluster management system uses a relational database to store all configuration, state, and user information. This document describes the database schema and relationships between tables. + +## Entity Relationship Diagram + +```mermaid +erDiagram + Sites ||--o{ Nodes : contains + Sites ||--o{ ExternalDomains : has + Nodes ||--o{ Containers : hosts + Containers ||--o{ Services : exposes + Services ||--|| HTTPServices : "type: http" + Services ||--|| TransportServices : "type: transport" + Services ||--|| DnsServices : "type: dns" + ExternalDomains ||--o{ HTTPServices : "used by" + Jobs ||--o{ JobStatuses : tracks + Users }o--o{ Groups : "member of" + UserGroups }|--|| Users : joins + UserGroups }|--|| Groups : joins + + Sites { + int id PK + string name + string internalDomain + string dhcpRange + string subnetMask + string gateway + string dnsForwarders + } + + Nodes { + int id PK + string name UK + string ipv4Address + string apiUrl + string apiTokenIdOrUsername + string apiTokenSecretOrPassword + boolean disableTlsVerification + int siteId FK + } + + Containers { + int id PK + string hostname UK + string name + string description + int nodeId FK + int containerId + string macAddress UK + string ipv4Address UK + string status + } + + Services { + int id PK + int containerId FK + enum type "http,transport,dns" + int containerPort + } + + HTTPServices { + int id PK + int serviceId FK,UK + string externalHostname + int externalDomainId FK + } + + TransportServices { + int id PK + int serviceId FK,UK + enum protocol "tcp,udp" + int externalPort UK + boolean useTls + } + + DnsServices { + int id PK + int serviceId FK,UK + enum recordType "SRV" + string serviceName + } + + ExternalDomains { + int id PK + string domain + string acmeEmail + string acmeDirectory + string cloudflareApiEmail + string cloudflareApiKey + int siteId FK + } + + Jobs { + int id PK + string name + string associatedResource + enum status "pending,running,success,failure,cancelled" + } + + JobStatuses { + int id PK + int jobId FK + text message + } + + Users { + int uidNumber PK + string username UK + string cn "Common Name" + string sn "Surname" + string givenName + string mail UK + text sshPublicKey + string userPassword + string status "pending,active,suspended" + } + + Groups { + int gidNumber PK + string cn UK "Group Name" + boolean isAdministrator + } + + UserGroups { + int uidNumber PK,FK + int gidNumber PK,FK + } + + SessionSecrets { + int id PK + string secret UK + } +``` + +## Core Models + +### Site + +The **Site** model represents a top-level organizational unit, typically corresponding to a physical or logical Proxmox cluster location. + +**Key Fields:** +- `name`: Display name for the site +- `internalDomain`: Internal DNS domain (e.g., `cluster.internal`) +- `dhcpRange`: IP range for container assignment (e.g., `192.168.1.100-192.168.1.200`) +- `subnetMask`: Network subnet mask +- `gateway`: Default gateway IP +- `dnsForwarders`: Upstream DNS servers (comma-separated) + +**Relationships:** +- Has many Nodes +- Has many ExternalDomains + +### Node + +The **Node** model represents a Proxmox VE server within a site. + +**Key Fields:** +- `name`: Node name (must match Proxmox hostname) +- `ipv4Address`: Node's IP address for DNS +- `apiUrl`: Proxmox API endpoint +- `apiTokenIdOrUsername`: Authentication credential (username or token ID) +- `apiTokenSecretOrPassword`: Authentication secret +- `disableTlsVerification`: Skip TLS certificate validation + +**Relationships:** +- Belongs to Site +- Has many Containers + +**Constraints:** +- `name` is unique across all nodes + +### Container + +The **Container** model represents an LXC container running on a Proxmox node. + +**Key Fields:** +- `hostname`: Container hostname +- `name`: Display name +- `containerId`: Proxmox container ID (CTID) +- `macAddress`: Unique MAC address +- `ipv4Address`: Assigned IP address +- `status`: Container state (e.g., 'running', 'stopped') + +**Relationships:** +- Belongs to Node +- Has many Services + +**Constraints:** +- Unique composite index on `(nodeId, containerId)` +- `hostname`, `macAddress`, and `ipv4Address` are globally unique + +### Service (Base Model) + +The **Service** model uses Single Table Inheritance (STI) to represent different types of services exposed by containers. + +**Key Fields:** +- `containerId`: Container exposing this service +- `type`: Service type ('http', 'transport', or 'dns') +- `containerPort`: Port number inside the container + +**Relationships:** +- Belongs to Container +- Has one HTTPService, TransportService, or DnsService (based on type) + +### HTTPService + +Represents HTTP/HTTPS services with automatic SSL certificate management. + +**Key Fields:** +- `externalHostname`: Subdomain for the service (e.g., 'app' for 'app.example.com') +- `externalDomainId`: External domain to use + +**Relationships:** +- Belongs to Service (one-to-one) +- Belongs to ExternalDomain + +**Constraints:** +- Unique composite index on `(externalHostname, externalDomainId)` + +### TransportService + +Represents TCP/UDP services exposed via port mapping. + +**Key Fields:** +- `protocol`: 'tcp' or 'udp' +- `externalPort`: Public port number +- `useTls`: Whether to use TLS for TCP connections + +**Relationships:** +- Belongs to Service (one-to-one) + +**Constraints:** +- Unique composite index on `(protocol, externalPort)` + +**Static Methods:** +- `findNextAvailablePort()`: Finds the next available external port + +### DnsService + +Represents services registered in DNS (typically SRV records). + +**Key Fields:** +- `recordType`: DNS record type (currently only 'SRV' supported) +- `serviceName`: Service name for DNS record + +**Relationships:** +- Belongs to Service (one-to-one) + +### ExternalDomain + +The **ExternalDomain** model manages public domains for HTTP service exposure. + +**Key Fields:** +- `domain`: Domain name (e.g., 'example.com') +- `acmeEmail`: Email for certificate notifications +- `acmeDirectory`: ACME CA endpoint URL +- `cloudflareApiEmail`: Cloudflare account email +- `cloudflareApiKey`: Cloudflare API key for DNS challenges + +**Relationships:** +- Belongs to Site +- Has many HTTPServices + +## User Management Models + +### User + +The **User** model stores user accounts with LDAP-compatible attributes. + +**Key Fields:** +- `uidNumber`: Unique user ID (starting at 2000) +- `username`: Login username +- `cn`: Common name (full name) +- `sn`: Surname (last name) +- `givenName`: First name +- `mail`: Email address +- `sshPublicKey`: SSH public key for container access +- `userPassword`: Hashed password (argon2) +- `status`: Account status ('pending', 'active', 'suspended') + +**Relationships:** +- Belongs to many Groups (through UserGroups) + +**Security:** +- Passwords are hashed with argon2 before storage +- Only 'active' users can authenticate +- First registered user is automatically added to 'sysadmins' group + +**Static Methods:** +- `getNextUid()`: Returns next available UID starting at 2000 + +**Instance Methods:** +- `validatePassword(password)`: Verifies password against hash + +### Group + +The **Group** model represents user groups with LDAP-compatible attributes. + +**Key Fields:** +- `gidNumber`: Unique group ID +- `cn`: Group name (common name) +- `isAdministrator`: Whether group members have admin privileges + +**Relationships:** +- Has many Users (through UserGroups) + +**Default Groups:** +- `ldapusers` (gid: 2000): Standard container access +- `sysadmins` (gid: 2001): Full cluster administration + +### UserGroup + +The **UserGroup** model is a join table for the many-to-many User-Group relationship. + +**Key Fields:** +- `uidNumber`: Foreign key to Users +- `gidNumber`: Foreign key to Groups + +**Constraints:** +- Composite primary key on `(uidNumber, gidNumber)` + +## Job Management Models + +### Job + +The **Job** model tracks asynchronous operations. + +**Key Fields:** +- `name`: Job description +- `associatedResource`: Reference to related resource +- `status`: Job state ('pending', 'running', 'success', 'failure', 'cancelled') + +**Relationships:** +- Has many JobStatuses + +### JobStatus + +The **JobStatus** model stores job execution history and progress messages. + +**Key Fields:** +- `jobId`: Foreign key to Jobs +- `message`: Status update message + +**Relationships:** +- Belongs to Job + +## Session Management + +### SessionSecret + +The **SessionSecret** model stores express-session secrets. + +**Key Fields:** +- `secret`: 32-64 character secret string + +**Constraints:** +- `secret` is unique + +## Database Abstraction + +The schema is implemented using **Sequelize ORM**, providing: + +- **Database Portability**: Supports SQLite (default), PostgreSQL, and MySQL +- **Migrations**: Schema versioning and updates via `sequelize-cli` +- **Validation**: Field-level validation rules +- **Hooks**: Automatic password hashing, UID/GID assignment +- **Associations**: Declarative relationship definitions + +## Key Design Patterns + +### Single Table Inheritance (STI) + +The Service model uses STI to handle different service types: +- Base `Services` table with `type` discriminator +- Child tables (`HTTPServices`, `TransportServices`, `DnsServices`) extend via one-to-one relationships +- Allows polymorphic service handling while maintaining type-specific fields + +### LDAP Schema Compatibility + +User and Group models follow LDAP naming conventions: +- `uidNumber` / `gidNumber` for numeric IDs +- `cn` (common name) for names +- `sn` (surname), `givenName` for user names +- Enables seamless integration with LDAP authentication + +### Hierarchical Organization + +Resources are organized hierarchically: +``` +Site → Nodes → Containers → Services +``` + +This mirrors the physical infrastructure topology and simplifies queries. + +## Next Steps + +- [System Architecture](system-architecture): Understand how the database integrates with other components +- [Development Workflow](development-workflow): Learn how to create migrations +- [Core Technologies](core-technologies): Sequelize ORM documentation diff --git a/mie-opensource-landing/docs/developers/development-workflow.md b/mie-opensource-landing/docs/developers/development-workflow.md new file mode 100644 index 00000000..4ce050a4 --- /dev/null +++ b/mie-opensource-landing/docs/developers/development-workflow.md @@ -0,0 +1,140 @@ +--- +sidebar_position: 3 +--- + +# Development Workflow + +This guide covers setting up a local development environment and contributing to the cluster management software. + +## Prerequisites + +To contribute to the cluster management software: + +1. **Node.js**: Version 18+ for the API server and LDAP gateway +2. **Database**: SQLite (included), PostgreSQL, or MySQL +3. **Proxmox Access**: A Proxmox VE 13+ instance for testing +4. **Git**: For version control and contributions + +## Local Development Setup + +```bash +# Clone the repository +git clone https://github.com/mieweb/opensource-server +cd opensource-server/create-a-container + +# Install dependencies +npm install + +# Configure environment +cp example.env .env +# Edit .env with your Proxmox and database settings + +# Run database migrations +npx sequelize-cli db:migrate + +# Start the development server +npm run dev +``` + +## Architecture Overview + +**Frontend:** +- EJS-based server-rendered UI for user and admin interfaces +- Rendered by the Express API server + +**Backend API:** +- Express.js REST API server +- Sequelize ORM for database abstraction +- Routes for user, admin, and container management + +**LDAP Server:** +- Standalone Node.js process +- Reads from the shared database +- Handles LDAP bind and search operations + +## Key Directories + +``` +create-a-container/ +├── models/ # Sequelize database models +├── routers/ # Express API route handlers +├── middlewares/ # Authentication & authorization +├── migrations/ # Database schema migrations +├── views/ # Server-rendered templates +└── public/ # Static assets +``` + +## Development Best Practices + +### Code Style + +- Follow the existing code style and conventions +- Use meaningful variable and function names +- Add comments for complex logic +- Keep functions small and focused + +### Database Changes + +- Always create migrations for schema changes +- Test migrations with both up and down +- Use transactions for multi-step migrations +- Document breaking changes + +### API Development + +- Follow RESTful conventions +- Validate input data before processing +- Return appropriate HTTP status codes +- Document new endpoints + +### Testing + +Before submitting changes: + +- Test container creation and deletion +- Verify DNS resolution and NGINX routing +- Ensure LDAP authentication works correctly +- Run the test suite: `npm test` +- Check for linting errors: `npm run lint` + +## Debugging + +### API Server + +```bash +# Run with debugging output +DEBUG=* npm run dev + +# Or use Node inspector +node --inspect index.js +``` + +### Database Queries + +Enable Sequelize query logging in your environment: + +``` +DB_LOGGING=true +``` + +### Common Issues + +**Port Already in Use:** +- Check for existing processes: `lsof -i :3000` +- Kill the process or use a different port + +**Database Connection Errors:** +- Verify database credentials in `.env` +- Ensure database service is running +- Check network connectivity + +**Proxmox API Errors:** +- Verify API credentials are correct +- Check TLS certificate settings +- Ensure Proxmox node is reachable + +## Next Steps + +- Review the [Contributing Guide](contributing) for submission guidelines +- Check the [System Architecture](system-architecture) to understand component interactions +- Visit the [GitHub repository](https://github.com/mieweb/opensource-server) for open issues diff --git a/mie-opensource-landing/docs/developers/system-architecture.md b/mie-opensource-landing/docs/developers/system-architecture.md new file mode 100644 index 00000000..09c7a5d5 --- /dev/null +++ b/mie-opensource-landing/docs/developers/system-architecture.md @@ -0,0 +1,225 @@ +--- +sidebar_position: 2 +--- + +# System Architecture + +The MIE Opensource Proxmox Cluster is built on a carefully integrated stack of open-source technologies that work together to provide automated container hosting and management. + +## System Architecture + +```mermaid +graph TB + subgraph "Management Layer" + WebUI[Web UI
EJS Templates] + API[Node.js API Server] + DB[(Database
SQLite/Postgres/MySQL)] + LDAP[LDAP Gateway
NodeJS] + end + + subgraph "Network Services" + DNS[DNSMasq
DHCP + DNS] + NGINX[NGINX
Reverse Proxy] + end + + subgraph PVE[Proxmox Cluster] + LXC[LXC Container] + end + + WebUI --> API + API --> DB + API --> PVE + API --> DNS + API --> NGINX + LDAP --> DB + LXC -.-> LDAP + DNS --> LXC + NGINX --> LXC + + classDef management fill:#e1f5ff,stroke:#01579b + classDef network fill:#f3e5f5,stroke:#4a148c + classDef compute fill:#e8f5e9,stroke:#1b5e20 + + class WebUI,API,DB,LDAP management + class DNS,NGINX network + class LXC compute +``` + +## Core Components + +### Proxmox VE 13+ + +**Proxmox Virtual Environment** serves as the hypervisor layer, providing virtualization capabilities through KVM and LXC. Version 13 or higher is required for OCI image support. + +**Key Features:** +- LXC (Linux Containers) management for lightweight compute nodes +- API-driven automation for container lifecycle management +- Web interface for manual container administration +- Clustering support for high availability + +**Integration:** +- The management API communicates with Proxmox via REST API +- [Nodes](/docs/admins/nodes) are registered Proxmox servers in the cluster +- [Containers](/docs/admins/containers) are LXC instances managed by Proxmox + +### DNSMasq + +**DNSMasq** provides both DHCP and DNS services for the cluster network. + +**DHCP Functionality:** +- Automatically assigns IP addresses to new containers from the configured range +- Containers and [nodes](/docs/admins/nodes) reserve their assigned IPs for stability +- IP reservations persist across container restarts and lifecycle events + +**DNS Functionality:** +- Provides name resolution for containers within the cluster +- Internal domain structure: `container-name.cluster.internal` +- Forwards external DNS queries to configured upstream servers + +**Integration:** +- Management API updates DNSMasq configuration when containers are created/destroyed +- IP assignments are tracked in the backend database +- DNS records are automatically created for all cluster resources + +### NGINX + +**NGINX** handles all ingress traffic to containers, supporting both HTTP/HTTPS and TCP protocols. + +**Layer 7 HTTP Proxying:** +- Terminates TLS for HTTPS traffic +- Routes requests based on hostname/subdomain +- Automatically obtains and renews SSL certificates for [external domains](/docs/admins/external-domains) +- Supports multiple domains and subdomains per container + +**Layer 4 TCP Proxying:** +- Proxies non-HTTP protocols (SSH, databases, custom services) +- Port mapping from external ports to container services +- Transparent connection handling + +**Integration:** +- Configuration is automatically generated based on container services +- Certificate management integrated with ACME providers (Let's Encrypt) +- Dynamic backend resolution using DNSMasq for container IPs + +### LDAP Gateway + +The **LDAP Gateway** is a Node.js-based LDAP server that provides centralized authentication for all cluster services. + +**Repository:** [github.com/mieweb/LDAPServer](https://github.com/mieweb/LDAPServer) + +**Functionality:** +- Serves LDAP authentication requests from containers +- Retrieves user and group data from the backend database +- Provides unified login credentials across all cluster resources +- Integrates with standard PAM/NSS on Linux containers + +**User Management:** +- Users authenticate with cluster-wide credentials +- Group memberships determine access permissions +- Password changes propagate immediately to all services + +**Integration:** +- Containers configure PAM to authenticate against the LDAP server +- All users in the `ldapusers` group can SSH into containers +- User data synchronized from the backend database + +### Backend Database + +The **backend database** stores all cluster state and configuration. + +**Supported Databases:** +- **SQLite** (default): Simple file-based database, no additional setup required +- **PostgreSQL**: Production-grade relational database for larger deployments +- **MySQL**: Alternative production database option + +**ORM Abstraction:** +- Uses Sequelize ORM for database abstraction +- Allows switching between database backends without code changes +- Handles migrations for schema updates + +**Stored Data:** +- User accounts and authentication credentials +- Group definitions and memberships +- Site configurations (network settings, domains) +- Node registrations (Proxmox API endpoints) +- Container metadata (IPs, ports, services) +- Service exposure rules and SSL certificate info + +## Data Flow + +### Container Creation + +```mermaid +sequenceDiagram + participant User + participant API + participant Proxmox + participant LXC + participant DNSMasq + participant DB + participant NGINX + + User->>API: Create Container Request + API->>Proxmox: Create LXC via API + Proxmox->>LXC: Create + LXC->>DNSMasq: Retrieve IP via DHCP + DNSMasq-->>LXC: IP assigned + API->>DNSMasq: Retrieve IP for new LXC + DNSMasq-->>API: LXC IP address + API->>DB: Store LXC + IP information + API-->>User: Container ready + NGINX->>API: Retrieve updated config + API-->>NGINX: Updated routing config +``` + +### User Authentication + +```mermaid +sequenceDiagram + participant User + participant Container + participant LDAP + participant DB + + User->>Container: SSH login attempt + Container->>LDAP: LDAP bind request + LDAP->>DB: Verify credentials + DB-->>LDAP: User authenticated + LDAP-->>Container: Authentication success + Container-->>User: Login granted +``` + +### HTTP Service Exposure + +```mermaid +sequenceDiagram + participant Client + participant NGINX + participant ACME + participant DNSMasq + participant Container + + Note over NGINX: Initial setup + NGINX->>ACME: Request certificate + ACME-->>NGINX: Certificate issued + + Note over Client: User request + Client->>NGINX: HTTPS request (app.example.com) + NGINX->>DNSMasq: Resolve container IP + DNSMasq-->>NGINX: Container IP address + NGINX->>Container: Forward request + Container-->>NGINX: Response + NGINX-->>Client: HTTPS response +``` + +## Next Steps + +For more information: + +- [Development Workflow](development-workflow): Set up your development environment +- [Contributing](contributing): Learn how to contribute to the project +- [Administrator Documentation](/docs/admins/): Configure and manage the cluster +- [User Documentation](/docs/users/creating-containers/web-gui): Create and deploy containers +- [GitHub Repository](https://github.com/mieweb/opensource-server): Source code and issues +- [GitHub Repository](https://github.com/mieweb/opensource-server): Source code and issues + diff --git a/mie-opensource-landing/docs/intro.md b/mie-opensource-landing/docs/intro.md deleted file mode 100644 index 22351080..00000000 --- a/mie-opensource-landing/docs/intro.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Welcome to MIE Opensource Proxmox Cluster - -Welcome to the documentation for the **Opensource Proxmox Cluster** at MIE (Medical Informatics Engineering). This platform provides developers and researchers with access to virtualized infrastructure for building, testing, and deploying applications in a collaborative opensource environment. - -## 🚀 Quick Start - -To begin using the MIE Opensource Proxmox Cluster, you'll need: - -### Prerequisites - -- **Valid Proxmox Account**: You must have an active PVE account at [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006) -- Basic understanding of virtualization concepts -- SSH client for remote access to containers - -:::tip Access Required -If you don't have an account yet, please contact the MIE team to request access to the opensource Proxmox cluster. -::: - -:::important Important -When logging into [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006), make sure you are logging in with the PVE Realm. -::: - -## What You Can Do - -Our documentation covers everything you need to work with the cluster: - -### New to Proxmox? -**[Introduction to Proxmox →](/docs/proxmox-introduction)** - -Learn the fundamentals of Proxmox Virtual Environment (VE), understand the interface, and discover how virtualization works in our cluster environment. - -### Ready to Build? -**[Create Your First Container →](/docs/creating-containers/basic-containers/command-line)** - -Step-by-step guide to creating and configuring your own Linux container (LXC) from scratch. Perfect for hosting applications, development environments, or testing new software. - -### Want to Deploy Applications Automatically? -**[Advanced Container Deployment →](/docs/creating-containers/advanced-containers/deploying-containers-overview)** - -Learn how to automatically deploy your applications during container creation, with support for single and multi-component applications. - -### Automate Your Deployments with GitHub -**[Proxmox Launchpad Integration →](/docs/proxmox-launchpad/what-is-proxmox-launchpad)** - -Connect your GitHub repositories to automatically deploy your projects to the cluster using our custom GitHub Actions workflow. Set up CI/CD pipelines that build and deploy directly to your Proxmox containers. - -### Develop with VSCode -**[VSCode Remote Development →](/docs/vscode-setup)** - -Connect VSCode directly to your containers for seamless remote development with full IDE capabilities. - -## Key Features - -- **Free Opensource Infrastructure**: Access to enterprise-grade virtualization at no cost -- **Flexible Container Support**: Run both lightweight and resource-intensive containers (LXC) -- **Automated Deployments**: Integrate with GitHub Actions for seamless CI/CD -- **Collaborative Environment**: Share resources and collaborate with other developers -- **Scalable Resources**: CPU, memory, and storage will be allocated based on your project needs - -## Getting Access - -1. **Login to Proxmox**: Navigate to [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006) -2. **Use your credentials**: Login with your provided username and password and **select the PVE Realm**. -3. **Explore the interface**: Familiarize yourself with the Proxmox web interface -4. **Start building**: Create your first container - -## Documentation Structure - -This documentation is organized into several sections: - -- **Introduction to Proxmox**: Learn the fundamentals of Proxmox and how our cluster works -- **Creating Containers**: Essential guides for creating basic and advanced containers -- **Proxmox Launchpad**: GitHub Actions integration for automated deployments -- **Monitoring & Development**: Tools for managing and developing in your containers - -## Need Help? - -- Review the [Protocol List](/docs/creating-containers/protocol-list) for supported network protocols -- Check the troubleshooting sections in each guide for common issues -- Contact the MIE team for account or access-related questions - ---- - -Ready to get started? Choose your path above and begin building on the MIE Opensource Proxmox Cluster! diff --git a/mie-opensource-landing/docs/intro.mdx b/mie-opensource-landing/docs/intro.mdx new file mode 100644 index 00000000..2c2eb11a --- /dev/null +++ b/mie-opensource-landing/docs/intro.mdx @@ -0,0 +1,59 @@ +--- +sidebar_position: 1 +--- + +import { ProxmoxUrl } from '@site/src/components/InstanceUrl'; + +# Introduction + +Welcome to the documentation for the **Opensource Proxmox Cluster** at MIE (Medical Informatics Engineering). This platform provides access to virtualized infrastructure for building, testing, and deploying applications in a collaborative opensource environment. + +## Key Features + +- **Free Opensource Infrastructure**: Access to enterprise-grade virtualization at no cost +- **Flexible Container Support**: Run both lightweight and resource-intensive containers (LXC) +- **Automated Deployments**: Integrate with GitHub Actions for seamless CI/CD +- **Collaborative Environment**: Share resources and collaborate with others +- **Scalable Resources**: CPU, memory, and storage allocated based on project needs + +## 🎯 Find Your Path + +This documentation is organized to help you quickly find what you need: + +### I want to deploy a new service to the cluster + +Start here: **[Using the Web GUI →](/docs/users/creating-containers/web-gui)** + +You'll learn how to: +- Create and manage Linux containers (LXC) +- Expose services through our network +- Deploy applications automatically with GitHub integration +- Develop remotely using VSCode + +**Prerequisites:** +- Valid Proxmox account with PVE Realm access at +- Basic understanding of virtualization concepts + +### I'm managing or installing a cluster + +Start here: **[Admin Documentation →](/docs/admins/)** + +You'll find information about: +- Cluster installation and configuration +- User management and access control +- Infrastructure maintenance +- System monitoring and troubleshooting + +:::note Coming Soon +Admin documentation is currently being developed. Check back soon for comprehensive guides on cluster management. +::: + +### I'm interested in contributing to the project + +Start here: **[System Architecture →](/docs/developers/system-architecture)** + +You'll learn about: +- Cluster architecture and infrastructure +- How the automation systems work +- Contributing to the codebase +- Development workflows and best practices diff --git a/mie-opensource-landing/docs/proxmox-introduction/_category_.json b/mie-opensource-landing/docs/proxmox-introduction/_category_.json deleted file mode 100644 index 8d1d005c..00000000 --- a/mie-opensource-landing/docs/proxmox-introduction/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Introduction to Proxmox", - "position": 2, - "link": { - "type": "generated-index", - "description": "Learn the basics of Proxmox, a powerful open-source virtualization platform." - } -} diff --git a/mie-opensource-landing/docs/proxmox-introduction/how-our-cluster-works.md b/mie-opensource-landing/docs/proxmox-introduction/how-our-cluster-works.md deleted file mode 100644 index 71d60267..00000000 --- a/mie-opensource-landing/docs/proxmox-introduction/how-our-cluster-works.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -sidebar_position: 2 ---- - -# How MIE's Proxmox Cluster Works - -MIE's Opensource Proxmox Cluster is a robust, automated container hosting environment designed for developers and researchers. It leverages open-source technologies to provide scalable, secure, and efficient infrastructure for deploying applications. - -![MIE Cluster Architecture Overview](./img/proxmox-cluster-infrastructure.jpg) - -:::note Note -In this diagram, the gateway represents our PVE1 hypervisor machine. This serves as the gateway between the internal subnet of the cluster (10.15.0.0/16) and external traffic. -::: - -## Cluster Architecture & Hypervisors - -Our cluster consists of **two Proxmox hypervisors**: -- **PVE1** -- **PVE2** - -Each of these machines are Dell PowerEdges, each with 500 GiB of RAM and 72 Core CPUs. - -We use a simple load balancing strategy: **odd-numbered containers are deployed to PVE1, and even-numbered containers are deployed to PVE2**. This ensures balanced resource usage and high availability across the cluster. - -## Core Services & Workflow - -- **Dnsmasq Service**: Manages DHCP and DNS, providing automatic subdomain routing for containers via wildcard DNS entries. -- **NGINX Reverse Proxy**: Dynamically resolves backend IPs and ports for each container using a registry file, and manages SSL certificates for secure access. -- **Gateway**: Handles network routing, access control, and daily cleanup scripts for cluster maintenance. -- **LDAP Authentication**: Centralized LDAP server manages user authentication for all containers, integrating with Proxmox VE user management and optional 2FA. -- **Container Creation**: Automated scripts handle the full lifecycle of LXC containers, including creation, configuration, and registration with the proxy and DNS infrastructure. -- **CI/CD Automation**: Helper scripts and workflows manage container updates, existence checks, and cleanup operations for efficient hosting. -- **Proxmox LaunchPad**: GitHub Action that automates container deployment, service installation, and application startup directly from repository pushes. -- **Wazuh Security**: All containers and hypervisors run Wazuh agents, sending logs to a centralized manager for threat detection and active response. - -## How It Works - -1. **User Access**: Users access their containers via subdomains routed by DNS and NGINX. -2. **Container Lifecycle**: - - Containers are created via web GUI, CLI, or GitHub Action - - DHCP assigns IP, ports are mapped, and NGINX updates its registry - - LDAP authenticates users for secure access - - Wazuh agents monitor security events -3. **Automated Deployment**: - - Push to GitHub triggers Proxmox LaunchPad - - Containers are provisioned, dependencies installed, and services started - - DNS and proxy are updated for seamless access -4. **Security & Monitoring**: - - Wazuh provides real-time threat detection and response - - Metrics for CPU, RAM, Swap, and SSD usage are monitored for each container - -## Key Features - -- **Automated DNS & Proxy**: Instant subdomain and port mapping for new containers -- **Centralized Authentication**: LDAP integration for secure, unified access -- **CI/CD Integration**: GitHub Actions for automated deployment and updates -- **Security Monitoring**: Wazuh agents for vulnerability detection and active response -- **Load Balanced Hypervisors**: Odd containers on PVE1, even containers on PVE2 - -## Getting Started - -- Create containers via the web GUI, CLI, or GitHub Action -- Monitor and manage your containers through the Proxmox web interface -- Integrate your projects with Proxmox LaunchPad for automated deployments -- Review container metrics and security events in the dashboard - ---- - -For more details, see our [GitHub repository](https://github.com/mieweb/opensource-server) and explore the documentation for step-by-step guides! - diff --git a/mie-opensource-landing/docs/proxmox-introduction/img/proxmox-cluster-infrastructure.jpg b/mie-opensource-landing/docs/proxmox-introduction/img/proxmox-cluster-infrastructure.jpg deleted file mode 100644 index 326f9358..00000000 Binary files a/mie-opensource-landing/docs/proxmox-introduction/img/proxmox-cluster-infrastructure.jpg and /dev/null differ diff --git a/mie-opensource-landing/docs/proxmox-introduction/proxmox-introduction.md b/mie-opensource-landing/docs/proxmox-introduction/proxmox-introduction.md deleted file mode 100644 index a97679a4..00000000 --- a/mie-opensource-landing/docs/proxmox-introduction/proxmox-introduction.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -sidebar_position: 1 ---- - - -# Proxmox Introduction - -:::note Note -This section provides a high-level overview of how Proxmox works. The next section, **[How MIE's Proxmox Cluster Works](/docs/proxmox-introduction/how-our-cluster-works.md)**, explains how we set up our Proxmox cluster specifically. -::: - -Proxmox Virtual Environment (Proxmox VE) is an open-source platform for managing virtual machines (VMs) and containers. It is widely used for building scalable, secure, and flexible infrastructure in both enterprise and research environments. - -## What is Proxmox? -Proxmox VE is a **Type 1 hypervisor**, meaning it runs directly on the hardware (bare metal) and manages virtualized resources without needing a host operating system. This provides high performance, security, and resource isolation. - -## Containers vs. Virtual Machines -- **Virtual Machines (VMs):** Full virtualization, each VM runs its own operating system and kernel. Suitable for running different OS types or legacy applications. -- **Containers (LXC):** Lightweight virtualization, containers share the host kernel but are isolated from each other. Ideal for running multiple Linux environments efficiently. - -:::note Note -In our cluster, we focus on creating and managing **containers** for resource efficiency and simplicity. -::: - -## Filesystem & Volumes -- **Filesystem:** Each container is provisioned with its own root filesystem (rootfs), isolated from other containers. In our setup, the rootfs for each container is stored as a dedicated ZFS volume (dataset). ZFS is a robust, modern filesystem and volume manager that provides features like snapshots, compression, and data integrity checks. Using ZFS allows you to easily manage, backup, and migrate containers individually. Snapshots can be taken for quick backups or rollbacks, and ZFS handles storage efficiently. -- **Volumes:** Storage volumes are allocated to containers for persistent data. You can attach, detach, and resize volumes as needed. - -## Container Templating - -Container templates in Proxmox serve as reusable blueprints for creating new containers quickly and consistently. Templates can include pre-installed packages, network configurations, and services, allowing you to standardize environments across your cluster. - -- **Cloning:** New containers are cloned from templates, inheriting all configurations and installed software. -- **Customization:** Different templates can be tailored for specific use cases, such as web servers, development environments, or database nodes. -- **Efficiency:** Using templates streamlines deployment, reduces setup time, and ensures consistency. - -Templates are managed through the Proxmox web interface, where you can create, update, and deploy containers based on your preferred configurations. - -## User Accounts & Permissions -- **User Accounts:** Each user has a unique account for accessing the Proxmox web interface and managing resources. -- **Permissions:** Role-based access control (RBAC) lets administrators assign permissions to users and groups, controlling who can create, modify, or delete containers and volumes. -- **Authentication:** Supports local users, LDAP, and other authentication backends for secure access. - -## Monitoring Container Metrics -Proxmox provides real-time monitoring and historical metrics for each container: -- **CPU (Cores):** Track usage and allocation per container -- **RAM:** Monitor memory consumption and limits -- **Swap:** View swap usage for containers under heavy load -- **SSD:** Check disk I/O, storage usage, and performance - -The Proxmox dashboard offers graphs and statistics for each metric, helping you optimize resource usage and troubleshoot performance issues. - ---- - -Want to see how our Proxmox Cluster works specifically? Head to the next section! - diff --git a/mie-opensource-landing/docs/users/_category_.json b/mie-opensource-landing/docs/users/_category_.json new file mode 100644 index 00000000..25eaa027 --- /dev/null +++ b/mie-opensource-landing/docs/users/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "Users", + "position": 2, + "collapsed": false +} diff --git a/mie-opensource-landing/docs/creating-containers/_category_.json b/mie-opensource-landing/docs/users/creating-containers/_category_.json similarity index 100% rename from mie-opensource-landing/docs/creating-containers/_category_.json rename to mie-opensource-landing/docs/users/creating-containers/_category_.json diff --git a/mie-opensource-landing/docs/users/creating-containers/command-line.mdx b/mie-opensource-landing/docs/users/creating-containers/command-line.mdx new file mode 100644 index 00000000..fc62f320 --- /dev/null +++ b/mie-opensource-landing/docs/users/creating-containers/command-line.mdx @@ -0,0 +1,252 @@ +--- +sidebar_position: 2 +--- + +import { ProxmoxUrl, ContainerCreationUrl } from '@site/src/components/InstanceUrl'; + +# Using the API with curl + +:::note Note +This walkthrough assumes that you already have a registered account in the cluster. If not, see [Introduction](/docs/intro). +::: + +This guide shows you how to create a basic LXC container on the MIE Opensource Proxmox Cluster using the REST API with curl commands. + +The API endpoint is: + +## Prerequisites + +- Active user account with appropriate permissions +- Access to a terminal with `curl` installed +- Knowledge of your site ID (available from the web interface) +- Cookie storage file for maintaining session authentication + +## 1. Authenticate and Establish Session + +First, log in to establish a session. The API uses cookie-based authentication: + +```bash +curl -X POST 'https://create-a-container.opensource.mieweb.org/login' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -c cookies.txt \ + --data-urlencode 'username=your_username' \ + --data-urlencode 'password=your_password' +``` + +**Parameters:** +- `username` - Your cluster account username +- `password` - Your cluster account password +- `-c cookies.txt` - Saves session cookies to a file for subsequent requests + +**Response:** +- On success: Redirects to home page (302) with session cookie set +- On failure: Returns login page with error message + +:::important Important +The `cookies.txt` file contains your authentication session. Keep it secure and delete it when done. The session expires after 24 hours of inactivity. +::: + +## 2. List Available Templates + +Before creating a container, you need to know what templates are available. Access the container creation form to see available templates: + +```bash +curl -X GET 'https://create-a-container.opensource.mieweb.org/sites/1/containers/new' \ + -b cookies.txt \ + -L +``` + +**Parameters:** +- Replace `1` with your actual site ID +- `-b cookies.txt` - Sends authentication cookies with the request +- `-L` - Follows redirects + +This returns an HTML page listing available templates with their node and VMID. Look for template entries in the format `nodeName,templateVmid`. + +## 3. Get External Domain IDs + +To configure HTTP services, you need the external domain ID: + +```bash +curl -X GET 'https://create-a-container.opensource.mieweb.org/sites/1/containers/new' \ + -b cookies.txt \ + -L | grep -o 'externalDomainId" value="[0-9]*"' +``` + +This extracts available external domain IDs from the form. Note the domain ID you want to use for your HTTP service. + +## 4. Create a Container + +Create a new container by POSTing to the containers endpoint: + +```bash +curl -X POST 'https://create-a-container.opensource.mieweb.org/sites/1/containers' \ + -b cookies.txt \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'hostname=my-app' \ + --data-urlencode 'template=pve1,100' \ + --data-urlencode 'services[0][type]=tcp' \ + --data-urlencode 'services[0][internalPort]=22' \ + --data-urlencode 'services[1][type]=http' \ + --data-urlencode 'services[1][internalPort]=3000' \ + --data-urlencode 'services[1][externalHostname]=my-app' \ + --data-urlencode 'services[1][externalDomainId]=1' +``` + +**Required Parameters:** +- `hostname` - Container hostname (letters, numbers, hyphens only) +- `template` - Template to clone, format: `nodeName,templateVmid` + +**Service Configuration:** + +Services are configured using a zero-indexed array. Each service needs an index starting from 0: + +**SSH Service (TCP) - Index 0:** +```bash +--data-urlencode 'services[0][type]=tcp' \ +--data-urlencode 'services[0][internalPort]=22' +``` +- `type` - Must be `tcp` for SSH +- `internalPort` - Internal SSH port (typically 22) +- External port is automatically assigned + +**HTTP Service - Index 1:** +```bash +--data-urlencode 'services[1][type]=http' \ +--data-urlencode 'services[1][internalPort]=3000' \ +--data-urlencode 'services[1][externalHostname]=my-app' \ +--data-urlencode 'services[1][externalDomainId]=1' +``` +- `type` - Must be `http` +- `internalPort` - Port your app listens on (80, 3000, 8080, etc.) +- `externalHostname` - Subdomain for your service +- `externalDomainId` - ID of the external domain to use + +**Additional TCP/UDP Services - Index 2, 3, etc.:** +```bash +--data-urlencode 'services[2][type]=tcp' \ +--data-urlencode 'services[2][internalPort]=5432' +``` +- `type` - Either `tcp` or `udp` +- `internalPort` - Internal port number +- External port is automatically assigned in range 2000-65565 + +**DNS (SRV) Services:** +```bash +--data-urlencode 'services[3][type]=srv' \ +--data-urlencode 'services[3][internalPort]=389' \ +--data-urlencode 'services[3][dnsName]=_ldap._tcp' +``` +- `type` - Must be `srv` +- `internalPort` - Service port +- `dnsName` - SRV record name (e.g., `_ldap._tcp`) + +## 5. Complete Example + +Here's a complete example creating a container with SSH, HTTP, and a custom TCP service: + +```bash +# Step 1: Authenticate +curl -X POST 'https://create-a-container.opensource.mieweb.org/login' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + -c cookies.txt \ + --data-urlencode 'username=myuser' \ + --data-urlencode 'password=mypass' + +# Step 2: Create container with multiple services +curl -X POST 'https://create-a-container.opensource.mieweb.org/sites/1/containers' \ + -b cookies.txt \ + -L \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'hostname=my-web-app' \ + --data-urlencode 'template=pve1,100' \ + --data-urlencode 'services[0][type]=tcp' \ + --data-urlencode 'services[0][internalPort]=22' \ + --data-urlencode 'services[1][type]=http' \ + --data-urlencode 'services[1][internalPort]=8080' \ + --data-urlencode 'services[1][externalHostname]=my-web-app' \ + --data-urlencode 'services[1][externalDomainId]=1' \ + --data-urlencode 'services[2][type]=tcp' \ + --data-urlencode 'services[2][internalPort]=5432' + +# Step 3: Clean up +rm cookies.txt +``` + +**Response:** +- On success: Redirects to the containers list page (302) +- On failure: Returns error message with details + +## 6. Understanding Container Creation + +The API performs these steps automatically: + +1. **Clone Template** - Clones the specified LXC template +2. **Configure Resources** - Sets CPU (4 cores), memory (4GB), networking +3. **Start Container** - Boots the container and waits for it to start +4. **DNS Registration** - Waits for DHCP lease and DNS propagation +5. **Service Registration** - Creates service records and configures reverse proxy +6. **Network Configuration** - Sets up port forwarding and firewall rules + +This process typically takes 2-5 minutes. The container will be accessible once DNS propagates and services are configured. + +## 7. Listing Your Containers + +To view your containers, access the containers list page: + +```bash +curl -X GET 'https://create-a-container.opensource.mieweb.org/sites/1/containers' \ + -b cookies.txt \ + -L +``` + +This returns an HTML page listing all your containers with their details, including hostnames, IP addresses, and port assignments. + +## 8. Accessing Your Container + +Once created, you can access your container via SSH: + +```bash +ssh -p @. +``` + +The SSH port is automatically assigned and displayed in the containers list. HTTP services are accessible via: + +``` +https://. +``` + +## 9. Viewing on Proxmox + +To see your container in the Proxmox GUI, navigate to . Your container will be listed with your username in the tags field. + +![Hostname](img/proxmox-lxc.jpg) + +:::note Note +You can start, stop, and reboot your container through the Proxmox interface. To delete a container, contact a cluster administrator. +::: + +## Troubleshooting + +**Authentication Failed:** +- Verify your username and password are correct +- Check that your account status is active +- Ensure cookies.txt is being saved correctly + +**Template Not Found:** +- Verify the template exists on the specified node +- Check that your site ID is correct +- Ensure the node has templates configured + +**Hostname Already Exists:** +- Choose a different hostname +- Check the containers list for existing containers + +**Service Configuration Errors:** +- HTTP services require both externalHostname and externalDomainId +- DNS services require a dnsName +- Port numbers must be valid integers + +--- + +**Need Help?**: For questions about API usage or automation, contact the MIE team. diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/distro.jpg b/mie-opensource-landing/docs/users/creating-containers/img/distro.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/distro.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/distro.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/hostname.jpg b/mie-opensource-landing/docs/users/creating-containers/img/hostname.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/hostname.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/hostname.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/login.jpg b/mie-opensource-landing/docs/users/creating-containers/img/login.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/login.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/login.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/port.jpg b/mie-opensource-landing/docs/users/creating-containers/img/port.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/port.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/port.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/proxmox-lxc.jpg b/mie-opensource-landing/docs/users/creating-containers/img/proxmox-lxc.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/proxmox-lxc.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/proxmox-lxc.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/img/ssh.jpg b/mie-opensource-landing/docs/users/creating-containers/img/ssh.jpg similarity index 100% rename from mie-opensource-landing/docs/creating-containers/basic-containers/img/ssh.jpg rename to mie-opensource-landing/docs/users/creating-containers/img/ssh.jpg diff --git a/mie-opensource-landing/docs/creating-containers/basic-containers/web-gui.md b/mie-opensource-landing/docs/users/creating-containers/web-gui.mdx similarity index 90% rename from mie-opensource-landing/docs/creating-containers/basic-containers/web-gui.md rename to mie-opensource-landing/docs/users/creating-containers/web-gui.mdx index 5ce92652..3b2ba607 100644 --- a/mie-opensource-landing/docs/creating-containers/basic-containers/web-gui.md +++ b/mie-opensource-landing/docs/users/creating-containers/web-gui.mdx @@ -2,12 +2,14 @@ sidebar_position: 1 --- -# Using a Web GUI +import { ProxmoxUrl, ContainerCreationUrl } from '@site/src/components/InstanceUrl'; + +# Using the Web GUI :::note Note -This walkthrough assumes that you already have a registered proxmox account in the cluster. If not, see [Introduction](/docs/intro.md). +This walkthrough assumes that you already have a registered proxmox account in the cluster. If not, see [Introduction](/docs/intro). ::: -This guide shows you how to set up a basic LXC container on the MIE Opensource Proxmox Cluster using the a Web GUI. The Web GUI can be accessed at [https://create-a-container.opensource.mieweb.org](https://create-a-container.opensource.mieweb.org). +This guide shows you how to set up a basic LXC container on the MIE Opensource Proxmox Cluster using the a Web GUI. The Web GUI can be accessed at . ## 1. Authenticate Your Proxmox Account @@ -148,7 +150,7 @@ Save your SSH port number, as well as any port numbers, because you will not be ## 8. Viewing your Container on Proxmox -To see your container on the Proxmox GUI, navigate to [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006). Once signed in, on the summary view, you should see the name of your container. If you double click on it, you will be able to access details, like the shell, metrics, and other network/filesystem information. +To see your container on the Proxmox GUI, navigate to . Once signed in, on the summary view, you should see the name of your container. If you double click on it, you will be able to access details, like the shell, metrics, and other network/filesystem information. ![Hostname](img/proxmox-lxc.jpg) @@ -158,4 +160,4 @@ As of writing, you are able to reboot, start, and shutdown your container as you --- -**Advanced Options**: For multi-component deployments, custom environment variables, or specific service configurations, refer to the [Advanced Container Configuration](/docs/category/creating-advanced-containers) documentation or contact the MIE team. +**Need Help?**: For questions about container configuration or troubleshooting, contact the MIE team. diff --git a/mie-opensource-landing/docs/users/img/container-charts.png b/mie-opensource-landing/docs/users/img/container-charts.png new file mode 100644 index 00000000..fc58aa4e Binary files /dev/null and b/mie-opensource-landing/docs/users/img/container-charts.png differ diff --git a/mie-opensource-landing/docs/users/img/container-metrics.png b/mie-opensource-landing/docs/users/img/container-metrics.png new file mode 100644 index 00000000..22b6d6e2 Binary files /dev/null and b/mie-opensource-landing/docs/users/img/container-metrics.png differ diff --git a/mie-opensource-landing/docs/users/img/fingerprint.jpg b/mie-opensource-landing/docs/users/img/fingerprint.jpg new file mode 100644 index 00000000..e0b71473 Binary files /dev/null and b/mie-opensource-landing/docs/users/img/fingerprint.jpg differ diff --git a/mie-opensource-landing/docs/users/img/image.png b/mie-opensource-landing/docs/users/img/image.png new file mode 100644 index 00000000..6452739b Binary files /dev/null and b/mie-opensource-landing/docs/users/img/image.png differ diff --git a/mie-opensource-landing/docs/users/img/proxmox-container-dashboard.png b/mie-opensource-landing/docs/users/img/proxmox-container-dashboard.png new file mode 100644 index 00000000..4fca8709 Binary files /dev/null and b/mie-opensource-landing/docs/users/img/proxmox-container-dashboard.png differ diff --git a/mie-opensource-landing/docs/users/img/proxmox_shell.png b/mie-opensource-landing/docs/users/img/proxmox_shell.png new file mode 100644 index 00000000..bebb11c4 Binary files /dev/null and b/mie-opensource-landing/docs/users/img/proxmox_shell.png differ diff --git a/mie-opensource-landing/docs/monitoring-container.md b/mie-opensource-landing/docs/users/monitoring-container.mdx similarity index 91% rename from mie-opensource-landing/docs/monitoring-container.md rename to mie-opensource-landing/docs/users/monitoring-container.mdx index 23322f31..160f4a62 100644 --- a/mie-opensource-landing/docs/monitoring-container.md +++ b/mie-opensource-landing/docs/users/monitoring-container.mdx @@ -2,9 +2,11 @@ sidebar_position: 5 --- +import { ProxmoxUrl } from '@site/src/components/InstanceUrl'; + # Monitoring Container in Proxmox Web GUI -Once you have created a container, whether through the Web GUI, command line, or Proxmox Launchpad, you can monitor the container's performance using the Proxmox Web GUI located at [https://opensource.mieweb.org:8006](https://opensource.mieweb.org:8006). +Once you have created a container, whether through the Web GUI, command line, or Proxmox Launchpad, you can monitor the container's performance using the Proxmox Web GUI located at . ## Container Dashboard diff --git a/mie-opensource-landing/docs/proxmox-launchpad/_category_.json b/mie-opensource-landing/docs/users/proxmox-launchpad/_category_.json similarity index 100% rename from mie-opensource-landing/docs/proxmox-launchpad/_category_.json rename to mie-opensource-landing/docs/users/proxmox-launchpad/_category_.json diff --git a/mie-opensource-landing/docs/proxmox-launchpad/automatic-runner-provisioning.md b/mie-opensource-landing/docs/users/proxmox-launchpad/automatic-runner-provisioning.md similarity index 98% rename from mie-opensource-landing/docs/proxmox-launchpad/automatic-runner-provisioning.md rename to mie-opensource-landing/docs/users/proxmox-launchpad/automatic-runner-provisioning.md index b7fd2323..9a6a78aa 100644 --- a/mie-opensource-landing/docs/proxmox-launchpad/automatic-runner-provisioning.md +++ b/mie-opensource-landing/docs/users/proxmox-launchpad/automatic-runner-provisioning.md @@ -651,10 +651,10 @@ sudo systemctl status actions.runner.* ### Alternative Approaches If you're uncomfortable sharing your PAT: -- Consider using [Path 1: Supplied Runners](/docs/proxmox-launchpad/supplied-runners) instead +- Consider using [Path 1: Supplied Runners](/docs/users/proxmox-launchpad/supplied-runners) instead - Set up your own self-hosted runners for enhanced security - Use organization-level runners with restricted permissions --- -**Next Steps**: Explore [Path 1: Supplied Runners](/docs/proxmox-launchpad/supplied-runners) for a more secure alternative. +**Next Steps**: Explore [Path 1: Supplied Runners](/docs/users/proxmox-launchpad/supplied-runners) for a more secure alternative. diff --git a/mie-opensource-landing/docs/proxmox-launchpad/img/pr-comment-example.png b/mie-opensource-landing/docs/users/proxmox-launchpad/img/pr-comment-example.png similarity index 100% rename from mie-opensource-landing/docs/proxmox-launchpad/img/pr-comment-example.png rename to mie-opensource-landing/docs/users/proxmox-launchpad/img/pr-comment-example.png diff --git a/mie-opensource-landing/docs/proxmox-launchpad/img/proxmox-launchpad-overview.png b/mie-opensource-landing/docs/users/proxmox-launchpad/img/proxmox-launchpad-overview.png similarity index 100% rename from mie-opensource-landing/docs/proxmox-launchpad/img/proxmox-launchpad-overview.png rename to mie-opensource-landing/docs/users/proxmox-launchpad/img/proxmox-launchpad-overview.png diff --git a/mie-opensource-landing/docs/proxmox-launchpad/img/proxmox-launchpad-page.png b/mie-opensource-landing/docs/users/proxmox-launchpad/img/proxmox-launchpad-page.png similarity index 100% rename from mie-opensource-landing/docs/proxmox-launchpad/img/proxmox-launchpad-page.png rename to mie-opensource-landing/docs/users/proxmox-launchpad/img/proxmox-launchpad-page.png diff --git a/mie-opensource-landing/docs/proxmox-launchpad/supplied-runners.md b/mie-opensource-landing/docs/users/proxmox-launchpad/supplied-runners.md similarity index 99% rename from mie-opensource-landing/docs/proxmox-launchpad/supplied-runners.md rename to mie-opensource-landing/docs/users/proxmox-launchpad/supplied-runners.md index 397636de..6d1511c8 100644 --- a/mie-opensource-landing/docs/proxmox-launchpad/supplied-runners.md +++ b/mie-opensource-landing/docs/users/proxmox-launchpad/supplied-runners.md @@ -503,4 +503,4 @@ tmux attach -t 0 --- -**Next Steps**: Learn about [Path 2: Automatic Runner Provisioning](/docs/proxmox-launchpad/automatic-runner-provisioning) for automatically provisioning your runners. +**Next Steps**: Learn about [Path 2: Automatic Runner Provisioning](/docs/users/proxmox-launchpad/automatic-runner-provisioning) for automatically provisioning your runners. diff --git a/mie-opensource-landing/docs/proxmox-launchpad/what-is-proxmox-launchpad.md b/mie-opensource-landing/docs/users/proxmox-launchpad/what-is-proxmox-launchpad.md similarity index 96% rename from mie-opensource-landing/docs/proxmox-launchpad/what-is-proxmox-launchpad.md rename to mie-opensource-landing/docs/users/proxmox-launchpad/what-is-proxmox-launchpad.md index 36698f05..02756042 100644 --- a/mie-opensource-landing/docs/proxmox-launchpad/what-is-proxmox-launchpad.md +++ b/mie-opensource-landing/docs/users/proxmox-launchpad/what-is-proxmox-launchpad.md @@ -105,5 +105,5 @@ Ready to start using Proxmox Launchpad? Check out our [setup guides](/docs/categ --- -**Next Steps**: Jump to [Path 1 Setup](/docs/proxmox-launchpad/supplied-runners) or [Path 2 Setup](/docs/proxmox-launchpad/automatic-runner-provisioning) to get started. +**Next Steps**: Jump to [Path 1 Setup](/docs/users/proxmox-launchpad/supplied-runners) or [Path 2 Setup](/docs/users/proxmox-launchpad/automatic-runner-provisioning) to get started. diff --git a/mie-opensource-landing/docs/vscode-setup.md b/mie-opensource-landing/docs/users/vscode-setup.md similarity index 95% rename from mie-opensource-landing/docs/vscode-setup.md rename to mie-opensource-landing/docs/users/vscode-setup.md index adbdb8e0..d4c6cc9e 100644 --- a/mie-opensource-landing/docs/vscode-setup.md +++ b/mie-opensource-landing/docs/users/vscode-setup.md @@ -11,7 +11,7 @@ When managing an entire repository, many developers prefer to work in an IDE, su Before getting started, ensure you have: - **VSCode installed** on your local machine -- **Container created** with Proxmox Launchpad (either [Path 1](/docs/proxmox-launchpad/supplied-runners) or [Path 2](/docs/proxmox-launchpad/automatic-runner-provisioning)) +- **Container created** with Proxmox Launchpad (either [Path 1](/docs/users/proxmox-launchpad/supplied-runners) or [Path 2](/docs/users/proxmox-launchpad/automatic-runner-provisioning)) - **Container access details** from your deployment output (SSH port, hostname, etc.) ## 1: Install Remote SSH Extension @@ -239,4 +239,4 @@ Host dev-environment --- -**Next Steps**: With VSCode connected to your container, you can now develop directly in your remote environment. Consider exploring [container deployment guides](/docs/creating-containers/advanced-containers/deploying-containers-overview) for automatic application setup. +**Next Steps**: With VSCode connected to your container, you can now develop directly in your remote environment. diff --git a/mie-opensource-landing/docusaurus.config.ts b/mie-opensource-landing/docusaurus.config.ts index c292c3e4..4b9642b1 100644 --- a/mie-opensource-landing/docusaurus.config.ts +++ b/mie-opensource-landing/docusaurus.config.ts @@ -1,6 +1,9 @@ import { themes as prismThemes } from "prism-react-renderer"; import type { Config } from "@docusaurus/types"; import type * as Preset from "@docusaurus/preset-classic"; +import dotenv from "dotenv"; + +dotenv.config(); // This runs in Node.js - Don't use client-side code here (browser APIs, JSX...) @@ -28,20 +31,29 @@ const config: Config = { locales: ["en"], }, + customFields: { + proxmoxUrl: process.env.PROXMOX_URL || "https://localhost:8006", + containerCreationUrl: process.env.CONTAINER_CREATION_URL || "https://localhost", + }, + presets: [ [ "classic", { docs: { sidebarPath: "./sidebars.ts", - editUrl: - "https://github.com/maxklema/mie-opensource-landing/tree/master/", } } satisfies Preset.Options, ], ], + themes: ["@docusaurus/theme-mermaid"], + + markdown: { + mermaid: true, + }, + themeConfig: { image: "img/docusaurus-social-card.jpg", navbar: { @@ -52,7 +64,7 @@ const config: Config = { }, items: [ { - to: "https://create-a-container.opensource.mieweb.org", + to: process.env.CONTAINER_CREATION_URL || "https://create-a-container.opensource.mieweb.org", label: "Create a Container", position: "left", }, @@ -61,11 +73,6 @@ const config: Config = { label: "Proxmox Launchpad", position: "left", }, - { - to: "/projects", - label: "Projects", - position: "left", - }, { type: "docSidebar", sidebarId: "tutorialSidebar", @@ -89,42 +96,38 @@ const config: Config = { label: "Introduction", to: "/docs/intro", }, - { - label: "Proxmox", - to: "/docs/category/introduction-to-proxmox" - }, { label: "Creating Containers", - to: "/docs/creating-containers/basic-containers/web-gui", + to: "/docs/users/creating-containers/web-gui", }, { label: "Proxmox Launchpad", - to: "/docs/proxmox-launchpad/what-is-proxmox-launchpad", + to: "/docs/users/proxmox-launchpad/what-is-proxmox-launchpad", }, { label: "Monitoring Containers", - to: "/docs/monitoring-container", + to: "/docs/users/monitoring-container", }, { label: "VSCode Integration", - to: "/docs/vscode-setup", + to: "/docs/users/vscode-setup", + }, + { + label: "Cluster Architecture", + to: "/docs/developers/system-architecture", }, ], }, { title: "Resources", items: [ - { - label: "Site Source", - href: "https://github.com/maxklema/mie-opensource-landing", - }, { label: "Opensource Cluster Source", href: "https://github.com/mieweb/opensource-server", }, { label: "Proxmox Launchpad Source", - href: "https://github.com/maxklema/proxmox-launchpad", + href: "https://github.com/mieweb/launchpad", }, { label: "Mieweb Github Organization", diff --git a/mie-opensource-landing/launchpad_README.md b/mie-opensource-landing/launchpad_README.md deleted file mode 100644 index 9bf1fc3f..00000000 --- a/mie-opensource-landing/launchpad_README.md +++ /dev/null @@ -1,359 +0,0 @@ -# Proxmox LaunchPad - -This GitHub action utilizes MIE's open source cluster to manage LXC containers derived from your github repository source code. - -> [!NOTE] -> This project is new and is in a early version. There are likely bugs. If you encounter any, please create an issue. - -## Two Usage Pathways - -This GitHub Action offers **two distinct pathways** for managing containers on our Proxmox cluster: - -### **Path 1: Use Your Own Runners (Recommended)** -Use your existing GitHub self-hosted runners or any external runner to automatically provision containers. **No GitHub PAT required.** You maintain full control over your runners and simply use our action to manage containers on the Proxmox cluster. - -### **Path 2: Automatic Runner Provisioning** -Our action automatically creates and manages GitHub runners for you. Each branch gets its own dedicated runner and container. **Requires a GitHub PAT** with runner management permissions. We handle runner lifecycle (creation/deletion) automatically. - -> [!WARNING] -> **Path 2 requires sharing your GitHub Personal Access Token** with our action to manage runners on your behalf. Only use this if you're comfortable with this security consideration. - -## Table of Contents -1. [Video Walkthroughs](#video-walkthroughs) -2. [Sequence Diagram](#sequence-diagram) -3. [Prerequisites](#prerequisites) -4. [Getting Started](#getting-started) - - [Path 1: Using Your Own Runners](#path-1-using-your-own-runners) - - [Path 2: Automatic Runner Provisioning](#path-2-automatic-runner-provisioning) - - [Personal Access Token Setup](#creating-a-github-pat-for-automatic-runner-provisioning) - - [Setup-Runner Job](#setup-runner-job) - - [Manage-Container Job](#manage-container-job-for-automatic-runners) -5. [Configurations](#configurations) - - [Basic Properties](#basic-properties) - - [Automatic Deployment Properties](#automatic-deployment-properties) -6. [Important Notes for Automatic Deployment](#important-notes-for-automatic-deployment) -7. [Output](#output) -8. [Sample Workflow Files](#sample-workflow-files) -9. [Misc.](#misc) - -## Video Walkthroughs - -I have created a series of videos to walk you through automatic deployment, both in GitHub and via the command line. - -**[Long-Form]** Proxmox LaunchPad Walkthrough: [Video](https://youtu.be/Xa2L1o-atEM)
-**[Short-Form]** Proxmox LaunchPad Demonstration: [Short](https://youtube.com/shorts/SuK73Jej5j4)
-**[Long-Form]** Automatic Deployment through Command Line: [Video](https://youtu.be/acDW-a32Yr8)
-**[Long-Form]** Getting Started with Creating LXC Continers with Proxmox: [Video](https://youtu.be/sVW3dkBqs4E) - -## Sequence Diagram - -The sequence diagram below describes the sequence of events executed by this Github Action. - -```mermaid -sequenceDiagram - participant Dev as Developer - participant GH as GitHub - participant GHAR as GitHub Actions Runner - participant Prox as Proxmox Cluster - participant LXC as LXC Container - - Dev->>GH: Push/Create/Delete branch - GH->>GHAR: Trigger workflow - - alt Push/Create event - GHAR->>Prox: Check if LXC container exists for branch - alt Container does not exist - GHAR->>Prox: Clone template, create LXC container - Prox->>LXC: Start container, configure self-hosted runner (if automatic runner provisioning is enabled). - GHAR->>LXC: Register self-hosted runner (if automatic runner provisioning is enabled). - GHAR->>LXC: Run manage container job (install deps, clone repo, install services, deploy app) - else Container exists - GHAR->>Prox: Call update script - Prox->>LXC: Update container contents, restart with latest branch - end - else Delete event - GHAR->>LXC: Call delete-container script - LXC->>Prox: Remove runner (if automatic runner provisioning is enabled) and delete LXC container - end -``` - -## Prerequisites -- Proxmox Datacluster Setup that mirrors/forks [https://github.com/mieweb/opensource-server](https://github.com/mieweb/opensource-server). -- Valid Proxmox Account. - -## Getting Started - -Both pathways require the following trigger events in your workflow file: - -```yaml -on: - push: - create: - delete: -``` - -This allows a container to be created/updated on a push command, created when a new branch is created, and deleted when a branch is deleted (like in the case of an accepted PR). - -### Path 1: Using Your Own Runners - -> [!TIP] -> **This is the recommended approach** as it gives you full control over your runners and doesn't require sharing a GitHub PAT. - -If you have your own GitHub self-hosted runners or external runners, you can use them directly with our action. Simply create a workflow file with the manage-container job: - -```yaml -name: Proxmox Container Management - -on: - push: - create: - delete: - -jobs: - manage-container: - runs-on: self-hosted # or your runner label - steps: - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - # No github_pat needed for this path - # Add other configuration options as needed -``` - -**Benefits of Path 1:** -- No GitHub PAT required -- Full control over runner environment -- Enhanced security -- Simpler workflow configuration - -### Path 2: Automatic Runner Provisioning - -> [!CAUTION] -> **This path requires you to provide your GitHub Personal Access Token**, giving our action permission to create and manage runners on your behalf. Only use this if you're comfortable with this security consideration. - -#### Creating a GitHub PAT for Automatic Runner Provisioning - -To use automatic runner provisioning, you must create a GitHub Personal Access Token with runner management permissions: - -1. Navigate to your GitHub account settings -2. Click "Developer settings" (bottom left) -3. Navigate to "Personal Access Tokens (classic)" -4. Click "Generate new token" -5. Give your token a name and expiration date -6. Select the **`manage_runners:org`** permission (or `manage_runners:enterprise` for enterprise repositories) -7. Generate the token and store it securely -8. Add it as a repository secret named `GH_PAT` in your repository - -> [!WARNING] -> This PAT gives our action the ability to create, modify, and delete runners in your GitHub organization/repository. Store it securely and never share it. - -#### Setup-Runner Job - -For automatic runner provisioning, you need both a `setup-runner` job and a `manage-container` job: - -```yaml -name: Proxmox Container Management - -on: - push: - create: - delete: - -jobs: - setup-runner: - runs-on: ubuntu-latest - steps: - - name: Install Dependencies - run: | - sudo apt install -y sshpass jq - - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - github_pat: ${{ secrets.GH_PAT }} - - manage-container: - runs-on: self-hosted - needs: setup-runner - steps: - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - github_pat: ${{ secrets.GH_PAT }} - # Add other configuration options as needed -``` - - -> [!TIP] -> It is recommended to also pass your `github_pat` in the manage-container job, too. This allows Proxmox Launchpad to create deployments on every update to your main branch. Additionally, if a branch is part of an open pull request, Proxmox Launchpad will comment on that PR with information regarding the public domain for that container, the job status, and the job ID, allowing others to easily access it. - -**What happens with automatic runner provisioning:** -- A new runner is created for each branch -- Runners are automatically deleted when branches are deleted -- Each branch gets its own dedicated container and runner -- Complete lifecycle management (no manual cleanup needed) - - - -## Configurations - -At the very minimum, two configuration settings are required to create any container. With all of these properties specified, you can create an empty container for a branch. - -### Basic Properties - -| Propety | Required? | Description | Supplied by Github? | -| ---------------- | ------ | ---------------------------------------------- | ------ | -| `proxmox_username` | Yes | Your proxmox username assigned to you. | N/A -| `proxmox_password` | Yes | Your proxmox password assigned to you. | N/A -| `http_port` | No | The HTTP Port for your container to listen on. It must be between `80` and `60000`. Default value is `3000`. | N/A -| `linux_distribution` | No | The Linux Distribution that runs on your container. Currently, `rocky` (Rocky 9.5) and `debian` (Debian 12) are available. Default value is `Debian`. | N/A -| `github_pat` | Conditional | Your GitHub Personal Access Token. This is used to manage runners in your containers. This is **only required for Path 2 (Automatic Runner Provisioning).**| Yes. Accessible in developer settings. | - -There are a few other properties that are not required, but can still be specified in the workflow file: -
- -| Propety | Required? | Description | Supplied by Github? | -| --------- | ----- | ------------------------------------ | ------ | -| `public_key` | No | Your machine's public key that will be stored in the `~/.ssh/authorized_keys` file of your repository. This allows you to SSH into your container without a password. It is more secure and recommended. | N/A - -### Automatic Deployment Properties - -This github action can *attempt* to automatically deploy services on your container. This is done by fetching your repository contents on the branch that the script is being ran in, installing dependencies/services, and running build and start commands in the background. - -Additionally, with automatic deployment enabled, your container will update on every push command automatically, preventing you from having to SSH into the container and setting it up manually. - -> [!NOTE] -> Properties below that are required assuming you want to automatically deploy your project. If not, none of these properties are needed. - -| Property | Required? | Description | -| --------- | ----- | ------------------------------------ | -| `project_root` | No | The root directory of your project to deploy from. Example: `/flask-server`. If the root directory is the same as the github root directory, leave blank. -| `services` | No | A JSON array of services to add to your container. Example: ```services: '["mongodb", "docker"]'```. These services will automatically install and start up on container creation. **NOTE**: All services in this list must belong on the list of available services below. If you need a service that is not on the list, see `custom_services`.

Available Services: `meteor`, `mongodb`, `docker`, `redis`, `postgresql`, `apache`, `nginx`, `rabbitmq`, `memcached`, `mariadb`. -| `custom_services` | No | A 2D JSON array of custom service installation commands to install any custom service(s) not in `services`.

Example: ```custom_services: [["sudo apt-get install -y service", "sudo systemctl enable service", "sudo systemctl start service"], ["sudo apt-get install -y service2", "sudo systemctl enable service2", "sudo systemctl start service2"]]``` - -There are two types of deployments: single component and multi-component deployment. Single component deployment involves deploying only a single service (i.e. a single Flask Server, REACT application, MCP Server, etc.). Multi-component deployment involves deploying more than one service at the same time (i.e. a flask backend and a vite.js backend). - -> [!IMPORTANT] -> In Multi-Component applications, each top-layer key represents the file path, relative to the root directory, to the component (service) to place those variables/commands in. - -| Propety | Required? | Description | Single Component | Multi-Component | -| --------- | ----- | ------------------------------------ | ---- | --- | -| `container_env_vars` | No. | Key-Value Environment variable pairs. | Dictionary in the form of: `{ "api_key": "123", "password": "abc"}` | Dictionary in the form of: `'{"/frontend": { "api_key": "123"}, "/backend": { "password": "abc123" }}'`. -| `install_command` | Yes | Commands to install all project dependencies | String of the installation command, i.e. `npm install`. | Dictionary in the form of: `'{"/frontend": "npm install", "/backend": "pip install -r ../requirements.txt"}'`. -| `build_command` | No | Commands to build project components | String of the build command, i.e. `npm build`. | Dictionary in the form of: `'{"/frontend": "npm build", "/backend": "python3 build.py"}'`. -| `start_command` | Yes | Commands to start project components. | String of the start command, i.e. `npm run`. | Dictionary in the form of: `'{"/frontend": "npm run", "/backend": "flask run"}'`. -| `runtime_language` | Yes | Runtime language of each project component, which can either be `nodejs` or `python`. | String of runtime environment, i.e. `nodejs` | Dictionary in the form of: `'{"/frontend": "nodejs", "/backend": "python"}'`. -| `root_start_command` | No | Command to run at the project directory root for **multi-component applications**. | N/A | String of the command, i.e. `Docker run` - -## Important Notes for Automatic Deployment - -Below are some important things to keep in mind if you want your application to be automatically deployed: -- If you are using meteor, you must start your application with the flags ``--allow-superuser`` and `--port 0.0.0.0:`. - - Meteor is a large package, so deploying it may take more time than other applications. -- When running a service, ensure it is listening on `0.0.0.0` (your IP) instead of only locally at `127.0.0.1`. -- The Github action will fail with an exit code and message if a property is not set up correctly. - -## Output - -When a container is successfully created (Github Action is successful), you will see an output with all of your container details. This includes all your ports, container ID, container IP Address (internal in 10.15.x.x subnet), public domain name, and ssh command to access your container. - -See an example output below: - -``` -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -🔔 COPY THESE PORTS DOWN — For External Access -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📌 Note: Your container listens on SSH Port 22 internally, - but EXTERNAL traffic must use the SSH port listed below: -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -✅ Hostname Registration: polyglot-test-maxklema-pull-request → 10.15.129.23 -🔐 SSH Port : 2344 -🌐 HTTP Port : 32000 -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -📦 Container ID : 136 -🌐 Internal IP : 10.15.129.23 -🔗 Domain Name : https://polyglot-test-maxklema-pull-request.opensource.mieweb.org -🛠️ SSH Access : ssh -p 2344 root@polyglot-test-maxklema-pull-request.opensource.mieweb.org -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -NOTE: Additional background scripts are being ran in detached terminal sessions. -Wait up to two minutes for all processes to complete. -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -Still not working? Contact Max K. at maxklema@gmail.com -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -``` - -> [!NOTE] -> Even if your GitHub Action workflow is finished, *it may not be accessible right away. Background tasks (migration, template cloning, cleanup, etc) are still be ran in detatched terminal sessions*. Wait a few minutes for all tasks to complete. - -## Sample Workflow Files - -### Path 1: Using Your Own Runners - -```yaml -name: Proxmox Container Management (Own Runners) - -on: - push: - create: - delete: - -jobs: - manage-container: - runs-on: self-hosted # Use your own runner - steps: - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - container_env_vars: '{"API_KEY": "1234"}' - install_command: npm i - start_command: npm start - runtime_language: nodejs - services: '["mongodb"]' -``` - -### Path 2: Automatic Runner Provisioning - -```yaml -name: Proxmox Container Management (Auto Runners) - -on: - push: - create: - delete: - -jobs: - setup-runner: - runs-on: ubuntu-latest - steps: - - name: Install Dependencies - run: | - sudo apt install -y sshpass jq - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - github_pat: ${{ secrets.GH_PAT }} - - manage-container: - runs-on: self-hosted - needs: setup-runner - steps: - - uses: maxklema/proxmox-launchpad@main - with: - proxmox_password: ${{ secrets.PROXMOX_PASSWORD }} - proxmox_username: ${{ secrets.PROXMOX_USERNAME }} - github_pat: ${{ secrets.GH_PAT }} - container_env_vars: '{"API_KEY": "1234"}' - install_command: npm i - start_command: npm start - runtime_language: nodejs - services: '["mongodb"]' -``` - -## Misc. -Written by [maxklema](https://github.com/maxklema).
-Feel free to submit a PR/issue here. \ No newline at end of file diff --git a/mie-opensource-landing/package-lock.json b/mie-opensource-landing/package-lock.json index 6e002d1e..2e66cfc5 100644 --- a/mie-opensource-landing/package-lock.json +++ b/mie-opensource-landing/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/theme-mermaid": "^3.8.1", "@heroui/react": "^2.8.2", "@heroui/snippet": "^2.2.25", "@heroui/system": "^2.4.20", @@ -23,6 +24,7 @@ "beautiful-backgrounds": "^0.0.7", "clsx": "^2.0.0", "cors": "^2.8.5", + "dotenv": "^17.2.3", "express": "^5.1.0", "framer-motion": "^12.23.12", "http-proxy-middleware": "^3.0.5", @@ -197,7 +199,6 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.35.0.tgz", "integrity": "sha512-FfmdHTrXhIduWyyuko1YTcGLuicVbhUyRjO3HbXE4aP655yKZgdTIfMhZ/V5VY9bHuxv/fGEh3Od1Lvv2ODNTg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/client-common": "5.35.0", "@algolia/requester-browser-xhr": "5.35.0", @@ -308,6 +309,18 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -336,7 +349,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -2009,6 +2021,55 @@ "node": ">=6.9.0" } }, + "node_modules/@braintree/sanitize-url": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz", + "integrity": "sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw==" + }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/cst-dts-gen/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2126,7 +2187,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2149,7 +2209,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2230,7 +2289,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2594,7 +2652,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3455,7 +3512,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.8.1.tgz", "integrity": "sha512-oByRkSZzeGNQByCMaX+kif5Nl2vmtj2IHQI2fWjCfCootsdKZDPFLonhIp5s3IGJO7PLUfe0POyw0Xh/RrGXJA==", "license": "MIT", - "peer": true, "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/logger": "3.8.1", @@ -3748,6 +3804,27 @@ "react-dom": "^18.0.0 || ^19.0.0" } }, + "node_modules/@docusaurus/theme-mermaid": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.8.1.tgz", + "integrity": "sha512-IWYqjyTPjkNnHsFFu9+4YkeXS7PD1xI3Bn2shOhBq+f95mgDfWInkpfBN4aYvx4fTT67Am6cPtohRdwh4Tidtg==", + "dependencies": { + "@docusaurus/core": "3.8.1", + "@docusaurus/module-type-aliases": "3.8.1", + "@docusaurus/theme-common": "3.8.1", + "@docusaurus/types": "3.8.1", + "@docusaurus/utils-validation": "3.8.1", + "mermaid": ">=11.6.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, "node_modules/@docusaurus/theme-search-algolia": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.8.1.tgz", @@ -3902,7 +3979,6 @@ "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", - "peer": true, "dependencies": { "@emotion/memoize": "0.7.4" } @@ -4995,7 +5071,6 @@ "version": "2.4.20", "resolved": "https://registry.npmjs.org/@heroui/system/-/system-2.4.20.tgz", "integrity": "sha512-bLl86ghOjsk8JLarLfL8wkuiNySJS1PHtd0mpGbAjVRQZYp4wH27R7hYBV55dre8Zw+nIRq58PgILdos7F+e0w==", - "peer": true, "dependencies": { "@heroui/react-utils": "2.1.12", "@heroui/system-rsc": "2.3.17", @@ -5085,7 +5160,6 @@ "version": "2.4.20", "resolved": "https://registry.npmjs.org/@heroui/theme/-/theme-2.4.20.tgz", "integrity": "sha512-wJdsz7XS9M7xbNd0d1EaaK5dCZIEOSI7eCr5A6f5aM48mtqLaXfsj3gYsfCy7GkQAvtKWuicwKe5D94Xoma6GA==", - "peer": true, "dependencies": { "@heroui/shared-utils": "2.1.10", "clsx": "^1.2.1", @@ -5426,6 +5500,21 @@ "react-dom": ">=18 || >=19.0.0-rc.0" } }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==" + }, + "node_modules/@iconify/utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "mlly": "^1.8.0" + } + }, "node_modules/@internationalized/date": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", @@ -5775,7 +5864,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5788,6 +5876,14 @@ "react": ">=16" } }, + "node_modules/@mermaid-js/parser": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.6.3.tgz", + "integrity": "sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==", + "dependencies": { + "langium": "3.3.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7389,7 +7485,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -7580,6 +7675,228 @@ "@types/node": "*" } }, + "node_modules/@types/d3": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", + "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", + "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", + "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", + "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", + "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz", + "integrity": "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", + "integrity": "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", + "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", + "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz", + "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==" + }, + "node_modules/@types/d3-format": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", + "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==" + }, + "node_modules/@types/d3-geo": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", + "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.7.tgz", + "integrity": "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", + "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", + "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==" + }, + "node_modules/@types/d3-random": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", + "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", + "integrity": "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", + "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.9.tgz", + "integrity": "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", + "integrity": "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -7660,6 +7977,11 @@ "@types/send": "*" } }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz", + "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==" + }, "node_modules/@types/gtag.js": { "version": "0.0.12", "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", @@ -7806,7 +8128,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -9360,7 +9681,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -9450,7 +9770,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -9496,7 +9815,6 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.35.0.tgz", "integrity": "sha512-Y+moNhsqgLmvJdgTsO4GZNgsaDWv8AOGAaPeIeHKlDn/XunoAqYbA+XNpBd1dW8GOXAUDyxC9Rxc7AV4kpFcIg==", "license": "MIT", - "peer": true, "dependencies": { "@algolia/abtesting": "1.1.0", "@algolia/client-abtesting": "5.35.0", @@ -10110,7 +10428,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001733", "electron-to-chromium": "^1.5.199", @@ -10488,6 +10805,35 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/chevrotain-allstar": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.3.1.tgz", + "integrity": "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==", + "dependencies": { + "lodash-es": "^4.17.21" + }, + "peerDependencies": { + "chevrotain": "^11.0.0" + } + }, + "node_modules/chevrotain/node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -11493,6 +11839,11 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==" + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -11756,6 +12107,14 @@ "node": ">= 0.10" } }, + "node_modules/cose-base": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-1.0.3.tgz", + "integrity": "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==", + "dependencies": { + "layout-base": "^1.0.0" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -11946,7 +12305,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -12166,131 +12524,596 @@ "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", "license": "MIT", "dependencies": { - "autoprefixer": "^10.4.19", - "browserslist": "^4.23.0", - "cssnano-preset-default": "^6.1.2", - "postcss-discard-unused": "^6.0.5", - "postcss-merge-idents": "^6.0.3", - "postcss-reduce-idents": "^6.0.3", - "postcss-zindex": "^6.0.2" + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/cwd": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.9.1.tgz", + "integrity": "sha512-4+0D+ojEasdLndYX4Cqff057I/Jp6ysXpwKkdLQLnZxV8f6IYZmZtTP5uqD91a/kWqejoc0sSqK4u8wpTKCh8A==", + "dependencies": { + "find-pkg": "^0.1.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cyclist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==" + }, + "node_modules/cytoscape": { + "version": "3.33.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", + "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/cytoscape-cose-bilkent": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz", + "integrity": "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==", + "dependencies": { + "cose-base": "^1.0.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cytoscape-fcose/-/cytoscape-fcose-2.2.0.tgz", + "integrity": "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==", + "dependencies": { + "cose-base": "^2.2.0" + }, + "peerDependencies": { + "cytoscape": "^3.2.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/cose-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cose-base/-/cose-base-2.2.0.tgz", + "integrity": "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==", + "dependencies": { + "layout-base": "^2.0.0" + } + }, + "node_modules/cytoscape-fcose/node_modules/layout-base": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-2.0.1.tgz", + "integrity": "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==" + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-sankey": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/d3-sankey/-/d3-sankey-0.12.3.tgz", + "integrity": "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==", + "dependencies": { + "d3-array": "1 - 2", + "d3-shape": "^1.2.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-array": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.12.1.tgz", + "integrity": "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==", + "dependencies": { + "internmap": "^1.0.0" + } + }, + "node_modules/d3-sankey/node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "node_modules/d3-sankey/node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-sankey/node_modules/internmap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.1.tgz", + "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==" + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" }, "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "node": ">=12" } }, - "node_modules/cssnano-preset-default": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", - "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", - "license": "MIT", + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", "dependencies": { - "browserslist": "^4.23.0", - "css-declaration-sorter": "^7.2.0", - "cssnano-utils": "^4.0.2", - "postcss-calc": "^9.0.1", - "postcss-colormin": "^6.1.0", - "postcss-convert-values": "^6.1.0", - "postcss-discard-comments": "^6.0.2", - "postcss-discard-duplicates": "^6.0.3", - "postcss-discard-empty": "^6.0.3", - "postcss-discard-overridden": "^6.0.2", - "postcss-merge-longhand": "^6.0.5", - "postcss-merge-rules": "^6.1.1", - "postcss-minify-font-values": "^6.1.0", - "postcss-minify-gradients": "^6.0.3", - "postcss-minify-params": "^6.1.0", - "postcss-minify-selectors": "^6.0.4", - "postcss-normalize-charset": "^6.0.2", - "postcss-normalize-display-values": "^6.0.2", - "postcss-normalize-positions": "^6.0.2", - "postcss-normalize-repeat-style": "^6.0.2", - "postcss-normalize-string": "^6.0.2", - "postcss-normalize-timing-functions": "^6.0.2", - "postcss-normalize-unicode": "^6.1.0", - "postcss-normalize-url": "^6.0.2", - "postcss-normalize-whitespace": "^6.0.2", - "postcss-ordered-values": "^6.0.2", - "postcss-reduce-initial": "^6.1.0", - "postcss-reduce-transforms": "^6.0.2", - "postcss-svgo": "^6.0.3", - "postcss-unique-selectors": "^6.0.4" + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" }, "engines": { - "node": "^14 || ^16 || >=18.0" - }, - "peerDependencies": { - "postcss": "^8.4.31" + "node": ">=12" } }, - "node_modules/cssnano-utils": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", - "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", - "license": "MIT", + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "engines": { - "node": "^14 || ^16 || >=18.0" + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" }, - "peerDependencies": { - "postcss": "^8.4.31" + "engines": { + "node": ">=12" } }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "license": "MIT", + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "dependencies": { - "css-tree": "~2.2.0" + "d3-array": "2 - 3" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">=12" } }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "license": "MIT", + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" + "d3-time": "1 - 3" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" + "node": ">=12" } }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "license": "CC0-1.0" + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } }, - "node_modules/cwd": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.9.1.tgz", - "integrity": "sha512-4+0D+ojEasdLndYX4Cqff057I/Jp6ysXpwKkdLQLnZxV8f6IYZmZtTP5uqD91a/kWqejoc0sSqK4u8wpTKCh8A==", + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "dependencies": { - "find-pkg": "^0.1.0" + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" }, "engines": { - "node": ">=0.8" + "node": ">=12" } }, - "node_modules/cyclist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", - "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==" + "node_modules/dagre-d3-es": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/dagre-d3-es/-/dagre-d3-es-7.0.13.tgz", + "integrity": "sha512-efEhnxpSuwpYOKRm/L5KbqoZmNNukHa/Flty4Wp62JRvgH2ojwVgPgdYyr4twpieZnyRDdIH7PY2mopX26+j2Q==", + "dependencies": { + "d3": "^7.9.0", + "lodash-es": "^4.17.21" + } }, "node_modules/datauri": { "version": "3.0.0", @@ -12318,6 +13141,11 @@ "node": ">=6.9.0" } }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==" + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", @@ -12468,6 +13296,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delaunator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz", + "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -12663,6 +13499,17 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -13559,7 +14406,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13831,7 +14677,6 @@ "version": "12.23.12", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.12.tgz", "integrity": "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==", - "peer": true, "dependencies": { "motion-dom": "^12.23.12", "motion-utils": "^12.23.6", @@ -14390,6 +15235,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/hachure-fill": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/hachure-fill/-/hachure-fill-0.5.2.tgz", + "integrity": "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==" + }, "node_modules/handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -15391,6 +16241,14 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" + } + }, "node_modules/intl-messageformat": { "version": "10.7.16", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz", @@ -16362,6 +17220,29 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/katex": { + "version": "0.16.27", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", + "integrity": "sha512-aeQoDkuRWSqQN6nSvVCEFvfXdqo1OQiCmmW1kc9xSdjutPv7BGO7pqY9sQRJpMOGrEdfDgF2TfRXe5eUAD2Waw==", + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -16371,6 +17252,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/khroma": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", + "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -16389,6 +17275,21 @@ "node": ">=6" } }, + "node_modules/langium": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", + "integrity": "sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==", + "dependencies": { + "chevrotain": "~11.0.3", + "chevrotain-allstar": "~0.3.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", + "vscode-uri": "~3.0.8" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/latest-version": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", @@ -16414,6 +17315,11 @@ "shell-quote": "^1.8.3" } }, + "node_modules/layout-base": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", + "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==" + }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -16524,6 +17430,11 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash-es": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", + "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==" + }, "node_modules/lodash-id": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/lodash-id/-/lodash-id-0.14.1.tgz", @@ -17375,6 +18286,61 @@ "node": ">= 8" } }, + "node_modules/mermaid": { + "version": "11.12.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.12.2.tgz", + "integrity": "sha512-n34QPDPEKmaeCG4WDMGy0OT6PSyxKCfy2pJgShP+Qow2KLrvWjclwbc3yXfSIf4BanqWEhQEpngWwNp/XhZt6w==", + "dependencies": { + "@braintree/sanitize-url": "^7.1.1", + "@iconify/utils": "^3.0.1", + "@mermaid-js/parser": "^0.6.3", + "@types/d3": "^7.4.3", + "cytoscape": "^3.29.3", + "cytoscape-cose-bilkent": "^4.1.0", + "cytoscape-fcose": "^2.2.0", + "d3": "^7.9.0", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.13", + "dayjs": "^1.11.18", + "dompurify": "^3.2.5", + "katex": "^0.16.22", + "khroma": "^2.1.0", + "lodash-es": "^4.17.21", + "marked": "^16.2.1", + "roughjs": "^4.6.6", + "stylis": "^4.3.6", + "ts-dedent": "^2.2.0", + "uuid": "^11.1.0" + } + }, + "node_modules/mermaid/node_modules/marked": { + "version": "16.4.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.2.tgz", + "integrity": "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/mermaid/node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==" + }, + "node_modules/mermaid/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/method-override": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", @@ -19351,6 +20317,17 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, "node_modules/morgan": { "version": "1.10.1", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", @@ -19693,7 +20670,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -20091,6 +21067,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==" + }, "node_modules/pacote": { "version": "2.7.38", "resolved": "https://registry.npmjs.org/pacote/-/pacote-2.7.38.tgz", @@ -20348,6 +21329,11 @@ "tslib": "^2.0.3" } }, + "node_modules/path-data-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", + "integrity": "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==" + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -20405,6 +21391,11 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -20447,6 +21438,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/please-upgrade-node": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", @@ -20465,6 +21466,20 @@ "node": ">=4" } }, + "node_modules/points-on-curve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/points-on-curve/-/points-on-curve-0.2.0.tgz", + "integrity": "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==" + }, + "node_modules/points-on-path": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/points-on-path/-/points-on-path-0.2.1.tgz", + "integrity": "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==", + "dependencies": { + "path-data-parser": "0.1.0", + "points-on-curve": "0.2.0" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -20492,7 +21507,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -21396,7 +22410,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -22305,7 +23318,6 @@ "version": "19.1.1", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -22474,6 +23486,7 @@ "version": "0.19.1", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -22483,7 +23496,6 @@ "version": "19.1.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", - "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -22548,7 +23560,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -22589,7 +23600,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -23488,6 +24498,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/roughjs": { + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/roughjs/-/roughjs-4.6.6.tgz", + "integrity": "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==", + "dependencies": { + "hachure-fill": "^0.5.2", + "path-data-parser": "^0.1.0", + "points-on-curve": "^0.2.0", + "points-on-path": "^0.2.1" + } + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", @@ -23570,6 +24596,11 @@ "aproba": "^1.1.1" } }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -24544,7 +25575,6 @@ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz", "integrity": "sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g==", "hasInstallScript": true, - "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.0.0", @@ -24603,8 +25633,7 @@ "node_modules/stylis": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", - "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==", - "peer": true + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" }, "node_modules/stylis-rule-sheet": { "version": "0.0.10", @@ -24682,7 +25711,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz", "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/dcastil" @@ -25068,6 +26096,14 @@ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "engines": { + "node": ">=18" + } + }, "node_modules/tinypool": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", @@ -25166,6 +26202,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "engines": { + "node": ">=6.10" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -25252,7 +26296,6 @@ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -25261,6 +26304,11 @@ "node": ">=14.17" } }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==" + }, "node_modules/undici-types": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", @@ -25618,7 +26666,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -25858,6 +26905,49 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" + }, + "node_modules/vscode-uri": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" + }, "node_modules/watchpack": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", @@ -25895,7 +26985,6 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.1.tgz", "integrity": "sha512-rHY3vHXRbkSfhG6fH8zYQdth/BtDgXXuR2pHF++1f/EBkI8zkgM5XWfsC3BvOoW9pr1CvZ1qQCxhCEsbNgT50g==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", diff --git a/mie-opensource-landing/package.json b/mie-opensource-landing/package.json index 30b177b3..c0a36feb 100644 --- a/mie-opensource-landing/package.json +++ b/mie-opensource-landing/package.json @@ -20,6 +20,7 @@ "dependencies": { "@docusaurus/core": "3.8.1", "@docusaurus/preset-classic": "3.8.1", + "@docusaurus/theme-mermaid": "^3.8.1", "@heroui/react": "^2.8.2", "@heroui/snippet": "^2.2.25", "@heroui/system": "^2.4.20", @@ -33,6 +34,7 @@ "beautiful-backgrounds": "^0.0.7", "clsx": "^2.0.0", "cors": "^2.8.5", + "dotenv": "^17.2.3", "express": "^5.1.0", "framer-motion": "^12.23.12", "http-proxy-middleware": "^3.0.5", diff --git a/mie-opensource-landing/proxy-server.js b/mie-opensource-landing/proxy-server.js deleted file mode 100644 index 5f14f7c4..00000000 --- a/mie-opensource-landing/proxy-server.js +++ /dev/null @@ -1,29 +0,0 @@ -const express = require('express'); -const { createProxyMiddleware } = require('http-proxy-middleware'); -const cors = require('cors'); - -const app = express(); - -app.use(cors({ - origin: '*', - credentials: true -})); - -// Create proxy middleware -const apiProxy = createProxyMiddleware({ - target: 'http://10.15.20.69:3001', - changeOrigin: true, - pathRewrite: { - '^/api/projects': '', - } -}); - -const apiAllProjectsProxy = createProxyMiddleware({ - target: 'http://10.15.20.69:3001/keys', - changeOrigin: true, -}); - -// Use the proxy middleware -app.use('/api/projects', apiProxy); -app.use('/api/all-projects', apiAllProjectsProxy); -app.listen(3001); \ No newline at end of file diff --git a/mie-opensource-landing/src/components/InstanceUrl/index.tsx b/mie-opensource-landing/src/components/InstanceUrl/index.tsx new file mode 100644 index 00000000..bc02f5e9 --- /dev/null +++ b/mie-opensource-landing/src/components/InstanceUrl/index.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +export const ProxmoxUrl = ({ children }: { children?: React.ReactNode }) => { + const { siteConfig } = useDocusaurusContext(); + const url = siteConfig.customFields.proxmoxUrl as string; + return children ? {children} : <>{url}; +}; + +export const ContainerCreationUrl = ({ children }: { children?: React.ReactNode }) => { + const { siteConfig } = useDocusaurusContext(); + const url = siteConfig.customFields.containerCreationUrl as string; + return children ? {children} : <>{url}; +}; diff --git a/mie-opensource-landing/src/components/projectGrid/index.module.css b/mie-opensource-landing/src/components/projectGrid/index.module.css deleted file mode 100644 index 29b163db..00000000 --- a/mie-opensource-landing/src/components/projectGrid/index.module.css +++ /dev/null @@ -1,128 +0,0 @@ -/* PROJECT SHOWCASE SECTION */ - -.projectShowcase { - display: flex; - flex-direction: column; - align-items: center; - padding: 1rem 0 1rem 0; - width: 100%; - max-width: 1200px; - margin: 0 auto; /* Center it */ -} - -.projectGrid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); - gap: 2rem; - width: 100%; - margin-bottom: 2.5rem; -} - -.projectCard { - border-radius: 10px; - padding: 1.0rem; - transition: transform 0.3s ease; - border: 0.5px solid var(--ifm-color-gray-400); -} - -.projectHeader { - display: flex; - align-items: top; - justify-content: space-between; - min-height: 5rem; - margin-bottom: 0.5rem; -} - -.projectInfo { - max-width: 80%; - margin-bottom: 0 !important; - padding-bottom: 0 !important; -} - -.projectName { - font-size: 1.2rem; - font-weight: 600; - margin-bottom: 0.25rem !important; - padding-bottom: 0 !important; - line-height: 1.3; - overflow: hidden; -} - -.projectAuthor { - font-size: 0.9rem; - color: #666; - margin: 0 !important; - padding: 0 !important; - line-height: 1.2; -} - -.projectDescription { - font-size: 0.9rem; - color: var(--ifm-color-gray-700); - margin-bottom: 1rem; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - min-height: 3rem; -} - -/* PAGINATION STYLES */ - -.pagination { - display: flex; - justify-content: center; - align-items: center; - margin-top: 2rem; - list-style: none; - padding: 0; -} - -.pageItem { - margin: 0 0.35rem; -} - -.pageLink { - display: block; - padding: 0.25rem 0.65rem 0.25rem 0.65rem; - color: var(--ifm-color-primary); - text-decoration: none; - border: 0.5px solid var(--ifm-color-primary-light); - border-radius: 0.25rem; - transition: all 0.2s; -} - -.activePage { - background-color: var(--ifm-color-primary); - border-radius: 0.25rem; - transition: all 0.2s; - text-decoration: none; -} - -.activeLinkPage { - color: #fff; -} - -.pageLink:hover { - background-color: var(--ifm-color-primary-lightest); - border-color: var(--ifm-color-primary-lightest); - color: #fff; - cursor: pointer; -} - -.pageItem:hover { - cursor: pointer; -} - -.TextField { - --vaadin-input-field-background: var(--ifm-color-gray-200) !important; - --vaadin-input-field-border-radius: 15px !important; - width: 300px; - margin-bottom: 2rem; -} - -.Button:hover { - cursor: pointer; -} - diff --git a/mie-opensource-landing/src/components/projectGrid/index.tsx b/mie-opensource-landing/src/components/projectGrid/index.tsx deleted file mode 100644 index 7e2d2f55..00000000 --- a/mie-opensource-landing/src/components/projectGrid/index.tsx +++ /dev/null @@ -1,235 +0,0 @@ -import styles from "./index.module.css"; -import React, { useEffect, useRef, useState } from "react"; -import BrowserOnly from '@docusaurus/BrowserOnly'; -import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; -import { GrGithub } from "react-icons/gr"; -import Link from "@docusaurus/Link"; -import ReactPaginate from 'react-paginate'; -import { TextField } from "@vaadin/react-components/TextField.js"; -import { Tooltip } from "@vaadin/react-components/Tooltip.js"; -import { Icon } from "@vaadin/react-components/Icon.js"; - -interface ProjectDetails { - name: string; - description: string; - author: string; - projectURL: string; - gitHubURL: string; -} - -interface ProjectGridProps { - ProjectList?: string[]; - itemsPerPage?: number; -} - -function useThemeAttribute() { - const [theme, setTheme] = useState(null); - - useEffect(() => { - if (!ExecutionEnvironment.canUseDOM) { - return; - } - - const initialTheme = document.documentElement.getAttribute('data-theme'); - setTheme(initialTheme); - - const observer = new MutationObserver((mutations) => { - mutations.forEach((mutation) => { - if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') { - const newTheme = document.documentElement.getAttribute('data-theme'); - setTheme(newTheme); - } - }); - }); - - observer.observe(document.documentElement, { - attributes: true, - attributeFilter: ['data-theme'] - }); - - return () => observer.disconnect(); - }, []); - - return theme; -} - -export default function ProjectGrid({ ProjectList, itemsPerPage }: ProjectGridProps) { - const [projectDetails, setProjectDetails] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - const fetchProjectDetails = async () => { - let projectsToShowCase: string[]; - if ( !ProjectList || ProjectList.length === 0) { - projectsToShowCase = ["vistamate", "mieweb-timeharbor-main", "landing-page", "lattln-questionnaire-builder-main", "mieapi-mcp-server", "rankroom"]; - } else { - const response = await fetch('/api/all-projects'); - projectsToShowCase = await response.json(); - } - - try { - const promises = projectsToShowCase.map(async (project) => { - const response = await fetch(`/api/projects/${project}`); - - if (!response.ok) { - throw new Error(`Failed to fetch ${project}`); - } - const data = await response.json(); - return { - name: project, - description: data.description || "No description available", - author: data.owner || "Unknown", - projectURL: `https://${project}.opensource.mieweb.org`, - gitHubURL: data.github_url - }; - }); - - const results = await Promise.all(promises); - setProjectDetails(results); - } catch (err) { - console.error('Error fetching project details:', err); - setError(err instanceof Error ? err.message : 'Failed to fetch projects'); - } finally { - setLoading(false); - } - }; - - fetchProjectDetails(); - }, []); - - if (loading) { - return ( -
-

Loading projects...

-
- ); - } - - if (error) { - return ( -
-

Error loading projects: {error}

-
- ); - } - - return ( - Loading projects...}> - {() => } - - ); -} - -function ProjectGridClient({ projectDetails, itemsPerPage }: { projectDetails: ProjectDetails[], itemsPerPage?: number }) { - const [projectsToShowCase, setProjectsToShowCase] = useState(projectDetails); - const [filteredProjects, setFilteredProjects] = useState([]); - const theme = useThemeAttribute(); - - //Pagination - const [itemOffset, setItemOffset] = useState(0); - const [pageCount, setPageCount] = useState(0); - const filterPagination = useRef(false); - - useEffect(() => { - setProjectsToShowCase(projectDetails); - }, [projectDetails]); - - useEffect(() => { - if (itemsPerPage === undefined) return; - console.log(filterPagination.current) - if (filterPagination.current) { - const endOffset = itemOffset + itemsPerPage; - setProjectsToShowCase(filteredProjects.slice(itemOffset, endOffset)); - setPageCount(Math.ceil(filteredProjects.length / itemsPerPage)); - } else { - const endOffset = itemOffset + itemsPerPage; - setProjectsToShowCase(projectDetails.slice(itemOffset, endOffset)); - setPageCount(Math.ceil(projectDetails.length / itemsPerPage)); - } - }, [projectDetails, itemOffset, itemsPerPage, filteredProjects]); - - const handlePageClick = (event: { selected: number }) => { - const newOffset = (event.selected * itemsPerPage) % projectDetails.length; - setItemOffset(newOffset); - }; - - const { Button } = require("@vaadin/react-components/Button.js"); - require('@vaadin/icons'); - - const searchProjects = (event: Event) => { - - const target = event.target as HTMLInputElement; - if (target.value.length < 1) { - filterPagination.current = false; - setProjectsToShowCase(projectDetails); - } - - const value = target.value || ""; - let searchFilterResults = projectDetails.filter(project => - project.name.toLowerCase().includes(value.toLowerCase()) || - project.description.toLowerCase().includes(value.toLowerCase()) || - project.author.toLowerCase().includes(value.toLowerCase()) - ); - - setFilteredProjects(searchFilterResults); - filterPagination.current = true; - setItemOffset(0); - }; - - return ( -
- {itemsPerPage && - - - - - } -
- {projectsToShowCase.map((project) => ( -
-
-
-

{project.name}

-

{project.author}

-
- {project.gitHubURL && project.gitHubURL !== "" && - - - - } -
-

{project.description}

- - - -
- ))} -
- <> - {itemsPerPage && pageCount > 1 && - - } - -
- ); -} \ No newline at end of file diff --git a/mie-opensource-landing/src/hooks/useInstanceUrls.ts b/mie-opensource-landing/src/hooks/useInstanceUrls.ts new file mode 100644 index 00000000..3d734929 --- /dev/null +++ b/mie-opensource-landing/src/hooks/useInstanceUrls.ts @@ -0,0 +1,9 @@ +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; + +export const useInstanceUrls = () => { + const { siteConfig } = useDocusaurusContext(); + return { + proxmoxUrl: siteConfig.customFields.proxmoxUrl as string, + containerCreationUrl: siteConfig.customFields.containerCreationUrl as string, + }; +}; diff --git a/mie-opensource-landing/src/pages/index.tsx b/mie-opensource-landing/src/pages/index.tsx index e271263f..ca2e9cf7 100644 --- a/mie-opensource-landing/src/pages/index.tsx +++ b/mie-opensource-landing/src/pages/index.tsx @@ -9,6 +9,7 @@ import Heading from "@theme/Heading"; import Link from "@docusaurus/Link"; import SyntaxHighlighter from 'react-syntax-highlighter'; import { github } from 'react-syntax-highlighter/dist/esm/styles/hljs'; +import { useInstanceUrls } from "@site/src/hooks/useInstanceUrls"; function HomepageHeader() { return ( @@ -25,11 +26,6 @@ function HomepageHeader() { return ( - Predefined templates - + Get started with containers → @@ -162,14 +158,14 @@ function ManagingContainers({GrAdd, GrView, Snippet, Button, Icon, FaCode, FaTer

- + - SSH Command + API with curl

-

Get started quickly with Docker by running a simple container. This command creates and starts a new nginx web server container in detached mode.

- - {"ssh create-container@opensource.mieweb.org"} - +

Create containers programmatically using our REST API. Authenticate with your credentials and configure services through simple HTTP requests.

+ + View API documentation → +

@@ -179,7 +175,7 @@ function ManagingContainers({GrAdd, GrView, Snippet, Button, Icon, FaCode, FaTer Use the Web GUI

Deploy and manage containers easily through the Proxmox Web GUI. While this approach is less flexible for more complex container setups, its a lot faster.

- + - -
); diff --git a/mie-opensource-landing/src/pages/projects/index.module.css b/mie-opensource-landing/src/pages/projects/index.module.css deleted file mode 100644 index 07b9f06e..00000000 --- a/mie-opensource-landing/src/pages/projects/index.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.projectShowcase { - display: flex; - flex-direction: column; - align-items: center; - padding: 2rem; -} - -.projectHeaderOverlay{ - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-image: - linear-gradient(rgba(200, 200, 200, 0.4) 1px, transparent 1px), - linear-gradient(90deg, rgba(200, 200, 200, 0.4) 1px, transparent 1px); - background-size: 20px 20px; - height: 225px; - opacity: 0.6; -} \ No newline at end of file diff --git a/mie-opensource-landing/src/pages/projects/index.tsx b/mie-opensource-landing/src/pages/projects/index.tsx deleted file mode 100644 index 46e04df0..00000000 --- a/mie-opensource-landing/src/pages/projects/index.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import Layout from "@theme/Layout"; -import BrowserOnly from '@docusaurus/BrowserOnly'; -import React, { ReactNode } from "react"; -import Heading from "@theme/Heading"; -import styles from "./index.module.css"; - -export default function Home(): ReactNode { - const { siteConfig } = useDocusaurusContext(); - - return ( - -
-
-
- MIE Opensource Projects -

Explore our open source projects and contributions.

- Loading projects...
}> - {() => { - const ProjectGrid = require("@site/src/components/projectGrid").default; - return ; - }} - - -
-
- ); -} \ No newline at end of file diff --git a/mie-opensource-landing/systemd/opensource-docs.service b/mie-opensource-landing/systemd/opensource-docs.service new file mode 100644 index 00000000..f208987f --- /dev/null +++ b/mie-opensource-landing/systemd/opensource-docs.service @@ -0,0 +1,17 @@ +[Unit] +Description=Opensource Documentation Server +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/opensource-server/mie-opensource-landing +ExecStart=/usr/bin/npm run serve +Restart=on-failure +RestartSec=10s + +# Environment +Environment=NODE_ENV=production + +[Install] +WantedBy=multi-user.target diff --git a/mie-opensource-landing/tailwind.config.js b/mie-opensource-landing/tailwind.config.js deleted file mode 100644 index 49435b10..00000000 --- a/mie-opensource-landing/tailwind.config.js +++ /dev/null @@ -1,14 +0,0 @@ -// tailwind.config.js -const {heroui} = require("@heroui/theme"); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./node_modules/@heroui/theme/dist/components/(snippet|button|ripple|spinner|popover).js", - ], - theme: { - extend: {}, - }, - darkMode: "class", - plugins: [heroui()], -}; \ No newline at end of file