FreezeOS Overview
FreezeOS is a secure, immutable, fleet-managed Linux operating system designed for managed endpoints. Every device is enrolled with a central fleet server, encrypted with server-issued keys, and monitored via automatic health checks.
Key Concepts
- Immutable Root — The base system is a read-only squashfs image. Changes are written to a persistent overlay. The core OS cannot be tampered with at runtime.
- Two-Factor Encryption — System partitions are unlocked by server-issued tokens (automatic at boot). User data is unlocked by a PIN entered at login.
- Fleet Management — All devices check in with the fleet server periodically. The server issues fresh tokens, collects health data, and pushes OTA updates.
- A/B System Slots — Two system partitions enable zero-downtime updates with automatic rollback on failure.
- Policy Enforcement — Organizations can define policies (security, network, power, restrictions) that are pushed to devices and enforced automatically.
- Two OS Flavors — A Debian-based image and a built-from-source FreezeOS Linux image. Both can coexist on one machine and share the user's encrypted data. See OS Flavors.
- Per-Model Performance Kernels — The fleet automatically builds kernels tuned to each device model and CPU micro-architecture. See Per-Model Kernels.
- Secure Boot — Install media ships with the signed shim boot chain; custom kernels are MOK-signed. See Secure Boot.
- Self-Healing — A background autofix system detects and repairs common problems from a fleet-managed fix catalog. See Self-Heal.
System Requirements
| Component | Minimum | Recommended |
|---|---|---|
| CPU | x86_64, 2 cores | 4+ cores with AES-NI |
| RAM | 2 GB | 4+ GB |
| Storage | 40 GB | 64+ GB SSD |
| Network | Ethernet or WiFi | Ethernet |
| Boot | UEFI | UEFI with Secure Boot |
Quick Start
- Get install media from the download page — the Linux USB Creator (recommended), the Windows Installer, the Boot ISO, or the Commander phone app's Install to USB feature
- Boot the target machine from the USB stick
- The recovery environment detects a blank machine and starts Install Mode — a 6-step wizard (hardware check, storage, registration, WiFi, login confirm, install)
- The installer partitions, encrypts, and installs the OS automatically
- Reboot into your new FreezeOS installation — if Secure Boot is on, enroll the FreezeOS key once via MOK Manager when prompted
Installation
FreezeOS installs from a compact bootable recovery image (~250 MB) that serves as installer, on-disk recovery, and repair tool. When it boots on a machine with no existing FreezeOS installation, it automatically enters Install Mode — a guided 6-step wizard.
Creating Install Media
| Tool | Platform | Description |
|---|---|---|
| Linux USB Creator | Debian-based Linux | Standalone graphical wizard from the download page. Installs its own dependencies on first run. Sign in with your fleet account, pick your device model (selects the matching performance kernel), release channel, and optional WiFi networks, then write. Supports Installer mode and Portable mode (a fully personalized FreezeOS on a 32 GB+ stick that boots directly). |
| Windows Installer | Windows | Lays down the recovery bootstrap; recovery then drives the actual install on reboot. |
| Commander app | Android | Writes a bootable install USB directly from the phone over a USB-OTG adapter — no PC or root required. Includes channel selection, model picker, download caching, and read-back verification. |
| Boot ISO | Any | Raw install image for writing with any USB imaging tool. |
Writing install media erases the entire target USB device. Double-check the target before writing.
Model Variants & Offline Install
Install USBs can bundle the performance kernel matching a chosen device model, so the correct optimized kernel is installed even with no network connection. If the target hardware doesn't match the bundled kernel, the installer falls back to fetching the right one from the fleet server. The install scripts themselves are pre-placed in the recovery image, so a USB-boot install works fully offline.
Install Mode Wizard
- Hardware check — diagnostics run on every internal device; unsupported hardware is named on a Compatibility screen (install never blocks — you can install now with the standard kernel, or wait for a custom kernel build)
- Storage — pick the target disk (minimum 40 GB)
- Registration — sign in or enroll with the fleet server
- WiFi — optional network setup carried into the installed system
- Login confirm — confirm the account and fleet password
- Install — automatic partitioning, encryption, image download, bootloader setup
Installation Process
Under the hood the wizard runs three sequential scripts:
- partition.sh (0-10%) — Creates GPT partition table with 10 partitions, sets up LUKS encryption on each, creates filesystems
- install-os.sh (10-90%) — Downloads the fleet system image (squashfs) from the fleet server and writes it to the system partition
- bootloader.sh (90-100%) — Installs the signed GRUB EFI boot chain, builds the initramfs with the FreezeOS init script, installs the recovery image to disk, configures boot entries
Install media boots on Secure Boot machines out of the box. Custom performance kernels require a one-time MOK key enrollment on first boot — see Secure Boot.
First Boot
After installation, the device reboots into FreezeOS. The first boot performs several setup tasks.
Boot Sequence
- GRUB loads the kernel and initramfs
- The FreezeOS init script validates the system token
- System partition is LUKS-decrypted with the server key
- Squashfs integrity is verified via SHA-256
- OverlayFS mounts the immutable base + persistent overlay
switch_roothands off to systemd- The FreezeOS greeter presents the login screen
- User logs in with their fleet password — or inserts a FreezeOS USB security key and enters its PIN — to unlock personal data partitions
First Login
Enter the fleet password you chose during enrollment. It derives the encryption key for your personal data, app data, and swap partitions via PBKDF2. If your account has a USB security key, you can instead insert the key and enter its PIN — see USB Key Login.
If Secure Boot is enabled and a custom performance kernel was installed, the first reboot shows the blue MOK Manager screen — choose Enroll MOK and confirm with the enrollment password. This happens once per machine.
The system token refreshes automatically on each device checkin. Production fleets issue long-lived boot tokens, so routine offline periods never lock a device out of booting.
Partition Layout
FreezeOS uses a 10-partition GPT layout. Each partition has a specific role in the security and update architecture. Several partitions are dynamically sized based on the total disk capacity (minimum 40 GB required).
| # | Name | Size | Type | Encryption | Purpose |
|---|---|---|---|---|---|
| 1 | ESP | 512 MB | FAT32 | None | EFI System Partition, GRUB bootloader |
| 2 | /boot | 1 GB | ext4 | None | Kernels, initramfs, tokens, node config |
| 3 | System A | 8 GB | LUKS | Server key | Primary system slot (squashfs) |
| 4 | Apps | Dynamic | LUKS | Server key | Persistent overlay (upper) |
| 5 | User Storage | 60% of available | LUKS | PIN-derived | /home — personal data |
| 6 | Swap | RAM-sized | LUKS | PIN-derived | Encrypted swap space |
| 7 | BIOS Boot | 2 MB | Raw | None | Legacy GRUB (fallback) |
| 8 | System B | 8 GB | LUKS | Server key | Secondary system slot (A/B updates) |
| 9 | App Data | Dynamic | LUKS | PIN-derived | Application persistent data |
| 10 | Recovery | 2 GB | ext4 | None | Recovery environment and tools |
Dynamic Sizing Algorithm
After subtracting all fixed-size partitions (ESP, /boot, System A/B, BIOS Boot, Recovery, Swap = ~19.5 GB + swap), the remaining space is called available space. Dynamic partitions scale proportionally with no caps:
| Partition | Formula | Min |
|---|---|---|
| User Storage (Part 5) | 60% of available space | — |
| Apps (Part 4) | 25% of available space | 4 GB |
| App Data (Part 9) | 15% of available space | 4 GB |
| Swap (Part 6) | Matches system RAM | 1 GB (max 16 GB) |
Example Partition Sizes
Example sizes assuming 4 GB RAM (swap = 4 GB):
| Disk Size | Apps | App Data | Swap | User Storage |
|---|---|---|---|---|
| 64 GB | 8.9 GB | 5.3 GB | 4 GB | ~21 GB |
| 128 GB | 25.6 GB | 15.4 GB | 4 GB | ~61 GB |
| 256 GB | 56.4 GB | 33.8 GB | 4 GB | ~135 GB |
| 512 GB | 117.9 GB | 70.7 GB | 4 GB | ~283 GB |
FreezeOS requires a minimum disk size of 40 GB. The installer will refuse to proceed on smaller disks.
Key Domains
- Server-key partitions (3, 4, 8) — Unlocked automatically at boot using the key from the fleet server token. No user interaction required.
- PIN-derived partitions (5, 6, 9) — Unlocked at login. Key is derived via
PBKDF2-HMAC-SHA256(PIN, SHA256(cert) + salt, 600000, 64). - Unencrypted partitions (1, 2, 7, 10) — Required for boot and recovery. Contain no user data.
Boot Flow
The FreezeOS boot process is managed by a custom init script that runs in a minimal busybox initramfs environment.
Sequence
GRUB EFI → initramfs → Token Validate → LUKS Decrypt → SHA-256 Verify → Overlay Mount → switch_root → systemd → LightDM → PIN Unlock → Desktop
1. GRUB
Standalone EFI binary with all modules embedded. Loads kernel and initramfs from the /boot partition. Passes kernel parameters including log server URL.
2. Initramfs Init
The freezeos-init.sh script runs as PID 1 in a busybox environment. It handles:
- Parsing kernel command line for tokens, recovery flags, log server
- Loading crypto kernel modules (ECB → cryptd → crypto_simd → XTS → SHA512 → AES-NI)
- Token validation (HMAC-SHA256 signature check, expiry check)
- LUKS decryption of system and apps partitions
- Squashfs integrity verification
- OverlayFS mount (squashfs lower + apps upper)
- Config injection (user, network, PAM hooks)
- switch_root to the merged filesystem
3. Systemd
After switch_root, systemd takes over and boots normally. The freezeos-boot-success.service resets the boot attempt counter to prevent false rollbacks.
Immutable OS Model
FreezeOS uses an OverlayFS-based immutable OS design. The base system image is a read-only squashfs file that cannot be modified at runtime.
How It Works
┌──────────────────────────────────┐ │ Overlay Upper (Apps partition) │ ← Read-Write (persistent) ├──────────────────────────────────┤ │ OverlayFS Merge Point │ ← Unified root filesystem ├──────────────────────────────────┤ │ SquashFS Lower (System partition)│ ← Read-Only (immutable) └──────────────────────────────────┘
- User-installed packages and config changes write to the overlay upper on the Apps partition
- The base system squashfs is never modified
- OTA updates replace the squashfs image entirely
- Safe mode boots with a tmpfs overlay, bypassing all user modifications
- Factory reset wipes the overlay, restoring the pristine base image
A/B System Updates
FreezeOS maintains two system partitions (Slot A and Slot B) for zero-downtime updates with automatic rollback.
Update Process
- New squashfs image downloaded from fleet server
- SHA-256 integrity verified
- Written to the inactive slot
- A/B state file updated to flip active slot
- Device reboots into new system
freezeos-boot-success.serviceconfirms successful boot
Automatic Rollback
If the boot attempt counter exceeds 3, the init script automatically rolls back to the previous slot. This protects against bad updates that prevent the system from booting fully.
A/B State File
Located at /boot/freezeos/ab-state, this shell-sourceable file tracks:
ACTIVE_SLOT=A SLOT_A_VERSION=2.9.86 SLOT_A_HASH=24117be33... SLOT_B_VERSION=2.9.85 SLOT_B_HASH=abc123def... BOOT_ATTEMPTS=0
OS Flavors
FreezeOS ships in two flavors that share the same fleet, security model, and desktop:
- Debian-based — the standard image, built on Debian with the signed kernel and full package compatibility.
- FreezeOS Linux (from source) — a distribution compiled entirely from upstream source, optimized per x86-64 micro-architecture level. Boots the FreezeOS desktop in roughly six seconds, with PipeWire audio, Bluetooth, WiFi, Chrome, and the NVIDIA driver all working. The desktop shows a SOURCE badge.
Architecture-Level Optimization
Rather than one source image per device model, the fleet builds a small set of images optimized per x86-64 feature level (v2 / v3), plus the stock baseline. Each device reports its CPU capability level at checkin and receives the matching image. Combined with per-model kernels (which handle driver fit), this captures nearly all of a fully model-specific build's performance with far fewer images to maintain.
Dual-Flavor Machines
Both flavors can be installed on one machine — one per system slot — and the user chooses which boots by default:
- Each flavor keeps its own system overlay; user files and settings live on the shared encrypted data partition, so your home directory, theme, and app settings follow you between flavors.
- freezeos-default-os (also in Settings) views and sets the default boot OS.
- freezeos-desktop-mode switches between the FreezeOS desktop and a stock XFCE fallback.
On dual-flavor machines the updater detects when the inactive slot holds the other flavor and refuses to overwrite it — a routine update can never wipe your second OS.
Per-Model Kernels
FreezeOS ships one general-purpose kernel, and the fleet automatically builds performance kernels tailored to each device model — so modern GPUs, WiFi, audio, and Bluetooth work fully, and the kernel is compiled for the machine's actual CPU.
How a Device Gets Its Kernel
- At install time, hardware diagnostics check every internal device; anything not fully supported by the standard kernel is named on a Compatibility screen
- Installation never blocks — install immediately with the standard kernel, or wait and watch the custom kernel build live
- If you install first, a "Kernel update available" notification appears in Commander, on the desktop, in the portal inbox, and by email when your model's kernel is ready
- Applying it downloads and installs the tailored kernel
CPU Micro-Architecture Tuning
Devices report their CPU feature level (x86-64-v2 / v3 / v4, read directly from processor capabilities — no compiler needed on the device) during normal checkins. The fleet groups similar machines into cohorts and automatically queues optimized kernels for each, so already-deployed devices shift from generic to tuned builds with no reinstall.
Safety
- New kernels are trial-booted: three failed boots automatically fall back to the previous kernel; a successful boot promotes the new one. A kernel update cannot strand a device.
- Kernels are named by hardware fingerprint (with a DMI vendor/model fallback), so identical models share one build.
- A post-boot benchmark confirms the device as "supported" or flags remaining hardware issues in the portal catalog.
- Under Secure Boot, custom kernels are MOK-signed — see Secure Boot.
Encryption
Every data partition on a FreezeOS device is encrypted with LUKS (Linux Unified Key Setup) using AES-XTS with 512-bit keys.
Encryption Specifications
| Parameter | Value |
|---|---|
| Cipher | AES-XTS-plain64 |
| Key Size | 512 bits (256-bit AES + 256-bit XTS) |
| LUKS Key Size | 64 bytes |
| Certificate | RSA-4096 |
| Token Signing | HMAC-SHA256 |
| PIN Key Derivation | PBKDF2-HMAC-SHA256, 600,000 iterations |
Two Key Domains
Server-Controlled (System, Apps, System B)
The LUKS key is generated during enrollment and stored encrypted on the fleet server. At each checkin, the key is embedded in a signed token and delivered to the device. The init script extracts the key and unlocks these partitions automatically.
PIN-Derived (User Storage, App Data, Swap)
The LUKS key is derived from the user's PIN combined with the device certificate fingerprint:
key = PBKDF2-HMAC-SHA256(
password = PIN,
salt = SHA256(DER(device_cert)) + enrollment_salt,
iterations = 600000,
key_length = 64 bytes
)
Token System
FreezeOS uses signed tokens to securely deliver LUKS encryption keys from the fleet server to devices. Tokens carry both an HMAC-SHA256 signature and an RSA-SHA256 signature, which the initramfs verifies against the fleet CA public key before unlocking the system.
Token Format
Tokens are Base64-encoded JSON with HMAC-SHA256 + RSA-SHA256 signatures. Each token contains:
- node_id — The device identifier
- key — Base64-encoded LUKS key
- type — "system" or "apps"
- issued_at — Token issue timestamp
- expires_at — Token expiry timestamp
- signature — HMAC-SHA256 of the payload
Token Lifetimes
| Token | Lifetime | Storage |
|---|---|---|
| System Token | Configurable per fleet — production issues long-lived (10-year) boot tokens | /boot/freezeos/system_token.enc |
| Apps Token | 30 days | /boot/freezeos/apps_token.enc |
Long-lived boot tokens ensure a device that sits offline never falls into recovery because a token quietly expired. Fleets that prefer expiry-based protection can shorten the lifetime as a policy choice; revocation and signature verification are enforced regardless.
Expired tokens are still accepted for key extraction — only tampered (bad signature) tokens are rejected. This means a device can boot even if it hasn't checked in recently, as long as the token hasn't been tampered with.
Login Unlock
When a user logs in at the FreezeOS greeter, their fleet password is used to derive the encryption key for personal data partitions. Alternatively, a USB security key with a PIN can be used — in that case the fleet server supplies a server-managed data key after certificate verification.
How It Works
- User enters their fleet password at the login screen
- PAM hook (
freezeos-data-unlock) intercepts the credential - Key derived:
PBKDF2(fleet_password, SHA256(cert_DER) + salt, 600000, 64) - LUKS unlock attempted on User Storage, App Data, and Swap partitions
- On success, partitions are mounted and login proceeds
- On failure, login is denied
Salt
A 32-byte hex salt is generated during enrollment and stored at /boot/freezeos/data.salt. Combined with the certificate fingerprint, this ensures the derived key is unique per device.
Certificates
Each FreezeOS device has an RSA-4096 client certificate issued by the fleet CA during enrollment.
Certificate Usage
- mTLS Authentication — The client cert authenticates the device to the fleet server during checkins
- Key Derivation — The certificate fingerprint (SHA-256 of DER) is used as part of the PBKDF2 salt for data-partition unlock
- Identity — The cert's CN contains the node ID
- USB Key Login — User certificates on a USB security key authenticate desktop login (see USB Key Login)
Certificate Lifetime
FreezeOS issues non-expiring device and user certificates by default: a valid certificate stays good with no forced expiry date. CA signature checks, revocation status, and signed-challenge verification are always enforced — only the time-based expiry is relaxed. Fleets that want enforced expiry can opt in as a policy setting, and the freezeos-cert-renew service handles renewal automatically in that mode.
File Locations
/boot/freezeos/certs/client.crt # Device certificate /boot/freezeos/certs/client.key # Private key /boot/freezeos/certs/ca.crt # Fleet CA certificate
Secure Boot
FreezeOS supports UEFI Secure Boot end to end. Install media is built with the signed shim boot chain by default, so installers and portable USB sticks boot on Secure Boot machines without any firmware changes. The Debian-signed kernel is always preserved through updates, keeping the stock boot path signed.
Custom Kernel Signing (MOK)
Performance-tuned kernels and out-of-tree modules (such as the NVIDIA driver) are signed with a FreezeOS Machine Owner Key. The first boot on a Secure Boot machine requires a one-time key enrollment:
- On reboot, the blue MOK Manager screen appears
- Select Enroll MOK (or Enroll key from disk and choose the FreezeOS certificate on the USB)
- Confirm with the enrollment password and reboot
After enrollment, tuned kernels and signed modules load automatically on every update. The FreezeOS GRUB menu includes an "Enroll / Manage Secure Boot Key (MOK Manager)" entry so key management is always reachable.
Firmware Notes
- Some firmware (for example certain Dell machines) can instead import the FreezeOS certificate into the firmware key database in Custom Mode, using the provided DER-format certificate.
- Machines whose firmware lacks the Microsoft third-party UEFI CA (some mini-PCs) can be served Secure Boot-off media on request.
USB Key Login
FreezeOS supports passwordless desktop login with a USB security key — a USB stick provisioned with the user's certificate. Insert the key at the login screen, enter its PIN, and you're in.
How It Works
- The fleet server generates an RSA-4096 user certificate signed by the fleet CA; the private key is encrypted with the user's PIN
- The key material is written to a USB stick labeled
freezeOS-key(using the built-in Key Writer utility, which formats the stick and writes the certificates) - At login, the greeter detects the key, reads the username from the certificate, and prompts for the PIN
- The PIN decrypts the private key, which signs a server challenge (RSA-PKCS1v15-SHA256); the fleet server verifies the signature
- The server returns the login credential and a server-managed data key that unlocks the user's encrypted partitions
Management
Users enable, generate, and revoke their login keys from the portal's Security page. Administrators can manage per-device keys from each device's detail page. A revoked certificate stops working immediately — revocation is checked on every authentication.
Phone Two-Factor Authentication
Portal sign-in supports phone-based two-factor approval through the Commander app: after entering your password, you approve the login on your paired phone. The password remains the first factor, and device login always offers "Use password instead" — the desktop never hard-requires the phone.
Pairing
Pair your phone from Commander's security settings. Once paired, portal logins show a "waiting for phone" page until you approve or deny the attempt in the app.
Lost Phone Recovery
If you lose your phone (or clear the Commander app and its 2FA key), recover by pairing from any of your enrolled FreezeOS machines:
- Open the built-in FreezeOS Devices app on the machine
- Generate a pairing code — protected by your fleet password and the machine's own certificate, so it works even when the portal or 2FA is unavailable
- Redeem the code in Commander on the new phone and re-enroll an authenticator key
- Clear old authenticator entries on the portal's Security page
The "waiting for phone" sign-in page includes collapsible recovery instructions covering this flow.
Admin Security Hardening
The FreezeOS admin portal and fleet API implement defense-in-depth security controls aligned with NIST 800-53 and DISA STIG requirements.
Credential Management
All database credentials and cryptographic keys are loaded from environment variables. No passwords are stored in source code.
- Environment file —
/etc/freezeos/fleet.env(mode 0640, owner:group tech:www-data) - PHP auto-loader — Config files auto-parse the env file via
putenv() - Flask systemd —
EnvironmentFile=/etc/freezeos/fleet.envin service unit - Python routes — Centralized
fleet/mysql_conn.pyreadsFLEET_MYSQL_*env vars
Security Headers
All HTTP responses include the following security headers:
X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1; mode=block Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: camera=(), microphone=(), geolocation=(), usb=() Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none' Strict-Transport-Security: max-age=31536000; includeSubDomains Cache-Control: no-store, no-cache, must-revalidate, private
Session cookies use Secure, HttpOnly, and SameSite=Strict flags.
Production Safeguards
- Fail-fast on dev keys — Flask refuses to start in production mode (
FLEET_DEBUG=0) if HMAC or master encryption keys are left at development defaults - 256-bit random keys — Token HMAC signing and LUKS key encryption use cryptographically random 256-bit keys
- No shell_exec — LDAP connection tests use native PHP LDAP functions instead of shell commands
- CSRF protection — All state-changing operations require a 256-bit CSRF token
- Rate limiting — Login: 5 attempts / 15-minute lockout. Auth API: 5 failures / 5-minute window
NIST 800-53 Control Mapping
| Control | Title | Implementation |
|---|---|---|
| AC-2 | Account Management | Admin user lifecycle, role assignment, deactivation |
| AC-3 | Access Enforcement | RBAC permission checks on every page and API endpoint |
| AC-6 | Least Privilege | 5 roles: viewer, operator, auditor, admin, super_admin |
| AU-2 | Audit Events | Login, logout, CRUD, role changes, MFA events, all admin actions |
| AU-3 | Content of Audit Records | Who, what, when, where (IP), detail, user agent |
| IA-2 | Identification and Authentication | Bcrypt password hashing + TOTP multi-factor authentication |
| IA-5 | Authenticator Management | Password complexity (8+ chars, upper, digit, special), MFA recovery codes |
| SC-8 | Transmission Confidentiality | HTTPS enforced via HSTS, secure session cookies |
| SC-12 | Cryptographic Key Establishment | AES-256-GCM for LUKS keys, HMAC-SHA256 for tokens, RSA-4096 for certificates |
| SC-28 | Protection of Information at Rest | MySQL TDE (InnoDB tablespace encryption), encrypted redo/undo/binlogs |
Role-Based Access Control
The admin portal implements granular RBAC with 5 roles, enforced on every page and API endpoint.
Roles
| Role | Level | Access |
|---|---|---|
| Viewer | 1 | Read-only: dashboard, devices, hardware catalog, wiki |
| Auditor | 2 | Read-only on everything + audit log access |
| Operator | 3 | Manage devices, groups, OUs, printers, issues, wiki |
| Admin | 4 | Everything except role management and security settings |
| Super Admin | 5 | Full access including role assignment, MFA enforcement, security settings |
Permission Matrix
Each action is mapped to a permission key (e.g., devices.manage) which lists allowed roles. Example permissions:
dashboard.view— All rolesdevices.manage— Operator, Admin, Super Adminpolicies.manage— Admin, Super Adminusers.roles— Super Admin onlyaudit.view— Auditor, Super Adminsecurity.manage— Super Admin only
Enforcement
Pages call require_permission('permission.name') after authentication. API endpoints call require_permission('permission.name', true) which returns HTTP 403 JSON instead of an HTML page. The sidebar navigation dynamically shows/hides links based on the current user's role.
Multi-Factor Authentication
FreezeOS supports TOTP-based MFA (RFC 6238) for admin portal access, meeting NIST 800-63B AAL2 requirements.
How It Works
- Admin navigates to MFA Settings in the sidebar
- Clicks Set Up Two-Factor Authentication
- Scans QR code with any authenticator app (Google Authenticator, Authy, 1Password, etc.)
- Enters the 6-digit code to verify setup
- Receives 8 one-time recovery codes (must be saved securely)
Login Flow with MFA
- Enter email + password (standard login)
- If MFA enabled: redirected to verification page
- Enter 6-digit TOTP code or a one-time recovery code
- Session established with
mfa_verified=trueflag
Technical Details
- Algorithm: HMAC-SHA1 with 30-second time step (RFC 6238 compliant)
- Secret: 20-byte random, stored encrypted in database
- Window: ±1 period tolerance for clock skew
- Recovery codes: 8 codes, 8-character hex, single-use
- MFA timeout: Verification must complete within 5 minutes of password entry
- Audit trail: All MFA events logged (setup, disable, recovery code use, failed attempts)
Audit Logging
Every admin action is recorded in an immutable audit log, meeting NIST 800-53 AU-2/AU-3/AU-12 controls.
What is Logged
| Category | Events |
|---|---|
| Authentication | login, logout, login_failed, login_rate_limited, login_sso |
| MFA | mfa_setup, mfa_disable, mfa_failed, mfa_recovery_used, mfa_recovery_regen |
| Devices | revoke, suspend, restore, move (OU), group add/remove, policy toggle |
| Policies | create, update, delete, assign, unassign, toggle |
| Organizations | member add/remove/promote/demote, policy toggle |
| Printers | create, update, delete, deploy, undeploy |
| Identity | provider change, LDAP test, Entra test |
| Users | account create, role change |
Audit Record Fields
id BIGINT Auto-increment (immutable) user_id INT Admin who performed the action username VARCHAR Username at time of action action VARCHAR Action verb (login, create, update, delete, revoke, etc.) target_type VARCHAR Entity type (node, policy, user, org, session, etc.) target_id VARCHAR Entity identifier (UUID, database ID) detail TEXT Human-readable description ip_address VARCHAR Source IP address user_agent VARCHAR Browser/client user agent string created_at DATETIME Timestamp (UTC)
Viewing the Audit Log
The audit log is accessible at System > Audit Log in the sidebar (requires Auditor or Super Admin role). It supports filtering by action, target type, username, date range, and free-text search.
Database Encryption at Rest
All database storage is encrypted using MySQL 8.0 Transparent Data Encryption (TDE), meeting NIST 800-53 SC-28.
What is Encrypted
- All 35 InnoDB tablespaces — Every table uses
ENCRYPTION='Y' - InnoDB redo logs —
innodb_redo_log_encrypt=ON - InnoDB undo logs —
innodb_undo_log_encrypt=ON - Binary logs —
binlog_encryption=ON - New tables —
default_table_encryption=ON(automatic)
Key Management
Encryption keys are managed by MySQL's keyring_file plugin. The master encryption key is stored in /var/lib/mysql-keyring/keyring (mode 0750, owned by mysql). Individual tablespace keys are encrypted by the master key and stored within the tablespace headers.
LUKS Keys (Application-Level)
In addition to database-level TDE, all LUKS encryption keys stored in the nodes table are encrypted with AES-256-GCM before database storage. The encryption master key is loaded from the FLEET_MASTER_KEY environment variable (256-bit random).
Enrollment
Device enrollment registers a new device with the fleet server, generates encryption keys, issues a client certificate, and provisions the device with tokens.
Enrollment Pipeline
- Boot the install USB on the target device (recovery Install Mode starts automatically)
- The wizard runs hardware diagnostics
- User signs in with their fleet account (or enrolls a new one)
- Device sends hardware profile to fleet server
- Fleet server generates LUKS keys, signs a client certificate, creates tokens
- Device receives tokens + certificate + node configuration
- Installer partitions the disk and installs the OS
- Device reboots and begins normal checkin cycle
Device Identity
- One record per machine — enrollment enforces a single active device record per physical machine; reinstalls supersede old records instead of creating duplicates
- Fleet-authoritative hostnames — a device's computer name is bound to its hardware serial on the fleet. Reinstalling or wiping restores the same name, and a device cannot rename itself against the fleet. Admins rename from the portal; the new name propagates on the next checkin.
Node Configuration
After enrollment, /boot/freezeos/node.json contains:
{
"node_id": "abc123...",
"fleet_url": "https://os.freeze2k.net",
"machine_serial": "SERIALNO",
"image_version": "2.9.86"
}
Device Checkin
Enrolled devices periodically check in with the fleet server to refresh tokens, report health data, and receive updates.
What Happens During Checkin
- Device POSTs to
/api/fleet/checkinwith node_id and optional health card - Server verifies the device exists and is not revoked/suspended
- Server issues fresh system and apps tokens
- Server returns merged policies for the device
- Device stores new tokens in
/boot/freezeos/
Checkin Triggers
- Boot — Every boot triggers a checkin during init
- Timer — Periodic checkin via systemd timer
- Manual — Can be triggered from the system info panel
Health Monitoring
FreezeOS includes a built-in health check system that scores device health from 0-100 across 17+ component tests.
Health Check Categories
- CPU — Temperature, frequency, load
- Memory — Usage, errors, swap pressure
- Storage — SMART data, disk usage, I/O performance
- GPU — Driver status, rendering tests
- Network — Connectivity, DNS resolution, fleet server reachability
- Battery — Capacity, cycle count, charge health
- USB — Controller status, device enumeration
Health cards are submitted with each checkin. The fleet portal displays health scores with color-coded badges (green >= 80, yellow >= 60, red < 60).
Policy Management
Organizations can create and assign policies to manage device configuration across their fleet.
Policy Categories
| Category | Settings |
|---|---|
| Date/Time | NTP enable/disable, timezone, custom NTP servers, RTC local time mode |
| Display | Wallpaper URL & style (stretched/centered/tiled/zoomed), lock wallpaper, DPMS enable, standby timeout |
| Proxy | Proxy mode (none/manual/auto), HTTP/HTTPS/FTP proxy, no-proxy bypass list, PAC URL |
| Security | Screen lock & delay, password min length/uppercase/digit, USB storage, SSH, firewall (UFW) |
| Power | Suspend on idle, lid close action, power button action, suspend when docked, CPU governor |
| Network | WiFi on/off, hotspot, custom DNS servers, DNS-over-TLS, require VPN, allowed SSIDs whitelist |
| Software | APT allowed, Flatpak allowed, blocked executables list, browser extensions, forced homepage |
| Updates | Auto-update enable, schedule (daily/weekly/monthly), auto-reboot after update, update channel |
| Restrictions | Terminal, settings panel, file manager, external drives, printing, camera, microphone |
| Custom Commands | Up to 3 shell commands, custom script URL, cron scheduling expression |
How Policies Work
- Admin creates a policy in the web portal and configures settings
- Policy is assigned to specific devices via the "Assign Devices" page
- During checkin, the device receives merged policies (higher priority wins)
- The
freezeos-policy-enforce.shscript applies settings idempotently - A systemd timer re-checks policies every 30 minutes
Policy Priority & Merging
Each policy has a priority number (0-999). When a device has multiple policies assigned, the fleet server merges them:
- Settings from higher priority policies override lower priority ones
- Settings not defined in any assigned policy use system defaults
- The merged result is a single flat JSON object delivered to the device
Enforcement Cycle
Policy enforcement runs on a continuous cycle:
- Timer fires — A systemd timer triggers
freezeos-policy-fetch.shevery 30 minutes - Fetch policies — The script calls
/api/fleet/policies?node_id={id}to get merged policies - Hash check — The fetched JSON is hashed (SHA-256) and compared against the last-applied hash
- Enforce if changed — If the hash differs (or no prior hash exists),
freezeos-policy-enforce.shapplies all settings idempotently - Store hash — The new hash is saved for future comparison
Enforcement also runs on every device boot (via checkin) and can be triggered manually.
Custom Commands
The Custom Commands category allows organizations to run arbitrary shell commands on managed devices. This is useful for org-specific configuration that doesn't fit into standard policy categories.
| Setting | Description |
|---|---|
| Custom Command 1-3 | Shell commands executed during each policy enforcement cycle |
| Custom Script URL | URL to a shell script that is downloaded and executed on enforcement |
| Custom Cron | Cron expression (e.g. */30 * * * *) for scheduling custom command execution independently of the enforcement cycle |
Custom commands run as root. Use with caution. Script URLs must be trusted — they are downloaded and executed with full system privileges.
OTA Updates & Channels
FreezeOS receives over-the-air system updates from the fleet server. Updates replace the entire squashfs system image on the inactive A/B slot.
Update Pipeline
- Device resolves its release channel against the fleet server for the pinned version
- If newer than current, downloads the squashfs image
- SHA-256 hash verified against server-provided hash
- Image written to the inactive system slot; new recovery image staged to /boot before reboot
- A/B state flipped to new slot
- Device reboots
- If boot fails 3 times, automatic rollback to previous slot
Release Channels
| Channel | Audience | Access |
|---|---|---|
| stable | Production devices | Default for everyone |
| beta | Opt-in early testing | Per-device request, admin-approved |
| dev | Bleeding-edge builds | Admin only |
Each channel is a pointer naming the exact version of every artifact it serves (image, scripts, recovery, kernel, installer). Publishing a new build never moves a channel until an admin explicitly repoints it — stable stays put by design. Admins manage channels from the portal's Release Management page: pinning versions, promoting beta to stable, and configuring auto-promotion (a beta build pinned for a configurable number of weeks graduates to stable automatically). Users request beta per-device from the device detail page; approval or denial arrives as a portal inbox notification.
Scripts Packages
System scripts and desktop tools ship as a separate lightweight package, versioned independently of the OS image. Script fixes reach devices without a full image update, and the installer always fetches the latest scripts at install time.
Update Safeguards
- Signed kernel preserved — the Debian-signed kernel is never overwritten by an update (Secure Boot chain stays intact)
- Boot-space preflight — staging refuses to proceed unless /boot has at least 300 MB free after cleanup, and reports the condition to the fleet
- Atomic installs — new boot files are written to a temp name, size- and integrity-checked, then renamed; a mid-copy failure can never truncate the live initramfs
- Verified backups — a rollback pair of the previous kernel and initramfs is kept and integrity-checked before any restore
- Dual-flavor guard — if the inactive slot holds a different OS flavor, the updater refuses rather than overwriting it (see OS Flavors)
- Persistent apply log — update apply progress is logged to /boot, survives reboots, and is submitted to the fleet on success or failure
App Repositories
Administrators manage which Flatpak app repositories are available across the fleet, and users search and install apps directly from the desktop.
Fleet-Managed Remotes
The portal's App Repos page lists configured Flatpak remotes (Flathub is included by default) and lets admins add, remove, enable, or disable repositories. Repository policy is fleet-wide with optional per-device overrides. Devices automatically reconcile their configured remotes to match fleet policy while preserving repositories a user added by hand.
Universal App Search
The desktop HUD's universal search covers local files, the web, and the app catalog — returning live results from Flathub alongside a curated catalog of roughly 200 apps. Clicking a result installs the app on demand for that user; installs are never force-pushed to devices. Installed apps are automatically added to the HUD Launcher with their real icon.
Self-Heal / Autofix
FreezeOS automatically detects and repairs common problems without user intervention. A background daemon periodically scans device logs, matches known error patterns, and applies vetted, idempotent fix scripts from a fleet-managed catalog.
Coverage
The fix catalog covers audio, networking, storage, display, power, session, authentication, time/locale, and general maintenance issues.
How It Stays Safe
- Fixes are individually versioned and tracked for success rate — a fix that repeatedly fails is automatically disabled fleet-wide
- Cascading or risky restarts are guarded by skip-lists so the system never fights itself
- Fixes that change the system can be queued for user confirmation or reverted; fixes needing a reboot flag that in the interface
Firmware Self-Heal
Missing device firmware fails silently — a laptop just has "no WiFi" or "no sound" with nothing naming firmware as the cause. FreezeOS closes this gap in two layers: images are built with the firmware their target hardware declares, and every device runs a firmware heal shortly after boot that scans the kernel log for failed firmware loads, checks what its drivers declare against what is on disk, fetches exactly the missing blobs from the fleet (never the internet), re-probes the affected drivers, and persists the files so they survive reboots. Anything the fleet cannot source is reported to the portal instead of failing silently.
User & Admin Control
Users can trigger an on-demand scan and Fix All from the Commander app; a clean scan reports an explicit "all clear". Administrators grow the fix catalog centrally from the portal's Autofix page, and devices pick up new fixes on their next check cycle — no software update needed.
Recovery Modes
Every FreezeOS machine carries a full graphical recovery environment on disk (/boot/recovery.img) — the same image used as the USB installer. When it boots, the recovery GUI picks one of three modes automatically:
| Mode | When It Runs | What It Offers |
|---|---|---|
| Install Mode | No FreezeOS installation detected | The 6-step install wizard (see Installation) |
| Standard Repair Mode | Normal recovery boot on an installed machine | Status, Diagnostics, and Install & Repair — reinstall the OS, repair the bootloader, apply staged updates |
| Decommissioned Mode | Machine has been logged out / decommissioned | File recovery and re-enrollment (see below) |
Other Recovery Paths
| Mode | How to Access | Description |
|---|---|---|
| Network Recovery | GRUB menu or freezeos.recovery=1 | Downloads fresh system image from fleet server |
| Safe Mode | GRUB menu or freezeos.safemode=1 | Boots with tmpfs overlay, bypassing all user changes |
| Automatic Rollback | Automatic after 3 failed boots | Reverts to previous A/B slot (kernel updates fall back the same way) |
| Manual Rollback | freezeos-system-update --rollback | Manually switch to previous slot |
Decommission & Re-Enrollment
Choosing Log Out from the desktop decommissions the machine: system state and credentials are wiped, but personal files are preserved. The machine reboots into Decommissioned Mode, where you can:
- Recover files — unlock your data with your PIN alone and copy files to a USB stick
- Re-enroll — give the device a fresh identity while keeping your files and the same PIN
Re-enrolled devices are linked to their prior identity in the fleet portal for audit purposes.
Network Recovery
Network recovery re-provisions the device by downloading a fresh system image from the fleet server.
Process
- Select "FreezeOS Network Recovery" from the GRUB menu
- Init script detects
freezeos.recovery=1kernel parameter - Establishes network connectivity (Ethernet or WiFi)
- Contacts fleet server, performs checkin to get fresh tokens
- Downloads latest system image
- Writes to active system slot
- Reboots into recovered system
Safe Mode
Safe mode boots with a tmpfs (RAM-based) overlay instead of the persistent Apps partition overlay. This bypasses all user-installed packages and configuration changes.
When to Use
- A user-installed package breaks the system
- Configuration change prevents login
- Need to diagnose issues without user modifications
Changes made in safe mode are lost on reboot (they're in RAM only).
Factory Reset
Factory reset wipes the persistent overlay (Apps partition), restoring the device to the base squashfs image state.
Factory reset removes all user-installed packages, configuration changes, and overlay data. User personal data on the User Storage partition is not affected.
Desktop Environment
FreezeOS uses XFCE 4 with a custom "Tron" theme — cyan glow accents, dark backgrounds, wireframe icons, a compositor with glow shadows, and a custom login greeter with wallpaper background and USB-key support.
HUD Panels
Two on-screen HUD panels are the heart of the desktop:
- Left HUD — app Launcher (installed apps are added automatically with their real icons) and file tree with hold-to-copy/paste
- Right HUD (Task Tree) — live window/task tree, network and volume applets, quick toggles, CPU/temperature readouts, and the Commander module
- Universal Search — one search box covering local files, the web, and the fleet app catalog (see App Repositories)
Panels support configurable transparency, fonts, glow, and idle auto-hide.
Included Applications & Utilities
- App Store — install applications, including Steam/Proton games (see App Store)
- FreezeOS Diagnostics — hardware health check UI
- FreezeOS Devices — phone pairing and 2FA recovery
- Control Panel / Settings — settings hub (default OS picker, desktop mode, display, network)
- System Update — OTA update GUI wizard
- Key Writer — provisions USB security keys for login
- Install USB maker — creates FreezeOS install USBs from the desktop
- Volume tray, media-key bindings, Bluetooth applet, on-screen keyboard, streaming applet, messenger tray
- Snowflake screensaver — CRT retro-futurism idle screen
- Chrome — web browser (with Widevine for streaming services)
- Thunar file manager and terminal
- Barrier — keyboard/mouse sharing across machines
Optional: Idle Mining
An opt-in, idle-only cryptocurrency mining feature. No miner software ships in the base system — enabling it downloads only the miner your hardware supports. Mining runs only after the machine has been idle (default 10+ minutes), shows a themed screensaver, and stops the instant you return. Automatic kill-switches cover temperature, crashes, and memory pressure. Earnings accrue on the mining pool keyed to your wallet address — nothing of value is stored on the machine.
App Store
The FreezeOS App Store installs applications with full desktop integration. Installed apps are automatically added to the HUD Launcher with their real icon, so users can relaunch them without reopening the store.
Availability States
Every app shows a clear availability state. Apps that can't be installed on the current system show a dimmed "Unavailable" button with a tooltip explaining why. On the from-source FreezeOS Linux flavor (which has no Debian package manager), the store automatically substitutes Flatpak equivalents where they exist, and marks tools already present in the base image as "In base".
Steam & Proton Games
The store carries Steam/Proton games (for example Dota 2, Team Fortress 2, Counter-Strike 2). If Steam isn't installed yet, selecting a game installs Steam automatically (as a Flatpak) and hands the game off to Steam to install via Proton.
Where Apps Come From
Apps come from fleet-managed Flatpak repositories and a curated catalog — see App Repositories. Installs are always user-initiated; the fleet never force-pushes apps to devices.
Diagnostics Tools
FreezeOS includes built-in diagnostic tools for hardware testing and system monitoring.
FreezeOS Diagnostics
A GTK3 application accessible from XFCE Settings Manager that runs comprehensive hardware tests and generates a health score.
FreezeOS Commander
A terminal-based fleet management tool that provides:
- Device status and fleet server connectivity
- Network diagnostics (ping, DNS, fleet reachability)
- Manual checkin and token refresh
- System update management
- Log submission
Log Submission
Devices can submit diagnostic logs to the fleet server for remote debugging.
Usage
report_log # Submit all logs report_log kernel # Submit kernel logs only report_log network # Submit network logs only
Submitted logs appear in the web portal under "My Logs" and expire after 30 days. Organization accounts can view logs from all member devices.
Commander Phone App
Commander is the FreezeOS companion app for Android, downloadable from the download page. It pairs with your fleet account and your devices.
Features
- Login approval (2FA) — approve portal sign-ins on your phone (see Phone 2FA)
- Device monitoring — see your enrolled devices, health, and notifications (including "kernel update available")
- Auto-Fix — trigger an on-demand self-heal scan and Fix All on a device (see Self-Heal)
- Bootable USB writer — create a FreezeOS install USB directly from the phone over a USB-OTG adapter, no PC or root required. Pick a channel (stable/beta/dev), download (resumable, cached, checksum-verified), select the stick, and write with read-back verification. A device-model picker bundles the matching performance kernel on the stick.
- Self-update — the app checks for newer versions on launch and offers one-tap, integrity-verified update
Writing a USB stick erases the entire stick. The app asks for explicit confirmation before the destructive write.
Web Portal
The FreezeOS web portal at os.freeze2k.net provides fleet management through a browser.
Portal Pages
| Page | Access | Description |
|---|---|---|
| My Devices | All users | View, deauthorize, restore, delete devices; request beta channel; manage per-device keys |
| My Logs | All users | View submitted diagnostic logs |
| Account / Security | All users | Profile, password change, USB login keys, phone 2FA authenticators |
| Downloads | All users | Linux USB Creator, Windows Installer, Boot ISO, Commander app |
| Supported Devices | All users | Hardware compatibility catalog with per-model support status |
| Organization | Org accounts | Add/remove members, manage roles |
| Policies | Org accounts | Create, edit, assign policies to devices |
| Admin Console | Admin accounts | Manage all users, orgs, devices, policies, images, kernels, autofix catalog, App Repos, analytics |
| Build & Deploy | Admin accounts | Queue and deploy image/kernel builds (see Build & Deploy) |
| Release Management | Admin accounts | Pin channel versions, promote beta→stable, approve beta requests |
| Fleet Servers / Overview / Network | Admin accounts | Server pool management and live dashboards (see Fleet Server Pool) |
Build & Deploy
All FreezeOS build types are managed from a single Build & Deploy page in the admin console — a wizard for queuing builds, a unified jobs view, and a deliberate deploy step.
Build Types
| Type | What It Builds |
|---|---|
| Source | A full from-source FreezeOS Linux image with an inline kernel, targeted at a specific device model. Choosing "full" queues the image and the per-device kernel in parallel across build servers. |
| Debian | A general-purpose Debian image with customization: extra packages, firmware packages, application toggles, and a settings overlay — applied automatically during the build. |
| Kernel | A per-device performance kernel (see Per-Model Kernels). |
Jobs & Deploy
- The Jobs tab shows a live, unified view of all build jobs across every type, with normalized status, target device, target server, and per-job cancel
- The Deploy tab lists finished images as built/unpublished — picking a channel and deploying is the only step that puts a build in front of devices
Distributed Build Servers
Builds run on a pool of dedicated build servers, never on the production web server. The load balancer assigns each queued job to the least-busy eligible server, and agents also pick up unassigned work — so a system image on one server and a kernel on another build in parallel. Builds are sandboxed and resource-capped, and the pipeline self-heals from transient failures with retries and resume. Signing is centralized: images can be built anywhere but are signed by the central signer.
Fleet Server Pool
FreezeOS runs a federated pool of fleet servers that share device traffic and provide failover — a writable primary plus one or more mirror servers that serve traffic and can be promoted if the primary fails. Pool-internal traffic flows over an encrypted private mesh; each member dials out to the hub, so mirrors need no inbound firewall openings.
Adding a Server
- In the portal's Fleet Servers page, choose Add Fleet Server — this generates a single-use provisioning code (24-hour expiry)
- Boot the new machine from the FreezeOS installer, open Advanced, choose Provision Fleet Server, and enter the code (validated live before install)
- The install selects the server image; on first boot the server redeems the code, receives a sealed identity bundle, stands up its services, joins the mesh, and reports in
Sensitive signing material for promotable mirrors is exported only on explicit opt-in — single-use, time-limited, admin-revocable, and encrypted end-to-end so only the target server can decrypt it.
Live Dashboards
- Fleet Overview — all servers on a map with per-server telemetry: storage, monthly bandwidth, link speed, active build jobs, CPU/memory load, the load balancer's next build target, and each server's HTTPS certificate expiry (color-coded)
- Fleet Network — a live auto-refreshing mesh-topology map that pulses servers actively processing builds, with a "Now processing" panel showing per-job progress and phase, and a staleness warning chip
Roles
- Primary — holds the writable master database (enrollment, certificates, latest images)
- Mirrors — serve device traffic and image downloads, act as build servers, and can be promoted on failover
Account Types
FreezeOS has three account types, each with escalating levels of access and control over the fleet.
User (Individual)
- Enroll and manage own devices
- View own device health, logs, and status
- Change own password and account settings
- Submit and view own diagnostic logs
Organization
Everything a User can do, plus:
- Create an organization and invite members by email
- View all devices across the organization
- View aggregated logs from all member devices
- Create, edit, and assign policies to member devices
- Manage organization members (add, remove, promote)
Admin (Global)
Everything an Organization can do, plus:
- Manage all users, organizations, and devices system-wide
- Change any user's account type (user, org, admin)
- Suspend or delete any account
- View all logs across the entire fleet
- Create and manage global policies
- Manage system images and OTA updates
Permissions Matrix
| Action | User | Org | Admin |
|---|---|---|---|
| Enroll devices | ✓ | ✓ | ✓ |
| View own devices | ✓ | ✓ | ✓ |
| View own logs | ✓ | ✓ | ✓ |
| Manage own account | ✓ | ✓ | ✓ |
| Create organization | — | ✓ | ✓ |
| Add/remove members | — | ✓ | ✓ |
| View member devices | — | ✓ | ✓ |
| View member logs | — | ✓ | ✓ |
| Create/assign policies | — | ✓ | ✓ |
| Manage all users | — | — | ✓ |
| Change account types | — | — | ✓ |
| Suspend/delete accounts | — | — | ✓ |
| View all logs | — | — | ✓ |
| Manage system images | — | — | ✓ |
Secondary OS
Run a second FreezeOS flavor in a virtual machine alongside your installed system — FreezeOS Debian on a source box, FreezeOS Linux (source) on a Debian box, or either one by choice. Nothing is installed on the host disk: the guest boots a prebuilt fleet image with no installer, no disk encryption and no device tokens, and you sign into the fleet from inside the guest desktop.
Enabling
- Enable VirtualBox first (Settings → Software Profile → Virtual Machines)
- Pick which flavor to run from the Secondary OS to run dropdown
- Press Set up secondary OS — the fleet image (1.5–4 GB) downloads, is sha256-verified, and the VM starts
Seamless Mode
The guest ships with VirtualBox Guest Additions baked in, so it behaves like part of the host desktop:
- Seamless windows — guest apps appear as individual windows on the host desktop (Parallels-style). Toggle in Settings.
- Show/hide hotkey —
Super+Vby default (configurable). The guest keeps running while hidden, so showing it is instant. - Start at login — optional: the VM starts hidden when you log in, ready behind the hotkey.
- Smooth mouse & clipboard — no pointer capture; bidirectional clipboard and drag & drop.
Guest Details
| Property | Value |
|---|---|
| Hostname | vm-<host hostname> — the reserved vm- prefix marks it as a secondary OS, never a real device |
| Local account | user freezeos, password freezeos (auto-login; sudo enabled) |
| Storage | virtio-scsi disk with host I/O cache; persistent — the guest keeps its state across reboots |
| Performance | nested paging, large pages, KVM paravirtualization, host CPU profile, VMSVGA graphics with 3D acceleration |
| Fleet | not enrolled until you sign in with your fleet credentials inside the guest |
Removing
Remove secondary OS in Settings powers the VM off and deletes the VM, its disks and the login autostart — the host system is untouched and the reclaimed disk space is reported.
Dynamic Wallpaper
Dynamic FreezeOS Wallpaper turns your desktop background into a living thing: the fleet generates brand-new artwork and your machine picks it up automatically, twice a day. Every rotation is a unique, procedurally generated Tron-style circuit board in the FreezeOS ember palette — glowing traces, chip packages and solder pads converging on a bright core. No two rotations are the same.
Turning it on
- Open Settings → Appearance → Wallpaper (or the Wallpaper picker directly)
- Switch on Dynamic FreezeOS Wallpaper
- The current artwork downloads and applies immediately — no need to wait for the next rotation
How it works
| Stage | What happens |
|---|---|
| Rotation | The fleet server renders new art twice a day (00:05 and 12:05 UTC). Every device on source sees the same artwork — the fleet feels coordinated. |
| Poll | Your machine checks every 30 minutes. The check is a few hundred bytes; the image is downloaded only when the version actually changed. |
| Verify | Each rotation is published with a SHA-256. The device verifies the download and refuses to apply anything that does not match. |
| Apply | The wallpaper is set and recorded as your current wallpaper, so it survives system updates and logins. |
| Disk | Only the current image is kept on the device (about 1 MB). |
Your own wallpaper still wins
Turning Dynamic on replaces whatever wallpaper you had, and turning it off puts your previous choice back. If you pick a wallpaper by hand while Dynamic is running, that is treated as a decision: Dynamic switches itself off and leaves your pick alone. You will never fight the rotation for control of your desktop.
For administrators
Each device page in the portal has a Dynamic Wallpaper card (admins only, shown for source devices): choose a rotation, push it to that device, or publish a brand-new rotation fleet-wide right away. A pushed wallpaper is applied on the device’s next poll, within 30 minutes.
The same actions are available on the fleet server:
| Command | Purpose |
|---|---|
wallpaper-rotate.py rotate | Publish this slot’s artwork (what the timer runs) |
wallpaper-rotate.py push --hostname HOST | Pin one device to the current rotation |
wallpaper-rotate.py show | Current rotation and recent history |
wallpaper-rotate.py render --seed N --out FILE | Preview artwork without touching the fleet |
Rotations are keyed to a slot (YYYYMMDD-am/-pm) and rendering is deterministic, so a server that was offline over a rotation boundary catches up safely without ever publishing the same slot twice.
Organizations
Organization accounts can manage multiple users and their devices under a single umbrella.
Features
- Member Management — Add users by email, assign admin or member roles
- Aggregated Logs — View logs from all member devices with member filter
- Policy Management — Create policies and assign to any member's device
- Device Visibility — See all devices across the organization
Member Roles
| Role | Description |
|---|---|
| Owner | The organization account itself. Full control over the org, its members, policies, and all member devices. Cannot be removed. |
| Admin | Can manage other members (promote/demote/remove), create and assign policies, view all devices and logs |
| Member | Devices are visible to the org. Policies can be applied to their devices. Can view own devices and logs only. |
Organization Scope
An organization has visibility and control over member devices as follows:
- Device visibility — The org can see all devices enrolled by its members, including health scores, last checkin time, and system version
- Log access — The org can view diagnostic logs submitted by any member device, with member-level filtering
- Policy assignment — The org can assign policies to any member's device. Policies are enforced automatically on the device.
- Device actions — The org can deauthorize, restore, or trigger updates on member devices
Policy Assignment Flow
- Org admin creates a policy in the portal with desired settings
- Org admin navigates to the policy's "Assign Devices" page
- Select one or more member devices to assign the policy to
- On the next device checkin, the fleet server merges all assigned policies (by priority) and returns the result
- The device's
freezeos-policy-enforce.shapplies the merged settings
API Reference
The fleet server exposes a REST API for device management.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/fleet/enroll | Enroll a new device |
| POST | /api/fleet/login-enroll | Enroll with existing account |
| POST | /api/fleet/checkin | Device checkin, token refresh |
| GET | /api/fleet/images/latest | Get latest system image metadata |
| GET | /api/fleet/images/download/{version} | Download system image |
| GET | /api/fleet/policies?node_id={id} | Get merged policies for a device |
| POST | /api/fleet/update-report | Report update status |
| POST | /api/fleet/submit-log | Submit diagnostic logs |
| GET | /api/fleet/recovery/latest | Get recovery image metadata |
| GET | /api/fleet/scripts/latest | Get latest scripts package |
| POST | /api/fleet/re-provision | Re-provision a device |
| POST | /api/fleet/deauth | Deauthorize a device |
| GET | /api/fleet/kernels/latest | Get latest per-model kernel metadata |
| GET | /api/fleet/install/supported-models | Live list of supported device models (used by USB creator) |
| GET | /api/fleet/flatpak-remotes | Fleet-managed app repository list |
| GET | /api/fleet/appsearch | Live app catalog search |
| POST | /api/fleet/cert-challenge / cert-verify | USB key login challenge/response |
| POST | /api/fleet/firmware/bundle | Fetch firmware blobs by path (device firmware heal) |
| GET | /health | Server health check |