Skip to content

Complete self-hosted relay smoke path#1

Open
EllAchE wants to merge 6 commits into
mainfrom
obsidian-relay-smoke-20260630-004840
Open

Complete self-hosted relay smoke path#1
EllAchE wants to merge 6 commits into
mainfrom
obsidian-relay-smoke-20260630-004840

Conversation

@EllAchE

@EllAchE EllAchE commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • make the PocketBase control plane apply at boot and add runtime routes for invitation acceptance, self-host key rotation, and relay config download
  • switch token-service to the smoke-tested RELAY_SERVER_AUTH flow, add /file-token, and remove the guessed local CWT signing path
  • tighten inferred PocketBase rules and document the tested EdDSA + legacy signing-key setup

Verification

  • node --check pb_hooks/relay_self_host.pb.js pb_hooks/relay_runtime.pb.js pb_hooks/oauth2_code_exchange.pb.js pb_migrations/1750000000_init_relay_control_plane.js token-service/src/index.js
  • docker compose stack healthy locally: relay-server :8080, token-service :3000, PocketBase :8090
  • backend smoke: self-host relay registration, invitation acceptance, key rotation, relay config download, /token, and /file-token all passed
  • git-backed smoke: initialized a bare Git repo, cloned two Obsidian-style vaults, copied plugin artifact to .obsidian/plugins/system3-relay, committed/pushed/cloned, minted a doc token, and opened a relay WebSocket

Remaining follow-up

  • configure PocketBase OAuth provider credentials and run the final two-window Obsidian UI sync test with network inspection for relay.md traffic
  • update the plugin checkout to call the non-conflicting self-host management paths if key rotation/config download are needed from the UI

EllAchE added 3 commits June 27, 2026 14:15
Manual OAuth code flow (LoginManager.poll) reads a code_exchange row keyed
by state.slice(0,15); nothing wrote it on self-host, so the manual/mobile
login flow hung for 30s and timed out.

- pb_hooks/oauth2_code_exchange.pb.js: global middleware on
  GET /api/oauth2-redirect that upserts {id: state[:15], code} via DAO, then
  calls next(c) so the built-in handler + popup/SSE flow stay intact.
  (additive middleware, not routerAdd, to avoid conflicting with the
  built-in route). v0.22 echo JS API.
- migration: code_exchange viewRule -> public. poll() runs pre-auth, so
  view: AUTHED would forbid the anonymous getOne and time out login. The
  15-char id is the high-entropy OAuth-state slice (capability); listRule
  stays null to block enumeration; writes go via DAO (bypass API rules).
- README: documented the new hook and marked the gap resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d8bca0867c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker-compose.yml
Comment on lines +43 to +45
"pocketbase migrate up --dir /pb/pb_data --migrationsDir /pb/pb_migrations &&
pocketbase serve --http=0.0.0.0:8090 --dir /pb/pb_data
--migrationsDir /pb/pb_migrations --hooksDir /pb/pb_hooks"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fix the quoted PocketBase shell command

With entrypoint: ["/bin/sh", "-c"], this folded block passes the leading and trailing double quotes literally into sh -c; the shell then treats everything between them as one command word, so && is not an operator and it tries to execute a command named pocketbase migrate up ... && pocketbase serve ..., exiting 127. In this compose workflow the PocketBase container never becomes healthy, so token-service remains blocked on depends_on; remove the wrapper quotes around the folded command.

Useful? React with 👍 / 👎.

@EllAchE

EllAchE commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

Added the cheap single-VM deployment path in abbbf21:

  • docker-compose.vm.yml runs Caddy + relay-server + token-service + PocketBase on one VM
  • deploy/Caddyfile maps API/auth/relay hostnames to internal services and only publishes 80/443
  • .env.vm.example and relay.vm.toml.example cover the domain/key setup
  • docs/single-vm.md walks through DNS, key generation, first boot, PocketBase setup, plugin build values, and backups

Validated with:

