How to contribute to LXD
The LXD team welcomes contributions through pull requests, issue reports, and discussions.
-
Contribute to the code or documentation, report bugs, or request features in the GitHub repository (opens in a new tab)
-
Ask questions or join discussions in the LXD forum (opens in a new tab).
Review the following guidelines before contributing to the project.
Code of Conduct
All contributors must adhere to the Ubuntu Code of Conduct (opens in a new tab).
License and copyright
All contributors must sign the Canonical contributor license agreement (CCLA) (opens in a new tab), which grants Canonical permission to use the contributions.
-
You retain copyright ownership of your contributions (no copyright assignment).
-
By default, contributions are licensed under the project’s AGPL-3.0-only license.
-
Exceptions:
-
Canonical may import code under AGPL-3.0-only compatible licenses, such as Apache-2.0.
-
Such code retains its original license and is marked as such in commit messages or file headers.
-
Some files and commits are licensed under Apache-2.0 rather than AGPL-3.0-only. These are indicated in their package-level COPYING file, file header, or commit message.
-
Pull requests
Submit pull requests on GitHub at: https://github.com/canonical/lxd
(opens in a new tab).
All pull requests undergo review and must be approved before being merged into the main branch.
Commit structure
Use separate commits for different types of changes:
Type
Affects files
Commit message format
API extensions
doc/api-extensions.md
, shared/version/api.go
api: Add XYZ extension
Documentation
Files in doc/
doc: Update XYZ
API structure
Files in shared/api/
shared/api: Add XYZ
Go client package
Files in client/
client: Add XYZ
CLI changes
Files in lxc/
lxc/<command>: Change XYZ
LXD daemon
Files in lxd/
lxd/<package>: Add support for XYZ
Tests
Files in tests/
tests: Add test for XYZ
Depending on complexity, large changes might be further split into smaller, logical commits. This commit structure facilitates the review process and simplifies backporting fixes to stable branches.
Developer Certificate of Origin sign-off
To ensure transparency and accountability in contributions to this project, all contributors must include a Signed-off-by line in their commits in accordance with DCO 1.1:
Developer Certificate of Origin Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 660 York Street, Suite 102, San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
Including a Signed-off-by line in your commits
Every commit must include a Signed-off-by line, even when part of a larger set of contributions. To do this, use the -s
flag when committing:
git commit -s -m "Your commit message"
This automatically adds the following to your commit message:
Signed-off-by: Your Name <[email protected]>
By including this line, you acknowledge your agreement to the DCO 1.1 for that specific contribution.
-
Use a valid name and email address—anonymous contributions are not accepted.
-
Ensure your email matches the one associated with your GitHub account.
Commit signature verification
In addition to the sign-off requirement, contributors must also cryptographically sign their commits to verify authenticity. See: GitHub’s documentation on commit signature verification (opens in a new tab).
Make-generated files
Some changes require regenerating certain files using Makefile commands.
After you run any of the commands below, you’ll be prompted whether to commit the changes. If you respond Y
, only the re-generated files are committed—any other staged files are ignored.
CLI tool string updates
If you modify CLI strings in lxc/
, regenerate and commit translation files:
make i18n
API updates
If you modify the LXD API (shared/api
), regenerate and commit the Swagger YAML file (doc/rest-api.yaml
) used for API reference documentation:
make update-api
Configuration options updates
If you add or update configuration options, regenerate and commit the documentation metadata files (lxd/metadata/configuration.json
and doc/metadata.txt
):
make update-metadata
Contribute to the code
Follow the steps below to set up your development environment and start working on new LXD features.
Install LXD from source
To build the dependencies, follow the instructions in Install LXD from source.
Add your fork as a remote
After setting up your build environment, add your GitHub fork as a remote and fetch the latest updates:
git remote add myfork [\[email protected]](/cdn-cgi/l/email-protection):<your\_username>/lxd.git
git remote update
Then switch to the main branch of your fork:
git switch myfork/main
Build LXD
Now you can build your fork of the project by running:
make
Before making changes, create a new branch on your fork:
git switch \-c <name\_of\_your\_new\_branch>
Set up tracking for the new branch to make future pushes easier:
git push -u myfork <name_of_your_new_branch>
Important notes for new LXD contributors
-
Persistent data is stored in the
LXD_DIR
directory, which is created by runninglxd init
.-
By default,
LXD_DIR
is located at/var/lib/lxd
(for non-snap installations) or/var/snap/lxd/common/lxd
(f or snap users). -
To prevent version conflicts, consider setting a separate
LXD_DIR
for your development fork.
-
-
Binaries compiled from your source are placed in
$(go env GOPATH)/bin
by default.-
When testing, explicitly invoke these binaries instead of the global
lxd
you might have installed. -
For convenience, you can create an alias in your
~/.bashrc
to call these binaries with the appropriate flags.
-
-
If you have a
systemd
service running LXD from a previous installation, consider disabling it to prevent version conflicts with your development build.
Contribute to the documentation
We strive to make LXD as easy and straightforward to use as possible. To achieve this, our documentation aims to provide the information users need, cover all common use cases, and answer typical questions.
You can contribute to the documentation in several ways. We appreciate your help!
Ways to contribute
Document new features or improvements you contribute to the code.
- Submit documentation updates in pull requests alongside your code changes. We will review and merge them together with the code.
Clarify concepts or common questions based on your own experience.
- Submit a pull request with your documentation improvements.
Report documentation issues by opening an issue on GitHub (opens in a new tab).
- We will evaluate and update the documentation as needed.
Ask questions or suggest improvements in the LXD forum (opens in a new tab).
- We monitor discussions and update the documentation when necessary.
Join discussions in the #lxd
channel on IRC via Libera Chat (opens in a new tab).
- While we cannot guarantee responses to IRC posts, we monitor the channel and use feedback to improve the documentation.
If you contribute images to doc/images
:
-
Use SVG or PNG formats.
-
Optimize PNG images for smaller file size using a tool like TinyPNG (opens in a new tab) (web-based), OptiPNG (opens in a new tab) (CLI-based), or similar.
Documentation framework
LXD’s documentation is built with Sphinx (opens in a new tab) and hosted on Read the Docs (opens in a new tab).
It is written in Markdown (opens in a new tab) with MyST (opens in a new tab) extensions. For syntax help and guidelines, see the MyST style guide (opens in a new tab) and the documentation cheat sheet (opens in a new tab) (source (opens in a new tab)).
For structuring, the documentation uses the Diátaxis (opens in a new tab) approach.
Build the documentation
To build the documentation, run make doc
from the root directory of the repository. This command installs the required tools and renders the output to the doc/_build/
directory. To update the documentation for changed files only (without re-installing the tools), run make doc-incremental
.
Before opening a pull request, make sure that the documentation builds without any warnings (warnings are treated as errors). To preview the documentation locally, run make doc-serve
and go to http://localhost:8000
(opens in a new tab) to view the rendered documentation.
When you open a pull request, a preview of the documentation hosted by Read the Docs is built automatically. To see this, view the details for the docs/readthedocs.com:canonical-lxd
check on the pull request. Others can also use this preview to validate your changes.
Automatic documentation checks
GitHub runs automatic checks on the documentation to verify the spelling, the validity of links, correct formatting of the Markdown files, and the use of inclusive language.
You can (and should!) run these tests locally before pushing your changes:
-
Check the spelling:
make doc-spellcheck
(ormake doc-spelling
to first build the documentation and then check it) -
Check the validity of links:
make doc-linkcheck
-
Check the Markdown formatting:
make doc-lint
-
Check for inclusive language:
make doc-woke
Document instructions (how-to guides)
LXD can be used with different clients, primarily the command-line interface (CLI), API, and UI. The documentation contains instructions for all of these, so when adding or updating how-to guides, remember to update the documentation for all clients.
Using tabs for client-specific information
When instructions differ between clients, use tabs to organize them:
````{group-tab} CLI
\[...\]
\[...\]
\[...\]
Tip
You might need to increase the number of backticks (\`) if there are code blocks or other directives in the tab content.
#### Guidelines for writing instructions
CLI instructions
* Link to the relevant `lxc` command reference. Example: ``[`lxc init`](./contributing/lxc_init.md)``
* You don’t need to document all available command flags, but mention any that are especially relevant.
* Examples are very helpful, so add a few if it makes sense.
API instructions
* When possible, use [`lxc query`](./reference/manpages/lxc/query/#lxc-query-md) to demonstrate API calls. For complex calls, use `curl` or other widely available tools.
* In the request data, include all required fields but keep it minimal—there’s no need to list every possible field.
* Link to the API call reference. Example: ``[`POST /1.0/instances`](./contributing/swagger:/instances/instances_post)``
UI instructions
* Use screenshots sparingly—they are difficult to keep up to date.
* When referring to labels in the UI, use the `{guilabel}` role. Example: ``To create an instance, go to the {guilabel}`Instances` section and click {guilabel}`Create instance`.``
### Document configuration options
Configuration options are documented by comments in the Go code. These comments are extracted automatically.
#### Adding or modifying configuration options
* Look for comments that start with `lxdmeta:generate` in the code.
* When adding or modifying a configuration option, include the corresponding documentation comment.
* Refer to the [`lxd-metadata` README file](https://github.com/canonical/lxd/blob/main/lxd/lxd-metadata/README.md) for formatting guidelines.
* When you add or modify configuration options, you must re-generate `doc/metadata.txt` and `lxd/metadata/configuration.json`. See the [Configuration options updates](./contributing/#configuration-options-updates) section for instructions.
#### Including configuration options in documentation
The documentation pulls sections from `doc/metadata.txt` to display a group of configuration options. For example, to include the core server options, use:
% Include content from \[metadata.txt\](./contributing/metadata.txt)
````{include} metadata.txt
:start-after: <!-- config group server-core start -->
:end-before: <!-- config group server-core end -->
When to update documentation files
-
If you add a new option to an existing group, no changes to the documentation files are needed, aside from re-generating
metadata.txt
. The option will be included automatically. -
If you define a new group, to add it to the documentation, you must add an
{include}
directive to the appropriate Markdown file indoc/
.