PageSourceSearch

https://kairos.io/assets/js/c3f78793.0094a827.js

js kairos.io collected 2026-10-03 19:59:53 UTC 13,464 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkkairos_docs=self.webpackChunkkairos_docs||[]).push([["36004"],{68441(e,t,n){n.r(t),n.d(t,{metadata:()=>s,default:()=>h,frontMatter:()=>r,contentTitle:()=>a,toc:()=>d,assets:()=>c});var s=JSON.parse('{"id":"expand-with-sysext","title":"Extending Hadron with extensions","description":"This page provides a strighforward example of using sysext/confext for Hadron.","source":"@site/hadron-docs/expand-with-sysext.md","sourceDirName":".","slug":"/expand-with-sysext","permalink":"/hadron-docs/expand-with-sysext","draft":false,"unlisted":false,"editUrl":"https://github.com/kairos-io/kairos-docs/tree/main/hadron-docs/expand-with-sysext.md","tags":[],"version":"current","lastUpdatedBy":"Itxaka","lastUpdatedAt":1784707026000,"sidebarPosition":3,"frontMatter":{"title":"Extending Hadron with extensions","sidebar_label":"Extending Hadron with extensions","sidebar_position":3},"sidebar":"hadronSidebar","previous":{"title":"Adding Hadron layers","permalink":"/hadron-docs/layers"},"next":{"title":"Overview","permalink":"/hadron-docs/nvidia/"}}'),o=n(74848),i=n(28453);let r={title:"Extending Hadron with extensions",sidebar_label:"Extending Hadron with extensions",sidebar_position:3},a,c={},d=[{value:"Building fwupd as a system+config extension with auroraboot",id:"building-fwupd-as-a-systemconfig-extension-with-auroraboot",level:3},{value:"Verifying the system/config extensions",id:"verifying-the-systemconfig-extensions",level:3},{value:"CLI extension management",id:"cli-extension-management",level:3}];function l(e){let t={a:"a",admonition:"admonition",code:"code",h3:"h3",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.R)(),...e.components},{ShortcodeCodeBlock:n}=t;return n||function(e,t){throw Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("ShortcodeCodeBlock",!0),(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.admonition,{title:"Full sysext/confext info",type:"info",children:(0,o.jsxs)(t.p,{children:["This page provides a strighforward example of using sysext/confext for Hadron.\nFor more information on system and config extensions, how they work, how to build them and how to manage them with the CLI, refer to the official documentation: ",(0,o.jsx)(t.a,{href:"/docs/advanced/sys-extensions/",children:"Kairos extensions documentation"}),"."]})}),"\n",(0,o.jsx)(t.h3,{id:"building-fwupd-as-a-systemconfig-extension-with-auroraboot",children:"Building fwupd as a system+config extension with auroraboot"}),"\n",(0,o.jsxs)(t.p,{children:["We will be building our sysext+confext from a docker image directly by using ",(0,o.jsx)(t.a,{href:"https://github.com/kairos-io/AuroraBoot",children:"auroraboot"})," and using a dockerfile to isolate the artifacts you want converted into a system extension."]}),"\n",(0,o.jsx)(t.p,{children:"Notice that when converting a docker image into a system extension, the last layer is the only one converted (The last command in a given Dockerfile) so have that in mind. This is useful for packages that ONLY install things in /usr or manual installation under /usr."}),"\n",(0,o.jsxs)(t.p,{children:["Using the existing example for ",(0,o.jsx)(t.a,{href:"https://github.com/kairos-io/hadron/blob/main/examples/add-packages/Dockerfile.fwupd",children:"fwupd"}),":"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"$ docker build -t quay.io/itxaka/test:fwupd -f Dockerfile.fwupd --target=default .\n"})}),"\n",(0,o.jsxs)(t.p,{children:["After building the chosen Dockerfile, we would just need to run Auroraboot with the ",(0,o.jsx)(t.code,{children:"sysext|confext"})," command and the key and certificate, like we would do with ",(0,o.jsx)(t.code,{children:"systemd-repart"}),". Notice that we are binding the local ",(0,o.jsx)(t.code,{children:"keys/"})," dir into the container ",(0,o.jsx)(t.code,{children:"/keys"})," dir for ease of access to the given keys and the current dir under ",(0,o.jsx)(t.code,{children:"/build"})," on the container so we set the ",(0,o.jsx)(t.code,{children:"--output=/build"})," flag when calling auroraboot:"]}),"\n",(0,o.jsx)(n,{language:"bash",template:'$ docker run \\\n-v "$PWD"/keys:/keys \\\n-v "$PWD":/build/ \\\n-v /var/run/docker.sock:/var/run/docker.sock \\\n--rm \\\n{{< RegistryURL  >}}/auroraboot:{{< AuroraBootVersion  >}} sysext --private-key=/keys/PRIVATE_KEY --certificate=/keys/CERTIFICATE --output=/build fwupd quay.io/itxaka/test:fwupd'}
1),"\n",(0,o.jsx)(t.p,{children:"The explanation of the docker command flags is as follows:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:'-v "$PWD"/keys:/keys'}),": We mount the current dir + keys dir into the container ",(0,o.jsx)(t.code,{children:"/keys"})," path. So auroraboot has access to the keys to sign the sysext."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:'-v "$PWD":/build/'}),": Mount the current dir into the container ",(0,o.jsx)(t.code,{children:"/build"})," path. So the generated sysext is available after the container is gone."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"-v /var/run/docker.sock:/var/run/docker.sock"}),": We pass the docker sock into the container so it can access our locally built container images. So we avoid pushing them and pulling them from a remote registry."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"--rm"}),": Once the container exit, remove it so we dont leave stuff lying around."]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"The explanation of the auroraboot command flags is as follows:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"sysext|confext"}),": Subcommand to call, in this case we want to build a sysext but we could be using confext as well if we wanted to build a config extension."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"--private-key"}),": Private key to sign the system extension."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"--certificate"}),": Certificate to sign the system extension."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"--output"}),": Dir where we will output the system extension. Make sure that this matches the directory that passed to the docker command to be able to keep the generated system extension once the container exists and its removed."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"fwupd"}),": Output and internal name of the sysext/confext."]}),"\n",(0,o.jsxs)(t.li,{children:[(0,o.jsx)(t.code,{children:"quay.io/itxaka/test:fwupd"}),": Image from which we will extract the last layer and covert it to a system extension."]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Example of a successful run:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"$ docker run -v /var/run/docker.sock:/var/run/docker.sock  -v $PWD/tests/assets/keys:/keys -v ${PWD}/build:/output auroraboot sysext --private-key=/keys/db.key --certificate=/keys/db.pem --output /output fwupd quay.io/itxaka/test:fwupd\n2026-03-11T10:06:01Z INF [1] \u{1F680} Start sysext creation\n2026-03-11T10:06:01Z INF [1] \u{1F4BF} Getting image info\n2026-03-11T10:06:01Z INF [1] \u{1F4E4} Extracting archives from image layer\n2026-03-11T10:06:01Z INF \u{1F4E6} Packing sysext into raw image\n2026-03-11T10:06:01Z INF \u{1F389} Done sysext creation output=/output/fwupd.sysext.raw\n"})}),"\n",(0,o.jsxs)(t.p,{children:["In this case, as the dockerfile for ",(0,o.jsx)(t.code,{children:"fwupd"})," also ships important configurations files under ",(0,o.jsx)(t.code,{children:"/etc"})," (certificates and remote repos) we would need to construct a config extension as well to be able to ship those files. The process is the same, but instead of using the ",(0,o.jsx)(t.code,{children:"sysext"})," subcommand we would use the ",(0,o.jsx)(t.code,{children:"confext"})," one:"]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"$ docker run -v /var/run/docker.sock:/var/run/docker.sock  -v $PWD/tests/assets/keys:/keys -v ${PWD}/build:/output auroraboot confext --private-key=/keys/db.key --certificate=/keys/db.pem --output /output fwupd quay.io/itxaka/test:fwupd\n2026-03-11T10:06:10Z INF [1] \u{1F680} Start confext creation\n2026-03-11T10:06:10Z INF [1] \u{1F4BF} Getting image info\n2026-03-11T10:06:10Z INF [1] \u{1F4E4} Extracting archives from image layer\n2026-03-11T10:06:11Z INF \u{1F4E6} Packing confext into raw image\n2026-03-11T10:06:11Z INF \u{1F389} Done confext creation output=/output/fwupd.confext.raw\n"})}),"\n",(0,o.jsxs)(t.admonition,{title:"Files and dirs for system/config extensions",type:"warning",children:[(0,o.jsxs)(t.p,{children:["Since the system extensions are mounted under ",(0,o.jsx)(t.code,{children:"/u
1sr"}),", only the files and directories under those specific directories will be included in the system extension."]}),(0,o.jsxs)(t.p,{children:["Since the config extensions are mounted under ",(0,o.jsx)(t.code,{children:"/etc"}),", only the files and directories under that specific directory will be included in the config extension."]}),(0,o.jsx)(t.p,{children:'If your image ships files in other paths, they will be fully ignored and not included in the final system/config extension. So make sure to place the files you want to include in the correct paths as explained in the section "System/Config extensions under Kairos" above.'})]}),"\n",(0,o.jsx)(t.h3,{id:"verifying-the-systemconfig-extensions",children:"Verifying the system/config extensions"}),"\n",(0,o.jsxs)(t.p,{children:["You can use ",(0,o.jsx)(t.code,{children:"systemd-dissect"})," to verify the system extension, the ID, ARCHITECTURE and the partitions that are included in the system extension."]}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"$ systemd-dissect fwupd.sysext.raw\n File Name: fwupd.sysext.raw\n      Size: 35.4M\n Sec. Size: 512\n     Arch.: x86-64\nImage UUID: 60f29b0d-f685-4878-b529-4ef35c3f1196\nImage Name: fwupd\n\n sysext R.: ID=_any\n            ARCHITECTURE=x86-64\n\n    Use As: \u2717 bootable system for UEFI\n            \u2717 bootable system for container\n            \u2717 portable service\n            \u2717 initrd\n            \u2713 sysext for system\n            \u2713 sysext for portable service\n            \u2717 sysext for initrd\n            \u2717 confext for system\n            \u2717 confext for portable service\n            \u2717 confext for initrd\n\nRW DESIGNATOR      PARTITION UUID                       PARTITION LABEL        FSTYPE                ARCHITECTURE VER>\nro root            5faedf12-ae10-79f9-4cbc-664cc53d6ac7 root-x86-64            erofs                 x86-64       sig>\nro root-verity     a6d2ae30-72d6-6c4c-7512-d988954599b5 root-x86-64-verity     DM_verity_hash        x86-64       -  >\nro root-verity-sig ba282899-118d-4b1c-ba8c-5e1af8e37c81 root-x86-64-verity-sig verity_hash_signature x86-64       -  >\n"})}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-bash",children:"systemd-dissect fwupd.confext.raw\n File Name: fwupd.confext.raw\n      Size: 1M\n Sec. Size: 512\n     Arch.: x86-64\nImage UUID: a67a9975-1de6-4af3-b833-cdffb2f18c54\nImage Name: fwupd\n\nconfext R.: ID=_any\n            ARCHITECTURE=x86-64\n\n    Use As: \u2717 bootable system for UEFI\n            \u2717 bootable system for container\n            \u2717 portable service\n            \u2717 initrd\n            \u2717 sysext for system\n            \u2717 sysext for portable service\n            \u2717 sysext for initrd\n            \u2713 confext for system\n            \u2713 confext for portable service\n            \u2717 confext for initrd\n\nRW DESIGNATOR      PARTITION UUID                       PARTITION LABEL        FSTYPE                ARCHITECTURE VER>\nro root            ce62b11b-3085-cbca-8559-9b3814c16526 root-x86-64            erofs                 x86-64       sig>\nro root-verity     a29e0dc1-e5d2-b07b-79cd-ac2c09679119 root-x86-64-verity     DM_verity_hash        x86-64       -  >\nro root-verity-sig 6e2b0c53-f591-4024-99f1-8de9ca337cce root-x86-64-verity-sig verity_hash_signature x86-64       -  >\n"})}),"\n",(0,o.jsxs)(t.p,{children:["Now both your system and config extensions with ",(0,o.jsx)(t.code,{children:"fwupd"})," are ready to be used securely on your Kairos system. Refer to the below section for more information on how to manage them with the CLI."]}),"\n",(0,o.jsx)(t.h3,{id:"cli-extension-management",children:"CLI extension management"}),"\n",(0,o.jsxs)(t.p,{children:["Refer to the Kairos CLI documentation for more information on how to manage system and config extensions with the CLI: ",(0,o.jsx)(t.a,{href:"https://kairos.io/docs/advanced/sys-extensions/#%EF%B8%8F-cli-usage",children:"Kairos extensions documentation"}),"."]})]})}function h(e={}){let{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},28453(e,t,n){n.d(t,{R:()=>r,x:()=>a});var s=n(96540);let o={},i=s.createContext(o);function r(e){let t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.