Skip to content
Kong Docs are moving soon! Our docs are migrating to a new home. You'll be automatically redirected to the new site in the future. In the meantime, view this page on the new site!
Kong Logo | Kong Docs Logo
  • Docs
    • Explore the API Specs
      View all API Specs View all API Specs View all API Specs arrow image
    • Documentation
      API Specs
      Kong Gateway
      Lightweight, fast, and flexible cloud-native API gateway
      Kong Konnect
      Single platform for SaaS end-to-end connectivity
      Kong AI Gateway
      Multi-LLM AI Gateway for GenAI infrastructure
      Kong Mesh
      Enterprise service mesh based on Kuma and Envoy
      decK
      Helps manage Kong’s configuration in a declarative fashion
      Kong Ingress Controller
      Works inside a Kubernetes cluster and configures Kong to proxy traffic
      Kong Gateway Operator
      Manage your Kong deployments on Kubernetes using YAML Manifests
      Insomnia
      Collaborative API development platform
  • Plugin Hub
    • Explore the Plugin Hub
      View all plugins View all plugins View all plugins arrow image
    • Functionality View all View all arrow image
      View all plugins
      AI's icon
      AI
      Govern, secure, and control AI traffic with multi-LLM AI Gateway plugins
      Authentication's icon
      Authentication
      Protect your services with an authentication layer
      Security's icon
      Security
      Protect your services with additional security layer
      Traffic Control's icon
      Traffic Control
      Manage, throttle and restrict inbound and outbound API traffic
      Serverless's icon
      Serverless
      Invoke serverless functions in combination with other plugins
      Analytics & Monitoring's icon
      Analytics & Monitoring
      Visualize, inspect and monitor APIs and microservices traffic
      Transformations's icon
      Transformations
      Transform request and responses on the fly on Kong
      Logging's icon
      Logging
      Log request and response data using the best transport for your infrastructure
  • Support
  • Community
  • Kong Academy
Get a Demo Start Free Trial
Kong Gateway
3.10.x (latest)
  • Home icon
  • Kong Gateway
  • Plugin Development
  • Installation and Distribution
