{
  "schema_version": 1,
  "generated_at": "2026-10-23T00:00:00.000Z",
  "canonical_url": "https://openlogs.fyi/tools/leantime",
  "slug": "leantime",
  "name": "Leantime",
  "tagline": "Project management system for teams that do not have a dedicated project manager.",
  "replaces": {
    "summary": "Paid project management services, such as Asana and Jira.",
    "products": [
      {
        "slug": "asana",
        "name": "Asana",
        "vendor": "Asana",
        "url": "https://openlogs.fyi/alternatives/asana"
      },
      {
        "slug": "jira",
        "name": "Jira",
        "vendor": "Atlassian",
        "url": "https://openlogs.fyi/alternatives/jira"
      }
    ]
  },
  "stack": [
    {
      "kind": "language",
      "name": "PHP"
    },
    {
      "kind": "database",
      "name": "MySQL"
    }
  ],
  "deployment_methods": [
    "docker_compose"
  ],
  "requirements": {
    "min_ram_mb": null,
    "min_cpu_cores": null,
    "source_url": null
  },
  "license": {
    "spdx": "AGPL-3.0",
    "class": "osi",
    "source_url": "https://github.com/Leantime/leantime/blob/8464a2eac9f6206f85e03269909c5227ea12f8ea/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/Leantime/leantime/blob/8464a2eac9f6206f85e03269909c5227ea12f8ea/README.md",
    "checked_at": "2026-10-22"
  },
  "difficulty": {
    "value": "hard",
    "reason": "3 services (2 database or broker: mysql), 5 volume mounts, 1 env value to set, host access: cap_add. Heuristic score 7 of 11: hard."
  },
  "repository": {
    "owner": "Leantime",
    "name": "leantime",
    "url": "https://github.com/Leantime/leantime"
  },
  "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": "Leantime/docker-leantime",
    "source_commit_sha": "8718fac482d8af4ff98cb995baf5aa23d5e90bec",
    "source_kind": "packaging_repo",
    "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/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/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/README.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 2,
      "kind": "compose",
      "language": "yaml",
      "label": "Save the compose file as docker-compose.yml",
      "body": "version: '3.3'\n\nservices:\n  leantime_db:\n    image: mysql:8.4\n    container_name: mysql_leantime\n    volumes:\n      - db_data:/var/lib/mysql\n    restart: unless-stopped\n    env_file: ./.env                                        # Environment file with settings\n    networks:\n      - leantime-net\n    command: --character-set-server=UTF8MB4 --collation-server=UTF8MB4_unicode_ci\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\"]\n      interval: 30s\n      timeout: 10s\n      retries: 3\n\n  leantime:\n    image: leantime/leantime:${LEAN_VERSION:-latest}\n    restart: unless-stopped\n    env_file: ./.env                                        # Environment file with settings\n    # Add security options\n    security_opt:\n      - no-new-privileges:true\n    # Add capabilities\n    cap_add:\n      # - CAP_NET_BIND_SERVICE\n      - CAP_CHOWN\n      - CAP_SETGID\n      - CAP_SETUID\n    ports:\n      - \"${LEAN_PORT:-8080}:8080\"\n    networks:\n      - leantime-net\n    volumes:\n      - public_userfiles:/var/www/html/public/userfiles     # Volume to store public files, logo etc\n      - userfiles:/var/www/html/userfiles                   # Original volume name for compatibility\n      - plugins:/var/www/html/app/Plugins                   # Plugin storage\n      - logs:/var/www/html/storage/logs                     # Log storage\n    depends_on:\n      leantime_db:\n        condition: service_healthy\n\n  # Add a helper container for volume permissions\n  # Run via docker compose --profile mysql_helper up -d\n  mysql_helper:\n    image: mysql:8.4\n    command: chown -R mysql:mysql /var/lib/mysql\n    volumes:\n      - db_data:/var/lib/mysql\n    user: root\n    profiles: [ \"helper\" ]\n\nvolumes:\n  db_data:\n  userfiles:                                               # New volume for public files\n  public_userfiles:\n  plugins:\n  logs:\n\nnetworks:\n  leantime-net:\n",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/docker-compose.yml",
      "validation_status": "config_ok"
    },
    {
      "order": 3,
      "kind": "env",
      "language": "dotenv",
      "label": "Save as .env next to the compose file",
      "body": "# This is a sample configuration file with all possible configuration options.\n# If you don't want to maintain a file like this you can pass in all variables via Server Variables\n\n## Minimum Configuration, these are required for installation\n\n# NOTE: PUID/PGID are BUILD arguments, not runtime settings. The published\n# leantime/leantime images are built with uid/gid 1000 and setting these here has\n# NO effect — they only apply if you build the image yourself and pass them with\n# --build-arg. To run the published image under a different uid, set `user:` in\n# docker-compose.yml with group 0, e.g. user: \"1001:0\".\n#\n# Upgrading an existing install? Docker only seeds a named volume from the image\n# when the volume is EMPTY, so userfiles/plugins/logs volumes created by an older\n# image keep their original ownership and will still throw permission errors under\n# a new uid. Fix them once from the host, e.g.\n#   docker run --rm -v leantime_userfiles:/v alpine chgrp -R 0 /v && chmod -R g=u /v\n# (repeat per volume), or recreate the volumes if you have no data to keep.\n\nLEAN_PORT = '8080'                                 # The port to expose and access Leantime\nLEAN_APP_URL = ''                                  # Base URL, needed for subfolder or proxy installs (including http:// or https://)\nLEAN_APP_DIR = ''                                  # Base of application without trailing slash (used for cookies), e.g, /leantime\n\nLEAN_DEBUG = 0                                     # Debug flag\n\n# Database - MySQL container\nMYSQL_ROOT_PASSWORD = 'changeme123'                # MySQL root password\nMYSQL_DATABASE = 'leantime'                        # Database name\nMYSQL_USER = 'lean'                                # Database username\nMYSQL_PASSWORD = 'changeme123'                     # Database password\n\n# Database - leantime container\nLEAN_DB_HOST = 'mysql_leantime'                    # Database host\nLEAN_DB_USER = 'lean'                              # Database username (needs to be the same as MYSQL_USER)\nLEAN_DB_PASSWORD = 'changeme123'                   # Database password (needs to be the same as MYSQL_PASSWORD)\nLEAN_DB_DATABASE = 'leantime'                      # Database name (needs to be the same as MYSQL_DATABASE)\nLEAN_DB_PORT = '3306'                              # Database port\n\n## Session Management\nLEAN_SESSION_PASSWORD = '3evBlq9zdUEuzKvVJHWWx3QzsQhturBApxwcws2m'  # Salting sessions, replace with a strong password\nLEAN_SESSION_EXPIRATION = 28800                    # How many seconds after inactivity should we logout?  28800seconds = 8hours\nLEAN_SESSION_SECURE = false                        # Serve cookies via https only? Set to true when using https, set to false when using http. \n\n\n## Optional Configuration, you may omit these from your .env file\n\n## Default Settings\nLEAN_SITENAME = 'Leantime'                         # Name of your site, can be changed later\nLEAN_LANGUAGE = 'en-US'                            # Default language\nLEAN_DEFAULT_TIMEZONE = 'America/Los_Angeles'      # Set default timezone\nLEAN_LOG_PATH = ''                                 # Default Log Path (including filename), if not set /logs/error.log will be used\nLEAN_DISABLE_LOGIN_FORM = false                    # If true then don't show the login form (useful only if additional auth method[s] are available)\n\n## Look & Feel, these settings are available in the UI and can be overwritten there.\nLEAN_LOGO_PATH = '/dist/images/logo.svg'           # Default logo path, can be changed later\nLEAN_PRINT_LOGO_URL = '/dist/images/logo.png'      # Default logo URL use for printing (must be jpg or png format)\nLEAN_DEFAULT_THEME = 'default'                     # Default theme\nLEAN_PRIMARY_COLOR = '#006d9f'                     # Primary Theme color\nLEAN_SECONDARY_COLOR =' #00a886'                   # Secondary Theme Color\n\n\n## Fileuploads\n\n# Local File Uploads\nLEAN_USER_FILE_PATH = 'userfiles/'                 # Local relative path to store uploaded files (if not using S3)\nLEAN_DB_BACKUP_PATH = 'backupdb/'                  # Local relative path to store backup files, need permission to write\n\n# S3 File Uploads\nLEAN_USE_S3 = false                                # Set to true if you want to use S3 instead of local files\nLEAN_S3_KEY = ''                                   # S3 Key\nLEAN_S3_SECRET = ''                                # S3 Secret\nLEAN_S3_BUCKET = ''                                # Your S3 bucket\nLEAN_S3_USE_PATH_STYLE_ENDPOINT = false            # Sets the endpoint style: false => https://[bucket].[endpoint] ; true => https://[endpoint]/[bucket]\nLEAN_S3_REGION = ''                                # S3 region\nLEAN_S3_FOLDER_NAME = ''                           # Foldername within S3 (can be empty)\nLEAN_S3_END_POINT = null                           # S3 EndPoint S3 Compatible (https://sfo2.digitaloceanspaces.com)\n\n## Email\nLEAN_EMAIL_RETURN = ''                             # Return email address, needs to be valid email address format\nLEAN_EMAIL_USE_SMTP = false                        # Use SMTP? If set to false, the default php mail() function will be used\nLEAN_EMAIL_SMTP_HOSTS = ''                         # SMTP host\nLEAN_EMAIL_SMTP_AUTH = true                        # SMTP authentication required\nLEAN_EMAIL_SMTP_USERNAME = ''                      # SMTP username\nLEAN_EMAIL_SMTP_PASSWORD = ''                      # SMTP password\nLEAN_EMAIL_SMTP_AUTO_TLS = true                    # SMTP Enable TLS encryption automatically if a server supports it\nLEAN_EMAIL_SMTP_SECURE = ''                        # SMTP Security protocol (usually one of: TLS, SSL, STARTTLS)\nLEAN_EMAIL_SMTP_SSLNOVERIFY = false                # SMTP Allow insecure SSL: Don't verify certificate, accept self-signed, etc.\nLEAN_EMAIL_SMTP_PORT = ''                          # Port (usually one of 25, 465, 587, 2526)\n\n## LDAP\nLEAN_LDAP_USE_LDAP = false                         # Set to true if you want to use LDAP\nLEAN_LDAP_LDAP_DOMAIN = ''                         # Domain name after username@ so users can login without domain definition\nLEAN_LDAP_LDAP_TYPE = 'OL'                         # Select the correct directory type. Currently Supported: OL - OpenLdap, AD - Active Directory\nLEAN_LDAP_HOST = ''                                # FQDN\nLEAN_LDAP_PORT = 389                               # Default Port\nLEAN_LDAP_URI = ''                                 # LDAP URI as alternative to hostname and port. Uses ldap://hostname:port\nLEAN_LDAP_DN = ''                                  # Location of users, example: CN=users,DC=example,DC=com\n                                                   # Leantime->Ldap attribute mapping\nLEAN_LDAP_KEYS=\"{\n        \\\"username\\\":\\\"uid\\\",\n        \\\"groups\\\":\\\"memberOf\\\",\n        \\\"email\\\":\\\"mail\\\",\n        \\\"firstname\\\":\\\"displayname\\\",\n        \\\"lastname\\\":\\\"\\\",\n        \\\"phone\\\":\\\"telephoneNumber\\\",\n        \\\"jobTitle\\\":\\\"title\\\"\n        \\\"jobLevel\\\":\\\"level\\\"\n        \\\"department\\\":\\\"department\\\"\n\n}\"\n\n# For AD use these default attributes\n# LEAN_LDAP_KEYS=\"{\n#        \\\"username\\\":\\\"cn\\\",\n#        \\\"groups\\\":\\\"memberOf\\\",\n#        \\\"email\\\":\\\"mail\\\",\n#        \\\"firstname\\\":\\\"givenName\\\",\n#        \\\"lastname\\\":\\\"sn\\\",\n#        \\\"phone\\\":\\\"telephoneNumber\\\",\n#        \\\"jobTitle\\\":\\\"title\\\"\n#        \\\"jobLevel\\\":\\\"level\\\"\n#        \\\"department\\\":\\\"department\\\"\n#      }\"\n\nLEAN_LDAP_DEFAULT_ROLE_KEY = 20;                   # Default Leantime Role on creation. (set to editor)\n\n# Default role assignments upon first login.\n# optional - Can be updated later in user settings for each user\nLEAN_LDAP_GROUP_ASSIGNMENT=\"{\n               \\\"5\\\": {\n                 \\\"ltRole\\\":\\\"readonly\\\",\n                 \\\"ldapRole\\\":\\\"readonly\\\"\n               },\n               \\\"10\\\": {\n                 \\\"ltRole\\\":\\\"commenter\\\",\n                  \\\"ldapRole\\\":\\\"commenter\\\"\n               },\n               \\\"20\\\": {\n                 \\\"ltRole\\\":\\\"editor\\\",\n                  \\\"ldapRole\\\":\\\"editor\\\"\n               },\n               \\\"30\\\": {\n                 \\\"ltRole\\\":\\\"manager\\\",\n                  \\\"ldapRole\\\":\\\"manager\\\"\n               },\n               \\\"40\\\": {\n                 \\\"ltRole\\\":\\\"admin\\\",\n                  \\\"ldapRole\\\":\\\"administrators\\\"\n               },\n               \\\"50\\\": {\n                 \\\"ltRole\\\":\\\"owner\\\",\n                 \\\"ldapRole\\\":\\\"administrators\\\"\n               }\n}\"\n\n## OpenID Connect\n# required\nLEAN_OIDC_ENABLE = false\nLEAN_OIDC_CLIENT_ID =\nLEAN_OIDC_CLIENT_SECRET =\n\n# required - the URL for your provider (examples down below)\n#LEAN_OIDC_PROVIDER_URL =\n\n#Create User if it doesn't exist in Leantime db, otherwise fail login\nLEAN_OIDC_CREATE_USER = false\n\n# Default role for users created via OIDC (20 is editor)\nLEAN_OIDC_DEFAULT_ROLE = 20\n\n# optional - these will be read from the well-known configuration if possible\n#LEAN_OIDC_AUTH_URL_OVERRIDE =\n#LEAN_OIDC_TOKEN_URL_OVERRIDE =\n#LEAN_OIDC_JWKS_URL_OVERRIDE =\n#LEAN_OIDC_USERINFO_URL_OVERRIDE =\n\n# optional - override the public key for RSA validation\n#LEAN_OIDC_CERTIFICATE_STRING =\n#LEAN_OIDC_CERTIFICATE_FILE =\n\n# optional - override the requested scopes\n#LEAN_OIDC_SCOPES =\n\n# optional - override the keys used for these fields\n#LEAN_OIDC_FIELD_EMAIL =\n#LEAN_OIDC_FIELD_FIRSTNAME =\n#LEAN_OIDC_FIELD_LASTNAME =\n#LEAN_OIDC_FIELD_PHONE =\n#LEAN_OIDC_FIELD_JOBTITLE =\n#LEAN_OIDC_FIELD_JOBLEVEL=\n#LEAN_OIDC_FIELD_DEPARTMENT =\n\n## OpenID Connect setting for GitHub\n#LEAN_OIDC_PROVIDER_URL = https://token.actions.githubusercontent.com/\n#LEAN_OIDC_AUTH_URL_OVERRIDE = https://github.com/login/oauth/authorize\n#LEAN_OIDC_TOKEN_URL_OVERRIDE = https://github.com/login/oauth/access_token\n#LEAN_OIDC_USERINFO_URL_OVERRIDE = https://api.github.com/user,https://api.github.com/user/emails\n#LEAN_OIDC_SCOPES = user:email,read:user\n#LEAN_OIDC_FIELD_EMAIL = 0.email\n#LEAN_OIDC_FIELD_FIRSTNAME = name\n\n\n## Redis (for session storage and cache)\nLEAN_USE_REDIS = false                             # Set to true to use redis as session cache\nLEAN_REDIS_URL = ''                                # Add URL path such as tcp://1.2.3.4:6379. If you are using a password, add ?auth=yourverycomplexpasswordhere to your URL\nLEAN_REDIS_HOST = ''\nLEAN_REDIS_PORT = 6379\nLEAN_REDIS_PASSWORD = ''\nLEAN_REDIS_SCHEME = ''\n\n## Rate limiting\nLEAN_RATELIMIT_GENERAL = 1000\nLEAN_RATELIMIT_API = 10\nLEAN_RATELIMIT_AUTH = 20\n\n\n",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/sample.env",
      "validation_status": "unvalidated"
    },
    {
      "order": 4,
      "kind": "note",
      "language": "text",
      "label": "What the compose file check ran with",
      "body": "The compose file check ran together with sample.env from the same commit, saved as .env. The folder held only these files. The README of the project's docker-leantime repository tells the reader to clone it, copy sample.env to .env, edit the settings and run docker compose up -d.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/README.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 5,
      "kind": "shell",
      "language": "bash",
      "label": "Start it",
      "body": "docker compose up -d",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/README.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 6,
      "kind": "verify",
      "language": "text",
      "label": "Open the app",
      "body": "Open http://localhost:8080. The compose file publishes host port 8080 for the leantime service.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/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: leantime: leantime/leantime:${LEAN_VERSION:-latest}. A later pull can get a different version.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file publishes host ports",
      "body": "Host ports: 8080 (leantime). A port without a host address listens on all host network interfaces.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "Some services get elevated host access",
      "body": "leantime adds Linux capabilities.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The example env file sample.env has placeholder values",
      "body": "The example env file sets placeholder text for: MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD, LEAN_DB_PASSWORD. Replace them before you rely on the install.",
      "source_url": "https://github.com/Leantime/docker-leantime/blob/8718fac482d8af4ff98cb995baf5aa23d5e90bec/sample.env",
      "checked_at": "2026-10-22"
    }
  ],
  "signals": {
    "captured_at": "2026-10-22",
    "stars": 11882,
    "forks": 1156,
    "open_issues": 236,
    "last_push": "2026-10-21",
    "days_since_push": 1,
    "latest_release": "v3.12.0",
    "latest_release_date": "2026-10-15",
    "days_since_release": 7
  },
  "links": {
    "html": "https://openlogs.fyi/tools/leantime",
    "markdown": "https://openlogs.fyi/tools/leantime.md",
    "json": "https://openlogs.fyi/tools/leantime.json"
  },
  "updated_at": "2026-10-22"
}
