upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/docs/how-to
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-11 15:09:46 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-11 15:09:46 +0000
commit51a3d810d2a73a6300c51d3baf6060bb33f6b92c (patch)
tree8ee4cffadb787cfdbf96ce133c01fd2884048d57 /docs/how-to
parent2b082868713cb889677332344b559e45cf6a3c6c (diff)
docs: add production deployment how-to guide
- Complete guide for deploying ngit-grasp to NixOS servers - Step-by-step deployment instructions - Configuration options reference - Troubleshooting section - Security hardening recommendations - Multiple instance examples - References nix/example-configuration.nix which has clear examples
Diffstat (limited to 'docs/how-to')
-rw-r--r--docs/how-to/deploy.md487
1 files changed, 487 insertions, 0 deletions
diff --git a/docs/how-to/deploy.md b/docs/how-to/deploy.md
new file mode 100644
index 0000000..6fe8776
--- /dev/null
+++ b/docs/how-to/deploy.md
@@ -0,0 +1,487 @@
1# How-To: Deploy ngit-grasp to Production
2
3**Purpose:** Deploy ngit-grasp to a production NixOS server
4**Difficulty:** Intermediate
5**Time:** 30-60 minutes
6
7---
8
9## Problem
10
11You want to:
12- Deploy ngit-grasp to a NixOS server
13- Configure it as a systemd service
14- Set up reverse proxy (Caddy)
15- Ensure proper security and monitoring
16
17---
18
19## Prerequisites
20
21- NixOS server with SSH access
22- Flakes enabled on server and local machine
23- Domain name configured (DNS pointing to server)
24- Basic knowledge of NixOS configuration
25
26---
27
28## Solution
29
30### Step 1: Add ngit-grasp to Your Server's Flake
31
32In your server's `flake.nix`, add ngit-grasp as an input:
33
34```nix
35{
36 inputs = {
37 nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
38 ngit-grasp.url = "github:DanConwayDev/ngit-grasp";
39 # or use a specific git repository:
40 # ngit-grasp.url = "git+https://git.shakespeare.diy/npub.../ngit-grasp.git";
41 };
42
43 outputs = { self, nixpkgs, ngit-grasp, ... }@inputs: {
44 nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem {
45 system = "x86_64-linux";
46 specialArgs = { inherit inputs; };
47 modules = [
48 ./configuration.nix
49 # ... other modules
50 ];
51 };
52 };
53}
54```
55
56---
57
58### Step 2: Create Service Configuration
59
60Create a new file for your ngit-grasp service (e.g., `services/ngit-grasp.nix`):
61
62```nix
63{ inputs, ... }:
64
65{
66 imports = [ inputs.ngit-grasp.nixosModules.default ];
67
68 services.ngit-grasp.production = {
69 enable = true;
70 domain = "ngit.example.com";
71
72 # Network
73 bindAddress = "127.0.0.1";
74 port = 8082;
75
76 # Storage
77 dataDir = "/persistent/ngit-grasp";
78
79 # Identity
80 relayName = "My GRASP Relay";
81 relayDescription = "A Rust GRASP implementation with proactive sync";
82 relayOwnerNsecFile = "/persistent/ngit-grasp/relay-owner.nsec";
83
84 # Sync - bootstrap from relay.ngit.dev
85 syncBootstrapRelayUrl = "wss://relay.ngit.dev";
86
87 # Metrics
88 metricsEnabled = true;
89
90 # Logging
91 logLevel = "info";
92 };
93
94 # Caddy reverse proxy
95 services.caddy.virtualHosts."ngit.example.com" = {
96 extraConfig = ''
97 reverse_proxy 127.0.0.1:8082 {
98 header_down X-Real-IP {http.request.remote}
99 header_down X-Forwarded-For {http.request.remote}
100 }
101 '';
102 };
103}
104```
105
106**Key configuration options:**
107
108- **Instance name** (`production`): Can be any name. Used for systemd service (`ngit-grasp-production`)
109- **domain**: Your relay's domain (used in GRASP validation)
110- **port**: Local port (use reverse proxy for HTTPS)
111- **dataDir**: Where git repos and database are stored
112- **relayOwnerNsecFile**: Path to file containing relay owner's nsec
113 - If file doesn't exist, ngit-grasp will auto-generate one
114 - Alternative: `relayOwnerNsec = "nsec1..."` (less secure, in nix store)
115- **syncBootstrapRelayUrl**: Bootstrap relay to sync from on startup
116
117See [nix/example-configuration.nix](../../nix/example-configuration.nix) for more examples.
118
119---
120
121### Step 3: Import the Service
122
123Import your service configuration in your main configuration file:
124
125```nix
126# In configuration.nix or services/default.nix
127{
128 imports = [
129 ./services/ngit-grasp.nix
130 # ... other services
131 ];
132}
133```
134
135---
136
137### Step 4: Update Flake Lock
138
139```bash
140cd /path/to/server/config
141nix flake update ngit-grasp
142git add flake.lock
143git commit -m "Add ngit-grasp and update flake.lock"
144```
145
146---
147
148### Step 5: Validate Configuration
149
150Before deploying, validate the configuration builds:
151
152```bash
153nix flake check
154```
155
156---
157
158### Step 6: Deploy to Server
159
160Deploy the new configuration to your server:
161
162```bash
163# Build and switch in one command (builds on server)
164nixos-rebuild switch --flake .#your-hostname \
165 --target-host user@server.example.com \
166 --use-remote-sudo \
167 --build-host user@server.example.com
168```
169
170**Alternative:** Build locally, then deploy:
171
172```bash
173# Build locally
174nixos-rebuild build --flake .#your-hostname
175
176# Deploy to server
177nixos-rebuild switch --flake .#your-hostname \
178 --target-host user@server.example.com \
179 --use-remote-sudo
180```
181
182**Note:** Building locally requires your machine to trust the server's nix signing key.
183
184---
185
186### Step 7: Verify Deployment
187
188SSH to the server and check the service:
189
190```bash
191ssh user@server.example.com
192
193# Check service status
194systemctl status ngit-grasp-production
195
196# View logs
197journalctl -u ngit-grasp-production -f
198
199# Check if listening on port
200ss -tlnp | grep 8082
201```
202
203---
204
205### Step 8: Test Functionality
206
207From your local machine, test the relay:
208
209```bash
210# Test NIP-11 relay info
211curl https://ngit.example.com -H "Accept: application/nostr+json" | jq
212
213# Test WebSocket connection
214websocat wss://ngit.example.com
215# Then type: ["REQ","test",{}]
216# Should receive events
217
218# Test git clone (if you have repos)
219git ls-remote https://ngit.example.com/<npub>/<repo>.git
220```
221
222---
223
224## Configuration Options
225
226### Required
227- `enable` - Enable this instance
228- `domain` - Domain where relay is hosted
229
230### Network
231- `bindAddress` - IP to bind to (default: "127.0.0.1")
232- `port` - Port to listen on (default: 8080)
233
234### Storage
235- `dataDir` - Base directory for data (default: /var/lib/ngit-grasp-{name})
236- `databaseBackend` - "lmdb" | "nostr-db" | "memory" (default: "lmdb")
237
238### Identity
239- `relayName` - Relay name for NIP-11 (default: "{domain} grasp relay")
240- `relayDescription` - Relay description
241- `relayOwnerNsecFile` - Path to file with relay owner nsec (recommended)
242- `relayOwnerNsec` - Inline nsec (less secure)
243
244### Sync
245- `syncBootstrapRelayUrl` - Bootstrap relay URL (optional)
246- `syncDisableNegentropy` - Disable NIP-77 negentropy (default: false)
247- `syncMaxBackoffSecs` - Max backoff for reconnection (default: 3600)
248- `syncDisconnectCheckIntervalSecs` - Check interval (default: 60)
249- `syncBaseBackoffSecs` - Base backoff time (default: 5)
250
251### Metrics
252- `metricsEnabled` - Enable /metrics endpoint (default: true)
253- `metricsConnectionPerIpAbuseThreshold` - Abuse threshold (default: 10)
254- `metricsTopNRepos` - Number of top repos to track (default: 10)
255
256### Logging
257- `logLevel` - "trace" | "debug" | "info" | "warn" | "error" (default: "info")
258
259### Security
260- `user` - User to run as (default: "ngit-grasp-{name}")
261- `group` - Group to run as (default: "ngit-grasp")
262
263See [nix/module.nix](../../nix/module.nix) for complete option definitions.
264
265---
266
267## Systemd Service
268
269The NixOS module creates a systemd service: `ngit-grasp-{instance-name}`
270
271```bash
272# Start/stop/restart
273systemctl start ngit-grasp-production
274systemctl stop ngit-grasp-production
275systemctl restart ngit-grasp-production
276
277# Enable/disable autostart
278systemctl enable ngit-grasp-production
279systemctl disable ngit-grasp-production
280
281# View logs
282journalctl -u ngit-grasp-production -f
283journalctl -u ngit-grasp-production --since "1 hour ago"
284
285# Check status
286systemctl status ngit-grasp-production
287```
288
289---
290
291## Multiple Instances
292
293You can run multiple instances on the same server:
294
295```nix
296services.ngit-grasp = {
297 production = {
298 enable = true;
299 domain = "ngit.example.com";
300 port = 8082;
301 dataDir = "/persistent/ngit-production";
302 };
303
304 staging = {
305 enable = true;
306 domain = "ngit-staging.example.com";
307 port = 8083;
308 dataDir = "/persistent/ngit-staging";
309 logLevel = "debug";
310 };
311};
312```
313
314Each instance:
315- Runs as separate systemd service: `ngit-grasp-production`, `ngit-grasp-staging`
316- Has its own user: `ngit-grasp-production`, `ngit-grasp-staging`
317- Stores data in separate directory
318- Can have different configuration
319
320---
321
322## Troubleshooting
323
324### Service won't start
325
326**Check logs:**
327```bash
328journalctl -u ngit-grasp-production -n 50
329```
330
331**Common issues:**
332- Port already in use: Check with `ss -tlnp | grep 8082`
333- Data directory permissions: Should be owned by service user
334- Invalid nsec file: Check file exists and contains valid nsec
335
336### Can't connect via WebSocket
337
338**Check:**
339- Service is running: `systemctl status ngit-grasp-production`
340- Firewall allows connections: `nix-shell -p nmap --run "nmap -p 443 ngit.example.com"`
341- Caddy is configured correctly: `systemctl status caddy`
342- DNS resolves: `dig ngit.example.com`
343
344### Sync not working
345
346**Check logs for sync errors:**
347```bash
348journalctl -u ngit-grasp-production | grep -i sync
349```
350
351**Common issues:**
352- Bootstrap relay URL incorrect or unreachable
353- Network connectivity issues
354- Bootstrap relay doesn't support negentropy (disable with `syncDisableNegentropy = true`)
355
356### High memory/CPU usage
357
358**Monitor metrics:**
359```bash
360curl http://localhost:8082/metrics
361```
362
363**Tune configuration:**
364- Reduce `metricsTopNRepos`
365- Increase `syncMaxBackoffSecs`
366- Switch to `databaseBackend = "nostr-db"` for better performance
367
368---
369
370## Rollback
371
372If deployment fails, rollback to previous configuration:
373
374```bash
375# On the server
376nixos-rebuild switch --rollback
377
378# Or remotely
379nixos-rebuild switch --rollback \
380 --target-host user@server.example.com \
381 --use-remote-sudo
382```
383
384---
385
386## Upgrading
387
388To upgrade ngit-grasp:
389
390```bash
391# Update flake input
392nix flake update ngit-grasp
393
394# Review changes
395git diff flake.lock
396
397# Commit
398git add flake.lock
399git commit -m "Update ngit-grasp"
400
401# Deploy
402nixos-rebuild switch --flake .#your-hostname \
403 --target-host user@server.example.com \
404 --use-remote-sudo \
405 --build-host user@server.example.com
406```
407
408---
409
410## Security Hardening
411
412The NixOS module includes systemd hardening:
413
414- `NoNewPrivileges = true` - Prevents privilege escalation
415- `ProtectSystem = "strict"` - Read-only filesystem except dataDir
416- `ProtectHome = true` - No access to home directories
417- `PrivateTmp = true` - Private /tmp
418- `RestrictAddressFamilies` - Only allow needed network families
419- `SystemCallFilter` - Restrict system calls
420
421Additional recommendations:
422
4231. **Use nsec file instead of inline:**
424 ```nix
425 relayOwnerNsecFile = "/persistent/ngit-grasp/relay-owner.nsec";
426 # NOT: relayOwnerNsec = "nsec1..."; # Ends up in nix store!
427 ```
428
4292. **Restrict data directory permissions:**
430 ```bash
431 chmod 750 /persistent/ngit-grasp
432 chown ngit-grasp-production:ngit-grasp /persistent/ngit-grasp
433 ```
434
4353. **Use HTTPS (reverse proxy required):**
436 - ngit-grasp binds to localhost by default
437 - Use Caddy/nginx for TLS termination
438 - Caddy handles certificates automatically
439
4404. **Monitor logs regularly:**
441 ```bash
442 journalctl -u ngit-grasp-production --since today | grep -i error
443 ```
444
445---
446
447## Monitoring
448
449### Prometheus Metrics
450
451ngit-grasp exposes Prometheus metrics at `/metrics`:
452
453```bash
454curl http://localhost:8082/metrics
455```
456
457See [Prometheus Setup](./prometheus-setup.md) for complete monitoring guide.
458
459### Basic Health Checks
460
461```bash
462# Check if service is running
463systemctl is-active ngit-grasp-production
464
465# Check if port is listening
466nc -zv localhost 8082
467
468# Check relay info
469curl https://ngit.example.com -H "Accept: application/nostr+json"
470
471# Check disk usage
472du -sh /persistent/ngit-grasp/*
473```
474
475---
476
477## Related Documentation
478
479- [Configuration Reference](../reference/configuration.md) - All configuration options
480- [NixOS Module](../../nix/module.nix) - Module source code
481- [Example Configuration](../../nix/example-configuration.nix) - More examples
482- [Prometheus Setup](./prometheus-setup.md) - Monitoring guide
483- [Nix Flakes How-To](./nix-flakes.md) - Nix development environment
484
485---
486
487*Part of the [ngit-grasp how-to guides](./)*