24 min read

Self-Host WhoDB with Docker and Localtonet HTTPS Access

Install and verify WhoDB with Docker, keep login sessions persistent, then access your database workspace over HTTPS with Localtonet.

Self-Hosting · WhoDB · Docker · Localtonet · 2026

Run a persistent database workspace locally, then give it controlled HTTPS access

WhoDB provides a browser-based workspace for connecting to databases, inspecting data, and working with database structures. In this guide, we install WhoDB with Docker Compose, preserve encrypted login sessions, and verify database connectivity from inside Docker. We bind the web interface to the host’s loopback address before connecting it to a Localtonet HTTP tunnel. You will also learn how to choose a reproducible image version, handle secure cookies, verify the remote path, and maintain the deployment.

🔒 Loopback-only host publication 🌐 Public HTTPS through an HTTP tunnel ⚡ Persistent sessions and practical verification

How the WhoDB and Localtonet architecture works

The deployment has three separate network paths. A browser reaches WhoDB through the tunnel’s public HTTPS address. The Localtonet client forwards requests to WhoDB’s published HTTP port on the Docker host. WhoDB then connects to databases from inside its container. A working browser interface does not prove that the database path works, and a healthy database does not prove that the tunnel is running.

Remote browser traffic reaches Docker-hosted WhoDB through Localtonet, while WhoDB connects separately to a database.
For the same-host workflow, our client forwards requests to 127.0.0.1:8080 on the Docker host. Database connectivity remains a separate path.

WhoDB’s default internal HTTP listener is port 8080. This guide publishes it using 127.0.0.1:8080:8080, making the host-side endpoint http://127.0.0.1:8080. Our client runs directly on that same host and targets 127.0.0.1, port 8080. A client running in a separate container has its own loopback namespace and is not the same arrangement.

The Localtonet client establishes an outbound connection to a relay server. Our platform provides the public address without requiring inbound router port forwarding, a public IP address, inbound firewall changes, or VPN setup. That does not change Docker’s own publication behavior: a mapping such as 8080:8080 normally publishes on all host interfaces and can expose WhoDB to reachable networks independently of the tunnel.

Use a current Docker release and review Docker’s port-publishing documentation for platform-specific behavior. Loopback publication reduces direct network exposure; it is not application authorization or isolation from other software and users on the host.

🐳 Application layer The published clidey/whodb image runs the interface and backend, with an internal HTTP listener on port 8080 by default.
💾 Persistent session layer A volume at /data retains the encrypted session database. A stable encryption key lets replacement containers decrypt it.
🗄️ Database network layer Database names and addresses must resolve and route from inside the WhoDB container, not just from the host.
🌐 Remote-access layer The HTTPS address works while the selected Localtonet device is connected and the HTTP tunnel is running.
A public database administration interface is sensitive

HTTPS protects the browser connection in transit. It does not decide who may use WhoDB, authorize database operations, or make a public URL private. Do not rely on an obscure address as an access control. Before publication, establish an authentication and access-control policy appropriate to your deployment, use least-privilege database accounts, and avoid exposing managed profiles that grant unintended access. If you cannot meet that policy, keep the interface private rather than starting a public tunnel.

Prepare the host and choose the publication address

This tutorial covers the published Docker image, not a source build or desktop installation. WhoDB also supports a standalone binary, desktop application, and source checkout, as described in its official installation guide. Docker Compose is useful here because it records the image, port binding, environment, volume, and restart policy together.

  • Install Docker and the Docker Compose plugin for your operating system.
  • Have permission to manage containers, images, volumes, and deployment files.
  • Choose an unused host port, normally 8080.
  • Have a reachable database and a dedicated, appropriately limited database account.
  • Have OpenSSL available for generating the session-encryption key.
  • Install the Localtonet client directly on the Docker host for the recommended workflow.
  • Keep your device-specific Localtonet authentication token private and separate from WhoDB configuration.
docker --version
docker compose version
openssl version

If Docker or Compose is unavailable, complete the supported installation for your host first. Docker’s Compose documentation explains installation and the Compose file model. The shell examples below use a POSIX-style terminal; adapt line continuations for another shell, or enter commands on one line.

Host ports and container ports are different

