A decentralized, Nostr-based git server that enables git repository hosting and collaboration using Nostr events. Repositories are announced via NIP-34, and all operations (clone, push, pull) are authenticated using NIP-98 HTTP authentication.
See [ARCHITECTURE_FAQ.md](./docs/ARCHITECTURE_FAQ.md) for answers to common architecture questions.
## Command Line Interface (CLI)
**The GitRepublic CLI is published and available via npm:**
```bash
npm install -g gitrepublic-cli
```
The CLI provides:
- **Git wrapper** with enhanced error messages for GitRepublic operations
- **Credential helper** for automatic NIP-98 authentication
- **Commit signing hook** that automatically signs commits using Nostr keys
- **Full API access** from the command line
### Quick Start with CLI
```bash
# Install
npm install -g gitrepublic-cli
# Set your Nostr private key
export NOSTRGIT_SECRET_KEY="nsec1..."
# Setup (configures credential helper and commit hook)
**Note**: `gitrep` is a shorter alias for `gitrepublic` - both work the same way.
For complete CLI documentation, see [gitrepublic-cli/README.md](./gitrepublic-cli/README.md).
---
## Overview
GitRepublic consists of three main components:
1. **Web Interface** - Full-featured web application for browsing, editing, and managing repositories
2. **Command Line Interface (CLI)** - Git wrapper and API client for command-line operations
3. **REST API** - Complete API for programmatic access (see `/api/openapi.json` for full documentation)
All three interfaces use the same underlying Nostr-based authentication and repository management system.
## Features
@ -43,7 +93,6 @@ See [ARCHITECTURE_FAQ.md](./docs/ARCHITECTURE_FAQ.md) for answers to common arch
@@ -43,7 +93,6 @@ See [ARCHITECTURE_FAQ.md](./docs/ARCHITECTURE_FAQ.md) for answers to common arch
- **Raw File View**: Direct access to raw file content
- **Download Repository**: Download repositories as ZIP archives
- **OpenGraph Metadata**: Rich social media previews with repository images and banners
- **Universal Git Dashboard**: Aggregate and view issues and pull requests from all configured git platforms (GitHub, GitLab, Gitea, etc.) in one place
### Security & Validation
- **Path Traversal Protection**: Validates and sanitizes file paths
@ -56,57 +105,75 @@ See [ARCHITECTURE_FAQ.md](./docs/ARCHITECTURE_FAQ.md) for answers to common arch
@@ -56,57 +105,75 @@ See [ARCHITECTURE_FAQ.md](./docs/ARCHITECTURE_FAQ.md) for answers to common arch
- **Git Operations**: Uses NIP-98 HTTP authentication (ephemeral signed events)
- ⚠️**Security Note**: Never send private keys (nsec) in API requests. Use NIP-07 for web UI or NIP-98 for git operations.
## Nostr Event Kinds Used
## Getting Started
This project uses the following Nostr event kinds. For complete JSON examples and tag documentation, see [docs/NIP_COMPLIANCE.md](./docs/NIP_COMPLIANCE.md#complete-event-kind-reference).
### Prerequisites
- Node.js 18+
- Git with `git-http-backend` installed
- NIP-07 browser extension (for web UI) - [Alby](https://getalby.com/) or [nos2x](https://github.com/fiatjaf/nos2x) recommended
All API endpoints are documented in OpenAPI format at `/api/openapi.json`. Use NIP-98 authentication for all write operations.
Example:
```bash
curl -X GET https://your-domain.com/api/repos/list
```
## How It Works
### Repository Creation Flow
1. **User Creates Announcement**:
- User visits `/signup` and connects NIP-07 extension
- Enters repository name, description, and optional clone URLs
- **Web**: Visit `/signup` and connect NIP-07 extension
- **CLI**: Run `gitrep publish repo-announcement <repo-name>`
- **API**: POST to `/api/repos/[npub]/[repo]` with announcement event
- System automatically creates a self-transfer event (kind 1641) for initial ownership proof
- Both announcement and self-transfer are published to Nostr relays
@ -126,13 +193,15 @@ These are not part of any NIP but are used by this application:
@@ -126,13 +193,15 @@ These are not part of any NIP but are used by this application:
### Git Operations Flow
1. **Clone/Fetch**:
- User runs `git clone https://{domain}/api/git/{npub}/{repo}.git` (or `/repos/` path)
- Before push, client creates a NIP-98 event (kind 27235) with:
- `u` tag: Request URL
- `method` tag: HTTP method (POST)
@ -153,6 +222,9 @@ These are not part of any NIP but are used by this application:
@@ -153,6 +222,9 @@ These are not part of any NIP but are used by this application:
### Ownership Transfer Flow
1. **Current Owner Initiates Transfer**:
- **Web**: Use transfer UI in repository settings
- **CLI**: `gitrep transfer <npub> <repo> <new-owner-npub>`
- **API**: POST to `/api/repos/[npub]/[repo]/transfer`
@ -171,68 +243,49 @@ These are not part of any NIP but are used by this application:
@@ -171,68 +243,49 @@ These are not part of any NIP but are used by this application:
- Updates current owner for all permission checks
- Maintainers remain valid (checked against current owner)
### Pull Requests & Issues Flow
1. **Creating a PR/Issue**:
- User creates a kind 1618 (PR) or 1621 (Issue) event
- Includes repository identifier in tags
- Publishes to Nostr relays
2. **Status Management**:
- Owner/maintainer creates status events (kind 1630-1633)
- Links to PR/Issue via event references
- Status changes: open → applied/closed/draft
- **PR Merging**: Creates merge commit and publishes status event (kind 1631) with merge commit ID
- **PR Updates**: PR author can update PR tip commit using kind 1619 events
- **Issue Management**: Owners, maintainers, and issue authors can update issue status
3. **Highlights & Comments**:
- User selects code in PR diff view
- Creates kind 9802 highlight event with code selection metadata
- Users can comment on highlights using kind 1111 events
- Comments are threaded using `A`, `K`, `P` tags (root) and `a`, `k`, `p` tags (parent)
### Forking Flow
1. **User Forks Repository**:
- User clicks "Fork" button on repository page
- Server:
- Clones original repository
- Creates new repository at `/repos/{user-npub}/{fork-name}.git`
- Creates new NIP-34 announcement for fork
- Creates self-transfer event for fork ownership
- Publishes both to Nostr relays
2. **Fork Identification**:
- Fork announcement includes reference to original repository
- UI displays "Forked from" badge
### Private Repository Access
1. **Privacy Setting**:
- Repository announcement includes `private` tag (or `t` tag with value `private`)
- Server marks repository as private
2. **Access Control**:
- All API endpoints check privacy status
- For private repos, requires NIP-98 authentication
- Verifies user is current owner or listed maintainer
- Returns 403 if unauthorized
### Relay Write Proof
Instead of traditional rate limiting, users must prove they can write to at least one default Nostr relay:
1. **Proof Mechanism**:
- User publishes a NIP-98 event (kind 27235) to a default relay
- Event must be within 60 seconds (per NIP-98 spec)
- Server verifies event exists on relay
- Alternative: User publishes kind 24 public message (5-minute window)
2. **Verification**:
- Server queries relay for the proof event
- Validates timestamp and signature
- Grants access if proof is valid
## Nostr Event Kinds Used
This project uses the following Nostr event kinds. For complete JSON examples and tag documentation, see [docs/NIP_COMPLIANCE.md](./docs/NIP_COMPLIANCE.md#complete-event-kind-reference).
- Allows requiring pull requests, reviewers, status checks for protected branches
- Tags: `d` (repo name), `a` (repo identifier), `branch` (branch name and protection settings)
- See [docs/NIP_COMPLIANCE.md](./docs/NIP_COMPLIANCE.md#30620---branch_protection) for complete example
## Architecture
@ -258,187 +311,53 @@ Instead of traditional rate limiting, users must prove they can write to at leas
@@ -258,187 +311,53 @@ Instead of traditional rate limiting, users must prove they can write to at leas
- **HighlightsService**: Manages NIP-84 highlights and NIP-22 comments
- **RelayWriteProof**: Verifies user can write to Nostr relays
│ ├── highlights/+server.ts # Highlights & comments API
│ ├── fork/+server.ts # Fork repository API
│ ├── readme/+server.ts # README fetching API
│ ├── raw/+server.ts # Raw file view API
│ ├── download/+server.ts # Download repository as ZIP
│ ├── settings/+server.ts # Repository settings API
│ ├── transfer/+server.ts # Ownership transfer API
│ └── verify/+server.ts # Ownership verification API
└── hooks.server.ts # Server initialization (starts polling)
```
## Development
### Prerequisites
- Node.js 18+
- Git with `git-http-backend` installed
- NIP-07 browser extension (for web UI)
### Setup
```bash
npm install # Installs dependencies for both web and CLI (workspace)
npm run dev
```
**Note**: This repository uses npm workspaces. The CLI (`gitrepublic-cli`) is included as a workspace package but can also be published independently. See `gitrepublic-cli/SYNC.md` for details on syncing to a separate repository.
## Security Features
### Lightweight Mode (Single Container)
### Lightweight Mode (Single Container) - Default
- **Resource Limits**: Per-user repository count and disk quota limits
- **Rate Limiting**: Per-IP and per-user rate limiting for all operations
- **Audit Logging**: Comprehensive logging of all security-relevant events
- **Path Validation**: Strict path validation to prevent traversal attacks
- **git-http-backend Hardening**: Timeouts, process isolation, scoped access
- **Mode**: Set `ENTERPRISE_MODE=false` or leave unset (default)
- **Resource Quotas**: Per-tenant CPU, memory, and storage limits
- **Separate Volumes**: Each tenant has their own PersistentVolume
- **Mode**: Set `ENTERPRISE_MODE=true` environment variable
- **Deployment**: See `k8s/ENTERPRISE_MODE.md` for setup instructions
See `docs/SECURITY.md` and `docs/SECURITY_IMPLEMENTATION.md` for detailed information.
## Environment Variables
- `NOSTRGIT_SECRET_KEY`: User's Nostr private key (nsec bech32 or hex) for git command-line operations via credential helper. Required for `git clone`, `git push`, and `git pull` operations from the command line. See [Git Command Line Setup](#git-command-line-setup) above. **Note**: Install the [GitRepublic CLI](https://github.com/your-org/gitrepublic-cli) package to use this.
### Core Configuration
- `ENTERPRISE_MODE`: Enable enterprise mode with Kubernetes (default: `false`). When `true`, expects container-per-tenant architecture. See `k8s/ENTERPRISE_MODE.md` for details.
- `GIT_REPO_ROOT`: Path to store git repositories (default: `/repos`)
- `GIT_DOMAIN`: Domain for git repositories (default: `localhost:6543`)
- `NOSTR_RELAYS`: Comma-separated list of Nostr relays (default: `wss://theforest.nostr1.com`)
- `TOR_SOCKS_PROXY`: Tor SOCKS proxy address (format: `host:port`, default: `127.0.0.1:9050`). Set to empty string to disable Tor support. When configured, the server will automatically route `.onion` addresses through Tor for both Nostr relay connections and git operations.
- `TOR_ONION_ADDRESS`: Tor hidden service .onion address (optional). If not set, the server will attempt to read it from Tor's hostname file. When configured, every repository will automatically get a `.onion` clone URL in addition to the regular domain URL, making repositories accessible via Tor even if the server is only running on localhost.
### Tor Hidden Service Setup
To provide `.onion` addresses for all repositories, you need to set up a Tor hidden service:
1. **Install and configure Tor**:
```bash
# On Debian/Ubuntu
sudo apt-get install tor
# Edit Tor configuration
sudo nano /etc/tor/torrc
```
2. **Add hidden service configuration**:
```
HiddenServiceDir /var/lib/tor/gitrepublic
HiddenServicePort 80 127.0.0.1:6543
```
- `NOSTR_SEARCH_RELAYS`: Comma-separated list of Nostr relays for searching (default: includes multiple relays)
3. **Restart Tor**:
```bash
sudo systemctl restart tor
```
### Git Operations
- `NOSTRGIT_SECRET_KEY`: User's Nostr private key (nsec bech32 or hex) for git command-line operations via credential helper. Required for `git clone`, `git push`, and `git pull` operations from the command line. **Note**: Install via `npm install -g gitrepublic-cli` to use this.
4. **Get your .onion address**:
```bash
sudo cat /var/lib/tor/gitrepublic/hostname
```
5. **Set environment variable** (optional, if hostname file is in a different location):
```bash
export TOR_ONION_ADDRESS=your-onion-address.onion
```
The server will automatically:
- Detect the `.onion` address from the hostname file or environment variable
- Add a `.onion` clone URL to every repository announcement
- Make repositories accessible via Tor even if the server is only on localhost
**Note**: The `.onion` address works even if your server is only accessible on `localhost` - Tor will handle the routing!
### Tor Support
- `TOR_SOCKS_PROXY`: Tor SOCKS proxy address (format: `host:port`, default: `127.0.0.1:9050`). Set to empty string to disable Tor support. When configured, the server will automatically route `.onion` addresses through Tor for both Nostr relay connections and git operations.
- `TOR_ONION_ADDRESS`: Tor hidden service .onion address (optional). If not set, the server will attempt to read it from Tor's hostname file. When configured, every repository will automatically get a `.onion` clone URL in addition to the regular domain URL, making repositories accessible via Tor even if the server is only running on localhost.
### Security Configuration
- `SECURITY_MODE`: `lightweight` (single container) or `enterprise` (Kubernetes) (default: `lightweight`)
- `MAX_REPOS_PER_USER`: Maximum repositories per user (default: `100`)
- `MAX_DISK_QUOTA_PER_USER`: Maximum disk quota per user in bytes (default: `10737418240` = 10GB)
- If set, logs are written to files with daily rotation (e.g., `audit-2024-01-01.log`)
- Example: `/var/log/gitrepublic/audit.log` → creates `audit-2024-01-01.log`, `audit-2024-01-02.log`, etc.
- `AUDIT_LOG_RETENTION_DAYS`: Number of days to keep audit log files (default: `90`)
- Old log files are automatically deleted after this period
- Set to `0` to disable automatic cleanup
### Git HTTP Backend Setup
The server uses `git-http-backend` for git operations. Ensure it's installed:
```bash
# On Debian/Ubuntu
sudo apt-get install git
# Verify installation
which git-http-backend
```
The server will automatically locate `git-http-backend` in common locations.
## Usage Examples
## Usage
### Creating a Repository
### Web Interface
#### Creating a Repository
1. Go to `/signup`
2. Connect your NIP-07 extension
3. Enter repository name and description
@ -448,133 +367,159 @@ The server will automatically locate `git-http-backend` in common locations.
@@ -448,133 +367,159 @@ The server will automatically locate `git-http-backend` in common locations.
The server will automatically provision the repository.
### Git Command Line Setup
#### Viewing Repositories
- Go to `/` to see all public repositories
- Go to `/repos/{npub}/{repo}` to view a specific repository
- Go to `/users/{npub}` to view a user's repositories
- Go to `/search` to search for repositories
To use git from the command line with GitRepublic, install the [GitRepublic CLI](https://github.com/your-org/gitrepublic-cli) tools. This lightweight package provides the credential helper and commit signing hook.
#### Managing Repositories
- **Settings**: Visit `/repos/{npub}/{repo}/settings` to manage privacy, maintainers, and description
- **Forking**: Click "Fork" button on repository page
- **Transfer Ownership**: Use the transfer UI in repository settings
**Note**: Use `/api/git/` or `/repos/` paths to ensure proper detection by the commit signing hook. All three paths (`/api/git/`, `/repos/`, and root `/`) work for cloning, but `/api/git/` is recommended for best compatibility.
3. **Run automatic setup**:
#### Pushing to a Repository
```bash
# Setup everything automatically
gitrepublic-setup
# Using GitRepublic CLI (automatic authentication)
gitrep push origin main
# Or with options:
gitrepublic-setup --domain your-domain.com # Configure for specific domain
# Or using standard git (requires credential helper)
git push origin main
```
The setup script automatically:
- Finds the scripts (works with npm install or git clone)
- Configures git credential helper
- Installs commit signing hook
- Checks if `NOSTRGIT_SECRET_KEY` is set
**Important Notes:**
- The `NOSTRGIT_SECRET_KEY` must match the repository owner or you must have maintainer permissions
- The credential helper generates fresh NIP-98 tokens for each request (per-request authentication)
- The commit signing hook only signs commits for GitRepublic repositories (detects `/api/git/npub` or `/repos/npub` URL patterns)
- Never commit your private key to version control
**CLI Features:**
- Full API access: `gitrepublic repos list`, `gitrepublic file get`, etc.
- Server configuration: `gitrepublic config server`
- JSON output support: `gitrepublic --json repos get <npub> <repo>`
For complete setup instructions, API commands, and troubleshooting, see the [GitRepublic CLI README](https://github.com/your-org/gitrepublic-cli).
### Cloning a Repository
The credential helper will automatically generate NIP-98 authentication tokens for push operations. The commit signing hook will automatically sign commits for GitRepublic repositories.
#### API Commands
```bash
# Using GitRepublic API endpoint (recommended for commit signing detection)
# Direct path (also works, but may conflict with GRASP servers)
git clone https://{domain}/{npub}/{repo-name}.git
```
**Note**: Use `/api/git/` or `/repos/` paths to ensure proper detection by the commit signing hook and to distinguish from GRASP servers. All three paths work for cloning, but `/api/git/` is recommended for best compatibility.
# List repositories
gitrep repos list
### Pushing to a Repository
# Get repository details
gitrep repos get <npub><repo>
```bash
# Add remote (use /api/git/ or /repos/ path for best compatibility)
The credential helper will automatically generate NIP-98 authentication tokens for push operations. The commit signing hook will automatically sign commits for GitRepublic repositories.
For complete CLI documentation, see [gitrepublic-cli/README.md](./gitrepublic-cli/README.md).
### Viewing Repositories
### API Access
- Go to `/` to see all public repositories
- Go to `/repos/{npub}/{repo}` to view a specific repository
- Go to `/users/{npub}` to view a user's repositories
- Go to `/search` to search for repositories
All API endpoints are documented in OpenAPI format. Access the API documentation at:
The CLI handles authentication automatically. For manual API access, see the [NIP-98 specification](https://github.com/nostr-protocol/nips/blob/master/98.md).
### Lightweight Mode (Single Container)
- **Resource Limits**: Per-user repository count and disk quota limits
- **Rate Limiting**: Per-IP and per-user rate limiting for all operations
- **Audit Logging**: Comprehensive logging of all security-relevant events
- **Path Validation**: Strict path validation to prevent traversal attacks
- **git-http-backend Hardening**: Timeouts, process isolation, scoped access
- **Resource Quotas**: Per-tenant CPU, memory, and storage limits
- **Separate Volumes**: Each tenant has their own PersistentVolume
### Prerequisites
- Node.js 18+
- Git with `git-http-backend` installed
- NIP-07 browser extension (for web UI)
### Security Considerations
### Setup
- **Path Traversal Protection**: All file paths are validated and sanitized
- **Input Validation**: Commit messages, author info, and file paths are validated
- **Size Limits**: 2 GB per repository, 500 MB per file
- **Authentication**: All write operations require NIP-98 authentication
- **Authorization**: Ownership and maintainer checks for all operations
- **Private Repositories**: Access restricted to owners and maintainers
- **Resource Limits**: Per-user repository count and disk quota limits (configurable)
- **Rate Limiting**: Per-IP and per-user rate limiting (configurable)
- **Audit Logging**: All security-relevant events are logged
```bash
npm install # Installs dependencies for both web and CLI (workspace)
npm run dev
```
See `docs/SECURITY.md` and `docs/SECURITY_IMPLEMENTATION.md` for detailed information.
**Note**: This repository uses npm workspaces. The CLI (`gitrepublic-cli`) is included as a workspace package but can also be published independently. See `gitrepublic-cli/SYNC.md` for details on syncing to a separate repository.
@ -140,7 +140,7 @@ Private repositories require authentication. You'll need to set up NIP-98 authen
@@ -140,7 +140,7 @@ Private repositories require authentication. You'll need to set up NIP-98 authen
#### Setting Up NIP-98 Authentication
For command-line git operations, you need to install the [GitRepublic CLI](https://github.com/your-org/gitrepublic-cli) which provides:
For command-line git operations, you need to install the [GitRepublic CLI](https://github.com/silberengel/gitrepublic-cli) which provides:
2. **Commit Signing Hook**: Automatically signs commits for GitRepublic repositories
@ -171,7 +171,7 @@ This automatically configures the credential helper and commit signing hook. See
@@ -171,7 +171,7 @@ This automatically configures the credential helper and commit signing hook. See
When prompted, the credential helper will automatically generate and use a NIP-98 authentication token.
**Note**: For command-line git operations, you'll need to install the [GitRepublic CLI](https://github.com/your-org/gitrepublic-cli) and set up the credential helper. See the README for complete setup instructions.
**Note**: For command-line git operations, you'll need to install the [GitRepublic CLI](https://github.com/silberengel/gitrepublic-cli) via `npm install -g gitrepublic-cli` and set up the credential helper. See the README for complete setup instructions.
Enterprise mode provides complete isolation between tenants using Kubernetes. Each tenant (user/npub) gets their own container, namespace, and persistent volume.
## Quick Start
### Prerequisites
1. **Kubernetes cluster** (minikube, kind, or production cluster)
2. **kubectl** configured to access your cluster
3. **envsubst** (usually comes with `gettext` package)
@ -455,7 +455,7 @@ Your commits will all be signed by your Nostr keys and saved to the event files
@@ -455,7 +455,7 @@ Your commits will all be signed by your Nostr keys and saved to the event files
@ -468,15 +468,15 @@ Your commits will all be signed by your Nostr keys and saved to the event files
@@ -468,15 +468,15 @@ Your commits will all be signed by your Nostr keys and saved to the event files
// This ensures git calls the credential helper proactively
// Git requires WWW-Authenticate header on ALL 401 responses, otherwise it won't retry
if(!rawAuthHeader){
returnnewResponse('Authentication required. Please configure the git credential helper. See https://github.com/your-org/gitrepublic-cli for setup instructions.',{
returnnewResponse('Authentication required. Please configure the git credential helper. Install via: npm install -g gitrepublic-cli\nSee https://github.com/silberengel/gitrepublic-cli for setup instructions.',{