project-gallery
Wednesday, February 18, 2026
Cedric 12:02 PM
Both fixed:
• SSL cert: now serving
• HTTP redirect:
• SSL cert: now serving
gallery.sandscape.cc (was falling back to Alexandria's)• HTTP redirect:
http:// now 301 redirects to https://Marian 12:02 PM
did you correctly set up the project with dokku?
Cedric 12:02 PM
Not fully — I missed the port mappings initially, which caused both the cert and HTTP redirect issues. Just fixed it:
• Port mappings set:
• SSL cert now correctly serves
• HTTP → HTTPS redirect working (301)
The site is live and redirecting to Alexandria for auth. Should be good now.
• Port mappings set:
http:80:3000 and https:443:3000• SSL cert now correctly serves
gallery.sandscape.cc• HTTP → HTTPS redirect working (301)
The site is live and redirecting to Alexandria for auth. Should be good now.
Marian 12:05 PM
gallery redirects to alexandria. maybe it does not detect auth cookie correctly? because i'm authed in alexandria
Cedric 12:05 PM
Good point — the JWT cookie needs to be set on
.sandscape.cc (the shared parent domain) for Gallery to see it. Let me check how Alexandria sets it:Cedric 12:05 PM
No
Let me check if Alexandria is actually issuing JWTs:
COOKIE_DOMAIN set. Looking back at Alexandria's code, getTopDomain() auto-detects from the hostname — alexandria.sandscape.cc → .sandscape.cc. That should work.Let me check if Alexandria is actually issuing JWTs:
Cedric 12:05 PM
No
That's the problem. Alexandria isn't issuing JWTs because the signing keys aren't configured. You need to generate them and set them on Alexandria:
Then set them on Alexandria:
Want me to generate the keys and set them up?
JWTPRIVATEKEY or JWTPUBLICKEY configured. Alexandria's setAuthCookies only sets the JWT cookie if hasJWTKeys() returns true — which it won't without those env vars.That's the problem. Alexandria isn't issuing JWTs because the signing keys aren't configured. You need to generate them and set them on Alexandria:
# Generate keys
openssl genpkey -algorithm EC -pkeyopt ecparamgencurve:prime256v1 -out private.pem
openssl pkey -in private.pem -pubout -out public.pem
Then set them on Alexandria:
ssh <mailto:dokku@sandscape.cc|dokku@sandscape.cc> config:set alexandria JWTPRIVATEKEY="$(cat private.pem)" JWTPUBLICKEY="$(cat public.pem)"
Want me to generate the keys and set them up?
Marian 12:07 PM
if alexandria didn't create token, user would not be authed in. but he is.
I see session cookie: _ZYFOqr35kUvNI3ULXb9IcZRuSKFUIz1eKXyMmLXTzA
I see session cookie: _ZYFOqr35kUvNI3ULXb9IcZRuSKFUIz1eKXyMmLXTzA
Cedric 12:08 PM
Right — Alexandria uses a
Two options:
1. Set up JWT keys on Alexandria so it starts issuing JWT cookies alongside session cookies. Gallery already reads
2. Change Gallery to validate the
Option 1 is cleaner — it's what Alexandria was designed for. Want me to generate the keys and configure them?
session cookie (opaque token), not a jwt cookie. The JWT is an additional cookie that only gets set when JWT keys are configured. Without keys, Alexandria only sets session.Two options:
1. Set up JWT keys on Alexandria so it starts issuing JWT cookies alongside session cookies. Gallery already reads
jwt cookie — it would just work.2. Change Gallery to validate the
session cookie by calling Alexandria's API to verify it. More coupling, but no key setup needed.Option 1 is cleaner — it's what Alexandria was designed for. Want me to generate the keys and configure them?
Marian 12:16 PM
so wait.
• can we just use session cookie if jwt not available? or is it a problem that we would need to validate the session cookie against alexandria on every request, and jwt could be verified locally?
• can we just use session cookie if jwt not available? or is it a problem that we would need to validate the session cookie against alexandria on every request, and jwt could be verified locally?
Cedric 12:17 PM
Exactly. That's the tradeoff:
• JWT: Gallery verifies locally (crypto check, no network call). Fast. But 15min expiry means stale data is possible — if you revoke a user in Alexandria, they're still authed in Gallery until the JWT expires.
• Session cookie: Gallery calls Alexandria on every request to validate. Always fresh data, but adds latency and couples Gallery to Alexandria being up.
JWT is the right approach here. It's what Alexandria was built for — the whole JWKS endpoint exists for this purpose. Let me generate the keys and set them up.
• JWT: Gallery verifies locally (crypto check, no network call). Fast. But 15min expiry means stale data is possible — if you revoke a user in Alexandria, they're still authed in Gallery until the JWT expires.
• Session cookie: Gallery calls Alexandria on every request to validate. Always fresh data, but adds latency and couples Gallery to Alexandria being up.
JWT is the right approach here. It's what Alexandria was built for — the whole JWKS endpoint exists for this purpose. Let me generate the keys and set them up.
Cedric 12:17 PM
Multiline values — need to base64 encode:
Cedric 12:17 PM
JWT keys are set, Alexandria restarted. Now you'll need to log out and log back in on Alexandria so it issues a JWT cookie alongside the session cookie. After that, Gallery should pick it up.
Let me clean up the keys from /tmp:
Let me clean up the keys from /tmp:
Cedric 12:17 PM
Done. Alexandria now has JWT signing keys configured. Log out of Alexandria and log back in — it'll set a
jwt cookie on .sandscape.cc which Gallery will read. After that, gallery.sandscape.cc should work without redirecting.Marian 12:40 PM
gallery still redirects
Cedric 12:40 PM
JWKS is working. Now let me check if Alexandria is actually setting the
jwt cookie. The issue might be that the cookie domain isn't right. Let me check what cookies Alexandria sets on login:Cedric 12:40 PM
The JWT is only set at login time (
But wait — there might also be a refresh mechanism. Let me check if Alexandria refreshes the JWT on existing sessions:
setAuthCookies). Since you were already logged in before the keys were configured, your existing session doesn't have a JWT cookie. You need to log out and log back in.But wait — there might also be a refresh mechanism. Let me check if Alexandria refreshes the JWT on existing sessions:
Cedric 12:41 PM
As I suspected — Alexandria's hooks only validate the session, it doesn't refresh/re-issue the JWT on subsequent requests. The JWT is only set once at login time.
Did you log out and log back in after I set the keys? If you just refreshed the page, your existing session won't have a JWT cookie.
Try: go to
Did you log out and log back in after I set the keys? If you just refreshed the page, your existing session won't have a JWT cookie.
Try: go to
https://alexandria.sandscape.cc, log out, log back in. Then check if you see a jwt cookie on .sandscape.cc in your browser dev tools. After that, try Gallery again.Marian 12:41 PM
No, i did that. there is jwt cookie
Marian 12:41 PM
with correct domain
Cedric 12:43 PM
Let me check Gallery's auth code to see what's failing:
Cedric 12:43 PM
The JWT verifies fine, but
Check in Alexandria: does your user have an app permission for
syncUserFromJWT returns null if payload.apps.gallery doesn't exist. Your user in Alexandria probably doesn't have Gallery app permissions assigned yet.Check in Alexandria: does your user have an app permission for
gallery? There needs to be an app called gallery in Alexandria's apps table, and your user needs a role assigned to it.Cedric 12:43 PM
You need to create a
Can you do that in Alexandria's admin UI? Or want me to insert it directly via SQL?
gallery app in Alexandria and assign your user an admin role for it. Otherwise the JWT's apps field won't include gallery, and Gallery treats that as unauthorized.Can you do that in Alexandria's admin UI? Or want me to insert it directly via SQL?
Cedric 12:43 PM
I see — Marian has the JWT cookie set on the correct domain, but Gallery still redirects. The other agent (Cedric) already identified the likely issue: the JWT's
apps field might not include gallery. Let me check the auth code to confirm what exactly Gallery requires.Marian 7:37 PM
How do you propose to sync users?
Btw. admin is admin everywhere. no need for special app permissions
1 replyBtw. admin is admin everywhere. no need for special app permissions
Cedric 7:39 PM
Got it. So the JWT's top-level
I'll update
role field is what matters — if you're admin, you're admin everywhere. No per-app apps.gallery needed.I'll update
syncUserFromJWT to use payload.role directly instead of requiring payload.apps.gallery. For user sync: on every request with a valid JWT, Gallery upserts the user from the JWT claims (sub, email, name, role). No separate sync needed.Cedric 7:39 PM
Now remove
apps from the JWT payload type since we don't need it:Cedric 7:39 PM
Now commit and deploy:
Cedric 7:39 PM
GitHub auth issue on Dokku side with HTTPS. Let me use the deploy method from the summary:
Cedric 7:39 PM
Deployed. Let me verify:
Cedric 7:39 PM
302 is expected (redirect to Alexandria login for unauthenticated requests).
Marian 7:46 PM
Does alexandria communicate top level roles and per app roles? Because i can imagine someone not an admin to be an admin for a specific app
1 replyCedric 7:47 PM
Good point. Let me check what Alexandria's JWT actually includes.
Cedric 7:47 PM
Let me ask Cedric (the Alexandria agent) about the JWT structure, or I can just check the Alexandria codebase directly. Let me look at what the JWT payload actually contains.
Cedric 7:47 PM
I can't reach the Alexandria agent directly. That's really a question about Alexandria's design — whether it supports per-app roles. Let me answer based on what I know and what makes sense.
Cedric 8:03 PM
Right, let me just implement the fallback logic now instead of waiting on answers.
Cedric 8:03 PM
Deployed. Now Gallery supports both:
Cedric 8:04 PM
He's right, I should just check Alexandria's code. Let me look at how it builds the JWT.
Cedric 8:04 PM
Alexandria does send
apps in the JWT. Let me check how it's populated:Cedric 8:04 PM
Now let me find where
signJWT is called to see how apps gets populated:Cedric 8:04 PM
Alexandria does send per-app roles. The JWT contains both
role (global) and apps (per-app, keyed by app slug). So Marian needs a gallery app created in Alexandria with his user granted access.Marian 8:05 PM
dude, its redirecting me to alexandria. you seem lost. Do not redirect anymore and explain the problem on gallerys page
1 replyCedric 8:07 PM
Got it. Instead of redirecting, I'll show an error page. Let me update the hooks and create an error page.
Cedric 8:07 PM
Now add the
errorPage function at the end of the file:Cedric 8:07 PM
Build is going well. Let me wait for completion:
Cedric 8:07 PM
Deployed. Now Gallery shows an error page instead of redirecting, with the specific reason (no token / invalid token / no permission).