> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zylon.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Full-Airgap Installation

> Install Zylon in completely offline environments

Airgap installation enables Zylon deployment in environments with zero internet access. This process requires **two separate Linux machines**: one with internet connectivity for downloading bundles, and one offline machine for running Zylon.

**Prerequisites Checklist**:

* [ ] Clean Linux machine (Ubuntu 22/24) meeting [hardware requirements](/en/operator-manual/installation/hardware-requirements)
* [ ] Root and SSH access to the machine
* [ ] A domain name for Zylon (e.g., zylon.company.com)
* [ ] Ability to reboot the machine when needed
* [ ] Machine has `curl` installed

- [ ] Online machine with internet access to download installation bundles
- [ ] Method to transfer files (70-100 GB) to the isolated target machine (USB drive, internal network, etc.)
- [ ] Target machine has NO internet connection
- [ ] Valid SSL certificate for your domain
- [ ] Sufficient storage on online machine and transfer media for large bundles

***

## Required Network Access

In your online machine, ensure firewall access to these domains:

**Essential Services (Mandatory):**

* `get.zylon.ai` - CLI installation
* `zylon-cli.s3.us-east-1.amazonaws.com` - CLI binaries and dependencies
* `zylon-artifacts.s3.us-east-1.amazonaws.com` - Zylon installation files and updates

<Warning>
  These domains must be reachable from the online machine to download Zylon bundles and updates.
  If direct internet access is not available, you can configure a proxy server.

  <Accordion title="Configuring Proxy Settings">
    Set the following environment variables before running any Zylon CLI commands:

    ```bash theme={null}
    export HTTP_PROXY="http://proxy.company.com:8080"
    export HTTPS_PROXY="http://proxy.company.com:8080"
    ```

    **Using Self-Signed Certificates**

    If your proxy uses a self-signed certificate, you must also configure the CA certificate:

    ```bash theme={null}
    export SSL_CERT_FILE="/path/to/your/ca-cert.pem"
    export REQUESTS_CA_BUNDLE="/path/to/your/ca-cert.pem"
    ```

    **Verify Proxy Configuration**

    Test connectivity through the proxy before proceeding:

    ```bash theme={null}
    # Test HTTP connectivity
    curl -v -x $HTTP_PROXY http://get.zylon.ai

    # Test HTTPS connectivity (if using self-signed cert)
    curl -v -x $HTTPS_PROXY --cacert $SSL_CERT_FILE https://get.zylon.ai
    ```

    **Running Commands with sudo**

    ⚠️ **Important:** The `sudo` command does not preserve environment variables by default. You must use the `-E` flag to pass proxy settings to commands requiring elevated privileges:

    ```bash theme={null}
    sudo -E zylon-cli download <version> --airgap
    ```
  </Accordion>
</Warning>

***

## Installing Zylon

<Steps>
  <Step title="Online Machine">
    Download Zylon bundles and AI models with internet access
  </Step>

  <Step title="Transfer">
    Move bundle files to offline machine via secure transfer method
  </Step>

  <Step title="Offline Machine">
    Import and install Zylon without any internet connectivity
  </Step>
</Steps>

***

### Part A: Online Machine Setup

