|
| 1 | +--- |
| 2 | +title: Creating a Devbox Plugin |
| 3 | +--- |
| 4 | + |
| 5 | +Plugins make it easier to get started with packages that require additional setup when installed with Nix, and they offer a familiar interface for configuring packages. They also help keep all of your project's configuration within your project directory, which helps maintain portability and isolation. |
| 6 | + |
| 7 | +## Getting Started |
| 8 | + |
| 9 | +Before writing a plugin, we recommend reading the [User Documentation](https://www.jetpack.io/devbox/docs/guides/plugins/) on plugins, as well as inspecting and testing a few of the plugins in the [plugin directory](https://github.com/jetpack-io/devbox/tree/main/plugins) of our repo. Note that the plugins in this directory are compiled into the Devbox binary, but your plugin can be sourced from a local directory or from within your project. |
| 10 | + |
| 11 | + |
| 12 | +If you're looking for plugin ideas, check out our [Issues page](https://github.com/jetpack-io/devbox/issues?q=is%3Aissue+is%3Aopen+label%3A%22plugin+request%22) for any user requests. |
| 13 | + |
| 14 | +Before contributing, please consult our [Contributing Guide](https://github.com/jetpack-io/devbox/CONTRIBUTING.md) and [Code of Conduct](https://github.com/jetpack-io/devbox/CODE_OF_CONDUCT.md) for details on how to contribute to Devbox. |
| 15 | + |
| 16 | +### Testing your Plugin |
| 17 | + |
| 18 | +1. Create a new `devbox.json` in an empty directory using `devbox init`. |
| 19 | +2. Add your plugin to the `include` section of the `devbox.json` file. Add any expected packages using `devbox add <pkg>`. |
| 20 | +3. Check that your plugin creates the correct files and environment variables when running `devbox shell` |
| 21 | +4. If you are looking for sample projects to test your plugin with, check out our [examples](https://github.com/jetpack-io/devbox/tree/main/examples). |
| 22 | + |
| 23 | +## Plugin Design |
| 24 | + |
| 25 | +Plugins are defined as Go JSON Template files, using the following schema: |
| 26 | + |
| 27 | +```json |
| 28 | +{ |
| 29 | + "name": "", |
| 30 | + "version": "", |
| 31 | + "match": "", |
| 32 | + "readme": "", |
| 33 | + "env": { |
| 34 | + "<key>": "<value>" |
| 35 | + }, |
| 36 | + "create_files": { |
| 37 | + "<destination>": "<source>" |
| 38 | + }, |
| 39 | + "init_hook": [ |
| 40 | + "<bash commands>" |
| 41 | + ] |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +A plugin can define services by adding a `process-compose.yaml` file in its `create_files` stanza. |
| 46 | + |
| 47 | +### Plugin Lifecycle |
| 48 | + |
| 49 | +Plugins are activated whenever a developer runs `devbox shell`, runs a script with `devbox run`, or starts a service using `devbox services start|restart`. The lifecycle of a devbox shell with plugins works as follows: |
| 50 | + |
| 51 | +```mermaid |
| 52 | +--- |
| 53 | +title: Devbox Shell Lifecycle |
| 54 | +--- |
| 55 | +flowchart TD |
| 56 | + A[Plugin env] --> B |
| 57 | + B[User env] --> C |
| 58 | + C[Plugin init_hook] --> D[User Init Hook] |
| 59 | + D --> E{Start Shell} |
| 60 | + E --> F & G & H |
| 61 | + F[Interactive Shell] |
| 62 | + G[Run Scripts] |
| 63 | + H[Start Services] |
| 64 | +``` |
| 65 | + |
| 66 | +### Template Placeholders |
| 67 | + |
| 68 | +Devbox's Plugin System provides a few special placeholders that should be used when specifying paths for env variables and helper files: |
| 69 | + |
| 70 | +* `{{ .DevboxDirRoot }}` – points to the root folder of their project, where the user's `devbox.json` is stored. |
| 71 | +* `{{ .DevboxDir }}` – points to `<projectDir>/devbox.d/<plugin.name>`. This directory is public and added to source control by default. This directory is not modified or recreated by Devbox after the initial package installation. You should use this location for files that a user will want to modify and check-in to source control alongside their project (e.g., `.conf` files or other configs). |
| 72 | +* `{{ .Virtenv }}` – points to `<projectDir>/.devbox/virtenv/<plugin_name>` whenever the plugin activates. This directory is hidden and added to `.gitignore` by default You should use this location for files or variables that a user should not check-in or edit directly. Files in this directory should be considered managed by Devbox, and may be recreated or modified after the initial installation. |
| 73 | + |
| 74 | +### Fields |
| 75 | + |
| 76 | +#### `name` *string* |
| 77 | + |
| 78 | +The name of your plugin. This is used to identify your plugin when a user runs `devbox info`. If `match` is not set, the plugin will automatically activate when a package is added to a devbox.json project that matches `name`. |
| 79 | + |
| 80 | +#### `version` *string* |
| 81 | + |
| 82 | +The version of your plugin. You should start your version at 0.0.1 and bump it whenever you merge an update to the plugin. |
| 83 | + |
| 84 | +#### `match` *string* |
| 85 | + |
| 86 | +A regex expression that is used to identify when the plugin will be activated. Devbox will activate your plugin when a package installed with `devbox add` matches this regular expression. |
| 87 | + |
| 88 | +The regex you provide should match a package name to automatically update. You can look up packages at `nixhub.io` |
| 89 | + |
| 90 | +#### `readme` *string* |
| 91 | + |
| 92 | +Special usage instructions or notes to display when your plugin activates or when a user runs `devbox info`. You do not need to document variables, helper files, or services, since these are automatically printed when a user runs `devbox info`. |
| 93 | + |
| 94 | +#### `env` *object* |
| 95 | + |
| 96 | +A map of `"key" : "value"` pairs used to set environment variables in `devbox shell` when the plugin is activated. These variables will be printed when a user runs `devbox info`, and can be overridden by a user's `devbox.json`. |
| 97 | + |
| 98 | +#### `create_files` *object* |
| 99 | + |
| 100 | +A map of `"destination":"source"` pairs that can be used to create or copy files into the user's devbox directory when the plugin is activated. For example: |
| 101 | + |
| 102 | +```json |
| 103 | +"create_files": { |
| 104 | + "{{ .DevboxDir }}/Caddyfile": "caddy/Caddyfile" |
| 105 | +} |
| 106 | +``` |
| 107 | + |
| 108 | +Will copy the Caddyfile in the `plugins/caddy` folder to `devbox.d/caddy/Caddyfile` in the user's project directory. |
| 109 | + |
| 110 | +You should use this to copy starter config files or templates needed to run the plugin's package. |
| 111 | + |
| 112 | +#### `init_hook` *string | string[]* |
| 113 | + |
| 114 | +A single `bash` command or list of `bash` commands that should run before the user's shell is initialized. This will run every time a shell is started, so you should avoid any resource heavy or long running processes in this step. |
| 115 | + |
| 116 | +### Adding Services |
| 117 | + |
| 118 | +Devbox uses [Process Compose](https://github.com/F1bonacc1/process-compose) to run services and background processes. |
| 119 | + |
| 120 | +Plugins can add services to a user's project by adding a `process-compose.yaml` file to the `create_files` stanza. This file will be automatically detected by Devbox, and started when a user runs `devbox services up` or `devbox services start`. |
| 121 | + |
| 122 | +See the process compose [docs](https://github.com/F1bonacc1/process-compose) for details on how to write define services in `process-compose.yaml`. You can also check the plugins in this directory for examples on how to write services. |
| 123 | + |
| 124 | +## Tips for Writing Plugins |
| 125 | + |
| 126 | +* Only add plugins for packages that require configuration to work with Devbox. |
| 127 | +* Plugins should try to use the same configuration conventions (environment variables, configuration files) as their packages. This lets developers configure their packages in a way that they are familiar with, using existing documentation. |
| 128 | +* If you think a user may want to override or change a parameter, define it as an environment variable in `env`. This makes it possible for a developer to override the parameter in their `devbox.json` file |
| 129 | +* If you're adding a helper file that you think a developer would want check into source control, create it in `{{ .DevboxDir }}`. If you're creating a file that would not be checked into source control, create it in `{{ .Virtenv }}`. |
| 130 | +* Unless there is a very good reason, we do not recommend creating files outside of `{{ .DevboxDir }}` or `{{ .Virtenv }}`. This helps keep user projects clean and well organized. |
0 commit comments