github-edit-pageEdit this page
report-issueReport an issue
  • Kong Gateway
  • Kong Konnect
  • Kong Mesh
  • Kong AI Gateway
  • Plugin Hub
  • decK
  • Kong Ingress Controller
  • Kong Gateway Operator
  • Insomnia
  • Kuma

  • Docs contribution guidelines
  • 3.10.x (latest)
  • 3.9.x
  • 3.8.x
  • 3.7.x
  • 3.6.x
  • 3.5.x
  • 3.4.x (LTS)
  • 3.3.x
  • 2.8.x (LTS)
  • Archive (3.0.x and pre-2.8.x)
  • Introduction
    • Overview of Kong Gateway
    • Support
      • Version Support Policy
      • Third Party Dependencies
      • Browser Support
      • Vulnerability Patching Process
      • Software Bill of Materials
    • Stability
    • Release Notes
    • Breaking Changes
      • Kong Gateway 3.10.x
      • Kong Gateway 3.9.x
      • Kong Gateway 3.8.x
      • Kong Gateway 3.7.x
      • Kong Gateway 3.6.x
      • Kong Gateway 3.5.x
      • Kong Gateway 3.4.x
      • Kong Gateway 3.3.x
      • Kong Gateway 3.2.x
      • Kong Gateway 3.1.x
      • Kong Gateway 3.0.x
      • Kong Gateway 2.8.x or earlier
    • Key Concepts
      • Services
      • Routes
      • Consumers
      • Upstreams
      • Plugins
      • Consumer Groups
    • How Kong Works
      • Routing Traffic
      • Load Balancing
      • Health Checks and Circuit Breakers
    • Glossary
  • Get Started with Kong
    • Get Kong
    • Services and Routes
    • Rate Limiting
    • Proxy Caching
    • Key Authentication
    • Load-Balancing
  • Install Kong
    • Overview
    • Kubernetes
      • Overview
      • Install Kong Gateway
      • Configure the Admin API
      • Install Kong Manager
    • Docker
      • Using docker run
      • Build your own Docker images
    • Linux
      • Amazon Linux
      • Debian
      • Red Hat
      • Ubuntu
    • Post-installation
      • Set up a data store
      • Apply Enterprise license
      • Enable Kong Manager
  • Kong in Production
    • Deployment Topologies
      • Overview
      • Kubernetes Topologies
      • Hybrid Mode
        • Overview
        • Deploy Kong Gateway in Hybrid mode
        • Incremental Configuration Sync
      • DB-less Deployment
      • Traditional
    • Running Kong
      • Running Kong as a non-root user
      • Securing the Admin API
      • Using systemd
    • Access Control
      • Start Kong Gateway Securely
      • Programatically Creating Admins
      • Enabling RBAC
      • Workspaces
    • Licenses
      • Overview
      • Download your License
      • Deploy Enterprise License
      • Using the License API
      • Monitor Licenses Usage
    • Networking
      • Default Ports
      • DNS Considerations
      • Network and Firewall
      • CP/DP Communication through a Forward Proxy
      • PostgreSQL TLS
        • Configure PostgreSQL TLS
        • Troubleshooting PostgreSQL TLS
    • Kong Configuration File
    • Environment Variables
    • Serving a Website and APIs from Kong
    • Secrets Management
      • Overview
      • Getting Started
      • Secrets Rotation
      • Advanced Usage
      • Backends
        • Overview
        • Environment Variables
        • AWS Secrets Manager
        • Azure Key Vaults
        • Google Cloud Secret Manager
        • HashiCorp Vault
      • How-To
        • Securing the Database with AWS Secrets Manager
      • Reference Format
    • Keyring and Data Encryption
    • Monitoring
      • Overview
      • Prometheus
      • StatsD
      • Datadog
      • Health Check Probes
      • Expose and graph AI Metrics
    • Tracing
      • Overview
      • Writing a Custom Trace Exporter
      • Tracing API Reference
    • Resource Sizing Guidelines
    • Blue-Green Deployments
    • Canary Deployments
    • Clustering Reference
    • Performance
      • Performance Testing Benchmarks
      • Establish a Performance Benchmark
      • Improve performance with Brotli compression
    • Logging and Debugging
      • Log Reference
      • Dynamic log level updates
      • Customize Gateway Logs
      • Debug Requests
      • AI Gateway Analytics
      • Audit Logging
    • Configure a gRPC service
    • Use the Expressions Router
    • Outage Handling
      • Configure Data Plane Resilience
      • About Control Plane Outage Management
    • Upgrade and Migration
      • Upgrading Kong Gateway 3.x.x
      • Backup and Restore
      • Upgrade Strategies
        • Dual-Cluster Upgrade
        • In-Place Upgrade
        • Blue-Green Upgrade
        • Rolling Upgrade
      • Upgrade from 2.8 LTS to 3.4 LTS
      • Migrate from OSS to Enterprise
      • Migration Guidelines Cassandra to PostgreSQL
      • Migrate to the new DNS client
      • Breaking Changes
    • FIPS 140-2
      • Overview
      • Install the FIPS Compliant Package
    • Authenticate your Kong Gateway Amazon RDS database with AWS IAM
    • Verify Signatures for Signed Kong Images
    • Verify Build Provenance for Signed Kong Images
  • Kong AI Gateway
    • Overview
    • Get started with AI Gateway
    • LLM Provider Integration Guides
      • OpenAI
      • Cohere
      • Azure
      • Anthropic
      • Mistral
      • Llama2
      • Vertex/Gemini
      • Amazon Bedrock
    • LLM Library Integration Guides
      • LangChain
    • AI Gateway Analytics
    • Expose and graph AI Metrics
    • AI Gateway Load Balancing
    • AI Gateway plugins
  • Kong Manager
    • Overview
    • Enable Kong Manager
    • Get Started with Kong Manager
      • Services and Routes
      • Rate Limiting
      • Proxy Caching
      • Authentication with Consumers
      • Load Balancing
    • Authentication and Authorization
      • Overview
      • Create a Super Admin
      • Workspaces and Teams
      • Reset Passwords and RBAC Tokens
      • Basic Auth
      • LDAP
        • Configure LDAP
        • LDAP Service Directory Mapping
      • OIDC
        • Configure OIDC
        • OIDC Authenticated Group Mapping
        • Migrate from previous configurations
      • Sessions
      • RBAC
        • Overview
        • Enable RBAC
        • Add a Role and Permissions
        • Create a User
        • Create an Admin
    • Networking Configuration
    • Workspaces
    • Create Consumer Groups
    • Sending Email
    • Troubleshoot
    • Strengthen Security
  • Develop Custom Plugins
    • Overview
    • Getting Started
      • Introduction
      • Set up the Plugin Project
      • Add Plugin Testing
      • Add Plugin Configuration
      • Consume External Services
      • Deploy Plugins
    • File Structure
    • Implementing Custom Logic
    • Plugin Configuration
    • Accessing the Data Store
    • Storing Custom Entities
    • Caching Custom Entities
    • Extending the Admin API
    • Writing Tests
    • Installation and Distribution
    • Proxy-Wasm Filters
      • Create a Proxy-Wasm Filter
      • Proxy-Wasm Filter Configuration
    • Plugin Development Kit
      • Overview
      • kong.client
      • kong.client.tls
      • kong.cluster
      • kong.ctx
      • kong.ip
      • kong.jwe
      • kong.log
      • kong.nginx
      • kong.node
      • kong.plugin
      • kong.request
      • kong.response
      • kong.router
      • kong.service
      • kong.service.request
      • kong.service.response
      • kong.table
      • kong.telemetry.log
      • kong.tracing
      • kong.vault
      • kong.websocket.client
      • kong.websocket.upstream
    • Plugins in Other Languages
      • Go
      • Javascript
      • Python
      • Running Plugins in Containers
      • External Plugin Performance
  • Kong Plugins
    • Overview
    • Authentication Reference
    • Allow Multiple Authentication Plugins
    • Plugin Queuing
      • Overview
      • Plugin Queuing Reference
    • Dynamic Plugin Ordering
      • Overview
      • Get Started with Dynamic Plugin Ordering
    • Redis Partials
    • Datakit
      • Overview
      • Get Started with Datakit
      • Datakit Configuration Reference
      • Datakit Examples Reference
  • Admin API
    • Overview
    • Declarative Configuration
    • Enterprise API
      • Information Routes
      • Health Routes
      • Tags
      • Debug Routes
      • Services
      • Routes
      • Consumers
      • Plugins
      • Certificates
      • CA Certificates
      • SNIs
      • Upstreams
      • Targets
      • Vaults
      • Keys
      • Filter Chains
      • Licenses
      • Workspaces
      • RBAC
      • Admins
      • Consumer Groups
      • Event Hooks
      • Keyring and Data Encryption
      • Audit Logs
      • Status API
  • Reference
    • kong.conf
    • Injecting Nginx Directives
    • CLI
    • Key Management
    • The Expressions Language
      • Overview
      • Language References
      • Performance Optimizations
    • Rate Limiting Library
    • WebAssembly
    • Event Hooks
    • FAQ
