Templates

Custom Templates

Create your own deployment templates for FlatRun.

You can extend FlatRun with custom templates for your own applications or frequently deployed stacks. Custom templates work exactly like built-in templates.

Template Location

Custom templates are stored in the .flatrun/templates directory within your deployments path:

/var/flatrun/deployments/
└── .flatrun/
    └── templates/
        ├── my-custom-app/
        │   ├── metadata.yml
        │   └── docker-compose.yml
        └── my-stack/
            ├── metadata.yml
            └── docker-compose.yml

Template Structure

Each template requires two files:

metadata.yml

Describes the template and its options:

id: my-custom-app
name: My Custom Application
description: A custom application template for my team
category: applications
icon: pi-code
logo: /logos/my-app.svg
priority: 10

container_port: 3000

mount_points:
  - id: app
    label: Application
    path: /app
    description: Mount the entire application

  - id: data
    label: Data Directory
    path: /app/data
    description: Mount only the data directory

files:
  - path: .env
    template: env.tmpl

docker-compose.yml

The compose file with variable placeholders:

version: "3.8"

services:
  app:
    image: my-registry/my-app:latest
    container_name: ${NAME}-app
    ports:
      - "${PORT}:3000"
    environment:
      NODE_ENV: production
      DATABASE_URL: mysql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:3306/${DB_NAME}
    volumes:
      - ./app:/app
    networks:
      - default
      - proxy
      - database
    restart: unless-stopped

networks:
  proxy:
    external: true
  database:
    external: true

Metadata Fields

Field Required Description
id Yes Unique identifier for the template
name Yes Display name
description Yes Short description
category Yes Category: applications, frameworks, runtimes, databases, infrastructure, basic
icon No PrimeIcons class (e.g., pi-globe)
logo No Path to logo image
priority No Sort order (lower = first)
container_port No Default container port
mount_points No Available mount options
files No Additional files to generate

Variable Substitution

Use these variables in your docker-compose.yml:

Variable Description
${NAME} Deployment name
${PORT} Assigned external port
${DOMAIN} Configured domain name
${DB_HOST} Database host
${DB_PORT} Database port
${DB_NAME} Database name
${DB_USER} Database username
${DB_PASSWORD} Database password

Mount Points

Mount points define what parts of the container can be persisted to the host. Each mount point has:

mount_points:
  - id: unique_id        # Used in API calls
    label: Display Name  # Shown in UI
    path: /container/path
    description: Help text for users

Users can select which mount points to use when deploying.

Generated Files

You can generate additional configuration files during deployment using templates:

files:
  - path: .env
    template: env.tmpl

  - path: config/app.json
    template: app-config.json.tmpl

Create template files in your template directory:

# templates/my-app/env.tmpl
APP_NAME=${NAME}
APP_URL=https://${DOMAIN}
DB_CONNECTION=mysql
DB_HOST=${DB_HOST}
DB_DATABASE=${DB_NAME}
DB_USERNAME=${DB_USER}
DB_PASSWORD=${DB_PASSWORD}

Infrastructure Templates

To create a template for infrastructure services (databases, proxies, etc.), set type: infrastructure:

id: my-cache
name: My Cache Server
description: Custom caching solution
category: infrastructure
type: infrastructure

container_port: 6380

Testing Templates

  1. Create your template in .flatrun/templates/
  2. Refresh templates via the API or UI
  3. Deploy a test instance
  4. Verify all variables are substituted correctly
  5. Test the deployed application
# Refresh templates
curl -X POST "http://localhost:8090/api/templates/refresh" \
  -H "Authorization: Bearer $TOKEN"

# Check your template appears
curl -X GET "http://localhost:8090/api/templates" \
  -H "Authorization: Bearer $TOKEN" | jq '.[] | select(.id == "my-custom-app")'

Example: Full-Stack Template

A complete example for a Node.js app with Redis:

metadata.yml

id: node-redis-app
name: Node.js + Redis
description: Node.js application with Redis caching
category: frameworks
icon: pi-server
priority: 5

container_port: 3000

mount_points:
  - id: app
    label: Application Code
    path: /app
    description: Mount your Node.js application
  - id: logs
    label: Logs
    path: /app/logs
    description: Mount only log files

files:
  - path: .env
    template: env.tmpl

docker-compose.yml

version: "3.8"

services:
  app:
    image: node:20-alpine
    container_name: ${NAME}-app
    working_dir: /app
    command: npm start
    ports:
      - "${PORT}:3000"
    environment:
      NODE_ENV: production
      REDIS_URL: redis://redis:6379
    volumes:
      - ./app:/app
    depends_on:
      - redis
    networks:
      - default
      - proxy
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    container_name: ${NAME}-redis
    volumes:
      - redis_data:/data
    networks:
      - default
    restart: unless-stopped

volumes:
  redis_data:

networks:
  proxy:
    external: true

env.tmpl

NODE_ENV=production
PORT=3000
REDIS_URL=redis://redis:6379
APP_NAME=${NAME}

Best Practices

  • Unique IDs — Use descriptive, unique template IDs
  • Good Descriptions — Write clear descriptions for mount points
  • Default Ports — Use standard ports for your applications
  • Networks — Include proxy and database networks as needed
  • Restart Policy — Always set restart: unless-stopped
  • Version Control — Keep templates in version control