docker compose -f docker-compose.vm.yml --env-file .env.vm.example config

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: abbbf2162c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docker-compose.vm.yml
Comment on lines +61 to +63
"pocketbase migrate up --dir /pb/pb_data --migrationsDir /pb/pb_migrations &&
pocketbase serve --http=0.0.0.0:8090 --dir /pb/pb_data
--migrationsDir /pb/pb_migrations --hooksDir /pb/pb_hooks"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the wrapper quotes from the VM command

When following docs/single-vm.md, this VM stack uses entrypoint: ["/bin/sh", "-c"], so the leading quote in the folded command is passed literally to sh -c; I verified /bin/sh -c '"echo hi && echo bye"' treats && as part of the command name and exits 127. PocketBase therefore never becomes healthy and the VM deployment remains blocked; drop the outer quotes around the folded command.

Useful? React with 👍 / 👎.


routerAdd(
"POST",
"/api/self-host-rotate-key",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose the rotate route the plugin calls

The Relay plugin path used for share-key rotation still posts to /api/rotate-key (patches/relay-plugin.patch only changes the build URLs and does not patch that call), but this hook registers only /api/self-host-rotate-key. In the Obsidian UI, rotating an invitation will therefore hit PocketBase's reserved/missing route instead of rotateInvitationKey, so the key will not rotate unless the plugin patch is updated or this hook also handles the original route.

Useful? React with 👍 / 👎.

Comment thread docker-compose.yml
Comment on lines +15 to +16
env_file:
- .env

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make the local env file optional

On a fresh checkout following the README's docker compose up -d, .env is gitignored and never created for the local compose path, but this new env_file entry is required by default (Docker documents required: true as the default: https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/#use-the-env_file-attribute). Because RELAY_SERVER_AUTH already has a ${...:-} fallback, this should be optional or the setup docs should create a local .env before starting the stack.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 800c0e625f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// can't produce a valid id and isn't something PB's own flow generates, so
// skip rather than write an invalid record.
if (state && code && state.length >= 15) {
const id = state.substring(0, 15);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a PocketBase-safe code_exchange ID

When the manual OAuth redirect state contains uppercase characters, this uses the raw state.substring(0, 15) as a PocketBase record id; PocketBase's default record id validation is lowercase-only, while OAuth states commonly include [A-Za-z0-9]. In that case dao.saveRecord(rec) throws, the catch only logs it, and no code_exchange row is written for LoginManager.poll, so those logins time out. Use an ID-safe derivation that the client also polls, or adjust the collection/client contract to allow the generated state slice.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6391e506ac

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +309 to +311
["roleowner000000", "Owner"],
["rolemember00000", "Member"],
["rolereader00000", "Reader"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Seed roles with the IDs the plugin knows

The plugin starts with a local role map keyed by the production Owner/Member ids (2arnubkcv7jpce8 and x6lllh2qsf9lxk6) and resolves RelayRole.role/RelayInvitation.role by looking up the relation id in that map, while it does not fetch the roles collection directly. Seeding different ids here means the hooks create relay roles and invitations whose role names are unknown until some later expanded role happens to be ingested, so immediate owner/member policy checks and folder-role creation after registration can fail. Seed the plugin-compatible ids or explicitly fetch/expand all roles before these records are used.

Useful? React with 👍 / 👎.

Comment thread README.md
```bash
cd ~/relay-self-hosted/relay-plugin
RELAY_API_URL=https://relay.example.com node esbuild.config.mjs
RELAY_API_URL=https://relay.example.com RELAY_AUTH_URL=https://auth.example.com node esbuild.config.mjs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point RELAY_API_URL at the API host

For the single-VM layout added in this change, relay.example.com is proxied to the relay-server, but API_URL is the token-service host (api.example.com in the table above and in docs/single-vm.md). Following this rebuild command makes the plugin send /token and /file-token to relay-server instead of token-service, so token minting fails on remote deployments built from the README.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant