26 min read

Self-Host EverShelf and Access It with Localtonet

Install and verify EverShelf with Docker Compose, then securely expose your pantry manager through a Localtonet HTTP tunnel.

Self-Hosting ยท EverShelf v1.11.11 ยท Localtonet ยท 2026

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.

๐Ÿ”’ Review access controls before public exposure ๐ŸŒ Verify locally before creating the tunnel ๐Ÿ“Œ Tutorial baseline: v1.11.11 at caa1ab2
A home server running EverShelf connects to a remote phone through a Localtonet HTTP tunnel.
EverShelf remains on infrastructure you control while the Localtonet client carries remote requests through an outbound tunnel.

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.

Do not treat the main branch as a fixed installation target

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 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.

๐Ÿ“ฆ Inventory and expiry tracking Record products, quantities, locations, expiry dates, opened packs, favourites, and stock changes.
๐Ÿ›’ Shopping workflows Maintain an internal shopping list, account for pantry stock, or enable the documented Bring! integration when needed.
๐Ÿณ Recipes and cooking Use pantry ingredients in recipes, follow cooking steps, use timers, and work with suggestions intended to reduce waste.
๐Ÿ“ฑ PWA and kiosk options Install the browser application as a PWA or use the separately maintained Android kiosk workflow.
๐Ÿค– Optional AI assistance EverShelf documents Gemini, OpenAI, and Llama for product identification, expiry OCR, recipes, and chat.
๐Ÿ’พ Self-hosted SQLite data The documented architecture uses SQLite under the application's 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 compose command.
  • Git for cloning the repository and checking out the pinned tag.
  • A terminal account authorized to run Docker commands.
  • A text editor for reviewing .env and 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.

Keep installation and remote access separate

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

Docker Compose creates an EverShelf container connected to persistent application data and a host web port.
The exact image, mount destination, port bind, restart policy, and health check must be confirmed in the pinned Compose file before startup.
1

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
2

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
3

Create the active environment file

Copy the pinned template to .env. Edit the copy, not .env.example.

cp .env.example .env
4

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
5

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.

6

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.

Do not start an internet-facing deployment with a placeholder AI key

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.

Pairing is not established as complete user authentication

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

A running EverShelf container and pantry interface are checked through the local port before remote access is enabled.
Container state is only the first check. Confirm logs, the browser interface, pairing behavior, and persistence locally.
1

Inspect Compose state

Confirm that the expected service is running rather than exiting or repeatedly restarting.

docker compose ps
2

Review startup logs

Look for environment, permission, database, port, or initialization errors.

docker compose logs
3

Open the documented local endpoint

On the Docker host, visit http://localhost:8080 and confirm that the interface finishes loading.

4

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.

5

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.

6

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:

  1. Record the EverShelf tag, commit, resolved Compose configuration, and active environment file.
  2. Identify every host path or Docker volume containing SQLite data, uploaded files, or other persistent state.
  3. Stop EverShelf cleanly with docker compose down so the SQLite database is not changing during the copy.
  4. Copy the complete persistent source, .env, Compose definition, and version record to storage outside the deployment directory.
  5. Protect the backup because .env may contain API tokens and provider credentials.
  6. Start the original deployment again with docker compose up -d and repeat the local checks.
The project evidence does not provide a verified restore command

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:

  1. Read the target release notes and changelog, including database migration and configuration changes.
  2. Create and validate a cold backup.
  3. Compare the old and new .env.example and Compose definitions without exposing secrets.
  4. Fetch tags and check out the exact target release rather than moving to an arbitrary point on main.
  5. Follow that release's documented image pull or build process.
  6. 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

Remote HTTPS requests pass through a Localtonet relay to EverShelf on a private Docker host.
The Localtonet client must remain connected, the HTTP tunnel must be started, and EverShelf must remain reachable at its local target.

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.

1

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.

2

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.

3

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.

4

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.

5

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.

6

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.

7

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

EverShelf currently documents no multi-user support

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.

๐Ÿ”‘ Protect every secret Keep API tokens, pairing codes, AI keys, integration credentials, and the Localtonet device token out of screenshots, repositories, and support logs.
๐Ÿ‘ฅ Account for shared access EverShelf currently has no documented multi-user model, so do not rely on per-user permissions or individual audit boundaries.
๐Ÿงฑ Trust proxies narrowly Set TRUSTED_PROXIES only after identifying the actual trusted peer addresses for your deployment.
๐Ÿงฉ Disable unused integrations Each AI provider, webhook, shopping service, and home-automation connection adds credentials and data flow.
๐Ÿ’พ Prove recoverability Back up the actual persistent source and complete an isolated restore drill before depending on the deployment.
โน๏ธ Limit exposure time Stop the Localtonet tunnel when remote access is not needed, especially if no separate browser authentication layer has been verified.

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 โ†’

Corrections & updates

Substantive changes approved by the Localtonet editorial team are listed transparently below.

Remove the outer <article> wrapper from Model.Body. Make the lt-hero the first body component and place the existing clickable What's in this guide card directly after it; move the lead diagram below that navigation or into the first relevant section. State the EverShelf release or commit tested and the date it was verified, while warning that cloning main is mutable. Recheck all commands and claims against the current README, docker-compose.yml, .env.example, SECURITY.md, backup.sh, and changelog. Document the exact persistence mappi

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support