Run your pantry manager at home, verify every local layer, and add remote access only when the deployment is ready
EverShelf is an open-source pantry and inventory web application for tracking products, locations, quantities, expiry dates, shopping items, and recipes. This guide installs a pinned EverShelf release with Docker Compose, explains which deployment details must be inspected before relying on persistence or backups, and verifies the application locally. It then connects the working service to a Localtonet HTTP tunnel without inbound router port forwarding, firewall changes, VPN setup, or a public IP address. Because EverShelf currently documents no multi-user support, the security section also explains why API pairing must not be mistaken for complete browser authentication.
๐ What's in this guide
Tutorial baseline and what was verified
This tutorial uses EverShelf v1.11.11, associated with commit caa1ab2 in the supplied release record. That release was published on October 10, 2026, and the evidence for this revision was checked against the project pages supplied on that date. The repository overview subsequently displayed v1.11.12 in its current change summary, so the default main branch was already ahead of this tutorial baseline.
A normal clone of main changes as new commits arrive. Commands, environment variables, database migrations, Compose behavior, and security controls may therefore differ from this article. For a reproducible installation, check out a release tag and record the resulting commit. Before choosing a newer release, read its notes and repeat the configuration, backup, local verification, and security checks described below.
The official project materials relevant to this deployment are:
- The official EverShelf repository for the project overview and installation entry point.
- The pinned release's Docker Compose definition for services, image or build behavior, ports, mounts, restart policy, and any health check.
- The pinned environment template for recognized variable names and supported values.
- The pinned EverShelf security policy for API-token and pairing behavior.
- The pinned backup script, which must be reviewed before it is used.
- The pinned changelog and release list for migrations and operational changes.
The supplied repository overview verifies the Docker quick start, the local URL http://localhost:8080, SQLite storage under data/, the documented container name evershelf used by the pairing-code command, and the presence of the configuration and security files above. It does not expose the complete contents of the pinned Compose file, environment template, security policy, or backup script in the evidence available to this revision.
Consequently, this article does not invent an exact container-side data path, host bind address, restart value, health-check command, backup archive format, or restoration command. Instead, it shows how to inspect the checked-out definition and the running container before you depend on those properties. This limitation matters most for backup and rollback. The repository proves that a backup.sh file exists, but the supplied evidence does not establish its invocation, output location, retention rules, validation process, or a supported restore procedure.
What EverShelf provides
EverShelf focuses on pantry, refrigerator, freezer, shopping, and cooking workflows. Its documented capabilities include barcode scanning, custom storage locations, expiry tracking, opened packs, favourites, and CSV import and export. Shopping tools can react to depleted stock and account for pantry quantities when ingredients are moved from a recipe to a shopping list.
EverShelf is installable as a progressive web app and supports an offline queue for relevant operations. Its wider integration set includes Home Assistant, Bring!, an Android kiosk, an MCP component, a health bridge, an ICS or WebCal expiry calendar, ntfy notifications, and JSON webhooks. Those optional integrations are outside this tutorial because they add separate credentials and operating requirements.
data/ area rather than requiring a separate database server.
Prerequisites and deployment plan
Choose a host that remains powered on whenever EverShelf should be available. A Localtonet tunnel cannot keep the application online if its host is sleeping, disconnected, or shut down. The host can be a home server, an always-on computer, or another system capable of running the checked-out Docker Compose configuration.
Prepare the following:
- A working Docker installation with the modern
docker composecommand. - Git for cloning the repository and checking out the pinned tag.
- A terminal account authorized to run Docker commands.
- A text editor for reviewing
.envand the Compose definition. - Storage for the repository, container image or build layers, application data, logs, and independent backups.
- A browser on the host or another device that can reach it.
- The Localtonet client later, running on the EverShelf host or another device that can reach the EverShelf target.
Docker installation differs by operating system and distribution. The supplied EverShelf evidence does not define one universal Docker installation command, so use the supported installation path for your host and then verify the required tools:
docker --version
docker compose version
git --version
Each command should return version information. Resolve Docker permissions and Compose availability before cloning EverShelf.
First make EverShelf work at its local endpoint. Create the Localtonet tunnel only after container state, logs, browser behavior, and persistence have been checked. This gives you a clean fault boundary between the application and the remote-access path.
Plan where the deployment will live
Place the repository in a directory intended to remain part of the deployment. Do not treat it as a temporary installer. It contains the Compose definition, active environment file, application tree, and potentially host-side persistent data. Record the absolute path so future administrators know where to run Compose commands.
EverShelf also mentions a manual web-server installation: clone the repository, copy .env.example to .env, set data/ to mode 755, and point a web server at the repository root. The supplied evidence does not establish a complete PHP version requirement, extension list, virtual-host configuration, service account, or hardening procedure. This guide therefore uses the project's recommended Docker approach.
Install the pinned EverShelf release
Clone the official repository at v1.11.11
Clone the release tag instead of following the mutable default branch.
git clone --branch v1.11.11 --depth 1 https://github.com/dadaloop82/EverShelf.git
cd EverShelf
Confirm the checked-out version
Record the tag and commit with your deployment notes and backups. The supplied v1.11.11 release record identifies commit caa1ab2.
git describe --tags --always
git rev-parse --short HEAD
Create the active environment file
Copy the pinned template to .env. Edit the copy, not .env.example.
cp .env.example .env
Inspect the resolved Compose configuration
Review the service name, container name, image or build source, published port, bind address, volume mapping, restart policy, environment inputs, and any health check before starting the application.
docker compose config
docker compose config --services
Review the environment values
Compare .env with the pinned template. Remove placeholder credentials, leave unused integrations disabled according to the template, and do not commit the active file.
Start EverShelf
Start the checked-out Compose application in detached mode.
docker compose up -d
Record the actual deployment properties
The project overview documents http://localhost:8080 and uses evershelf in its Docker pairing-code example. Those facts support port 8080 as the expected browser endpoint and evershelf as the documented container name for the referenced setup. They do not, by themselves, prove whether the host port is bound only to loopback or to every interface.
Use the resolved configuration and running state to record these items:
| Property | Where to verify it | Why it matters |
|---|---|---|
| Service and container name | docker compose config --services and docker compose ps |
Needed for logs, inspection, backup quiescing, and troubleshooting. |
| Image or build source | docker compose config |
Determines whether pulling an image is sufficient or local source must also be updated and rebuilt. |
| Port and bind address | docker compose config and docker compose ps |
Determines whether EverShelf is limited to the host or reachable from the LAN. |
| Persistence mapping | Compose volumes output and container mount inspection |
Identifies the host path or named volume that must be backed up. |
| Restart policy | docker compose config |
Determines what happens after a process failure or host reboot. |
| Health check | docker compose config and docker compose ps |
Shows whether Compose has an application-health signal beyond process state. |
If the pinned file does not define a health check, do not describe the container as healthy merely because it is running. Use the local browser test and an actual application workflow as the readiness check.
Configure EverShelf without exposing secrets
Reconcile the displayed AI example with optional AI
The repository overview labels the following as its displayed minimum environment example:
AI_ENABLED=true
AI_PROVIDER=gemini
GEMINI_API_KEY=your_key
The official EverShelf site also states that AI assistance is optional and that inventory and barcode functions continue to work when AI is turned off. These statements are compatible: the README block is a minimum example for an AI-enabled configuration, not proof that AI is required by the core application.
your_key is a placeholder, not a usable credential. If you want AI, replace it with a valid credential for the provider supported by the pinned release and protect the file. If you do not want AI, use the exact disabled value documented in the pinned .env.example. That value is not visible in the supplied evidence, so this article does not guess its spelling or accepted alternatives.
The repository overview also identifies API_TOKEN and SHOPPING_MODE=bring as optional configuration. Do not enable Bring!, AI, Home Assistant, webhooks, or other integrations until the base application is working and you understand what data and credentials each integration uses.
API token and one-time pairing
When API_TOKEN is set, EverShelf documents a one-time pairing flow. An unpaired web interface asks for a pairing code, and the API token is not returned to an anonymous request. A device that is already paired can display the current code under Settings โ System โ Security, with the project also referencing its information area.
The documented Docker log query is:
docker logs evershelf 2>&1 | grep -i " pairing code " | tail -1
Use that command only if the container is actually named evershelf. Confirm the name with docker compose ps first. Pairing codes and logs are sensitive operational information and should not be pasted into public issues or support channels.
The supplied project evidence describes pairing as protection for API-token delivery and API access. It does not establish that the complete browser application is protected by individual user accounts, sessions, roles, or a login boundary. EverShelf currently documents no multi-user support. Do not describe pairing as full application authentication, and do not assume that a paired browser identifies a distinct authorized person.
EverShelf documents API_BOOTSTRAP_OPEN=true as an opt-out for a fully trusted LAN and warns that it re-exposes the API token. Do not use that setting for an instance reachable through a public tunnel.
Reverse-proxy settings
The project documents TRUSTED_PROXIES so rate limiting can interpret real client addresses when EverShelf runs behind a reverse proxy. It also documents EVERSHELF_CANONICAL_HOST in docker/apache-evershelf.conf for forced-HTTPS redirect behavior.
Do not guess a proxy IP, CIDR, canonical hostname, or forwarded-header policy. The correct value depends on the address EverShelf sees as its immediate peer and on the exact network path. Our Localtonet evidence does not provide a universal relay CIDR that should be trusted by EverShelf. An overly broad trusted-proxy setting can allow untrusted clients to influence address headers used by application controls.
Verify EverShelf locally before creating a tunnel
Inspect Compose state
Confirm that the expected service is running rather than exiting or repeatedly restarting.
docker compose ps
Review startup logs
Look for environment, permission, database, port, or initialization errors.
docker compose logs
Open the documented local endpoint
On the Docker host, visit http://localhost:8080 and confirm that the interface finishes loading.
Complete API pairing if requested
If API_TOKEN is configured, obtain the one-time code from a trusted paired device or the local server log.
Test a core workflow
Navigate the inventory interface. On a new disposable installation, create a small test record, refresh the page, and confirm it remains present.
Verify restart persistence
Restart the Compose application, reopen EverShelf, and confirm that the test record remains available before trusting the configured data mapping.
docker compose down
docker compose up -d
docker compose ps
When testing from another LAN device, remember that localhost refers to that device, not the Docker host. Use the Docker host's reachable LAN address with port 8080 only if the resolved Compose port bind and local network policy permit it.
If the Localtonet client will run on another machine, test EverShelf from that machine before creating the tunnel. The client must be able to reach exactly the address and port entered as the local target.
Back up, update, and define a rollback boundary
Identify the active data location
EverShelf documents SQLite under data/, but the exact host-to-container mapping must come from the pinned Compose definition. Record whether the deployment uses a bind mount or a named Docker volume, along with its source and destination. Do not assume that copying the visible repository folder captures active data until the mount mapping confirms it.
You can inspect the running container's mounts with Docker after confirming its name:
docker compose ps
docker inspect evershelf
Review the Mounts section rather than publishing the complete output, which may reveal host paths and environment details.
Create a conservative cold backup
The repository contains backup.sh, but the supplied evidence does not document how to run it or how to restore its output. Do not assume that executing an unreviewed script creates a complete, validated, or recoverable backup.
Until the script and release documentation establish a supported procedure, use this conservative process:
- Record the EverShelf tag, commit, resolved Compose configuration, and active environment file.
- Identify every host path or Docker volume containing SQLite data, uploaded files, or other persistent state.
- Stop EverShelf cleanly with
docker compose downso the SQLite database is not changing during the copy. - Copy the complete persistent source,
.env, Compose definition, and version record to storage outside the deployment directory. - Protect the backup because
.envmay contain API tokens and provider credentials. - Start the original deployment again with
docker compose up -dand repeat the local checks.
A backup is not proven recoverable until it has been restored into an isolated test deployment and the application can read the recovered records. The supplied evidence does not define an official restore sequence, database downgrade procedure, or compatibility guarantee across releases. Treat restoration as unverified until you have reviewed the pinned backup.sh, security documentation, changelog, and release notes and completed a restore drill.
Validate the backup
At minimum, confirm that the backup destination contains the expected persistent path, a non-empty SQLite database where applicable, the deployment configuration, and a version record. Compare file counts and sizes with the stopped source, and generate checksums using tools appropriate to your operating system.
A meaningful restore drill uses an isolated host, directory, Docker project name, and non-conflicting local port. Do not overwrite the working deployment merely to test a backup. After restoration, confirm the expected version starts, the browser loads, representative inventory records are present, and normal reads succeed.
Understand repository and image updates
The repository overview documents:
docker compose pull
docker compose up -d
These commands pull images referenced by the current Compose file and recreate services as needed. They do not update the checked-out Git repository, switch release tags, or automatically review changes to .env.example. If the release builds from local source instead of using a remote image, pulling alone may not update the application. Verify the image or build section in docker compose config.
For a deliberate release update:
- Read the target release notes and changelog, including database migration and configuration changes.
- Create and validate a cold backup.
- Compare the old and new
.env.exampleand Compose definitions without exposing secrets. - Fetch tags and check out the exact target release rather than moving to an arbitrary point on
main. - Follow that release's documented image pull or build process.
- Verify logs, local browser behavior, persistence, and pairing before testing the public URL.
Define the rollback boundary
Code and container images can be returned to an earlier release only if that release remains available and its configuration is preserved. Application data is a separate boundary. A newer release may migrate SQLite in a way an older release cannot read. Therefore, checking out an old tag is not a complete rollback.
The safe rollback boundary is the combination of the old release, its matching configuration, and a pre-update data backup proven compatible with that release. Without all three, rollback is not established. Never point an older application release at a database already migrated by a newer version unless the project explicitly documents that downgrade path.
Expose the verified service with Localtonet
A Localtonet HTTP tunnel can provide a public HTTPS address for EverShelf. Our client establishes an outbound connection to a Localtonet relay, so this workflow does not require inbound router port forwarding, firewall changes, VPN setup, or a public IP address.
Use the installer and operating-system instructions linked from the current Localtonet HTTP tunnel documentation. Client installation differs by platform, so this article does not invent a universal command or an unverified download URL.
Install and run the Localtonet client
Install our current client on the EverShelf host or another trusted device that can reach the verified EverShelf endpoint. Keep it running whenever remote access is required.
Authenticate or select the client device
Use the device-specific token for the client that will run the tunnel. Never publish, guess, or share that token.
Select an available relay server
Choose a currently available server or region in the dashboard. Availability can vary, so obtain the value from the current product rather than copying a hardcoded server code.
Create the HTTP tunnel
Choose the HTTP tunnel family and enter the IP address and port that reach EverShelf from the Localtonet client. If both run on the same host, use the loopback target that reaches port 8080. If the client runs elsewhere, use the verified LAN address and port.
Choose the HTTP process type
Select Random Sub Domain, Custom Sub Domain, or Custom Domain according to the currently available dashboard options. Each serves the local content at a public HTTPS address.
Start and test the tunnel
Creating the configuration does not start it. Press Start, then test the assigned public URL from a private browser window or an external connection.
Stop or delete access when finished
Stop the tunnel to remove the active public route while keeping its configuration, or delete the tunnel if it is no longer required.
Custom-domain DNS requirements must be checked against the current dashboard and documentation before changing DNS. Do not invent a CNAME target or verification record. The tunnel is available only while the selected Localtonet client is connected and the tunnel is running.
Security considerations before public exposure
The project's own comparison material marks multi-user functionality as unavailable and lists it on the roadmap. Do not expose one instance with the expectation that it provides separate household accounts, individual permissions, user isolation, or administrator roles. Anyone who can use the exposed application may be interacting with the same shared pantry and configuration context.
A generated public URL is not an access-control mechanism. The documented one-time pairing flow protects API-token delivery and API use, but the supplied security evidence does not prove that it places the entire browser application behind full user authentication. Until the installed release's security policy explicitly establishes otherwise, treat the public browser surface and the API pairing mechanism as separate concerns.
If your threat model requires an authenticated login before any browser content is available, role-based access, individual accounts, or user revocation, do not assume EverShelf provides those controls. Keep the service restricted to a trusted network, add a separately verified access-control layer, or use Localtonet only for short supervised sessions. Any additional proxy or identity layer must be tested with EverShelf's PWA, API, pairing, and redirect behavior.
TRUSTED_PROXIES only after identifying the actual trusted peer addresses for your deployment.
Public HTTPS protects the public transport path but does not replace application authorization, host security, updates, secret handling, or backup discipline. Review the pinned EverShelf security policy before enabling the tunnel and repeat that review when upgrading.
Troubleshoot installation and remote access
docker compose is unavailable
Run docker compose version. If it fails, install or repair Docker Compose using the supported procedure for the host. Also confirm that the current account can communicate with Docker.
The container exits or repeatedly restarts
Run docker compose ps and docker compose logs. Look for invalid environment values, missing credentials for enabled features, data permissions, database errors, port conflicts, or initialization failures. Correct the first meaningful error before restarting again.
Port 8080 is already occupied
Identify the conflicting host process using operating-system tools. Before editing Compose, inspect the pinned definition and determine whether the host-side port is configurable. The supplied evidence does not document an official alternate-port variable, so this guide does not invent one.
The browser cannot open http://localhost:8080
Confirm that the browser is on the Docker host. On another device, localhost refers to that device. Check the resolved port publication, container logs, host networking, and firewall policy. Leave the Localtonet tunnel stopped until the local page works.
The interface requests a pairing code
This is expected when API_TOKEN is set and the device is unpaired. Obtain the code from a trusted paired device or the local Docker log. Do not enable API_BOOTSTRAP_OPEN=true merely to avoid pairing over a public connection.
EverShelf works locally but not through Localtonet
Confirm that the selected Localtonet client is connected, the HTTP tunnel has been started, and its target is reachable from that client. If the client is on another machine, its localhost does not refer to the EverShelf host. Test the LAN target directly from the client machine.
The public URL redirects incorrectly
Review the installed release's canonical-host and trusted-proxy behavior. Compare the incoming host and scheme with the configuration supported by that release. Do not add broad trusted-proxy ranges or guessed canonical hosts as a trial fix.
Data disappears after recreation
Stop making changes and inspect the resolved Compose volumes and container mounts. Confirm whether the active database is in a host bind mount, a named Docker volume, or a container-only path. Do not run Docker cleanup or volume-removal commands while investigating.
Remote access disappears after reboot
Check the Docker service, EverShelf container, Localtonet client, and tunnel state separately. A restart policy may restart EverShelf, but its exact value must be confirmed in the pinned Compose file. The public route still requires a connected Localtonet client and a running tunnel.
An update succeeds but the application behaves unexpectedly
Verify the active Git commit, image, configuration, logs, and database state. Review release notes for migrations. Test locally before involving the tunnel. Roll back only to a matching pre-update data backup and configuration that you have already validated.
Frequently asked questions
Which EverShelf version does this guide use?
This guide uses EverShelf v1.11.11 at commit caa1ab2. The repository's main branch is mutable and was already showing later changes in the supplied evidence.
Does EverShelf require AI?
No. EverShelf states that AI is optional and that inventory and barcode functions work without it. The README's displayed minimum block is an AI-enabled Gemini example, not proof that AI is mandatory.
What local address should I verify?
The documented Docker endpoint is http://localhost:8080. Confirm the actual bind address and publication in the resolved Compose configuration before assuming that port is also reachable from other LAN devices.
Does API pairing protect the complete EverShelf website?
The supplied evidence establishes pairing for API-token delivery and API access. It does not establish a complete browser login boundary with individual users, sessions, roles, and permissions. Do not present pairing as full user authentication without confirming that behavior in the installed release.
Does EverShelf support multiple users?
No multi-user support is currently documented. The project comparison marks it as unavailable, and the project site lists it on the roadmap. Do not expect separate accounts or per-user permissions.
Is the included backup script enough to guarantee recovery?
No such guarantee is established by the supplied evidence. The repository contains backup.sh, but its invocation, output, retention, and restoration procedure were not available here. Review the pinned script and prove recovery with an isolated restore drill.
Do I need router port forwarding?
No. The Localtonet client establishes an outbound connection to our relay, so an HTTP tunnel does not require inbound router port forwarding, firewall changes, VPN setup, or a public IP address.
Does creating a Localtonet tunnel make it active?
No. Creation and runtime are separate lifecycle states. Press Start after creating the tunnel. The route works only while the selected client is connected, the tunnel is running, and EverShelf is reachable at the configured target.
Connect your verified EverShelf deployment
Pin the EverShelf release, inspect its real persistence and network configuration, verify the application locally, and review the limits of its pairing and multi-user model. When the deployment is ready for your threat model, create a Localtonet HTTP tunnel and start remote access without opening an inbound router port.
Get Started Free โ