mirror of
https://relay.ngit.dev/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr/ngit-grasp.git
synced 2026-10-05 15:08:24 +00:00
488 lines
11 KiB
Markdown
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](./)*
|