|
|
3 weeks ago | |
|---|---|---|
| docs | 3 weeks ago | |
| gitrepublic-cli@be480332eb | 3 weeks ago | |
| k8s | 4 weeks ago | |
| nostr | 3 weeks ago | |
| scripts | 3 weeks ago | |
| src | 3 weeks ago | |
| static | 4 weeks ago | |
| .dockerignore | 4 weeks ago | |
| .gitignore | 4 weeks ago | |
| Dockerfile | 4 weeks ago | |
| LICENSE | 3 weeks ago | |
| README.md | 3 weeks ago | |
| docker-compose.yml | 4 weeks ago | |
| package-lock.json | 3 weeks ago | |
| package.json | 3 weeks ago | |
| svelte.config.js | 4 weeks ago | |
| tsconfig.json | 4 weeks ago | |
| vite.config.ts | 4 weeks ago | |
README.md
gitrepublic-web
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 for answers to common architecture questions.
Features
Core Functionality
- NIP-34 Repo Announcements: Create and manage repository announcements on Nostr
- NIP-07 Authentication: Web UI authentication via browser extensions (e.g., Alby, nos2x)
- NIP-98 HTTP Authentication: Git operations (clone, push, pull) authenticated using ephemeral Nostr events
- SSH Key Attestation: Link SSH keys to Nostr identity for git operations over SSH (see docs/SSH_KEY_ATTESTATION.md)
- Auto-provisioning: Automatically creates git repositories from NIP-34 announcements
- Multi-remote Sync: Automatically syncs repositories to multiple remotes listed in announcements
- Repository Size Limits: Enforces 2 GB maximum repository size
- Relay Write Proof: Verifies users can write to at least one default Nostr relay before allowing operations
Repository Management
- Repository Ownership Transfer: Transfer ownership using kind 1641 events with a chain of ownership
- Private Repositories: Mark repositories as private, limiting access to owners and maintainers
- Maintainer Management: Add/remove maintainers who can push to repositories
- Forking: Fork repositories with automatic announcement creation and ownership setup
- Repository Settings: Manage privacy, maintainers, and description via web UI
- Branch Protection: Protect branches from direct pushes, require pull requests and reviews
Collaboration Features
- Issues: Create and manage issues (kind 1621) with status tracking
- Pull Requests: Create pull requests (kind 1618) with status management
- Highlights & Comments:
- NIP-84 highlights (kind 9802) for code selections
- NIP-22 comments (kind 1111) for threaded discussions
- Comment on PRs, issues, and code highlights
- Status Events: Track issue/PR status (open, applied/merged, closed, draft)
Web Interface
- Repository Browser: Browse files, directories, and commit history
- Code Editor: Edit files directly in the browser with syntax highlighting
- Branch Management: Create, switch, and manage branches
- Tag Management: Create and view git tags
- README Rendering: Automatic markdown rendering for README files
- Search: Search repositories by name, description, or author
- User Profiles: View user repositories and activity
- 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
- Input Validation: Validates commit messages, author names, emails, and file paths
- File Size Limits: 500 MB maximum per file (allows for images and demo videos)
- Ownership Verification: Verifies repository ownership via self-transfer events or verification files
- Commit Signing: Sign commits using Nostr private keys
- Signatures embedded in commit messages as trailers
- Web UI: Uses NIP-07 browser extension (secure, keys never leave browser)
- 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
This project uses the following Nostr event kinds. For complete JSON examples and tag documentation, see docs/NIP_COMPLIANCE.md.
Standard NIP Event Kinds
- 30617 (
REPO_ANNOUNCEMENT): Repository announcements (NIP-34) - 30618 (
REPO_STATE): Repository state announcements (NIP-34, optional) - 1617 (
PATCH): Git patches (NIP-34) - 1618 (
PULL_REQUEST): Pull request events (NIP-34) - 1619 (
PULL_REQUEST_UPDATE): Pull request updates (NIP-34) - 1621 (
ISSUE): Issue events (NIP-34) - 1630 (
STATUS_OPEN): Open status (NIP-34) - 1631 (
STATUS_APPLIED): Applied/merged status (NIP-34) - 1632 (
STATUS_CLOSED): Closed status (NIP-34) - 1633 (
STATUS_DRAFT): Draft status (NIP-34) - 9802 (
HIGHLIGHT): NIP-84 highlight events for code selections - 1111 (
COMMENT): NIP-22 comment events for threaded discussions - 27235 (
NIP98_AUTH): NIP-98 HTTP authentication events - 3: Contact list (NIP-02, for relay discovery)
- 10002: Relay list metadata (NIP-65, for relay discovery)
- 24: Public message (NIP-24, for relay write proof)
- 5: Event deletion request (NIP-09)
Custom Event Kinds
These are not part of any NIP but are used by this application:
-
1640 (
COMMIT_SIGNATURE): Git commit signature events- Used to cryptographically sign git commits using Nostr keys
- Tags:
commit(hash),author(name, email),message(commit message),e(NIP-98 auth event reference, optional) - See docs/NIP_COMPLIANCE.md for complete example
-
1641 (
OWNERSHIP_TRANSFER): Repository ownership transfer events (non-replaceable)- Transfers ownership from one pubkey to another
- Self-transfers (owner → owner) used for initial ownership proof
- Non-replaceable to maintain immutable chain of ownership
- Tags:
a(repo identifier),p(new owner),d(repo name),t(self-transfer marker, optional) - See docs/NIP_COMPLIANCE.md for complete example
-
30001 (
SSH_KEY_ATTESTATION): SSH key attestation (server-side only, not published to relays)- Links SSH public keys to Nostr identity for git operations over SSH
- Content contains the SSH public key
- Tags:
revoke(optional, set to 'true' to revoke an attestation) - See docs/SSH_KEY_ATTESTATION.md for complete documentation
-
30620 (
BRANCH_PROTECTION): Branch protection rules (replaceable)- 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 for complete example
How It Works
Repository Creation Flow
-
User Creates Announcement:
- User visits
/signupand connects NIP-07 extension - Enters repository name, description, and optional clone URLs
- System automatically creates a self-transfer event (kind 1641) for initial ownership proof
- Both announcement and self-transfer are published to Nostr relays
- User visits
-
Auto-Provisioning:
- Server polls Nostr relays for new repository announcements (kind 30617)
- When found, server:
- Creates a bare git repository at
/repos/{npub}/{repo-name}.git - Fetches the self-transfer event for ownership verification
- Creates initial commit with
.nostr-ownership-transferfile containing the self-transfer event - Creates
.nostr-announcementfile with the full signed announcement event JSON - If repository has
clonetags pointing to other remotes, syncs from those remotes
- Creates a bare git repository at
-
Repository Access:
- Public repositories: Anyone can clone and view
- Private repositories: Only owners and maintainers can access
- Access is checked via NIP-98 authentication for git operations
Git Operations Flow
-
Clone/Fetch:
- User runs
git clone https://{domain}/api/git/{npub}/{repo}.git(or/repos/path) - Server handles GET requests to
info/refs?service=git-upload-pack - For private repos, verifies NIP-98 authentication
- Proxies request to
git-http-backendwhich serves the repository
- User runs
-
Push:
- User configures git with NIP-98 authentication
- Before push, client creates a NIP-98 event (kind 27235) with:
utag: Request URLmethodtag: HTTP method (POST)payloadtag: SHA256 hash of request body
- Client signs event and includes in
Authorization: Nostr {event}header - Server verifies:
- Event signature
- Event timestamp (within 60 seconds)
- URL and method match
- Payload hash matches request body
- Pubkey is current owner or maintainer
- Server checks repository size limit (2 GB)
- Server proxies to
git-http-backend - After successful push, server:
- Extracts other
cloneURLs from announcement - Syncs to all other remotes using
git push --all
- Extracts other
Ownership Transfer Flow
-
Current Owner Initiates Transfer:
- Owner creates a kind 1641 event with:
fromtag: Current owner pubkeytotag: New owner pubkeyatag: Repository identifier (30617:{owner}:{repo})
- Signs and publishes event
- Owner creates a kind 1641 event with:
-
Server Processes Transfer:
- Server fetches all ownership transfer events for repository
- Validates chain of ownership chronologically
- Updates current owner for all permission checks
- Maintainers remain valid (checked against current owner)
Pull Requests & Issues Flow
-
Creating a PR/Issue:
- User creates a kind 1618 (PR) or 1621 (Issue) event
- Includes repository identifier in tags
- Publishes to Nostr relays
-
Status Management:
- Owner/maintainer creates status events (kind 1630-1633)
- Links to PR/Issue via event references
- Status changes: open → applied/closed/draft
-
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,Ptags (root) anda,k,ptags (parent)
Forking Flow
-
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
-
Fork Identification:
- Fork announcement includes reference to original repository
- UI displays "Forked from" badge
Private Repository Access
-
Privacy Setting:
- Repository announcement includes
privatetag (orttag with valueprivate) - Server marks repository as private
- Repository announcement includes
-
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:
-
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)
-
Verification:
- Server queries relay for the proof event
- Validates timestamp and signature
- Grants access if proof is valid
Architecture
Frontend
- Framework: SvelteKit + TypeScript
- Authentication: NIP-07 browser extension integration
- Components: Code editor, PR detail view, repository browser
Backend
- Git Server:
git-http-backendwrapper for git operations - Authentication: NIP-98 HTTP authentication for git operations
- Repository Management: Automatic provisioning and syncing
- Nostr Integration: WebSocket client for relay communication
Services
- NostrClient: WebSocket client for fetching and publishing Nostr events
- RepoManager: Server-side repository provisioning, syncing, and size management
- FileManager: File operations within git repositories with validation
- CommitSigner: Git commit signing using Nostr keys (supports nsec and hex formats)
- OwnershipTransferService: Manages repository ownership transfers
- MaintainerService: Checks maintainer permissions and privacy settings
- HighlightsService: Manages NIP-84 highlights and NIP-22 comments
- RelayWriteProof: Verifies user can write to Nostr relays
Project Structure
src/
├── lib/
│ ├── services/
│ │ ├── nostr/
│ │ │ ├── nostr-client.ts # WebSocket client for Nostr relays
│ │ │ ├── nip07-signer.ts # NIP-07 browser extension integration
│ │ │ ├── nip98-auth.ts # NIP-98 HTTP authentication
│ │ │ ├── repo-polling.ts # Auto-provision repos from announcements
│ │ │ ├── user-relays.ts # Fetch user's preferred relays
│ │ │ ├── ownership-transfer-service.ts # Repository ownership transfers
│ │ │ ├── maintainer-service.ts # Maintainer permission checks
│ │ │ ├── highlights-service.ts # NIP-84 highlights & NIP-22 comments
│ │ │ ├── relay-write-proof.ts # Relay write proof verification
│ │ │ ├── prs-service.ts # Pull request management
│ │ │ └── issues-service.ts # Issue management
│ │ └── git/
│ │ ├── repo-manager.ts # Repository provisioning & syncing
│ │ └── file-manager.ts # File operations with validation
│ ├── components/
│ │ ├── CodeEditor.svelte # Code editor with syntax highlighting
│ │ └── PRDetail.svelte # Pull request detail view
│ └── types/
│ └── nostr.ts # TypeScript types for Nostr events
├── routes/
│ ├── +page.svelte # Main page: list repositories
│ ├── signup/
│ │ └── +page.svelte # Create/update repo announcements
│ ├── repos/[npub]/[repo]/
│ │ ├── +page.svelte # Repository detail page
│ │ ├── +page.ts # OpenGraph metadata loader
│ │ └── settings/
│ │ └── +page.svelte # Repository settings UI
│ ├── users/[npub]/
│ │ └── +page.svelte # User profile page
│ ├── search/
│ │ └── +page.svelte # Search interface
│ └── api/
│ ├── git/[...path]/
│ │ └── +server.ts # Git HTTP backend API
│ └── repos/[npub]/[repo]/
│ ├── file/+server.ts # File read/write API
│ ├── tree/+server.ts # Directory listing API
│ ├── branches/+server.ts # Branch management API
│ ├── commits/+server.ts # Commit history API
│ ├── tags/+server.ts # Tag management API
│ ├── issues/+server.ts # Issues API
│ ├── prs/+server.ts # Pull requests API
│ ├── 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-backendinstalled - NIP-07 browser extension (for web UI)
Setup
npm install
npm run dev
Security Features
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
Enterprise Mode (Kubernetes)
- Process Isolation: Container-per-tenant architecture
- Network Isolation: Kubernetes Network Policies
- Resource Quotas: Per-tenant CPU, memory, and storage limits
- Separate Volumes: Each tenant has their own PersistentVolume
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 forgit clone,git push, andgit pulloperations from the command line. See Git Command Line Setup above. Note: Install the GitRepublic CLI package to use this.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)SSH_ATTESTATION_LOOKUP_SECRET: Secret key for HMAC-based SSH key fingerprint lookup (default:change-me-in-production). Important: Set this to a secure random value in production!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.onionaddresses 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.onionclone 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:
-
Install and configure Tor:
# On Debian/Ubuntu sudo apt-get install tor # Edit Tor configuration sudo nano /etc/tor/torrc -
Add hidden service configuration:
HiddenServiceDir /var/lib/tor/gitrepublic HiddenServicePort 80 127.0.0.1:6543 -
Restart Tor:
sudo systemctl restart tor -
Get your .onion address:
sudo cat /var/lib/tor/gitrepublic/hostname -
Set environment variable (optional, if hostname file is in a different location):
export TOR_ONION_ADDRESS=your-onion-address.onion
The server will automatically:
- Detect the
.onionaddress from the hostname file or environment variable - Add a
.onionclone 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!
Security Configuration
SECURITY_MODE:lightweight(single container) orenterprise(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)RATE_LIMIT_ENABLED: Enable rate limiting (default:true)RATE_LIMIT_WINDOW_MS: Rate limit window in milliseconds (default:60000= 1 minute)RATE_LIMIT_GIT_MAX: Max git operations per window (default:60)RATE_LIMIT_API_MAX: Max API requests per window (default:120)RATE_LIMIT_FILE_MAX: Max file operations per window (default:30)RATE_LIMIT_SEARCH_MAX: Max search requests per window (default:20)AUDIT_LOGGING_ENABLED: Enable audit logging (default:true)AUDIT_LOG_FILE: Optional file path for audit logs (default: console only)- If set, logs are written to files with daily rotation (e.g.,
audit-2024-01-01.log) - Example:
/var/log/gitrepublic/audit.log→ createsaudit-2024-01-01.log,audit-2024-01-02.log, etc.
- If set, logs are written to files with daily rotation (e.g.,
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
0to disable automatic cleanup
Git HTTP Backend Setup
The server uses git-http-backend for git operations. Ensure it's installed:
# 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
Creating a Repository
- Go to
/signup - Connect your NIP-07 extension
- Enter repository name and description
- Optionally add clone URLs (your domain will be added automatically)
- Optionally add images/banners for OpenGraph previews
- Publish the announcement
The server will automatically provision the repository.
Git Command Line Setup
To use git from the command line with GitRepublic, install the GitRepublic CLI tools. This lightweight package provides the credential helper and commit signing hook.
Quick Setup:
-
Install via npm (recommended):
npm install -g gitrepublic-cliOr clone from GitHub:
git clone https://github.com/your-org/gitrepublic-cli.git cd gitrepublic-cli npm install -
Set your Nostr private key:
export NOSTRGIT_SECRET_KEY="nsec1..." # Or add to ~/.bashrc or ~/.zshrc for persistence echo 'export NOSTRGIT_SECRET_KEY="nsec1..."' >> ~/.bashrc -
Run automatic setup:
# Setup everything automatically gitrepublic-setup # Or with options: gitrepublic-setup --domain your-domain.com # Configure for specific domain gitrepublic-setup --global-hook # Install hook globallyThe 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_KEYis set
Important Notes:
- The
NOSTRGIT_SECRET_KEYmust 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/npubor/repos/npubURL 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.
Cloning a Repository
# Using GitRepublic API endpoint (recommended for commit signing detection)
git clone https://{domain}/api/git/{npub}/{repo-name}.git
# Or using repos endpoint
git clone https://{domain}/repos/{npub}/{repo-name}.git
# 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.
Pushing to a Repository
# Add remote (use /api/git/ or /repos/ path for best compatibility)
git remote add origin https://{domain}/api/git/{npub}/{repo-name}.git
# Push (requires credential helper setup)
git push origin main
The credential helper will automatically generate NIP-98 authentication tokens for push operations. The commit signing hook will automatically sign commits for GitRepublic repositories.
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
/searchto search for repositories
Managing Repositories
- Settings: Visit
/repos/{npub}/{repo}/settingsto manage privacy, maintainers, and description - Forking: Click "Fork" button on repository page
- Transfer Ownership: Use the transfer API endpoint or create a kind 1641 event manually
Security Features
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
Enterprise Mode (Kubernetes)
- Process Isolation: Container-per-tenant architecture
- Network Isolation: Kubernetes Network Policies
- Resource Quotas: Per-tenant CPU, memory, and storage limits
- Separate Volumes: Each tenant has their own PersistentVolume
See docs/SECURITY.md and docs/SECURITY_IMPLEMENTATION.md for detailed information.
Security Considerations
- Path Traversal: 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
License
[Add your license here]
Contributing
[Add contribution guidelines here]