In 127.0.0.1:8080:8080, the first value is the host binding address, the second is the host port, and the third is the container port. To avoid an occupied host port, change only the middle value. Changing WhoDB’s PORT variable instead changes the application’s internal listener and requires corresponding mapping and health-check changes.

ConfigurationHost URL and tunnel targetPurpose
127.0.0.1:8080:8080http://127.0.0.1:8080Recommended same-host workflow.
127.0.0.1:3000:8080http://127.0.0.1:3000Alternative host port; internal listener remains 8080.
PORT=3000 with 127.0.0.1:3000:3000http://127.0.0.1:3000Intentional change to the internal listener as well.

When the Localtonet client runs on another device

A second device cannot reach the Docker host’s loopback binding. That layout requires deliberately publishing WhoDB on a host address reachable from the client, then targeting that address and host port in Localtonet. Prefer a specific LAN interface rather than all interfaces, and restrict access according to your local network and firewall policy. Verify reachability from the actual client device before creating the tunnel.

This is a separate local-network decision, not a requirement to open an internet-facing router port for Localtonet. If you do not need cross-device connectivity, retain the loopback binding. Also remember that stopping the tunnel does not disable any LAN access you deliberately enabled.

Choose a reproducible WhoDB image

clidey/whodb:latest is convenient for a disposable evaluation, but it is a moving tag. A later pull can retrieve different software even when the Compose file has not changed. For controlled deployments, review a release and select its versioned image rather than relying on latest.

The official WhoDB 0.138.0 release lists clidey/whodb:0.138.0 and is marked as an immutable GitHub release. We use that evidenced version in the persistent examples below as a reproducibility example, not as a promise that it is the newest or appropriate release for every deployment. Check current release notes and security fixes before selecting your version.

An immutable GitHub release and an immutable container reference are not identical guarantees. Registry tags can be reassigned unless the registry enforces immutability. For strict reproducibility, pull your reviewed version, record its repository digest, and use the verified clidey/whodb@sha256:... reference in Compose. Do not paste the ellipsis literally.

docker pull clidey/whodb:0.138.0
docker image inspect clidey/whodb:0.138.0 --format '{{json .RepoDigests}}'

Pinning makes changes intentional; it does not install security updates automatically. Keep an explicit review, backup, update, and verification process. Preserve the previous image reference so you know which software was deployed before a change.

Run a quick local WhoDB container

For a temporary smoke test, the following command adapts WhoDB’s official Docker integration to a loopback-only binding. The moving latest tag is intentional for this disposable test. Do not use sensitive database credentials just to prove the page loads.

docker run -d \
  --name whodb \
  -p 127.0.0.1:8080:8080 \
  clidey/whodb:latest

docker ps --filter name=whodb
docker logs whodb

Open http://127.0.0.1:8080 on the Docker host. If the page does not load, inspect the container state and logs before adding a tunnel. Follow new output with docker logs -f whodb; interrupting the log viewer does not stop the container.

This quick test is not a persistent installation

A plain container can generate an encryption key and store sessions in its writable filesystem. Removing and replacing it loses that container-local state. Use the volume and stable key below for session continuity across recreation.

Before moving to Compose, remove the disposable container to release its name and port. This command deletes that container’s nonpersistent state:

docker rm -f whodb

Install WhoDB with persistent encrypted sessions

Original and replacement WhoDB containers share persistent session data and a stable encryption key.
Session continuity requires both the stored session data and the key that can decrypt it.

WhoDB stores login sessions server-side. Database credentials are encrypted with AES-256-GCM in a local SQLite file under its data directory. The browser receives an opaque HttpOnly session cookie rather than the credentials themselves. Persisting /data and setting a stable WHODB_ENCRYPTION_KEY keeps these encrypted sessions usable after container replacement, subject to normal expiration.

Generate and protect the encryption key

mkdir whodb-deployment
cd whodb-deployment
openssl rand -hex 32

The OpenSSL command produces 32 random bytes represented as 64 hexadecimal characters. Generate this value once, store it securely, and replace the placeholder in the configuration below. Do not commit the real key to source control or include it in support output.

Protect both the key and the session volume