<Steps>
  <Step title="Install CLI">
    *Estimated time: 2 min*

    <Warning>
      Before starting the installation, validate that your machine can reach `get.zylon.ai`:

      ```bash theme={null}
      curl -sLv get.zylon.ai -m 3 | exit 1
      ```

      If the connection is giving errors, work with your network team to resolve them. Once connectivity is verified, you can proceed.
    </Warning>

    The Zylon CLI will speed up the time it takes to get everything ready, it will take care of installing drivers, updating Zylon and configuring the system.
    To install it, SSH into the machine where you want to install Zylon and run:

    ```bash theme={null}
    # ssh <user>@<host-ip>
    sudo curl -sL get.zylon.ai | sh
    ```

    Verify the installation:

    ```bash theme={null}
    sudo zylon-cli version
    ```

    <Note>
      Root access is required for CLI operations as it manages system-level dependencies and configurations.
    </Note>
  </Step>

  <Step title="Configure Zylon">
    *Estimated time: 10min*

    Zylon is configured using a YAML file located at `/etc/zylon/zylon-conf.yaml`.

    **Generate Initial Configuration**

    Use the CLI to generate an initial configuration file:

    ```bash theme={null}
    sudo zylon-cli config init
    ```

    This opens an interactive prompt to guide you through configuration options.

    <Info>
      If for any reason you got stuck during the interactive prompt, you can skip it by adding the `-y` flag to auto-generate a default configuration:

      ```bash theme={null}
      sudo zylon-cli config init -y
      ```

      You will need to manually edit `/etc/zylon/zylon-conf.yaml` afterward to set your desired configuration based on the [manual configuration](#manual-configuration) section.
    </Info>

    <Tabs>
      <Tab title="Auto Configuration">
        If you executed `sudo zylon-cli config init`, all configuration is set.
        Review `/etc/zylon/zylon-conf.yaml` to confirm settings. You can know more information about which settings are required in [Manual Configuration](#manual-configuration) section.

        <Info>
          If you need to re-run the configuration wizard, execute:

          ```bash theme={null}
          sudo zylon-cli config init
          ```
        </Info>
      </Tab>

      <Tab title="Manual Configuration">
        Edit `/etc/zylon/zylon-conf.yaml` to adjust settings as needed.

        **Define your OS distribution**

        Set `node.distro` to match your Ubuntu version:

        ```yaml theme={null}
        node:
          distro: "ubuntu22"  # for Ubuntu 22.04
          # distro: "ubuntu24"  # for Ubuntu 24.04
        ```

        **Define your CPU architecture**

        Set `node.arch` to match your hardware:

        ```yaml theme={null}
        node:
          arch: "amd64"  # for Intel/AMD processors
        ```

        **Set your hardware drivers (if applicable)**

        Set `node.drivers` to `generic` (this is the only supported option):

        ```yaml theme={null}
        node:
          drivers: "generic"
        ```

        **Configure cluster type**

        Set `cluster.type` to `k0s` (this is the only supported option for single instance installations):

        ```yaml theme={null}
        cluster:
          type: "k0s"
        ```

        **Select your release channel**

        Set `channel` to `stable` (recommended for production and normal use) or `unstable` (available under request for testing):

        ```yaml theme={null}
        channel: "stable"
        ```

        **Add your license information**

        Set `license.email` to the email address assigned to your license (provided during registration).

        Set `license.id` to the license ID shared with you by the Zylon team via email:

        ```yaml theme={null}
        license:
          email: "champion@company.com"
          id: "2oq..."
        ```

        **Choose your AI preset**

        Set `ai.preset` based on your available GPU memory. See [AI Presets](/en/operator-manual/ai-presets/getting-started) for details.

        ```yaml theme={null}
        ai:
          preset: "baseline-48g"
        ```

        **Set your company identifier**

        Set `companyIdentifier` to any identifier for anonymous metrics tracking (e.g., `acme-corp`). If you have multiple installations, use different identifiers (e.g., `company` and `company-test`):

        ```yaml theme={null}
        companyIdentifier: "your-company"
        ```

        **Disable telemetry & crash reporting**

        To disable telemetry and crash reporting, add the following section:

        ```yaml theme={null}
        observability:
            crashReporting: false
            usageMetrics: false
        ```

        **Configure network ingress**

        Set `ingress.host` to the domain you've prepared for Zylon. This should be a fully qualified domain name (FQDN) that points to your server's IP address.

        Examples:

        * `zylon.company.com`
        * `ai.acme-corp.com`
        * `zylon-prod.yourcompany.io`

        ```yaml theme={null}
        ingress:
          host: "zylon.your-company.com"
          enabled: true
          tlsEnabled: true
        ```

        **Configure SSL certificate generation**

        If your server is accessible from the internet, Let's Encrypt will automatically generate and renew SSL certificates. Keep the default `certManagerAnnotations`:

        ```yaml theme={null}
        ingress:
          certManagerAnnotations:
            cert-manager.io/cluster-issuer: "letsencrypt-prod"
        ```

        If you're in a private network or need to use a custom certificate, see [Disable Let's Encrypt](#disable-lets-encrypt) below.

        **Airgap Settings**

        Ensure these settings are included to indicate airgap installation and operation:

        ```yaml theme={null}
        airgap:
          offlineInstall: true
          offlineOperation: true
        ```

        **Local License**

        Since the offline machine cannot reach `api.replicated.com`, you need a local license. Contact Zylon support to obtain it, then add:

        ```yaml theme={null}
        license:
          email: "champion@company.com"
          id: "2xo..."
          type: "Zylon"
          data: |-
            eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
        ```

        <Warning>
          Replace the `data` field with the actual license data provided by Zylon team. Please be careful with formatting and indentation.
          Just copy the token that starts with `eyJ...` and ends with `...`.
        </Warning>
      </Tab>
    </Tabs>

    **View Current Configuration**

    ```bash theme={null}
    sudo cat /etc/zylon/zylon-conf.yaml
    ```

    You can edit the configuration file directly using your preferred text editor (e.g., `nano`, `vim`):

    ```bash theme={null}
    # Choose one of the following commands:
    sudo nano /etc/zylon/zylon-conf.yaml
    sudo vim /etc/zylon/zylon-conf.yaml
    ```

    For detailed information about all available configuration options, see the [Configuration Guide](/en/operator-manual/configuration/index).
  </Step>

  <Step title="Download AI Models">
    *Estimated time: 10min to 1h, depending on network speed and models.*

    **Before downloading Zylon**, you must download the AI models on the online machine. The models are determined by your AI preset configuration.

    Check available models and compare with your AI preset:

    ```bash theme={null}
    sudo zylon-cli models list
    ```

    More preset details in the [AI Presets documentation](/en/operator-manual/ai-presets/presets).

    Download the models based on your configuration:

    ```bash theme={null}
    sudo zylon-cli models download --no-install
    ```

    This will download the AI models that you have specified in the Wizard.

    If for some reason you need to download specific models, you can do so with:

    ```bash theme={null}
    sudo zylon-cli models list
    sudo zylon-cli models download --no-install model-a model-b model-c
    ```

    For example, for `baseline-48g` preset:

    ```bash theme={null}
    sudo zylon-cli models download --no-install qwen/qwen3-14b-awq mixedbread-ai/mxbai-embed-large-v1
    ```
  </Step>

  <Step title="Export AI Models">
    *Estimated time: 5 to 30 min, depending on models size.*

    After downloading the models, export them for transfer to the offline machine:

    ```bash theme={null}
    sudo zylon-cli models export
    ```

    This creates a `zylon-models-<timestamp>.tar` file in your current directory containing all selected AI models.

    <Note>
      The model export file can be 10-100 GB depending on which models you have downloaded.
    </Note>
  </Step>

  <Step title="Download Zylon Bundle">
    *Estimated time: 15min to 2h, depending on network speed.*

    Download the specific Zylon version you want to install:

    ```bash theme={null}
    sudo zylon-cli list-versions
    # Choose your desired version from the list
    sudo zylon-cli download <version> --airgap
    ```

    Replace `<version>` with your target version (e.g., `1.50.0`).

    <Note>
      Note that we **do not use** the `--models` flag here since models were already handled in the previous steps.
    </Note>
  </Step>

  <Step title="Export Bundle">
    *Estimated time: 15 to 60 min, depending on version.*

    Export the downloaded version into an airgap bundle:

    ```bash theme={null}
    sudo zylon-cli export <version>
    ```

    This creates `zylon-<version>-<os>-<arch>.tar` in your current directory. Additionally, it will generate
    the commands to run on the offline machine for installation to import and install Zylon. Store these commands safely.

    <Note>
      Export can take significant time. The resulting tar file may be 60-80GB.
    </Note>
  </Step>

  <Step title="Prepare Initial Transfer (First Install Only)">
    <Warning>
      **First installation only!** After initial setup, the CLI self-updates from airgap bundles.
    </Warning>

    Create a bundle with CLI tools and configuration:

    ```bash theme={null}
    sudo tar -czf zylon-initial.tar.gz \
      /usr/local/bin/zylon-cli \
      /usr/local/bin/zylon-forge-cli \
      /etc/zylon/zylon-conf.yaml
    ```
  </Step>

  <Step title="Prepare Certificates (Optional)">
    *Estimated time: 5 min*

    If your Zylon instance is in a private network or VPN, you need to manually provide SSL certificates.
    Prepare them for transfer:

    Gather your SSL certificate files:

    * `crt.pem` (Certificate + Intermediate)
    * `key.pem` (Private Key)

    Create a tarball for transfer:

    ```bash theme={null}
    sudo tar -czf zylon-ssl-certs.tar.gz crt.pem key.pem
    ```
  </Step>

  <Step title="Transfer Files">
    Transfer files to the offline machine using your preferred method (SCP, USB, external drive):

    **First installation:**

    * `zylon-<version>-<os>-<arch>.tar` (main bundle)
    * `zylon-models-<timestamp>.tar` (AI models)
    * `zylon-initial.tar.gz` (CLI and config)
    * `zylon-ssl-certs.tar.gz` (SSL certs, if applicable)

    **Subsequent updates:**

    * `zylon-<version>-<os>-<arch>.tar` (main bundle)
    * `zylon-models-<timestamp>.tar` (AI models export, if adding new models)

    **SCP Example**

    ```bash theme={null}
    scp zylon-<version>-<os>-<arch>.tar user@offline-machine:/tmp/
    scp zylon-models-*.tar user@offline-machine:/tmp/
    scp zylon-initial.tar.gz user@offline-machine:/tmp/
    scp zylon-ssl-certs.tar.gz user@offline-machine:/tmp/
    ```
  </Step>
</Steps>

***

### Part B: Offline Machine Installation

<Steps>
  <Step title="Install CLI (First Time Only)">
    *Estimated time: 2 min*

    <Warning>
      **Skip if updating an existing installation.** This is only for first-time installations.
    </Warning>

    Extract CLI tools and configuration:

    ```bash theme={null}
    cd /tmp
    sudo tar -xzf zylon-initial.tar.gz -C /
    sudo chmod +x /usr/local/bin/zylon-cli /usr/local/bin/zylon-forge-cli
    ```

    Verify installation:

    ```bash theme={null}
    sudo zylon-cli version
    cat /etc/zylon/zylon-conf.yaml
    ```

    <Note>
      Future updates automatically update the CLI from airgap bundles—no manual transfer needed.
    </Note>
  </Step>

  <Step title="Verify Zylon minimum requirements">
    Ensure your machine meets the [hardware requirements](/en/operator-manual/installation/hardware-requirements) for Zylon.

    To validate automatically if your installation meets the minimum requirements, run:

    ```bash theme={null}
    sudo zylon-cli preflight --fresh-system -v
    ```

    Address any issues reported before proceeding with the installation. You will not be able to continue until all preflight checks pass.
  </Step>

  <Step title="Import AI Models">
    *Estimated time: 5 to 30 min, depending on model sizes.*

    **Before importing Zylon**, import the AI models that were exported on the online machine:

    ```bash theme={null}
    cd /tmp
    sudo zylon-cli models import zylon-models-<timestamp>.tar
    sudo zylon-cli models download --offline
    ```

    `models import` registers the model artifacts locally, and `models download --offline` installs them into the offline runtime.

    Verify models were installed successfully:

    ```bash theme={null}
    sudo zylon-cli models list --installed
    ```
  </Step>

  <Step title="Import Airgap Bundle">
    *Estimated time: 10 to 60 min, depending on bundle size and system performance.*

    Import the Zylon bundle:

    ```bash theme={null}
    cd /tmp
    sudo zylon-cli import zylon-<version>-<os>-<arch>.tar
    ```

    This process:

    * Extracts all container images
    * Installs dependencies offline
    * Prepares the system for installation

    <Warning>
      Import can take 30+ minutes depending on bundle size and system performance. Do not interrupt.
    </Warning>

    Verify that import completed successfully by checking installed versions:

    ```bash theme={null}
    sudo zylon-cli list-versions --offline
    ```
  </Step>

  <Step title="Install Zylon">
    *Estimated time: 15min to 1hour, depending on system performance.*

    Install Zylon using the imported bundle:

    ```bash theme={null}
    sudo zylon-cli install <version> --airgap
    ```

    <Note>
      The AI models have already been imported in a previous step, so no `--models` flag is needed here.
    </Note>
  </Step>

  <Step title="Create Organization">
    *Estimated time: 5 min*

    After Zylon is installed and running, create your organization and root administrator account.

    **Prepare Information**

    You'll need:

    * **Organization name**: Your company or team name (can be changed later)
    * **Admin password**: Secure password for root administrator (can be changed later)
      * Use alphanumeric characters due to encoding limitations with special symbols
    * **Email regex**: Pattern to auto-allow users to join
      * For `name@company.com` emails, use: `.*@company\.com`
      * For SSO (Microsoft Entra, Google), you can use: `.*`

    **Run Seed Command**

    ```bash theme={null}
    sudo zylon-cli seed \
      --org-name "My Organization" \
      --admin-password "secure-password" \
      --email-regex ".*@yourcompany\.com"
    ```

    The command will wait if Zylon is not fully ready.

    <Danger>
      **Running the seed command will WIPE ALL DATA.** Only run this once during the initial Zylon setup.
    </Danger>

    **Login Credentials**

    After seeding, use these credentials to log in:

    ```
    Username: admin@zylon.ai
    Password: [the password you set]
    ```

    The root admin email is always `admin@zylon.ai` and cannot be changed.

    <Note>
      After first login, you can create additional administrators and configure SSO authentication.
    </Note>
  </Step>

  <Step title="Configure SSL Certificates (If applicable)">
    *Estimated time: 10 min*

    If you prepared SSL certificates on the online machine, extract them now:

    ```bash theme={null}
    cd /tmp
    sudo tar -xzf zylon-ssl-certs.tar.gz -C /tmp/
    ls /tmp/crt.pem /tmp/key.pem
    ```

    If you see both files, proceed to install them as follows:

    **Remove Automatic Certificate Generation**

    Edit `/etc/zylon/zylon-conf.yaml` and **remove** these lines:

    ```yaml theme={null}
    certManagerAnnotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
    ```

    **Prepare Certificate Files**

    Kubernetes requires the certificate split into two files:

    * `tls.crt` - The certificate file
    * `tls.key` - The private key file

    **Convert from PFX (if applicable):**

    If you have a `.pfx` file, convert it:

    ```bash theme={null}
    openssl pkcs12 -in <your-certificate.pfx> -clcerts -nokeys -out tls.crt
    openssl pkcs12 -in <your-certificate.pfx> -nocerts -out tls.key
    ```

    **Import Certificate into Kubernetes**

    ```bash theme={null}
    # Remove any existing certificate
    sudo k0s kubectl delete secret tls zylon-tls --ignore-not-found -n zylon

    # Import your certificate
    sudo k0s kubectl create secret tls zylon-tls \
      --key tls.key \
      --cert tls.crt \
      -n zylon

    # Verify creation
    sudo k0s kubectl describe secret zylon-tls -n zylon
    ```

    **Apply Changes**

    Reload the Zylon configuration:

    ```bash theme={null}
    sudo zylon-cli sync
    ```

    **Verify**

    Access your Zylon instance at `https://zylon.your-company.com` and confirm:

    * The connection uses HTTPS
    * The browser shows a valid certificate
    * No certificate warnings appear

    <Tip>
      Certificate renewal must be done manually by repeating this process with updated certificate files.
    </Tip>
  </Step>
</Steps>

***

## Updating Zylon

Updates in airgap environments follow a similar two-machine workflow. The process is faster than initial installation since you're only transferring changes, not the entire platform.

<Note>
  **Estimated Time**: 45-60 minutes total (15-20 min online machine, 25-40 min offline machine)
</Note>

<Steps>
  <Step title="On Online Machine: Download New Models (If Needed)">
    *Estimated time: 10 to 60 min (only if adding new models)*

    **Skip this step if you're not adding new AI models.**

    If you're changing AI presets, upgrading GPU requirements, or need additional models:

    First, check your current and available models:

    ```bash theme={null}
    sudo zylon-cli models list
    ```

    Download the new models:

    ```bash theme={null}
    sudo zylon-cli models download --no-install new-model-a new-model-b
    ```

    <Info>
      Compare the available models with your AI preset requirements to determine if additional models are needed. See [AI Presets documentation](/en/operator-manual/ai-presets/presets).
    </Info>
  </Step>

  <Step title="On Online Machine: Export New Models (If Applicable)">
    *Estimated time: 5 to 30 min (only if new models were downloaded)*

    **Skip this step if you didn't add new AI models.**

    Export the newly downloaded models:

    ```bash theme={null}
    sudo zylon-cli models export
    ```

    This creates a `zylon-models-<timestamp>.tar` file containing all currently downloaded models.
  </Step>

  <Step title="On Online Machine: Download Update">
    *Estimated time: 10 to 60 min*

    Download the new Zylon version bundle:

    ```bash theme={null}
    sudo zylon-cli download <new-version> --airgap
    ```

    <Note>
      Note that we **no longer use** the `--models` flag during download, as models are handled separately.
    </Note>
  </Step>

  <Step title="On Online Machine: Create Update Bundle">
    *Estimated time: 10 to 60 min*

    Export an incremental update bundle:

    ```bash theme={null}
    sudo zylon-cli export <new-version> --from <current-version>
    ```

    The `--from` flag creates a differential bundle containing only changes between versions, significantly reducing bundle size and transfer time.

    <Note>
      Differential bundles are typically 5-20 GB vs. 60-80 GB for full bundles.
    </Note>
  </Step>

  <Step title="Transfer Bundle to Offline Machine">
    Transfer the bundle file(s) using your secure method:

    **If you updated models:**

    ```bash theme={null}
    scp zylon-<new-version>-to-<old-version>-<os>-<arch>.tar user@offline-machine:/tmp/
    scp zylon-models-*.tar user@offline-machine:/tmp/
    ```

    **If no new models:**

    ```bash theme={null}
    scp zylon-<new-version>-to-<old-version>-<os>-<arch>.tar user@offline-machine:/tmp/
    ```

    **Alternative methods:**

    * USB drive
    * Internal file transfer system
    * Network share (if available)
  </Step>

  <Step title="On Offline Machine: Import New Models (If Applicable)">
    *Estimated time: 5 to 30 min (only if new models were transferred)*

    **Skip this step if you didn't transfer new AI models.**

    Import the new models:

    ```bash theme={null}
    cd /tmp
    sudo zylon-cli models import zylon-models-*.tar
    sudo zylon-cli models download --offline
    ```

    Verify models were installed successfully:

    ```bash theme={null}
    sudo zylon-cli models list --installed
    ```
  </Step>

  <Step title="On Offline Machine: Import Update">
    Import the update bundle:

    ```bash theme={null}
    cd /tmp
    sudo zylon-cli import zylon-<new-version>-to-<old-version>-<os>-<arch>.tar
    ```

    The import process:

    * Extracts container images for the new version
    * Updates system dependencies
    * Prepares upgrade artifacts

    <Warning>
      This may take 10-30 minutes. Don't interrupt the process.
    </Warning>

    Verify that import completed successfully by checking installed versions:

    ```bash theme={null}
    sudo zylon-cli list-versions --offline
    ```
  </Step>

  <Step title="On Offline Machine: Apply Update">
    *Estimated time: 15 to 60 min*

    Apply the update to your running Zylon instance:

    ```bash theme={null}
    sudo zylon-cli install <new-version> --airgap
    ```

    <Note>
      New AI models (if any) were already imported in a previous step, so no `--models` flag is needed here.
    </Note>
  </Step>
</Steps>

***

## Migrating to Airgap

If you have an existing Zylon installation (online or semi-airgap) and want to migrate it to a fully airgapped environment, follow this guide. This process preserves your data, configuration, and SSL certificates while transitioning to offline operation.

<Info>
  **Migration differs from fresh installation:**

  * Your existing configuration and data will be preserved
  * SSL certificates will be migrated
  * Organization and users already exist
</Info>

**Migration Prerequisites:**

* [ ] Existing Zylon installation (online or semi-airgap) with access
* [ ] Online machine with internet access for downloading migration bundles
* [ ] Method to transfer files (70-100 GB) between machines
* [ ] Target airgap machine with NO internet connection
* [ ] Root and SSH access to all machines involved

***

### Part A: Extract from Existing Zylon Machine

<Steps>
  <Step title="Extract Current Configuration">
    *Estimated time: 5 min*

    Copy the current Zylon configuration file:

    ```bash theme={null}
    # On existing Zylon machine
    sudo cp /etc/zylon/zylon-conf.yaml /tmp/zylon-conf-backup.yaml
    ```
  </Step>

  <Step title="Extract SSL Certificates">
    *Estimated time: 5 min*

    Extract the current SSL certificates from Kubernetes to avoid regeneration:

    ```bash theme={null}
    # Extract certificate from Kubernetes secret
    sudo k0s kubectl get secret zylon-tls -n zylon -o jsonpath='{.data.tls\.crt}' | base64 -d > /tmp/tls.crt
    sudo k0s kubectl get secret zylon-tls -n zylon -o jsonpath='{.data.tls\.key}' | base64 -d > /tmp/tls.key

    # Verify files were created
    ls -lh /tmp/tls.crt /tmp/tls.key
    ```

    <Note>
      If the certificate extraction fails, it means you're using Let's Encrypt auto-generation. In this case, you'll need to provide your own certificates or continue using Let's Encrypt on the airgap machine (not recommended for airgap environments).
    </Note>
  </Step>

  <Step title="Transfer Files to Online Machine">
    Transfer the configuration and certificates to your online machine:

    **SCP Example:**

    ```bash theme={null}
    # From existing Zylon machine to online machine
    scp /tmp/zylon-conf-backup.yaml user@online-machine:/tmp/
    scp /tmp/tls.crt user@online-machine:/tmp/
    scp /tmp/tls.key user@online-machine:/tmp/
    ```

    **Alternative methods:**

    * USB drive
    * Secure internal file transfer
    * Network share
  </Step>
</Steps>

***

### Part B: Prepare bundle on Online Machine

<Steps>
  <Step title="Install Zylon CLI">
    *Estimated time: 2 min*

    The Zylon CLI will speed up the time it takes to get everything ready, it will take care of installing drivers, updating Zylon and configuring the system.
    To install it, SSH into the machine where you want to install Zylon and run:

    ```bash theme={null}
    # ssh <user>@<host-ip>
    sudo curl -sL get.zylon.ai | sh
    ```

    Verify the installation:

    ```bash theme={null}
    sudo zylon-cli version
    ```

    <Note>
      Root access is required for CLI operations as it manages system-level dependencies and configurations.
    </Note>
  </Step>

  <Step title="Transfer Configuration File">
    *Estimated time: 2 min*

    Place the backed-up configuration in the correct location:

    ```bash theme={null}
    sudo mkdir -p /etc/zylon
    sudo cp /tmp/zylon-conf-backup.yaml /etc/zylon/zylon-conf.yaml
    ```
  </Step>

  <Step title="Reconfigure for Airgap">
    *Estimated time: 10 min*

    Run the configuration wizard to update settings for airgap deployment:

    ```bash theme={null}
    sudo zylon-cli config init
    ```

    The wizard will guide you through updating the following settings:

    **Potential Required Changes:**

    1. **Installation Type**: Change from your current type (online/semi-airgap) to **Airgap**

    2. **SSL Certificates**: The wizard will prompt for certificates in text format:

    * Paste the contents of `/tmp/tls.crt` when prompted for the certificate
    * Paste the contents of `/tmp/tls.key` when prompted for the private key

    <Accordion title="How to view Certificate Contents:">
      ```bash theme={null}
      # Display certificate (copy this output)
      cat /tmp/tls.crt

      # Display private key (copy this output)
      cat /tmp/tls.key
      ```
    </Accordion>

    <Warning>
      When pasting certificates into the wizard:

      * Include the full content including `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` headers
      * Maintain proper line breaks and formatting
      * Do not add extra spaces or characters
    </Warning>

    3. **License Information** (if changing channel):

       * License Email: Provided by Zylon team
       * License ID: Provided by Zylon team
       * License Data: Full license token provided by Zylon team

           <Warning>
             Ensure the license data is copied exactly as provided, preserving formatting and line breaks.
           </Warning>

    4. **Channel** (if applicable):
       * Change from `stable` to `X` (or as instructed by Zylon)

    5. **Review All Other Settings**: The wizard will display current values—confirm or update as needed

    **Verify Updated Configuration:**

    ```bash theme={null}
    sudo cat /etc/zylon/zylon-conf.yaml
    ```

    Confirm that everything is set correctly for AirGap operation.
  </Step>

  <Step title="Download Migration Bundle">
    *Estimated time: 15 min to 1 hour*

    Download the Zylon version bundle (without AI models, as they already exist):

    ```bash theme={null}
    sudo zylon-cli list-versions
    # Choose your target version
    sudo zylon-cli download <version> --airgap
    ```

    <Note>
      We're **not** including `--models` flag because:

      * Existing AI models from your current installation will be preserved
      * If you need to add new models, include them with `--models=model-a,model-b`. More info in fresh installation guide below.
    </Note>
  </Step>

  <Step title="Export Migration Bundle">
    *Estimated time: 15 to 60 min*

    Export the migration bundle:

    ```bash theme={null}
    sudo zylon-cli export <version>
    ```

    This creates `zylon-<version>-<os>-<arch>.tar` in your current directory.
  </Step>

  <Step title="Prepare Migration Package">
    *Estimated time: 5 min*

    Create a complete migration package with CLI tools and configuration:

    ```bash theme={null}
    sudo tar -czf zylon-migration.tar.gz \
      /usr/local/bin/zylon-cli \
      /usr/local/bin/zylon-forge-cli \
      /etc/zylon/zylon-conf.yaml
    ```
  </Step>

  <Step title="Transfer Files to Airgap Machine">
    Transfer the migration package to your airgap machine:

    **Files to transfer:**

    * `zylon-<version>-<os>-<arch>.tar` (main bundle)
    * `zylon-migration.tar.gz` (CLI and updated config)

    **SCP Example:**

    ```bash theme={null}
    scp zylon-<version>-<os>-<arch>.tar user@airgap-machine:/tmp/
    scp zylon-migration.tar.gz user@airgap-machine:/tmp/
    ```
  </Step>
</Steps>

***

### Part C: Migrate to Airgap on Offline Machine

<Steps>
  <Step title="Extract Migration Package">
    *Estimated time: 2 min*

    Extract the CLI tools and configuration:

    ```bash theme={null}
    cd /tmp
    sudo tar -xzf zylon-migration.tar.gz -C /
    sudo chmod +x /usr/local/bin/zylon-cli /usr/local/bin/zylon-forge-cli
    ```

    Verify extraction:

    ```bash theme={null}
    sudo zylon-cli version
    cat /etc/zylon/zylon-conf.yaml
    ```

    Should show:

    ```yaml theme={null}
    airgap:
      offlineInstall: true
      offlineOperation: true
    ```
  </Step>

  <Step title="Verify System Requirements">
    Ensure the airgap machine meets all requirements:

    ```bash theme={null}
    sudo zylon-cli preflight -v
    ```

    Address any issues before proceeding.
  </Step>

  <Step title="Import Migration Bundle">
    *Estimated time: 10 to 60 min*

    Import the Zylon bundle:

    ```bash theme={null}
    cd /tmp
    sudo zylon-cli import zylon-<version>-<os>-<arch>.tar
    ```

    This process:

    * Extracts all container images
    * Installs dependencies offline
    * Prepares the system for installation

    <Warning>
      Import can take 30+ minutes. Do not interrupt the process.
    </Warning>

    Verify import completion:

    ```bash theme={null}
    sudo zylon-cli list-versions --offline
    ```
  </Step>

  <Step title="Install Zylon in Airgap Mode">
    *Estimated time: 15 min to 1 hour*

    Install Zylon using the imported bundle:

    ```bash theme={null}
    sudo zylon-cli install <version> --airgap
    ```
  </Step>
</Steps>

***

## Next Steps

After completing the installation, consider the following next steps to optimize your Zylon deployment:

* [Configure AI Presets](/en/operator-manual/ai-presets) to optimize for your hardware
* [Configure Backups](/en/operator-manual/operations/backup) for data protection
* [Review User Manual](/en/user-manual/quick-start-guide) to get started
