Compare commits
33 Commits
732e5aca11
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ad83ae84e4 | |||
| b1a47685f9 | |||
| 6202ef8e83 | |||
| 2bb892dfdc | |||
| a463a09329 | |||
| 45aaec9e47 | |||
| 3a25138d5b | |||
| b90c725cdb | |||
| 98bedf6487 | |||
| 8029bcfa15 | |||
| e36c855bf4 | |||
| 4e8fb66e25 | |||
| 11b8196d84 | |||
| 78f99033fa | |||
| 4b11d839ec | |||
| d9dcb00b0f | |||
| 95b2dbac04 | |||
| 8b5183d98a | |||
| d55206af82 | |||
| b335b0d9f3 | |||
| c98b5b0935 | |||
| 0e26ed99bc | |||
| 945217c536 | |||
| 4ad93e7fe5 | |||
| def02bb36d | |||
| 746cf809df | |||
| 315e44bb62 | |||
| a7ba6c83ea | |||
| 27b0400ef3 | |||
| f1a344bf6a | |||
| e1a66dc7df | |||
| 1c53988cbd | |||
| b4ef76f0d0 |
23
README.md
23
README.md
@@ -1,6 +1,6 @@
|
||||
# atlasOS
|
||||
# AtlasOS
|
||||
|
||||
atlasOS is an appliance-style storage controller build by Adastra
|
||||
AtlasOS is an appliance-style storage controller build by Adastra
|
||||
|
||||
**v1 Focus**
|
||||
- ZFS storage engine
|
||||
@@ -11,3 +11,22 @@ atlasOS is an appliance-style storage controller build by Adastra
|
||||
- Prometheus metrics
|
||||
|
||||
> This repository contains the management plane and appliance tooling.
|
||||
|
||||
## Quick Installation
|
||||
|
||||
### Standard Installation (with internet)
|
||||
```bash
|
||||
sudo ./installer/install.sh
|
||||
```
|
||||
|
||||
### Airgap Installation (offline)
|
||||
```bash
|
||||
# Step 1: Download bundle (on internet-connected system)
|
||||
sudo ./installer/bundle-downloader.sh ./atlas-bundle
|
||||
|
||||
# Step 2: Transfer bundle to airgap system
|
||||
# Step 3: Install on airgap system
|
||||
sudo ./installer/install.sh --offline-bundle /path/to/atlas-bundle
|
||||
```
|
||||
|
||||
See `installer/README.md` and `docs/INSTALLATION.md` for detailed instructions.
|
||||
|
||||
174
docs/AIRGAP_INSTALLATION.md
Normal file
174
docs/AIRGAP_INSTALLATION.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Airgap Installation Guide for AtlasOS
|
||||
|
||||
## Overview
|
||||
|
||||
AtlasOS installer supports airgap (offline) installation for data centers without internet access. All required packages and dependencies are bundled into a single directory that can be transferred to the airgap system.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Step 1: Download Bundle (On System with Internet)
|
||||
|
||||
On a system with internet access and Ubuntu 24.04:
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone <repository-url>
|
||||
cd atlas
|
||||
|
||||
# Run bundle downloader (requires root)
|
||||
sudo ./installer/bundle-downloader.sh ./atlas-bundle
|
||||
```
|
||||
|
||||
This will create a directory `./atlas-bundle` containing:
|
||||
- All required .deb packages (~100-200 packages)
|
||||
- All dependencies
|
||||
- Go binary (fallback)
|
||||
- Manifest and README files
|
||||
|
||||
**Estimated bundle size:** 500MB - 1GB
|
||||
|
||||
### Step 2: Transfer Bundle to Airgap System
|
||||
|
||||
Transfer the entire bundle directory to your airgap system using:
|
||||
- USB drive
|
||||
- Internal network (if available)
|
||||
- Physical media
|
||||
|
||||
```bash
|
||||
# Example: Copy to USB drive
|
||||
cp -r ./atlas-bundle /media/usb/
|
||||
|
||||
# On airgap system: Copy from USB
|
||||
cp -r /media/usb/atlas-bundle /tmp/
|
||||
```
|
||||
|
||||
### Step 3: Install on Airgap System
|
||||
|
||||
On the airgap system (Ubuntu 24.04):
|
||||
|
||||
```bash
|
||||
# Navigate to bundle directory
|
||||
cd /tmp/atlas-bundle
|
||||
|
||||
# Run installer with offline bundle
|
||||
cd /path/to/atlas
|
||||
sudo ./installer/install.sh --offline-bundle /tmp/atlas-bundle
|
||||
```
|
||||
|
||||
## Bundle Contents
|
||||
|
||||
The bundle includes:
|
||||
|
||||
### Main Packages
|
||||
- **Build Tools**: build-essential, git, curl, wget
|
||||
- **ZFS**: zfsutils-linux, zfs-zed, zfs-initramfs
|
||||
- **Storage Services**: samba, samba-common-bin, nfs-kernel-server, rpcbind
|
||||
- **iSCSI**: targetcli-fb
|
||||
- **Database**: sqlite3, libsqlite3-dev
|
||||
- **Go Compiler**: golang-go
|
||||
- **Utilities**: openssl, net-tools, iproute2
|
||||
|
||||
### Dependencies
|
||||
All transitive dependencies are automatically included.
|
||||
|
||||
## Verification
|
||||
|
||||
Before transferring, verify the bundle:
|
||||
|
||||
```bash
|
||||
# Count .deb files (should be 100-200)
|
||||
find ./atlas-bundle -name "*.deb" | wc -l
|
||||
|
||||
# Check manifest
|
||||
cat ./atlas-bundle/MANIFEST.txt
|
||||
|
||||
# Check total size
|
||||
du -sh ./atlas-bundle
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Missing Dependencies
|
||||
|
||||
If installation fails with dependency errors:
|
||||
|
||||
1. Ensure all .deb files are present in bundle
|
||||
2. Check that bundle was created on Ubuntu 24.04
|
||||
3. Verify system architecture matches (amd64/arm64)
|
||||
|
||||
### Go Installation Issues
|
||||
|
||||
If Go is not found after installation:
|
||||
|
||||
1. Check if `golang-go` package is installed: `dpkg -l | grep golang-go`
|
||||
2. If missing, the bundle includes `go.tar.gz` as fallback
|
||||
3. Installer will automatically extract it if needed
|
||||
|
||||
### Package Conflicts
|
||||
|
||||
If you encounter package conflicts:
|
||||
|
||||
```bash
|
||||
# Fix broken packages
|
||||
sudo apt-get install -f -y
|
||||
|
||||
# Or manually install specific packages
|
||||
sudo dpkg -i /path/to/bundle/*.deb
|
||||
sudo apt-get install -f -y
|
||||
```
|
||||
|
||||
## Bundle Maintenance
|
||||
|
||||
### Updating Bundle
|
||||
|
||||
To update the bundle with newer packages:
|
||||
|
||||
1. Run `./installer/bundle-downloader.sh` again on internet-connected system
|
||||
2. This will download latest versions
|
||||
3. Transfer new bundle to airgap system
|
||||
|
||||
### Bundle Size Optimization
|
||||
|
||||
To reduce bundle size (optional):
|
||||
|
||||
```bash
|
||||
# Remove unnecessary packages (be careful!)
|
||||
# Only remove if you're certain they're not needed
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Verify bundle integrity before transferring
|
||||
- Use secure transfer methods (encrypted USB, secure network)
|
||||
- Keep bundle in secure location on airgap system
|
||||
- Verify package signatures if possible
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Bundle Location
|
||||
|
||||
```bash
|
||||
# Download to custom location
|
||||
sudo ./installer/bundle-downloader.sh /opt/atlas-bundles/ubuntu24.04
|
||||
|
||||
# Install from custom location
|
||||
sudo ./installer/install.sh --offline-bundle /opt/atlas-bundles/ubuntu24.04
|
||||
```
|
||||
|
||||
### Partial Bundle (if some packages already installed)
|
||||
|
||||
If some packages are already installed on airgap system:
|
||||
|
||||
```bash
|
||||
# Installer will skip already-installed packages
|
||||
# Missing packages will be installed from bundle
|
||||
sudo ./installer/install.sh --offline-bundle /path/to/bundle
|
||||
```
|
||||
|
||||
## Support
|
||||
|
||||
For issues with airgap installation:
|
||||
1. Check installation logs
|
||||
2. Verify bundle completeness
|
||||
3. Ensure Ubuntu 24.04 compatibility
|
||||
4. Review MANIFEST.txt for package list
|
||||
@@ -1,6 +1,6 @@
|
||||
# Background Job System
|
||||
|
||||
The atlasOS API includes a background job system that automatically executes snapshot policies and manages long-running operations.
|
||||
The AtlasOS API includes a background job system that automatically executes snapshot policies and manages long-running operations.
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ The easiest way to install AtlasOS is using the provided installer script:
|
||||
cd /path/to/atlas
|
||||
|
||||
# Run installer (requires root)
|
||||
sudo ./install.sh
|
||||
sudo ./installer/install.sh
|
||||
```
|
||||
|
||||
The installer will:
|
||||
@@ -50,22 +50,22 @@ The installer will:
|
||||
|
||||
```bash
|
||||
# Custom installation directory
|
||||
sudo ./install.sh --install-dir /opt/custom-atlas
|
||||
sudo ./installer/install.sh --install-dir /opt/custom-atlas
|
||||
|
||||
# Custom data directory
|
||||
sudo ./install.sh --data-dir /mnt/atlas-data
|
||||
sudo ./installer/install.sh --data-dir /mnt/atlas-data
|
||||
|
||||
# Skip dependency installation (if already installed)
|
||||
sudo ./install.sh --skip-deps
|
||||
sudo ./installer/install.sh --skip-deps
|
||||
|
||||
# Skip building binaries (use pre-built)
|
||||
sudo ./install.sh --skip-build
|
||||
sudo ./installer/install.sh --skip-build
|
||||
|
||||
# Custom HTTP address
|
||||
sudo ./install.sh --http-addr :8443
|
||||
sudo ./installer/install.sh --http-addr :8443
|
||||
|
||||
# Show help
|
||||
sudo ./install.sh --help
|
||||
sudo ./installer/install.sh --help
|
||||
```
|
||||
|
||||
## Manual Installation
|
||||
|
||||
226
docs/POSTGRESQL_MIGRATION.md
Normal file
226
docs/POSTGRESQL_MIGRATION.md
Normal file
@@ -0,0 +1,226 @@
|
||||
# PostgreSQL Migration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
AtlasOS now supports both SQLite and PostgreSQL databases. You can switch between them by changing the database connection string.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using PostgreSQL
|
||||
|
||||
Set the `ATLAS_DB_CONN` environment variable to a PostgreSQL connection string:
|
||||
|
||||
```bash
|
||||
export ATLAS_DB_CONN="postgres://username:password@localhost:5432/atlas?sslmode=disable"
|
||||
./atlas-api
|
||||
```
|
||||
|
||||
### Using SQLite (Default)
|
||||
|
||||
Set the `ATLAS_DB_PATH` environment variable to a file path:
|
||||
|
||||
```bash
|
||||
export ATLAS_DB_PATH="/var/lib/atlas/atlas.db"
|
||||
./atlas-api
|
||||
```
|
||||
|
||||
Or use the connection string format:
|
||||
|
||||
```bash
|
||||
export ATLAS_DB_CONN="sqlite:///var/lib/atlas/atlas.db"
|
||||
./atlas-api
|
||||
```
|
||||
|
||||
## Connection String Formats
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```
|
||||
postgres://[user[:password]@][netloc][:port][/dbname][?param1=value1&...]
|
||||
```
|
||||
|
||||
Examples:
|
||||
- `postgres://user:pass@localhost:5432/atlas`
|
||||
- `postgres://user:pass@localhost:5432/atlas?sslmode=disable`
|
||||
- `postgresql://user:pass@db.example.com:5432/atlas?sslmode=require`
|
||||
|
||||
### SQLite
|
||||
|
||||
- File path: `/var/lib/atlas/atlas.db`
|
||||
- Connection string: `sqlite:///var/lib/atlas/atlas.db`
|
||||
|
||||
## Setup PostgreSQL Database
|
||||
|
||||
### 1. Install PostgreSQL
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install postgresql postgresql-contrib
|
||||
```
|
||||
|
||||
**CentOS/RHEL:**
|
||||
```bash
|
||||
sudo yum install postgresql-server postgresql-contrib
|
||||
sudo postgresql-setup initdb
|
||||
sudo systemctl start postgresql
|
||||
sudo systemctl enable postgresql
|
||||
```
|
||||
|
||||
### 2. Create Database and User
|
||||
|
||||
```bash
|
||||
# Switch to postgres user
|
||||
sudo -u postgres psql
|
||||
|
||||
# Create database
|
||||
CREATE DATABASE atlas;
|
||||
|
||||
# Create user
|
||||
CREATE USER atlas_user WITH PASSWORD 'your_secure_password';
|
||||
|
||||
# Grant privileges
|
||||
GRANT ALL PRIVILEGES ON DATABASE atlas TO atlas_user;
|
||||
|
||||
# Exit
|
||||
\q
|
||||
```
|
||||
|
||||
### 3. Configure AtlasOS
|
||||
|
||||
Update your systemd service file (`/etc/systemd/system/atlas-api.service`):
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
Environment="ATLAS_DB_CONN=postgres://atlas_user:your_secure_password@localhost:5432/atlas?sslmode=disable"
|
||||
```
|
||||
|
||||
Or update `/etc/atlas/atlas.conf`:
|
||||
|
||||
```bash
|
||||
# PostgreSQL connection string
|
||||
ATLAS_DB_CONN=postgres://atlas_user:your_secure_password@localhost:5432/atlas?sslmode=disable
|
||||
```
|
||||
|
||||
### 4. Restart Service
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart atlas-api
|
||||
```
|
||||
|
||||
## Migration from SQLite to PostgreSQL
|
||||
|
||||
### Option 1: Fresh Start (Recommended for new installations)
|
||||
|
||||
1. Set up PostgreSQL database (see above)
|
||||
2. Update connection string
|
||||
3. Restart service - tables will be created automatically
|
||||
|
||||
### Option 2: Data Migration
|
||||
|
||||
If you have existing SQLite data:
|
||||
|
||||
1. **Export from SQLite:**
|
||||
```bash
|
||||
sqlite3 /var/lib/atlas/atlas.db .dump > atlas_backup.sql
|
||||
```
|
||||
|
||||
2. **Convert SQL to PostgreSQL format:**
|
||||
- Replace `INTEGER` with `BOOLEAN` for boolean fields
|
||||
- Replace `TEXT` with `VARCHAR(255)` or `TEXT` as appropriate
|
||||
- Update timestamp formats
|
||||
|
||||
3. **Import to PostgreSQL:**
|
||||
```bash
|
||||
psql -U atlas_user -d atlas < converted_backup.sql
|
||||
```
|
||||
|
||||
## Rebuilding the Application
|
||||
|
||||
### 1. Install PostgreSQL Development Libraries
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
sudo apt-get install libpq-dev
|
||||
```
|
||||
|
||||
**CentOS/RHEL:**
|
||||
```bash
|
||||
sudo yum install postgresql-devel
|
||||
```
|
||||
|
||||
### 2. Update Dependencies
|
||||
|
||||
```bash
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### 3. Build
|
||||
|
||||
```bash
|
||||
go build -o atlas-api ./cmd/atlas-api
|
||||
go build -o atlas-tui ./cmd/atlas-tui
|
||||
```
|
||||
|
||||
Or use the installer:
|
||||
|
||||
```bash
|
||||
sudo ./installer/install.sh
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Example |
|
||||
|----------|-------------|---------|
|
||||
| `ATLAS_DB_CONN` | Database connection string (takes precedence) | `postgres://user:pass@host:5432/db` |
|
||||
| `ATLAS_DB_PATH` | SQLite database path (fallback if `ATLAS_DB_CONN` not set) | `/var/lib/atlas/atlas.db` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Refused
|
||||
|
||||
- Check PostgreSQL is running: `sudo systemctl status postgresql`
|
||||
- Verify connection string format
|
||||
- Check firewall rules for port 5432
|
||||
|
||||
### Authentication Failed
|
||||
|
||||
- Verify username and password
|
||||
- Check `pg_hba.conf` for authentication settings
|
||||
- Ensure user has proper permissions
|
||||
|
||||
### Database Not Found
|
||||
|
||||
- Verify database exists: `psql -l`
|
||||
- Check database name in connection string
|
||||
|
||||
### SSL Mode Errors
|
||||
|
||||
- For local connections, use `?sslmode=disable`
|
||||
- For production, configure SSL properly
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### PostgreSQL Advantages
|
||||
|
||||
- Better concurrency (multiple writers)
|
||||
- Advanced query optimization
|
||||
- Better for high-traffic scenarios
|
||||
- Supports replication and clustering
|
||||
|
||||
### SQLite Advantages
|
||||
|
||||
- Zero configuration
|
||||
- Single file deployment
|
||||
- Lower resource usage
|
||||
- Perfect for small deployments
|
||||
|
||||
## Schema Differences
|
||||
|
||||
The application automatically handles schema differences:
|
||||
|
||||
- **SQLite**: Uses `INTEGER` for booleans, `TEXT` for strings
|
||||
- **PostgreSQL**: Uses `BOOLEAN` for booleans, `VARCHAR/TEXT` for strings
|
||||
|
||||
The migration system creates the appropriate schema based on the database type.
|
||||
150
docs/RBAC_PERMISSIONS.md
Normal file
150
docs/RBAC_PERMISSIONS.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Role-Based Access Control (RBAC) - Current Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
AtlasOS implements a three-tier role-based access control system with the following roles:
|
||||
|
||||
1. **Administrator** (`administrator`) - Full system control
|
||||
2. **Operator** (`operator`) - Storage and service operations
|
||||
3. **Viewer** (`viewer`) - Read-only access
|
||||
|
||||
## Current Implementation Status
|
||||
|
||||
### ✅ Fully Implemented (Administrator-Only)
|
||||
|
||||
These operations **require Administrator role**:
|
||||
|
||||
- **User Management**: Create, update, delete users, list users
|
||||
- **Service Management**: Start, stop, restart, reload services, view service logs
|
||||
- **Maintenance Mode**: Enable/disable maintenance mode
|
||||
|
||||
### ⚠️ Partially Implemented (Authentication Required, No Role Check)
|
||||
|
||||
These operations **require authentication** but **don't check specific roles** (any authenticated user can perform them):
|
||||
|
||||
- **ZFS Operations**: Create/delete pools, datasets, ZVOLs, import/export pools, scrub operations
|
||||
- **Snapshot Management**: Create/delete snapshots, create/delete snapshot policies
|
||||
- **Storage Services**: Create/update/delete SMB shares, NFS exports, iSCSI targets
|
||||
- **Backup & Restore**: Create backups, restore backups
|
||||
|
||||
### ✅ Public (No Authentication Required)
|
||||
|
||||
These endpoints are **publicly accessible**:
|
||||
|
||||
- **Read-Only Operations**: List pools, datasets, ZVOLs, shares, exports, targets, snapshots
|
||||
- **Dashboard Data**: System statistics and health information
|
||||
- **Web UI Pages**: All HTML pages (authentication required for mutations via API)
|
||||
|
||||
## Role Definitions
|
||||
|
||||
### Administrator (`administrator`)
|
||||
- **Full system access**
|
||||
- Can manage users (create, update, delete)
|
||||
- Can manage services (start, stop, restart, reload)
|
||||
- Can enable/disable maintenance mode
|
||||
- Can perform all storage operations
|
||||
- Can view audit logs
|
||||
|
||||
### Operator (`operator`)
|
||||
- **Storage and service operations** (intended)
|
||||
- Currently: Same as authenticated user (can perform storage operations)
|
||||
- Should be able to: Create/manage pools, datasets, shares, snapshots
|
||||
- Should NOT be able to: Manage users, manage services, maintenance mode
|
||||
|
||||
### Viewer (`viewer`)
|
||||
- **Read-only access** (intended)
|
||||
- Currently: Can view all public data
|
||||
- Should be able to: View all system information
|
||||
- Should NOT be able to: Perform any mutations (create, update, delete)
|
||||
|
||||
## Current Permission Matrix
|
||||
|
||||
| Operation | Administrator | Operator | Viewer | Unauthenticated |
|
||||
|-----------|--------------|----------|--------|-----------------|
|
||||
| **User Management** |
|
||||
| List users | ✅ | ❌ | ❌ | ❌ |
|
||||
| Create user | ✅ | ❌ | ❌ | ❌ |
|
||||
| Update user | ✅ | ❌ | ❌ | ❌ |
|
||||
| Delete user | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Service Management** |
|
||||
| View service status | ✅ | ❌ | ❌ | ❌ |
|
||||
| Start/stop/restart service | ✅ | ❌ | ❌ | ❌ |
|
||||
| View service logs | ✅ | ❌ | ❌ | ❌ |
|
||||
| **Storage Operations** |
|
||||
| List pools/datasets/ZVOLs | ✅ | ✅ | ✅ | ✅ (public) |
|
||||
| Create pool/dataset/ZVOL | ✅ | ✅* | ❌ | ❌ |
|
||||
| Delete pool/dataset/ZVOL | ✅ | ✅* | ❌ | ❌ |
|
||||
| Import/export pool | ✅ | ✅* | ❌ | ❌ |
|
||||
| **Share Management** |
|
||||
| List shares/exports/targets | ✅ | ✅ | ✅ | ✅ (public) |
|
||||
| Create share/export/target | ✅ | ✅* | ❌ | ❌ |
|
||||
| Update share/export/target | ✅ | ✅* | ❌ | ❌ |
|
||||
| Delete share/export/target | ✅ | ✅* | ❌ | ❌ |
|
||||
| **Snapshot Management** |
|
||||
| List snapshots/policies | ✅ | ✅ | ✅ | ✅ (public) |
|
||||
| Create snapshot/policy | ✅ | ✅* | ❌ | ❌ |
|
||||
| Delete snapshot/policy | ✅ | ✅* | ❌ | ❌ |
|
||||
| **Maintenance Mode** |
|
||||
| View status | ✅ | ✅ | ✅ | ✅ (public) |
|
||||
| Enable/disable | ✅ | ❌ | ❌ | ❌ |
|
||||
|
||||
*Currently works but not explicitly restricted - any authenticated user can perform these operations
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Role Checking
|
||||
|
||||
Roles are checked using the `requireRole()` middleware:
|
||||
|
||||
```go
|
||||
// Example: Administrator-only endpoint
|
||||
a.mux.HandleFunc("/api/v1/users", methodHandler(
|
||||
func(w http.ResponseWriter, r *http.Request) { a.handleListUsers(w, r) },
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
adminRole := models.RoleAdministrator
|
||||
a.requireRole(adminRole)(http.HandlerFunc(a.handleCreateUser)).ServeHTTP(w, r)
|
||||
},
|
||||
nil, nil, nil,
|
||||
))
|
||||
```
|
||||
|
||||
### Multiple Roles Support
|
||||
|
||||
The `requireRole()` function accepts multiple roles:
|
||||
|
||||
```go
|
||||
// Allow both Administrator and Operator
|
||||
a.requireRole(models.RoleAdministrator, models.RoleOperator)(handler)
|
||||
```
|
||||
|
||||
### Current Limitations
|
||||
|
||||
1. **No Operator/Viewer Differentiation**: Most storage operations don't check roles - they only require authentication
|
||||
2. **Hardcoded Role Checks**: Role permissions are defined in route handlers, not in a centralized permission matrix
|
||||
3. **No Granular Permissions**: Can't assign specific permissions (e.g., "can create pools but not delete them")
|
||||
|
||||
## Future Improvements
|
||||
|
||||
To properly implement Operator and Viewer roles:
|
||||
|
||||
1. **Add Role Checks to Storage Operations**:
|
||||
- Allow Operator and Administrator for create/update/delete operations
|
||||
- Restrict Viewer to read-only (GET requests only)
|
||||
|
||||
2. **Centralize Permission Matrix**:
|
||||
- Create a permission configuration file or database table
|
||||
- Map operations to required roles
|
||||
|
||||
3. **Granular Permissions** (Future):
|
||||
- Allow custom permission sets
|
||||
- Support resource-level permissions (e.g., "can manage pool X but not pool Y")
|
||||
|
||||
## Testing Roles
|
||||
|
||||
To test different roles:
|
||||
|
||||
1. Create users with different roles via the Management page
|
||||
2. Login as each user
|
||||
3. Attempt operations and verify permissions
|
||||
|
||||
**Note**: Currently, most operations work for any authenticated user. Only user management, service management, and maintenance mode are properly restricted to Administrators.
|
||||
305
docs/SMB_LDAP_AD_INTEGRATION.md
Normal file
305
docs/SMB_LDAP_AD_INTEGRATION.md
Normal file
@@ -0,0 +1,305 @@
|
||||
# SMB/CIFS Shares - LDAP/Active Directory Integration
|
||||
|
||||
## Skema Autentikasi Saat Ini
|
||||
|
||||
### Implementasi Current (v0.1.0-dev)
|
||||
|
||||
1. **Samba Configuration:**
|
||||
- `security = user` - User-based authentication
|
||||
- User management terpisah antara:
|
||||
- **Atlas Web UI**: In-memory `UserStore` (untuk login web)
|
||||
- **Samba**: User harus dibuat manual di sistem Linux menggunakan `smbpasswd` atau `pdbedit`
|
||||
|
||||
2. **Masalah yang Ada:**
|
||||
- ❌ User Atlas (web UI) ≠ User Samba (SMB access)
|
||||
- ❌ Tidak ada sinkronisasi user antara Atlas dan Samba
|
||||
- ❌ User harus dibuat manual di sistem untuk akses SMB
|
||||
- ❌ Tidak ada integrasi dengan LDAP/AD
|
||||
- ❌ `ValidUsers` di SMB share hanya berupa list username string, tidak terintegrasi dengan sistem user management
|
||||
|
||||
3. **Arsitektur Saat Ini:**
|
||||
```
|
||||
Atlas Web UI (UserStore) ──┐
|
||||
├──> Tidak terhubung
|
||||
Samba (smbpasswd/pdbedit) ─┘
|
||||
```
|
||||
|
||||
## Feasibility untuk LDAP/AD Integration
|
||||
|
||||
### ✅ **SANGAT FEASIBLE**
|
||||
|
||||
Samba memiliki dukungan native untuk LDAP dan Active Directory:
|
||||
|
||||
1. **Samba Security Modes:**
|
||||
- `security = ads` - Active Directory Domain Services (recommended untuk AD)
|
||||
- `security = domain` - NT4 Domain (legacy)
|
||||
- `passdb backend = ldapsam` - LDAP backend untuk user database
|
||||
|
||||
2. **Keuntungan Integrasi LDAP/AD:**
|
||||
- ✅ Single Sign-On (SSO) - user login sekali untuk semua service
|
||||
- ✅ Centralized user management - tidak perlu manage user di multiple tempat
|
||||
- ✅ Group-based access control - bisa assign share berdasarkan AD groups
|
||||
- ✅ Enterprise-ready - sesuai dengan best practices enterprise storage
|
||||
- ✅ Audit trail yang lebih baik - semua akses ter-track di AD
|
||||
|
||||
## Rekomendasi Implementasi
|
||||
|
||||
### Phase 1: LDAP/AD Configuration Support (Priority: High)
|
||||
|
||||
**1. Tambahkan Configuration Model:**
|
||||
```go
|
||||
// internal/models/config.go
|
||||
type LDAPConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
Type string `json:"type"` // "ldap" or "ad"
|
||||
Server string `json:"server"` // LDAP/AD server FQDN or IP
|
||||
BaseDN string `json:"base_dn"` // Base DN for searches
|
||||
BindDN string `json:"bind_dn"` // Service account DN
|
||||
BindPassword string `json:"bind_password"` // Service account password
|
||||
UserDN string `json:"user_dn"` // User DN template (e.g., "CN=Users,DC=example,DC=com")
|
||||
GroupDN string `json:"group_dn"` // Group DN template
|
||||
Realm string `json:"realm"` // AD realm (e.g., "EXAMPLE.COM")
|
||||
Workgroup string `json:"workgroup"` // Workgroup name
|
||||
}
|
||||
```
|
||||
|
||||
**2. Update SMB Service untuk Support LDAP/AD:**
|
||||
```go
|
||||
// internal/services/smb.go
|
||||
func (s *SMBService) generateConfig(shares []models.SMBShare, ldapConfig *models.LDAPConfig) (string, error) {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString("[global]\n")
|
||||
b.WriteString(" server string = AtlasOS Storage Server\n")
|
||||
b.WriteString(" dns proxy = no\n")
|
||||
|
||||
if ldapConfig != nil && ldapConfig.Enabled {
|
||||
if ldapConfig.Type == "ad" {
|
||||
// Active Directory mode
|
||||
b.WriteString(" security = ads\n")
|
||||
b.WriteString(fmt.Sprintf(" realm = %s\n", ldapConfig.Realm))
|
||||
b.WriteString(fmt.Sprintf(" workgroup = %s\n", ldapConfig.Workgroup))
|
||||
b.WriteString(" idmap config * : backend = tdb\n")
|
||||
b.WriteString(" idmap config * : range = 10000-20000\n")
|
||||
b.WriteString(" winbind enum users = yes\n")
|
||||
b.WriteString(" winbind enum groups = yes\n")
|
||||
} else {
|
||||
// LDAP mode
|
||||
b.WriteString(" security = user\n")
|
||||
b.WriteString(" passdb backend = ldapsam:ldap://" + ldapConfig.Server + "\n")
|
||||
b.WriteString(fmt.Sprintf(" ldap admin dn = %s\n", ldapConfig.BindDN))
|
||||
b.WriteString(fmt.Sprintf(" ldap suffix = %s\n", ldapConfig.BaseDN))
|
||||
b.WriteString(fmt.Sprintf(" ldap user suffix = %s\n", ldapConfig.UserDN))
|
||||
b.WriteString(fmt.Sprintf(" ldap group suffix = %s\n", ldapConfig.GroupDN))
|
||||
}
|
||||
} else {
|
||||
// Default: user mode (current implementation)
|
||||
b.WriteString(" security = user\n")
|
||||
b.WriteString(" map to guest = Bad User\n")
|
||||
}
|
||||
|
||||
// ... rest of share configuration
|
||||
}
|
||||
```
|
||||
|
||||
**3. Tambahkan API Endpoints untuk LDAP/AD Config:**
|
||||
```go
|
||||
// internal/httpapp/api_handlers.go
|
||||
// GET /api/v1/config/ldap - Get LDAP/AD configuration
|
||||
// PUT /api/v1/config/ldap - Update LDAP/AD configuration
|
||||
// POST /api/v1/config/ldap/test - Test LDAP/AD connection
|
||||
```
|
||||
|
||||
### Phase 2: User Sync & Group Support (Priority: Medium)
|
||||
|
||||
**1. LDAP/AD User Sync Service:**
|
||||
```go
|
||||
// internal/services/ldap.go
|
||||
type LDAPService struct {
|
||||
config *models.LDAPConfig
|
||||
conn *ldap.Conn
|
||||
}
|
||||
|
||||
func (s *LDAPService) SyncUsers() ([]LDAPUser, error) {
|
||||
// Query LDAP/AD untuk get users
|
||||
// Return list of users dengan attributes
|
||||
}
|
||||
|
||||
func (s *LDAPService) SyncGroups() ([]LDAPGroup, error) {
|
||||
// Query LDAP/AD untuk get groups
|
||||
// Return list of groups dengan members
|
||||
}
|
||||
|
||||
func (s *LDAPService) Authenticate(username, password string) (*LDAPUser, error) {
|
||||
// Authenticate user against LDAP/AD
|
||||
}
|
||||
```
|
||||
|
||||
**2. Update SMB Share Model untuk Support Groups:**
|
||||
```go
|
||||
// internal/models/storage.go
|
||||
type SMBShare struct {
|
||||
// ... existing fields
|
||||
ValidUsers []string `json:"valid_users"` // Username list
|
||||
ValidGroups []string `json:"valid_groups"` // Group name list (NEW)
|
||||
}
|
||||
```
|
||||
|
||||
**3. Update Samba Config untuk Support Groups:**
|
||||
```go
|
||||
if len(share.ValidUsers) > 0 {
|
||||
b.WriteString(fmt.Sprintf(" valid users = %s\n", strings.Join(share.ValidUsers, ", ")))
|
||||
}
|
||||
if len(share.ValidGroups) > 0 {
|
||||
b.WriteString(fmt.Sprintf(" valid groups = %s\n", strings.Join(share.ValidGroups, ", ")))
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: UI Integration (Priority: Medium)
|
||||
|
||||
**1. LDAP/AD Configuration Page:**
|
||||
- Form untuk configure LDAP/AD connection
|
||||
- Test connection button
|
||||
- Display sync status
|
||||
- Manual sync button
|
||||
|
||||
**2. Update SMB Share Creation UI:**
|
||||
- Dropdown untuk select users dari LDAP/AD (bukan manual input)
|
||||
- Dropdown untuk select groups dari LDAP/AD
|
||||
- Auto-complete untuk username/group search
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Add LDAP Library Dependency
|
||||
```bash
|
||||
go get github.com/go-ldap/ldap/v3
|
||||
```
|
||||
|
||||
### Step 2: Create LDAP Service
|
||||
- Implement `internal/services/ldap.go`
|
||||
- Support both LDAP and AD protocols
|
||||
- Handle connection, authentication, and queries
|
||||
|
||||
### Step 3: Update SMB Service
|
||||
- Modify `generateConfig()` to accept LDAP config
|
||||
- Support both `security = ads` and `passdb backend = ldapsam`
|
||||
|
||||
### Step 4: Add Configuration Storage
|
||||
- Store LDAP/AD config (encrypted password)
|
||||
- Add API endpoints for config management
|
||||
|
||||
### Step 5: Update UI
|
||||
- Add LDAP/AD configuration page
|
||||
- Update SMB share creation form
|
||||
- Add user/group selector with LDAP/AD integration
|
||||
|
||||
## Dependencies & Requirements
|
||||
|
||||
### System Packages:
|
||||
```bash
|
||||
# For AD integration
|
||||
sudo apt-get install winbind libnss-winbind libpam-winbind krb5-user
|
||||
|
||||
# For LDAP integration
|
||||
sudo apt-get install libnss-ldap libpam-ldap ldap-utils
|
||||
|
||||
# Samba packages (should already be installed)
|
||||
sudo apt-get install samba samba-common-bin
|
||||
```
|
||||
|
||||
### Go Dependencies:
|
||||
```go
|
||||
// go.mod
|
||||
require (
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
)
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Password Storage:**
|
||||
- Encrypt LDAP bind password di storage
|
||||
- Use environment variables atau secret management untuk production
|
||||
|
||||
2. **TLS/SSL:**
|
||||
- Always use `ldaps://` (LDAP over TLS) untuk production
|
||||
- Support certificate validation
|
||||
|
||||
3. **Service Account:**
|
||||
- Use dedicated service account dengan minimal permissions
|
||||
- Read-only access untuk user/group queries
|
||||
|
||||
4. **Network Security:**
|
||||
- Firewall rules untuk LDAP/AD ports (389, 636, 88, 445)
|
||||
- Consider VPN atau private network untuk LDAP/AD server
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
1. **Unit Tests:**
|
||||
- LDAP connection handling
|
||||
- User/group query parsing
|
||||
- Samba config generation dengan LDAP/AD
|
||||
|
||||
2. **Integration Tests:**
|
||||
- Test dengan LDAP server (OpenLDAP)
|
||||
- Test dengan AD server (Windows Server atau Samba AD)
|
||||
- Test user authentication flow
|
||||
|
||||
3. **Manual Testing:**
|
||||
- Create SMB share dengan AD user
|
||||
- Create SMB share dengan AD group
|
||||
- Test access dari Windows client
|
||||
- Test access dari Linux client
|
||||
|
||||
## Migration Path
|
||||
|
||||
### For Existing Installations:
|
||||
|
||||
1. **Backward Compatibility:**
|
||||
- Keep support untuk `security = user` mode
|
||||
- Existing shares tetap berfungsi
|
||||
- LDAP/AD adalah optional enhancement
|
||||
|
||||
2. **Gradual Migration:**
|
||||
- Admin bisa enable LDAP/AD secara gradual
|
||||
- Test dengan non-production shares dulu
|
||||
- Migrate user-by-user atau group-by-group
|
||||
|
||||
## Estimated Effort
|
||||
|
||||
- **Phase 1 (LDAP/AD Config):** 2-3 days
|
||||
- **Phase 2 (User Sync & Groups):** 3-4 days
|
||||
- **Phase 3 (UI Integration):** 2-3 days
|
||||
- **Testing & Documentation:** 2-3 days
|
||||
|
||||
**Total: ~10-13 days** untuk full LDAP/AD integration
|
||||
|
||||
## Alternative: Hybrid Approach
|
||||
|
||||
Jika full LDAP/AD integration terlalu kompleks untuk sekarang, bisa implement **hybrid approach**:
|
||||
|
||||
1. **Keep current `security = user` mode**
|
||||
2. **Add manual user import from LDAP/AD:**
|
||||
- Admin bisa sync users dari LDAP/AD ke local Samba
|
||||
- Users tetap di-manage di Samba, tapi source of truth adalah LDAP/AD
|
||||
- Periodic sync job untuk update users
|
||||
|
||||
3. **Benefits:**
|
||||
- Simpler implementation
|
||||
- No need untuk complex Samba AD join
|
||||
- Still provides centralized user management
|
||||
|
||||
## Conclusion
|
||||
|
||||
✅ **LDAP/AD integration sangat feasible dan recommended untuk enterprise storage solution**
|
||||
|
||||
**Recommended Approach:**
|
||||
1. Start dengan **Phase 1** (LDAP/AD config support)
|
||||
2. Test dengan environment development
|
||||
3. Gradually implement Phase 2 dan 3
|
||||
4. Consider hybrid approach jika full integration terlalu complex
|
||||
|
||||
**Priority:**
|
||||
- High untuk enterprise customers yang sudah punya AD/LDAP infrastructure
|
||||
- Medium untuk SMB customers yang mungkin belum punya AD/LDAP
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: atlasOS Storage Controller API
|
||||
title: AtlasOS Storage Controller API
|
||||
description: |
|
||||
REST API for managing ZFS storage, storage services (SMB/NFS/iSCSI), snapshots, and system configuration.
|
||||
|
||||
@@ -17,7 +17,7 @@ info:
|
||||
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: atlasOS Support
|
||||
name: AtlasOS Support
|
||||
url: https://github.com/atlasos
|
||||
|
||||
servers:
|
||||
|
||||
34
fix-sudoers.sh
Executable file
34
fix-sudoers.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# Quick fix script to add current user to ZFS sudoers for development
|
||||
# Usage: sudo ./fix-sudoers.sh
|
||||
|
||||
set -e
|
||||
|
||||
CURRENT_USER=$(whoami)
|
||||
SUDOERS_FILE="/etc/sudoers.d/atlas-zfs"
|
||||
|
||||
echo "Adding $CURRENT_USER to ZFS sudoers for development..."
|
||||
|
||||
# Check if sudoers file exists
|
||||
if [ ! -f "$SUDOERS_FILE" ]; then
|
||||
echo "Creating sudoers file..."
|
||||
cat > "$SUDOERS_FILE" <<EOF
|
||||
# Allow ZFS commands without password for development
|
||||
# This file is auto-generated - modify with caution
|
||||
EOF
|
||||
chmod 440 "$SUDOERS_FILE"
|
||||
fi
|
||||
|
||||
# Check if user is already in the file
|
||||
if grep -q "^$CURRENT_USER" "$SUDOERS_FILE"; then
|
||||
echo "User $CURRENT_USER already has ZFS sudoers access"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Add user to sudoers file
|
||||
cat >> "$SUDOERS_FILE" <<EOF
|
||||
$CURRENT_USER ALL=(ALL) NOPASSWD: /usr/sbin/zpool, /usr/bin/zpool, /sbin/zpool, /usr/sbin/zfs, /usr/bin/zfs, /sbin/zfs
|
||||
EOF
|
||||
|
||||
echo "Added $CURRENT_USER to ZFS sudoers"
|
||||
echo "You can now run atlas-api without sudo password prompts"
|
||||
3
go.mod
3
go.mod
@@ -4,7 +4,9 @@ go 1.24.4
|
||||
|
||||
require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/lib/pq v1.10.9
|
||||
golang.org/x/crypto v0.46.0
|
||||
modernc.org/sqlite v1.40.1
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -18,5 +20,4 @@ require (
|
||||
modernc.org/libc v1.66.10 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/sqlite v1.40.1 // indirect
|
||||
)
|
||||
|
||||
28
go.sum
28
go.sum
@@ -2,8 +2,12 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
@@ -14,14 +18,38 @@ golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4=
|
||||
modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A=
|
||||
modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q=
|
||||
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A=
|
||||
modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.40.1 h1:VfuXcxcUWWKRBuP8+BR9L7VnmusMgBNNnBYGEe9w/iY=
|
||||
modernc.org/sqlite v1.40.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
|
||||
757
install.sh
757
install.sh
@@ -1,757 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# AtlasOS Installation Script
|
||||
# Installs AtlasOS storage controller on a Linux system
|
||||
#
|
||||
# Usage: sudo ./install.sh [options]
|
||||
#
|
||||
# Note: Run this script from the atlas repository root directory
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Default values
|
||||
INSTALL_DIR="/opt/atlas"
|
||||
DATA_DIR="/var/lib/atlas"
|
||||
CONFIG_DIR="/etc/atlas"
|
||||
SERVICE_USER="atlas"
|
||||
LOG_DIR="/var/log/atlas"
|
||||
BACKUP_DIR="/var/lib/atlas/backups"
|
||||
HTTP_ADDR=":8080"
|
||||
DB_PATH="/var/lib/atlas/atlas.db"
|
||||
BUILD_BINARIES=true
|
||||
SKIP_DEPS=false
|
||||
REPO_DIR=""
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--install-dir)
|
||||
INSTALL_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--data-dir)
|
||||
DATA_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--skip-deps)
|
||||
SKIP_DEPS=true
|
||||
shift
|
||||
;;
|
||||
--skip-build)
|
||||
BUILD_BINARIES=false
|
||||
shift
|
||||
;;
|
||||
--http-addr)
|
||||
HTTP_ADDR="$2"
|
||||
shift 2
|
||||
;;
|
||||
--repo-dir)
|
||||
REPO_DIR="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
echo "AtlasOS Installation Script"
|
||||
echo ""
|
||||
echo "Usage: sudo ./install.sh [options]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --install-dir DIR Installation directory (default: /opt/atlas)"
|
||||
echo " --data-dir DIR Data directory (default: /var/lib/atlas)"
|
||||
echo " --skip-deps Skip dependency installation"
|
||||
echo " --skip-build Skip building binaries (use existing)"
|
||||
echo " --http-addr ADDR HTTP address (default: :8080)"
|
||||
echo " --repo-dir DIR Repository directory (if not in current dir)"
|
||||
echo " -h, --help Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if running as root
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "${RED}Error: This script must be run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get script directory early (for path resolution)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# Detect distribution
|
||||
detect_distro() {
|
||||
if [[ -f /etc/os-release ]]; then
|
||||
. /etc/os-release
|
||||
DISTRO=$ID
|
||||
VERSION=$VERSION_ID
|
||||
else
|
||||
echo -e "${RED}Error: Cannot detect Linux distribution${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Install dependencies
|
||||
install_dependencies() {
|
||||
echo -e "${GREEN}Installing dependencies...${NC}"
|
||||
|
||||
case $DISTRO in
|
||||
ubuntu|debian)
|
||||
apt-get update
|
||||
|
||||
# Try targetcli-fb first (common on newer Ubuntu/Debian), fallback to targetcli
|
||||
TARGETCLI_PKG="targetcli-fb"
|
||||
if ! apt-cache show targetcli-fb &>/dev/null; then
|
||||
TARGETCLI_PKG="targetcli"
|
||||
fi
|
||||
|
||||
apt-get install -y \
|
||||
zfsutils-linux \
|
||||
samba \
|
||||
nfs-kernel-server \
|
||||
$TARGETCLI_PKG \
|
||||
sqlite3 \
|
||||
golang-go \
|
||||
git \
|
||||
build-essential \
|
||||
curl
|
||||
;;
|
||||
fedora|rhel|centos)
|
||||
if command -v dnf &> /dev/null; then
|
||||
dnf install -y \
|
||||
zfs \
|
||||
samba \
|
||||
nfs-utils \
|
||||
targetcli \
|
||||
sqlite \
|
||||
golang \
|
||||
git \
|
||||
gcc \
|
||||
make \
|
||||
curl
|
||||
else
|
||||
yum install -y \
|
||||
zfs \
|
||||
samba \
|
||||
nfs-utils \
|
||||
targetcli \
|
||||
sqlite \
|
||||
golang \
|
||||
git \
|
||||
gcc \
|
||||
make \
|
||||
curl
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo -e "${YELLOW}Warning: Unknown distribution. Please install dependencies manually:${NC}"
|
||||
echo " - ZFS utilities"
|
||||
echo " - Samba (SMB/CIFS)"
|
||||
echo " - NFS server"
|
||||
echo " - targetcli or targetcli-fb (iSCSI)"
|
||||
echo " - SQLite"
|
||||
echo " - Go compiler"
|
||||
echo " - Build tools"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${GREEN}Dependencies installed${NC}"
|
||||
}
|
||||
|
||||
# Create system user
|
||||
create_user() {
|
||||
echo -e "${GREEN}Creating system user...${NC}"
|
||||
|
||||
if ! id "$SERVICE_USER" &>/dev/null; then
|
||||
useradd -r -s /bin/false -d "$DATA_DIR" "$SERVICE_USER"
|
||||
echo -e "${GREEN}User $SERVICE_USER created${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}User $SERVICE_USER already exists${NC}"
|
||||
fi
|
||||
|
||||
# Add user to disk group for block device access (required for ZFS)
|
||||
if getent group disk > /dev/null 2>&1; then
|
||||
usermod -a -G disk "$SERVICE_USER"
|
||||
echo -e "${GREEN}Added $SERVICE_USER to disk group${NC}"
|
||||
fi
|
||||
|
||||
# Create sudoers configuration for ZFS commands
|
||||
echo -e "${GREEN}Configuring sudo for ZFS operations...${NC}"
|
||||
cat > /etc/sudoers.d/atlas-zfs <<EOF
|
||||
# Allow atlas user to run ZFS commands without password
|
||||
# This is required for ZFS pool operations
|
||||
$SERVICE_USER ALL=(ALL) NOPASSWD: /usr/sbin/zpool, /usr/bin/zpool, /sbin/zpool, /usr/sbin/zfs, /usr/bin/zfs, /sbin/zfs
|
||||
EOF
|
||||
chmod 440 /etc/sudoers.d/atlas-zfs
|
||||
echo -e "${GREEN}Sudo configuration created${NC}"
|
||||
}
|
||||
|
||||
# Create directories
|
||||
create_directories() {
|
||||
echo -e "${GREEN}Creating directories...${NC}"
|
||||
|
||||
mkdir -p "$INSTALL_DIR/bin"
|
||||
mkdir -p "$DATA_DIR"
|
||||
mkdir -p "$CONFIG_DIR"
|
||||
mkdir -p "$LOG_DIR"
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
mkdir -p "$CONFIG_DIR/tls"
|
||||
|
||||
# Set ownership
|
||||
chown -R "$SERVICE_USER:$SERVICE_USER" "$DATA_DIR"
|
||||
chown -R "$SERVICE_USER:$SERVICE_USER" "$LOG_DIR"
|
||||
chown -R "$SERVICE_USER:$SERVICE_USER" "$BACKUP_DIR"
|
||||
chown -R "$SERVICE_USER:$SERVICE_USER" "$CONFIG_DIR"
|
||||
|
||||
# Set permissions
|
||||
chmod 755 "$INSTALL_DIR"
|
||||
chmod 755 "$INSTALL_DIR/bin"
|
||||
chmod 700 "$DATA_DIR"
|
||||
chmod 700 "$CONFIG_DIR"
|
||||
chmod 750 "$LOG_DIR"
|
||||
chmod 750 "$BACKUP_DIR"
|
||||
|
||||
echo -e "${GREEN}Directories created${NC}"
|
||||
}
|
||||
|
||||
# Build binaries
|
||||
build_binaries() {
|
||||
if [[ "$BUILD_BINARIES" == "false" ]]; then
|
||||
echo -e "${YELLOW}Skipping binary build${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}Building binaries...${NC}"
|
||||
|
||||
# Check if we're in the right directory
|
||||
# Look for go.mod and internal/ directory (indicates we're in the repo root)
|
||||
BUILD_DIR=""
|
||||
|
||||
# Function to check if directory is valid repo root
|
||||
is_repo_root() {
|
||||
local dir="$1"
|
||||
[[ -f "$dir/go.mod" ]] && [[ -d "$dir/internal" ]]
|
||||
}
|
||||
|
||||
# Try REPO_DIR first
|
||||
if [[ -n "$REPO_DIR" ]] && is_repo_root "$REPO_DIR"; then
|
||||
BUILD_DIR="$(cd "$REPO_DIR" && pwd)"
|
||||
# Try current directory
|
||||
elif is_repo_root "."; then
|
||||
BUILD_DIR="$(pwd)"
|
||||
# Try script directory
|
||||
elif is_repo_root "$SCRIPT_DIR"; then
|
||||
BUILD_DIR="$SCRIPT_DIR"
|
||||
# Try parent of script directory
|
||||
elif is_repo_root "$SCRIPT_DIR/.."; then
|
||||
BUILD_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
fi
|
||||
|
||||
# If still not found, show error
|
||||
if [[ -z "$BUILD_DIR" ]]; then
|
||||
echo -e "${RED}Error: Cannot find atlas repository root${NC}"
|
||||
echo " Current directory: $(pwd)"
|
||||
echo " Script directory: $SCRIPT_DIR"
|
||||
echo ""
|
||||
echo " Looking for directory with:"
|
||||
echo " - go.mod file"
|
||||
echo " - internal/ directory"
|
||||
echo ""
|
||||
echo " Checking current directory:"
|
||||
[[ -f "./go.mod" ]] && echo " ✓ Found go.mod" || echo " ✗ No go.mod"
|
||||
[[ -d "./internal" ]] && echo " ✓ Found internal/" || echo " ✗ No internal/"
|
||||
echo ""
|
||||
echo " Please run installer from the atlas repository root"
|
||||
echo " Or specify path with: --repo-dir /path/to/atlas"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$BUILD_DIR"
|
||||
echo "Building from: $(pwd)"
|
||||
|
||||
# Create cmd directory structure if it doesn't exist
|
||||
if [[ ! -f "./cmd/atlas-api/main.go" ]]; then
|
||||
echo -e "${YELLOW}cmd/ directory not found, creating...${NC}"
|
||||
mkdir -p ./cmd/atlas-api
|
||||
mkdir -p ./cmd/atlas-tui
|
||||
|
||||
# Create atlas-api/main.go
|
||||
cat > ./cmd/atlas-api/main.go <<'MAINGO'
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"time"
|
||||
|
||||
"gitea.avt.data-center.id/othman.suseno/atlas/internal/httpapp"
|
||||
tlscfg "gitea.avt.data-center.id/othman.suseno/atlas/internal/tls"
|
||||
)
|
||||
|
||||
func main() {
|
||||
addr := env("ATLAS_HTTP_ADDR", ":8080")
|
||||
dbPath := env("ATLAS_DB_PATH", "data/atlas.db")
|
||||
|
||||
app, err := httpapp.New(httpapp.Config{
|
||||
Addr: addr,
|
||||
TemplatesDir: "web/templates",
|
||||
StaticDir: "web/static",
|
||||
DatabasePath: dbPath,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("init app: %v", err)
|
||||
}
|
||||
|
||||
tlsConfig := tlscfg.LoadConfig()
|
||||
if err := tlsConfig.Validate(); err != nil {
|
||||
log.Fatalf("TLS configuration error: %v", err)
|
||||
}
|
||||
|
||||
var tlsServerConfig interface{}
|
||||
if tlsConfig.Enabled {
|
||||
var err error
|
||||
tlsServerConfig, err = tlsConfig.BuildTLSConfig()
|
||||
if err != nil {
|
||||
log.Fatalf("TLS configuration error: %v", err)
|
||||
}
|
||||
log.Printf("[atlas-api] TLS enabled (cert: %s, key: %s)", tlsConfig.CertFile, tlsConfig.KeyFile)
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: app.Router(),
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
WriteTimeout: 30 * time.Second,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
if tlsServerConfig != nil {
|
||||
if cfg, ok := tlsServerConfig.(*tls.Config); ok {
|
||||
srv.TLSConfig = cfg
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Printf("[atlas-api] listening on %s", addr)
|
||||
var err error
|
||||
if tlsConfig.Enabled {
|
||||
err = srv.ListenAndServeTLS("", "")
|
||||
} else {
|
||||
err = srv.ListenAndServe()
|
||||
}
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("listen: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt, os.Kill)
|
||||
<-stop
|
||||
log.Printf("[atlas-api] shutdown requested")
|
||||
|
||||
app.StopScheduler()
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
log.Printf("[atlas-api] shutdown error: %v", err)
|
||||
} else {
|
||||
log.Printf("[atlas-api] shutdown complete")
|
||||
}
|
||||
}
|
||||
|
||||
func env(key, def string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
MAINGO
|
||||
|
||||
# Create atlas-tui/main.go
|
||||
cat > ./cmd/atlas-tui/main.go <<'MAINGO'
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"gitea.avt.data-center.id/othman.suseno/atlas/internal/tui"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultAPIURL = "http://localhost:8080"
|
||||
)
|
||||
|
||||
func main() {
|
||||
apiURL := os.Getenv("ATLAS_API_URL")
|
||||
if apiURL == "" {
|
||||
apiURL = defaultAPIURL
|
||||
}
|
||||
|
||||
client := tui.NewAPIClient(apiURL)
|
||||
app := tui.NewApp(client)
|
||||
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-sigChan
|
||||
app.Cleanup()
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
if err := app.Run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
MAINGO
|
||||
|
||||
echo -e "${GREEN}Created cmd/ directory structure${NC}"
|
||||
fi
|
||||
|
||||
# Verify cmd files exist now
|
||||
if [[ ! -f "./cmd/atlas-api/main.go" ]]; then
|
||||
echo -e "${RED}Error: Failed to create cmd/atlas-api/main.go${NC}"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "./cmd/atlas-tui/main.go" ]]; then
|
||||
echo -e "${RED}Error: Failed to create cmd/atlas-tui/main.go${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build binaries
|
||||
echo "Building atlas-api..."
|
||||
if ! go build -o "$INSTALL_DIR/bin/atlas-api" ./cmd/atlas-api; then
|
||||
echo -e "${RED}Error: Failed to build atlas-api${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Building atlas-tui..."
|
||||
if ! go build -o "$INSTALL_DIR/bin/atlas-tui" ./cmd/atlas-tui; then
|
||||
echo -e "${RED}Error: Failed to build atlas-tui${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chown root:root "$INSTALL_DIR/bin/atlas-api"
|
||||
chown root:root "$INSTALL_DIR/bin/atlas-tui"
|
||||
chmod 755 "$INSTALL_DIR/bin/atlas-api"
|
||||
chmod 755 "$INSTALL_DIR/bin/atlas-tui"
|
||||
|
||||
# Create symlinks in /usr/local/bin for global access
|
||||
echo -e "${GREEN}Creating symlinks for global access...${NC}"
|
||||
ln -sf "$INSTALL_DIR/bin/atlas-api" /usr/local/bin/atlas-api
|
||||
ln -sf "$INSTALL_DIR/bin/atlas-tui" /usr/local/bin/atlas-tui
|
||||
chmod 755 /usr/local/bin/atlas-api
|
||||
chmod 755 /usr/local/bin/atlas-tui
|
||||
|
||||
echo -e "${GREEN}Binaries built and installed successfully${NC}"
|
||||
echo " Binaries available at: $INSTALL_DIR/bin/"
|
||||
echo " Global commands: atlas-api, atlas-tui"
|
||||
}
|
||||
|
||||
# Create systemd service
|
||||
create_systemd_service() {
|
||||
echo -e "${GREEN}Creating systemd service...${NC}"
|
||||
|
||||
cat > /etc/systemd/system/atlas-api.service <<EOF
|
||||
[Unit]
|
||||
Description=AtlasOS Storage Controller API
|
||||
After=network.target zfs.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$SERVICE_USER
|
||||
Group=$SERVICE_USER
|
||||
WorkingDirectory=$INSTALL_DIR
|
||||
ExecStart=$INSTALL_DIR/bin/atlas-api
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
SyslogIdentifier=atlas-api
|
||||
|
||||
# Environment variables
|
||||
Environment="ATLAS_HTTP_ADDR=$HTTP_ADDR"
|
||||
Environment="ATLAS_DB_PATH=$DB_PATH"
|
||||
Environment="ATLAS_BACKUP_DIR=$BACKUP_DIR"
|
||||
Environment="ATLAS_LOG_LEVEL=INFO"
|
||||
Environment="ATLAS_LOG_FORMAT=json"
|
||||
|
||||
# Security
|
||||
# Note: NoNewPrivileges is set to false to allow sudo for ZFS operations
|
||||
# This is necessary for ZFS pool management
|
||||
NoNewPrivileges=false
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=$DATA_DIR $LOG_DIR $BACKUP_DIR $CONFIG_DIR
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
echo -e "${GREEN}Systemd service created${NC}"
|
||||
}
|
||||
|
||||
# Create configuration file
|
||||
create_config() {
|
||||
echo -e "${GREEN}Creating configuration...${NC}"
|
||||
|
||||
cat > "$CONFIG_DIR/atlas.conf" <<EOF
|
||||
# AtlasOS Configuration
|
||||
# This file is sourced by the systemd service
|
||||
|
||||
# HTTP Server
|
||||
ATLAS_HTTP_ADDR=$HTTP_ADDR
|
||||
|
||||
# Database
|
||||
ATLAS_DB_PATH=$DB_PATH
|
||||
|
||||
# Backup Directory
|
||||
ATLAS_BACKUP_DIR=$BACKUP_DIR
|
||||
|
||||
# Logging
|
||||
ATLAS_LOG_LEVEL=INFO
|
||||
ATLAS_LOG_FORMAT=json
|
||||
|
||||
# TLS (optional - uncomment to enable)
|
||||
# ATLAS_TLS_ENABLED=true
|
||||
# ATLAS_TLS_CERT=$CONFIG_DIR/tls/cert.pem
|
||||
# ATLAS_TLS_KEY=$CONFIG_DIR/tls/key.pem
|
||||
|
||||
# JWT Secret (generate with: openssl rand -hex 32)
|
||||
# ATLAS_JWT_SECRET=your-secret-here
|
||||
EOF
|
||||
|
||||
chown "$SERVICE_USER:$SERVICE_USER" "$CONFIG_DIR/atlas.conf"
|
||||
chmod 600 "$CONFIG_DIR/atlas.conf"
|
||||
|
||||
echo -e "${GREEN}Configuration created${NC}"
|
||||
}
|
||||
|
||||
# Generate JWT secret
|
||||
generate_jwt_secret() {
|
||||
echo -e "${GREEN}Generating JWT secret...${NC}"
|
||||
|
||||
if command -v openssl &> /dev/null; then
|
||||
JWT_SECRET=$(openssl rand -hex 32)
|
||||
echo "ATLAS_JWT_SECRET=$JWT_SECRET" >> "$CONFIG_DIR/atlas.conf"
|
||||
echo -e "${GREEN}JWT secret generated${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}Warning: openssl not found. Please set ATLAS_JWT_SECRET manually${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Setup ZFS (if needed)
|
||||
setup_zfs() {
|
||||
echo -e "${GREEN}Checking ZFS...${NC}"
|
||||
|
||||
if ! command -v zpool &> /dev/null; then
|
||||
echo -e "${YELLOW}Warning: ZFS not found. Please install ZFS utilities${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Check if ZFS module is loaded
|
||||
if ! lsmod | grep -q zfs; then
|
||||
echo -e "${YELLOW}Warning: ZFS kernel module not loaded${NC}"
|
||||
echo " Run: modprobe zfs"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}ZFS check complete${NC}"
|
||||
}
|
||||
|
||||
# Setup Samba
|
||||
setup_samba() {
|
||||
echo -e "${GREEN}Setting up Samba...${NC}"
|
||||
|
||||
if ! command -v smbd &> /dev/null; then
|
||||
echo -e "${YELLOW}Warning: Samba not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Enable and start Samba (if not already)
|
||||
systemctl enable smbd 2>/dev/null || true
|
||||
systemctl enable nmbd 2>/dev/null || true
|
||||
|
||||
echo -e "${GREEN}Samba setup complete${NC}"
|
||||
}
|
||||
|
||||
# Setup NFS
|
||||
setup_nfs() {
|
||||
echo -e "${GREEN}Setting up NFS...${NC}"
|
||||
|
||||
if ! command -v exportfs &> /dev/null; then
|
||||
echo -e "${YELLOW}Warning: NFS not found${NC}"
|
||||
return
|
||||
fi
|
||||
|
||||
# Enable and start NFS (if not already)
|
||||
systemctl enable nfs-server 2>/dev/null || true
|
||||
systemctl enable rpcbind 2>/dev/null || true
|
||||
|
||||
echo -e "${GREEN}NFS setup complete${NC}"
|
||||
}
|
||||
|
||||
# Setup iSCSI
|
||||
setup_iscsi() {
|
||||
echo -e "${GREEN}Setting up iSCSI...${NC}"
|
||||
|
||||
# Check for targetcli or targetcli-fb
|
||||
TARGETCLI_CMD=""
|
||||
if command -v targetcli &> /dev/null; then
|
||||
TARGETCLI_CMD="targetcli"
|
||||
elif command -v targetcli-fb &> /dev/null; then
|
||||
TARGETCLI_CMD="targetcli-fb"
|
||||
# Create symlink if targetcli doesn't exist
|
||||
if ! command -v targetcli &> /dev/null; then
|
||||
ln -s $(which targetcli-fb) /usr/local/bin/targetcli 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$TARGETCLI_CMD" ]]; then
|
||||
echo -e "${YELLOW}Warning: targetcli or targetcli-fb not found${NC}"
|
||||
echo " Install with: apt-get install targetcli-fb (Ubuntu/Debian)"
|
||||
return
|
||||
fi
|
||||
|
||||
# Enable and start iSCSI target (if not already)
|
||||
systemctl enable target 2>/dev/null || true
|
||||
|
||||
echo -e "${GREEN}iSCSI setup complete (using $TARGETCLI_CMD)${NC}"
|
||||
}
|
||||
|
||||
# Create initial admin user
|
||||
create_admin_user() {
|
||||
echo -e "${GREEN}Creating initial admin user...${NC}"
|
||||
|
||||
echo ""
|
||||
echo -e "${YELLOW}Please set up the initial admin user:${NC}"
|
||||
echo " Username: admin"
|
||||
echo " Password: (you will be prompted)"
|
||||
echo ""
|
||||
echo "After starting the service, you can create the admin user via:"
|
||||
echo " curl -X POST http://localhost:8080/api/v1/users \\"
|
||||
echo " -H 'Content-Type: application/json' \\"
|
||||
echo " -d '{\"username\":\"admin\",\"password\":\"your-password\",\"role\":\"administrator\"}'"
|
||||
echo ""
|
||||
echo "Or use the TUI:"
|
||||
echo " $INSTALL_DIR/bin/atlas-tui"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Start service
|
||||
start_service() {
|
||||
echo -e "${GREEN}Starting AtlasOS service...${NC}"
|
||||
|
||||
systemctl enable atlas-api
|
||||
systemctl start atlas-api
|
||||
|
||||
# Wait a moment for service to start
|
||||
sleep 2
|
||||
|
||||
if systemctl is-active --quiet atlas-api; then
|
||||
echo -e "${GREEN}AtlasOS service started successfully${NC}"
|
||||
else
|
||||
echo -e "${RED}Error: Service failed to start${NC}"
|
||||
echo "Check logs with: journalctl -u atlas-api -n 50"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Print summary
|
||||
print_summary() {
|
||||
echo ""
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}AtlasOS Installation Complete!${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
echo "Installation Directory: $INSTALL_DIR"
|
||||
echo "Data Directory: $DATA_DIR"
|
||||
echo "Config Directory: $CONFIG_DIR"
|
||||
echo "Log Directory: $LOG_DIR"
|
||||
echo ""
|
||||
echo "Service Status:"
|
||||
systemctl status atlas-api --no-pager -l || true
|
||||
echo ""
|
||||
echo "Useful Commands:"
|
||||
echo " Service: systemctl {start|stop|restart|status} atlas-api"
|
||||
echo " Logs: journalctl -u atlas-api -f"
|
||||
echo " TUI: $INSTALL_DIR/bin/atlas-tui"
|
||||
echo ""
|
||||
echo "Web Interface:"
|
||||
echo " http://localhost:8080"
|
||||
echo ""
|
||||
echo "API Documentation:"
|
||||
echo " http://localhost:8080/api/docs"
|
||||
echo ""
|
||||
echo -e "${YELLOW}Next Steps:${NC}"
|
||||
echo "1. Create initial admin user (see instructions above)"
|
||||
echo "2. Configure TLS certificates (optional)"
|
||||
echo "3. Review configuration in $CONFIG_DIR/atlas.conf"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main installation
|
||||
main() {
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}AtlasOS Installation Script${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo ""
|
||||
|
||||
detect_distro
|
||||
echo "Detected distribution: $DISTRO $VERSION"
|
||||
echo ""
|
||||
|
||||
if [[ "$SKIP_DEPS" == "false" ]]; then
|
||||
install_dependencies
|
||||
else
|
||||
echo -e "${YELLOW}Skipping dependency installation${NC}"
|
||||
fi
|
||||
|
||||
create_user
|
||||
create_directories
|
||||
build_binaries
|
||||
create_config
|
||||
generate_jwt_secret
|
||||
create_systemd_service
|
||||
|
||||
setup_zfs
|
||||
setup_samba
|
||||
setup_nfs
|
||||
setup_iscsi
|
||||
|
||||
create_admin_user
|
||||
|
||||
# Ask if user wants to start service
|
||||
echo ""
|
||||
read -p "Start AtlasOS service now? (y/n) " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
start_service
|
||||
else
|
||||
echo -e "${YELLOW}Service not started. Start manually with: systemctl start atlas-api${NC}"
|
||||
fi
|
||||
|
||||
print_summary
|
||||
}
|
||||
|
||||
# Run main
|
||||
main
|
||||
51
installer/README.md
Normal file
51
installer/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# AtlasOS Installer
|
||||
|
||||
This directory contains installation scripts for AtlasOS on Ubuntu 24.04.
|
||||
|
||||
## Files
|
||||
|
||||
- **`install.sh`** - Main installation script
|
||||
- **`bundle-downloader.sh`** - Downloads all packages for airgap installation
|
||||
- **`README.md`** - This file
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Standard Installation (with internet)
|
||||
|
||||
```bash
|
||||
# From repository root
|
||||
sudo ./installer/install.sh
|
||||
```
|
||||
|
||||
### Airgap Installation (offline)
|
||||
|
||||
**Step 1: Download bundle (on internet-connected system)**
|
||||
```bash
|
||||
sudo ./installer/bundle-downloader.sh ./atlas-bundle
|
||||
```
|
||||
|
||||
**Step 2: Transfer bundle to airgap system**
|
||||
|
||||
**Step 3: Install on airgap system**
|
||||
```bash
|
||||
sudo ./installer/install.sh --offline-bundle /path/to/atlas-bundle
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
See help for all options:
|
||||
```bash
|
||||
sudo ./installer/install.sh --help
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- **Installation Guide**: `../docs/INSTALLATION.md`
|
||||
- **Airgap Installation**: `../docs/AIRGAP_INSTALLATION.md`
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ubuntu 24.04 (Noble Numbat)
|
||||
- Root/sudo access
|
||||
- Internet connection (for standard installation)
|
||||
- Or offline bundle (for airgap installation)
|
||||
34
installer/atlas-bundle-ubuntu24.04/MANIFEST.txt
Normal file
34
installer/atlas-bundle-ubuntu24.04/MANIFEST.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
AtlasOS Bundle for Ubuntu 24.04 (Noble Numbat)
|
||||
Generated: 2025-12-15 14:23:10 UTC
|
||||
Packages: 21 main packages + dependencies
|
||||
|
||||
Main Packages:
|
||||
build-essential
|
||||
git
|
||||
curl
|
||||
wget
|
||||
ca-certificates
|
||||
software-properties-common
|
||||
apt-transport-https
|
||||
zfsutils-linux
|
||||
zfs-zed
|
||||
zfs-initramfs
|
||||
samba
|
||||
samba-common-bin
|
||||
nfs-kernel-server
|
||||
rpcbind
|
||||
targetcli-fb
|
||||
sqlite3
|
||||
libsqlite3-dev
|
||||
golang-go
|
||||
openssl
|
||||
net-tools
|
||||
iproute2
|
||||
|
||||
Total .deb files: 326
|
||||
|
||||
Installation Instructions:
|
||||
1. Transfer this entire directory to your airgap system
|
||||
2. Run: sudo ./installer/install.sh --offline-bundle "/app/atlas/installer/atlas-bundle-ubuntu24.04"
|
||||
|
||||
Note: Ensure all .deb files are present before transferring
|
||||
42
installer/atlas-bundle-ubuntu24.04/README.md
Normal file
42
installer/atlas-bundle-ubuntu24.04/README.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# AtlasOS Offline Bundle for Ubuntu 24.04
|
||||
|
||||
This bundle contains all required packages and dependencies for installing AtlasOS on an airgap (offline) Ubuntu 24.04 system.
|
||||
|
||||
## Contents
|
||||
|
||||
- All required .deb packages with dependencies
|
||||
- Go binary (fallback, if needed)
|
||||
- Installation manifest
|
||||
|
||||
## Usage
|
||||
|
||||
1. Transfer this entire directory to your airgap system
|
||||
2. On the airgap system, run:
|
||||
```bash
|
||||
sudo ./installer/install.sh --offline-bundle /path/to/this/directory
|
||||
```
|
||||
|
||||
## Bundle Size
|
||||
|
||||
The bundle typically contains:
|
||||
- ~100-200 .deb packages (including dependencies)
|
||||
- Total size: ~500MB - 1GB (depending on architecture)
|
||||
|
||||
## Verification
|
||||
|
||||
Before transferring, verify the bundle:
|
||||
```bash
|
||||
# Count .deb files
|
||||
find . -name "*.deb" | wc -l
|
||||
|
||||
# Check manifest
|
||||
cat MANIFEST.txt
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If installation fails:
|
||||
1. Check that all .deb files are present
|
||||
2. Verify you're on Ubuntu 24.04
|
||||
3. Check disk space (need at least 2GB free)
|
||||
4. Review installation logs
|
||||
BIN
installer/atlas-bundle-ubuntu24.04/adduser_3.137ubuntu1_all.deb
Normal file
BIN
installer/atlas-bundle-ubuntu24.04/adduser_3.137ubuntu1_all.deb
Normal file
Binary file not shown.
Binary file not shown.
BIN
installer/atlas-bundle-ubuntu24.04/apt_2.8.3_amd64.deb
Normal file
BIN
installer/atlas-bundle-ubuntu24.04/apt_2.8.3_amd64.deb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
installer/atlas-bundle-ubuntu24.04/debconf_1.5.86ubuntu1_all.deb
Normal file
BIN
installer/atlas-bundle-ubuntu24.04/debconf_1.5.86ubuntu1_all.deb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
installer/atlas-bundle-ubuntu24.04/go.tar.gz
Normal file
BIN
installer/atlas-bundle-ubuntu24.04/go.tar.gz
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
installer/atlas-bundle-ubuntu24.04/iso-codes_4.16.0-1_all.deb
Normal file
BIN
installer/atlas-bundle-ubuntu24.04/iso-codes_4.16.0-1_all.deb
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user