Document verified Dokku deployment and live sync results

This commit is contained in:
Peter Stockings
2026-10-01 20:47:58 +10:00
parent 8555695c5e
commit fe9888092c
2 changed files with 30 additions and 11 deletions
+10 -9
View File
@@ -26,8 +26,8 @@ account exists. Subsequent accounts start empty.
The local app uses SQLite in `instance/dashboard.db`. Set `DATABASE_URL` to a
PostgreSQL connection string to use PostgreSQL. Database changes use Alembic
migrations. Local schema creation/upgrade has been verified on SQLite; PostgreSQL
runtime validation is recorded in docs/DEPLOYMENT.md.
migrations. SQLite and deployed PostgreSQL migrations have been verified; see
[deployment validation](docs/DEPLOYMENT.md).
### Accounts and sharing
@@ -49,9 +49,10 @@ runtime validation is recorded in docs/DEPLOYMENT.md.
### Bringing in more activities
Run the local sync below, then choose **Settings & imports -> Load new downloads**.
This button imports the cache assigned to your account, without contacting Garmin.
Any account can also upload an original FIT file through Settings & imports.
Use **Settings & imports -> Connect Garmin** to upload an exported session, then
choose **Sync now** or leave hourly sync enabled. Any account can also upload an
original FIT file through Settings & imports. Operators can import local caches
with the command below.
Original files remain private and are not exposed by web download routes.
If multiple Garmin caches existed at setup, an operator can explicitly assign one:
@@ -61,10 +62,10 @@ uv run --locked flask --app app import-local --email owner@example.com --account
```
The application uses CSRF protection, hashed passwords, login throttling, and
server-side authorization on every activity page and data endpoint. Before public
deployment, finish email verification/recovery, shared production rate-limit
storage, and account recovery. Deployment instructions and sync behavior are in docs/DEPLOYMENT.md.
The current server binds only to loopback and runs without debug mode.
server-side authorization on every activity page and data endpoint. Email
verification/recovery and shared production rate-limit storage remain outstanding.
Deployment instructions and sync behavior are in docs/DEPLOYMENT.md.
The local server binds only to loopback; production runs behind the Dokku HTTPS proxy.
Users will upload FIT files or connect Garmin by authenticating locally with
`python-garminconnect` and uploading their exported session tokens. The server
+20 -2
View File
@@ -12,7 +12,8 @@ key separately from database backups; losing it requires Garmin reconnection.
Push to Gitea, then deploy with `dokku git:sync --build stride
https://gitea.peterstockings.com/peterstockings/Stride.git main` on the server.
Enable HTTPS using `dokku letsencrypt:enable stride`.
Map the web port with `dokku ports:set stride http:80:8000`, then enable HTTPS
using `dokku letsencrypt:enable stride`.
## Sync
@@ -42,4 +43,21 @@ implemented. For a larger public deployment configure shared rate-limit storage.
Local automated suite: 39 passing tests, including manual/scheduled jobs,
encryption, retry/authentication failure, locking, CSRF, and access control.
Live deployment and Garmin results will be recorded after verification.
Live verification on 2026-10-01:
- Built and deployed on Dokku 0.38.23; all PostgreSQL migrations succeeded.
- HTTPS certificate issued; external `/health` returned HTTP 200 and `status: ok`.
- Migrated the existing local account and 18 activities, preserving its password hash.
- Reused the local Garmin session on the Linux server, saved it encrypted, and
imported one new activity (19 total).
- Submitted a manual sync to the public HTTPS endpoint with an authenticated
session, CSRF token, and same-origin Referer. The background worker completed it.
- Moved `next_sync` into the past with `pending=false` and scheduling enabled.
The running worker picked it up automatically and completed the scheduled run.
This exercises the schedule due check without waiting an hour.
- Both repeat syncs imported zero duplicates and reported zero failures.
- Authenticated dashboard returned 200; anonymous private activity access returned 404.
- Production uses one web container (two Gunicorn processes) and one worker;
hourly scheduling remains enabled. The local session copy should no longer be
used concurrently with the server.