Skip to main content
Version: master

PVR Builtin Templates & Variables

The pvr tool uses a builtin template system to generate the run.json manifest and lxc.container.conf configuration file for containers. This generation happens when using commands like pvr app add or when processing pvrexport contents.

These templates utilize the standard Go text/template engine with custom functions (pvr_ifNull, pvr_isSlice, etc.) and the sprig library.

Template Source

The core templates are defined in templates/builtin-lxc-docker.go.

Template functions come from three sets:

  • sprig functions, available both unprefixed (splitList, trimPrefix, quote, join, hasKey, ...) and with a sprig_ prefix.
  • gtf functions, available with a gtf_ prefix only.
  • pvr helpers, available with a pvr_ prefix only (pvr_ifNull, pvr_isSlice, pvr_sliceIndex, pvr_sliceFrom, pvr_sliceTo, pvr_isEmpty, pvr_jsonIndent, pvr_dockerVolumeName, pvr_mergePersistentMaps).

Context Namespaces

The templates have access to several namespaces:

  • .Source: The container's src.json as a map (see below).
  • .Docker: Configuration derived from the Docker image manifest, overlaid with src.json's config section.
  • .EffectiveGroup: The group written to run.json. Resolved from PV_GROUP; if neither PV_GROUP nor PV_RUNLEVEL is set, the default group from groups.json is used.

Source Context (.Source)

FieldDescription
.Source.nameContainer/app name (the directory name).
.Source.baseBase app name when the container is an overlay on another rootfs.
.Source.argsThe args map — all PV_* / LXC_* variables documented below.
.Source.persistencePer-path persistence map (permanent, revision, boot, optional @<disk> suffix, optional ovl: prefix).
.Source.exportsList of export globs, copied into run.json as exports.
.Source.logsLog configuration, copied into run.json as logs.
.Source.dm_enabledMap of volumes to be verity/dm protected; those entries get a dm: prefix in run.json.
.Source.docker_ovl_digestSet when the rootfs is an overlay (root.ovl.squashfs) on top of base.

Docker Context (.Docker)

When a Docker image is converted to a Pantavisor pvrexport, pvr extracts metadata from the Docker image manifest and populates the .Docker namespace. These values are used to determine the default execution behavior (init command, environment, working directory).

Standard Docker Variables

VariableSourceDescription
.Docker.EntrypointEntrypointThe command to run as PID 1.
.Docker.CmdCmdArguments to the Entrypoint.
.Docker.EnvEnvEnvironment variables defined in the image.
.Docker.WorkingDirWorkingDirDefault working directory for the process.
.Docker.VolumesVolumesList of volumes defined as VOLUME in Dockerfile.

Overloading with config.json

You can explicitly override these Docker manifest values using a config.json file. This is useful when you want to change the entrypoint or environment of an existing image without rebuilding it.

In the pvr CLI, use the --config-json flag:

pvr app add myapp --from=nginx --config-json=custom-config.json

Individual keys can also be set/removed without a file (app add, app update, app install):

pvr app update myapp --config WorkingDir=/app --unset-config Entrypoint

Example custom-config.json:

{
"Entrypoint": ["/usr/bin/custom-init"],
"Cmd": ["--flag", "value"],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"CUSTOM_VAR=enabled"
],
"WorkingDir": "/app"
}

When provided, these values will replace the ones extracted from the image manifest in the template rendering process.

Variables (args.json)

The following variables can be defined in the args section of your container source (typically args.json) to customize the generated configuration.

They can be supplied on the CLI as well (app add, app update, app install):

pvr app add myapp --from=nginx --arg PV_GROUP=platform --arg PV_VOLUME_MOUNTS=data:/var/lib/data
pvr app update myapp --arg-json args.json # whole file, merged into src.json args
pvr app update myapp --unset-arg PV_DEBUG_MODE # applied after --arg

Run Manifest (run.json)

These variables directly affect the structure and metadata of the run.json file.

