---
title: App Store
description: Browse a curated catalogue of Docker Compose templates and deploy any of them as a new stack with one click.
---

The **App Store** is a browseable catalogue of Docker Compose templates. Each template is a turn-key recipe with sensible defaults for ports, volumes, and environment variables, so you can stand up a new stack without writing YAML. Pick a tile, fill in a name, click **Deploy** and Sencho creates the directory, generates `compose.yaml` and `.env`, runs `docker compose up -d`, and switches you to the editor for the new stack.

<Frame>
  <img src="/images/app-store/app-store-hero.png" alt="App Store with the categories rail on the left, a featured template hero pinned at the top, and a grid of editorial tiles with per-tile scan badges" />
</Frame>

## Browsing templates

Templates load from a remote registry. The default registry is **LinuxServer.io**; you can point Sencho at any [Portainer v2 compatible JSON catalogue](#custom-template-registry) instead. The registry is configured per node, so the catalogue reflects whichever node is active and reloads automatically when you switch nodes.

### Search and counts

The search bar at the top filters tiles by name, description, or category in real time. The chip on the right shows the number of templates currently visible (for example, `201 apps`).

### Categories rail

The left rail lists every category the registry exposes, plus an **All** entry, with a count for each. The active category gets a brand-coloured rail and tinted background. The rail appears once at least one template has loaded. The category rail is desktop only; see [Mobile](#mobile) for the small-screen layout.

### Featured template

A single template is pinned to the top of the grid in a wide editorial banner. The banner includes its own **Deploy** button so you can ship the featured template without opening its tile. Sencho rotates the featured pick **weekly** through the five most-starred templates in the registry, so the catalogue stays fresh without you doing anything. The banner disappears whenever you have a search query active.

### Tiles

Each tile shows:

- A brand-tinted logo (falls back to a generic icon when the registry has no artwork)
- The template name and the first sentence of its description
- A GitHub star count (when the registry provides one)
- The primary category
- A **scan badge** on the right, derived from Sencho's vulnerability scanner:
  - **Clean** (no CVEs detected on the most recent scan)
  - **{N} CVE** or **{N} CVEs** (the count of open vulnerabilities, in amber)
  - **Unscanned** (no scan has been recorded for this image yet)

Tiles are sorted by GitHub star count, descending. Click any tile to open the deployment sheet on the right.

### Mobile

On small screens, the App Store adapts to a single-column layout. The masthead shows the store label, the total app count, the category count, and an action menu for navigation. Templates are listed alphabetically rather than by star count, and the category sidebar and featured hero are not shown on mobile.

<Frame>
  <img src="/images/app-store/app-store-mobile.png" alt="App Store on a mobile device: status masthead showing APP STORE, 201 apps, and 12 categories, with an alphabetical single-column template list below" />
</Frame>

## Deploying a template

The deployment sheet slides in from the right. The header carries a breadcrumb (`App store › <template>`), the template name as the sheet's title, and a meta line built from whichever of these the registry and deploy target supply: architecture chips, the GitHub star count, and the target node name when you are deploying to a remote node.

### About

The first section is a description block with the template logo, the full description, a **Read more** / **Read less** toggle, and a row of secondary metadata: the GitHub star count, and, when the registry payload includes them, architecture chips (for example `amd64`, `arm64`), a **Source** link to the template's repository, and a **Docs** link to the project's official documentation. The bundled LinuxServer.io registry currently supplies only the star count here; a custom registry populates the rest when its template JSON includes `architectures`, `github_url`, and `docs_url`.

### Essentials tab

The **Essentials** tab is intentionally minimal: a single **Stack Name** field and a hint that the template's defaults will be used as-is. Click **Deploy {template}** to ship it.

<Frame>
  <img src="/images/app-store/deploy-sheet-essentials.png" alt="Deployment sheet open on the Essentials tab for qbittorrent, showing the App store breadcrumb, the About panel with Read more, the Stack Name field pre-filled with the template slug, and the Deploy with defaults hint card" />
</Frame>

The stack name pre-fills with the template slug (lowercased, hyphens, no spaces). You can change it; the same [naming rules](/features/stack-management#creating-a-stack) apply.

If any of the template's default ports are already bound on the active node, the Essentials hint card is replaced by a **Port conflict** warning that lists each conflicting port and the application using it, with a pulsating amber accent. Switch to **Advanced** to remap the host port before deploying.

For anything beyond the defaults, switch to **Advanced**.

### Advanced tab

The **Advanced** tab exposes every knob the template declares. Every field is pre-populated with the template's recommended value, so customisation is additive rather than required.

<Frame>
  <img src="/images/app-store/deploy-sheet-advanced.png" alt="Deployment sheet on the Advanced tab for qbittorrent, showing three host port inputs, a single Volumes mount point, Environment Variables with PUID, PGID, and Timezone, a Custom variables row, and the Security scan checkbox" />
</Frame>

#### Ports

Each declared port shows an editable **host port** on the left and the fixed **container port** on the right. Host ports must be integers between 1 and 65535; invalid values are highlighted and block deployment.

When the host port you typed is already in use somewhere on the active node, an inline amber **`in use by {stack}`** message appears next to the container port, alongside a pulsating amber dot. The message names the offending stack when Sencho manages it, or reads `in use by an external app` when the binding belongs to a process outside Sencho.

<Frame>
  <img src="/images/app-store/app-store-port-conflict.png" alt="Port conflict indicator on the radarr deploy sheet: an inline amber message names the stack already using port 7878, next to a pulsating warning dot" />
</Frame>

#### Volumes

For each container mount point the template declares, type the **host path** where that data should live. Sencho pre-fills sensible defaults like `./config` or `./data`.

<Note>
  Relative paths such as `./config` resolve against the new stack's directory inside `COMPOSE_DIR`. Absolute paths map directly onto the host filesystem.
</Note>

#### Environment variables

Each template can declare the variables it expects, and Sencho pre-fills defaults where the registry supplies them. Every deploy also adds three baseline LinuxServer.io conventions automatically when the template does not already define them: **PUID** (`1000`), **PGID** (`1000`), and **TZ**, seeded from your browser's reported timezone.

<Note>
  With the bundled LinuxServer.io registry, these three baseline variables are currently the only ones that appear in this section, regardless of the app: template-specific variables (a password, an API key, a subdomain) are not pulled through from that registry today. Check the app's own documentation (linked from its GitHub page) for the variables it needs and set them yourself using **Custom variables** below. A custom registry that supplies its own `env` array in its template JSON is not affected by this and populates the section normally.
</Note>

#### Custom variables

The **Custom variables** block lets you add arbitrary key/value pairs that the template did not declare. Type a key and value, then click **+** to add it. If you add a key that already exists in the template defaults, a toast warns you that your custom value will override the default (`"{KEY}" already exists in template defaults. The custom value will override it.`).

#### Security

When [vulnerability scanning](/features/vulnerability-scanning) is configured on the active node, a **Security** section appears at the bottom of the Advanced tab with a single checkbox: **Scan images for vulnerabilities after deploy**. The checkbox is on by default. Leave it on to queue a Trivy scan against every image the new stack pulls. The scan runs in the background once the stack is up; results land on the per-image severity badges in the [Resources Hub](/features/resources) and open the [scan results drawer](/features/vulnerability-scanning#the-scan-results-drawer) when clicked.

The Security section is hidden entirely when Trivy is not available on the node.

## What happens on Deploy

Clicking **Deploy** runs the following sequence:

1. **Pre-flight name check.** Sencho asks the active node whether a stack of that name already exists. If it does, you get an immediate error toast and nothing else happens.
2. **Directory creation.** A new directory is created under `COMPOSE_DIR/<stack-name>` on the active node.
3. **File generation.** Sencho writes `compose.yaml` (rendered from the template, with your port and volume overrides) and a `.env` file (when you configured environment variables).
4. **Policy gate.** Any [deploy-enforcement policies](/features/deploy-enforcement) configured on the node run against the generated compose. If a rule blocks the deploy, the directory is cleaned up and you get the rule's reason.
5. **`docker compose up -d`.** The deploy is **atomic**: any container that fails to start triggers an automatic rollback to the previous state.
6. **Outcome.**
   - On success, you are switched to the editor for the new stack and a success toast confirms the deploy.
   - On failure, Sencho parses the error. Most failures (image pull, port collision, volume permission, compose validation) trigger a clean rollback: the stack is brought down and the directory is removed. A small set of failures that point to live containers (for example, a startup that crashes after the container is running) leave the stack on disk so you can inspect it. The error toast tells you which.

## Watching the deploy

Sencho can stream the live `docker compose` output for every template install. Open **Settings › Infrastructure › Stacks** and enable **Deploy progress**; from then on, every App Store deploy streams its output. In Modal style it opens a structured log modal you can minimise to a pill that follows you across navigation; in Inline style it shows as that pill, which opens the same log on click. See [Deploy Progress](/features/deploy-progress) for the full reference.

<Note>
  Deploying a template requires the `stack:create` permission on the target node, which **admin** and **node-admin** roles hold by default. The Deploy button stays disabled when your account does not have it.
</Note>

## Custom template registry

By default Sencho uses LinuxServer.io's hosted catalogue. To point at your own:

<Note>
  Changing the registry URL requires an **admin** account.
</Note>

<Frame>
  <img src="/images/app-store/app-store-settings-registry.png" alt="Settings › Infrastructure › App Store with two panels: Default registry showing LinuxServer.io and the api.linuxserver.io/api/v1/images URL, and Custom registry with a Registry URL input, a using-default hint, and Reset to default and Save and refresh buttons" />
</Frame>

1. Open **Settings › Infrastructure › App Store**.
2. Type your catalogue URL into **Registry URL**. The URL must start with `http://` or `https://` and serve a JSON array of template objects in the [Portainer v2 template format](https://documentation.portainer.io/v2.0-be/api/templates/).
3. Click **Save & refresh**. Sencho persists the new URL and immediately invalidates the template cache so the App Store reloads from the new source.

A hint next to the **Save & refresh** button reads **using custom registry** when an override is set and **using default** when the field is empty. Click **Reset to default** to clear the override and fall back to LinuxServer.io.

The default registry display at the top of the page is informational only; you cannot remove the LinuxServer.io fallback, and Sencho uses it whenever the custom field is empty.

## Troubleshooting

<AccordionGroup>
  <Accordion title="No tiles appear">
    Sencho fetches templates from the configured registry on demand. If the grid stays empty and the loading spinner is gone, the registry returned an empty list or the request failed before parsing. Open **Settings › Infrastructure › App Store** and confirm the **Registry URL** is reachable from the node (try the URL in a browser tab); a custom catalogue served from a private host will not load if the Sencho container cannot resolve or reach it. Click **Save & refresh** to invalidate the cache and try again. If you switched to a custom registry by mistake, click **Reset to default**. Sencho also bounds the registry response size: a catalogue that returns an excessively large payload is rejected with a size-limit error instead of being loaded, so a misconfigured or runaway endpoint cannot stall the node.
  </Accordion>
  <Accordion title="The port-conflict warning will not clear">
    The conflict indicator is computed against a snapshot of the node's bound ports taken when you opened the deployment sheet. If you freed the port from another stack while the sheet was open, the warning does not refresh on its own. Close the sheet and reopen it to recompute, or pick a different host port. The message `in use by an external app` means a process outside Sencho holds the binding (often the host's reverse proxy or a system service); changing the host port is usually faster than tracking down the offender.
  </Accordion>
  <Accordion title="Deploy failed but the stack directory remains">
    Sencho rolls back the directory only when the failure points cleanly at template generation, image pull, or first-time container creation. Failures that involve a container that did manage to start (for example, a crashloop after Compose returned success, or a healthcheck that flapped) leave the stack on disk so you can read the logs and decide whether to fix forward. The error toast tells you which path was taken; the response also carries a `rolledBack` flag and a `ruleId` you can search for in the [audit log](/features/audit-log). Use the editor to repair the compose, or delete the stack from the cockpit if you want to retry from scratch.
  </Accordion>
  <Accordion title="The Security checkbox is missing from the Advanced tab">
    The **Scan images for vulnerabilities after deploy** checkbox renders only when the active node reports that Trivy is installed. Configure scanning per the [Vulnerability Scanning](/features/vulnerability-scanning) page, then reopen the deployment sheet. Even with the checkbox missing, the rest of the Advanced tab works exactly the same; you just lose the post-deploy scan trigger.
  </Accordion>
  <Accordion title="An app needs a variable that isn't in Environment Variables">
    Some apps require a variable Sencho doesn't pre-fill for you, most commonly a password (code-server's `PASSWORD`, for example). With the bundled LinuxServer.io registry, the Environment Variables section only ever shows the PUID/PGID/TZ baseline, not the app's own declared variables. Check the app's GitHub page (linked from its LinuxServer.io listing) for the full variable list, then add what you need through **Custom variables** on the Advanced tab before deploying. If you skip a required variable like a password, the app typically starts with no authentication rather than failing to start, so add it up front rather than discovering the gap afterward.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Vulnerability Scanning" icon="shield-halved" href="/features/vulnerability-scanning">
    Understand the CVE badges that appear on every template tile and what they mean.
  </Card>
  <Card title="Deploy Progress" icon="chart-line" href="/features/deploy-progress">
    Stream live docker compose output for every App Store deploy.
  </Card>
  <Card title="Deploy Enforcement" icon="ban" href="/features/deploy-enforcement">
    Set risk policies that gate App Store deploys before the stack is created.
  </Card>
  <Card title="Resources Hub" icon="box-archive" href="/features/resources">
    View scan results for images pulled by App Store templates.
  </Card>
</CardGroup>
