Skip to main content
Version: v3.9.0

Bootstrap

potctl installs Edgelet with embedded shell layers. The layers are staged under a transient directory and run in a fixed order. Go-side configuration and provisioning follow the scripts. potctl does not call an upstream monolith install.sh as the whole install.

Both site flavors use the same layers. apiVersion, image registry, and banner strings follow the flavor. Align tags with control plane v3.9.0 and Edgelet v1.1.0. See Edgelet nodes.

This page covers remote Agent, LocalAgent, and the system Edgelet node prepared during control plane deploy. Scripts on a node live at spec.scripts. Control plane hosts use controllers[].systemAgent.scripts or spec.systemAgent.scripts.

Platform and deployment matrix​

Host OS​

ContextHow the OS is determined
Remote Agent or control plane system nodeSSH uname -s, normalized to linux, darwin, or windows on first bootstrap
LocalAgent or local control planeOS of the machine running potctl

Remote deploy assumes SSH. Windows hosts use Windows path conventions inside scripts. Scripts are still staged to /tmp/edgelet-scripts over SSH.

Deployment combinations​

Host OSDeploy kinddeploymentTypeTypical useBootstrap runner
linuxRemote Agent, control plane system nodenativeProduction Edgelet nodesSSH and sudo env
linuxRemote Agent, control plane system nodecontainerDocker or Podman on the hostSSH and sudo env
linux, darwin, windowsLocalAgent, local control planenativeLocal Edgelet binaryLocal sh -c (sudo on native Linux)
darwin, windowsLocalAgent, local control planecontainerDesktop development with DockerLocal shell, no sudo

Defaults when omitted: deploymentType: native, containerEngine: edgelet.

Paths​

OSEdgelet binaryConfig directoryConfig fileScript share dir after bundled.sh
linux/usr/local/bin/edgelet/etc/edgelet/etc/edgelet/config.yaml/usr/share/edgelet
darwin/usr/local/bin/edgelet/etc/edgelet/etc/edgelet/config.yaml/usr/local/share/edgelet
windows%ProgramFiles%\Edgelet\edgelet.exe%ProgramData%\Edgelet\config…\config\config.yaml%ProgramData%\Edgelet\scripts

Staging directory on every platform: /tmp/edgelet-scripts.

WASM shim staging, when enabled: /tmp/edgelet-scripts/wasm/.

When installation runs​

Installation splits into bootstrap (scripts plus config materialization) and provision (edgelet config and edgelet provision).

Parse YAML
-> defaults for local or remote Edgelet
-> optional script merge
-> airgap and WASM prep when enabled
-> Bootstrap: stage scripts, pre-install, write config, post-install, bundled, WASM RuntimeClass
-> AgentConfig when spec.config is set
-> edgelet config / edgelet provision
Deploy targetBootstrapProvisionWhere scripts lives
Remote AgentDuring deploy -fSame deploy, after bootstrapspec.scripts
LocalAgentDuring local deploySame deploy, after bootstrapspec.scripts
Remote control plane, each controller hostWhile that host is preparedLater, when the system node is registeredcontrollers[].systemAgent.scripts
Local control planeWhile the local host is preparedLater, when the local system node is registeredsystemAgent.scripts

Edgelet on a control plane host is bootstrapped when that host is prepared. The system-node step that follows only pushes AgentConfig and runs provision. It does not bootstrap again.

isSystem: true changes system-node defaults (router role, port checks, quieter progress). It does not change script merge or execution.

Default bootstrap pipeline​

When scripts is omitted, or an entrypoint is left empty, potctl embeds and runs the full bundle.

