EasyP

Installation

Container image tags, the Helm chart and its required values, the compose stack, and release binaries.

Every release publishes a container image, a Helm chart and binaries. The current release is v1.0.2 (chart version 1.0.2).

What the service needs

DependencyRequiredNotes
PostgreSQLyesOne DSN in DB_POSTGRES_DSN. The service creates its own tables.
S3-compatible object storagenoWithout it, plugin binaries must already be on the service's disk under registry.plugins_dir.
A writable volume for plugins_diryesPlugin cache and download staging. Sized above registry.cache_max_bytes (20 GiB by default).
Prometheus, an OTLP collector, PyroscopenoMetrics are always served; traces and profiles only when an endpoint is set.

Container image

ghcr.io/easyp-tech/service, multi-architecture (linux/amd64, linux/arm64).

TagMeaning
v1.0.2A release. Immutable.
latestThe newest release. Moves only when a release is tagged.
edgeThe tip of the master branch. Moves on every push.
sha-<short>One commit. Immutable.

Pin vX.Y.Z in production.

The image runs as UID 65532, its entrypoint is /easyp-svc, and it declares a HEALTHCHECK that runs easyp-svc health against /live on the health port. The probe does not see the start command's --cfg, so if ports are set in a config file, point EASYP_CONFIG at that file on the container — both the service and the probe read it:

environment:
  EASYP_CONFIG: /etc/easyp/config.yml
command: ["service", "start"]

Without it the container serves normally but reports unhealthy.

Helm

kubectl create secret generic easyp-env \
  --from-literal=DB_POSTGRES_DSN='postgres://user:pass@host:5432/easyp?sslmode=require'

helm install easyp oci://ghcr.io/easyp-tech/charts/easyp-service \
  --version 1.0.2 \
  --set secrets.existingSecret=easyp-env \
  --set tls.enabled=false

That is a running service with no transport security and no writes enabled — enough to confirm it works, not enough to expose.

What the chart refuses to install without

The chart checks these at render time and fails with a message naming the missing value:

ConditionError names
No database DSNsecrets.existingSecret (or secrets.create=true with secrets.data)
tls.enabled=true (the default) with no certificatetls.serverSecret or certManager.enabled
ingress.enabled=true with no trusted proxiesconfig.server.trustedProxies
generationTimeoutSeconds < forceShutdownAfterSeconds < terminationGracePeriodSeconds violatedthe three values
maxConcurrentGenerations × maxOutputSize does not fit the memory limitresources.limits.memory
Cache volume not larger than cacheMaxBytespersistence.size / persistence.ephemeralSizeLimit

Secret keys

The pod loads the secret with envFrom, so the keys are environment variable names:

KeyWhen
DB_POSTGRES_DSNAlways.
REGISTRY_S3_ACCESS_KEY_ID, REGISTRY_S3_SECRET_ACCESS_KEYWhen config.registry.s3.bucket is set.
LICENSE_KEYEnterprise. Absent means Community.
AUTH_WRITE_TOKENSTo allow writes: name=<sha256>,name=<sha256>. Absent means no writes.

Prefer secrets.existingSecret. Values passed through secrets.data end up in Helm release history.

Values worth knowing

ValueDefaultWhy it matters
replicaCount1Do not raise it on a shared volume. See Architecture.
image.tag"" (chart appVersion)Pin it.
ports.grpc / metric / health / mcp8080 / 8081 / 8082 / 8083The chart overrides the binary's 23410–23413.
mcp.enabledfalseMCP sits outside the gRPC interceptor chain.
config.server.trustedProxies[]Required behind an ingress, else every client shares one rate-limit bucket.
config.workerPool.*binary defaultsworkers: 4, queueSize: 16, maxConcurrentGenerations: 16, generationTimeoutSeconds: 120.
config.registry.s3.bucket""Empty means local mode.
config.license.publicKeyseasyp.tech key 2026-08The licence trust anchor. Replace only if you issue your own licences.
tls.enabled / tls.clientCASecrettrue / ""With a CA the listener requires client certificates (mTLS). "-" disables the client check.
certManager.enabledfalseLet cert-manager issue server and ingress client certificates.
ingress.*disabled, TraefikDefaults target Traefik because it can express an mTLS backend leg (ServersTransport).
persistence.size25GiMust exceed cacheMaxBytes.
resources.limitscpu: 4, memory: 4GiSized for 16 generations × 64 MiB output, twice.
serviceMonitor.enabled, prometheusRule.enabledfalseNeed the Prometheus Operator CRDs. Turn on where you run it.
prometheusRule.runbookBaseUrlhttps://easyp.tech/docs/api-service/runbooksEvery alert links to a section of Runbooks.
networkPolicy.enabledtrueEgress limited to DNS, 5432, 443 and 4317. Add ports if your database, storage or collector use others.
reloader.enabledtrueRestarts on certificate rotation if stakater/Reloader is installed.

Every value, with the chart's own description, is in the Helm values reference.

The NetworkPolicy is the one isolation control that ships on by default. It is the chart's, not the service's: plugins inherit it only because they run in the same pod. See Security.

Docker Compose

deploy/docker-compose.yml in the service repository is the development stack: PostgreSQL, RustFS as S3, Traefik with mutual TLS in front, and a Grafana/Loki/ Tempo/Mimir/Pyroscope suite. It is driven by task up and is the reference for how the pieces fit, not a production template. A minimal compose file is in the Quickstart.

Binaries

easyp-svc for linux and darwin, amd64 and arm64, on the releases page. The same binary is the server and the operator CLI.

Plugins built by easyp-svc plugins build are Linux binaries, so a service running natively on macOS can register them but not execute them (exec format error). Run the service in a Linux container on macOS.

Go modules

ModuleLicenceUse
github.com/easyp-tech/serviceElastic-2.0The service. Not meant to be imported.
github.com/easyp-tech/service/apiApache-2.0Generated gRPC contract.
github.com/easyp-tech/service/sdkApache-2.0Go client.

They are tagged together: v1.0.2, api/v1.0.2, sdk/v1.0.2.

On this page