Skip to content

virt.herorun2 #

HeroRun - Remote Container Management

A V library for managing remote containers using runc and tmux, with support for multiple cloud providers.

Features

  • Multi-provider support: Currently supports Hetzner, with ThreeFold coming soon
  • Automatic setup: Installs required packages (runc, tmux, curl, xz-utils) automatically
  • Container isolation: Uses runc for lightweight container management
  • tmux integration: Each container gets its own tmux session for multiple concurrent shells
  • Clean API: Simple interface that hides infrastructure complexity

Project Structure

lib/virt/herorun/

Usage

Basic Example

import incubaid.herolib.virt.herorun

// Create user with SSH key
mut user := herorun.new_user(keyname: 'id_ed25519')!

// Create Hetzner backend
mut backend := herorun.new_hetzner_backend(
    node_ip: '65.21.132.119'
    user:    'root'
)!

// Connect to node (installs required packages automatically)
backend.connect(keyname: user.keyname)!

// Send a test command to the node
backend.send_command(cmd: 'ls')!

// Get or create container (uses tmux behind the scenes)
mut container := backend.get_or_create_container(name: 'test_container')!

// Attach to container tmux session
container.attach()!

// Send command to container
container.send_command(cmd: 'ls')!

// Get container logs
logs := container.get_logs()!
println('Container logs:')
println(logs)

Running the Example

##chmod +x examples/virt/herorun/herorun.vsh

##./examples/virt/herorun/herorun.vsh

Architecture

Interfaces

  • NodeBackend: Defines operations for connecting to and managing remote nodes
  • ContainerBackend: Defines operations for container lifecycle management

Providers

  • HetznerBackend: Implementation for Hetzner cloud servers
  • ThreeFoldBackend: (Coming soon) Implementation for ThreeFold nodes

Key Components

  1. SSH Integration: Uses herolib's sshagent module for secure connections
  2. tmux Management: Uses herolib's tmux module for session management
  3. Container Runtime: Uses runc for lightweight container execution
  4. Hetzner Integration: Uses herolib's hetznermanager module

Dependencies

  • incubaid.herolib.osal.sshagent
  • incubaid.herolib.osal.tmux
  • incubaid.herolib.installers.web.hetznermanager
  • incubaid.herolib.ui.console

Future Enhancements

  • ThreeFold backend implementation
  • Support for additional cloud providers (AWS, GCP, etc.)
  • Container image management
  • Network configuration
  • Volume mounting
  • Resource limits and monitoring

fn install_all_requirements #

fn install_all_requirements(node_ip string, user string) !

Install all required packages for herorun

fn install_curl #

fn install_curl(node_ip string, user string) !

Install curl for downloading files

fn install_git #

fn install_git(node_ip string, user string) !

Install git for version control

fn install_runc #

fn install_runc(node_ip string, user string) !

Install runc container runtime

fn install_tar #

fn install_tar(node_ip string, user string) !

Install tar for archive extraction

fn install_tmux #

fn install_tmux(node_ip string, user string) !

Install tmux terminal multiplexer

fn new_backend #

fn new_backend(provider Provider, args NewNodeArgs) !NodeBackend

Factory function to create appropriate backend

fn new_executor #

fn new_executor(args ExecutorArgs) !Executor

Create new executor with proper module integration

fn new_hetzner_backend #

fn new_hetzner_backend(args NewNodeArgs) !HetznerBackend

Create new Hetzner backend

fn new_hetzner_node #

fn new_hetzner_node(args NewNodeArgs) !NodeBackend

Convenience function for Hetzner (most common case)

fn new_node #

fn new_node(args NewNodeArgs) Node

Create new node

fn new_user #

fn new_user(args NewUserArgs) !UserConfig

Create new user with SSH agent setup

interface ContainerBackend #

interface ContainerBackend {
mut:
	// Attach to container tmux session
	attach() !

	// Send command to container
	send_command(args ContainerCommandArgs) !

	// Get container logs
	get_logs() !string
}

ContainerBackend defines container operations

interface NodeBackend #

interface NodeBackend {
mut:
	// Connect to the node and ensure required packages
	connect(args NodeConnectArgs) !