#StepScript or CLIPurposeSkip notes
0Stage scriptsCLIWrite the bundle to /tmp/edgelet-scriptsRemote: copy and install -m 755. Local: write files.
0bPrepare WASMCLIResolve and extract shim binaries, set envSkipped unless WASM scope allows
1Prerequisitescheck_prereqs.shRemote: passwordless sudo probeLocal exits 0 immediately (LOCAL_INSTALL=1)
2Detect initdetect_init.shOS, architecture, init systemAlways runs
3Dependenciesinstall_deps.shInstall or check Docker or PodmanNo-op when containerEngine is edgelet. On darwin and windows, engine configure is skipped.
3bConfigure engineconfigure_container_engine.shEngine socket, groups, serviceOnly when the deps layer runs (not the edgelet engine)
4Install Edgeletinstall.sh or install_container.shBinary install or container prepNative uses install.sh with --skip-config and --skip-start. Container uses install_container.sh.
5WASM runtimesinstall_wasm_runtimes.shInstall pre-staged shims to /usr/local/binOmitted unless WASM scope allows. Also a no-op on non-Linux or container deploy.
Write configCLIWrite config.yaml and a sample CA if missingSkipped on desktop container local
6Init unitsinstall_init_units.shsystemd, OpenRC, or procd unitsLinux-focused. Desktop paths differ.
7Startstart_edgelet.shEnable and start the daemon or container unitDesktop native darwin starts a background daemon. Windows native is platform-specific.
8Configure containerconfigure_container_edgelet.shApply config inside the running containerDesktop container only. Exits 0 otherwise.
9Wait readywait_edgelet_ready.shPoll until the Edgelet API is readyDesktop container uses an alternate wait.
RuntimeClassCLIApply WASM RuntimeClass manifestsOnly when WASM handlers are configured
10Bundled publishbundled.shCopy scripts to the OS share directorySkipped on desktop container local
ProvisionCLIedgelet config, optional cert, edgelet provisionAfter bootstrap in the deploy flow

WASM runtime scope​

WASM install runs only when all of the following hold:

RequirementValue
Host OSlinux only
deploymentTypenative (not container)
containerEngineedgelet or docker (not podman)
package.wasmAt least one handler configured

If package.wasm is set and scope fails, potctl prints a skip message and continues.

WASM artifacts are extracted on the CLI machine. They are not unpacked with tar on the remote host. Remote deploy copies raw shim binaries into the WASM staging directory.

Default install arguments​

Native install.sh receives:

  • --version=<edgelet version>
  • --container-engine=<engine>
  • --skip-config and --skip-start (config and start are separate layers)
  • Optional --arch=, --airgap, and --bin-path= for airgap

Container install_container.sh receives:

  • --image=<container image>
  • --engine=docker or --engine=podman
  • --tz=<timezone>

Desktop container​

A local container install on darwin or windows sets desktop container behavior (LOCAL_INSTALL=1, EDGELET_INSTALL_MODE=container, desktop host OS).

BehaviorProduction LinuxDesktop container local
SudoRequired on remote. Local native Linux uses sudo.No sudo
Host config.yaml writeYesSkipped
bundled.shPublishes to the share directoryNo-op. Scripts stay in the stage directory.
configure_container_edgelet.shExits 0Runs the bootstrap config command inside the container
wait_edgelet_ready.shService or API pollDesktop container wait
Extra envStandard bootstrap envStage directory on PATH

Install Docker (or Podman where it is supported) before deploy. potctl does not install container engines unless your custom scripts do.

Embedded scripts​

Top-level scripts​

ScriptRole
check_prereqs.shPasswordless sudo on remote hosts. Skipped locally.
detect_init.shOS, architecture, and init system. Sourced by most other layers.
install_deps.shDocker or Podman when the engine is not edgelet
configure_container_engine.shDocker or Podman socket access. Skipped on darwin and windows.
install.shEdgelet binary, directories, and receipt. Airgap, upgrade, and rollback flags.
install_container.shContainerized Edgelet. Desktop and Linux branches.
install_wasm_runtimes.shStaged WASM shims. Gated by EDGELET_WASM_INSTALL=1.
install_init_units.shInit units for native and container deployments
start_edgelet.shStart or restart the daemon or container unit
configure_container_edgelet.shDesktop container: apply bootstrap config inside the container
wait_edgelet_ready.shWait for the Edgelet API
bundled.shPublish the script bundle to the OS share directory
uninstall.shRemove binary, units, and optional data (--remove-data)

