Introduction
StoreIT is a self-hosted home inventory management system. It helps you track where everything in your home is stored — from tools in the garage to craft supplies in the closet.
Key Features
- Hierarchical organization — Organize belongings as Locations > Containers > Items, with unlimited nesting
- AI-powered identification — Snap a photo and AI identifies the item, generating searchable descriptions automatically
- NFC tag support — Tap an NFC tag on a container to instantly see contents or move items
- Full-text search — Find items by name, description, or AI-generated tags
- Progressive Web App — Install on any phone or tablet; works offline
- Single-binary deployment — One file to run, no external web server needed
- Multi-user — Share inventory across family members with OIDC authentication
How It Works
StoreIT uses a simple hierarchy:
Home (Location)
├── Kitchen (Sub-Location)
│ ├── Drawer Left (Container)
│ │ ├── Scissors
│ │ ├── Tape
│ │ └── Markers
│ └── Cabinet Top (Container)
│ └── Small Box (Sub-Container)
│ ├── Batteries
│ └── Light Bulbs
└── Garage (Sub-Location)
└── Shelf A (Container)
├── Drill
└── Screwdriver Set
Locations are physical spaces (rooms, buildings). Containers hold items and can be nested. Items are the things you’re tracking.
Every entity can have photos attached. When you add an item by photo, the AI examines the image and suggests a name, description, and searchable tags — you just confirm or tweak.
Installation
Using storeit-ctl (Recommended)
storeit-ctl is a single Python script (Python 3.8+, no pip dependencies) that handles downloading, installing, and managing StoreIT.
# Download storeit-ctl
curl -O https://raw.githubusercontent.com/Bronson-Brown-deVost/StoreIT/main/tools/storeit-ctl
chmod +x storeit-ctl
# Install the latest version
./storeit-ctl install
This downloads the correct binary for your platform from GitHub Releases, places it at /usr/local/bin/storeit-server, and creates the data directory.
Start the server:
storeit-server
Open http://localhost:8080. Default login: admin / changeme.
Configuration
Configure storeit-ctl via environment variables or ~/.config/storeit/ctl.conf:
export STOREIT_CTL_SERVER_URL=http://localhost:8080
export STOREIT_CTL_BINARY_PATH=/usr/local/bin/storeit-server
export STOREIT_CTL_DATA_DIR=/var/lib/storeit
Docker Compose
For Docker users, see Deployment > Docker Compose.
mkdir storeit && cd storeit
curl -O https://raw.githubusercontent.com/Bronson-Brown-deVost/StoreIT/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/Bronson-Brown-deVost/StoreIT/main/.env.docker
cp .env.docker .env
# Edit .env — at minimum, change STOREIT_SESSION_SECRET
docker compose up -d
Manual Binary Install
Download the latest release for your platform from the Releases page:
| Platform | File |
|---|---|
| Linux x86_64 (glibc) | storeit-server-linux-x86_64 |
| Linux x86_64 (musl, static) | storeit-server-linux-x86_64-musl |
| Linux ARM64 (glibc) | storeit-server-linux-aarch64 |
| Linux ARM64 (musl, static) | storeit-server-linux-aarch64-musl |
| macOS (Apple Silicon) | storeit-server-darwin-aarch64 |
| macOS (Intel) | storeit-server-darwin-x86_64 |
| Windows | storeit-server-windows-x86_64.exe |
chmod +x storeit-server-linux-x86_64
./storeit-server-linux-x86_64
The server starts on http://localhost:8080 by default.
Build from Source
Requirements: Rust 1.85+, Node.js 22+, SQLite 3.
git clone https://github.com/Bronson-Brown-deVost/StoreIT.git
cd StoreIT
make frontend-install
make build-all
./target/release/storeit-server
First Steps
After starting StoreIT, open http://localhost:8080 in your browser (or your server’s address).
Create Your First Location
- You’ll see an empty home page with an Add Location button
- Click it, enter a name (e.g., “Kitchen”, “Garage”, “Office”)
- Optionally add a description and photo
- Click Create
Your location appears immediately.
Add a Container
- Navigate into a location by clicking on it
- Click the + button and select Add Container
- Name it (e.g., “Top Shelf”, “Drawer Left”, “Blue Box”)
- Click Create
Containers can be nested — open a container and add sub-containers the same way.
Add an Item
There are two ways to add items:
Quick Add (with AI)
- Navigate to the location or container where the item lives
- Click Add Item
- Take a photo or select one from your gallery
- The AI identifies the item and suggests a name, description, and tags
- Review and adjust the suggestions, then click Create
Manual Add
- Go to
/addor use the bottom navigation - Enter the item name and description manually
- Select where it’s stored
- Click Create
Search for Items
Use the search bar at the top of any page. StoreIT searches across item names, descriptions, and AI-generated tags. Results show the full location path so you know exactly where to find things.
Install as an App
StoreIT is a Progressive Web App. On your phone:
- iOS: Open in Safari → tap Share → “Add to Home Screen”
- Android: Open in Chrome → tap the install prompt or Menu → “Install app”
This gives you a full-screen app experience with offline support.
Configuration
All configuration is done via environment variables. No config file is needed.
Core Settings
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | sqlite:./data/storeit.db?mode=rwc | SQLite database path |
STOREIT_BIND | 0.0.0.0:8080 | Server listen address |
STOREIT_IMAGE_PATH | ./data/images | Image storage directory |
Authentication
| Variable | Default | Description |
|---|---|---|
STOREIT_AUTH_ISSUER | (none — uses mock auth) | OIDC issuer URL |
STOREIT_AUTH_CLIENT_ID | storeit | OIDC client ID |
STOREIT_AUTH_CLIENT_SECRET | changeme | OIDC client secret |
STOREIT_AUTH_REDIRECT_URI | http://localhost:8080/api/v1/auth/callback | OIDC callback URL |
STOREIT_AUTH_GROUP_PREFIX | storeit: | OIDC group claim prefix filter |
STOREIT_SESSION_SECRET | (dev default) | Cookie signing secret (change in production) |
STOREIT_SESSION_TTL_HOURS | 24 | Session lifetime in hours |
AI Identification
| Variable | Default | Description |
|---|---|---|
STOREIT_ANTHROPIC_API_KEY | (none) | Anthropic API key for AI identification |
STOREIT_AI_MODEL | claude-haiku-4-5-20251001 | Claude model to use |
STOREIT_CLAUDE_PATH | claude | Path to Claude CLI binary (fallback) |
AI identification is optional. Without an API key, the identify feature is disabled but all other features work normally.
Example .env File
DATABASE_URL=sqlite:./data/storeit.db?mode=rwc
STOREIT_BIND=0.0.0.0:8080
STOREIT_IMAGE_PATH=./data/images
STOREIT_SESSION_SECRET=your-random-secret-at-least-32-chars
STOREIT_ANTHROPIC_API_KEY=sk-ant-...
Locations
Locations represent physical spaces — rooms, buildings, floors, or any area where you store things.
Creating Locations
From the home page, click Add Location (or the + button if locations already exist). Enter a name and optional description.
Sub-Locations
Locations can be nested. Inside any location, click Add Sub-Location to create a child location. This is useful for organizing large spaces:
House
├── Kitchen
├── Living Room
└── Garage
├── Left Wall
└── Right Wall
Location Details
Each location page shows:
- Sub-locations — child locations
- Containers — storage containers in this location
- Items — items stored directly in this location (not in a container)
- Photos — images of the location
Navigation
The breadcrumb trail at the top shows your current position in the hierarchy. Click any breadcrumb to navigate up.
Containers
Containers represent physical storage — boxes, drawers, shelves, bins, bags, or any object that holds items.
Creating Containers
Inside a location or another container, click the + button and select Add Container.
Nesting
Containers can be nested to any depth:
Garage Shelf (Container)
├── Red Toolbox (Sub-Container)
│ ├── Drill Bits
│ └── Screws
└── Blue Bin (Sub-Container)
└── Paint Supplies
Moving Containers
Containers can be moved between locations or into other containers:
- Open the container
- Click the Move button in the header
- Select the new parent location or container
- Confirm the move
When you move a container, everything inside it moves too.
Container Details
Each container page shows:
- Sub-containers — nested containers
- Items — items stored in this container
- Photos — images of the container
- NFC tag — linked NFC tag, if any
Items
Items are the individual things you’re tracking — tools, supplies, documents, collectibles, or anything else.
Adding Items
With AI Identification
- Navigate to where the item is stored
- Click Add Item
- Take a photo or select one from your gallery
- AI analyzes the photo and suggests a name, description, and tags
- Review, adjust if needed, and click Create
Manual Entry
- Go to the Add Item page
- Enter name, description, and tags manually
- Select the parent location or container
- Optionally attach a photo
- Click Create
Editing Items
Click the Edit button on any item’s detail page to modify its name, description, or tags.
Moving Items
- Open the item’s detail page
- Click the Move button
- Select the new location or container
- Confirm the move
Deleting Items
On the item’s detail page, click Delete Item and confirm. This action cannot be undone.
Item Details
Each item page shows:
- Name and description
- Tags — searchable keywords (often AI-generated)
- Location path — full breadcrumb trail showing where the item is stored
- Photos — all attached images
Photos
Every entity (location, container, item) can have photos attached.
Uploading Photos
On any entity’s detail page, click Add Photo and select an image from your camera or gallery. Photos up to 50MB are supported (covering high-resolution mobile camera shots).
Thumbnails
StoreIT automatically generates optimized thumbnails for fast browsing. Thumbnails are served as WebP images and cached aggressively by the browser. When you tap a thumbnail, the full-resolution original is displayed in a lightbox.
Photo Gallery
Photos appear in a scrollable gallery on each entity’s page. The gallery supports:
- Tap to view full-resolution image in a lightbox
- Swipe through multiple photos in the lightbox
- Photos load quickly thanks to server-generated thumbnails
File Input
The photo upload accepts images from both your camera and your photo gallery — it does not force camera-only mode, so you can select existing photos on mobile devices.
Search
StoreIT provides full-text search across all items, containers, and locations.
How to Search
Type your query in the search bar. Results appear as you type, showing:
- The matching entity’s name
- Its type (location, container, or item)
- The full location path so you know where to find it
What’s Searchable
- Item names and descriptions
- AI-generated tags and metadata
- Container and location names
Search Tips
- Use natural language: “green stretchy thing for bowls”
- Search is powered by SQLite FTS5 and supports partial matches
- Results are ranked by relevance
QR Codes & Print Labels
StoreIT can generate QR codes for any location, container, or item. Scanning a QR code opens the entity directly in StoreIT — useful for labeling shelves, bins, and storage areas.
Generating QR Codes
On any location, container, or item detail page, tap the Print Label button. This opens a print-ready label that includes:
- The entity name
- Its location path (e.g., “Garage > Shelf A > Box 3”)
- A QR code linking directly to that entity
Printing Labels
The print label opens in a new window optimized for printing. Use your browser’s print function (Ctrl+P / Cmd+P) to print it. Labels are designed to work well on:
- Standard label printers (e.g., Brother, Dymo)
- Regular paper (cut to size)
- Adhesive label sheets
How QR Codes Work
Each QR code encodes a URL pointing to your StoreIT instance:
https://your-server/nfc/tag?uid=container-{uuid}
When scanned with any phone camera or QR reader, it opens StoreIT and navigates directly to that entity. If the user is not logged in, they’ll be prompted to authenticate first.
QR Codes vs NFC Tags
| Feature | QR Codes | NFC Tags |
|---|---|---|
| Cost | Free (print on paper) | Requires NFC stickers |
| Scanning | Camera app | Hold phone near tag |
| Durability | Can fade/tear | Waterproof, durable |
| Range | Line of sight | ~2cm proximity |
| Setup | Print and stick | Write tag URI, then assign in app |
Both can be used together — put a QR code on the outside of a box and an NFC tag inside the lid.
NFC Tags
NFC (Near Field Communication) tags let you tap your phone on a physical container to instantly see its contents or move items.
Setup
- Get NFC sticker tags (NTAG213 or NTAG215 are common and inexpensive)
- Use an NFC writing app to write a URL to the tag:
https://your-storeit-server/nfc/{tag-id} - In StoreIT, navigate to the container and link the NFC tag via the container’s settings
Usage
View Contents
Tap your phone on an NFC-tagged container. StoreIT opens and shows the container’s contents.
Move Items
- Open an item and tap Move
- Tap the NFC tag on the destination container
- The item moves to that container
Requirements
- A phone with NFC capability (most modern smartphones)
- NFC sticker tags
- StoreIT accessible via HTTPS (required for Web NFC API on some browsers)
AI Identification
StoreIT can use Claude (Anthropic’s AI) to automatically identify items from photos.
How It Works
- You take a photo of an item
- The photo is sent to the Claude API
- Claude analyzes the image and returns:
- A suggested name for the item
- A description of what it is
- Tags for searchability (color, material, category, etc.)
- You review and confirm or edit the suggestions
Setup
Set the STOREIT_ANTHROPIC_API_KEY environment variable with your Anthropic API key. You can get one at console.anthropic.com.
STOREIT_ANTHROPIC_API_KEY=sk-ant-api03-...
Optionally, configure the model:
STOREIT_AI_MODEL=claude-haiku-4-5-20251001 # default, fast and cheap
Without AI
If no API key is configured, AI identification is disabled. You can still add items manually with name, description, and tags. All other features work normally.
Privacy
Photos are sent to Anthropic’s API for identification only. They are not stored by Anthropic beyond the API request. All data remains on your server.
Authentication Setup
StoreIT supports three authentication modes.
Mock Auth (Development)
When no STOREIT_AUTH_ISSUER is set, StoreIT uses a built-in mock auth provider. This is suitable for development and testing — any username/password is accepted.
Local Login
StoreIT supports local username/password authentication managed through the admin panel. This is suitable for small deployments without an external identity provider.
OIDC (Recommended for Production)
For production use, configure an OpenID Connect provider like Authentik, Keycloak, or any OIDC-compliant identity provider.
Configuration
STOREIT_AUTH_ISSUER=https://auth.example.com/application/o/storeit/
STOREIT_AUTH_CLIENT_ID=storeit
STOREIT_AUTH_CLIENT_SECRET=your-client-secret
STOREIT_AUTH_REDIRECT_URI=https://storeit.example.com/api/v1/auth/callback
STOREIT_SESSION_SECRET=random-string-at-least-32-characters
Authentik Setup
- Create a new OAuth2/OpenID Provider in Authentik
- Set the redirect URI to
https://your-domain/api/v1/auth/callback - Create an Application and link it to the provider
- Copy the client ID and secret to your StoreIT configuration
Groups
StoreIT uses OIDC group claims to manage access. Set STOREIT_AUTH_GROUP_PREFIX to filter which groups are relevant (default: storeit:). Users see inventory for groups they belong to.
Deployment
Single Binary
StoreIT compiles to a single binary with the frontend embedded. No separate web server is needed.
./storeit-server
By default, the database is created at ./data/storeit.db and images are stored in ./data/images/. See Configuration for all options.
Systemd Service
[Unit]
Description=StoreIT Inventory Management
After=network.target
[Service]
Type=simple
User=storeit
WorkingDirectory=/opt/storeit
ExecStart=/opt/storeit/storeit-server
EnvironmentFile=/opt/storeit/.env
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Docker Compose (Recommended for Docker)
A ready-to-use docker-compose.yml and .env.docker template are included in the repository:
mkdir storeit && cd storeit
# Download compose file and env template
curl -O https://raw.githubusercontent.com/Bronson-Brown-deVost/StoreIT/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/Bronson-Brown-deVost/StoreIT/main/.env.docker
# Create your .env from the template — at minimum, change STOREIT_SESSION_SECRET
cp .env.docker .env
nano .env
docker compose up -d
Open http://localhost:8080. Default login: admin / changeme.
Data Storage
The compose file uses bind mounts by default, so your data lives directly on the host filesystem where you can see, back up, and manage it:
./data/
db/storeit.db # SQLite database
images/ # Uploaded photos and thumbnails
ab/ab1234...jpg
ab/ab1234..._thumb.webp
To change where data is stored, edit the volume paths in docker-compose.yml:
volumes:
- /mnt/nas/storeit/db:/data/db
- /mnt/nas/storeit/images:/data/images
If you prefer Docker named volumes instead (opaque, managed by Docker):
volumes:
- storeit-db:/data/db
- storeit-images:/data/images
# Add at the bottom of the file:
volumes:
storeit-db:
storeit-images:
Docker Run
If you prefer a single command:
mkdir -p ./data/db ./data/images
docker run -d \
--name storeit \
-p 8080:8080 \
-v ./data/db:/data/db \
-v ./data/images:/data/images \
--env-file .env \
ghcr.io/bronson-brown-devost/storeit:latest
Building Locally
Build the binary first, then create the Docker image:
git clone https://github.com/Bronson-Brown-deVost/StoreIT.git
cd StoreIT
make build-all
docker build --build-arg BINARY=./target/release/storeit-server -t storeit .
docker run -d --name storeit -p 8080:8080 -v ./data/db:/data/db -v ./data/images:/data/images --env-file .env storeit
Docker Image Details
- Registry:
ghcr.io/bronson-brown-devost/storeit - Tags:
latestand version-specific (e.g.,0.1.0) - Architectures:
linux/amd64andlinux/arm64 - Base image: Alpine Linux
- Data paths:
/data/db(database) and/data/images(photos) - Port:
8080
Reverse Proxy
For production, put StoreIT behind a reverse proxy for TLS termination.
Caddy
storeit.example.com {
reverse_proxy localhost:8080
}
Nginx
server {
listen 443 ssl;
server_name storeit.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
client_max_body_size 50M;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Production Checklist
- Set
STOREIT_SESSION_SECRETto a random 32+ character string - Configure OIDC authentication (or change the default admin password)
- Set
STOREIT_AUTH_REDIRECT_URIto your public callback URL - Set
STOREIT_ANTHROPIC_API_KEYfor AI identification - Ensure database and image paths point to persistent storage
- Set up TLS via reverse proxy
- Set up regular backups (see Backup & Restore)
Backup & Restore
StoreIT stores all data in two places:
- SQLite database — all inventory data, user sessions, settings
- Image directory — uploaded photos and generated thumbnails
Built-in Backup (Recommended)
The Admin UI provides backup and restore under Settings > Backup. Backups are exported as .storeit archives (zstd-compressed tar) containing all data and optionally all images.
Via the Admin UI
- Go to Settings > Backup
- Choose whether to include images
- Click Start Backup and wait for completion
- Download the
.storeitarchive
Via storeit-ctl
# Download a full backup (data + images)
storeit-ctl backup -o my-backup.storeit
Via the API
# Start a backup job
curl -X POST http://localhost:8080/api/v1/admin/backup \
-H "Content-Type: application/json" \
-d '{"include_images": true}'
# Returns: {"job_id": "..."}
# Poll status
curl http://localhost:8080/api/v1/admin/backup/{job_id}/status
# Download when complete
curl -o backup.storeit http://localhost:8080/api/v1/admin/backup/{job_id}/download
Restore
Via the Admin UI
- Go to Settings > Restore
- Upload a
.storeitarchive - Choose Replace (wipe and restore) or Merge (add alongside existing data)
Via the CLI (offline import)
For importing into a stopped server (e.g., during upgrades):
storeit-server import backup.storeit --mode replace
This creates a fresh database, runs migrations, and imports all data. The previous database is saved as storeit.db.pre-import for rollback.
Upgrade & Downgrade
The storeit-ctl tool orchestrates version migrations:
storeit-ctl upgrade # Upgrade to latest version
storeit-ctl upgrade 0.2.0 # Upgrade to specific version
storeit-ctl downgrade 0.1.0 # Downgrade to older version
storeit-ctl rollback # Revert if something goes wrong
storeit-ctl cleanup # Remove rollback files after confirming
The upgrade flow: backup via API, download new binary, stop server, import data with new binary, start, health check. On failure, automatic rollback.
Manual Backup
You can also back up the raw files directly:
# Stop the server (or use SQLite online backup)
sqlite3 /path/to/storeit.db ".backup '/path/to/backup/storeit.db'"
# Copy images
rsync -a /path/to/images/ /path/to/backup/images/
Docker Volumes
If using Docker, back up the volume:
docker run --rm \
-v storeit-data:/data \
-v $(pwd)/backup:/backup \
alpine tar czf /backup/storeit-backup.tar.gz /data
Upgrading
StoreIT uses a snapshot-based migration system. Upgrades work by exporting all data from the old version, then importing it into a fresh database created by the new version. This ensures clean migrations regardless of how many versions you skip.
Using storeit-ctl (Recommended)
The storeit-ctl tool automates the full upgrade process:
storeit-ctl upgrade # Upgrade to latest release
storeit-ctl upgrade 0.2.0 # Upgrade to a specific version
This will:
- Back up your data via the running server’s API
- Download the new binary for your platform
- Stop the server
- Import data into a fresh database using the new binary
- Start the new server
- Run a health check
If the health check fails, it automatically rolls back to the previous version.
After Upgrading
Verify everything works, then clean up rollback files:
storeit-ctl status # Check version and health
storeit-ctl cleanup # Remove .pre-import DB and old binary
Rolling Back
storeit-ctl rollback
This restores the previous binary and database, then restarts the server.
Downgrading
storeit-ctl downgrade 0.1.0
Docker Compose
Docker upgrades are fully automatic:
docker compose pull
docker compose up -d
On startup, the container detects if the database schema version doesn’t match the new binary. If a migration is needed, it automatically:
- Exports all data and images from the existing database
- Renames the old database to
.pre-upgrade - Creates a fresh database with the new schema
- Imports all data with version transforms applied
- Starts the server
You’ll see this in the container logs:
schema version mismatch: database has 1, binary expects 2 — auto-upgrading
exported data to temporary archive
backing up database to /data/db/storeit.db.pre-upgrade
import completed successfully
listening on 0.0.0.0:8080
If the migration fails, the old database is automatically restored.
Rolling Back (Docker)
If an upgrade causes problems:
docker compose down
# The old database was saved automatically
ls ./data/db/storeit.db.pre-upgrade
# Remove the new database and restore the old one
rm ./data/db/storeit.db
mv ./data/db/storeit.db.pre-upgrade ./data/db/storeit.db
# Pin to the previous version in docker-compose.yml
# e.g., image: ghcr.io/bronson-brown-devost/storeit:0.1.0
docker compose up -d
Pinning a Version
To control when you upgrade, pin to a specific version in docker-compose.yml:
image: ghcr.io/bronson-brown-devost/storeit:0.1.0
Manual Binary Upgrade
If you prefer to manage the process yourself:
- Back up your data:
storeit-ctl backup -o pre-upgrade.storeit - Stop the server
- Replace the binary with the new version
- Import:
storeit-server import pre-upgrade.storeit --mode replace - Start the server
Schema Versioning
StoreIT tracks database schema versions independently from app versions. Each binary expects a specific schema version. If there’s a mismatch, the server refuses to start (or auto-upgrades in Docker).
The import command handles version transitions: it creates a fresh database with the new schema, applies version transforms to the data, and imports everything.
Check current versions:
storeit-server version