mid coding commit
This commit is contained in:
@@ -0,0 +1,403 @@
|
||||
# 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):
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```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:
|
||||
|
||||
```markdown
|
||||
# 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
|
||||
|
||||
```markdown
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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:
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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)**
|
||||
```bash
|
||||
# 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
|
||||
```bash
|
||||
# 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`:
|
||||
|
||||
```yaml
|
||||
config:
|
||||
get:
|
||||
type: script
|
||||
set:
|
||||
type: script
|
||||
|
||||
# Then create scripts/procedures/getConfig.ts and setConfig.ts
|
||||
```
|
||||
|
||||
### Adding User Actions
|
||||
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```bash
|
||||
# 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](https://docs.start9.com)
|
||||
- **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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user