Files
ngit-grasp/docs/how-to/deploy.md
T

488 lines
11 KiB
Markdown

# How-To: Deploy ngit-grasp to Production
**Purpose:** Deploy ngit-grasp to a production NixOS server
**Difficulty:** Intermediate
**Time:** 30-60 minutes
---
## Problem
You want to:
- Deploy ngit-grasp to a NixOS server
- Configure it as a systemd service
- Set up reverse proxy (Caddy)
- Ensure proper security and monitoring
---
## Prerequisites
- NixOS server with SSH access
- Flakes enabled on server and local machine
- Domain name configured (DNS pointing to server)
- Basic knowledge of NixOS configuration
---
## Solution
### Step 1: Add ngit-grasp to Your Server's Flake
In your server's `flake.nix`, add ngit-grasp as an input:
```nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
ngit-grasp.url = "github:DanConwayDev/ngit-grasp";
# or use a specific git repository:
# ngit-grasp.url = "git+https://git.shakespeare.diy/npub.../ngit-grasp.git";
};
outputs = { self, nixpkgs, ngit-grasp, ... }@inputs: {
nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [
./configuration.nix
# ... other modules
];
};
};
}
```
---
### Step 2: Create Service Configuration
Create a new file for your ngit-grasp service (e.g., `services/ngit-grasp.nix`):
```nix
{ inputs, ... }:
{
imports = [ inputs.ngit-grasp.nixosModules.default ];
services.ngit-grasp.production = {
enable = true;
domain = "ngit.example.com";
# Network
bindAddress = "127.0.0.1";
port = 8082;
# Storage
dataDir = "/persistent/ngit-grasp";
# Identity
relayName = "My GRASP Relay";
relayDescription = "A Rust GRASP implementation with proactive sync";
relayOwnerNsecFile = "/persistent/ngit-grasp/relay-owner.nsec";
# Sync - bootstrap from relay.ngit.dev
syncBootstrapRelayUrl = "wss://relay.ngit.dev";
# Metrics
metricsEnabled = true;
# Logging
logLevel = "info";
};
# Caddy reverse proxy
services.caddy.virtualHosts."ngit.example.com" = {
extraConfig = ''
reverse_proxy 127.0.0.1:8082 {
header_down X-Real-IP {http.request.remote}
header_down X-Forwarded-For {http.request.remote}
}
'';
};
}
```
**Key configuration options:**
- **Instance name** (`production`): Can be any name. Used for systemd service (`ngit-grasp-production`)
- **domain**: Your relay's domain (used in GRASP validation)
- **port**: Local port (use reverse proxy for HTTPS)
- **dataDir**: Where git repos and database are stored
- **relayOwnerNsecFile**: Path to file containing relay owner's nsec
- If file doesn't exist, ngit-grasp will auto-generate one
- Alternative: `relayOwnerNsec = "nsec1..."` (less secure, in nix store)
- **syncBootstrapRelayUrl**: Bootstrap relay to sync from on startup
See [nix/example-configuration.nix](../../nix/example-configuration.nix) for more examples.
---
### Step 3: Import the Service
Import your service configuration in your main configuration file:
```nix
# In configuration.nix or services/default.nix
{
imports = [
./services/ngit-grasp.nix
# ... other services
];
}
```
---
### Step 4: Update Flake Lock
```bash
cd /path/to/server/config
nix flake update ngit-grasp
git add flake.lock
git commit -m "Add ngit-grasp and update flake.lock"
```
---
### Step 5: Validate Configuration
Before deploying, validate the configuration builds:
```bash
nix flake check
```
---
### Step 6: Deploy to Server
Deploy the new configuration to your server:
```bash
# Build and switch in one command (builds on server)
nixos-rebuild switch --flake .#your-hostname \
--target-host user@server.example.com \
--use-remote-sudo \
--build-host user@server.example.com
```
**Alternative:** Build locally, then deploy:
```bash
# Build locally
nixos-rebuild build --flake .#your-hostname
# Deploy to server
nixos-rebuild switch --flake .#your-hostname \
--target-host user@server.example.com \
--use-remote-sudo
```
**Note:** Building locally requires your machine to trust the server's nix signing key.
---
### Step 7: Verify Deployment
SSH to the server and check the service:
```bash
ssh user@server.example.com
# Check service status
systemctl status ngit-grasp-production
# View logs
journalctl -u ngit-grasp-production -f
# Check if listening on port
ss -tlnp | grep 8082
```
---
### Step 8: Test Functionality
From your local machine, test the relay:
```bash
# Test NIP-11 relay info
curl https://ngit.example.com -H "Accept: application/nostr+json" | jq
# Test WebSocket connection
websocat wss://ngit.example.com
# Then type: ["REQ","test",{}]
# Should receive events
# Test git clone (if you have repos)
git ls-remote https://ngit.example.com/<npub>/<repo>.git
```
---
## Configuration Options
### Required
- `enable` - Enable this instance
- `domain` - Domain where relay is hosted
### Network
- `bindAddress` - IP to bind to (default: "127.0.0.1")
- `port` - Port to listen on (default: 7334)
### Storage
- `dataDir` - Base directory for data (default: /var/lib/ngit-grasp-{name})
- `databaseBackend` - "lmdb" | "memory" (default: "lmdb")
### Identity
- `relayName` - Relay name for NIP-11 (default: "{domain} grasp relay")
- `relayDescription` - Relay description
- `relayOwnerNsecFile` - Path to file with relay owner nsec (recommended)
- `relayOwnerNsec` - Inline nsec (less secure)
### Sync
- `syncBootstrapRelayUrl` - Bootstrap relay URL (optional)
- `syncDisableNegentropy` - Disable NIP-77 negentropy (default: false)
- `syncMaxBackoffSecs` - Max backoff for reconnection (default: 3600)
- `syncDisconnectCheckIntervalSecs` - Check interval (default: 60)
- `syncBaseBackoffSecs` - Base backoff time (default: 5)
### Metrics
- `metricsEnabled` - Enable /metrics endpoint (default: true)
- `metricsConnectionPerIpAbuseThreshold` - Abuse threshold (default: 10)
- `metricsTopNRepos` - Number of top repos to track (default: 10)
### Logging
- `logLevel` - "trace" | "debug" | "info" | "warn" | "error" (default: "info")
### Security
- `user` - User to run as (default: "ngit-grasp-{name}")
- `group` - Group to run as (default: "ngit-grasp")
See [nix/module.nix](../../nix/module.nix) for complete option definitions.
---
## Systemd Service
The NixOS module creates a systemd service: `ngit-grasp-{instance-name}`
```bash
# Start/stop/restart
systemctl start ngit-grasp-production
systemctl stop ngit-grasp-production
systemctl restart ngit-grasp-production
# Enable/disable autostart
systemctl enable ngit-grasp-production
systemctl disable ngit-grasp-production
# View logs
journalctl -u ngit-grasp-production -f
journalctl -u ngit-grasp-production --since "1 hour ago"
# Check status
systemctl status ngit-grasp-production
```
---
## Multiple Instances
You can run multiple instances on the same server:
```nix
services.ngit-grasp = {
production = {
enable = true;
domain = "ngit.example.com";
port = 8082;
dataDir = "/persistent/ngit-production";
};
staging = {
enable = true;
domain = "ngit-staging.example.com";
port = 8083;
dataDir = "/persistent/ngit-staging";
logLevel = "debug";
};
};
```
Each instance:
- Runs as separate systemd service: `ngit-grasp-production`, `ngit-grasp-staging`
- Has its own user: `ngit-grasp-production`, `ngit-grasp-staging`
- Stores data in separate directory
- Can have different configuration
---
## Troubleshooting
### Service won't start
**Check logs:**
```bash
journalctl -u ngit-grasp-production -n 50
```
**Common issues:**
- Port already in use: Check with `ss -tlnp | grep 8082`
- Data directory permissions: Should be owned by service user
- Invalid nsec file: Check file exists and contains valid nsec
### Can't connect via WebSocket
**Check:**
- Service is running: `systemctl status ngit-grasp-production`
- Firewall allows connections: `nix-shell -p nmap --run "nmap -p 443 ngit.example.com"`
- Caddy is configured correctly: `systemctl status caddy`
- DNS resolves: `dig ngit.example.com`
### Sync not working
**Check logs for sync errors:**
```bash
journalctl -u ngit-grasp-production | grep -i sync
```
**Common issues:**
- Bootstrap relay URL incorrect or unreachable
- Network connectivity issues
- Bootstrap relay doesn't support negentropy (disable with `syncDisableNegentropy = true`)
### High memory/CPU usage
**Monitor metrics:**
```bash
curl http://localhost:8082/metrics
```
**Tune configuration:**
- Reduce `metricsTopNRepos`
- Increase `syncMaxBackoffSecs`
- Tune `syncMaxBackoffSecs` for your network conditions
---
## Rollback
If deployment fails, rollback to previous configuration:
```bash
# On the server
nixos-rebuild switch --rollback
# Or remotely
nixos-rebuild switch --rollback \
--target-host user@server.example.com \
--use-remote-sudo
```
---
## Upgrading
To upgrade ngit-grasp:
```bash
# Update flake input
nix flake update ngit-grasp
# Review changes
git diff flake.lock
# Commit
git add flake.lock
git commit -m "Update ngit-grasp"
# Deploy
nixos-rebuild switch --flake .#your-hostname \
--target-host user@server.example.com \
--use-remote-sudo \
--build-host user@server.example.com
```
---
## Security Hardening
The NixOS module includes systemd hardening:
- `NoNewPrivileges = true` - Prevents privilege escalation
- `ProtectSystem = "strict"` - Read-only filesystem except dataDir
- `ProtectHome = true` - No access to home directories
- `PrivateTmp = true` - Private /tmp
- `RestrictAddressFamilies` - Only allow needed network families
- `SystemCallFilter` - Restrict system calls
Additional recommendations:
1. **Use nsec file instead of inline:**
```nix
relayOwnerNsecFile = "/persistent/ngit-grasp/relay-owner.nsec";
# NOT: relayOwnerNsec = "nsec1..."; # Ends up in nix store!
```
2. **Restrict data directory permissions:**
```bash
chmod 750 /persistent/ngit-grasp
chown ngit-grasp-production:ngit-grasp /persistent/ngit-grasp
```
3. **Use HTTPS (reverse proxy required):**
- ngit-grasp binds to localhost by default
- Use Caddy/nginx for TLS termination
- Caddy handles certificates automatically
4. **Monitor logs regularly:**
```bash
journalctl -u ngit-grasp-production --since today | grep -i error
```
---
## Monitoring
### Prometheus Metrics
ngit-grasp exposes Prometheus metrics at `/metrics`:
```bash
curl http://localhost:8082/metrics
```
See [Prometheus Setup](./prometheus-setup.md) for complete monitoring guide.
### Basic Health Checks
```bash
# Check if service is running
systemctl is-active ngit-grasp-production
# Check if port is listening
nc -zv localhost 8082
# Check relay info
curl https://ngit.example.com -H "Accept: application/nostr+json"
# Check disk usage
du -sh /persistent/ngit-grasp/*
```
---
## Related Documentation
- [Configuration Reference](../reference/configuration.md) - All configuration options
- [NixOS Module](../../nix/module.nix) - Module source code
- [Example Configuration](../../nix/example-configuration.nix) - More examples
- [Prometheus Setup](./prometheus-setup.md) - Monitoring guide
- [Nix Flakes How-To](./nix-flakes.md) - Nix development environment
---
*Part of the [ngit-grasp how-to guides](./)*