Files

Hass.io Add-ons: Wger

I maintain this and other Home Assistant add-ons in my free time: keeping up with upstream changes, HA changes, and testing on real hardware takes a lot of time (and some money). I use around 5-10 of my >110 addons so regularly I install test machines (and purchase some test services such as vpn) that I don't use myself to troubleshoot and improve the addons

If this add-on saves you time or makes your setup easier, I would be very grateful for your support!

Buy me a coffee Donate via PayPal

Addon informations

Version Ingress Arch

Codacy Badge GitHub Super-Linter Builder

Thanks to everyone having starred my repo! To star it click on the image below, then it will be on top right. Thanks!

Stargazers repo roster for @alexbelgium/hassio-addons

downloads evolution

About

wger Workout Manager is a free, open source web application that helps you manage your personal workouts, weight and diet plans and can also be used as a simple gym management utility. It offers a REST API as well, for easy integration with other projects and tools.

Configuration

Use the add-on env_vars option to pass extra environment variables (uppercase or lowercase names). See https://github.com/alexbelgium/hassio-addons/wiki/Add-Environment-variables-to-your-Addon-2 for details.

  • Start the addon. Wait a while and check the log for any errors. Initial start can take up to 15 minutes !
  • Open yourdomain.com:9927 (default host mapping for the add-on port 80/tcp, as indicated by the webui hint).
  • Default
    • Username: admin
    • Password: adminadmin

Options can be configured through two ways :

  • Addon options
"CONFIG_LOCATION": location of the config.yaml # Sets the location of the config.yaml (see below)
  • Config.yaml (advanced usage)

Additional variables can be set as ENV variables by adding them in the config.yaml in the location defined in your addon options according to this guide : https://github.com/alexbelgium/hassio-addons/wiki/Addons-feature:-add-env-variables

The complete list of ENV variables can be seen here : not available

Mobile app offline sync (PowerSync)

The official wger mobile app (2.0.3 and newer) syncs offline through a PowerSync service, which it expects to find at <SITE_URL>/ps/. The add-on ships that service and can run it alongside wger, off by default. Turn it on with the POWERSYNC_ENABLED option.

Switching to PostgreSQL, and switching back

PowerSync cannot replicate from SQLite, which is what this add-on uses by default, and wger's integration with it is built around PostgreSQL. Enabling PowerSync therefore means pointing wger at a PostgreSQL database — and the add-on moves your data across for you.

The first time you start it with PowerSync enabled, the add-on copies the contents of its SQLite database into the PostgreSQL one. Two things are guaranteed about that:

  • The SQLite database is never written to. It is copied first, and everything is read from the copy, so the original is left byte for byte as it was. Removing PS_DATABASE_URI again puts wger straight back onto it — remove it from everywhere you set it, both the env_vars option and the CONFIG_LOCATION file, since either one takes precedence over the SQLite default.
  • An import only ever happens into a PostgreSQL database with no user accounts. That is wger's own test for a database that was never set up, since its bootstrap creates the admin user as the very last step. So once your data is in PostgreSQL, turning PowerSync off and on again later imports nothing and leaves it alone. The test is that one and no more: a PostgreSQL database holding rows but no users at all — a half-built one, say — still counts as never set up and would be imported into.

What the import does not do is keep the two databases in step. After the switch, PostgreSQL is the live database and the SQLite file is a frozen copy of the moment you switched. If you go back to SQLite, anything you did in the meantime stays in PostgreSQL, and vice versa. You will also be logged out of the web interface once, because sessions are deliberately not carried over.

If the import cannot finish — the database is unreachable, or the copy or the load fails — the add-on refuses to start wger at all, with the reason in the log. That is deliberate: if it carried on, wger would set the empty PostgreSQL database up as a brand new instance, complete with its own admin user, and from then on the add-on would see a database that already holds data and would never import your SQLite rows again. Stopping instead keeps them importable.

So if the add-on will not start and the log says the import did not complete, fix the cause — most often the database connection or the privileges above — and start it again. To abandon the move entirely, remove PS_DATABASE_URI and the add-on goes back to the SQLite database as if nothing had happened.

What you need

  1. A PostgreSQL server the add-on can reach — the Postgres 17 add-on from this repository works. PowerSync reads the logical write-ahead log, so the server needs wal_level = logical, which is not the default. With the Postgres add-on, add

    wal_level = logical
    

    to the file its CONFIG_LOCATION option points at, then restart it. The add-on checks this on startup and tells you in the log if it is still replica.

  2. A database and a role for wger. PowerSync's bucket storage lives in a dedicated role and schema inside that same database, and the add-on creates them on every startup with upstream's idempotent manage.py setup-powersync-storage. The wger role therefore needs CREATEROLE, and CREATE on the database, for as long as PowerSync is enabled — not just for the first start:

    ALTER ROLE wger CREATEROLE;
    GRANT CREATE ON DATABASE wger TO wger;
    

    The same role — the one in PS_DATABASE_URI, not powersync_storage — also needs REPLICATION, which is how PowerSync reads the logical WAL:

    ALTER ROLE wger REPLICATION;
    

    On PostgreSQL 16 and later — which includes the Postgres 17 add-on — that is still not quite enough. Creating the schema runs CREATE SCHEMA ... AUTHORIZATION powersync_storage, and the documentation requires that you "must be able to SET ROLE to that role". A CREATEROLE user is only given ADMIN OPTION on the roles it creates, not SET, because createrole_self_grant defaults to empty. Grant it for the roles wger is about to create:

    ALTER ROLE wger SET createrole_self_grant = 'set, inherit';
    

    If the storage role already exists from an earlier attempt, grant it directly instead — this one has to be run by a role allowed to hand out that membership, normally the superuser:

    GRANT powersync_storage TO wger WITH ADMIN OPTION, SET TRUE;
    

    The PostgreSQL superuser has all of this already, which is why pointing at it works and is the quickest way to get going, but a role with just these grants is the better choice.

  3. The URL your phone uses to reach wger, in SITE_URL. The app is handed <SITE_URL>/ps/ as its sync endpoint, so a LAN-only address will not work from outside your network.

