diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index bf042f0..44fcd39 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -2,8 +2,6 @@ name: Test deployment on: pull_request: - branches: - - main # Review gh actions docs if you want to further define triggers, paths, etc # https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on diff --git a/blog/2025-02-27-releasing-version-12-and-a-roadmap.mdx b/blog/2025-02-27-releasing-version-12-and-a-roadmap.mdx index cc761bc..888fbc3 100644 --- a/blog/2025-02-27-releasing-version-12-and-a-roadmap.mdx +++ b/blog/2025-02-27-releasing-version-12-and-a-roadmap.mdx @@ -103,7 +103,7 @@ that are considered to be out of its scope even for the future. The report can be disabled by specifying `agama.ay_check=0` as a boot parameter. We also took the opportunity to update the corresponding information at the [AutoYaST compatibility -reference document](/docs/user/autoyast/reference). What is even better, we introduced some +reference document](/docs/user/unattended/autoyast/reference). What is even better, we introduced some mechanisms to generate such a document based on the same information used by Agama to generate the compatibility report during execution, so we can make sure the documentation is in sync with the actual implementation. diff --git a/blog/2025-04-08-agama-13.mdx b/blog/2025-04-08-agama-13.mdx index 8ac0632..253c370 100644 --- a/blog/2025-04-08-agama-13.mdx +++ b/blog/2025-04-08-agama-13.mdx @@ -140,7 +140,7 @@ automatically search for it in the same pre-defined locations used by AutoYaST. Agama expects a file named `autoinst.jsonnet`, `autoinst.json` or `autoinst.xml` (in that order) to be located on: -- The root of a file system named `OEMDRV`. +- The root of a file system with the label `OEMDRV`. - Or the root (`/`) of the installation environment. The first file found is used as the profile, starting the installation right away. diff --git a/docs/faq.md b/docs/faq.md index 3684243..c3c390e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -80,11 +80,11 @@ But there are also some caveats. Bear in mind that Agama is focused on the insta further configuration to other tools. Therefore it includes less features and there are some sections you can find in an AutoYaST profile that are ignored by Agama. -You can find further details in the [AutoYaST support section](/docs/user/autoyast). +You can find further details in the [AutoYaST support section](/docs/user/unattended/autoyast). ## Will Agama replace YaST as the main installer for SUSE Linux? -Although nothing is set in stone, that is the plan for SUSE Linux Enterprise Server 16. +Although nothing is set in stone, that is the plan for SUSE Linux Enterprise Server 16. ## Will Agama replace YaST as the main installer for openSUSE distributions? @@ -93,4 +93,3 @@ There are no concrete plans in that regard. The YaST Team works in close collaboration with several openSUSE contributors to make sure Agama can install openSUSE Tumbleweed, openSUSE MicroOS and the first prototypes of Leap 16.0. But there is no concrete roadmap for the adoption of Agama as an endorsed installer for those distributions. - diff --git a/docs/user/interactive/storage.md b/docs/user/interactive/storage.md index f130fda..685ea81 100644 --- a/docs/user/interactive/storage.md +++ b/docs/user/interactive/storage.md @@ -55,7 +55,7 @@ developed. Every change to any of the configuration options will result in an immediate re-calculation of the section that presents the result. As already mentioned, the configuration options are identical to the case of unattended installation (see detailed description at the [corresponding -section](../unattended/storage.md)), although the user interface presents more clearly the +section](../unattended/profile/storage)), although the user interface presents more clearly the relationship between those settings and the system being used for installation. ![Selecting a device for installation](/img/user/storage-device.png) @@ -67,7 +67,7 @@ storage configuration. For example, there is not support yet for representing RA If a given configuration is not manageable by the web interface, then the storage section shows a message explaining the situation and offers to reset to the default settings. Such an alert is always shown if the loaded configuration uses [the legacy AutoYaST -mode](../unattended/storage#unattended-installation-using-the-legacy-autoyast-mode). +mode](../unattended/profile/storage#unattended-installation-using-the-legacy-autoyast-mode). ::: There are several interactive elements allowing to control several aspects of the installation. diff --git a/docs/user/autoyast/index.md b/docs/user/unattended/autoyast/index.md similarity index 97% rename from docs/user/autoyast/index.md rename to docs/user/unattended/autoyast/index.md index 0767efc..5304298 100644 --- a/docs/user/autoyast/index.md +++ b/docs/user/unattended/autoyast/index.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- # AutoYaST support diff --git a/docs/user/autoyast/profiles.md b/docs/user/unattended/autoyast/profiles.md similarity index 84% rename from docs/user/autoyast/profiles.md rename to docs/user/unattended/autoyast/profiles.md index 10013d6..042668f 100644 --- a/docs/user/autoyast/profiles.md +++ b/docs/user/unattended/autoyast/profiles.md @@ -1,8 +1,8 @@ # Loading an AutoYaST profile The typical way of starting an unattended installation in Agama is by passing the URL of an AutoYaST -profile through the [`inst.auto`](../boot_options/index.md#boot-options) argument in the kernel's -command-line[^agama-profile-import]. For example: +profile through the [`inst.auto`](/docs/user/boot_options) argument in the kernel's +command-line[^agama-config-load]. For example: ```text inst.auto=http://example.net/agama/tumbleweed.xml @@ -27,4 +27,4 @@ this pre-processing, it supports handling of [dynamic profiles][dynamic-profiles [ask-list-runner]: https://github.com/yast/yast-autoinstallation/blob/c2dc34560df4ba890688a0c84caec94cc2718f14/src/lib/autoinstall/ask/runner.rb#L50 [ask-list-dialog]: https://github.com/yast/yast-autoinstallation/blob/c2dc34560df4ba890688a0c84caec94cc2718f14/src/lib/autoinstall/ask/dialog.rb#L23 -[^agama-profile-import]: You can use the `agama profile import` command, but that's out of the scope of this document. +[^agama-config-load]: You can use the `agama config load` command, but that's out of the scope of this document. Check the [Working with profiles](/docs/user/unattended/working-with-profiles) section. diff --git a/docs/user/autoyast/reference.md b/docs/user/unattended/autoyast/reference.md similarity index 100% rename from docs/user/autoyast/reference.md rename to docs/user/unattended/autoyast/reference.md diff --git a/docs/user/unattended/dynamic.md b/docs/user/unattended/dynamic.md new file mode 100644 index 0000000..c14adf0 --- /dev/null +++ b/docs/user/unattended/dynamic.md @@ -0,0 +1,70 @@ +--- +sidebar_position: 3 +--- + +# Writing a dynamic profile + +It is not unusual that you need to write a profile that adapts dynamically to the underlying system. +For instance, you might want Agama to take some decisions depending on the hardware of the system +you are installing. + +Fortunately, Jsonnet can work as a templating language and it offers many structures that allow +generating data. For that reason, Agama injects the hardware information that you can process using +the powerful [Jsonnet standard library](https://jsonnet.org/ref/stdlib.html). + +You can access to the hardware information by importing the `hw.libsonnet` library, as you can see +in the example below. + +```jsonnet +// There are included also helpers to search this hardware tree. To see helpers check +// "/usr/share/agama-cli/agama.libsonnet" +local agama = import 'hw.libsonnet'; + +// Find the biggest disk which is suitable for installing the system. +local findBiggestDisk(disks) = + local sizedDisks = std.filter(function(d) std.objectHas(d, 'size'), disks); + local sorted = std.sort(sizedDisks, function(x) -x.size); + sorted[0].logicalname; + +// Find how much physical memory system has. +local memory = agama.findByID(agama.lshw, 'memory').size; + +{ + product: { + id: if memory < 8000000000 then 'MicroOS' else 'Tumbleweed', + }, + user: { + fullName: 'Jane Doe', + userName: 'jane.doe', + password: '123456', + }, + root: { + password: 'nots3cr3t', + sshPublicKey: '...', + }, + storage: { + boot: { + configure: true, + device: 'boot', + }, + drives: [ + { + search: findBiggestDisk(agama.selectByClass(agama.lshw, 'disk')), + alias: 'boot', + }, + ], + }, +} +``` + +Agama ships a few helpers to make it easier to search for the information you need from the hardware +tree. See +[agama.libsonnet](https://github.com/agama-project/agama/blob/master/rust/share/agama.libsonnet) for +further details. + +:::tip Getting hardware information + +You can inspect the available data by installing the `lshw` package and running the following +command: `lshw -json`. + +::: diff --git a/docs/user/unattended/index.md b/docs/user/unattended/index.md index 439bd2e..857828e 100644 --- a/docs/user/unattended/index.md +++ b/docs/user/unattended/index.md @@ -4,118 +4,33 @@ sidebar_position: 2 # Unattended installation -One of the main use cases of Agama is unatteded installation. The user provides a file, known as a -"profile", that describes how the system should look like (partitioning, networking, software -selection, etc.) and Agama takes care of installing the system according to such a description. This -approach might sound familiar to AutoYaST users. +Agama is able to install a system without user interaction. The user provides a definition of the +system, known as a "profile", that describes how the system should look like (partitioning, +networking, software selection, etc.) and Agama takes care of installing the system. This approach +might sound familiar to AutoYaST users. -Although Agama defines its own [profile -format](https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/profile.schema.json), it -is able to partially handle AutoYaST profiles. Please, check the [AutoYaST support -section](./autoyast) for further information. +Agama uses [Jsonnet](https://jsonnet.org/), a superset of JSON, which allows writing readable and +concise profiles. The example below instructs Agama to install _Tumbleweed_ and create a first user +so you can log in. -## Profile format - -A profile defines which options to use during installation: which product to install, localization -settings, partitioning schema, etc. Although it sounds similar to AutoYaST, there are some essential -differences: - -- Profiles are written in [Jsonnet](https://jsonnet.org/) instead of XML. Jsonnet is a superset of - JSON (so you can use just plain JSON), which allows for writing more readable and concise - profiles. -- You can take advantage of Jsonnet to build dynamic profiles, without having to rely on _rules_ or - _Embedded Ruby (ERB)_. Agama injects hardware information that can be processed using the [Jsonnet - standard library](https://jsonnet.org/ref/stdlib.html). - -You can check the [Tumbleweed installation -profile](https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/examples/profile_tw.json) -included in the repository to get an impression of how a profile looks like. - -### A minimal example - -```json +```jsonnet { - "localization": { - "language": "en_US.UTF-8" - }, - "product": { - "id": "Tumbleweed" + product: { + id: "Tumbleweed" }, - "user": { - "fullName": "Jane Doe", - "userName": "jane.doe", - "password": "123456" + user: { + fullName: "Jane Doe", + userName: "jane.doe", + password: "123456" } } ``` -### Supported configuration values - -Check the [JSON -Schema](https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/profile.schema.json) to -learn about the supported elements. - -Some areas are relatively complex and just looking at the schema may not be enough to fully -understand how they work. That is definitely the case of the storage setup, that is described in its -own [separate section](./storage.md). - -### Dynamic profiles - -The profile can be adapted at runtime depending on the system where the auto-installation is -running. For such use cases, Agama injects the hardware information into the profile to be processed -using Jsonnet. - -Please, check [the example -profile](https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/examples/profile.jsonnet) -for further information. - -:::tip Getting hardware information -You can inspect the available data by installing the `lshw` package and running the following -command: `lshw -json`. -::: - -### Validating and evaluating a profile - -Agama includes a handy command-line interface available in the `agama` package. Among many other -things, it allows downloading, validating and evaluating profiles. For instance, we could check the -result of the previous profile by running the following command: - -```console -sudo agama profile evaluate my-profile.jsonnet -``` - -:::warning Use `sudo` -You need to use `sudo` to access the hardware information. -::: - -Do you want to check whether your profile is valid? `agama` have you covered. Bear in mind that you -can only validate JSON profiles (a Jsonnet profile must be evaluated first). - -```console -agama profile validate my-profile.json -``` - -### Generating a configuration file - -Writing the profile by hand is relatively easy. However, you might want to ask Agama to do it for -you. You can boot the installation, use the web interface to tweak all the values and, from the -terminal, generate the file by running the following command: - -```console -sudo agama config show > profile.json -``` - -## Starting the installation - -To start an unattended installation process, you need to tell Agama where to find the profile. When -using the Live ISO, you must use the `inst.auto` boot option. Please, check the -[boot options](../boot_options/index.md) for further information. - -If you do not specify any profile, Agama will automatically search for it in a few predefined -locations. Agama expects a file named `autoinst.jsonnet`, `autoinst.json` or `autoinst.xml` (in that -order) to be located on: - -- The root of a file system named `OEMDRV`. -- Or the root (`/`) of the installation environment. +It is possible to define the storage layout, which software to install, the network configuration, +etc. Check the [profile format](./unattended/profile) section to learn more. Once you have your +first profile, you might want to learn how to +[start the installation](./unattended/working-with-profiles#starting-the-installation). -The first file found is used as the profile, starting the installation right away. +Finally, it is worth to mention that although Agama defines its own profile format, it is able to +partially handle AutoYaST profiles. Please, check the +[AutoYaST support section](./unattended/autoyast) for further information. diff --git a/docs/user/unattended/profile/bootloader.md b/docs/user/unattended/profile/bootloader.md new file mode 100644 index 0000000..a5c942a --- /dev/null +++ b/docs/user/unattended/profile/bootloader.md @@ -0,0 +1,25 @@ +--- +sidebar_position: 11 +--- + +# Bootloader configuration + +Agama offers a reduced set of settings to change the bootloader configuration, although it is able +to set it up correctly in many situations and architectures. + +These options are defined in the `bootloader` section. + +- `stopOnBootMenu`: stop on the menu instead of booting the system automatically. +- `timeout`: specify how many seconds the bootloader should wait on the menu before booting the + default entry. Unlike AutoYaST, the timeout should be a positive number. If you want the + bootloader to stop indefinitely, just set `stopOnBootMenu` to `true`. +- `extraKernelParams`: additional kernel parameters. + +``` +{ + bootloader: { + stopOnBootMenu: true, + extraKernelParams: "processor.max_cstate=1" + } +} +``` diff --git a/docs/user/unattended/profile/files.md b/docs/user/unattended/profile/files.md new file mode 100644 index 0000000..d90edf7 --- /dev/null +++ b/docs/user/unattended/profile/files.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 7 +--- + +# Copying files + +In many cases, you might need to copy some files to the installed system. This feature is especially +useful when you want to tweak your system configuration (for instance, dropping a file to +`/etc/sysctl.d`), but it can be used in other situations too. + +## File properties + +Agama provides a `files` key where you can define the source (the content or an URL to fetch the +file from), the permissions, the owner and the destination of the file. + +- `content`: the content of the file. +- `url`: alternatively to the `content`, you can define a URL to fetch the file from. The files are + downloaded and written to the disk at the end of the installation. In addition to the + [supported URLs](../../urls) you can use a URL relative to the profile (e.g., "/motd"). +- `destination`: the location of the file in the installed system. +- `permissions`: a string describing the file permissions in numeric mode (e.g.: `"0640"`). By + default it is set to `"0644"`). +- `user`: user owner of the file (`"root"` by default). +- `group`: group owner of the file (`"root"` by default). + +:::note Working with relative URLs + +If you use the `inst.auto` boot option to specify the URL of the profile, any relative URL will use +the URL of the profile as its base. + +However, loading the profile using the `agama config load` will not work in the same way. +Check the [Manually loading a profile](../working-with-profiles#manually-loading-a-profile) section +for further information. + +::: + +## Example + +The example below adds a welcome message to the system and registers a new user by deploying a file +in `/etc/issue.d`: + +```jsonnet +{ + files: [ + { + url: "/motd", + destination: "/etc/issue.d/welcome.issue", + permissions: "0644", + }, + { + destination: "/etc/sysusers.d/myapp.conf", + content: ||| + # Type Name ID GECOS Home + u myapp - "My Application" /var/lib/myapp + ||| + } + ] +} +``` + +## Binary files + +Although the intention is to work with text files, Agama does not impose any limitation of the kind +of files you can deploy. So using a URL to a binary file should work too. + +:::note Generating a file using a script + +Unlike AutoYaST, Agama does not allow to generate the file using an script. For that use case, you +might use the [scripts](./scripts) section. + +::: diff --git a/docs/user/unattended/profile/hostname.md b/docs/user/unattended/profile/hostname.md new file mode 100644 index 0000000..ca3f86b --- /dev/null +++ b/docs/user/unattended/profile/hostname.md @@ -0,0 +1,23 @@ +--- +sidebar_position: 10 +--- + +# Hostname + +Traditionally, the hostname is considered part of the network configuration. However, although +closely related, Agama features a separate section for it. + +At this point, it is possible to set the `static` and the `transient` hostnames. + +```jsonnet +{ + hostname: { + "static": "myhost.example.lan", + "transient": "installation.lan" + } +} +``` + +To learn the difference between both hostnames, make sure to check the +[hostnamectl documentation](https://manpages.opensuse.org/Tumbleweed/systemd/hostnamectl.1.en.html). +If you are in doubt, you most probably want to set (if any) the `static` hostname. diff --git a/docs/user/unattended/profile/index.md b/docs/user/unattended/profile/index.md new file mode 100644 index 0000000..ce9f9f8 --- /dev/null +++ b/docs/user/unattended/profile/index.md @@ -0,0 +1,38 @@ +--- +sidebar_position: 2 +--- + +# Profile format + +A profile defines which options to use during installation: which product to install, localization +settings, partitioning schema, etc. Agama profiles are written in [Jsonnet](https://jsonnet.org/) +which is a superset of JSON. It brings a few advantages: + +- More relaxed syntax which makes it easier to read and write. +- Support for comments and multi-line values. +- Constructs for generating dynamic content. + +Let's have a look to an example to get an idea. The following profile is rather small: it just +instructs Agama to install Tumbleweed and defines a first user so you can log in. + +```jsonnet +{ + product: { + id: "Tumbleweed" + }, + user: { + fullName: "Jane Doe", + userName: "jane.doe", + password: "123456" + } +} +``` + +Reading throught the following sections you can find the supported configuration values. The +documentation includes several examples to make it easier to write your own profiles. Alternatively, +you can check the +[JSON Schema](https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/profile.schema.json) +to learn about the supported elements. + +If you are interested in the dynamic bits, you can check the [Writing a dynamic profile](./dynamic) +section. diff --git a/docs/user/unattended/profile/localization.md b/docs/user/unattended/profile/localization.md new file mode 100644 index 0000000..08d4f9d --- /dev/null +++ b/docs/user/unattended/profile/localization.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 9 +--- + +# Localization + +The `localization` settings allows to specify the locale, the keyboard layout and the timezone of +the system to install. + +It supports the following elements: + +- `language`: corresponds to the system's locale. You can find a list of locales using the + `localectl list-locales` command. +- `keyboard`: keyboard layout. You can find a list of layouts typing `localectl list-keymaps`. Both + formats, using dashes or parenthesis, are supported: `us(dvorak)` or `us-dvorak`. +- `timezone`: timezone identifier. + +```jsonnet +{ + localization: { + language: "de_DE.UTF-8", + keyboard: "de", + timezone: "Europe/Berlin" + } +} +``` diff --git a/docs/user/unattended/profile/network.md b/docs/user/unattended/profile/network.md new file mode 100644 index 0000000..25deac3 --- /dev/null +++ b/docs/user/unattended/profile/network.md @@ -0,0 +1,180 @@ +--- +sidebar_position: 4 +--- + +# Network configuration + +Together with the storage set up, the network configuration is probably the most complex area. Agama +needs to cover many different requirements that, in some cases, conflict with each other. + +To set up the network, you can: + +- Specify the network configuration at boot time, so it is set up even before Agama starts. +- Define the configuration as part of the Agama profile. + +But, in some cases, you might be also want to combine both approaches. A typical scenario is when +you do not have a DHCP server and you need to set up the network so Agama can fetch the +configuration. + +The rest of this section explains how to configure the network using an Agama profile. For the boot +options, please check the [boot options section](/docs/user/boot_options). + +## Defining network connections + +The main concept of the network configuration is the _connection_. The `network` section includes a +list of `connections` where you can define as many as needed. + +```jsonnet +{ + network: { + connections: [ + { + id: "Ethernet device 1", + method4: "auto", + }, + { + id: "Wireless device 1", + method4: "auto", + wireless: { + ssid: "HOME_NETWORK", + password: "secret", + security: "wpa-psk", + mode: "infrastructure" + } + } + ] + } +} +``` + +If you are familiar with _[NetworkManager][NM]_, the connection concept will not be new for you. + +[NM]: https://www.networkmanager.dev/docs/ + +For each type of connection, you might need a different set of fields. However, there are many of +them that are common to any type of connection. Those fields include the connection identifier, the +IPv4/IPv6 configuration, some device parameters, etc. + +- `id`: connection identifier. +- `method4` and `method6`: IPv4 and IPV6 configuration method. Possible values are `auto` (usually + DHCP), `manual`, `link-local` and `disabled` (default). +- `interface`: the name of the network interface to bound to this connection. If it is not + specified, NetworkManager will select one. +- `macAddress`: MAC address to asign. It can be a MAC address or one of the following values: + `preserve`, `permanent`, `random` or `stable`. +- `mtu`: connection MTU. +- `gateway4` and `gateway6`: gateway address for IPv4 and IPv6. +- `addresses`: IP addresses. They can be IPv4 and/or IPv6. +- `nameservers`: name servers IP addresses (IPv4 and/or IPV6). +- `dnsSearchlist`: DNS domains to search. +- `ignoreAutoDns`: whether DNS options provided via DHCP are ignored or not. +- `status`: the wanted status for the connection. It can be `up`, `down`, or `removed`. +- `autoconnect`: whether the connection should be automatically activated. +- `match`: define a criteria to select the device to apply the connection to. + +These are the common fields to any kind of connection. Now, if you want to set up a bridge, you need +to add a `bridge` section; for a Wi-Fi connection, you need a `wireless` section; and so on. + +### Wi-Fi networks + +To connect to a Wi-Fi network, you need to include a `wireless` section in the connection. It +supports the following fields: + +- `ssid`: network SSID. +- `security`: security method/key management. Possible values are `none` (default), `owe`, + `ieee8021x`, `wpa-psk`, `sae`, `wpa-eap` and `wpa-eap-suite-b192`. +- `password`: password to connect to the network. +- `mode`: wireless mode. Possible values are: `infrastructure` (default), `adhoc`, `mesh` and `ap`. + +```jsonnet +{ + network: { + connections: [ + { + id: "Wireless device 1", + method4: "auto", + method6: "disabled", + interface: "wlan0", + addresses: [ + "192.168.122.100/24" + ], + wireless: { + ssid: "HOME_NETWORK", + password: "secret", + security: "wpa-psk", + mode: "infrastructure" + } + } + ] + } +} +``` + +### Bridges + +To create a bridge you need to include a `bridge` section which, among other optional settings, +includes the list of ports to connect. + +```jsonnet +{ + network: { + connections: [ + { + id: "Bridge #0", + interface: "br0", + bridge: { + ports: ["eth0", "eth1"] + } + } + ] + } +} +``` + +The `interface` element specifies the device name for the bridge while the `id` is the connection +name. + +About the `bridge` section, it can include: + +- `ports`: a list of interfaces or connections IDs which will be part of the bridge. +- `stp`: whether the + [Spanning Tree Protocol (STP)](https://es.wikipedia.org/wiki/Spanning_Tree_Protocol) should be + enabled. +- `forwardDelay`: STP forward delay, in seconds. +- `priority`: STP priority. It is represented by a number equal or greater than zero. Lower values + are "better". +- `maxAge`: STP maximum message, in seconds. +- `helloTime`: STP hello time, in seconds. + +### Bonding + +To create a bond you need to include a `bond` section which, among other optional settings, includes +the list of ports to connect. + +```jsonnet +{ + network: { + connections: [ + { + id: "Bond #0", + interface: "bond0", + bond: { + ports: ["eth0", "eth1"], + mode: "active-backup", + options: "primary=eth1" + } + } + ] + } +} +``` + +The `interface` element specifies the device name for the bonding while the `id` is the connection +name. + +The `bond` section can contain: + +- `ports`: devices to be included in the bond. +- `mode`: bond mode. Possible values: `balance-rr` (default), `active-backup`, `balance-xor`, + `broadcast`, `802.3ad`, `balance-tlb`, `balance-alb`. +- `options`: additional options. diff --git a/docs/user/unattended/profile/product.md b/docs/user/unattended/profile/product.md new file mode 100644 index 0000000..f460370 --- /dev/null +++ b/docs/user/unattended/profile/product.md @@ -0,0 +1,106 @@ +--- +sidebar_position: 1 +--- + +# Products and registration + +The `product` section is a mandatory. It specifies which product (distribution) you want to install. +For the SUSE Linux Enteprise family of products, it allows registering the system, activating +extensions, etc. + +If you want to select patterns and packages for installation, check the [software](./software) +section. + +## Selecting the product + +To select the product, you need to specify its identifier (ID). + +```jsonnet +{ + product: { + id: "Tumbleweed" + } +} +``` + +Here is the list of known products: + +- `SLES`: SUSE Linux Enteprise Server. +- `SLES_SAP`: SUSE Linux Enterprise Server for SAP Applications. +- `Tumbleweed`: Tumbleweed. +- `Slowroll`: Slowroll. +- `Leap_16.0`: Leap 16.0 +- `MicroOS`: openSUSE Micro OS. + +Beware that which products are available depend on the installation image you are using. + +## Registering a product + +:::note Only for SUSE Linux Enterprise + +Product registration is only available for the SUSE Linux Enteprise family of products. + +::: + +If you want to register a product with the SUSE Customer Center, you need to specify the +_registration code_ and, optionally, an _e-mail address_. + +```jsonnet +{ + product: { + id: "SLES", + registrationCode: "MY-REGISTRATION-CODE", + registrationEmail: "info@example.net" + } +} +``` + +### Enabling add-ons + +You can use the `addons` section if you want to activate an add-on/extension. For each of them, you +can specify: + +- `id`: add-on identifier. This field is mandatory. +- `version`: add-on version. In the very rare case that there are more than one version of the same + add-on. +- `registrationCode`: needed for those add-ons that require a separate registration code. + +```jsonnet +{ + product: { + id: "SLES", + registrationCode: "MY-REGISTRATION-CODE", + registrationEmail: "info@example.net", + addons: [ + { + id: "SLES-HA" + } + ] + } +} +``` + +### Using a custom registration server + +In case you want to use a different registration server, for instance when using the RMT, you need +to specify its URL via the `registrationUrl` key. + +```jsonnet +{ + product: { + id: "SLES", + registrationCode: "MY-REGISTRATION-CODE", + registrationUrl: "http://rmt.example.lan" + } +} +``` + +If you are using HTTPS, you might be interested in the +[sslCertificates list](./security#list-of-trusted-certificates). + +:::note Using a boot argument + +Alternatively, you can specify the registration URL setting the +[`register_url` boot argument](/docs/user/boot_options). + +::: diff --git a/docs/user/unattended/scripts.md b/docs/user/unattended/profile/scripts.md similarity index 77% rename from docs/user/unattended/scripts.md rename to docs/user/unattended/profile/scripts.md index a33d6c5..ad26f4c 100644 --- a/docs/user/unattended/scripts.md +++ b/docs/user/unattended/profile/scripts.md @@ -1,10 +1,10 @@ --- -sidebar_position: 3 +sidebar_position: 6 --- # Running scripts -Agama allows execute scripts at the following points of the installation process: +Agama allows to execute scripts at the following points of the installation process: - Previous to any installation work (pre-installation scripts). - After the system is installed (post-installation scripts). @@ -12,11 +12,6 @@ Agama allows execute scripts at the following points of the installation process This section describes how to specify a script and goes through some use-cases. -:::note -You can compare Agama scripts to the AutoYaST ones in the [scripts section](../autoyast/reference.md#scripts) -of the backward compatibility documentation. -::: - ## Scripts definition User scripts are defined in the `scripts` section of the Agama profile. There is a key for each of @@ -54,7 +49,8 @@ the three scripts types, and each key can contain a list of scripts. } ``` -:::note +:::note Better use Jsonnet for profiles containing scripts + JSON does not allow multiline strings, so it might be better to use Jsonnet instead. However, you need to pay attention to the indentation, because it matters. @@ -77,8 +73,20 @@ All scripts share the same elements: - `name`: a name to identify the script. It makes it easier to find the script logs. - `content`: the content of the script. It is important to include the _shebang_ as the first line of the script. -- `url`: alternatively to the `content`, you can define a URL to download the script. The scripts - are downloaded and written to the disk after the profile is imported. +- `url`: alternatively to the `content`, you can define a URL to fetch the file from. The scripts + are downloaded and written to the disk when loading the profile. In addition to the + [supported URLs](../../urls) you can use a URL relative to the profile (e.g., "/my-script.sh"). + +:::note Working with relative URLs + +If you use the `inst.auto` boot option to specify the URL of the profile, any relative URL will use +the URL of the profile as its base. + +However, loading the profile using the `agama config load` will not work in the same way. Check the +[Manually loading a profile](../working-with-profiles#manually-loading-a-profile) section for +further information. + +::: Check the following sections to find out the differences between the script types. @@ -87,17 +95,18 @@ Check the following sections to find out the differences between the script type The pre-installation scripts are executed before the system is analyzed. They are useful for enabling hardware, tweaking the installation media, etc. -:::warning +:::warning Pre-installation scripts cannot modify the current profile + Unlike AutoYaST, the pre-installation scripts cannot modify the current profile. We recommend using -Jsonnet to build a dynamic profile. If you need something that behaves exactly like AutoYaST, you can -still use an AutoYaST profile with its own pre-scripts section. +Jsonnet to build a dynamic profile. If you need something that behaves exactly like AutoYaST, you +can still use an AutoYaST profile with its own pre-scripts section. + ::: ## Post-partitioning scripts -The post-partitioning scripts are executed during the installation, after the storage is -set up. A typical use case is to create configuration files that can modify the behavior of -the RPM scripts. +The post-partitioning scripts are executed during the installation, after the storage is set up. A +typical use case is to create configuration files that can modify the behavior of the RPM scripts. ## Post-installation scripts @@ -108,8 +117,8 @@ scripts have an additional option, `chroot`, that determines _where_ to run: - On the installation media (`chroot` is set to `false`), which is the behavior by default. You can find the installed system mounted at `/mnt`. - On the installed system (`chroot` is set to `true`). Beware that systemd is not running on the - installed system. For that reason, some commands might not work. If that's a problem, check the init - scripts. + installed system. For that reason, some commands might not work. If that's a problem, check the + init scripts. ## Init scripts diff --git a/docs/user/unattended/profile/security.md b/docs/user/unattended/profile/security.md new file mode 100644 index 0000000..d3d77a4 --- /dev/null +++ b/docs/user/unattended/profile/security.md @@ -0,0 +1,32 @@ +--- +sidebar_position: 8 +--- + +# Security + +The `security` section is expected to contain a set of options to configure security-related aspects +of the system (e.g., enabling remote access). However, at this time, it just allows to define a +collections of SSL certificates to trust. + +## List of trusted certificates + +It is not unusual to install the system using your own infrastructure. For instance, you might want +to use a set of mirrored repositories instead of the original ones. + +For those cases, Agama allows to define a list of SSL certificates to trust. The list should contain +the _fingerprint_ and the _algorithm_ of each certificate. + +```jsonnet +{ + security: { + sslCertificates: [ + { + fingerprint: "C0:40:C7:2F:33:5E:2A:56:99:97:C9:DA:6B:F8:74:C1:96:F8:BE:70:3F:4F:D6:2B:7E:CD:2F:07:36:2D:9F:F4", + algorithm: "SHA256" + } + ] + } +} +``` + +The known values for the `algorithm` are `SHA1` and `SHA256`. diff --git a/docs/user/unattended/profile/software.md b/docs/user/unattended/profile/software.md new file mode 100644 index 0000000..8fcfc23 --- /dev/null +++ b/docs/user/unattended/profile/software.md @@ -0,0 +1,53 @@ +--- +sidebar_position: 2 +--- + +# Additional software + +Depending on the [product you are installing](./product), Agama will select a set of repositories, +patterns and packages to install. However, it is possible to add your own list of repositories, +patterns and packages using the `software` section. + +This section supports three keys: + +- `patterns`: list of patterns to install (e.g., `gnome`, `kde`, `fips`, etc.). You can find a list + of patterns for your distribution using `zypper se --type pattern`. +- `packages`: list of packages to install (e.g., `neovim`). +- `extraRepositories`: list of additional repositories that will be used as installation source. See + the [User-defined repositories](#user-defined-repositories) for further information. + +```jsonnet +{ + software: { + patterns: ["gnome", "office"], + packages: ["neovim", "emacs"], + extraRepositories: [ + { + alias: "games", + url: "https://download.opensuse.org/repositories/games/openSUSE_Tumbleweed/", + gpgFingerprints: ["AEF1 EE83 0A27 90AB ABC2 CDA2 8F91 B0E6 C862 B42C"] + } + ] + } +} +``` + +## User-defined repositories + +The `software` section allows you to define custom repositories using a list under the +`extraRepositories` key. Each repository in the list can have the following properties: + +- `alias`: A unique identifier for the repository. Mandatory property. +- `url`: The repository's URL, recognized by `libzypp`. Mandatory property. +- `priority`: Sets the priority for using this repository. A lower number means higher precedence. + If you don't specify this, it'll use the same default priority as other repositories. +- `name` (string): A user-friendly name for the repository. If omitted, it defaults to the `alias`. +- `productDir`: A path to a specific product related to the URL. This is mainly used for + multi-product media and isn't used by default. +- `enabled`: Controls whether the repository is active. This is handy for pre-defining repositories + you plan to enable later. By default, repositories are enabled. +- `allowUnsigned`: If set to `true`, the repository will be accepted even if it lacks a GPG + signature. This can be useful for your own repositories. It's not set by default. +- `gpgFingerprints`: A list of accepted GPG fingerprints for the repository. This is helpful if the + repository is signed by a GPG key not included in your installation medium. This list is empty by + default. diff --git a/docs/user/unattended/storage.md b/docs/user/unattended/profile/storage.md similarity index 99% rename from docs/user/unattended/storage.md rename to docs/user/unattended/profile/storage.md index a7820e4..05a806f 100644 --- a/docs/user/unattended/storage.md +++ b/docs/user/unattended/profile/storage.md @@ -5,7 +5,7 @@ sidebar_position: 1 # Storage configuration The general concepts regarding configuration of storage devices with Agama are exposed at the -[corresponding subsection](../interactive/storage.md) of the interactive installation documentation. +[corresponding subsection](../../interactive/storage.md) of the interactive installation documentation. It is recommended to read that section before diving into the details below. ## Unattended installation using the legacy AutoYaST mode diff --git a/docs/user/unattended/users.md b/docs/user/unattended/profile/users.md similarity index 81% rename from docs/user/unattended/users.md rename to docs/user/unattended/profile/users.md index de9603c..721219e 100644 --- a/docs/user/unattended/users.md +++ b/docs/user/unattended/profile/users.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 5 --- # Users and authentication @@ -14,16 +14,16 @@ For a successful installation, one of the following conditions must be met: - A password or an SSH public key is defined for the `root` user. - A first user is defined. -## `root` +## `root` user The `root` section allows to specify an authentication method for the `root` user. -```json +```jsonnet { - "root": { - "sshPublicKey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPj/J1N38v/7Gbxz5A6jiSBhLbUwrJOVlBxDQhuW8tvg user@example.net", - "hashedPassword": true, - "password": "$y$j9T$qGMrxRmEHUV3kCXQAywcP1$g4n4.O2tUf2Dq9CJTohTb4/HJ9Wdzr2Z33MD8srkPV1" + root: { + sshPublicKey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPj/J1N38v/7Gbxz5A6jiSBhLbUwrJOVlBxDQhuW8tvg user@example.net", + hashedPassword: true, + password: "$y$j9T$qGMrxRmEHUV3kCXQAywcP1$g4n4.O2tUf2Dq9CJTohTb4/HJ9Wdzr2Z33MD8srkPV1" } } ``` @@ -34,17 +34,17 @@ The following fields are supported: - `hashedPassword`: whether the `password` is hashed (`true`) or not (`false` or undefined). - `sshPublicKey`: SSH public key to be copied to the `/root/.ssh/authorized_keys` file. -## `user` +## First user The `user` section defines a first user: -```json +```jsonnet { - "user": { - "fullName": "Jane Doe", - "userName": "jane.doe", - "hashedPassword": false, - "password": "123456" + user: { + fullName: "Jane Doe", + userName: "jane.doe", + hashedPassword: false, + password: "123456" } } ``` @@ -67,8 +67,10 @@ Make sure the selected hashing method is supported by the target system, differe support different set of methods. :::warning + Do not use any DES or MD5 based algorithms, these are considered insecure. Check `man 5 crypt` manual page for details about the hashing methods and their strength. + ::: Alternatively you can use the `openssl passwd -6` command. This generates a SHA-512 password hash, diff --git a/docs/user/unattended/working-with-profiles.md b/docs/user/unattended/working-with-profiles.md new file mode 100644 index 0000000..8d749be --- /dev/null +++ b/docs/user/unattended/working-with-profiles.md @@ -0,0 +1,112 @@ +--- +sidebar_position: 1 +--- + +# Working with profiles + +To start an unattended installation, you just need to tell Agama where to find the profile, usually +through the `inst.auto` boot option. In an ideal world, Agama should get the profile and perform the +installation without your intervention. + +However, getting your profile right is not always easy. For that reason, it might be interesting to +learn how to work with profiles using [Agama's commad-line interface](../cli). This tool is a +valuable help when you are writing or debugging your profile, and it allows validating, loading and +exporting a profile from a running Agama instance. + +## Starting the installation + +Before jumping into the usage of the command-line interface, let's have a look at the regular way of +starting the unattended installation. To tell Agama where to find the profile, you usually set the +`inst.auto` [boot option](../boot_options). You can use any of the +[URLs that Agama supports](../urls). + +If you do not specify any profile, Agama will automatically search for it in a few predefined +locations. Agama expects a file named `autoinst.jsonnet`, `autoinst.json` or `autoinst.xml` (in that +order) to be located on: + +- The root of a file system named `OEMDRV`. +- Or the root (`/`) of the installation environment. + +The first file found is used as the profile, starting the installation right away. If no profile is +found, Agama will fall back to the interactive installation. + +Keep reading if you want to learn more about how profiles are processed. + +## Manually loading a profile + +An Agama profile is written in Jsonnet, which is a superset of JSON. It means that any valid JSON +file is a valid Jsonnet file too. + +However, a profile (either Jsonnet or JSON) should be converted to plain JSON before it is processed +by Agama internals. For that reason, we might consider that loading a profile is a three steps +process: + +1. Fetch the profile from the given URL. +2. Evaluate the Jsonnet code to generate the final JSON file. If you are using + [files](./profile/files) or [scripts](./profile/scripts), any relative URL will be resolved in + this stage. It will use the URL of the profile as the base URL. +3. Load the JSON file into the Agama service. + +These steps are handled by the `agama config generate` (steps 1 and 2) and `agama config load` +(step 3) subcommands. + +```console +$ agama config generate http://example.lan/agama.jsonnet > agama.json +$ agama config load < agama.json +``` + +Or if you prefer, you can use this one-liner: + +``` +$ agama config generate http://example.lan/agama.jsonnet | agama config load +``` + +:::tip `agama config load` does not start the installation + +The `agama config load` just loads the configuration but it does not start the installation. You can +use the web user interface to check that everything looks as you expect. If you want to start the +installation from the command-line, you can issue the `agama install` command. + +::: + +If you are using relative URLs (for instance, within the [files](./profile/files) or the +[scripts](./profile/scripts) section), the `agama config load` might not work as you expect. As +`agama config load` only receives a piece of JSON, it does not know which is the base URL and it +will use, as a fallback, the path to the working directory (the one where you are executing the +command from). For that reason, it is usually a good idea to pre-process the profile using the +`agama config generate` command. + +## Validating a profile + +You can validate a JSON profile using the command-line tool. + +```console +$ agama config validate my-profile.json +``` + +Bear in mind that you can only validate JSON profiles, not Jsonnet ones. So if you have a Jsonnet +file, you need to convert it to JSON using the `agama config generate` subcommand. + +```console +$ agama config generate my-profile.jsonnet > my-profile.json +$ agama config validate my-profile.json +``` + +:::note Automatic validation + +All of the `agama config` subcommands validate the profile automatically. + +::: + +### Exporting a profile + +Writing the profile by hand is relatively easy. However, you might want to ask Agama to do it for +you. You can boot the installation, use the web interface to tweak all the values and, from the +terminal, generate the file by running the following command: + +```console +agama config show > profile.json +``` + +Bear in mind that using `agama config show` you might discover some options that are not available +using the web-based user interface. diff --git a/docs/user/urls.md b/docs/user/urls.md index d784f3a..3b486a2 100644 --- a/docs/user/urls.md +++ b/docs/user/urls.md @@ -32,7 +32,7 @@ In addition to those schemes, Agama supports a set of specific ones which can be The typical protocols are enough for most use cases. However, more specific URLs can be handy in many situations. For instance, instead of serving your profile through HTTP, you could just put it on a USB stick and tell Agama about it with `usb:///profile.json`. Agama would search on all your -USB devices for the profile to use. Cool, right? +USB devices for the profile to use. Let's have a look to the different kind of URLs that Agama offers.