11# Self-Host Your Own Happy Server
22
3- Run your own relay server in 3 minutes. Keep complete control over your Claude Code mobile setup.
3+ Run your own relay server in minutes. Keep complete control over your Claude Code mobile setup.
44
55## Why Run Your Own Server?
66
7- When you self-host Happy Server, you get:
7+ When you self-host the Happy Server, you get:
88- ** Total privacy** - Your encrypted data stays on your hardware
99- ** No limits** - Set your own rate limits and storage
1010- ** Team control** - Run one server for your whole team
1111- ** Zero dependencies** - Never worry about a service shutting down
1212
13- The entire server is only 900 lines of code. You can read it yourself to verify it just forwards encrypted messages.
13+ The entire server is only 1,293 lines of typescript. You can read it yourself to
14+ verify it just forwards encrypted messages.
1415
1516## Quick Start
1617
@@ -30,27 +31,37 @@ docker build -t happy-server:latest .
3031``` bash
3132docker run -d \
3233 --name happy-server \
33- -p 8080:8080 \
34- -v $( pwd) /data:/data \
34+ -p 3000:3000 \
35+ -e NODE_ENV=production \
36+ -e DATABASE_URL=" postgresql://postgres:postgres@localhost:5432/happy-server" \
37+ -e REDIS_URL=" redis://localhost:6379" \
38+ -e SEED=" your-seed-for-token-generation" \
39+ -e PORT=3005 \
3540 --restart unless-stopped \
3641 happy-server:latest
3742```
3843
44+ ** Important** : Replace the environment variable values with your actual configuration:
45+ - ` DATABASE_URL ` : Your PostgreSQL connection string
46+ - ` REDIS_URL ` : Your Redis connection string
47+ - ` SEED ` : A secure random seed for token generation
48+ - ` PORT ` : The port the application listens on (3005)
49+
3950### Step 3: Configure Your Devices
4051
4152** On your phone:**
42- 1 . Open Happy Coder app
53+ 1 . Open Happy app
43542 . Go to Settings
44- 3 . Set "Relay Server URL" to ` http://your-server:8080 `
55+ 3 . Set "Relay Server URL" to ` http://your-server:3000 `
45564 . Save
4657
4758** On your computer:**
4859``` bash
49- export HAPPY_SERVER_URL =" http://your-server:8080 "
50- happy # Now connects to your server
60+ export HANDY_SERVER_URL =" http://your-server:3000 "
61+ # Configure your CLI to use your server
5162```
5263
53- That's it! Your Happy Coder setup now runs through your own server.
64+ That's it! Your Happy setup now runs through your own server.
5465
5566## Production Setup with HTTPS
5667
@@ -67,7 +78,7 @@ sudo apt install caddy
6778# Configure reverse proxy
6879sudo tee /etc/caddy/Caddyfile << EOF
6980your-domain.com {
70- reverse_proxy localhost:8080
81+ reverse_proxy localhost:3000
7182}
7283EOF
7384
@@ -88,17 +99,45 @@ services:
8899 happy-server :
89100 image : happy-server:latest
90101 ports :
91- - " 8080:8080"
92- volumes :
93- - ./data:/data
102+ - " 3000:3000"
94103 restart : unless-stopped
95104 environment :
96- - MAX_BLOB_SIZE=100MB
97- - RATE_LIMIT=2000
105+ - NODE_ENV=production
106+ - DATABASE_URL=postgresql://postgres:postgres@localhost:5432/handy
107+ - REDIS_URL=redis://localhost:6379
108+ - SEED=your-seed-for-token-generation
109+ - PORT=3005
110+ depends_on :
111+ - postgres
112+ - redis
113+
114+ postgres :
115+ image : postgres:15
116+ environment :
117+ - POSTGRES_DB=handy
118+ - POSTGRES_USER=postgres
119+ - POSTGRES_PASSWORD=postgres
120+ volumes :
121+ - postgres_data:/var/lib/postgresql/data
122+ ports :
123+ - " 5432:5432"
124+
125+ redis :
126+ image : redis:7-alpine
127+ ports :
128+ - " 6379:6379"
129+ volumes :
130+ - redis_data:/data
131+
132+ volumes :
133+ postgres_data :
134+ redis_data :
98135` ` `
99136
100137Run with: ` docker-compose up -d`
101138
139+ This setup includes PostgreSQL and Redis containers that the Happy Server depends on.
140+
102141# # Where to Host
103142
104143# ## Option 1: Home Server (Free)
@@ -141,10 +180,10 @@ Check server health:
141180docker logs -f happy-server
142181
143182# Check health endpoint
144- curl http://your-server:8080 /health
183+ curl http://your-server:3000 /health
145184
146- # See connection count
147- curl http://your-server:8080 /stats
185+ # See connection count
186+ curl http://your-server:3000 /stats
148187` ` `
149188
150189# # Backup Your Data
@@ -161,36 +200,6 @@ rsync -av ./data/ backup-location/
161200
162201Remember : These backups are encrypted. No one can read them without your device keys.
163202
164- # # Troubleshooting
165-
166- # ## Can't Connect?
167-
168- Check these things :
169-
170- 1. **Server running?** `docker ps | grep happy-server`
171- 2. **Port open?** `curl http://localhost:8080/health`
172- 3. **Firewall?** `sudo ufw allow 8080`
173- 4. **Right URL?** Make sure both devices use the same server URL
174-
175- # ## Using a Corporate Proxy?
176-
177- Add proxy settings to Docker :
178- ` ` ` bash
179- docker run -d \
180- -e HTTP_PROXY=http://proxy.corp.com:8080 \
181- -e HTTPS_PROXY=http://proxy.corp.com:8080 \
182- happy-server:latest
183- ` ` `
184-
185- # ## Need More Performance?
186-
187- Increase rate limits :
188- ` ` ` bash
189- docker run -d \
190- -e RATE_LIMIT=5000 \
191- -e MAX_CONNECTIONS=1000 \
192- happy-server:latest
193- ` ` `
194203
195204# # Security Notes
196205
@@ -222,14 +231,19 @@ Self-hosting saves money and gives you control.
222231
223232# # Advanced: Kubernetes Deployment
224233
225- For teams using Kubernetes :
234+ For teams using Kubernetes, here's the production configuration :
226235
227236` ` ` yaml
228237apiVersion: apps/v1
229238kind: Deployment
230239metadata:
231240 name: happy-server
232241spec:
242+ strategy:
243+ type: RollingUpdate
244+ rollingUpdate:
245+ maxUnavailable: 0
246+ maxSurge: 1
233247 replicas: 1
234248 selector:
235249 matchLabels:
@@ -241,12 +255,23 @@ spec:
241255 spec:
242256 containers:
243257 - name: happy-server
244- image: happy-server:latest
258+ image: happy-server:latest # Use your actual image registry
245259 ports:
246- - containerPort: 8080
247- volumeMounts:
248- - name: data
249- mountPath: /data
260+ - containerPort: 3005
261+ envFrom:
262+ - secretRef:
263+ name: happy-secrets
264+ ---
265+ apiVersion: policy/v1
266+ kind: PodDisruptionBudget
267+ metadata:
268+ name: happy-server-pdb
269+ spec:
270+ minAvailable: 1
271+ selector:
272+ matchLabels:
273+ app: happy-server
274+
250275---
251276apiVersion: v1
252277kind: Service
@@ -256,11 +281,45 @@ spec:
256281 selector:
257282 app: happy-server
258283 ports:
259- - port: 80
260- targetPort: 8080
261- type: LoadBalancer
284+ - port: 3005
285+ targetPort: 3005
286+ type: ClusterIP
287+ ` ` `
288+
289+ **Configuration Notes**:
290+ - All ports now consistently use 3005 (the application's actual listening port)
291+ - Uses the `happy-secrets` secret created in the previous section
292+ - Update the image name to match your actual container registry
293+
294+ # # Kubernetes Secrets
295+
296+ Create a secret file for your environment variables :
297+
298+ ` ` ` yaml
299+ # happy-secrets.yaml
300+ apiVersion: v1
301+ kind: Secret
302+ metadata:
303+ name: happy-secrets
304+ type: Opaque
305+ stringData:
306+ DATABASE_URL: "postgresql://postgres:postgres@postgres-service:5432/handy"
307+ REDIS_URL: "redis://redis-service:6379"
308+ SEED: "your-secure-seed-for-token-generation"
309+ PORT: "3005"
310+ NODE_ENV: "production"
262311` ` `
263312
313+ Apply the secret :
314+ ` ` ` bash
315+ kubectl apply -f happy-secrets.yaml
316+ ` ` `
317+
318+ **Security Note**: Replace the values with your actual configuration. For production:
319+ - Use a strong, random SEED value
320+ - Use proper database credentials
321+ - Consider using external secret management tools like external-secrets-operator with Vault
322+
264323# # Next Steps
265324
266325After setting up your server :
0 commit comments