25 min read

Install wger and Access It Remotely with Localtonet

Install and verify the self-hosted wger fitness tracker with Docker Compose, then provide remote web access through a Localtonet HTTP tunnel.

A self-hosted wger server connected to a remote phone through an HTTP tunnel.
wger runs on a local Docker host while Localtonet carries remote browser traffic to it.
Self-Hosting ยท wger ยท Localtonet ยท 2026

Run your own fitness platform locally, verify the deployment, and publish it through a controlled HTTP tunnel

wger is a free and open-source workout, nutrition, body-weight, and fitness tracking application that supports self-hosting with Docker Compose. This guide explains the documented deployment path, the configuration details you must confirm in the official Compose bundle, local verification, routine container operations, version 2.6 upgrade considerations, and practical troubleshooting. After the local application works, we show how to connect its verified HTTP endpoint to Localtonet for remote browser or mobile access without inbound router port forwarding, firewall changes, a public IP address, or VPN setup.

๐Ÿ”’ Keep the deployment private until authentication is ready ๐ŸŒ Publish the verified web endpoint through an HTTP tunnel โšก Separate application installation from remote-access setup

What you are installing

wger is a self-hosted fitness manager for people who want control over their workout and nutrition data. Its application code is licensed under AGPL-3.0-or-later. Exercise and ingredient data use Creative Commons licenses that can vary by entry, while the documentation is licensed under CC-BY-SA-4.0.

The platform covers more than a simple exercise list. It supports custom workout routines, automatic weight progression rules, diet plans, calorie logging, body-weight records, custom measurements, progress photos, an exercise wiki, multiple users, and basic gym-management functionality. Nutrition features can use food information from Open Food Facts. wger also provides a REST API for integrations and automation.

Cross-platform applications are available for Android, iOS, F-Droid, and Flathub. A self-hosted server can therefore act as the backend used from a browser or compatible application. Remote access should be treated as a separate stage, however. First build a healthy local wger deployment. Only then should you expose its web endpoint.

๐Ÿ‹๏ธ Workout planning Create flexible routines and use progression rules while recording workout sessions and logs.
๐Ÿฝ๏ธ Nutrition management Build diet plans, record calories, and work with ingredient information, including data from Open Food Facts.
๐Ÿ“Š Body tracking Record body weight, custom measurements, and other information used to follow fitness progress.
๐Ÿ“ธ Progress gallery Upload photos and maintain a visual record of progress alongside workout and measurement data.
๐Ÿ”— REST API Integrate other applications and automations with the server while respecting wger authentication and API changes.
๐Ÿณ Docker deployment The official project recommends Docker Compose as the straightforward self-hosting path.

How the deployment and tunnel fit together

The complete workflow has two independent layers. Docker Compose runs wger and its supporting services on your machine. Localtonet then connects a public HTTPS address to the local HTTP listener exposed by that deployment. Localtonet does not install, configure, repair, or replace the wger containers.

Keeping those layers separate makes diagnosis much easier. If the application does not load locally, fix the Compose deployment before creating a tunnel. If it works locally but not through the public address, investigate the tunnel target, tunnel state, authentication, and public URL.

Important evidence limitation

The verified wger project information confirms the Docker Compose installation method and the command used to start it, but it does not establish a universal local hostname, published HTTP port, Compose file path, or initial credential. Those values must be read from the current official wger Docker bundle and your deployed configuration. This guide does not invent fixed values that may be wrong for your release.

Prerequisites and deployment decisions

Choose a machine that can stay online whenever you need wger. A desktop can work for occasional personal use, while an always-on server is more convenient for regular browser or mobile access. The machine must have sufficient storage for the container images, database, uploaded content, and backups. Exact CPU, memory, and storage requirements are not established by the supplied project evidence, so size the host according to your users, data volume, and the requirements documented with the current Docker bundle.

Install Docker with the Compose plugin using the supported procedure for the host operating system. Verify that your account is permitted to operate Docker. The official wger self-hosting path relies on the modern docker compose command form.

Obtain the current official Docker Compose bundle through the Docker deployment link in the wger project README. The application repository points readers to a dedicated Compose file and corresponding documentation. Use that maintained bundle rather than assembling an unrelated container stack from memory, because releases can introduce new services, settings, and proxy configuration.

