diff --git a/404.html b/404.html
index f7b6930c..ea9bf4c4 100644
--- a/404.html
+++ b/404.html
@@ -137,7 +137,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/about/index.html b/about/index.html
index efbc6b83..539b8500 100644
--- a/about/index.html
+++ b/about/index.html
@@ -156,7 +156,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/blog/2019/12/23/0.3-release/index.html b/blog/2019/12/23/0.3-release/index.html
index f01e18f3..ccec3b02 100644
--- a/blog/2019/12/23/0.3-release/index.html
+++ b/blog/2019/12/23/0.3-release/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/blog/2019/12/23/website-is-up/index.html b/blog/2019/12/23/website-is-up/index.html
index aef3bcf5..36da4eb5 100644
--- a/blog/2019/12/23/website-is-up/index.html
+++ b/blog/2019/12/23/website-is-up/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/blog/index.html b/blog/index.html
index 8b9984b2..d0547302 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -140,7 +140,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -162,7 +162,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/blog/news/index.html b/blog/news/index.html
index 2b283d8a..6b1986d8 100644
--- a/blog/news/index.html
+++ b/blog/news/index.html
@@ -138,7 +138,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -160,7 +160,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/blog/releases/index.html b/blog/releases/index.html
index a1a9e74f..15ef3810 100644
--- a/blog/releases/index.html
+++ b/blog/releases/index.html
@@ -138,7 +138,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -160,7 +160,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/community/index.html b/community/index.html
index ccbda8eb..5a99ff45 100644
--- a/community/index.html
+++ b/community/index.html
@@ -139,7 +139,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/docs/concepts/index.html b/docs/concepts/index.html
index fd42ff6d..2d238b0a 100644
--- a/docs/concepts/index.html
+++ b/docs/concepts/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -409,7 +409,7 @@ if (!doNotTrack) {
diff --git a/docs/concepts/overview/build_packages/index.html b/docs/concepts/overview/build_packages/index.html
index a90ad7b2..fd6e9731 100644
--- a/docs/concepts/overview/build_packages/index.html
+++ b/docs/concepts/overview/build_packages/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -523,7 +523,7 @@ $~/workdir> cat <<EOF > package3/definit
diff --git a/docs/concepts/overview/constraints/index.html b/docs/concepts/overview/constraints/index.html
index 8d3b919d..1f72f5c1 100644
--- a/docs/concepts/overview/constraints/index.html
+++ b/docs/concepts/overview/constraints/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -403,7 +403,7 @@ They share the same SAT logic of expansion, allowing to swap entire version rang
diff --git a/docs/concepts/overview/index.html b/docs/concepts/overview/index.html
index b88364ce..a0529bca 100644
--- a/docs/concepts/overview/index.html
+++ b/docs/concepts/overview/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -440,7 +440,7 @@ Luet allows also to create packages entirely from Docker images content. In this
diff --git a/docs/concepts/overview/repositories/index.html b/docs/concepts/overview/repositories/index.html
index ff729575..d496b582 100644
--- a/docs/concepts/overview/repositories/index.html
+++ b/docs/concepts/overview/repositories/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -507,7 +507,7 @@ foo-bar-0.1-builder.image.tar foo-bar-0.1.image.tar foo-bar-0.1.metadata.yaml
diff --git a/docs/concepts/overview/usage/index.html b/docs/concepts/overview/usage/index.html
index 0317000e..fa6e9e60 100644
--- a/docs/concepts/overview/usage/index.html
+++ b/docs/concepts/overview/usage/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -448,7 +448,7 @@ $ luet search --table <regex>
diff --git a/docs/concepts/packages/collections/index.html b/docs/concepts/packages/collections/index.html
index ee6bfcbb..32381c5d 100644
--- a/docs/concepts/packages/collections/index.html
+++ b/docs/concepts/packages/collections/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -408,7 +408,7 @@ if (!doNotTrack) {
diff --git a/docs/concepts/packages/index.html b/docs/concepts/packages/index.html
index 7981bde1..493918d8 100644
--- a/docs/concepts/packages/index.html
+++ b/docs/concepts/packages/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -588,7 +588,7 @@ distro/raspbian/buster
diff --git a/docs/concepts/packages/specfile/index.html b/docs/concepts/packages/specfile/index.html
index 3fe78b7a..7311a6d2 100644
--- a/docs/concepts/packages/specfile/index.html
+++ b/docs/concepts/packages/specfile/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -826,7 +826,7 @@ The directory must represent exactly how the files will be ultimately installed
diff --git a/docs/concepts/packages/templates/index.html b/docs/concepts/packages/templates/index.html
index 360bbf56..88596f80 100644
--- a/docs/concepts/packages/templates/index.html
+++ b/docs/concepts/packages/templates/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -486,7 +486,7 @@ if (!doNotTrack) {
diff --git a/docs/concepts/plugins-and-extensions/index.html b/docs/concepts/plugins-and-extensions/index.html
index 72def8c6..01c6a155 100644
--- a/docs/concepts/plugins-and-extensions/index.html
+++ b/docs/concepts/plugins-and-extensions/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -481,7 +481,7 @@ $ luet --plugin test-foo install -y foopackage
diff --git a/docs/contribution-guidelines/index.html b/docs/contribution-guidelines/index.html
index fc80ca7c..b64517d0 100644
--- a/docs/contribution-guidelines/index.html
+++ b/docs/contribution-guidelines/index.html
@@ -28,13 +28,13 @@ We use Hugo to format and generate our website, the Docsy theme for styling and
-
+
-
+
@@ -149,7 +149,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -171,7 +171,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -433,7 +433,7 @@ the content.
diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html
index 816faa8a..9d7fedc5 100644
--- a/docs/getting-started/index.html
+++ b/docs/getting-started/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -498,7 +498,7 @@ mv .luet.yaml /etc/luet/luet.yaml
diff --git a/docs/index.html b/docs/index.html
index 95c5576c..faf66c06 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -138,7 +138,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -160,7 +160,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -425,7 +425,7 @@ if (!doNotTrack) {
diff --git a/docs/index.xml b/docs/index.xml
index 2e40ffba..5e4322fb 100644
--- a/docs/index.xml
+++ b/docs/index.xml
@@ -1475,6 +1475,10 @@ docker run -ti --entrypoint /bin/bash --rm luet-runtime-test-image
<td>mocaccinoOS extra</td>
<td><a href="https://github.com/mocaccinoOS/mocaccino-extra">https://github.com/mocaccinoOS/mocaccino-extra</a></td>
</tr>
+<tr>
+<td>agregOS built with luet/mocaccino</td>
+<td><a href="https://interne.agreg.org/agregOS/">https://interne.agreg.org/agregOS/</a></td>
+</tr>
</tbody>
</table>
diff --git a/docs/resources/arm/index.html b/docs/resources/arm/index.html
index e29686bd..8e90a39f 100644
--- a/docs/resources/arm/index.html
+++ b/docs/resources/arm/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -439,7 +439,7 @@ $> sudo make build-all
diff --git a/docs/resources/building/index.html b/docs/resources/building/index.html
index bf95e95e..6d293a8d 100644
--- a/docs/resources/building/index.html
+++ b/docs/resources/building/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -441,7 +441,7 @@ $> luet build bar/foo-0.1 --compression gzip
diff --git a/docs/resources/faq/index.html b/docs/resources/faq/index.html
index 1e3572aa..1c578ff4 100644
--- a/docs/resources/faq/index.html
+++ b/docs/resources/faq/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -394,7 +394,7 @@ if (!doNotTrack) {
diff --git a/docs/resources/index.html b/docs/resources/index.html
index e63ee800..346d161b 100644
--- a/docs/resources/index.html
+++ b/docs/resources/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -425,7 +425,7 @@ if (!doNotTrack) {
diff --git a/docs/resources/index.xml b/docs/resources/index.xml
index 6a95ac6b..21589134 100644
--- a/docs/resources/index.xml
+++ b/docs/resources/index.xml
@@ -254,6 +254,10 @@ docker run -ti --entrypoint /bin/bash --rm luet-runtime-test-image
<td>mocaccinoOS extra</td>
<td><a href="https://github.com/mocaccinoOS/mocaccino-extra">https://github.com/mocaccinoOS/mocaccino-extra</a></td>
</tr>
+<tr>
+<td>agregOS built with luet/mocaccino</td>
+<td><a href="https://interne.agreg.org/agregOS/">https://interne.agreg.org/agregOS/</a></td>
+</tr>
</tbody>
</table>
diff --git a/docs/resources/references/index.html b/docs/resources/references/index.html
index de6ce45c..388812c2 100644
--- a/docs/resources/references/index.html
+++ b/docs/resources/references/index.html
@@ -25,12 +25,12 @@
-
+
-
-
+
+
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -343,6 +343,10 @@ if (!doNotTrack) {
mocaccinoOS extra |
https://github.com/mocaccinoOS/mocaccino-extra |
+
+agregOS built with luet/mocaccino |
+https://interne.agreg.org/agregOS/ |
+
@@ -411,7 +415,7 @@ if (!doNotTrack) {
diff --git a/docs/resources/scratch/index.html b/docs/resources/scratch/index.html
index 94be4f17..96271109 100644
--- a/docs/resources/scratch/index.html
+++ b/docs/resources/scratch/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -400,7 +400,7 @@ docker run -ti --entrypoint /bin/bash --rm luet-runtime-test-image
diff --git a/docs/tutorials/build_package/index.html b/docs/tutorials/build_package/index.html
index 358a5039..ab5cc508 100644
--- a/docs/tutorials/build_package/index.html
+++ b/docs/tutorials/build_package/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -573,7 +573,7 @@ luet box exec --rootfs
- Last modified February 4, 2022: :notebook: docs: Update repository section (fe504e9)
+ Last modified February 15, 2022: :notebook: Update docs to mention agregOS (660c5a2)
diff --git a/docs/tutorials/hello_world/index.html b/docs/tutorials/hello_world/index.html
index 714d4bcf..c2844dec 100644
--- a/docs/tutorials/hello_world/index.html
+++ b/docs/tutorials/hello_world/index.html
@@ -27,12 +27,12 @@
-
+
-
+
@@ -146,7 +146,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -168,7 +168,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -458,7 +458,7 @@ For this purpose, we have picked a real-world example:
- Last modified February 4, 2022: :notebook: docs: Update repository section (fe504e9)
+ Last modified February 15, 2022: :notebook: Update docs to mention agregOS (660c5a2)
diff --git a/docs/tutorials/index.html b/docs/tutorials/index.html
index a92bd5f1..05127612 100644
--- a/docs/tutorials/index.html
+++ b/docs/tutorials/index.html
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -164,7 +164,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
@@ -401,7 +401,7 @@ if (!doNotTrack) {
diff --git a/index.html b/index.html
index a7fc9f03..0946f3e5 100644
--- a/index.html
+++ b/index.html
@@ -155,7 +155,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/index.json b/index.json
index af3e074b..39bf551e 100644
--- a/index.json
+++ b/index.json
@@ -25,11 +25,11 @@
-
+
-
+
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json b/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json
similarity index 91%
rename from offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json
rename to offline-search-index.72b6075a770705d05a5c74adb1af94ee.json
index e93e2d4d..11d95aaf 100644
--- a/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json
+++ b/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json
@@ -1 +1 @@
-[{"body":"Prerequisistes Luet currently supports Docker and Img as backends to build packages. Both of them can be used and switched in runtime with the --backend option, so either one of them must be present in the host system.\nDocker Docker is the (less) experimental Luet engine supported. Be sure to have Docker installed and the daemon running. The user running luet commands needs the corresponding permissions to run the docker executable, and to connect to a docker daemon. The only feature needed by the daemon is the ability to build images, so it fully supports remote daemon as well (this can be specified with the DOCKER_HOST environment variable, that is respected by luet)\nImg Luet supports Img. To use it, simply install it in your system, and while running luet build, you can switch the backend by providing it as a parameter: luet build --backend img. For small packages it is particularly powerful, as it doesn’t require any docker daemon running in the host.\nBuilding packages on Kubernetes Luet and img can be used together to orchestrate package builds also on kubernetes. There is available an experimental Kubernetes CRD for Luet which allows to build packages seamelessly in Kubernetes and push package artifacts to an S3 Compatible object storage (e.g. Minio).\nBuilding packages Luet provides an abstraction layer on top of the container image layer to make the package a first class construct. A package definition and all its dependencies are translated by Luet to Dockerfiles which can then be built anywhere that docker runs.\nTo resolve the dependency tree Luet uses a SAT solver and no database. It is responsible for calculating the dependencies of a package and to prevent conflicts. The Luet core is still young, but it has a comprehensive test suite that we use to validate any future changes.\nBuilding a package with Luet requires only a definition. This definition can be self-contained and be only composed of one specfile, or a group of them, forming a Luet tree. For more complex use-cases, see collections.\nRun luet build --help to get more help for each parameter.\nBuild accepts a list of packages to build, which syntax is in the category/name-version notation. See also specfile documentation page to see how to express packages from the CLI.\nEnvironmental variables Luet builds passes its environment variable at the engine which is called during build, so for example the environment variable DOCKER_HOST or DOCKER_BUILDKIT can be setted.\nEvery argument from the CLI can be setted via environment variable too with a LUET_ prefix, for instance the flag --clean, can be setted via environment with LUET_CLEAN, --privileged can be enabled with LUET_PRIVILEGED and so on.\nSupported compression format At the moment, luet can compress packages and tree with zstd and gzip. For example:\nluet build --compression zstd ... Will output package compressed in the zstd format.\nSee the --help of create-repo and build to learn all the available options.\nExample A package definition is composed of a build.yaml and a sibiling definition.yaml.\nIn the following example, we are creating a dummy package (bar/foo). Which ships one file only, /foo\n$\u003e # put yourself in some workdir $~/workdir\u003e mkdir package $~/workdir\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo=bar\" \u003e /foo EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" EOF To build it, simply run luet build bar/foo or luet build --all to build all the packages in the current directory:\n$\u003e luet build --all 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... Luet “trees” are just a group of specfiles, in the above example, our tree was the current directory. You can also specify a directory with the --tree option. Luet doesn’t enforce any tree layout, so they can be nested at any level. The only rule of thumb is that a build.yaml file needs to have either a definition.yaml or a collection.yaml file next to it.\nNesting dependencies In the example above we have created a package from a delta. Luet by default creates packages by analyzing the differences between the generated containers, and extracts the differences as archive, the resulting files then are compressed and can be consumed later on by luet install.\nLuet can create packages from different building strategies: by delta, by taking a whole container content, or by considering a single directory in the build container.\nBesides that, a package can reference a strict dependency on others.\nExample Let’s extend the above example with two packages which depends on it during the build phase.\n$~/workdir\u003e mkdir package2 $~/workdir\u003e cat \u003c\u003cEOF \u003e package2/build.yaml requires: - name: \"foo\" category: \"bar\" version: \"\u003e=0\" steps: - source /foo \u0026\u0026 echo \"$foo\" \u003e /bar EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package2/definition.yaml name: \"ineedfoo\" version: \"0.1\" category: \"bar\" EOF $~/workdir\u003e mkdir package3 $~/workdir\u003e cat \u003c\u003cEOF \u003e package3/build.yaml requires: - name: \"foo\" category: \"bar\" version: \"\u003e=0\" - name: \"ineedfoo\" category: \"bar\" version: \"\u003e=0\" steps: - source /foo \u0026\u0026 echo \"$foo\" \u003e /ineedboth - cat /bar \u003e /bar EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package3/definition.yaml name: \"ineedfooandbar\" version: \"0.1\" category: \"bar\" EOF To build, run again:\n$\u003e luet build --all As we can see, now Luet generated 3 packages, bar/foo, bar/ineedfoo and bar/ineedfooandbar. They aren’t doing anything special than just shipping text files, this is an illustrative example on how build requirements can be combined to form new packages:\nbar/ineedfooandbar depends on both bar/ineedfoo and bar/foo during build-time, while bar/foo uses a docker image as a build base.\nSee the package definition documentation page for more details on how to instruct the Luet compiler to build packages with different strategies.\nCaching docker images Luet can push and pull the docker images that are being generated during the build process. A tree is represented by a single docker image, and each package can have one or more tags attached to it.\nTo push automatically docker images that are built, use the --push option, to pull, use the --pull option. An image repository can be specified with --image-repository flag, and can include also the remote registries where the images are pushed to.\nLuet doesn’t handle login to registries, so that has to be handled separately with docker login or img login before the build process starts.\nBuild faster When packages are cached, for iterating locally it’s particularly useful to jump straight to the image that you want to build. You can use --only-target-package to jump directly to the image you are interested in. Luet will take care of checking if the images are present in the remote registry, and would build them if any of those are missing.\nNotes All the files which are next to a build.yaml are copied in the container which is running your build, so they are always accessible during build time. If you notice errors about disk space, mind to set the TMPDIR env variable to a different folder. By default luet respects the O.S. default (which in the majority of system is /tmp). ","categories":"","description":"How to build packages with Luet\n","excerpt":"How to build packages with Luet\n","ref":"/docs/concepts/overview/build_packages/","tags":"","title":"Building packages"},{"body":"This article will guide you to build your first package with Luet! For this purpose, we have picked a real-world example: gogs which is a “painless self-hosted Git service”, an open-source alternative to Github.\nGogs is written in Golang, and we need a working Golang version in order to build it.\nHere you can see a live recorded session of this tutorial:\n Define a Luet tree Everything starts from a Luet tree. A Luet tree is just a directory containing one (or more) Luet specfile, here on we assume that you are working in a dedicated folder (e.g. ~/demo) in your system.\nLet’s create then a package that will be our base to build other packages from now on, we have picked busybox here - it is really small and enough for our purpose.\nbusybox mkdir busybox Let’s now write the build specification, which is just containing the image tag that we are referencing to\ncat \u003c\u003cEOF \u003e busybox/build.yaml image: \"busybox:{{.Values.version}}-glibc\" EOF Now, lets write the definition.yaml, which contains the metadata information about our package ( e.g. how we refer to it with luet, the version, and so on )\ncat \u003c\u003cEOF \u003e busybox/definition.yaml category: \"distro\" name: \"busybox\" version: \"1.33.0\" EOF golang We need now golang in order to build gogs. Let’s declare then a golang package:\nmkdir golang And a build specfile, which is simply fetch golang from https://golang.org and installing it in the busybox container:\ncat \u003c\u003cEOF \u003e golang/build.yaml requires: - category: \"distro\" name: \"busybox\" version: \"\u003e=0\" prelude: - wget https://golang.org/dl/go{{.Values.version}}.linux-{{.Values.arch}}.tar.gz -O golang.tar.gz - mkdir /usr/local steps: - tar -C /usr/local -xzf golang.tar.gz EOF Note how we require busybox. The Golang container will now be based from busybox, and the prelude and steps fields will be executed in that context.\nAnd finally let’s write the golang metadata files, so we can refer to it from other packages\ncat \u003c\u003cEOF \u003e golang/definition.yaml name: \"go\" category: \"dev-lang\" version: \"1.15.6\" arch: \"amd64\" EOF gogs Finally we can write the gogs package definition!\nmkdir gogs The build specfile, will just fetch the gogs sources at a given version (specified in the definition.yaml) and build the sources with go:\ncat \u003c\u003c'EOF' \u003e gogs/build.yaml requires: - category: \"dev-lang\" name: \"go\" version: \"\u003e=0\" env: - GOPATH=\"/go\" - GOGSPATH=\"$GOPATH/src/github.com/gogs/gogs\" - PATH=$PATH:/usr/local/go/bin - CGO_ENABLED=0 prelude: - mkdir -p $GOPATH/src/github.com/gogs - wget https://github.com/gogs/gogs/archive/v{{.Values.version}}.tar.gz -O - | tar -xzf - -C ./ \u0026\u0026 mv gogs-{{.Values.version}} $GOGSPATH steps: - mkdir /usr/bin - cd $GOGSPATH \u0026\u0026 go build \u0026\u0026 mv gogs /usr/bin/gogs excludes: # Cache generated by Golang - ^/root EOF And the metadata, in this way we can refer to gogs in a Luet tree:\ncat \u003c\u003cEOF \u003e gogs/definition.yaml category: \"dev-vcs\" name: \"gogs\" version: \"0.11.91\" EOF Build packages The simplest and mostly immediate way to build packages, is running luet build \u003cpackagename\u003e in the same folder you have your Luet tree.\nIn this case, to build gogs and its deps, we can do:\nluet build dev-vcs/gogs And that’s it! you will find the package archives in build/ in the same folder where you started the command.\nYou will see that Luet generates not only archives with the file resulting to your builds, but it will also generate metadata files (ending with .metadata.yaml) that contains additional metadata information about your build and the package itself (e.g. checksums).\nYou can use tools like yq to inspect those:\nyq r build/gogs-dev-vcs-0.11.91.metadata.yaml checksums Now if you want to consume the artifacts just built with luet install, you can create a repository with luet create-repo.\n","categories":"","description":"Everything starts from an \"Hello!\"\n","excerpt":"Everything starts from an \"Hello!\"\n","ref":"/docs/tutorials/hello_world/","tags":"","title":"Hello world!"},{"body":"Prerequisites No dependencies. For building packages see the Build Packages section\nGet Luet From release Just grab a release from the release page on GitHub. The binaries are statically compiled.\nOr you can install Luet also with a single command:\ncurl https://luet.io/install.sh | sudo sh Building Luet from source Requirements:\n Golang installed in your system. make $\u003e git clone https://github.com/mudler/luet $\u003e cd luet $\u003e make build # or just go build Install it as a system package In the following section we will see how to install luet with luet itself. We will use a transient luet version that we are going to throw away right after we install it in the system.\n# Get a luet release. It will be used to install luet in your system wget https://github.com/mudler/luet/releases/download/0.8.3/luet-0.8.3-linux-amd64 -O luet chmod +x luet # Creates the luet configuration file and add the luet-index repository. # The luet-index repository contains a collection of repositories which are # installable and tracked in your system as standard packages. cat \u003e .luet.yaml \u003c\u003cEOF repositories: - name: \"mocaccino-repository-index\" description: \"MocaccinoOS Repository index\" type: \"http\" enable: true cached: true priority: 1 urls: - \"https://raw.githubusercontent.com/mocaccinoOS/repository-index/gh-pages\" EOF # Install the official luet repository to get always the latest luet version ./luet install repository/luet # Install luet (with luet) in your system ./luet install system/luet # Remove the temporary luet used for bootstrapping rm -rf luet # Copy over the config file to your system mkdir -p /etc/luet mv .luet.yaml /etc/luet/luet.yaml Configuration Luet stores its configuration files in /etc/luet. If you wish to override its default settings, create a file /etc/luet/luet.yaml.\nA example of a luet.yaml file can be found here.\nThere are a bunch of configuration settings available, but the most relevant are:\nlogging:color:true# Enable/Disable colored outputenable_emoji:true# Enable/Disable emoji from outputgeneral:debug:false# Enable/Disable debugsystem:rootfs:\"/\"# What's our rootfs. Luet can install packages outside of \"/\"database_path:\"/var/db/luet\"# Where to store DB filesdatabase_engine:\"boltdb\"tmpdir_base:\"/var/tmp/luet\"# The temporary directory to be usedAdding repositories To add repositories, you can either add a repositories stanza in your /etc/luet/luet.yaml or either add one or more yaml files in /etc/luet/repos.conf.d/.\nConfiguration in /etc/luet/luet.yaml logging:color:true# Enable/Disable colored outputenable_emoji:true# Enable/Disable emoji from outputgeneral:debug:false# Enable/Disable debugsystem:rootfs:\"/\"# What's our rootfs. Luet can install packages outside of \"/\"database_path:\"/var/db/luet\"# Where to store DB filesdatabase_engine:\"boltdb\"tmpdir_base:\"/var/tmp/luet\"# The temporary directory to be usedrepositories:- name:\"some-repository-name\"# Repository namedescription:\"A beautiful description\"type:\"http\"# Repository type, disk or http are supported (disk for local path)enable:true# Enable/Disable repocached:true# Enable cache for repositorypriority:3# Cache priorityurls:# Repository URLs- \"....\"Configuration in /etc/luet/repos.conf.d/ A repository file can be for example:\nname:\"...\"# Repository namedescription:\"...\"type:\"http\"# Repository type, disk or http are supported (disk for local path)enable:true# Enable/Disable repocached:true# Enable cache for repositorypriority:3# Cache priorityurls:# Repository URLs- \"...\"There is available a collection of repositories, which is containing a list of repositories that can be installed in the system with luet install.\nIf you installed Luet from the curl command, you just need to run luet search repository to see a list of all the available repository, and you can install them singularly by running luet install repository/\u003cname\u003e. Otherwise, add the repository stanzas you need to /etc/luet/luet.yaml.\n","categories":"","description":"First steps with Luet\n","excerpt":"First steps with Luet\n","ref":"/docs/getting-started/","tags":"","title":"Getting Started"},{"body":"Luet provides an abstraction layer on top of the container image layer to make the package a first class construct. A package definition and all its dependencies are translated by Luet to Dockerfiles which can then be built anywhere that docker runs.\nLuet is written entirely in Go and comes as a single static binary. This has a few advantages:\n Easy to recover. You can use luet to bootstrap the system entirely from the ground-up. Package manager has no dependencies on the packages that it installs. There is no chance of breaking the package manager by installing a conflicting package, or uninstalling one. Portable - it can run on any architecture Luet brings the containers ecosystem to standard software package management and delivery. It is fully built around the container concept, and leverages the huge catalog already present in the wild. It lets you use Docker images from Docker Hub, or from private registries to build packages, and helps you to redistribute them.\nSystems that are using luet as a package manager can consume Luet repositories with only luet itself. No dependency is required by the Package manager, giving you the full control on what you install or not in the system. It can be used to generate Linux from Scratch distributions, also to build Docker images, or to simply build standalone packages that you might want to redistribute.\nThe syntax proposed aims to be KISS - you define a set of steps that need to be run to build your image, and a set of constraints denoting the requirements or conflicts of your package.\nWhy another Package manager? There is no known package manager with 0-dependency that fully leverages the container ecosystem. This gap forces current package managers to depend on a specific system layout as base of the building process and the corresponding depencies. This can cause situations leading to a broken system. We want to fix that by empowering the user, by building their own packages, and redistribute them. Luet allows also to create packages entirely from Docker images content. In this way the user can actually bundle all the files of an image into a package and deliver part of it, or entirely as a layer. All of that, without the package manager depending on a single bit from it.\nPackage definitions Luet uses YAML for the package specification format, Luet parses the requirements to build packages, so Luet can consume them.\nBelow you can find links to tutorials on how to build packages, images and repositories.\n","categories":"","description":"See Luet in action.\n","excerpt":"See Luet in action.\n","ref":"/docs/concepts/overview/","tags":"","title":"Overview"},{"body":"After a set of packages has been built, a repository must be created in order to make them accessible by Luet clients. A Repository can be served either local files or via http(s) (at the moment of writing). Luet, by default, supports multiple-repositories with priorities.\nRepository fields name:\"...\"description:\"...\"type:\"docker\"cached:trueenabled:truearch:\"amd64\"priority:3urls:- \"...\"Repositories have the following fields, notably:\n name: Repository name description: Repository description cached: Enable/disable repository cache enable: Enable/disables the repository urls: A List of urls where the repository is hosted from type: Repository type ( docker, disk, http are currently supported ) arch: (optional) Denotes the arch repository. If present, it will enable the repository automatically if the corresponding arch is matching with the host running luet. enable: true would override this behavior reference: (optional) A reference to a repository index file to use to retrieve the repository metadata instead of latest. This can be used to point to a different or an older repository index to act as a “wayback machine”. The client will consume the repository state from that snapshot instead of latest. Note The reference field has to be a valid tag. For example, if a repository is a docker type, browse the image tags. The repository index snapshots are prefixed with a timestamp, and ending in repository.yaml. For example 20211027153653-repository.yaml Create a repository After issuing a luet build, the built packages are present in the output build directory. The create-repo step is needed to generate a portable tree, which is read by the clients, and a repository.yaml which contains the repository metadata.\nNote that the output of create-repo is additive so it integrates with the current build content. The repository is composed by the packages generated by the build command (or pack) and the create-repo generated metadata.\nFlags Some of the relevant flags for create-repo are:\n –descr: Repository description –name: Repository name –output: Metadata output folder (while a different path can be specified, it’s prefered to output the metadata files directly to the package directory).This most of the time matches the packages path for convenience. –packages: Directory where built packages are stored. This most of the time is also the output path. –reset-revision: Reset the repository revision number –tree-path: Specify a custom name for the tree path. (Defaults to tree.tar) –tree-compression: Specify a compression algorithm for the tree. (Available: gzip, Defaults: none) –tree: Path of the tree which was used to generate the packages and holds package metadatas –type: Repository type (http/local). It is just descriptive, the clients will be able to consume the repo in whatsoever way it is served. –urls: List of URIS where the repository is available See luet create-repo --help for a full description.\nExample Build a package and generate the repository metadata:\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" # optional! EOF $\u003e luet build --all --destination $PWD/out/ --tree $PWD/package 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... $\u003e luet create-repo --name \"test\" --output $PWD/out --packages $PWD/out --tree $PWD/package For repository test creating revision 1 and last update 1580641614... $\u003e ls out foo-bar-0.1-builder.image.tar foo-bar-0.1.image.tar foo-bar-0.1.metadata.yaml foo-bar-0.1.package.tar repository.yaml tree.tar Repositories type There are 3 types of repositories supported by luet: disk, http, docker.\ndisk It is a repository which is merely a local folder in your system. When creating a repository and specifying --output, luet expects a local path to the system where to store the generated metadata.\nhttp It is a repository type which is hosted behind a webserver. When creating a repository and specifying --output, luet expects a local path to the system where to store the generated metadata, similarly to the disk repository type. Luet is not handling any file upload. The http repository type gains meaning when being used from the client, where the repository source must be specified\ndocker When specifying the docker repository type, luet will generate final images from the build results and upload them to the docker reference specified with --output. The images contains the artifact output from the build result, and they are tagged accordingly to their package name. A single image reference needs to be passed, all the packages will be pushed in a single image but with different tags.\nThe login to the container registry is not handled, the daemon needs to have already proper permissions to push the image to the destination.\nRepositories snapshots Luet automatically will create repository index snapshots. This allows clients to point to specific references of repositories besides the latest package set published.\nluet create-repo optionally takes a --snapshot-id argument to define the snapshot name, otherwise it defaults to the unix date timestamp.\nCombined with --push-images with a container repository type, it automatically tags and pushes snapshots images too.\nConsuming repository snapshots A client can define a repository, with an optional reference keyword:\nname:\"...\"description:\"...\"type:\"docker\"priority:3reference:20220204175357-repository.yamlurls:- \"...\"Notes The tree of definition being used to build the repository, and the package directories must not be symlinks. To build a repository is not required to hold the packages artifacts, only the respective metadata.yaml file is required. ","categories":"","description":"How to create Luet repositories\n","excerpt":"How to create Luet repositories\n","ref":"/docs/concepts/overview/repositories/","tags":"","title":"Creating Luet repositories"},{"body":"","categories":"","description":"Documentation references\n","excerpt":"Documentation references\n","ref":"/docs/concepts/","tags":"","title":"Concepts"},{"body":"A Package in Luet is denoted by a triple (name, category and version), here called package form in a definition.yaml file in YAML:\nname:\"awesome\"version:\"0.1\"category:\"foo\"While category and version can be omitted, the name is required. Note that when refering to a package, the triplet is always present:\nrequires:- name:\"awesome\"version:\"0.1\"category:\"foo\"- name:\"bar\"version:\"0.1\"category:\"foo\"Building process When a package is required to be built, Luet resolves the dependency trees and orders the spec files to satisfy the given contraints.\nEach package build context is where the spec files are found (definition.yaml and build.yaml). This means that in the container, which is running the build process, the resources inside the package folder are accessible, as normally in Docker.\n❯ tree distro/raspbian/buster distro/raspbian/buster ├── build.sh ├── build.yaml ├── definition.yaml └── finalize.yaml In the example above, build.sh is accessible in build time and can be invoked easily in build time in build.yaml:\nsteps:- sh build.shPackage provides Packages can specify a list of provides. This is a list of packages in package form, which indicates that the current definition replaces every occurrence of the packages in the list (both at build and runtime). This mechanism is particularly helpful for handling package moves or for enabling virtual packages (e.g., gentoo virtual packages).\nNote: packages in the provides list don’t need to exist or have a valid build definition either.\nPackage types By a combination of keywords in build.yaml, you end up with categories of packages that can be built:\n Seed packages Packages deltas Package layers Package with includes Check the Specfile concept page for a full overview of the available keywords in the Luet specfile format.\nSeed packages Seed packages denote a parent package (or root) that can be used by other packages as a dependency. Normally, seed packages include just an image (preferably tagged) used as a base for other packages to depend on.\nIt is useful to pin to specific image versions, and to write down in a tree where packages are coming from. There can be as many seed packages as you like in a tree.\nA seed package build.yaml example is the following:\nimage:\"alpine:3.1\"Every other package that depends on it will inherit the layers from it.\nIf you want to extract the content of the seed package in a separate packages (splitting), you can just create as many package as you wish depending on that one, and extract its content, for example:\nalpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"sh/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# Tells luet to use the image content by unpacking itincludes:- /bin/shsh/definition.yaml\nname:\"sh\"category:\"utils\"version:\"1.0\"In this example, there are two packages being specified:\n One is the seed package, which is the base image employed to later extract packages. It has no installable content, and it is just virtually used during build phase. sh is the package which contains /bin/sh, extracted from the seed image and packaged. This can be consumed by Luet clients in order to install sh in their system. Packages delta Luet, by default, will try to calculate the delta of the package that is meant to be built. This means that it tracks incrementally the changes in the packages, to ease the build definition. Let’s see an example.\nGiven the root package: alpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"We can generate any file, and include it in our package by defining this simple package:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"steps:- echo \"Awesome\" \u003e /foofoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"By analyzing the difference between the two packages, Luet will automatically track and package /foo as part of the foo package.\nTo allow operations that must not be accounted in to the final package, you can use the prelude keyword:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"prelude:- echo \"Not packaged\" \u003e /invisiblesteps:- echo \"Awesome\" \u003e /foofoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"The list of commands inside prelude that would produce artifacts, are not accounted to the final package. In this example, only /foo would be packaged (which output is equivalent to the example above).\nThis can be used, for instance, to fetch sources that must not be part of the package.\nYou can apply restrictions anytime and use the includes keyword to specifically pin to the files you wish in your package.\nPackage layers Luet can be used to track entire layers and make them installable by Luet clients.\nGiven the examples above:\nalpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"An installable package derived by the seed, with the actual full content of the layer can be composed as follows:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as isfoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"This can be combined with other keywords to manipulate the resulting package (layer), for example:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as issteps:- apk update- apk add git- apk add ..foo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"Package includes In addition, the includes keyword can be set in order to extract portions from the package image.\ngit/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as issteps:- apk update- apk add gitincludes:- /usr/bin/gitfoo/definition.yaml\nname:\"git\"category:\"utils\"version:\"1.0\"As a reminder, the includes keywords accepts regular expressions in the Golang format. Any criteria expressed by means of Golang regular expressions, and matching the file name (absolute path), will be part of the final package.\n","categories":"","description":"Package definition syntax\n","excerpt":"Package definition syntax\n","ref":"/docs/concepts/packages/","tags":"","title":"Packages"},{"body":"Specfiles Luet packages are defined by specfiles. Specfiles define the runtime and builtime requirements of a package. There is an hard distinction between runtime and buildtime. A spec is composed at least by the runtime (definition.yaml or a collection.yaml) and the buildtime specification (build.yaml).\nLuet identifies the package definition by looking at directories that contains a build.yaml and a definition.yaml (or collection.yaml) files. A Luet tree is merely a composition of directories that follows this convention. There is no constriction on either folder naming or hierarchy.\nExample of a tree folder hierarchy\ntree distro distro ├── funtoo │ ├── 1.4 │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ ├── docker │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ └── meta │ └── rpi │ └── 0.1 │ ├── build.yaml │ └── definition.yaml ├── packages │ ├── container-diff │ │ └── 0.15.0 │ │ ├── build.yaml │ │ └── definition.yaml │ └── luet │ ├── build.yaml │ └── definition.yaml ├── raspbian │ ├── buster │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ ├── buster-boot │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml Build specs Build specs are defined in build.yaml files. They denote the build-time dependencies and conflicts, together with a definition of the content of the package.\nExample of a build.yaml file:\nsteps:- echo \"Luet is awesome\" \u003e /awesomeprelude:- echo \"nooops!\"requires:- name:\"echo\"version:\"\u003e=1.0\"conflicts:- name:\"foo\"version:\"\u003e=1.0\"provides:- name:\"bar\"version:\"\u003e=1.0\"env:- FOO=barincludes:- /awesomeunpack:trueBuilding strategies Luet can create packages with different strategies:\n by delta. Luet will analyze the containers differencies to find out which files got added. You can use the prelude section to exclude certains file during analysis. by taking a whole container content by considering a single directory in the build container. Package by delta By default Luet will analyze the container content and extract any file that gets added to it. The difference is calculated by using the container which is depending on, or either by the container which is created by running the steps in the prelude section of the package build spec:\nprelude:- # do something...steps:- # real work that should be calculated delta overBy omitting the prelude keyword, the delta will be calculated from the parent container where the build will start from.\nPackage by container content Luet can also generate a package content from a container. This is really useful when creating packages that are entire versioned rootfs. To enable this behavior, simply add unpack: true to the build.yaml. This enables the Luet unpacking features, which will extract all the files contained in the container which is built from the prelude and steps fields.\nTo include/exclude single files from it, use the includes and excludes directives.\nPackage by a folder in the final container Similarly, you can tell Luet to create a package from a folder in the build container. To enable this behavior, simply add package_dir: \"/path/to/final/dir\". The directory must represent exactly how the files will be ultimately installed from clients, and they will show up in the same layout in the final archive.\nSo for example, to create a package which ships /usr/bin/mybin, we could write:\npackage_dir:\"/output\"steps:- mkdir -p /output/usr/bin/- echo \"fancy stuff\" \u003e /output/usr/bin/mybin \u0026\u0026 chmod +x /output/usr/bin/mybinBuild time dependencies A package build spec defines how a package is built. In order to do this, Luet needs to know where to start. Hence a package must declare at least either one of the following:\n an image keyword which tells which Docker image to use as base, or a list of requires, which are references to other packages available in the tree. They can’t be both present in the same specfile.\nTo note, it’s not possible to mix package build definitions from different image sources. They must form a unique sub-graph in the build dependency tree.\nOn the other hand it’s possible to have multiple packages depending on a combination of different requires, given they are coming from the same image parent.\nExcluding/including files explictly Luet can also exclude and include single files or folders from a package by using the excludes and includes keyword respecitvely.\nBoth of them are parsed as a list of Golang regex expressions, and they can be combined together to fine-grainly decide which files should be inside the final artifact. You can refer to the files as they were in the resulting package. So if a package produces a /foo file, and you want to exclude it, you can add it to excludes as /foo.\nPackage source image Luet needs an image to kick-off the build process for each package. This image is being used to run the commands in the steps and prelude, and then the image is processed by the building strategies explained above.\nThe image can be resolved either by:\n providing a specific image name with image providing a set of package requirements with requires which will be constructed a new image from. The resulting image is an image linked between each other with the FROM field in the Dockerfile following the SAT solver ordering. providing a set of packages to squash their result from requires and by specifying requires_final_images: true. Note The above keywords cannot be present in the same spec at the same time, or they cannot be combined. But you are free to create further intermediate specs to achieve the desired image. Difference between requires and requires with requires_final_images: true requires generates a graph from all the images of the specfile referenced inside the list. This means it builds a chain of images that are used to build the packages, e.g.: packageA(image: busybox) -\u003e packageB (requires: A) -\u003e packageC (requires: C). The container which is running your build then inherits it’s parents from a chain of order resolution, provided by the SAT solver.\nWhen specifying requires_final_images: true luet builds an artifact for each of the packages listed from their compilation specs and it will later squash them together in a new container image which is then used in the build process to create an artifact.\nThe key difference is about where your build is going to run from. By specifying requires_final_images it will be constructed a new image with the content of each package - while if setting it to false, it will order the images appropriately and link them together with the Dockerfile FROM field. That allows to reuse the same images used to build the packages in the require section - or - create a new one from the result of each package compilation.\nKeywords Here is a list of the full keyword refereces for the build.yaml file.\nconflicts (optional) List of packages which it conflicts with in build time. In the same form of requires it is a list of packages that the current one is conflicting with.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\ncopy since luet\u003e=0.15.0\n(optional) A list of packages/images where to copy files from. It is the Docker multi-stage build equivalent but enhanced with tree hashing resolution.\nTo copy a specific file from a package build container:\nsteps:- ...prelude:- ...copy:- package:category:\"foo\"name:\"bar\"version:\"\u003e=0\"source:\"/foo\"destination:\"/bar\"Any package that is listed in the section will be compiled beforeahead the package, and the file is available both in prelude and steps.\nInternally, it’s rendered as COPY --from=package/image:sha /foo /bar\nTo copy a specific file from an external image:\nsteps:- ...prelude:- ...copy:- image:\"buxybox:latest\"source:\"/foo\"destination:\"/bar\"env (optional) A list of environment variables ( in NAME=value format ) that are expanded in step and in prelude. ( e.g. ${NAME} ).\nenv:- PATH=$PATH:/usr/local/go/bin- GOPATH=/luetbuild/go- GO111MODULE=on- CGO_ENABLED=0- LDFLAGS=\"-s -w\"excludes (optional) List of golang regexes. They are in full path form (e.g. ^/usr/bin/foo ) and indicates that the files listed shouldn’t be part of the final artifact\nWildcards and golang regular expressions are supported. If specified, files which are not matching any of the regular expressions in the list will be excluded in the final package.\nexcludes:- ^/etc/shadow- ^/etc/os-release- ^/etc/gshadowBy combining excludes with includes, it’s possible to include certain files while excluding explicitly some others (excludes takes precedence over includes).\nimage (optional/required) Docker image to be used to build the package.\nimage:\"busybox\"It might be omitted in place of requires, and indicates the image used to build the package. The image will be pulled and used to build the package.\nincludes (optional) List of regular expressions to match files in the resulting package. The path is absolute as it would refer directly to the artifact content.\nWildcards and golang regular expressions are supported. If specified, files which are not matching any of the regular expressions in the list will be excluded in the final package.\nincludes:- /etc$- /etc/lvm$- /etc/lvm/.*- /usr$- /usr/bin$- /usr/bin/cc.*- /usr/bin/c\\+\\+.*- /usr/bin/cpp.*- /usr/bin/g\\+\\+.*Note: Directories are treated as standard entries, so to include a single file, you need also to explictly include also it’s directory. Consider this example to include /etc/lvm/lvm.conf:\nincludes:- /etc$- /etc/lvm$- /etc/lvm/lvm.confjoin since luet\u003e=0.16.0 to be deprecated in luet\u003e=0.18.0 in favor of requires_final_images\n(optional/required) List of packages which are used to generate a parent image from.\nIt might be omitted in place of image or requires, and will generate an image which will be used as source of the package from the final packages in the above list. The new image is used to run eventually the package building process and a new artifact can be generated out of it.\njoin:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nExamples https://github.com/mocaccinoOS/mocaccino-stage3/blob/278e3637cf65761bf01a22c891135e237e4717ad/packages/system/stage3/build.yaml package_dir (optional) A path relative to the build container where to create the package from.\nSimilarly to unpack, changes the building strategy.\nsteps:- mkdir -p /foo/bar/etc/myapp- touch /foo/bar/etc/myapp/configpackage_dir:/foo/barprelude (optional) A list of commands to perform in the build container before building.\nprelude:- |PACKAGE_VERSION=${PACKAGE_VERSION%\\+*} \u0026\u0026 \\ git clone https://github.com/mudler/yip \u0026\u0026 cd yip \u0026\u0026 git checkout \"${PACKAGE_VERSION}\" -b buildrequires (optional/required) List of packages which it depends on.\nA list of packages that the current package depends on in build time. It might be omitted in place of image, and determines the resolution tree of the package itself. A new image is composed from the packages listed in this section in order to build the package\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nrequires_final_images since luet\u003e=0.17.0\n(optional) A boolean flag which instruct luet to use the final images in the requires field.\nBy setting requires_final_images: true in the compilation spec, packages in the requires section will be first compiled, and afterwards the final packages are squashed together in a new image that will be used during build.\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"requires_final_images:truerequires_final_images replaces the use of join, which will be deprecated in luet \u003e=0.18.0.\nstep (optional) List of commands to perform in the build container.\nsteps:- |cd yip \u0026\u0026 make build-small \u0026\u0026 mv yip /usr/bin/yipunpack (optional) Boolean flag. It indicates to use the unpacking strategy while building a package\nunpack:trueIt indicates that the package content is the whole container content.\nRutime specs Runtime specification are denoted in a definition.yaml or a collection.yaml sibiling file. It identifies the package and the runtime contraints attached to it.\ndefinition.yaml:\nname:\"awesome\"version:\"0.1\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"A collection.yaml can be used in place of a definition.yaml to identify a set of packages that instead shares a common build.yaml:\ncollection.yaml:\npackages:- name:\"awesome\"version:\"0.1\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"- name:\"awesome\"version:\"0.2\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"...All the fields (also the ones which are not part of the spec) in the definition.yaml file are available as templating values when rendering the build.yaml file. When running finalizers instead only the fields belonging to the specs are available.\nKeywords Here is a list of the full keyword refereces\nannotations (optional) A map of freeform package annotations:\nannotations:foo:\"bar\"baz:\"test\"category (optional) A string containing the category of the package\ncategory:\"system\"conflicts (optional) List of packages which it conflicts with in runtime. In the same form of requires it is a list of packages that the current one is conflicting with.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\ndescription (optional) A string indicating the package description\nname:\"foo\"description:\"foo is capable of...\"hidden (optional) A boolean indicating whether the package has to be shown or not in the search results (luet search...)\nhidden:truelabels (optional) A map of freeform package labels:\nlabels:foo:\"bar\"baz:\"test\"Labels can be used in luet search to find packages by labels, e.g.:\n$\u003e luet search --by-label foo license (optional) A string indicating the package license type.\nlicense:\"GPL-3\"name (required) A string containing the name of the package\nname:\"foo\"provides (optional) List of packages which the current package is providing.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nrequires (optional) List of packages which it depends on in runtime.\nA list of packages that the current package depends on in runtime. The determines the resolution tree of the package itself.\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nuri (optional) A list of URI relative to the package ( e.g. the official project pages, wikis, README, etc )\nuri:- \"http://www.mocaccino.org\"- ...version (required) A string containing the version of the package\nversion:\"1.0\"Refering to packages from the CLI All the luet commands which takes a package as argument, respect the following syntax notation:\n cat/name: will default to selecting any available package =cat/name: will default to gentoo parsing with regexp so also =cat/name-1.1 works cat/name@version: will select the specific version wanted ( e.g. cat/name@1.1 ) but can also include ranges as well cat/name@\u003e=1.1 name: just name, category is omitted and considered empty Finalizers Finalizers are denoted in a finalize.yaml file, which is a sibiling of definition.yaml and build.yaml file. It contains a list of commands that finalize the package when it is installed in the machine.\nfinalize.yaml:\ninstall:- rc-update add docker defaultKeywords install: List of commands to run in the host machine. Failures are eventually ignored, but will be reported and luet will exit non-zero in such case. ","categories":"","description":"Luet specfile syntax\n","excerpt":"Luet specfile syntax\n","ref":"/docs/concepts/packages/specfile/","tags":"","title":"Specfile"},{"body":"Installing a package To install a package with luet, simply run:\n$ luet install \u003cpackage_name\u003e To relax dependency constraints and avoid auto-upgrades, add the --relax flag:\n$ luet install --relax \u003cpackage name\u003e To install only the package without considering the deps, add the --nodeps flag:\n$ luet install --nodeps \u003cpackage name\u003e To install only package dependencies, add the --onlydeps flag:\n$ luet install --onlydeps \u003cpackage name\u003e To only download packages, without installing them use the --download-only flag:\n$ luet install --download-only \u003cpackage name\u003e Uninstalling a package To uninstall a package with luet, simply run:\n$ luet uninstall \u003cpackage_name\u003e Upgrading the system To upgrade your system, simply run:\n$ luet upgrade Refreshing repositories Luet automatically syncs repositories definition on the machine when necessary, but it avoids to sync up in a 24h range. In order to refresh the repositories manually, run:\n$ luet repo update Searching a package To search a package:\n$ luet search \u003cregex\u003e To search a package and display results in a table:\n$ luet search --table \u003cregex\u003e To look into the installed packages:\n$ luet search --installed \u003cregex\u003e Note: the regex argument is optional\nSearch file belonging to packages $ luet search --file \u003cfile_pattern\u003e Search output Search can return results in the terminal in different ways: as terminal output, as json or as yaml.\nJSON $ luet search --json \u003cregex\u003e YAML $ luet search --yaml \u003cregex\u003e Tabular $ luet search --table \u003cregex\u003e Quiet luet output Luet output is verbose by default and colourful, however will try to adapt to the terminal, based on which environment is executed (as a service, in the terminal, etc.)\nYou can quiet luet output with the --quiet flag or -q to have a more compact output in all the commands.\n","categories":"","description":"How to install packages, manage repositories, ...\n","excerpt":"How to install packages, manage repositories, ...\n","ref":"/docs/concepts/overview/usage/","tags":"","title":"CLI usage"},{"body":" Warning This article contains references to Luet repositories that were deprecated, and needs to be updated. Please refer to the “Hello World” tutorial instead. Catclock example In this example, we will build the awesome CatClock on containers we will run it locally in a Luet box.\nWe will do this experiment to prove two things:\n how we can build a package with Luet and two packages from different distributions can (sometime) work together. Prerequisites To build packages with Luet, you must have installed Docker and container-diff, follow our setup guide.\n1) Create the package To prove our point, we will build our package from an OpenSUSE image, and later on we will consume entropy repositories for runtime dependencies. To note, this is not the main focus of Luet, and this is a restricted example on its features on build-time resolution. For more syntax examples, see also Build specs and Package types.\nRun this commands in any directory you choose to be your workspace:\n# Let's create a directory to store our package spec: mkdir -p tree/misc/catclock/ 1.1) Build spec Now, let’s generate our build spec:\n# Create a build file. We use here opensuse/leap to build the package, as an example cat \u003c\u003cEOF \u003e tree/misc/catclock/build.yaml image: opensuse/leap # Preparation phase prelude: - zypper in -y git make libXt-devel xmh gcc motif-devel libXext-devel libpulse-devel libaubio-devel - git clone https://github.com/BarkyTheDog/catclock # Here we define the steps that Luet will follow steps: - cd catclock \u0026\u0026 make DEFINES=\"-Wno-incompatible-pointer-types\" - mv catclock/xclock /usr/bin/xclock # (optional) File list that will be included in the final package # Luet will filter out files that won't match any entry in the list (regex syntax IS supported) includes: - /usr/bin/xclock EOF build.yaml is what an ebuild is for Gentoo and for e.g. what PKGBUILD is for Arch.\n image: opensuse/leap tells luet to use opensuse/leap as a build image. We collect the build time dependencies with zypper (the openSUSE package manager), and the CatClock with git. When we declare an image keyword in a spec, it becomes a seed package ( Package types ) as doesn’t depend on any package in build time, we will cover more use cases in other examples. prelude is a list of commands that will happen during the build phase. They might generate binaries, or download sources, but those are not took into consideration when generating the final package. steps is a list of commands that will happen during the build phase. Luet will execute those commands and all the binaries generated from them become part of the final package includes is a (optional) list of regex that tells to Luet what files to filter out from the final artifact. 1.2) Runtime spec Now we generate the runtime spec, it’s the part about the binary end which will be installed in the system. It also holds the metadata relative to the package definition (name, category, version).\n# Create a runtime definition. # We will leverage packages already present on Sabayon Entropy repositories # the end-system needs to have the Luet Sabayon Entropy repositories enabled. cat \u003c\u003cEOF \u003e tree/misc/catclock/definition.yaml category: \"misc\" name: \"catclock\" version: \"0.20200318\" requires: - category: meta name: users version: \"\u003e=0\" - category: x11-libs name: motif version: \"\u003e=0.1\" - category: media-libs name: libjpeg-turbo version: \"\u003e=0.1\" EOF category, name, and version: identifies the package in a Luet tree. This is the unique identifier for a package. requires it’s a list of packages which our catclock depends on during runtime (when we will execute catclock inside a small-container!). To find out what’s required by your binaries it can be a try-learn-fail effort. If the package you wish to build is specifying the deps it requires, and those are available in a Luet repository, you are all set, just point them there. Otherwise you have to figure out after you build the binary the first time (for example, with ldd) to which libraries it depends on. In this example we consume the dependencies from the Luet Entropy Repo, that we will enable on the following steps. 2) Build it! sudo /usr/bin/luet build \\ --tree=$PWD/tree misc/catclock \\ --destination $PWD/build \\ --compression gzip sudo chown -R $USER $PWD/build # So later on, we can access to the repository with our user We are building the specs in this step.\n tree: is the path where our specs are, in our case it’s tree. destination: is the path where our packages will be stored, in our case this is build. compression: is the compression algorithm used to compress the final artifacts Note, we need sudo to keep the permissions properly mapped in the artifact which is produced this is not always the case. Depends on the package content.\n3) Create a local repository We will generate now our repository metadata:\n/usr/bin/luet create-repo --tree \"tree\" \\ --output $PWD/build \\ --packages $PWD/build \\ --name \"test repo\" \\ --descr \"Test Repo\" \\ --tree-compression gzip \\ --meta-compression gzip Creating a repository in Luet is about adding metadata and make our spec tree available to other systems running Luet to intall the package.\n output: a path which is where Luet will store the repository metadata. packages: a path containing the packages that were built during the build step name: Repository name descr: Repository description tree-compression: optional, algorithm to use when compression the tree metadata meta-compression: optional, algorithm to use when compression the repository metadata 4) Let’s test it! Now we are all set. We have the packages compiled, and we are ready to consume them. We don’t want to break our host system, and we want to test this from our user.\nLet’s create a directory, we will try to setup a full running system, and install everything there.\n# Let's create a directory for our \"fake\" rootfilesystem # it will be populated with a minimal set of packages needed to run # our amazing catclock mkdir -p $PWD/rootfs # Let's also create a directory to store our config files mkdir -p $PWD/conf We will generate now a Luet config. The Luet config is used to read where install things from, and in which directory. It also lists the repositories that are used by the client to retrieve packages remotely.\n# We create here a config file which references the rootfs. # In this way, luet instead installing packages to your host system, will populate the rootfs # (note, all the steps are run by a user here, no root required!) cat \u003c\u003cEOF \u003e conf/luet-dso-local.yaml system: rootfs: $PWD/rootfs # our \"fake\" rootfs that we created before database_path: \"/\" # this is where our Luet DB will live database_engine: \"boltdb\" # this is the Luet DB engine repositories: - name: \"main\" type: \"disk\" priority: 3 enable: true urls: - \"$PWD/build\" # This is the repository we have created before! - name: \"sabayonlinux.org\" description: \"Sabayon Linux Repository\" type: \"http\" enable: true cached: true priority: 2 urls: - \"https://dispatcher.sabayon.org/sbi/namespace/luet-entropy-repo\" - name: \"luet-repo\" description: \"Luet Official Repository\" type: \"http\" enable: true cached: true priority: 1 urls: - \"https://raw.githubusercontent.com/Luet-lab/luet-repo/gh-pages\" EOF # we have specified an additional repository, one that is luet-entropy-repo (which contains # the runtime dependencies we specified in our package) # Let's populate our rootfs with some minimal things: base-gcc, and bash # meta/users is a meta package providing minimal base to run things with a full # user-level support. export LUET_NOLOCK=true luet install \\ --config $PWD/conf/luet-dso-local.yaml \\ meta/users # catclock is a X11 app! we want to be able to play with it locally from our host :) # Let's copy the .Xauthority file to allow the X app to communicate with our X server # Note: This can be achieved in other ways (set up a tcp X server, and so on) cp -rfv $HOME/.Xauthority $PWD/rootfs/ luet install \\ --config $PWD/conf/luet-dso-local.yaml \\ misc/catclock # Let's run our beautiful catclock :) luet box exec --rootfs $PWD/rootfs \\ --stdin --stdout --stderr --env DISPLAY=$DISPLAY \\ --env XAUTHORITY=/.Xauthority --mount /tmp --entrypoint /usr/bin/xclock Spawn a bash shell inside our box (with permission to access to our running X):\nluet box exec --rootfs $PWD/rootfs \\ --stdin --stdout --stderr --env DISPLAY=$DISPLAY \\ --env XAUTHORITY=/.Xauthority --mount /tmp --entrypoint /bin/bash ","categories":"","description":"Example on how to build a package and run it locally with luet box\n","excerpt":"Example on how to build a package and run it locally with luet box\n","ref":"/docs/tutorials/build_package/","tags":"","title":"Build a package"},{"body":"Luet can be extended in 2 ways by extensions and plugins.\nBefore you begin You need to have a working luet binary installed.\nExtensions Extensions expand Luet featureset horizontally, so for example, “luet geniso” will allow you to build an iso using luet, without this needing to be part of the luet core.\nAn Extension is nothing more than a standalone executable file, whose name begins with luet-. To install an extension, simply move its executable file to anywhere on your system PATH.\nAll the plugins will be accessible to luet as luet pluginname\nWriting an Extension You can write an extension in any programming language or script that allows you to write command-line commands.\nExecutables receive the inherited environment from luet. An extension determines which command path it wishes to implement based on its name. For example, a plugin wanting to provide a new command luet foo, would simply be named luet-foo, and live somewhere in your PATH.\nExample Extension #!/bin/bash if [[ \"$1\" == \"help\" ]] then echo \"Extension help\" exit 0 fi if [[ \"$1\" == \"run\" ]] then # do something interesting fi echo \"I am an Extension named luet-foo\" Using an Extension To use the above extension, simply make it executable:\n$ sudo chmod +x ./luet-foo and place it anywhere in your PATH:\n$ sudo mv ./luet-foo /usr/local/bin You may now invoke your extension as a luet command:\n$ luet foo I am an Extension named luet-foo All args and flags are passed as-is to the executable:\n$ luet foo help Extension help Plugins Plugins instead are expanding Luet vertically by hooking into internal events. Plugins and Extensions can be written in any language, bash included! Luet uses go-pluggable so it can dispatch events to external binaries.\nSimilarly to Extensions, a Plugin is nothing more than a standalone executable file, but without any special prefix. To install a plugin, simply move its executable file to anywhere on your system PATH.\nDifferently from Extensions, they are not available from the CLI and cannot be invoked directly by the user, instead they are called by Luet during its lifecycle.\nWriting a Plugin You can write a plugin in any programming language or script.\nThe first argument that is passed to a plugin will always be the event that was emitted by Luet in its lifecycle. You can see all the events available here. The second argument, is a JSON encoded payload of the object that Luet is emitting with the event. The object(s) may vary depending on the emitted event.\nThe output of the plugin (stdout) will be parsed as JSON. Every plugin must return a valid JSON at the end of its execution, or it will be marked as failed and stops luet further execution. See also the go-pluggable README.\nThe returning payload should be in the following form:\n{ \"state\": \"\", \"data\": \"data\", \"error\": \"\"} By returning a json with the error field not empty, it will make fail the overall execution.\nExample Plugin #!/bin/bash echo \"$1\" \u003e\u003e /tmp/event.txt echo \"$2\" \u003e\u003e /tmp/payload.txt echo \"{}\" Using a plugin To use the above plugin, simply make it executable:\n$ sudo chmod +x ./test-foo and place it anywhere in your PATH:\n$ sudo mv ./test-foo /usr/local/bin Now, when running luet, add --plugin test-foo:\n$ luet --plugin test-foo install -y foopackage And check /tmp/event.txt to see the event fired and /tmp/payload.txt to check the payloads that were emitted by Luet.\nConcrete example A plugin that prints the images that are being built in /tmp/exec.log:\n#!/bin/bash exec \u003e\u003e /tmp/exec.log exec 2\u003e\u00261 event=\"$1\" payload=\"$2\" if [ \"$event\" == \"image.post.build\" ]; then image=$(echo \"$payload\" | jq -r .data | jq -r .ImageName ) echo \"{ \\\"data\\\": \\\"$imagebuilt\\\" }\" else echo \"{}\" fi ","categories":"","description":"Extend luet with plugins and extensions\n","excerpt":"Extend luet with plugins and extensions\n","ref":"/docs/concepts/plugins-and-extensions/","tags":"","title":"Plugins and Extensions"},{"body":"Luet supports the sprig rendering engine template, like helm. It’s being used to interpolate build.yaml and finalize.yaml files before their execution. The following document assumes you are familiar with the helm templating.\nThe build.yaml and finalize.yaml files are rendered during build time, and it’s possible to use the helm templating syntax inside such files. The definition.yaml file will be used to interpolate templating values available in build.yaml\nGiven the following definition.yaml:\nname:\"test\"category:\"foo\"version:\"1.1\"additional_field:\"baz\"A build.yaml can look like the following, and interpolates it’s values during build time:\nimage:...steps:- echo {{.Values.name}} \u003e /package_name- echo {{.Values.additional_field}} \u003e /extraWhich would be for example automatically rendered by luet like the following:\nimage:...steps:- echo test \u003e /package_name- echo baz \u003e /extraThis mechanism can be used in collections as well, and each stanza in packages is used to interpolate each single package.\nInterpolating globally It’s possible to interpolate during build phase all the package specs targeted for build with the --values flag, which takes a yaml file of an arbitrary format, if variables are clashing, the yaml supplied in --values takes precedence and overwrite the values of each single definition.yaml file.\nShared templates Since luet 0.17.5 it is possible to share templates across different packages. All templates blocks found inside the templates folder inside the root luet tree of a repository gets templated and shared across all the packages while rendering each compilation spec of the given tree.\nConsider the following:\nshared_templates ├── templates │ └── writefile.yaml └── test ├── build.yaml └── collection.yaml collection.yaml We define here two packages with a collection. They will share the same compilation spec to generate two different packages packages:- category:\"test\"name:\"foo\"version:\"1.0\"- category:\"test\"name:\"bar\"version:\"1.0\" Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/collection.yaml writefile.yaml All the files in the templates folder will get rendered by the template for each package in the tree. We define here a simple block to write out a file from the context which is passed by: {{define \"writefile\" }}- echo conflict \u003e /foo/{{.}}{{end}} Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/templates/writefile.yaml build.yaml Finally the build spec consumes the template block we declared above, passing by the name of the package: image:\"alpine\"prelude:- mkdir /foosteps:{{template \"writefile\" .Values.name }}package_dir:/foo Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/build.yaml Limitations The finalize.yaml file has access only to the package fields during templating. Extra fields that are present in the definition.yaml file are not accessible during rendering in the finalize.yaml file, but only the package fields (name, version, labels, annotations, …)\nReferences Sprig docs Helm Templating functions Helm Templating variable Examples https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/tar ","categories":"","description":"Use templates to fine tune build specs\n","excerpt":"Use templates to fine tune build specs\n","ref":"/docs/concepts/packages/templates/","tags":"","title":"Templated packages"},{"body":" Warning This article is outdated. Please refer to the “Hello World” tutorial instead. Here we show an example on how to build “burnable” SD images for Raspberry Pi with Luet. This approach lets you describe and version OTA upgrades for your embedded devices, delivering upgrades as layer upgrades on the Pi.\nThe other good side of the medal is that you can build a Luet package repository with multiple distributions (e.g. Raspbian, OpenSUSE, Gentoo, … ) and switch among them in runtime. In the above example Raspbian and Funtoo (at the time of writing) are available.\nPrerequisites You have to run the following steps inside an ARM board to produce arm-compatible binaries. Any distribution with Docker will work. Note that the same steps could be done in a cross-compilation approach, or with qemu-binfmt in a amd64 host.\nYou will also need in your host:\n Docker Luet installed (+container-diff) in /usr/bin/luet (arm build) make Build the packages Clone the repository https://github.com/Luet-lab/luet-embedded\n$\u003e git clone https://github.com/Luet-lab/luet-embedded $\u003e cd luet-embedded $\u003e sudo make build-all ... If a rebuild is needed, just do sudo make rebuild-all after applying the changes.\nCreate the repository $\u003e sudo make create-repo ... Serve the repo locally $\u003e make serve-repo ... Create the flashable image Funtoo based system $\u003e sudo LUET_PACKAGES='distro/funtoo-1.4 distro/raspbian-boot-0.20191208 system/luet-develop-0.5' make image ... Raspbian based system $\u003e sudo LUET_PACKAGES='distro/raspbian-0.20191208 distro/raspbian-boot-0.20191208 system/luet-develop-0.5' make image ... At the end of the process, a file luet_os.img, ready to be flashed to an SD card, should be present in the current directory.\nAdd packages In order to build and add packages to the exiting repository, simply add or edit the specfiles under the distro folder. When doing make rebuild-all the packages will be automatically compiled and made available to the local repository.\n","categories":"","description":"Use Luet to build, track, and release OTA update for your embedded devices.\n","excerpt":"Use Luet to build, track, and release OTA update for your embedded …","ref":"/docs/resources/arm/","tags":"","title":"ARM images"},{"body":"Simple package build Creating and building a simple package:\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" EOF $\u003e luet build --all 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... Build packages In order to build a specific version, a full package definition (triple of category, name and version) has to be specified. In this example we will also enable package compression (gzip).\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" EOF $\u003e luet build bar/foo-0.1 --compression gzip 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... ","categories":"","description":"Examples to build with Luet\n","excerpt":"Examples to build with Luet\n","ref":"/docs/resources/building/","tags":"","title":"Building"},{"body":"Collections are a special superset of packages. To define a collection, instead of using a definition.yaml file, create a collection.yaml file with a list of packages:\npackages:- category:\"test\"name:\"foo\"version:\"1.0\"- category:\"test\"name:\"bar\"version:\"1.0\" Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/collection.yaml Packages under a collection shares the same build.yaml and finalize.yaml, so a typical package layout can be:\ncollection/ collection.yaml build.yaml finalize.yaml ... additional files in the build context Luet during the build phase, will treat packages of a collection individually. A collection is a way to share the same build process across different packages.\nTemplating The templating mechanism can be used in collections as well, and each stanza in packages is used to interpolate each single package.\nExamples https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/entities https://github.com/mocaccinoOS/portage-tree/tree/master/multi-arch/packages/groups https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/X ","categories":"","description":"Group a set of package build spec with templating\n","excerpt":"Group a set of package build spec with templating\n","ref":"/docs/concepts/packages/collections/","tags":"","title":"Collections"},{"body":"Under the hood, Luet uses boolean satisfiability problem (SAT) reinforcement learning techniques to solve package constraints.\nLuet allows you to specify 3 types of set of contraints on a package definition:\n Requires Conflicts Provides The package definition in your tree definition, along with its Requires and Conflicts, are turned into Boolean formulas that are consumed by the solver to compute a solution. The solution represent the state of your system after a particular query is asked to the solver (Install, Uninstall, Upgrade).\nRequires and Conflicts A list of requires and conflicts, composed of one or more packages, becomes a SAT formula. The formula is then given to the SAT solver to compute a finite state set of packages which must be installed in the system in order to met the requirements.\nAs Luet allows to express constraints with selectors ( e.g. A depends on \u003e=B-1.0) it generates additional constraints to guarantee that at least one package and at most one is picked as dependency (ALO and AMO).\nProvides Provides constraints are not encoded in a SAT formula. Instead, they are expanded into an in-place substitution of the packages that they have to be replaced with. They share the same SAT logic of expansion, allowing to swap entire version ranges (e.g. \u003e=1.0), allowing to handle package rename, removals, and virtuals.\nReferences OPIUM (Luet is inspired by it): https://ranjitjhala.github.io/static/opium.pdf FROM TRACTABLE CSP TO TRACTABLE SAT: https://www.cs.ox.ac.uk/files/4014/maxclosed_orderencoding_v16_TR.pdf Solver concepts applied to packages (zypper): https://en.opensuse.org/openSUSE:Libzypp_satsolver_basics ","categories":"","description":"How Luet turns Image resolution into CSP\n","excerpt":"How Luet turns Image resolution into CSP\n","ref":"/docs/concepts/overview/constraints/","tags":"","title":"CSP, SAT \u0026\u0026 RL"},{"body":"Can’t build packages There might be several reasons why packages fails to build, for example, if your build fails like this:\n$ luet build ... INFO Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? ERROR Error: Failed compiling development/toolchain-go-0.6: failed building package image: Could not push image: quay.io/mocaccino/micro-toolchain:latest toolchain-go-development-0.6-builder.dockerfile: Could not build image: quay.io/mocaccino/micro-toolchain:latest toolchain-go-development-0.6-builder.dockerfile: Failed running command: : exit status 1 ERROR Bailing out means the user you are running the build command can’t either connect to docker or docker is not started.\nCheck if the user you are running the build is in the docker group, or if the docker daemon is started.\nLuet by default if run with multiple packages summarize errors and can be difficult to navigate to logs, but if you think you might have found a bug, run the build with --debug before opening an issue.\nWhy the name luet? Well, I have the idea that programs should be small, so they are not difficult to type and easy to remember, and easy to stick in. luet is really a combination of the first letters of my fiancee name (Lucia) and my name (Ettore) lu+et = luet! and besides, happen to be also a small bridge in Italy ;)\n","categories":"","description":"FAQ\n","excerpt":"FAQ\n","ref":"/docs/resources/faq/","tags":"","title":"Frequently Asked Questions"},{"body":"The Docker image quay.io/luet/base is a scratch Docker image always kept up-to-date with the latest luet version. That image can be used to bootstrap new images with Luet repositories with the packages you want, from the repositories you prefer.\nFor example we can mount a config file, and later on install a package:\ncat \u003c\u003cEOF \u003e $PWD/luet.yaml repositories: - name: \"micro-stable\" enable: true cached: true priority: 1 type: \"http\" urls: - \"https://get.mocaccino.org/mocaccino-micro-stable\" EOF docker rm luet-runtime-test || true docker run --name luet-runtime-test \\ -ti -v /tmp:/tmp \\ -v $PWD/luet.yaml:/etc/luet/luet.yaml:ro \\ quay.io/luet/base install shells/bash docker commit luet-runtime-test luet-runtime-test-image # Try your new image! docker run -ti --entrypoint /bin/bash --rm luet-runtime-test-image In this way we will create a new image, with only luet and bash, and nothing else from a scratch image.\n","categories":"","description":"Using Luet to compose images from scratch\n","excerpt":"Using Luet to compose images from scratch\n","ref":"/docs/resources/scratch/","tags":"","title":"Images from scratch"},{"body":"","categories":"","description":"Howtos, Cookbooks \n","excerpt":"Howtos, Cookbooks \n","ref":"/docs/tutorials/","tags":"","title":"Tutorials"},{"body":"","categories":"","description":"Luet examples, resources, API reference\n","excerpt":"Luet examples, resources, API reference\n","ref":"/docs/resources/","tags":"","title":"Resources"},{"body":"Luet is a Package Manager based on containers. It provides an abstraction layer over container specfile format, enhancing the image resolution process of open container inititative (OCI) runtimes with boolean satisfiability problem (SAT) solving techniques.\nLuet can be used to build packages, container images, as well as to manage and distribute installations of derived packages locally.\nAllows to apply semver constraints to Image dependencies, treating it as a classical CSP.\n ","categories":"","description":"","excerpt":"Luet is a Package Manager based on containers. It provides an …","ref":"/docs/","tags":"","title":"Documentation"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/news/","tags":"","title":"News About Luet"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/releases/","tags":"","title":"New Releases"},{"body":"References Here is a list of references to projects that are related to Luet (open up a PR to add yours to the list!):\n Description URL Official Luet repository https://github.com/Luet-lab/luet-repo Example repository to host package browser websites on gh-pages. It uses the package-browser extension to generate HTML pages from a list of luet repositories https://github.com/Luet-lab/package-browser-sample LineageOS builds with luet https://github.com/mudler/android-builds Example repository template to build packages on github actions and push packages on a container registry https://github.com/Luet-lab/github-repository Immutable container OS toolkit https://github.com/rancher-sandbox/cOS-toolkit mocaccinoOS desktop https://github.com/mocaccinoOS/desktop mocaccinoOS extra https://github.com/mocaccinoOS/mocaccino-extra ","categories":"","description":"References to various resources related to luet","excerpt":"References to various resources related to luet","ref":"/docs/resources/references/","tags":"","title":"References"},{"body":"Contributing to Luet Contribution guidelines for the Luet project are on the Github repository. Here you can find some heads up for contributing to the documentation website.\nContributing to the Docs website We Develop with Github We use github to host code, to track issues and feature requests, as well as accept pull requests.\nWe use Hugo to format and generate our website, the Docsy theme for styling and site structure, and Github Actions to manage the deployment of the site. Hugo is an open-source static site generator that provides us with templates, content organisation in a standard directory structure, and a website generation engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.\nAll submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.\nAny contributions you make will be under the Software License of the repository In short, when you submit code changes, your submissions are understood to be under the same License that covers the project. Feel free to contact the maintainers if that’s a concern.\nUpdating a single page If you’ve just spotted something you’d like to change while using the docs, Docsy has a shortcut for you:\n Click Edit this page in the top right hand corner of the page you want to modify. If you don’t already have an up to date fork of the project repo, you are prompted to get one - click Fork this repository and propose changes or Update your Fork to get an up to date version of the project to edit. The appropriate page in your fork is displayed in edit mode. Quick start with a local checkout Here’s a quick guide to updating the docs with a git local checkout. It assumes you’re familiar with the GitHub workflow and you’re happy to use the automated preview of your doc updates:\n Fork the the Docs repo on GitHub. Make your changes, to see the preview run make serve and browse to localhost:1313 If you’re not yet ready for a review, add “WIP” to the PR name to indicate it’s a work in progress. Continue updating your doc and pushing your changes until you’re happy with the content. When you’re ready for a review, add a comment to the PR, and remove any “WIP” markers. When you are satisfied send a pull request (PR). License By contributing, you agree that your contributions will be licensed under the project Licenses.\n","categories":"","description":"","excerpt":"Contributing to Luet Contribution guidelines for the Luet project are …","ref":"/docs/contribution-guidelines/","tags":"","title":"Contributing"},{"body":"This release comes with a lot of bugfixes and enhancement to the SAT solver core:\n Add support for provides. They allow to have virtual packages which can be replaced during solving by other drop-in packages. Tons of fixes Preparation for upcoming compression support ","categories":"","description":"X-Mas release!\n","excerpt":"X-Mas release!\n","ref":"/blog/2019/12/23/0.3-release/","tags":"","title":"0.3 Release"},{"body":"Finally the website is up! Docs are a work in progress. Stay tuned for more upcoming updates\n","categories":"","description":"Website is up\n","excerpt":"Website is up\n","ref":"/blog/2019/12/23/website-is-up/","tags":"","title":"Website is up"},{"body":"","categories":"","description":"","excerpt":"","ref":"/index.json","tags":"","title":""},{"body":" #td-cover-block-0 { background-image: url(/about/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_806797_960x540_fill_q75_catmullrom_bottom.jpg); } @media only screen and (min-width: 1200px) { #td-cover-block-0 { background-image: url(/about/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_806797_1920x1080_fill_q75_catmullrom_bottom.jpg); } } About Luet Luet is a Package Manager which uses Containers technologies. Luet uses Container technologies ( Docker, img ) to build packages. It provides an abstraction over the Dockerfile format introducing relation and versioning of images.\n Zero-deps installer The installer can run in \"from scratch\" environment - your system will be always recoverable - everything which was built from containers can be installed locally. In few commands it allows you to switch between multiple Linux Distributions, in runtime! ","categories":"","description":"","excerpt":" #td-cover-block-0 { background-image: …","ref":"/about/","tags":"","title":"About Luet"},{"body":"This is the blog section. It has two categories: News and Releases.\nFiles in these directories will be listed in reverse chronological order.\n","categories":"","description":"","excerpt":"This is the blog section. It has two categories: News and Releases. …","ref":"/blog/","tags":"","title":"Luet Blog"},{"body":"","categories":"","description":"","excerpt":"","ref":"/community/","tags":"","title":"Community"},{"body":" #td-cover-block-0 { background-image: url(/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_291319_960x540_fill_q75_catmullrom_top.jpg); } @media only screen and (min-width: 1200px) { #td-cover-block-0 { background-image: url(/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_291319_1920x1080_fill_q75_catmullrom_top.jpg); } } Luet Documentation Download Container Package Manager\n Luet uses Container technologies ( Docker, img ) to build packages. It provides an abstraction over the Dockerfile format introducing relation and versioning of images.\n SAT Solver Luet uses SAT Solving techniques to compute the dependencies graph. This allows to refer to docker images by using semver constraints.\nNo Relational db is involved.\n Contributions welcome! If you like to play with code, check out our issues that are marked as “good first issue” and open a Pull Request on GitHub. New users are always welcome, and have fun!\n Read more …\n Container-based Use container abstraction to define your package repositories\n Releasing is not anymore a nightmare You can carefully pick now dependencies to make your release - release composed of container images or either of a set of packages Package Management Build, ship and delivery your software. Faster\n 0 dep installer When Luet is used as installer, it has zero dependencies.\nYour system can’t break anymore\n Reconstruct images Thanks to its SAT core, Luet can reconstruct images defined by dependencies and version constraints.\nBuilding a de-facto tree of container images\n ","categories":"","description":"","excerpt":" #td-cover-block-0 { background-image: …","ref":"/","tags":"","title":"Luet docs"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"}]
\ No newline at end of file
+[{"body":"Prerequisistes Luet currently supports Docker and Img as backends to build packages. Both of them can be used and switched in runtime with the --backend option, so either one of them must be present in the host system.\nDocker Docker is the (less) experimental Luet engine supported. Be sure to have Docker installed and the daemon running. The user running luet commands needs the corresponding permissions to run the docker executable, and to connect to a docker daemon. The only feature needed by the daemon is the ability to build images, so it fully supports remote daemon as well (this can be specified with the DOCKER_HOST environment variable, that is respected by luet)\nImg Luet supports Img. To use it, simply install it in your system, and while running luet build, you can switch the backend by providing it as a parameter: luet build --backend img. For small packages it is particularly powerful, as it doesn’t require any docker daemon running in the host.\nBuilding packages on Kubernetes Luet and img can be used together to orchestrate package builds also on kubernetes. There is available an experimental Kubernetes CRD for Luet which allows to build packages seamelessly in Kubernetes and push package artifacts to an S3 Compatible object storage (e.g. Minio).\nBuilding packages Luet provides an abstraction layer on top of the container image layer to make the package a first class construct. A package definition and all its dependencies are translated by Luet to Dockerfiles which can then be built anywhere that docker runs.\nTo resolve the dependency tree Luet uses a SAT solver and no database. It is responsible for calculating the dependencies of a package and to prevent conflicts. The Luet core is still young, but it has a comprehensive test suite that we use to validate any future changes.\nBuilding a package with Luet requires only a definition. This definition can be self-contained and be only composed of one specfile, or a group of them, forming a Luet tree. For more complex use-cases, see collections.\nRun luet build --help to get more help for each parameter.\nBuild accepts a list of packages to build, which syntax is in the category/name-version notation. See also specfile documentation page to see how to express packages from the CLI.\nEnvironmental variables Luet builds passes its environment variable at the engine which is called during build, so for example the environment variable DOCKER_HOST or DOCKER_BUILDKIT can be setted.\nEvery argument from the CLI can be setted via environment variable too with a LUET_ prefix, for instance the flag --clean, can be setted via environment with LUET_CLEAN, --privileged can be enabled with LUET_PRIVILEGED and so on.\nSupported compression format At the moment, luet can compress packages and tree with zstd and gzip. For example:\nluet build --compression zstd ... Will output package compressed in the zstd format.\nSee the --help of create-repo and build to learn all the available options.\nExample A package definition is composed of a build.yaml and a sibiling definition.yaml.\nIn the following example, we are creating a dummy package (bar/foo). Which ships one file only, /foo\n$\u003e # put yourself in some workdir $~/workdir\u003e mkdir package $~/workdir\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo=bar\" \u003e /foo EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" EOF To build it, simply run luet build bar/foo or luet build --all to build all the packages in the current directory:\n$\u003e luet build --all 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... Luet “trees” are just a group of specfiles, in the above example, our tree was the current directory. You can also specify a directory with the --tree option. Luet doesn’t enforce any tree layout, so they can be nested at any level. The only rule of thumb is that a build.yaml file needs to have either a definition.yaml or a collection.yaml file next to it.\nNesting dependencies In the example above we have created a package from a delta. Luet by default creates packages by analyzing the differences between the generated containers, and extracts the differences as archive, the resulting files then are compressed and can be consumed later on by luet install.\nLuet can create packages from different building strategies: by delta, by taking a whole container content, or by considering a single directory in the build container.\nBesides that, a package can reference a strict dependency on others.\nExample Let’s extend the above example with two packages which depends on it during the build phase.\n$~/workdir\u003e mkdir package2 $~/workdir\u003e cat \u003c\u003cEOF \u003e package2/build.yaml requires: - name: \"foo\" category: \"bar\" version: \"\u003e=0\" steps: - source /foo \u0026\u0026 echo \"$foo\" \u003e /bar EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package2/definition.yaml name: \"ineedfoo\" version: \"0.1\" category: \"bar\" EOF $~/workdir\u003e mkdir package3 $~/workdir\u003e cat \u003c\u003cEOF \u003e package3/build.yaml requires: - name: \"foo\" category: \"bar\" version: \"\u003e=0\" - name: \"ineedfoo\" category: \"bar\" version: \"\u003e=0\" steps: - source /foo \u0026\u0026 echo \"$foo\" \u003e /ineedboth - cat /bar \u003e /bar EOF $~/workdir\u003e cat \u003c\u003cEOF \u003e package3/definition.yaml name: \"ineedfooandbar\" version: \"0.1\" category: \"bar\" EOF To build, run again:\n$\u003e luet build --all As we can see, now Luet generated 3 packages, bar/foo, bar/ineedfoo and bar/ineedfooandbar. They aren’t doing anything special than just shipping text files, this is an illustrative example on how build requirements can be combined to form new packages:\nbar/ineedfooandbar depends on both bar/ineedfoo and bar/foo during build-time, while bar/foo uses a docker image as a build base.\nSee the package definition documentation page for more details on how to instruct the Luet compiler to build packages with different strategies.\nCaching docker images Luet can push and pull the docker images that are being generated during the build process. A tree is represented by a single docker image, and each package can have one or more tags attached to it.\nTo push automatically docker images that are built, use the --push option, to pull, use the --pull option. An image repository can be specified with --image-repository flag, and can include also the remote registries where the images are pushed to.\nLuet doesn’t handle login to registries, so that has to be handled separately with docker login or img login before the build process starts.\nBuild faster When packages are cached, for iterating locally it’s particularly useful to jump straight to the image that you want to build. You can use --only-target-package to jump directly to the image you are interested in. Luet will take care of checking if the images are present in the remote registry, and would build them if any of those are missing.\nNotes All the files which are next to a build.yaml are copied in the container which is running your build, so they are always accessible during build time. If you notice errors about disk space, mind to set the TMPDIR env variable to a different folder. By default luet respects the O.S. default (which in the majority of system is /tmp). ","categories":"","description":"How to build packages with Luet\n","excerpt":"How to build packages with Luet\n","ref":"/docs/concepts/overview/build_packages/","tags":"","title":"Building packages"},{"body":"This article will guide you to build your first package with Luet! For this purpose, we have picked a real-world example: gogs which is a “painless self-hosted Git service”, an open-source alternative to Github.\nGogs is written in Golang, and we need a working Golang version in order to build it.\nHere you can see a live recorded session of this tutorial:\n Define a Luet tree Everything starts from a Luet tree. A Luet tree is just a directory containing one (or more) Luet specfile, here on we assume that you are working in a dedicated folder (e.g. ~/demo) in your system.\nLet’s create then a package that will be our base to build other packages from now on, we have picked busybox here - it is really small and enough for our purpose.\nbusybox mkdir busybox Let’s now write the build specification, which is just containing the image tag that we are referencing to\ncat \u003c\u003cEOF \u003e busybox/build.yaml image: \"busybox:{{.Values.version}}-glibc\" EOF Now, lets write the definition.yaml, which contains the metadata information about our package ( e.g. how we refer to it with luet, the version, and so on )\ncat \u003c\u003cEOF \u003e busybox/definition.yaml category: \"distro\" name: \"busybox\" version: \"1.33.0\" EOF golang We need now golang in order to build gogs. Let’s declare then a golang package:\nmkdir golang And a build specfile, which is simply fetch golang from https://golang.org and installing it in the busybox container:\ncat \u003c\u003cEOF \u003e golang/build.yaml requires: - category: \"distro\" name: \"busybox\" version: \"\u003e=0\" prelude: - wget https://golang.org/dl/go{{.Values.version}}.linux-{{.Values.arch}}.tar.gz -O golang.tar.gz - mkdir /usr/local steps: - tar -C /usr/local -xzf golang.tar.gz EOF Note how we require busybox. The Golang container will now be based from busybox, and the prelude and steps fields will be executed in that context.\nAnd finally let’s write the golang metadata files, so we can refer to it from other packages\ncat \u003c\u003cEOF \u003e golang/definition.yaml name: \"go\" category: \"dev-lang\" version: \"1.15.6\" arch: \"amd64\" EOF gogs Finally we can write the gogs package definition!\nmkdir gogs The build specfile, will just fetch the gogs sources at a given version (specified in the definition.yaml) and build the sources with go:\ncat \u003c\u003c'EOF' \u003e gogs/build.yaml requires: - category: \"dev-lang\" name: \"go\" version: \"\u003e=0\" env: - GOPATH=\"/go\" - GOGSPATH=\"$GOPATH/src/github.com/gogs/gogs\" - PATH=$PATH:/usr/local/go/bin - CGO_ENABLED=0 prelude: - mkdir -p $GOPATH/src/github.com/gogs - wget https://github.com/gogs/gogs/archive/v{{.Values.version}}.tar.gz -O - | tar -xzf - -C ./ \u0026\u0026 mv gogs-{{.Values.version}} $GOGSPATH steps: - mkdir /usr/bin - cd $GOGSPATH \u0026\u0026 go build \u0026\u0026 mv gogs /usr/bin/gogs excludes: # Cache generated by Golang - ^/root EOF And the metadata, in this way we can refer to gogs in a Luet tree:\ncat \u003c\u003cEOF \u003e gogs/definition.yaml category: \"dev-vcs\" name: \"gogs\" version: \"0.11.91\" EOF Build packages The simplest and mostly immediate way to build packages, is running luet build \u003cpackagename\u003e in the same folder you have your Luet tree.\nIn this case, to build gogs and its deps, we can do:\nluet build dev-vcs/gogs And that’s it! you will find the package archives in build/ in the same folder where you started the command.\nYou will see that Luet generates not only archives with the file resulting to your builds, but it will also generate metadata files (ending with .metadata.yaml) that contains additional metadata information about your build and the package itself (e.g. checksums).\nYou can use tools like yq to inspect those:\nyq r build/gogs-dev-vcs-0.11.91.metadata.yaml checksums Now if you want to consume the artifacts just built with luet install, you can create a repository with luet create-repo.\n","categories":"","description":"Everything starts from an \"Hello!\"\n","excerpt":"Everything starts from an \"Hello!\"\n","ref":"/docs/tutorials/hello_world/","tags":"","title":"Hello world!"},{"body":"Prerequisites No dependencies. For building packages see the Build Packages section\nGet Luet From release Just grab a release from the release page on GitHub. The binaries are statically compiled.\nOr you can install Luet also with a single command:\ncurl https://luet.io/install.sh | sudo sh Building Luet from source Requirements:\n Golang installed in your system. make $\u003e git clone https://github.com/mudler/luet $\u003e cd luet $\u003e make build # or just go build Install it as a system package In the following section we will see how to install luet with luet itself. We will use a transient luet version that we are going to throw away right after we install it in the system.\n# Get a luet release. It will be used to install luet in your system wget https://github.com/mudler/luet/releases/download/0.8.3/luet-0.8.3-linux-amd64 -O luet chmod +x luet # Creates the luet configuration file and add the luet-index repository. # The luet-index repository contains a collection of repositories which are # installable and tracked in your system as standard packages. cat \u003e .luet.yaml \u003c\u003cEOF repositories: - name: \"mocaccino-repository-index\" description: \"MocaccinoOS Repository index\" type: \"http\" enable: true cached: true priority: 1 urls: - \"https://raw.githubusercontent.com/mocaccinoOS/repository-index/gh-pages\" EOF # Install the official luet repository to get always the latest luet version ./luet install repository/luet # Install luet (with luet) in your system ./luet install system/luet # Remove the temporary luet used for bootstrapping rm -rf luet # Copy over the config file to your system mkdir -p /etc/luet mv .luet.yaml /etc/luet/luet.yaml Configuration Luet stores its configuration files in /etc/luet. If you wish to override its default settings, create a file /etc/luet/luet.yaml.\nA example of a luet.yaml file can be found here.\nThere are a bunch of configuration settings available, but the most relevant are:\nlogging:color:true# Enable/Disable colored outputenable_emoji:true# Enable/Disable emoji from outputgeneral:debug:false# Enable/Disable debugsystem:rootfs:\"/\"# What's our rootfs. Luet can install packages outside of \"/\"database_path:\"/var/db/luet\"# Where to store DB filesdatabase_engine:\"boltdb\"tmpdir_base:\"/var/tmp/luet\"# The temporary directory to be usedAdding repositories To add repositories, you can either add a repositories stanza in your /etc/luet/luet.yaml or either add one or more yaml files in /etc/luet/repos.conf.d/.\nConfiguration in /etc/luet/luet.yaml logging:color:true# Enable/Disable colored outputenable_emoji:true# Enable/Disable emoji from outputgeneral:debug:false# Enable/Disable debugsystem:rootfs:\"/\"# What's our rootfs. Luet can install packages outside of \"/\"database_path:\"/var/db/luet\"# Where to store DB filesdatabase_engine:\"boltdb\"tmpdir_base:\"/var/tmp/luet\"# The temporary directory to be usedrepositories:- name:\"some-repository-name\"# Repository namedescription:\"A beautiful description\"type:\"http\"# Repository type, disk or http are supported (disk for local path)enable:true# Enable/Disable repocached:true# Enable cache for repositorypriority:3# Cache priorityurls:# Repository URLs- \"....\"Configuration in /etc/luet/repos.conf.d/ A repository file can be for example:\nname:\"...\"# Repository namedescription:\"...\"type:\"http\"# Repository type, disk or http are supported (disk for local path)enable:true# Enable/Disable repocached:true# Enable cache for repositorypriority:3# Cache priorityurls:# Repository URLs- \"...\"There is available a collection of repositories, which is containing a list of repositories that can be installed in the system with luet install.\nIf you installed Luet from the curl command, you just need to run luet search repository to see a list of all the available repository, and you can install them singularly by running luet install repository/\u003cname\u003e. Otherwise, add the repository stanzas you need to /etc/luet/luet.yaml.\n","categories":"","description":"First steps with Luet\n","excerpt":"First steps with Luet\n","ref":"/docs/getting-started/","tags":"","title":"Getting Started"},{"body":"Luet provides an abstraction layer on top of the container image layer to make the package a first class construct. A package definition and all its dependencies are translated by Luet to Dockerfiles which can then be built anywhere that docker runs.\nLuet is written entirely in Go and comes as a single static binary. This has a few advantages:\n Easy to recover. You can use luet to bootstrap the system entirely from the ground-up. Package manager has no dependencies on the packages that it installs. There is no chance of breaking the package manager by installing a conflicting package, or uninstalling one. Portable - it can run on any architecture Luet brings the containers ecosystem to standard software package management and delivery. It is fully built around the container concept, and leverages the huge catalog already present in the wild. It lets you use Docker images from Docker Hub, or from private registries to build packages, and helps you to redistribute them.\nSystems that are using luet as a package manager can consume Luet repositories with only luet itself. No dependency is required by the Package manager, giving you the full control on what you install or not in the system. It can be used to generate Linux from Scratch distributions, also to build Docker images, or to simply build standalone packages that you might want to redistribute.\nThe syntax proposed aims to be KISS - you define a set of steps that need to be run to build your image, and a set of constraints denoting the requirements or conflicts of your package.\nWhy another Package manager? There is no known package manager with 0-dependency that fully leverages the container ecosystem. This gap forces current package managers to depend on a specific system layout as base of the building process and the corresponding depencies. This can cause situations leading to a broken system. We want to fix that by empowering the user, by building their own packages, and redistribute them. Luet allows also to create packages entirely from Docker images content. In this way the user can actually bundle all the files of an image into a package and deliver part of it, or entirely as a layer. All of that, without the package manager depending on a single bit from it.\nPackage definitions Luet uses YAML for the package specification format, Luet parses the requirements to build packages, so Luet can consume them.\nBelow you can find links to tutorials on how to build packages, images and repositories.\n","categories":"","description":"See Luet in action.\n","excerpt":"See Luet in action.\n","ref":"/docs/concepts/overview/","tags":"","title":"Overview"},{"body":"After a set of packages has been built, a repository must be created in order to make them accessible by Luet clients. A Repository can be served either local files or via http(s) (at the moment of writing). Luet, by default, supports multiple-repositories with priorities.\nRepository fields name:\"...\"description:\"...\"type:\"docker\"cached:trueenabled:truearch:\"amd64\"priority:3urls:- \"...\"Repositories have the following fields, notably:\n name: Repository name description: Repository description cached: Enable/disable repository cache enable: Enable/disables the repository urls: A List of urls where the repository is hosted from type: Repository type ( docker, disk, http are currently supported ) arch: (optional) Denotes the arch repository. If present, it will enable the repository automatically if the corresponding arch is matching with the host running luet. enable: true would override this behavior reference: (optional) A reference to a repository index file to use to retrieve the repository metadata instead of latest. This can be used to point to a different or an older repository index to act as a “wayback machine”. The client will consume the repository state from that snapshot instead of latest. Note The reference field has to be a valid tag. For example, if a repository is a docker type, browse the image tags. The repository index snapshots are prefixed with a timestamp, and ending in repository.yaml. For example 20211027153653-repository.yaml Create a repository After issuing a luet build, the built packages are present in the output build directory. The create-repo step is needed to generate a portable tree, which is read by the clients, and a repository.yaml which contains the repository metadata.\nNote that the output of create-repo is additive so it integrates with the current build content. The repository is composed by the packages generated by the build command (or pack) and the create-repo generated metadata.\nFlags Some of the relevant flags for create-repo are:\n –descr: Repository description –name: Repository name –output: Metadata output folder (while a different path can be specified, it’s prefered to output the metadata files directly to the package directory).This most of the time matches the packages path for convenience. –packages: Directory where built packages are stored. This most of the time is also the output path. –reset-revision: Reset the repository revision number –tree-path: Specify a custom name for the tree path. (Defaults to tree.tar) –tree-compression: Specify a compression algorithm for the tree. (Available: gzip, Defaults: none) –tree: Path of the tree which was used to generate the packages and holds package metadatas –type: Repository type (http/local). It is just descriptive, the clients will be able to consume the repo in whatsoever way it is served. –urls: List of URIS where the repository is available See luet create-repo --help for a full description.\nExample Build a package and generate the repository metadata:\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" # optional! EOF $\u003e luet build --all --destination $PWD/out/ --tree $PWD/package 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... $\u003e luet create-repo --name \"test\" --output $PWD/out --packages $PWD/out --tree $PWD/package For repository test creating revision 1 and last update 1580641614... $\u003e ls out foo-bar-0.1-builder.image.tar foo-bar-0.1.image.tar foo-bar-0.1.metadata.yaml foo-bar-0.1.package.tar repository.yaml tree.tar Repositories type There are 3 types of repositories supported by luet: disk, http, docker.\ndisk It is a repository which is merely a local folder in your system. When creating a repository and specifying --output, luet expects a local path to the system where to store the generated metadata.\nhttp It is a repository type which is hosted behind a webserver. When creating a repository and specifying --output, luet expects a local path to the system where to store the generated metadata, similarly to the disk repository type. Luet is not handling any file upload. The http repository type gains meaning when being used from the client, where the repository source must be specified\ndocker When specifying the docker repository type, luet will generate final images from the build results and upload them to the docker reference specified with --output. The images contains the artifact output from the build result, and they are tagged accordingly to their package name. A single image reference needs to be passed, all the packages will be pushed in a single image but with different tags.\nThe login to the container registry is not handled, the daemon needs to have already proper permissions to push the image to the destination.\nRepositories snapshots Luet automatically will create repository index snapshots. This allows clients to point to specific references of repositories besides the latest package set published.\nluet create-repo optionally takes a --snapshot-id argument to define the snapshot name, otherwise it defaults to the unix date timestamp.\nCombined with --push-images with a container repository type, it automatically tags and pushes snapshots images too.\nConsuming repository snapshots A client can define a repository, with an optional reference keyword:\nname:\"...\"description:\"...\"type:\"docker\"priority:3reference:20220204175357-repository.yamlurls:- \"...\"Notes The tree of definition being used to build the repository, and the package directories must not be symlinks. To build a repository is not required to hold the packages artifacts, only the respective metadata.yaml file is required. ","categories":"","description":"How to create Luet repositories\n","excerpt":"How to create Luet repositories\n","ref":"/docs/concepts/overview/repositories/","tags":"","title":"Creating Luet repositories"},{"body":"","categories":"","description":"Documentation references\n","excerpt":"Documentation references\n","ref":"/docs/concepts/","tags":"","title":"Concepts"},{"body":"A Package in Luet is denoted by a triple (name, category and version), here called package form in a definition.yaml file in YAML:\nname:\"awesome\"version:\"0.1\"category:\"foo\"While category and version can be omitted, the name is required. Note that when refering to a package, the triplet is always present:\nrequires:- name:\"awesome\"version:\"0.1\"category:\"foo\"- name:\"bar\"version:\"0.1\"category:\"foo\"Building process When a package is required to be built, Luet resolves the dependency trees and orders the spec files to satisfy the given contraints.\nEach package build context is where the spec files are found (definition.yaml and build.yaml). This means that in the container, which is running the build process, the resources inside the package folder are accessible, as normally in Docker.\n❯ tree distro/raspbian/buster distro/raspbian/buster ├── build.sh ├── build.yaml ├── definition.yaml └── finalize.yaml In the example above, build.sh is accessible in build time and can be invoked easily in build time in build.yaml:\nsteps:- sh build.shPackage provides Packages can specify a list of provides. This is a list of packages in package form, which indicates that the current definition replaces every occurrence of the packages in the list (both at build and runtime). This mechanism is particularly helpful for handling package moves or for enabling virtual packages (e.g., gentoo virtual packages).\nNote: packages in the provides list don’t need to exist or have a valid build definition either.\nPackage types By a combination of keywords in build.yaml, you end up with categories of packages that can be built:\n Seed packages Packages deltas Package layers Package with includes Check the Specfile concept page for a full overview of the available keywords in the Luet specfile format.\nSeed packages Seed packages denote a parent package (or root) that can be used by other packages as a dependency. Normally, seed packages include just an image (preferably tagged) used as a base for other packages to depend on.\nIt is useful to pin to specific image versions, and to write down in a tree where packages are coming from. There can be as many seed packages as you like in a tree.\nA seed package build.yaml example is the following:\nimage:\"alpine:3.1\"Every other package that depends on it will inherit the layers from it.\nIf you want to extract the content of the seed package in a separate packages (splitting), you can just create as many package as you wish depending on that one, and extract its content, for example:\nalpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"sh/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# Tells luet to use the image content by unpacking itincludes:- /bin/shsh/definition.yaml\nname:\"sh\"category:\"utils\"version:\"1.0\"In this example, there are two packages being specified:\n One is the seed package, which is the base image employed to later extract packages. It has no installable content, and it is just virtually used during build phase. sh is the package which contains /bin/sh, extracted from the seed image and packaged. This can be consumed by Luet clients in order to install sh in their system. Packages delta Luet, by default, will try to calculate the delta of the package that is meant to be built. This means that it tracks incrementally the changes in the packages, to ease the build definition. Let’s see an example.\nGiven the root package: alpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"We can generate any file, and include it in our package by defining this simple package:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"steps:- echo \"Awesome\" \u003e /foofoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"By analyzing the difference between the two packages, Luet will automatically track and package /foo as part of the foo package.\nTo allow operations that must not be accounted in to the final package, you can use the prelude keyword:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"prelude:- echo \"Not packaged\" \u003e /invisiblesteps:- echo \"Awesome\" \u003e /foofoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"The list of commands inside prelude that would produce artifacts, are not accounted to the final package. In this example, only /foo would be packaged (which output is equivalent to the example above).\nThis can be used, for instance, to fetch sources that must not be part of the package.\nYou can apply restrictions anytime and use the includes keyword to specifically pin to the files you wish in your package.\nPackage layers Luet can be used to track entire layers and make them installable by Luet clients.\nGiven the examples above:\nalpine/build.yaml\nimage:\"alpine:3.1\"alpine/definition.yaml\nname:\"alpine\"version:\"3.1\"category:\"seed\"An installable package derived by the seed, with the actual full content of the layer can be composed as follows:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as isfoo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"This can be combined with other keywords to manipulate the resulting package (layer), for example:\nfoo/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as issteps:- apk update- apk add git- apk add ..foo/definition.yaml\nname:\"foo\"category:\"utils\"version:\"1.0\"Package includes In addition, the includes keyword can be set in order to extract portions from the package image.\ngit/build.yaml\n# List of build-time dependenciesrequires:- name:\"alpine\"version:\"3.1\"category:\"seed\"unpack:true# It advertize Luet to consume the package as issteps:- apk update- apk add gitincludes:- /usr/bin/gitfoo/definition.yaml\nname:\"git\"category:\"utils\"version:\"1.0\"As a reminder, the includes keywords accepts regular expressions in the Golang format. Any criteria expressed by means of Golang regular expressions, and matching the file name (absolute path), will be part of the final package.\n","categories":"","description":"Package definition syntax\n","excerpt":"Package definition syntax\n","ref":"/docs/concepts/packages/","tags":"","title":"Packages"},{"body":"Specfiles Luet packages are defined by specfiles. Specfiles define the runtime and builtime requirements of a package. There is an hard distinction between runtime and buildtime. A spec is composed at least by the runtime (definition.yaml or a collection.yaml) and the buildtime specification (build.yaml).\nLuet identifies the package definition by looking at directories that contains a build.yaml and a definition.yaml (or collection.yaml) files. A Luet tree is merely a composition of directories that follows this convention. There is no constriction on either folder naming or hierarchy.\nExample of a tree folder hierarchy\ntree distro distro ├── funtoo │ ├── 1.4 │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ ├── docker │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ └── meta │ └── rpi │ └── 0.1 │ ├── build.yaml │ └── definition.yaml ├── packages │ ├── container-diff │ │ └── 0.15.0 │ │ ├── build.yaml │ │ └── definition.yaml │ └── luet │ ├── build.yaml │ └── definition.yaml ├── raspbian │ ├── buster │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml │ ├── buster-boot │ │ ├── build.sh │ │ ├── build.yaml │ │ ├── definition.yaml │ │ └── finalize.yaml Build specs Build specs are defined in build.yaml files. They denote the build-time dependencies and conflicts, together with a definition of the content of the package.\nExample of a build.yaml file:\nsteps:- echo \"Luet is awesome\" \u003e /awesomeprelude:- echo \"nooops!\"requires:- name:\"echo\"version:\"\u003e=1.0\"conflicts:- name:\"foo\"version:\"\u003e=1.0\"provides:- name:\"bar\"version:\"\u003e=1.0\"env:- FOO=barincludes:- /awesomeunpack:trueBuilding strategies Luet can create packages with different strategies:\n by delta. Luet will analyze the containers differencies to find out which files got added. You can use the prelude section to exclude certains file during analysis. by taking a whole container content by considering a single directory in the build container. Package by delta By default Luet will analyze the container content and extract any file that gets added to it. The difference is calculated by using the container which is depending on, or either by the container which is created by running the steps in the prelude section of the package build spec:\nprelude:- # do something...steps:- # real work that should be calculated delta overBy omitting the prelude keyword, the delta will be calculated from the parent container where the build will start from.\nPackage by container content Luet can also generate a package content from a container. This is really useful when creating packages that are entire versioned rootfs. To enable this behavior, simply add unpack: true to the build.yaml. This enables the Luet unpacking features, which will extract all the files contained in the container which is built from the prelude and steps fields.\nTo include/exclude single files from it, use the includes and excludes directives.\nPackage by a folder in the final container Similarly, you can tell Luet to create a package from a folder in the build container. To enable this behavior, simply add package_dir: \"/path/to/final/dir\". The directory must represent exactly how the files will be ultimately installed from clients, and they will show up in the same layout in the final archive.\nSo for example, to create a package which ships /usr/bin/mybin, we could write:\npackage_dir:\"/output\"steps:- mkdir -p /output/usr/bin/- echo \"fancy stuff\" \u003e /output/usr/bin/mybin \u0026\u0026 chmod +x /output/usr/bin/mybinBuild time dependencies A package build spec defines how a package is built. In order to do this, Luet needs to know where to start. Hence a package must declare at least either one of the following:\n an image keyword which tells which Docker image to use as base, or a list of requires, which are references to other packages available in the tree. They can’t be both present in the same specfile.\nTo note, it’s not possible to mix package build definitions from different image sources. They must form a unique sub-graph in the build dependency tree.\nOn the other hand it’s possible to have multiple packages depending on a combination of different requires, given they are coming from the same image parent.\nExcluding/including files explictly Luet can also exclude and include single files or folders from a package by using the excludes and includes keyword respecitvely.\nBoth of them are parsed as a list of Golang regex expressions, and they can be combined together to fine-grainly decide which files should be inside the final artifact. You can refer to the files as they were in the resulting package. So if a package produces a /foo file, and you want to exclude it, you can add it to excludes as /foo.\nPackage source image Luet needs an image to kick-off the build process for each package. This image is being used to run the commands in the steps and prelude, and then the image is processed by the building strategies explained above.\nThe image can be resolved either by:\n providing a specific image name with image providing a set of package requirements with requires which will be constructed a new image from. The resulting image is an image linked between each other with the FROM field in the Dockerfile following the SAT solver ordering. providing a set of packages to squash their result from requires and by specifying requires_final_images: true. Note The above keywords cannot be present in the same spec at the same time, or they cannot be combined. But you are free to create further intermediate specs to achieve the desired image. Difference between requires and requires with requires_final_images: true requires generates a graph from all the images of the specfile referenced inside the list. This means it builds a chain of images that are used to build the packages, e.g.: packageA(image: busybox) -\u003e packageB (requires: A) -\u003e packageC (requires: C). The container which is running your build then inherits it’s parents from a chain of order resolution, provided by the SAT solver.\nWhen specifying requires_final_images: true luet builds an artifact for each of the packages listed from their compilation specs and it will later squash them together in a new container image which is then used in the build process to create an artifact.\nThe key difference is about where your build is going to run from. By specifying requires_final_images it will be constructed a new image with the content of each package - while if setting it to false, it will order the images appropriately and link them together with the Dockerfile FROM field. That allows to reuse the same images used to build the packages in the require section - or - create a new one from the result of each package compilation.\nKeywords Here is a list of the full keyword refereces for the build.yaml file.\nconflicts (optional) List of packages which it conflicts with in build time. In the same form of requires it is a list of packages that the current one is conflicting with.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\ncopy since luet\u003e=0.15.0\n(optional) A list of packages/images where to copy files from. It is the Docker multi-stage build equivalent but enhanced with tree hashing resolution.\nTo copy a specific file from a package build container:\nsteps:- ...prelude:- ...copy:- package:category:\"foo\"name:\"bar\"version:\"\u003e=0\"source:\"/foo\"destination:\"/bar\"Any package that is listed in the section will be compiled beforeahead the package, and the file is available both in prelude and steps.\nInternally, it’s rendered as COPY --from=package/image:sha /foo /bar\nTo copy a specific file from an external image:\nsteps:- ...prelude:- ...copy:- image:\"buxybox:latest\"source:\"/foo\"destination:\"/bar\"env (optional) A list of environment variables ( in NAME=value format ) that are expanded in step and in prelude. ( e.g. ${NAME} ).\nenv:- PATH=$PATH:/usr/local/go/bin- GOPATH=/luetbuild/go- GO111MODULE=on- CGO_ENABLED=0- LDFLAGS=\"-s -w\"excludes (optional) List of golang regexes. They are in full path form (e.g. ^/usr/bin/foo ) and indicates that the files listed shouldn’t be part of the final artifact\nWildcards and golang regular expressions are supported. If specified, files which are not matching any of the regular expressions in the list will be excluded in the final package.\nexcludes:- ^/etc/shadow- ^/etc/os-release- ^/etc/gshadowBy combining excludes with includes, it’s possible to include certain files while excluding explicitly some others (excludes takes precedence over includes).\nimage (optional/required) Docker image to be used to build the package.\nimage:\"busybox\"It might be omitted in place of requires, and indicates the image used to build the package. The image will be pulled and used to build the package.\nincludes (optional) List of regular expressions to match files in the resulting package. The path is absolute as it would refer directly to the artifact content.\nWildcards and golang regular expressions are supported. If specified, files which are not matching any of the regular expressions in the list will be excluded in the final package.\nincludes:- /etc$- /etc/lvm$- /etc/lvm/.*- /usr$- /usr/bin$- /usr/bin/cc.*- /usr/bin/c\\+\\+.*- /usr/bin/cpp.*- /usr/bin/g\\+\\+.*Note: Directories are treated as standard entries, so to include a single file, you need also to explictly include also it’s directory. Consider this example to include /etc/lvm/lvm.conf:\nincludes:- /etc$- /etc/lvm$- /etc/lvm/lvm.confjoin since luet\u003e=0.16.0 to be deprecated in luet\u003e=0.18.0 in favor of requires_final_images\n(optional/required) List of packages which are used to generate a parent image from.\nIt might be omitted in place of image or requires, and will generate an image which will be used as source of the package from the final packages in the above list. The new image is used to run eventually the package building process and a new artifact can be generated out of it.\njoin:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nExamples https://github.com/mocaccinoOS/mocaccino-stage3/blob/278e3637cf65761bf01a22c891135e237e4717ad/packages/system/stage3/build.yaml package_dir (optional) A path relative to the build container where to create the package from.\nSimilarly to unpack, changes the building strategy.\nsteps:- mkdir -p /foo/bar/etc/myapp- touch /foo/bar/etc/myapp/configpackage_dir:/foo/barprelude (optional) A list of commands to perform in the build container before building.\nprelude:- |PACKAGE_VERSION=${PACKAGE_VERSION%\\+*} \u0026\u0026 \\ git clone https://github.com/mudler/yip \u0026\u0026 cd yip \u0026\u0026 git checkout \"${PACKAGE_VERSION}\" -b buildrequires (optional/required) List of packages which it depends on.\nA list of packages that the current package depends on in build time. It might be omitted in place of image, and determines the resolution tree of the package itself. A new image is composed from the packages listed in this section in order to build the package\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nrequires_final_images since luet\u003e=0.17.0\n(optional) A boolean flag which instruct luet to use the final images in the requires field.\nBy setting requires_final_images: true in the compilation spec, packages in the requires section will be first compiled, and afterwards the final packages are squashed together in a new image that will be used during build.\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"requires_final_images:truerequires_final_images replaces the use of join, which will be deprecated in luet \u003e=0.18.0.\nstep (optional) List of commands to perform in the build container.\nsteps:- |cd yip \u0026\u0026 make build-small \u0026\u0026 mv yip /usr/bin/yipunpack (optional) Boolean flag. It indicates to use the unpacking strategy while building a package\nunpack:trueIt indicates that the package content is the whole container content.\nRutime specs Runtime specification are denoted in a definition.yaml or a collection.yaml sibiling file. It identifies the package and the runtime contraints attached to it.\ndefinition.yaml:\nname:\"awesome\"version:\"0.1\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"A collection.yaml can be used in place of a definition.yaml to identify a set of packages that instead shares a common build.yaml:\ncollection.yaml:\npackages:- name:\"awesome\"version:\"0.1\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"- name:\"awesome\"version:\"0.2\"category:\"foo\"requires:- name:\"echo\"version:\"\u003e=1.0\"category:\"bar\"conflicts:- name:\"foo\"version:\"1.0\"provides:- name:\"bar\"version:\"\u003c1.0\"...All the fields (also the ones which are not part of the spec) in the definition.yaml file are available as templating values when rendering the build.yaml file. When running finalizers instead only the fields belonging to the specs are available.\nKeywords Here is a list of the full keyword refereces\nannotations (optional) A map of freeform package annotations:\nannotations:foo:\"bar\"baz:\"test\"category (optional) A string containing the category of the package\ncategory:\"system\"conflicts (optional) List of packages which it conflicts with in runtime. In the same form of requires it is a list of packages that the current one is conflicting with.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\ndescription (optional) A string indicating the package description\nname:\"foo\"description:\"foo is capable of...\"hidden (optional) A boolean indicating whether the package has to be shown or not in the search results (luet search...)\nhidden:truelabels (optional) A map of freeform package labels:\nlabels:foo:\"bar\"baz:\"test\"Labels can be used in luet search to find packages by labels, e.g.:\n$\u003e luet search --by-label foo license (optional) A string indicating the package license type.\nlicense:\"GPL-3\"name (required) A string containing the name of the package\nname:\"foo\"provides (optional) List of packages which the current package is providing.\nconflicts:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nrequires (optional) List of packages which it depends on in runtime.\nA list of packages that the current package depends on in runtime. The determines the resolution tree of the package itself.\nrequires:- name:\"foo\"category:\"bar\"version:\"1.0\"...- name:\"baz\"category:\"bar\"version:\"1.0\"See Package concepts for more information on how to represent a package in a Luet tree.\nuri (optional) A list of URI relative to the package ( e.g. the official project pages, wikis, README, etc )\nuri:- \"http://www.mocaccino.org\"- ...version (required) A string containing the version of the package\nversion:\"1.0\"Refering to packages from the CLI All the luet commands which takes a package as argument, respect the following syntax notation:\n cat/name: will default to selecting any available package =cat/name: will default to gentoo parsing with regexp so also =cat/name-1.1 works cat/name@version: will select the specific version wanted ( e.g. cat/name@1.1 ) but can also include ranges as well cat/name@\u003e=1.1 name: just name, category is omitted and considered empty Finalizers Finalizers are denoted in a finalize.yaml file, which is a sibiling of definition.yaml and build.yaml file. It contains a list of commands that finalize the package when it is installed in the machine.\nfinalize.yaml:\ninstall:- rc-update add docker defaultKeywords install: List of commands to run in the host machine. Failures are eventually ignored, but will be reported and luet will exit non-zero in such case. ","categories":"","description":"Luet specfile syntax\n","excerpt":"Luet specfile syntax\n","ref":"/docs/concepts/packages/specfile/","tags":"","title":"Specfile"},{"body":"Installing a package To install a package with luet, simply run:\n$ luet install \u003cpackage_name\u003e To relax dependency constraints and avoid auto-upgrades, add the --relax flag:\n$ luet install --relax \u003cpackage name\u003e To install only the package without considering the deps, add the --nodeps flag:\n$ luet install --nodeps \u003cpackage name\u003e To install only package dependencies, add the --onlydeps flag:\n$ luet install --onlydeps \u003cpackage name\u003e To only download packages, without installing them use the --download-only flag:\n$ luet install --download-only \u003cpackage name\u003e Uninstalling a package To uninstall a package with luet, simply run:\n$ luet uninstall \u003cpackage_name\u003e Upgrading the system To upgrade your system, simply run:\n$ luet upgrade Refreshing repositories Luet automatically syncs repositories definition on the machine when necessary, but it avoids to sync up in a 24h range. In order to refresh the repositories manually, run:\n$ luet repo update Searching a package To search a package:\n$ luet search \u003cregex\u003e To search a package and display results in a table:\n$ luet search --table \u003cregex\u003e To look into the installed packages:\n$ luet search --installed \u003cregex\u003e Note: the regex argument is optional\nSearch file belonging to packages $ luet search --file \u003cfile_pattern\u003e Search output Search can return results in the terminal in different ways: as terminal output, as json or as yaml.\nJSON $ luet search --json \u003cregex\u003e YAML $ luet search --yaml \u003cregex\u003e Tabular $ luet search --table \u003cregex\u003e Quiet luet output Luet output is verbose by default and colourful, however will try to adapt to the terminal, based on which environment is executed (as a service, in the terminal, etc.)\nYou can quiet luet output with the --quiet flag or -q to have a more compact output in all the commands.\n","categories":"","description":"How to install packages, manage repositories, ...\n","excerpt":"How to install packages, manage repositories, ...\n","ref":"/docs/concepts/overview/usage/","tags":"","title":"CLI usage"},{"body":" Warning This article contains references to Luet repositories that were deprecated, and needs to be updated. Please refer to the “Hello World” tutorial instead. Catclock example In this example, we will build the awesome CatClock on containers we will run it locally in a Luet box.\nWe will do this experiment to prove two things:\n how we can build a package with Luet and two packages from different distributions can (sometime) work together. Prerequisites To build packages with Luet, you must have installed Docker and container-diff, follow our setup guide.\n1) Create the package To prove our point, we will build our package from an OpenSUSE image, and later on we will consume entropy repositories for runtime dependencies. To note, this is not the main focus of Luet, and this is a restricted example on its features on build-time resolution. For more syntax examples, see also Build specs and Package types.\nRun this commands in any directory you choose to be your workspace:\n# Let's create a directory to store our package spec: mkdir -p tree/misc/catclock/ 1.1) Build spec Now, let’s generate our build spec:\n# Create a build file. We use here opensuse/leap to build the package, as an example cat \u003c\u003cEOF \u003e tree/misc/catclock/build.yaml image: opensuse/leap # Preparation phase prelude: - zypper in -y git make libXt-devel xmh gcc motif-devel libXext-devel libpulse-devel libaubio-devel - git clone https://github.com/BarkyTheDog/catclock # Here we define the steps that Luet will follow steps: - cd catclock \u0026\u0026 make DEFINES=\"-Wno-incompatible-pointer-types\" - mv catclock/xclock /usr/bin/xclock # (optional) File list that will be included in the final package # Luet will filter out files that won't match any entry in the list (regex syntax IS supported) includes: - /usr/bin/xclock EOF build.yaml is what an ebuild is for Gentoo and for e.g. what PKGBUILD is for Arch.\n image: opensuse/leap tells luet to use opensuse/leap as a build image. We collect the build time dependencies with zypper (the openSUSE package manager), and the CatClock with git. When we declare an image keyword in a spec, it becomes a seed package ( Package types ) as doesn’t depend on any package in build time, we will cover more use cases in other examples. prelude is a list of commands that will happen during the build phase. They might generate binaries, or download sources, but those are not took into consideration when generating the final package. steps is a list of commands that will happen during the build phase. Luet will execute those commands and all the binaries generated from them become part of the final package includes is a (optional) list of regex that tells to Luet what files to filter out from the final artifact. 1.2) Runtime spec Now we generate the runtime spec, it’s the part about the binary end which will be installed in the system. It also holds the metadata relative to the package definition (name, category, version).\n# Create a runtime definition. # We will leverage packages already present on Sabayon Entropy repositories # the end-system needs to have the Luet Sabayon Entropy repositories enabled. cat \u003c\u003cEOF \u003e tree/misc/catclock/definition.yaml category: \"misc\" name: \"catclock\" version: \"0.20200318\" requires: - category: meta name: users version: \"\u003e=0\" - category: x11-libs name: motif version: \"\u003e=0.1\" - category: media-libs name: libjpeg-turbo version: \"\u003e=0.1\" EOF category, name, and version: identifies the package in a Luet tree. This is the unique identifier for a package. requires it’s a list of packages which our catclock depends on during runtime (when we will execute catclock inside a small-container!). To find out what’s required by your binaries it can be a try-learn-fail effort. If the package you wish to build is specifying the deps it requires, and those are available in a Luet repository, you are all set, just point them there. Otherwise you have to figure out after you build the binary the first time (for example, with ldd) to which libraries it depends on. In this example we consume the dependencies from the Luet Entropy Repo, that we will enable on the following steps. 2) Build it! sudo /usr/bin/luet build \\ --tree=$PWD/tree misc/catclock \\ --destination $PWD/build \\ --compression gzip sudo chown -R $USER $PWD/build # So later on, we can access to the repository with our user We are building the specs in this step.\n tree: is the path where our specs are, in our case it’s tree. destination: is the path where our packages will be stored, in our case this is build. compression: is the compression algorithm used to compress the final artifacts Note, we need sudo to keep the permissions properly mapped in the artifact which is produced this is not always the case. Depends on the package content.\n3) Create a local repository We will generate now our repository metadata:\n/usr/bin/luet create-repo --tree \"tree\" \\ --output $PWD/build \\ --packages $PWD/build \\ --name \"test repo\" \\ --descr \"Test Repo\" \\ --tree-compression gzip \\ --meta-compression gzip Creating a repository in Luet is about adding metadata and make our spec tree available to other systems running Luet to intall the package.\n output: a path which is where Luet will store the repository metadata. packages: a path containing the packages that were built during the build step name: Repository name descr: Repository description tree-compression: optional, algorithm to use when compression the tree metadata meta-compression: optional, algorithm to use when compression the repository metadata 4) Let’s test it! Now we are all set. We have the packages compiled, and we are ready to consume them. We don’t want to break our host system, and we want to test this from our user.\nLet’s create a directory, we will try to setup a full running system, and install everything there.\n# Let's create a directory for our \"fake\" rootfilesystem # it will be populated with a minimal set of packages needed to run # our amazing catclock mkdir -p $PWD/rootfs # Let's also create a directory to store our config files mkdir -p $PWD/conf We will generate now a Luet config. The Luet config is used to read where install things from, and in which directory. It also lists the repositories that are used by the client to retrieve packages remotely.\n# We create here a config file which references the rootfs. # In this way, luet instead installing packages to your host system, will populate the rootfs # (note, all the steps are run by a user here, no root required!) cat \u003c\u003cEOF \u003e conf/luet-dso-local.yaml system: rootfs: $PWD/rootfs # our \"fake\" rootfs that we created before database_path: \"/\" # this is where our Luet DB will live database_engine: \"boltdb\" # this is the Luet DB engine repositories: - name: \"main\" type: \"disk\" priority: 3 enable: true urls: - \"$PWD/build\" # This is the repository we have created before! - name: \"sabayonlinux.org\" description: \"Sabayon Linux Repository\" type: \"http\" enable: true cached: true priority: 2 urls: - \"https://dispatcher.sabayon.org/sbi/namespace/luet-entropy-repo\" - name: \"luet-repo\" description: \"Luet Official Repository\" type: \"http\" enable: true cached: true priority: 1 urls: - \"https://raw.githubusercontent.com/Luet-lab/luet-repo/gh-pages\" EOF # we have specified an additional repository, one that is luet-entropy-repo (which contains # the runtime dependencies we specified in our package) # Let's populate our rootfs with some minimal things: base-gcc, and bash # meta/users is a meta package providing minimal base to run things with a full # user-level support. export LUET_NOLOCK=true luet install \\ --config $PWD/conf/luet-dso-local.yaml \\ meta/users # catclock is a X11 app! we want to be able to play with it locally from our host :) # Let's copy the .Xauthority file to allow the X app to communicate with our X server # Note: This can be achieved in other ways (set up a tcp X server, and so on) cp -rfv $HOME/.Xauthority $PWD/rootfs/ luet install \\ --config $PWD/conf/luet-dso-local.yaml \\ misc/catclock # Let's run our beautiful catclock :) luet box exec --rootfs $PWD/rootfs \\ --stdin --stdout --stderr --env DISPLAY=$DISPLAY \\ --env XAUTHORITY=/.Xauthority --mount /tmp --entrypoint /usr/bin/xclock Spawn a bash shell inside our box (with permission to access to our running X):\nluet box exec --rootfs $PWD/rootfs \\ --stdin --stdout --stderr --env DISPLAY=$DISPLAY \\ --env XAUTHORITY=/.Xauthority --mount /tmp --entrypoint /bin/bash ","categories":"","description":"Example on how to build a package and run it locally with luet box\n","excerpt":"Example on how to build a package and run it locally with luet box\n","ref":"/docs/tutorials/build_package/","tags":"","title":"Build a package"},{"body":"Luet can be extended in 2 ways by extensions and plugins.\nBefore you begin You need to have a working luet binary installed.\nExtensions Extensions expand Luet featureset horizontally, so for example, “luet geniso” will allow you to build an iso using luet, without this needing to be part of the luet core.\nAn Extension is nothing more than a standalone executable file, whose name begins with luet-. To install an extension, simply move its executable file to anywhere on your system PATH.\nAll the plugins will be accessible to luet as luet pluginname\nWriting an Extension You can write an extension in any programming language or script that allows you to write command-line commands.\nExecutables receive the inherited environment from luet. An extension determines which command path it wishes to implement based on its name. For example, a plugin wanting to provide a new command luet foo, would simply be named luet-foo, and live somewhere in your PATH.\nExample Extension #!/bin/bash if [[ \"$1\" == \"help\" ]] then echo \"Extension help\" exit 0 fi if [[ \"$1\" == \"run\" ]] then # do something interesting fi echo \"I am an Extension named luet-foo\" Using an Extension To use the above extension, simply make it executable:\n$ sudo chmod +x ./luet-foo and place it anywhere in your PATH:\n$ sudo mv ./luet-foo /usr/local/bin You may now invoke your extension as a luet command:\n$ luet foo I am an Extension named luet-foo All args and flags are passed as-is to the executable:\n$ luet foo help Extension help Plugins Plugins instead are expanding Luet vertically by hooking into internal events. Plugins and Extensions can be written in any language, bash included! Luet uses go-pluggable so it can dispatch events to external binaries.\nSimilarly to Extensions, a Plugin is nothing more than a standalone executable file, but without any special prefix. To install a plugin, simply move its executable file to anywhere on your system PATH.\nDifferently from Extensions, they are not available from the CLI and cannot be invoked directly by the user, instead they are called by Luet during its lifecycle.\nWriting a Plugin You can write a plugin in any programming language or script.\nThe first argument that is passed to a plugin will always be the event that was emitted by Luet in its lifecycle. You can see all the events available here. The second argument, is a JSON encoded payload of the object that Luet is emitting with the event. The object(s) may vary depending on the emitted event.\nThe output of the plugin (stdout) will be parsed as JSON. Every plugin must return a valid JSON at the end of its execution, or it will be marked as failed and stops luet further execution. See also the go-pluggable README.\nThe returning payload should be in the following form:\n{ \"state\": \"\", \"data\": \"data\", \"error\": \"\"} By returning a json with the error field not empty, it will make fail the overall execution.\nExample Plugin #!/bin/bash echo \"$1\" \u003e\u003e /tmp/event.txt echo \"$2\" \u003e\u003e /tmp/payload.txt echo \"{}\" Using a plugin To use the above plugin, simply make it executable:\n$ sudo chmod +x ./test-foo and place it anywhere in your PATH:\n$ sudo mv ./test-foo /usr/local/bin Now, when running luet, add --plugin test-foo:\n$ luet --plugin test-foo install -y foopackage And check /tmp/event.txt to see the event fired and /tmp/payload.txt to check the payloads that were emitted by Luet.\nConcrete example A plugin that prints the images that are being built in /tmp/exec.log:\n#!/bin/bash exec \u003e\u003e /tmp/exec.log exec 2\u003e\u00261 event=\"$1\" payload=\"$2\" if [ \"$event\" == \"image.post.build\" ]; then image=$(echo \"$payload\" | jq -r .data | jq -r .ImageName ) echo \"{ \\\"data\\\": \\\"$imagebuilt\\\" }\" else echo \"{}\" fi ","categories":"","description":"Extend luet with plugins and extensions\n","excerpt":"Extend luet with plugins and extensions\n","ref":"/docs/concepts/plugins-and-extensions/","tags":"","title":"Plugins and Extensions"},{"body":"Luet supports the sprig rendering engine template, like helm. It’s being used to interpolate build.yaml and finalize.yaml files before their execution. The following document assumes you are familiar with the helm templating.\nThe build.yaml and finalize.yaml files are rendered during build time, and it’s possible to use the helm templating syntax inside such files. The definition.yaml file will be used to interpolate templating values available in build.yaml\nGiven the following definition.yaml:\nname:\"test\"category:\"foo\"version:\"1.1\"additional_field:\"baz\"A build.yaml can look like the following, and interpolates it’s values during build time:\nimage:...steps:- echo {{.Values.name}} \u003e /package_name- echo {{.Values.additional_field}} \u003e /extraWhich would be for example automatically rendered by luet like the following:\nimage:...steps:- echo test \u003e /package_name- echo baz \u003e /extraThis mechanism can be used in collections as well, and each stanza in packages is used to interpolate each single package.\nInterpolating globally It’s possible to interpolate during build phase all the package specs targeted for build with the --values flag, which takes a yaml file of an arbitrary format, if variables are clashing, the yaml supplied in --values takes precedence and overwrite the values of each single definition.yaml file.\nShared templates Since luet 0.17.5 it is possible to share templates across different packages. All templates blocks found inside the templates folder inside the root luet tree of a repository gets templated and shared across all the packages while rendering each compilation spec of the given tree.\nConsider the following:\nshared_templates ├── templates │ └── writefile.yaml └── test ├── build.yaml └── collection.yaml collection.yaml We define here two packages with a collection. They will share the same compilation spec to generate two different packages packages:- category:\"test\"name:\"foo\"version:\"1.0\"- category:\"test\"name:\"bar\"version:\"1.0\" Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/collection.yaml writefile.yaml All the files in the templates folder will get rendered by the template for each package in the tree. We define here a simple block to write out a file from the context which is passed by: {{define \"writefile\" }}- echo conflict \u003e /foo/{{.}}{{end}} Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/templates/writefile.yaml build.yaml Finally the build spec consumes the template block we declared above, passing by the name of the package: image:\"alpine\"prelude:- mkdir /foosteps:{{template \"writefile\" .Values.name }}package_dir:/foo Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/build.yaml Limitations The finalize.yaml file has access only to the package fields during templating. Extra fields that are present in the definition.yaml file are not accessible during rendering in the finalize.yaml file, but only the package fields (name, version, labels, annotations, …)\nReferences Sprig docs Helm Templating functions Helm Templating variable Examples https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/tar ","categories":"","description":"Use templates to fine tune build specs\n","excerpt":"Use templates to fine tune build specs\n","ref":"/docs/concepts/packages/templates/","tags":"","title":"Templated packages"},{"body":" Warning This article is outdated. Please refer to the “Hello World” tutorial instead. Here we show an example on how to build “burnable” SD images for Raspberry Pi with Luet. This approach lets you describe and version OTA upgrades for your embedded devices, delivering upgrades as layer upgrades on the Pi.\nThe other good side of the medal is that you can build a Luet package repository with multiple distributions (e.g. Raspbian, OpenSUSE, Gentoo, … ) and switch among them in runtime. In the above example Raspbian and Funtoo (at the time of writing) are available.\nPrerequisites You have to run the following steps inside an ARM board to produce arm-compatible binaries. Any distribution with Docker will work. Note that the same steps could be done in a cross-compilation approach, or with qemu-binfmt in a amd64 host.\nYou will also need in your host:\n Docker Luet installed (+container-diff) in /usr/bin/luet (arm build) make Build the packages Clone the repository https://github.com/Luet-lab/luet-embedded\n$\u003e git clone https://github.com/Luet-lab/luet-embedded $\u003e cd luet-embedded $\u003e sudo make build-all ... If a rebuild is needed, just do sudo make rebuild-all after applying the changes.\nCreate the repository $\u003e sudo make create-repo ... Serve the repo locally $\u003e make serve-repo ... Create the flashable image Funtoo based system $\u003e sudo LUET_PACKAGES='distro/funtoo-1.4 distro/raspbian-boot-0.20191208 system/luet-develop-0.5' make image ... Raspbian based system $\u003e sudo LUET_PACKAGES='distro/raspbian-0.20191208 distro/raspbian-boot-0.20191208 system/luet-develop-0.5' make image ... At the end of the process, a file luet_os.img, ready to be flashed to an SD card, should be present in the current directory.\nAdd packages In order to build and add packages to the exiting repository, simply add or edit the specfiles under the distro folder. When doing make rebuild-all the packages will be automatically compiled and made available to the local repository.\n","categories":"","description":"Use Luet to build, track, and release OTA update for your embedded devices.\n","excerpt":"Use Luet to build, track, and release OTA update for your embedded …","ref":"/docs/resources/arm/","tags":"","title":"ARM images"},{"body":"Simple package build Creating and building a simple package:\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" EOF $\u003e luet build --all 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... Build packages In order to build a specific version, a full package definition (triple of category, name and version) has to be specified. In this example we will also enable package compression (gzip).\n$\u003e mkdir package $\u003e cat \u003c\u003cEOF \u003e package/build.yaml image: busybox steps: - echo \"foo\" \u003e /foo EOF $\u003e cat \u003c\u003cEOF \u003e package/definition.yaml name: \"foo\" version: \"0.1\" category: \"bar\" EOF $\u003e luet build bar/foo-0.1 --compression gzip 📦 Selecting foo 0.1 📦 Compiling foo version 0.1 .... ☕ 🐋 Downloading image luet/cache-foo-bar-0.1-builder 🐋 Downloading image luet/cache-foo-bar-0.1 📦 foo Generating 🐋 definition for builder image from busybox 🐋 Building image luet/cache-foo-bar-0.1-builder 🐋 Building image luet/cache-foo-bar-0.1-builder done Sending build context to Docker daemon 4.096kB ... ","categories":"","description":"Examples to build with Luet\n","excerpt":"Examples to build with Luet\n","ref":"/docs/resources/building/","tags":"","title":"Building"},{"body":"Collections are a special superset of packages. To define a collection, instead of using a definition.yaml file, create a collection.yaml file with a list of packages:\npackages:- category:\"test\"name:\"foo\"version:\"1.0\"- category:\"test\"name:\"bar\"version:\"1.0\" Complete source code: https://github.com/mudler/luet/blob/master/tests/fixtures/shared_templates/test/collection.yaml Packages under a collection shares the same build.yaml and finalize.yaml, so a typical package layout can be:\ncollection/ collection.yaml build.yaml finalize.yaml ... additional files in the build context Luet during the build phase, will treat packages of a collection individually. A collection is a way to share the same build process across different packages.\nTemplating The templating mechanism can be used in collections as well, and each stanza in packages is used to interpolate each single package.\nExamples https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/entities https://github.com/mocaccinoOS/portage-tree/tree/master/multi-arch/packages/groups https://github.com/mocaccinoOS/mocaccino-musl-universe/tree/master/multi-arch/packages/X ","categories":"","description":"Group a set of package build spec with templating\n","excerpt":"Group a set of package build spec with templating\n","ref":"/docs/concepts/packages/collections/","tags":"","title":"Collections"},{"body":"Under the hood, Luet uses boolean satisfiability problem (SAT) reinforcement learning techniques to solve package constraints.\nLuet allows you to specify 3 types of set of contraints on a package definition:\n Requires Conflicts Provides The package definition in your tree definition, along with its Requires and Conflicts, are turned into Boolean formulas that are consumed by the solver to compute a solution. The solution represent the state of your system after a particular query is asked to the solver (Install, Uninstall, Upgrade).\nRequires and Conflicts A list of requires and conflicts, composed of one or more packages, becomes a SAT formula. The formula is then given to the SAT solver to compute a finite state set of packages which must be installed in the system in order to met the requirements.\nAs Luet allows to express constraints with selectors ( e.g. A depends on \u003e=B-1.0) it generates additional constraints to guarantee that at least one package and at most one is picked as dependency (ALO and AMO).\nProvides Provides constraints are not encoded in a SAT formula. Instead, they are expanded into an in-place substitution of the packages that they have to be replaced with. They share the same SAT logic of expansion, allowing to swap entire version ranges (e.g. \u003e=1.0), allowing to handle package rename, removals, and virtuals.\nReferences OPIUM (Luet is inspired by it): https://ranjitjhala.github.io/static/opium.pdf FROM TRACTABLE CSP TO TRACTABLE SAT: https://www.cs.ox.ac.uk/files/4014/maxclosed_orderencoding_v16_TR.pdf Solver concepts applied to packages (zypper): https://en.opensuse.org/openSUSE:Libzypp_satsolver_basics ","categories":"","description":"How Luet turns Image resolution into CSP\n","excerpt":"How Luet turns Image resolution into CSP\n","ref":"/docs/concepts/overview/constraints/","tags":"","title":"CSP, SAT \u0026\u0026 RL"},{"body":"Can’t build packages There might be several reasons why packages fails to build, for example, if your build fails like this:\n$ luet build ... INFO Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? ERROR Error: Failed compiling development/toolchain-go-0.6: failed building package image: Could not push image: quay.io/mocaccino/micro-toolchain:latest toolchain-go-development-0.6-builder.dockerfile: Could not build image: quay.io/mocaccino/micro-toolchain:latest toolchain-go-development-0.6-builder.dockerfile: Failed running command: : exit status 1 ERROR Bailing out means the user you are running the build command can’t either connect to docker or docker is not started.\nCheck if the user you are running the build is in the docker group, or if the docker daemon is started.\nLuet by default if run with multiple packages summarize errors and can be difficult to navigate to logs, but if you think you might have found a bug, run the build with --debug before opening an issue.\nWhy the name luet? Well, I have the idea that programs should be small, so they are not difficult to type and easy to remember, and easy to stick in. luet is really a combination of the first letters of my fiancee name (Lucia) and my name (Ettore) lu+et = luet! and besides, happen to be also a small bridge in Italy ;)\n","categories":"","description":"FAQ\n","excerpt":"FAQ\n","ref":"/docs/resources/faq/","tags":"","title":"Frequently Asked Questions"},{"body":"The Docker image quay.io/luet/base is a scratch Docker image always kept up-to-date with the latest luet version. That image can be used to bootstrap new images with Luet repositories with the packages you want, from the repositories you prefer.\nFor example we can mount a config file, and later on install a package:\ncat \u003c\u003cEOF \u003e $PWD/luet.yaml repositories: - name: \"micro-stable\" enable: true cached: true priority: 1 type: \"http\" urls: - \"https://get.mocaccino.org/mocaccino-micro-stable\" EOF docker rm luet-runtime-test || true docker run --name luet-runtime-test \\ -ti -v /tmp:/tmp \\ -v $PWD/luet.yaml:/etc/luet/luet.yaml:ro \\ quay.io/luet/base install shells/bash docker commit luet-runtime-test luet-runtime-test-image # Try your new image! docker run -ti --entrypoint /bin/bash --rm luet-runtime-test-image In this way we will create a new image, with only luet and bash, and nothing else from a scratch image.\n","categories":"","description":"Using Luet to compose images from scratch\n","excerpt":"Using Luet to compose images from scratch\n","ref":"/docs/resources/scratch/","tags":"","title":"Images from scratch"},{"body":"","categories":"","description":"Howtos, Cookbooks \n","excerpt":"Howtos, Cookbooks \n","ref":"/docs/tutorials/","tags":"","title":"Tutorials"},{"body":"","categories":"","description":"Luet examples, resources, API reference\n","excerpt":"Luet examples, resources, API reference\n","ref":"/docs/resources/","tags":"","title":"Resources"},{"body":"Luet is a Package Manager based on containers. It provides an abstraction layer over container specfile format, enhancing the image resolution process of open container inititative (OCI) runtimes with boolean satisfiability problem (SAT) solving techniques.\nLuet can be used to build packages, container images, as well as to manage and distribute installations of derived packages locally.\nAllows to apply semver constraints to Image dependencies, treating it as a classical CSP.\n ","categories":"","description":"","excerpt":"Luet is a Package Manager based on containers. It provides an …","ref":"/docs/","tags":"","title":"Documentation"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/news/","tags":"","title":"News About Luet"},{"body":"","categories":"","description":"","excerpt":"","ref":"/blog/releases/","tags":"","title":"New Releases"},{"body":"References Here is a list of references to projects that are related to Luet (open up a PR to add yours to the list!):\n Description URL Official Luet repository https://github.com/Luet-lab/luet-repo Example repository to host package browser websites on gh-pages. It uses the package-browser extension to generate HTML pages from a list of luet repositories https://github.com/Luet-lab/package-browser-sample LineageOS builds with luet https://github.com/mudler/android-builds Example repository template to build packages on github actions and push packages on a container registry https://github.com/Luet-lab/github-repository Immutable container OS toolkit https://github.com/rancher-sandbox/cOS-toolkit mocaccinoOS desktop https://github.com/mocaccinoOS/desktop mocaccinoOS extra https://github.com/mocaccinoOS/mocaccino-extra agregOS built with luet/mocaccino https://interne.agreg.org/agregOS/ ","categories":"","description":"References to various resources related to luet","excerpt":"References to various resources related to luet","ref":"/docs/resources/references/","tags":"","title":"References"},{"body":"Contributing to Luet Contribution guidelines for the Luet project are on the Github repository. Here you can find some heads up for contributing to the documentation website.\nContributing to the Docs website We Develop with Github We use github to host code, to track issues and feature requests, as well as accept pull requests.\nWe use Hugo to format and generate our website, the Docsy theme for styling and site structure, and Github Actions to manage the deployment of the site. Hugo is an open-source static site generator that provides us with templates, content organisation in a standard directory structure, and a website generation engine. You write the pages in Markdown (or HTML if you want), and Hugo wraps them up into a website.\nAll submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult GitHub Help for more information on using pull requests.\nAny contributions you make will be under the Software License of the repository In short, when you submit code changes, your submissions are understood to be under the same License that covers the project. Feel free to contact the maintainers if that’s a concern.\nUpdating a single page If you’ve just spotted something you’d like to change while using the docs, Docsy has a shortcut for you:\n Click Edit this page in the top right hand corner of the page you want to modify. If you don’t already have an up to date fork of the project repo, you are prompted to get one - click Fork this repository and propose changes or Update your Fork to get an up to date version of the project to edit. The appropriate page in your fork is displayed in edit mode. Quick start with a local checkout Here’s a quick guide to updating the docs with a git local checkout. It assumes you’re familiar with the GitHub workflow and you’re happy to use the automated preview of your doc updates:\n Fork the the Docs repo on GitHub. Make your changes, to see the preview run make serve and browse to localhost:1313 If you’re not yet ready for a review, add “WIP” to the PR name to indicate it’s a work in progress. Continue updating your doc and pushing your changes until you’re happy with the content. When you’re ready for a review, add a comment to the PR, and remove any “WIP” markers. When you are satisfied send a pull request (PR). License By contributing, you agree that your contributions will be licensed under the project Licenses.\n","categories":"","description":"","excerpt":"Contributing to Luet Contribution guidelines for the Luet project are …","ref":"/docs/contribution-guidelines/","tags":"","title":"Contributing"},{"body":"This release comes with a lot of bugfixes and enhancement to the SAT solver core:\n Add support for provides. They allow to have virtual packages which can be replaced during solving by other drop-in packages. Tons of fixes Preparation for upcoming compression support ","categories":"","description":"X-Mas release!\n","excerpt":"X-Mas release!\n","ref":"/blog/2019/12/23/0.3-release/","tags":"","title":"0.3 Release"},{"body":"Finally the website is up! Docs are a work in progress. Stay tuned for more upcoming updates\n","categories":"","description":"Website is up\n","excerpt":"Website is up\n","ref":"/blog/2019/12/23/website-is-up/","tags":"","title":"Website is up"},{"body":"","categories":"","description":"","excerpt":"","ref":"/index.json","tags":"","title":""},{"body":" #td-cover-block-0 { background-image: url(/about/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_806797_960x540_fill_q75_catmullrom_bottom.jpg); } @media only screen and (min-width: 1200px) { #td-cover-block-0 { background-image: url(/about/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_806797_1920x1080_fill_q75_catmullrom_bottom.jpg); } } About Luet Luet is a Package Manager which uses Containers technologies. Luet uses Container technologies ( Docker, img ) to build packages. It provides an abstraction over the Dockerfile format introducing relation and versioning of images.\n Zero-deps installer The installer can run in \"from scratch\" environment - your system will be always recoverable - everything which was built from containers can be installed locally. In few commands it allows you to switch between multiple Linux Distributions, in runtime! ","categories":"","description":"","excerpt":" #td-cover-block-0 { background-image: …","ref":"/about/","tags":"","title":"About Luet"},{"body":"This is the blog section. It has two categories: News and Releases.\nFiles in these directories will be listed in reverse chronological order.\n","categories":"","description":"","excerpt":"This is the blog section. It has two categories: News and Releases. …","ref":"/blog/","tags":"","title":"Luet Blog"},{"body":"","categories":"","description":"","excerpt":"","ref":"/community/","tags":"","title":"Community"},{"body":" #td-cover-block-0 { background-image: url(/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_291319_960x540_fill_q75_catmullrom_top.jpg); } @media only screen and (min-width: 1200px) { #td-cover-block-0 { background-image: url(/featured-background_hu3d03a01dcc18bc5be0e67db3d8d209a6_291319_1920x1080_fill_q75_catmullrom_top.jpg); } } Luet Documentation Download Container Package Manager\n Luet uses Container technologies ( Docker, img ) to build packages. It provides an abstraction over the Dockerfile format introducing relation and versioning of images.\n SAT Solver Luet uses SAT Solving techniques to compute the dependencies graph. This allows to refer to docker images by using semver constraints.\nNo Relational db is involved.\n Contributions welcome! If you like to play with code, check out our issues that are marked as “good first issue” and open a Pull Request on GitHub. New users are always welcome, and have fun!\n Read more …\n Container-based Use container abstraction to define your package repositories\n Releasing is not anymore a nightmare You can carefully pick now dependencies to make your release - release composed of container images or either of a set of packages Package Management Build, ship and delivery your software. Faster\n 0 dep installer When Luet is used as installer, it has zero dependencies.\nYour system can’t break anymore\n Reconstruct images Thanks to its SAT core, Luet can reconstruct images defined by dependencies and version constraints.\nBuilding a de-facto tree of container images\n ","categories":"","description":"","excerpt":" #td-cover-block-0 { background-image: …","ref":"/","tags":"","title":"Luet docs"},{"body":"","categories":"","description":"","excerpt":"","ref":"/search/","tags":"","title":"Search Results"}]
\ No newline at end of file
diff --git a/search/index.html b/search/index.html
index fcaf7e2c..728b40b4 100644
--- a/search/index.html
+++ b/search/index.html
@@ -25,11 +25,11 @@
-
+
-
+
@@ -142,7 +142,7 @@ if (!doNotTrack) {
aria-label="Search this site…"
autocomplete="off"
- data-offline-search-index-json-src="/offline-search-index.2d5033d97ec0001a71adb66bf2d6599d.json"
+ data-offline-search-index-json-src="/offline-search-index.72b6075a770705d05a5c74adb1af94ee.json"
data-offline-search-base-href="/"
data-offline-search-max-results="10"
>
diff --git a/sitemap.xml b/sitemap.xml
index 4f2cf45d..842c264c 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -3,102 +3,102 @@
xmlns:xhtml="http://www.w3.org/1999/xhtml">
https://luet.io/docs/concepts/overview/build_packages/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/tutorials/hello_world/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/getting-started/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/overview/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/overview/repositories/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/packages/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/packages/specfile/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/overview/usage/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/tutorials/build_package/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/plugins-and-extensions/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/packages/templates/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/arm/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/building/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/packages/collections/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/concepts/overview/constraints/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/faq/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/scratch/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/tutorials/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/blog/news/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/blog/releases/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/resources/references/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/docs/contribution-guidelines/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/blog/2019/12/23/0.3-release/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/blog/2019/12/23/website-is-up/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/index.json
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/about/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/blog/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/community/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00
https://luet.io/search/
- 2022-02-04T19:55:03+01:00
+ 2022-02-15T21:17:32+01:00