Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/features/apps/install-scripts/curated/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<!-- curated:index:start -->
| App | Download | Size | Last Modified |
|---|---|---:|---|
| `home-assistant` | [home-assistant.json](/install-scripts/home-assistant.json) | 1.4 KB | 2025-11-17 |
| `immich` | [immich.json](/install-scripts/immich.json) | 1.6 KB | 2025-11-17 |
| `jellyfin` | [jellyfin.json](/install-scripts/jellyfin.json) | 2.1 KB | 2025-11-17 |
| `plex` | [plex.json](/install-scripts/plex.json) | 3.0 KB | 2025-11-22 |
| `prowlarr` | [prowlarr.json](/install-scripts/prowlarr.json) | 443 B | 2025-11-21 |
| `qbittorrent` | [qbittorrent.json](/install-scripts/qbittorrent.json) | 881 B | 2025-11-21 |
| `radarr` | [radarr.json](/install-scripts/radarr.json) | 904 B | 2025-11-21 |
| `sonarr` | [sonarr.json](/install-scripts/sonarr.json) | 901 B | 2025-11-21 |
| `home-assistant` | [home-assistant.json](/install-scripts/home-assistant.json) | 1.6 KB | 2025-12-04 |
| `immich` | [immich.json](/install-scripts/immich.json) | 1.7 KB | 2025-12-12 |
| `jellyfin` | [jellyfin.json](/install-scripts/jellyfin.json) | 2.2 KB | 2025-12-12 |
| `plex` | [plex.json](/install-scripts/plex.json) | 3.4 KB | 2025-12-12 |
| `prowlarr` | [prowlarr.json](/install-scripts/prowlarr.json) | 766 B | 2025-12-04 |
| `qbittorrent` | [qbittorrent.json](/install-scripts/qbittorrent.json) | 1.0 KB | 2025-12-04 |
| `radarr` | [radarr.json](/install-scripts/radarr.json) | 1.2 KB | 2025-12-04 |
| `sonarr` | [sonarr.json](/install-scripts/sonarr.json) | 1.2 KB | 2025-12-04 |
<!-- curated:index:end -->
163 changes: 163 additions & 0 deletions docs/features/apps/install-scripts/reference/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,169 @@ Resolves to the server's LAN IP address. Useful for constructing URLs that point
]
```

## `$SERVER_HOST_ID`
Resolves to the server's unique host ID. This is particularly useful for constructing HexOS Tunnels (e.g., `https://<host-id>.direct.hexos.com`) for remote tunneled access to your apps and services.

**Example:**
```json
{
"value": "https://$SERVER_HOST_ID.direct.hexos.com"
}
```

## `$APP_INSTALLED(appName)`
Checks if a specific app is installed on the TrueNAS system. Returns `true` if installed, `false` otherwise. The check is case-insensitive.

**Example:**
```json
"$APP_INSTALLED(qbittorrent)" // Returns "true" or "false"
```

## `$QUESTION(key)`
Accesses user responses from installation questions. The value is replaced with the user's response, which can be a boolean, string, number, or empty. When used in conditional expressions, values are converted appropriately:
- Boolean values become `"true"` or `"false"`
- Empty/null values become `"false"`
- String values are quoted unless they're "true" or "false"
- Numbers are converted to strings

**Examples:**
```json
"enabled": "$QUESTION(enable_feature)" // Direct value replacement
"$IF($QUESTION(use_ssl), \"https\", \"http\")" // Boolean check
"$IF($QUESTION(port) != \"\", $QUESTION(port), \"8080\")" // Default value
```

## `$GPU_CONFIG()`
Automatically detects and configures GPU resources for applications. The macro queries the system's available GPUs and generates the appropriate TrueNAS GPU configuration object.

**Basic Usage:**
```json
"resources": {
"gpus": "$GPU_CONFIG()"
}
```

**Conditional Usage:**
```json
"gpus": "$IF($QUESTION(enable_gpu), '$GPU_CONFIG()', {'use_all_gpus': false})"
```

**Detected Configurations & Expanded Values:**

