deploy/app.env.example
Rama main · réplica de lectura del repositorio original.
# shellcheck shell=bash
# ════════════════════════════════════════════════════════════════════════════
# app.env — the ONE config for an app installed by the deploy/ framework
#
# Every script sources this file, so it is the single source of truth.
# Copy it and edit the values:
#
# cp deploy/app.env.example <your-app>/deploy/app.env
#
# It is plain bash: `KEY="value"`, and everything after # is a comment.
# Paths may reference earlier keys (INSTALL_DIR uses ${APP_NAME}).
#
# A block below is only needed for the mode you actually use: fill the
# "source mode" block OR the "binary mode" block, not both.
# ════════════════════════════════════════════════════════════════════════════
# ── Identity ───────────────────────────────────────────────────────────────
APP_NAME="myapp" # short lower-case name: log prefix [myapp], unit name, default paths
APP_DESC="My App — a service that does things" # one line for the systemd Description
# ── Distribution ───────────────────────────────────────────────────────────
DIST="source" # "source" = git checkout, "binary" = release artifact
# ── source mode ────────────────────────────────────────────────────────────
REPO_URL="" # git URL (https://...; file://... works too, e.g. for tests)
CHECKOUT_POLICY="stable" # stable | latest | prerelease | <branch> (stable = newest tag without '-')
# in binary mode a <branch> is rejected — a branch has no release asset
# ── binary mode ────────────────────────────────────────────────────────────
# RELEASE_API is the LIST endpoint (…/releases?per_page=N), not /releases/latest:
# /latest silently excludes prereleases and cannot express CHECKOUT_POLICY.
RELEASE_API="" # unauthenticated = 60 req/hour/IP; a 403/429 tells you to pass --version <tag>
RELEASES_BASE="" # download base; asset URL = ${RELEASES_BASE}/${TAG}/${ASSET}
# Single quotes are REQUIRED: every script SOURCES this file, so double quotes
# would expand ${APP_NAME}/${OS}/${ARCH}/${TAG} at load time and render_template()
# would have nothing left to substitute.
ASSET_PATTERN='${APP_NAME}-${TAG}-${OS}-${ARCH}.tar.gz' # may be a plain binary or a .tar.gz payload
APP_VERSION_CMD='${BIN} --version' # must print "APP_NAME <version>"; ${BIN} = the binary path
# ── binary mode: payload shape ─────────────────────────────────────────────
# The four lists describe THIS app's release tarball — its executable name, its
# native libraries, its example files. The defaults are SynaptoMind's, so an app
# with a different payload names its own here rather than editing framework code.
# BINARY_SUPPORTED_PLATFORMS="linux-x86_64" # "os-arch" list, space separated
# BINARY_REQUIRED_FILES="synaptomind vec0.so lib/libonnxruntime.so.1" # verified before anything is touched
# BINARY_ROLLBACK_FILES="vec0.so lib/libonnxruntime.so.1 synaptomind" # kept as <file>.prev for a no-git rollback
# BINARY_SWAP_ORDER="vec0.so lib/libonnxruntime.so.1 config.json.example .env.example synaptomind"
# ── Paths ──────────────────────────────────────────────────────────────────
INSTALL_DIR="/opt/${APP_NAME}" # code/binary live here; empty -> /opt/${APP_NAME}
DATA_DIR="/var/lib/${APP_NAME}" # persistent data; empty disables the ./data symlink
RUN_DIR="" # state (scripts, hooks, config); empty -> ${HOME}/.${APP_NAME}
# ── First-run seeding (copied only when the destination does NOT exist) ─────
# An "example:dest" pair copies ${INSTALL_DIR}/<example> to <dest>. The source is
# always resolved against INSTALL_DIR — the payload ships the examples — so only
# the DESTINATION differs between the two lists. A seeded config.json has
# "port"/"httpPort" aligned to PORT/MCP_PORT, on the seeding path only.
SEED_FILES="config.json.example:config.json .env.example:.env" # "example:dest" pairs into INSTALL_DIR, space separated
SEED_FILES_DATA="" # the same pairs, seeded into DATA_DIR instead — for an app whose config home is /var/lib/<app> rather than the payload tree (empty = off)
CONFIG_LINK_NAME="" # bare FILE NAME (e.g. "config.json"); empty = no link. Seeds into DATA_DIR? Then this is how the app finds it:
# ${INSTALL_DIR}/<name> -> ${DATA_DIR}/<name>, created/refreshed AFTER seeding. Use it when the app resolves its
# config relative to its WorkingDirectory (/opt/<app>) and has no path flag — the link is what lets the config
# live in DATA_DIR and survive a payload swap. An app that takes --settings / STATE_DIRECTORY / an
# EnvironmentFile needs none. A real file at the link path is reported, never replaced. Name a dest in
# ONE list only: in both, the install produces two files and the link step refuses to replace the
# payload-tree one (with a warning naming the move that fixes it).
GENERATE_SECRET_IN=".env" # add <APP_NAME>_SECRET=<uuid> here when seeded (empty = off)
# an ABSOLUTE path is used as given (e.g. "/etc/myapp/myapp.env"); a relative one resolves under INSTALL_DIR. Parent directories are created.
# ── Runtime / service ──────────────────────────────────────────────────────
SERVICE_USER="" # systemd User=; empty -> invoking user (SUDO_USER when run via sudo)
SERVICE_GROUP="" # systemd Group=; empty -> TARGET_GROUP, which itself defaults to SERVICE_USER. Group= is ALWAYS rendered, so the line and the chown agree; the group must already exist
EXEC_START="" # start command; empty -> mode-specific default (binary / bun run …)
PORT="3000" # port written to the seeded config and used by the health check
MCP_PORT="" # optional; port written to mcp.httpPort in a seeded config. Empty -> PORT + 1. Must differ from PORT
HEALTH_URL="" # empty -> http://127.0.0.1:${PORT}/health
HEALTH_TIMEOUT="60" # seconds to wait for a healthy service after (re)start
HEALTH_CONFIRM_TIMEOUT="30" # second window, used only when the first expired with NO answer
# ── Health contract ────────────────────────────────────────────────────────
# Which JSON keys wait_health() reads, and what counts as healthy. The defaults
# are SynaptoMind's own /health shape; an app that answers {"ok":true} — no
# status, no version — sets its own three keys instead of being reported as a
# contract violation on a perfectly healthy service.
# The field names must be plain JSON keys (letters, digits, _). They are put into
# a pattern, and a name carrying `.` or `*` would match more than the field it names.
HEALTH_STATUS_FIELD="status" # key carrying the state
HEALTH_OK_VALUES="ok degraded" # values of that key that mean healthy; space separated
HEALTH_VERSION_FIELD="version" # key carrying the version; EMPTY disables the version check (and warns once)
# ── Unit extras (each rendered only when non-empty) ────────────────────────
# Needed by an app the fixed template cannot express. All three are guarded by
# the same check as every other value that lands in a unit file.
UNIT_STATE_DIRECTORY="" # e.g. "myapp" -> StateDirectory= + StateDirectoryMode=0700, exports STATE_DIRECTORY
UNIT_ENV_FILE="" # e.g. "/etc/myapp/myapp.env" -> EnvironmentFile=
UNIT_EXTRA_ENV="" # "K=V" pairs, SPACE separated, one Environment= line each (e.g. "BUN_RUNTIME_TRANSPILER_CACHE_PATH=0"). A TAB or a newline separates nothing — it is refused, because the guard reads those as a line break in the unit (task #1117)
# ── source mode: dependencies & build ─────────────────────────────────────
# Flags for `bun install`, run in INSTALL_DIR as the service user. Drop
# --production when BUILD_CMD is set: a build needs its devDependencies, and
# --production prunes exactly those.
INSTALL_FLAGS="--frozen-lockfile --production"
BUILD_CMD="" # e.g. "bun run build"; run in INSTALL_DIR as the service user. Empty = no build step
BUILD_TIMEOUT="600" # seconds; a build that hangs aborts the install instead of hanging it
# a non-zero BUILD_CMD aborts the install (a failed build is a missing artefact)
# ── host requirements ──────────────────────────────────────────────────────
REQUIRES_BUN="yes" # yes -> install Bun when missing and run `bun install`
SYSTEM_DEP_CMDS="git tar" # OS packages the mode needs (source: "git"; binary: "tar" + git for the updater bootstrap)
HOOKS_DIR="" # pre-update / post-update hooks; empty -> ${RUN_DIR}/hooks
LIB_RAW_URL="" # curl|bash: lib/common.sh source; optional (defaults to the published deploy base)
# ── curl|bash only (environment variables, not needed for a local checkout) ─
# In the piped form BOTH LIB_RAW_URL (above) and APP_ENV_URL are optional:
# install.sh defaults them to the published deploy base (DEPLOY_RAW_URL).
# Set either only to install from a fork or mirror.
# APP_ENV_URL="https://example.com/myapp/app.env" # published app.env for the one-liner