Library scripts​

LibraryProvides
lib/common.shErrors, info, sudo wrapper, desktop container detection
lib/paths.shOS-specific share, config, binary, and runtime paths
lib/receipt.shInstall receipt for upgrade and rollback
lib/binary.shBinary download, checksum, airgap copy
lib/service.shInit helpers to start, stop, and restart Edgelet
lib/container_engine.shEngine detection and defaults
lib/container_cli.shDocker and Podman wrappers
lib/container_mounts.shBind mounts for container deploy

Default install.sh is always invoked with --skip-config and --skip-start. The CLI writes config. start_edgelet.sh owns the start layer.

Bootstrap environment variables​

potctl prefixes every script command with these variables.

VariableMeaning
EDGELET_INSTALL_MODEnative or container
CONTAINER_ENGINEedgelet, docker, or podman
DEPLOYMENT_TYPESame as spec (native by default)
EDGELET_VERSIONBinary or tag version from the package
EDGELET_CONTAINER_IMAGEContainer image when deploymentType is container
EDGELET_TZTimezone. Default UTC.
EDGELET_GITHUB_REPORelease base for binary download
EDGELET_CONTAINER_ENGINE_URLSocket URL for Docker or Podman
LOCAL_INSTALL=1Local bootstrap. Skips the remote sudo check.
EDGELET_SCRIPT_STAGE_DIRStage directory (desktop container)
PATHStage bin prepended on desktop container
EDGELET_BOOTSTRAP_CONFIG_CMDQuoted edgelet config command (desktop container)
EDGELET_WASM_INSTALL=1Set when WASM shims are staged
EDGELET_WASM_MANIFESTJSON manifest of staged WASM binaries
EDGELET_WASM_RESTART_ENGINE=1Hint to restart the engine after shim install

Remote commands use sudo env VAR=… /tmp/edgelet-scripts/….sh so sudo does not strip variables. Local native Linux may wrap with sudo env.

Scripts block​

scripts
scripts:
dir: /path/to/scripts
deps:
entrypoint: install_deps.sh
args:
- docker
- native
install:
entrypoint: install.sh
args:
- "--version=1.1.0"
- "--skip-config"
- "--skip-start"
uninstall:
entrypoint: uninstall.sh
args:
- "--remove-data"
FieldRequiredDescription
dirYes, if the block is presentDirectory on the operator machine. potctl reads files locally, then stages them.
*.entrypointNoFilename relative to the staged script root. Empty means the embedded default for that layer.
*.argsNoArguments appended to the entrypoint

Only deps, install, and uninstall are overridable. detect_init, install_init_units, start_edgelet, configure_container_edgelet, wait_edgelet_ready, and bundled always use the embedded script names. YAML cannot point those layers at a different entrypoint name.

ResourceYAML path
Remote Agentspec.scripts
LocalAgentspec.scripts
Remote control plane system nodecontrollers[].systemAgent.scripts
Local control plane system nodesystemAgent.scripts
remote-agent-scripts.yaml
apiVersion: datasance.com/v3
kind: Agent
metadata:
name: edge-node-1
spec:
host: 10.0.0.5
ssh:
user: ubuntu
keyFile: ~/.ssh/id_rsa
package:
version: "1.1.0"
config:
arch: amd64
deploymentType: native
containerEngine: edgelet
scripts:
dir: ./my-edgelet-scripts
install:
entrypoint: install.sh
args:
- "--version=1.1.0"
- "--skip-config"
- "--skip-start"

Script merge​

Remote and local deploys use the same merge rules.

  1. Read every non-directory file from scripts.dir into the stage list.
  2. Always append embedded check_prereqs.sh. A same-named file from dir is overwritten when staged.
  3. For each overridable layer, an empty entrypoint embeds the default scripts. A set entrypoint uses your script for that layer.
  4. Fill missing post-install entrypoints from defaults (names and destination paths).
  5. Bind destination paths under /tmp/edgelet-scripts.
  6. If scripts.install.entrypoint is set, the install is custom.
