porterui

package
v0.9.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2026 License: MIT Imports: 44 Imported by: 0

README

Porter UI Backend

This package provides the backend API server for Porter's web-based server management interface.

Overview

The porterui package implements a REST API and WebSocket server that powers the Porter web UI. It provides comprehensive server management capabilities including:

  • Machine Management - Add, edit, and organize remote servers
  • Terminal Access - Interactive SSH terminals via WebSocket
  • File Management - Browse, edit, upload, and download files
  • Service Management - Control systemd services
  • Docker Management - Manage containers and images
  • Log Viewing - Real-time log streaming with journalctl
  • System Monitoring - CPU, memory, disk, and network metrics
  • Script Execution - Run and schedule deployment scripts
  • VNC/Remote Desktop - Remote desktop access via noVNC
  • Backup Management - Scheduled backups and restore
  • Network Tools - Ping, traceroute, DNS lookup, port scanning

Architecture

porterui/
├── router.go          # Route setup and middleware
├── auth.go            # Authentication and JWT handling
├── machines.go        # Machine CRUD and SSH connections
├── terminal.go        # WebSocket terminal sessions
├── files.go           # File browser and editor
├── system.go          # System info and monitoring
├── logs.go            # Log retrieval and streaming
├── docker.go          # Docker container management (in system.go)
├── scheduler.go       # Cron-based job scheduling
├── backup.go          # Backup job management
├── vnc.go             # VNC proxy for remote desktop
└── ...

API Routes

All routes are prefixed with /api/ when authentication is enabled.

Authentication
  • POST /api/auth/login - Login with username/password
  • GET /api/auth/status - Check authentication status
  • POST /api/auth/logout - Logout
Machines
  • GET /api/machines - List all machines
  • POST /api/machines - Add a new machine
  • PUT /api/machines/{id} - Update machine
  • DELETE /api/machines/{id} - Delete machine
  • POST /api/machines/{id}/test - Test SSH connection
Terminal
  • GET /api/terminal/{id} - WebSocket terminal session
Files
  • GET /api/files/{id} - List directory contents
  • GET /api/files/{id}/read - Read file content
  • POST /api/files/{id}/write - Write file content
  • POST /api/files/{id}/upload - Upload file
  • GET /api/files/{id}/download - Download file
System
  • GET /api/system/{id}/info - System information
  • GET /api/system/{id}/services - List systemd services
  • POST /api/system/{id}/services/{name}/{action} - Control service
Logs
  • GET /api/logs/{id} - Get logs with journalctl
  • GET /api/logs/{id}/stream - WebSocket log streaming

Usage

package main

import (
    "net/http"
    "github.com/gorilla/mux"
    "github.com/booyaka101/porter/porterui"
)

func main() {
    r := mux.NewRouter()
    
    // Setup routes with authentication
    porterui.SetupRoutesWithAuth(r)
    
    // Or without authentication
    // porterui.SetupRoutes(r)
    
    http.ListenAndServe(":8080", r)
}

Configuration

The backend uses environment variables and a SQLite/MySQL database for configuration:

  • Machine credentials (encrypted)
  • User accounts
  • Scheduled jobs
  • Custom scripts
  • Bookmarks and history

Security

  • JWT-based authentication
  • Encrypted credential storage
  • SSH key management
  • Audit logging

Documentation

Index

Constants

View Source
const DefaultUIBuildRoot = "build"
View Source
const UserContextKey contextKey = "user"

Variables

View Source
var DefaultUIBuildFS embed.FS
View Source
var EmbeddedScripts embed.FS

EmbeddedScripts will be set from main.go

View Source
var ErrEncryptionNotInitialized = errors.New("encryption not initialized")

Functions

func AddAuditLog

func AddAuditLog(action, category, machineID, machineName string, details map[string]interface{}, success bool, errMsg string)

AddAuditLog adds an entry to the audit log

func AuthMiddleware

func AuthMiddleware(next http.Handler) http.Handler

AuthMiddleware validates JWT tokens and adds user to context

func AuthRoutes

func AuthRoutes(router *mux.Router)

AuthRoutes sets up authentication API routes

func BackupRoutes

func BackupRoutes(r *mux.Router)

BackupRoutes sets up backup management API routes

func BookmarkRoutes

func BookmarkRoutes(r *mux.Router)

BookmarkRoutes sets up bookmark API routes

func BroadcastExecutionUpdate

func BroadcastExecutionUpdate(executionID string, status string, progress int)

BroadcastExecutionUpdate broadcasts an execution status update

func BroadcastMachineStatus

func BroadcastMachineStatus(machineID string, status string)

BroadcastMachineStatus broadcasts a machine status change

func BroadcastNotification

func BroadcastNotification(level string, title string, message string)

BroadcastNotification broadcasts a notification to all clients

func BuildClientRoutes added in v0.9.1

func BuildClientRoutes(r *mux.Router)

BuildClientRoutes sets up build client API routes

func BuildDockerTask

func BuildDockerTask(containerName, action string) porter.Task

BuildDockerTask creates a Porter task for Docker container management

func BuildExecuteManifest

func BuildExecuteManifest(cfg ScriptDeployConfig) []porter.Task

BuildExecuteManifest creates the script execution manifest

func BuildServiceTask

func BuildServiceTask(serviceName, action string, isUser bool) porter.Task

BuildServiceTask creates a Porter task for systemd service management

func BuildSetupManifest

func BuildSetupManifest(cfg ScriptDeployConfig) []porter.Task

BuildSetupManifest creates the directory setup manifest

func BuildUploadManifest

func BuildUploadManifest(cfg ScriptDeployConfig) []porter.Task

BuildUploadManifest creates the file upload manifest

func CheckAllMachines

func CheckAllMachines(machines []*Machine) map[string]*MachineHealth

CheckAllMachines checks health of all machines concurrently

func CheckPassword

func CheckPassword(password, hash string) bool

CheckPassword verifies a password against a hash

func CheckStandaloneAgentStatus

func CheckStandaloneAgentStatus(machine *Machine) bool

CheckStandaloneAgentStatus checks if a standalone agent is running on a machine

func CustomScriptsRoutes

func CustomScriptsRoutes(r *mux.Router)

CustomScriptsRoutes sets up custom script API routes

func DashboardWSRoutes

func DashboardWSRoutes(r *mux.Router)

DashboardWSRoutes sets up WebSocket routes for dashboard updates

func Decrypt

func Decrypt(ciphertext string) (string, error)

Decrypt decrypts ciphertext using AES-GCM

func DecryptPassword

func DecryptPassword(encrypted string) (string, error)

DecryptPassword decrypts a stored password

func DeriveKey

func DeriveKey(passphrase string) []byte

DeriveKey derives a key from a passphrase

func DiffRoutes

func DiffRoutes(r *mux.Router)

DiffRoutes sets up file diff API routes

func Encrypt

func Encrypt(plaintext string) (string, error)

Encrypt encrypts plaintext using AES-GCM

func EncryptPassword

func EncryptPassword(password string) (string, error)

EncryptPassword encrypts a password for storage

func EnsureVNCReady

func EnsureVNCReady(machine *Machine, display string) error

EnsureVNCReady ensures x11vnc is running, enabling/starting service if needed

func ExecuteSSHCommandOnMachine

func ExecuteSSHCommandOnMachine(machine *Machine, command string) (string, error)

ExecuteSSHCommandOnMachine executes a command on a machine via SSH

func ExportMySQLToJSON

func ExportMySQLToJSON(mysqlConfig DBConfig) (map[string]interface{}, error)

ExportMySQLToJSON exports MySQL data to JSON for backup

func ExtractEmbeddedScripts

func ExtractEmbeddedScripts(scriptPath string) (string, error)

ExtractEmbeddedScripts extracts embedded scripts to a temporary directory scriptPath should be the directory containing the scripts (e.g., "embedded-scripts/ubuntu-setup")

func FilesRoutes

func FilesRoutes(r *mux.Router)

FilesRoutes sets up file management API routes

func FirewallAddRuleManifest

func FirewallAddRuleManifest(port, action, protocol string) []porter.Task

func FirewallDisableManifest

func FirewallDisableManifest() []porter.Task

func FirewallEnableManifest

func FirewallEnableManifest() []porter.Task

FirewallManifest returns Porter tasks for firewall management

func GenerateToken

func GenerateToken(user *User, permissions []string) (string, error)

GenerateToken creates a JWT token for a user

func GetConnectedAgentCount

func GetConnectedAgentCount() int

GetConnectedAgentCount returns the number of connected agents

func GetCustomScriptPath

func GetCustomScriptPath() string

