Multi-select (Ctrl/Cmd+click toggle, Shift+click range, right-click the
active selection for bulk actions - same conventions as a native file
manager):
- Print Labels (N) / Export CSV (N) for any mix of individually-picked
assets and whole folders. Labels/export now take asset_ids/folder_ids
instead of a single asset_id/folder_id.
- Edit Status..., Check Out..., Duplicate, Move to..., and Delete, bulk
versions of the existing single-asset actions. Checkout/Move modals
were generalized to accept an array of ids instead of just one; status
editing got its own lightweight POST /app/assets/{id}/status endpoint
(assets.SetStatus) so a bulk status change doesn't need to resend every
other field the way a full PATCH would.
Labels:
- Choose QR (a /scan/<tag> URL, for a phone camera) or Code128 barcode
(the bare Asset ID, for a USB scanner typing into the search box) via a
format selector on the print page. New barcodeDataURI using
github.com/boombuler/barcode alongside the existing QR generator.
- "Start at #" lets printing resume partway into an already-used sheet
instead of wasting it on a fresh one.
- Added the Avery 5260 label template (same grid as 5160, rounded
corners, so it isn't flagged approximate).
Also: the configured Site Name now shows on the login page too, not just
the authenticated navbar.
234 lines
9.8 KiB
Markdown
234 lines
9.8 KiB
Markdown
# inventree
|
|
|
|
A small, self-contained IT asset inventory system. The heart of inventree is a
|
|
nested folder tree — like a file manager — for organizing physical and
|
|
virtual IT assets (servers, switches, laptops, printers, etc.).
|
|
|
|
- Single compiled Go binary, embedded HTML templates and static assets
|
|
- SQLite storage (WAL mode, foreign keys, migrations)
|
|
- Bootstrap 5 UI, minimal vanilla JavaScript (no Node/React/build step)
|
|
- Session-based auth with two roles: Admin and User
|
|
- Custom, admin-defined asset types with custom fields
|
|
- CSV import/export, full-text-ish search with breadcrumbs
|
|
|
|
## Quick start
|
|
|
|
```sh
|
|
go build -o inventree ./cmd/inventree
|
|
./inventree serve
|
|
```
|
|
|
|
Then open http://localhost:8080 and log in with:
|
|
|
|
```
|
|
Username: admin
|
|
Password: admin
|
|
```
|
|
|
|
(This default account is created intentionally on first run. Change or
|
|
disable it via the Users admin page once you're up and running.)
|
|
|
|
The database file is created automatically at `data/inventree.db` on first
|
|
run, with migrations applied and seed data (default statuses, item types,
|
|
and the admin account) inserted.
|
|
|
|
## CLI
|
|
|
|
```sh
|
|
inventree # same as `inventree serve`
|
|
inventree serve # start the web server
|
|
inventree version # print the version
|
|
inventree database migrate # apply pending migrations and exit
|
|
inventree database backup [path] # write a consistent VACUUM INTO snapshot
|
|
```
|
|
|
|
`serve` flags:
|
|
|
|
| Flag | Default | Description |
|
|
|---------------------|------------------------|--------------------------------------------|
|
|
| `-addr` | `:8080` | Listen address |
|
|
| `-db` | `data/inventree.db` | Path to the SQLite database file |
|
|
| `-secure-cookies` | `false` | Mark the session cookie `Secure` (enable when serving over HTTPS) |
|
|
|
|
`/healthz` is available for load balancer / container health checks.
|
|
|
|
## The inventory tree
|
|
|
|
The Inventory page is the default page after login and the center of the
|
|
application: a folder/asset tree on the left, and a detail panel on the
|
|
right that shows whatever is selected (a folder's contents, or a single
|
|
asset).
|
|
|
|
- **Folders** can nest arbitrarily deep, and contain both subfolders and
|
|
assets.
|
|
- **Expand/collapse** state is remembered per user (persisted server-side),
|
|
and folder contents are fetched lazily via small AJAX requests — the page
|
|
never fully reloads when you browse the tree.
|
|
- **Drag and drop** folders and assets onto another folder (or onto
|
|
"Inventory" itself) to move them. Admin only.
|
|
- **Right-click for everything**: it's meant to feel like a native file
|
|
manager. Right-click a folder, an asset, a breadcrumb crumb, or empty
|
|
tree/panel background for the actions available there (New Subfolder, Add
|
|
Asset, Rename, Check Out, Move, Print Label, Delete, …) instead of hunting
|
|
for a toolbar button. The main panel itself stays blank until you actually
|
|
click into a folder or asset — browsing happens in the tree.
|
|
- **Deleting a folder** that still contains subfolders or assets requires
|
|
confirmation, and offers a safe "move contents elsewhere" option instead
|
|
of an accidental cascade. A "permanently delete everything inside" option
|
|
is also available for when that's genuinely what you want.
|
|
- **Search** (top of the tree pane) looks across asset ID, name, folder
|
|
name, item type, assigned user, notes, and custom field values, and shows
|
|
each result's full folder breadcrumb.
|
|
|
|
## Item types and custom fields
|
|
|
|
Admins can define arbitrary asset types (Laptop, Switch, Firewall, …) under
|
|
**Item Types**, each with its own set of custom fields (text, long text,
|
|
number, date, boolean, dropdown, URL, IP address), marked required or not,
|
|
with a default value and display order. A representative starter set of
|
|
types and fields is seeded on first run — feel free to edit or delete it.
|
|
|
|
## Checkout, quantity, and contacts
|
|
|
|
- **Check out / check in**: right-click an asset → **Check Out…** to assign
|
|
it to a user (or clear the assignment to check it back in). Works from any
|
|
asset row, not just its detail view.
|
|
- **Quantity vs. unique**: item types have a **Unique** flag (checked by
|
|
default). Unique types — a laptop, a server — get one asset row per
|
|
physical unit, same as before. Uncheck it for bulk/consumable types (a USB
|
|
cable, a box of screws) and assets of that type are tracked as a single
|
|
row with a **Quantity** and +/- steppers in the asset panel and folder
|
|
tables, instead of one row per unit. Flipping a type back to Unique clamps
|
|
any existing quantities back down to 1.
|
|
- **Contacts**: under Settings → Users, a third role alongside Admin and
|
|
User. Contacts can't sign in at all — they exist purely so you can assign
|
|
assets to end users (e.g. "this laptop belongs to Jane in Accounting")
|
|
without creating them a login account. A blank password is fine when
|
|
creating one.
|
|
|
|
## QR/barcode asset tags and printable labels
|
|
|
|
Every asset can have a scannable label printed for it: right-click an asset
|
|
for **Print Label**, or right-click a folder for **Print Labels…** (every
|
|
asset in that folder, recursively). Choose the code format on the print
|
|
page itself:
|
|
|
|
- **QR code** — encodes an absolute `/scan/<Asset ID>` URL, so scanning it
|
|
with a phone camera opens straight to that asset.
|
|
- **Barcode (Code128)** — encodes the bare Asset ID, meant for a dedicated
|
|
USB barcode scanner typing it into whatever's focused (e.g. the app's
|
|
search box).
|
|
|
|
The print page also supports three label sheet layouts, switchable from a
|
|
dropdown:
|
|
|
|
- **Avery 5160 / 5260** (1" x 2-5/8", 30/sheet) — standard address labels
|
|
(5260 is the same grid, just rounded corners), exact published
|
|
dimensions.
|
|
- **61526** asset tag labels (3/4" x 2", ~48/sheet) — the grid/margins here
|
|
are a best-effort layout, not a verified spec sheet, so print one test
|
|
page on plain paper and check it against a real label before committing a
|
|
full (often non-refundable) sheet.
|
|
|
|
**Printing a batch without wasting sheet space**: Ctrl/Cmd+click (toggle)
|
|
or Shift+click (range) multiple folders/assets in the tree, the same way
|
|
you would in a file manager, then right-click the selection for **Print
|
|
Labels (N)** — along with **Export CSV (N)**, **Edit Status…**,
|
|
**Check Out…**, **Duplicate**, **Move to…**, and **Delete**, all bulk
|
|
versions of the single-item actions. On the print page itself, **Start at
|
|
#** lets you resume printing partway into an already-used sheet (position 1
|
|
= top-left, counting left-to-right, top-to-bottom) instead of starting a
|
|
fresh one over a few peeled-off labels.
|
|
|
|
## CSV import / export
|
|
|
|
- **Export**: from the tree's right-click menu, or `/export/assets.csv`
|
|
(optionally scoped to a folder, with `?recursive=1` to include
|
|
subfolders). Includes a `Quantity` column and one `cf_<field_key>` column
|
|
per distinct custom field in use.
|
|
- **Folder-scoped import**: right-click a folder → **Import CSV…** imports
|
|
every row directly into that folder. No `Folder` column needed — that's
|
|
the whole point of doing it from a specific folder. Never available at the
|
|
top level.
|
|
- **Global import**: Settings → Import / Export has the full-featured
|
|
version — a CSV with a `Folder` column (a `/`-separated path, e.g.
|
|
`Main Office/Network`) that can optionally auto-create missing folders —
|
|
plus a separate CSV import for bulk-adding/updating Statuses (`Name`,
|
|
`Color`). Both matching-by-name/Asset-ID semantics and full column
|
|
references with examples are documented right on that page.
|
|
|
|
A full backup/restore of everything (folders, assets, types, custom fields,
|
|
statuses, users) is just `inventree database backup` — it's a consistent
|
|
snapshot of the whole SQLite database.
|
|
|
|
## Project layout
|
|
|
|
```
|
|
cmd/inventree/ CLI entrypoint (serve, version, database migrate/backup)
|
|
internal/
|
|
auth/ session management, secure cookies
|
|
database/ SQLite connection, pragmas, migrations
|
|
migrations/ embedded .sql migration files
|
|
models/ shared domain types
|
|
folders/ nested folder tree
|
|
assets/ asset CRUD, search, CSV import/export
|
|
itemtypes/ admin-defined types + custom field definitions
|
|
users/ accounts
|
|
statuses/ configurable asset statuses
|
|
settings/ key/value app settings
|
|
web/ HTTP router, handlers, template rendering
|
|
web/
|
|
templates/ Go html/template pages and partials (embedded)
|
|
static/ Bootstrap 5, Bootstrap Icons, app.css, app.js (embedded)
|
|
deploy/ systemd unit example
|
|
```
|
|
|
|
## Development
|
|
|
|
```sh
|
|
go build ./...
|
|
go vet ./...
|
|
go test ./...
|
|
```
|
|
|
|
The SQLite driver is [modernc.org/sqlite](https://pkg.go.dev/modernc.org/sqlite),
|
|
a pure-Go implementation, so `CGO_ENABLED=0` builds work out of the box and
|
|
the compiled binary has no C library dependencies.
|
|
|
|
## Docker
|
|
|
|
```sh
|
|
docker compose up --build
|
|
```
|
|
|
|
This builds the image, starts inventree on port 8080, and persists the
|
|
database in a named volume (`inventree-data`, mounted at `/app/data`).
|
|
|
|
Or directly:
|
|
|
|
```sh
|
|
docker build -t inventree .
|
|
docker run -p 8080:8080 -v inventree-data:/app/data inventree
|
|
```
|
|
|
|
## systemd
|
|
|
|
See `deploy/inventree.service` for an example unit. Adjust the paths, then:
|
|
|
|
```sh
|
|
sudo useradd --system --home /opt/inventree --shell /usr/sbin/nologin inventree
|
|
sudo mkdir -p /opt/inventree/data
|
|
sudo cp inventree /opt/inventree/inventree
|
|
sudo chown -R inventree:inventree /opt/inventree
|
|
sudo cp deploy/inventree.service /etc/systemd/system/
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now inventree
|
|
```
|
|
|
|
## Scope
|
|
|
|
inventree is intentionally a focused MVP: folders, assets, custom types,
|
|
statuses, users, search, and CSV import/export. It does not include
|
|
ticketing, purchasing, monitoring, RMM, MDM, or accounting features — if you
|
|
need those, look elsewhere and integrate via CSV.
|