LayerYAML keyEmpty entrypointSet entrypoint
Prerequisites(none)Embedded check_prereqs.sh is always appendedSame. Always embedded.
Detect init(none)Embedded file in the default bundleThe command still runs the embedded name. The file must exist in dir if the install bundle is not embedded.
Depsscripts.depsEmbed install_deps.sh and configure_container_engine.shYour script only. Embedded deps are not added.
Installscripts.installEmbed the install bundle and all lib/*.shCustom install. The install bundle and libs are not embedded.
WASM(none)Included in the default install bundleIf install is custom, the file must be in dir.
Post-install (init, start, configure, wait, bundled)(none)Embedded in the default bundleCommands still run. Files must be in dir when install was custom.
Uninstallscripts.uninstallEmbed uninstall.shYour script. Embedded uninstall is not added.

When scripts.install.entrypoint is set:

BehaviorDefault installCustom install
potctl applies package.version to install argsYesNo. Pass the version in scripts.install.args.
potctl applies package.container.image to install argsYesNo. Pass image flags in args.
Airgap binary path wiringYesYes
Embedded install.sh, install_container.sh, and lib/* stagedYesNo
Post-install layers executedYesYes, unless your install script fails the deploy

If only scripts.deps.entrypoint is set, your deps script runs, and the embedded install bundle and post-install scripts still run.

If scripts.install.entrypoint is set and the post-install scripts are not in dir, bootstrap fails when those commands run. Copy the required scripts into dir, or do not set a custom install entrypoint.

Staging and execution​

ConceptWhat it is
StagingFiles written to /tmp/edgelet-scripts on the target host
ExecutionOrdered shell commands with the bootstrap environment prefix

Pre-install order:

check_prereqs -> detect_init -> deps -> install -> install_wasm_runtimes when WASM scope allows

Post-install order:

install_init_units -> start_edgelet -> configure_container_edgelet -> wait_edgelet_ready -> bundled

WASM RuntimeClass deploy runs after those four shell layers (install_init_units through wait_edgelet_ready) and immediately before bundled.sh. The order is the same on remote and local hosts.

Remote and local execution​

AspectRemoteLocal
Stage directory/tmp/edgelet-scripts over SSHSame path on the local filesystem
How files landCopy to /tmp, then install -m 755Local write
ShellSSH runs the command stringsh -c
SudoAlways on bootstrap commandsNative Linux: sudo. Desktop container: none.
PrerequisitesPasswordless sudoSkipped (LOCAL_INSTALL=1)
Config writeSSH install when the file is missingCLI writes config.yaml
OS detectionuname -s over SSHOS of the potctl process

Steps scripts cannot replace​

Custom install scripts must cooperate with these steps. Use --skip-config so the CLI can write config.

StepWhenDescription
Airgap binary transferairgap: true, nativeCopy the Edgelet binary. Sets --bin-path on install.
Airgap image transferairgap: trueedgelet image load on the host
WASM extractpackage.wasmExtract on the CLI machine. Remote copy of raw shims.
Write config.yamlAfter pre-install, before post-installHost config and a sample CA when absent
WASM RuntimeClassAfter the post-install shell layers, before bundled.shApply RuntimeClass manifests through Edgelet
AgentConfigDeploy with spec.configController API record
edgelet configProvisionSets the Controller URL. Installs the Controller CA when one is returned.
edgelet provisionProvisionRegisters the Edgelet node
edgelet deploy -fControl plane hostsDeploys translated Registry and ControlPlane manifests
Private registryControl plane with a private controller imageRegistry login plus a Controller registry record

Uninstall and delete​

Uninstall re-stages scripts with the same merge rules, then runs the uninstall entrypoint.

TriggerData removal
Delete an Edgelet node, or tear down a control plane hostuninstall.sh with --remove-data
Detach an Edgelet nodeUninstall does not run. Binaries and data can remain.

Custom uninstall: set scripts.uninstall.entrypoint and optional args. When the entrypoint is set, embedded uninstall.sh is not added. Your script in dir must implement teardown. uninstall.sh handles Linux, darwin, and Windows paths.

See Attach and detach for delete versus detach.

Examples​

Defaults only​

Omit scripts. The full embedded bundle runs. Set config.arch, deploymentType, containerEngine, and package.version or package.container.image.

Directory without entrypoint overrides​

vendor-scripts
scripts:
dir: ./vendor/edgelet-scripts

Files from dir are staged first. Embedded defaults for deps, install, uninstall, and post-install are appended. Use this to vendor scripts while keeping default entrypoints.

Custom deps only​

custom-deps
scripts:
dir: ./scripts
deps:
entrypoint: install_deps.sh
args: ["docker", "native"]

Place install_deps.sh in dir. The embedded install bundle and post-install scripts still run.

Custom install​

custom-install
scripts:
dir: ./scripts
install:
entrypoint: my_install.sh
args:
- "--version=1.1.0"
- "--airgap"
- "--bin-path=/opt/airgap/edgelet-linux-amd64"

dir must include at least detect_init.sh, install_init_units.sh, start_edgelet.sh, configure_container_edgelet.sh, wait_edgelet_ready.sh, bundled.sh, and any lib/*.sh that my_install.sh sources. Pass version and image flags yourself.

All three layers​

all-layers
scripts:
dir: /tmp/my-scripts
deps:
entrypoint: install_deps.sh
install:
entrypoint: install.sh
args: ["1.1.0"]
uninstall:
entrypoint: uninstall.sh

Only check_prereqs.sh is appended from the embed. dir must contain every other script the sequence invokes.

System node on a remote control plane​

system-agent-scripts
controllers:
- name: cp-host-1
host: 10.0.0.10
ssh:
user: ubuntu
keyFile: ~/.ssh/id_rsa
systemAgent:
config:
arch: amd64
deploymentType: native
containerEngine: edgelet
scripts:
dir: ./cp-scripts

Bootstrap runs during control plane host deploy. Provision runs when the system node is registered. The full control plane kind is on Remote.

Airgap with a custom install​

Set airgap: true on the node or control plane. potctl transfers the binary before bootstrap. With a custom install, include the airgap flags in scripts.install.args:

airgap-install-args
scripts:
install:
entrypoint: install.sh
args:
- "--airgap"
- "--bin-path=/tmp/edgelet-linux-amd64"
- "--version=1.1.0"
- "--skip-config"
- "--skip-start"

Local desktop container​

desktop-container.yaml
apiVersion: datasance.com/v3
kind: LocalAgent
spec:
config:
deploymentType: container
containerEngine: docker
package:
container:
image: ghcr.io/datasance/edgelet:1.1.0

Expect no sudo, no host config.yaml, no bundled.sh publish, and the desktop wait and configure paths. Docker must already be installed.

Windows local native​

Use LocalAgent on a Windows machine running potctl. Scripts use %ProgramData% and %ProgramFiles%. Staging still uses /tmp/edgelet-scripts in the shell environment. Confirm init and start paths match that shell.

Troubleshooting​

SymptomLikely causeAction
Post-install script not found after a custom installEmbedded post-install scripts are not staged when install is customAdd the missing scripts to scripts.dir
Version or image ignoredCustom install entrypoint is setPass --version= or --image= in scripts.install.args
install_deps exits immediatelycontainerEngine: edgeletExpected no-op
Remote deploy fails at prerequisitesPasswordless sudo is missingFix sudoers for the SSH user
WASM step skippedScope gate (OS, deployment type, engine)See WASM runtime scope
WASM on macOS never runsWASM is Linux native onlyUse a Linux host for WASM shims
bundled.sh does nothing locallyDesktop container deployExpected. Scripts remain in the stage directory.
Configure container skippedNot a desktop container deployExpected on Linux native and Linux container server deploy
Duplicate script behaviorA file in dir is overwritten by the embedcheck_prereqs.sh always wins. Later duplicates in the stage list overwrite earlier writes.
System node provision fails but Edgelet is installedBootstrap succeeded earlierCheck the Controller endpoint, auth, and provision key separately
Group 3See anything wrong with the document? Help us improve it!