{
  "schema_version": 1,
  "generated_at": "2026-10-23T00:00:00.000Z",
  "canonical_url": "https://openlogs.fyi/tools/inventree",
  "slug": "inventree",
  "name": "InvenTree",
  "tagline": "Inventory and parts management system with stock tracking and bills of materials.",
  "replaces": {
    "summary": "Paid inventory management services, such as Sortly.",
    "products": [
      {
        "slug": "sortly",
        "name": "Sortly",
        "vendor": "Sortly",
        "url": "https://openlogs.fyi/alternatives/sortly"
      }
    ]
  },
  "stack": [
    {
      "kind": "language",
      "name": "Python"
    },
    {
      "kind": "database",
      "name": "PostgreSQL"
    },
    {
      "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/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/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/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/README.md",
    "checked_at": "2026-10-22"
  },
  "difficulty": {
    "value": "hard",
    "reason": "5 services (2 database or broker: postgres, redis), 9 volume mounts, 6 env values to set, no elevated host access. Heuristic score 8 of 11: hard. A source checkout is needed, so the rating is at least medium."
  },
  "repository": {
    "owner": "inventree",
    "name": "InvenTree",
    "url": "https://github.com/inventree/InvenTree"
  },
  "compose_check": {
    "status": "config_ok",
    "validated_at": "2026-10-22",
    "summary": "config_ok on 2026-10-22"
  },
  "recipe": {
    "version": 1,
    "source_path": "contrib/container/docker-compose.yml",
    "source_repo": "inventree/InvenTree",
    "source_commit_sha": "b9793b0a1fb803f2d2833d58ac77e6020acc5381",
    "source_kind": "app_repo",
    "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml"
  },
  "install_steps": [
    {
      "order": 1,
      "kind": "prerequisite",
      "language": "text",
      "label": "Docker with the Compose plugin and git",
      "body": "A host with Docker, the Docker Compose plugin and git. This entry needs a checkout of the project repository.",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 2,
      "kind": "shell",
      "language": "bash",
      "label": "Get the source at commit b9793b0",
      "body": "git init InvenTree\ncd InvenTree\ngit remote add origin https://github.com/inventree/InvenTree.git\ngit sparse-checkout init --cone\ngit sparse-checkout set contrib/container\ngit fetch --depth 1 --filter=blob:none origin b9793b0a1fb803f2d2833d58ac77e6020acc5381\ngit checkout FETCH_HEAD",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 3,
      "kind": "shell",
      "language": "bash",
      "label": "Go to the folder the docs use",
      "body": "cd contrib/container",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 4,
      "kind": "compose",
      "language": "yaml",
      "label": "The compose file in the checkout: contrib/container/docker-compose.yml (shown here for reading)",
      "body": "# Docker compose recipe for a production-ready InvenTree setup, with the following containers:\n# - PostgreSQL as the database backend\n# - gunicorn as the InvenTree web server\n# - django-q as the InvenTree background worker process\n# - Caddy as a reverse proxy\n# - redis as the cache manager (optional, enabled by default)\n\n# ---------------------\n# READ BEFORE STARTING!\n# ---------------------\n\n# -----------------------------\n# Setting environment variables\n# -----------------------------\n# Shared environment variables should be stored in the .env file\n# Changes made to this file are reflected across all containers!\n#\n# IMPORTANT NOTE:\n# You should not have to change *anything* within this docker-compose.yml file!\n# Instead, make any changes in the .env file!\n\n# ------------------------\n# InvenTree Image Versions\n# ------------------------\n# By default, this docker-compose script targets the STABLE version of InvenTree,\n# image: inventree/inventree:stable\n#\n# To run the LATEST (development) version of InvenTree,\n# change the INVENTREE_TAG variable (in the .env file) to \"latest\"\n#\n# Alternatively, you could target a specific tagged release version with (for example):\n# INVENTREE_TAG=0.7.5\n#\n\n# ----------------------------\n# Docker compose customization\n# ----------------------------\n# If you wish to customize the docker-compose script, you should only do so if you understand the stack!\n# Do not expect support for customizations that are not part of the standard InvenTree setup!\n\nservices:\n    # Database service\n    # Use PostgreSQL as the database backend\n    inventree-db:\n        image: postgres:17\n        container_name: inventree-db\n        expose:\n            - ${INVENTREE_DB_PORT:-5432}/tcp\n        environment:\n            - PGDATA=/var/lib/postgresql/data/pgdb\n            - POSTGRES_USER=${INVENTREE_DB_USER:?You must provide the 'INVENTREE_DB_USER' variable in the .env file}\n            - POSTGRES_PASSWORD=${INVENTREE_DB_PASSWORD:?You must provide the 'INVENTREE_DB_PASSWORD' variable in the .env file}\n            - POSTGRES_DB=${INVENTREE_DB_NAME:?You must provide the 'INVENTREE_DB_NAME' variable in the .env file}\n        volumes:\n            # Map 'data' volume such that postgres database is stored externally\n            - ${INVENTREE_EXT_VOLUME:?You must specify the 'INVENTREE_EXT_VOLUME' variable in the .env file!}:/var/lib/postgresql/data/:z\n        healthcheck:\n            test: ['CMD-SHELL', 'pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\"']\n            interval: 15s\n            timeout: 5s\n            retries: 10\n            start_period: 20s\n        restart: unless-stopped\n\n    # redis acts as database cache manager\n    inventree-cache:\n        image: redis:7-alpine\n        container_name: inventree-cache\n        # Disable disk persistence to avoid permission errors on Windows bind mounts.\n        # The /data volume is retained for layout consistency (#11100); cache data is ephemeral.\n        command: redis-server --save \"\" --appendonly no\n        env_file:\n            - .env\n        expose:\n            - ${INVENTREE_CACHE_PORT:-6379}\n        volumes:\n            - ${INVENTREE_EXT_VOLUME}/redis:/data\n        healthcheck:\n            test: ['CMD', 'redis-cli', 'ping']\n            interval: 15s\n            timeout: 5s\n            retries: 10\n            start_period: 10s\n        restart: always\n\n    # InvenTree web server service\n    # Uses gunicorn as the web server\n    inventree-server:\n        # If you wish to specify a particular InvenTree version, do so here\n        image: inventree/inventree:${INVENTREE_TAG:-stable}\n        container_name: inventree-server\n        # Only change this port if you understand the stack.\n        expose:\n            - ${INVENTREE_WEB_PORT:-8000}\n        depends_on:\n            inventree-db:\n                condition: service_healthy\n            inventree-cache:\n                condition: service_healthy\n        env_file:\n            - .env\n        environment:\n          INVENTREE_SERVER: http://inventree-server:${INVENTREE_WEB_PORT}\n        volumes:\n            # Data volume must map to /home/inventree/data\n            - ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z\n        healthcheck:\n            test:\n                [\n                    'CMD-SHELL',\n                    'invoke server-health --address \"http://localhost:$${INVENTREE_WEB_PORT:-8000}\"',\n                ]\n            interval: 20s\n            timeout: 5s\n            retries: 10\n            start_period: 60s\n        restart: unless-stopped\n\n    # Background worker process handles long-running or periodic tasks\n    inventree-worker:\n        # If you wish to specify a particular InvenTree version, do so here\n        image: inventree/inventree:${INVENTREE_TAG:-stable}\n        container_name: inventree-worker\n        command: invoke worker\n        depends_on:\n            inventree-server:\n                condition: service_healthy\n        env_file:\n            - .env\n        volumes:\n            # Data volume must map to /home/inventree/data\n            - ${INVENTREE_EXT_VOLUME}:/home/inventree/data:z\n        healthcheck:\n            test: ['CMD-SHELL', 'invoke worker-health']\n            interval: 60s\n            timeout: 10s\n            retries: 3\n            start_period: 180s\n        restart: unless-stopped\n\n    # caddy acts as reverse proxy and static file server\n    # You can adjust the ports that the proxy listens on via the .env file\n    # https://hub.docker.com/_/caddy\n    inventree-proxy:\n        container_name: inventree-proxy\n        image: caddy:alpine\n        restart: always\n        depends_on:\n            inventree-server:\n                condition: service_healthy\n            inventree-worker:\n                condition: service_healthy\n        ports:\n            - ${INVENTREE_HTTP_PORT:-80}:80\n            - ${INVENTREE_HTTPS_PORT:-443}:443\n        env_file:\n            - .env\n        healthcheck:\n            test: ['CMD', 'wget', '--spider', '-q', 'http://127.0.0.1:9090/api/system/health/']\n            interval: 20s\n            timeout: 5s\n            retries: 10\n            start_period: 20s\n        volumes:\n            - ./Caddyfile:/etc/caddy/Caddyfile:ro,z\n            - ${INVENTREE_EXT_VOLUME}/static:/var/www/static:z\n            - ${INVENTREE_EXT_VOLUME}/media:/var/www/media:z\n            - ${INVENTREE_EXT_VOLUME}:/var/log:z\n            - ${INVENTREE_EXT_VOLUME}:/data:z\n            - ${INVENTREE_EXT_VOLUME}:/config:z\n",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml",
      "validation_status": "config_ok"
    },
    {
      "order": 5,
      "kind": "note",
      "language": "text",
      "label": "What the compose file check ran with",
      "body": "The compose file check ran in a checkout of inventree/InvenTree at b9793b0a1fb803f2d2833d58ac77e6020acc5381 (a sparse checkout: the top-level files and the folder contrib/container), in the folder contrib/container. The Docker install guide tells the reader to download docker-compose.yml, .env and Caddyfile from the contrib/container folder into one folder, set the data folder and database login in .env and run docker compose up -d.",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 6,
      "kind": "shell",
      "language": "bash",
      "label": "Start it",
      "body": "docker compose up -d",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    },
    {
      "order": 7,
      "kind": "verify",
      "language": "text",
      "label": "Open the app",
      "body": "Open http://inventree.localhost. The docs name this address. The compose file publishes host port 80 for the inventree-proxy service. The docs say a custom domain can be set in .env.",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/docs/docs/start/docker_install.md",
      "validation_status": "unvalidated"
    }
  ],
  "notes": [
    {
      "kind": "gotcha",
      "title": "The compose file publishes host ports",
      "body": "Host ports: 80 (inventree-proxy), 443 (inventree-proxy). A port without a host address listens on all host network interfaces.",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml",
      "checked_at": "2026-10-22"
    },
    {
      "kind": "gotcha",
      "title": "The compose file mounts host folders",
      "body": "Host paths mounted into containers: ${INVENTREE_EXT_VOLUME}/redis at /data (inventree-cache), ${INVENTREE_EXT_VOLUME} at /home/inventree/data (inventree-server), ${INVENTREE_EXT_VOLUME} at /home/inventree/data (inventree-worker), ./Caddyfile at /etc/caddy/Caddyfile (inventree-proxy), ${INVENTREE_EXT_VOLUME}/static at /var/www/static (inventree-proxy), ${INVENTREE_EXT_VOLUME}/media at /var/www/media (inventree-proxy), ${INVENTREE_EXT_VOLUME} at /var/log (inventree-proxy), ${INVENTREE_EXT_VOLUME} at /data (inventree-proxy) and 1 more.",
      "source_url": "https://github.com/inventree/InvenTree/blob/b9793b0a1fb803f2d2833d58ac77e6020acc5381/contrib/container/docker-compose.yml",
      "checked_at": "2026-10-22"
    }
  ],
  "signals": {
    "captured_at": "2026-10-22",
    "stars": 7743,
    "forks": 1591,
    "open_issues": 148,
    "last_push": "2026-10-22",
    "days_since_push": 0,
    "latest_release": "1.6.1",
    "latest_release_date": "2026-10-21",
    "days_since_release": 1
  },
  "links": {
    "html": "https://openlogs.fyi/tools/inventree",
    "markdown": "https://openlogs.fyi/tools/inventree.md",
    "json": "https://openlogs.fyi/tools/inventree.json"
  },
  "updated_at": "2026-10-22"
}
