{
  "schema_version": 1,
  "generated_at": "2026-10-22T00:00:00.000Z",
  "canonical_url": "https://openlogs.fyi/tools/kener",
  "slug": "kener",
  "name": "Kener",
  "tagline": "Status page generator that shows service uptime and incidents.",
  "replaces": {
    "summary": "Paid status page services, such as Statuspage.",
    "products": [
      {
        "slug": "statuspage",
        "name": "Statuspage",
        "vendor": "Atlassian",
        "url": "https://openlogs.fyi/alternatives/statuspage"
      }
    ]
  },
  "stack": [
    {
      "kind": "language",
      "name": "TypeScript"
    },
    {
      "kind": "database",
      "name": "Redis"
    }
  ],
  "deployment_methods": [
    "docker_compose"
  ],
  "requirements": {
    "min_ram_mb": null,
    "min_cpu_cores": null,
    "source_url": null
  },
  "license": {
    "spdx": "MIT",
    "class": "osi",
    "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/LICENSE"
  },
  "business_model": {
    "value": "unknown",
    "notes": "The README at the pinned commit does not state a business model, so it stays unknown.",
    "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/README.md",
    "checked_at": "2026-10-22"
  },
  "difficulty": {
    "value": "medium",
    "reason": "2 services (1 database or broker: redis), 2 volume mounts, no env values to set, no elevated host access. Heuristic score 3 of 11: medium."
  },
  "repository": {
    "owner": "rajnandan1",
    "name": "kener",
    "url": "https://github.com/rajnandan1/kener"
  },
  "compose_check": {
    "status": "config_ok",
    "validated_at": "2026-10-22",
    "summary": "config_ok on 2026-10-22"
  },
  "recipe": {
    "version": 1,
    "source_path": "docker-compose.yml",
    "source_repo": "rajnandan1/kener",
    "source_commit_sha": "5bc658b771d44f48b61a514cfdb5037468c5aa36",
    "source_kind": "app_repo",
    "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml"
  },
  "install_steps": [
    {
      "order": 1,
      "kind": "prerequisite",
      "language": "text",
      "label": "Docker with the Compose plugin",
      "body": "A host with Docker and the Docker Compose plugin. This entry runs from a compose file.",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "validation_status": "unvalidated"
    },
    {
      "order": 2,
      "kind": "compose",
      "language": "yaml",
      "label": "Save the compose file as docker-compose.yml",
      "body": "# =============================================================================\n# Kener v4 — Production Docker Compose\n#\n# Usage:\n#   docker compose up -d\n#\n# Defaults to the published image. To use a local build instead:\n#   docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d\n# =============================================================================\n\nservices:\n  # ---------------------------------------------------------------------------\n  # Redis — required for BullMQ queues, caching, and scheduler\n  # ---------------------------------------------------------------------------\n  redis:\n    image: redis:7-alpine\n    container_name: kener-redis\n    restart: unless-stopped\n    volumes:\n      - redis_data:/data\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"ping\"]\n      interval: 10s\n      timeout: 5s\n      retries: 5\n\n  # ---------------------------------------------------------------------------\n  # Kener — Status Page Application\n  # ---------------------------------------------------------------------------\n  kener:\n    image: rajnandan1/kener:latest\n    # For Alpine variant use: rajnandan1/kener:alpine\n    container_name: kener\n    environment:\n      # ── Required ──\n      KENER_SECRET_KEY: replace_me_with_a_random_string # generate: openssl rand -base64 32\n      ORIGIN: http://localhost:3000 # public URL of your Kener instance (required for CSRF protection)\n      REDIS_URL: redis://redis:6379\n\n      # ── Database (default: SQLite) ──\n      # DATABASE_URL: sqlite://./database/kener.sqlite.db\n      # DATABASE_URL: postgresql://user:password@postgres:5432/kener\n      # DATABASE_URL: mysql://user:password@mysql:3306/kener\n\n      # ── Email (optional) ──\n      # RESEND_API_KEY:\n      # RESEND_SENDER_EMAIL:\n      # SMTP_HOST:\n      # SMTP_PORT:\n      # SMTP_USER:\n      # SMTP_PASSWORD:\n      # SMTP_SENDER:\n      # SMTP_SECURE: 0\n\n      # ── Advanced (you likely don't need to change these) ──\n      # PORT: 3000\n      # KENER_BASE_PATH:\n      # NODE_ENV: production          # already set in the image\n    ports:\n      - \"3000:3000\"\n    volumes:\n      - data:/app/database\n    depends_on:\n      redis:\n        condition: service_healthy\n    restart: unless-stopped\n\n  # ---------------------------------------------------------------------------\n  # Optional: PostgreSQL (uncomment and set DATABASE_URL above)\n  # ---------------------------------------------------------------------------\n  # postgres:\n  #   image: postgres:16-alpine\n  #   container_name: kener-postgres\n  #   environment:\n  #     POSTGRES_USER: kener\n  #     POSTGRES_PASSWORD: change_me        # use a strong password\n  #     POSTGRES_DB: kener\n  #   volumes:\n  #     - postgres_data:/var/lib/postgresql/data\n  #   restart: unless-stopped\n  #   healthcheck:\n  #     test: [\"CMD-SHELL\", \"pg_isready -U kener\"]\n  #     interval: 10s\n  #     timeout: 5s\n  #     retries: 5\n\n  # ---------------------------------------------------------------------------\n  # Optional: MySQL / MariaDB (uncomment and set DATABASE_URL above)\n  # ---------------------------------------------------------------------------\n  # mysql:\n  #   image: mariadb:11\n  #   container_name: kener-mysql\n  #   environment:\n  #     MYSQL_USER: kener\n  #     MYSQL_PASSWORD: change_me            # use a strong password\n  #     MYSQL_DATABASE: kener\n  #     MYSQL_RANDOM_ROOT_PASSWORD: \"true\"\n  #   volumes:\n  #     - mysql_data:/var/lib/mysql\n  #   restart: unless-stopped\n  #   healthcheck:\n  #     test: [\"CMD\", \"healthcheck.sh\", \"--connect\", \"--innodb_initialized\"]\n  #     interval: 10s\n  #     timeout: 5s\n  #     retries: 5\n\nvolumes:\n  data:\n    name: kener_db\n  redis_data:\n    name: kener_redis\n  # postgres_data:\n  #   name: kener_postgres\n  # mysql_data:\n  #   name: kener_mysql\n",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "validation_status": "config_ok"
    },
    {
      "order": 3,
      "kind": "env",
      "language": "text",
      "label": "Set the values the compose file needs",
      "body": "Replace the placeholder values listed under Gotchas.",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "validation_status": "unvalidated"
    },
    {
      "order": 4,
      "kind": "shell",
      "language": "bash",
      "label": "Start it",
      "body": "docker compose up -d",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "validation_status": "unvalidated"
    },
    {
      "order": 5,
      "kind": "verify",
      "language": "text",
      "label": "Open the app",
      "body": "Open http://localhost:3000. The compose file publishes host port 3000 for the kener service.",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "validation_status": "unvalidated"
    }
  ],
  "notes": [
    {
      "kind": "gotcha",
      "title": "Some images use the latest tag or no tag",
      "body": "Images without a pinned version: kener: rajnandan1/kener:latest. A later pull can get a different version.",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file has placeholder values",
      "body": "Placeholder values: KENER_SECRET_KEY is \"replace_me_with_a_random_string\" (kener).",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file publishes host ports",
      "body": "Host ports: 3000 (kener). A port without a host address listens on all host network interfaces.",
      "source_url": "https://github.com/rajnandan1/kener/blob/5bc658b771d44f48b61a514cfdb5037468c5aa36/docker-compose.yml",
      "checked_at": "2026-10-22"
    }
  ],
  "signals": {
    "captured_at": "2026-10-22",
    "stars": 5212,
    "forks": 311,
    "open_issues": 64,
    "last_push": "2026-10-22",
    "days_since_push": 0,
    "latest_release": "v4.1.8",
    "latest_release_date": "2026-10-22",
    "days_since_release": 0
  },
  "links": {
    "html": "https://openlogs.fyi/tools/kener",
    "markdown": "https://openlogs.fyi/tools/kener.md",
    "json": "https://openlogs.fyi/tools/kener.json"
  },
  "updated_at": "2026-10-22"
}
