mirror of
https://github.com/Start9Labs/documentation.git
synced 2026-03-26 02:11:55 +00:00
revap dev docs
This commit is contained in:
@@ -12,63 +12,6 @@ Please pardon our dust...
|
||||
|
||||
.. .. raw:: html
|
||||
|
||||
.. <!doctype html>
|
||||
.. <html class="no-js" lang="en">
|
||||
.. <head>
|
||||
.. <meta charset="utf-8">
|
||||
.. <meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
.. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
.. <title>Start9 - Roadmap</title>
|
||||
.. <meta name="author" content="Start9">
|
||||
.. <meta name="description" content="The world of free and open source software is rich and expanding. With the Embassy device and platform, Start9 aims to unleash open source software and usher in a new era of sovereign computing.">
|
||||
.. <meta name="twitter:card" content="summary">
|
||||
.. <meta name="twitter:site" content="@start9labs">
|
||||
.. <meta name="og:title" content="Start9 - Sovereign Computing">
|
||||
.. <meta property="og:image" content="https://start9.com/images/icon.png" />
|
||||
.. <meta name="og:description" content="The world of free and open source software is rich and expanding. With the Embassy device and platform, Start9 aims to unleash open source software and usher in a new era of sovereign computing.">
|
||||
.. <link rel="icon" type="image/png" href="images/favicon.ico">
|
||||
.. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
||||
.. <link href="styles/main.css" rel="stylesheet">
|
||||
.. </head>
|
||||
.. <body class="body--transparent-header">
|
||||
.. <!-- <div class="banner" id="banner" role="banner">
|
||||
.. <span class="banner-text">Limited time sale on the <b>Embassy One</b>! Only $219. Custom engraving available. <a href="https://store.start9.com/collections/embassy">Purchase now!</a></span>
|
||||
.. <div class="banner-x" onclick="hideBanner()">×</div>
|
||||
.. </div> -->
|
||||
.. <header class="site-header-wrapper" id="top" role="navigation">
|
||||
.. <div class="site-header">
|
||||
.. <nav class="navbar navbar-expand-lg main-navigation navbar-dark">
|
||||
.. <a href="/" class="logo-box"><img src="images/Start9_logo.png" class="logo" alt="Start9 Logo"></a>
|
||||
.. <button class="navbar-toggler nav-toggle" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
|
||||
.. aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
|
||||
.. <span class="navbar-toggler-icon"></span>
|
||||
.. </button>
|
||||
.. <div class="collapse navbar-collapse" id="navbarNavDropdown">
|
||||
.. <ul class="navbar-nav">
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link" href="https://store.start9.com/collections/" target="_blank">Store</a>
|
||||
.. </li>
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link documentation" href="#" target="_blank" rel="noopener noreferrer">Docs</a>
|
||||
.. </li>
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link" href="https://www.youtube.com/channel/UCGEw4HJDvOn3Oy8ykR36P7Q" target="_blank" rel="noopener noreferrer">Videos</a>
|
||||
.. </li>
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link" href="news">News</a>
|
||||
.. </li>
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link" href="roadmap">Roadmap</a>
|
||||
.. </li>
|
||||
.. <li class="nav-item">
|
||||
.. <a class="nav-link" href="join-us">Jobs</a>
|
||||
.. </li>
|
||||
.. </ul>
|
||||
.. </div>
|
||||
.. </nav>
|
||||
.. </div>
|
||||
.. </header>
|
||||
|
||||
.. <section class="margin-top-7 margin-bottom-7 content s-page-roadmap">
|
||||
.. <div class="container text-center">
|
||||
.. <h1 class="accent container">Roadmap</h1>
|
||||
@@ -307,57 +250,3 @@ Please pardon our dust...
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. </section>
|
||||
|
||||
.. <footer class="s-footer">
|
||||
.. <div class="container">
|
||||
.. <div class="row align-items-start s-footer__logo-row">
|
||||
.. <div class="col-md-6 col-12 order-2 order-md-1">
|
||||
.. <div class="row s-footer__logo">
|
||||
.. <div class="col-2">
|
||||
.. <a href="#top"><img src="images/icon-transparent.png" class="s-footer__logo-img" alt="S9 Logo"></a>
|
||||
.. </div>
|
||||
.. <div class="col-10 s-footer__social invert">
|
||||
.. <a href="https://medium.com/@start9labs" target="_blank" rel="noopener nofollow"><img class="s-footer__social-icon" alt="medium icon" src="images/Medium-new.png" title="Medium"></a>
|
||||
.. <a href="https://github.com/Start9Labs/" target="_blank" rel="noopener nofollow"><img class="s-footer__social-icon" alt="github icon" src="images/developer-community-github-1.png" title="GitHub"></a>
|
||||
.. <a href="https://twitter.com/start9labs?lang=en" target="_blank" rel="noopener nofollow"><img class="s-footer__social-icon" alt="twitter icon" src="images/social-media-twitter.png" title="Twitter"></a>
|
||||
.. <a href="https://t.me/start9_labs" target="_blank" rel="noopener nofollow"><img class="s-footer__social-icon" alt="telegram icon" src="images/telegram.png" title="Telegram"></a>
|
||||
.. <a href="http://privacy34kn4ez3y3nijweec6w4g54i3g54sdv7r5mr6soma3w4begyd.onion" target="_blank" rel="noopener nofollow"><img class="s-footer__social-icon" alt="tor icon" src="images/tor_icon.png" title="Tor Website"></a>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. <div class="row padding-top-1">
|
||||
.. <p class="s-footer__logo-copyright">© Copyright 2021 Start9Labs</p>
|
||||
.. <p class="s-footer__logo-copyright">BTC Donations: bc1qdah5dculyuw8c6f3wzzannpjt4w5and4knf87h</p>
|
||||
.. <p class="s-footer__logo-copyright">We have never received a secret government request to hand over user
|
||||
.. information.</p>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. <div class="col-12 col-md-6 order-1 order-md-2 s-footer__nav">
|
||||
.. <div class="row justify-content-end">
|
||||
.. <div class="col-12 col-md-4">
|
||||
.. <h4>company</h4>
|
||||
.. <ul>
|
||||
.. <li><a href="news">Media</a></li>
|
||||
.. <li><a href="/#community">Community</a></li>
|
||||
.. <li><a href="join-us">Careers</a></li>
|
||||
.. </ul>
|
||||
.. </div>
|
||||
.. <div class="col-12 col-md-5">
|
||||
.. <h4>resources</h4>
|
||||
.. <ul>
|
||||
.. <li><a href="https://medium.com/@start9labs" target="_blank" rel="nofollow noopener">Blog</a></li>
|
||||
.. <li><a href="privacy">Privacy Policy</a></li>
|
||||
.. <li><a href="license-v1.0">License</a></li>
|
||||
.. </ul>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. </div>
|
||||
.. </footer>
|
||||
|
||||
.. <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
|
||||
.. <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
||||
.. <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
|
||||
.. <script src="scripts/bundle.js"></script>
|
||||
.. </body>
|
||||
.. </html>
|
||||
|
||||
36
site/source/service-packaging/advanced/index.rst
Normal file
36
site/source/service-packaging/advanced/index.rst
Normal file
@@ -0,0 +1,36 @@
|
||||
.. _advanced-packaging:
|
||||
|
||||
===========================
|
||||
Advanced Packaging Overview
|
||||
===========================
|
||||
|
||||
This section included advanced commands for working with packages in EmbassyOS.
|
||||
|
||||
.. topic-box::
|
||||
:title: Developer Tools
|
||||
:link: dev-tools/index
|
||||
:icon: scylla-icon scylla-icon--developers-blog
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
EmbassyOS developer CLI tools
|
||||
|
||||
.. topic-box::
|
||||
:title: Service Containers
|
||||
:link: dev-tools/service-container
|
||||
:icon: scylla-icon scylla-icon--overview
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
How to interact with containers on the Embassy
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div></div>
|
||||
|
||||
.. This is for the side navigation display
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
dev-tools/index
|
||||
750
site/source/service-packaging/build-package-example/index.rst
Normal file
750
site/source/service-packaging/build-package-example/index.rst
Normal file
@@ -0,0 +1,750 @@
|
||||
.. _build-package-example:
|
||||
|
||||
========================
|
||||
Build Your First Package
|
||||
========================
|
||||
|
||||
This guide will take you through the fundamentals of packaging a service for EmbassyOS by creating a real service. Let's get started!
|
||||
|
||||
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 service code referenced in this guide on `GitHub <https://github.com/Start9Labs/hello-world-wrapper>`_.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
That's it! We 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 `localhost:80` to see your running web page!
|
||||
|
||||
Build for RaspberryPi
|
||||
======================
|
||||
|
||||
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`
|
||||
|
||||
Build with Docker
|
||||
=================
|
||||
|
||||
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.
|
||||
|
||||
#. Create the necessary Docker files:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
touch Dockerfile
|
||||
touch docker_entrypoint.sh
|
||||
|
||||
#. We start by importing a base image, in this case Alpine, as recommended.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
FROM arm64v8/alpine:3.12
|
||||
|
||||
#. 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
|
||||
|
||||
#. 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
|
||||
|
||||
#. 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"]
|
||||
|
||||
#. 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"]
|
||||
|
||||
#. 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.
|
||||
|
||||
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:
|
||||
|
||||
.. 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:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
# Arguments to pass into the entrypoint. 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"
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
|
||||
Package into s9pk
|
||||
=================
|
||||
|
||||
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!
|
||||
|
||||
Wrapper Repo
|
||||
============
|
||||
|
||||
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. 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
|
||||
|
||||
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
|
||||
|
||||
Install on EmbassyOS
|
||||
====================
|
||||
|
||||
Now that we have a process for iterating on producing a valid package for EmbassyOS, let's try to load it onto an Embassy device! If you do not have one, you can either :ref:`purchase <purchasing>` a device or build one using our :ref:`DIY guide <diy>`.
|
||||
|
||||
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:
|
||||
|
||||
#. Click on Embassy in the menu
|
||||
#. Click on SSH under SETTINGS
|
||||
#. Click on + Add new key
|
||||
#. Paste pubkey from clipboard
|
||||
|
||||
3. Copy the `hello-world.s9pk` to the Embassy device:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
# Confirm you can ssh into your Embassy
|
||||
ssh root@<lan-url>
|
||||
# Log out of Embassy SSH session
|
||||
exit
|
||||
|
||||
scp <package-id>.s9pk ssh root@<lan-url>:/working/directory/path
|
||||
|
||||
eg. scp hello-world.s9pk ssh root@embassy-12345678.local:/root
|
||||
|
||||
4. Finally, install the package on an Embassy device:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
ssh root@<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
|
||||
|
||||
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@start9labs.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!
|
||||
@@ -0,0 +1,18 @@
|
||||
.. _packaging-references:
|
||||
|
||||
====================
|
||||
Packaging 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:
|
||||
|
||||
TODO update links when merged to master
|
||||
|
||||
- Detailed `docker_entrypoint.sh` - `filebrowser-wrapper <https://github.com/Start9Labs/filebrowser-wrapper/blob/master/docker_entrypoint.sh>`_
|
||||
- Optional dependencies - `btcpayserver <>`_
|
||||
- Config spec - `btcpayserver <>`_
|
||||
- Config rules - `btcpayserver <>`_
|
||||
- Multiple dependencies - `btcpayserver <>`_
|
||||
- Actions - `btcpayserver <>`_
|
||||
- Health checks - `btcpayserver <>`_
|
||||
- Alerts - `lnd <https://github.com/Start9Labs/lnd-wrapper/blob/87daf4e5ed7231e22aaa28be533e794f67f98289/manifest.yaml#L30>`_
|
||||
@@ -0,0 +1,93 @@
|
||||
.. _environment-setup:
|
||||
|
||||
===========================
|
||||
Packaging Environment Setup
|
||||
===========================
|
||||
|
||||
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, `jump ahead <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 the build 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.
|
||||
|
||||
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 to your computer platform. 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 https://github.com/Start9Labs/embassy-os.git
|
||||
cd 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. ... TODO add more
|
||||
|
||||
You can acquire EmbassyOS by :ref:`Purchase <purchasing>` or following the :ref:`DIY guide <diy>`.
|
||||
|
||||
.. _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>`_
|
||||
63
site/source/service-packaging/getting-started/index.rst
Normal file
63
site/source/service-packaging/getting-started/index.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
.. _packaging-getting-started:
|
||||
|
||||
========================
|
||||
Getting Started Overview
|
||||
========================
|
||||
|
||||
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: Packaging Quick Start
|
||||
:link: packaging-quick-start
|
||||
:icon: scylla-icon scylla-icon--roadmap
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
Quickly get started with concise packaging steps
|
||||
|
||||
.. 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
|
||||
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div></div>
|
||||
|
||||
.. This is for the side navigation display
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
environment-setup
|
||||
sdk
|
||||
quick-start
|
||||
@@ -0,0 +1,33 @@
|
||||
.. _packaging-quick-start:
|
||||
|
||||
=====================
|
||||
Packaging Quick Start
|
||||
=====================
|
||||
|
||||
This guide outlines a checklist of steps to complete in order to package a service for EmbassyOS. For a more in depth example, visit the :ref:`build your first package <build-package-example>` guide.
|
||||
|
||||
Packaging
|
||||
---------
|
||||
|
||||
1. Create or select project
|
||||
2. Build project
|
||||
3. Cross compile for armv8/aarch64 if necessary
|
||||
4. Create Dockerfile and docker entrypoint file
|
||||
5. Add build steps, compiled executables, assets, etc in Dockerfile and specify run command in docker entrypoint, handling signal exiting if the service does not already do this gracefully
|
||||
6. Create Manifest file
|
||||
7. Create instructions file
|
||||
8. Create icon file
|
||||
9. Add license
|
||||
10. Package all components into s9pk using embassy-sdk
|
||||
11. Verify package components using embassy-sdk
|
||||
12. Create a wrapper repository on GitHub to host all package assets for review
|
||||
13. (Optional) Add all package build steps to a Makefile for replicability
|
||||
|
||||
Testing:
|
||||
--------
|
||||
|
||||
1. Sideload s9pk onto an Embassy
|
||||
2. Install package using embassy-cli
|
||||
3. Start package using embassy-cli, or in the UI
|
||||
4. Check logs to see if errors
|
||||
5. Ensure service is reachable/launchable
|
||||
97
site/source/service-packaging/getting-started/sdk.rst
Normal file
97
site/source/service-packaging/getting-started/sdk.rst
Normal file
@@ -0,0 +1,97 @@
|
||||
.. _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
|
||||
----------------
|
||||
|
||||
Initialized 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
|
||||
89
site/source/service-packaging/index.rst
Normal file
89
site/source/service-packaging/index.rst
Normal file
@@ -0,0 +1,89 @@
|
||||
.. _service-packaging:
|
||||
|
||||
==========================
|
||||
Service Packaging Overview
|
||||
==========================
|
||||
|
||||
Welcome to Service Packaging!
|
||||
|
||||
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!
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<div class="topics-grid grid-container full">
|
||||
|
||||
<div class="grid-x grid-margin-x">
|
||||
|
||||
.. topic-box::
|
||||
:title: Getting Started
|
||||
:link: packaging-getting-started
|
||||
:icon: scylla-icon scylla-icon--nsql-guides
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
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: Packaging Quick Start
|
||||
:link: packaging-quick-start
|
||||
:icon: scylla-icon scylla-icon--roadmap
|
||||
:class: large-4
|
||||
:anchor: Begin
|
||||
|
||||
Quickly get started with concise packaging steps
|
||||
|
||||
.. 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: Full Specification
|
||||
:link: packaging-specification
|
||||
:icon: scylla-icon scylla-icon--glossary
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Detailed service packaging specification and advanced features
|
||||
|
||||
.. topic-box::
|
||||
:title: Advanced Guides
|
||||
:link: advanced/index
|
||||
:icon: scylla-icon scylla-icon--integrations
|
||||
:class: large-4
|
||||
:anchor: View
|
||||
|
||||
Guides for implementing advanced service configurations
|
||||
|
||||
.. raw:: html
|
||||
|
||||
</div></div>
|
||||
|
||||
.. This is for the side navigation display
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
getting-started/index
|
||||
build-package-example/index
|
||||
specification/index
|
||||
advanced/index
|
||||
@@ -22,8 +22,3 @@ Ultimately, ``/datadir/.backupignore`` gets populated with:
|
||||
|
||||
/root/volumes/btcpayserver/start9/public
|
||||
/root/volumes/btcpayserver/start9/shared
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
@@ -33,8 +33,3 @@ Example
|
||||
-------
|
||||
|
||||
The `LND wrapper <https://github.com/Start9Labs/lnd-wrapper/blob/master/Dockerfile>`_ features a well defined Dockerfile, for example.
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
21
site/source/service-packaging/specification/index.rst
Normal file
21
site/source/service-packaging/specification/index.rst
Normal file
@@ -0,0 +1,21 @@
|
||||
.. _service-packaging-spec:
|
||||
|
||||
===============================
|
||||
Service Packaging Specification
|
||||
===============================
|
||||
|
||||
The following guides provide an in depth overview of the full capabilities available for packaging a service.
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
overview
|
||||
wrapper
|
||||
manifest
|
||||
docker
|
||||
makefile
|
||||
config
|
||||
properties
|
||||
instructions
|
||||
backups
|
||||
submission
|
||||
360
site/source/service-packaging/specification/manifest.rst
Normal file
360
site/source/service-packaging/specification/manifest.rst
Normal file
@@ -0,0 +1,360 @@
|
||||
.. _service_manifest:
|
||||
|
||||
========
|
||||
Manifest
|
||||
========
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This file describes the service and it's requirements. It is used to:
|
||||
|
||||
- create a listing in the marketplace
|
||||
- denote any installation considerations
|
||||
- define dependency requirements
|
||||
- define actions such as health checks, backups, and configuration
|
||||
- define alerts and other messaging / descriptions for the user interface
|
||||
|
||||
Each time a service is updated, the Manifest should be updated to include the new version, release notes, and any pertinent updates to the install, uninstall, or restoration flows. All this information is displayed in the marketplace listing, and the optionally denoted alerts will be displayed when appropriate to provide the user with more information.
|
||||
|
||||
There is nothing you need to do as a developer to set up Tor for running a service. This is *completely* handled by EmbassyOS - a Tor address will be automatically generated when the service is installed. Just define an interface with a tor config in the Manifest file. You do, however, need to ensure the service is in fact capable of running over Tor.
|
||||
|
||||
The Manifest is also responsible for outlining service :ref:`dependencies <dependencies>`. By defining rules using the :ref:`EmbassyOS DSL specification <config_rules>`, users can easily and selectively install, uninstall, and update any service without getting stuck in dependency hell. EmbassyOS presents this information in a polished install/uninstall/update wizard, so there's no need for editing configuration files or jumping into the command line. For you as a developer, this simply means populating this key in the manifest!
|
||||
|
||||
Formatting
|
||||
----------
|
||||
|
||||
- Serialization language:``.yaml``
|
||||
- Case style: ``kebab-case``
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
Below are the types and sub-type definitions, with necessary elaborations. Any item that contains ``Option<>`` is an optional field.
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
# The package identifier used by the OS
|
||||
id: String
|
||||
# A human readable service title
|
||||
title: String
|
||||
# Service version - accepts up to four digits, where the last confirms to revisions necessary for EmbassyOS - see documentation: https://github.com/Start9Labs/emver-rs. This value will change with each release of the service.
|
||||
version: Number
|
||||
# Release notes for the update - can be a string, paragraph or URL
|
||||
release-notes: String
|
||||
# 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: String
|
||||
# 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: String
|
||||
# The original project repository URL. There is no upstream repo in this example
|
||||
upstream-repo: String
|
||||
# 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: String
|
||||
# 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: String
|
||||
# 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: List<String>
|
||||
# Minimum required version of EmbassyOS
|
||||
min-os-version: Number
|
||||
# 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: String
|
||||
# This description will display with additional details in the service's individual marketplace page
|
||||
long: String
|
||||
# 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: String
|
||||
# Default = icon.png
|
||||
icon: String
|
||||
# Default = INSTRUCTIONS.md
|
||||
instructions: String
|
||||
# Default = image.tar
|
||||
docker-images: String
|
||||
# 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: String
|
||||
# Identifier for the main image volume, which will be used when other actions need to mount to this volume.
|
||||
image: String
|
||||
# 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: String
|
||||
# Any arguments that should be passed into the entrypoint executable
|
||||
args: List<String>
|
||||
# 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: String
|
||||
# Health checks
|
||||
health-checks:
|
||||
main:
|
||||
name: String
|
||||
description: String
|
||||
type: String
|
||||
image: String
|
||||
entrypoint: String
|
||||
args: List<String>
|
||||
# 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: Boolean
|
||||
# Optional if false - indicates if an image that is preloaded onto the system will be used
|
||||
system: Boolean
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: Enum<json|yaml|toml>
|
||||
# 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: String
|
||||
# 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: String
|
||||
# Indicates if an image that is preloaded onto the system will be used
|
||||
system: Boolean
|
||||
# The initial run command to execute the config get action
|
||||
entrypoint: String
|
||||
# Any arguments that need to be passed into the run command
|
||||
args: List<String>
|
||||
# The locations at which to mount the specified Docker images
|
||||
mounts:
|
||||
compat: String
|
||||
main: String
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: Enum<yaml|json|toml>
|
||||
# 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: String
|
||||
image: String
|
||||
system: Boolean
|
||||
entrypoint: String
|
||||
args: List<String>
|
||||
mounts:
|
||||
compat: String
|
||||
main: String
|
||||
io-format: Enum<yaml|json|toml>
|
||||
# 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: Emver
|
||||
# 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: Boolean
|
||||
# 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: Enum<opt-in|opt-out|required>
|
||||
# An explanation of how to opt-in or opt-out. This value is optional for type=required
|
||||
how: String
|
||||
# Description of the dependency relationship
|
||||
description: String
|
||||
# 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: Enum<data|asset>
|
||||
# This is an example of an asset volume
|
||||
compat:
|
||||
type: Enum<data|asset>
|
||||
# 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: String
|
||||
# A descriptive description of what the interface does
|
||||
description: String
|
||||
tor-config:
|
||||
# Port mappings are from the external port to the internal container port
|
||||
port-mapping:
|
||||
80: String
|
||||
# Port mappings are from the external port to the internal container port
|
||||
lan-config:
|
||||
80:
|
||||
ssl: Boolean
|
||||
internal: Number
|
||||
# Denotes if the service has a user interface to display
|
||||
ui: Boolean
|
||||
# Denotes the protocol specifications used by this interface
|
||||
protocols: List<String>
|
||||
# Alerts: omitting these will result in using the default alerts in EmbassyOS, except for start, which has no default.
|
||||
alerts:
|
||||
install-alert: String
|
||||
uninstall-alert: String
|
||||
restore-alert: String
|
||||
start-alert: String
|
||||
# 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:
|
||||
type: String
|
||||
image: String
|
||||
system: Boolean
|
||||
entrypoint: String
|
||||
# Arguments to pass into the entrypoint.
|
||||
args: List<String>
|
||||
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: String
|
||||
main: String
|
||||
restore:
|
||||
type: String
|
||||
image: String
|
||||
system: Boolean
|
||||
entrypoint: String
|
||||
args: List<String>
|
||||
mounts:
|
||||
BACKUP: String
|
||||
main: String
|
||||
# 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: String
|
||||
description: String
|
||||
warning: Option<String>
|
||||
# Indicates what state the service can be in while executing the action
|
||||
allowed-statuses: List<String>
|
||||
# Defines how the action is run
|
||||
implementation:
|
||||
type: String
|
||||
image: String
|
||||
entrypoint: String
|
||||
args: [List<String>
|
||||
# Same as note on health-checks
|
||||
inject: Boolean
|
||||
# Required - valid values are yaml, toml, json
|
||||
io-format: Enum<yaml|json|toml>
|
||||
|
||||
.. _dependencies-spec:
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Many services depend on other libraries and services on EmbassyOS (such as Bitcoin), sometimes even a particular version of those services, which need to be specified by the developers so that EmbassyOS can handle installing these dependencies under the hood.
|
||||
|
||||
The key of each field in the dependencies object is the lowercase, kebab-case app ID of the service that is depended on. Each dependency contains a set of rules that need to be fulfilled as true if the dependency is to be properly installed. The "config rules" here are for auto-configuring dependencies - the action defined by the rule will be executed if the service is auto configured with defaults during initial setup. This simplifies and streamlines the user experience. The interface should provide suggestions for the behavior if the denoted rule cannot be met with previous configurations.
|
||||
|
||||
Let's take this snippet for example:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
...
|
||||
btc-rpc-proxy:
|
||||
version: ">=0.3.2.1 <0.4.0"
|
||||
requirement:
|
||||
type: "opt-in"
|
||||
how: Can alternatively configure an external bitcoind node.
|
||||
critical: false
|
||||
description: Used to fetch validated blocks.
|
||||
config:
|
||||
check:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
args:
|
||||
- dependency
|
||||
- check
|
||||
- btcpayserver
|
||||
- "btc-rpc-proxy"
|
||||
- /datadir
|
||||
- "/mnt/assets/btc-rpc-proxy_config_rules.yaml"
|
||||
mounts:
|
||||
main: /datadir
|
||||
compat: /mnt/assets
|
||||
io-format: yaml
|
||||
auto-configure:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
args:
|
||||
- dependency
|
||||
- "auto-configure"
|
||||
- btcpayserver
|
||||
- "btc-rpc-proxy"
|
||||
- /datadir
|
||||
- "/mnt/assets/btc-rpc-proxy_config_rules.yaml"
|
||||
mounts:
|
||||
main: /datadir
|
||||
compat: /mnt/assets
|
||||
io-format: yaml
|
||||
...
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
|
||||
TODO update for accuracy
|
||||
|
||||
The service ``btc-rpc-proxy`` is a dependency of the service ``c-lightning``. ``c-lightning`` requires it to be installed at a version >=0.3.2.1 but <0.4.0. There exists a rule that states the config option ``user.name`` must be equal to "c-lightning". If this value does not exist for ``user.name`` when accessed, ``PUSH`` the value "c-lighting" to the field. This all takes place during the initial service configuration, before the service is started for the first time.
|
||||
|
||||
.. note::
|
||||
Dependency config rules are processed in order.
|
||||
|
||||
Type definitions
|
||||
================
|
||||
|
||||
Types for ``manifest.yaml`` fields: TODO check accuracy
|
||||
|
||||
.. code:: typescript
|
||||
|
||||
interface Dependencies [{
|
||||
serviceId: DepInfo
|
||||
}]
|
||||
|
||||
interface DepInfo {
|
||||
version: String // ie. 0.11.1.1
|
||||
optional?: String,
|
||||
description?: String,
|
||||
config: [ConfigRule],
|
||||
],
|
||||
}
|
||||
|
||||
interface ConfigRule {
|
||||
rule: String, // ie. 'users.*.name = "lnd"
|
||||
description: String,
|
||||
suggestions: [SuggestionVariant]
|
||||
}
|
||||
|
||||
interface SuggestionVariant {
|
||||
SET: {
|
||||
var: String,
|
||||
to: SetVariant,
|
||||
},
|
||||
DELETE: {
|
||||
src: String,
|
||||
},
|
||||
PUSH: {
|
||||
to: String,
|
||||
value: Value,
|
||||
},
|
||||
}
|
||||
|
||||
interface SetVariant {
|
||||
to: Option<String>,
|
||||
to-value: Option<Value>, // ie. true/false
|
||||
to-entropy: Option<{
|
||||
charset: String // ie. 'a-z,A-Z,0-9'
|
||||
len: number
|
||||
}>
|
||||
}
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
- `filebrowser <>`_
|
||||
- `embassy-pages <>`_
|
||||
- `photoview <>`_
|
||||
- `btcpayserver <>`_
|
||||
- `lnd <>`_
|
||||
- `synapse <>`_
|
||||
@@ -1,13 +0,0 @@
|
||||
.. _dev-faq:
|
||||
|
||||
=============
|
||||
Developer FAQ
|
||||
=============
|
||||
|
||||
Frequently Asked Questions by and for developers. If you have a suggestion, please use the Github link at the top of the page.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
faq-contributing
|
||||
faq-service-packaging
|
||||
@@ -1,24 +0,0 @@
|
||||
.. _dev-docs:
|
||||
|
||||
==============
|
||||
Developer Docs
|
||||
==============
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:hidden:
|
||||
|
||||
dev-tools/index
|
||||
packaging-example
|
||||
service-packaging/index
|
||||
dev-faq/index
|
||||
|
||||
.. panel-box::
|
||||
:title: Overview
|
||||
:id: "dev-docs"
|
||||
:class: my-panel
|
||||
|
||||
* :doc:`Developer Tools <dev-tools/index>` - An overview of tools for those interested in contributing to the OS or packaging a service.
|
||||
* :doc:`Package Example <packaging-example>` - A walkthrough of how to package a service using an example.
|
||||
* :doc:`Service Packaging <service-packaging/index>` - The full specification for packaging a service.
|
||||
* :doc:`Developer FAQ <dev-faq/index>` - Frequently asked questions by developers in regard to EmbassyOS and packaging services.
|
||||
@@ -1,543 +0,0 @@
|
||||
.. _packaging-example:
|
||||
|
||||
=========================
|
||||
Service Packaging Example
|
||||
=========================
|
||||
|
||||
.. contents::
|
||||
:depth: 4
|
||||
:local:
|
||||
|
||||
|
||||
Welcome! The following guide will provide the prerequisites, introduce a brief overview of the packaging process, use an example demonstrating how to package a service, and finally, describe the submission process. This essentially describes how you can take an existing app (or one you have written yourself), and wrap it up into an ``s9pk`` such that it can be added to an EmbassyOS (EOS) Marketplace! The ``s9pk`` is the final product, which is the portable version of a package that is understood by EOS, and can be distributed to any EOS users either directly, or via a Marketplace.
|
||||
|
||||
Pre-requisites
|
||||
--------------
|
||||
|
||||
EmbassyOS (EOS)
|
||||
===============
|
||||
|
||||
It is **HIGHLY RECOMMENDED** to have a copy of EmbassyOS for testing your packaged service.
|
||||
|
||||
There are 3 options for this:
|
||||
#. Build from `source <https://github.com/Start9Labs/embassy-os/build>`_
|
||||
#. Follow the :ref:`DIY guide <diy>` to build on a Raspberry Pi
|
||||
#. :ref:`Purchase <purchasing>` a device or copy of the OS
|
||||
|
||||
Development Environment
|
||||
=======================
|
||||
|
||||
Once you have EOS installed, you'll want to get your development system set up with the necessary software.
|
||||
|
||||
At minimum you will need the following:
|
||||
#. `Docker <https://docs.docker.com/get-docker>`_
|
||||
#. `Docker-buildx <https://docs.docker.com/buildx/working-with-buildx/>`_
|
||||
#. `Embassy-SDK <https://github.com/Start9Labs/embassy-os/tree/master/backend>`_
|
||||
|
||||
The following are recommended:
|
||||
#. `Cargo <https://doc.rust-lang.org/cargo/>`_
|
||||
#. `yq <https://mikefarah.gitbook.io/yq/>`_ (version 4)
|
||||
#. `make <https://www.gnu.org/software/make/>`_
|
||||
#. `rust-musl-cross <https://github.com/Start9Labs/rust-musl-cross>`_ (For cross compiling Rust to Alpine, not needed otherwise)
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Components
|
||||
==========
|
||||
|
||||
The package is made up of the following parts:
|
||||
|
||||
#. Container Image - Each service is running in a container (typically Docker). Best results will come from an arm based linux; [Alpine](https://www.alpinelinux.org/) is highly recommended.
|
||||
#. Volume(s) - Each service gets one or more volumes, allocated by EOS. This is the filesystem where the service data will be stored and mounted by the container. The volume directory within EOS (for seeding data into the volume) is located at `/embassy-data/package-data/volumes/<service-id>`
|
||||
#. Dependencies - Rules and requirements of your service, which appear as UI elements, such as inputs, toggles, and drop-downs. These are enforced by validations and clear user instructions. EmbassyOS has a unique and powerful system for managing dependencies which allows anyone to have the power of systems administrators without an advanced skillset.
|
||||
#. Manifest - Describes the service and its requirements. This file describes the marketplace listing, installation considerations, configuration and dependency requirements, health checks, backups and additional info.
|
||||
#. Config - EOS makes a service's configuration available to the user in the GUI and must be valid regardless of user skill.
|
||||
#. Instructions & Docs - Directions for setup, use, external integrations, etc.
|
||||
#. License - The Open Source license of the service wapper.
|
||||
#. Icon - Image used to identify the service in the UI.
|
||||
|
||||
The ``.s9pk`` is the image, manifest, license, icon, and instructions files bundled into a package. Optional additional assets for use with system images can also be bundled. This is the file a user downloads from the Marketplace, at which point EOS uses to unpack assets and install the service.
|
||||
|
||||
Check :ref:`here <service_package_overview>` for a detailed overview of package components.
|
||||
|
||||
Service Wrapper Repo and Submodules
|
||||
===================================
|
||||
|
||||
See :ref:`here <service_wrapper>` for how to structure your service wrapper's git repository.
|
||||
|
||||
Git submodules allow the use of another project while in the working project directory. In this case, you can use an existing app's git repo in order to source its code in your service wrapper. You can add the submodule into the wrapper so that you can build the submodule and also track the exact code you're building.
|
||||
|
||||
Simply run:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git submodule add <link_to_source_project>
|
||||
|
||||
Example - Hello World
|
||||
---------------------
|
||||
|
||||
Okay, let's actually package a service! For this example, we're going to use an example service `Hello World <https://github.com/Start9Labs/hello-world>`_. This repository can also be used as a template to quickly get started with your service. The guide will provide good overview of service packaging, but obviously your app will be different, so don't hesitate to reach out to our community `dev chat <https://matrix.to/#/#community-dev:matrix.start9labs.com>`_ with questions.
|
||||
|
||||
The commands below assume a Linux development environment with all the recommended dependencies listed above installed. To get started quickly, we'll use Start9's wrapper template.
|
||||
|
||||
Clone the Template Repo and Edit the Manifest
|
||||
=============================================
|
||||
|
||||
#. Clone and rename the repo (or alternatively, use the template generation button found on the github `repo <https://github.com/Start9Labs/hello-world-wrapper>`_)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git clone https://github.com/Start9Labs/hello-world-wrapper
|
||||
cd hello-world-wrapper
|
||||
|
||||
#. Edit the ``README.md`` to explain what the service is, what dependencies are required, build/install/contribute instructions, and any other information you'd like.
|
||||
|
||||
#. Edit the ``manifest`` file. This must be in ``.json``, ``.toml``, or ``.yaml`` format and in ``kebab-case`` style. You can see descriptions of each key (and some notes) in our 'Hello World' example ``manifest.yaml`` below:
|
||||
|
||||
Manifest example
|
||||
================
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
id: hello-world
|
||||
title: "Hello World"
|
||||
version: 0.2.0 # Service version
|
||||
release-notes: "Upgrade to EmbassyOS 2.16.0 and then to v0.3.0"
|
||||
license: mit
|
||||
wrapper-repo: "https://github.com/Start9Labs/hello-world-wrapper"
|
||||
upstream-repo: "https://github.com/Start9Labs/hello-world-wrapper" # There is no upstream repo in this example
|
||||
support-site: "https://docs.start9.com/"
|
||||
marketing-site: "https://start9.com/"
|
||||
build: ["make"] # Series of commands to build into an s9pk, in this case we are using make and all the build commands are in the makefile
|
||||
min-os-version: "0.3.0" # Minimum required version of EmbassyOS
|
||||
description:
|
||||
short: Example service
|
||||
long: |
|
||||
Hello World is a simple example of a service wrapper that launches a web interface to say hello and nothing more.
|
||||
assets:
|
||||
license: LICENSE # default = LICENSE.md
|
||||
icon: icon.png # default = icon.png
|
||||
instructions: docs/instructions.md # default = INSTRUCTIONS.md
|
||||
docker-images: image.tar # default = image.tar
|
||||
main:
|
||||
type: docker
|
||||
image: main
|
||||
entrypoint: "/usr/local/bin/docker_entrypoint.sh"
|
||||
args: []
|
||||
mounts: {} # Specifies where to put volumes, if there are any. Empty in this example
|
||||
health-checks: {} # Health check config would go here
|
||||
config: ~ # Configuration options, none for hello-world, but see below example for format:
|
||||
# get:
|
||||
# type: docker
|
||||
# image: compat
|
||||
# entrypoint: compat
|
||||
# args:
|
||||
# - "config"
|
||||
# - "get"
|
||||
# - "/root/.hello-world/start9/config.yaml"
|
||||
# - "/mnt/assets/config_spec.yaml"
|
||||
# mounts:
|
||||
# compat: "/mnt/assets"
|
||||
# main: "/root"
|
||||
# io-format: yaml
|
||||
# set:
|
||||
# type: docker
|
||||
# image: compat
|
||||
# entrypoint: compat
|
||||
# args:
|
||||
# - "config"
|
||||
# - "set"
|
||||
# - "/root/.hello-world/start9/config.yaml"
|
||||
# mounts:
|
||||
# main: "/root"
|
||||
# io-format: yaml
|
||||
dependencies: {} # Service pre-requisites, none for hello-world, but see below example (which would make BTC Proxy a dependency) for format:
|
||||
# btc-rpc-proxy:
|
||||
# version: ">=0.3.2.1 <0.4.0"
|
||||
# recommended: true
|
||||
# critical: false
|
||||
# optional: Can alternatively configure an external bitcoin node.
|
||||
# description: Used to fetch validated blocks.
|
||||
# config:
|
||||
# check:
|
||||
# type: docker
|
||||
# image: compat
|
||||
# system: true
|
||||
# # the compat image will contain a tool to check the config rules against the specified dependency
|
||||
# entrypoint: compat
|
||||
# args:
|
||||
# - "dependency"
|
||||
# - "check"
|
||||
# - "/mnt/assets/btc-rpc-proxy.rules.yaml"
|
||||
# mounts:
|
||||
# compat: "/mnt/assets"
|
||||
# auto-configure:
|
||||
# type: docker
|
||||
# image: compat
|
||||
# # if true, the denoted image is prebuilt and comes stock with EOS
|
||||
# # uncommon: if you want something not prebuilt with EOS, you can bundle multiple docker images into the `image.tar` during the `make` build process
|
||||
# system: true
|
||||
# entrypoint: compat
|
||||
# args:
|
||||
# - "dependency"
|
||||
# - "auto-configure"
|
||||
# - "/mnt/assets/btc-rpc-proxy.rules.yaml"
|
||||
# mounts:
|
||||
# compat: "/mnt/assets"
|
||||
volumes: # this is the image where data will go from 0.2.x
|
||||
main:
|
||||
type: data # this is the image where files from the project asset directory will go
|
||||
compat:
|
||||
type: assets
|
||||
interfaces:
|
||||
main:
|
||||
name: Network Interface
|
||||
description: Specifies the interface to listen on for HTTP connections.
|
||||
tor-config:
|
||||
port-mapping:
|
||||
80: "80"
|
||||
lan-config:
|
||||
80:
|
||||
ssl: false
|
||||
mapping: 80
|
||||
ui: true
|
||||
protocols:
|
||||
- tcp
|
||||
- http
|
||||
alerts: {}
|
||||
backup:
|
||||
create:
|
||||
type: docker
|
||||
image: compat # default backup process of the compat docker image is duplicity - EOS will have access to the image defined here
|
||||
system: true
|
||||
entrypoint: compat # command to run the backup executable, in this case, duplicity
|
||||
args: # arguments to pass into the entrypoint, in this case duplicity - in this example, the full command run will be: `duplicity hello-world file:///mnt/backup /root`
|
||||
- duplicity
|
||||
- hello-world
|
||||
- /mnt/backup
|
||||
- /root
|
||||
mounts:
|
||||
# BACKUP is the default volume that is used for backups. This is whatever backup drive is mounted to the defice, or a network filesystem.
|
||||
# The value here donates where the data mount point will be. Backup drive is mounted to this location, which contains previous backups.
|
||||
BACKUP: "/mnt/backup"
|
||||
main: "/root"
|
||||
restore:
|
||||
type: docker
|
||||
image: compat
|
||||
system: true
|
||||
entrypoint: compat
|
||||
args:
|
||||
- duplicity
|
||||
- hello-world
|
||||
- /root
|
||||
- /mnt/backup
|
||||
mounts:
|
||||
# See above comments under `backup: -> mounts:`
|
||||
BACKUP: "/mnt/backup"
|
||||
main: "/root"
|
||||
actions: {} # Commands that can be issued from the UI. None for hello-world, but see below example (resetting a root user) for format:
|
||||
# reset-root-user:
|
||||
# name: Reset Root User
|
||||
# description: Resets your root user (the first user) to username "admin" and a random password; restores any lost admin privileges.
|
||||
# warning: This will invalidate existing sessions and password managers if you have them set up.
|
||||
# allowed-statuses:
|
||||
# - stopped
|
||||
# implementation:
|
||||
# type: docker
|
||||
# image: main
|
||||
# system: true
|
||||
# entrypoint: docker_entrypoint.sh
|
||||
# args: ["reset-root-user"]
|
||||
# mounts:
|
||||
# main: "/root"
|
||||
|
||||
Note the ``dependencies`` and ``volumes`` sections, which may access another service, e.g. File Browser, such that files stored on a user's Embassy can be accessed in your service.
|
||||
|
||||
For details on all the different possible dependency, type, and subtype definitions available for the ``manifest`` file, please see :ref:`here <service_manifest>`.
|
||||
|
||||
Edit the Dockerfile and Entrypoint
|
||||
==================================
|
||||
|
||||
Next, it's time to edit the ``Dockerfile``. This defines how to build the image for the package by declaring the environment, building stages, and copying any binaries or assets needed to run the service or its health checks to the image filesystem.
|
||||
|
||||
#. We start by importing a base image, in this case Alpine, as recommended.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
FROM arm64v8/alpine:3.12
|
||||
|
||||
#. Next we issue some commands, which in this example simply updates repositories, installs required software, and finally creates a directory for nginx.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
RUN apk update
|
||||
RUN apk add tini
|
||||
|
||||
RUN mkdir /run/nginx
|
||||
|
||||
#. Next we will add the cross-compiled binary of ``hello-world`` to ``/usr/local/bin/`` and add the ``docker_entrypoint.sh`` file from the repository. 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
|
||||
|
||||
#. 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 clarity.
|
||||
|
||||
.. code:: docker
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
|
||||
|
||||
#. Great, let's take a look at our final Hello World ``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
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
|
||||
|
||||
Docker Entrypoint
|
||||
=================
|
||||
|
||||
#. Okay, let's move on to our ``docker_entrypoint.sh`` file. This is a script that defines what to do when 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 it does all of the signal handling and container exits when it is stopped/exits. If you have built a "configurator," this will also need to be called to execute here. More on configurators below. Let's take a look at our (extremely basic) Hello World example:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
export HOST_IP=$(ip -4 route list match 0/0 | awk '{print $3}')
|
||||
|
||||
exec tini hello-world
|
||||
|
||||
#. We've defined the file, exported the IP address of the Embassy (host), and run the program.
|
||||
|
||||
For a more detailed ``docker_entrypoint.sh``, please check out the `filebrowser-wrapper <https://github.com/Start9Labs/filebrowser-wrapper/blob/master/docker_entrypoint.sh>`_. Additional details on the ``Dockerfile`` and ``docker_entrypoint`` can be found `here <https://docs.start9.com/contributing/services/docker.html>`_.
|
||||
|
||||
Configurators
|
||||
.............
|
||||
|
||||
- Broadly, a "configurator" is any code that translates the configuration coming from the OS to a format the service can understand. Technically all services with a config have one of these (so, most services on Embassy). The configurator also writes the stats.yaml file, which is used in properties.
|
||||
|
||||
- Narrowly, a configurator is a piece of code separate from the docker_entrypoint.sh script, that does the same as the task above. If you can configure the service in bash, inside the docker_entrypoint.sh script, then you don't need a separate piece of code called "configurator", as we have in LND, CL, and synapse, for example. You might want to create a separate configurator if configuring your service would be complicated or impossible in bash. In the case of CL and LND (and bitcoind, where the configurator is actually called a "manager"), the configurator actually has a long-running element that runs concurrently with the service itself.
|
||||
|
||||
There's really no reason a service has to be engineered in this manner. It's really up to the package maintainer how they want to accomplish translation of the config and implementing the properties action, which doesn't even require a stats.yaml file as of 0.3.
|
||||
|
||||
You can check out an example configurator in the `BitcoinD Wrapper <https://github.com/Start9Labs/bitcoind-wrapper/tree/master/manager>`_, which in this case is called a manager.
|
||||
|
||||
Makefile (Optional)
|
||||
===================
|
||||
|
||||
Here, we will create a ``Makefile``, which is optional, but recommended as it outlines the build and streamlines additional developer contributions. Alternatively, you could use ``nix``, ``bash``, ``python``, ``perl``, ``ruby``, etc instead of ``make`` for build orchestration.
|
||||
|
||||
Our example ``Makefile`` is again fairly simple for Hello World. Let's take a look:
|
||||
|
||||
.. code-block:: Makefile
|
||||
|
||||
ASSETS := $(shell yq e '.assets.[].src' manifest.yaml)
|
||||
ASSET_PATHS := $(addprefix assets/,$(ASSETS))
|
||||
VERSION := $(shell toml get hello-world/Cargo.toml package.version)
|
||||
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_ON_ERROR:
|
||||
|
||||
all: verify
|
||||
|
||||
verify: hello-world.s9pk $(S9PK_PATH)
|
||||
embassy-sdk verify $(S9PK_PATH)
|
||||
|
||||
# embassy-sdk pack errors come from here, check your manifest, config, instructions, and icon
|
||||
hello-world.s9pk: manifest.yaml assets/compat/config_spec.yaml config_rules.yaml image.tar docs/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 --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 +beta build --release
|
||||
docker run --rm -it -v ~/.cargo/registry:/root/.cargo/registry -v "$(shell pwd)"/hello-world:/home/rust/src start9/rust-musl-cross:aarch64-musl musl-strip target/aarch64-unknown-linux-musl/release/hello-world
|
||||
|
||||
manifest.yaml: hello-world/Cargo.toml
|
||||
yq e -i '.version = $(VERSION)' manifest.yaml
|
||||
|
||||
#. The first 5 lines set environment variables.
|
||||
|
||||
#. The next line simply removes the progress of a ``make`` process if it fails.
|
||||
|
||||
.. code-block:: Makefile
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
#. The ``all`` step is run when the ``make`` command is issued. This attempts the ``verify`` step, which requires that the ``hello-world.s9pk`` must first be built, which first requires the ``image.tar``, and so on. In this case, each step requires the next and each step indicates the necessary existence of a file. If an indicated file has been altered, such as the `docker_entrypoint.sh`, then any step that contains this file will be rebuilt.
|
||||
|
||||
#. So the ``.s9pk`` is created with the ``embassy-sdk pack`` command, supplied with the ``manifest``, ``config_spec``, previously created ``image.tar``, and ``instructions.md``. Your project may likely also contain a ``config_rules`` file. Some of these files we have not yet edited, but that will come shortly.
|
||||
|
||||
#. The ``image.tar`` is built below this, the cross-compiled ``hello-world`` source code, and ``manifest`` at the bottom.
|
||||
|
||||
For more details on creating a ``Makefile`` for your project, please check :ref:`here <service_makefile>`.
|
||||
|
||||
Service Config Specification and Rules
|
||||
======================================
|
||||
|
||||
Most self-hosted packages require a configuration. With EmbassyOS, these config options are provided to the user in a friendly GUI, and invalid configs are not permitted. This allows the user to manage their software without a lot of technical skill, and minimal risk of borking their software.
|
||||
|
||||
In the config section of the `manifest`, you can
|
||||
Two files are created in this process:
|
||||
|
||||
``config_spec.yaml`` for specifying all the config options your package depends on to run
|
||||
|
||||
``config_rules.yaml`` for defining the ruleset that defines dependencies between config variables
|
||||
|
||||
These are stored in ``assets/compat/`` for 0.2.x compatibility, and in ``/assets/`` for anything built for v0.3.0 and up (almost certainly what you're doing). These files contain a detailed mapping of configuration options with acceptable values, defaults, and relational rule-sets. Hello World has no configuration, as you can see `here <https://github.com/Start9Labs/hello-world-wrapper/blob/0.3.0/assets/compat/config_spec.yaml>`_. Instead, let's take a look at our ``config_spec`` for Embassy Pages, which actually has some config options:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
homepage:
|
||||
name: Homepage
|
||||
description: The page that will be displayed when your Embassy Pages .onion address is visited. Since this page is technically publicly accessible, you can choose to which type of page to display.
|
||||
type: union
|
||||
default: welcome
|
||||
tag:
|
||||
id: type
|
||||
name: Type
|
||||
variant-names:
|
||||
welcome: Welcome
|
||||
index: Subdomain Index
|
||||
filebrowser: Web Page
|
||||
redirect: Redirect
|
||||
fuck-off: Fuck Off
|
||||
variants:
|
||||
welcome: {}
|
||||
index: {}
|
||||
filebrowser:
|
||||
directory:
|
||||
type: string
|
||||
name: Directory Path
|
||||
description: The path to the directory in File Browser that contains the static files of your website. For example, a value of "websites/resume_site" would tell Embassy Pages to look for that directory in File Browser.
|
||||
pattern: "^(\\.|[a-zA-Z0-9_ -][a-zA-Z0-9_ .-]*|([a-zA-Z0-9_ .-][a-zA-Z0-9_ -]+\\.*)+)(/[a-zA-Z0-9_ -][a-zA-Z0-9_ .-]*|/([a-zA-Z0-9_ .-][a-zA-Z0-9_ -]+\\.*)+)*/?$"
|
||||
pattern-description: Must be a valid relative file path
|
||||
nullable: false
|
||||
redirect:
|
||||
target:
|
||||
type: string
|
||||
name: Target Subdomain
|
||||
description: The name of the subdomain to redirect users to. This must be a valid subdomain site within your Embassy Pages.
|
||||
pattern: '^[a-z-]+$'
|
||||
pattern-description: May contain only lowercase characters and hyphens.
|
||||
nullable: false
|
||||
fuck-off: {}
|
||||
subdomains:
|
||||
type: list
|
||||
name: Subdomains
|
||||
description: The websites you want to serve.
|
||||
default: []
|
||||
range: '[0, *)'
|
||||
subtype: object
|
||||
spec:
|
||||
unique-by: name
|
||||
display-as: "{{name}}"
|
||||
spec:
|
||||
name:
|
||||
type: string
|
||||
nullable: false
|
||||
name: Subdomain name
|
||||
description: The subdomain of your Embassy Pages .onion address to host the website on. For example, a value of "me" would produce a website hosted at http://me.myaddress.onion.
|
||||
pattern: "^[a-z-]+$"
|
||||
pattern-description: "May contain only lowercase characters and hyphens"
|
||||
settings:
|
||||
type: union
|
||||
name: Settings
|
||||
description: The desired behavior you want to occur when the subdomain is visited. You can either redirect to another subdomain, or load a web page from File Browser.
|
||||
default: filebrowser
|
||||
tag:
|
||||
id: type
|
||||
name: Type
|
||||
variant-names:
|
||||
filebrowser: Web Page
|
||||
redirect: Redirect
|
||||
variants:
|
||||
filebrowser:
|
||||
directory:
|
||||
type: string
|
||||
name: Directory Path
|
||||
description: The path to the directory in File Browser that contains the static files of your website. For example, a value of "websites/resume_site" would tell Embassy Pages to look for that directory in File Browser.
|
||||
pattern: "^(\\.|[a-zA-Z0-9_ -][a-zA-Z0-9_ .-]*|([a-zA-Z0-9_ .-][a-zA-Z0-9_ -]+\\.*)+)(/[a-zA-Z0-9_ -][a-zA-Z0-9_ .-]*|/([a-zA-Z0-9_ .-][a-zA-Z0-9_ -]+\\.*)+)*/?$"
|
||||
pattern-description: Must be a valid relative file path
|
||||
nullable: false
|
||||
redirect:
|
||||
target:
|
||||
type: string
|
||||
name: Target Subdomain
|
||||
description: The subdomain of your Embassy Pages .onion address to redirect to. This should be the name of another subdomain on Embassy Pages. Leave empty to redirect to the homepage.
|
||||
pattern: '^[a-z-]+$'
|
||||
pattern-description: May contain only lowercase characters and hyphens.
|
||||
nullable: false
|
||||
|
||||
We essentially have 2 config options (homepage and subdomains), with all of their specifications nested below them. Looking at the homepage, it contains a ``union`` type, which is a necessary dependency, which can be of 5 variants (welcome, index, filebrowser, redirect, or fuck-off). The below images show how this is displayed in the UI.
|
||||
|
||||
.. figure:: /_static/images/dev/pages0.png
|
||||
:width: 60%
|
||||
:alt: Pages Config
|
||||
|
||||
.. figure:: /_static/images/dev/pages1.png
|
||||
:width: 60%
|
||||
:alt: Pages Union
|
||||
|
||||
For all the possible types, please check our :ref:`Service Config Spec <service_config>`.
|
||||
|
||||
In our example, there is *no need* for a ``config_rules`` file. This is because there is not a rule-set required to define dependencies between config variables. An example of when this would be required would be the following code, from the [LND wrapper](https://github.com/Start9Labs/lnd-wrapper/blob/master/config_rules.yaml):
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
---
|
||||
- rule: '!(max-chan-size?) OR !(min-chan-size?) OR (#max-chan-size > #min-chan-size)'
|
||||
description: "Maximum Channel Size must exceed Minimum Channel Size"
|
||||
|
||||
Here we see that a Maximum Channel Size **MUST** be one of 3 possible options in order to be a valid config.
|
||||
|
||||
Properties
|
||||
==========
|
||||
|
||||
Next we need to create the Properties section for our package, to display any relevant info. The result of this step is a ``stats.yaml`` file, which is only populated at runtime. These commands will be issued in the ``docker_entrypoint`` file (or ``configurator``, if you are using one).
|
||||
|
||||
.. ***STATS.YAML IS APPARENTLY BEING DEPRECATED, THIS SECTION NEEDS COMMENT*** Possibly this is not actually the case?
|
||||
|
||||
Instructions
|
||||
============
|
||||
|
||||
Instructions are the basic directions or any particular details that you would like to convey to the user to help get them on their way. Each wrapper repo should contain a ``docs`` directory which can include anything you'd like, but specifically if you include an ``instructions.md`` file, formatted in Markdown language, it will be displayed simply for the user as shown below.
|
||||
|
||||
.. figure:: /_static/images/dev/instructions.png
|
||||
:width: 60%
|
||||
:alt: Instructions
|
||||
|
||||
You can find the ``instructions.md`` file for Embassy Pages `here <https://github.com/Start9Labs/embassy-pages-wrapper/tree/master/docs>`_ if you are interested.
|
||||
|
||||
Backups
|
||||
=======
|
||||
|
||||
Everything in the root folder of the mounted system directory will be stored in an EOS backup. If you want to ignore any particular files for backup, you can create a ``.backupignore`` file and add the relative paths of any directories you would like ignored.
|
||||
|
||||
Submission Process
|
||||
------------------
|
||||
|
||||
When you have built and tested your project for EmbassyOS, please send Start9 a submission with the project repository to dev@start9labs.com. After being reviewed for security and compatibility, the service will be deployed to the 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!
|
||||
@@ -1,35 +0,0 @@
|
||||
.. _service-packaging-spec:
|
||||
|
||||
======================
|
||||
Service Packaging Spec
|
||||
======================
|
||||
|
||||
Welcome! If you are here, you are interested in becoming part of the mission to change the future of personal computing. This guide will take you through the process of packaging a service for EmbassyOS, a novel, self-hosted, sovereign computing platform.
|
||||
|
||||
A service in this context is any open source project that has been bundled into the appropriate format to run on EmbassyOS. By configuring and packaging a project according to this guide, it can be installed on EmbassyOS with no command line or technical expertise required. This opens up an entire platform for self-hosted software to run independent of third parties in a completely private and sovereign way for all individuals.
|
||||
|
||||
This guide is technical, but breaks down the steps for deployment. If you have any feedback or questions concerning this guide, please don't hesitate to `reach out <https://matrix.to/#/#community-dev:matrix.start9labs.com>`_ or submit a pull request with alterations.
|
||||
|
||||
To start, you will need to acquire EmbassyOS for testing the packaged service. This can be done by:
|
||||
|
||||
- building from `source <https://github.com/Start9Labs/embassy-os/blob/master/CONTRIBUTING.md#setting-up-your-development-environment>`_
|
||||
- following the :ref:`DIY <diy>` guide
|
||||
- :ref:`purchasing <purchasing>` the ready to run personal server
|
||||
|
||||
While you are waiting to receive or assemble a device, you can begin the process of packaging a project. The next sections outline these steps in detail.
|
||||
|
||||
Happy building!
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
overview
|
||||
wrapper
|
||||
manifest
|
||||
docker
|
||||
makefile
|
||||
config
|
||||
properties
|
||||
instructions
|
||||
backups
|
||||
submission
|
||||
@@ -1,353 +0,0 @@
|
||||
.. _service_manifest:
|
||||
|
||||
========
|
||||
Manifest
|
||||
========
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
This file describes the service and it's requirements. It is used to:
|
||||
|
||||
- create a listing in the marketplace
|
||||
- denote any installation considerations
|
||||
- define dependency requirements
|
||||
|
||||
Each time a service is updated, the manifest should be updated to include the new version, release notes, and any pertinent updates to the install, uninstall, or restoration flows. All this information is displayed in the marketplace listing, and the optionally denoted alerts will be displayed when appropriate to provide the user with more information.
|
||||
|
||||
For instance, `LND displays alerts <https://github.com/Start9Labs/lnd-wrapper/blob/87daf4e5ed7231e22aaa28be533e794f67f98289/manifest.yaml#L30>`_ around restoration since data will be overwritten.
|
||||
|
||||
There is nothing you need to do as a developer to set up Tor for running a service. This is *completely* handled by EmbassyOS - a Tor address will be automatically generated when the service is installed. Just define the port and which version of Tor the service needs in this manifest file! You do, however, need to ensure the service is in fact capable of running over Tor.
|
||||
|
||||
The manifest is also responsible for outlining service :ref:`dependencies <dependencies>`. By defining rules using the :ref:`EmbassyOS DSL specification <config_rules>`, users can easily and selectively install, uninstall, and update any service without getting stuck in dependency hell. EmbassyOS presents this information in a polished install/uninstall/update wizard, so there's no need for editing configuration files or jumping into the command line. For you as a developer, this simply means populating this key in the manifest!
|
||||
|
||||
Formatting
|
||||
----------
|
||||
|
||||
- Serialization language:``.yaml``
|
||||
- Case style: ``kebab-case``
|
||||
|
||||
Type definitions
|
||||
----------------
|
||||
|
||||
Below are the types and sub-type definitions, with necessary elaborations. Any item that contains ``Option<>`` is an optional field.
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
# manifest version compatibility ie. v0 (this is currently the only option)
|
||||
compat: v0
|
||||
# service id, used for uniqueness and BE identification ie. bitcoind
|
||||
id: String
|
||||
# version number of the release conforming to the semantic versioning scheme
|
||||
version: String
|
||||
# display name of service
|
||||
title: String
|
||||
# an object containing a short and long description of the service. TODO character lengths
|
||||
description:
|
||||
short: String
|
||||
long: String
|
||||
# a link to the release tag notes in GitHub, or a short description TODO character length
|
||||
release-notes: String
|
||||
# a notification message that should caution the user with any service particularities, eg. beta tech
|
||||
install-alert: Option<String>
|
||||
# a notification message warning users of potential problems with uninstalling, such as dependency failures or data loss
|
||||
uninstall-alert: Option<String>
|
||||
# a notification message containing warning or details about backup restoration
|
||||
restore-alert: Option<String>
|
||||
# denoting the existence of instructions.md
|
||||
has-instructions: Boolean
|
||||
# required semver version range of EmbassyOS to run service eg. ">=1.0.0"
|
||||
os-version-required: VersionReq
|
||||
# recommended semver version range of EmbassyOS to run service eg."^1.0.0"
|
||||
os-version-recommended: VersionReq
|
||||
# a list of objects of ports to run the service on localhost and tor
|
||||
ports:
|
||||
- internal: String
|
||||
tor: String
|
||||
# currently only tar is supported
|
||||
image:
|
||||
type: String
|
||||
# shared memory container size
|
||||
shm-size-mb: Option<usize>
|
||||
# path to mount the image on the volume, ie: /root/bitcoind
|
||||
mount: String
|
||||
# read only data exposed to dependencies (path is relevant to mount)
|
||||
public: Option<String>
|
||||
# shared filesystem segment with each of your dependencies (path is relevant to mount)
|
||||
shared: Option<String>
|
||||
# deprecated - will default to an empty vector
|
||||
assets: []
|
||||
# version of tor support, eg. v2, v3
|
||||
hidden-service-version: String
|
||||
# A map of dependent services, see below for more details
|
||||
dependencies: Dependencies
|
||||
|
||||
.. _dependencies-spec:
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Many services depend on other libraries and services on EmbassyOS (such as Bitcoin), sometimes even a particular version of those services, which need to be specified by the developers so that EmbassyOS can handle installing these dependencies under the hood.
|
||||
|
||||
The key of each field in the dependencies object is the lowercase, kebab-case app ID of the service that is depended on. Each dependency contains a set of rules that need to be fulfilled as true if the dependency is to be properly installed. The "config rules" here are for auto-configuring dependencies - the action defined by the rule will be executed if the service is auto configured with defaults during initial setup. This simplifies and streamlines the user experience. The interface should provide suggestions for the behavior if the denoted rule cannot be met with previous configurations.
|
||||
|
||||
Let's take this snippet for example:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
...
|
||||
dependencies:
|
||||
btc-rpc-proxy:
|
||||
version: "^0.1.0"
|
||||
optional: Can configure an external bitcoin node.
|
||||
description: Required for fetching validated blocks.
|
||||
config:
|
||||
- rule: '''users.*.name = "c-lightning"'
|
||||
description: 'Must have an RPC user named "c-lightning"'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users'
|
||||
value:
|
||||
name: c-lightning
|
||||
...
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
|
||||
The service ``btc-rpc-proxy`` is a dependency of the service ``c-lightning``. ``c-lightning`` requires it to be installed at a version >=0.1.0 <0.2.0. There exists a rule that states the config option ``user.name`` must be equal to "c-lightning". If this value does not exist for ``user.name`` when accessed, ``PUSH`` the value "c-lighting" to the field. This all takes place during the initial service configuration, before the service is started for the first time.
|
||||
|
||||
.. note::
|
||||
Dependency config rules are processed in order.
|
||||
|
||||
Type definitions
|
||||
================
|
||||
|
||||
Types for ``manifest.yaml`` fields:
|
||||
|
||||
.. code:: typescript
|
||||
|
||||
interface Dependencies [{
|
||||
serviceId: DepInfo
|
||||
}]
|
||||
|
||||
interface DepInfo {
|
||||
version: String // ie. 0.11.1.1
|
||||
optional?: String,
|
||||
description?: String,
|
||||
config: [ConfigRule],
|
||||
],
|
||||
}
|
||||
|
||||
interface ConfigRule {
|
||||
rule: String, // ie. 'users.*.name = "lnd"
|
||||
description: String,
|
||||
suggestions: [SuggestionVariant]
|
||||
}
|
||||
|
||||
interface SuggestionVariant {
|
||||
SET: {
|
||||
var: String,
|
||||
to: SetVariant,
|
||||
},
|
||||
DELETE: {
|
||||
src: String,
|
||||
},
|
||||
PUSH: {
|
||||
to: String,
|
||||
value: Value,
|
||||
},
|
||||
}
|
||||
|
||||
interface SetVariant {
|
||||
to: Option<String>,
|
||||
to-value: Option<Value>, // ie. true/false
|
||||
to-entropy: Option<{
|
||||
charset: String // ie. 'a-z,A-Z,0-9'
|
||||
len: number
|
||||
}>
|
||||
}
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Actual ``manifest.yaml`` files for existing services:
|
||||
|
||||
LND
|
||||
...
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
compat: v0
|
||||
id: lnd
|
||||
version: 0.11.1.1
|
||||
title: Lightning Network Daemon
|
||||
description:
|
||||
short: "A complete implementation of a Lightning Network node by Lightning Labs"
|
||||
long: "LND fully conforms to the Lightning Network specification (BOLTs). BOLT stands for: Basis of Lightning Technology. In the current state lnd is capable of: creating channels, closing channels, managing all channel states (including the exceptional ones!), maintaining a fully authenticated+validated channel graph, performing path finding within the network, passively forwarding incoming payments, sending outgoing onion-encrypted payments through the network, updating advertised fee schedules, and automatic channel management (autopilot)."
|
||||
release-notes: https://github.com/lightningnetwork/lnd/releases/tag/v0.11.1-beta
|
||||
ports:
|
||||
- internal: 8080
|
||||
tor: 8080
|
||||
- internal: 9735
|
||||
tor: 9735
|
||||
- internal: 9911
|
||||
tor: 9911
|
||||
- internal: 10009
|
||||
tor: 10009
|
||||
image:
|
||||
type: tar
|
||||
mount: /root/.lnd
|
||||
public: public
|
||||
has-instructions: true
|
||||
os-version-required: ">=0.2.8"
|
||||
os-version-recommended: ">=0.2.8"
|
||||
install-alert: |
|
||||
READ CAREFULLY! LND and the Lightning Network are considered beta software. Please use with caution and do not risk more money than you are willing to lose. We encourage frequent backups. If for any reason, you need to restore LND from a backup, your on-chain wallet will be restored, but all your channels will be closed and their funds returned to your on-chain wallet, minus fees. It may also take some time for this process to occur.
|
||||
uninstall-alert: "READ CAREFULLY! Uninstalling LND will result in permanent loss of data, including its private keys for its on-chain wallet and all channel states. Please make a backup if you have any funds in your on-chain wallet or in any channels. Recovering from backup will restore your on-chain wallet, but due to the architecture of the Lightning Network, your channels cannot be recovered. All your channels will be closed and their funds returned to your on-chain wallet, minus fees. \n"
|
||||
restore-alert: |
|
||||
Restoring LND will overwrite its current data, including its on-chain wallet and channels. Any channels opened since the last backup will be forgotten and may linger indefinitely, and channels contained in the backup will be closed and their funds returned to your on-chain wallet, minus fees.
|
||||
assets: []
|
||||
hidden-service-version: v3
|
||||
dependencies:
|
||||
btc-rpc-proxy:
|
||||
version: "^0.2.4"
|
||||
optional: Can alternatively configure an external bitcoin node.
|
||||
description: Used to fetch validated blocks.
|
||||
config:
|
||||
- rule: '''users.*.name = "lnd"'
|
||||
description: 'Must have an RPC user named "lnd"'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: "users"
|
||||
value:
|
||||
name: lnd
|
||||
allowed-calls: []
|
||||
- SET:
|
||||
var: 'users.[first(item => ''item.name = "lnd")].password'
|
||||
to-entropy:
|
||||
charset: "a-z,A-Z,0-9"
|
||||
len: 22
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getinfo"'
|
||||
description: 'RPC user "lnd" must have "getinfo" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getinfo"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getbestblockhash"'
|
||||
description: 'RPC user "lnd" must have "getbestblockhash" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getbestblockhash"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "gettxout"'
|
||||
description: 'RPC user "lnd" must have "gettxout" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "gettxout"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getblockchaininfo"'
|
||||
description: 'RPC user "lnd" must have "getblockchaininfo" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getblockchaininfo"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "sendrawtransaction"'
|
||||
description: 'RPC user "lnd" must have "sendrawtransaction" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "sendrawtransaction"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getblockhash"'
|
||||
description: 'RPC user "lnd" must have "getblockhash" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getblockhash"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getblock"'
|
||||
description: 'RPC user "lnd" must have "getblock" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getblock"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getblockheader"'
|
||||
description: 'RPC user "lnd" must have "getblockheader" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getblockheader"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "estimatesmartfee"'
|
||||
description: 'RPC user "lnd" must have "estimatesmartfee" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "estimatesmartfee"
|
||||
- rule: '''users.[first(item => ''item.name = "lnd")].allowed-calls.* = "getnetworkinfo"'
|
||||
description: 'RPC user "lnd" must have "getnetworkinfo" enabled'
|
||||
suggestions:
|
||||
- PUSH:
|
||||
to: 'users.[first(item => ''item.name = "lnd")].allowed-calls'
|
||||
value: "getnetworkinfo"
|
||||
- rule: 'users.[first(item => ''item.name = "lnd")].fetch-blocks?'
|
||||
description: 'RPC user "lnd" must have "Fetch Blocks" enabled'
|
||||
suggestions:
|
||||
- SET:
|
||||
var: 'users.[first(item => ''item.name = "lnd")].fetch-blocks'
|
||||
to-value: true
|
||||
bitcoind:
|
||||
version: "^0.21.0"
|
||||
optional: Can alternatively configure an external bitcoin node.
|
||||
description: Used to subscribe to new block events.
|
||||
config:
|
||||
- rule: "zmq-enabled?"
|
||||
description: "Must have an ZeroMQ enabled"
|
||||
suggestions:
|
||||
- SET:
|
||||
var: "zmq-enabled"
|
||||
to-value: true
|
||||
|
||||
Cups
|
||||
....
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
compat: v0
|
||||
id: cups
|
||||
version: "0.3.6"
|
||||
title: "Cups Messenger"
|
||||
description:
|
||||
short: "Real private messaging"
|
||||
long: "Cups is a private, self-hosted, peer-to-peer, Tor-based, instant messenger. Unlike other end-to-end encrypted messengers, with Cups on the Embassy there are no trusted third parties."
|
||||
release-notes: |
|
||||
Features
|
||||
- Adds instructions defined by EmbassyOS 0.2.4 instructions feature
|
||||
ports:
|
||||
- internal: 59001
|
||||
tor: 59001
|
||||
- internal: 80
|
||||
tor: 80
|
||||
image:
|
||||
type: tar
|
||||
mount: /root
|
||||
has-instructions: true
|
||||
os-version-required: ">=0.2.4"
|
||||
os-version-recommended: ">=0.2.4"
|
||||
assets:
|
||||
- src: httpd.conf
|
||||
dst: "."
|
||||
overwrite: true
|
||||
- src: www
|
||||
dst: "."
|
||||
overwrite: true
|
||||
hidden-service-version: v3
|
||||
|
||||
.. role:: raw-html(raw)
|
||||
:format: html
|
||||
|
||||
:raw-html:`<br />`
|
||||
@@ -11,16 +11,3 @@ Please follow the guide `here <https://github.com/Start9Labs/embassy-os/blob/mas
|
||||
Do I need to be a professional developer or have coding experience to contribute?
|
||||
---------------------------------------------------------------------------------
|
||||
Absolutely not! Contributions can be as simple as finding a typo in our docs, making a suggestion on GitHub, creating educational or promotional content, and the list goes on! Everyone that wants to contribute can do so in some unique way. Please don't hesitate to :ref:`Contact <contact>` us for ideas if you're not sure where to begin.
|
||||
|
||||
|
||||
|
||||
.. Expound the following into FAQs:
|
||||
.. --------------------------------
|
||||
|
||||
.. - Release notes need to be in quotations? As it is a string? (they aren’t by default) – this is a yaml thing and SOMETIMES they are required and SOMETIMES NOT
|
||||
.. - Alerts in LND example are not wrapped in quotes, same with CUPS release notes – yaml thing
|
||||
.. - Ports in manifest – can leave as default (80), as it is a docker container?? - Sure
|
||||
|
||||
.. - Type definitions – is this just for dependencies? Can a blurb be added here for extra clarity?
|
||||
.. - Config spec – Admin pass?
|
||||
|
||||
@@ -39,10 +39,6 @@ How can my service access the data directory of another service?
|
||||
|
||||
Check out `LND <https://github.com/Start9Labs/lnd-wrapper/blob/master/manifest.yaml>`_ and `RTL <https://github.com/Start9Labs/ride-the-lightning-wrapper/blob/master/manifest.yaml>`_ as an example.
|
||||
|
||||
The guide says that a Makefile is optional, why is this?
|
||||
--------------------------------------------------------
|
||||
The ``Makefile`` simplifies the development process by putting all your build steps into one place so that you can simply use the ``make`` to build with. A ``Makefile`` is not required however, and you may instead choose to use something like ``nix``, ``bash``, ``perl``, ``python``, or ``ruby`` for your build orchestration.
|
||||
|
||||
Why am I getting the error "No rule to make target yq, needed by manifest.yaml?"
|
||||
--------------------------------------------------------------------------------
|
||||
This is the message you get when you're missing the executable on your ``$PATH``.
|
||||
This is the message you get when you're missing the yq executable on your ``$PATH``. You can find details to `install yq here <https://github.com/mikefarah/yq#install>`_.`
|
||||
Reference in New Issue
Block a user