Agent skill
routeros-app-yaml
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.
Install this agent skill to your Project
npx add-skill https://github.com/aiskillstore/marketplace/tree/main/skills/tikoci/routeros-app-yaml
SKILL.md
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. Think of it as MikroTik's opinionated alternative to docker-compose.
Key concepts:
- Each
/appis 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
| Feature | docker-compose | RouterOS /app |
|---|---|---|
| Port format | host:container[/protocol] |
Two styles (see below) |
| Environment | KEY=value or list |
Same, but placeholders expand |
| Volumes | Named or bind mounts | Subset — no bind mount options |
| Networks | Full docker network model | Simplified — name + external |
| Build | Full Dockerfile support | Minimal (context + dockerfile) |
| Configs | Docker configs API | Inline content only |
| Deploy/resources | Yes | No — not supported |
Top-level version: |
Deprecated (was required) | Not used |
| File extension | .yml / .yaml |
.tikapp.yaml (convention) |
Top-Level Properties
| Property | Type | Required | Description |
|---|---|---|---|
name |
string | No | Unique identifier for the /app |
descr |
string | No | Human-readable description shown in app UI |
page |
string (URI) | No | Project homepage URL |
category |
string (enum) | No | App store classification |
icon |
string (URI) | No | Icon URL (shown in WebFig with show-in-webfig=yes) |
default-credentials |
string or null | No | username:password shown in UI |
url-path |
string | No | URL path suffix for browser access (e.g., /admin) |
credentials |
string | No | Credential hint (alternative to default-credentials) |
option |
boolean | No | Whether app is optional |
auto-update |
boolean | No | Pull and restart containers on every boot |
services |
object | Yes | Container service definitions (≥1 required) |
volumes |
object | No | Named volume declarations |
networks |
object | No | Network declarations |
configs |
object | No | Config 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.
| Property | Type | Description |
|---|---|---|
image |
string | Container image (omit registry to use /container/config's registry-url) |
container_name |
string | Explicit name; used as base for file paths under /container |
hostname |
string | Container hostname |
entrypoint |
string or string[] | Override default entrypoint |
command |
string or string[] | Override default command |
ports |
array | Port mappings (see format section) |
environment |
object or array or null | Environment variables (KEY=value list or {KEY: value} map) |
volumes |
array of strings | Volume mounts (e.g., my-vol:/data) |
configs |
array of objects | Config file placements ({source, target, mode}) |
restart |
enum | no, always, on-failure, unless-stopped |
depends_on |
array or object | Service dependency ordering |
devices |
array of strings | Device mappings passed to container |
user |
string | User to run container as |
security_opt |
array of strings | Security options |
shm_size |
string | Shared memory size |
stop_grace_period |
string or int | Time before SIGKILL |
ulimits |
object | Resource limits (e.g., nofile: {soft: 65536, hard: 65536}) |
build |
object or string | Build configuration (context, dockerfile, args) |
healthcheck |
object | Health check (test, interval, timeout, retries, start_period) |
stdin_open |
boolean | Keep stdin open |
expose |
array | Internal ports (not published to host) |
secrets |
array of strings | Secrets to expose |
attach |
boolean | Attach 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:
| Placeholder | Expands 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:
| Schema | Purpose | Port validation | Env var names |
|---|---|---|---|
*.latest.json |
CI/strict validation | Regex patterns enforced | ^[A-Z_][A-Z0-9_]*$ only |
*.editor.json |
Editor/SchemaStore UX | No 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/:udpsuffix) - 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.jsonfor mixed case - Forgetting the container package —
/appreturns 404 without thecontainerextra package - Using
deploy:orresources:— not supported by RouterOS
Additional Resources
- For RouterOS fundamentals, CLI syntax, REST API: see the
routeros-fundamentalsskill - For running CHR in QEMU (needed to test /app): see the
routeros-qemu-chrskill - MikroTik forum reference: https://forum.mikrotik.com/t/amm0s-manual-for-custom-app-containers-7-22beta/268036/22
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
perigon-backend
Perigon ASP.NET Core + EF Core + Aspire conventions
perigon-agent
Pointers for Copilot/agents to apply Perigon conventions
perigon-angular
Angular 21+ standalone/Material/signal conventions for Perigon WebApp
fastapi-mastery
Comprehensive FastAPI development skill covering REST API creation, routing, request/response handling, validation, authentication, database integration, middleware, and deployment. Use when working with FastAPI projects, building APIs, implementing CRUD operations, setting up authentication/authorization, integrating databases (SQL/NoSQL), adding middleware, handling WebSockets, or deploying FastAPI applications. Triggered by requests involving .py files with FastAPI code, API endpoint creation, Pydantic models, or FastAPI-specific features.
context7-efficient
Token-efficient library documentation fetcher using Context7 MCP with 86.8% token savings through intelligent shell pipeline filtering. Fetches code examples, API references, and best practices for JavaScript, Python, Go, Rust, and other libraries. Use when users ask about library documentation, need code examples, want API usage patterns, are learning a new framework, need syntax reference, or troubleshooting with library-specific information. Triggers include questions like "Show me React hooks", "How do I use Prisma", "What's the Next.js routing syntax", or any request for library/framework documentation.
browser-use
Browser automation using Playwright MCP. Navigate websites, fill forms, click elements, take screenshots, and extract data. Use when tasks require web browsing, form submission, web scraping, UI testing, or any browser interaction.
Didn't find tool you were looking for?