GetCustomScriptPath returns the base path for custom scripts

func GetDecryptedPassword

func GetDecryptedPassword(m *Machine) string

GetDecryptedPassword returns the decrypted password for a machine

func GetPooledClient

func GetPooledClient(machine *Machine) (*goph.Client, func(), error)

GetPooledClient is a helper function to get a pooled connection for a machine

func GetRolePermissions

func GetRolePermissions(roleName string) ([]string, error)

GetRolePermissions retrieves permissions for a role

func GetSQLitePath

func GetSQLitePath() string

GetSQLitePath returns the default SQLite database path

func HasPermission

func HasPermission(permissions []string, required string) bool

HasPermission checks if a user has a specific permission

func HashPassword

func HashPassword(password string) (string, error)

HashPassword hashes a password using bcrypt

func HealthCheckManifest

func HealthCheckManifest() []porter.Task

HealthCheckManifest returns the Porter manifest for health checks

func HealthRoutes

func HealthRoutes(r *mux.Router)

HealthRoutes sets up health check API routes

func HistoryRoutes

func HistoryRoutes(r *mux.Router)

HistoryRoutes sets up history API routes

func ImportExportRoutes

func ImportExportRoutes(r *mux.Router)

ImportExportRoutes sets up import/export API routes

func InitAuth

func InitAuth() error

InitAuth initializes the authentication system

func InitBookmarkStore

func InitBookmarkStore() error

InitBookmarkStore initializes the bookmark store

func InitBuildClientStore added in v0.9.1

func InitBuildClientStore() error

InitBuildClientStore initializes the build client store

func InitCustomScripts

func InitCustomScripts() error

InitCustomScripts initializes the custom scripts store

func InitEncryption

func InitEncryption() error

InitEncryption initializes the encryption key

func InitHistoryStore

func InitHistoryStore() error

InitHistoryStore initializes the history store

func InitMySQLDatabase

func InitMySQLDatabase(config DBConfig) error

InitDatabase initializes the MySQL database connection with retry logic

func InitNotifications

func InitNotifications() error

InitNotifications initializes the notification system

func InitSQLiteDatabase

func InitSQLiteDatabase(dbPath string) error

InitSQLiteDatabase initializes a SQLite database connection

func InitScheduler

func InitScheduler() error

InitScheduler initializes the scheduler

func IsAgentConnected

func IsAgentConnected(machineID string) bool

IsAgentConnected checks if an agent is connected for a machine

func IsDangerousCommand

func IsDangerousCommand(cmd string) bool

IsDangerousCommand checks if a command matches dangerous patterns

func IsEncrypted

func IsEncrypted(s string) bool

IsEncrypted checks if a string appears to be encrypted

func IsMySQL

func IsMySQL() bool

IsMySQL returns true if using MySQL database

func IsSQLite

func IsSQLite() bool

IsSQLite returns true if using SQLite database

func LogAudit

func LogAudit(userID, username, action, resourceType, resourceID string, details interface{}, ipAddress string)

LogAudit logs an audit event with deduplication

func LogDebug

func LogDebug(msg string, fields map[string]interface{})

LogDebug logs a debug message with fields

func LogError

func LogError(msg string, fields map[string]interface{})

LogError logs an error message with fields

func LogInfo

func LogInfo(msg string, fields map[string]interface{})

LogInfo logs an info message with fields

func LogWarn

func LogWarn(msg string, fields map[string]interface{})

LogWarn logs a warning message with fields

func LogsRoutes

func LogsRoutes(r *mux.Router)

LogsRoutes sets up log streaming API routes

func MachinesRoutes

func MachinesRoutes(router *mux.Router)

func ManifestRoutes

func ManifestRoutes(r *mux.Router)

ManifestRoutes sets up manifest-related API routes

func MigrateFromJSON

func MigrateFromJSON() error

MigrateFromJSON migrates all data from JSON files to MySQL

func MigrateFromMySQLToSQLite

func MigrateFromMySQLToSQLite(mysqlConfig DBConfig, sqlitePath string) error

MigrateFromMySQLToSQLite migrates all data from MySQL to SQLite

func MultiTerminalRoutes

func MultiTerminalRoutes(r *mux.Router)

MultiTerminalRoutes sets up multi-machine terminal API routes

func NetworkToolsRoutes

func NetworkToolsRoutes(r *mux.Router)

NetworkToolsRoutes sets up network diagnostic API routes

func NotificationRoutes

func NotificationRoutes(r *mux.Router)

NotificationRoutes sets up notification API routes

func NotifyBatchComplete

func NotifyBatchComplete(scriptName string, total, success, failed int)

NotifyBatchComplete sends a notification for batch execution

func NotifyExecutionComplete

func NotifyExecutionComplete(result ExecutionResult, scriptName string)

NotifyExecutionComplete sends a notification for script execution

func NowFunc

func NowFunc() string

NowFunc returns the current time formatted for the database

func PackageInstallManifest

func PackageInstallManifest(packages string) []porter.Task

PackageManifest returns a Porter manifest for package management

func PackageRemoveManifest

func PackageRemoveManifest(packages string) []porter.Task

func PackageUpgradeManifest

func PackageUpgradeManifest() []porter.Task

func RecordExecution

func RecordExecution(result ExecutionResult, scriptPath, args, presetName string)

RecordExecution creates a history record from an execution result

func ReloadMachineRepo

func ReloadMachineRepo()

ReloadMachineRepo reloads machines from database after DB is initialized

func RequirePermission

func RequirePermission(permission string) func(http.Handler) http.Handler

RequirePermission middleware checks for specific permission

func Run

func Run(config RunConfig)

Run starts Porter with the given configuration. Wrappers should call this after setting EmbeddedScripts and ScriptDiscoveryConfig.

Example wrapper:

package main

import (
    "embed"
    "github.com/booyaka101/porter/porterui"
)

//go:embed embedded-scripts/*
var scripts embed.FS

//go:embed build/*
var ui embed.FS

func main() {
    porterui.EmbeddedScripts = scripts
    porterui.SetScriptDiscoveryConfig(&porterui.ScriptDiscoveryConfig{
        EmbeddedRoot: "embedded-scripts",
        TopLevelScripts: map[string]bool{"setup.sh": true},
    })
    porterui.Run(porterui.RunConfig{UIBuildFS: ui})
}

func RunPorterCommand

func RunPorterCommand(client *goph.Client, password, taskName, command string) error

RunPorterCommand executes a single Porter Run task (no output capture)

func RunPorterManifest

func RunPorterManifest(client *goph.Client, password, manifestName string, tasks []porter.Task) (*porter.Stats, error)

RunPorterManifest executes a full Porter manifest with multiple tasks

func RunPorterManifestWithVars

func RunPorterManifestWithVars(client *goph.Client, password, manifestName string, tasks []porter.Task, vars *porter.Vars) (*porter.Stats, error)

RunPorterManifestWithVars executes a Porter manifest with custom variables

func RunPorterSudoCommand

func RunPorterSudoCommand(client *goph.Client, password, taskName, command string) error

RunPorterSudoCommand executes a command with sudo using Porter's Run task

func RunPorterTask

func RunPorterTask(client *goph.Client, password, taskName, command, registerVar string) (string, error)

RunPorterTask executes a single Porter task and returns the captured output This is a helper to standardize the Ansible-like task execution pattern

func SSHKeyRoutes

func SSHKeyRoutes(r *mux.Router)

SSHKeyRoutes sets up SSH key management API routes

func SanitizeFileName

func SanitizeFileName(name, fileName string) string

SanitizeFileName creates a safe filename from input

func SanitizeFilePath

func SanitizeFilePath(path string) string

SanitizeFilePath prevents path traversal attacks

func SchedulerRoutes

func SchedulerRoutes(r *mux.Router)

SchedulerRoutes sets up scheduler API routes

func ScriptsRoutes

func ScriptsRoutes(r *mux.Router)

func SetPortableMode

func SetPortableMode(enabled bool)

SetPortableMode enables portable mode (data stored alongside binary)

func SetScriptDiscoveryConfig

func SetScriptDiscoveryConfig(config *ScriptDiscoveryConfig)

SetScriptDiscoveryConfig allows customization of script discovery behavior

func SetupAgentRoutes

func SetupAgentRoutes(r *mux.Router)

SetupAgentRoutes sets up the agent WebSocket routes

func SetupRoutes

func SetupRoutes(r *mux.Router)

func SetupRoutesWithAuth

func SetupRoutesWithAuth(r *mux.Router)

SetupRoutesWithAuth sets up routes with authentication middleware

func SetupStandaloneAgentRoutes

