diff --git a/.gitignore b/.gitignore index c2de2c7..f75eeb7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /config/Caddyfile /docker-compose.override.yml /dev-postgres/.env +/dev-postgres-powersync/.env /dev/.env \ No newline at end of file diff --git a/config/dev.env b/config/dev.env index 0cad326..0bda3b4 100644 --- a/config/dev.env +++ b/config/dev.env @@ -1,5 +1,17 @@ DJANGO_DEBUG=True WGER_USE_GUNICORN=False EXERCISE_CACHE_TTL=30 +DJANGO_PERFORM_MIGRATIONS=True SYNC_EXERCISES_ON_STARTUP=False +DOWNLOAD_EXERCISE_IMAGES_ON_STARTUP=False +DOWNLOAD_EXERCISE_VIDEOS_ON_STARTUP=False +LOAD_ONLINE_FIXTURES_ON_STARTUP=False # a couple of ingredients +SYNC_INGREDIENTS_ON_STARTUP=False # lots of ingredients. expensive AXES_ENABLED=False + +# These can be generated by following the instructions in the `key-generator` folder +# A temporary key will be used if these are not specified +# --> keys generated with https://github.com/powersync-ja/powersync-jwks-example/blob/main/README.md +POWERSYNC_JWKS_PUBLIC_KEY=eyJhbGciOiAiUlMyNTYiLCAia3R5IjogIlJTQSIsICJuIjogInFhdVVnb0ZXenRNcjVEYks3bFIxZXUxazJrdllyblJkRGh1NDFyWnFLeWhDWkJya0FTS0d0N25KbVUwVEpKb1d0cFF2eHVvc0ZGeW1BMUhXQnNaY0dtVlcxdlowdDJlazl4THg5bjg2UWRIVWc1MktsRG9ZUzNtRTFaWW5BYzJfRDM3UmxyQkVxRXpuSnBNeDJ3VkpLcVdRZHlWSWh6Q082YzRnOWN3VExGbUhkVXVURXMzdDNBN1MyNENrUkM2TE1KSFFvRTJzay1uWlJyZE9fTHVNNUJJcVp2b1dWUC1Salp4OWk4OGdaaDhvOEcyWW1xZnMwczRzYW1fam85bmFaYlo4aFBFQ0FZdnZUZ29ObzRHMGpXZERZeGdPWHlXTE80bTk1SEdMSFJMZjZ5M29vdkZad2QwN2FFbThEU3dBX3hsY1V4WHNNZ0ZlYVVVZkp2NEV4USIsICJlIjogIkFRQUIiLCAia2lkIjogInBvd2Vyc3luYyJ9 +POWERSYNC_JWKS_PRIVATE_KEY=eyJhbGciOiAiUlMyNTYiLCAia3R5IjogIlJTQSIsICJuIjogInFhdVVnb0ZXenRNcjVEYks3bFIxZXUxazJrdllyblJkRGh1NDFyWnFLeWhDWkJya0FTS0d0N25KbVUwVEpKb1d0cFF2eHVvc0ZGeW1BMUhXQnNaY0dtVlcxdlowdDJlazl4THg5bjg2UWRIVWc1MktsRG9ZUzNtRTFaWW5BYzJfRDM3UmxyQkVxRXpuSnBNeDJ3VkpLcVdRZHlWSWh6Q082YzRnOWN3VExGbUhkVXVURXMzdDNBN1MyNENrUkM2TE1KSFFvRTJzay1uWlJyZE9fTHVNNUJJcVp2b1dWUC1Salp4OWk4OGdaaDhvOEcyWW1xZnMwczRzYW1fam85bmFaYlo4aFBFQ0FZdnZUZ29ObzRHMGpXZERZeGdPWHlXTE80bTk1SEdMSFJMZjZ5M29vdkZad2QwN2FFbThEU3dBX3hsY1V4WHNNZ0ZlYVVVZkp2NEV4USIsICJlIjogIkFRQUIiLCAiZCI6ICJQZXVwNjhUakZ1RVhaQmFoRWNDT0RWcEUwNndaZkhWb0hvVjhmQk9maEhlUlh6STNJcmprZkhtWHV0UlhsNlNLaElCcFBVbHA0OVo2R2IwTWhIVncySXRDV1hvaFYydkNWdzg1Y2RHMXc1NmQxWml4b2UzZnZ1LXV6RG9icXp0WXJvR0VZTi1jZHVWMS1HeUFwZU4wYzlWdmR5UUtwNWZQbUVGTFl4amlxR3k5UUhyTldpcGJmZXdPUGY0YUl4X05VRnE3R1BsUk1yalA4VEhvSzNPOVNfXzJpR09LRVpINDFUWkpscVBZX0s5dFNkbFNKd1FPWEtwOFc2ZUdGT3l2MElueVhsUXhHb0ZBWVNrUC12WTlWQy1vTUtzdmhocm1GeGM0VlU2OUZ3VWFJYUdaOU9jaXF4M3B0aE9sU1drRjFhbEtxNWFJZ2VHbEUzM2VyNGthSXciLCAicCI6ICI1WDN0QzN4Z0hwbm91U1JwSlg4c0ZWRm5vamhxMWJoWkF3c3VRaXBxWWgtZmJNRGI4a2NTTy1fT3BEMExNekYzcHp0dVNRb0NZOFc0WjI0TEJ6cFRuUlFid0JrYWt3VDMybmZIU1J0d3RnM1ZjWkkxZFNsdHgtclhEcHlBMDNHa1RvLUxEZkp1UzF0a1FYQXB0OTBkcnJHMndjQ25oRXc4bGx2SzR2cWRucHMiLCAicSI6ICJ2VVM2V2QtY2trTUJMVmJvSkVaVnRtMlFLTFE2dV9oZEFrbTFWa3dGajMxZWZWRTlFRWRSa0F0dGVoOWh2ZzBkM2FXVDZ1bFQ4YlpubWo3WkFjNG55aVdwOTlFd0k5U0hFX01UUE11YVZSeUw5SmFIX2R0Uk5nVGE5UV9hZUs2d1pkY3RwLUZRT1lteVlDWmhzRnVOTG45TFJ3UklJOVJ0YlBXYW55X01jQjgiLCAiZHAiOiAiWjFNNkhmakN3aVJqcnJBaEV6dmQyajlMbkxNd0RzZXdjX2xkdTNhamJVaDFuQjU5S09rczRZV0lFVlJXclpieEczOWJtVkVEWUc2T0p5dFpsY2lDQ3ZBWnluVEREVHlvWjFtVWhXcndaVmQzS1dvOTNXRm94eUVKOE04d0JZTmVDZTBCRzZkeVYwVnZyekxUNWEtTmhMRUk2dFZWMXZBSU8xNWF5N1V3c0U4IiwgImRxIjogIktsclpBUWZEZUEtNmtiVGpHa3NMSDFvQmFycDZjbG93SmpUc2ViVmxnU2pqSGxReHdCVFZzZEI4M1Zsc2ZDVmZTNXlrTDJ1cnQybkVZWVl5OWU1MmhReE1yd0tITFYyQUpQeS1qMXBZM1RjWU10SUUtTkE5cWtNSDVOTjVab3hoT1VrZ0ZIT2RpbUxBSWpnMG9FeThtVzB2SVdOWjZYcS1TaVhrUmo5aUZxMCIsICJxaSI6ICJzSV84RTh0MTBsRDY2NTh3UXRpY19BaUUxOVk1Rms0SDJWbnpGclBhVU04aWFNaVc2eUZxMFZuN3RXa2RTWS1STTB1SFMwdmVmSEcyZTBKSWxEanhBUmZWZUcwNTFyVUNRZjBkSnR4U0ZDQUp2eGxMRTZsYjZOQlUwZVIyMld6bjVob1ZZTVpHZnQ5QnA0SlVOOHJkMF9lMm1kSjhxc09wM1NLQ3NTSTByUkkiLCAia2lkIjogInBvd2Vyc3luYyJ9 +POWERSYNC_URL=http://localhost:8080 diff --git a/config/prod.env b/config/prod.env index 4e2f8eb..72394ae 100644 --- a/config/prod.env +++ b/config/prod.env @@ -101,6 +101,10 @@ DJANGO_DB_HOST=db DJANGO_DB_PORT=5432 DJANGO_PERFORM_MIGRATIONS=True # Perform any new database migrations on startup +# postgres://:@:/ +PS_PG_URI=postgres://wger:wger@db:5432/wger +PS_MONGO_URI: mongodb://mongo:27017/powersync_wger + # # Cache DJANGO_CACHE_BACKEND=django_redis.cache.RedisCache @@ -180,9 +184,6 @@ FROM_EMAIL='wger Workout Manager ' # Needs a working email configuration # DJANGO_ADMINS=your name,email@example.com -# Whether to compress css and js files into one (of each) -# COMPRESS_ENABLED=True - # # Django Rest Framework # The number of proxies in front of the application. In the default configuration @@ -201,5 +202,5 @@ NUMBER_OF_PROXIES=1 GUNICORN_CMD_ARGS="--workers 3 --threads 2 --worker-class gthread --proxy-protocol True --timeout 240" # -# Prometheus metrics -EXPOSE_PROMETHEUS_METRICS=False \ No newline at end of file +# Powersync +PS_PORT=8080 \ No newline at end of file diff --git a/dev-postgres-powersync/.env.example b/dev-postgres-powersync/.env.example new file mode 100644 index 0000000..a814d23 --- /dev/null +++ b/dev-postgres-powersync/.env.example @@ -0,0 +1,3 @@ +# Copy to .env + +WGER_CODEPATH=/path/to/wger/server \ No newline at end of file diff --git a/dev-postgres-powersync/config-powersync/powersync.yaml b/dev-postgres-powersync/config-powersync/powersync.yaml new file mode 100644 index 0000000..7b0008c --- /dev/null +++ b/dev-postgres-powersync/config-powersync/powersync.yaml @@ -0,0 +1,78 @@ +# yaml-language-server: $schema=../schema/schema.json + +# Note that this example uses YAML custom tags for environment variable substitution. +# Using `!env [variable name]` will substitute the value of the environment variable named +# [variable name]. +# +# Only environment variables with names starting with `PS_` can be substituted. +# +# e.g. With the environment variable `export PS_MONGO_URI=mongodb://localhost:27017` +# and YAML code: +# uri: !env PS_MONGO_URI +# The YAML will resolve to: +# uri: mongodb://localhost:27017 +# +# If using VS Code see the `.vscode/settings.json` definitions which define custom tags. + +# migrations: +# # Migrations run automatically by default. +# # Setting this to true will skip automatic migrations. +# # Migrations can be triggered externally by altering the container `command`. +# disable_auto_migration: true + +# Settings for telemetry reporting +# See https://docs.powersync.com/self-hosting/telemetry +telemetry: + # Opt out of reporting anonymized usage metrics to PowerSync telemetry service + disable_telemetry_sharing: false + +# Settings for source database replication +replication: + # Specify database connection details + # Note only 1 connection is currently supported + # Multiple connection support is on the roadmap + connections: + - type: postgresql + # The PowerSync server container can access the Postgres DB via the DB's service name. + # In this case the hostname is db + + # The connection URI or individual parameters can be specified. + # Individual params take precedence over URI params + uri: !env PS_PG_URI + + # Or use individual params + + # hostname: db # From the Docker Compose service name + # port: 5432 + # database: postgres + # username: postgres + # password: mypassword + + # SSL settings + sslmode: disable # 'verify-full' (default) or 'verify-ca' or 'disable' + # 'disable' is OK for local/private networks, not for public networks + + +# Connection settings for sync bucket storage +storage: + type: mongodb + uri: !env PS_MONGO_URI + +# The port which the PowerSync API server will listen on +port: !env PS_PORT + +# Specify sync rules +sync_rules: + path: sync_rules.yaml + +# Client (application end user) authentication settings +client_auth: + # Enable this if using Supabase Auth + # supabase: true + allow_local_jwks: true + + # JWKS URIs can be specified here + jwks_uri: !env PS_JWKS_URL + + # JWKS audience + audience: ["powersync-dev", "powersync"] diff --git a/dev-postgres-powersync/config-powersync/sync_rules.yaml b/dev-postgres-powersync/config-powersync/sync_rules.yaml new file mode 100644 index 0000000..f25c790 --- /dev/null +++ b/dev-postgres-powersync/config-powersync/sync_rules.yaml @@ -0,0 +1,53 @@ +# See Documentation for more information: +# https://docs.powersync.com/usage/sync-rules +# Note that changes to this file are not watched. +# The service needs to be restarted for changes to take effect. +# Warning, parameter queries have a limit of 1000 rows (before filtering)! +config: + edition: 2 + +bucket_definitions: + global: + data: + # Core tables + - SELECT * FROM core_language + - SELECT * FROM core_license + - SELECT * FROM core_repetitionunit; + - SELECT * FROM core_weightunit; + + # Exercises + - SELECT * FROM exercises_exercise + - SELECT * FROM exercises_translation + - SELECT * FROM exercises_alias + - SELECT * FROM exercises_muscle + - SELECT * FROM exercises_exercise_muscles + - SELECT * FROM exercises_exercise_muscles_secondary + - SELECT * FROM exercises_equipment + - SELECT * FROM exercises_exercise_equipment + - SELECT * FROM exercises_exercisecategory + - SELECT * FROM exercises_exerciseimage + - SELECT * FROM exercises_exercisevideo + - SELECT * FROM exercises_variation + by_user_id: + parameters: SELECT token_parameters.user_id AS user_id + data: + - SELECT uuid AS id, * FROM weight_weightentry WHERE user_id = bucket.user_id + - SELECT uuid AS id, * FROM manager_workoutlog WHERE user_id = bucket.user_id + - SELECT uuid AS id, * FROM manager_workoutsession WHERE user_id = bucket.user_id + - SELECT * FROM measurements_category WHERE user_id = bucket.user_id + +# - select * from ivm_nutrition_nutritionplan as nutrition_nutritionplan where user_id = bucket.user_id +# - select * from ivm_nutrition_meal as nutrition_meal where user_id = bucket.user_id +# - select * from ivm_nutrition_mealitem as nutrition_mealitem where user_id = bucket.user_id +# - select * from ivm_nutrition_logitem as nutrition_logitem where user_id = bucket.user_id + # "too many buckets" errors + # meal_item_ingredients: # note: we are restricted by <=1000 distinct ingredient_id values here + # parameters: select ingredient_id as ingredient_id FROM ivm_nutrition_mealitem WHERE user_id = token_parameters.user_id + # data: + # - select * from nutrition_ingredient WHERE ingredient_id = bucket.ingredient_id + # - select * from nutrition_image WHERE ingredient_id = bucket.ingredient_id + # log_item_ingredients: + # parameters: select ingredient_id as ingredient_id FROM ivm_nutrition_logitem WHERE user_id = token_parameters.user_id + # data: + # - select * from nutrition_ingredient WHERE ingredient_id = bucket.ingredient_id + # - select * from nutrition_image WHERE ingredient_id = bucket.ingredient_id diff --git a/dev-postgres-powersync/docker-compose.yml b/dev-postgres-powersync/docker-compose.yml new file mode 100644 index 0000000..2cb73fa --- /dev/null +++ b/dev-postgres-powersync/docker-compose.yml @@ -0,0 +1,76 @@ +name: wger-dev-postgres-powersync + +services: + web: + build: + pull: true + context: ${WGER_CODEPATH:?set the absolute path to the wger backend code in the .env file or env variable} + dockerfile: ./extras/docker/development/Dockerfile + depends_on: + db: + condition: service_healthy + env_file: + - ../config/prod.env + - ../config/dev.env + develop: + watch: + - action: sync + path: ${WGER_CODEPATH} + target: /home/wger/src + - action: rebuild + path: ${WGER_CODEPATH}/pyproject.toml + - action: rebuild + path: ${WGER_CODEPATH}/package.json + ports: + - "8000:8000" + + cache: + image: redis + expose: + - 6379 + healthcheck: + test: redis-cli ping + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + restart: unless-stopped + + db: + build: + context: ../postgres + dockerfile: Dockerfile + environment: + - POSTGRES_USER=wger + - POSTGRES_PASSWORD=wger + - POSTGRES_DB=wger + volumes: + - postgres-dev-data:/var/lib/postgresql/data/ + # automatically import dump +# - ../wger-2025-09-09_19-25.dump:/docker-entrypoint-initdb.d/00-init-db.sql:ro +# - ../wger-reset-password.sql:/docker-entrypoint-initdb.d/01-reset-pw.sql:ro +# - ../wger-cleanup.sql:/docker-entrypoint-initdb.d/02-cleanup.sql:ro + ports: + - "5432:5432" + expose: + - 5432 + # "-c", "log_statement=all", "-c", "log_min_error_statement=DEBUG1" + command: ["postgres", "-c", "wal_level=logical"] + healthcheck: + test: pg_isready -U wger + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + restart: unless-stopped + +volumes: + postgres-dev-data: + +networks: + default: + name: wger-dev-network + +include: + - path: powersync-services/mongo.yaml + - path: powersync-services/powersync.yaml diff --git a/dev-postgres-powersync/powersync-services/mongo.yaml b/dev-postgres-powersync/powersync-services/mongo.yaml new file mode 100644 index 0000000..9381497 --- /dev/null +++ b/dev-postgres-powersync/powersync-services/mongo.yaml @@ -0,0 +1,24 @@ +services: + # MongoDB Service used internally + mongo: + image: mongo:8 + command: --replSet rs0 --bind_ip_all --quiet + restart: unless-stopped + ports: + - 27017:27017 + volumes: + - mongo_storage:/data/db + + # Initializes the MongoDB replica set. This service will not usually be actively running + mongo-rs-init: + image: mongo:8 + depends_on: + - mongo + restart: on-failure + entrypoint: + - bash + - -c + - 'mongosh --host mongo:27017 --eval ''try{rs.status().ok && quit(0)} catch {} rs.initiate({_id: "rs0", version: 1, members: [{ _id: 0, host : "mongo:27017" }]})''' + +volumes: + mongo_storage: diff --git a/dev-postgres-powersync/powersync-services/powersync.yaml b/dev-postgres-powersync/powersync-services/powersync.yaml new file mode 100644 index 0000000..14096cc --- /dev/null +++ b/dev-postgres-powersync/powersync-services/powersync.yaml @@ -0,0 +1,52 @@ +services: + powersync: + depends_on: + mongo-rs-init: + condition: service_completed_successfully + restart: unless-stopped + image: journeyapps/powersync-service:latest + # The unified service runs an API server and replication worker in the same container. + # These services can be executed in different containers by using individual entry commands e.g. + # Start only the API server with + # command: ['start', '-r', 'api'] + # Start only the replication worker with + # command: ['start', '-r', 'sync'] + + # Migations occur automatically by default. Default migrations can be disabled in `powersync.yaml`: + # migrations: + # disable_auto_migration: true + # + # Service migrations can be manually triggered by starting a container with the + # following command: + # command: ['migrate', 'up'] + # Note that this container must finish executing before starting the sync or unified container. + command: ["start", "-r", "unified"] + volumes: + # Mounts the specified config folder to the container + # This folder should contain `powersync.yaml and sync_rules.yaml + - ../config-powersync:/config + env_file: + - ../../config/prod.env + - ../../config/dev.env + environment: + # This is the path (inside the container) to the YAML config file + # Alternatively the config path can be specified in the command + # e.g: + # command: ['start', '-r', 'unified', '-c', '/config/powersync.yaml'] + # + # The config file can also be specified in Base 64 encoding + # e.g.: Via an environment variable + # POWERSYNC_CONFIG_B64: [base64 encoded content] + # or e.g.: Via a command line parameter + # command: ['start', '-r', 'unified', '-c64', '[base64 encoded content]'] + POWERSYNC_CONFIG_PATH: /config/powersync.yaml + + # Sync rules can be specified as base 64 encoded YAML + # e.g: Via an environment variable + # POWERSYNC_SYNC_RULES_B64: "[base64 encoded sync rules]" + # or e.g.: Via a command line parameter + # command: ['start', '-r', 'unified', '-sync64', '[base64 encoded content]'] + PS_JWKS_URL: http://web:8000/api/v2/powersync-keys + + ports: + - 8080:8080 diff --git a/postgres/Dockerfile b/postgres/Dockerfile new file mode 100644 index 0000000..0a2b15e --- /dev/null +++ b/postgres/Dockerfile @@ -0,0 +1,24 @@ +FROM postgres:15-bookworm AS builder + +ENV VERSION=1.12 + +RUN apt-get update && \ + apt-get install -y \ + git \ + build-essential \ + postgresql-server-dev-15 + +WORKDIR /tmp +RUN git clone -b v${VERSION} https://github.com/sraoss/pg_ivm.git + +WORKDIR /tmp/pg_ivm +RUN make + +# Create the final image +FROM postgres:15-bookworm + +COPY --from=builder /tmp/pg_ivm/pg_ivm*.sql /usr/share/postgresql/15/extension +COPY --from=builder /tmp/pg_ivm/pg_ivm.control /usr/share/postgresql/15/extension +COPY --from=builder /tmp/pg_ivm/pg_ivm.so /usr/lib/postgresql/15/lib + +EXPOSE 5432 \ No newline at end of file