VariableTypeDescription
PV_GROUPstringGroup the container belongs to (e.g., "data", "root", "platform", "app", or any group from groups.json). Preferred over PV_RUNLEVEL on Pantavisor 015+.
PV_RUNLEVELstringDeprecated runlevel: "data", "root", "platform" or "app". Mutually exclusive with PV_GROUP.
PV_STATUS_GOALstringStatus the container must reach after bootup: "MOUNTED", "STARTED" or "READY".
PV_CONDITIONSmapConditional startup logic.
PV_RESTART_POLICYstringWhat is restarted when this container is modified/fails: "system" or "container".
PV_ROLESarrayList of roles assigned to this container (e.g., ["mgmt"]).
PV_AUTO_RECOVERYobjectAuto-recovery configuration settings.
PV_DRIVERS_MANUALarrayList of manual drivers.
PV_DRIVERS_REQUIREDarrayList of required drivers.
PV_DRIVERS_OPTIONALarrayList of optional drivers.
PV_SERVICES_MANUALarrayList of manual services.
PV_SERVICES_REQUIREDarrayList of required services (used for pv-xconnect).
PV_SERVICES_OPTIONALarrayList of optional services.
PV_NETWORK_POOLstringNetwork pool to use (e.g., "lxcbr0").
PV_NETWORK_HOSTNAMEstringContainer hostname. Defaults to container name.
PV_NETWORK_IPstringStatic IP address.
PV_NETWORK_MACstringMAC address.
PV_EXTRA_VOLUMEScsvComma-separated list of extra volumes to create. Volumes referenced by PV_VOLUME_MOUNTS are added automatically.
PV_DEV_LOGboolRenders "dev-log". Value false (or the string "false") disables the per-container devlog; any other value enables it. Omit the key to leave dev-log out of run.json entirely.
PV_AUTOMODFWboolRenders "automodfw": auto-mount of /lib/modules and /lib/firmware into the container.
PV_REMOUNTobjectRenders "remount": per-container remount policies, e.g. {"default": [{"/.*": "nosuid,noexec,noatime,nodev"}, {"/": "ro"}]}. The active policy is chosen by the device's PV_REMOUNT_POLICY config key.

Note: when PV_RUNLEVEL is data or PV_STATUS_GOAL is MOUNTED, the container is a pure data/volume container: no lxc.container.conf is generated at all, and config, type, roles, exports and logs are omitted from run.json.

LXC Configuration (lxc.container.conf)

These variables control the low-level LXC configuration parameters.

General & Security

VariableDefaultDescription
PV_DEBUG_MODEfalseIf set, redirects lxc.log.file to /pv/logs/<name>.log.
PV_LXC_NAMESPACE_KEEPuser net ipcSpace-separated namespaces to inherit from Pantavisor. When unset, the default is user ipc plus netnet is only included when PV_LXC_NETWORK_TYPE is unset or host.
PV_LXC_CAP_DROP-List of capabilities to drop (e.g., ["SYS_TIME"]); lowercased on render.
PV_LXC_CAP_KEEP-List of capabilities to keep. Use either keep or drop, not both.
PVR_LXC_CGROUP_DEVICES_WHITE-List of cgroup device allow rules. When set, lxc.cgroup.devices.deny = a is emitted first; when unset, lxc.cgroup.devices.allow = a is emitted.
PVR_LXC_CGROUP_V1-List of raw cgroup v1 settings appended after lxc.cgroup., e.g. ["memory.limit_in_bytes = 100M"].
PV_LXC_EXTRA_CONF-Raw string appended to lxc.container.conf.
PV_LXC_EXTRA_ENV-List of extra KEY=VALUE entries rendered as lxc.environment, on top of .Docker.Env.
PV_DISABLE_AUTODEVfalseSets lxc.autodev = 0. Only do this if you know what you are doing.

Network & TTY

VariableDefaultDescription
PV_LXC_NETWORK_TYPE-Network type: veth, host, phys, empty. When unset, no lxc.net.0.* is emitted and net is inherited from the host.
PV_LXC_NETWORK_LINK-Physical interface to link (required for phys).
PV_LXC_NETWORK_IPV4_ADDRESS-Static IPv4 address for veth.
PV_LXC_NETWORK_IPV4_GATEWAY"auto"IPv4 gateway. Only emitted together with PV_LXC_NETWORK_IPV4_ADDRESS.
LXC_TTY_MIN-Min TTYs (lxc.tty.min); omitted when unset.
LXC_TTY_MAX"8"Max TTYs.
LXC_PTY_MAX"1024"Max PTYs.
PV_LXC_DISABLE_CONSOLEfalseSets lxc.console.path = none.

Mounts & Storage

VariableDefaultDescription
LXC_MOUNT_AUTO_PROC"proc"First lxc.mount.auto entry (e.g. proc:mixed).
LXC_MOUNT_AUTO_SYS"sys:rw"Second lxc.mount.auto entry (e.g. sys:ro).
LXC_MOUNT_AUTO_GROUP"cgroup"Third lxc.mount.auto entry (e.g. cgroup:mixed).
PV_VOLUME_MOUNTS-Comma-separated <volume-name>:<target-path>. Mounts a volume owned by this container at additional places; the volume is also added to run.json volumes.
PV_VOLUME_IMPORTS-List of <source-container>:[<subpath>@]<source-volume>:<target-path>[:<perms>] (perms default rw). Imports a volume, or a subpath within a volume, from another container.
PV_IMPORT_CONFIGVOLUMES-Comma-separated <volume-name>:<target-path>. Mounts config volumes — volumes holding configs for several containers, keyed by container name at the top level. For a container foo, <volume-name>/foo is mounted at <target-path> (bind, rw, optional, noexec).
PV_FILEIMPORTS-Comma-separated <source>:<target> file imports from /exports/.
PV_SECURITY_FULLDEVfalseMounts host /dev into container (bind, rw). Usually you do not want this.
PV_SECURITY_WITH_HOSTfalseMounts host / at host/ in the container (bind, rw).
PV_SECURITY_WITH_HOSTPROCfalseMounts host /proc at host/proc in the container.
PV_SECURITY_WITH_STORAGEfalseMounts the Pantavisor /storage partition into the container.
PV_RUN_TMPFS_DISABLEfalseIf true, disables default /run tmpfs.
PV_RUN_TMPFS_PATH"run"Target path of the default tmpfs mount (container-relative).
PV_RESOLV_CONF_DISABLEfalseIf true, disables default /etc/resolv.conf bind mount.
PV_RESOLV_CONF_PATH"etc/resolv.conf"Target path of the host resolv.conf bind mount (container-relative).