func SetupStandaloneAgentRoutes(r *mux.Router)

SetupStandaloneAgentRoutes sets up the standalone agent-related routes

func StartAgentPoller

func StartAgentPoller()

StartAgentPoller starts background WebSocket connections to all agents

func StartHealthPoller

func StartHealthPoller()

StartHealthPoller starts the background health polling goroutine

func StopAgentPoller

func StopAgentPoller()

StopAgentPoller stops the background agent connections

func StopHealthPoller

func StopHealthPoller()

StopHealthPoller stops the background health polling

func StopScheduler

func StopScheduler()

StopScheduler stops the scheduler

func StopVNCServer

func StopVNCServer(machine *Machine) error

StopVNCServer stops x11vnc on the remote machine

func StreamingRoutes

func StreamingRoutes(r *mux.Router)

StreamingRoutes sets up SSE streaming routes

func SystemInfoManifest

func SystemInfoManifest() []porter.Task

SystemInfoManifest returns a Porter manifest for gathering system information

func SystemRoutes

func SystemRoutes(r *mux.Router)

SystemRoutes sets up system management API routes

func SystemToolsRoutes

func SystemToolsRoutes(r *mux.Router)

SystemToolsRoutes sets up system tools API routes (packages, firewall, users)

func TerminalRoutes

func TerminalRoutes(r *mux.Router)

TerminalRoutes sets up WebSocket terminal routes

func UserCreateManifest

func UserCreateManifest(username, shell, password, groups string) []porter.Task

UserManifest returns a Porter manifest for user management

func UserDeleteManifest

func UserDeleteManifest(username string) []porter.Task

func UserRoutes

func UserRoutes(router *mux.Router)

UserRoutes sets up user management API routes

func VNCRoutes

func VNCRoutes(r *mux.Router)

VNCRoutes sets up VNC-related API routes

func VNCWebSocketProxy

func VNCWebSocketProxy(w http.ResponseWriter, r *http.Request, machineIP string, vncPort int)

VNCWebSocketProxy proxies WebSocket to VNC TCP connection

func ValidateCommand

func ValidateCommand(cmd string) (string, error)

ValidateCommand performs basic command validation

func ValidateScriptInput

func ValidateScriptInput(input *ScriptInput, requireContent bool) error

ValidateScriptInput validates script input

func WOLRoutes

func WOLRoutes(r *mux.Router)

WOLRoutes sets up Wake-on-LAN and related API routes

func WakeOnLAN

func WakeOnLAN(macAddress string, broadcastIP string) error

WakeOnLAN sends a magic packet to wake a machine

Types

type APIResponse

type APIResponse struct {
	Success bool        `json:"success"`
	Data    interface{} `json:"data,omitempty"`
	Error   string      `json:"error,omitempty"`
	Message string      `json:"message,omitempty"`
}

APIResponse provides consistent API responses

type AgentConnection

type AgentConnection struct {
	MachineID string
	Conn      *websocket.Conn
	LastSeen  time.Time
	Connected bool
}

AgentConnection represents a connected agent

type AgentMetrics

type AgentMetrics struct {
	Hostname      string `json:"hostname"`
	MachineID     string `json:"machine_id"`
	Timestamp     int64  `json:"timestamp"`
	Online        bool   `json:"online"`
	Uptime        string `json:"uptime"`
	LoadAvg       string `json:"load_avg"`
	CPUUsage      string `json:"cpu_usage"`
	CPUCores      string `json:"cpu_cores"`
	CPUModel      string `json:"cpu_model"`
	MemoryUsage   string `json:"memory_usage"`
	MemoryTotal   string `json:"memory_total"`
	MemoryFree    string `json:"memory_free"`
	SwapUsage     string `json:"swap_usage"`
	DiskUsage     string `json:"disk_usage"`
	DiskTotal     string `json:"disk_total"`
	DiskFree      string `json:"disk_free"`
	ProcessCount  string `json:"process_count"`
	LoggedUsers   string `json:"logged_users"`
	KernelVersion string `json:"kernel_version"`
	OSInfo        string `json:"os_info"`
	NetworkRX     string `json:"network_rx"`
	NetworkTX     string `json:"network_tx"`
}

AgentMetrics represents metrics received from an agent

type AgentStore

type AgentStore struct {
	// contains filtered or unexported fields
}

AgentStore manages connected agents

type AuditLogEntry

type AuditLogEntry struct {
	ID          string                 `json:"id"`
	Timestamp   time.Time              `json:"timestamp"`
	Action      string                 `json:"action"`
	Category    string                 `json:"category"`
	MachineID   string                 `json:"machine_id,omitempty"`
	MachineName string                 `json:"machine_name,omitempty"`
	Details     map[string]interface{} `json:"details,omitempty"`
	Success     bool                   `json:"success"`
	Error       string                 `json:"error,omitempty"`
}

AuditLogEntry represents an action taken in the system

type BackupHistory

type BackupHistory struct {
	ID        string     `json:"id"`
	JobID     string     `json:"job_id"`
	JobName   string     `json:"job_name"`
	MachineID string     `json:"machine_id"`
	StartedAt time.Time  `json:"started_at"`
	EndedAt   *time.Time `json:"ended_at,omitempty"`
	Status    string     `json:"status"` // running, success, failed
	Size      int64      `json:"size,omitempty"`
	Error     string     `json:"error,omitempty"`
	Output    string     `json:"output,omitempty"`
}

BackupHistory represents a backup execution record

type BackupJob

type BackupJob struct {
	ID          string     `json:"id"`
	Name        string     `json:"name"`
	MachineID   string     `json:"machine_id"`
	MachineName string     `json:"machine_name"`
	SourcePath  string     `json:"source_path"`
	DestPath    string     `json:"dest_path"`
	Schedule    string     `json:"schedule"` // cron expression or "manual"
	Compress    bool       `json:"compress"`
	Enabled     bool       `json:"enabled"`
	LastRun     *time.Time `json:"last_run,omitempty"`
	LastStatus  string     `json:"last_status,omitempty"`
	CreatedAt   time.Time  `json:"created_at"`
}

BackupJob represents a backup configuration

type Bookmark

type Bookmark struct {
	ID          string   `json:"id"`
	Name        string   `json:"name"`
	Type        string   `json:"type"` // "script" or "command"
	ScriptPath  string   `json:"script_path,omitempty"`
	Command     string   `json:"command,omitempty"`
	Args        string   `json:"args,omitempty"`
	MachineIDs  []string `json:"machine_ids,omitempty"`
	Description string   `json:"description,omitempty"`
	Color       string   `json:"color,omitempty"`
	CreatedAt   string   `json:"created_at"`
}

Bookmark represents a saved script or command for quick access

type BookmarkStore

type BookmarkStore struct {
	// contains filtered or unexported fields
}

BookmarkStore manages bookmarks

func (*BookmarkStore) Add

func (b *BookmarkStore) Add(bookmark Bookmark) error

Add adds a new bookmark

func (*BookmarkStore) List

func (b *BookmarkStore) List() []Bookmark

List returns all bookmarks

func (*BookmarkStore) Remove

func (b *BookmarkStore) Remove(id string) error

Remove removes a bookmark by ID

func (*BookmarkStore) Update

func (b *BookmarkStore) Update(bookmark Bookmark) error

Update updates an existing bookmark

type BuildClient added in v0.9.1

type BuildClient struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	Customer  string `json:"customer"`
	Pack      string `json:"pack"`
	Branch    string `json:"branch"`
	Version   string `json:"version,omitempty"`
	CreatedAt string `json:"created_at,omitempty"`
	UpdatedAt string `json:"updated_at,omitempty"`
}

BuildClient represents a saved build configuration for quick 1-click builds

type BuildClientStore added in v0.9.1

type BuildClientStore struct {
	// contains filtered or unexported fields
}

BuildClientStore manages build clients

func (*BuildClientStore) Add added in v0.9.1

func (s *BuildClientStore) Add(client *BuildClient) error

Add adds a new build client and returns the created client with ID

func (*BuildClientStore) Get added in v0.9.1

func (s *BuildClientStore) Get(id string) (*BuildClient, error)

Get returns a build client by ID

func (*BuildClientStore) List added in v0.9.1

func (s *BuildClientStore) List() []BuildClient

List returns all build clients

func (*BuildClientStore) Remove added in v0.9.1

func (s *BuildClientStore) Remove(id string) error

Remove removes a build client by ID

func (*BuildClientStore) Update added in v0.9.1

func (s *BuildClientStore) Update(client BuildClient) error

Update updates an existing build client

type CommandBookmark