On this pageOn this page
  • Packaging sources
  • Install the plugin
    • Via LuaRocks from the created ‘rock’
    • Via LuaRocks from the source archive
    • Via a Dockerfile or docker run (install and load)
    • Manually
  • Load the plugin
  • Verify loading the plugin
  • Remove a plugin
  • Distribute your plugin
    • LuaRocks
    • OCI Artifacts
  • Troubleshooting

Installation and Distribution

Custom plugins for Kong consist of Lua source files that need to be in the file system of each of your Kong nodes. This guide will provide you with step-by-step instructions that will make a Kong node aware of your custom plugin(s).

These steps should be applied to each node in your Kong cluster, to ensure the custom plugin(s) are available on each one of them.

Packaging sources

You can either use a regular packing strategy (e.g. tar), or use the LuaRocks package manager to do it for you. We recommend LuaRocks as it is installed along with Kong when using one of the official distribution packages.

When using LuaRocks, you must create a rockspec file, which specifies the package contents. For an example, see the Kong plugin template. For more info about the format, see the LuaRocks documentation on rockspecs.

Pack your rock using the following command (from the plugin repo):

  1. Install it locally (based on the .rockspec in the current directory):
     luarocks make
    
  2. Pack the installed rock:

    Important: luarocks pack is dependent on the zip utility being installed. More recent images of Kong Gateway have been hardened, and utilities such as zip are no longer available. If this is being performed as part of a custom Docker image, ensure zip is installed prior to running this command.

     luarocks pack <plugin-name> <version>
    

    Assuming your plugin rockspec is called kong-plugin-my-plugin-0.1.0-1.rockspec, the above would become;

     luarocks pack kong-plugin-my-plugin 0.1.0-1
    

