archy/neode-ui/PACKAGING_S9PK_GUIDE.md
2026-01-24 22:59:20 +00:00

8.5 KiB

Packaging Apps for Neode/StartOS

This guide explains how to package containerized applications (like nostrdevs/atob) as .s9pk files for installation on Neode.

What is an S9PK?

An .s9pk file is a package format for Neode/StartOS that contains:

  • Manifest (metadata, dependencies, interfaces)
  • Docker Images (your containerized app)
  • Icon (PNG/WEBP/JPG)
  • License (LICENSE.md)
  • Instructions (INSTRUCTIONS.md)
  • Configuration (optional config.yaml)
  • Actions (optional scripts for user actions)

Prerequisites

  1. Install StartOS SDK (needed for packing):

    # Clone the Neode repo (you already have this)
    cd /Users/tx1138/Code/Neode
    
    # Build the SDK
    cd core
    cargo build --release --bin startos
    
    # The binary will be at: target/release/startos
    
  2. Docker for building container images

Creating an S9PK for nostrdevs/atob

Step 1: Create Package Directory Structure

mkdir -p ~/atob-package
cd ~/atob-package

Create the following structure:

atob-package/
├── manifest.yaml          # Package metadata
├── LICENSE.md             # License file
├── INSTRUCTIONS.md        # User instructions
├── icon.png              # 512x512 icon
├── docker_images/        # Docker image archive
│   └── aarch64.tar       # or x86_64.tar
└── scripts/
    └── procedures/
        └── main.ts       # Main entry point

Step 2: Create manifest.yaml

id: atob
title: "ATOB"
version: "0.1.0"
release-notes: "Initial release"
license: MIT
wrapper-repo: "https://github.com/nostrdevs/atob"
upstream-repo: "https://github.com/nostrdevs/atob"
support-site: "https://github.com/nostrdevs/atob/issues"
marketing-site: "https://github.com/nostrdevs/atob"
donation-url: null
description:
  short: "ATOB - A containerized application for Nostr"
  long: |
    ATOB is a containerized application designed for the Nostr ecosystem.
    This package runs ATOB on your Neode server with automatic configuration.

# Assets
assets:
  license: LICENSE.md
  icon: icon.png
  instructions: INSTRUCTIONS.md
  docker-images: docker_images

# Main container
main:
  type: docker
  image: main
  entrypoint: "docker_entrypoint.sh"
  args: []
  mounts:
    main: /data

# Volumes
volumes:
  main:
    type: data

# Interfaces (exposed services)
interfaces:
  main:
    name: Web Interface
    description: Main ATOB web interface
    tor-config:
      port-mapping:
        80: "80"
    lan-config:
      443:
        ssl: true
        internal: 80
    ui: true
    protocols:
      - tcp
      - http

# Health checks
health-checks:
  web-ui:
    name: Web Interface
    success-message: "ATOB is ready!"
    type: docker
    image: main
    entrypoint: "check-web.sh"
    args: []
    io-format: yaml
    inject: true

# Configuration (optional)
config: ~

# Properties
properties: ~

# Dependencies
dependencies: {}

# Backup configuration
backup:
  create:
    type: docker
    image: compat
    system: true
    entrypoint: compat
    args:
      - duplicity
      - create
      - /mnt/backup
      - /data
    mounts:
      BACKUP: /mnt/backup
      main: /data
  restore:
    type: docker
    image: compat
    system: true
    entrypoint: compat
    args:
      - duplicity
      - restore
      - /mnt/backup
      - /data
    mounts:
      BACKUP: /mnt/backup
      main: /data

# Migrations (for updates)
migrations:
  from:
    "*":
      type: none
  to:
    "*":
      type: none

Step 3: Create LICENSE.md

Copy your project's license or create a simple one:

# MIT License

Copyright (c) 2025 Nostr Devs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction...

Step 4: Create INSTRUCTIONS.md

# ATOB Instructions

## Getting Started

1. After installation, ATOB will be available at the interface URL
2. Access it through the Neode dashboard
3. Configuration is automatic

## Usage

[Add specific instructions for your app]

## Support

For issues, visit: https://github.com/nostrdevs/atob/issues

Step 5: Add an Icon

Create or download a 512x512 PNG icon and save it as icon.png

Step 6: Export Docker Image