type CommandBookmark struct {
	ID          string    `json:"id"`
	MachineID   string    `json:"machine_id"`
	Name        string    `json:"name"`
	Command     string    `json:"command"`
	Description string    `json:"description"`
	CreatedAt   time.Time `json:"created_at"`
}

CommandBookmark represents a saved command for a machine

type ConnectionPool

type ConnectionPool struct {
	// contains filtered or unexported fields
}

ConnectionPool manages SSH connections to machines

func GetConnectionPool

func GetConnectionPool() *ConnectionPool

GetConnectionPool returns the singleton connection pool

func NewConnectionPool

func NewConnectionPool(maxAge, maxIdle time.Duration) *ConnectionPool

NewConnectionPool creates a new connection pool

func (*ConnectionPool) Close

func (p *ConnectionPool) Close()

Close closes all connections in the pool

func (*ConnectionPool) Get

func (p *ConnectionPool) Get(machine *Machine) (*goph.Client, error)

Get retrieves or creates a connection for a machine

func (*ConnectionPool) Release

func (p *ConnectionPool) Release(machineID string)

Release marks a connection as no longer in use

func (*ConnectionPool) Remove

func (p *ConnectionPool) Remove(machineID string)

Remove closes and removes a connection from the pool

func (*ConnectionPool) StartCleanup

func (p *ConnectionPool) StartCleanup()

StartCleanup starts the background cleanup goroutine

func (*ConnectionPool) Stats

func (p *ConnectionPool) Stats() map[string]interface{}

Stats returns pool statistics

func (*ConnectionPool) StopCleanup

func (p *ConnectionPool) StopCleanup()

StopCleanup stops the background cleanup goroutine

type CustomScript

