mirror of
https://github.com/Start9Labs/documentation.git
synced 2026-03-26 10:21:53 +00:00
Merge pull request #190 from Start9Labs/update/dev-docs
Dev Docs Refactor and Update
This commit is contained in:
321
poetry.lock
generated
321
poetry.lock
generated
@@ -98,7 +98,7 @@ optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.extras]
|
||||
test = ["hypothesis (==3.55.3)", "flake8 (==3.7.8)"]
|
||||
test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "docutils"
|
||||
@@ -409,8 +409,8 @@ python-versions = ">=3.7"
|
||||
sphinx = ">=3"
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest", "pre-commit"]
|
||||
doc = ["alabaster"]
|
||||
test = ["pre-commit", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinx-copybutton"
|
||||
@@ -424,8 +424,8 @@ python-versions = ">=3.6"
|
||||
sphinx = ">=1.8"
|
||||
|
||||
[package.extras]
|
||||
rtd = ["sphinx-book-theme", "myst-nb", "ipython", "sphinx"]
|
||||
code_style = ["pre-commit (==2.12.1)"]
|
||||
rtd = ["sphinx", "ipython", "myst-nb", "sphinx-book-theme"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinx-multiversion-scylla"
|
||||
@@ -526,8 +526,8 @@ optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.extras]
|
||||
lint = ["flake8", "mypy", "docutils-stubs"]
|
||||
test = ["pytest"]
|
||||
lint = ["docutils-stubs", "mypy", "flake8"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-devhelp"
|
||||
@@ -538,8 +538,8 @@ optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.extras]
|
||||
lint = ["flake8", "mypy", "docutils-stubs"]
|
||||
test = ["pytest"]
|
||||
lint = ["docutils-stubs", "mypy", "flake8"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-htmlhelp"
|
||||
@@ -550,8 +550,8 @@ optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.extras]
|
||||
test = ["html5lib", "pytest"]
|
||||
lint = ["docutils-stubs", "mypy", "flake8"]
|
||||
lint = ["flake8", "mypy", "docutils-stubs"]
|
||||
test = ["pytest", "html5lib"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-jsmath"
|
||||
@@ -562,7 +562,7 @@ optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.extras]
|
||||
test = ["mypy", "flake8", "pytest"]
|
||||
test = ["pytest", "flake8", "mypy"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-qthelp"
|
||||
@@ -573,8 +573,8 @@ optional = false
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[package.extras]
|
||||
lint = ["flake8", "mypy", "docutils-stubs"]
|
||||
test = ["pytest"]
|
||||
lint = ["docutils-stubs", "mypy", "flake8"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-serializinghtml"
|
||||
@@ -601,7 +601,7 @@ requests = "*"
|
||||
Sphinx = ">=0.6"
|
||||
|
||||
[package.extras]
|
||||
doc = ["furo", "sphinx-copybutton"]
|
||||
doc = ["sphinx-copybutton", "furo"]
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
@@ -669,59 +669,278 @@ python-versions = "^3.7"
|
||||
content-hash = "95d7a496b22ba873ce8df134690fe30b3fac088d4fe393bd505e025598d55711"
|
||||
|
||||
[metadata.files]
|
||||
alabaster = []
|
||||
argh = []
|
||||
alabaster = [
|
||||
{file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
|
||||
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
|
||||
]
|
||||
argh = [
|
||||
{file = "argh-0.26.2-py2.py3-none-any.whl", hash = "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3"},
|
||||
{file = "argh-0.26.2.tar.gz", hash = "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65"},
|
||||
]
|
||||
atomicwrites = []
|
||||
attrs = []
|
||||
babel = []
|
||||
beautifulsoup4 = []
|
||||
beautifulsoup4 = [
|
||||
{file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"},
|
||||
{file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"},
|
||||
]
|
||||
certifi = []
|
||||
charset-normalizer = []
|
||||
colorama = []
|
||||
commonmark = []
|
||||
docutils = []
|
||||
commonmark = [
|
||||
{file = "commonmark-0.9.1-py2.py3-none-any.whl", hash = "sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9"},
|
||||
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
|
||||
]
|
||||
docutils = [
|
||||
{file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
|
||||
{file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
|
||||
]
|
||||
idna = []
|
||||
imagesize = []
|
||||
imagesize = [
|
||||
{file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"},
|
||||
{file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"},
|
||||
]
|
||||
importlib-metadata = []
|
||||
jinja2 = []
|
||||
livereload = []
|
||||
markupsafe = []
|
||||
jinja2 = [
|
||||
{file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"},
|
||||
{file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"},
|
||||
]
|
||||
livereload = [
|
||||
{file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"},
|
||||
]
|
||||
markupsafe = [
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
|
||||
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
|
||||
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
|
||||
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
|
||||
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
|
||||
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
|
||||
]
|
||||
more-itertools = []
|
||||
packaging = []
|
||||
pathtools = []
|
||||
pluggy = []
|
||||
port-for = []
|
||||
py = []
|
||||
packaging = [
|
||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||
]
|
||||
pathtools = [
|
||||
{file = "pathtools-0.1.2.tar.gz", hash = "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"},
|
||||
]
|
||||
pluggy = [
|
||||
{file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
|
||||
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
|
||||
]
|
||||
port-for = [
|
||||
{file = "port-for-0.3.1.tar.gz", hash = "sha256:b16a84bb29c2954db44c29be38b17c659c9c27e33918dec16b90d375cc596f1c"},
|
||||
]
|
||||
py = [
|
||||
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
|
||||
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
|
||||
]
|
||||
pygments = []
|
||||
pyparsing = []
|
||||
pytest = []
|
||||
pyparsing = [
|
||||
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
|
||||
{file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
|
||||
]
|
||||
pytest = [
|
||||
{file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"},
|
||||
{file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"},
|
||||
]
|
||||
pytz = []
|
||||
pyyaml = []
|
||||
recommonmark = []
|
||||
requests = []
|
||||
six = []
|
||||
snowballstemmer = []
|
||||
soupsieve = []
|
||||
sphinx = []
|
||||
sphinx-autobuild = []
|
||||
sphinx-collapse = []
|
||||
sphinx-copybutton = []
|
||||
sphinx-multiversion-scylla = []
|
||||
pyyaml = [
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
|
||||
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
|
||||
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
|
||||
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
|
||||
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
|
||||
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
|
||||
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
|
||||
]
|
||||
recommonmark = [
|
||||
{file = "recommonmark-0.5.0-py2.py3-none-any.whl", hash = "sha256:c85228b9b7aea7157662520e74b4e8791c5eacd375332ec68381b52bf10165be"},
|
||||
{file = "recommonmark-0.5.0.tar.gz", hash = "sha256:a520b8d25071a51ae23a27cf6252f2fe387f51bdc913390d83b2b50617f5bb48"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
|
||||
{file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
|
||||
]
|
||||
six = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
snowballstemmer = [
|
||||
{file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
|
||||
{file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
|
||||
]
|
||||
soupsieve = [
|
||||
{file = "soupsieve-2.3.2.post1-py3-none-any.whl", hash = "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759"},
|
||||
{file = "soupsieve-2.3.2.post1.tar.gz", hash = "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d"},
|
||||
]
|
||||
sphinx = [
|
||||
{file = "Sphinx-4.5.0-py3-none-any.whl", hash = "sha256:ebf612653238bcc8f4359627a9b7ce44ede6fdd75d9d30f68255c7383d3a6226"},
|
||||
{file = "Sphinx-4.5.0.tar.gz", hash = "sha256:7bf8ca9637a4ee15af412d1a1d9689fec70523a68ca9bb9127c2f3eeb344e2e6"},
|
||||
]
|
||||
sphinx-autobuild = [
|
||||
{file = "sphinx-autobuild-0.7.1.tar.gz", hash = "sha256:66388f81884666e3821edbe05dd53a0cfb68093873d17320d0610de8db28c74e"},
|
||||
{file = "sphinx_autobuild-0.7.1-py2-none-any.whl", hash = "sha256:e60aea0789cab02fa32ee63c7acae5ef41c06f1434d9fd0a74250a61f5994692"},
|
||||
]
|
||||
sphinx-collapse = [
|
||||
{file = "sphinx_collapse-0.1.2-py3-none-any.whl", hash = "sha256:7a2082da3c779916cc4c4d44832db3522a3a8bfbd12598ef01fb9eb523a164d0"},
|
||||
{file = "sphinx_collapse-0.1.2.tar.gz", hash = "sha256:a186000bf3fdac8ac0e8a99979f720ae790de15a5efc1435d4816f79a3d377c2"},
|
||||
]
|
||||
sphinx-copybutton = [
|
||||
{file = "sphinx-copybutton-0.5.0.tar.gz", hash = "sha256:a0c059daadd03c27ba750da534a92a63e7a36a7736dcf684f26ee346199787f6"},
|
||||
{file = "sphinx_copybutton-0.5.0-py3-none-any.whl", hash = "sha256:9684dec7434bd73f0eea58dda93f9bb879d24bff2d8b187b1f2ec08dfe7b5f48"},
|
||||
]
|
||||
sphinx-multiversion-scylla = [
|
||||
{file = "sphinx-multiversion-scylla-0.2.10.tar.gz", hash = "sha256:b54d664ecedcf45b98d6be1e939eac596719daa514e4a35f58d8e6330fb05d22"},
|
||||
]
|
||||
sphinx-notfound-page = []
|
||||
sphinx-scylladb-theme = []
|
||||
sphinx-sitemap = []
|
||||
sphinx-substitution-extensions = []
|
||||
sphinx-tabs = []
|
||||
sphinxcontrib-applehelp = []
|
||||
sphinxcontrib-devhelp = []
|
||||
sphinxcontrib-htmlhelp = []
|
||||
sphinxcontrib-jsmath = []
|
||||
sphinxcontrib-qthelp = []
|
||||
sphinxcontrib-serializinghtml = []
|
||||
sphinxcontrib-youtube = []
|
||||
tornado = []
|
||||
sphinx-scylladb-theme = [
|
||||
{file = "sphinx-scylladb-theme-1.2.1.tar.gz", hash = "sha256:55923651acb74988755fd818175999e953e018d372cb778dd5120b03f71fe5ab"},
|
||||
{file = "sphinx_scylladb_theme-1.2.1-py3-none-any.whl", hash = "sha256:2666a6990c87c9601beb0c49f118e87d03b27c248ad263e553c3c9dbd9247ec9"},
|
||||
]
|
||||
sphinx-sitemap = [
|
||||
{file = "sphinx-sitemap-2.1.0.tar.gz", hash = "sha256:ba3576f38e8d1cabde483dabed2cc2b958af85ff97f2a4442f990b02e967d6a5"},
|
||||
]
|
||||
sphinx-substitution-extensions = [
|
||||
{file = "Sphinx Substitution Extensions-2022.2.16.tar.gz", hash = "sha256:ff7d05bd00e8b2d7eb8a403b9f317d70411d4e9b6812bf91534a50df22190c75"},
|
||||
{file = "Sphinx_Substitution_Extensions-2022.2.16-py3-none-any.whl", hash = "sha256:5a8ca34dac3984486344e95c36e3ed4766d402a71bdee7390d600f153db9795b"},
|
||||
]
|
||||
sphinx-tabs = [
|
||||
{file = "sphinx-tabs-3.4.0.tar.gz", hash = "sha256:75e97ce10b74700deaf87b662539a293c8afc9dfa9d21f126b860118064cb0c5"},
|
||||
{file = "sphinx_tabs-3.4.0-py3-none-any.whl", hash = "sha256:31dbe7594b5ef4cfa76a7960448d4607dca167ff21467000213920572c302072"},
|
||||
]
|
||||
sphinxcontrib-applehelp = [
|
||||
{file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
|
||||
{file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
|
||||
]
|
||||
sphinxcontrib-devhelp = [
|
||||
{file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
|
||||
{file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
|
||||
]
|
||||
sphinxcontrib-htmlhelp = [
|
||||
{file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"},
|
||||
{file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"},
|
||||
]
|
||||
sphinxcontrib-jsmath = [
|
||||
{file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
|
||||
{file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
|
||||
]
|
||||
sphinxcontrib-qthelp = [
|
||||
{file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
|
||||
{file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
|
||||
]
|
||||
sphinxcontrib-serializinghtml = [
|
||||
{file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"},
|
||||
{file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"},
|
||||
]
|
||||
sphinxcontrib-youtube = [
|
||||
{file = "sphinxcontrib-youtube-1.2.0.tar.gz", hash = "sha256:f468b76550e926c6d918c97b921d6ccc8ec6bc13004746dea309788ea9268991"},
|
||||
{file = "sphinxcontrib_youtube-1.2.0-py3-none-any.whl", hash = "sha256:fcc9301b5df3269597310c1ab41806b25fb7bfe41b0344aa8871dbd820d08ca4"},
|
||||
]
|
||||
tornado = [
|
||||
{file = "tornado-6.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:20f638fd8cc85f3cbae3c732326e96addff0a15e22d80f049e00121651e82e72"},
|
||||
{file = "tornado-6.2-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:87dcafae3e884462f90c90ecc200defe5e580a7fbbb4365eda7c7c1eb809ebc9"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba09ef14ca9893954244fd872798b4ccb2367c165946ce2dd7376aebdde8e3ac"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b8150f721c101abdef99073bf66d3903e292d851bee51910839831caba341a75"},
|
||||
{file = "tornado-6.2-cp37-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3a2f5999215a3a06a4fc218026cd84c61b8b2b40ac5296a6db1f1451ef04c1e"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:5f8c52d219d4995388119af7ccaa0bcec289535747620116a58d830e7c25d8a8"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_i686.whl", hash = "sha256:6fdfabffd8dfcb6cf887428849d30cf19a3ea34c2c248461e1f7d718ad30b66b"},
|
||||
{file = "tornado-6.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:1d54d13ab8414ed44de07efecb97d4ef7c39f7438cf5e976ccd356bebb1b5fca"},
|
||||
{file = "tornado-6.2-cp37-abi3-win32.whl", hash = "sha256:5c87076709343557ef8032934ce5f637dbb552efa7b21d08e89ae7619ed0eb23"},
|
||||
{file = "tornado-6.2-cp37-abi3-win_amd64.whl", hash = "sha256:e5f923aa6a47e133d1cf87d60700889d7eae68988704e20c75fb2d65677a8e4b"},
|
||||
{file = "tornado-6.2.tar.gz", hash = "sha256:9b630419bde84ec666bfd7ea0a4cb2a8a651c2d5cccdbdd1972a0c859dfc3c13"},
|
||||
]
|
||||
typing-extensions = []
|
||||
urllib3 = []
|
||||
watchdog = []
|
||||
wcwidth = []
|
||||
watchdog = [
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"},
|
||||
{file = "watchdog-2.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ee3e38a6cc050a8830089f79cbec8a3878ec2fe5160cdb2dc8ccb6def8552658"},
|
||||
{file = "watchdog-2.1.9-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64a27aed691408a6abd83394b38503e8176f69031ca25d64131d8d640a307591"},
|
||||
{file = "watchdog-2.1.9-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:195fc70c6e41237362ba720e9aaf394f8178bfc7fa68207f112d108edef1af33"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bfc4d351e6348d6ec51df007432e6fe80adb53fd41183716017026af03427846"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8250546a98388cbc00c3ee3cc5cf96799b5a595270dfcfa855491a64b86ef8c3"},
|
||||
{file = "watchdog-2.1.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:117ffc6ec261639a0209a3252546b12800670d4bf5f84fbd355957a0595fe654"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:97f9752208f5154e9e7b76acc8c4f5a58801b338de2af14e7e181ee3b28a5d39"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:247dcf1df956daa24828bfea5a138d0e7a7c98b1a47cf1fa5b0c3c16241fcbb7"},
|
||||
{file = "watchdog-2.1.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:226b3c6c468ce72051a4c15a4cc2ef317c32590d82ba0b330403cafd98a62cfd"},
|
||||
{file = "watchdog-2.1.9-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9820fe47c20c13e3c9dd544d3706a2a26c02b2b43c993b62fcd8011bcc0adb3"},
|
||||
{file = "watchdog-2.1.9-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:70af927aa1613ded6a68089a9262a009fbdf819f46d09c1a908d4b36e1ba2b2d"},
|
||||
{file = "watchdog-2.1.9-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed80a1628cee19f5cfc6bb74e173f1b4189eb532e705e2a13e3250312a62e0c9"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9f05a5f7c12452f6a27203f76779ae3f46fa30f1dd833037ea8cbc2887c60213"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_armv7l.whl", hash = "sha256:255bb5758f7e89b1a13c05a5bceccec2219f8995a3a4c4d6968fe1de6a3b2892"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_i686.whl", hash = "sha256:d3dda00aca282b26194bdd0adec21e4c21e916956d972369359ba63ade616153"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64.whl", hash = "sha256:186f6c55abc5e03872ae14c2f294a153ec7292f807af99f57611acc8caa75306"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:083171652584e1b8829581f965b9b7723ca5f9a2cd7e20271edf264cfd7c1412"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_s390x.whl", hash = "sha256:b530ae007a5f5d50b7fbba96634c7ee21abec70dc3e7f0233339c81943848dc1"},
|
||||
{file = "watchdog-2.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4f4e1c4aa54fb86316a62a87b3378c025e228178d55481d30d857c6c438897d6"},
|
||||
{file = "watchdog-2.1.9-py3-none-win32.whl", hash = "sha256:5952135968519e2447a01875a6f5fc8c03190b24d14ee52b0f4b1682259520b1"},
|
||||
{file = "watchdog-2.1.9-py3-none-win_amd64.whl", hash = "sha256:7a833211f49143c3d336729b0020ffd1274078e94b0ae42e22f596999f50279c"},
|
||||
{file = "watchdog-2.1.9-py3-none-win_ia64.whl", hash = "sha256:ad576a565260d8f99d97f2e64b0f97a48228317095908568a9d5c786c829d428"},
|
||||
{file = "watchdog-2.1.9.tar.gz", hash = "sha256:43ce20ebb36a51f21fa376f76d1d4692452b2527ccd601950d69ed36b9e21609"},
|
||||
]
|
||||
wcwidth = [
|
||||
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
|
||||
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
|
||||
]
|
||||
zipp = []
|
||||
|
||||
BIN
site/source/_static/images/dev/nc-install.png
Normal file
BIN
site/source/_static/images/dev/nc-install.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
site/source/_static/images/dev/nc-service.png
Normal file
BIN
site/source/_static/images/dev/nc-service.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 189 KiB |
@@ -1,34 +0,0 @@
|
||||
.. _packaging-framework:
|
||||
|
||||
=============
|
||||
1 - Framework
|
||||
=============
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
What we'll build
|
||||
----------------
|
||||
|
||||
We'll create a web application that produces a hello world page. This web application will be the service we package for the Embassy. During this guide we will:
|
||||
|
||||
1. Create a simple hello world web service
|
||||
2. Create a Dockerfile
|
||||
3. Create a Package Manifest
|
||||
4. Create a hosted repository which will contain all the service components
|
||||
5. Create the packaged service file
|
||||
|
||||
You can find the `complete code <https://github.com/Start9Labs/hello-world-wrapper>`_ referenced in this guide on GitHub.
|
||||
|
||||
Download required tools
|
||||
-----------------------
|
||||
|
||||
If necessary, download any of the system requirements:
|
||||
|
||||
- Docker
|
||||
- EmbassySDK
|
||||
- A code editor
|
||||
- Terminal
|
||||
|
||||
For more details and installation steps for these tools, visit the :ref:`environment setup <environment-setup>` page.
|
||||
@@ -1,80 +0,0 @@
|
||||
.. _packaging-create-service:
|
||||
|
||||
==================
|
||||
2 - Create Service
|
||||
==================
|
||||
|
||||
For this example, we are going to create a simple Rust project that serves a static web page.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mkdir hello-world && cd hello-world
|
||||
cargo init
|
||||
touch src/index.html
|
||||
|
||||
In ``index.html`` add:
|
||||
|
||||
.. code:: html
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
In ``main.rs`` add:
|
||||
|
||||
.. code:: rust
|
||||
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{body::Bytes, Body, Request, Response, Server};
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
async fn handle(_req: Request<Body>) -> Result<Response<Body>, Infallible> {
|
||||
Ok(Response::new(Body::from(Bytes::from_static(
|
||||
include_bytes!("index.html"),
|
||||
))))
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// Construct our SocketAddr to listen on...
|
||||
let addr = SocketAddr::from(([0, 0, 0, 0], 80));
|
||||
|
||||
// And a MakeService to handle each connection...
|
||||
let make_service = make_service_fn(|_conn| async { Ok::<_, Infallible>(service_fn(handle)) });
|
||||
|
||||
// Then bind and serve...
|
||||
let server = Server::bind(&addr).serve(make_service);
|
||||
|
||||
// And run forever...
|
||||
if let Err(e) = server.await {
|
||||
eprintln!("server error: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Finally, in our ``Cargo.toml``, we need to add some dependencies, which will look like this:
|
||||
|
||||
.. code:: toml
|
||||
|
||||
[dependencies]
|
||||
hyper = { version = "0.14.4", features = ["server", "http1", "http2", "tcp", "stream"] }
|
||||
tokio = { version = "1.4.0", features = ["full"] }
|
||||
|
||||
|
||||
**That's it!** We now have the code for our service.
|
||||
|
||||
Let's build and run it!
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# build the project
|
||||
cargo build
|
||||
# start the executable
|
||||
target/debug/hello-world
|
||||
|
||||
Visit `<http://localhost:80>`_ to see your running web page!
|
||||
@@ -1,39 +0,0 @@
|
||||
.. _packaging-compile-raspi:
|
||||
|
||||
==================
|
||||
3 - Hardware Build
|
||||
==================
|
||||
|
||||
embassyOS is run on the arm-v8 architecture, specifically the aarch64 state, for the RaspberryPi.
|
||||
|
||||
Depending on the programming language or libraries used in a project, you might need to set up an environment to *cross compile* the executable for this runtime environment.
|
||||
|
||||
We were able to easily build and run our project locally. However, Rust is one of those programming languages that needs to be cross compiled. This step can be skipped if it does not apply to your project.
|
||||
|
||||
Since Start9 uses Rust throughout its service ecosystem, the team has built a helper to cross compile Rust projects for the Embassy.
|
||||
|
||||
This Rust cross compiler for aarch64 can be downloaded and build from `GitHub <https://github.com/Start9Labs/rust-musl-cross>`_:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git clone https://github.com/Start9Labs/rust-musl-cross.git
|
||||
cd rust-musl-cross
|
||||
chmod a+x ./build.sh
|
||||
./build.sh
|
||||
|
||||
This actually builds a Docker container for us to use locally so we can emulate the environment we need to compile our project for aarch64!
|
||||
|
||||
|
||||
Next, we enable cross-arch emulated builds in Docker
|
||||
|
||||
.. code:: bash
|
||||
|
||||
docker run --privileged --rm linuxkit/binfmt:v0.8
|
||||
|
||||
Finally, we run the following command to build the project, replacing `/absolute/path/to` with the output of `pwd` as necessary:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
docker run --rm -it -v ~/.cargo/registry:/root/.cargo/registry -v "/absolute/path/to"/hello-world:/home/rust/src start9/rust-musl-cross:aarch64-musl cargo build --release
|
||||
|
||||
Awesome! We can now see the compiled executable here: `./hello-world/target/aarch64-unknown-linux-musl/release/hello-world`
|
||||
@@ -1,77 +0,0 @@
|
||||
.. _packaging-docker-build:
|
||||
|
||||
================
|
||||
4 - Docker Build
|
||||
================
|
||||
|
||||
Now that we have our code properly built/compiled, we can create a Dockerfile. This file defines how to build the Docker image for the service by declaring the environment, building stages, and copying any binaries or assets needed to run the service to the Docker image filesystem.
|
||||
|
||||
In other words, the Dockerfile serves as a recipe for creating a Docker image, from which Docker containers are spun up. This is ultimately what runs an instance of your service on the Embassy.
|
||||
|
||||
1. Create the necessary Docker files:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch Dockerfile
|
||||
touch docker_entrypoint.sh
|
||||
|
||||
2. We'll start editing the ``Dockerfile`` by importing a base image, in this case Alpine, as recommended.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
FROM arm64v8/alpine:3.12
|
||||
|
||||
3. Next, we issue some commands to setup the filesystem. Here we update repositories and install required system packages.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
RUN apk update
|
||||
RUN apk add tini curl
|
||||
|
||||
4. Next, we add the cross-compiled binary of ``hello-world`` to ``/usr/local/bin/`` and add the ``docker_entrypoint.sh`` file from the project root. Then, we set permissions for ``docker_entrypoint.sh``.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
ADD ./hello-world/target/aarch64-unknown-linux-musl/release/hello-world /usr/local/bin/hello-world
|
||||
ADD ./docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
|
||||
RUN chmod a+x /usr/local/bin/docker_entrypoint.sh
|
||||
|
||||
5. Next, we set a working directory, and set the location of the entrypoint. Exposing ports is not necessary for eOS, but its often useful to leave this line for quick reference and clarity.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
|
||||
|
||||
6. **That's it!** Let's take a look at our final ``Dockerfile``:
|
||||
|
||||
.. code:: docker
|
||||
|
||||
FROM arm64v8/alpine:3.12
|
||||
|
||||
RUN apk update
|
||||
RUN apk add tini
|
||||
|
||||
ADD ./hello-world/target/aarch64-unknown-linux-musl/release/hello-world /usr/local/bin/hello-world
|
||||
ADD ./docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
|
||||
RUN chmod a+x /usr/local/bin/docker_entrypoint.sh
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
# not necessary for embassyOS, but often left for quick reference and clarity
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
|
||||
|
||||
7. Finally, add the following code to the ``docker_entrypoint.sh``:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
exec tini hello-world
|
||||
|
||||
This is a script that defines how the service starts, and often acts as an init system. It will need to complete any environment setup (such as folder substructure), set any environment variables, and execute the run command. It's also PID 1 in the Docker container, so should do all of the signal handling for container exits.
|
||||
@@ -1,257 +0,0 @@
|
||||
.. _packaging-create-manifest:
|
||||
|
||||
===================
|
||||
5 - Create Manifest
|
||||
===================
|
||||
|
||||
The Manifest file specifies the details embassyOS needs to operate a service. It is the connection point between your service and embassyOS.
|
||||
|
||||
In this file, values and actions exist for:
|
||||
|
||||
- Displaying the service in the marketplace
|
||||
- Specifying the project assets (eg. icon, instructions, license)
|
||||
- Defining the docker mount points
|
||||
- Specifying how to configure the service
|
||||
- Relaying how to run health checks, backups, and other custom actions
|
||||
- Outlining dependency relationships (if applicable) and configuration rules for dependencies
|
||||
- Denoting copy to display in EmbassyUI elements, alerts, descriptions
|
||||
|
||||
This file can be written in:
|
||||
|
||||
- yaml
|
||||
- toml
|
||||
- json
|
||||
|
||||
Let's create a yaml manifest file for our hello-world project:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch manifest.yaml
|
||||
|
||||
And populate it with the following example manifest (see the line comments for a description of each key and view the full :ref:`type specification here <service_manifest>`):
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
# The package identifier used by the OS
|
||||
id: hello-world
|
||||
# A human readable service title
|
||||
title: "Hello World"
|
||||
# Service version - accepts up to four digits, where the last confirms to revisions necessary for embassyOS - see documentation: https://github.com/Start9Labs/emver-rs
|
||||
version: 0.3.0
|
||||
# Release notes for the update - can be a string, paragraph or URL
|
||||
release-notes: "Upgrade to embassyOS v0.3.0"
|
||||
# The type of license for the project. Include the LICENSE in the root of the project directory. A license is required for a Start9 package.
|
||||
license: mit
|
||||
# The Start9 wrapper repository URL for the package. This repo contains the manifest file (this), any scripts necessary for configuration, backups, actions, or health checks (more below). This key must exist. But could be embedded into the source repository.
|
||||
wrapper-repo: "https://github.com/Start9Labs/hello-world-wrapper"
|
||||
# The original project repository URL. There is no upstream repo in this example
|
||||
upstream-repo: "https://github.com/Start9Labs/hello-world-wrapper"
|
||||
# URL to the support site / channel for the project. This key can be omitted if none exists, or it can link to the original project repository issues.
|
||||
support-site: "https://docs.start9.com/"
|
||||
# URL to the marketing site for the project. This key can be omitted if none exists, or it can link to the original project repository.
|
||||
marketing-site: "https://start9.com/"
|
||||
# The series of commands to build the project into an s9pk for arm64/v8. In this case we are using a Makefile with the simple build command "make".
|
||||
build: ["make"]
|
||||
# Minimum required version of embassyOS
|
||||
min-os-version: "0.3.0"
|
||||
# Human readable descriptors for the service. These are used throughout the embassyOS user interface, primarily in the marketplace.
|
||||
description:
|
||||
# This is the first description visible to the user in the marketplace.
|
||||
short: Example service
|
||||
# This description will display with additional details in the service's individual marketplace page
|
||||
long: |
|
||||
Hello World is a simple example of a service wrapper that launches a web interface to say hello and nothing more.
|
||||
# These assets are static files necessary for packaging the service for Start9 (into an s9pk). Each value is a path to the specified asset. If an asset is missing from this list, or otherwise denoted, it will be defaulted to the values denoted below.
|
||||
assets:
|
||||
# Default = LICENSE.md
|
||||
license: LICENSE
|
||||
# Default = icon.png
|
||||
icon: icon.png
|
||||
# Default = INSTRUCTIONS.md
|
||||
instructions: instructions.md
|
||||
# Default = image.tar
|
||||
docker-images: image.tar
|
||||
# The main action for initializing the service. Currently, the only type of action available is docker.
|
||||
main:
|
||||
# Docker is currently the only action implementation
|
||||
type: docker
|
||||
# Identifier for the main image volume, which will be used when other actions need to mount to this volume.
|
||||
image: main
|
||||
# The executable binary for starting the initialization action. For docker actions, this is typically a "docker_entrypoint.sh" file. See the Dockerfile and the docker_entrypoint.sh in this project for additional details.
|
||||
entrypoint: "docker_entrypoint.sh"
|
||||
# Any arguments that should be passed into the entrypoint executable
|
||||
args: []
|
||||
# Specifies where to mount the data volume(s), if there are any. Mounts for pointer dependency volumes are also denoted here. These are necessary if data needs to be read from / written to these volumes.
|
||||
mounts:
|
||||
# Specifies where on the service's file system its persistence directory should be mounted prior to service startup
|
||||
main: /root
|
||||
# Health checks
|
||||
health-checks:
|
||||
main:
|
||||
name: Web Interface
|
||||
description: Ensures the network interface is accessible via HTTP.
|
||||
type: docker
|
||||
image: main
|
||||
entrypoint: "sh"
|
||||
args: ["-c", "curl --silent --show-error --fail http://loacalhost:80"]
|
||||
# When `inject` is true, the health check will use the main image to run the health check. This is faster as there is no need to spin up an additional docker container
|
||||
# When `inject` is false, the health check will use whatever image is specified. This is useful when using a system image with additional utilities to run a health check. If inject=false, then system must equal true
|
||||
inject: true
|
||||
# Optional if false - indicates if an image that is preloaded onto the system will be used
|
||||
system: false
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: json
|
||||
# Specifies how to get and set configuration file values for the service. NOTE: This stanza can be left empty (null) if the service has no configuration options.
|
||||
config:
|
||||
# The config action to run to get the specified config file (default is config.yaml)
|
||||
get:
|
||||
# The type of implementation to run this action (currently, only Docker is available)
|
||||
type: docker
|
||||
# The Docker image to run the action command in. This could be the service's main image, or an image that is preloaded onto the system, like compat (which holds compatible helper functions for default functionality)
|
||||
image: compat
|
||||
# Indicates if an image that is preloaded onto the system will be used
|
||||
system: true
|
||||
# The initial run command to execute the config get action
|
||||
entrypoint: compat
|
||||
# Any arguments that need to be passed into the run command
|
||||
args:
|
||||
- config
|
||||
- get
|
||||
- /root
|
||||
- "/mnt/assets/config_spec.yaml"
|
||||
# The locations at which to mount the specified Docker images
|
||||
mounts:
|
||||
compat: /mnt/assets
|
||||
main: /root
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: yaml
|
||||
# The config action to run to set the specified config file (default is config.yaml). Details for the keys below are the same as above.
|
||||
set:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
args:
|
||||
- config
|
||||
- set
|
||||
- hello-world
|
||||
- /root
|
||||
- "/mnt/assets/config_rules.yaml"
|
||||
mounts:
|
||||
compat: /mnt/assets
|
||||
main: /root
|
||||
io-format: yaml
|
||||
# This is a key value map specifying dependent services that this service needs in order to function. The keys are the package id's on which you depend. NOTE: if developing a standalone service, you may leave this stanza as an empty object (the key dependencies is required)
|
||||
dependencies:
|
||||
# Key must be the package id of another service that exists in the marketplace
|
||||
filebrowser:
|
||||
# The version range that is acceptable for this dependency
|
||||
version: "^2.14.1.1"
|
||||
# Describes if the dependency is critical to the service functioning. If the dependency is critical, the service will stop if this dependency is stopped.
|
||||
critical: false
|
||||
# Specifies the requirement type of the dependency
|
||||
requirement:
|
||||
# "Opt-out" means the dependency will be required according to the default config. "Opt-in" means the dependency may be required if you change the config. And "required" just means it's always required.
|
||||
type: "opt-out"
|
||||
# An explanation of how to opt-in or opt-out. This value is optional for type=required
|
||||
how: Optionally use the selected dependency
|
||||
# Description of the dependency relationship
|
||||
description: A dependency that demonstrates the way to configure a dependent service
|
||||
# This is a list of rules that levies requirements on the configuration of the dependency and suggests ways to remedy any incompatibilities. Documentation of this feature is outside the scope of this example.
|
||||
config: ~
|
||||
# This denotes any data, asset, or pointer volumes that should be connected when the "docker run" command is invoked
|
||||
volumes:
|
||||
# This is the image where files from the project asset directory will go
|
||||
main:
|
||||
type: data
|
||||
# This is an example of an asset volume
|
||||
compat:
|
||||
type: assets
|
||||
# This specifies how to configure the port mapping for exposing the service over TOR and LAN (if applicable). Many interfaces can be specified depending on the needs of the service. If it can be launched over a Local Area Network connection, specify a `lan-config`. Otherwise, at minimum, a `tor-config` must be specified.
|
||||
interfaces:
|
||||
# This key is the internal name that the OS will use to configure the interface
|
||||
main:
|
||||
# A human readable name for display in the UI
|
||||
name: Network Interface
|
||||
# A descriptive description of what the interface does
|
||||
description: Specifies the interface to listen on for HTTP connections.
|
||||
tor-config:
|
||||
# Port mappings are from the external port to the internal container port
|
||||
port-mapping:
|
||||
80: "80"
|
||||
# Port mappings are from the external port to the internal container port
|
||||
lan-config:
|
||||
80:
|
||||
ssl: false
|
||||
internal: 80
|
||||
# Denotes if the service has a user interface to display
|
||||
ui: true
|
||||
# Denotes the protocol specifications used by this interface
|
||||
protocols:
|
||||
- tcp
|
||||
- http
|
||||
# Alerts: omitting these will result in using the default alerts in embassyOS, except for start, which has no default.
|
||||
alerts:
|
||||
install-alert: This is an alert that will present before the user installs this service
|
||||
uninstall-alert: This is an alert that will present before the user uninstalls this service
|
||||
restore-alert: This is an alert that will present before the user restores this service from Embassy backup
|
||||
start-alert: This is an alert that will present before the user starts this service
|
||||
# Specifies how backups should be run for this service. The default embassyOS provided option is to use the duplicity backup library on a system image (compat)
|
||||
backup:
|
||||
create:
|
||||
# Currently, only docker actions are supported.
|
||||
type: docker
|
||||
# The docker image to use. In this case, a pre-loaded system image called compat
|
||||
image: compat
|
||||
# Required if the action uses a system image. The default value is false.
|
||||
system: true
|
||||
# The executable to run the command to begin the backup create process
|
||||
entrypoint: compat
|
||||
# Arguments to pass into the entrypoint executable. In this example, the full command run will be: `compat duplicity hello-world /mnt/backup /root/data`
|
||||
args:
|
||||
- duplicity
|
||||
- hello-world
|
||||
- /mnt/backup
|
||||
# For duplicity, the backup mount point needs to be something other than `/root`, so we default to `/root/data`
|
||||
- /root/data
|
||||
mounts:
|
||||
# BACKUP is the default volume that is used for backups. This is whatever backup drive is mounted to the device, or a network filesystem.
|
||||
# The value here donates where the mount point will be. The backup drive is mounted to this location.
|
||||
BACKUP: "/mnt/backup"
|
||||
main: "/root"
|
||||
# The action to execute the backup restore functionality. Details for the keys below are the same as above.
|
||||
restore:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
args:
|
||||
- duplicity
|
||||
- hello-world
|
||||
- /root/data
|
||||
- /mnt/backup
|
||||
mounts:
|
||||
BACKUP: "/mnt/backup"
|
||||
main: "/root"
|
||||
# Commands that can be issued from the UI. NOTE: if no actions are required, this section can be left as an empty object
|
||||
actions:
|
||||
hello-world-action:
|
||||
name: Hello World Action
|
||||
description: A description that describes what the action will accomplish.
|
||||
warning: |
|
||||
A warning message indicating and potential dangers associated with the action
|
||||
# Indicates what state the service can be in while executing the action
|
||||
allowed-statuses:
|
||||
- running
|
||||
# Defines how the action is run
|
||||
implementation:
|
||||
type: docker
|
||||
image: main
|
||||
entrypoint: sh
|
||||
args: ["-c", "echo 'hello-world'"]
|
||||
# Same as note on health-checks
|
||||
inject: true
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: json
|
||||
|
||||
**That's it!** You now have the structure for your service's Manifest.
|
||||
@@ -1,56 +0,0 @@
|
||||
.. _packaging-create-assets:
|
||||
|
||||
=================
|
||||
6 - Create Assets
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Each ``s9pk`` package contains a set of assets. They include:
|
||||
|
||||
- Instructions
|
||||
- License
|
||||
- Icon
|
||||
|
||||
Instructions
|
||||
------------
|
||||
|
||||
An instructions file is a convenient way to share any steps users should take to setup or interact with your service. This file gets displayed within an EmbassyUI component and should be written in `Markdown <https://www.markdownguide.org/>`_ language.
|
||||
|
||||
Let's add instructions to our hello world project:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch instructions.md
|
||||
|
||||
And add the following code to the file:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# Instructions for Hello World
|
||||
|
||||
Instructions go here. These appear to the user in the UI on the Service page under 'Instructions.'
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Start9 ensures that the proper license is displayed for all open source software running on an embassyOS platform. Let's make sure to include the full open source license so users can view the distribution permissions of your service, among other licensing details.
|
||||
|
||||
The name and location of this file should be specified in the ``assets.license`` section of the Manifest. The default value if not specified is ``LICENSE``, located in the root of the project folder.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch ./hello-world/LICENSE
|
||||
|
||||
Icon
|
||||
----
|
||||
|
||||
Icons are displayed throughout the EmbassyUI to reference to your service.
|
||||
|
||||
Simply add the icon file to the root of the project directory. The icon file can be named anything, but this must be specified in the ``assets.icon`` section of the Manifest. The default filename the SDk looks for when packaging the service assets is ``icon.png``.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mv /local/path/to/icon ./hello-world/icon.png
|
||||
@@ -1,23 +0,0 @@
|
||||
.. _packaging-create-s9pk:
|
||||
|
||||
==================
|
||||
7 - Format Package
|
||||
==================
|
||||
|
||||
We now have all of the necessary components to package the service into the format needed for the OS. This format is a custom filetype with an extension of ``.s9pk``, short for Start9 Package.
|
||||
|
||||
To package all components into an ``.s9pk``, run the following command from the root of your project directory:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk pack
|
||||
|
||||
Let's also make sure to verify the validity of the package:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk verify s9pk /path/to/hello-world.s9pk
|
||||
|
||||
If anything goes wrong, an error message will indicate the missing component or other failure.
|
||||
|
||||
**That's it!**
|
||||
@@ -1,92 +0,0 @@
|
||||
.. _packaging-makefile:
|
||||
|
||||
===================
|
||||
8 - Create Makefile
|
||||
===================
|
||||
|
||||
For convenience and repeatability, let's combine all of these commands into a Makefile. Then, we can use `make <https://www.gnu.org/software/make/>`_ to rebuild our project quickly.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch Makefile
|
||||
|
||||
1. Add the build rule with the target executable as the key, including a list of dependencies needed to build the target file. In this case, the ``hello-world`` binary compiled for aarch is the target, and the dependencies are the hello-world source files needed to compile this binary:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
HELLO_WORLD_SRC := $(shell find ./hello-world/src) hello-world/Cargo.toml hello-world/Cargo.lock
|
||||
|
||||
hello-world/target/aarch64-unknown-linux-musl/release/hello-world: $(HELLO_WORLD_SRC)
|
||||
docker run --rm -it -v ~/.cargo/registry:/root/.cargo/registry -v "$(shell pwd)"/hello-world:/home/rust/src start9/rust-musl-cross:aarch64-musl cargo build --release
|
||||
|
||||
2. Add the step to build the Docker image. Here, the target is the Docker `image.tar` artifact, and the dependencies are the Dockerfile, docker_entrypoint.sh, and the aarch64 compiled hello-world executable:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
image.tar: Dockerfile docker_entrypoint.sh hello-world/target/aarch64-unknown-linux-musl/release/hello-world
|
||||
DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build --tag start9/hello-world/main:$(VERSION) --platform=linux/arm64 -o type=docker,dest=image.tar .
|
||||
|
||||
3. Next, add the step for building the ``s9pk`` package, with the ``hello-world.s9pk`` as the target, and all the component files as the dependencies:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
ASSETS := $(shell yq e '.assets.[].src' manifest.yaml)
|
||||
|
||||
hello-world.s9pk: manifest.yaml assets/compat/config_spec.yaml assets/compat/config_rules.yaml image.tar instructions.md $(ASSET_PATHS)
|
||||
embassy-sdk pack
|
||||
|
||||
4. Then, add the step to verify the package:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
S9PK_PATH=$(shell find . -name hello-world.s9pk -print)
|
||||
|
||||
verify: hello-world.s9pk $(S9PK_PATH)
|
||||
embassy-sdk verify s9pk $(S9PK_PATH)
|
||||
|
||||
5. Add steps to clean up the Makefile build artifacts when you want to build from a fresh slate:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
clean:
|
||||
rm -f image.tar
|
||||
rm -f hello-world.s9pk
|
||||
|
||||
6. Finally, add the ``all`` make target.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
all: verify
|
||||
|
||||
This serves as the entrypoint to build multiple targets, which we have in this case. When the ``make`` command is invoked here, it looks for the "verify" target. Since the "verify" target depends on the "hello-world.s9pk" target, make then runs this target. It continues down this graph until the first target and its dependencies are satisfied, then works its way back up. The final output of this Makefile is the ``image.tar`` and ``hello-world.s9pk`` files.
|
||||
|
||||
**That's it!** Our completed Makefile looks like this:
|
||||
|
||||
.. code:: make
|
||||
|
||||
ASSETS := $(shell yq e '.assets.[].src' manifest.yaml)
|
||||
ASSET_PATHS := $(addprefix assets/,$(ASSETS))
|
||||
VERSION := $(shell yq e ".version" manifest.yaml)
|
||||
HELLO_WORLD_SRC := $(shell find ./hello-world/src) hello-world/Cargo.toml hello-world/Cargo.lock
|
||||
S9PK_PATH=$(shell find . -name hello-world.s9pk -print)
|
||||
|
||||
# delete the target of a rule if it has changed and its recipe exits with a nonzero exit status
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
all: verify
|
||||
|
||||
verify: hello-world.s9pk $(S9PK_PATH)
|
||||
embassy-sdk verify s9pk $(S9PK_PATH)
|
||||
|
||||
clean:
|
||||
rm -f image.tar
|
||||
rm -f hello-world.s9pk
|
||||
|
||||
hello-world.s9pk: manifest.yaml assets/compat/config_spec.yaml assets/compat/config_rules.yaml image.tar instructions.md $(ASSET_PATHS)
|
||||
embassy-sdk pack
|
||||
|
||||
image.tar: Dockerfile docker_entrypoint.sh hello-world/target/aarch64-unknown-linux-musl/release/hello-world
|
||||
DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build --tag start9/hello-world/main:$(VERSION) --platform=linux/arm64 -o type=docker,dest=image.tar .
|
||||
|
||||
hello-world/target/aarch64-unknown-linux-musl/release/hello-world: $(HELLO_WORLD_SRC)
|
||||
docker run --rm -it -v ~/.cargo/registry:/root/.cargo/registry -v "$(shell pwd)"/hello-world:/home/rust/src start9/rust-musl-cross:aarch64-musl cargo build --release
|
||||
@@ -1,65 +0,0 @@
|
||||
.. _packaging-create-wrapper:
|
||||
|
||||
==================
|
||||
9 - Create Wrapper
|
||||
==================
|
||||
|
||||
In order for the Start9 team to review your package for submission to the Start9 Marketplace, we ask that you create a wrapper repository for the project and its components. This repo should contain everything you need to build the service.
|
||||
|
||||
Let's do that for our hello-world service.
|
||||
|
||||
For a quick start convenience, Start9 has made the finalized version of the `hello-world-wrapper <https://github.com/Start9Labs/hello-world-wrapper>`_ available as a *GitHub template*. Clicking "Use this template" in that repository will clone the entire contents to a specified location. Each file will still have to be manually edited to reflect the changes necessary for your service.
|
||||
|
||||
If you want to proceed from scratch, follow these steps:
|
||||
|
||||
1. In GitHub, create a new public repository with the name "hello-world-wrapper" under your user profile. Go ahead and select the options to include a README file and a .gitignore file. You can always add these files later too.
|
||||
|
||||
2. Once the hosted repository is created, select the "Code" dropdown to copy the https or ssh URL for the repository. If you do not have git setup locally, follow the :ref:`setup steps <environment-setup-git>` first.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git clone https://github.com/<username>/hello-world-wrapper.git
|
||||
cd hello-world-wrapper
|
||||
|
||||
|
||||
3. Include the ``hello-world`` project in the wrapper repo. It can either be included directly, or it can be hosted separately. If it is hosted separately, it should be included as a `git submodule <https://git-scm.com/book/en/v2/Git-Tools-Submodules>`_ within the wrapper repository:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git submodule add <link_to_source_project>
|
||||
|
||||
4. Edit the ``.gitignore`` file to include the ``.s9pk`` file and ``image.tar`` bundle. This will exclude these files from being published remotely, as they can be large or binary representations.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
hello-world.s9pk
|
||||
image.tar
|
||||
|
||||
5. Move the ``Dockerfile``, ``docker_entrypoint.sh``, ``LICENSE``, ``icon``, and ``Manifest`` to the root of the wrapper repository. At the end, your project structure should look similar to this:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
├── Dockerfile
|
||||
├── LICENSE
|
||||
├── Makefile
|
||||
├── README.md
|
||||
├── assets
|
||||
│ └── compat
|
||||
│ ├── config_rules.yaml
|
||||
│ └── config_spec.yaml
|
||||
├── docker_entrypoint.sh
|
||||
├── hello-world
|
||||
│ ├── Cargo.lock
|
||||
│ ├── Cargo.toml
|
||||
│ ├── src
|
||||
│ │ ├── index.html
|
||||
│ │ └── main.rs
|
||||
│ └── target
|
||||
│ ├── aarch64-unknown-linux-musl
|
||||
│ ├── debug
|
||||
│ └── release
|
||||
├── hello-world.s9pk
|
||||
├── icon.png
|
||||
├── image.tar
|
||||
├── instructions.md
|
||||
└── manifest.yaml
|
||||
@@ -1,65 +0,0 @@
|
||||
.. _packaging-install:
|
||||
|
||||
============
|
||||
10 - Install
|
||||
============
|
||||
|
||||
Now that we have a process for iterating on producing a valid package for embassyOS, let's load it onto an Embassy!
|
||||
|
||||
1. First, generate an ssh key for the Embassy:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
ssh-keygen -t ed25519
|
||||
# Press Enter to leave filename as default
|
||||
# Press Enter to leave password empty
|
||||
# Press Enter to confirm password is empty
|
||||
# Copy file contents to clipboard. This is your ssh pubkey.
|
||||
pbcopy .ssh/id_ed25519.pub
|
||||
|
||||
2. On an Embassy device, enter the ssh pubkey into your SSH settings:
|
||||
|
||||
1. Click on Embassy in the menu
|
||||
2. Click on SSH under SETTINGS
|
||||
3. Click on + Add new key
|
||||
4. Paste pubkey from clipboard
|
||||
|
||||
3. Copy the ``hello-world.s9pk`` to the Embassy device:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# Confirm you can ssh into your Embassy
|
||||
ssh start9@<lan-url>
|
||||
# Log out of Embassy SSH session
|
||||
exit
|
||||
|
||||
scp <package-id>.s9pk ssh start9@<lan-url>:/working/directory/path
|
||||
|
||||
eg. scp hello-world.s9pk ssh start9@embassy-12345678.local:~
|
||||
|
||||
4. Finally, install the package on an Embassy device:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
ssh start9@<lan-url>
|
||||
# log in to the command line interface using the Embassy password
|
||||
embassy-cli auth login
|
||||
embassy-cli package install hello-world.s9pk
|
||||
|
||||
**Congratulations!** You have successfully created and installed a package you created onto embassyOS. The package should now be viewable in the "Services" tab in EmbassyUI.
|
||||
|
||||
From here, you can play with viewing the results of your Manifest file settings, such as config, actions, interfaces, health checks, etc. You can also view the logs of your service right in the UI!
|
||||
|
||||
In order to verify your service is functioning as expected:
|
||||
|
||||
- Ensure your service is in "Running" state
|
||||
- Make sure there are no apparent errors or warnings in the logs
|
||||
- Ensure each UI component renders as expected:
|
||||
- Instructions
|
||||
- Config
|
||||
- Properties
|
||||
- Actions
|
||||
- Interfaces
|
||||
- Marketplace listing
|
||||
- Donation
|
||||
- Launch or use your service in the intended way and make sure all aspects function
|
||||
@@ -1,122 +0,0 @@
|
||||
.. _build-package-example:
|
||||
|
||||
===============
|
||||
Build a Package
|
||||
===============
|
||||
|
||||
This guide will take you through the fundamentals of packaging a service for embassyOS by creating a real service. Let's get started!
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div class="topics-grid grid-container full">
|
||||
|
||||
<div class="grid-x grid-margin-x">
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 1
|
||||
:link: 01_setup
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Context and environment setup
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 2
|
||||
:link: 02_create-service
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Create a service
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 3
|
||||
:link: 03_hardware-compile
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Compile for Embassy hardware
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 4
|
||||
:link: 04_docker-build
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Build service with Docker
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 5
|
||||
:link: 05_create-manifest
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Create Manifest file
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 6
|
||||
:link: 06_create-assets
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Create package assets
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 7
|
||||
:link: 07_create-s9pk
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Package service components together
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 8
|
||||
:link: 08_create-makefile
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Create Makefile with build steps (optional)
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 9
|
||||
:link: 09_create-wrapper
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Create wrapper repository to host code for review
|
||||
|
||||
.. topic-box::
|
||||
:title: Step 10
|
||||
:link: 10_install-package
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Install packaged service on embassyOS
|
||||
|
||||
.. topic-box::
|
||||
:title: Resources
|
||||
:link: resources
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Get help, learn how to submit your package to a marketplace, and example references
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div></div>
|
||||
|
||||
.. This is for the side navigation display
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
01_setup
|
||||
02_create-service
|
||||
03_hardware-compile
|
||||
04_docker-build
|
||||
05_create-manifest
|
||||
06_create-assets
|
||||
07_create-s9pk
|
||||
08_create-makefile
|
||||
09_create-wrapper
|
||||
10_install-package
|
||||
resources
|
||||
@@ -1,35 +0,0 @@
|
||||
.. _packaging-resources:
|
||||
|
||||
=========
|
||||
Resources
|
||||
=========
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Get help
|
||||
--------
|
||||
|
||||
If you get stuck or are having issues debugging why your service is not packaging or running as expected, reach out to our community `dev chat <https://matrix.to/#/#community-dev:matrix.start9labs.com>`_ with questions.
|
||||
|
||||
Submission Process
|
||||
------------------
|
||||
|
||||
When you have built and tested your project for embassyOS, please send Start9 a submission to dev@start9.com with a link to the wrapper repository. After being reviewed for security and compatibility, the service will be deployed to the Start9 Marketplace and available for all embassyOS users to download.
|
||||
|
||||
If you are deploying to an alternative marketplace, please shout it out in our community channels!
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
Below are links to working examples of more advanced configurations for current Embassy services. They might serve as a starting point or reference during your development process:
|
||||
|
||||
- Detailed ``docker_entrypoint.sh`` - `Filebrowser <https://github.com/Start9Labs/filebrowser-wrapper/blob/master/docker_entrypoint.sh>`_
|
||||
- Optional dependencies - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/assets/compat/dependencies.yaml>`__
|
||||
- Config spec - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/assets/compat/config_spec.yaml>`__
|
||||
- Config rules - `BTC RPC Proxy <https://github.com/Start9Labs/btc-rpc-proxy-wrapper/blob/master/assets/compat/config_rules.yaml>`__
|
||||
- Multiple dependencies - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/manifest.yaml#L172-L187>`__
|
||||
- Actions - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/actions/btcpay-admin.sh>`__
|
||||
- Health checks - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/assets/utils/health_check.sh>`__
|
||||
- Alerts - `BTCPay Server <https://github.com/Start9Labs/btcpayserver-wrapper/blob/master/manifest.yaml#L207-L218>`__
|
||||
@@ -1,97 +0,0 @@
|
||||
.. _environment-setup:
|
||||
|
||||
=================
|
||||
Environment Setup
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
To get started packaging a service for embassyOS, some basic knowledge of software development is required. Don't worry if you are inexperienced, we will provide enough context to get you started, and you can always reach out with questions.
|
||||
|
||||
If you are already an experienced developer, :ref:`jump ahead <environment-quick-start>`.
|
||||
|
||||
The only system requirements are `Docker <https://docs.docker.com/get-docker>`_ and `Cargo <https://doc.rust-lang.org/cargo/>`_ (Rust package manager).
|
||||
|
||||
Of course, there are additional recommendations that would streamline your development experience, but they are not required.
|
||||
|
||||
Code Editor
|
||||
-----------
|
||||
|
||||
A code editor is recommended since you will, after all, be writing code! We are fans of `Visual Studio Code <https://code.visualstudio.com/>`_ . Visual Studio Code is a free, batteries-included text editor made by Microsoft.
|
||||
|
||||
Terminal / CLI
|
||||
--------------
|
||||
|
||||
We recommend using your computer's built-in terminal as a command line interface (CLI) for your operating system. For Windows users, we recommend the built-in command line (cmd) *Command Prompt* or the Powershell CLI, running in Administrator mode. For macOS and Linux, the native *Terminal* is recommended, but virtually any terminal will work.
|
||||
|
||||
If you are new to the command line, Ionic has published this awesome `guide <https://ionicframework.com/blog/new-to-the-command-line/>`_ to get you started.
|
||||
|
||||
.. _environment-setup-git:
|
||||
|
||||
Git
|
||||
---
|
||||
|
||||
Although not required, the version control system Git is highly recommended.
|
||||
|
||||
Git is often accompanied by a Git Host, such as `GitHub <https://github.com/>`_, in which case additional setup is required. Follow the tutorial from the GitHub `here <https://docs.github.com/en/get-started/quickstart/set-up-git>`_ to set up your environment.
|
||||
|
||||
To verify the installation, open a new terminal window and run:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git --version
|
||||
|
||||
Docker
|
||||
------
|
||||
|
||||
`Docker <https://docs.docker.com/get-docker>`_ must be installed on your computer. It is needed to build an image for your package, which will be used to create the running instance of your package on embassyOS. In essence, it declares the necessary environment and building stages for your package to run.
|
||||
|
||||
We also recommend installing and using `Docker buildx <https://docs.docker.com/buildx/working-with-buildx/>`_, as this adds desirable new features to the Docker build experience. It is included by default with Docker Desktop for Windows and macOS.
|
||||
|
||||
|
||||
Cargo
|
||||
-----
|
||||
|
||||
Cargo is the package management solution for the Rust programming language. It will install Rust to your system, and provide the required environment to build the Embassy SDK for packaging your service into the required format needed by embassyOS.
|
||||
|
||||
Installation instructions for Cargo can be found `here <https://doc.rust-lang.org/cargo/getting-started/installation.html>`__.
|
||||
|
||||
To verify the installation, open a terminal window and run:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
cargo --version
|
||||
|
||||
SDK
|
||||
---
|
||||
|
||||
embassyOS provides a :ref:`software development kit <sdk>` embedded in its environment. You do not need a running instance of embassyOS to use this component, it can be installed on any computer platform.
|
||||
|
||||
To install the SDK:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git clone --recursive https://github.com/Start9Labs/embassy-os.git && cd embassy-os/backend && ./install-sdk.sh
|
||||
|
||||
To verify the installation, open a terminal window and run:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk --version
|
||||
|
||||
embassyOS
|
||||
---------
|
||||
|
||||
While not strictly necessary, having a running instance of embassyOS is recommended to test installing, running, configuring, and using your package. Without this component, you will have to coordinate with Start9's internal development team to test.
|
||||
|
||||
.. _environment-quick-start:
|
||||
|
||||
Quick Start Environment Setup
|
||||
-----------------------------
|
||||
- `Docker <https://docs.docker.com/get-docker>`_
|
||||
- `Docker buildx <https://docs.docker.com/buildx/working-with-buildx/>`_
|
||||
- `Cargo <https://doc.rust-lang.org/cargo/getting-started/installation.html>`__
|
||||
- `embassyOS <https://github.com/Start9Labs/embassy-os>`_
|
||||
- `Embassy SDK <https://github.com/Start9Labs/embassy-os/blob/master/backend/install-sdk.sh>`_
|
||||
@@ -1,62 +0,0 @@
|
||||
.. _packaging-getting-started:
|
||||
|
||||
===============
|
||||
Getting Started
|
||||
===============
|
||||
|
||||
Select an option below to get started with packing a service for embassyOS.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div class="topics-grid grid-container full">
|
||||
|
||||
<div class="grid-x grid-margin-x">
|
||||
|
||||
.. topic-box::
|
||||
:title: Environment Setup
|
||||
:link: environment-setup
|
||||
:icon: scylla-icon scylla-icon--integrations
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Get your environment setup to optimize service packaging
|
||||
|
||||
.. topic-box::
|
||||
:title: Build your first Package
|
||||
:link: build-package-example/index
|
||||
:icon: scylla-icon scylla-icon--open-source
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
Follow along to learn packaging fundamentals with an example
|
||||
|
||||
.. topic-box::
|
||||
:title: SDK
|
||||
:link: sdk
|
||||
:icon: scylla-icon scylla-icon--apps
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Discover details about Start9's Software Development Kit
|
||||
|
||||
.. topic-box::
|
||||
:title: Checklist
|
||||
:link: checklist
|
||||
:icon: scylla-icon scylla-icon--roadmap
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
Quickly get started with concise steps
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div></div>
|
||||
|
||||
.. This is for the side navigation display
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
environment-setup
|
||||
sdk
|
||||
checklist
|
||||
@@ -1,97 +0,0 @@
|
||||
.. _sdk:
|
||||
|
||||
===========
|
||||
Embassy SDK
|
||||
===========
|
||||
|
||||
Embassy SDK, or Software Development Kit, is a CLI (Command Line Interface) tool that aids in building and packaging services you wish to deploy to the Embassy.
|
||||
|
||||
It mainly helps you validate that the necessary components of your package exist, and package all of those components into a special file type that is understood by embassyOS.
|
||||
|
||||
To install, checkout the SDK step in :ref:`setting up your environment <environment-setup>`.
|
||||
|
||||
Commands
|
||||
========
|
||||
|
||||
To see a list of all available commands provided, run the following from an terminal window:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk --help
|
||||
|
||||
|
||||
embassy-sdk init
|
||||
----------------
|
||||
|
||||
Initialize the developer key for interacting with the SDK.
|
||||
|
||||
By default, this creates the developer key at `/etc/embassy`. You might need to change ownership of this folder depending on your system permissions.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
chown <user> /etc/embassy
|
||||
|
||||
Alternatively, you can write a config file with your desired developer location, it simply needs the following format:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
developer-key-path: /desired/path/to/key
|
||||
|
||||
And load it by running:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk -c /path/to/config init
|
||||
|
||||
|
||||
embassy-sdk pack
|
||||
----------------
|
||||
|
||||
This command takes the necessary package components and assembles them into the `s9pk` file format needed to install a service on embassyOS. It expects the following files to exist:
|
||||
|
||||
- Manifest
|
||||
- Instructions
|
||||
- License
|
||||
- Icon
|
||||
|
||||
If this command fails, the error response will indicate which component is missing.
|
||||
|
||||
embassy-sdk verify
|
||||
-------------------
|
||||
|
||||
This command verifies aspects about the components assembled into the `s9pk`, such as:
|
||||
|
||||
- Ensures that all mounts are real volumes in the manifest
|
||||
- Ensures all cert volumes point to real interfaces in the manifest
|
||||
- Ensures all actions refer to real images in the manifest
|
||||
- Ensures all images are tagged correctly in the manifest
|
||||
- Ensures the icon is less than 100KB
|
||||
|
||||
It should be run _after_ `embassy-sdk pack` in order to verify the validity of each component.
|
||||
|
||||
If this command fails, the error message will indicate the mismatched details.
|
||||
|
||||
embassy-sdk git-info
|
||||
--------------------
|
||||
|
||||
This command outputs the git commit hash of the SDK version installed on your platform.
|
||||
|
||||
embassy-sdk inspect
|
||||
-------------------
|
||||
|
||||
This command contains several utilities for reading components once packaged into the `s9pk`. In development, it can be helpful to determine if each component is successfully included in the `s9pk` package.
|
||||
|
||||
It contains the following subcommands, and requires the path to the `<pacakge-id>.s9pk` file as the last argument:
|
||||
|
||||
- docker-images
|
||||
- hash
|
||||
- icon
|
||||
- instructions
|
||||
- license
|
||||
- manifest
|
||||
|
||||
For example:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
embassy-sdk inspect instructions /path/to/<package-id>.s9pk
|
||||
@@ -4,15 +4,7 @@
|
||||
Developer Docs
|
||||
==============
|
||||
|
||||
Welcome to Service Packaging for embassyOS!
|
||||
|
||||
If you are here, you are interested in becoming part of the mission to change the future of personal computing.
|
||||
|
||||
The guides below provide the fundamentals that will take you through the process of packing a service for embassyOS. Services are any open source project (application) that can be run on a self-hosted platform, independent of third parties.
|
||||
|
||||
By configuring and packaging a project according to these guides, it can be installed on embassyOS so that users can interact with the service without needing any technical expertise.
|
||||
|
||||
Let's get started!
|
||||
Welcome to the Service Packaging documentation for embassyOS. If you are here, you have heard the call to help empower users with sovereign computing!
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -21,56 +13,29 @@ Developer Docs
|
||||
<div class="grid-x grid-margin-x">
|
||||
|
||||
.. topic-box::
|
||||
:title: Getting Started
|
||||
:link: getting-started
|
||||
:icon: scylla-icon scylla-icon--nsql-guides
|
||||
:title: Service Packaging
|
||||
:link: packaging
|
||||
:icon: scylla-icon scylla-icon--resource-center
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
:anchor: Build
|
||||
|
||||
Set up your environment and follow along with an example
|
||||
|
||||
.. topic-box::
|
||||
:title: Build your first Package
|
||||
:link: build-package-example
|
||||
:icon: scylla-icon scylla-icon--open-source
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
Follow along to learn packaging fundamentals with an example
|
||||
|
||||
.. topic-box::
|
||||
:title: SDK
|
||||
:link: getting-started/sdk
|
||||
:icon: scylla-icon scylla-icon--apps
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Discover details about the Start9 Software Development Kit
|
||||
A concise guide to Service Packaging
|
||||
|
||||
.. topic-box::
|
||||
:title: Full Specification
|
||||
:link: specification
|
||||
:icon: scylla-icon scylla-icon--glossary
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
:anchor: Read
|
||||
|
||||
Detailed service packaging specification and advanced features
|
||||
|
||||
.. topic-box::
|
||||
:title: Packaging Checklist
|
||||
:link: getting-started/checklist
|
||||
:icon: scylla-icon scylla-icon--roadmap
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
A quick way to check your work
|
||||
|
||||
.. topic-box::
|
||||
:title: Advanced Guides
|
||||
:link: advanced
|
||||
:icon: scylla-icon scylla-icon--integrations
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
:anchor: Tinker
|
||||
|
||||
Guides for implementing advanced service configurations
|
||||
|
||||
@@ -83,7 +48,6 @@ Developer Docs
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
getting-started/index
|
||||
build-package-example/index
|
||||
packaging
|
||||
specification/index
|
||||
advanced/index
|
||||
402
site/source/developer-docs/packaging.rst
Normal file
402
site/source/developer-docs/packaging.rst
Normal file
@@ -0,0 +1,402 @@
|
||||
.. _service-packaging:
|
||||
|
||||
=================
|
||||
Service Packaging
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:depth: 2
|
||||
:local:
|
||||
|
||||
Welcome! Thank you for your interest in contributing to the growing ecosystem of open software. We call the software applications that run on `embassyOS <https://github.com/start9labs/embassy-os>`_ "services." This distinction is made to differentiate from "applications" (apps), which are generally run on a client, and used to access server-side software (services). To run services on embassyOS, a package of file components needs to be composed. This guide will dive into the basic structure of how to compose this package.
|
||||
|
||||
Check out the :ref:`glossary <glossary>` to get acquainted with unfamiliar terms. The bottom of this guide also includes :ref:`support <packaging-support>` links, including a master checklist.
|
||||
|
||||
Let's get started!
|
||||
|
||||
Steps
|
||||
-----
|
||||
|
||||
#. :ref:`Choose software to package <choosing-software>`
|
||||
#. :ref:`Set up the development environment <development-environment>`
|
||||
#. :ref:`Try out the hello-world demo project <hello-world-example>`
|
||||
#. :ref:`Package the service <package-the-service>`
|
||||
|
||||
#. :ref:`Build a Dockerfile <build-a-dockerfile>`
|
||||
#. :ref:`Create the file structure <create-file-structure>`
|
||||
#. :ref:`Format the package <format-package>`
|
||||
|
||||
#. :ref:`Test the service on embassyOS <testing>`
|
||||
#. :ref:`Submit and/or distribute <submission-and-distribution>`
|
||||
|
||||
.. _choosing-software:
|
||||
|
||||
Choosing Software
|
||||
=================
|
||||
|
||||
Almost any type of open source software can be run on embassyOS. No matter what programming language, framework, database or interface the service has, it can be adapted for embassyOS. This is made possible by the power of Docker containers (don't worry, we'll get to this). We do have a few recommendations for choosing a service that will perform optimally across platforms:
|
||||
|
||||
#. It either has a web user interface (it can be interacted with in a web browser), or is server software that external applications or internal services can connect to. Please keep in mind that embassyOS users are not expected to have SSH and/or CLI access.
|
||||
|
||||
- The interfaces supported are: HTTP, TCP, and REST APIs
|
||||
|
||||
#. It can be compiled for ARM (``arm64v8``)
|
||||
#. It can be served over TOR
|
||||
#. It creates a container image that is optimized for size (under 1GB) to save device space and expedite installation time
|
||||
|
||||
.. _development-environment:
|
||||
|
||||
Development Environment
|
||||
=======================
|
||||
|
||||
A basic development and testing environment includes:
|
||||
|
||||
#. An Embassy One or Pro with latest `embassyOS <https://github.com/start9labs/embassy-os/releases>`_
|
||||
|
||||
- Use your own hardware to `DIY <https://start9.com/latest/diy>`_
|
||||
- Purchase a device from the `Start9 Store <https://store.start9.com>`_
|
||||
- x86/VM support coming soon
|
||||
|
||||
#. A development machine
|
||||
|
||||
- Linux is highly recommended, and this walkthrough will assume a Debian-based (Ubuntu) distribution
|
||||
|
||||
Dependencies - Recommended
|
||||
..........................
|
||||
These tools may or may not be necessary, depending on your environment and the package you are building.
|
||||
|
||||
- Code Editor (IDE) - We recommend `Visual Studio Code <https://code.visualstudio.com/>`_
|
||||
|
||||
- Build essentials (Ubuntu) - Common build tools and encryption libraries.
|
||||
|
||||
.. code-block::
|
||||
|
||||
sudo apt-get install -y build-essential openssl libssl-dev libc6-dev clang libclang-dev ca-certificates
|
||||
|
||||
- Git - This is a version control system that is used widely in Open Source development.
|
||||
|
||||
.. code-block::
|
||||
|
||||
sudo apt install git
|
||||
|
||||
Use the following verify installation:
|
||||
|
||||
.. code-block::
|
||||
|
||||
git --version
|
||||
|
||||
.. note:: Anytime you use a ``git clone`` command in this guide, it will create a new directory with code in it, so make sure you are executing this command from a directory that you want to store code in, such as your ``home`` folder.
|
||||
|
||||
- yq - A lightweight and portable command-line YAML, JSON and XML processor.
|
||||
|
||||
.. code-block::
|
||||
|
||||
sudo snap install yq
|
||||
|
||||
Dependencies - Required
|
||||
.......................
|
||||
- `Docker <https://docs.docker.com/get-docker/>`_ - Docker is currently the only supported containerization method for embassyOS. This declares the necessary environment and building stages for your package to run. Install the desktop GUI or via the command line:
|
||||
|
||||
.. code-block::
|
||||
|
||||
curl -fsSL https://get.docker.com -o- | bash
|
||||
sudo usermod -aG docker "$USER"
|
||||
exec sudo su -l $USER
|
||||
|
||||
We need to enable cross-arch emulated builds in Docker (unless you are building on an ARM machine, such as an M1 Mac - in which case, skip this step).
|
||||
|
||||
.. code-block::
|
||||
|
||||
docker run --privileged --rm linuxkit/binfmt:v0.8
|
||||
|
||||
- `Buildx <https://docs.docker.com/buildx/working-with-buildx/>`_ - This adds desirable new features to the Docker build experience. It is included by default with Docker Desktop GUI. If Docker was installed via command line, additionally run:
|
||||
|
||||
.. code-block::
|
||||
|
||||
docker buildx install
|
||||
docker buildx create --use
|
||||
|
||||
- Rust & Cargo - Cargo is the package management solution for the Rust programming language. It is needed to build the Embassy SDK. The following will install both Rust and Cargo:
|
||||
|
||||
.. code-block::
|
||||
|
||||
curl https://sh.rustup.rs -sSf | sh
|
||||
source $HOME/.cargo/env
|
||||
|
||||
Verify install:
|
||||
|
||||
.. code-block::
|
||||
|
||||
cargo --version
|
||||
|
||||
- Embassy SDK - embassyOS has an embedded Software Development Kit (SDK). You can install this component on any system, without needing to run embassyOS.
|
||||
|
||||
.. code-block::
|
||||
|
||||
git clone -b latest --recursive https://github.com/Start9Labs/embassy-os.git && cd embassy-os/backend && ./install-sdk.sh
|
||||
|
||||
Initialize sdk & verify install
|
||||
|
||||
.. code-block::
|
||||
|
||||
embassy-sdk init
|
||||
embassy-sdk --version
|
||||
|
||||
- Deno (an optional component for more advanced SDK features) - A simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust. It is used to enable the scripting API portion of the SDK.
|
||||
|
||||
.. code-block::
|
||||
|
||||
sudo snap install deno
|
||||
|
||||
.. _hello-world-example:
|
||||
|
||||
Demo with Hello World
|
||||
=====================
|
||||
Check your environment setup by building a demo project and installing it to embassyOS.
|
||||
|
||||
#. Get Hello World
|
||||
|
||||
.. code-block::
|
||||
|
||||
git clone https://github.com/Start9Labs/hello-world-wrapper.git
|
||||
cd hello-world-wrapper
|
||||
|
||||
#. Build to create ``hello-world.s9pk``
|
||||
|
||||
.. code-block::
|
||||
|
||||
make
|
||||
|
||||
#. Sideload & Run
|
||||
- In the embassyOS web UI menu, navigate to `Embassy -> Settings -> Sideload Service`
|
||||
- Drag and drop or select the ``hello-world.s9pk`` from your filesystem to install
|
||||
- Once the service has installed, navigate to `Services -> Hello World` and click "Start"
|
||||
- Once the Health Check is successful, click "Launch UI" and verify you see the Hello World page
|
||||
|
||||
.. _package-the-service:
|
||||
|
||||
Package the service
|
||||
===================
|
||||
The package file produced by this process has a ``s9pk`` extension. This file is what is installed to run a service on embassyOS.
|
||||
|
||||
.. _build-a-dockerfile:
|
||||
|
||||
Build a Dockerfile
|
||||
..................
|
||||
A Dockerfile defines the recipe for building the environment to run a service. Currently, embassyOS only supports one Dockerfile per project (i.e. no Docker compose), so it should include any necessary database configurations. There are several methods to build a Dockerfile for your service.
|
||||
|
||||
First, check to see if the upstream project has already built one. This is usually your best source for finding Docker images that are compatible with ARM. Next, you can:
|
||||
|
||||
- Download an image from [Docker Hub](https://hub.docker.com/)
|
||||
|
||||
- Make a new Dockerfile, and pull in an image the upstream project hosted on Docker Hub as the base
|
||||
|
||||
- Make a new Dockerfile, and pull in a small distribution base (eg. alpine) and compile the build environment yourself using the upstream project source code
|
||||
|
||||
After coding the build steps, build the Docker image using ``docker buildx``, replacing the placeholder variables:
|
||||
|
||||
.. code-block::
|
||||
|
||||
docker buildx build --tag start9/$(PKG_ID)/main:$(PKG_VERSION) --platform=linux/arm64 -o type=docker,dest=image.tar .
|
||||
|
||||
The resulting ``image.tar`` artifact is the Docker image that needs to be included in the ``s9pk`` package.
|
||||
|
||||
.. _create-file-structure:
|
||||
|
||||
Create File Structure
|
||||
.....................
|
||||
|
||||
Once we have a Docker image, we can create the service wrapper. A service wrapper is a repository of a new git committed project that "wraps" an existing project (i.e. the upstream project). It contains the set of metadata files needed to build a ``s9pk``, define information displayed in the user interface, and establish the data structure of your package. This repository can exist on any hosted git server - it does not need to be a part of the Start9 GitHub ecosystem.
|
||||
|
||||
The following files should be included in the service wrapper repository:
|
||||
|
||||
- ``manifest.yaml``, which defines:
|
||||
|
||||
- The package id - a unique lowercase and hyphenated package identifier (eg. hello-world)
|
||||
|
||||
- Essential initialization details, such as version
|
||||
|
||||
- Where you are persisting your data on the filesystem (i.e. mounts and volumes)
|
||||
|
||||
- Port mappings (i.e. interfaces)
|
||||
|
||||
- Check out the `Hello World example <https://github.com/Start9Labs/hello-world-wrapper/blob/master/manifest.yaml>`_ to see line-by-line details
|
||||
|
||||
- ``instructions.md``
|
||||
|
||||
- Instructions for the user
|
||||
|
||||
- Appears as a menu item in the service page UI
|
||||
|
||||
- ``LICENSE``
|
||||
|
||||
- The Open Source License for your wrapper
|
||||
|
||||
- ``icon.png``
|
||||
|
||||
- The image that will be associated with the service throughout the UI, including in a marketplace
|
||||
|
||||
- ``MAKEFILE``
|
||||
|
||||
- Build instructions to create the s9pk
|
||||
|
||||
- `Example <https://github.com/Start9Labs/hello-world-wrapper/blob/f44899be8523b784861aac92e43fe60f0bf219eb/Makefile#L1-L28>`_
|
||||
|
||||
- ``Dockerfile``
|
||||
|
||||
- A recipe for service creation
|
||||
|
||||
- Add here any prerequisite environment variables, files, or permissions
|
||||
|
||||
- Examples:
|
||||
- `Using an existing docker image <https://github.com/kn0wmad/robosats-wrapper/blob/d4a0bd609ce18036dfd7ee57e88d437e54d8efb9/Dockerfile#L1>`_
|
||||
- `Implementing a database <https://github.com/Start9Labs/photoview-wrapper/blob/ba399208ebfaabeafe9bea0829f494aafeaa9422/Dockerfile#L3-L9>`_
|
||||
- `Using a submodule <https://github.com/Start9Labs/ride-the-lightning-wrapper/blob/3dfe28b13a3886ae2f685d10ef1ae79fc4617207/Dockerfile#L9-L28>`_
|
||||
|
||||
- ``docker_entrypoint.sh``
|
||||
|
||||
- Starts and governs the operation of a service container
|
||||
|
||||
- Gracefully handles container errors and user preferences, i.e. username/password, SIGTERMs
|
||||
|
||||
- Examples:
|
||||
|
||||
- `Robosats <https://github.com/kn0wmad/robosats-wrapper/blob/master/docker_entrypoint.sh>`_
|
||||
|
||||
- `Photoview <https://github.com/Start9Labs/photoview-wrapper/blob/master/docker_entrypoint.sh>`_
|
||||
|
||||
- `RTL <https://github.com/Start9Labs/ride-the-lightning-wrapper/blob/master/docker_entrypoint.sh>`_
|
||||
|
||||
.. _format-package:
|
||||
|
||||
Format Package
|
||||
..............
|
||||
|
||||
Building the final ``s9pk`` artifact depends on the existence of the files listed above, and the execution of the following steps (which should be added to the Makefile):
|
||||
|
||||
- Package the ``s9pk``:
|
||||
|
||||
.. code-block::
|
||||
|
||||
embassy-sdk pack
|
||||
|
||||
- Verify the ``s9pk`` (replace PKG_ID with your package identifier):
|
||||
|
||||
.. code-block::
|
||||
|
||||
embassy-sdk verify s9pk PKG_ID.s9pk
|
||||
|
||||
The verification step will provide details about missing files, or fields in the service manifest file.
|
||||
|
||||
That's it! You now have a package!
|
||||
|
||||
.. _testing:
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
#. Run the ``make`` command from the root folder of your wrapper repository to execute the build instructions defined in the ``MAKEFILE``
|
||||
|
||||
#. Install the package, via either:
|
||||
|
||||
#. Drag and drop:
|
||||
|
||||
- In the embassyOS web UI menu, navigate to `Embassy -> Settings -> Sideload Service`
|
||||
|
||||
- Drag and drop or select the ``<package>.s9pk`` from your filesystem to install
|
||||
|
||||
#. Use the CLI:
|
||||
|
||||
- Create a config file with the IP address of the device running embassyOS:
|
||||
|
||||
.. code-block::
|
||||
|
||||
touch /etc/embassy/config.yaml
|
||||
echo "host: <IP_ADDRESS_REPLACE_ME>" > /etc/embassy/config.yaml
|
||||
|
||||
- Login with master password
|
||||
|
||||
.. code-block::
|
||||
|
||||
embassy-cli auth login
|
||||
embassy-cli package install <PACKAGE_ID_REPLACE_ME>.s9pk
|
||||
|
||||
|
||||
.. figure:: /_static/images/dev/nc-install.png
|
||||
:width: 60%
|
||||
:alt: Installing a service
|
||||
|
||||
#. Once the service has installed, navigate to `Services -> <Service Name>` and click "Start"
|
||||
|
||||
#. Check that the service operations function as expected by either launching the UI, or querying if a server application
|
||||
|
||||
#. Check that each UI element on the service's page displays the proper information and is accurately formatted
|
||||
|
||||
#. Ensure the service can be stopped, restarted, and upgraded (if applicable)
|
||||
|
||||
.. figure:: /_static/images/dev/nc-service.png
|
||||
:scale: 40%
|
||||
:alt: An eOS service page
|
||||
|
||||
.. _submission-and-distribution:
|
||||
|
||||
Submission and Distribution
|
||||
===========================
|
||||
|
||||
The ``s9pk`` file can be uploaded for distribution to any website, repository, or marketplace. You can also submit your package for publication consideration on a Start9 Marketplace by emailing us at submissions@start9labs.com or by contacting us in one of our [community channels](https://start9.com/latest/about/contact). Please include a link to the wrapper repository with a detailed README in the submission.
|
||||
|
||||
Advanced configuration
|
||||
======================
|
||||
|
||||
Scripting on embassyOS
|
||||
......................
|
||||
|
||||
Start9 has developed a highly extensible scripting API for developers to create the best possible user experience. This is your toolkit for creating the most powerful service possible by enabling features such as:
|
||||
|
||||
- Configuration
|
||||
- Version migration
|
||||
- Dependencies
|
||||
- Health checks
|
||||
- Properties
|
||||
|
||||
Use is optional. To experiment, simply use the existing skeleton from the Hello World wrapper `example <https://github.com/Start9Labs/hello-world-wrapper/tree/master/scripts>`_, changing only the package version in the `migration file <https://github.com/Start9Labs/hello-world-wrapper/blob/f44899be8523b784861aac92e43fe60f0bf219eb/scripts/procedures/migrations.ts#L4>`_.
|
||||
|
||||
Check out the specification `here <https://start9.com/latest/developer-docs/specification/js-procedure>`_.
|
||||
|
||||
.. _packaging-support:
|
||||
|
||||
Support
|
||||
=======
|
||||
Have a question? Need a hand? Please jump into our `Community <https://community.start9.com>`_, or our `Matrix Community Dev Channel <https://matrix.to/#/#community-dev:matrix.start9labs.com>`_. You can also check out our full list of :ref:`Community Channels <contact>`.
|
||||
|
||||
Need more details? Check out the :ref:`Service Packaging Specification <service-packaging-spec>`
|
||||
|
||||
You may like to use this handy :ref:`Checklist <packaging-checklist>` to be sure you have everything covered.
|
||||
|
||||
.. _glossary:
|
||||
|
||||
Glossary
|
||||
========
|
||||
|
||||
`service` - open software applications that run on embassyOS
|
||||
|
||||
`package` - the composed set of a Docker image, a service manifest, and service instructions, icon, and license, that are formatted into a file with the `s9pk` extension using `embassy-sdk`
|
||||
|
||||
`wrapper` - the project repository that "wraps" the upstream project, and includes additionally necessary files for building and packaging a service for eOS
|
||||
|
||||
`scripts` - a set of developer APIs that enable advanced configuration options for services
|
||||
|
||||
`embassy-sdk` - the Software Development Toolkit used to package and verify services for embassyOS
|
||||
|
||||
`open source software` - computer software that is released under a license in which the copyright holder grants users the rights to use, study, change, and distribute the software and its source code to anyone and for any purpose
|
||||
|
||||
`upstream project` - the original, source project code that is used as the base for a service
|
||||
|
||||
`embassyOS` - a browser-based, graphical operating system for a personal server
|
||||
|
||||
`eOS` - shorthand for embassyOS
|
||||
|
||||
`s9pk` - the file extension for the packaged service artifact needed to install and run a service on embassyOS
|
||||
|
||||
|
||||
:ref:`Back to Top <service-packaging>`
|
||||
@@ -1,4 +1,4 @@
|
||||
.. _packaging-quick-start:
|
||||
.. _packaging-checklist:
|
||||
|
||||
=========
|
||||
Checklist
|
||||
@@ -120,3 +120,4 @@ The following guides provide an in depth overview of the full capabilities avail
|
||||
js-procedure
|
||||
submission
|
||||
compat/index
|
||||
checklist
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
.. hero-box::
|
||||
:title: Welcome
|
||||
|
||||
Here you will find documentation about embassyOS, including DIY guides, user manuals, and developer docs. Welcome to the era of sovereign computing. Anyone can do it. No one can stop it.
|
||||
Here you will find information on embassyOS, including DIY guides, user manuals, and developer docs. Welcome to the era of sovereign computing. Anyone can do it. No one can stop it.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
@@ -46,15 +46,6 @@
|
||||
|
||||
Read our FAQ and learn about platform concepts
|
||||
|
||||
.. topic-box::
|
||||
:title: Developer Docs
|
||||
:link: developer-docs
|
||||
:icon: scylla-icon scylla-icon--open-source
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Package a service for the Embassy Marketplace
|
||||
|
||||
.. topic-box::
|
||||
:title: Contribute
|
||||
:link: contribute
|
||||
@@ -64,6 +55,14 @@
|
||||
|
||||
Use your skills to add to the Start9 ecosystem
|
||||
|
||||
.. topic-box::
|
||||
:title: Developer Docs
|
||||
:link: developer-docs
|
||||
:icon: scylla-icon scylla-icon--open-source
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Package a service for the Marketplace
|
||||
|
||||
.. raw:: html
|
||||
|
||||
|
||||
Reference in New Issue
Block a user