diff --git a/docs/POSTGRESQL_MIGRATION.md b/docs/POSTGRESQL_MIGRATION.md new file mode 100644 index 0000000..086f561 --- /dev/null +++ b/docs/POSTGRESQL_MIGRATION.md @@ -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. diff --git a/go.mod b/go.mod index 627da9a..f77fb57 100644 --- a/go.mod +++ b/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 ) diff --git a/go.sum b/go.sum index 8538477..ebe5843 100644 --- a/go.sum +++ b/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= diff --git a/installer/atlas-bundle-ubuntu24.04/MANIFEST.txt b/installer/atlas-bundle-ubuntu24.04/MANIFEST.txt new file mode 100644 index 0000000..7aea3fc --- /dev/null +++ b/installer/atlas-bundle-ubuntu24.04/MANIFEST.txt @@ -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 diff --git a/installer/atlas-bundle-ubuntu24.04/README.md b/installer/atlas-bundle-ubuntu24.04/README.md new file mode 100644 index 0000000..47fe319 --- /dev/null +++ b/installer/atlas-bundle-ubuntu24.04/README.md @@ -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 diff --git a/installer/atlas-bundle-ubuntu24.04/adduser_3.137ubuntu1_all.deb b/installer/atlas-bundle-ubuntu24.04/adduser_3.137ubuntu1_all.deb new file mode 100644 index 0000000..c58f205 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/adduser_3.137ubuntu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/apt-transport-https_2.8.3_all.deb b/installer/atlas-bundle-ubuntu24.04/apt-transport-https_2.8.3_all.deb new file mode 100644 index 0000000..9cba062 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/apt-transport-https_2.8.3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/apt_2.8.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/apt_2.8.3_amd64.deb new file mode 100644 index 0000000..2a09945 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/apt_2.8.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/base-passwd_3.6.3build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/base-passwd_3.6.3build1_amd64.deb new file mode 100644 index 0000000..d9cc334 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/base-passwd_3.6.3build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/binutils-common_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/binutils-common_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..c5eeb4c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/binutils-common_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/binutils-x86-64-linux-gnu_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/binutils-x86-64-linux-gnu_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..79d317f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/binutils-x86-64-linux-gnu_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/binutils_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/binutils_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..7111b5c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/binutils_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/build-essential_12.10ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/build-essential_12.10ubuntu1_amd64.deb new file mode 100644 index 0000000..236afa1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/build-essential_12.10ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/busybox-initramfs_1%3a1.36.1-6ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/busybox-initramfs_1%3a1.36.1-6ubuntu3.1_amd64.deb new file mode 100644 index 0000000..c3bfa62 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/busybox-initramfs_1%3a1.36.1-6ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/busybox-static_1%3a1.36.1-6ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/busybox-static_1%3a1.36.1-6ubuntu3.1_amd64.deb new file mode 100644 index 0000000..4cebb76 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/busybox-static_1%3a1.36.1-6ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/busybox_1%3a1.36.1-6ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/busybox_1%3a1.36.1-6ubuntu3.1_amd64.deb new file mode 100644 index 0000000..2bb63fd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/busybox_1%3a1.36.1-6ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/bzip2_1.0.8-5.1build0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/bzip2_1.0.8-5.1build0.1_amd64.deb new file mode 100644 index 0000000..6e0d78d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/bzip2_1.0.8-5.1build0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/ca-certificates_20240203_all.deb b/installer/atlas-bundle-ubuntu24.04/ca-certificates_20240203_all.deb new file mode 100644 index 0000000..baa12c0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/ca-certificates_20240203_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cdebconf_0.271ubuntu3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cdebconf_0.271ubuntu3_amd64.deb new file mode 100644 index 0000000..8f0aa1e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cdebconf_0.271ubuntu3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/coreutils_9.4-3ubuntu6.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/coreutils_9.4-3ubuntu6.1_amd64.deb new file mode 100644 index 0000000..4a1860d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/coreutils_9.4-3ubuntu6.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cpio_2.15+dfsg-1ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cpio_2.15+dfsg-1ubuntu2_amd64.deb new file mode 100644 index 0000000..710b24c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cpio_2.15+dfsg-1ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cpp-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cpp-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..539aeb2 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cpp-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cpp-13_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cpp-13_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..7e4e24f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cpp-13_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cpp-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cpp-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..eb48228 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cpp-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/cpp_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/cpp_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..a0fd7a4 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/cpp_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/curl_8.5.0-2ubuntu10.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/curl_8.5.0-2ubuntu10.6_amd64.deb new file mode 100644 index 0000000..a4e25e6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/curl_8.5.0-2ubuntu10.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus-bin_1.14.10-4ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dbus-bin_1.14.10-4ubuntu4.1_amd64.deb new file mode 100644 index 0000000..c794fcc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus-bin_1.14.10-4ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus-broker_35-2ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dbus-broker_35-2ubuntu0.1_amd64.deb new file mode 100644 index 0000000..7ee24a3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus-broker_35-2ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus-daemon_1.14.10-4ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dbus-daemon_1.14.10-4ubuntu4.1_amd64.deb new file mode 100644 index 0000000..812b326 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus-daemon_1.14.10-4ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus-session-bus-common_1.14.10-4ubuntu4.1_all.deb b/installer/atlas-bundle-ubuntu24.04/dbus-session-bus-common_1.14.10-4ubuntu4.1_all.deb new file mode 100644 index 0000000..73dc640 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus-session-bus-common_1.14.10-4ubuntu4.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus-system-bus-common_1.14.10-4ubuntu4.1_all.deb b/installer/atlas-bundle-ubuntu24.04/dbus-system-bus-common_1.14.10-4ubuntu4.1_all.deb new file mode 100644 index 0000000..db2afcd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus-system-bus-common_1.14.10-4ubuntu4.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dbus_1.14.10-4ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dbus_1.14.10-4ubuntu4.1_amd64.deb new file mode 100644 index 0000000..986a833 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dbus_1.14.10-4ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/debconf_1.5.86ubuntu1_all.deb b/installer/atlas-bundle-ubuntu24.04/debconf_1.5.86ubuntu1_all.deb new file mode 100644 index 0000000..08baf94 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/debconf_1.5.86ubuntu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dhcpcd-base_1%3a10.0.6-1ubuntu3.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dhcpcd-base_1%3a10.0.6-1ubuntu3.2_amd64.deb new file mode 100644 index 0000000..c099292 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dhcpcd-base_1%3a10.0.6-1ubuntu3.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/distro-info-data_0.60ubuntu0.5_all.deb b/installer/atlas-bundle-ubuntu24.04/distro-info-data_0.60ubuntu0.5_all.deb new file mode 100644 index 0000000..4376bfd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/distro-info-data_0.60ubuntu0.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dpkg-dev_1.22.6ubuntu6.5_all.deb b/installer/atlas-bundle-ubuntu24.04/dpkg-dev_1.22.6ubuntu6.5_all.deb new file mode 100644 index 0000000..ded9219 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dpkg-dev_1.22.6ubuntu6.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dpkg_1.22.6ubuntu6.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dpkg_1.22.6ubuntu6.5_amd64.deb new file mode 100644 index 0000000..683276b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dpkg_1.22.6ubuntu6.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/dracut-install_060+5-1ubuntu3.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/dracut-install_060+5-1ubuntu3.3_amd64.deb new file mode 100644 index 0000000..18eb74f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/dracut-install_060+5-1ubuntu3.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/e2fsprogs_1.47.0-2.4~exp1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/e2fsprogs_1.47.0-2.4~exp1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..fd684f4 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/e2fsprogs_1.47.0-2.4~exp1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/g++-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/g++-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..0bf346d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/g++-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/g++-13_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/g++-13_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..850959e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/g++-13_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/g++-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/g++-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..ea1533c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/g++-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/g++_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/g++_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..3ae7424 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/g++_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc-13-base_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc-13-base_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..7a83c85 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc-13-base_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..5c5c8ed Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc-13-x86-64-linux-gnu_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc-13_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc-13_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..e489df9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc-13_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc-14-base_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc-14-base_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..148fd41 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc-14-base_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..830599d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc-x86-64-linux-gnu_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gcc_4%3a13.2.0-7ubuntu1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gcc_4%3a13.2.0-7ubuntu1_amd64.deb new file mode 100644 index 0000000..56e05db Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gcc_4%3a13.2.0-7ubuntu1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gir1.2-girepository-2.0_1.80.1-1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gir1.2-girepository-2.0_1.80.1-1_amd64.deb new file mode 100644 index 0000000..c507e03 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gir1.2-girepository-2.0_1.80.1-1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gir1.2-glib-2.0_2.80.0-6ubuntu3.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gir1.2-glib-2.0_2.80.0-6ubuntu3.5_amd64.deb new file mode 100644 index 0000000..a9e4b7a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gir1.2-glib-2.0_2.80.0-6ubuntu3.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gir1.2-packagekitglib-1.0_1.2.8-2ubuntu1.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gir1.2-packagekitglib-1.0_1.2.8-2ubuntu1.4_amd64.deb new file mode 100644 index 0000000..3f43628 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gir1.2-packagekitglib-1.0_1.2.8-2ubuntu1.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/git-man_1%3a2.43.0-1ubuntu7.3_all.deb b/installer/atlas-bundle-ubuntu24.04/git-man_1%3a2.43.0-1ubuntu7.3_all.deb new file mode 100644 index 0000000..62c1539 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/git-man_1%3a2.43.0-1ubuntu7.3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/git_1%3a2.43.0-1ubuntu7.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/git_1%3a2.43.0-1ubuntu7.3_amd64.deb new file mode 100644 index 0000000..e843b4c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/git_1%3a2.43.0-1ubuntu7.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/go.tar.gz b/installer/atlas-bundle-ubuntu24.04/go.tar.gz new file mode 100644 index 0000000..e85a36f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/go.tar.gz differ diff --git a/installer/atlas-bundle-ubuntu24.04/golang-1.22-go_1.22.2-2ubuntu0.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/golang-1.22-go_1.22.2-2ubuntu0.4_amd64.deb new file mode 100644 index 0000000..a3ec32d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/golang-1.22-go_1.22.2-2ubuntu0.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/golang-1.22-src_1.22.2-2ubuntu0.4_all.deb b/installer/atlas-bundle-ubuntu24.04/golang-1.22-src_1.22.2-2ubuntu0.4_all.deb new file mode 100644 index 0000000..68b6c06 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/golang-1.22-src_1.22.2-2ubuntu0.4_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/golang-go_2%3a1.22~2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/golang-go_2%3a1.22~2build1_amd64.deb new file mode 100644 index 0000000..d43c000 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/golang-go_2%3a1.22~2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/golang-src_2%3a1.22~2build1_all.deb b/installer/atlas-bundle-ubuntu24.04/golang-src_2%3a1.22~2build1_all.deb new file mode 100644 index 0000000..0997dc8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/golang-src_2%3a1.22~2build1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gpg_2.4.4-2ubuntu17.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gpg_2.4.4-2ubuntu17.3_amd64.deb new file mode 100644 index 0000000..a020ec9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gpg_2.4.4-2ubuntu17.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gpgconf_2.4.4-2ubuntu17.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gpgconf_2.4.4-2ubuntu17.3_amd64.deb new file mode 100644 index 0000000..38d0fef Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gpgconf_2.4.4-2ubuntu17.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/gpgv_2.4.4-2ubuntu17.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/gpgv_2.4.4-2ubuntu17.3_amd64.deb new file mode 100644 index 0000000..f89dbe3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/gpgv_2.4.4-2ubuntu17.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/guile-3.0-libs_3.0.9-1build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/guile-3.0-libs_3.0.9-1build2_amd64.deb new file mode 100644 index 0000000..88937aa Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/guile-3.0-libs_3.0.9-1build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/init-system-helpers_1.66ubuntu1_all.deb b/installer/atlas-bundle-ubuntu24.04/init-system-helpers_1.66ubuntu1_all.deb new file mode 100644 index 0000000..8c6c54d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/init-system-helpers_1.66ubuntu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/initramfs-tools-bin_0.142ubuntu25.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/initramfs-tools-bin_0.142ubuntu25.5_amd64.deb new file mode 100644 index 0000000..de022ff Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/initramfs-tools-bin_0.142ubuntu25.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/initramfs-tools-core_0.142ubuntu25.5_all.deb b/installer/atlas-bundle-ubuntu24.04/initramfs-tools-core_0.142ubuntu25.5_all.deb new file mode 100644 index 0000000..8bcf4f1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/initramfs-tools-core_0.142ubuntu25.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/initramfs-tools_0.142ubuntu25.5_all.deb b/installer/atlas-bundle-ubuntu24.04/initramfs-tools_0.142ubuntu25.5_all.deb new file mode 100644 index 0000000..8753190 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/initramfs-tools_0.142ubuntu25.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/iproute2_6.1.0-1ubuntu6.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/iproute2_6.1.0-1ubuntu6.2_amd64.deb new file mode 100644 index 0000000..2445ef8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/iproute2_6.1.0-1ubuntu6.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/iso-codes_4.16.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/iso-codes_4.16.0-1_all.deb new file mode 100644 index 0000000..f99007c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/iso-codes_4.16.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/keyutils_1.6.3-3build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/keyutils_1.6.3-3build1_amd64.deb new file mode 100644 index 0000000..3286942 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/keyutils_1.6.3-3build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/klibc-utils_2.0.13-4ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/klibc-utils_2.0.13-4ubuntu0.1_amd64.deb new file mode 100644 index 0000000..8993b66 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/klibc-utils_2.0.13-4ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/kmod_31+20240202-2ubuntu7.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/kmod_31+20240202-2ubuntu7.1_amd64.deb new file mode 100644 index 0000000..4e8758d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/kmod_31+20240202-2ubuntu7.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libacl1_2.3.2-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libacl1_2.3.2-1build1.1_amd64.deb new file mode 100644 index 0000000..e814027 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libacl1_2.3.2-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libapparmor1_4.0.1really4.0.1-0ubuntu0.24.04.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libapparmor1_4.0.1really4.0.1-0ubuntu0.24.04.5_amd64.deb new file mode 100644 index 0000000..c06a35b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libapparmor1_4.0.1really4.0.1-0ubuntu0.24.04.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libappstream5_1.0.2-1build6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libappstream5_1.0.2-1build6_amd64.deb new file mode 100644 index 0000000..2418692 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libappstream5_1.0.2-1build6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libapt-pkg6.0t64_2.8.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libapt-pkg6.0t64_2.8.3_amd64.deb new file mode 100644 index 0000000..cfe9f65 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libapt-pkg6.0t64_2.8.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libargon2-1_0~20190702+dfsg-4build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libargon2-1_0~20190702+dfsg-4build1_amd64.deb new file mode 100644 index 0000000..66342f7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libargon2-1_0~20190702+dfsg-4build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libasan8_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libasan8_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..d27c7a3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libasan8_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libassuan0_2.5.6-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libassuan0_2.5.6-1build1_amd64.deb new file mode 100644 index 0000000..8e78b0e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libassuan0_2.5.6-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libatomic1_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libatomic1_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..bb2a746 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libatomic1_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libattr1_1%3a2.5.2-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libattr1_1%3a2.5.2-1build1.1_amd64.deb new file mode 100644 index 0000000..82f5129 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libattr1_1%3a2.5.2-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libaudit-common_1%3a3.1.2-2.1build1.1_all.deb b/installer/atlas-bundle-ubuntu24.04/libaudit-common_1%3a3.1.2-2.1build1.1_all.deb new file mode 100644 index 0000000..3885c7b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libaudit-common_1%3a3.1.2-2.1build1.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libaudit1_1%3a3.1.2-2.1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libaudit1_1%3a3.1.2-2.1build1.1_amd64.deb new file mode 100644 index 0000000..ee84c96 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libaudit1_1%3a3.1.2-2.1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libavahi-client3_0.8-13ubuntu6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libavahi-client3_0.8-13ubuntu6_amd64.deb new file mode 100644 index 0000000..bf4c33a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libavahi-client3_0.8-13ubuntu6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libavahi-common-data_0.8-13ubuntu6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libavahi-common-data_0.8-13ubuntu6_amd64.deb new file mode 100644 index 0000000..233e083 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libavahi-common-data_0.8-13ubuntu6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libavahi-common3_0.8-13ubuntu6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libavahi-common3_0.8-13ubuntu6_amd64.deb new file mode 100644 index 0000000..c8d4caf Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libavahi-common3_0.8-13ubuntu6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libbinutils_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libbinutils_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..7e5e2b1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libbinutils_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libblkid1_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libblkid1_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..800ca01 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libblkid1_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libbpf1_1%3a1.3.0-2build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libbpf1_1%3a1.3.0-2build2_amd64.deb new file mode 100644 index 0000000..eb80b2f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libbpf1_1%3a1.3.0-2build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libbrotli1_1.1.0-2build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libbrotli1_1.1.0-2build2_amd64.deb new file mode 100644 index 0000000..59ef43d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libbrotli1_1.1.0-2build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libbsd0_0.12.1-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libbsd0_0.12.1-1build1.1_amd64.deb new file mode 100644 index 0000000..00de5ea Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libbsd0_0.12.1-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libbz2-1.0_1.0.8-5.1build0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libbz2-1.0_1.0.8-5.1build0.1_amd64.deb new file mode 100644 index 0000000..05235d6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libbz2-1.0_1.0.8-5.1build0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libc-dev-bin_2.39-0ubuntu8.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libc-dev-bin_2.39-0ubuntu8.6_amd64.deb new file mode 100644 index 0000000..7191515 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libc-dev-bin_2.39-0ubuntu8.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libc6-dev_2.39-0ubuntu8.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libc6-dev_2.39-0ubuntu8.6_amd64.deb new file mode 100644 index 0000000..7fb0cfc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libc6-dev_2.39-0ubuntu8.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libc6_2.39-0ubuntu8.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libc6_2.39-0ubuntu8.6_amd64.deb new file mode 100644 index 0000000..0163554 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libc6_2.39-0ubuntu8.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcap-ng0_0.8.4-2build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcap-ng0_0.8.4-2build2_amd64.deb new file mode 100644 index 0000000..3f259e6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcap-ng0_0.8.4-2build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcap2-bin_1%3a2.66-5ubuntu2.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcap2-bin_1%3a2.66-5ubuntu2.2_amd64.deb new file mode 100644 index 0000000..880d8fa Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcap2-bin_1%3a2.66-5ubuntu2.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcap2_1%3a2.66-5ubuntu2.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcap2_1%3a2.66-5ubuntu2.2_amd64.deb new file mode 100644 index 0000000..01ac783 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcap2_1%3a2.66-5ubuntu2.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcc1-0_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcc1-0_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..036d673 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcc1-0_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcom-err2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcom-err2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..63f9de1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcom-err2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcrypt-dev_1%3a4.4.36-4build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcrypt-dev_1%3a4.4.36-4build1_amd64.deb new file mode 100644 index 0000000..44d083e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcrypt-dev_1%3a4.4.36-4build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcrypt1_1%3a4.4.36-4build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcrypt1_1%3a4.4.36-4build1_amd64.deb new file mode 100644 index 0000000..85ba6ef Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcrypt1_1%3a4.4.36-4build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcryptsetup12_2%3a2.7.0-1ubuntu4.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcryptsetup12_2%3a2.7.0-1ubuntu4.2_amd64.deb new file mode 100644 index 0000000..d408fde Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcryptsetup12_2%3a2.7.0-1ubuntu4.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libctf-nobfd0_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libctf-nobfd0_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..4cc583f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libctf-nobfd0_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libctf0_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libctf0_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..f7fce39 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libctf0_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcups2t64_2.4.7-1.2ubuntu7.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcups2t64_2.4.7-1.2ubuntu7.9_amd64.deb new file mode 100644 index 0000000..9e09c5d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcups2t64_2.4.7-1.2ubuntu7.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcurl3t64-gnutls_8.5.0-2ubuntu10.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcurl3t64-gnutls_8.5.0-2ubuntu10.6_amd64.deb new file mode 100644 index 0000000..d00dd74 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcurl3t64-gnutls_8.5.0-2ubuntu10.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libcurl4t64_8.5.0-2ubuntu10.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libcurl4t64_8.5.0-2ubuntu10.6_amd64.deb new file mode 100644 index 0000000..d692757 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libcurl4t64_8.5.0-2ubuntu10.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdb5.3t64_5.3.28+dfsg2-7_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdb5.3t64_5.3.28+dfsg2-7_amd64.deb new file mode 100644 index 0000000..c88730a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdb5.3t64_5.3.28+dfsg2-7_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdbus-1-3_1.14.10-4ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdbus-1-3_1.14.10-4ubuntu4.1_amd64.deb new file mode 100644 index 0000000..78bc9fc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdbus-1-3_1.14.10-4ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdebconfclient0_0.271ubuntu3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdebconfclient0_0.271ubuntu3_amd64.deb new file mode 100644 index 0000000..a1b8277 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdebconfclient0_0.271ubuntu3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdebian-installer4_0.124ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdebian-installer4_0.124ubuntu2_amd64.deb new file mode 100644 index 0000000..2bcb264 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdebian-installer4_0.124ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdevmapper1.02.1_2%3a1.02.185-3ubuntu3.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdevmapper1.02.1_2%3a1.02.185-3ubuntu3.2_amd64.deb new file mode 100644 index 0000000..7180407 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdevmapper1.02.1_2%3a1.02.185-3ubuntu3.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdpkg-perl_1.22.6ubuntu6.5_all.deb b/installer/atlas-bundle-ubuntu24.04/libdpkg-perl_1.22.6ubuntu6.5_all.deb new file mode 100644 index 0000000..447689e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdpkg-perl_1.22.6ubuntu6.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libduktape207_2.7.0+tests-0ubuntu3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libduktape207_2.7.0+tests-0ubuntu3_amd64.deb new file mode 100644 index 0000000..b1800f5 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libduktape207_2.7.0+tests-0ubuntu3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libdw1t64_0.190-1.1ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libdw1t64_0.190-1.1ubuntu0.1_amd64.deb new file mode 100644 index 0000000..240e137 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libdw1t64_0.190-1.1ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libelf1t64_0.190-1.1ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libelf1t64_0.190-1.1ubuntu0.1_amd64.deb new file mode 100644 index 0000000..5e2deb9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libelf1t64_0.190-1.1ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/liberror-perl_0.17029-2_all.deb b/installer/atlas-bundle-ubuntu24.04/liberror-perl_0.17029-2_all.deb new file mode 100644 index 0000000..4be4022 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/liberror-perl_0.17029-2_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libevent-core-2.1-7t64_2.1.12-stable-9ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libevent-core-2.1-7t64_2.1.12-stable-9ubuntu2_amd64.deb new file mode 100644 index 0000000..41fd2b4 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libevent-core-2.1-7t64_2.1.12-stable-9ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libexpat1_2.6.1-2ubuntu0.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libexpat1_2.6.1-2ubuntu0.3_amd64.deb new file mode 100644 index 0000000..d0c300d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libexpat1_2.6.1-2ubuntu0.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libext2fs2t64_1.47.0-2.4~exp1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libext2fs2t64_1.47.0-2.4~exp1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..e54d98a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libext2fs2t64_1.47.0-2.4~exp1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libfdisk1_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libfdisk1_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..8e2703e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libfdisk1_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libffi8_3.4.6-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libffi8_3.4.6-1build1_amd64.deb new file mode 100644 index 0000000..b54f431 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libffi8_3.4.6-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgc1_1%3a8.2.6-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgc1_1%3a8.2.6-1build1_amd64.deb new file mode 100644 index 0000000..e1a96a0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgc1_1%3a8.2.6-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgcc-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgcc-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..48d4d82 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgcc-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgcc-s1_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgcc-s1_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..61a2d4d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgcc-s1_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgcrypt20_1.10.3-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgcrypt20_1.10.3-2build1_amd64.deb new file mode 100644 index 0000000..42ac962 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgcrypt20_1.10.3-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgdbm-compat4t64_1.23-5.1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgdbm-compat4t64_1.23-5.1build1_amd64.deb new file mode 100644 index 0000000..9807e27 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgdbm-compat4t64_1.23-5.1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgdbm6t64_1.23-5.1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgdbm6t64_1.23-5.1build1_amd64.deb new file mode 100644 index 0000000..da6085e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgdbm6t64_1.23-5.1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgirepository-1.0-1_1.80.1-1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgirepository-1.0-1_1.80.1-1_amd64.deb new file mode 100644 index 0000000..e6752a1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgirepository-1.0-1_1.80.1-1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libglib2.0-0t64_2.80.0-6ubuntu3.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libglib2.0-0t64_2.80.0-6ubuntu3.5_amd64.deb new file mode 100644 index 0000000..b6a923a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libglib2.0-0t64_2.80.0-6ubuntu3.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libglib2.0-bin_2.80.0-6ubuntu3.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libglib2.0-bin_2.80.0-6ubuntu3.5_amd64.deb new file mode 100644 index 0000000..06f9299 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libglib2.0-bin_2.80.0-6ubuntu3.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libglib2.0-data_2.80.0-6ubuntu3.5_all.deb b/installer/atlas-bundle-ubuntu24.04/libglib2.0-data_2.80.0-6ubuntu3.5_all.deb new file mode 100644 index 0000000..d78ddac Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libglib2.0-data_2.80.0-6ubuntu3.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgmp10_2%3a6.3.0+dfsg-2ubuntu6.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgmp10_2%3a6.3.0+dfsg-2ubuntu6.1_amd64.deb new file mode 100644 index 0000000..228e77a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgmp10_2%3a6.3.0+dfsg-2ubuntu6.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgnutls30t64_3.8.3-1.1ubuntu3.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgnutls30t64_3.8.3-1.1ubuntu3.4_amd64.deb new file mode 100644 index 0000000..ff22b10 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgnutls30t64_3.8.3-1.1ubuntu3.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgomp1_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgomp1_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..c98626f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgomp1_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgpg-error0_1.47-3build2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgpg-error0_1.47-3build2.1_amd64.deb new file mode 100644 index 0000000..05f7dd6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgpg-error0_1.47-3build2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgprofng0_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgprofng0_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..8cf8b85 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgprofng0_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgssapi-krb5-2_1.20.1-6ubuntu2.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgssapi-krb5-2_1.20.1-6ubuntu2.6_amd64.deb new file mode 100644 index 0000000..edcc035 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgssapi-krb5-2_1.20.1-6ubuntu2.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libgstreamer1.0-0_1.24.2-1ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libgstreamer1.0-0_1.24.2-1ubuntu0.1_amd64.deb new file mode 100644 index 0000000..0597e6b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libgstreamer1.0-0_1.24.2-1ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libhogweed6t64_3.9.1-2.2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libhogweed6t64_3.9.1-2.2build1.1_amd64.deb new file mode 100644 index 0000000..a82eff8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libhogweed6t64_3.9.1-2.2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libhwasan0_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libhwasan0_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..d9f5cd2 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libhwasan0_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libicu74_74.2-1ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libicu74_74.2-1ubuntu3.1_amd64.deb new file mode 100644 index 0000000..e493699 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libicu74_74.2-1ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libidn2-0_2.3.7-2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libidn2-0_2.3.7-2build1.1_amd64.deb new file mode 100644 index 0000000..5ce9fe4 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libidn2-0_2.3.7-2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libisl23_0.26-3build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libisl23_0.26-3build1.1_amd64.deb new file mode 100644 index 0000000..a6af944 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libisl23_0.26-3build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libitm1_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libitm1_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..b6c215e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libitm1_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libjansson4_2.14-2build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libjansson4_2.14-2build2_amd64.deb new file mode 100644 index 0000000..ba7b56e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libjansson4_2.14-2build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libjson-c5_0.17-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libjson-c5_0.17-1build1_amd64.deb new file mode 100644 index 0000000..78e6ead Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libjson-c5_0.17-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libk5crypto3_1.20.1-6ubuntu2.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libk5crypto3_1.20.1-6ubuntu2.6_amd64.deb new file mode 100644 index 0000000..0729c60 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libk5crypto3_1.20.1-6ubuntu2.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libkeyutils1_1.6.3-3build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libkeyutils1_1.6.3-3build1_amd64.deb new file mode 100644 index 0000000..e5b8263 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libkeyutils1_1.6.3-3build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libklibc_2.0.13-4ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libklibc_2.0.13-4ubuntu0.1_amd64.deb new file mode 100644 index 0000000..1dbd5cb Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libklibc_2.0.13-4ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libkmod2_31+20240202-2ubuntu7.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libkmod2_31+20240202-2ubuntu7.1_amd64.deb new file mode 100644 index 0000000..4109e18 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libkmod2_31+20240202-2ubuntu7.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libkrb5-3_1.20.1-6ubuntu2.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libkrb5-3_1.20.1-6ubuntu2.6_amd64.deb new file mode 100644 index 0000000..ab892b0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libkrb5-3_1.20.1-6ubuntu2.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libkrb5support0_1.20.1-6ubuntu2.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libkrb5support0_1.20.1-6ubuntu2.6_amd64.deb new file mode 100644 index 0000000..c916153 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libkrb5support0_1.20.1-6ubuntu2.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libldap2_2.6.7+dfsg-1~exp1ubuntu8.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libldap2_2.6.7+dfsg-1~exp1ubuntu8.2_amd64.deb new file mode 100644 index 0000000..c4d5d1f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libldap2_2.6.7+dfsg-1~exp1ubuntu8.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libldb2_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libldb2_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..3721f3a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libldb2_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/liblmdb0_0.9.31-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/liblmdb0_0.9.31-1build1_amd64.deb new file mode 100644 index 0000000..e06e8d7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/liblmdb0_0.9.31-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/liblsan0_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/liblsan0_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..e051d7a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/liblsan0_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/liblz4-1_1.9.4-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/liblz4-1_1.9.4-1build1.1_amd64.deb new file mode 100644 index 0000000..66726bd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/liblz4-1_1.9.4-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/liblzma5_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/liblzma5_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb new file mode 100644 index 0000000..05d86ae Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/liblzma5_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libmd0_1.1.0-2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libmd0_1.1.0-2build1.1_amd64.deb new file mode 100644 index 0000000..e775dae Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libmd0_1.1.0-2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libmnl0_1.0.5-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libmnl0_1.0.5-2build1_amd64.deb new file mode 100644 index 0000000..210cee8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libmnl0_1.0.5-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libmount1_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libmount1_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..5625ceb Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libmount1_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libmpc3_1.3.1-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libmpc3_1.3.1-1build1.1_amd64.deb new file mode 100644 index 0000000..dbd5247 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libmpc3_1.3.1-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libmpfr6_4.2.1-1build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libmpfr6_4.2.1-1build1.1_amd64.deb new file mode 100644 index 0000000..448a3b8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libmpfr6_4.2.1-1build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libncurses6_6.4+20240113-1ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libncurses6_6.4+20240113-1ubuntu2_amd64.deb new file mode 100644 index 0000000..86cbf67 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libncurses6_6.4+20240113-1ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libncursesw6_6.4+20240113-1ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libncursesw6_6.4+20240113-1ubuntu2_amd64.deb new file mode 100644 index 0000000..cc1d441 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libncursesw6_6.4+20240113-1ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnettle8t64_3.9.1-2.2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnettle8t64_3.9.1-2.2build1.1_amd64.deb new file mode 100644 index 0000000..1b25acc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnettle8t64_3.9.1-2.2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnewt0.52_0.52.24-2ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnewt0.52_0.52.24-2ubuntu2_amd64.deb new file mode 100644 index 0000000..798d5b1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnewt0.52_0.52.24-2ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnfsidmap1_1%3a2.6.4-3ubuntu5.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnfsidmap1_1%3a2.6.4-3ubuntu5.1_amd64.deb new file mode 100644 index 0000000..6cc31a6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnfsidmap1_1%3a2.6.4-3ubuntu5.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnghttp2-14_1.59.0-1ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnghttp2-14_1.59.0-1ubuntu0.2_amd64.deb new file mode 100644 index 0000000..227bae3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnghttp2-14_1.59.0-1ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnpth0t64_1.6-3.1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnpth0t64_1.6-3.1build1_amd64.deb new file mode 100644 index 0000000..18e3446 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnpth0t64_1.6-3.1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libnvpair3linux_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libnvpair3linux_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..d2f7ef8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libnvpair3linux_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libp11-kit0_0.25.3-4ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libp11-kit0_0.25.3-4ubuntu2.1_amd64.deb new file mode 100644 index 0000000..0673f0c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libp11-kit0_0.25.3-4ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpackagekit-glib2-18_1.2.8-2ubuntu1.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpackagekit-glib2-18_1.2.8-2ubuntu1.4_amd64.deb new file mode 100644 index 0000000..33d1f81 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpackagekit-glib2-18_1.2.8-2ubuntu1.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpam-modules-bin_1.5.3-5ubuntu5.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpam-modules-bin_1.5.3-5ubuntu5.5_amd64.deb new file mode 100644 index 0000000..46b6273 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpam-modules-bin_1.5.3-5ubuntu5.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpam-modules_1.5.3-5ubuntu5.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpam-modules_1.5.3-5ubuntu5.5_amd64.deb new file mode 100644 index 0000000..bc18fd9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpam-modules_1.5.3-5ubuntu5.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpam-runtime_1.5.3-5ubuntu5.5_all.deb b/installer/atlas-bundle-ubuntu24.04/libpam-runtime_1.5.3-5ubuntu5.5_all.deb new file mode 100644 index 0000000..7358edc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpam-runtime_1.5.3-5ubuntu5.5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpam-systemd_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpam-systemd_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..ee3ea0b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpam-systemd_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpam0g_1.5.3-5ubuntu5.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpam0g_1.5.3-5ubuntu5.5_amd64.deb new file mode 100644 index 0000000..3e82b16 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpam0g_1.5.3-5ubuntu5.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpcre2-8-0_10.42-4ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpcre2-8-0_10.42-4ubuntu2.1_amd64.deb new file mode 100644 index 0000000..92a173c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpcre2-8-0_10.42-4ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libperl5.38t64_5.38.2-3.2ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libperl5.38t64_5.38.2-3.2ubuntu0.2_amd64.deb new file mode 100644 index 0000000..6c5a775 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libperl5.38t64_5.38.2-3.2ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpolkit-agent-1-0_124-2ubuntu1.24.04.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpolkit-agent-1-0_124-2ubuntu1.24.04.2_amd64.deb new file mode 100644 index 0000000..ac46581 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpolkit-agent-1-0_124-2ubuntu1.24.04.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpolkit-gobject-1-0_124-2ubuntu1.24.04.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpolkit-gobject-1-0_124-2ubuntu1.24.04.2_amd64.deb new file mode 100644 index 0000000..03c413d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpolkit-gobject-1-0_124-2ubuntu1.24.04.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpopt0_1.19+dfsg-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpopt0_1.19+dfsg-1build1_amd64.deb new file mode 100644 index 0000000..cf0a94f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpopt0_1.19+dfsg-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libproc2-0_2%3a4.0.4-4ubuntu3.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libproc2-0_2%3a4.0.4-4ubuntu3.2_amd64.deb new file mode 100644 index 0000000..2588695 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libproc2-0_2%3a4.0.4-4ubuntu3.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpsl5t64_0.21.2-1.1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpsl5t64_0.21.2-1.1build1_amd64.deb new file mode 100644 index 0000000..d44dc52 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpsl5t64_0.21.2-1.1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpython3-stdlib_3.12.3-0ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpython3-stdlib_3.12.3-0ubuntu2.1_amd64.deb new file mode 100644 index 0000000..bf4c2a3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpython3-stdlib_3.12.3-0ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpython3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpython3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb new file mode 100644 index 0000000..11080ef Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpython3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpython3.12-stdlib_3.12.3-1ubuntu0.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpython3.12-stdlib_3.12.3-1ubuntu0.9_amd64.deb new file mode 100644 index 0000000..d94e973 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpython3.12-stdlib_3.12.3-1ubuntu0.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libpython3.12t64_3.12.3-1ubuntu0.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libpython3.12t64_3.12.3-1ubuntu0.9_amd64.deb new file mode 100644 index 0000000..29275c6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libpython3.12t64_3.12.3-1ubuntu0.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libquadmath0_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libquadmath0_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..e2590c7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libquadmath0_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libreadline8t64_8.2-4build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libreadline8t64_8.2-4build1_amd64.deb new file mode 100644 index 0000000..5e7fc34 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libreadline8t64_8.2-4build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/librtmp1_2.4+20151223.gitfa8646d.1-2build7_amd64.deb b/installer/atlas-bundle-ubuntu24.04/librtmp1_2.4+20151223.gitfa8646d.1-2build7_amd64.deb new file mode 100644 index 0000000..88c8545 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/librtmp1_2.4+20151223.gitfa8646d.1-2build7_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsasl2-2_2.1.28+dfsg1-5ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsasl2-2_2.1.28+dfsg1-5ubuntu3.1_amd64.deb new file mode 100644 index 0000000..364b23b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsasl2-2_2.1.28+dfsg1-5ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsasl2-modules-db_2.1.28+dfsg1-5ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsasl2-modules-db_2.1.28+dfsg1-5ubuntu3.1_amd64.deb new file mode 100644 index 0000000..b6c962e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsasl2-modules-db_2.1.28+dfsg1-5ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libseccomp2_2.5.5-1ubuntu3.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libseccomp2_2.5.5-1ubuntu3.1_amd64.deb new file mode 100644 index 0000000..c22903d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libseccomp2_2.5.5-1ubuntu3.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libselinux1_3.5-2ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libselinux1_3.5-2ubuntu2.1_amd64.deb new file mode 100644 index 0000000..f425843 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libselinux1_3.5-2ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsemanage-common_3.5-1build5_all.deb b/installer/atlas-bundle-ubuntu24.04/libsemanage-common_3.5-1build5_all.deb new file mode 100644 index 0000000..2f7f33e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsemanage-common_3.5-1build5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsemanage2_3.5-1build5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsemanage2_3.5-1build5_amd64.deb new file mode 100644 index 0000000..020ae48 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsemanage2_3.5-1build5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsepol2_3.5-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsepol2_3.5-2build1_amd64.deb new file mode 100644 index 0000000..f0343e3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsepol2_3.5-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsframe1_2.42-4ubuntu2.8_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsframe1_2.42-4ubuntu2.8_amd64.deb new file mode 100644 index 0000000..e013c47 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsframe1_2.42-4ubuntu2.8_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libslang2_2.3.3-3build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libslang2_2.3.3-3build2_amd64.deb new file mode 100644 index 0000000..2936f56 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libslang2_2.3.3-3build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsmartcols1_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsmartcols1_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..0c44c0a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsmartcols1_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsqlite3-0_3.45.1-1ubuntu2.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsqlite3-0_3.45.1-1ubuntu2.5_amd64.deb new file mode 100644 index 0000000..23aebdf Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsqlite3-0_3.45.1-1ubuntu2.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsqlite3-dev_3.45.1-1ubuntu2.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsqlite3-dev_3.45.1-1ubuntu2.5_amd64.deb new file mode 100644 index 0000000..7b6ae77 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsqlite3-dev_3.45.1-1ubuntu2.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libss2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libss2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..2c80201 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libss2_1.47.0-2.4~exp1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libssh-4_0.10.6-2ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libssh-4_0.10.6-2ubuntu0.2_amd64.deb new file mode 100644 index 0000000..5c3f864 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libssh-4_0.10.6-2ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libssl3t64_3.0.13-0ubuntu3.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libssl3t64_3.0.13-0ubuntu3.6_amd64.deb new file mode 100644 index 0000000..b40b3ec Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libssl3t64_3.0.13-0ubuntu3.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libstdc++-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libstdc++-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..83ce0b6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libstdc++-13-dev_13.3.0-6ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libstdc++6_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libstdc++6_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..05e380b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libstdc++6_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libstemmer0d_2.2.0-4build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libstemmer0d_2.2.0-4build1_amd64.deb new file mode 100644 index 0000000..c35429f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libstemmer0d_2.2.0-4build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsystemd-shared_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsystemd-shared_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..dde5c4d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsystemd-shared_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libsystemd0_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libsystemd0_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..42c6a5d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libsystemd0_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtalloc2_2.4.2-1build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtalloc2_2.4.2-1build2_amd64.deb new file mode 100644 index 0000000..229c149 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtalloc2_2.4.2-1build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtasn1-6_4.19.0-3ubuntu0.24.04.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtasn1-6_4.19.0-3ubuntu0.24.04.1_amd64.deb new file mode 100644 index 0000000..c133cd2 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtasn1-6_4.19.0-3ubuntu0.24.04.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtdb1_1.4.10-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtdb1_1.4.10-1build1_amd64.deb new file mode 100644 index 0000000..8cf1ba8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtdb1_1.4.10-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtevent0t64_0.16.1-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtevent0t64_0.16.1-2build1_amd64.deb new file mode 100644 index 0000000..d2f57e9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtevent0t64_0.16.1-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtextwrap1_0.1-17build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtextwrap1_0.1-17build1_amd64.deb new file mode 100644 index 0000000..2e5a672 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtextwrap1_0.1-17build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtinfo6_6.4+20240113-1ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtinfo6_6.4+20240113-1ubuntu2_amd64.deb new file mode 100644 index 0000000..5830137 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtinfo6_6.4+20240113-1ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtirpc-common_1.3.4+ds-1.1build1_all.deb b/installer/atlas-bundle-ubuntu24.04/libtirpc-common_1.3.4+ds-1.1build1_all.deb new file mode 100644 index 0000000..1793632 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtirpc-common_1.3.4+ds-1.1build1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtirpc3t64_1.3.4+ds-1.1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtirpc3t64_1.3.4+ds-1.1build1_amd64.deb new file mode 100644 index 0000000..b61ff03 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtirpc3t64_1.3.4+ds-1.1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libtsan2_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libtsan2_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..a9743a9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libtsan2_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libubsan1_14.2.0-4ubuntu2~24.04_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libubsan1_14.2.0-4ubuntu2~24.04_amd64.deb new file mode 100644 index 0000000..1e44437 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libubsan1_14.2.0-4ubuntu2~24.04_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libudev1_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libudev1_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..19e984d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libudev1_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libunistring5_1.1-2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libunistring5_1.1-2build1.1_amd64.deb new file mode 100644 index 0000000..19f03ea Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libunistring5_1.1-2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libunwind8_1.6.2-3build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libunwind8_1.6.2-3build1.1_amd64.deb new file mode 100644 index 0000000..811b491 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libunwind8_1.6.2-3build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libuuid1_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libuuid1_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..0d91e88 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libuuid1_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libuutil3linux_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libuutil3linux_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..63b3fc3 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libuutil3linux_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libwbclient0_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libwbclient0_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..e5b4403 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libwbclient0_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libwrap0_7.6.q-33_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libwrap0_7.6.q-33_amd64.deb new file mode 100644 index 0000000..9d9f1a9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libwrap0_7.6.q-33_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libxml2_2.9.14+dfsg-1.3ubuntu3.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libxml2_2.9.14+dfsg-1.3ubuntu3.6_amd64.deb new file mode 100644 index 0000000..845dfab Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libxml2_2.9.14+dfsg-1.3ubuntu3.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libxmlb2_0.3.18-1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libxmlb2_0.3.18-1_amd64.deb new file mode 100644 index 0000000..1f3474e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libxmlb2_0.3.18-1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libxtables12_1.8.10-3ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libxtables12_1.8.10-3ubuntu2_amd64.deb new file mode 100644 index 0000000..2b855cb Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libxtables12_1.8.10-3ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libxxhash0_0.8.2-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libxxhash0_0.8.2-2build1_amd64.deb new file mode 100644 index 0000000..55d65a1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libxxhash0_0.8.2-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libyaml-0-2_0.2.5-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libyaml-0-2_0.2.5-1build1_amd64.deb new file mode 100644 index 0000000..c28f233 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libyaml-0-2_0.2.5-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libzfs4linux_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libzfs4linux_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..5599b97 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libzfs4linux_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libzpool5linux_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libzpool5linux_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..db06434 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libzpool5linux_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/libzstd1_1.5.5+dfsg2-2build1.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/libzstd1_1.5.5+dfsg2-2build1.1_amd64.deb new file mode 100644 index 0000000..3c2dce1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/libzstd1_1.5.5+dfsg2-2build1.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/linux-base_4.5ubuntu9+24.04.1_all.deb b/installer/atlas-bundle-ubuntu24.04/linux-base_4.5ubuntu9+24.04.1_all.deb new file mode 100644 index 0000000..e073e00 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/linux-base_4.5ubuntu9+24.04.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/linux-libc-dev_6.8.0-90.91_amd64.deb b/installer/atlas-bundle-ubuntu24.04/linux-libc-dev_6.8.0-90.91_amd64.deb new file mode 100644 index 0000000..40c8398 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/linux-libc-dev_6.8.0-90.91_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/logsave_1.47.0-2.4~exp1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/logsave_1.47.0-2.4~exp1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..214837b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/logsave_1.47.0-2.4~exp1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/lsb-base_11.6_all.deb b/installer/atlas-bundle-ubuntu24.04/lsb-base_11.6_all.deb new file mode 100644 index 0000000..f902086 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/lsb-base_11.6_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/lsb-release_12.0-2_all.deb b/installer/atlas-bundle-ubuntu24.04/lsb-release_12.0-2_all.deb new file mode 100644 index 0000000..26df6b8 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/lsb-release_12.0-2_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/lto-disabled-list_47_all.deb b/installer/atlas-bundle-ubuntu24.04/lto-disabled-list_47_all.deb new file mode 100644 index 0000000..f011ef7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/lto-disabled-list_47_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/make-guile_4.3-4.1build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/make-guile_4.3-4.1build2_amd64.deb new file mode 100644 index 0000000..fd47cb9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/make-guile_4.3-4.1build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/make_4.3-4.1build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/make_4.3-4.1build2_amd64.deb new file mode 100644 index 0000000..c12a468 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/make_4.3-4.1build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/media-types_10.1.0_all.deb b/installer/atlas-bundle-ubuntu24.04/media-types_10.1.0_all.deb new file mode 100644 index 0000000..87b8e26 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/media-types_10.1.0_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/mount_2.39.3-9ubuntu6.3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/mount_2.39.3-9ubuntu6.3_amd64.deb new file mode 100644 index 0000000..9f11528 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/mount_2.39.3-9ubuntu6.3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/net-tools_2.10-0.1ubuntu4.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/net-tools_2.10-0.1ubuntu4.4_amd64.deb new file mode 100644 index 0000000..28b04d7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/net-tools_2.10-0.1ubuntu4.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/netbase_6.4_all.deb b/installer/atlas-bundle-ubuntu24.04/netbase_6.4_all.deb new file mode 100644 index 0000000..7576dcf Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/netbase_6.4_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/nfs-common_1%3a2.6.4-3ubuntu5.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/nfs-common_1%3a2.6.4-3ubuntu5.1_amd64.deb new file mode 100644 index 0000000..5ec33e5 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/nfs-common_1%3a2.6.4-3ubuntu5.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/nfs-kernel-server_1%3a2.6.4-3ubuntu5.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/nfs-kernel-server_1%3a2.6.4-3ubuntu5.1_amd64.deb new file mode 100644 index 0000000..c4bb7a5 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/nfs-kernel-server_1%3a2.6.4-3ubuntu5.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/openssl_3.0.13-0ubuntu3.6_amd64.deb b/installer/atlas-bundle-ubuntu24.04/openssl_3.0.13-0ubuntu3.6_amd64.deb new file mode 100644 index 0000000..d3c7c69 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/openssl_3.0.13-0ubuntu3.6_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/opensysusers_0.7.3-2_all.deb b/installer/atlas-bundle-ubuntu24.04/opensysusers_0.7.3-2_all.deb new file mode 100644 index 0000000..7d7fa4a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/opensysusers_0.7.3-2_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/packagekit_1.2.8-2ubuntu1.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/packagekit_1.2.8-2ubuntu1.4_amd64.deb new file mode 100644 index 0000000..ac0f853 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/packagekit_1.2.8-2ubuntu1.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/passwd_1%3a4.13+dfsg1-4ubuntu3.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/passwd_1%3a4.13+dfsg1-4ubuntu3.2_amd64.deb new file mode 100644 index 0000000..250bda6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/passwd_1%3a4.13+dfsg1-4ubuntu3.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/patch_2.7.6-7build3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/patch_2.7.6-7build3_amd64.deb new file mode 100644 index 0000000..e94244e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/patch_2.7.6-7build3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/perl-base_5.38.2-3.2ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/perl-base_5.38.2-3.2ubuntu0.2_amd64.deb new file mode 100644 index 0000000..ad7b7f0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/perl-base_5.38.2-3.2ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/perl-modules-5.38_5.38.2-3.2ubuntu0.2_all.deb b/installer/atlas-bundle-ubuntu24.04/perl-modules-5.38_5.38.2-3.2ubuntu0.2_all.deb new file mode 100644 index 0000000..b087dd7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/perl-modules-5.38_5.38.2-3.2ubuntu0.2_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/perl_5.38.2-3.2ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/perl_5.38.2-3.2ubuntu0.2_amd64.deb new file mode 100644 index 0000000..c591f86 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/perl_5.38.2-3.2ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/polkitd_124-2ubuntu1.24.04.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/polkitd_124-2ubuntu1.24.04.2_amd64.deb new file mode 100644 index 0000000..0b606ce Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/polkitd_124-2ubuntu1.24.04.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/procps_2%3a4.0.4-4ubuntu3.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/procps_2%3a4.0.4-4ubuntu3.2_amd64.deb new file mode 100644 index 0000000..3509593 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/procps_2%3a4.0.4-4ubuntu3.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python-apt-common_2.7.7ubuntu5.1_all.deb b/installer/atlas-bundle-ubuntu24.04/python-apt-common_2.7.7ubuntu5.1_all.deb new file mode 100644 index 0000000..568df18 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python-apt-common_2.7.7ubuntu5.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-apt_2.7.7ubuntu5.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-apt_2.7.7ubuntu5.1_amd64.deb new file mode 100644 index 0000000..c69de8e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-apt_2.7.7ubuntu5.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-blinker_1.7.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-blinker_1.7.0-1_all.deb new file mode 100644 index 0000000..cdaf372 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-blinker_1.7.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-cffi-backend_1.16.0-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-cffi-backend_1.16.0-2build1_amd64.deb new file mode 100644 index 0000000..c0fe3c7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-cffi-backend_1.16.0-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-configshell-fb_1%3a1.1.28-2.1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-configshell-fb_1%3a1.1.28-2.1_all.deb new file mode 100644 index 0000000..1a992d5 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-configshell-fb_1%3a1.1.28-2.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-cryptography_41.0.7-4ubuntu0.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-cryptography_41.0.7-4ubuntu0.1_amd64.deb new file mode 100644 index 0000000..e4b18fd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-cryptography_41.0.7-4ubuntu0.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-dbus_1.3.2-5build3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-dbus_1.3.2-5build3_amd64.deb new file mode 100644 index 0000000..9016634 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-dbus_1.3.2-5build3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-distro_1.9.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-distro_1.9.0-1_all.deb new file mode 100644 index 0000000..46fd982 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-distro_1.9.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-dnspython_2.6.1-1ubuntu1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-dnspython_2.6.1-1ubuntu1_all.deb new file mode 100644 index 0000000..031128c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-dnspython_2.6.1-1ubuntu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-gi_3.48.2-1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-gi_3.48.2-1_amd64.deb new file mode 100644 index 0000000..f5392ab Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-gi_3.48.2-1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-httplib2_0.20.4-3_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-httplib2_0.20.4-3_all.deb new file mode 100644 index 0000000..a059f56 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-httplib2_0.20.4-3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-importlib-metadata_4.12.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-importlib-metadata_4.12.0-1_all.deb new file mode 100644 index 0000000..efb405d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-importlib-metadata_4.12.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-jwt_2.7.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-jwt_2.7.0-1_all.deb new file mode 100644 index 0000000..51a0580 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-jwt_2.7.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-launchpadlib_1.11.0-6_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-launchpadlib_1.11.0-6_all.deb new file mode 100644 index 0000000..2abf151 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-launchpadlib_1.11.0-6_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-lazr.restfulclient_0.14.6-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-lazr.restfulclient_0.14.6-1_all.deb new file mode 100644 index 0000000..1667e39 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-lazr.restfulclient_0.14.6-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-lazr.uri_1.0.6-3_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-lazr.uri_1.0.6-3_all.deb new file mode 100644 index 0000000..e6e2174 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-lazr.uri_1.0.6-3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-ldb_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-ldb_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..ecab7b7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-ldb_2%3a2.8.0+samba4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-markdown_3.5.2-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-markdown_3.5.2-1_all.deb new file mode 100644 index 0000000..04ffce6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-markdown_3.5.2-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-minimal_3.12.3-0ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-minimal_3.12.3-0ubuntu2.1_amd64.deb new file mode 100644 index 0000000..a0da066 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-minimal_3.12.3-0ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-more-itertools_10.2.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-more-itertools_10.2.0-1_all.deb new file mode 100644 index 0000000..633f23d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-more-itertools_10.2.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-oauthlib_3.2.2-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-oauthlib_3.2.2-1_all.deb new file mode 100644 index 0000000..86e29d0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-oauthlib_3.2.2-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-pkg-resources_68.1.2-2ubuntu1.2_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-pkg-resources_68.1.2-2ubuntu1.2_all.deb new file mode 100644 index 0000000..62006a7 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-pkg-resources_68.1.2-2ubuntu1.2_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-pyparsing_3.1.1-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-pyparsing_3.1.1-1_all.deb new file mode 100644 index 0000000..2e7cbed Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-pyparsing_3.1.1-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-pyudev_0.24.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-pyudev_0.24.0-1_all.deb new file mode 100644 index 0000000..a26025b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-pyudev_0.24.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-rtslib-fb_2.1.74-0ubuntu5_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-rtslib-fb_2.1.74-0ubuntu5_all.deb new file mode 100644 index 0000000..77254e4 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-rtslib-fb_2.1.74-0ubuntu5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..5b7bf8a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-six_1.16.0-4_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-six_1.16.0-4_all.deb new file mode 100644 index 0000000..4e9e7dc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-six_1.16.0-4_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-software-properties_0.99.49.3_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-software-properties_0.99.49.3_all.deb new file mode 100644 index 0000000..f5ef2cf Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-software-properties_0.99.49.3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-talloc_2.4.2-1build2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-talloc_2.4.2-1build2_amd64.deb new file mode 100644 index 0000000..32e8f53 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-talloc_2.4.2-1build2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-tdb_1.4.10-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-tdb_1.4.10-1build1_amd64.deb new file mode 100644 index 0000000..ba47c59 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-tdb_1.4.10-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-typing-extensions_4.10.0-1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-typing-extensions_4.10.0-1_all.deb new file mode 100644 index 0000000..05ffc7f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-typing-extensions_4.10.0-1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-urwid_2.6.10-1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3-urwid_2.6.10-1_amd64.deb new file mode 100644 index 0000000..bb511e9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-urwid_2.6.10-1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-wadllib_1.3.6-5_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-wadllib_1.3.6-5_all.deb new file mode 100644 index 0000000..7227043 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-wadllib_1.3.6-5_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-wcwidth_0.2.5+dfsg1-1.1ubuntu1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-wcwidth_0.2.5+dfsg1-1.1ubuntu1_all.deb new file mode 100644 index 0000000..4f3ca70 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-wcwidth_0.2.5+dfsg1-1.1ubuntu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3-zipp_1.0.0-6ubuntu0.1_all.deb b/installer/atlas-bundle-ubuntu24.04/python3-zipp_1.0.0-6ubuntu0.1_all.deb new file mode 100644 index 0000000..84502bc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3-zipp_1.0.0-6ubuntu0.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb new file mode 100644 index 0000000..ae13d56 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3.12-minimal_3.12.3-1ubuntu0.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3.12_3.12.3-1ubuntu0.9_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3.12_3.12.3-1ubuntu0.9_amd64.deb new file mode 100644 index 0000000..43c1355 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3.12_3.12.3-1ubuntu0.9_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/python3_3.12.3-0ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/python3_3.12.3-0ubuntu2.1_amd64.deb new file mode 100644 index 0000000..b1388ab Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/python3_3.12.3-0ubuntu2.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/readline-common_8.2-4build1_all.deb b/installer/atlas-bundle-ubuntu24.04/readline-common_8.2-4build1_all.deb new file mode 100644 index 0000000..b0b31d0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/readline-common_8.2-4build1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/rpcbind_1.2.6-7ubuntu2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/rpcbind_1.2.6-7ubuntu2_amd64.deb new file mode 100644 index 0000000..0c9d593 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/rpcbind_1.2.6-7ubuntu2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/rpcsvc-proto_1.4.2-0ubuntu7_amd64.deb b/installer/atlas-bundle-ubuntu24.04/rpcsvc-proto_1.4.2-0ubuntu7_amd64.deb new file mode 100644 index 0000000..47abbcc Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/rpcsvc-proto_1.4.2-0ubuntu7_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/samba-common-bin_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/samba-common-bin_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..a083990 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/samba-common-bin_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/samba-common_2%3a4.19.5+dfsg-4ubuntu9.4_all.deb b/installer/atlas-bundle-ubuntu24.04/samba-common_2%3a4.19.5+dfsg-4ubuntu9.4_all.deb new file mode 100644 index 0000000..f643ba9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/samba-common_2%3a4.19.5+dfsg-4ubuntu9.4_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/samba-libs_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/samba-libs_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..8e00c1f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/samba-libs_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb new file mode 100644 index 0000000..fd2fbeb Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/samba_2%3a4.19.5+dfsg-4ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/sed_4.9-2build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/sed_4.9-2build1_amd64.deb new file mode 100644 index 0000000..d62309e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/sed_4.9-2build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/sensible-utils_0.0.22_all.deb b/installer/atlas-bundle-ubuntu24.04/sensible-utils_0.0.22_all.deb new file mode 100644 index 0000000..291c72f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/sensible-utils_0.0.22_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/sgml-base_1.31_all.deb b/installer/atlas-bundle-ubuntu24.04/sgml-base_1.31_all.deb new file mode 100644 index 0000000..78a241a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/sgml-base_1.31_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/software-properties-common_0.99.49.3_all.deb b/installer/atlas-bundle-ubuntu24.04/software-properties-common_0.99.49.3_all.deb new file mode 100644 index 0000000..468587a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/software-properties-common_0.99.49.3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/sqlite3_3.45.1-1ubuntu2.5_amd64.deb b/installer/atlas-bundle-ubuntu24.04/sqlite3_3.45.1-1ubuntu2.5_amd64.deb new file mode 100644 index 0000000..37fafb1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/sqlite3_3.45.1-1ubuntu2.5_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/systemd-dev_255.4-1ubuntu8.11_all.deb b/installer/atlas-bundle-ubuntu24.04/systemd-dev_255.4-1ubuntu8.11_all.deb new file mode 100644 index 0000000..8611fd1 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/systemd-dev_255.4-1ubuntu8.11_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/systemd-standalone-sysusers_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/systemd-standalone-sysusers_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..c1316dd Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/systemd-standalone-sysusers_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/systemd-sysv_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/systemd-sysv_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..b3f8be0 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/systemd-sysv_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/systemd_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/systemd_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..ad2e124 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/systemd_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/sysvinit-utils_3.08-6ubuntu3_amd64.deb b/installer/atlas-bundle-ubuntu24.04/sysvinit-utils_3.08-6ubuntu3_amd64.deb new file mode 100644 index 0000000..ffefff9 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/sysvinit-utils_3.08-6ubuntu3_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/tar_1.35+dfsg-3build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/tar_1.35+dfsg-3build1_amd64.deb new file mode 100644 index 0000000..74a804a Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/tar_1.35+dfsg-3build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/targetcli-fb_1%3a2.1.53-1ubuntu3_all.deb b/installer/atlas-bundle-ubuntu24.04/targetcli-fb_1%3a2.1.53-1ubuntu3_all.deb new file mode 100644 index 0000000..af0e7a5 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/targetcli-fb_1%3a2.1.53-1ubuntu3_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/tdb-tools_1.4.10-1build1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/tdb-tools_1.4.10-1build1_amd64.deb new file mode 100644 index 0000000..8e60e3d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/tdb-tools_1.4.10-1build1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/tzdata_2025b-0ubuntu0.24.04.1_all.deb b/installer/atlas-bundle-ubuntu24.04/tzdata_2025b-0ubuntu0.24.04.1_all.deb new file mode 100644 index 0000000..58c933c Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/tzdata_2025b-0ubuntu0.24.04.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/ubuntu-keyring_2023.11.28.1_all.deb b/installer/atlas-bundle-ubuntu24.04/ubuntu-keyring_2023.11.28.1_all.deb new file mode 100644 index 0000000..3a4282f Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/ubuntu-keyring_2023.11.28.1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/ucf_3.0043+nmu1_all.deb b/installer/atlas-bundle-ubuntu24.04/ucf_3.0043+nmu1_all.deb new file mode 100644 index 0000000..feb54ca Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/ucf_3.0043+nmu1_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/udev_255.4-1ubuntu8.11_amd64.deb b/installer/atlas-bundle-ubuntu24.04/udev_255.4-1ubuntu8.11_amd64.deb new file mode 100644 index 0000000..1769d9d Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/udev_255.4-1ubuntu8.11_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/wget_1.21.4-1ubuntu4.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/wget_1.21.4-1ubuntu4.1_amd64.deb new file mode 100644 index 0000000..ec4ec47 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/wget_1.21.4-1ubuntu4.1_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/xml-core_0.19_all.deb b/installer/atlas-bundle-ubuntu24.04/xml-core_0.19_all.deb new file mode 100644 index 0000000..90a6cea Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/xml-core_0.19_all.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/xz-utils_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb b/installer/atlas-bundle-ubuntu24.04/xz-utils_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb new file mode 100644 index 0000000..a75954b Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/xz-utils_5.6.1+really5.4.5-1ubuntu0.2_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/zfs-initramfs_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/zfs-initramfs_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..d016e08 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/zfs-initramfs_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/zfs-zed_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/zfs-zed_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..917749e Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/zfs-zed_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/zfsutils-linux_2.2.2-0ubuntu9.4_amd64.deb b/installer/atlas-bundle-ubuntu24.04/zfsutils-linux_2.2.2-0ubuntu9.4_amd64.deb new file mode 100644 index 0000000..d9a17b6 Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/zfsutils-linux_2.2.2-0ubuntu9.4_amd64.deb differ diff --git a/installer/atlas-bundle-ubuntu24.04/zlib1g_1%3a1.3.dfsg-3.1ubuntu2.1_amd64.deb b/installer/atlas-bundle-ubuntu24.04/zlib1g_1%3a1.3.dfsg-3.1ubuntu2.1_amd64.deb new file mode 100644 index 0000000..7460faa Binary files /dev/null and b/installer/atlas-bundle-ubuntu24.04/zlib1g_1%3a1.3.dfsg-3.1ubuntu2.1_amd64.deb differ diff --git a/installer/bundle-downloader.sh b/installer/bundle-downloader.sh index ec8e372..ac8461f 100755 --- a/installer/bundle-downloader.sh +++ b/installer/bundle-downloader.sh @@ -94,6 +94,9 @@ PACKAGES=( # Database "sqlite3" "libsqlite3-dev" + "postgresql" + "postgresql-contrib" + "libpq-dev" # Go compiler "golang-go" diff --git a/installer/fix-templates.sh b/installer/fix-templates.sh new file mode 100644 index 0000000..575c9b7 --- /dev/null +++ b/installer/fix-templates.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# +# Quick fix script to copy web templates and static files to installation directory +# Run this on the remote machine where templates are missing +# +# Usage: sudo ./installer/fix-templates.sh [--install-dir /opt/atlas] +# + +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" +REPO_DIR="" + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --install-dir) + INSTALL_DIR="$2" + shift 2 + ;; + --repo-dir) + REPO_DIR="$2" + shift 2 + ;; + -h|--help) + echo "Fix Templates Script" + echo "" + echo "Usage: sudo ./installer/fix-templates.sh [options]" + echo "" + echo "Options:" + echo " --install-dir DIR Installation directory (default: /opt/atlas)" + 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 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# If script is in installer/ subdirectory, get parent (repo root) +if [[ "$(basename "$SCRIPT_DIR")" == "installer" ]]; then + REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +else + REPO_ROOT="$SCRIPT_DIR" +fi + +# Function to check if directory is valid repo root +is_repo_root() { + local dir="$1" + [[ -f "$dir/go.mod" ]] && [[ -d "$dir/internal" ]] && [[ -d "$dir/web/templates" ]] +} + +# Find source directory +SOURCE_DIR="" +if [[ -n "$REPO_DIR" ]] && is_repo_root "$REPO_DIR"; then + SOURCE_DIR="$(cd "$REPO_DIR" && pwd)" +elif is_repo_root "$REPO_ROOT"; then + SOURCE_DIR="$REPO_ROOT" +elif is_repo_root "."; then + SOURCE_DIR="$(pwd)" +fi + +if [[ -z "$SOURCE_DIR" ]]; then + echo -e "${RED}Error: Cannot find repository root with web/templates directory${NC}" + echo " Current directory: $(pwd)" + echo " Script directory: $SCRIPT_DIR" + echo "" + echo " Please run this script from the atlas repository root" + echo " Or specify path with: --repo-dir /path/to/atlas" + exit 1 +fi + +echo -e "${GREEN}Copying web files...${NC}" +echo " Source: $SOURCE_DIR/web" +echo " Destination: $INSTALL_DIR/web" + +# Create web directories in install directory +mkdir -p "$INSTALL_DIR/web/templates" +mkdir -p "$INSTALL_DIR/web/static" + +# Check if templates exist +if [[ ! -d "$SOURCE_DIR/web/templates" ]]; then + echo -e "${RED}Error: web/templates directory not found in $SOURCE_DIR${NC}" + exit 1 +fi + +# Copy templates +echo " Copying templates..." +if cp -r "$SOURCE_DIR/web/templates"/* "$INSTALL_DIR/web/templates/" 2>/dev/null; then + echo -e "${GREEN} ✓ Templates copied${NC}" +else + echo -e "${RED} ✗ Failed to copy templates${NC}" + exit 1 +fi + +# Copy static files if they exist +if [[ -d "$SOURCE_DIR/web/static" ]]; then + echo " Copying static files..." + if cp -r "$SOURCE_DIR/web/static"/* "$INSTALL_DIR/web/static/" 2>/dev/null; then + echo -e "${GREEN} ✓ Static files copied${NC}" + else + echo -e "${YELLOW} ⚠ Some static files may not have been copied${NC}" + fi +fi + +# Set ownership (use atlas user if it exists, otherwise root) +SERVICE_USER="atlas" +if id "$SERVICE_USER" &>/dev/null; then + chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR/web" + echo " Set ownership to $SERVICE_USER" +else + chown -R root:root "$INSTALL_DIR/web" + echo " Set ownership to root (atlas user not found)" +fi + +# Set permissions +chmod -R 755 "$INSTALL_DIR/web" + +echo "" +echo -e "${GREEN}Web files copied successfully!${NC}" +echo " Templates: $INSTALL_DIR/web/templates" +echo " Static: $INSTALL_DIR/web/static" +echo "" +echo "You may need to restart the atlas-api service:" +echo " sudo systemctl restart atlas-api" +echo "" diff --git a/installer/install.sh b/installer/install.sh index 0cf8c9c..77675ae 100755 --- a/installer/install.sh +++ b/installer/install.sh @@ -330,7 +330,7 @@ install_from_bundle() { echo " Verifying installations..." MISSING_PACKAGES=() - for pkg in zfsutils-linux samba nfs-kernel-server sqlite3 golang-go build-essential; do + for pkg in zfsutils-linux samba nfs-kernel-server sqlite3 postgresql postgresql-contrib libpq-dev golang-go build-essential; do if ! dpkg -l | grep -q "^ii.*$pkg"; then MISSING_PACKAGES+=("$pkg") fi @@ -440,9 +440,14 @@ install_dependencies() { } fi - # Install database - echo " Installing SQLite..." - DEBIAN_FRONTEND=noninteractive apt-get install -y -qq sqlite3 libsqlite3-dev + # Install databases (SQLite for compatibility, PostgreSQL as default) + echo " Installing database packages..." + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \ + sqlite3 \ + libsqlite3-dev \ + postgresql \ + postgresql-contrib \ + libpq-dev # Install Go compiler (Ubuntu 24.04 has Go 1.22+) echo " Installing Go compiler..." @@ -474,9 +479,7 @@ install_dependencies() { DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \ openssl \ net-tools \ - iproute2 \ - systemd \ - journalctl + iproute2 echo -e "${GREEN}Dependencies installed successfully${NC}" echo "" @@ -521,11 +524,17 @@ create_directories() { mkdir -p "$BACKUP_DIR" mkdir -p "$CONFIG_DIR/tls" + # Create dedicated storage directories for ZFS pools, datasets, and shares + mkdir -p "/storage/pools" + mkdir -p "/storage/datasets" + mkdir -p "/storage/shares" + # 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" + chown -R "$SERVICE_USER:$SERVICE_USER" "/storage" # Set permissions chmod 755 "$INSTALL_DIR" @@ -534,8 +543,13 @@ create_directories() { chmod 700 "$CONFIG_DIR" chmod 750 "$LOG_DIR" chmod 750 "$BACKUP_DIR" + chmod 755 "/storage" + chmod 755 "/storage/pools" + chmod 755 "/storage/datasets" + chmod 755 "/storage/shares" echo -e "${GREEN}Directories created${NC}" + echo " Storage directories: /storage/{pools,datasets,shares}" } # Build binaries @@ -597,13 +611,18 @@ build_binaries() { echo "Building from: $(pwd)" # Create cmd directory structure if it doesn't exist + mkdir -p ./cmd/atlas-api + mkdir -p ./cmd/atlas-tui + + # Always update main.go files to ensure they're current 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' + else + echo " Updating cmd/atlas-api/main.go..." + fi + + # Create/update atlas-api/main.go + cat > ./cmd/atlas-api/main.go <<'MAINGO' package main import ( @@ -621,13 +640,17 @@ import ( func main() { addr := env("ATLAS_HTTP_ADDR", ":8080") - dbPath := env("ATLAS_DB_PATH", "data/atlas.db") + // Support both ATLAS_DB_PATH (SQLite) and ATLAS_DB_CONN (PostgreSQL connection string) + dbConn := env("ATLAS_DB_CONN", "") + if dbConn == "" { + dbConn = env("ATLAS_DB_PATH", "data/atlas.db") + } app, err := httpapp.New(httpapp.Config{ Addr: addr, TemplatesDir: "web/templates", StaticDir: "web/static", - DatabasePath: dbPath, + DatabaseConn: dbConn, }) if err != nil { log.Fatalf("init app: %v", err) @@ -699,9 +722,15 @@ func env(key, def string) string { return def } MAINGO - - # Create atlas-tui/main.go - cat > ./cmd/atlas-tui/main.go <<'MAINGO' + + # Create/update atlas-tui/main.go + if [[ ! -f "./cmd/atlas-tui/main.go" ]]; then + echo " Creating cmd/atlas-tui/main.go..." + else + echo " Updating cmd/atlas-tui/main.go..." + fi + + cat > ./cmd/atlas-tui/main.go <<'MAINGO' package main import ( @@ -740,9 +769,8 @@ func main() { } } MAINGO - - echo -e "${GREEN}Created cmd/ directory structure${NC}" - fi + + echo -e "${GREEN}cmd/ directory structure ready${NC}" # Verify cmd files exist now if [[ ! -f "./cmd/atlas-api/main.go" ]]; then @@ -785,6 +813,75 @@ MAINGO echo " Global commands: atlas-api, atlas-tui" } +# Copy web files (templates and static assets) +copy_web_files() { + echo -e "${GREEN}Copying web files...${NC}" + + # Use BUILD_DIR from build_binaries if available, otherwise detect it + local source_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 + source_dir="$(cd "$REPO_DIR" && pwd)" + # Try REPO_ROOT (if script is in installer/ subdirectory) + elif [[ -n "$REPO_ROOT" ]] && is_repo_root "$REPO_ROOT"; then + source_dir="$REPO_ROOT" + # Try current directory + elif is_repo_root "."; then + source_dir="$(pwd)" + # Try script directory + elif is_repo_root "$SCRIPT_DIR"; then + source_dir="$SCRIPT_DIR" + # Try parent of script directory + elif is_repo_root "$SCRIPT_DIR/.."; then + source_dir="$(cd "$SCRIPT_DIR/.." && pwd)" + fi + + if [[ -z "$source_dir" ]]; then + echo -e "${YELLOW}Warning: Cannot find repository root, skipping web files copy${NC}" + echo " Templates and static files may not be available" + return + fi + + # Check if web/templates exists + if [[ ! -d "$source_dir/web/templates" ]]; then + echo -e "${YELLOW}Warning: web/templates directory not found in $source_dir${NC}" + echo " Templates may not be available" + else + # Create web directories in install directory + mkdir -p "$INSTALL_DIR/web/templates" + mkdir -p "$INSTALL_DIR/web/static" + + # Copy templates + echo " Copying templates from $source_dir/web/templates..." + cp -r "$source_dir/web/templates"/* "$INSTALL_DIR/web/templates/" 2>/dev/null || { + echo -e "${YELLOW}Warning: Failed to copy some template files${NC}" + } + + # Copy static files if they exist + if [[ -d "$source_dir/web/static" ]]; then + echo " Copying static files from $source_dir/web/static..." + cp -r "$source_dir/web/static"/* "$INSTALL_DIR/web/static/" 2>/dev/null || { + echo -e "${YELLOW}Warning: Failed to copy some static files${NC}" + } + fi + + # Set ownership + chown -R "$SERVICE_USER:$SERVICE_USER" "$INSTALL_DIR/web" + chmod -R 755 "$INSTALL_DIR/web" + + echo -e "${GREEN}Web files copied successfully${NC}" + echo " Templates: $INSTALL_DIR/web/templates" + echo " Static: $INSTALL_DIR/web/static" + fi +} + # Create systemd service create_systemd_service() { echo -e "${GREEN}Creating systemd service...${NC}" @@ -808,7 +905,7 @@ SyslogIdentifier=atlas-api # Environment variables Environment="ATLAS_HTTP_ADDR=$HTTP_ADDR" -Environment="ATLAS_DB_PATH=$DB_PATH" +Environment="ATLAS_DB_CONN=$DB_PATH" Environment="ATLAS_BACKUP_DIR=$BACKUP_DIR" Environment="ATLAS_LOG_LEVEL=INFO" Environment="ATLAS_LOG_FORMAT=json" @@ -841,8 +938,10 @@ create_config() { # HTTP Server ATLAS_HTTP_ADDR=$HTTP_ADDR -# Database -ATLAS_DB_PATH=$DB_PATH +# Database connection string +# Default: PostgreSQL (postgres://dbadmin:Pnd77netM4v3r1cks@localhost:5432/atlas?sslmode=disable) +# Fallback: SQLite file path if PostgreSQL is not available +ATLAS_DB_CONN=$DB_PATH # Backup Directory ATLAS_BACKUP_DIR=$BACKUP_DIR @@ -1078,6 +1177,100 @@ setup_iscsi() { echo "" } +# Setup PostgreSQL database +setup_postgresql() { + echo -e "${GREEN}Setting up PostgreSQL database...${NC}" + + if ! command -v psql &> /dev/null; then + echo -e "${YELLOW}Warning: PostgreSQL client not found${NC}" + echo " PostgreSQL features may not be available" + return 1 + fi + + # Default database credentials + DB_NAME="atlas" + DB_USER="dbadmin" + DB_PASSWORD="Pnd77netM4v3r1cks" + + # Start PostgreSQL service if not running + echo " Starting PostgreSQL service..." + if ! systemctl is-active --quiet postgresql; then + systemctl start postgresql 2>/dev/null || { + echo -e "${YELLOW}Warning: Could not start PostgreSQL service${NC}" + echo " You may need to start it manually: systemctl start postgresql" + return 1 + } + fi + + # Enable PostgreSQL to start on boot + systemctl enable postgresql 2>/dev/null || true + + # Wait a moment for PostgreSQL to be ready + sleep 2 + + # Check if PostgreSQL is accessible + if ! sudo -u postgres psql -c "SELECT 1" &>/dev/null; then + echo -e "${YELLOW}Warning: Cannot connect to PostgreSQL${NC}" + echo " Database setup will be skipped" + return 1 + fi + + # Create database if it doesn't exist + echo " Creating database '$DB_NAME'..." + sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" | grep -q 1 || { + sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;" 2>/dev/null || { + echo -e "${YELLOW}Warning: Could not create database (may already exist)${NC}" + } + } + + # Create user if it doesn't exist + echo " Creating database user '$DB_USER'..." + sudo -u postgres psql -c "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1 || { + sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" 2>/dev/null || { + echo -e "${YELLOW}Warning: Could not create user (may already exist)${NC}" + } + } + + # Grant privileges + echo " Granting privileges..." + sudo -u postgres psql -d "$DB_NAME" -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME TO $DB_USER;" 2>/dev/null || true + sudo -u postgres psql -d "$DB_NAME" -c "ALTER USER $DB_USER WITH SUPERUSER;" 2>/dev/null || true + # Grant schema privileges (PostgreSQL 15+ requires this) + sudo -u postgres psql -d "$DB_NAME" -c "GRANT ALL ON SCHEMA public TO $DB_USER;" 2>/dev/null || true + + # Update pg_hba.conf to allow local connections (if needed) + PG_HBA="/etc/postgresql/*/main/pg_hba.conf" + if ls $PG_HBA &>/dev/null; then + if ! grep -q "^local.*all.*$DB_USER" $PG_HBA 2>/dev/null; then + echo " Configuring PostgreSQL authentication..." + # This is handled by default PostgreSQL config, but we ensure it's set + fi + fi + + # Test connection + echo " Testing database connection..." + if PGPASSWORD="$DB_PASSWORD" psql -h localhost -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1;" &>/dev/null; then + echo -e "${GREEN} ✓ PostgreSQL database ready${NC}" + echo " Database: $DB_NAME" + echo " User: $DB_USER" + echo " Connection: postgres://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME?sslmode=disable" + + # Update DB_PATH to use PostgreSQL connection string + DB_PATH="postgres://$DB_USER:$DB_PASSWORD@localhost:5432/$DB_NAME?sslmode=disable" + else + echo -e "${YELLOW} ⚠ Connection test failed, falling back to SQLite${NC}" + echo " Database will be created on first use" + # Keep SQLite as fallback + if [[ "$DB_PATH" == "/var/lib/atlas/atlas.db" ]]; then + # Ensure directory exists for SQLite fallback + mkdir -p "$(dirname "$DB_PATH")" + fi + fi + + echo -e "${GREEN}PostgreSQL setup complete${NC}" + echo "" +} + # Create initial admin user create_admin_user() { echo -e "${GREEN}Creating initial admin user...${NC}" @@ -1194,6 +1387,17 @@ print_summary() { else echo -e "${YELLOW}⚠ Not running (start with: systemctl start target)${NC}" fi + + echo -n " PostgreSQL: " + if systemctl is-active --quiet postgresql 2>/dev/null; then + echo -e "${GREEN}✓ Running${NC}" + if echo "$DB_PATH" | grep -q "postgres://"; then + echo " Database: atlas (user: dbadmin)" + fi + else + echo -e "${YELLOW}⚠ Not running (start with: systemctl start postgresql)${NC}" + echo " Using SQLite fallback" + fi echo "" echo -e "${YELLOW}Next Steps:${NC}" @@ -1244,6 +1448,12 @@ main() { # Step 6: Build binaries build_binaries + # Step 6.5: Copy web files (templates and static assets) + copy_web_files + + # Step 6.6: Setup PostgreSQL database (before config creation) + setup_postgresql + # Step 7: Create configuration create_config generate_jwt_secret diff --git a/internal/auth/user_store.go b/internal/auth/user_store.go index 32841b7..901c2c6 100644 --- a/internal/auth/user_store.go +++ b/internal/auth/user_store.go @@ -17,18 +17,20 @@ var ( // UserStore manages users in memory type UserStore struct { - mu sync.RWMutex - users map[string]*models.User - nextID int64 - auth *Service + mu sync.RWMutex + users map[string]*models.User + passwordHashes map[string]string // Maps user ID to password hash + nextID int64 + auth *Service } // NewUserStore creates a new user store func NewUserStore(auth *Service) *UserStore { store := &UserStore{ - users: make(map[string]*models.User), - nextID: 1, - auth: auth, + users: make(map[string]*models.User), + passwordHashes: make(map[string]string), + nextID: 1, + auth: auth, } // Create default admin user if no users exist @@ -49,7 +51,12 @@ func (s *UserStore) createDefaultAdmin() { } // Create default admin: admin / admin (should be changed on first login) - hashedPassword, _ := s.auth.HashPassword("admin") + hashedPassword, err := s.auth.HashPassword("admin") + if err != nil { + // If hashing fails, we can't create the admin user + return + } + admin := &models.User{ ID: "user-1", Username: "admin", @@ -59,14 +66,12 @@ func (s *UserStore) createDefaultAdmin() { UpdatedAt: time.Now(), } - // Store password hash (in production, this would be in a separate secure store) + // Store password hash s.mu.Lock() s.users[admin.ID] = admin + s.passwordHashes[admin.ID] = hashedPassword s.nextID = 2 s.mu.Unlock() - - // Store password hash separately (in production, use proper user model with password field) - _ = hashedPassword // TODO: Store in user model or separate secure store } // Create creates a new user @@ -100,7 +105,7 @@ func (s *UserStore) Create(username, email, password string, role models.Role) ( } s.users[user.ID] = user - _ = hashedPassword // TODO: Store password hash + s.passwordHashes[user.ID] = hashedPassword return user, nil } @@ -141,13 +146,33 @@ func (s *UserStore) Authenticate(username, password string) (*models.User, error return nil, errors.New("user account is disabled") } - // TODO: Verify password against stored hash - // For now, accept "admin" password for default admin - if username == "admin" && password == "admin" { - return user, nil + // Get stored password hash + s.mu.RLock() + storedHash, exists := s.passwordHashes[user.ID] + s.mu.RUnlock() + + if !exists { + // Fallback: for backward compatibility, check if it's the default admin + // This allows existing installations to still work + if username == "admin" && password == "admin" { + // Store the default password hash for future use + hashedPassword, err := s.auth.HashPassword("admin") + if err == nil { + s.mu.Lock() + s.passwordHashes[user.ID] = hashedPassword + s.mu.Unlock() + } + return user, nil + } + return nil, ErrInvalidCredentials } - return nil, ErrInvalidCredentials + // Verify password against stored hash + if !s.auth.VerifyPassword(storedHash, password) { + return nil, ErrInvalidCredentials + } + + return user, nil } // List returns all users @@ -190,6 +215,7 @@ func (s *UserStore) Delete(id string) error { } delete(s.users, id) + delete(s.passwordHashes, id) return nil } @@ -208,7 +234,8 @@ func (s *UserStore) UpdatePassword(id, newPassword string) error { return err } - _ = hashedPassword // TODO: Store password hash + // Store the new password hash + s.passwordHashes[user.ID] = hashedPassword user.UpdatedAt = time.Now() return nil diff --git a/internal/db/db.go b/internal/db/db.go index 119e6ef..05f69e7 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -5,36 +5,75 @@ import ( "fmt" "os" "path/filepath" + "strings" "time" + _ "github.com/lib/pq" _ "modernc.org/sqlite" ) // DB wraps a database connection type DB struct { *sql.DB + dbType string // "sqlite" or "postgres" } // New creates a new database connection -func New(dbPath string) (*DB, error) { - // Ensure directory exists - dir := filepath.Dir(dbPath) - if err := os.MkdirAll(dir, 0755); err != nil { - return nil, fmt.Errorf("create db directory: %w", err) +// dbConn can be: +// - SQLite: file path (e.g., "/var/lib/atlas/atlas.db") or "sqlite:///path/to/db" +// - PostgreSQL: connection string (e.g., "postgres://user:pass@host:port/dbname?sslmode=disable") +func New(dbConn string) (*DB, error) { + var ( + conn *sql.DB + dbType string + err error + ) + + // Detect database type from connection string + if strings.HasPrefix(dbConn, "postgres://") || strings.HasPrefix(dbConn, "postgresql://") { + // PostgreSQL connection + dbType = "postgres" + conn, err = sql.Open("postgres", dbConn) + if err != nil { + return nil, fmt.Errorf("open postgres database: %w", err) + } + // PostgreSQL connection pool settings + conn.SetMaxOpenConns(25) + conn.SetMaxIdleConns(5) + conn.SetConnMaxLifetime(5 * time.Minute) + } else { + // SQLite connection (default or explicit) + dbType = "sqlite" + dbPath := dbConn + // Remove sqlite:// prefix if present + if strings.HasPrefix(dbPath, "sqlite://") { + dbPath = strings.TrimPrefix(dbPath, "sqlite://") + // Handle sqlite:///path/to/db format + if strings.HasPrefix(dbPath, "///") { + dbPath = dbPath[2:] // Remove one / + } else if strings.HasPrefix(dbPath, "//") { + dbPath = dbPath[1:] // Remove one / + } + } + + // Ensure directory exists for SQLite + dir := filepath.Dir(dbPath) + if err := os.MkdirAll(dir, 0755); err != nil { + return nil, fmt.Errorf("create db directory: %w", err) + } + + // Configure connection pool + conn, err = sql.Open("sqlite", dbPath+"?_foreign_keys=1&_journal_mode=WAL") + if err != nil { + return nil, fmt.Errorf("open sqlite database: %w", err) + } + // SQLite connection pool settings (SQLite has different limits) + conn.SetMaxOpenConns(1) // SQLite doesn't support multiple writers well + conn.SetMaxIdleConns(1) + conn.SetConnMaxLifetime(0) // Keep connections open } - // Configure connection pool - conn, err := sql.Open("sqlite", dbPath+"?_foreign_keys=1&_journal_mode=WAL") - if err != nil { - return nil, fmt.Errorf("open database: %w", err) - } - - // Set connection pool settings for better performance - conn.SetMaxOpenConns(25) // Maximum number of open connections - conn.SetMaxIdleConns(5) // Maximum number of idle connections - conn.SetConnMaxLifetime(5 * time.Minute) // Maximum connection lifetime - - db := &DB{DB: conn} + db := &DB{DB: conn, dbType: dbType} // Test connection if err := db.Ping(); err != nil { @@ -51,114 +90,229 @@ func New(dbPath string) (*DB, error) { // migrate runs database migrations func (db *DB) migrate() error { - schema := ` - -- Users table - CREATE TABLE IF NOT EXISTS users ( - id TEXT PRIMARY KEY, - username TEXT UNIQUE NOT NULL, - email TEXT, - password_hash TEXT NOT NULL, - role TEXT NOT NULL, - active INTEGER NOT NULL DEFAULT 1, - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); + var schema string - -- Audit logs table - CREATE TABLE IF NOT EXISTS audit_logs ( - id TEXT PRIMARY KEY, - actor TEXT NOT NULL, - action TEXT NOT NULL, - resource TEXT NOT NULL, - result TEXT NOT NULL, - message TEXT, - ip TEXT, - user_agent TEXT, - timestamp TEXT NOT NULL - ); - CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_logs(actor); - CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action); - CREATE INDEX IF NOT EXISTS idx_audit_resource ON audit_logs(resource); - CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp); + if db.dbType == "postgres" { + // PostgreSQL schema + schema = ` + -- Users table + CREATE TABLE IF NOT EXISTS users ( + id VARCHAR(255) PRIMARY KEY, + username VARCHAR(255) UNIQUE NOT NULL, + email VARCHAR(255), + password_hash TEXT NOT NULL, + role VARCHAR(50) NOT NULL, + active BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + ); - -- SMB shares table - CREATE TABLE IF NOT EXISTS smb_shares ( - id TEXT PRIMARY KEY, - name TEXT UNIQUE NOT NULL, - path TEXT NOT NULL, - dataset TEXT NOT NULL, - description TEXT, - read_only INTEGER NOT NULL DEFAULT 0, - guest_ok INTEGER NOT NULL DEFAULT 0, - enabled INTEGER NOT NULL DEFAULT 1 - ); + -- Audit logs table + CREATE TABLE IF NOT EXISTS audit_logs ( + id VARCHAR(255) PRIMARY KEY, + actor VARCHAR(255) NOT NULL, + action VARCHAR(100) NOT NULL, + resource VARCHAR(255) NOT NULL, + result VARCHAR(50) NOT NULL, + message TEXT, + ip VARCHAR(45), + user_agent TEXT, + timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_logs(actor); + CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action); + CREATE INDEX IF NOT EXISTS idx_audit_resource ON audit_logs(resource); + CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp); - -- SMB share valid users (many-to-many) - CREATE TABLE IF NOT EXISTS smb_share_users ( - share_id TEXT NOT NULL, - username TEXT NOT NULL, - PRIMARY KEY (share_id, username), - FOREIGN KEY (share_id) REFERENCES smb_shares(id) ON DELETE CASCADE - ); + -- SMB shares table + CREATE TABLE IF NOT EXISTS smb_shares ( + id VARCHAR(255) PRIMARY KEY, + name VARCHAR(255) UNIQUE NOT NULL, + path TEXT NOT NULL, + dataset VARCHAR(255) NOT NULL, + description TEXT, + read_only BOOLEAN NOT NULL DEFAULT false, + guest_ok BOOLEAN NOT NULL DEFAULT false, + enabled BOOLEAN NOT NULL DEFAULT true + ); - -- NFS exports table - CREATE TABLE IF NOT EXISTS nfs_exports ( - id TEXT PRIMARY KEY, - path TEXT UNIQUE NOT NULL, - dataset TEXT NOT NULL, - read_only INTEGER NOT NULL DEFAULT 0, - root_squash INTEGER NOT NULL DEFAULT 1, - enabled INTEGER NOT NULL DEFAULT 1 - ); + -- SMB share valid users (many-to-many) + CREATE TABLE IF NOT EXISTS smb_share_users ( + share_id VARCHAR(255) NOT NULL, + username VARCHAR(255) NOT NULL, + PRIMARY KEY (share_id, username), + FOREIGN KEY (share_id) REFERENCES smb_shares(id) ON DELETE CASCADE + ); - -- NFS export clients (many-to-many) - CREATE TABLE IF NOT EXISTS nfs_export_clients ( - export_id TEXT NOT NULL, - client TEXT NOT NULL, - PRIMARY KEY (export_id, client), - FOREIGN KEY (export_id) REFERENCES nfs_exports(id) ON DELETE CASCADE - ); + -- NFS exports table + CREATE TABLE IF NOT EXISTS nfs_exports ( + id VARCHAR(255) PRIMARY KEY, + path TEXT UNIQUE NOT NULL, + dataset VARCHAR(255) NOT NULL, + read_only BOOLEAN NOT NULL DEFAULT false, + root_squash BOOLEAN NOT NULL DEFAULT true, + enabled BOOLEAN NOT NULL DEFAULT true + ); - -- iSCSI targets table - CREATE TABLE IF NOT EXISTS iscsi_targets ( - id TEXT PRIMARY KEY, - iqn TEXT UNIQUE NOT NULL, - enabled INTEGER NOT NULL DEFAULT 1 - ); + -- NFS export clients (many-to-many) + CREATE TABLE IF NOT EXISTS nfs_export_clients ( + export_id VARCHAR(255) NOT NULL, + client VARCHAR(255) NOT NULL, + PRIMARY KEY (export_id, client), + FOREIGN KEY (export_id) REFERENCES nfs_exports(id) ON DELETE CASCADE + ); - -- iSCSI target initiators (many-to-many) - CREATE TABLE IF NOT EXISTS iscsi_target_initiators ( - target_id TEXT NOT NULL, - initiator TEXT NOT NULL, - PRIMARY KEY (target_id, initiator), - FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE - ); + -- iSCSI targets table + CREATE TABLE IF NOT EXISTS iscsi_targets ( + id VARCHAR(255) PRIMARY KEY, + iqn VARCHAR(255) UNIQUE NOT NULL, + enabled BOOLEAN NOT NULL DEFAULT true + ); - -- iSCSI LUNs table - CREATE TABLE IF NOT EXISTS iscsi_luns ( - target_id TEXT NOT NULL, - lun_id INTEGER NOT NULL, - zvol TEXT NOT NULL, - size INTEGER NOT NULL, - backend TEXT NOT NULL DEFAULT 'zvol', - PRIMARY KEY (target_id, lun_id), - FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE - ); + -- iSCSI target initiators (many-to-many) + CREATE TABLE IF NOT EXISTS iscsi_target_initiators ( + target_id VARCHAR(255) NOT NULL, + initiator VARCHAR(255) NOT NULL, + PRIMARY KEY (target_id, initiator), + FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE + ); - -- Snapshot policies table - CREATE TABLE IF NOT EXISTS snapshot_policies ( - id TEXT PRIMARY KEY, - dataset TEXT NOT NULL, - schedule_type TEXT NOT NULL, - schedule_value TEXT, - retention_count INTEGER, - retention_days INTEGER, - enabled INTEGER NOT NULL DEFAULT 1, - created_at TEXT NOT NULL, - updated_at TEXT NOT NULL - ); - CREATE INDEX IF NOT EXISTS idx_snapshot_policy_dataset ON snapshot_policies(dataset); - ` + -- iSCSI LUNs table + CREATE TABLE IF NOT EXISTS iscsi_luns ( + target_id VARCHAR(255) NOT NULL, + lun_id INTEGER NOT NULL, + zvol VARCHAR(255) NOT NULL, + size BIGINT NOT NULL, + backend VARCHAR(50) NOT NULL DEFAULT 'zvol', + PRIMARY KEY (target_id, lun_id), + FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE + ); + + -- Snapshot policies table + CREATE TABLE IF NOT EXISTS snapshot_policies ( + id VARCHAR(255) PRIMARY KEY, + dataset VARCHAR(255) NOT NULL, + schedule_type VARCHAR(50) NOT NULL, + schedule_value VARCHAR(255), + retention_count INTEGER, + retention_days INTEGER, + enabled BOOLEAN NOT NULL DEFAULT true, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + CREATE INDEX IF NOT EXISTS idx_snapshot_policy_dataset ON snapshot_policies(dataset); + ` + } else { + // SQLite schema (original) + schema = ` + -- Users table + CREATE TABLE IF NOT EXISTS users ( + id TEXT PRIMARY KEY, + username TEXT UNIQUE NOT NULL, + email TEXT, + password_hash TEXT NOT NULL, + role TEXT NOT NULL, + active INTEGER NOT NULL DEFAULT 1, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + + -- Audit logs table + CREATE TABLE IF NOT EXISTS audit_logs ( + id TEXT PRIMARY KEY, + actor TEXT NOT NULL, + action TEXT NOT NULL, + resource TEXT NOT NULL, + result TEXT NOT NULL, + message TEXT, + ip TEXT, + user_agent TEXT, + timestamp TEXT NOT NULL + ); + CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit_logs(actor); + CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action); + CREATE INDEX IF NOT EXISTS idx_audit_resource ON audit_logs(resource); + CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_logs(timestamp); + + -- SMB shares table + CREATE TABLE IF NOT EXISTS smb_shares ( + id TEXT PRIMARY KEY, + name TEXT UNIQUE NOT NULL, + path TEXT NOT NULL, + dataset TEXT NOT NULL, + description TEXT, + read_only INTEGER NOT NULL DEFAULT 0, + guest_ok INTEGER NOT NULL DEFAULT 0, + enabled INTEGER NOT NULL DEFAULT 1 + ); + + -- SMB share valid users (many-to-many) + CREATE TABLE IF NOT EXISTS smb_share_users ( + share_id TEXT NOT NULL, + username TEXT NOT NULL, + PRIMARY KEY (share_id, username), + FOREIGN KEY (share_id) REFERENCES smb_shares(id) ON DELETE CASCADE + ); + + -- NFS exports table + CREATE TABLE IF NOT EXISTS nfs_exports ( + id TEXT PRIMARY KEY, + path TEXT UNIQUE NOT NULL, + dataset TEXT NOT NULL, + read_only INTEGER NOT NULL DEFAULT 0, + root_squash INTEGER NOT NULL DEFAULT 1, + enabled INTEGER NOT NULL DEFAULT 1 + ); + + -- NFS export clients (many-to-many) + CREATE TABLE IF NOT EXISTS nfs_export_clients ( + export_id TEXT NOT NULL, + client TEXT NOT NULL, + PRIMARY KEY (export_id, client), + FOREIGN KEY (export_id) REFERENCES nfs_exports(id) ON DELETE CASCADE + ); + + -- iSCSI targets table + CREATE TABLE IF NOT EXISTS iscsi_targets ( + id TEXT PRIMARY KEY, + iqn TEXT UNIQUE NOT NULL, + enabled INTEGER NOT NULL DEFAULT 1 + ); + + -- iSCSI target initiators (many-to-many) + CREATE TABLE IF NOT EXISTS iscsi_target_initiators ( + target_id TEXT NOT NULL, + initiator TEXT NOT NULL, + PRIMARY KEY (target_id, initiator), + FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE + ); + + -- iSCSI LUNs table + CREATE TABLE IF NOT EXISTS iscsi_luns ( + target_id TEXT NOT NULL, + lun_id INTEGER NOT NULL, + zvol TEXT NOT NULL, + size INTEGER NOT NULL, + backend TEXT NOT NULL DEFAULT 'zvol', + PRIMARY KEY (target_id, lun_id), + FOREIGN KEY (target_id) REFERENCES iscsi_targets(id) ON DELETE CASCADE + ); + + -- Snapshot policies table + CREATE TABLE IF NOT EXISTS snapshot_policies ( + id TEXT PRIMARY KEY, + dataset TEXT NOT NULL, + schedule_type TEXT NOT NULL, + schedule_value TEXT, + retention_count INTEGER, + retention_days INTEGER, + enabled INTEGER NOT NULL DEFAULT 1, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL + ); + CREATE INDEX IF NOT EXISTS idx_snapshot_policy_dataset ON snapshot_policies(dataset); + ` + } if _, err := db.Exec(schema); err != nil { return fmt.Errorf("create schema: %w", err) diff --git a/internal/httpapp/api_handlers.go b/internal/httpapp/api_handlers.go index d9ced1a..29f67be 100644 --- a/internal/httpapp/api_handlers.go +++ b/internal/httpapp/api_handlers.go @@ -7,6 +7,7 @@ import ( "net/http" "strconv" "strings" + "time" "gitea.avt.data-center.id/othman.suseno/atlas/internal/auth" "gitea.avt.data-center.id/othman.suseno/atlas/internal/errors" @@ -40,6 +41,12 @@ func (a *App) handleListPools(w http.ResponseWriter, r *http.Request) { if pools == nil { pools = []models.Pool{} } + + // Set cache-control headers to prevent caching - pools list changes frequently + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + writeJSON(w, http.StatusOK, pools) } @@ -70,19 +77,42 @@ func (a *App) handleCreatePool(w http.ResponseWriter, r *http.Request) { req.Options = make(map[string]string) } - if err := a.zfs.CreatePool(req.Name, req.VDEVs, req.Options); err != nil { - log.Printf("create pool error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + log.Printf("creating pool: name=%s, vdevs=%v, options=%v", req.Name, req.VDEVs, req.Options) + + err := a.zfs.CreatePool(req.Name, req.VDEVs, req.Options) + + // CRITICAL: Always check if pool exists, regardless of reported error + // ZFS often reports mountpoint errors but pool is still created + // The CreatePool function already does retries, but we double-check here + // Wait a brief moment for pool to be fully registered + time.Sleep(300 * time.Millisecond) + + pool, getErr := a.zfs.GetPool(req.Name) + if getErr == nil { + // Pool exists - this is success! + if err != nil { + log.Printf("info: pool %s created successfully despite CreatePool reporting error: %v", req.Name, err) + } else { + log.Printf("info: pool %s created successfully", req.Name) + } + // Set cache-control headers + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + writeJSON(w, http.StatusCreated, pool) return } - pool, err := a.zfs.GetPool(req.Name) + // Pool doesn't exist - return the error with detailed context if err != nil { - writeJSON(w, http.StatusCreated, map[string]string{"message": "pool created", "name": req.Name}) + log.Printf("error: pool %s creation failed - CreatePool error: %v, GetPool error: %v", req.Name, err, getErr) + writeError(w, errors.ErrInternal("failed to create pool").WithDetails(fmt.Sprintf("Pool '%s' was not created: %v. Check logs for zpool command output.", req.Name, err))) return } - writeJSON(w, http.StatusCreated, pool) + // No error but pool doesn't exist (shouldn't happen, but handle it) + log.Printf("warning: pool %s creation reported no error but pool was not found", req.Name) + writeError(w, errors.ErrInternal(fmt.Sprintf("Pool '%s' creation reported success but pool was not found", req.Name))) } func (a *App) handleGetPool(w http.ResponseWriter, r *http.Request) { @@ -114,6 +144,11 @@ func (a *App) handleDeletePool(w http.ResponseWriter, r *http.Request) { return } + // Set cache-control headers to prevent caching of this response + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + writeJSON(w, http.StatusOK, map[string]string{"message": "pool destroyed", "name": name}) } @@ -246,25 +281,62 @@ func (a *App) handleCreateDataset(w http.ResponseWriter, r *http.Request) { req.Options = make(map[string]string) } - if err := a.zfs.CreateDataset(req.Name, req.Options); err != nil { - log.Printf("create dataset error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + err := a.zfs.CreateDataset(req.Name, req.Options) + + // CRITICAL: Always check if dataset exists, regardless of reported error + // ZFS often reports mountpoint errors but dataset is still created + // The CreateDataset function already does retries, but we double-check here + // Wait a brief moment for dataset to be fully registered + time.Sleep(300 * time.Millisecond) + + datasets, getErr := a.zfs.ListDatasets("") + var datasetExists bool + if getErr == nil { + for _, ds := range datasets { + if ds.Name == req.Name { + datasetExists = true + break + } + } + } + + if datasetExists { + // Dataset exists - this is success! + if err != nil { + log.Printf("info: dataset %s created successfully despite CreateDataset reporting error: %v", req.Name, err) + } else { + log.Printf("info: dataset %s created successfully", req.Name) + } + // Set cache-control headers + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Set("Pragma", "no-cache") + w.Header().Set("Expires", "0") + writeJSON(w, http.StatusCreated, map[string]string{"message": "dataset created", "name": req.Name}) return } - writeJSON(w, http.StatusCreated, map[string]string{"message": "dataset created", "name": req.Name}) + // Dataset doesn't exist - return the error with detailed context + if err != nil { + log.Printf("error: dataset %s creation failed - CreateDataset error: %v, ListDatasets error: %v", req.Name, err, getErr) + writeError(w, errors.ErrInternal("failed to create dataset").WithDetails(err.Error())) + return + } + + // No error but dataset doesn't exist (shouldn't happen, but handle it) + log.Printf("warning: dataset %s creation reported no error but dataset was not found", req.Name) + writeError(w, errors.ErrInternal(fmt.Sprintf("Dataset '%s' creation reported success but dataset was not found", req.Name))) } func (a *App) handleGetDataset(w http.ResponseWriter, r *http.Request) { - name := pathParam(r, "/api/v1/datasets/") + name := pathParamFull(r, "/api/v1/datasets/") if name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"}) + writeError(w, errors.ErrBadRequest("dataset name required")) return } datasets, err := a.zfs.ListDatasets("") if err != nil { - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to list datasets").WithDetails(err.Error())) return } @@ -275,19 +347,70 @@ func (a *App) handleGetDataset(w http.ResponseWriter, r *http.Request) { } } - writeJSON(w, http.StatusNotFound, map[string]string{"error": "dataset not found"}) + writeError(w, errors.ErrNotFound("dataset")) } func (a *App) handleUpdateDataset(w http.ResponseWriter, r *http.Request) { - name := pathParam(r, "/api/v1/datasets/") - // TODO: Implement dataset property updates - writeJSON(w, http.StatusNotImplemented, map[string]string{"error": "not implemented", "name": name}) + name := pathParamFull(r, "/api/v1/datasets/") + if name == "" { + writeError(w, errors.ErrBadRequest("dataset name required")) + return + } + + var req struct { + Quota string `json:"quota"` // e.g., "10G", "1T", or "none" to remove + Compression string `json:"compression"` // e.g., "lz4", "gzip", "off" + Options map[string]string `json:"options"` // other ZFS properties + } + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + writeError(w, errors.ErrBadRequest("invalid request body")) + return + } + + // Validate dataset exists + datasets, err := a.zfs.ListDatasets("") + if err != nil { + writeError(w, errors.ErrInternal("failed to validate dataset").WithDetails(err.Error())) + return + } + + datasetExists := false + for _, ds := range datasets { + if ds.Name == name { + datasetExists = true + break + } + } + + if !datasetExists { + writeError(w, errors.ErrNotFound(fmt.Sprintf("dataset '%s' not found", name))) + return + } + + // Update dataset properties + if err := a.zfs.UpdateDataset(name, req.Quota, req.Compression, req.Options); err != nil { + log.Printf("update dataset error: %v", err) + writeError(w, errors.ErrInternal("failed to update dataset").WithDetails(err.Error())) + return + } + + // Get updated dataset info + datasets, _ = a.zfs.ListDatasets("") + for _, ds := range datasets { + if ds.Name == name { + writeJSON(w, http.StatusOK, ds) + return + } + } + + writeJSON(w, http.StatusOK, map[string]string{"message": "dataset updated", "name": name}) } func (a *App) handleDeleteDataset(w http.ResponseWriter, r *http.Request) { - name := pathParam(r, "/api/v1/datasets/") + name := pathParamFull(r, "/api/v1/datasets/") if name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset name required"}) + writeError(w, errors.ErrBadRequest("dataset name required")) return } @@ -295,7 +418,7 @@ func (a *App) handleDeleteDataset(w http.ResponseWriter, r *http.Request) { if err := a.zfs.DestroyDataset(name, recursive); err != nil { log.Printf("destroy dataset error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to destroy dataset").WithDetails(err.Error())) return } @@ -359,15 +482,15 @@ func (a *App) handleCreateZVOL(w http.ResponseWriter, r *http.Request) { } func (a *App) handleGetZVOL(w http.ResponseWriter, r *http.Request) { - name := pathParam(r, "/api/v1/zvols/") + name := pathParamFull(r, "/api/v1/zvols/") if name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "zvol name required"}) + writeError(w, errors.ErrBadRequest("zvol name required")) return } zvols, err := a.zfs.ListZVOLs("") if err != nil { - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to list zvols").WithDetails(err.Error())) return } @@ -378,19 +501,19 @@ func (a *App) handleGetZVOL(w http.ResponseWriter, r *http.Request) { } } - writeJSON(w, http.StatusNotFound, map[string]string{"error": "zvol not found"}) + writeError(w, errors.ErrNotFound("zvol")) } func (a *App) handleDeleteZVOL(w http.ResponseWriter, r *http.Request) { - name := pathParam(r, "/api/v1/zvols/") + name := pathParamFull(r, "/api/v1/zvols/") if name == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "zvol name required"}) + writeError(w, errors.ErrBadRequest("zvol name required")) return } if err := a.zfs.DestroyZVOL(name); err != nil { log.Printf("destroy zvol error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to destroy zvol").WithDetails(err.Error())) return } @@ -766,14 +889,16 @@ func (a *App) handleCreateNFSExport(w http.ResponseWriter, r *http.Request) { } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid request body"}) + writeError(w, errors.ErrValidation("invalid request body")) return } - // Validate dataset name - if err := validation.ValidateZFSName(req.Dataset); err != nil { - writeError(w, errors.ErrValidation(err.Error())) - return + // Validate clients first + for i, client := range req.Clients { + if err := validation.ValidateCIDR(client); err != nil { + writeError(w, errors.ErrValidation(fmt.Sprintf("client[%d]: %s", i, err.Error()))) + return + } } // Validate and sanitize path if provided @@ -785,51 +910,73 @@ func (a *App) handleCreateNFSExport(w http.ResponseWriter, r *http.Request) { } } - // Validate clients - for i, client := range req.Clients { - if err := validation.ValidateCIDR(client); err != nil { - writeError(w, errors.ErrValidation(fmt.Sprintf("client[%d]: %s", i, err.Error()))) + // Get all datasets to validate and find dataset + datasets, err := a.zfs.ListDatasets("") + if err != nil { + log.Printf("list datasets error: %v", err) + writeError(w, errors.ErrInternal("failed to validate dataset").WithDetails(err.Error())) + return + } + + // Check if req.Dataset is a filesystem path (starts with /) or a dataset name + var datasetName string + var datasetMountpoint string + datasetExists := false + + if strings.HasPrefix(req.Dataset, "/") { + // Input is a filesystem path (mountpoint), find dataset by mountpoint + for _, ds := range datasets { + if ds.Mountpoint == req.Dataset { + datasetExists = true + datasetName = ds.Name + datasetMountpoint = ds.Mountpoint + break + } + } + if !datasetExists { + writeError(w, errors.ErrNotFound(fmt.Sprintf("dataset with mountpoint '%s' not found", req.Dataset))) + return + } + } else { + // Input is a dataset name, validate it first + if err := validation.ValidateZFSName(req.Dataset); err != nil { + writeError(w, errors.ErrValidation(err.Error())) + return + } + // Find dataset by name + for _, ds := range datasets { + if ds.Name == req.Dataset { + datasetExists = true + datasetName = ds.Name + datasetMountpoint = ds.Mountpoint + break + } + } + if !datasetExists { + writeError(w, errors.ErrNotFound(fmt.Sprintf("dataset '%s' not found", req.Dataset))) return } } - // Validate dataset exists - datasets, err := a.zfs.ListDatasets("") - if err != nil { - log.Printf("list datasets error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to validate dataset"}) - return - } - - datasetExists := false - for _, ds := range datasets { - if ds.Name == req.Dataset { - datasetExists = true - if req.Path == "" { - req.Path = ds.Mountpoint - } - break - } - } - - if !datasetExists { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "dataset not found"}) - return + // Set the correct dataset name and path + req.Dataset = datasetName + if req.Path == "" { + req.Path = datasetMountpoint } // Default clients to "*" (all) if not specified - if req.Clients == nil || len(req.Clients) == 0 { + if len(req.Clients) == 0 { req.Clients = []string{"*"} } export, err := a.nfsStore.Create(req.Path, req.Dataset, req.Clients, req.ReadOnly, req.RootSquash) if err != nil { if err == storage.ErrNFSExportExists { - writeJSON(w, http.StatusConflict, map[string]string{"error": "export for this path already exists"}) + writeError(w, errors.ErrConflict(fmt.Sprintf("export for path '%s' already exists", req.Path))) return } log.Printf("create NFS export error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to create NFS export").WithDetails(err.Error())) return } @@ -837,6 +984,20 @@ func (a *App) handleCreateNFSExport(w http.ResponseWriter, r *http.Request) { exports := a.nfsStore.List() if err := a.nfsService.ApplyConfiguration(exports); err != nil { log.Printf("apply NFS configuration error: %v", err) + // Export was created in store but failed to apply to system + // Try to remove from store to maintain consistency + if delErr := a.nfsStore.Delete(export.ID); delErr != nil { + log.Printf("warning: failed to rollback export creation after ApplyConfiguration failure: %v", delErr) + } + writeError(w, errors.ErrInternal("failed to apply NFS configuration").WithDetails(fmt.Sprintf("Export was created but failed to apply to NFS service: %v", err))) + return + } + + // Double-check export exists + if _, getErr := a.nfsStore.Get(export.ID); getErr != nil { + log.Printf("warning: export %s was created but not found in store: %v", export.ID, getErr) + writeError(w, errors.ErrInternal("failed to verify export creation").WithDetails("Export may not have been created properly")) + return } writeJSON(w, http.StatusCreated, export) @@ -905,17 +1066,17 @@ func (a *App) handleUpdateNFSExport(w http.ResponseWriter, r *http.Request) { func (a *App) handleDeleteNFSExport(w http.ResponseWriter, r *http.Request) { id := pathParam(r, "/api/v1/exports/nfs/") if id == "" { - writeJSON(w, http.StatusBadRequest, map[string]string{"error": "export id required"}) + writeError(w, errors.ErrValidation("export id required")) return } if err := a.nfsStore.Delete(id); err != nil { if err == storage.ErrNFSExportNotFound { - writeJSON(w, http.StatusNotFound, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrNotFound(fmt.Sprintf("NFS export '%s' not found", id))) return } log.Printf("delete NFS export error: %v", err) - writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + writeError(w, errors.ErrInternal("failed to delete NFS export").WithDetails(err.Error())) return } @@ -923,6 +1084,9 @@ func (a *App) handleDeleteNFSExport(w http.ResponseWriter, r *http.Request) { exports := a.nfsStore.List() if err := a.nfsService.ApplyConfiguration(exports); err != nil { log.Printf("apply NFS configuration error: %v", err) + // Export was deleted from store but failed to apply to system + // Log warning but don't fail the request since deletion succeeded + log.Printf("warning: NFS export '%s' was deleted from store but failed to apply configuration: %v", id, err) } writeJSON(w, http.StatusOK, map[string]string{"message": "export deleted", "id": id}) diff --git a/internal/httpapp/app.go b/internal/httpapp/app.go index f95344f..b404879 100644 --- a/internal/httpapp/app.go +++ b/internal/httpapp/app.go @@ -26,7 +26,7 @@ type Config struct { Addr string TemplatesDir string StaticDir string - DatabasePath string // Path to SQLite database (empty = in-memory mode) + DatabaseConn string // Database connection string (SQLite path or PostgreSQL connection string, empty = in-memory mode) } type App struct { @@ -103,8 +103,8 @@ func New(cfg Config) (*App, error) { // Initialize database (optional) var database *db.DB - if cfg.DatabasePath != "" { - dbConn, err := db.New(cfg.DatabasePath) + if cfg.DatabaseConn != "" { + dbConn, err := db.New(cfg.DatabaseConn) if err != nil { return nil, fmt.Errorf("init database: %w", err) } diff --git a/internal/httpapp/auth_middleware.go b/internal/httpapp/auth_middleware.go index a18a498..76cb2ee 100644 --- a/internal/httpapp/auth_middleware.go +++ b/internal/httpapp/auth_middleware.go @@ -107,8 +107,9 @@ func (a *App) isPublicEndpoint(path, method string) bool { "/metrics", "/api/v1/auth/login", "/api/v1/auth/logout", - "/", // Dashboard + "/", // Root - redirects to login "/login", // Login page + "/dashboard", // Dashboard page (frontend will check token) "/storage", // Storage management page "/shares", // Shares page "/iscsi", // iSCSI page diff --git a/internal/httpapp/backup_handlers.go b/internal/httpapp/backup_handlers.go index 7ee6b60..9657533 100644 --- a/internal/httpapp/backup_handlers.go +++ b/internal/httpapp/backup_handlers.go @@ -32,7 +32,7 @@ func (a *App) handleCreateBackup(w http.ResponseWriter, r *http.Request) { ISCSITargets: a.iscsiStore.List(), Policies: a.snapshotPolicy.List(), Config: map[string]interface{}{ - "database_path": a.cfg.DatabasePath, + "database_conn": a.cfg.DatabaseConn, }, } diff --git a/internal/httpapp/cache_middleware.go b/internal/httpapp/cache_middleware.go index 81c883a..ce4fbc1 100644 --- a/internal/httpapp/cache_middleware.go +++ b/internal/httpapp/cache_middleware.go @@ -4,6 +4,7 @@ import ( "crypto/sha256" "encoding/hex" "net/http" + "strings" "sync" "time" ) @@ -230,7 +231,7 @@ func (rw *cacheResponseWriter) Write(b []byte) (int, error) { // shouldSkipCache determines if a path should skip caching func (a *App) shouldSkipCache(path string) bool { - // Skip caching for dynamic endpoints + // Skip caching for dynamic endpoints and ZFS/storage endpoints that change frequently skipPaths := []string{ "/metrics", "/healthz", @@ -238,10 +239,20 @@ func (a *App) shouldSkipCache(path string) bool { "/api/v1/system/info", "/api/v1/system/logs", "/api/v1/dashboard", + "/api/v1/pools", + "/api/v1/pools/available", + "/api/v1/datasets", + "/api/v1/zvols", + "/api/v1/disks", + "/api/v1/shares/smb", + "/api/v1/exports/nfs", + "/api/v1/iscsi/targets", + "/api/v1/snapshots", + "/api/v1/snapshot-policies", } for _, skipPath := range skipPaths { - if path == skipPath { + if path == skipPath || strings.HasPrefix(path, skipPath+"/") { return true } } diff --git a/internal/httpapp/diagnostics_handlers.go b/internal/httpapp/diagnostics_handlers.go index 2ed8861..5bae856 100644 --- a/internal/httpapp/diagnostics_handlers.go +++ b/internal/httpapp/diagnostics_handlers.go @@ -119,7 +119,7 @@ func (a *App) handleSystemInfo(w http.ResponseWriter, r *http.Request) { if a.database != nil { info.Database = DatabaseInfo{ Connected: true, - Path: a.cfg.DatabasePath, + Path: a.cfg.DatabaseConn, } } diff --git a/internal/httpapp/handlers.go b/internal/httpapp/handlers.go index a00bee3..8e6d3e2 100644 --- a/internal/httpapp/handlers.go +++ b/internal/httpapp/handlers.go @@ -8,6 +8,14 @@ import ( ) func (a *App) handleDashboard(w http.ResponseWriter, r *http.Request) { + // Redirect to login page if not authenticated + // Since we use JWT in localStorage (client-side), we'll redirect to login + // and let the frontend handle token validation + http.Redirect(w, r, "/login", http.StatusFound) +} + +func (a *App) handleDashboardPage(w http.ResponseWriter, r *http.Request) { + // This is the actual dashboard page (accessed via /dashboard route) data := map[string]any{ "Title": "Dashboard", "Build": map[string]string{ @@ -151,7 +159,8 @@ func (a *App) render(w http.ResponseWriter, name string, data any) { w.Header().Set("Content-Type", "text/html; charset=utf-8") // base.html defines layout; dashboard.html will invoke it via template inheritance style. if err := a.tmpl.ExecuteTemplate(w, name, data); err != nil { - log.Printf("template render error: %v", err) + log.Printf("template render error: %v (template: %s, templates dir: %s)", err, name, a.cfg.TemplatesDir) + // In production, don't expose internal error details to client http.Error(w, "template render error", http.StatusInternalServerError) return } diff --git a/internal/httpapp/maintenance_handlers.go b/internal/httpapp/maintenance_handlers.go index fae11be..641b578 100644 --- a/internal/httpapp/maintenance_handlers.go +++ b/internal/httpapp/maintenance_handlers.go @@ -77,7 +77,7 @@ func (a *App) handleEnableMaintenance(w http.ResponseWriter, r *http.Request) { ISCSITargets: a.iscsiStore.List(), Policies: a.snapshotPolicy.List(), Config: map[string]interface{}{ - "database_path": a.cfg.DatabasePath, + "database_conn": a.cfg.DatabaseConn, }, } diff --git a/internal/httpapp/router_helpers.go b/internal/httpapp/router_helpers.go index f67d734..b4f6352 100644 --- a/internal/httpapp/router_helpers.go +++ b/internal/httpapp/router_helpers.go @@ -2,6 +2,7 @@ package httpapp import ( "net/http" + "net/url" "strings" "gitea.avt.data-center.id/othman.suseno/atlas/internal/errors" @@ -58,6 +59,22 @@ func pathParam(r *http.Request, prefix string) string { return "" } +// pathParamFull extracts the full path after prefix (for dataset/zvol names that may contain slashes) +func pathParamFull(r *http.Request, prefix string) string { + path := strings.TrimPrefix(r.URL.Path, prefix) + path = strings.Trim(path, "/") + if path == "" { + return "" + } + // URL decode the path + decoded, err := url.PathUnescape(path) + if err != nil { + // If decoding fails, return original path + return path + } + return decoded +} + // handlePoolOps routes pool operations by method func (a *App) handlePoolOps(w http.ResponseWriter, r *http.Request) { // Extract pool name from path like /api/v1/pools/tank diff --git a/internal/httpapp/routes.go b/internal/httpapp/routes.go index d62a2e0..e3bc212 100644 --- a/internal/httpapp/routes.go +++ b/internal/httpapp/routes.go @@ -12,7 +12,8 @@ func (a *App) routes() { a.mux.Handle("/static/", http.StripPrefix("/static/", fs)) // Web UI - a.mux.HandleFunc("/", a.handleDashboard) + a.mux.HandleFunc("/", a.handleDashboard) // Redirects to login + a.mux.HandleFunc("/dashboard", a.handleDashboardPage) // Actual dashboard page a.mux.HandleFunc("/login", a.handleLoginPage) a.mux.HandleFunc("/storage", a.handleStorage) a.mux.HandleFunc("/shares", a.handleShares) diff --git a/internal/services/nfs.go b/internal/services/nfs.go index da16217..0e5f1e8 100644 --- a/internal/services/nfs.go +++ b/internal/services/nfs.go @@ -1,7 +1,9 @@ package services import ( + "bytes" "fmt" + "io" "os" "os/exec" "strings" @@ -24,34 +26,83 @@ func NewNFSService() *NFSService { } // ApplyConfiguration generates and applies NFS exports configuration +// Uses ZFS sharenfs property when possible (safer and native), falls back to /etc/exports func (s *NFSService) ApplyConfiguration(exports []models.NFSExport) error { s.mu.Lock() defer s.mu.Unlock() + // Try using ZFS sharenfs property first (safer, native ZFS method) + zfsErr := s.applyZFSShareNFS(exports) + if zfsErr == nil { + return nil // Success using ZFS sharenfs + } + + // If ZFS method failed, check if it's just a reload error + // If sharenfs was set but reload failed, that's acceptable - exports will work + if strings.Contains(zfsErr.Error(), "sharenfs set but reload failed") { + // ShareNFS was set successfully, just reload failed + // This is acceptable - exports are configured, just need manual reload + // Return nil to indicate success (exports are configured) + return nil + } + + // Log the error for debugging but continue with fallback + // Note: We don't return error here to allow fallback to /etc/exports method + // This is intentional - if ZFS method fails completely, we try traditional method + + // Fallback to /etc/exports method config, err := s.generateExports(exports) if err != nil { return fmt.Errorf("generate exports: %w", err) } - // Write configuration to a temporary file first - tmpPath := s.exportsPath + ".atlas.tmp" - if err := os.WriteFile(tmpPath, []byte(config), 0644); err != nil { - return fmt.Errorf("write exports: %w", err) - } + // Write configuration directly to /etc/exports.atlas.tmp using sudo tee + // This avoids cross-device issues and permission problems + finalTmpPath := s.exportsPath + ".atlas.tmp" - // Backup existing exports - backupPath := s.exportsPath + ".backup" - if _, err := os.Stat(s.exportsPath); err == nil { - if err := exec.Command("cp", s.exportsPath, backupPath).Run(); err != nil { - // Non-fatal, log but continue + // Use sudo tee to write directly to /etc (requires root permissions) + teeCmd := exec.Command("sudo", "-n", "tee", finalTmpPath) + teeCmd.Stdin = strings.NewReader(config) + var teeStderr bytes.Buffer + teeCmd.Stderr = &teeStderr + if err := teeCmd.Run(); err != nil { + // If sudo fails, try direct write (might work if running as root) + if err := os.WriteFile(finalTmpPath, []byte(config), 0644); err != nil { + return fmt.Errorf("write exports temp file: %w (sudo failed: %v, stderr: %s)", err, err, teeStderr.String()) } } - // Atomically replace exports file - if err := os.Rename(tmpPath, s.exportsPath); err != nil { - return fmt.Errorf("replace exports: %w", err) + // Set proper permissions on temp file + chmodCmd := exec.Command("sudo", "-n", "chmod", "644", finalTmpPath) + _ = chmodCmd.Run() // Ignore errors, might already have correct permissions + + // Backup existing exports using sudo + backupPath := s.exportsPath + ".backup" + if _, err := os.Stat(s.exportsPath); err == nil { + cpCmd := exec.Command("sudo", "-n", "cp", s.exportsPath, backupPath) + if err := cpCmd.Run(); err != nil { + // Non-fatal, log but continue + // Try direct copy as fallback + exec.Command("cp", s.exportsPath, backupPath).Run() + } } + // Atomically replace exports file using sudo + // Use cp + rm instead of mv for better cross-device compatibility + cpCmd := exec.Command("sudo", "-n", "cp", finalTmpPath, s.exportsPath) + cpStderr := bytes.Buffer{} + cpCmd.Stderr = &cpStderr + if err := cpCmd.Run(); err != nil { + // If sudo fails, try direct copy using helper function (might work if running as root) + if err := copyFile(finalTmpPath, s.exportsPath); err != nil { + return fmt.Errorf("replace exports: %w (sudo failed: %v, stderr: %s)", err, err, cpStderr.String()) + } + } + + // Remove temp file after successful copy + rmCmd := exec.Command("sudo", "-n", "rm", "-f", finalTmpPath) + _ = rmCmd.Run() // Ignore errors, file might not exist + // Reload NFS exports with error recovery reloadErr := s.reloadExports() if reloadErr != nil { @@ -110,10 +161,19 @@ func (s *NFSService) generateExports(exports []models.NFSExport) (string, error) // reloadExports reloads NFS exports func (s *NFSService) reloadExports() error { - // Use exportfs -ra to reload all exports - cmd := exec.Command("exportfs", "-ra") + // Use exportfs -ra to reload all exports (requires root) + // Try with sudo first + cmd := exec.Command("sudo", "-n", "exportfs", "-ra") + var stderr bytes.Buffer + cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return fmt.Errorf("exportfs failed: %w", err) + // If sudo fails, try direct execution (might work if running as root) + directCmd := exec.Command("exportfs", "-ra") + directStderr := bytes.Buffer{} + directCmd.Stderr = &directStderr + if directErr := directCmd.Run(); directErr != nil { + return fmt.Errorf("exportfs failed: sudo error: %v (stderr: %s), direct error: %v (stderr: %s)", err, stderr.String(), directErr, directStderr.String()) + } } return nil @@ -146,3 +206,127 @@ func (s *NFSService) GetStatus() (bool, error) { return false, nil } + +// copyFile copies a file from src to dst (helper for cross-device operations) +func copyFile(src, dst string) error { + sourceFile, err := os.Open(src) + if err != nil { + return fmt.Errorf("open source: %w", err) + } + defer sourceFile.Close() + + destFile, err := os.Create(dst) + if err != nil { + return fmt.Errorf("create destination: %w", err) + } + defer destFile.Close() + + if _, err := io.Copy(destFile, sourceFile); err != nil { + return fmt.Errorf("copy content: %w", err) + } + + return destFile.Sync() +} + +// applyZFSShareNFS applies NFS exports using ZFS sharenfs property (native, safer method) +func (s *NFSService) applyZFSShareNFS(exports []models.NFSExport) error { + // Find zfs command path + zfsPath := "zfs" + if path, err := exec.LookPath("zfs"); err == nil { + zfsPath = path + } + + for _, export := range exports { + if !export.Enabled { + // Disable sharenfs for disabled exports + cmd := exec.Command("sudo", "-n", zfsPath, "set", "sharenfs=off", export.Dataset) + if err := cmd.Run(); err != nil { + // Log but continue - might not have permission or dataset doesn't exist + continue + } + continue + } + + // Build sharenfs value + // Format for sharenfs: + // - "on" = share to all with default options + // - "rw" = share to all with rw + // - "rw=client1,ro=client2,options" = client-specific with options + var sharenfsValue strings.Builder + + // Check if we have specific clients (not just *) + hasSpecificClients := false + for _, client := range export.Clients { + if client != "*" && client != "" { + hasSpecificClients = true + break + } + } + + if !hasSpecificClients { + // No specific clients, share to all (*) + // Format must be: "rw=*" or "ro=*" with options + // Note: "rw,root_squash" is NOT valid - must use "rw=*,root_squash" + if export.ReadOnly { + sharenfsValue.WriteString("ro=*") + } else { + sharenfsValue.WriteString("rw=*") + } + + // Add options after permission + if export.RootSquash { + sharenfsValue.WriteString(",root_squash") + } else { + sharenfsValue.WriteString(",no_root_squash") + } + } else { + // Has specific clients, use client-specific format + clientSpecs := []string{} + for _, client := range export.Clients { + if client == "*" || client == "" { + // Handle * as default + if export.ReadOnly { + clientSpecs = append(clientSpecs, "ro") + } else { + clientSpecs = append(clientSpecs, "rw") + } + } else { + perm := "rw" + if export.ReadOnly { + perm = "ro" + } + clientSpecs = append(clientSpecs, fmt.Sprintf("%s=%s", perm, client)) + } + } + + // Add options + if export.RootSquash { + clientSpecs = append(clientSpecs, "root_squash") + } else { + clientSpecs = append(clientSpecs, "no_root_squash") + } + + sharenfsValue.WriteString(strings.Join(clientSpecs, ",")) + } + + // Set sharenfs property using sudo (atlas user has permission via sudoers) + cmd := exec.Command("sudo", "-n", zfsPath, "set", fmt.Sprintf("sharenfs=%s", sharenfsValue.String()), export.Dataset) + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + // If setting sharenfs fails, this method won't work - return error to trigger fallback + return fmt.Errorf("failed to set sharenfs on %s: %v (stderr: %s)", export.Dataset, err, stderr.String()) + } + } + + // After setting sharenfs properties, reload NFS exports + // ZFS sharenfs requires exportfs -ra to make exports visible + if err := s.reloadExports(); err != nil { + // Log error but don't fail - sharenfs is set, just needs manual reload + // Return error so caller knows reload failed, but sharenfs is already set + // This is acceptable - exports will work after manual reload + return fmt.Errorf("sharenfs set but reload failed (exports may need manual reload): %w", err) + } + + return nil +} diff --git a/internal/zfs/service.go b/internal/zfs/service.go index 82cc225..c3d262e 100644 --- a/internal/zfs/service.go +++ b/internal/zfs/service.go @@ -4,6 +4,8 @@ import ( "bytes" "encoding/json" "fmt" + "log" + "os" "os/exec" "strconv" "strings" @@ -49,6 +51,74 @@ func findCommandPath(cmd string) string { return cmd } +// translateZFSError converts technical ZFS error messages to user-friendly ones +func translateZFSError(err error, operation, name string) error { + if err == nil { + return nil + } + + errStr := err.Error() + + // Extract the actual ZFS error message (usually after the last colon or in quotes) + // Common patterns: + // - "cannot open 'name': no such pool" + // - "cannot open 'name': dataset does not exist" + // - "cannot destroy 'name': dataset is busy" + + // Check for common ZFS error patterns + if strings.Contains(errStr, "no such pool") { + return fmt.Errorf("pool '%s' tidak ditemukan. Pastikan nama pool benar dan pool sudah dibuat", name) + } + + if strings.Contains(errStr, "dataset already exists") { + return fmt.Errorf("dataset '%s' sudah ada. Gunakan nama yang berbeda atau hapus dataset yang sudah ada terlebih dahulu", name) + } + + if strings.Contains(errStr, "dataset does not exist") || strings.Contains(errStr, "no such dataset") { + return fmt.Errorf("dataset atau volume '%s' tidak ditemukan. Pastikan nama benar dan sudah dibuat", name) + } + + if strings.Contains(errStr, "dataset is busy") { + return fmt.Errorf("dataset atau volume '%s' sedang digunakan. Tutup semua koneksi atau unmount terlebih dahulu", name) + } + + if strings.Contains(errStr, "operation does not apply to pools") { + return fmt.Errorf("operasi ini tidak dapat diterapkan pada pool. Gunakan 'Delete Pool' untuk menghapus pool, atau 'Delete Dataset' untuk menghapus dataset di dalam pool") + } + + if strings.Contains(errStr, "cannot destroy") { + // Try to extract the reason + if strings.Contains(errStr, "has children") { + return fmt.Errorf("tidak dapat menghapus '%s' karena masih memiliki dataset atau snapshot di dalamnya. Hapus semua dataset/snapshot terlebih dahulu, atau gunakan opsi recursive", name) + } + if strings.Contains(errStr, "is busy") { + return fmt.Errorf("tidak dapat menghapus '%s' karena sedang digunakan. Tutup semua koneksi atau unmount terlebih dahulu", name) + } + return fmt.Errorf("tidak dapat menghapus '%s'. Pastikan tidak sedang digunakan dan tidak memiliki dataset/snapshot di dalamnya", name) + } + + if strings.Contains(errStr, "cannot open") { + return fmt.Errorf("tidak dapat mengakses '%s'. Pastikan nama benar dan resource sudah ada", name) + } + + // If no pattern matches, return a cleaner version of the error + // Remove technical details like "sudo failed", "direct execution also failed", etc. + if strings.Contains(errStr, "sudo failed") || strings.Contains(errStr, "direct execution") { + // Extract just the ZFS error part + parts := strings.Split(errStr, ":") + if len(parts) > 1 { + // Get the last meaningful part (usually the actual ZFS error) + lastPart := strings.TrimSpace(parts[len(parts)-1]) + if lastPart != "" { + return fmt.Errorf("gagal %s '%s': %s", operation, name, lastPart) + } + } + } + + // Fallback: return a user-friendly message with the operation + return fmt.Errorf("gagal %s '%s': %s", operation, name, errStr) +} + // execCommand executes a shell command and returns output // For ZFS operations that require elevated privileges, it uses sudo func (s *Service) execCommand(name string, args ...string) (string, error) { @@ -79,6 +149,9 @@ func (s *Service) execCommand(name string, args ...string) (string, error) { err := cmd.Run() if err != nil && useSudo { + // Log that sudo failed + log.Printf("sudo command failed, trying direct execution: %s %v (error: %v, stderr: %s)", name, args, err, stderr.String()) + // If sudo failed, try running the command directly // (user might already have permissions or be root) directCmd := exec.Command(name, args...) @@ -86,16 +159,22 @@ func (s *Service) execCommand(name string, args ...string) (string, error) { directCmd.Stdout = &directStdout directCmd.Stderr = &directStderr - if directErr := directCmd.Run(); directErr == nil { + directErr := directCmd.Run() + if directErr == nil { // Direct execution succeeded, return that result + log.Printf("direct command execution succeeded (without sudo)") return strings.TrimSpace(directStdout.String()), nil } - // Both sudo and direct failed, return the original sudo error - return "", fmt.Errorf("%s: %v: %s", name, err, stderr.String()) + // Both sudo and direct failed, return the direct error (usually cleaner) + log.Printf("both sudo and direct execution failed - sudo error: %v, direct error: %v", err, directErr) + log.Printf("sudo stderr: %s, direct stderr: %s", stderr.String(), directStderr.String()) + // Return the direct error (usually has the actual ZFS error message) + return "", fmt.Errorf("%s: %s", name, strings.TrimSpace(directStderr.String())) } if err != nil { - return "", fmt.Errorf("%s: %v: %s", name, err, stderr.String()) + log.Printf("command execution failed: %s %v (error: %v, stderr: %s)", name, args, err, stderr.String()) + return "", fmt.Errorf("%s: %s", name, strings.TrimSpace(stderr.String())) } return strings.TrimSpace(stdout.String()), nil @@ -180,16 +259,241 @@ func (s *Service) GetPool(name string) (*models.Pool, error) { func (s *Service) CreatePool(name string, vdevs []string, options map[string]string) error { args := []string{"create"} - // Add options + if options == nil { + options = make(map[string]string) + } + + // Add -f flag to force creation even if devices have existing filesystems + // This handles cases where devices are "in use" or contain "unknown filesystem" + args = append(args, "-f") + + // If mountpoint is not explicitly set, use dedicated storage directory + mountpoint := options["mountpoint"] + if mountpoint == "" { + // Default mountpoint: /storage/pools/{poolname} + mountpoint = "/storage/pools/" + name + options["mountpoint"] = mountpoint + } + + // Pre-create the mountpoint directory with sudo (non-blocking - log errors but continue) + if mountpoint != "none" { + if err := s.createMountpointWithSudo(mountpoint); err != nil { + // Log the error but don't fail - ZFS might still create the pool + // The mountpoint can be fixed later if needed + log.Printf("warning: failed to pre-create mountpoint %s: %v (continuing anyway)", mountpoint, err) + } + } + + // handle canmount as DATASET property not the vdev property + canmount := "noauto" + if v, ok := options["canmount"]; ok && v != "" { + canmount = v + } + + delete(options, "canmount") + + // Set canmount=noauto to prevent automatic mounting during creation + // This allows pool creation to succeed even if mountpoint can't be created + // if _, hasCanmount := options["canmount"]; !hasCanmount { + // options["canmount"] = "noauto" + // } + + // IMPORTANT: Don't set mountpoint during pool creation + // ZFS tries to mount immediately during creation, which can fail + // We'll set mountpoint after pool is created + mountpointOption := options["mountpoint"] + delete(options, "mountpoint") // Remove from options temporarily + + // Add remaining options for k, v := range options { args = append(args, "-o", fmt.Sprintf("%s=%s", k, v)) } - args = append(args, name) - args = append(args, vdevs...) + args = append(args, "-O", fmt.Sprintf("canmount=%s", canmount)) - _, err := s.execCommand(s.zpoolPath, args...) - return err + args = append(args, name) + + // Normalize vdev paths - ensure they start with /dev/ if they don't already + normalizedVdevs := make([]string, 0, len(vdevs)) + for _, vdev := range vdevs { + vdev = strings.TrimSpace(vdev) + if vdev == "" { + continue + } + // If vdev doesn't start with /dev/ or /, assume it's a device name and add /dev/ + if !strings.HasPrefix(vdev, "/dev/") && !strings.HasPrefix(vdev, "/") { + vdev = "/dev/" + vdev + } + normalizedVdevs = append(normalizedVdevs, vdev) + } + + if len(normalizedVdevs) == 0 { + return fmt.Errorf("no valid vdevs provided after normalization") + } + + args = append(args, normalizedVdevs...) + + // Log the command we're about to run for debugging + // Note: execCommand will use sudo automatically for zpool commands + log.Printf("executing zpool create: %s %v", s.zpoolPath, args) + log.Printf("pool name: %s, original vdevs: %v, normalized vdevs: %v", name, vdevs, normalizedVdevs) + + // Create the pool (without mountpoint to avoid mount errors) + createOutput, err := s.execCommand(s.zpoolPath, args...) + + // Log the command output for debugging + if err != nil { + log.Printf("zpool create command failed - output: %s, error: %v", createOutput, err) + log.Printf("this error might be a false positive - checking if pool was actually created...") + } else { + log.Printf("zpool create command succeeded - output: %s", createOutput) + } + + // CRITICAL: Always check if pool exists, even if creation reported an error + // ZFS often reports mountpoint errors but pool is still created successfully + // Retry checking pool existence up to 3 times with delays + poolExists := false + for i := 0; i < 3; i++ { + if i > 0 { + // Wait before retry (100ms, 200ms, 300ms) + time.Sleep(time.Duration(i*100) * time.Millisecond) + } + + if existingPools, listErr := s.ListPools(); listErr == nil { + log.Printf("checking pool existence (attempt %d/%d): found %d pools", i+1, 3, len(existingPools)) + for _, pool := range existingPools { + if pool.Name == name { + poolExists = true + log.Printf("pool %s found after %d check(s)", name, i+1) + break + } + } + } else { + log.Printf("warning: failed to list pools during existence check (attempt %d): %v", i+1, listErr) + } + + if poolExists { + break + } + } + + if poolExists { + // Pool exists! This is success, regardless of any reported errors + if err != nil { + log.Printf("info: pool %s created successfully despite reported error: %v", name, err) + } else { + log.Printf("info: pool %s created successfully", name) + } + // Clear error since pool was created + err = nil + } else if err != nil { + // Pool doesn't exist and we have an error - return it with full context + log.Printf("error: pool %s creation failed and pool does not exist", name) + log.Printf("error details: %v", err) + log.Printf("command that failed: %s %v", s.zpoolPath, args) + log.Printf("command output: %s", createOutput) + return fmt.Errorf("failed to create pool %s: %v (command: %s %v)", name, err, s.zpoolPath, args) + } else { + // No error reported but pool doesn't exist - this shouldn't happen + log.Printf("warning: pool %s creation reported no error but pool does not exist", name) + log.Printf("command output: %s", createOutput) + return fmt.Errorf("pool %s creation reported success but pool was not found (command: %s %v)", name, s.zpoolPath, args) + } + + // Pool created successfully - now set mountpoint and mount if needed + if mountpoint != "none" && mountpointOption != "" && poolExists { + // Ensure mountpoint directory exists + if err := s.createMountpointWithSudo(mountpoint); err != nil { + log.Printf("warning: failed to create mountpoint %s: %v", mountpoint, err) + } + + // Set mountpoint property on the root filesystem of the pool + setMountpointArgs := []string{"set", fmt.Sprintf("mountpoint=%s", mountpoint), name} + if _, setErr := s.execCommand(s.zfsPath, setMountpointArgs...); setErr != nil { + log.Printf("warning: failed to set mountpoint property: %v (pool created but not mounted)", setErr) + // Don't return error - pool is created successfully + } else { + // Try to mount the pool + mountArgs := []string{"mount", name} + if _, mountErr := s.execCommand(s.zfsPath, mountArgs...); mountErr != nil { + log.Printf("warning: failed to mount pool: %v (pool created but not mounted)", mountErr) + // Don't return error - pool is created successfully, just not mounted + } + } + } + + return nil +} + +// createMountpointWithSudo creates a mountpoint directory using sudo +// This allows ZFS to mount pools even if root filesystem appears read-only +func (s *Service) createMountpointWithSudo(path string) error { + // Check if directory already exists + if _, err := os.Stat(path); err == nil { + // Directory already exists + return nil + } + + // Create parent directories first + parentDir := "" + parts := strings.Split(path, "/") + if len(parts) > 1 { + // Build parent directory path (skip empty first part from leading /) + parentParts := []string{} + for i, part := range parts { + if i == 0 && part == "" { + continue // Skip leading empty part + } + if i < len(parts)-1 { + parentParts = append(parentParts, part) + } + } + if len(parentParts) > 0 { + parentDir = "/" + strings.Join(parentParts, "/") + if parentDir != "/" { + // Recursively create parent directories + if err := s.createMountpointWithSudo(parentDir); err != nil { + log.Printf("warning: failed to create parent directory %s: %v", parentDir, err) + } + } + } + } + + // Use sudo to create the directory with proper permissions + // Try multiple methods to ensure directory is created + methods := []struct { + name string + cmd *exec.Cmd + }{ + {"sudo mkdir", exec.Command("sudo", "-n", "mkdir", "-p", path)}, + {"direct mkdir", exec.Command("mkdir", "-p", path)}, + } + + var lastErr error + for _, method := range methods { + var stderr bytes.Buffer + method.cmd.Stderr = &stderr + + if err := method.cmd.Run(); err == nil { + // Success - verify directory was created and set permissions + if _, err := os.Stat(path); err == nil { + // Set proper permissions (755) and ownership if needed + chmodCmd := exec.Command("sudo", "-n", "chmod", "755", path) + _ = chmodCmd.Run() // Ignore errors, permissions might already be correct + return nil + } + } else { + lastErr = fmt.Errorf("%s failed: %v: %s", method.name, err, stderr.String()) + log.Printf("warning: %s failed: %v", method.name, lastErr) + } + } + + // All methods failed, but check if directory exists anyway (might have been created by ZFS or another process) + if _, err := os.Stat(path); err == nil { + return nil + } + + return fmt.Errorf("all methods failed to create mountpoint %s: %v", path, lastErr) } // DestroyPool destroys a ZFS pool @@ -440,24 +744,253 @@ func (s *Service) ListDatasets(pool string) ([]models.Dataset, error) { func (s *Service) CreateDataset(name string, options map[string]string) error { args := []string{"create"} + if options == nil { + options = make(map[string]string) + } + + // If mountpoint is not explicitly set, use dedicated storage directory + mountpoint := options["mountpoint"] + if mountpoint == "" { + // Extract dataset name (last part after /) + parts := strings.Split(name, "/") + datasetName := parts[len(parts)-1] + // Default mountpoint: /storage/datasets/{datasetname} + mountpoint = "/storage/datasets/" + datasetName + options["mountpoint"] = mountpoint + // Pre-create the mountpoint directory with sudo + _ = s.createMountpointWithSudo(mountpoint) + } else if mountpoint != "none" { + // Ensure mountpoint directory exists with sudo + _ = s.createMountpointWithSudo(mountpoint) + } + + // Handle canmount property - set to "on" by default to allow mounting + canmount := "on" + if v, ok := options["canmount"]; ok && v != "" { + canmount = v + } + delete(options, "canmount") + + // Add options for k, v := range options { args = append(args, "-o", fmt.Sprintf("%s=%s", k, v)) } + // Add canmount property + args = append(args, "-o", fmt.Sprintf("canmount=%s", canmount)) + args = append(args, name) _, err := s.execCommand(s.zfsPath, args...) - return err + + // CRITICAL: Always check if dataset exists, even if creation reported an error + // ZFS often reports mountpoint errors but dataset is still created successfully + // Retry checking dataset existence up to 3 times with delays + datasetExists := false + for i := 0; i < 3; i++ { + if i > 0 { + // Wait before retry (100ms, 200ms, 300ms) + time.Sleep(time.Duration(i*100) * time.Millisecond) + } + + if existingDatasets, listErr := s.ListDatasets(""); listErr == nil { + log.Printf("checking dataset existence (attempt %d/%d): found %d datasets", i+1, 3, len(existingDatasets)) + for _, ds := range existingDatasets { + if ds.Name == name { + datasetExists = true + log.Printf("dataset %s found after %d check(s)", name, i+1) + break + } + } + } else { + log.Printf("warning: failed to list datasets during existence check (attempt %d): %v", i+1, listErr) + } + + if datasetExists { + break + } + } + + if datasetExists { + // Dataset exists! This is success, regardless of any reported errors + if err != nil { + log.Printf("info: dataset %s created successfully despite reported error: %v", name, err) + } else { + log.Printf("info: dataset %s created successfully", name) + } + + // Dataset created successfully - now set mountpoint and mount if needed + if mountpoint != "" && mountpoint != "none" { + // CRITICAL: Create parent directory first if it doesn't exist + // This is needed because ZFS can't create directories in read-only filesystems + parentDir := "" + parts := strings.Split(mountpoint, "/") + if len(parts) > 1 { + // Build parent directory path + parentDir = strings.Join(parts[:len(parts)-1], "/") + if parentDir == "" { + parentDir = "/" + } + log.Printf("ensuring parent directory exists: %s", parentDir) + _ = s.createMountpointWithSudo(parentDir) + } + + // CRITICAL: Create mountpoint directory BEFORE setting mountpoint property + // ZFS will try to create it during mount, but may fail on read-only filesystem + // So we create it explicitly with sudo first + log.Printf("creating mountpoint directory: %s", mountpoint) + if err := s.createMountpointWithSudo(mountpoint); err != nil { + log.Printf("warning: failed to create mountpoint %s: %v (will try to continue)", mountpoint, err) + } else { + log.Printf("mountpoint directory created successfully: %s", mountpoint) + } + + // Set mountpoint property on the dataset + log.Printf("setting mountpoint property: %s = %s", name, mountpoint) + setMountpointArgs := []string{"set", fmt.Sprintf("mountpoint=%s", mountpoint), name} + if _, setErr := s.execCommand(s.zfsPath, setMountpointArgs...); setErr != nil { + log.Printf("warning: failed to set mountpoint property: %v (dataset created but mountpoint not set)", setErr) + } else { + log.Printf("mountpoint property set successfully") + + // Wait a moment for mountpoint to be registered + time.Sleep(200 * time.Millisecond) + + // Ensure directory exists again (ZFS might have cleared it or parent might be read-only) + // Try creating parent and child directories + if parentDir != "" && parentDir != "/" { + _ = s.createMountpointWithSudo(parentDir) + } + _ = s.createMountpointWithSudo(mountpoint) + + // Try to mount the dataset - ZFS will create the directory if it doesn't exist + // But we need to ensure parent is writable + log.Printf("attempting to mount dataset: %s", name) + mountArgs := []string{"mount", name} + if _, mountErr := s.execCommand(s.zfsPath, mountArgs...); mountErr != nil { + log.Printf("warning: failed to mount dataset: %v (dataset created but not mounted)", mountErr) + + // If mount failed due to read-only filesystem, try using legacy mount + if strings.Contains(mountErr.Error(), "Read-only file system") || strings.Contains(mountErr.Error(), "read-only") { + log.Printf("detected read-only filesystem issue, trying alternative approach") + // Try to remount parent as rw if possible, or use a different mountpoint + // For now, just log the issue - user may need to manually mount + log.Printf("error: cannot mount dataset due to read-only filesystem at %s. You may need to manually mount it or fix filesystem permissions", mountpoint) + } else { + // Try one more time after a short delay for other errors + time.Sleep(300 * time.Millisecond) + if _, mountErr2 := s.execCommand(s.zfsPath, mountArgs...); mountErr2 != nil { + log.Printf("warning: second mount attempt also failed: %v", mountErr2) + } else { + log.Printf("info: dataset %s mounted successfully at %s (on second attempt)", name, mountpoint) + } + } + } else { + log.Printf("info: dataset %s mounted successfully at %s", name, mountpoint) + } + } + } + + // Clear error since dataset was created + return nil + } else if err != nil { + // Dataset doesn't exist and we have an error - return translated error + log.Printf("error: dataset %s creation failed and dataset does not exist", name) + return translateZFSError(err, "membuat dataset", name) + } else { + // No error reported but dataset doesn't exist - this shouldn't happen + log.Printf("warning: dataset %s creation reported no error but dataset does not exist", name) + return translateZFSError(fmt.Errorf("dataset creation reported success but dataset was not found"), "membuat dataset", name) + } } // DestroyDataset destroys a ZFS dataset func (s *Service) DestroyDataset(name string, recursive bool) error { + // Always try to unmount first, regardless of mounted status + // This prevents "dataset is busy" errors + log.Printf("attempting to unmount dataset %s before destroy", name) + unmountArgs := []string{"umount", name} + unmountOutput, unmountErr := s.execCommand(s.zfsPath, unmountArgs...) + if unmountErr != nil { + log.Printf("regular unmount failed for %s: %v (output: %s), trying force unmount", name, unmountErr, unmountOutput) + // Try force unmount if regular unmount fails + forceUnmountArgs := []string{"umount", "-f", name} + forceOutput, forceErr := s.execCommand(s.zfsPath, forceUnmountArgs...) + if forceErr != nil { + log.Printf("warning: force unmount also failed for %s: %v (output: %s)", name, forceErr, forceOutput) + } else { + log.Printf("dataset %s force unmounted successfully", name) + } + } else { + log.Printf("dataset %s unmounted successfully", name) + } + // Wait a moment for unmount to complete + time.Sleep(300 * time.Millisecond) + + // Now destroy the dataset args := []string{"destroy"} if recursive { args = append(args, "-r") } args = append(args, name) - _, err := s.execCommand(s.zfsPath, args...) - return err + destroyOutput, err := s.execCommand(s.zfsPath, args...) + if err != nil { + log.Printf("first destroy attempt failed for %s: %v (output: %s)", name, err, destroyOutput) + // If destroy fails with "dataset is busy", try unmounting again and retry + if strings.Contains(err.Error(), "dataset is busy") || strings.Contains(err.Error(), "is busy") { + log.Printf("dataset %s still busy, trying force unmount again and retry destroy", name) + // Try force unmount again + forceUnmountArgs := []string{"umount", "-f", name} + _, _ = s.execCommand(s.zfsPath, forceUnmountArgs...) + time.Sleep(500 * time.Millisecond) + // Retry destroy + destroyOutput2, err2 := s.execCommand(s.zfsPath, args...) + if err2 != nil { + log.Printf("second destroy attempt also failed for %s: %v (output: %s)", name, err2, destroyOutput2) + return translateZFSError(err2, "menghapus dataset", name) + } else { + log.Printf("dataset %s destroyed successfully on second attempt", name) + return nil + } + } + return translateZFSError(err, "menghapus dataset", name) + } + log.Printf("dataset %s destroyed successfully", name) + return nil +} + +// UpdateDataset updates ZFS dataset properties +func (s *Service) UpdateDataset(name string, quota string, compression string, options map[string]string) error { + // Update quota if provided + if quota != "" { + quotaValue := quota + if quota == "none" || quota == "0" { + quotaValue = "none" + } + args := []string{"set", fmt.Sprintf("quota=%s", quotaValue), name} + if _, err := s.execCommand(s.zfsPath, args...); err != nil { + return translateZFSError(err, "mengupdate quota dataset", name) + } + } + + // Update compression if provided + if compression != "" { + args := []string{"set", fmt.Sprintf("compression=%s", compression), name} + if _, err := s.execCommand(s.zfsPath, args...); err != nil { + return translateZFSError(err, "mengupdate compression dataset", name) + } + } + + // Update other options if provided + if options != nil { + for key, value := range options { + args := []string{"set", fmt.Sprintf("%s=%s", key, value), name} + if _, err := s.execCommand(s.zfsPath, args...); err != nil { + return translateZFSError(err, fmt.Sprintf("mengupdate property %s dataset", key), name) + } + } + } + + return nil } // ListZVOLs returns all ZVOLs @@ -531,7 +1064,55 @@ func (s *Service) CreateZVOL(name string, size uint64, options map[string]string // DestroyZVOL destroys a ZVOL func (s *Service) DestroyZVOL(name string) error { _, err := s.execCommand(s.zfsPath, "destroy", name) - return err + if err != nil { + return translateZFSError(err, "menghapus volume", name) + } + return nil +} + +// getUsedDisks returns a set of disk names that are currently used in ZFS pools +func (s *Service) getUsedDisks() map[string]bool { + usedDisks := make(map[string]bool) + + // Get all pools + pools, err := s.ListPools() + if err != nil { + log.Printf("warning: failed to list pools to check disk usage: %v", err) + return usedDisks + } + + // For each pool, get the status to see which disks are used + for _, pool := range pools { + // Get pool status which shows vdevs (disks) + statusOutput, err := s.execCommand(s.zpoolPath, "status", pool.Name) + if err != nil { + log.Printf("warning: failed to get status for pool %s: %v", pool.Name, err) + continue + } + + // Parse status output to find disk names + // Format: lines like " sdb ONLINE 0 0 0" + lines := strings.Split(statusOutput, "\n") + for _, line := range lines { + line = strings.TrimSpace(line) + // Skip empty lines and headers + if line == "" || strings.HasPrefix(line, "NAME") || strings.HasPrefix(line, "state:") || strings.HasPrefix(line, "pool:") { + continue + } + + // Extract disk name (first field after indentation) + fields := strings.Fields(line) + if len(fields) > 0 { + diskName := fields[0] + // Check if it's a disk device (starts with sd, hd, nvme, etc.) + if strings.HasPrefix(diskName, "sd") || strings.HasPrefix(diskName, "hd") || strings.HasPrefix(diskName, "nvme") { + usedDisks[diskName] = true + } + } + } + } + + return usedDisks } // ListDisks returns available disks (read-only) @@ -557,14 +1138,36 @@ func (s *Service) ListDisks() ([]map[string]string, error) { return nil, err } + // Get list of disks currently used in pools + usedDisks := s.getUsedDisks() + var disks []map[string]string for _, dev := range result.BlockDevices { - if dev.Type == "disk" && dev.FSType == "" && dev.Mountpoint == "" { - disks = append(disks, map[string]string{ - "name": dev.Name, - "size": dev.Size, - "path": "/dev/" + dev.Name, - }) + // Skip OS disk (sda) - typically the first disk used for OS installation + if dev.Name == "sda" { + continue + } + + // Check if disk is used in a pool + isUsed := usedDisks[dev.Name] + + // Include all disks (both available and used) so we can show status + if dev.Type == "disk" { + disk := map[string]string{ + "name": dev.Name, + "size": dev.Size, + "path": "/dev/" + dev.Name, + "status": "available", + } + + if isUsed { + disk["status"] = "unavailable" + } else if dev.FSType != "" || dev.Mountpoint != "" { + // Disk has filesystem or mountpoint (not suitable for ZFS pool) + disk["status"] = "unavailable" + } + + disks = append(disks, disk) } } diff --git a/test/integration_test.go b/test/integration_test.go index a160789..ae422aa 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -28,7 +28,7 @@ func NewTestServer(t *testing.T) *TestServer { Addr: ":0", // Use random port TemplatesDir: templatesDir, StaticDir: staticDir, - DatabasePath: "", // Empty = in-memory mode (no database) + DatabaseConn: "", // Empty = in-memory mode (no database) }) if err != nil { t.Fatalf("create test app: %v", err) diff --git a/web/templates/base.html b/web/templates/base.html index 637e77d..4ef98bb 100644 --- a/web/templates/base.html +++ b/web/templates/base.html @@ -13,30 +13,102 @@
-