type CustomScript struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description"`
	Category    string    `json:"category"`
	Content     string    `json:"content,omitempty"`
	FileName    string    `json:"file_name"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
	Size        int64     `json:"size"`
	Tags        []string  `json:"tags,omitempty"`
}

CustomScript represents a user-uploaded script

type CustomScriptStore

type CustomScriptStore struct {
	// contains filtered or unexported fields
}

CustomScriptStore manages user-uploaded scripts

func (*CustomScriptStore) Add

func (s *CustomScriptStore) Add(input *ScriptInput) (*CustomScript, error)

Add adds a new custom script

func (*CustomScriptStore) Count

func (s *CustomScriptStore) Count() int

Count returns the number of custom scripts

func (*CustomScriptStore) Delete

func (s *CustomScriptStore) Delete(id string) error

Delete removes a custom script

func (*CustomScriptStore) Get

func (s *CustomScriptStore) Get(id string) (*CustomScript, bool)

Get returns a script by ID

func (*CustomScriptStore) GetContent

func (s *CustomScriptStore) GetContent(id string) (string, error)

GetContent returns the content of a script

func (*CustomScriptStore) GetScriptForExecution

func (s *CustomScriptStore) GetScriptForExecution(id string) (string, func(), error)

GetScriptForExecution returns the script path for execution

func (*CustomScriptStore) List

func (s *CustomScriptStore) List() []*CustomScript

List returns all custom scripts sorted by name

func (*CustomScriptStore) Update

func (s *CustomScriptStore) Update(id string, input *ScriptInput) (*CustomScript, error)

Update updates an existing script

type DBConfig

type DBConfig struct {
	Host     string
	Port     int
	User     string
	Password string
	Database string
}

DBConfig holds database configuration

func LoadDBConfigFromEnv

func LoadDBConfigFromEnv() DBConfig

LoadDBConfigFromEnv loads database config from environment variables

type DashboardClient

type DashboardClient struct {
	// contains filtered or unexported fields
}

DashboardClient represents a connected WebSocket client

type DashboardHub

type DashboardHub struct {
	// contains filtered or unexported fields
}

DashboardHub manages WebSocket connections for dashboard updates

func GetDashboardHub

func GetDashboardHub() *DashboardHub

GetDashboardHub returns the singleton dashboard hub

func (*DashboardHub) Broadcast

func (h *DashboardHub) Broadcast(updateType string, data interface{})

Broadcast sends an update to all connected clients

type DashboardUpdate

type DashboardUpdate struct {
	Type      string      `json:"type"`
	Timestamp time.Time   `json:"timestamp"`
	Data      interface{} `json:"data"`
}

DashboardUpdate represents a real-time update for the dashboard

type Database

type Database struct {
	// contains filtered or unexported fields
}

Database holds the MySQL connection

func GetDB

func GetDB() *Database

GetDB returns the database instance

func (*Database) Close

func (d *Database) Close() error

Close closes the database connection

type DiffLine

type DiffLine struct {
	Line1    int    `json:"line1"`
	Line2    int    `json:"line2"`
	Content1 string `json:"content1"`
	Content2 string `json:"content2"`
	Status   string `json:"status"` // equal, added, removed, changed
}

DiffLine represents a line in the diff output

type DownloadConfig

type DownloadConfig struct {
	Name            string   `json:"name"`
	Description     string   `json:"description"`
	URL             string   `json:"url"`
	FallbackMessage string   `json:"fallback_message"`
	RequiredBy      []string `json:"required_by"`
	SizeMB          int      `json:"size_mb"`
}

DownloadConfig represents a file that needs to be downloaded

func GetRequiredDownloads

func GetRequiredDownloads(scriptDir string, enabledFlags []string) ([]DownloadConfig, error)

GetRequiredDownloads returns list of files that need to be downloaded for given flags

type DownloadsConfig

type DownloadsConfig struct {
	Description string           `json:"description"`
	Files       []DownloadConfig `json:"files"`
	Note        string           `json:"note"`
}

DownloadsConfig represents the downloads.json structure

type ExecutionHistory

type ExecutionHistory struct {
	// contains filtered or unexported fields
}

func NewExecutionHistory

func NewExecutionHistory() *ExecutionHistory

func (*ExecutionHistory) Add

func (h *ExecutionHistory) Add(result ExecutionResult)

func (*ExecutionHistory) List

func (h *ExecutionHistory) List() []ExecutionResult

type ExecutionRecord

type ExecutionRecord struct {
	ID          string    `json:"id"`
	MachineID   string    `json:"machine_id"`
	MachineName string    `json:"machine_name"`
	MachineIP   string    `json:"machine_ip"`
	ScriptPath  string    `json:"script_path"`
	ScriptName  string    `json:"script_name"`
	Args        string    `json:"args"`
	PresetName  string    `json:"preset_name,omitempty"`
	StartedAt   time.Time `json:"started_at"`
	FinishedAt  time.Time `json:"finished_at"`
	Duration    string    `json:"duration"`
	Success     bool      `json:"success"`
	Output      string    `json:"output"`
	Error       string    `json:"error,omitempty"`
	ExitCode    int       `json:"exit_code"`
	Operator    string    `json:"operator,omitempty"`
}

ExecutionRecord represents a single script execution in history

func (*ExecutionRecord) ToSummary

func (r *ExecutionRecord) ToSummary() ExecutionRecordSummary

ToSummary converts an ExecutionRecord to ExecutionRecordSummary

type ExecutionRecordSummary

type ExecutionRecordSummary struct {
	ID          string    `json:"id"`
	MachineID   string    `json:"machine_id"`
	MachineName string    `json:"machine_name"`
	MachineIP   string    `json:"machine_ip"`
	ScriptPath  string    `json:"script_path"`
	ScriptName  string    `json:"script_name"`
	Args        string    `json:"args"`
	PresetName  string    `json:"preset_name,omitempty"`
	StartedAt   time.Time `json:"started_at"`
	FinishedAt  time.Time `json:"finished_at"`
	Duration    string    `json:"duration"`
	Success     bool      `json:"success"`
	Error       string    `json:"error,omitempty"`
	ExitCode    int       `json:"exit_code"`
	Operator    string    `json:"operator,omitempty"`
}

ExecutionRecordSummary is a lightweight version without Output for list views

type ExecutionRequest

type ExecutionRequest struct {
	MachineIDs []string          `json:"machine_ids"`
	ScriptPath string            `json:"script_path"`
	Flags      map[string]string `json:"flags"`
}

type ExecutionResult

type ExecutionResult struct {
	MachineID   string    `json:"machine_id"`
	MachineName string    `json:"machine_name"`
	ScriptPath  string    `json:"script_path"`
	Success     bool      `json:"success"`
	Output      string    `json:"output"`
	Error       string    `json:"error"`
	StartedAt   time.Time `json:"started_at"`
	FinishedAt  time.Time `json:"finished_at"`
}

func RunScriptWithStreaming

func RunScriptWithStreaming(m *Machine, scriptPath, args, execID string, useSudo bool) ExecutionResult

RunScriptWithStreaming executes a script with real-time output streaming using Porter manifests useSudo: if true, runs script with sudo (for admin users); if false, runs as regular user (for operators)

type ExecutionStream

type ExecutionStream struct {
	// contains filtered or unexported fields
}

ExecutionStream manages real-time output streaming

func (*ExecutionStream) Broadcast

func (e *ExecutionStream) Broadcast(execID string, event StreamEvent)

Broadcast sends an event to all listeners for an execution

func (*ExecutionStream) Subscribe

func (e *ExecutionStream) Subscribe(execID string) chan StreamEvent

Subscribe creates a new listener for an execution

func (*ExecutionStream) Unsubscribe

func (e *ExecutionStream) Unsubscribe(execID string, ch chan StreamEvent)

Unsubscribe removes a listener

type ExecutionTracker

type ExecutionTracker struct {
	// contains filtered or unexported fields
}

func NewExecutionTracker

func NewExecutionTracker() *ExecutionTracker

func (*ExecutionTracker) AddResult

func (t *ExecutionTracker) AddResult(id string, result ExecutionResult)

func (*ExecutionTracker) Cancel

func (t *ExecutionTracker) Cancel(id string) bool

func (*ExecutionTracker) Create

func (t *ExecutionTracker) Create(id, scriptPath, args string, machineIDs []string) *ScriptExecution

func (*ExecutionTracker) Get

func (*ExecutionTracker) List

func (t *ExecutionTracker) List() []*ScriptExecution

List returns all executions (running and completed)

func (*ExecutionTracker) ListRunning

func (t *ExecutionTracker) ListRunning() []*ScriptExecution

ListRunning returns all currently running executions

func (*ExecutionTracker) SetStatus

func (t *ExecutionTracker) SetStatus(id, status string)

type ExportData

type ExportData struct {
	Version    string                 `json:"version"`
	ExportedAt time.Time              `json:"exported_at"`
	Machines   []*Machine             `json:"machines,omitempty"`
	Groups     []*MachineGroup        `json:"groups,omitempty"`
	Bookmarks  []*CommandBookmark     `json:"bookmarks,omitempty"`
	SSHKeys    []*SSHKey              `json:"ssh_keys,omitempty"`
	BackupJobs []*BackupJob           `json:"backup_jobs,omitempty"`
	Manifests  map[string]interface{} `json:"manifests,omitempty"`
}

ExportData represents all exportable configuration

type HealthPollerConfig

type HealthPollerConfig struct {
	Enabled      bool `json:"enabled"`
	IntervalMins int  `json:"interval_mins"` // How often to poll all machines
	DelayBetween int  `json:"delay_between"` // Seconds between each machine check
	TimeoutSecs  int  `json:"timeout_secs"`  // Timeout for each check
}

HealthPollerConfig holds configuration for background health polling

type HealthStore

type HealthStore struct {
	// contains filtered or unexported fields
}

HealthStore manages machine health status

func (*HealthStore) Get

func (h *HealthStore) Get(machineID string) *MachineHealth

GetHealth returns health status for a machine

func (*HealthStore) GetAggregateStats

func (h *HealthStore) GetAggregateStats() map[string]interface{}

GetAggregateStats returns aggregate statistics across all online machines

func (*HealthStore) GetAll

func (h *HealthStore) GetAll() map[string]*MachineHealth

GetAll returns all health statuses

func (*HealthStore) Update

func (h *HealthStore) Update(health *MachineHealth)

UpdateHealth updates the health status for a machine

type HistoryStore

type HistoryStore struct {
	// contains filtered or unexported fields
}

HistoryStore manages persistent execution history

func (*HistoryStore) Add

func (h *HistoryStore) Add(record ExecutionRecord)

Add adds a new execution record

func (*HistoryStore) Clear

func (h *HistoryStore) Clear() error

Clear clears all history

func (*HistoryStore) GetAll

func (h *HistoryStore) GetAll() []ExecutionRecord

GetAll returns all execution records

func (*HistoryStore) GetByID

func (h *HistoryStore) GetByID(id string) *ExecutionRecord

GetByID returns a single record by ID

func (*HistoryStore) GetByMachine

func (h *HistoryStore) GetByMachine(machineID string) []ExecutionRecord

GetByMachine returns records for a specific machine

func (*HistoryStore) GetByScript

func (h *HistoryStore) GetByScript(scriptPath string) []ExecutionRecord

GetByScript returns records for a specific script

func (*HistoryStore) GetRecent

func (h *HistoryStore) GetRecent(n int) []ExecutionRecord

GetRecent returns the most recent N records

func (*HistoryStore) GetStats

func (h *HistoryStore) GetStats() map[string]interface{}

GetStats returns execution statistics

type JWTClaims

type JWTClaims struct {
	UserID      string   `json:"user_id"`
	Username    string   `json:"username"`
	Role        string   `json:"role"`
	Permissions []string `json:"permissions"`
	jwt.RegisteredClaims
}

JWTClaims represents JWT token claims

func GetCurrentUser

func GetCurrentUser(r *http.Request) *JWTClaims

GetCurrentUser returns the current user from request context

func ValidateToken

func ValidateToken(tokenString string) (*JWTClaims, error)

ValidateToken validates a JWT token and returns the claims

type LogEntry

type LogEntry struct {
	Timestamp string                 `json:"timestamp"`
	Level     string                 `json:"level"`
	Message   string                 `json:"message"`
	Fields    map[string]interface{} `json:"fields,omitempty"`
}

LogEntry represents a structured log entry

type LogLevel

type LogLevel int

LogLevel represents the severity of a log message

const (
	LevelDebug LogLevel = iota
	LevelInfo
	LevelWarn
	LevelError
)

func (LogLevel) String

func (l LogLevel) String() string

type LogStreamManager

type LogStreamManager struct {
	// contains filtered or unexported fields
}

LogStreamManager manages active log streaming sessions

func (*LogStreamManager) GetSession

func (m *LogStreamManager) GetSession(id string) (*LogStreamSession, bool)

GetSession retrieves a session by ID

func (*LogStreamManager) ListSessions

func (m *LogStreamManager) ListSessions() []*LogStreamSession

ListSessions returns all active sessions

func (*LogStreamManager) StartSession

func (m *LogStreamManager) StartSession(session *LogStreamSession)

StartSession starts a new log streaming session

func (*LogStreamManager) StopByMachineID

func (m *LogStreamManager) StopByMachineID(machineID string) int

StopByMachineID stops all sessions for a given machine

func (*LogStreamManager) StopSession

func (m *LogStreamManager) StopSession(id string) bool

StopSession stops and removes a session

type LogStreamSession

type LogStreamSession struct {
	ID        string    `json:"id"`
	MachineID string    `json:"machine_id"`
	Type      string    `json:"type"`   // "journalctl", "tail", "docker", "compose"
	Target    string    `json:"target"` // unit name, file path, or container name
	StartedAt time.Time `json:"started_at"`
	// contains filtered or unexported fields
}

LogStreamSession represents an active log streaming session

type Logger

type Logger struct {
	// contains filtered or unexported fields
}

Logger provides structured logging capabilities

func GetLogger

func GetLogger() *Logger

GetLogger returns the singleton logger instance

func Log

func Log() *Logger

Log returns the default logger

func NewLogger

func NewLogger() *Logger

NewLogger creates a new logger instance

func (*Logger) Close

func (l *Logger) Close()

Close closes the log file

func (*Logger) Debug

func (l *Logger) Debug(msg string)

Debug logs a debug message

func (*Logger) Debugf

func (l *Logger) Debugf(format string, args ...interface{})

Debugf logs a formatted debug message

func (*Logger) Error

func (l *Logger) Error(msg string)

Error logs an error message

func (*Logger) Errorf

func (l *Logger) Errorf(format string, args ...interface{})

Errorf logs a formatted error message

func (*Logger) Info

func (l *Logger) Info(msg string)

Info logs an info message

func (*Logger) Infof

func (l *Logger) Infof(format string, args ...interface{})

Infof logs a formatted info message

func (*Logger) SetLevel

func (l *Logger) SetLevel(level LogLevel)

SetLevel sets the minimum log level

func (*Logger) Warn

func (l *Logger) Warn(msg string)

Warn logs a warning message

func (*Logger) Warnf

func (l *Logger) Warnf(format string, args ...interface{})

Warnf logs a formatted warning message

func (*Logger) WithField

func (l *Logger) WithField(key string, value interface{}) *Logger

WithField returns a new logger with an additional field

func (*Logger) WithFields

func (l *Logger) WithFields(fields map[string]interface{}) *Logger

WithFields returns a new logger with additional fields

type Machine

type Machine struct {
	ID        string   `json:"id"`
	Name      string   `json:"name"`
	IP        string   `json:"ip"`
	Username  string   `json:"username"`
	Password  string   `json:"password,omitempty"`
	Status    string   `json:"status"`
	Category  string   `json:"category,omitempty"`
	Notes     string   `json:"notes,omitempty"`
	AgentPort int      `json:"agent_port,omitempty"`
	HasAgent  bool     `json:"has_agent"`
	Tags      []string `json:"tags,omitempty"`
	MAC       string   `json:"mac,omitempty"`
}

func LoadMachines

func LoadMachines() ([]Machine, error)

LoadMachines loads all machines from storage (helper for other packages)

func LoadMachinesFromDB

func LoadMachinesFromDB() ([]Machine, error)

LoadMachinesFromDB loads all machines from the database

func MigratePasswords

func MigratePasswords(machines []Machine) ([]Machine, bool, error)

MigratePasswords encrypts any plain-text passwords in machines

type MachineExecutionResult

type MachineExecutionResult struct {
	MachineID   string       `json:"machine_id"`
	MachineName string       `json:"machine_name"`
	MachineIP   string       `json:"machine_ip"`
	Status      string       `json:"status"` // running, success, failed
	TaskResults []TaskResult `json:"task_results"`
	Error       string       `json:"error,omitempty"`
	StartedAt   time.Time    `json:"started_at"`
	FinishedAt  *time.Time   `json:"finished_at,omitempty"`
}

MachineExecutionResult represents execution result for a single machine

type MachineGroup

type MachineGroup struct {
	ID        string    `json:"id"`
	Name      string    `json:"name"`
	Color     string    `json:"color"`
	Icon      string    `json:"icon"`
	CreatedAt time.Time `json:"created_at"`
}

MachineGroup represents a group of machines

type MachineHealth

type MachineHealth struct {
	MachineID     string    `json:"machine_id"`
	MachineName   string    `json:"machine_name"`
	IP            string    `json:"ip"`
	Online        bool      `json:"online"`
	LastChecked   time.Time `json:"last_checked"`
	LastOnline    time.Time `json:"last_online,omitempty"`
	LastExecution time.Time `json:"last_execution,omitempty"`
	ResponseTime  int64     `json:"response_time_ms"`
	Error         string    `json:"error,omitempty"`
	// Basic stats
	Uptime      string `json:"uptime,omitempty"`
	LoadAvg     string `json:"load_avg,omitempty"`
	DiskUsage   string `json:"disk_usage,omitempty"`
	MemoryUsage string `json:"memory_usage,omitempty"`
	// Extended stats
	CPUUsage      string `json:"cpu_usage,omitempty"`
	CPUCores      string `json:"cpu_cores,omitempty"`
	CPUModel      string `json:"cpu_model,omitempty"`
	MemoryTotal   string `json:"memory_total,omitempty"`
	MemoryFree    string `json:"memory_free,omitempty"`
	SwapUsage     string `json:"swap_usage,omitempty"`
	DiskTotal     string `json:"disk_total,omitempty"`
	DiskFree      string `json:"disk_free,omitempty"`
	ProcessCount  string `json:"process_count,omitempty"`
	LoggedUsers   string `json:"logged_users,omitempty"`
	Hostname      string `json:"hostname,omitempty"`
	KernelVersion string `json:"kernel_version,omitempty"`
	OSInfo        string `json:"os_info,omitempty"`
	NetworkRX     string `json:"network_rx,omitempty"`
	NetworkTX     string `json:"network_tx,omitempty"`
}

MachineHealth represents the health status of a machine

func CheckMachineHealth

func CheckMachineHealth(m *Machine) *MachineHealth

CheckMachineHealth checks if a machine is reachable and gets basic stats

type MachineRepo

type MachineRepo struct {
	// contains filtered or unexported fields
}

func NewMachineRepo

func NewMachineRepo(store *Store) *MachineRepo

func (*MachineRepo) Add

func (r *MachineRepo) Add(m *Machine)

func (*MachineRepo) Delete

func (r *MachineRepo) Delete(id string)

func (*MachineRepo) Get

func (r *MachineRepo) Get(id string) (*Machine, bool)

func (*MachineRepo) List

func (r *MachineRepo) List() []*Machine

func (*MachineRepo) Update

func (r *MachineRepo) Update(updated *Machine) bool

func (*MachineRepo) UpdateAgentStatus

func (r *MachineRepo) UpdateAgentStatus(id string, hasAgent bool, port int)

func (*MachineRepo) UpdateStatus

func (r *MachineRepo) UpdateStatus(id, status string)

type Manifest

type Manifest struct {
	ID          string            `json:"id"`
	Name        string            `json:"name"`
	Description string            `json:"description,omitempty"`
	Variables   map[string]string `json:"variables,omitempty"`
	Tasks       []TaskDefinition  `json:"tasks"`
	CreatedAt   time.Time         `json:"created_at"`
}

Manifest represents a deployment manifest

type ManifestExecution

type ManifestExecution struct {
	ID           string                   `json:"id"`
	ManifestID   string                   `json:"manifest_id"`
	ManifestName string                   `json:"manifest_name"`
	MachineIDs   []string                 `json:"machine_ids"`
	Variables    map[string]string        `json:"variables"`
	Status       string                   `json:"status"` // pending, running, completed, failed
	StartedAt    time.Time                `json:"started_at"`
	FinishedAt   *time.Time               `json:"finished_at,omitempty"`
	Results      []MachineExecutionResult `json:"results,omitempty"`
}

ManifestExecution represents an execution of a manifest

type MultiTerminalExecution

type MultiTerminalExecution struct {
	ID         string                `json:"id"`
	Command    string                `json:"command"`
	MachineIDs []string              `json:"machine_ids"`
	StartedAt  time.Time             `json:"started_at"`
	Status     string                `json:"status"`
	Results    []MultiTerminalResult `json:"results"`
}

MultiTerminalExecution represents a command run on multiple machines

type MultiTerminalResult

type MultiTerminalResult struct {
	MachineID   string     `json:"machine_id"`
	MachineName string     `json:"machine_name"`
	MachineIP   string     `json:"machine_ip"`
	Status      string     `json:"status"` // pending, running, success, failed
	Output      string     `json:"output"`
	Error       string     `json:"error,omitempty"`
	StartedAt   *time.Time `json:"started_at,omitempty"`
	EndedAt     *time.Time `json:"ended_at,omitempty"`
}

type Notification

type Notification struct {
	ID        string    `json:"id"`
	Type      string    `json:"type"` // success, failure, info, warning
	Title     string    `json:"title"`
	Message   string    `json:"message"`
	Timestamp time.Time `json:"timestamp"`
	Read      bool      `json:"read"`
	Data      any       `json:"data,omitempty"`
}

Notification represents a notification event

type NotificationConfig

type NotificationConfig struct {
	Enabled       bool   `json:"enabled"`
	SlackWebhook  string `json:"slack_webhook,omitempty"`
	EmailSMTP     string `json:"email_smtp,omitempty"`
	EmailFrom     string `json:"email_from,omitempty"`
	EmailTo       string `json:"email_to,omitempty"`
	EmailPassword string `json:"email_password,omitempty"`
	OnSuccess     bool   `json:"on_success"`
	OnFailure     bool   `json:"on_failure"`
	OnScheduled   bool   `json:"on_scheduled"`
}

NotificationConfig holds notification settings

type NotificationStore

type NotificationStore struct {
	// contains filtered or unexported fields
}

NotificationStore manages notifications

func (*NotificationStore) Add

func (n *NotificationStore) Add(notif Notification)

Add adds a new notification

func (*NotificationStore) Clear

func (n *NotificationStore) Clear()

Clear clears all notifications

func (*NotificationStore) GetAll

func (n *NotificationStore) GetAll() []Notification

GetAll returns all notifications

func (*NotificationStore) GetConfig

func (n *NotificationStore) GetConfig() NotificationConfig

GetConfig returns the notification config

func (*NotificationStore) GetUnread

func (n *NotificationStore) GetUnread() []Notification

GetUnread returns unread notifications

func (*NotificationStore) MarkAllRead

func (n *NotificationStore) MarkAllRead()

MarkAllRead marks all notifications as read

func (*NotificationStore) MarkRead

func (n *NotificationStore) MarkRead(id string)

MarkRead marks a notification as read

func (*NotificationStore) UpdateConfig

func (n *NotificationStore) UpdateConfig(config NotificationConfig) error

UpdateConfig updates the notification config

type PooledConnection

type PooledConnection struct {
	Client    *goph.Client
	MachineID string
	CreatedAt time.Time
	LastUsed  time.Time
	InUse     bool
}

PooledConnection represents a connection in the pool

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter for API endpoints

func NewRateLimiter

func NewRateLimiter(limit int, window time.Duration) *RateLimiter

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(key string) bool

type Role

type Role struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Description string    `json:"description"`
	Permissions []string  `json:"permissions"`
	IsSystem    bool      `json:"is_system"`
	CreatedAt   time.Time `json:"created_at"`
}

Role represents a user role with permissions

type RunConfig

type RunConfig struct {
	// UIBuildFS is the embedded filesystem containing the UI build
	UIBuildFS embed.FS
	// UIBuildRoot is the root directory in UIBuildFS (default: "build")
	UIBuildRoot string
	// DefaultPort is the default server port (default: 8069)
	DefaultPort int
	// AppName is used in log messages (default: "Porter")
	AppName string
	// Port overrides DefaultPort (set via flag or config)
	Port int
	// OpenBrowser controls whether to auto-open browser
	OpenBrowser bool
	// PortableMode stores data alongside binary
	PortableMode bool
	// UseMySQL uses MySQL instead of SQLite
	UseMySQL bool
	// UseSQLite uses SQLite (default true)
	UseSQLite bool
	// MigrateData migrates JSON data to database
	MigrateData bool
	// MigrateFromMySQL migrates from MySQL to SQLite
	MigrateFromMySQL bool
	// CustomRoutes allows wrappers to add custom API routes
	CustomRoutes func(r *mux.Router)
}

RunConfig holds configuration for running Porter

type SSHClient

type SSHClient struct {
	// contains filtered or unexported fields
}

SSHClient wraps SSH operations

func NewSSHClient

func NewSSHClient(cfg SSHConfig) *SSHClient

NewSSHClient creates a new SSH client

func (*SSHClient) ExecuteCommand

func (c *SSHClient) ExecuteCommand(cmd string) (string, int, error)

ExecuteCommand executes a command and returns output, exit code, and error

func (*SSHClient) RunCommand

func (c *SSHClient) RunCommand(cmd string) (string, error)

RunCommand executes a command over SSH and returns output

func (*SSHClient) RunCommandWithSudo

func (c *SSHClient) RunCommandWithSudo(cmd, password string) (string, error)

RunCommandWithSudo executes a command with sudo

func (*SSHClient) TestConnection

func (c *SSHClient) TestConnection() error

TestConnection tests if SSH connection is possible

func (*SSHClient) UploadDirectory

func (c *SSHClient) UploadDirectory(localPath, remotePath, password string) error

UploadDirectory uploads a directory via SSH using tar

func (*SSHClient) UploadFile

func (c *SSHClient) UploadFile(content []byte, remotePath string) error

UploadFile uploads a single file via SSH

type SSHConfig

type SSHConfig struct {
	Host     string
	Port     int
	Username string
	Password string
	Timeout  time.Duration
}

SSHConfig holds SSH connection configuration

type SSHKey

type SSHKey struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	PublicKey   string    `json:"public_key"`
	Fingerprint string    `json:"fingerprint"`
	CreatedAt   time.Time `json:"created_at"`
}

SSHKey represents a managed SSH key

type ScheduledJob

type ScheduledJob struct {
	ID           string    `json:"id"`
	Name         string    `json:"name"`
	Description  string    `json:"description,omitempty"`
	ScriptPath   string    `json:"script_path"`
	Args         string    `json:"args,omitempty"`
	MachineIDs   []string  `json:"machine_ids"`
	CronExpr     string    `json:"cron_expr"`
	Enabled      bool      `json:"enabled"`
	CreatedAt    time.Time `json:"created_at"`
	LastRun      time.Time `json:"last_run,omitempty"`
	NextRun      time.Time `json:"next_run,omitempty"`
	LastStatus   string    `json:"last_status,omitempty"`
	LastError    string    `json:"last_error,omitempty"`
	RunCount     int       `json:"run_count"`
	SuccessCount int       `json:"success_count"`
	FailCount    int       `json:"fail_count"`
	// Advanced options
	TimeoutMins     int  `json:"timeout_mins,omitempty"`    // Job timeout in minutes (0 = no timeout)
	RetryCount      int  `json:"retry_count,omitempty"`     // Number of retries on failure
	RetryDelayMin   int  `json:"retry_delay_min,omitempty"` // Delay between retries in minutes
	NotifyOnFail    bool `json:"notify_on_fail"`            // Send notification on failure
	NotifyOnSuccess bool `json:"notify_on_success"`         // Send notification on success
}

ScheduledJob represents a scheduled script execution

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Scheduler manages scheduled jobs

func (*Scheduler) AddJob

func (s *Scheduler) AddJob(job *ScheduledJob) error

AddJob adds a new scheduled job

func (*Scheduler) DeleteJob

func (s *Scheduler) DeleteJob(jobID string) error

DeleteJob removes a scheduled job

func (*Scheduler) GetJob

func (s *Scheduler) GetJob(jobID string) *ScheduledJob

GetJob returns a specific job

func (*Scheduler) GetJobs

func (s *Scheduler) GetJobs() []*ScheduledJob

GetJobs returns all scheduled jobs

func (*Scheduler) UpdateJob

func (s *Scheduler) UpdateJob(job *ScheduledJob) error

UpdateJob updates an existing job

type Script

type Script struct {
	Path         string       `json:"path"`
	Name         string       `json:"name"`
	Description  string       `json:"description"`
	Category     string       `json:"category"`
	Flags        []ScriptFlag `json:"flags"`
	IsTopLevel   bool         `json:"is_top_level"`
	IsCustom     bool         `json:"is_custom,omitempty"`
	CustomID     string       `json:"custom_id,omitempty"`
	RequiredTags []string     `json:"required_tags,omitempty"`
}

type ScriptDeployConfig

type ScriptDeployConfig struct {
	LocalTempDir    string
	RemoteBase      string
	RemoteScriptDir string
	ScriptName      string
	LibDir          string
	HasLib          bool
	Args            string
	Password        string
}

ScriptDeployConfig holds configuration for script deployment

type ScriptDiscoveryConfig

type ScriptDiscoveryConfig struct {
	// TopLevelScripts are scripts that should always be shown prominently
	TopLevelScripts map[string]bool
	// HiddenScripts are scripts that should not be shown in the UI
	HiddenScripts map[string]bool
	// EmbeddedRoot is the root directory name for embedded scripts (default: "embedded-scripts")
	EmbeddedRoot string
	// ScriptRequiredTags maps script names to required machine tags
	// Scripts will only show when a machine with matching tags is selected
	ScriptRequiredTags map[string][]string
}

ScriptDiscoveryConfig allows customization of script discovery

type ScriptExecution

type ScriptExecution struct {
	ID         string            `json:"id"`
	Status     string            `json:"status"`
	Results    []ExecutionResult `json:"results"`
	ScriptPath string            `json:"script_path,omitempty"`
	ScriptName string            `json:"script_name,omitempty"`
	MachineIDs []string          `json:"machine_ids,omitempty"`
	Args       string            `json:"args,omitempty"`
	StartedAt  time.Time         `json:"started_at,omitempty"`
}

type ScriptFlag

type ScriptFlag struct {
	Short       string `json:"short"`
	Long        string `json:"long"`
	Description string `json:"description"`
	HasValue    bool   `json:"has_value"`
	ValueHint   string `json:"value_hint,omitempty"`
}

func ParseScriptFlagsFromContent

func ParseScriptFlagsFromContent(content string) ([]ScriptFlag, string, bool)

ParseScriptFlagsFromContent parses flags from script content (exported for use by embedders)

type ScriptInput

type ScriptInput struct {
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Category    string   `json:"category"`
	Content     string   `json:"content"`
	FileName    string   `json:"file_name"`
	Tags        []string `json:"tags"`
}

ScriptInput represents the input for creating/updating a script

type Session

type Session struct {
	ID        string    `json:"id"`
	UserID    string    `json:"user_id"`
	Token     string    `json:"token"`
	IPAddress string    `json:"ip_address"`
	UserAgent string    `json:"user_agent"`
	ExpiresAt time.Time `json:"expires_at"`
	CreatedAt time.Time `json:"created_at"`
}

Session represents an active user session

type StandaloneAgentConnection

type StandaloneAgentConnection struct {
	MachineID string
	Conn      *websocket.Conn
	LastSeen  time.Time
	Metrics   StandaloneAgentMetrics
}

StandaloneAgentConnection represents a WebSocket connection to a standalone agent

type StandaloneAgentManager

type StandaloneAgentManager struct {
	// contains filtered or unexported fields
}

type StandaloneAgentMetrics

type StandaloneAgentMetrics struct {
	Hostname      string   `json:"hostname"`
	Timestamp     int64    `json:"timestamp"`
	Online        bool     `json:"online"`
	Uptime        string   `json:"uptime"`
	LoadAverage   string   `json:"load_average"`
	CPUUsage      float64  `json:"cpu_usage"`
	MemoryUsage   float64  `json:"memory_usage"`
	MemoryTotal   string   `json:"memory_total"`
	MemoryUsed    string   `json:"memory_used"`
	DiskUsage     float64  `json:"disk_usage"`
	DiskTotal     string   `json:"disk_total"`
	DiskUsed      string   `json:"disk_used"`
	ProcessCount  int      `json:"process_count"`
	LoggedInUsers []string `json:"logged_in_users"`
	KernelVersion string   `json:"kernel_version"`
	OSInfo        string   `json:"os_info"`
	NetworkRX     string   `json:"network_rx"`
	NetworkTX     string   `json:"network_tx"`
	CPUModel      string   `json:"cpu_model"`
	CPUCores      int      `json:"cpu_cores"`
}

StandaloneAgentMetrics represents metrics from a standalone agent

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store handles persistence for application data

func DefaultStore

func DefaultStore() *Store

DefaultStore returns a store using ~/.idx-deploy

func GetStore

func GetStore() *Store

GetStore returns the global store instance

func NewStore

func NewStore(dataDir string) *Store

NewStore creates a new store with the given data directory

func (*Store) Delete

func (s *Store) Delete(filename string) error

Delete removes a file from the store

func (*Store) Exists

func (s *Store) Exists(filename string) bool

Exists checks if a file exists in the store

func (*Store) Load

func (s *Store) Load(filename string, data interface{}) error

Load reads data from a JSON file

func (*Store) Save

func (s *Store) Save(filename string, data interface{}) error

Save persists data to a JSON file with backup

type StreamEvent

type StreamEvent struct {
	Type      string    `json:"type"` // output, status, error, complete
	MachineID string    `json:"machine_id"`
	Machine   string    `json:"machine"`
	Data      string    `json:"data"`
	Timestamp time.Time `json:"timestamp"`
}

StreamEvent represents a real-time execution event

type TaskDefinition

type TaskDefinition struct {
	ID          string            `json:"id"`
	Type        TaskType          `json:"type"`
	Name        string            `json:"name"`
	Description string            `json:"description,omitempty"`
	Params      map[string]string `json:"params"`
	Options     TaskOptions       `json:"options,omitempty"`
}

TaskDefinition represents a single task in a manifest

type TaskOptions

type TaskOptions struct {
	Sudo     bool   `json:"sudo,omitempty"`
	User     bool   `json:"user,omitempty"`
	Retry    int    `json:"retry,omitempty"`
	Ignore   bool   `json:"ignore,omitempty"`
	Creates  string `json:"creates,omitempty"`
	When     string `json:"when,omitempty"`
	Register string `json:"register,omitempty"`
	Timeout  string `json:"timeout,omitempty"`
}

TaskOptions represents optional task configuration

type TaskResult

type TaskResult struct {
	TaskID     string     `json:"task_id"`
	TaskName   string     `json:"task_name"`
	Status     string     `json:"status"` // pending, running, ok, changed, failed, skipped
	Output     string     `json:"output,omitempty"`
	Error      string     `json:"error,omitempty"`
	StartedAt  time.Time  `json:"started_at"`
	FinishedAt *time.Time `json:"finished_at,omitempty"`
}

TaskResult represents the result of a single task execution

type TaskType

type TaskType string

TaskType represents the type of Porter task

const (
	TaskUpload       TaskType = "upload"
	TaskCopy         TaskType = "copy"
	TaskMove         TaskType = "move"
	TaskWrite        TaskType = "write"
	TaskMkdir        TaskType = "mkdir"
	TaskRm           TaskType = "rm"
	TaskChmod        TaskType = "chmod"
	TaskChown        TaskType = "chown"
	TaskSymlink      TaskType = "symlink"
	TaskTemplate     TaskType = "template"
	TaskRun          TaskType = "run"
	TaskCapture      TaskType = "capture"
	TaskSvcStart     TaskType = "svc_start"
	TaskSvcStop      TaskType = "svc_stop"
	TaskSvcRestart   TaskType = "svc_restart"
	TaskSvcEnable    TaskType = "svc_enable"
	TaskDaemonReload TaskType = "daemon_reload"
	TaskDockerStart  TaskType = "docker_start"
	TaskDockerStop   TaskType = "docker_stop"
	TaskDockerPull   TaskType = "docker_pull"
	TaskComposeUp    TaskType = "compose_up"
	TaskComposeDown  TaskType = "compose_down"
	TaskComposePull  TaskType = "compose_pull"
	TaskWaitPort     TaskType = "wait_port"
	TaskWaitHTTP     TaskType = "wait_http"
	TaskScript       TaskType = "script"
)

type TerminalManager

type TerminalManager struct {
	// contains filtered or unexported fields
}

TerminalManager manages active terminal sessions

func (*TerminalManager) Add

func (tm *TerminalManager) Add(session *TerminalSession)

func (*TerminalManager) Get

func (tm *TerminalManager) Get(id string) (*TerminalSession, bool)

func (*TerminalManager) Remove

func (tm *TerminalManager) Remove(id string)

type TerminalRecording

type TerminalRecording struct {
	ID          string                   `json:"id"`
	MachineID   string                   `json:"machineId"`
	MachineName string                   `json:"machineName"`
	StartTime   time.Time                `json:"startTime"`
	Duration    float64                  `json:"duration"`
	Events      []TerminalRecordingEvent `json:"events"`
}

TerminalRecording represents a recorded terminal session

type TerminalRecordingEvent

type TerminalRecordingEvent struct {
	Time float64 `json:"time"` // Seconds since start
	Type string  `json:"type"` // "o" for output, "i" for input
	Data string  `json:"data"` // The actual data
}

TerminalRecordingEvent represents a single event in a terminal recording

type TerminalSession

type TerminalSession struct {
	ID        string
	MachineID string
	SSHClient *ssh.Client
	Session   *ssh.Session
	StdinPipe io.WriteCloser
	WSConn    *websocket.Conn
	// contains filtered or unexported fields
}

TerminalSession represents an active terminal session

func (*TerminalSession) Close

func (ts *TerminalSession) Close()

type User

type User struct {
	ID          string     `json:"id"`
	Username    string     `json:"username"`
	Email       string     `json:"email,omitempty"`
	Password    string     `json:"-"` // Never expose password hash
	Role        string     `json:"role"`
	DisplayName string     `json:"display_name,omitempty"`
	AvatarURL   string     `json:"avatar_url,omitempty"`
	IsActive    bool       `json:"is_active"`
	LastLogin   *time.Time `json:"last_login,omitempty"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
}