	// Send command to the node
	send_command(args SendCommandArgs) !

	// Container lifecycle
	get_or_create_container(args NewContainerArgs) !Container

	// Get node information
	get_info() !NodeInfo
}

NodeBackend defines the contract that all node providers must follow

enum BaseImage #

enum BaseImage {
	alpine        // Standard Alpine Linux minirootfs
	alpine_python // Alpine Linux with Python 3 pre-installed
}

Base image types for containers

enum Provider #

enum Provider {
	hetzner
	threefold
}

Provider types

struct Container #

struct Container {
pub:
	name string
	node Node
pub mut:
	tmux tmux.Tmux
}

Container struct and related functionality

fn (Container) attach #

fn (mut c Container) attach() !

Implement ContainerBackend interface for Container

fn (Container) send_command #

fn (mut c Container) send_command(args ContainerCommandArgs) !

fn (Container) get_logs #

fn (mut c Container) get_logs() !string

struct ContainerCommandArgs #

@[params]
struct ContainerCommandArgs {
pub:
	cmd string @[required]
}

struct Executor #

struct Executor {
pub mut:
	node         Node
	container_id string
	image_script string
	base_image   BaseImage
	tmux         tmux.Tmux
	session_name string
	window_name  string
	agent        sshagent.SSHAgent
}

Executor - Optimized for AI agent usage with proper module integration

fn (Executor) setup #

fn (mut e Executor) setup() !

Setup - Create container and tmux infrastructure using proper modules

fn (Executor) execute #

fn (mut e Executor) execute(cmd string) !string

Execute - Fast command execution using osal module

fn (Executor) execute_tmux #

fn (mut e Executor) execute_tmux(cmd string, context_id string) !string

Execute with tmux - for interactive sessions

fn (Executor) get_or_create_container #

fn (mut e Executor) get_or_create_container(args NewContainerArgs) !Container

Get or create container with optional image script

fn (Executor) cleanup #

fn (mut e Executor) cleanup() !

Cleanup - Remove everything using proper modules

struct ExecutorArgs #

@[params]
struct ExecutorArgs {
pub:
	node_ip      string @[required]
	user         string @[required]
	container_id string @[required]
	keyname      string @[required]
	image_script string // Optional entry point script
	base_image   BaseImage = .alpine // Base image type (default: alpine)
}

struct HetznerBackend #

struct HetznerBackend {
pub mut:
	node Node
}

HetznerBackend implements NodeBackend for Hetzner cloud servers

fn (HetznerBackend) connect #

fn (mut h HetznerBackend) connect(args NodeConnectArgs) !

Implement NodeBackend interface

fn (HetznerBackend) send_command #

fn (h HetznerBackend) send_command(args SendCommandArgs) !

fn (HetznerBackend) get_or_create_container #

fn (mut h HetznerBackend) get_or_create_container(args NewContainerArgs) !Container

fn (HetznerBackend) get_info #

fn (h HetznerBackend) get_info() !NodeInfo

struct NewContainerArgs #

@[params]
struct NewContainerArgs {
pub:
	name         string @[required]
	image_script string // Optional path to entry point script (e.g., './images/python_server.sh')
	base_image   BaseImage = .alpine // Base image type (default: alpine)
}

struct NewNodeArgs #

@[params]
struct NewNodeArgs {
pub:
	node_ip string
	user    string
}

struct NewUserArgs #

@[params]
struct NewUserArgs {
pub:
	keyname string @[required]
}

struct Node #

struct Node {
pub:
	settings NodeSettings
}

struct NodeConnectArgs #

@[params]
struct NodeConnectArgs {
pub:
	keyname string @[required]
}

struct NodeInfo #

struct NodeInfo {
pub:
	ip       string
	user     string
	provider string
	status   string
}

Node information struct

struct NodeSettings #

struct NodeSettings {
pub:
	node_ip string
	user    string
}

Node-related structs and functionality

struct SendCommandArgs #

@[params]
struct SendCommandArgs {
pub:
	cmd string @[required]
}

Shared parameter structs used across the module

struct UserConfig #

struct UserConfig {
pub:
	keyname string
}

User configuration for SSH