Changing or losing the key makes existing encrypted sessions unreadable, requiring users to sign in again. Anyone who obtains both the key and session data may gain access to stored credentials. Encryption is not a substitute for protecting the host, Docker access, deployment files, and backups.

Create docker-compose.yml

services:
  whodb:
    image: clidey/whodb:0.138.0
    container_name: whodb
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      PORT: "8080"
      WHODB_LOG_LEVEL: info
      WHODB_ENCRYPTION_KEY: replace_with_your_64_character_hex_key
    restart: unless-stopped
    volumes:
      - whodb-data:/data

volumes:
  whodb-data:

Replace the key placeholder before startup. A value written in Compose is visible to people who can read the file, and container environment values are accessible to users with sufficient Docker permissions. Limit access using your operating system’s permissions and secret-management practices. Moving a secret into an environment file keeps it out of the main YAML but does not, by itself, make it inaccessible.

docker compose up -d
docker compose ps
docker compose logs whodb

Open http://127.0.0.1:8080. Leave WHODB_SECURE unset during this plain-HTTP test. We enable secure cookies before authenticated use through the HTTPS tunnel.

Session lifetime and optional environment settings

The default WHODB_SESSION_TTL is 168h, or seven days, using a sliding idle timeout. Persistence protects sessions from container replacement; it does not bypass expiration. Choose a session duration that fits your access policy rather than increasing it simply to avoid reauthentication.

VariableDocumented behaviorPractical guidance
WHODB_LOG_LEVELdebug, info, warn, error, or none; default info.Use verbose logging temporarily for diagnosis.
WHODB_LOG_FORMATjson enables JSON logs; default is text.Useful for log-processing systems.
WHODB_SESSION_TTLSliding idle timeout expressed as a Go duration.Default is 168h.
WHODB_SECUREtrue marks the session cookie Secure.Enable for HTTPS browser access, not plain-HTTP testing.
WHODB_ALLOWED_ORIGINSComma-separated CORS allowlist.CORS is not authentication or a general access-control boundary.
WHODB_MAX_PAGE_SIZEMaximum rows per page request; default 10000.Consider the amount of data each request may return.
WHODB_DISABLE_CREDENTIAL_FORMHides manual credentials and requires managed profiles or providers.Configure and test the managed login path first. Hiding a form alone is not authorization.

Connect WhoDB to databases from inside Docker

WhoDB connects to another container by service name or to a host database by a host-reachable address.
Inside WhoDB’s container, localhost refers to that container, not the Docker host or a sibling database container.

Choose the database hostname according to the database’s location. For a sibling service on the same Compose network, use its service name, such as postgres, and its internal database port. For a remote server, use a hostname or address routable from the container. Only a database inside the WhoDB container itself would normally be reached through that container’s localhost.

Connecting to a database on the Docker host

Docker Desktop commonly provides host.docker.internal for reaching the host. Do not assume that name exists in every Docker Engine environment. On compatible Docker Engine installations, particularly Linux hosts, add this fragment under the existing whodb service to map the name to Docker’s host gateway:

extra_hosts:
  - "host.docker.internal:host-gateway"

Recreate the service with docker compose up -d after changing it. The special host-gateway value requires a supporting Docker Engine version. Rootless, remote-daemon, and customized network configurations may need a different reachable host address; verify the network route rather than copying a fixed bridge IP.

Name resolution is only the first requirement. A host database bound solely to host loopback may not accept traffic arriving through a bridge gateway. Configure the database listener, database client-access policy, and host firewall deliberately for the container source. Do not solve a connection failure by exposing the database indiscriminately. Prefer a shared private Compose network when both applications can run as containers.

Disposable PostgreSQL networking demonstration

The following fragment is an optional addition to the services section of the existing Compose file. It demonstrates service-name networking only. It does not replace the persistent WhoDB configuration:

  postgres:
    image: postgres:16
    environment:
      POSTGRES_USER: whodb_demo
      POSTGRES_PASSWORD: replace_with_a_unique_demo_password
      POSTGRES_DB: whodb_demo
Use only disposable test data in this PostgreSQL example