Requirement Why it matters What to confirm
Docker Engine Runs the wger application and supporting containers Docker is installed, running, and available to the deployment account
Docker Compose plugin Creates and coordinates the multi-container deployment The host accepts the docker compose command form
Official wger Docker bundle Defines the services and current release configuration You obtained it through the project-maintained Docker deployment link
Persistent storage Protects database and uploaded data from container replacement The current Compose bundle defines the required volumes or bind mounts
Local HTTP listener Provides the endpoint used for browser verification and tunneling You know the actual host address and published port after deployment
Localtonet client Creates the outbound connection to our relay platform It runs on the wger host or another device that can reach the HTTP listener

Review configuration before startup

Do not start a production-facing deployment without reading the environment and Compose files included in the current bundle. Identify the database settings, generated secrets or cryptographic key requirements, persistent storage definitions, web-facing service, proxy configuration, site URL, and published host port. Replace documented example passwords and secrets according to the project instructions.

Keep environment files and database credentials out of public repositories, screenshots, support messages, and tunnel descriptions. The same rule applies to Localtonet device authentication tokens. A device token identifies the client that can run the tunnel and must not be copied into an article, public issue, shell transcript, or shared configuration.

If your host already runs another web server, check whether the port selected by the Compose bundle conflicts with an existing listener. Do not solve a conflict by guessing a different internal container port. Change only the documented host-side mapping or proxy setting, then record the final host address and published port for local verification.

Install and start wger with Docker Compose

Four stages of deploying wger with Docker Compose and persistent storage.
Docker Compose creates the wger services, attaches persistent data, and starts the local web application.

The wger project describes self-hosting as essentially a Docker Compose startup. In practice, the short command works only after you have downloaded the maintained deployment files and completed their documented configuration. Treat preparation and startup as separate actions.

1

Install Docker and Docker Compose

Install Docker Engine and its Compose plugin through the supported method for your operating system. Confirm that Docker is running and that your deployment account has the required permission to manage containers.

2

Obtain the official wger Docker deployment

Open the wger project README and follow its maintained Docker Compose link. Work from that deployment bundle so the Compose definition, environment template, proxy configuration, and supporting services match the current wger release.

3

Review and complete the supplied configuration

Follow the instructions distributed with the bundle. Set every required value, replace documented examples, protect secrets, confirm persistent storage, and identify the web service's published host address and port. Do not assume a port that is not present in your configuration.

4

Start the deployment

From the directory containing the active Compose definition, run the official startup command shown below. The detached option allows the services to continue running after the command returns.

5

Wait for initialization and inspect service health

A first startup may need time to create storage, initialize the database, and bring dependent services online. Use Docker's status and log facilities to inspect the actual services named in your Compose file. Resolve failed or repeatedly restarting services before proceeding.

6

Open the configured local address

Use the host address and published HTTP port from your Compose configuration. Complete any first-run account workflow presented by the deployed version, then sign in and test the functions you intend to use.

docker compose up -d

Run this command in the directory associated with the official Compose deployment. It is not a download command and does not create missing environment files for you. If Docker reports that it cannot find a Compose configuration, confirm that you are in the correct deployment directory and that the official bundle was downloaded completely.

Do not publish the service yet

Keep wger accessible only from the local machine or trusted network while you verify initialization, account access, persistent storage, and authentication. A public tunnel cannot correct an unhealthy container, an incomplete migration, or a misconfigured application URL.

Do not invent an endpoint from an online example

The address used by another installation may not match yours. Docker can publish a container port to a different host port, bind it to a specific interface, or place an HTTP proxy in front of the application. Read the active Compose configuration and runtime state. The value needed later is the address that successfully serves wger from the perspective of the device running the Localtonet client.

If our client runs directly on the Docker host, a loopback or host-bound address may be appropriate when it is confirmed by your configuration. If our client runs on another device, the listener must be reachable from that device over the local network. In that case, test from the client device itself rather than assuming that a browser test performed only on the Docker host proves network reachability.

Verify wger before enabling remote access

Docker Compose services running beside a locally loaded wger page.
Confirm that the containers are running and wger loads locally before creating a tunnel.

Local verification should prove more than the presence of a login page. It should show that the web application, database, account system, and persistent storage work together. This prevents an application problem from being mistaken for a tunnel problem.

Confirm the web interface

Open the configured local URL in a browser. A successful response should render the wger interface rather than a generic proxy error, an unrelated site, or an endless redirect. If the deployment uses a local reverse proxy, confirm that the browser reaches that proxy on its published port.

Sign in with an account created through the supported first-run or administrative procedure for your deployed version. No universal default username or password is established by the supplied project evidence. Do not try common default credentials or publish any credentials you create.

