> For the complete documentation index, see [llms.txt](https://documentation.ocsinventory-ng.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.ocsinventory-ng.org/ocs-inventory-v3-extensions/overview/managing-extensions.md).

# Managing Extensions

### Extension folder layout

An extension is made of up to two subfolders, a mandatory backend one and an optional frontend one, that get deployed to two different locations on the server. For an extension named `sampleextension`:

```
sampleextension/
├── backend/sampleextension/    (mandatory)
└── frontend/sampleextension/   (optional)
```

* The `backend/sampleextension` folder must be placed in the server's `extensions` folder.
* The `frontend/sampleextension` folder, if present, must be placed in `public/extensions`.

If OCS Inventory was installed from the `.deb` or `.rpm` packages, these two locations already exist by default:

| Component | Default base directory             | Extensions go in                                     |
| --------- | ---------------------------------- | ---------------------------------------------------- |
| Backend   | `/usr/share/ocsinventory-backend`  | `/usr/share/ocsinventory-backend/extensions`         |
| Frontend  | `/usr/share/ocsinventory-frontend` | `/usr/share/ocsinventory-frontend/public/extensions` |

Once both folders are in place, the extension is ready to be installed.

### Installing and managing an extension

Once an extension has been placed on the server (typically by copying its `backend/<name>` folder into the `extensions` directory and its `frontend/<name>` folder into `public/extensions` if it has one), it goes through a simple lifecycle:

1. **Install** it - this registers the extension and sets up whatever it needs (database tables, etc.).
2. **Enable** it - this switches it on.
3. **Restart the application server** - extensions build their routes when the server starts, so a restart is what makes an install/enable/disable actually visible to users.

All of this lifecycle is managed with a single command, run from the server:

```bash
manage.py extensions <action> [extension folder name]
```

You can also enable or disable an extension from the web console, it does exactly the same thing as the `enable` / `disable` commands below, just with a click instead of a command line.

{% hint style="info" %}
New to extensions ? See the [Introduction](/ocs-inventory-v3-extensions/overview/introduction.md) page for an overview of how the extension system works.
{% endhint %}

### Command reference

| Command                   | What it does                                                          |
| ------------------------- | --------------------------------------------------------------------- |
| `list`                    | Shows every extension found on the server and its current state       |
| `install <name>`          | Registers a new extension and prepares it for use                     |
| `enable <name>`           | Turns an installed extension on                                       |
| `disable <name>`          | Turns an extension off                                                |
| `uninstall <name>`        | Removes an extension from the server's registry                       |
| `check-migrations`        | Checks that everything is set up correctly, without changing anything |
| `apply-migrations <name>` | Re-applies an extension's setup (useful after an update)              |
| `clean <name>`            | Cleans up leftovers after an extension's files were deleted manually  |

#### `list`

Shows every extension the server knows about, along with a short status for each one (e.g. *ok*, *not installed*, *disabled*). Use this first whenever you want a quick overview, or to check whether an extension is behaving as expected.

```bash
manage.py extensions list
```

<details>

<summary><em>Example output</em></summary>

```bash
FOLDER            MANIFEST  MARKED  DB     ENABLED  STATUS
sampleextension   1.0.0     yes     1.0.0  yes      ok
```

</details>

#### `install`

Registers a new extension so the server can use it, and prepares anything it needs to run (such as its database tables). This is the first command to run after placing a new extension's files on the server.

```bash
manage.py extensions install <name>
```

Add `--enable` to switch the extension on in the same step:

```bash
manage.py extensions install <name> --enable
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions install sampleextension --enable
sampleextension is not marked installed yet. Installing it writes .installed into
its folder and restarts the application (a fresh 'manage.py extensions install'
subprocess) so Django loads it. This has no effect on extension data.
Type 'yes' to continue: yes
sampleextension: marked installed (extensions/sampleextension/.installed)
Restarting to load the extension...
sampleextension: registered as 'Sample Extension' 1.0.0
Operations to perform:
  Apply all migrations: sampleextension
Running migrations:
  Applying sampleextension.0001_initial... OK
sampleextension enabled in the database.
This is not yet visible to users: the running application server(s) built
sampleextension's routes at startup and won't re-read this change. Restart the
application server (all worker processes) so sampleextension's routes appear.
```

</details>

Installing a brand-new extension requires the server process to restart itself once, this happens automatically as part of the command, you don't need to do anything extra. You will still need to restart your application server(s) afterwards for the extension's pages and routes to show up for users.

#### `enable`

Turns on an extension that has already been installed. Does the same thing as flipping the toggle in the web console.

```bash
manage.py extensions enable <name>
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions enable sampleextension
sampleextension enabled in the database.
This is not yet visible to users: the running application server(s) built
sampleextension's routes at startup and won't re-read this change. Restart the
application server (all worker processes) so sampleextension's routes appear.
```

</details>

{% hint style="info" %}
After enabling (or disabling) an extension, restart your application server so the change actually takes effect for users.
{% endhint %}

#### `disable`

Turns off an extension without removing it. The extension stays installed and can be re-enabled at any time.

```bash
manage.py extensions disable <name>
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions disable sampleextension
sampleextension disabled in the database.
This is not yet visible to users: the running application server(s) built
sampleextension's routes at startup and won't re-read this change. Restart the
application server (all worker processes) so sampleextension's routes stop
responding.
```

</details>

#### `uninstall`

Removes an extension from the server's registry and turns it off. By default this keeps the extension's data intact, in case you reinstall it later.

```bash
manage.py extensions uninstall <name>
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions uninstall sampleextension
sampleextension: disabled
sampleextension: removed from the registry
sampleextension: .installed marker removed
The code is still in extensions/sampleextension
It is no longer marked installed, so 'manage.py migrate' will not load it or
touch its migrations. Restart the application server to unload it from the
running process. Remove the folder entirely if you also want it gone from
'extensions list'.
```

</details>

Add `--erase-data` if you also want to permanently delete the extension's data:

```bash
manage.py extensions uninstall <name> --erase-data
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions uninstall sampleextension --erase-data
About to unapply 1 migration(s) of sampleextension and drop its tables. All of
its data will be lost.
Type 'yes' to continue: yes
sampleextension: disabled
Operations to perform:
  Unapply all migrations: sampleextension
Running migrations:
  Rendering model states... DONE
  Unapplying sampleextension.0001_initial... OK
sampleextension: 3 stale permission/content-type row(s) deleted
sampleextension: removed from the registry
sampleextension: .installed marker removed
```

</details>

{% hint style="warning" %}
**`--erase-data` permanently deletes the extension's data.** There is no undo. The command will ask for confirmation unless you add `--noinput`.
{% endhint %}

Uninstalling does not delete the extension's files from the server — do that separately (and restart your application server) once you're sure you no longer need it.

#### `check-migrations`

A read-only health check: it verifies that every installed extension is set up correctly, without changing anything. Useful for troubleshooting, or as a routine check after updates.

```bash
manage.py extensions check-migrations
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions check-migrations
sampleextension: up to date
otherextension: up to date
```

</details>

You can also target a single extension:

```bash
manage.py extensions check-migrations <name>
```

#### `apply-migrations`

Re-applies an extension's setup. You'll mainly need this after updating an extension to a new version that changed its database structure.

```bash
manage.py extensions apply-migrations <name>
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions apply-migrations sampleextension
Operations to perform:
  Apply all migrations: sampleextension
Running migrations:
  Applying sampleextension.0002_add_field... OK
```

</details>

Add `--redo` only if you want to reset the extension's setup from scratch:

```bash
manage.py extensions apply-migrations <name> --redo
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions apply-migrations sampleextension --redo
About to unapply 2 migration(s) of sampleextension and drop its tables. All of
its data will be lost.
Type 'yes' to continue: yes
Operations to perform:
  Unapply all migrations: sampleextension
Running migrations:
  Unapplying sampleextension.0002_add_field... OK
  Unapplying sampleextension.0001_initial... OK
Operations to perform:
  Apply all migrations: sampleextension
Running migrations:
  Applying sampleextension.0001_initial... OK
  Applying sampleextension.0002_add_field... OK
```

</details>

{% hint style="warning" %}
**`--redo` permanently deletes the extension's data** before rebuilding it from scratch. The command will ask for confirmation unless you add `--noinput`.
{% endhint %}

#### `clean`

A cleanup tool for one specific situation: an extension's folder was deleted from the server directly (instead of using `uninstall` first), and some leftovers remain in the server's records. Running `clean` removes those leftovers.

```bash
manage.py extensions clean <name>
```

<details>

<summary><em>Example output</em></summary>

```bash
> python3 manage.py extensions clean sampleextension
About to remove sampleextension from the registry and delete its migration
history. The 2 table(s) left behind will NOT be dropped.
Type 'yes' to continue: yes
sampleextension: removed from the registry
sampleextension: 2 migration history row(s) deleted
sampleextension: 3 stale permission/content-type row(s) deleted
Tables left in the database (not dropped):
  sampleextension_device
  sampleextension_setting
Reinstalling will FAIL while they exist: migrate would try to create them
again. 'manage.py migrate sampleextension --fake' re-records the history
without touching them.
Only the 'sampleextension_' prefix was inspected. Because clean never
unapplies, anything this extension's data migrations wrote into other apps'
tables is still in the database, and a model with an explicit db_table is not
listed either.
```

</details>

If this extension left its own database tables behind, `clean` will list them but won't delete the data in them automatically, this is a deliberate safety measure. The command's output will tell you what to do if you want to remove them.

### Typical workflows

**Installing and enabling a new extension**

```bash
manage.py extensions install my_extension --enable
```

Then restart your application server(s).

**Checking that everything is healthy**

```bash
manage.py extensions check-migrations
```

**Turning an extension off temporarily**

```bash
manage.py extensions disable my_extension
```

Then restart your application server(s).

**Removing an extension for good, including its data**

```bash
manage.py extensions uninstall my_extension --erase-data
```

Then delete its files from the server and restart your application server(s).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.ocsinventory-ng.org/ocs-inventory-v3-extensions/overview/managing-extensions.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
