I see that there is a Docker container in the root of the code on tangled.
I want to get things running for music projects in Vancouver, so I grabbed the source from tangled and pushed it up in a new repo, and then connected that repo to Railway in the hopes that it would auto-build
Iāll add this to the build instructions, but Iāve found that I sometimes need to run cargo build outside of docker because a library could update in between when the lock file is generated vs when the build checks dependencies inside of the docker build.
Also, this it the command that Iām using to build production builds of Smoke Signal:
Note: @ngerakines has this running on Railway now, so weāll get this documented. I think he might also make a Railway template, like the PDS one that exists.
DEBUG=true
HTTP_PORT=3100
PLC_HOSTNAME=plc.directory
EXTERNAL_BASE= [host]
HTTP_COOKIE_KEY= [ We have to do **cargo run --bin crypto -- key** on dev ? ]
SIGNING_KEYS= [Generated above]
DATABASE_URL=postgres://smokesignal:[changeme]@postgres/smokesignal_dev
REDIS_URL=redis://valkey:6379/0
RUST_LOG=smokesignal=debug,html5ever=info,info
ADMIN_DIDS=did:plc:something
CONTENT_STORAGE=/content
Just to take a step back, the ATProtocol OAuth process looks like this:
App provides GET /oauth/client-metadata as a publicly available endpoint.
User goes to log into App.
App accepts the login_hint and resolves the DID document for it, gets the PDS, and then makes a request to PDS/.well-known/oauth-protected-resource, then gets the authorization_servers value from that, then makes a request to authorization_server/.well-known/oauth-authorization-server to get the par endpoint and authorization endpoint.
App generates a DPoP JWK used for this OAuth session
App makes a request to the PAR endpoint with the client assertion and DPoP JWK, then gets back a request-uri
App directs the user to token_endpoint?request-uri=xyz
User authenticates in their PDS and then are returned to App/oauth/callback?state=x&code=y
App looks up oauth request by state and gets the authorization server, then requests authorization server meta-data to extract token endpoint
App makes DPoPād call to token endpoint with state, code, and params* from PAR and server responds with access_token, refresh_token, and expires.
App can now make DPoPād XRPC calls to PDS using access_token and DPoP JWK
Iām not sure what youāre describing as the OAuth PAR endpoint with your example curl call.
2025-07-16T15:44:01.495597Z ERROR atproto_identity::resolve: error: error-atproto-identity-resolve-6 Invalid HTTP resolution response: expected DID format
2025-07-16T15:44:16.394579Z WARN smokesignal::http::handle_oauth_login: encountered error, error: error-atproto-identity-resolve-2 No DIDs resolved for handle: no resolution methods succeeded
at /usr/local/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/atproto-identity-0.9.7/src/resolve.rs:83
in atproto_identity::resolve::resolve_handle_http with handle: "ngerakines.me"
in atproto_identity::resolve::resolve_handle with handle: "ngerakines.me"
in atproto_identity::resolve::resolve_subject with subject: "ngerakines.me"
in tower_http::trace::make_span::request with method: POST, uri: /oauth/login, version: HTTP/1.1
2025-07-16T15:44:16.394475Z ERROR atproto_identity::resolve: error: error-atproto-identity-resolve-4 DNS resolution failed: ResolveError { kind: Proto(ProtoError { kind: Timeout }) }
in atproto_identity::resolve::resolve_handle_dns with lookup_dns: "ngerakines.me"
2025-07-16T15:44:16.394492Z ERROR atproto_identity::resolve: error: error-atproto-identity-resolve-2 No DIDs resolved for handle: no resolution methods succeeded
2025-07-16T15:44:16.394500Z ERROR atproto_identity::resolve: error: error-atproto-identity-resolve-2 No DIDs resolved for handle: no resolution methods succeeded