# Build your Docker image
cd /path/to/atob
docker build -t atob:latest .

# Save the image
mkdir -p ~/atob-package/docker_images
docker save atob:latest -o ~/atob-package/docker_images/$(uname -m).tar

# The filename should match your architecture:
# - x86_64.tar for Intel/AMD
# - aarch64.tar for ARM64/Apple Silicon

Step 7: Create scripts/procedures/main.ts

This is the entry point for your service:

import { types as T, matches, YAML } from "../deps.ts";

// This is the main entry point for your service
export const main: T.ExpectedExports.main = async (effects: T.Effects) => {
  return await effects.createContainer({
    image: "main",
    entrypoint: ["/bin/sh"],
    mounts: {
      main: "/data",
    },
  });
};

// Properties that will be displayed in the UI
export const properties: T.ExpectedExports.properties = async (
  effects: T.Effects
) => {
  return {
    version: "0.1.0",
    "Automatic TOR Address": {
      type: "string",
      value: effects.interfaces.main.torAddress,
      qr: true,
      copyable: true,
      masked: false,
    },
  };
};

// Health check
export const health: T.ExpectedExports.health = async (effects: T.Effects) => {
  return await effects.health.checkWebUrl("http://main.embassy:80");
};

Step 8: Build the S9PK

# Navigate to your package directory
cd ~/atob-package

# Use the StartOS CLI to pack it
/Users/tx1138/Code/Neode/core/target/release/startos pack

# This will create: atob.s9pk

Step 9: Install on Neode

Option A: Via CLI (Direct)

# Copy the .s9pk to your Neode server
scp atob.s9pk user@neode-server:/tmp/

# SSH into the server
ssh user@neode-server

# Install using CLI
startos package.sideload /tmp/atob.s9pk

Option B: Via UI (Once Marketplace is Connected)

  1. Navigate to Marketplace in Neode UI
  2. Click "Sideload Package"
  3. Upload atob.s9pk
  4. Wait for installation to complete

Testing Your Package

Validate Before Installing

# Inspect the package without installing
/Users/tx1138/Code/Neode/core/target/release/startos inspect atob.s9pk

Development Workflow

  1. Make changes to your manifest or scripts
  2. Rebuild the s9pk: startos pack
  3. Uninstall old version: startos package.uninstall atob
  4. Install new version: startos package.sideload atob.s9pk

Advanced Features

Adding Configuration Options

Add to manifest.yaml:

config:
  get:
    type: script
  set:
    type: script

# Then create scripts/procedures/getConfig.ts and setConfig.ts

Adding User Actions

actions:
  restart-service:
    name: "Restart Service"
    description: "Manually restart the ATOB service"
    warning: "This will temporarily interrupt service"
    allowed-statuses:
      - running
    implementation:
      type: docker
      image: main
      entrypoint: "restart.sh"

Multi-Architecture Support

Build for multiple architectures:

# Build for x86_64
docker buildx build --platform linux/amd64 -t atob:amd64 .
docker save atob:amd64 -o docker_images/x86_64.tar

# Build for ARM64
docker buildx build --platform linux/arm64 -t atob:arm64 .
docker save atob:arm64 -o docker_images/aarch64.tar

Resources

  • StartOS Package Manifest Schema: Official Docs
  • Example Packages: /Users/tx1138/Code/Neode/core/startos/test/
  • SDK Reference: Built binaries in core/target/release/

Troubleshooting

Package Won't Install

  • Check manifest syntax: yamllint manifest.yaml
  • Verify docker image exists: tar -tzf docker_images/aarch64.tar | head
  • Check logs on server: journalctl -u startos -f

Service Won't Start

  • Check container logs: docker logs $(docker ps -a | grep atob | awk '{print $1}')
  • Verify entrypoint script exists and is executable
  • Check volume mounts in manifest

Interface Not Accessible

  • Verify port mappings in interfaces section
  • Check that your container is listening on the correct port
  • Wait for TOR address generation (can take 2-3 minutes)

Quick Reference

# Pack a package
startos pack

# Inspect a package
startos inspect atob.s9pk

# Install (CLI)
startos package.sideload atob.s9pk

# List installed packages
startos package.list

# Uninstall
startos package.uninstall atob

# Check package status
startos package.properties atob