Help us shape the future of Go! Take the 2026 Go Developer Survey

compose

package
v1.4.14 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package compose: service toggle helper.

Compose-aware plugin enable/disable for Model A.

For Model A plugins (compose-managed services), enable/disable means commenting or uncommenting the service block in docker-compose.yml. We do this with a textual scanner rather than a full YAML parse so the operation is reversible and survives surrounding hand-edits.

Conventions:

  • A service block runs from the `<service-name>:` line at indentation 2 (two spaces) to the next service header (also at indentation 2) or the next top-level key.
  • To DISABLE: prefix every line of the service block with `# ` (the existing indentation is preserved). A `# nself-disabled: <name>` marker line is inserted immediately above the block so we can find it again.
  • To ENABLE: locate the marker line, strip the `# ` prefix from each subsequent block line, and remove the marker.

Idempotency: ToggleService is safe to call repeatedly with the same target state. ToggleService(yaml, "claw", false) on an already-disabled service returns the input unchanged.

Index

Constants

View Source
const (
	EngineRedis  = "redis"
	EngineValkey = "valkey"
)

Cache engines REDIS_ENGINE accepts.

View Source
const (
	// LockHeader is the value of the first key, `_generated`.
	LockHeader = "GENERATED BY tools/imagelock — DO NOT HAND EDIT"
	// LockSchemaVersion is the lock's schema_version.
	LockSchemaVersion = "1"
	// EnvImagePinning selects the pinning mode: lock or legacy.
	EnvImagePinning = "IMAGE_PINNING"
	// PinningLock emits repository:version@index_digest.
	PinningLock = "lock"
	// PinningLegacy emits each entry's legacy_ref (byte-identical to before).
	PinningLegacy = "legacy"
)

Lock file constants.

View Source
const AdminServiceName = "nself-admin"

AdminServiceName is the compose SERVICE name for the nSelf Admin UI.

It is deliberately NOT "admin". "admin" is the image pin key (ImageKey below) and the container suffix (`<project>_admin`), so all three names for the same thing differ by one character. Passing "admin" to `docker compose up` fails with "no such service", which is how the E2E golden path broke at step 11: the failure surfaced only as `exit status 1` because Run discards subprocess stderr in non-TTY contexts.

Use this constant wherever a compose service name is needed, so the string exists once rather than at each call site.

View Source
const AuthEncryptionKeyEnv = "AUTH_ENCRYPTION_KEY"

AuthEncryptionKeyEnv is the key nhost/auth 0.43.0 and later require: 32 bytes, hex.

View Source
const DigestConfigFile = ".nself-image-digests.json"

DigestConfigFile is the filename where image digests are stored.

View Source
const DigestLength = 64

DigestLength is the hex length of a sha256 digest.

View Source
const DigestPrefix = "sha256:"

DigestPrefix is the fixed algorithm prefix for OCI image digests.

View Source
const NginxConfDDir = "nginx/conf.d"

NginxConfDDir is the host-side directory for env-specific nginx conf.d files. Hand-managed, safe to edit directly.

View Source
const NginxSitesDir = "nginx/sites"

NginxSitesDir is the host-side directory for generated nginx site configs. GENERATED by nself build — never hand-edit.

View Source
const ProjectLockFile = "nself.lock.yaml"

ProjectLockFile is the lock's file name at the project root (lock.FileName).

View Source
const (
	RoleCore, RoleOptional, RoleMonitoring, RoleTool, RolePlugin = "core", "optional", "monitoring", "tool", "plugin"
)

Image roles.

Variables

View Source
var ImageDigests = map[string]string{}

ImageDigests maps service name to sha256 digest for image pinning. When a digest is available, ResolveImage appends @sha256:... to the tag. Populated by LoadImageDigests from the project config directory.

Functions

func ActiveStore added in v1.4.14

func ActiveStore(cfg *config.Config, installed bool) string

Purpose: name the object store custom services should reach. Inputs: loaded config and whether the minio plugin is installed. Outputs: "seaweedfs", "minio-plugin", "minio-core" (v1.4 only) or "none". Constraints: v1.4 follows cfg.Minio.Enabled unchanged; in v1.5 the core store wins over the plugin, the plugin counts only with MinIO intent (cfg.Minio.Enabled), and missing-plugin MinIO intent is rejected separately (E138).

func AuthEntry added in v1.4.14

func AuthEntry(passthrough map[string]string) (entry string, keyMissing bool)

