@@ -7,13 +7,17 @@ A web application for managing LXC container creation, configuration, and lifecy
77``` mermaid
88erDiagram
99 Node ||--o{ Container : "hosts"
10+ Node ||--o{ Volume : "stores"
1011 Container ||--o{ Service : "exposes"
12+ Container ||--o{ ContainerVolume : "mounts"
13+ ContainerVolume }o--|| Volume : "references"
1114
1215 Node {
1316 int id PK
1417 string name UK "Proxmox node name"
1518 string apiUrl "Proxmox API URL"
1619 boolean tlsVerify "Verify TLS certificates"
20+ int placeholderCtId "VMID for volume storage"
1721 datetime createdAt
1822 datetime updatedAt
1923 }
@@ -34,6 +38,27 @@ erDiagram
3438 datetime updatedAt
3539 }
3640
41+ Volume {
42+ int id PK
43+ string name "User-friendly name"
44+ string username "Owner username"
45+ string proxmoxVolume "Proxmox reference"
46+ int sizeGb "Size in GB"
47+ int siteId FK "References Site"
48+ int nodeId FK "References Node"
49+ datetime createdAt
50+ datetime updatedAt
51+ }
52+
53+ ContainerVolume {
54+ int id PK
55+ int containerId FK "References Container"
56+ int volumeId FK "References Volume"
57+ string mountPath "Mount point path"
58+ datetime createdAt
59+ datetime updatedAt
60+ }
61+
3762 Service {
3863 int id PK
3964 int containerId FK "References Container"
@@ -51,6 +76,9 @@ erDiagram
5176- ` (Node.name) ` - Unique
5277- ` (Container.hostname) ` - Unique
5378- ` (Container.nodeId, Container.containerId) ` - Unique (same VMID can exist on different nodes)
79+ - ` (Volume.username, Volume.name, Volume.siteId) ` - Unique (volume names unique per user per site)
80+ - ` (ContainerVolume.containerId, ContainerVolume.volumeId) ` - Unique (one attachment per volume per container)
81+ - ` (ContainerVolume.containerId, ContainerVolume.mountPath) ` - Unique (mount paths unique per container)
5482- ` (Service.externalHostname) ` - Unique when type='http'
5583- ` (Service.type, Service.externalPort) ` - Unique when type='tcp' or type='udp'
5684
@@ -59,6 +87,7 @@ erDiagram
5987- ** User Authentication** - Proxmox VE authentication integration
6088- ** Container Management** - Create, list, and track LXC containers
6189- ** Docker/OCI Support** - Pull and deploy containers from Docker Hub, GHCR, or any OCI registry
90+ - ** Persistent Volumes** - Named volumes that survive container deletion for data persistence
6291- ** Service Registry** - Track HTTP/TCP/UDP services running on containers
6392- ** Dynamic Nginx Config** - Generate nginx reverse proxy configurations on-demand
6493- ** Real-time Progress** - SSE (Server-Sent Events) for container creation progress
@@ -407,6 +436,75 @@ SELECT id, status FROM Jobs WHERE id = <ID>;
407436- Add batching or file-based logs for high-volume output to reduce DB pressure
408437- Implement job timeout/deadline and automatic cancellation
409438
439+ ### Volume Management Routes
440+
441+ #### ` GET /sites/:siteId/volumes ` (Auth Required)
442+ List all volumes owned by the authenticated user in a site
443+ - ** Returns** : HTML page with volume list
444+
445+ #### ` GET /sites/:siteId/volumes/new ` (Auth Required)
446+ Display volume creation form
447+ - ** Returns** : HTML page with form
448+
449+ #### ` POST /sites/:siteId/volumes ` (Auth Required)
450+ Create a new persistent volume
451+ - ** Body** : ` { name, nodeId } `
452+ - ` name ` : Volume name (alphanumeric, dash, underscore only)
453+ - ` nodeId ` : Node where the volume should be created
454+ - ** Process** :
455+ 1 . Allocates disk on the node's storage
456+ 2 . Attaches to the node's placeholder container
457+ 3 . Creates Volume record in database
458+ - ** Returns** : Redirect to volumes list
459+
460+ #### ` DELETE /sites/:siteId/volumes/:id ` (Auth Required)
461+ Delete a volume permanently
462+ - ** Path Parameter** : ` id ` - Volume database ID
463+ - ** Authorization** : User can only delete their own volumes
464+ - ** Validation** : Volume must not be attached to any container
465+ - ** Process** :
466+ 1 . Detaches from placeholder container
467+ 2 . Deletes disk from Proxmox storage
468+ 3 . Removes Volume record from database
469+ - ** Returns** : ` { success: true, message: "Volume deleted successfully" } `
470+ - ** Errors** :
471+ - ` 400 ` - Volume is currently attached to a container
472+ - ` 403 ` - User doesn't own the volume
473+ - ` 404 ` - Volume not found
474+
475+ ### Volume Attachment
476+
477+ Volumes can be attached to containers during container creation:
478+
479+ #### During ` POST /sites/:siteId/containers `
480+ - ** Additional Body Fields** :
481+ - ` volumes ` : Array of volume attachments
482+ - ` volumes[N][volumeId] ` : Volume ID to attach
483+ - ` volumes[N][mountPath] ` : Mount point inside container (e.g., ` /data ` )
484+ - ** Process** :
485+ 1 . Validates all volumes exist and are owned by user
486+ 2 . Validates volumes are on the same node as the target container
487+ 3 . Creates container and ContainerVolume records
488+ 4 . Job runner moves volumes from placeholder to new container
489+ - ** Note** : Cross-node volume attachment requires manual migration
490+
491+ #### During ` DELETE /sites/:siteId/containers/:id `
492+ When a container with attached volumes is deleted:
493+ 1 . All attached volumes are transferred to the placeholder container
494+ 2 . ContainerVolume records are deleted
495+ 3 . Volume records are preserved (data persists)
496+ 4 . Volumes can be reattached to new containers
497+
498+ ### Placeholder Container
499+
500+ Each Proxmox node has a "placeholder container" for volume storage:
501+
502+ - ** Purpose** : Holds volumes not attached to user containers
503+ - ** Auto-creation** : Created when node is registered
504+ - ** Configuration** : Minimal Alpine, 16MB RAM, no network, protection enabled
505+ - ** VMID** : Stored in ` Node.placeholderCtId `
506+ - ** Never started** : Exists only to own volumes
507+
410508### Configuration Routes
411509
412510#### ` GET /nginx.conf `
0 commit comments