This demonstration has no explicitly managed database data volume or backup workflow. Do not rely on its database state surviving replacement. The official PostgreSQL image initializes POSTGRES_USER as a privileged account, not a least-privilege application user. Use it only to demonstrate connectivity with synthetic data. For a real database, configure persistent storage, backups, and a separate restricted account before connecting WhoDB.

Replace the password placeholder, then start and inspect PostgreSQL:

docker compose up -d postgres
docker compose logs postgres
docker compose exec postgres pg_isready -U whodb_demo -d whodb_demo

In WhoDB, choose PostgreSQL and enter host postgres, port 5432, database whodb_demo, user whodb_demo, and the password you set. No PostgreSQL host port needs publishing because both services share the Compose network. A readiness check confirms that the server is accepting connections; a successful WhoDB login separately verifies the credentials and network path.

You may add depends_on: [postgres] to WhoDB for startup ordering, but basic depends_on does not prove database readiness. PostgreSQL may still be initializing when WhoDB starts. Inspect readiness and retry the connection, or use an appropriate database health check and Compose health-based dependency condition when designing automated startup.

For actual work, grant only the schemas, tables, and operations needed by the operator. Read-only inspection should not require a database superuser. WhoDB’s effective database capabilities depend on the permissions of the account used to connect.

Verify the application, database, and session persistence

Complete local verification before creating a tunnel. A tunnel cannot repair an exited container, incorrect Docker mapping, or unreachable database.

  1. Run docker compose ps and confirm WhoDB is not repeatedly exiting or restarting.
  2. Check the host-side health endpoint and expect the plain-text body ok.
  3. Open the browser interface at http://127.0.0.1:8080.
  4. Connect with the intended database account and verify only authorized operations.
  5. Recreate WhoDB, keeping its volume and key, then test the existing browser session.
curl --fail --show-error http://127.0.0.1:8080/health
docker compose up -d --force-recreate whodb

Revisit the same browser origin after recreation. A session on 127.0.0.1 is not the same browser cookie context as a later public hostname. Normal idle expiration can also require reauthentication. Do not run docker compose down -v for this test: -v removes the named volume needed for continuity.

Add an internal Docker health check

Add this fragment under the existing whodb service:

healthcheck:
  test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8080/health | grep -qx ok"]
  interval: 30s
  timeout: 5s
  retries: 3
  start_period: 20s

Apply it with docker compose up -d. This follows the documented WhoDB health-check approach and executes inside the container. It therefore uses the internal listener port, even if the host port is 3000. Verify that the selected image includes the commands used by the probe.

An internal health check does not test the host publication, a database query, or the tunnel. An unhealthy status also does not by itself make the Docker restart policy restart a running process. Continue testing each layer separately.

Add Localtonet HTTPS access

Once the local service works, use an HTTP tunnel for WhoDB’s browser-based interface. For this same-host deployment, the local target is 127.0.0.1 and port 8080. If you selected host port 3000, use port 3000 in the tunnel, not the container’s internal 8080.

Prepare secure cookies before remote login

WhoDB does not infer the original HTTPS scheme from proxy headers. Add WHODB_SECURE: "true" under its existing environment mapping before using the public HTTPS address for authenticated access:

environment:
  PORT: "8080"
  WHODB_LOG_LEVEL: info
  WHODB_ENCRYPTION_KEY: replace_with_your_64_character_hex_key
  WHODB_SECURE: "true"

Retain your actual existing key; do not generate a new one for this change. Keep the reviewed image, loopback port binding, volume, and other settings unchanged.

docker compose up -d
curl --fail --show-error http://127.0.0.1:8080/health

The health endpoint remains usable over local HTTP because it does not require an authenticated browser session. Secure cookies are intended for HTTPS; do not rely on local HTTP login behavior after enabling this setting.

Create and start the HTTP tunnel

Use the current Localtonet HTTP tunnel documentation alongside the workflow below. Client installation details vary by operating system and version; obtain the current installer and device token through our official product pages rather than using an invented CLI command.

1

Install and run our client

Run the Localtonet client directly on the Docker host so it can reach the loopback-published WhoDB service.

2

Authenticate the device

Use its device-specific authentication token. Keep that token out of Compose files, screenshots, repositories, and shared logs.

3

Select an available relay server

Choose a currently available server or region from the dashboard. Do not copy an assumed server code from another deployment.

