core

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 29, 2026 License: AGPL-3.0 Imports: 38 Imported by: 0

Documentation

Overview

Package core is the privileged half of Zelie. It runs as root, owns containerd, and accepts a small set of typed requests over a Unix socket. Nothing here listens on the network.

Index

Constants

View Source
const DefaultSocket = "/run/zelie/core.sock"

DefaultSocket is where the core listens.

View Source
const ExternalUser = "zelie_external"

ExternalUser is the database user desktop tools sign in as. It is not the apps' user, so its password can change or go without touching them.

View Source
const MaxUploadChunk = 32 << 20

MaxUploadChunk is the most one piece of an upload may carry.

Variables

This section is empty.

Functions

func LoadExternal

func LoadExternal(path string) (*External, []ExternalListener, error)

LoadExternal reads the saved listeners. Start opens them.

Types

type Backup

type Backup = backup.Info

Backup is a backup file as the core describes it.

type BackupMeta

type BackupMeta struct {
	// Engine is the database's; empty for a backup of an app's volumes.
	Engine  string   `json:"engine"`
	Volumes []string `json:"volumes,omitempty"`
	Size    int64    `json:"size,omitempty"`
}

BackupMeta is what a backup holds, sent along with it, encrypted, so another server can tell what to restore it into.

type Builder

type Builder interface {
	Build(ctx context.Context, req build.Request, out io.Writer) (build.Result, error)
	RemoveCache(app string) error
}

Builder is what the core needs to build images.

type Client

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

Client talks to the core over its socket. The panel and the CLI use it.

func NewClient

func NewClient(socket string) *Client

func (*Client) AddOldKey

func (c *Client) AddOldKey(ctx context.Context, recovery string) ([]string, error)

AddOldKey adds the keys of another recovery file, and returns the public halves of the new ones.

func (*Client) AppendUpload

func (c *Client) AppendUpload(ctx context.Context, id string, offset int64, piece io.Reader) (Upload, error)

AppendUpload sends one piece of an upload, which starts at offset.

func (*Client) BackUpVolumes

func (c *Client) BackUpVolumes(ctx context.Context, app string, vols []VolumeRef, live bool) (Backup, error)

BackUpVolumes backs up an app's volumes into one archive. Live copies them while the app runs; otherwise the app must be stopped.

func (*Client) Backups

func (c *Client) Backups(ctx context.Context, app string) ([]Backup, error)

Backups lists an app's backup files, newest first.

func (*Client) Build

func (c *Client) Build(ctx context.Context, app, version string, env, sealedEnv []string, source io.Reader, out io.Writer) (build.Result, error)

Build sends source, a gzipped tar with one top-level directory, to be built for app, with the app's variables: env as NAME=value, sealedEnv sealed for the core. The build's output is written to out as it happens.

func (*Client) CreateBackup

func (c *Client) CreateBackup(ctx context.Context, app, container, kind string) (Backup, error)

CreateBackup backs up a database from its running container.

func (*Client) CreateVolume

func (c *Client) CreateVolume(ctx context.Context, name string) error

CreateVolume makes an empty volume.

func (*Client) DataExport

func (c *Client) DataExport(ctx context.Context, app, container, engine string, q dataview.Query, w io.Writer) error

DataExport writes every row the query finds to w as CSV.

func (*Client) DataKey

func (c *Client) DataKey(ctx context.Context, app, container, key string) (dataview.Value, error)

DataKey reads what one Redis key holds.

func (*Client) DataKeys

func (c *Client) DataKeys(ctx context.Context, app, container, pattern, cursor string) (dataview.KeyPage, error)

DataKeys goes one step through a Redis database's keys.

func (*Client) DataRows

func (c *Client) DataRows(ctx context.Context, app, container, engine string, q dataview.Query) (dataview.Page, error)

DataRows reads a page of a table.

func (*Client) DataTables

func (c *Client) DataTables(ctx context.Context, app, container, engine string) ([]dataview.Table, error)

DataTables lists a database's tables and views, with their columns.

func (*Client) DownloadBackup

func (c *Client) DownloadBackup(ctx context.Context, app, name string, w io.Writer) error

DownloadBackup copies the encrypted file to w.

func (*Client) FetchBackup

func (c *Client) FetchBackup(ctx context.Context, app, name string) error

FetchBackup brings a backup back from the destination onto this server.

func (*Client) Host

func (c *Client) Host(ctx context.Context) (engine.Host, error)