Generation Process

  1. Input: pvr takes the Docker container configuration (Env, Cmd, Entrypoint, Volumes) and the user-supplied args.json.
  2. Processing: The values are merged into a context object (.Source, .Docker, etc.).
  3. Rendering:
    • lxc.container.conf: Generates the LXC config file using the template logic.
    • run.json: Generates the Pantavisor manifest, mapping Docker settings and args variables to the standard fields.
  4. Output: These files are written to the container directory (or pvrexport).

Advanced Feature Configuration

IPAM Networking

The PV_NETWORK_* keys configure container networking via Pantavisor's IPAM subsystem.

{
"PV_NETWORK_POOL": "internal",
"PV_NETWORK_IP": "10.0.3.50",
"PV_NETWORK_HOSTNAME": "my-custom-host"
}

Volumes, Imports and Config Volumes

{
"PV_EXTRA_VOLUMES": "data,cache",
"PV_VOLUME_MOUNTS": "data:/var/lib/myapp,cache:/var/cache/myapp",
"PV_VOLUME_IMPORTS": ["pvr-sdk:certs@config:/etc/ssl/certs:ro"],
"PV_IMPORT_CONFIGVOLUMES": "_config:/etc/myapp-config"
}
  • PV_VOLUME_MOUNTS mounts volumes owned by this container (/volumes/<container>/<volume>) at extra paths.
  • PV_VOLUME_IMPORTS mounts a volume of another container; the optional subpath@volume form imports only a subdirectory, and the trailing field sets mount options (ro/rw).
  • PV_IMPORT_CONFIGVOLUMES mounts a shared config volume, picking the subdirectory named after this container. For a container foo, the entry above mounts /volumes/_config/foo at /etc/myapp-config. The mount is optional, so a missing directory does not fail container start, and noexec.

Service Mesh & Ingress (pv-xconnect)

The PV_SERVICES_REQUIRED key is used to define dependencies on other containers or to configure external traffic ingress.

TCP Ingress

Routes external traffic from port 2222 into the container, which then proxies it to a backend service named raw-unix.

{
"PV_SERVICES_REQUIRED": [
{
"name": "raw-unix",
"type": "tcp",
"target": "0.0.0.0:2222"
}
]
}

HTTP Ingress with Path Rewriting

Routes external traffic on port 80 with path /api to a backend service named network-manager. The path prefix is stripped when forwarding to the provider.

{
"PV_SERVICES_REQUIRED": [
{
"name": "network-manager",
"type": "http",
"target": "0.0.0.0:80/api"
}
]
}

Auto-Recovery (Restart Policies)

The PV_AUTO_RECOVERY key defines how Pantavisor should handle container crashes using an exponential backoff strategy.

Option 1: Wholesale JSON object

{
"PV_AUTO_RECOVERY": {
"policy": "on-failure",
"max_retries": 10,
"retry_delay": 5,
"backoff_factor": 2.0,
"reset_window": 300
}
}

Option 2: Granular variables (Less error-prone)

{
"PV_AUTO_RECOVERY_POLICY": "on-failure",
"PV_AUTO_RECOVERY_MAX_RETRIES": 10,
"PV_AUTO_RECOVERY_RETRY_DELAY": 5,
"PV_AUTO_RECOVERY_BACKOFF_FACTOR": 2.0,
"PV_AUTO_RECOVERY_RESET_WINDOW": 300
}

If PV_AUTO_RECOVERY is present it wins; the granular keys are only used when it is absent.

Remount Policies

PV_REMOUNT defines per-container remount operations applied after the rootfs and volumes are mounted. Each policy is a list of path-regex: mount-options directives; the policy actually executed is selected by the device's PV_REMOUNT_POLICY configuration key (default: default).

{
"PV_REMOUNT": {
"default": [
{ "/.*": "nosuid,noexec,noatime,nodev" },
{ "/dev": "dev" },
{ "/": "ro" }
],
"dev": [
{ "/.*": "nosuid,exec,noatime,nodev" }
]
}
}