Add-on configuration

Set POWERSYNC_ENABLED to true and add the following through the add-on's env_vars option (the CONFIG_LOCATION config.yaml file documented above works for these too):

env_vars:
  - name: PS_DATABASE_URI
    value: postgres://wger:yourpassword@db21ed7f-postgres-latest:5432/wger
  - name: PS_STORAGE_PG_URI
    value: postgres://powersync_storage:anotherpassword@db21ed7f-postgres-latest:5432/wger
  - name: SITE_URL
    value: https://wger.yourdomain.com
  • PS_DATABASE_URI is wger's own database. Setting it takes precedence over the DJANGO_DB_* variables, so this single value both moves wger onto PostgreSQL and tells PowerSync what to replicate: in the shipped configuration they read the same URI, so they cannot be pointed at different databases by accident.
  • PS_STORAGE_PG_URI is PowerSync's bucket storage. Point it at the same database with a different role name and a password of your choosing; that is the role the add-on creates. It must be set, it has no useful default.
  • SITE_URL must be an absolute http:// or https:// URL with no path.

db21ed7f-postgres-latest is the internal hostname of this repository's Postgres 17 add-on, so it works without exposing port 5432. A LAN IP also works when PostgreSQL is running on an external server.

Use passwords made only of letters, digits and -._~. Characters such as @, :, /, ?, # or % break the URI, and percent-encoding them is no way out: wger decodes %40 back to @, but PowerSync passes it to PostgreSQL unchanged, so its connections fail to authenticate.

Set these through the env_vars option rather than the CONFIG_LOCATION file if the password contains a $ or a backtick. Both routes work, but the config.yaml route writes the value unquoted into the add-on's environment file, where the shell expands those characters and silently truncates the password — wger would get the mangled value too, not just PowerSync.

The two URIs contain passwords, and the add-on prints every variable it loads to its log at startup. The shared startup code masks values whose variable name looks like a secret, and these two names do not, so both PostgreSQL passwords appear in the add-on log in full — including when the value comes from !secret. Treat the add-on log as sensitive, and prefer a dedicated wger role with a password you are willing to see there over reusing credentials from elsewhere.

The add-on generates the RS256 JWT keypair the app and PowerSync need on first start and keeps it at /data/powersync/jwt.env, so app sessions survive restarts. If you would rather manage it yourself, generate one with python3 manage.py generate-jwt-keys and pass both JWT_PUBLIC_KEY and JWT_PRIVATE_KEY as env vars — both halves or neither.

Your PostgreSQL server also has to be a version PowerSync supports, and the sync rules shipped with the add-on come from the upstream wger project. If replication fails for a reason other than wal_level, the add-on log carries PowerSync's own error.

Checking it works

With everything in place the add-on log reports the PowerSync URL, and <SITE_URL>/ps/probes/liveness answers instead of logging Not Found: /ps/probes/liveness. If a variable is missing or invalid, the log says exactly which one and /ps/ stays unrouted. wger itself still starts, unless PS_DATABASE_URI points at Postgres while there is SQLite data waiting to be imported: then it refuses to start, so the empty Postgres database is not set up as a new instance. Fix the variable, or remove PS_DATABASE_URI to go back to SQLite.

The wal_level check and the PowerSync storage setup only run once wger is up, after /ps/ is already routed. If either fails, the log says so, PowerSync is not started, and /ps/ answers 502 Bad Gateway until you fix the cause and restart the add-on.

If you put your own reverse proxy in front of the add-on, nothing extra is needed: the /ps/ route forwards an incoming X-Forwarded-Proto unchanged and only falls back to its own scheme when there is none, so PowerSync sees the external scheme your proxy terminated.

Licence

The bundled PowerSync service is published by Journey Mobile, Inc. under the Functional Source License 1.1 with an Apache 2.0 future grant (FSL-1.1-ALv2). Its licence text ships in the image at /opt/powersync/LICENSE. The service is pinned to a specific upstream release rather than tracking latest.

Installation

The installation of this add-on is pretty straightforward and not different in comparison to installing any other Hass.io add-on.

  1. Add my add-ons repository to your home assistant instance (in supervisor addons store at top right, or click button below if you have configured my HA) Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.
  2. Install this add-on.
  3. Click the Save button to store your configuration.
  4. Start the add-on.
  5. Check the logs of the add-on to see if everything went well.
  6. Carefully configure the add-on to your preferences, see the official documentation for for that.

Support

If you have in issue with your installation, please be sure to checkout github.