Host describes the server.

func (*Client) ImportUpload

func (c *Client) ImportUpload(ctx context.Context, id, kind string) (Backup, error)

ImportUpload makes a backup of a whole upload, as a dump of kind.

func (c *Client) Links(ctx context.Context, app string) ([]engine.Link, error)

Links returns the links of an app.

func (*Client) List

func (c *Client) List(ctx context.Context) ([]engine.Status, error)

func (*Client) Logs

func (c *Client) Logs(ctx context.Context, id string, follow bool, tail int64, w io.Writer) error

Logs writes a container's output to w. With tail above zero it starts at the first whole line within that many bytes of the end. With follow set it keeps streaming new output until ctx is cancelled.

func (*Client) Offsite

func (c *Client) Offsite(ctx context.Context) (OffsiteInfo, error)

Offsite returns the destination backups are copied to.

func (*Client) OffsiteBackups

func (c *Client) OffsiteBackups(ctx context.Context) (OffsiteList, error)

OffsiteBackups lists the backups in the destination, and what each holds.

func (*Client) Pin added in v0.5.0

func (c *Client) Pin(ctx context.Context, image string) (string, error)

Pin returns image pinned to the digest its tag points at here.

func (*Client) RecoveryKey

func (c *Client) RecoveryKey(ctx context.Context, host string, w io.Writer) error

RecoveryKey returns the recovery file for the backups.

func (*Client) Remove

func (c *Client) Remove(ctx context.Context, id string) error

func (*Client) RemoveBackup

func (c *Client) RemoveBackup(ctx context.Context, app, name string) error

func (*Client) RemoveBuildCache

func (c *Client) RemoveBuildCache(ctx context.Context, app string) error

RemoveBuildCache deletes what builds of an app keep between them.

func (*Client) RemoveExternal

func (c *Client) RemoveExternal(ctx context.Context, app, engine, container string) error

RemoveExternal closes a database's loopback port and, if container is running, drops the external user.

func (*Client) RemoveImage

func (c *Client) RemoveImage(ctx context.Context, name string) error

RemoveImage deletes an image Zelie built.

func (*Client) RemoveOffsite

func (c *Client) RemoveOffsite(ctx context.Context) error

RemoveOffsite forgets the destination; the bucket is left as it is.

func (*Client) RemoveOffsiteBackup

func (c *Client) RemoveOffsiteBackup(ctx context.Context, app, name string) error

RemoveOffsiteBackup deletes a backup's copy in the destination.

func (*Client) RemoveUpload

func (c *Client) RemoveUpload(ctx context.Context, id string) error

func (*Client) RemoveVolume

func (c *Client) RemoveVolume(ctx context.Context, name string) error

RemoveVolume deletes a volume and its files. No container may use it.

func (*Client) RestoreBackup

func (c *Client) RestoreBackup(ctx context.Context, app, name, kind, container, volume string) error

RestoreBackup puts a backup back: into the running container for kinds that load in place, into the stopped database's volume for the others.

func (*Client) RestoreVolumes

func (c *Client) RestoreVolumes(ctx context.Context, app, name string, vols []VolumeRef, size int64) error

RestoreVolumes replaces the files of a stopped app's volumes with a backup's. size is how much the backup's files take, from when it was made.

func (*Client) Run

func (c *Client) Run(ctx context.Context, s engine.Spec) error

func (*Client) RunApp

func (c *Client) RunApp(ctx context.Context, s engine.Spec, sealedEnv []string, linked ...LinkedVar) (string, error)

RunApp runs a container of s.App with secret variables sealed for it, and variables made from the secrets of apps it is linked to. It returns the image that runs, pinned by digest (see engine.Pin).

func (*Client) SecretKey

func (c *Client) SecretKey(ctx context.Context) (secret.PublicKey, error)

SecretKey returns the key to seal secret variables with.

func (*Client) SetExternal

func (c *Client) SetExternal(ctx context.Context, app, engine, container string, port, target int, sealedPassword string) error

SetExternal opens a database's loopback port. With a sealed password it also makes the external user, or gives it the new password.

func (c *Client) SetLinks(ctx context.Context, app string, links []engine.Link) error

SetLinks replaces the links of an app: which other apps it may reach, on which port, and by what name.

func (*Client) SetOffsite

func (c *Client) SetOffsite(ctx context.Context, cfg OffsiteConfig) (OffsiteInfo, error)

SetOffsite checks a destination and saves it.

func (*Client) StartUpload

func (c *Client) StartUpload(ctx context.Context, app string, size int64) (Upload, error)

StartUpload makes room for a file of size bytes for app.

func (*Client) Stop

func (c *Client) Stop(ctx context.Context, id string, graceSeconds int) error

func (*Client) SweepImages

func (c *Client) SweepImages(ctx context.Context, keep []string) ([]string, error)

SweepImages tells the core which images are still needed. It deletes those that have not been for a week and returns their names.

func (*Client) SyncExternal

func (c *Client) SyncExternal(ctx context.Context, list []ExternalListener) error

SyncExternal makes the core's loopback ports exactly these.

func (*Client) Update added in v0.2.0

func (c *Client) Update(ctx context.Context, version string) error

Update starts an update to version. It returns once the release is downloaded and checked; the services restart after.

func (*Client) UpdateStatus added in v0.2.0

func (c *Client) UpdateStatus(ctx context.Context) (UpdateStatus, error)

func (*Client) Upload

func (c *Client) Upload(ctx context.Context, id string) (Upload, error)

func (*Client) UploadBackup

func (c *Client) UploadBackup(ctx context.Context, app, name string, meta BackupMeta) error

UploadBackup copies a backup to the destination, with what it holds.

func (*Client) Usage

func (c *Client) Usage(ctx context.Context, id string) (engine.Usage, error)

Usage reports what a running container uses.

func (*Client) Version added in v0.2.0

func (c *Client) Version(ctx context.Context) (string, error)

Version asks the running core which version it is.

func (*Client) VolumeSizes

func (c *Client) VolumeSizes(ctx context.Context) (map[string]int64, error)

VolumeSizes returns the disk each volume takes, by name.

func (*Client) Wait

func (c *Client) Wait(ctx context.Context, id string) (int, error)

Wait waits until the container's process has exited and returns its exit code.

type Engine

type Engine interface {
	Run(ctx context.Context, s engine.Spec) error
	Stop(ctx context.Context, id string, grace time.Duration) error
	Remove(ctx context.Context, id string) error
	List(ctx context.Context) ([]engine.Status, error)
	RemoveImage(ctx context.Context, name string) error
	Images(ctx context.Context) ([]engine.Image, error)
	SetUnused(ctx context.Context, name string, since time.Time) error
	Pin(ctx context.Context, ref string) (string, error)
	Wait(ctx context.Context, id string) (uint32, error)
	Usage(id string) (engine.Usage, error)
	CreateVolume(name string) error
	RemoveVolume(ctx context.Context, name string) error
	VolumeSizes() (map[string]int64, error)
	Links(app string) ([]engine.Link, error)
	SetLinks(ctx context.Context, app string, links []engine.Link) error
	Exec(ctx context.Context, id string, args []string, stdin io.Reader, stdout, stderr io.Writer) (uint32, error)
	OpenVolume(ctx context.Context, name string) (*os.Root, error)
	ReadVolume(name string) (*os.Root, error)
	VolumeSize(name string) (int64, error)
}

Engine is what the core needs from the container engine.

type Error

type Error struct {
	Status  int
	Message string
	// Code and Params are set for a message meant for the user.
	Code   string
	Params map[string]any
}

Error is a failure reported by the core.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Msg

func (e *Error) Msg() msg.Msg

Msg is the error as a message for the user: the core's own, when it wrote one, or else its text as it is.

type External

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

External keeps the loopback listeners, and saves them so they come back when the core restarts.

func (*External) Remove

func (x *External) Remove(app string) error

Remove closes an app's listener and the connections through it.

func (*External) Set

func (x *External) Set(l ExternalListener) error

Set opens or moves an app's listener.

func (*External) Start

func (x *External) Start(list []ExternalListener)

Start opens the saved listeners. One that cannot open is logged and left for the panel to set again.

func (*External) Sync

func (x *External) Sync(list []ExternalListener) error

Sync makes the listeners exactly list, which the panel sends when it starts.

type ExternalListener

type ExternalListener struct {
	App    string `json:"app"`
	Port   int    `json:"port"`   // on 127.0.0.1
	Target int    `json:"target"` // the database's port in its container
}

ExternalListener is one loopback port and where it leads.

type LinkedVar

type LinkedVar struct {
	Name string
	// Template is the value, with {secret} where the secret goes.
	Template string
	// From is the app the secret belongs to, and Sealed the secret, sealed
	// for it.
	From, Sealed string
}