The LuaRocks pack command has now created a .rock file (this is simply a zip file containing everything needed to install the rock).

If you do not or cannot use LuaRocks, then use tar to pack the .lua files of which your plugin consists into a .tar.gz archive. You can also include the .rockspec file if you do have LuaRocks on the target systems.

The contents of this archive should be close to the following:

tree <plugin-name>
<plugin-name>
├── INSTALL.txt
├── README.md
├── kong
│   └── plugins
│       └── <plugin-name>
│           ├── handler.lua
│           └── schema.lua
└── <plugin-name>-<version>.rockspec

Install the plugin

For a Kong node to be able to use the custom plugin, the custom plugin’s Lua sources must be installed on your host’s file system. There are multiple ways of doing so: via LuaRocks, or manually. Choose one of the following paths.

Reminder: regardless of which method you are using to install your plugin’s sources, you must still do so for each node in your Kong cluster.

Via LuaRocks from the created ‘rock’

The .rock file is a self contained package that can be installed locally or from a remote server.

If the luarocks utility is installed in your system (this is likely the case if you used one of the official installation packages), you can install the ‘rock’ in your LuaRocks tree (a directory in which LuaRocks installs Lua modules).

It can be installed by doing:

luarocks install <rock-filename>

The filename can be a local name, or any of the supported methods, e.g. http://myrepository.lan/rocks/my-plugin-0.1.0-1.all.rock

Via LuaRocks from the source archive

If the luarocks utility is installed in your system (this is likely the case if you used one of the official installation packages), you can install the Lua sources in your LuaRocks tree (a directory in which LuaRocks installs Lua modules).

You can do so by changing the current directory to the extracted archive, where the rockspec file is:

cd <plugin-name>

And then run the following:

luarocks make

This will install the Lua sources in kong/plugins/<plugin-name> in your system’s LuaRocks tree, where all the Kong sources are already present.

Via a Dockerfile or docker run (install and load)

If you are running Kong Gateway on Docker or Kubernetes, the plugin needs to be installed inside the Kong Gateway container. Copy or mount the plugin’s source code into the container.

Note: Official Kong Gateway images are configured to run as the nobody user. When building a custom image, to copy files into the Kong Gateway image, you must temporarily set the user to root.

Here’s an example Dockerfile that shows how to mount your plugin in the Kong Gateway image:

FROM kong/kong-gateway:latest

# Ensure any patching steps are executed as root user
USER root

# Add custom plugin to the image
COPY example-plugin/kong/plugins/example-plugin /usr/local/share/lua/5.1/kong/plugins/example-plugin
ENV KONG_PLUGINS=bundled,example-plugin

# Ensure kong user is selected for image execution
USER kong

# Run kong
ENTRYPOINT ["/entrypoint.sh"]
EXPOSE 8000 8443 8001 8444
STOPSIGNAL SIGQUIT
HEALTHCHECK --interval=10s --timeout=10s --retries=10 CMD kong health
CMD ["kong", "docker-start"]

Or, include the following in your docker run command:

-v "$custom_plugin_folder:/tmp/custom_plugins/kong" 
-e "KONG_LUA_PACKAGE_PATH=/tmp/custom_plugins/?.lua;;"
-e "KONG_PLUGINS=bundled,example-plugin"

Manually

A more conservative way of installing your plugin’s sources is to avoid “polluting” the LuaRocks tree, and instead, point Kong to the directory containing them.

This is done by tweaking the lua_package_path property of your Kong configuration. Under the hood, this property is an alias to the LUA_PATH variable of the Lua VM, if you are familiar with it.

Those properties contain a semicolon-separated list of directories in which to search for Lua sources. It should be set like so in your Kong configuration file:

lua_package_path = /<path-to-plugin-location>/?.lua;;

Where:

  • /<path-to-plugin-location> is the path to the directory containing the extracted archive. It should be the location of the kong directory from the archive.
  • ? is a placeholder that will be replaced by kong.plugins.<plugin-name> when Kong will try to load your plugin. Do not change it.
  • ;; a placeholder for the “the default Lua path”. Do not change it.

