Our Personal Data Server from scratch! tranquil.farm
pds rust database fun oauth atproto
237
fork

Configure Feed

Select the types of activity you want to include in your feed.

PDS not working #21

open opened by joinsakurajima.org

Encountering some issues getting the PDS working. The register and login pages do not work, although the health says OK.

https://sakurasora.social/oauth/client-metadata.json brings a 404 error looking at the javascript console for https://sakurasora.social/app/register

The post on https://sakurasora.social/oauth/par http request gave a response of invalid client with https://sakurasora.social/oauth/client-metadata.json bringing a 404 error.

Doing a curl request on the local host to the PDS directly running on port 3009 gives the same 404 error.

[root@mizuka chikorita157]# curl -v -s http://sakurasora.social:3009/oauth/client-metadata.json

  • Trying 127.0.0.1:3009...
  • Connected to sakurasora.social (127.0.0.1) port 3009 (#0)

GET /oauth/client-metadata.json HTTP/1.1 Host: sakurasora.social:3009 User-Agent: curl/7.76.1 Accept: /

  • Mark bundle as not supporting multiuse < HTTP/1.1 404 Not Found < vary: origin, access-control-request-method, access-control-request-headers < access-control-allow-origin: * < access-control-expose-headers: www-authenticate,dpop-nonce,atproto-repo-rev,atproto-content-labelers < content-length: 0 < date: Fri, 13 Feb 2026 11:45:38 GMT <
  • Connection #0 to host sakurasora.social left intact

What might be causing this?

I built this manually, running on Red Hat Enterprise Linux 9.7. I converted the nginx config to apache.

[deleted by author]
[deleted by author]

I figured, and I was able to get that json file to get served in Apache.

Here is an example Apache config that I used, not fully tested. However, the user needs to manually edit the json file to replace the host name placeholders as that can"t be done in Apache, I believe.

<VirtualHost *:443>
	ServerName pds.example.com
	ServerAlias *.pds.example.com
	
	SSLEngine on
	SSLCertificateFile /etc/letsencrypt/live/pds.example.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/pds.example.com/privkey.pem
	
	# Enable HTTP/2
	Protocols h2 http/1.1
	
	# Client max body size equivalent
	LimitRequestBody 10737418240
	
	DocumentRoot /var/www/tranquil-pds
	
	# Proxy configuration
	ProxyPreserveHost On
	ProxyTimeout 86400
	
	# /xrpc/ location
	<Location /xrpc/>
		ProxyPass http://127.0.0.1:3000/xrpc/
		ProxyPassReverse http://127.0.0.1:3000/xrpc/
		
		RequestHeader set X-Real-IP %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
		
		# WebSocket support
		RewriteEngine On
		RewriteCond %{HTTP:Upgrade} websocket [NC]
		RewriteCond %{HTTP:Connection} upgrade [NC]
		RewriteRule .* ws://127.0.0.1:3000%{REQUEST_URI} [P,L]
		
		# Disable buffering
		SetEnv proxy-sendcl 1
		SetEnv proxy-interim-response RFC
	</Location>
	
	# /oauth/ location
	<Location /oauth/>
		ProxyPass http://127.0.0.1:3000/oauth/ timeout=300
		ProxyPassReverse http://127.0.0.1:3000/oauth/
		
		RequestHeader set X-Real-IP %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
	</Location>
   
	<Location /oauth/client-metadata.json>
		# Serve from local file first
		ProxyPass !
	</Location>
	<FilesMatch "client-metadata\.json$">
		 Header set Content-Type "application/json"
	</FilesMatch>
	<Directory /var/www/tranquil-pds/oauth>
		Require all granted
	</Directory>

	# /.well-known/ location
	<Location /.well-known/>
		ProxyPass http://127.0.0.1:3000/.well-known/
		ProxyPassReverse http://127.0.0.1:3000/.well-known/
		
		RequestHeader set X-Real-IP %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
	</Location>
	
	# /webhook/ location
	<Location /webhook/>
		ProxyPass http://127.0.0.1:3000/webhook/
		ProxyPassReverse http://127.0.0.1:3000/webhook/
		
		RequestHeader set X-Real-IP %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
	</Location>
	
	# /metrics location
	<Location /metrics>
		ProxyPass http://127.0.0.1:3000/metrics
		ProxyPassReverse http://127.0.0.1:3000/metrics
	</Location>
	
	# /health location
	<Location /health>
		ProxyPass http://127.0.0.1:3000/health
		ProxyPassReverse http://127.0.0.1:3000/health
	</Location>
	
	# /robots.txt location
	<Location /robots.txt>
		ProxyPass http://127.0.0.1:3000/robots.txt
		ProxyPassReverse http://127.0.0.1:3000/robots.txt
	</Location>
	
	# /logo location
	<Location /logo>
		ProxyPass http://127.0.0.1:3000/logo
		ProxyPassReverse http://127.0.0.1:3000/logo
	</Location>
	
	# /u/{username}/did.json pattern
	<LocationMatch "^/u/[^/]+/did\.json$">
		ProxyPass http://127.0.0.1:3000
		ProxyPassReverse http://127.0.0.1:3000
		
		RequestHeader set X-Real-IP %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
		RequestHeader set X-Forwarded-Proto %{REQUEST_SCHEME}s
	</LocationMatch>
	
	# /assets/ with caching
	<Directory /var/www/tranquil-pds/assets>
		Require all granted
	</Directory>
	
	# /app/ fallback to index.html
	<Directory /var/www/tranquil-pds/app>
		Require all granted
		FallbackResource /index.html
	</Directory>
	
	# Root directory
	<Directory /var/www/tranquil-pds>
		Require all granted
		Options -Indexes +FollowSymLinks
		AllowOverride None
		
		# Fallback handling for / and other paths
		RewriteEngine On
		RewriteCond %{REQUEST_URI} ^/$
		RewriteCond %{DOCUMENT_ROOT}/homepage.html -f
		RewriteRule ^(.*)$ /homepage.html [L]
		
		RewriteCond %{REQUEST_FILENAME} !-f
		RewriteCond %{REQUEST_FILENAME} !-d
		RewriteRule ^(.*)$ /index.html [L]
	</Directory>
	
	ErrorLog pds.example.com-error.log
	CustomLog pds.example.com-access.log combined
</VirtualHost>
sign up or login to add to the discussion
Labels

None yet.

assignee

None yet.

Participants 2
AT URI
at://did:plc:imp5q2a3i22bu2ukex42b2y5/sh.tangled.repo.issue/3meqgp5algm22