AuthEntry names the image lock entry the auth service runs by default: auth-v14 (nhost/auth:0.36.0) in v1.4; in v1.5 auth (the current release) once the env sets a valid AUTH_ENCRYPTION_KEY, else auth-v14 with keyMissing true. The update plan asks it too (D-0661).

func AuthKeySet added in v1.4.14

func AuthKeySet(passthrough map[string]string) bool

AuthKeySet reports whether passthrough (config.Passthrough, forwarded to the container verbatim) holds a valid AUTH_ENCRYPTION_KEY.

func AuthRefNeedsKey added in v1.4.14

func AuthRefNeedsKey(ref string) bool

AuthRefNeedsKey reports whether an auth image reference is a release from 0.43.0 (tag) or the current lock entry (digest-only), so it needs the key and has migrated a database it ran on one way. The update plan asks it (D-0661).

func CLILockedRef added in v1.4.14

func CLILockedRef(ref string) (string, bool)

CLILockedRef finds the CLI image lock entry whose version a tag reference names, in the short or the docker.io/ spelling. The pre-rename nhost/hasura-auth spelling names nhost/auth (same digests, P7-LIVE-20).

func CLIOwned added in v1.4.14

func CLIOwned(all map[string]string) map[string]string

CLIOwned keeps the services the CLI image lock names and whose image is a literal reference (no variable). The result is keyed by pin key (PinKey), the key the project lock and ResolveImage use, not by compose service name.

func CanonicalRef added in v1.4.14

func CanonicalRef(ref string) string

CanonicalRef reduces an image reference to one spelling for comparison: no digest, no docker.io/, index.docker.io/ or library/ prefix, host and path in lower case, the tag as written (tags are case-sensitive). The bootstrap pins a reference as docker.io/<repo>:<tag>@sha256 while the legacy image strings omit the host, so every comparison of two spellings goes through here (internal/docker cannot be imported: its tests import this package).

func CatalogNames added in v1.3.0

func CatalogNames() []string

CatalogNames returns every catalogued service name, sorted.

func CustomServiceEnvVarNames added in v1.4.3

func CustomServiceEnvVarNames(svc config.CustomService) []string

CustomServiceEnvVarNames returns every environment variable name svc will receive: the fixed core set (FixedCoreEnvVarNames), then its CS_N_ENV_PASSTHROUGH allowlist names in declared order, then its CS_N_ENV explicit keys in declared order. Names only — never the resolved values — so this is safe to print in a dry-run summary.

func DefaultImage added in v1.4.13

func DefaultImage(service string) string

DefaultImage returns the default reference for a service when the caller supplies none: the lock entry rendered in the active pinning mode. The postgres service falls back to the pgvector entry (the pre-lock pin), which is only reachable for an unparseable POSTGRES_VERSION.

func DigestForContent added in v1.0.9

func DigestForContent(b []byte) string

DigestForContent returns the sha256 hex digest for the given bytes. Primarily useful for tests and for computing digests of content the CLI itself generates (manifests, configs). NOT a replacement for pulling an authoritative digest from a registry — that requires talking to the registry API.

func ExistingCacheEngine added in v1.4.14

func ExistingCacheEngine(composeYAML []byte) string

ExistingCacheEngine reads the cache engine out of an existing docker-compose.yml: EngineValkey when the `redis` service image names valkey, EngineRedis when that service exists in any other form (a literal or ${VAR:-default} image, a build) or a redis_data volume is declared, EngineValkey for a valkey_data volume alone, "" when the file shows no cache at all. An unparseable file shows nothing.

func FixedCoreEnvVarNames added in v1.4.3

func FixedCoreEnvVarNames() []string

FixedCoreEnvVarNames returns the environment variable names every custom service receives regardless of CS_N_ENV_PASSTHROUGH or CS_N_ENV, sorted for stable output.

func HasuraEntry added in v1.4.14

func HasuraEntry() string

HasuraEntry names the image lock entry the hasura service runs by default (EPIC D17, P7-LIVE-23): hasura-v14 (graphql-engine v2.44.0) in v1.4, hasura (the current v2.51.0) in v1.5. The update plan asks it too.

The metadata catalog version is 48 on both v2.44.0 and v2.51.0 (P7-LIVE-23 smoke), and v2.44.0 started cleanly on a database v2.51.0 had run on. Rollback is still supported only as restore-then-pin-back, by policy: the CLI does not check the catalog version (Image-Lock wiki page, Roll back).

func ImageRef added in v1.4.13

func ImageRef(name, version string) string

