openapi: 3.0.3 info: title: AtlasOS Storage Controller API description: | REST API for managing ZFS storage, storage services (SMB/NFS/iSCSI), snapshots, and system configuration. ## Authentication Most endpoints require authentication via JWT token. Include the token in the Authorization header: ``` Authorization: Bearer ``` ## Roles - **Administrator**: Full system access - **Operator**: Storage and service operations - **Viewer**: Read-only access version: 1.0.0 contact: name: AtlasOS Support url: https://github.com/atlasos servers: - url: http://localhost:8080 description: Local development server - url: https://atlas.example.com description: Production server tags: - name: Authentication description: User authentication and authorization - name: Users description: User management (Administrator only) - name: ZFS description: ZFS pool, dataset, and ZVOL management - name: Snapshots description: Snapshot management and policies - name: Storage Services description: SMB, NFS, and iSCSI service management - name: Jobs description: Background job management - name: Audit description: Audit log access - name: System description: System health and metrics paths: /api/v1/auth/login: post: tags: - Authentication summary: Authenticate user description: Login with username and password to receive JWT token operationId: login requestBody: required: true content: application/json: schema: type: object required: - username - password properties: username: type: string example: admin password: type: string format: password example: admin responses: '200': description: Login successful content: application/json: schema: type: object properties: token: type: string description: JWT token for authentication user: $ref: '#/components/schemas/User' expires_in: type: integer description: Token expiration in seconds example: 86400 '401': $ref: '#/components/responses/Unauthorized' '400': $ref: '#/components/responses/BadRequest' /api/v1/auth/logout: post: tags: - Authentication summary: Logout user description: Logout (client-side token removal for stateless JWT) operationId: logout security: - bearerAuth: [] responses: '200': description: Logout successful content: application/json: schema: type: object properties: message: type: string example: logged out /api/v1/users: get: tags: - Users summary: List users description: List all users (requires authentication) operationId: listUsers security: - bearerAuth: [] responses: '200': description: List of users content: application/json: schema: type: array items: $ref: '#/components/schemas/User' post: tags: - Users summary: Create user description: Create a new user (Administrator only) operationId: createUser security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - username - password properties: username: type: string email: type: string format: email password: type: string format: password role: $ref: '#/components/schemas/Role' responses: '201': description: User created content: application/json: schema: $ref: '#/components/schemas/User' '400': $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' '403': $ref: '#/components/responses/Forbidden' '409': $ref: '#/components/responses/Conflict' /api/v1/users/{id}: get: tags: - Users summary: Get user operationId: getUser security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/UserId' responses: '200': description: User details content: application/json: schema: $ref: '#/components/schemas/User' '404': $ref: '#/components/responses/NotFound' put: tags: - Users summary: Update user description: Update user (Administrator only) operationId: updateUser security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/UserId' requestBody: required: true content: application/json: schema: type: object properties: email: type: string format: email role: $ref: '#/components/schemas/Role' active: type: boolean responses: '200': description: User updated content: application/json: schema: $ref: '#/components/schemas/User' '404': $ref: '#/components/responses/NotFound' delete: tags: - Users summary: Delete user description: Delete user (Administrator only, cannot delete yourself) operationId: deleteUser security: - bearerAuth: [] parameters: - $ref: '#/components/parameters/UserId' responses: '200': description: User deleted '400': $ref: '#/components/responses/BadRequest' '404': $ref: '#/components/responses/NotFound' /api/v1/pools: get: tags: - ZFS summary: List ZFS pools operationId: listPools security: - bearerAuth: [] responses: '200': description: List of ZFS pools content: application/json: schema: type: array items: $ref: '#/components/schemas/Pool' post: tags: - ZFS summary: Create ZFS pool operationId: createPool security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name - vdevs properties: name: type: string example: tank vdevs: type: array items: type: string example: ["/dev/sdb", "/dev/sdc"] options: type: object additionalProperties: type: string responses: '201': description: Pool created content: application/json: schema: $ref: '#/components/schemas/Pool' /api/v1/pools/{name}: get: tags: - ZFS summary: Get pool details operationId: getPool security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Pool details content: application/json: schema: $ref: '#/components/schemas/Pool' '404': $ref: '#/components/responses/NotFound' delete: tags: - ZFS summary: Delete pool operationId: deletePool security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Pool deleted '404': $ref: '#/components/responses/NotFound' /api/v1/pools/{name}/scrub: post: tags: - ZFS summary: Scrub pool operationId: scrubPool security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Scrub started content: application/json: schema: type: object properties: message: type: string example: scrub started /api/v1/datasets: get: tags: - ZFS summary: List datasets operationId: listDatasets security: - bearerAuth: [] parameters: - name: pool in: query schema: type: string description: Filter by pool name responses: '200': description: List of datasets content: application/json: schema: type: array items: $ref: '#/components/schemas/Dataset' post: tags: - ZFS summary: Create dataset operationId: createDataset security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string example: tank/data options: type: object additionalProperties: type: string responses: '201': description: Dataset created content: application/json: schema: $ref: '#/components/schemas/Dataset' /api/v1/datasets/{name}: get: tags: - ZFS summary: Get dataset operationId: getDataset security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Dataset details content: application/json: schema: $ref: '#/components/schemas/Dataset' '404': $ref: '#/components/responses/NotFound' put: tags: - ZFS summary: Update dataset operationId: updateDataset security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: options: type: object additionalProperties: type: string responses: '200': description: Dataset updated content: application/json: schema: $ref: '#/components/schemas/Dataset' delete: tags: - ZFS summary: Delete dataset operationId: deleteDataset security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Dataset deleted '404': $ref: '#/components/responses/NotFound' /api/v1/zvols: get: tags: - ZFS summary: List ZVOLs operationId: listZVOLs security: - bearerAuth: [] parameters: - name: pool in: query schema: type: string description: Filter by pool name responses: '200': description: List of ZVOLs content: application/json: schema: type: array items: $ref: '#/components/schemas/ZVOL' post: tags: - ZFS summary: Create ZVOL operationId: createZVOL security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name - size properties: name: type: string example: tank/block/vol1 size: type: string description: Size in human-readable format (e.g., "10G", "1T") example: 10G options: type: object additionalProperties: type: string responses: '201': description: ZVOL created content: application/json: schema: $ref: '#/components/schemas/ZVOL' /api/v1/zvols/{name}: get: tags: - ZFS summary: Get ZVOL operationId: getZVOL security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: ZVOL details content: application/json: schema: $ref: '#/components/schemas/ZVOL' '404': $ref: '#/components/responses/NotFound' delete: tags: - ZFS summary: Delete ZVOL operationId: deleteZVOL security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: ZVOL deleted '404': $ref: '#/components/responses/NotFound' /api/v1/snapshots: get: tags: - Snapshots summary: List snapshots operationId: listSnapshots security: - bearerAuth: [] parameters: - name: dataset in: query schema: type: string description: Filter by dataset name responses: '200': description: List of snapshots content: application/json: schema: type: array items: $ref: '#/components/schemas/Snapshot' post: tags: - Snapshots summary: Create snapshot operationId: createSnapshot security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - dataset - name properties: dataset: type: string example: tank/data name: type: string example: manual-20241215 responses: '201': description: Snapshot created content: application/json: schema: $ref: '#/components/schemas/Snapshot' /api/v1/snapshots/{name}: get: tags: - Snapshots summary: Get snapshot operationId: getSnapshot security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string description: Full snapshot name (dataset@snapshot) responses: '200': description: Snapshot details content: application/json: schema: $ref: '#/components/schemas/Snapshot' '404': $ref: '#/components/responses/NotFound' delete: tags: - Snapshots summary: Delete snapshot operationId: deleteSnapshot security: - bearerAuth: [] parameters: - name: name in: path required: true schema: type: string responses: '200': description: Snapshot deleted '404': $ref: '#/components/responses/NotFound' /api/v1/snapshot-policies: get: tags: - Snapshots summary: List snapshot policies operationId: listSnapshotPolicies security: - bearerAuth: [] responses: '200': description: List of snapshot policies content: application/json: schema: type: array items: $ref: '#/components/schemas/SnapshotPolicy' post: tags: - Snapshots summary: Create snapshot policy operationId: createSnapshotPolicy security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SnapshotPolicy' responses: '201': description: Policy created content: application/json: schema: $ref: '#/components/schemas/SnapshotPolicy' /api/v1/snapshot-policies/{dataset}: get: tags: - Snapshots summary: Get snapshot policy operationId: getSnapshotPolicy security: - bearerAuth: [] parameters: - name: dataset in: path required: true schema: type: string responses: '200': description: Policy details content: application/json: schema: $ref: '#/components/schemas/SnapshotPolicy' '404': $ref: '#/components/responses/NotFound' put: tags: - Snapshots summary: Update snapshot policy operationId: updateSnapshotPolicy security: - bearerAuth: [] parameters: - name: dataset in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SnapshotPolicy' responses: '200': description: Policy updated content: application/json: schema: $ref: '#/components/schemas/SnapshotPolicy' delete: tags: - Snapshots summary: Delete snapshot policy operationId: deleteSnapshotPolicy security: - bearerAuth: [] parameters: - name: dataset in: path required: true schema: type: string responses: '200': description: Policy deleted '404': $ref: '#/components/responses/NotFound' /api/v1/shares/smb: get: tags: - Storage Services summary: List SMB shares operationId: listSMBShares security: - bearerAuth: [] responses: '200': description: List of SMB shares content: application/json: schema: type: array items: $ref: '#/components/schemas/SMBShare' post: tags: - Storage Services summary: Create SMB share operationId: createSMBShare security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name - dataset properties: name: type: string example: data path: type: string description: Mount point path (auto-filled from dataset if not provided) dataset: type: string example: tank/data description: type: string read_only: type: boolean default: false guest_ok: type: boolean default: false valid_users: type: array items: type: string responses: '201': description: Share created content: application/json: schema: $ref: '#/components/schemas/SMBShare' /api/v1/shares/smb/{id}: get: tags: - Storage Services summary: Get SMB share operationId: getSMBShare security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Share details content: application/json: schema: $ref: '#/components/schemas/SMBShare' '404': $ref: '#/components/responses/NotFound' put: tags: - Storage Services summary: Update SMB share operationId: updateSMBShare security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: description: type: string read_only: type: boolean guest_ok: type: boolean enabled: type: boolean valid_users: type: array items: type: string responses: '200': description: Share updated content: application/json: schema: $ref: '#/components/schemas/SMBShare' delete: tags: - Storage Services summary: Delete SMB share operationId: deleteSMBShare security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Share deleted '404': $ref: '#/components/responses/NotFound' /api/v1/exports/nfs: get: tags: - Storage Services summary: List NFS exports operationId: listNFSExports security: - bearerAuth: [] responses: '200': description: List of NFS exports content: application/json: schema: type: array items: $ref: '#/components/schemas/NFSExport' post: tags: - Storage Services summary: Create NFS export operationId: createNFSExport security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - dataset properties: path: type: string description: Mount point path (auto-filled from dataset if not provided) dataset: type: string example: tank/data clients: type: array items: type: string description: Allowed clients (CIDR or hostnames), default ["*"] example: ["192.168.1.0/24"] read_only: type: boolean default: false root_squash: type: boolean default: true responses: '201': description: Export created content: application/json: schema: $ref: '#/components/schemas/NFSExport' /api/v1/exports/nfs/{id}: get: tags: - Storage Services summary: Get NFS export operationId: getNFSExport security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Export details content: application/json: schema: $ref: '#/components/schemas/NFSExport' '404': $ref: '#/components/responses/NotFound' put: tags: - Storage Services summary: Update NFS export operationId: updateNFSExport security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: clients: type: array items: type: string read_only: type: boolean root_squash: type: boolean enabled: type: boolean responses: '200': description: Export updated content: application/json: schema: $ref: '#/components/schemas/NFSExport' delete: tags: - Storage Services summary: Delete NFS export operationId: deleteNFSExport security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Export deleted '404': $ref: '#/components/responses/NotFound' /api/v1/iscsi/targets: get: tags: - Storage Services summary: List iSCSI targets operationId: listISCSITargets security: - bearerAuth: [] responses: '200': description: List of iSCSI targets content: application/json: schema: type: array items: $ref: '#/components/schemas/ISCSITarget' post: tags: - Storage Services summary: Create iSCSI target operationId: createISCSITarget security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - iqn properties: iqn: type: string description: iSCSI Qualified Name example: iqn.2024-12.com.atlas:storage.target1 initiators: type: array items: type: string description: Allowed initiator IQNs responses: '201': description: Target created content: application/json: schema: $ref: '#/components/schemas/ISCSITarget' /api/v1/iscsi/targets/{id}: get: tags: - Storage Services summary: Get iSCSI target operationId: getISCSITarget security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Target details content: application/json: schema: $ref: '#/components/schemas/ISCSITarget' '404': $ref: '#/components/responses/NotFound' put: tags: - Storage Services summary: Update iSCSI target operationId: updateISCSITarget security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object properties: initiators: type: array items: type: string enabled: type: boolean responses: '200': description: Target updated content: application/json: schema: $ref: '#/components/schemas/ISCSITarget' delete: tags: - Storage Services summary: Delete iSCSI target operationId: deleteISCSITarget security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Target deleted '404': $ref: '#/components/responses/NotFound' /api/v1/iscsi/targets/{id}/luns: post: tags: - Storage Services summary: Add LUN to target operationId: addLUN security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - zvol properties: zvol: type: string example: tank/block/vol1 responses: '201': description: LUN added content: application/json: schema: $ref: '#/components/schemas/LUN' '404': $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' /api/v1/iscsi/targets/{id}/luns/remove: post: tags: - Storage Services summary: Remove LUN from target operationId: removeLUN security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - lun_id properties: lun_id: type: integer example: 0 responses: '200': description: LUN removed '404': $ref: '#/components/responses/NotFound' /api/v1/jobs: get: tags: - Jobs summary: List jobs operationId: listJobs security: - bearerAuth: [] parameters: - name: status in: query schema: $ref: '#/components/schemas/JobStatus' description: Filter by job status responses: '200': description: List of jobs content: application/json: schema: type: array items: $ref: '#/components/schemas/Job' /api/v1/jobs/{id}: get: tags: - Jobs summary: Get job operationId: getJob security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Job details content: application/json: schema: $ref: '#/components/schemas/Job' '404': $ref: '#/components/responses/NotFound' /api/v1/jobs/{id}/cancel: post: tags: - Jobs summary: Cancel job operationId: cancelJob security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string responses: '200': description: Job cancelled '404': $ref: '#/components/responses/NotFound' /api/v1/audit: get: tags: - Audit summary: List audit logs operationId: listAuditLogs security: - bearerAuth: [] parameters: - name: actor in: query schema: type: string description: Filter by actor (user ID) - name: action in: query schema: type: string description: Filter by action (e.g., "pools.create") - name: resource in: query schema: type: string description: Filter by resource - name: limit in: query schema: type: integer default: 100 description: Limit number of results responses: '200': description: List of audit logs content: application/json: schema: type: array items: $ref: '#/components/schemas/AuditLog' /api/v1/dashboard: get: tags: - System summary: Get dashboard data operationId: getDashboard security: - bearerAuth: [] responses: '200': description: Dashboard statistics content: application/json: schema: type: object properties: storage: type: object properties: total_capacity: type: integer format: int64 pool_count: type: integer dataset_count: type: integer zvol_count: type: integer snapshot_count: type: integer services: type: object properties: smb_shares: type: integer nfs_exports: type: integer iscsi_targets: type: integer smb_status: type: boolean nfs_status: type: boolean iscsi_status: type: boolean jobs: type: object properties: total: type: integer running: type: integer completed: type: integer failed: type: integer /healthz: get: tags: - System summary: Health check operationId: healthz responses: '200': description: Service is healthy content: application/json: schema: type: object properties: status: type: string example: ok ts: type: string description: Request ID for correlation /metrics: get: tags: - System summary: Prometheus metrics operationId: metrics description: Returns metrics in Prometheus format responses: '200': description: Prometheus metrics content: text/plain: schema: type: string components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: JWT token obtained from /api/v1/auth/login parameters: UserId: name: id in: path required: true schema: type: string description: User ID schemas: User: type: object properties: id: type: string example: user-1 username: type: string example: admin email: type: string format: email example: admin@example.com role: $ref: '#/components/schemas/Role' active: type: boolean created_at: type: string format: date-time updated_at: type: string format: date-time Role: type: string enum: - administrator - operator - viewer example: administrator Pool: type: object properties: name: type: string example: tank status: type: string enum: [ONLINE, DEGRADED, FAULTED, OFFLINE] example: ONLINE size: type: integer format: int64 description: Total size in bytes allocated: type: integer format: int64 description: Allocated space in bytes free: type: integer format: int64 description: Free space in bytes health: type: string example: ONLINE created_at: type: string format: date-time Dataset: type: object properties: name: type: string example: tank/data pool: type: string example: tank type: type: string enum: [filesystem, volume] size: type: integer format: int64 used: type: integer format: int64 available: type: integer format: int64 mountpoint: type: string example: /tank/data created_at: type: string format: date-time ZVOL: type: object properties: name: type: string example: tank/block/vol1 pool: type: string example: tank size: type: integer format: int64 description: Size in bytes used: type: integer format: int64 created_at: type: string format: date-time Snapshot: type: object properties: name: type: string example: tank/data@hourly-20241215-143000 dataset: type: string example: tank/data size: type: integer format: int64 created_at: type: string format: date-time SnapshotPolicy: type: object properties: dataset: type: string example: tank/data frequent: type: integer description: Keep N frequent snapshots example: 4 hourly: type: integer description: Keep N hourly snapshots example: 24 daily: type: integer description: Keep N daily snapshots example: 7 weekly: type: integer description: Keep N weekly snapshots example: 4 monthly: type: integer description: Keep N monthly snapshots example: 12 yearly: type: integer description: Keep N yearly snapshots example: 2 autosnap: type: boolean description: Enable automatic snapshots autoprune: type: boolean description: Enable automatic pruning SMBShare: type: object properties: id: type: string example: smb-1 name: type: string example: data path: type: string example: /tank/data dataset: type: string example: tank/data description: type: string read_only: type: boolean guest_ok: type: boolean valid_users: type: array items: type: string enabled: type: boolean NFSExport: type: object properties: id: type: string example: nfs-1 path: type: string example: /tank/data dataset: type: string example: tank/data clients: type: array items: type: string example: ["192.168.1.0/24", "10.0.0.0/8"] read_only: type: boolean root_squash: type: boolean enabled: type: boolean ISCSITarget: type: object properties: id: type: string example: iscsi-1 iqn: type: string example: iqn.2024-12.com.atlas:storage.target1 luns: type: array items: $ref: '#/components/schemas/LUN' initiators: type: array items: type: string example: ["iqn.2024-12.com.client:initiator1"] enabled: type: boolean LUN: type: object properties: id: type: integer description: LUN number example: 0 zvol: type: string example: tank/block/vol1 size: type: integer format: int64 description: Size in bytes backend: type: string example: zvol Job: type: object properties: id: type: string example: job-1 type: type: string example: snapshot.create status: $ref: '#/components/schemas/JobStatus' progress: type: integer description: Progress percentage (0-100) message: type: string error: type: string created_at: type: string format: date-time started_at: type: string format: date-time completed_at: type: string format: date-time JobStatus: type: string enum: - pending - running - completed - failed - cancelled AuditLog: type: object properties: id: type: string example: audit-1 actor: type: string description: User ID or "system" example: user-1 action: type: string example: pools.create resource: type: string example: pools/tank result: type: string enum: [success, failure] message: type: string ip: type: string example: 192.168.1.100 user_agent: type: string example: curl/7.68.0 timestamp: type: string format: date-time Error: type: object properties: code: type: string example: NOT_FOUND message: type: string example: dataset not found details: type: string example: tank/missing responses: BadRequest: description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' Unauthorized: description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' Forbidden: description: Forbidden content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' Conflict: description: Resource conflict content: application/json: schema: $ref: '#/components/schemas/Error' InternalServerError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error'