Skip to main content

Overview

This template provides a production‑ready Strapi instance as a Monk runnable. You can:
  • Run it directly to get a managed headless CMS with customizable content types
  • Inherit it in your own applications to add a flexible, developer-friendly CMS
Strapi is the leading open-source headless CMS. It’s 100% JavaScript, fully customizable, and developer-first. Build powerful APIs in minutes with a beautiful admin panel that makes content management easy.

What this template manages

  • Strapi server with admin UI
  • PostgreSQL or MySQL database
  • Media library and file uploads
  • REST and GraphQL APIs
  • Content type builder
  • Web UI on port 1337

Quick start (run directly)

  1. Load templates
monk load MANIFEST
  1. Run Strapi with defaults
monk run strapi/strapi
  1. Customize credentials (recommended via inheritance)
Running directly uses the defaults defined in this template’s variables. Secrets added with monk secrets add will not affect this runnable unless you inherit it and reference those secrets.
  • Preferred: inherit and replace variables with secret("...") as shown below.
  • Alternative: fork/clone and edit the variables in strapi/strapi.yaml, then monk load MANIFEST and run.
Once started, access Strapi at http://localhost:1337/admin and create your admin user on first launch.

Configuration

Key variables you can customize in this template:
variables:
  strapi-image-tag: "latest"          # Strapi image tag
  strapi-port: "1337"                 # web UI and API port
  app-keys: "..."                     # app secret keys (comma-separated, 4 keys required)
  api-token-salt: "..."               # API token salt (env: API_TOKEN_SALT)
  admin-jwt-secret: "..."             # admin JWT secret (env: ADMIN_JWT_SECRET)
  jwt-secret: "..."                   # JWT secret (env: JWT_SECRET)
  db-client: "postgres"               # database client (postgres, mysql, sqlite)
  postgres-password: "..."            # PostgreSQL password (env: DATABASE_PASSWORD)
  postgres-user: "strapi"             # PostgreSQL user (env: DATABASE_USERNAME)
  postgres-db: "strapi"               # PostgreSQL database name (env: DATABASE_NAME)
Data is persisted under ${monk-volume-path}/strapi and ${monk-volume-path}/postgres on the host. Inherit the Strapi runnable in your application and declare a connection. Example:
namespace: myapp
cms:
  defines: runnable
  inherits: strapi/strapi
  variables:
    app-keys:
      value: <- secret("strapi-app-keys")
    jwt-secret:
      value: <- secret("strapi-jwt-secret")
    admin-jwt-secret:
      value: <- secret("strapi-admin-jwt-secret")
    api-token-salt:
      value: <- secret("strapi-api-token-salt")
webapp:
  defines: runnable
  containers:
    app:
      image: myorg/webapp
  connections:
    content:
      runnable: cms
      service: strapi
  variables:
    strapi-url:
      value: <- connection-hostname("content")
    strapi-api-token:
      value: <- secret("strapi-api-token")
Then set the secrets once and run your app group:
monk secrets add -g strapi-app-keys="<key1>,<key2>,<key3>,<key4>"
monk secrets add -g strapi-jwt-secret="<jwt-secret>"
monk secrets add -g strapi-admin-jwt-secret="<admin-jwt-secret>"
monk secrets add -g strapi-api-token-salt="<api-token-salt>"
monk secrets add -g strapi-api-token="<api-token>"
monk run myapp/webapp

Ports and connectivity

  • Service: strapi on TCP port 1337
  • Admin: http://\<host>:1337/admin
  • REST API: http://\<host>:1337/api/\<content-type>
  • GraphQL: http://\<host>:1337/graphql (plugin)
  • From other runnables in the same process group, use connection-hostname("\<connection-name>") to resolve the Strapi host.

Persistence and configuration

  • Uploads: ${monk-volume-path}/strapi/public:/opt/app/public
  • App data: ${monk-volume-path}/strapi/.strapi:/opt/app/.strapi
  • Database: ${monk-volume-path}/postgres:/var/lib/postgresql/data

Features

  • Content Type Builder: Visual editor for data models
  • Media Library: Upload, manage, and optimize assets
  • REST & GraphQL: Auto-generated APIs from content types
  • Role-Based Access: Granular permissions for users and API tokens
  • Plugins: Extend functionality (i18n, email, upload providers)
  • Webhooks: Trigger external services on content changes
  • Draft & Publish: Content versioning workflow
  • Customizable Admin: Extend with React components
  • Multi-Database: PostgreSQL, MySQL, SQLite, MariaDB

API Access

REST API example:
# Get all articles
curl http://localhost:1337/api/articles

# Get single article
curl http://localhost:1337/api/articles/1

# Create article (authenticated)
curl -X POST http://localhost:1337/api/articles \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "title": "Hello Strapi",
      "content": "My first article"
    }
  }'

Content Types

Create content types in the admin:
  1. Go to Content-Type Builder
  2. Create new collection type (e.g., “Article”)
  3. Add fields (title, content, image, etc.)
  4. Save and auto-restart
  5. API endpoints are automatically generated

Use cases

Strapi excels at:
  • Headless CMS for websites and mobile apps
  • E-commerce backends
  • Blog and publishing platforms
  • Multi-channel content delivery
  • Rapid prototyping and MVPs
  • Internal admin dashboards
  • API-first applications
  • Combine with PostgreSQL or MySQL templates for content storage
  • Use with CDN templates for static asset delivery
  • Integrate with object storage (S3, MinIO) for media files

Troubleshooting

  • Access Strapi admin at http://localhost:1337/admin on first launch to create your admin user.
  • Generate secrets:
# Generate random secrets for app-keys, jwt-secret, etc.
openssl rand -base64 32
  • For first-time setup, ensure app-keys has 4 comma-separated keys (e.g., "key1,key2,key3,key4").
  • Create API tokens in the Strapi admin: Settings → API Tokens.
  • Check logs:
monk logs -l 500 -f strapi/strapi
  • If database connection fails, verify PostgreSQL is running and credentials are correct.
  • For file upload issues, ensure volume permissions allow the container to write.
  • For API errors, verify authentication tokens and content type permissions in the admin.