For example, if the plugin something is located on the file system and the handler file is in the following directory:

/usr/local/custom/kong/plugins/<something>/handler.lua

The location of the kong directory is /usr/local/custom, so the proper path setup would be:

lua_package_path = /usr/local/custom/?.lua;;

Multiple plugins

If you want to install two or more custom plugins this way, you can set the variable to something like:

lua_package_path = /path/to/plugin1/?.lua;/path/to/plugin2/?.lua;;
  • ; is the separator between directories.
  • ;; still means “the default Lua path”.

You can also set this property via its environment variable equivalent: KONG_LUA_PACKAGE_PATH.

Load the plugin

  1. Add the custom plugin’s name to the plugins list in your Kong configuration (on each Kong node):

     plugins = bundled,<plugin-name>
    

    Or, if you don’t want to include the bundled plugins:

     plugins = <plugin-name>
    

    If you are using two or more custom plugins, insert commas in between, like so:

     plugins = bundled,plugin1,plugin2
    

    Or:

     plugins = plugin1,plugin2
    

    You can also set this property via its environment variable equivalent: KONG_PLUGINS.

  2. Update the plugins directive for each node in your Kong cluster.

  3. Restart Kong to apply the plugin:

     kong restart
    

    Or, if you want to apply a plugin without stopping Kong, you can use this:

     kong prepare
     kong reload
    

Verify loading the plugin

You should now be able to start Kong without any issue. Consult your custom plugin’s instructions on how to enable/configure your plugin on a Service, Route, or Consumer entity.

  1. To make sure your plugin is being loaded by Kong, you can start Kong with a debug log level:

     log_level = debug
    

    or:

     KONG_LOG_LEVEL=debug
    
  2. Then, you should see the following log for each plugin being loaded:

     [debug] Loading plugin <plugin-name>
    

Remove a plugin

There are three steps to completely remove a plugin.

  1. Remove the plugin from your Kong Service or Route configuration. Make sure that it is no longer applied globally nor for any Service, Route, or consumer. This has to be done only once for the entire Kong cluster, no restart/reload required. This step in itself will make that the plugin is no longer in use. But it remains available and it is still possible to re-apply the plugin.

  2. Remove the plugin from the plugins directive (on each Kong node). Make sure to have completed step 1 before doing so. After this step it will be impossible for anyone to re-apply the plugin to any Kong Service, Route, Consumer, or even globally. This step requires to restart/reload the Kong node to take effect.

  3. To remove the plugin thoroughly, delete the plugin-related files from each of the Kong nodes. Make sure to have completed step 2, including restarting/reloading Kong, before deleting the files. If you used LuaRocks to install the plugin, you can do luarocks remove <plugin-name> to remove it.

Distribute your plugin

Depending on the platform that Gateway is running on, there are different ways of distributing custom plugins.

LuaRocks

One way to do so is to use LuaRocks, a package manager for Lua modules. It calls such modules “rocks”. Your module does not have to live inside the Kong repository, but it can be if that’s how you’d like to maintain your Kong setup.

By defining your modules (and their eventual dependencies) in a rockspec file, you can install those modules on your platform via LuaRocks. You can also upload your module on LuaRocks and make it available to everyone!

Here is an example rockspec using the builtin build type to define modules in Lua notation and their corresponding file.

For more information about the format, see the LuaRocks documentation on rockspecs.

OCI Artifacts

Many users will have access to an OCI-compliant registry like Docker Hub or Amazon ECR. Kong Plugins can be packaged as generic OCI artifacts and uploaded to one of these registries for versioning, storage, and distribution.

The advantage of distributing plugins as OCI artifacts is that users can make use of a number of ecosystem benefits including tooling around building, pushing and pulling, and signing (for secure provenance attestation) of these artifacts. The steps below illustrate a sample flow for packaging, distributing, and verifying a Kong custom plugin as an OCI artifact.

