mcpField
R
routeros-app-yaml

routeros-app-yaml

github.com/tikociCloud & DevOps8343 installsUpdated 5d ago
Repository

About routeros-app-yaml

A reference guide to the YAML format for defining and managing container applications through MikroTik RouterOS `/app`. It is for RouterOS users and tool builders, and details schema differences, supported properties, validation, and API usage.

Key features

  1. 01Define services, volumes, and networks
  2. 02Configure ports and placeholders
  3. 03Declare inline configuration files
  4. 04Validate with JSON schemas
  5. 05Load apps through CLI or REST API

Use cases

  1. 01Create a RouterOS container app
  2. 02Check YAML before deployment
  3. 03Configure an app-store collection
  4. 04Set up YAML editor completion

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/tikoci/routeros-skills --skill routeros-app-yaml

After installing, type/routeros-app-yamlin Claude Code to confirm it loaded.

Bundled filesreferences/examples.md

Details

From the project README

RouterOS /app YAML Format (7.21+)

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

Comments

Markdown supported