**No GPU detected:**
```json
// System has no GPUs
"$GPU_CONFIG()" → {"use_all_gpus": false}
```

**Intel integrated GPU detected:**
```json
// System has Intel UHD Graphics 770
"$GPU_CONFIG()" → {"use_all_gpus": true}
```

**AMD GPU detected:**
```json
// System has AMD Radeon RX 6700 XT
"$GPU_CONFIG()" → {"use_all_gpus": true}
```

**Single NVIDIA GPU detected (with drivers):**
```json
// System has NVIDIA RTX 4090
"$GPU_CONFIG()" → {
"use_all_gpus": true,
"nvidia_gpu_selection": {
"0000:01:00.0": {
"use_gpu": true,
"uuid": "GPU-8a5f3c21-b4e9-4d72-a123-456789abcdef"
}
}
}
```

**Multiple NVIDIA GPUs detected (with drivers):**
```json
// System has 2x NVIDIA RTX A4000
"$GPU_CONFIG()" → {
"use_all_gpus": true,
"nvidia_gpu_selection": {
"0000:01:00.0": {
"use_gpu": true,
"uuid": "GPU-1a2b3c4d-5e6f-7890-abcd-ef1234567890"
},
"0000:02:00.0": {
"use_gpu": true,
"uuid": "GPU-9f8e7d6c-5b4a-3210-fedc-ba0987654321"
}
}
}
```

**Mixed GPUs (Intel + NVIDIA with drivers):**
```json
// System has Intel UHD 770 + NVIDIA RTX 3060
"$GPU_CONFIG()" → {
"use_all_gpus": true,
"nvidia_gpu_selection": {
"0000:03:00.0": {
"use_gpu": true,
"uuid": "GPU-7c8d9e0f-1a2b-3c4d-5e6f-789012345678"
}
}
}
```

**NVIDIA GPU without drivers (falls back to disabled):**
```json
// System has NVIDIA GPU but drivers not installed
"$GPU_CONFIG()" → {"use_all_gpus": false}
```

**Common Use Cases:**
- **Media Servers**: Plex, Jellyfin, Emby (hardware transcoding)
- **AI/ML Applications**: Ollama, Stable Diffusion, ComfyUI
- **Photo Management**: Immich (ML face detection)
- **Video Processing**: Handbrake, FFmpeg-based apps
- **Game Streaming**: Sunshine, Steam Link

**NVIDIA Driver Update Steps:**
NVIDIA drivers were installed already if this was a fresh install, however if this system was adopted or for whatever reason they require manual updating of the drivers from within the TrueNAS ui they can perform the following:

1. Apps → Settings (gear icon) → Advanced Settings
2. Toggle "Enable GPU Support" or "NVIDIA Runtime" OFF → Save
3. Wait 10-30 seconds
4. Toggle back ON → Save
5. This triggers a `docker.update` with latest compatible NVIDIA drivers

## `$IF(condition, trueValue, [falseValue])`
Provides conditional logic in install scripts. Evaluates a condition and returns different values based on the result.

**Syntax Variations:**
1. **Basic if/else**: `$IF(condition, trueValue, falseValue)`
2. **If only**: `$IF(condition, trueValue)` - Returns empty string if false
3. **Multiple conditions with AND**: `$IF(['condition1', 'condition2'], trueValue, falseValue, 'AND')`
4. **Multiple conditions with OR**: `$IF(['condition1', 'condition2'], trueValue, falseValue, 'OR')`

**Supported Conditions:**
- Boolean literals: `true`, `false`
- Negation: `!condition`
- App installation checks: `$APP_INSTALLED(appName)`
- Question responses: `$QUESTION(key)`
- Equality comparison: `value1 == value2`
- Inequality comparison: `value1 != value2`

**Example:**
```json
"additional_storage": [
"$IF($APP_INSTALLED(qbittorrent), '$MOUNTED_HOST_PATH($LOCATION(Downloads)/qbittorrent, /downloads)')",
"$IF($APP_INSTALLED(sabnzbd), '$MOUNTED_HOST_PATH($LOCATION(Downloads)/sabnzbd, /downloads)')",
"$IF($QUESTION(use_qbittorent), '$MOUNTED_HOST_PATH($LOCATION(Downloads)/qbittorent, /downloads/qbittorent)')",
...
]
```
*Conditionally mounts download folders based on installed apps and user preferences*

#### `$MEMORY(percentage, minimum_mb)`
Dynamically allocates memory based on system resources. Takes the higher value between the percentage of system memory and the minimum specified in MB.

Expand Down
130 changes: 49 additions & 81 deletions docs/features/apps/install-scripts/reference/schema.md
Original file line number Diff line number Diff line change
@@ -1,94 +1,51 @@
### Install Script Schema

Install scripts are JSON objects with the following structure:
Install scripts are JSON objects with the following structure. Scripts can use various macros (template variables) that are dynamically replaced during processing.

## Root Properties

- **`version`** (required): Schema version. Must be `1` or `2`.
- **`requirements`** (optional): System requirements that are validated before installation
- **`installation_questions`** (optional, introduced in version 2): Array of questions to ask the user during installation
- **`version`** (required): Schema version. Must be `3` or higher (currently latest supported version).
- **`script`** (required): Metadata about the install script itself
- **`version`** (required): Semantic version of this install script (e.g., "1.0.0", "2.1.3")
- **`updateCompatibility`** (optional): Semver range expression defining which script versions can update to this version (e.g., ">=1.0.0" allows updates from any version 1.0.0 or higher, "^2.0.0" allows updates from 2.x.x versions). Supports all [semver range syntax](https://www.npmjs.com/package/semver#ranges) including `>=`, `>`, `<`, `<=`, `^`, `~`, and complex ranges like `">=1.0.0 <3.0.0"`
- **`changeLog`** (optional): Description of changes in this version of the script
- **`requirements`** (required): System requirements that are validated before installation
- **`installation_questions`** (optional): Array of questions to ask the user during installation
- **`ensure_directories_exists`** (optional): Array of directories to create before installation
- **`ensure_permissions_exists`** (optional): Array of permission modifications for specific paths
- **`app_values`** (required): Configuration object passed directly to TrueNAS API

## Available Macros

Install scripts support various macros that are replaced dynamically during script processing:

### Basic Macros
- **`$SERVER_LAN_IP`**: Server's LAN IP address
- **`$SERVER_HOST_ID`**: Server's unique host ID
- **`$LOCATION(locationId)`**: Resolves to configured location path
- **`$RANDOM_STRING(length)`**: Generates random alphanumeric string
- **`$MEMORY(percentage, minimum_mb)`**: Calculates memory allocation
- **`$HOST_PATH(path)`**: Creates host path configuration object
- **`$MOUNTED_HOST_PATH(path, mount_point)`**: Creates mounted host path configuration

### Conditional Macros
- **`$APP_INSTALLED(appName)`**: Returns "true" or "false" if app is installed
- **`$QUESTION(key)`**: References user's response to installation question
- **`$IF(condition, trueValue, [falseValue])`**: Conditional logic with support for:
- Boolean literals: `true`, `false`
- Negation: `!condition`
- App checks: `$APP_INSTALLED(appName)`
- Question values: `$QUESTION(key)`
- Equality: `value1 == value2`
- Inequality: `value1 != value2`
- AND logic: `$IF(["condition1", "condition2"], trueValue, falseValue, "AND")`
- OR logic: `$IF(["condition1", "condition2"], trueValue, falseValue, "OR")`

For detailed macro documentation and examples, see the [Macros Reference](/features/apps/install-scripts/reference/macros).

## Example Structure
```json
{
"version": 2,
"requirements": {
"locations": ["ApplicationsPerformance", "Photos"],
"specifications": ["2CORE", "200MB"],
"permissions": ["READ_WRITE_LOCATIONS"],
"ports": []
},
"installation_questions": [
{
"question": "Database Password",
"description": "A secure password for the PostgreSQL database.",
"type": "text",
"key": "db_password",
"required": true,
"default": "$RANDOM_STRING(16)"
},
{
"question": "Enable GPU acceleration for machine learning?",
"description": "GPU acceleration significantly improves photo recognition speed but requires compatible hardware.",
"type": "select",
"key": "gpu_passthrough",
"required": true,
"options": [
{
"text": "Yes - Use GPU for faster photo recognition",
"value": true
},
{
"text": "No - Use CPU only",
"value": false
}
],
"default": false
},
{
"question": "Web Port",
"description": "The port number where the web interface will be accessible.",
"placeholder": "2283",
"type": "number",
"key": "web_port",
"required": false,
"default": 2283
}
],
"ensure_directories_exists": [
"/path/to/directory",
{
"path": "/path/with/options",
"network_share": true,
"posix": true
}
],
"ensure_permissions_exists": [
{
"path": "/path/to/set/permissions",
"username": "netdata",
"access": "read",
"posix": { "groupname": "docker" }
}
],
"app_values": {
"network": {
"web_port": {
"bind_mode": "published",
"port_number": "$QUESTION(web_port)"
}
},
"resources": {
"gpus": {
"use_all_gpus": "$QUESTION(gpu_passthrough)"
}
}
}
}
```

For complete, working examples of install scripts, please refer to the [curated install scripts](/features/apps/install-scripts/curated/). These production-ready scripts demonstrate best practices and real-world usage patterns for popular applications like Plex, Jellyfin, Immich, and more.

## Requirements

Expand Down Expand Up @@ -273,6 +230,10 @@ Reference question responses in your `app_values` using the `$QUESTION(key)` syn
}
```

**Using Questions in Conditionals:**

Question responses can be used in conditional logic with the `$IF` macro. See the [$IF macro documentation](/features/apps/install-scripts/reference/macros#if-condition-truevalue-falsevalue) for examples of using questions in conditional expressions.

## Directory Creation
- **String format**: Simple path string
- **Object format**:
Expand All @@ -289,3 +250,10 @@ Required for apps that need specific user/group permissions (like PostgreSQL).

## App Values
This object is passed directly to TrueNAS's app installation API. The structure varies by application and corresponds to the app's configuration schema in the [TrueNAS apps repository](https://github.com/truenas/apps). For example, you can see Plex's schema for the `storage` property [here](https://github.com/truenas/apps/blob/1d2a6e9811f9af2ceae6529cc094a432a7da4e96/trains/stable/plex/app_versions.json#L422).

### Conditional Configuration

Install scripts support conditional logic to customize app configuration based on:
- Other installed apps using [`$APP_INSTALLED(appName)`](/features/apps/install-scripts/reference/macros#app_installedappname)
- User responses to installation questions using [`$QUESTION(key)`](/features/apps/install-scripts/reference/macros#questionkey)
- Complex conditions using the [`$IF`](/features/apps/install-scripts/reference/macros#if-condition-truevalue-falsevalue) macro
8 changes: 6 additions & 2 deletions docs/public/install-scripts/home-assistant.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"version": 1,
"version": 3,
"script": {
"version": "1.0.0",
"changeLog": "Upgraded Home Assistant install script to be compatible with latest HexOS script changes"
},
"requirements": {
"locations": ["ApplicationsPerformance", "Media"],
"specifications": ["2CORE", "200MB"],
"permissions": ["READ_WRITE_LOCATIONS"],
"ports": []
"ports": [8123]
},
"ensure_directories_exists": [
{
Expand Down
12 changes: 7 additions & 5 deletions docs/public/install-scripts/immich.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
{
"version": 1,
"version": 3,
"script": {
"version": "1.0.0",
"changeLog": "Upgraded Immich install script to be compatible with latest HexOS script changes"
},
"requirements": {
"locations": ["ApplicationsPerformance", "Photos"],
"specifications": ["2CORE", "200MB"],
"permissions": ["READ_WRITE_LOCATIONS"],
"ports": []
"ports": [2283]
},
"ensure_directories_exists": [
{
Expand Down Expand Up @@ -61,9 +65,7 @@
"cpus": 2,
"memory": "$MEMORY(10%, 4096)"
},
"gpus": {
"use_all_gpus": true
}
"gpus": "$GPU_CONFIG()"
}
}
}
Loading