4

Configure an HTTP tunnel

Set the local IP to 127.0.0.1 and port to 8080, or your selected host port. Choose the appropriate Process Type: Random Sub Domain, Custom Sub Domain, or Custom Domain, according to current availability.

5

Start the tunnel

Use Start. Creating or saving a configuration does not make it run. Both the selected client connection and the tunnel must be active.

6

Verify the public HTTPS address

Open the assigned address and test the intended login and permitted database operations. Stop or delete the tunnel when remote access is no longer needed.

Custom-domain DNS requirements must be checked against current documentation before changing records. Options and availability can vary by plan or deployment. This HTTP workflow exposes WhoDB, not a raw database port, and is not a VPN.

Verify the complete remote path

Test from a different device or network when possible. Confirm the URL uses HTTPS, the interface renders, login persists after refresh, and the account cannot perform operations outside its intended permissions. You will normally sign in again on the public hostname because its browser cookie context differs from the local address.

Inspect browser cookie and network diagnostics without copying cookie values into support tickets. Test the access restrictions you actually configured, including rejection of unauthorized users where applicable. Successful access by an authorized user alone does not prove that restrictions are effective.

Finally, stop the tunnel and confirm the public path becomes unavailable while the local health check still succeeds. This verifies that you can withdraw remote access independently. It does not revoke existing credentials or disable other network paths you may have published.

Operate, update, back up, and troubleshoot WhoDB

Routine operation

docker compose ps
docker compose logs -f whodb
docker compose restart whodb
docker compose stop whodb
docker compose start whodb

A restart retains the container’s current configuration. After changing environment variables, image references, or port mappings, use docker compose up -d to apply the configuration through recreation where needed. The unless-stopped restart policy does not manage the Localtonet client or tunnel. Verify both layers after reboot, and account for host sleep or network loss.

An explicit update process

  1. Review the intended WhoDB release, compatibility notes, and security fixes.
  2. Record the current image reference and back up the session data, key, and deployment configuration.
  3. Change the Compose image to the newly reviewed version or verified digest.
  4. Pull and recreate WhoDB, preferably during a maintenance window.
  5. Repeat local health, browser, database, session-persistence, and remote-path checks.
docker compose pull whodb
docker compose up -d whodb
curl --fail --show-error http://127.0.0.1:8080/health
docker compose logs whodb

With a pinned image, pulling does not select a newer version automatically. With latest, pulling can change what the tag resolves to. Neither choice updates a running container merely because a release exists. Keep a rollback plan, but do not assume an older image can safely read data modified by a newer version; review migration behavior and retain a restorable backup.

Backups and logs

Back up the /data volume and stable encryption key through protected processes. Use a consistent volume snapshot or stop WhoDB during a filesystem backup of its SQLite data. Preserve the deployment configuration and image reference, and test restoration in an isolated environment before depending on it. Compose project naming can affect which named volume is selected, so preserve or deliberately map the correct volume when moving the deployment.

The WhoDB session volume is not a backup of connected databases. Each database needs its own persistence, backup, recovery, and access policy. Avoid casually running docker compose down -v or volume-pruning commands against a deployment you intend to retain.

Standard logs are available through Docker. WhoDB also supports WHODB_LOG_FILE, WHODB_ACCESS_LOG_FILE, and WHODB_AUDIT_LOG_FILE. Setting them to default uses files under /var/log/whodb/; the audit log is append-only NDJSON for audited actions such as logins, reads, and changes. Mount an appropriate path if file logs must survive recreation, and plan permissions and retention.

Inspect logs before sharing them. Hostnames, database names, usernames, query content, and other operational data may be sensitive. Do not expose encryption keys, device tokens, database passwords, or session cookies during troubleshooting.

Port conflicts and binding mistakes

If WhoDB cannot start, inspect logs for an occupied port, invalid YAML, an invalid key, or a conflicting container named whodb from the quick test. To change only the host port, use:

ports:
  - "127.0.0.1:3000:8080"

Then use http://127.0.0.1:3000, http://127.0.0.1:3000/health, and tunnel target port 3000. The internal Docker health probe still uses 8080. Inspect the published mapping in docker compose ps; a displayed all-interface binding is not the intended same-host configuration.