Exercise a complete data path

Create a small test record, such as a routine, measurement, or other non-sensitive entry available to your account. Reload the page and verify that the record remains. This tests a database-backed operation rather than only static page delivery.

If you plan to use nutrition tracking, progress photos, multiple users, or API automation, test those specific functions locally before remote exposure. Uploaded content may use a different storage path than database records, so a successful routine entry does not prove that gallery uploads are persistent.

Test restart persistence

Restart the deployment using the normal Docker Compose lifecycle appropriate to your environment, then sign in again and verify that the test data remains. Persistent information must live in the volumes or mounts defined by the maintained deployment rather than only inside disposable container layers.

If data disappears after containers are recreated, stop and correct the storage configuration. A tunnel would only make the faulty deployment reachable from more places.

๐ŸŒ HTTP response The configured local address loads the actual wger interface without a proxy or redirect failure.
๐Ÿ” Account access Registration or administrative account creation follows the current deployment instructions, and sign-in succeeds.
๐Ÿ’พ Database writes A test record can be created, reloaded, and retrieved after the relevant services restart.
๐Ÿ“ Uploaded content If you use the gallery, an upload survives the same lifecycle expected during upgrades and maintenance.

Routine operation, backups, and wger 2.6 upgrades

Container deployment simplifies startup, but it does not remove operational responsibilities. Keep the official Compose bundle, environment configuration, persistent data, and recovery process under controlled administration. Back up the persistent database and uploaded files using methods compatible with the services defined in the current deployment.

A useful backup is one that can be restored. Periodically test restoration in an isolated environment rather than assuming that copied files are complete or consistent. Do not expose a restored test instance publicly until its accounts, URLs, and credentials have been reviewed.

Understand the difference between a fresh installation and an upgrade

The wger 2.6 release introduced breaking changes and specifically instructed Docker users to pull the latest changes from the Docker repository. The release added a new powersync service, related proxy configuration, and new settings in prod.env. Updating only an application image while retaining an older Compose definition can therefore omit required services and configuration.

Existing Docker installations upgrading to 2.6 are instructed to create the dedicated PowerSync database user and schema by running the following command against the web service:

docker compose exec web ./manage.py setup-powersync-storage

The release also replaced SIGNING_KEY with JWT_PRIVATE_KEY and JWT_PUBLIC_KEY. It provides this command to generate the new key pair:

docker compose exec web ./manage.py generate-jwt-keys

The version 2.6 instructions say to set SITE_URL to the server's URL. They also document PS_STORAGE_PG_URI for changing PowerSync storage defaults and PS_DATABASE_URI for the wger database connection when the default database password has been changed. PostgreSQL credentials are read from prod.env through POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB instead of being hardcoded in the Compose file.

Upgrade commands are not a complete upgrade plan

The commands above are verified release 2.6 requirements, but they do not replace the full release notes and the current Docker deployment instructions. Back up the installation, obtain the updated Docker repository configuration, review every environment-file change, and follow all migration steps applicable to your data. Never paste literal placeholder database values into production.

API changes that can affect integrations

Version 2.6 changed IDs from integers to strings using UUIDs for several version 2 API resources, including measurements, nutrition plans, meals, nutrition diaries, workout sessions, and workout logs. Scripts that assume numeric IDs may fail even if the web interface appears healthy.

The release removed the older /api/v2/login/, /api/v2/register/, and /api/v2/token flows. The documented allauth login flow respects multi-factor authentication. Users who still need a permanent token are directed to the API key page in user settings. Do not disable two-factor authentication merely to preserve an obsolete integration.

JWT refresh tokens now rotate on use and can be blacklisted after rotation, making refresh tokens single-use under that configuration. Test API clients after an upgrade to ensure they store and use each newly returned token correctly. Keep API keys, refresh tokens, and private keys outside source control and tunnel configuration.

Access the working wger service with Localtonet

Remote browser traffic passing through a Localtonet HTTP tunnel to a local wger service.
The Localtonet agent forwards requests from its public endpoint to the local wger web service.

Once local verification is complete, an HTTP tunnel can make the web application reachable remotely. Our client establishes an outbound connection to a Localtonet relay server, so this workflow does not require inbound router port forwarding, firewall changes, a VPN, or a public IP address.

The HTTP tunnel points to a local IP address and port reachable from the selected client device. For wger, use the exact HTTP endpoint that passed your local test. Do not target a database port, an internal-only container address, or an assumed default.