User represents a system user

func GetUserByID

func GetUserByID(id string) (*User, error)

GetUserByID retrieves a user by ID

func GetUserByUsername

func GetUserByUsername(username string) (*User, error)

GetUserByUsername retrieves a user by username

type VNCCapability

type VNCCapability struct {
	Available     bool   `json:"available"`
	Installed     bool   `json:"installed"`
	ServiceExists bool   `json:"service_exists"`
	ServiceActive bool   `json:"service_active"`
	Display       string `json:"display"`
	Error         string `json:"error,omitempty"`
}

VNCCapability represents whether a machine supports VNC

func CheckVNCCapability

func CheckVNCCapability(machine *Machine) *VNCCapability

CheckVNCCapability checks if x11vnc is available on a machine

type VNCSession

type VNCSession struct {
	MachineID   string    `json:"machine_id"`
	MachineName string    `json:"machine_name"`
	MachineIP   string    `json:"machine_ip"`
	VNCPort     int       `json:"vnc_port"`
	Display     string    `json:"display"`
	StartedAt   time.Time `json:"started_at"`
	Active      bool      `json:"active"`
}

VNCSession represents an active VNC session

func GetVNCSession

func GetVNCSession(machineID string) *VNCSession

GetVNCSession returns the active VNC session for a machine

func StartVNCServer

func StartVNCServer(machine *Machine, display string) (*VNCSession, error)

StartVNCServer starts x11vnc on the remote machine via SSH

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL