RouterOS /app YAML Format (7.21+)

SkillFiles & storage

RouterOS /app YAML format for container applications (7.21+ builtin app, 7.22+ custom YAML creation). Use when: writing or validating RouterOS /app YAML files, working with MikroTik container apps, building docker-compose-like definitions for RouterOS, creating /app store schemas, debugging /app validation errors, or when the user mentions /app, tikapp, or RouterOS container YAML.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the RouterOS /app YAML Format (7.21+) skill

What this skill tells your AI

The instructions your AI receives, as published by tikoci/routeros-skills in routeros-app-yaml/SKILL.md and read by ahel’s review.

RouterOS 7.21 introduced the /app path (built-in app listing and management). The full YAML app creation feature (/app/add) appeared in 7.22 (first seen in 7.22beta5). Think of it as MikroTik's opinionated alternative to docker-compose — but it is NOT docker-compose, with significant differences.

What /app Is

The /app subsystem lets users define one or more containers as a single "application" in YAML. RouterOS parses the YAML, creates containers, volumes, networks, and config files, then manages the lifecycle.

Key concepts:

  • Each /app is defined by a YAML document with services, configs, volumes, and networks
  • The YAML is loaded into RouterOS via CLI (/app/add yaml-url=...) or REST API
  • Built-in apps ship with RouterOS (visible at GET /rest/app)
  • Custom apps can be added from URLs or inline YAML
  • App stores (app-store-urls=) provide curated collections

Critical Differences from docker-compose

Featuredocker-composeRouterOS /app
Port formathost:container[/protocol]Two styles (see below)
EnvironmentKEY=value or listSame, but placeholders expand
VolumesNamed or bind mountsSubset — no bind mount options
NetworksFull docker network modelSimplified — name + external
BuildFull Dockerfile supportMinimal (context + dockerfile)
ConfigsDocker configs APIInline content only
Deploy/resourcesYesNo — not supported
Top-level version:Deprecated (was required)Not used
File extension.yml / .yaml.tikapp.yaml (convention)

Top-Level Properties

PropertyTypeRequiredDescription
namestringNoUnique identifier for the /app
descrstringNoHuman-readable description shown in app UI
pagestring (URI)NoProject homepage URL
categorystring (enum)NoApp store classification
iconstring (URI)NoIcon URL (shown in WebFig with show-in-webfig=yes)
default-credentialsstring or nullNousername:password shown in UI
url-pathstringNoURL path suffix for browser access (e.g., /admin)
credentialsstringNoCredential hint (alternative to default-credentials)
optionbooleanNoWhether app is optional
auto-updatebooleanNoPull and restart containers on every boot
servicesobjectYesContainer service definitions (≥1 required)
volumesobjectNoNamed volume declarations
networksobjectNoNetwork declarations
configsobjectNoConfig file declarations with inline content

Category Values (Exhaustive)

productivity, storage, networking, development, communication,
file-management, search, video, media, media-management,
home-automation, monitoring, database, automation, ai,
messaging, radio, security, business

New categories appear when MikroTik adds built-in apps. The CI schema validation catches these.

Service Properties

Each key under services: defines one container. Required property: image.

PropertyTypeDescription
imagestringContainer image (omit registry to use /container/config's registry-url)
container_namestringExplicit name; used as base for file paths under /container
hostnamestringContainer hostname
entrypointstring or string[]Override default entrypoint
commandstring or string[]Override default command
portsarrayPort mappings (see format section)
environmentobject or array or nullEnvironment variables (KEY=value list or {KEY: value} map)
volumesarray of stringsVolume mounts (e.g., my-vol:/data)
configsarray of objectsConfig file placements ({source, target, mode})
restartenumno, always, on-failure, unless-stopped
depends_onarray or objectService dependency ordering
devicesarray of stringsDevice mappings passed to container
userstringUser to run container as
security_optarray of stringsSecurity options
shm_sizestringShared memory size
stop_grace_periodstring or intTime before SIGKILL
ulimitsobjectResource limits (e.g., nofile: {soft: 65536, hard: 65536})
buildobject or stringBuild configuration (context, dockerfile, args)
healthcheckobjectHealth check (test, interval, timeout, retries, start_period)
stdin_openbooleanKeep stdin open
exposearrayInternal ports (not published to host)
secretsarray of stringsSecrets to expose
attachbooleanAttach to stdio

Port Format — Two Styles

RouterOS supports two port mapping string formats. Both are valid; new apps from 7.23beta2+ prefer the colon style.

Old OCI-style (pre-7.23)

[ip:]host_port:container_port[/tcp|/udp][:label]

Examples:

ports:
  - "8080:80/tcp"
  - "8443:443/tcp:https"
  - "192.168.1.1:53:53/udp:dns"

New RouterOS style (7.23+)

[ip:]host_port:container_port[:label][:tcp|:udp]

Protocol is appended with colon instead of slash:

ports:
  - "8080:80:web:tcp"
  - "8443:443:https:tcp"
  - "53:53:dns:udp"

Long-form (object) syntax

ports:
  - target: 80
    published: 8080
    protocol: tcp
    name: web
    app_protocol: http

IP Addresses and Placeholders in Ports

Port strings can include literal IPs or placeholder expressions:

ports:
  - "[accessIP]:[accessPort]:80/tcp:web"      # Old style with placeholders
  - "[accessIP]:[accessPort]:80:web:tcp"       # New style with placeholders

Placeholders

RouterOS expands these placeholders at deploy time:

PlaceholderExpands to
[accessIP]IP address for accessing the app from outside
[accessPort]Primary host port for external access
[accessPort2]Secondary host port
[containerIP]IP address assigned to the container
[routerIP]Router's own IP address

Placeholders appear in port mappings, environment values, and config content.

Configs (Inline Files)

Top-level configs: declares config content; services reference them:

configs:
  my-config:
    content: |
      server {
        listen 80;
        server_name [accessIP];
      }

services:
  web:
    image: nginx:alpine
    configs:
      - source: my-config
        target: /etc/nginx/conf.d/default.conf
        mode: 0644

Volumes and Networks

volumes:
  app-data: {}      # Named volume (null or empty object)

networks:
  app-net:
    name: my-network
    external: true   # Use existing RouterOS network

Store Schema (app-store-urls)

RouterOS can load app collections from URLs configured via app-store-urls=. The store format is simply a YAML array of /app definitions:

- name: app-one
  services:
    web:
      image: nginx:alpine
- name: app-two
  services:
    db:
      image: postgres:16

Store files use the .tikappstore.yaml extension by convention.

REST API for /app

// List all /app entries (built-in + custom)
const apps = await fetch(`${base}/app`, auth).then(r => r.json());

// Each entry has: .id, name, yaml (raw YAML string), and metadata
// The 'yaml' field is a RouterOS string containing the full YAML document

// Add a custom /app from URL
await fetch(`${base}/app`, {
  method: "PUT",
  ...auth,
  body: JSON.stringify({ "yaml-url": "https://example.com/my-app.tikapp.yaml" }),
});

Note: The /app endpoint requires the container extra package to be installed.

JSON Schema for Validation

Two schema variants exist for each /app document:

SchemaPurposePort validationEnv var names
*.latest.jsonCI/strict validationRegex patterns enforced^[A-Z_][A-Z0-9_]*$ only
*.editor.jsonEditor/SchemaStore UXNo regex (allows autocompletion)Case-insensitive

The strict schema has regex pattern on port strings which prevents VSCode autocompletion — the YAML extension won't suggest values for fields with patterns. The editor variant removes these patterns.

VSCode Integration

Add to VSCode settings for YAML autocompletion:

{
  "yaml.schemas": {
    "https://tikoci.github.io/restraml/routeros-app-yaml-schema.latest.json": "*.tikapp.yaml",
    "https://tikoci.github.io/restraml/routeros-app-yaml-store-schema.latest.json": "*.tikappstore.yaml"
  }
}

Use .editor.json URLs for better autocompletion at the cost of less strict validation.

Version History

  • 7.22: Initial /app support with basic service properties
  • 7.23beta2: New colon-style port format (:tcp/:udp suffix)
  • 7.23+: Additional service properties (devices, expose, secrets, attach)

Common Mistakes

  • Assuming docker-compose compatibility — not all properties are supported, some behave differently
  • Using version: key — RouterOS ignores it; not needed
  • Mixing port format styles in a single entry — each port string must use ONE style exclusively
  • Uppercase env var names required in strict validation — use *.editor.json for mixed case
  • Forgetting the container package/app returns 404 without the container extra package
  • Using deploy: or resources: — not supported by RouterOS

Additional Resources

Signals

GitHub stars
59
Forks
14
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
routeros-app-yaml
Source
github.com/tikoci/routeros-skills