HTTP tunnels can use a random subdomain, a custom subdomain, or a custom domain where the selected configuration supports it. These process types serve the same local content at a public HTTPS address. Custom-domain DNS details can change, so consult the current dashboard and documentation before changing DNS records.

1

Install and run the Localtonet client

Install our client on the wger host or on another device that can reach the verified local HTTP endpoint. Keep the client running for as long as remote access is required.

2

Authenticate or select the client device

Use the device-specific authentication token through the supported client and dashboard workflow. Never put the token in public documentation, screenshots, Compose files committed to source control, or a web page.

3

Select an available relay server

Choose from the server or region values currently available in your Localtonet dashboard. Availability can vary, so this guide does not hardcode a server code.

4

Create an HTTP tunnel

Configure the tunnel with the local IP address and published HTTP port that successfully served wger during verification. Select the appropriate HTTP process type for the public address you intend to use.

5

Start the tunnel

Creating a tunnel does not start it. Use the Start button, then wait until the selected client is connected and the tunnel is running.

6

Test the assigned public address

Open the assigned public HTTPS URL from a network outside the host's local environment. Confirm that the expected wger page loads, authentication works, and the application does not redirect to an incorrect internal address.

For the current dashboard workflow and available options, consult our Localtonet HTTP tunnel documentation. The public address remains available only while the selected client device is connected and the tunnel is running.

Creating and running are separate lifecycle states

A saved tunnel configuration is not automatically reachable. Start it explicitly after creation. You can later stop it to suspend public access without deleting the configuration, or delete it when it is no longer needed.

Choose the correct target from the client's perspective

Suppose the wger page opens on the Docker host but the Localtonet client runs on a different machine. A loopback address on the second machine refers to that second machine, not the Docker host. Configure the tunnel with an address and port that the client device can actually reach, and test that same endpoint from the client device before starting the tunnel.

Conversely, when the client runs on the Docker host, there is usually no reason to expose the container's HTTP port to an entire local network solely for tunneling. Use the narrowest documented host binding that still lets the client connect. The exact binding syntax and port remain properties of your active wger Docker configuration and should not be guessed.

Security checklist for a remotely accessible fitness tracker

Workout schedules, body measurements, nutrition logs, account details, and progress photos can be sensitive. Public reachability should therefore be paired with application authentication, least privilege, secure account recovery, current software, and tested backups.

Use wger authentication for every user

Do not treat an unguessable public URL as authentication. Require individual user accounts and avoid sharing an administrator login. Version 2.6 supports two-factor authentication using security codes or passkeys, as well as social login providers when those providers are configured correctly.

Test login, logout, account recovery, and two-factor authentication through the final public hostname. If a social provider is used, its registered redirect URLs must match the actual public site configuration. Exact provider-specific values are outside the verified evidence for this guide, so follow the current wger social-auth instructions rather than guessing callback paths.

Set the application URL consistently

wger 2.6 specifically calls for SITE_URL to contain the server URL. When the service is published through a Localtonet HTTPS address, review this setting as part of the deployment. An incorrect canonical URL can contribute to redirects toward a local hostname or an obsolete public address.

Do not change an application URL blindly on a working production system. Record the old value, understand how your deployment consumes the environment file, and test authentication and integrations after applying the supported change.

Minimize exposure

Publish only the HTTP endpoint required for wger. Do not create public tunnels for PostgreSQL, container administration sockets, internal cache services, PowerSync storage databases, or Docker management interfaces. Those components should remain on protected internal networks unless a separately reviewed architecture explicitly requires otherwise.

Stop the Localtonet tunnel when remote access is not needed. Because the tunnel depends on the selected client and its outbound relay connection, stopping the tunnel or disconnecting that client removes the public route. This does not stop wger itself, erase its data, or replace application logout.

Protect all credentials and keys

Never expose the Localtonet device token, wger API keys, database passwords, JWT private keys, refresh tokens, social-login secrets, or account credentials. Store them using the secure configuration method supported by your deployment and rotate any value that has been disclosed.

Troubleshooting wger and Localtonet

The Compose command cannot find the configuration

Confirm that you obtained the official wger Docker deployment and that your shell is in the directory associated with its active Compose file. The startup command does not download wger automatically. Also confirm that the Docker Compose plugin is installed and that you are using the command form supported by the project.

One or more containers repeatedly restart