On the machine where the plugin is developed, or as part of an automated workflow, run the following steps:

  1. Package the plugin according to the Packaging Sources section above.

     tar czf my-plugin.tar.gz ./my-plugin-dir
    
  2. Use the OSS Cosign tool to generate a key pair for use signing and verifying plugins:

     cosign generate-key-pair
    

    The private key (cosign.key) should be kept secure and is used for signing the plugin artifact. The public key (cosign.pub) should be distributed and used by target machines to validate the downloaded plugin later in the flow.

    There are also key-less methods for signing and verifying artifacts with Cosign. More information is available in their documentation.

  3. Login to your OCI-compliant registry. In this case we’ll use Docker Hub:

     cat ~/foo_password.txt | docker login --username foo-user --password-stdin
    
  4. Upload the plugin artifact to the OCI registry using Cosign. This is the equivalent of running docker push <image> when pushing a local Docker image up to a registry.

     cosign upload blob -f my-plugin.tar.gz docker.io/foo-user/my-plugin
    

    The cosign upload command will return the digest of the artifact if it’s successfully uploaded.

  5. Sign the artifact with the key pair generated in step 1:

     cosign sign --key cosign.key index.docker.io/foo-user/my-plugin@sha256:xxxxxxxxxx
    

    The command may prompt for the private key passphrase. It also may prompt to confirm that you consent to the signing information being permanently recorded in Rekor, the transparency log. For more information on Sigstore tooling and flows visit the documentation.

Then, on the machines where the plugin should be installed (the Gateway data plane nodes), run the following steps (which can also be automated):

  1. Ensure the cosign.pub public key is available. Verify the signature of the plugin artifact that you want to pull:

     cosign verify --key cosign.pub index.docker.io/foo-user/my-plugin@sha256:xxxxxxxxxx
    

    The command should succeed if the artifact was verified.

  2. Use the OSS Crane tool to pull the plugin artifact to the machine:

     crane pull index.docker.io/foo-user/my-plugin@sha256:xxxxxxxxxx my-downloaded-plugin.tar.gz
    

    The command should pull the artifact and save it to the working directory.

  3. Unpackage the plugin. The downloaded .tar.gz file will contain a manifest file and another nested .tar.gz. This nested archive contains the plugin directory.

     tar xvf my-downloaded-plugin.tar.gz
     tar xvf xxxxxxxxxxxxxxxxxxxxx.tar.gz
    
  4. Copy the plugin directory to the correct location according to the install manually section above. If you have not set a custom KONG_LUA_PACKAGE_PATH, copy the plugin in to /usr/local/share/lua/5.1/kong/plugins.

  5. Update Kong’s configuration to load the custom plugin by configuring plugins=bundled,my-downloaded-plugin in kong.conf or set the KONG_PLUGINS environment variable to plugins=bundled,my-downloaded-plugin

Troubleshooting

Kong can fail to start because of a misconfigured custom plugin for several reasons:

plugin is in use but not enabled
You configured a custom plugin from another node, and that the plugin configuration is in the database, but the current node you are trying to start does not have it in its plugins directive. To resolve, add the plugin’s name to the node’s plugins directive.
plugin is enabled but not installed
The plugin’s name is present in the plugins directive, but Kong can’t load the handler.lua source file from the file system. To resolve, make sure that the lua_package_path directive is properly set to load this plugin’s Lua sources.
no configuration schema found for plugin
The plugin is installed and enabled in the plugins directive, but Kong is unable to load the schema.lua source file from the file system. To resolve, make sure that the schema.lua file is present alongside the plugin’s handler.lua file.

Previous Writing tests
Next Create a Proxy-Wasm filter
Thank you for your feedback.
Was this page useful?
Too much on your plate? close cta icon
More features, less infrastructure with Kong Konnect. 1M requests per month for free.
Try it for Free
  • Kong
    Powering the API world

    Increase developer productivity, security, and performance at scale with the unified platform for API management, service mesh, and ingress controller.

    • Products
      • Kong Konnect
      • Kong Gateway Enterprise
      • Kong Gateway
      • Kong Mesh
      • Kong Ingress Controller
      • Kong Insomnia
      • Product Updates
      • Get Started
    • Documentation
      • Kong Konnect Docs
      • Kong Gateway Docs
      • Kong Mesh Docs
      • Kong Insomnia Docs
      • Kong Konnect Plugin Hub
    • Open Source
      • Kong Gateway
      • Kuma
      • Insomnia
      • Kong Community
    • Company
      • About Kong
      • Customers
      • Careers
      • Press
      • Events
      • Contact
  • Terms• Privacy• Trust and Compliance
© Kong Inc. 2025