Database and hostname failures

If the page works but database login fails, check the hostname from the container’s perspective, the database listener and port, credentials, permissions, and network policy. If host.docker.internal does not resolve, review platform support and the extra_hosts mapping. If it resolves but the connection fails, investigate the route and database listener rather than repeatedly changing passwords. A newly started PostgreSQL container may simply not be ready yet.

Session resets and login loops

If sessions disappear after recreation, confirm that the same volume is mounted at /data and the encryption key has not changed. Check expiration and whether you switched browser hostnames. If the key is lost, old sessions cannot be decrypted and users must sign in again. If login fails after enabling secure cookies, verify that authenticated access uses HTTPS and that the changed environment was applied with Compose.

Public-path failures

If local access works but public access does not, check the Localtonet device connection, tunnel running state, target address, and host port. A client on another device cannot use this host’s loopback endpoint. Either move the client to the Docker host or intentionally configure a restricted, reachable LAN publication. A sleeping device, stopped client, or stopped tunnel interrupts public availability even if WhoDB is configured correctly.

SymptomFirst checkLikely area
Local and public URLs both failContainer state, logs, host health requestApplication listener or Docker publication
Internal health succeeds, host request failsPublished address and host portPort mapping or wrong network namespace
Local works, public failsClient, tunnel, target IP and portTunnel lifecycle or target reachability
Page works, database failsDatabase hostname, readiness, and accountDatabase network path or permissions
Sessions reset after recreationVolume, key, hostname, idle lifetimePersistence or cookie context
Public HTTPS login loopsApplied secure-cookie setting and browser diagnosticsCookie policy or session configuration

Frequently asked questions

Why use 127.0.0.1:8080:8080 instead of 8080:8080?

The explicit loopback binding limits the host-published interface to local access in the recommended same-host layout. A mapping without a host address normally publishes on all interfaces, potentially making WhoDB reachable independently of Localtonet.

Does Localtonet require router port forwarding or firewall changes?

Our client establishes an outbound relay connection, so the tunnel does not require inbound router port forwarding or inbound firewall changes. Docker publication is separate. A client on another device needs deliberately permitted local-network access to the WhoDB host.

Why do persistent sessions need a volume and a stable key?

The volume retains encrypted session data under /data. The stable WHODB_ENCRYPTION_KEY lets replacement containers decrypt it. Losing either prevents existing sessions from continuing normally, and persistence does not override session expiration.

When should WHODB_SECURE be enabled?

Leave it unset for initial plain-HTTP testing. Set it to true before authenticated use through the public HTTPS address, then recreate the service and verify login. The local health endpoint can still be checked over HTTP.

Does host.docker.internal work everywhere?

No. Docker Desktop commonly supplies it, while compatible Docker Engine environments may need an explicit host-gateway mapping. Name resolution alone does not ensure that a host database listens on an address reachable from the container.

Does the tunnel expose PostgreSQL or other database ports?

Not in this workflow. The HTTP tunnel targets WhoDB’s web interface. WhoDB reaches databases through its own network path. That interface still provides sensitive database capabilities, so not publishing a raw database port does not remove the need for authorization.

Will everything return automatically after reboot?

WhoDB uses restart: unless-stopped, but Docker must be running. Remote access separately requires the Localtonet client to reconnect and the tunnel to be running. Verify the application, database, and tunnel after reboot.

Can I stop public access without stopping WhoDB?

Yes. Stop the Localtonet tunnel while leaving WhoDB running locally. Any separately configured LAN publication remains independent, so retain the loopback-only binding unless another device genuinely needs direct access.

Give your verified WhoDB deployment HTTPS access

Start with a healthy loopback-bound container, protected session storage, and least-privilege database credentials. Then use a Localtonet HTTP tunnel for the remote-access window you actually need, without configuring inbound router port forwarding.

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 hero the first component and keep the guide navigation immediately after it; move the opening architecture figure into the architecture section; replace all em dashes; change the recommended same-host Docker publication to a loopback-only binding and update local URLs, health checks, Compose examples, Localtonet targets, troubleshooting, and port-alternative examples consistently; explain that a client on another device requires a deliberately reachable host address and approp

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