Inspect the status and logs for the service names defined in your Compose file. Common categories include missing environment values, unavailable dependent services, database authentication failures, incomplete migrations, permissions on persistent storage, and port conflicts. The exact diagnosis must come from the current service logs rather than from guessed container names or ports.

If this started during a 2.6 upgrade, verify that you pulled the latest Docker repository changes instead of updating only an image. Confirm that the new PowerSync service, proxy configuration, environment settings, database user and schema, and JWT key changes were handled according to the release instructions.

wger works on the Docker host but not from the Localtonet client

Check where our client is running. If it is on another device, test the wger endpoint from that device. Confirm that the host-side HTTP listener is reachable on the selected local address and port. A service bound only to the Docker host's loopback interface cannot be reached from a separate local device.

Prefer moving our client onto the wger host when that simplifies the trust boundary, rather than broadly opening an internal listener without review. If the client must remain separate, use only the local network access required between the two devices.

The public URL does not respond

Verify that the Localtonet client is connected, the correct device token is selected, and the tunnel was explicitly started. Then recheck the tunnel's local IP address and port. A common category of error is creating a tunnel successfully but leaving it stopped.

Test the local target again from the client device. If that test fails, return to the wger or local-network configuration. If it succeeds, review the tunnel state and assigned public endpoint in the dashboard.

The public URL redirects to a private address

Review wger's configured site URL and any proxy configuration supplied with the official Docker bundle. For version 2.6, confirm that SITE_URL reflects the intended server URL. Also clear stale browser state or test in a private browsing session after correcting the configuration.

Login or API automation fails after upgrading to 2.6

Existing browser sessions may require a new login because of the authentication changes. API scripts must not continue using the removed version 2 login, registration, or token endpoints. Update integrations to the documented allauth flow or use a permanent token created from the API key page where appropriate.

Check whether scripts assume integer IDs for resources that now use string UUIDs. For JWT clients, support refresh-token rotation and save the newly returned token instead of repeatedly presenting an already consumed refresh token.

Data is missing after recreation or upgrade

Stop making changes until you understand where the database and uploaded files were stored. Review the volumes and bind mounts in the Compose deployment, then compare them with your backups. Avoid repeatedly recreating containers or initializing new storage against the same public URL, because that can make recovery and diagnosis more confusing.

Frequently asked questions

What is the official command to start a self-hosted wger deployment?

The wger project documents docker compose up -d as the basic startup command. Run it only after obtaining the official Docker deployment bundle, completing its current environment configuration, and entering the directory associated with the Compose definition.

Which local port does wger use?

The supplied verified evidence does not establish one universal host port. Read the published port and web service configuration from the current official wger Docker bundle and your active deployment. Use the endpoint that actually loads wger locally rather than assuming a value from another installation.

Does Localtonet install or host the wger containers?

No. Docker Compose runs wger on your machine. With Localtonet, our client creates an outbound connection that publishes the already working local HTTP service through a public address. The tunnel does not replace Docker, wger configuration, persistent storage, or backups.

Do I need router port forwarding or a public IP address?

No. The Localtonet client establishes an outbound connection to our relay platform, so the documented tunnel workflow does not require inbound router port forwarding, firewall changes, VPN setup, or a public IP address.

Will the wger public URL remain available if the Localtonet client stops?

No. The tunnel is available only while the selected client device is connected and the tunnel is running. Stopping the tunnel or disconnecting that client removes remote access, but it does not stop the local wger containers.

Can I tunnel the PostgreSQL port instead of the web application?

That is not the workflow in this guide and is not appropriate for normal wger browser access. Create an HTTP tunnel to the verified web endpoint. Keep PostgreSQL and other internal services private unless a separately reviewed administrative architecture explicitly requires remote database connectivity.

What must existing Docker users review before upgrading to wger 2.6?

They must review the full release instructions and update the Docker repository configuration, not only the application image. Version 2.6 adds PowerSync, changes database and environment configuration, replaces the older signing key with JWT private and public keys, requires a correct SITE_URL, and introduces API changes that can break existing scripts.

Can I use a custom domain for the wger tunnel?

HTTP tunnels can use a random subdomain, custom subdomain, or custom domain process type where supported. Check the current Localtonet dashboard and documentation for availability and exact DNS requirements instead of relying on hardcoded instructions.

Make your verified wger installation available remotely

After wger loads locally, its data persists, and account security is configured, install our client and create an HTTP tunnel to the exact local endpoint you tested.

Get Started Free โ†’

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