---
title: "Deploy SurfSense Self-Hosted Web"
description: "SurfSense NotebookLM alternative with local embeddings and signup gate"
category: "AI/ML"
url: https://railway.com/deploy/surfsense-self-hosted-web
---

# Deploy SurfSense Self-Hosted Web

SurfSense NotebookLM alternative with local embeddings and signup gate

**[Deploy SurfSense Self-Hosted Web on Railway](https://railway.com/template/surfsense-self-hosted-web)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/surfsense-self-hosted-web/manifest.json

- **Creator:** Protemplate
- **Category:** AI/ML
- **Total deploys:** 2

## Template content

### SurfSense https://raw.githubusercontent.com/MODSetter/SurfSense/main/surfsense_web/public/homepage/icon.png

- **Image:** caddy:2.11-alpine
- **Start command:** `sh -c 'echo IyEvYmluL3NoCiMgUmFpbHdheSBzdGFydCBjb21tYW5kIGZvciB0aGUgIlN1cmZTZW5zZSIgZ2F0ZXdheSBzZXJ2aWNlIChjYWRkeToyLjExLWFscGluZSkuCiMgVGhpcyBmaWxlIGlzIHRoZSBTT1VSQ0Ugb2YgdGhlIGJhc2U2NCBibG9iIGluIHNlcmlhbGl6ZWQtY29uZmlnLmpzb24gLT4KIyBzZXJ2aWNlcy4iU3VyZlNlbnNlIi5kZXBsb3kuc3RhcnRDb21tYW5kLiBBZnRlciBlZGl0aW5nLCByZWdlbmVyYXRlIHdpdGg6CiMgICBiYXNlNjQgPCBzdXJmc2Vuc2UtcmFpbHdheS9zdGFydC1nYXRld2F5LnNoIHwgdHIgLWQgJ1xuJwojIGFuZCBwYXN0ZSBpdCBiYWNrIGludG8gdGhlIHN0YXJ0Q29tbWFuZC4KIwojIFdoeSB0aGlzIGV4aXN0czoKIyAgMS4gVXBzdHJlYW0ncyBkb2NrZXIvcHJveHkvQ2FkZHlmaWxlIGlzIHRoZSBzaW5nbGUgcHVibGljIGVudHJ5IHBvaW50IGFuZAojICAgICByb3V0ZXMgYnkgcGF0aCB0byBmcm9udGVuZDozMDAwLCBiYWNrZW5kOjgwMDAgYW5kIHplcm8tY2FjaGU6NDg0OC4gT24KIyAgICAgUmFpbHdheSB0aG9zZSBhcmUgcHJpdmF0ZSBob3N0cywgc28gdGhlIENhZGR5ZmlsZSBpcyByZW5kZXJlZCBhdCBib290CiMgICAgIHdpdGggdGhlICoucmFpbHdheS5pbnRlcm5hbCB1cHN0cmVhbXMgZnJvbSB2YXJpYWJsZXMuCiMgIDIuIFNpZ251cCBnYXRlLiBTdXJmU2Vuc2UgaGFzIG9wZW4gc2VsZi1yZWdpc3RyYXRpb24sIGFuZCBpdHMgb3duCiMgICAgIFJFR0lTVFJBVElPTl9FTkFCTEVEPUZBTFNFIGFsc28gYmxvY2tzIExPR0lOIChhcHAvYXBwLnB5CiMgICAgIHJlZ2lzdHJhdGlvbl9hbGxvd2VkKCkpLCBzbyBpdCBjYW5ub3QgYmUgdXNlZCB0byBjbG9zZSBzaWdudXAuIFRoZQojICAgICBnYXRld2F5IGFza3MgZm9yIFNJR05VUF9VU0VSTkFNRSAvIFNJR05VUF9QQVNTV09SRCBiZWZvcmUgdGhlIC9yZWdpc3RlcgojICAgICBwYWdlIChmdWxsIHBhZ2UgbG9hZHMgb25seSkgYW5kIGJlZm9yZSBQT1NUIC9hdXRoL3JlZ2lzdGVyLiBFdmVyeXRoaW5nCiMgICAgIGVsc2UsIGluY2x1ZGluZyBsb2dpbiBhbmQgdGhlIEFQSSB1c2VkIGJ5IFBBVHMgLyBNQ1AgLyB0aGUgZXh0ZW5zaW9uLAojICAgICBzdGF5cyBvbiBTdXJmU2Vuc2UncyBvd24gYXV0aC4KIyAgMy4gQnJvd3NlcnMga2VlcCBzZW5kaW5nIHRoZSBjYWNoZWQgQmFzaWMgY3JlZGVudGlhbHMgdG8gZXZlcnkgcGF0aCBvbmNlCiMgICAgIHRoZSBnYXRlIHdhcyBwYXNzZWQuIFRoZXkgYXJlIHN0cmlwcGVkIGJlZm9yZSBwcm94eWluZywgc28gdGhlIGFwcCBvbmx5CiMgICAgIHNlZXMgaXRzIG93biBjb29raWVzLCBhbmQgaXRzIENTUkYgY2hlY2sgKHdoaWNoIGlzIHNraXBwZWQgZm9yIHJlcXVlc3RzCiMgICAgIHRoYXQgY2FycnkgYW4gQXV0aG9yaXphdGlvbiBoZWFkZXIpIHN0YXlzIGFjdGl2ZS4Kc2V0IC1lCjogIiR7UE9SVDo/UE9SVCBpcyByZXF1aXJlZH0iCjogIiR7U0lHTlVQX1VTRVJOQU1FOj9TSUdOVVBfVVNFUk5BTUUgaXMgcmVxdWlyZWR9Igo6ICIke1NJR05VUF9QQVNTV09SRDo/U0lHTlVQX1BBU1NXT1JEIGlzIHJlcXVpcmVkfSIKOiAiJHtXRUJfVVBTVFJFQU06P1dFQl9VUFNUUkVBTSBtdXN0IGJlIDxob3N0Pjo8cG9ydD4gb2YgdGhlIFN1cmZTZW5zZSBXZWIgc2VydmljZX0iCjogIiR7QVBJX1VQU1RSRUFNOj9BUElfVVBTVFJFQU0gbXVzdCBiZSA8aG9zdD46PHBvcnQ+IG9mIHRoZSBTdXJmU2Vuc2UgQVBJIHNlcnZpY2V9Igo6ICIke1pFUk9fVVBTVFJFQU06P1pFUk9fVVBTVFJFQU0gbXVzdCBiZSA8aG9zdD46PHBvcnQ+IG9mIHRoZSBaZXJvIENhY2hlIHNlcnZpY2V9IgpCT0RZPSIke01BWF9CT0RZX1NJWkU6LTFHQn0iCkhBU0g9IiQoY2FkZHkgaGFzaC1wYXNzd29yZCAtLXBsYWludGV4dCAiJFNJR05VUF9QQVNTV09SRCIpIgoKY2F0ID4gL2V0Yy9jYWRkeS9DYWRkeWZpbGUgPDxFT0YKewoJYXV0b19odHRwcyBvZmYKCWFkbWluIG9mZgoJc2VydmVycyB7CgkJdHJ1c3RlZF9wcm94aWVzIHN0YXRpYyAwLjAuMC4wLzAgOjovMAoJCWNsaWVudF9pcF9oZWFkZXJzIFgtRm9yd2FyZGVkLUZvciBYLVJlYWwtSVAKCX0KfQoKOiR7UE9SVH0gewoJcmVxdWVzdF9ib2R5IHsKCQltYXhfc2l6ZSAke0JPRFl9Cgl9CgoJQHNpZ251cF9wYWdlIHsKCQlwYXRoIC9yZWdpc3RlciAvcmVnaXN0ZXIvKgoJCW5vdCBoZWFkZXIgUlNDICoKCX0KCWJhc2ljX2F1dGggQHNpZ251cF9wYWdlIHsKCQkke1NJR05VUF9VU0VSTkFNRX0gJHtIQVNIfQoJfQoJQHNpZ251cF9hcGkgcGF0aCAvYXV0aC9yZWdpc3RlciAvYXV0aC9yZWdpc3Rlci8qCgliYXNpY19hdXRoIEBzaWdudXBfYXBpIHsKCQkke1NJR05VUF9VU0VSTkFNRX0gJHtIQVNIfQoJfQoKCUBiYXNpYyBoZWFkZXJfcmVnZXhwIEF1dGhvcml6YXRpb24gXkJhc2ljXHMKCXJlcXVlc3RfaGVhZGVyIEBiYXNpYyAtQXV0aG9yaXphdGlvbgoKCWhhbmRsZSAvZ2F0ZXdheS1oZWFsdGggewoJCXJlc3BvbmQgIm9rIiAyMDAKCX0KCWhhbmRsZSAvYXV0aC9jYWxsYmFjayogewoJCXJldmVyc2VfcHJveHkgJHtXRUJfVVBTVFJFQU19Cgl9CgloYW5kbGUgL2F1dGgvKiB7CgkJcmV2ZXJzZV9wcm94eSAke0FQSV9VUFNUUkVBTX0KCX0KCWhhbmRsZSAvdXNlcnMvKiB7CgkJcmV2ZXJzZV9wcm94eSAke0FQSV9VUFNUUkVBTX0KCX0KCWhhbmRsZSAvYXBpL3YxLyogewoJCXJldmVyc2VfcHJveHkgJHtBUElfVVBTVFJFQU19IHsKCQkJZmx1c2hfaW50ZXJ2YWwgLTEKCQl9Cgl9CgloYW5kbGUgL3plcm8vY29udGV4dCB7CgkJcmV2ZXJzZV9wcm94eSAke0FQSV9VUFNUUkVBTX0KCX0KCWhhbmRsZSAvemVyby8qIHsKCQlyZXZlcnNlX3Byb3h5ICR7WkVST19VUFNUUkVBTX0KCX0KCWhhbmRsZSB7CgkJcmV2ZXJzZV9wcm94eSAke1dFQl9VUFNUUkVBTX0KCX0KfQpFT0YKCmVjaG8gInN1cmZzZW5zZS1nYXRld2F5OiBsaXN0ZW5pbmcgb24gOiRQT1JUOyB3ZWI9JFdFQl9VUFNUUkVBTSBhcGk9JEFQSV9VUFNUUkVBTSB6ZXJvPSRaRVJPX1VQU1RSRUFNOyBzaWdudXAgZ2F0ZSBvbiAvcmVnaXN0ZXIgYW5kIC9hdXRoL3JlZ2lzdGVyIgpleGVjIGNhZGR5IHJ1biAtLWNvbmZpZyAvZXRjL2NhZGR5L0NhZGR5ZmlsZSAtLWFkYXB0ZXIgY2FkZHlmaWxlCg== | base64 -d > /tmp/railway-start.sh && exec sh /tmp/railway-start.sh'`
- **Health check:** /gateway-health
- **Public domain:** Yes

### Redis https://avatars.githubusercontent.com/u/1529926?v=4

- **Image:** redis:7.4.2-alpine
- **Start command:** `sh -c 'exec docker-entrypoint.sh redis-server --requirepass "$REDIS_PASSWORD" --appendonly yes --dir /data --bind :: 0.0.0.0'`

### SurfSense Web https://raw.githubusercontent.com/MODSetter/SurfSense/main/surfsense_web/public/homepage/icon.png

- **Image:** ghcr.io/modsetter/surfsense-web:git-a51f9a3
- **Health check:** /robots.txt

### SurfSense API https://raw.githubusercontent.com/MODSetter/SurfSense/main/surfsense_web/public/homepage/icon.png

- **Image:** ghcr.io/modsetter/surfsense-backend:git-a51f9a3
- **Start command:** `sh -c 'echo IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoiIiJSYWlsd2F5IHN0YXJ0IGNvbW1hbmQgZm9yIHRoZSAiU3VyZlNlbnNlIEFQSSIgc2VydmljZQooZ2hjci5pby9tb2RzZXR0ZXIvc3VyZnNlbnNlLWJhY2tlbmQsIFNFUlZJQ0VfUk9MRT1hbGwpLgoKVGhpcyBmaWxlIGlzIHRoZSBTT1VSQ0Ugb2YgdGhlIGJhc2U2NCBibG9iIGluIHNlcmlhbGl6ZWQtY29uZmlnLmpzb24gLT4Kc2VydmljZXMuIlN1cmZTZW5zZSBBUEkiLmRlcGxveS5zdGFydENvbW1hbmQuIEFmdGVyIGVkaXRpbmcsIHJlZ2VuZXJhdGUgd2l0aDoKICBiYXNlNjQgPCBzdXJmc2Vuc2UtcmFpbHdheS9zdGFydC1hcGkucHkgfCB0ciAtZCAnXG4nCmFuZCBwYXN0ZSBpdCBiYWNrIGludG8gdGhlIHN0YXJ0Q29tbWFuZC4KCldoeTogdGhlIGdhdGV3YXkgYW5kIHRoZSBOZXh0LmpzIHNlcnZlciBjYWxsIHRoaXMgc2VydmljZSBvdmVyIFJhaWx3YXkncwpwcml2YXRlIG5ldHdvcmsgKElQdjYpLCB3aGlsZSBSYWlsd2F5J3MgaGVhbHRoY2hlY2sgYXJyaXZlcyBvdmVyIElQdjQuCnV2aWNvcm4gYmluZHMgb25lIGFkZHJlc3MgZmFtaWx5IGF0IGEgdGltZSAoVVZJQ09STl9IT1NUPTo6IGlzIElQdjYgb25seQp1bmRlciBhc3luY2lvKSwgc28gdGhpcyBjcmVhdGVzIG9uZSBkdWFsLXN0YWNrIGxpc3RlbmluZyBzb2NrZXQKKElQVjZfVjZPTkxZPTApIGFuZCBoYW5kcyBpdCB0byB1dmljb3JuIHRocm91Z2ggVVZJQ09STl9GRCwgd2hpY2gKYXBwL2NvbmZpZy91dmljb3JuLnB5IGFscmVhZHkgc3VwcG9ydHMuIFRoZW4gaXQgZXhlY3MgdGhlIGltYWdlJ3Mgb3duCmVudHJ5cG9pbnQgdW5jaGFuZ2VkLCBzbyBTRVJWSUNFX1JPTEU9YWxsIHN0aWxsIHJ1bnMgbWlncmF0aW9ucywgdGhlIEFQSSwKdGhlIENlbGVyeSB3b3JrZXIgYW5kIENlbGVyeSBiZWF0IGV4YWN0bHkgYXMgdXBzdHJlYW0gZG9lcy4KIiIiCmltcG9ydCBvcwppbXBvcnQgc29ja2V0Cgpwb3J0ID0gaW50KG9zLmVudmlyb24uZ2V0KCJQT1JUIiwgIjgwMDAiKSkKc29jayA9IHNvY2tldC5zb2NrZXQoc29ja2V0LkFGX0lORVQ2LCBzb2NrZXQuU09DS19TVFJFQU0pCnNvY2suc2V0c29ja29wdChzb2NrZXQuU09MX1NPQ0tFVCwgc29ja2V0LlNPX1JFVVNFQUREUiwgMSkKc29jay5zZXRzb2Nrb3B0KHNvY2tldC5JUFBST1RPX0lQVjYsIHNvY2tldC5JUFY2X1Y2T05MWSwgMCkKc29jay5iaW5kKCgiOjoiLCBwb3J0KSkKc29jay5saXN0ZW4oMjA0OCkKb3Muc2V0X2luaGVyaXRhYmxlKHNvY2suZmlsZW5vKCksIFRydWUpCm9zLmVudmlyb25bIlVWSUNPUk5fRkQiXSA9IHN0cihzb2NrLmZpbGVubygpKQpwcmludCgKICAgIGYic3VyZnNlbnNlLWFwaTogZHVhbC1zdGFjayBsaXN0ZW5lciBvbiBbOjpdOntwb3J0fSAoZmQge3NvY2suZmlsZW5vKCl9KSwgIgogICAgZiJTRVJWSUNFX1JPTEU9e29zLmVudmlyb24uZ2V0KCdTRVJWSUNFX1JPTEUnLCAnYWxsJyl9IiwKICAgIGZsdXNoPVRydWUsCikKZW50cnlwb2ludCA9ICIvYXBwL3NjcmlwdHMvZG9ja2VyL2VudHJ5cG9pbnQuc2giCm9zLmV4ZWN2KGVudHJ5cG9pbnQsIFtlbnRyeXBvaW50XSkK | base64 -d > /tmp/railway-start.py && exec python3 /tmp/railway-start.py'`
- **Health check:** /ready

### Postgres https://avatars.githubusercontent.com/u/177543?v=4

- **Image:** pgvector/pgvector:pg17
- **Start command:** `docker-entrypoint.sh postgres -c "listen_addresses=*" -c wal_level=logical -c max_replication_slots=10 -c max_wal_senders=10 -c max_connections=200 -c shared_buffers=256MB`

### Zero Cache https://avatars.githubusercontent.com/u/54663044?v=4

- **Image:** rocicorp/zero:1.6.0
- **Start command:** `sh -c 'echo IyEvYmluL3NoCiMgUmFpbHdheSBzdGFydCBjb21tYW5kIGZvciB0aGUgIlplcm8gQ2FjaGUiIHNlcnZpY2UgKHJvY2ljb3JwL3plcm86MS42LjAsIEFscGluZSwgcm9vdCkuCiMgVGhpcyBmaWxlIGlzIHRoZSBTT1VSQ0Ugb2YgdGhlIGJhc2U2NCBibG9iIGluIHNlcmlhbGl6ZWQtY29uZmlnLmpzb24gLT4KIyBzZXJ2aWNlcy4iWmVybyBDYWNoZSIuZGVwbG95LnN0YXJ0Q29tbWFuZC4gQWZ0ZXIgZWRpdGluZywgcmVnZW5lcmF0ZSB3aXRoOgojICAgYmFzZTY0IDwgc3VyZnNlbnNlLXJhaWx3YXkvc3RhcnQtemVyby1jYWNoZS5zaCB8IHRyIC1kICdcbicKIyBhbmQgcGFzdGUgaXQgYmFjayBpbnRvIHRoZSBzdGFydENvbW1hbmQuCiMKIyBXaHk6IHplcm8tY2FjaGUgcmVwbGljYXRlcyB0aGUgYHplcm9fcHVibGljYXRpb25gIHB1YmxpY2F0aW9uLCB3aGljaCB0aGUKIyBTdXJmU2Vuc2UgQVBJIGNyZWF0ZXMgaW4gaXRzIEFsZW1iaWMgbWlncmF0aW9ucy4gVXBzdHJlYW0gY29tcG9zZSBtYWtlcwojIHplcm8tY2FjaGUgd2FpdCBmb3IgdGhlIG9uZS1zaG90IGBtaWdyYXRpb25zYCBzZXJ2aWNlCiMgKGNvbmRpdGlvbjogc2VydmljZV9jb21wbGV0ZWRfc3VjY2Vzc2Z1bGx5KS4gUmFpbHdheSBzdGFydHMgZXZlcnkgc2VydmljZSBhdAojIG9uY2UsIGFuZCB1cHN0cmVhbSdzIGRvY3Mgc2F5IGEgemVyby1jYWNoZSB0aGF0IHN0YXJ0cyBiZWZvcmUgdGhlCiMgcHVibGljYXRpb24gZXhpc3RzIGNhbiBnZXQgc3R1Y2sgb24gIlVua25vd24gb3IgaW52YWxpZCBwdWJsaWNhdGlvbnMiIHdpdGggYQojIGhhbGYtYnVpbHQgcmVwbGljYSB0aGF0IGhhcyB0byBiZSB3aXBlZCBieSBoYW5kLiBTbyB3YWl0IHVudGlsIHRoZSBBUEkncwojIC9yZWFkeSBlbmRwb2ludCAoMjAwIG9ubHkgb25jZSB6ZXJvX3B1YmxpY2F0aW9uIGV4aXN0cykgYW5zd2VycywgdGhlbiBydW4KIyB0aGUgaW1hZ2UncyBvd24gY29tbWFuZC4gTm9kZSAyMiBpcyBpbiB0aGUgaW1hZ2UsIHNvIG5vIGV4dHJhIHRvb2xzIG5lZWRlZC4Kc2V0IC1lCjogIiR7U1VSRlNFTlNFX1JFQURZX1VSTDo/U1VSRlNFTlNFX1JFQURZX1VSTCBtdXN0IGJlIGh0dHA6Ly88U3VyZlNlbnNlIEFQSSBwcml2YXRlIGhvc3Q+OjgwMDAvcmVhZHl9IgppPTAKdW50aWwgbm9kZSAtZSAnZmV0Y2gocHJvY2Vzcy5lbnYuU1VSRlNFTlNFX1JFQURZX1VSTCx7c2lnbmFsOkFib3J0U2lnbmFsLnRpbWVvdXQoNTAwMCl9KS50aGVuKHI9PnByb2Nlc3MuZXhpdChyLm9rPzA6MSksKCk9PnByb2Nlc3MuZXhpdCgxKSknOyBkbwogIGk9JCgoaSsxKSkKICBlY2hvICJ6ZXJvLWNhY2hlOiB3YWl0aW5nIGZvciBTdXJmU2Vuc2UgQVBJIG1pZ3JhdGlvbnMgKHplcm9fcHVibGljYXRpb24pIGF0ICRTVVJGU0VOU0VfUkVBRFlfVVJMLCBhdHRlbXB0ICRpIgogIHNsZWVwIDUKZG9uZQplY2hvICJ6ZXJvLWNhY2hlOiB6ZXJvX3B1YmxpY2F0aW9uIHByZXNlbnQsIHN0YXJ0aW5nIHplcm8tY2FjaGUgb24gcG9ydCAke1pFUk9fUE9SVDotNDg0OH0iCmV4ZWMgbnB4IHplcm8tY2FjaGUK | base64 -d > /tmp/railway-start.sh && exec sh /tmp/railway-start.sh'`
- **Health check:** /keepalive

## Documentation

# Deploy and Host SurfSense on Railway

SurfSense is a privacy-focused, open-source alternative to NotebookLM for individuals and teams. Upload PDFs, Office files and Markdown, capture web pages, connect Notion, Slack, Google Drive, Jira and more, then ask questions across everything with cited answers and turn your sources into reports, slide decks, podcasts and study material. You choose the model: OpenAI, Anthropic, OpenRouter, Azure, Ollama, LM Studio or any OpenAI-compatible endpoint.

## About Hosting SurfSense

Hosting SurfSense means running a Next.js web app, a FastAPI backend with Celery background workers, Rocicorp Zero for real-time sync, PostgreSQL with pgvector and logical replication, and Redis, all behind one reverse proxy. This template mirrors upstream's `docker/docker-compose.yml` as six Railway services, with images pinned to the immutable `git-a51f9a3` build. Only the Caddy gateway is public; it routes `/api/v1`, `/auth` and `/zero` over the private network exactly like upstream's Caddyfile. The API, Celery worker, Celery beat and migrations run together in one service (upstream's `SERVICE_ROLE=all`) because uploads are handed from the API to the worker as local files, and Railway volumes cannot be shared between services. Zero Cache waits for the migrations before it starts, the API binds a dual-stack socket, and Postgres runs with `wal_level=logical`.

**Signup is protected.** SurfSense lets anyone who reaches the URL register, and its own switch to turn that off also disables login. The gateway therefore asks for a generated signup password before anyone can open `/register` or create an account. Login and API tokens are unaffected.

**Plan requirement:** the API image is about 2.2 GB and loads PyTorch, Docling and a local embedding model, so use the Hobby plan or higher. The first deploy takes several minutes.

Upstream note: SurfSense's maintainers now recommend their desktop app for new users; the self-hosted web stack remains open source and community supported. SurfSense is Apache-2.0 except a BSL-1.1 scraper module, which may be used in production but not resold as a hosted service.

## Common Use Cases

- **Private NotebookLM for a team**: shared workspaces over your own documents, with your own model keys
- **Research assistant**: cited answers across papers, notes, captured web pages and connected tools
- **Knowledge base over SaaS tools**: index Notion, Slack, Google Drive, Gmail, Jira, Linear, Confluence and more
- **Content from sources**: summaries, reports, slide decks and two-host podcasts generated from selected documents
- **Local model friendly**: point it at Ollama, LM Studio or vLLM; parsing and embeddings already run locally

## Dependencies for SurfSense Hosting

- **PostgreSQL 17 with pgvector**: included, with logical replication enabled for Zero
- **Redis**: included, Celery broker and cache
- **Rocicorp Zero**: included, real-time sync
- **A model provider**: not needed to boot; add one after deploy under Workspace Settings, Models
- **No GPU required**: Docling parsing, MiniLM embeddings, Kokoro TTS and Whisper STT run on CPU

### Deployment Dependencies

- [SurfSense Docker installation guide](https://github.com/MODSetter/SurfSense/blob/main/surfsense_web/content/docs/legacy/docker-installation/index.mdx)
- [Upstream docker-compose.yml](https://github.com/MODSetter/SurfSense/blob/main/docker/docker-compose.yml)
- [Environment reference (.env.example)](https://github.com/MODSetter/SurfSense/blob/main/docker/.env.example)
- [SurfSense GitHub repository](https://github.com/MODSetter/SurfSense)

### Implementation Details

First steps after deploy:

1. Wait until all six services are green (Zero Cache turns green after the API finishes its migrations)
2. Copy `SIGNUP_PASSWORD` from the **SurfSense** service, Variables tab
3. Open `https:///register`, enter `admin` and that password in the browser prompt, then create your account
4. Open **Workspace Settings, Models** and add a provider key or a local model server URL
5. Upload a document or add a note and start asking questions

Key variables:

```env
# SurfSense (gateway, public)
PORT=8080
SIGNUP_USERNAME=admin
SIGNUP_PASSWORD=${{secret(24)}}
WEB_UPSTREAM=${{SurfSense Web.RAILWAY_PRIVATE_DOMAIN}}:3000
API_UPSTREAM=${{SurfSense API.RAILWAY_PRIVATE_DOMAIN}}:8000
ZERO_UPSTREAM=${{Zero Cache.RAILWAY_PRIVATE_DOMAIN}}:4848

# SurfSense API
PORT=8000
SERVICE_ROLE=all
SECRET_KEY=${{secret(64)}}
DATABASE_URL=postgresql+asyncpg://${{Postgres.POSTGRES_USER}}:${{Postgres.POSTGRES_PASSWORD}}@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/${{Postgres.POSTGRES_DB}}
REDIS_URL=${{Redis.REDIS_URL}}
SURFSENSE_PUBLIC_URL=https://${{SurfSense.RAILWAY_PUBLIC_DOMAIN}}
REGISTRATION_ENABLED=TRUE
EMBEDDING_MODEL=sentence-transformers/all-MiniLM-L6-v2
SANDBOX_ENABLED=FALSE
FILE_STORAGE_LOCAL_PATH=/data/object_store

# SurfSense Web
PORT=3000
HOSTNAME=::
SURFSENSE_BACKEND_INTERNAL_URL=http://${{SurfSense API.RAILWAY_PRIVATE_DOMAIN}}:8000
ZERO_QUERY_API_KEY=${{Zero Cache.ZERO_QUERY_API_KEY}}

# Zero Cache
ZERO_UPSTREAM_DB=postgresql://...@${{Postgres.RAILWAY_PRIVATE_DOMAIN}}:5432/surfsense?sslmode=disable
ZERO_APP_PUBLICATIONS=zero_publication
ZERO_QUERY_URL=http://${{SurfSense Web.RAILWAY_PRIVATE_DOMAIN}}:3000/api/zero/query
```

Keep `REGISTRATION_ENABLED=TRUE` (in SurfSense, FALSE also blocks login). Set `EMBEDDING_MODEL` once: changing it after documents are indexed breaks the vector dimensions. The code execution sandbox is off because upstream's sandbox server needs the Docker socket; set `SANDBOX_PROVIDER=daytona` with a Daytona key to enable it.

## Why Deploy SurfSense on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying SurfSense on Railway, you get a complete self-hosted research workspace with Postgres, pgvector, Redis and real-time sync wired together over private networking, generated secrets, persistent volumes, healthchecks, a gated signup, and managed SSL on one public domain.


## Similar templates

- [Chat Chat](https://railway.com/deploy/-WWW5r) — Chat Chat, your own unified chat and search to AI platform.
- [stella](https://railway.com/deploy/stella) — Self-host stella with web, API, Postgres, Redis, and object storage.
- [Hermes Agent | OpenClaw Alternative with Dashboard](https://railway.com/deploy/hermes-agent-or-openclaw-alternative-wit) — Self-Hosted Hermes AI Agent for Telegram, Discord & Slack

Open this page in a browser: https://railway.com/deploy/surfsense-self-hosted-web