ImageRef returns the image string for lock entry name at the requested version. An empty version, the lock version, or the frozen legacy_ref version (the pre-lock default that config and .env files carry) means "the default": legacy_ref in legacy mode, repository:version@digest in lock mode. That keeps a pin bump from turning the shipped default into an unpinned override. Any other version is an explicit user override and is used as given, unpinned, on the entry's pre-lock repository spelling. An unknown name yields "" (the tests assert every generator name exists).

func IsCLIOwned added in v1.4.14

func IsCLIOwned(service string) bool

IsCLIOwned reports whether a compose service is one the CLI image lock names, looked up under its pin key (nself-admin is pinned as "admin").

func IsValidDigest added in v1.0.9

func IsValidDigest(s string) bool

IsValidDigest returns true if s is a well-formed sha256 digest (64 hex chars, with or without the "sha256:" prefix).

func LoadImageDigests added in v1.0.6

func LoadImageDigests(projectDir string) error

LoadImageDigests reads digest pins from the project config directory. Missing file is not an error (digests are opt-in via `nself update images`).

func LoadProjectPins added in v1.4.14

func LoadProjectPins(projectDir string) error

LoadProjectPins installs the pins of the lock file in projectDir (digest-pinned images and tag-only unpinned entries). A project without a lock has no pins: that is not an error, and any earlier pins are cleared.

func LockError added in v1.4.13

func LockError() error

LockError reports why the embedded lock failed to load (nil when it is sound).

func MarshalLock added in v1.4.13

func MarshalLock(f *LockFile) ([]byte, error)

MarshalLock renders a lock deterministically: 2-space indent, trailing newline, no HTML escaping, platforms with sorted keys.

func NormalizeDigest added in v1.0.9

func NormalizeDigest(s string) (string, error)

NormalizeDigest strips a leading "sha256:" prefix and lower-cases the hex. Returns an error if the input is not a valid sha256 digest.

func ObjectStoragePreflight added in v1.4.14

func ObjectStoragePreflight(cfg *config.Config, profile ProfileName) error

Purpose: stop a v1.5 build that wants MinIO without the minio plugin before it writes anything. Inputs: the loaded config and the build profile ("" means app). Outputs: E138 under the same rule as Generate; nil for profiles without object storage. Constraints: read-only; internal/build calls it right after config load (before secrets, dirs, SSL and nginx), and Generate keeps its own check for other callers.

func PinImage added in v1.0.9

func PinImage(imageTag, digest string) string

PinImage returns the fully-pinned image reference for the given image:tag and digest. If digest is empty the image is returned unchanged (no pin).

PinImage("postgres:16", "abc...") -> "postgres:16@sha256:abc..."
PinImage("postgres:16", "")       -> "postgres:16"

If the image already contains an @sha256: suffix, the existing pin is replaced with the new one (trust the caller — they asked to repin).

func PinKey added in v1.4.14

func PinKey(service string) string

PinKey maps a compose service name to the key of its image pin: the project lock (images, unpinned), the CLI image lock and ResolveImage all use that key. It is the catalog's ImageKey (nself-admin is pinned as "admin") and the name itself for every other service. Every place that looks a compose service up in the lock goes through here (CLIOwned, the build's lock merge, the bootstrap), so a renamed service cannot slip out of the lock again.

func PinNoticeSink added in v1.4.14

func PinNoticeSink(w io.Writer) (restore func())

PinNoticeSink routes the drop notices to w (nil silences them), forgets which notices were already printed, and returns the function that restores the previous writer. Tests use it to count notices.

func PinningMode added in v1.4.13

func PinningMode() string

PinningMode returns the active mode. IMAGE_PINNING=lock|legacy wins (the env cascade is loaded into the process environment before generation); unset, or an invalid value that reached here without config.Load (which rejects it), falls back to the ADR 0021 default: legacy in v1.4, lock in v1.5.

func ProjectPins added in v1.4.14

func ProjectPins() map[string]string

ProjectPins returns a copy of the installed pins.

func ResolveImage

func ResolveImage(service, image string) string

ResolveImage returns the image reference for a service, optionally with a sha256 digest suffix when a project digest is recorded.