LinkedVar is a variable made from a secret of another app, such as a database URL with the database's password in it.

type Offsite

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

Offsite holds the destination. Its keys stay in a file only root reads: the panel can set them but never read them back, so a panel taken over cannot hand them out. Pointing the backups at another bucket gains it nothing either, since they are encrypted.

func LoadOffsite

func LoadOffsite(path string) (*Offsite, error)

LoadOffsite reads the destination saved at path, if there is one.

type OffsiteBackup

type OffsiteBackup struct {
	App     string    `json:"app"`
	Name    string    `json:"name"`
	Bytes   int64     `json:"bytes"`
	Created time.Time `json:"created"`
	// Meta is what the backup holds, when it was asked for and could be
	// read. Locked is set when it is there but no key here opens it.
	Meta   *BackupMeta `json:"meta,omitempty"`
	Locked bool        `json:"locked,omitempty"`
}

OffsiteBackup is a backup file found in the bucket.

type OffsiteConfig

type OffsiteConfig struct {
	Endpoint  string `json:"endpoint"`
	Region    string `json:"region"`
	Bucket    string `json:"bucket"`
	Prefix    string `json:"prefix"`
	AccessKey string `json:"access_key"`
	// SecretKey may be left out when changing the folder or the region;
	// the one already saved is kept.
	SecretKey string `json:"secret_key,omitempty"`
}

OffsiteConfig is where backups are copied off this server: a folder in an S3 bucket, and the keys to it.

type OffsiteInfo

type OffsiteInfo struct {
	Set       bool   `json:"set"`
	Endpoint  string `json:"endpoint,omitempty"`
	Region    string `json:"region,omitempty"`
	Bucket    string `json:"bucket,omitempty"`
	Prefix    string `json:"prefix,omitempty"`
	AccessKey string `json:"access_key,omitempty"`
}

OffsiteInfo is the destination as the panel may see it: everything but the secret key.

type OffsiteList

type OffsiteList struct {
	// Key is the public key the folder's backups were encrypted for, from
	// the note beside them, and Opens whether a key here opens them.
	Key     string          `json:"key,omitempty"`
	Opens   bool            `json:"opens"`
	Backups []OffsiteBackup `json:"backups"`
}

OffsiteList is what the destination's folder holds.

type Server

type Server struct {
	Engine  Engine
	Builder Builder
	Secrets *secret.Keys
	Backups *backup.Dir
	Offsite *Offsite
	// External holds the loopback ports of databases open to desktop tools.
	External *External
	// Updater updates Zelie itself; nil where it cannot.
	Updater *Updater
	Paths   engine.Paths
	Log     *slog.Logger
	Allowed peer.Policy
	// Host describes the server; tests replace it.
	Host func() (engine.Host, error)
	// contains filtered or unexported fields
}

func (*Server) Handler

func (s *Server) Handler() http.Handler

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, socket string) error

Serve listens on the socket until ctx is cancelled.

func (*Server) StartExternal

func (s *Server) StartExternal(list []ExternalListener)

StartExternal opens the saved listeners once the server can find containers.

type UpdateStatus added in v0.2.0

type UpdateStatus struct {
	Version string         `json:"version"`
	Last    *update.Result `json:"last,omitempty"`
}

UpdateStatus is the running version and how the last update went.

type Updater added in v0.2.0

type Updater struct {
	// Fetch downloads a release's binary and checks its signature.
	Fetch func(ctx context.Context, version string) ([]byte, error)
	// Place puts it where the services run from, keeping the old one.
	Place func(bin []byte) error
	// Start runs the unit that restarts the services and checks them.
	Start func(ctx context.Context, from, to string) error
	// Running reports whether that unit runs now.
	Running func(ctx context.Context) bool
	// Last is the outcome of the last update.
	Last func() (update.Result, error)
	// Installed reports whether the services run from the installed binary.
	Installed func() bool
}

Updater does the parts of an update that touch the machine. Tests replace it.

type Upload

type Upload struct {
	ID       string `json:"id"`
	App      string `json:"app"`
	Size     int64  `json:"size"`
	Received int64  `json:"received"`
}

Upload is an upload in progress as the core describes it.

type VolumeRef

type VolumeRef struct {
	Name string `json:"name"`
	Dir  string `json:"dir"`
}

VolumeRef names one of an app's volumes and the folder it gets in the backup: where the app sees it, without the leading slash.

Jump to

Keyboard shortcuts

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