Precedence: an explicit *_IMAGE/*_VERSION in the env wins, then the project lock pin (nself.lock.yaml, P7-LIVE-09), then the caller-supplied image (built from config via ImageRef, or ResolvePostgresImage for postgres), then DefaultImage when the caller supplies none. A reference that already carries a digest (lock mode) is left alone.

func ResolvePostgresImage added in v1.3.6

func ResolvePostgresImage(pg config.PostgresConfig) string

ResolvePostgresImage decides which Postgres image `nself build` emits.

Purpose: fix cli#384 — nself build previously ignored the pgvector pin entirely and always emitted postgres:<POSTGRES_VERSION>, silently swapping a running pgvector/pgvector container (uid 999, PGDATA subdir) for a plain alpine postgres image (uid 70, no PGDATA) on every regen. Restarting postgres under the swapped image on a populated database is a data-loss event (P1 EOP staging incident 2026-06-10). Inputs: pg — the resolved PostgresConfig (Image, Version, Extensions). Outputs: the image reference the postgres service should run. Constraints: precedence is fixed and MUST NOT be reordered:

  1. pg.Image (POSTGRES_IMAGE), when set, always wins — an explicit operator pin overrides every inference below it.
  2. pg.Extensions containing "pgvector" (POSTGRES_EXTENSIONS) selects the pgvector image matching the configured Postgres major version.
  3. Otherwise, postgres:<POSTGRES_VERSION> (unchanged default behavior).

buildPostgresService derives PGDATA and the container uid from the resulting image name (alpine vs. debian-family), so getting this precedence right also fixes PGDATA/uid preservation: a pgvector or other debian-family image always resolves to uid 999 + PGDATA, matching what the upstream image actually requires.

func SaveImageDigests added in v1.0.6

func SaveImageDigests(projectDir string, digests map[string]string) error

SaveImageDigests writes digest pins to the project config directory.

func SetExistingCacheEngine added in v1.4.14

func SetExistingCacheEngine(engine string) (restore func())

SetExistingCacheEngine installs the engine the project's existing compose shows (ExistingCacheEngine; "" = no evidence) for one render and returns the function that restores the previous value. The build calls it when the lock has no redis pin, so an image the bootstrap cannot pin (${VAR} forms, a build: section) or a bare redis_data volume still counts as a running cache.

func SetProjectPins added in v1.4.14

func SetProjectPins(pins map[string]string) (restore func())

SetProjectPins installs pins (service -> reference) and returns a function that restores the previous set. A nil or empty map clears the pins.

func SplitImageRef added in v1.0.9

func SplitImageRef(ref string) (name, tag, digest string)

SplitImageRef splits an image reference into its constituent parts:

SplitImageRef("postgres:16@sha256:abc...")
-> name="postgres", tag="16", digest="abc..."

SplitImageRef("ghcr.io/foo/bar:v1")
-> name="ghcr.io/foo/bar", tag="v1", digest=""

SplitImageRef("alpine")
-> name="alpine", tag="latest", digest=""

Registries with port numbers (localhost:5000/foo:v1) are handled by scanning right-to-left for the tag separator.

func ToggleService added in v1.0.16

func ToggleService(yaml, serviceName string, enable bool) (string, bool, error)

ToggleService comments or uncomments the named service block in the supplied docker-compose YAML text. It returns the new YAML text and a bool reporting whether the file was changed.

enable=true → uncomment a previously disabled block (no-op if already enabled) enable=false → comment out an enabled block (no-op if already disabled)

func ValidProfiles added in v1.1.11

func ValidProfiles() []string

ValidProfiles returns the list of known profile names in deterministic order. Used by --help text and shell completions.

Types

type BuildConfig

type BuildConfig struct {
	Context    string `yaml:"context"`
	Dockerfile string `yaml:"dockerfile,omitempty"`
	// Target selects a multi-stage build target (CS_N_BUILD_TARGET).
	Target string `yaml:"target,omitempty"`
}

BuildConfig represents the build context for a service.

type CatalogEntry added in v1.3.0

type CatalogEntry struct {
	// Name is the compose service name, matching the key in DockerCompose.Services.
	Name string
	// Tier is required or optional.
	Tier ServiceTier
	// Purpose is a one-line description for docs and `service list`.
	Purpose string
	// EnableEnv is the environment variable that switches an optional service
	// on. Empty for required services, which have no off switch.
	EnableEnv string
	// VersionEnv is the environment variable that overrides the image tag.
	VersionEnv string
	// DefaultImage is the pinned image used when VersionEnv is unset. Resolved
	// from the image lock (images.yaml) so version bumps have a single home.
	DefaultImage string
	// ImageKey overrides the the image lock (images.yaml) lookup key when the compose
	// service name differs from it (nself-admin is pinned under "admin").
	ImageKey string
}

CatalogEntry describes one service in the stack.

func CatalogEntryFor added in v1.3.0

func CatalogEntryFor(name string) (CatalogEntry, bool)

CatalogEntryFor looks a service up by compose name.

func CoreServices added in v1.3.0

func CoreServices() []CatalogEntry

CoreServices returns the services present in every app-profile stack.

func OptionalServices added in v1.3.0

func OptionalServices() []CatalogEntry

OptionalServices returns the services that require a config gate.

func ServiceCatalog added in v1.3.0

func ServiceCatalog() []CatalogEntry

ServiceCatalog returns every catalogued service with its default image resolved from the image lock (images.yaml).

type DepOn

type DepOn struct {
	Condition string `yaml:"condition"`
}

DepOn represents a service dependency with a condition.

type DeployConfig

type DeployConfig struct {
	Resources *Resources `yaml:"resources,omitempty"`
}

DeployConfig represents deployment constraints for a service.

type DockerCompose

type DockerCompose struct {
	Name         string                   `yaml:"name"`
	Networks     map[string]NetworkConfig `yaml:"networks"`
	Volumes      map[string]VolumeConfig  `yaml:"volumes"`
	Services     map[string]ServiceConfig `yaml:"-"`
	ServiceOrder []string                 `yaml:"-"`
}

DockerCompose represents a complete docker-compose.yml file. Services are stored as a map for fast lookup, but ServiceOrder tracks insertion order so that MarshalYAML emits them in dependency order (init containers before their dependents, postgres before hasura, nginx last).

func (*DockerCompose) AddService

func (dc *DockerCompose) AddService(name string, svc ServiceConfig)

AddService inserts a service into the compose file, preserving insertion order via ServiceOrder. If the service name already exists, it is replaced in-place without changing the order.

func (*DockerCompose) MarshalYAML

func (dc *DockerCompose) MarshalYAML() (interface{}, error)

MarshalYAML outputs the compose file with services in ServiceOrder rather than Go's default alphabetical map ordering. This ensures init containers appear before services that depend on them, which Docker Compose v5 requires.

type Generator

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

Generator builds a docker-compose.yml from project configuration.

func NewGenerator

func NewGenerator(cfg *config.Config) *Generator

NewGenerator creates a compose Generator from the given config using the default "app" profile (full service set — no regression from pre-profile builds).

func NewGeneratorWithProfile added in v1.1.11

func NewGeneratorWithProfile(cfg *config.Config, name ProfileName) *Generator

NewGeneratorWithProfile creates a compose Generator that emits only the services permitted by the named profile. Unknown profile names fall back to ProfileApp and are not treated as hard errors here (the caller should warn).

Purpose: enable curated deployments (e.g. ProfileOps for an observability server) without touching the config layer. Inputs: cfg — project configuration; name — profile selected by the user. Outputs: *Generator with profile gate set.

func (*Generator) Generate

func (g *Generator) Generate() ([]byte, error)

Generate produces the complete docker-compose.yml as YAML bytes. It marshals a DockerCompose struct via gopkg.in/yaml.v3.

func (*Generator) WithEnvOverlay added in v1.4.14

func (g *Generator) WithEnvOverlay(files map[string][]byte) *Generator

WithEnvOverlay sets pending env-file bytes (project-relative path -> bytes) that CS_N_ENV_FILE reads use instead of the files on disk, and returns the same Generator. The build sets it in plan mode only (P7-LIVE-05), so a plan of a pending `config set` sees the value a custom service will get.

func (*Generator) WithWorkDir added in v1.3.6

func (g *Generator) WithWorkDir(dir string) *Generator

WithWorkDir sets the project root used to resolve CS_N_ENV_FILE paths and returns the same Generator for chaining. Callers that build compose from a known project directory (rather than assuming os.Getwd()) should always set this — see internal/build/orchestrator_build_compose.go.

type Healthcheck

type Healthcheck struct {
	Test        []string `yaml:"test"`
	Interval    string   `yaml:"interval,omitempty"`
	Timeout     string   `yaml:"timeout,omitempty"`
	Retries     int      `yaml:"retries,omitempty"`
	StartPeriod string   `yaml:"start_period,omitempty"`
}

Healthcheck represents a service health check configuration.

type ImageInput added in v1.4.14

type ImageInput struct {
	Service string   // compose service name; also the lock pin key
	Entry   string   // image lock entry the generator renders for it
	Vars    []string // variables that feed the rendered reference, precedence order
	// NotInitDefault marks an entry whose version nself init never writes into .env
	// (hasura: init writes v2.44.0, the hasura-v14 entry). Setting a variable to that
	// version is a deliberate choice, so it is an override and not a default.
	NotInitDefault bool
}

ImageInput is one row of the table.

func ImageInputs added in v1.4.14

func ImageInputs() []ImageInput

ImageInputs returns a copy of the table.

func (ImageInput) ImageVars added in v1.4.14

func (in ImageInput) ImageVars() []string

ImageVars returns the full-reference variables (*_IMAGE) of the row: the only ones whose value can carry a digest.

func (ImageInput) Set added in v1.4.14

func (in ImageInput) Set(getenv func(string) string) string

Set returns the first variable of the row that is explicitly set, in precedence order, or "". A variable holding nothing, or the default of one of the service's lock entries (what nself init writes into .env; Ref.IsDefaultVersion, the test ImageRef applies), is not set: it renders the CLI default, so it must not drop a pin.

type LockFile added in v1.4.13

type LockFile struct {
	Generated     string `json:"_generated"`
	SchemaVersion string `json:"schema_version"`
	Images        []Ref  `json:"images"`
}

LockFile is the decoded images.lock.json.

func ParseLock added in v1.4.13

func ParseLock(data []byte) (*LockFile, error)

ParseLock decodes and validates a lock: header, schema version, entries sorted by name and unique, every field present, an index digest and at least linux/amd64, and a mirror that is null exactly for role plugin.

type LoggingConfig

type LoggingConfig struct {
	Driver  string            `yaml:"driver"`
	Options map[string]string `yaml:"options,omitempty"`
}

LoggingConfig represents the logging driver and options for a service.

type NetworkConfig

type NetworkConfig struct {
	Driver string `yaml:"driver,omitempty"`
	// Name pins the real Docker network name. Without it, compose prefixes the
	// project name (e.g. key "myproj_network" becomes "myproj_myproj_network"),
	// which split recreated services onto a new network on existing deployments
	// (P1 EOP prod incident 2026-06-10: nginx 502 on api.nself.org).
	Name string `yaml:"name,omitempty"`
	// External marks a network that already exists and is not created by this
	// compose file (CS_N_NETWORKS: another <PROJECT_NAME>_* network).
	External bool `yaml:"external,omitempty"`
}

NetworkConfig represents a docker-compose network definition.

type ProfileName added in v1.1.11

type ProfileName string

ProfileName identifies a named service profile.

const (
	// ProfileApp is the default profile: every service enabled by config
	// is included. Identical to pre-profile behaviour — no regression.
	ProfileApp ProfileName = "app"

	// ProfileOps is the observability + CI + functions + registry profile.
	// Core data services (postgres, hasura, auth, nginx) plus the monitoring
	// stack are included. App-specific services (minio, mailpit, admin,
	// functions-v8 SaaS, search, nself-admin) are excluded.
	//
	// Reserve service name stubs for ops-only services whose compose fragments
	// will be contributed by dedicated plugins (forgejo, container-registry,
	// functions-v8). Listing them here documents the intended topology even
	// before those plugins exist.
	ProfileOps ProfileName = "ops"
)

type Ref added in v1.4.13

type Ref struct {
	Name        string            `json:"name"`
	Role        string            `json:"role"`
	Repository  string            `json:"repository"`
	Version     string            `json:"version"`
	IndexDigest string            `json:"index_digest"`
	Platforms   map[string]string `json:"platforms"`
	LegacyRef   string            `json:"legacy_ref"`
	License     string            `json:"license"`
	Source      string            `json:"source"`
	Mirror      *string           `json:"mirror"`
}

Ref is one lock entry. JSON field order is the contract's.

func LockedImages added in v1.4.13

func LockedImages() []Ref

LockedImages returns every lock entry sorted by name (a copy).

func LockedRef added in v1.4.13

func LockedRef(name string) (Ref, bool)

LockedRef returns the lock entry for name.

func (Ref) IsDefaultVersion added in v1.4.14

func (r Ref) IsDefaultVersion(v string) bool

IsDefaultVersion reports whether v means "use the default" for this entry: it is blank, the lock version, or the frozen legacy_ref version that config defaults and `nself init` .env files carry. It is the one definition of an explicit override: ImageRef (imageFor) and the project pin rule (projectPin) both ask it, so a *_VERSION holding the CLI default never counts as set.

func (Ref) LegacyRepository added in v1.4.13

func (r Ref) LegacyRepository() string

LegacyRepository is legacy_ref without its tag, the repository spelling the CLI used before the lock (for example `redis`, `docker.io/pgsty/minio`).

func (Ref) LegacyVersion added in v1.4.13

func (r Ref) LegacyVersion() string

LegacyVersion is the tag of legacy_ref: the version the CLI ran before the lock, which config defaults and `nself setup` .env files still carry. It stays frozen when a pin bump moves Version.

func (Ref) String added in v1.4.13

func (r Ref) String() string

String is the lock-mode reference: repository:version@index_digest.

type ResourceLimits

type ResourceLimits struct {
	Memory string `yaml:"memory,omitempty"`
	CPUs   string `yaml:"cpus,omitempty"`
	Pids   int64  `yaml:"pids,omitempty"`
}

ResourceLimits represents CPU and memory limits.

type Resources

type Resources struct {
	Limits       *ResourceLimits `yaml:"limits,omitempty"`
	Reservations *ResourceLimits `yaml:"reservations,omitempty"`
}

Resources represents resource constraints.

type ServiceConfig

type ServiceConfig struct {
	Image         string            `yaml:"image,omitempty"`
	Build         *BuildConfig      `yaml:"build,omitempty"`
	ContainerName string            `yaml:"container_name,omitempty"`
	Restart       string            `yaml:"restart,omitempty"`
	ShmSize       string            `yaml:"shm_size,omitempty"`
	User          string            `yaml:"user,omitempty"`
	GroupAdd      []string          `yaml:"group_add,omitempty"`
	Networks      []string          `yaml:"networks,omitempty"`
	NetworkMode   string            `yaml:"network_mode,omitempty"`
	DependsOn     map[string]DepOn  `yaml:"depends_on,omitempty"`
	Environment   map[string]string `yaml:"environment,omitempty"`
	Volumes       []string          `yaml:"volumes,omitempty"`
	Ports         []string          `yaml:"ports,omitempty"`
	Expose        []string          `yaml:"expose,omitempty"`
	Command       interface{}       `yaml:"command,omitempty"`
	Entrypoint    interface{}       `yaml:"entrypoint,omitempty"`
	Healthcheck   *Healthcheck      `yaml:"healthcheck,omitempty"`
	Deploy        *DeployConfig     `yaml:"deploy,omitempty"`
	Logging       *LoggingConfig    `yaml:"logging,omitempty"`
	SecurityOpt   []string          `yaml:"security_opt,omitempty"`
	CapDrop       []string          `yaml:"cap_drop,omitempty"`
	CapAdd        []string          `yaml:"cap_add,omitempty"`
	StopGrace     string            `yaml:"stop_grace_period,omitempty"`
	Labels        map[string]string `yaml:"labels,omitempty"`
	Profiles      []string          `yaml:"profiles,omitempty"`
	ReadOnly      bool              `yaml:"read_only,omitempty"`
	Tmpfs         []string          `yaml:"tmpfs,omitempty"`
	Privileged    bool              `yaml:"privileged,omitempty"`
	WorkingDir    string            `yaml:"working_dir,omitempty"`
	StdinOpen     bool              `yaml:"stdin_open,omitempty"`
	Tty           bool              `yaml:"tty,omitempty"`

	// CapDropComment is an optional comment injected into the generated YAML
	// above cap_add when cap_drop is intentionally omitted. Not serialized as
	// a YAML field — rendered as a comment via MarshalYAML.
	CapDropComment string `yaml:"-"`
}

ServiceConfig represents a single service in docker-compose.yml.

type ServiceSecurity

type ServiceSecurity struct {
	CapDrop     []string
	CapAdd      []string
	SecurityOpt []string
	ReadOnly    bool
	Tmpfs       []string
	User        string
}

ServiceSecurity holds Docker security configuration for a service.

func DefaultSecurity

func DefaultSecurity() ServiceSecurity

DefaultSecurity returns the security config applied to most services. read_only root FS with /tmp and /run as tmpfs.

func InitContainerSecurity added in v1.4.11

func InitContainerSecurity() ServiceSecurity

InitContainerSecurity returns the security config for ownership-fixing init containers (meilisearch-init). They run as root with CapDrop ALL, and "chown -R 1000:1000 /data; chmod -R 755 /data" then fails with "Operation not permitted" on any data dir it did not create, which aborted nself start and left nginx created but never started (nself-web prod, 2026-09-23). CHOWN changes owners, FOWNER lets chmod act on files owned by another uid, DAC_READ_SEARCH lets root descend into a 0700 directory once it no longer owns it. Verified minimal on a Linux volume: dropping any one fails.

func MinioSecurity added in v1.0.6

func MinioSecurity() ServiceSecurity

MinioSecurity returns the security config for the MinIO service. MinIO needs CHOWN/SETUID/SETGID for data directory ownership.

func NginxSecurity added in v1.0.6

func NginxSecurity() ServiceSecurity

NginxSecurity returns the security config for the Nginx service. Nginx needs NET_BIND_SERVICE for ports 80/443 when running non-root.

DAC_READ_SEARCH is required because CapDrop: ALL takes away root's usual ability to ignore file permissions, and the TLS material is bind-mounted from the host with host ownership. privkey.pem is written 0600 by mkcert/openssl and owned by whoever ran `nself build`, so without this the master cannot open it and nginx exits with

[emerg] cannot load certificate ".../fullchain.pem": Permission denied

then crash-loops. The alternative was relaxing the private key to be world-readable on the host, which is a worse trade: this grants read and traverse bypass to one container that must read TLS material at startup, whereas DAC_OVERRIDE would also grant write bypass, and a 0644 key would expose it to every user on the machine.

func PostgresSecurity

func PostgresSecurity() ServiceSecurity

PostgresSecurity returns the security config for the PostgreSQL service. PostgreSQL needs IPC_LOCK for shared memory and CHOWN/SETUID/SETGID for initdb. Root FS is read-only; data dir is a writable volume.

func RedisSecurity added in v1.0.6

func RedisSecurity() ServiceSecurity

RedisSecurity returns the security config for the Redis service.

type ServiceSet added in v1.1.11

type ServiceSet struct {
	// CoreDB enables postgres (unless EmbeddedPG is active).
	CoreDB bool
	// Hasura enables the Hasura GraphQL engine.
	Hasura bool
	// Auth enables the nhost/hasura-auth service.
	Auth bool
	// Nginx enables the nginx reverse proxy (always last in the compose file).
	Nginx bool

	// Redis enables the Redis cache/queue service (when cfg.Redis.Enabled).
	Redis bool
	// Minio enables the MinIO object storage service (when cfg.Minio.Enabled).
	Minio bool
	// Mailpit enables the Mailpit dev SMTP server (when cfg.Mailpit.Enabled).
	Mailpit bool
	// AdminUI enables the nSelf Admin web UI (when cfg.Admin.Enabled).
	AdminUI bool
	// Functions enables the Functions runtime (when cfg.Functions.Enabled).
	Functions bool
	// Search enables the search engine (meilisearch/typesense) when configured.
	Search bool

	// Monitoring enables the monitoring stack (prometheus, grafana, loki, etc.)
	// when cfg.Monitoring.Enabled. The compose services are contributed by the
	// nself-monitoring plugin; this flag only gates the config rendering step.
	Monitoring bool

	// OpsServices is true when ops-profile-specific reserved service stubs are
	// declared. Actual compose fragments for forgejo, container-registry, and
	// functions-v8 are contributed by dedicated plugins; this flag marks intent.
	//
	// Reserved ops service names (F08-SERVICE-INVENTORY):
	//   - forgejo          (lightweight Gitea-compatible forge for CI/CD)
	//   - container-registry (OCI-compatible image registry, e.g. Zot/Distribution)
	//   - functions-v8     (Deno V8-isolate function runtime, ops-server variant)
	OpsServices bool
}

ServiceSet describes which service families are allowed in a profile. Every bool field corresponds to a builder or conditional block in generator.go. Fields default to false; set only what the profile needs.

func ProfileForName added in v1.1.11

func ProfileForName(name ProfileName) (ServiceSet, bool)

ProfileForName returns the ServiceSet for the given profile name. Falls back to the ProfileApp set if the name is unrecognised, and returns false as the second value so callers can warn the user.

Callers: compose.Generator, build.Build.

type ServiceTier added in v1.3.0

type ServiceTier string

ServiceTier says whether a service is part of every stack or opt-in.

const (
	// TierRequired services are present in every app profile. Removing one
	// produces a stack that cannot serve a request.
	TierRequired ServiceTier = "required"

	// TierOptional services are added only when their config gate is enabled.
	TierOptional ServiceTier = "optional"
)

type VolumeConfig

type VolumeConfig struct {
	Driver string `yaml:"driver,omitempty"`
}

VolumeConfig represents a docker-compose volume definition.

Directories

Path Synopsis
Package monitoring — alert rule and Alertmanager config generators.
Package monitoring — alert rule and Alertmanager config generators.

Jump to

Keyboard shortcuts

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