GitBlixt
A GitLab-compatible, self-hosted Git forge built in Elixir/Phoenix. One command to install.
Features
- GitLab API compatible — existing integrations (CodeRabbit, CI tools) work out of the box
- Automatic HTTPS — Let's Encrypt certificates provisioned on first boot
- SSH + HTTP — clone and push over both protocols
- Real-time UI — Phoenix LiveView powers a fast, modern interface
- Issues, Merge Requests, Wiki, Labels, Pipelines — full forge functionality
- Issue Boards — kanban-style planning per repository
- Forks and Collaboration — fork repos, manage collaborators with role-based access
- Organizations — group repos under shared namespaces with member roles
- Search — find repos, issues, MRs, and code across your instance
- Releases & Milestones — tag releases and plan work with milestones
- Code Review — blame view, file history, side-by-side diffs, draft MRs, approval rules, squash merge, auto-merge
- Protected Branches — enforce push/merge access levels and approval requirements
- CI/CD — GitLab CI- and GitHub Actions-compatible pipelines with runners, jobs, artifacts, and variables
- Built-in PaaS — deploy any repo as a Docker service with managed Postgres and preview environments per merge request
- AI Assistance — fix issues and review MRs with Claude Code running in isolated containers
- Scheduled Agents — run recurring AI tasks on a cron schedule that open a merge request for review (never auto-merged)
- Import — bulk-migrate repos, issues, PRs, labels, and wiki from GitHub or GitLab
- Mirrors — push or pull mirror to/from GitHub, GitLab, or any git remote
- Webhooks — outbound webhooks with delivery history
- OAuth — sign in with GitHub or GitLab
- 2FA — TOTP-based two-factor authentication
- Personal Access Tokens — scoped tokens for the API and git over HTTPS
- Snippets — share standalone code snippets (public, internal, or private)
- Notifications — in-app notification center with unread badge
- Activity Feeds — see recent actions on your dashboard and per-project
- Explore — discover public repositories on your instance
- Admin Panel — user management, settings, migrations, app overview, log streaming, remote shell
- Backups — scheduled and on-demand backups (database, repos, uploads) to local disk or S3
Quick Start
Install Docker Engine and the Compose plugin (docker-ce and docker-compose-plugin) if you haven't already — see Docker's install docs.
curl -fsSL https://gitblixt.com/install.sh | GITBLIXT_HOST=git.yourdomain.com sh
That's it. The installer creates the config, downloads the compose file, and starts GitBlixt.
Open https://git.yourdomain.com — the first registered user becomes admin.
Manual Install
If you prefer to set things up yourself:
mkdir gitblixt && cd gitblixt
# Generate config
cat > .env <<EOF
POSTGRES_PASSWORD=$(openssl rand -hex 32)
GITBLIXT_HOST=git.yourdomain.com
DATA_DIR=./data
EOF
# Download compose file and Caddyfile
curl -fsSL https://gitblixt.com/docker-compose.yml -o docker-compose.yml
mkdir -p caddy
curl -fsSL https://gitblixt.com/Caddyfile -o caddy/Caddyfile
# Edit caddy/Caddyfile — replace gitblixt.example.com with your domain
nano caddy/Caddyfile
# Create overlay networks (required for Swarm + PaaS)
docker swarm init 2>/dev/null || true
docker network create --driver overlay --attachable gitblixt 2>/dev/null || true
docker network create --driver overlay --attachable proxy 2>/dev/null || true
# Start
docker compose up -d
Caddy and PaaS
GitBlixt uses Caddy as a reverse proxy for both itself and any apps you deploy via the built-in PaaS. The Caddyfile must include admin 0.0.0.0:2019 in the global options block so GitBlixt can manage routes via Caddy's admin API over the Docker overlay network.
The caddy and gitblixt services must both be on the proxy overlay network so GitBlixt can reach Caddy at http://caddy:2019. The gitblixt network is used for Postgres connectivity.
When you enable deployment for a repository, GitBlixt will automatically register Caddy routes for the app's domains. Caddy handles TLS certificate provisioning via Let's Encrypt.
Requirements
- Standard rootful Docker with the Compose plugin. GitBlixt drives the host Docker (CI, PaaS deploys, AI jobs) and runs as a Swarm service, so the daemon must not use
userns-remapor rootless mode, and must not havelive-restoreenabled (it's incompatible with Swarm mode). Some cloud images ship these on — symptoms arepermission denied … docker.sockin CI, aswarm initfailure, or/datafiles owned by uid100000. See Troubleshooting. - A domain pointing at your server
- Ports 80, 443, and 22 open
Configuration
All configuration is via environment variables in your .env file (next to docker-compose.yml).
| Variable | Default | Description |
|---|---|---|
GITBLIXT_HOST |
localhost |
Your domain name |
POSTGRES_PASSWORD |
required | Database password |
DATA_DIR |
./data |
Host path for persistent data |
SSL_MODE |
auto |
off (installer default — Caddy terminates SSL), auto (app gets its own cert, standalone only), or manual |
SMTP_HOST |
— | SMTP server hostname (e.g. email-smtp.us-west-2.amazonaws.com) |
SMTP_PORT |
587 |
SMTP port |
SMTP_USERNAME |
— | SMTP username |
SMTP_PASSWORD |
— | SMTP password |
GITBLIXT_FROM_EMAIL |
— | Sender address for outgoing emails |
A secret key is auto-generated and persisted to data/config/secret_key_base on first boot.
External Database
To use an existing Postgres instead of the compose-managed one, set DATABASE_URL in the
gitblixt service environment and remove the postgres service from your compose file:
environment:
DATABASE_URL: ecto://user:pass@your-db-host:5432/gitblixt
Minimum Postgres version: 14.
SSL Modes
| Mode | Description |
|---|---|
auto (default) |
Automatic HTTPS via Let's Encrypt |
manual |
Provide your own cert at data/ssl/cert.pem and data/ssl/key.pem |
off |
HTTP only (for behind-a-proxy setups like Cloudflare or nginx) |
Behind Cloudflare
If using Cloudflare as a reverse proxy, set SSL_MODE=off and configure Cloudflare's SSL mode to Full or Flexible.
Data & Volumes
All persistent data lives under your DATA_DIR (default ./data):
data/
postgres/ # PostgreSQL data directory
repos/ # Bare git repositories
uploads/ # Avatars and file uploads
ssl/ # SSL certificates
ssh/ # SSH host keys
config/ # Auto-generated config (secret key)
Upgrading
docker service update --image willc0de4food/gitblixt:latest gitblixt
Swarm performs a zero-downtime rolling update (start-first). Migrations run automatically on startup. Your data persists across upgrades.
New installs run Postgres 18. Minor updates within the same major are safe (docker compose pull && docker compose up -d). A major upgrade (e.g. 16 → 18) is not — Postgres won't start on a data directory from an older major, so existing installs must dump-and-restore across the bump. Full procedure: Upgrading → Postgres major version.
Backup and Restore
Configure scheduled backups (local or S3) and trigger on-demand ones under Admin → Backups. Enable encryption there too — GitBlixt shows the private key once; save it off-server. With encryption on, each backup is two objects (*.tar.gz.enc + *.key.enc) and you need both plus the private key to restore.
The app runs as a Swarm service named
gitblixt(only Postgres and Caddy are Compose-managed), so runbin/gitblixtcommands viadocker exec $(docker ps -q -f name=gitblixt.1) bin/gitblixt …, notdocker compose exec.
Restoring has real footguns — the private key must be PEM (not OpenSSH), you must restore into an empty database, and the encryption key (secret_key_base / APP_SECRETS_KEY) has to carry over or encrypted columns won't decrypt. The full, tested procedure is in the docs:
- Backup & Restore — creating, encrypting, and restoring backups
- Migrating to a New Server — end-to-end cutover runbook
Troubleshooting
SSL not working: Check that port 80 is open (needed for ACME HTTP-01 challenges). Try SSL_MODE=off to verify the app works over HTTP first.
SSH not working: Ensure port 22 is not in use by another SSH server on the host.
Container won't start: Check docker service logs gitblixt for startup errors.
CI/deploys fail with permission denied … docker.sock (or /data owned by uid 100000): the daemon is using userns-remap or rootless mode. GitBlixt needs rootful Docker — see Troubleshooting → docker.sock.
docker swarm init fails / "not a swarm manager": live-restore is incompatible with Swarm — set "live-restore": false in /etc/docker/daemon.json, restart Docker, then docker swarm init.
git push warns "REMOTE HOST IDENTIFICATION HAS CHANGED" after a migration: expected (host keys aren't in the backup). Run ssh-keygen -R your-host and accept the new key.
Cloudflare error 526: origin has no valid cert yet — see SSL & HTTPS.
Email not sending: See the Email (SMTP) section below.
More install, restore, and migration gotchas — and their fixes — are documented at /docs/troubleshooting.
Email (SMTP)
Email is used for login links, password resets, admin-created user invitations, and notifications.
There are two ways to configure SMTP — environment variables or the Admin UI. Admin UI (database) settings take priority over environment variables.
Option 1: Environment Variables
Add these to your .env file:
SMTP_HOST=email-smtp.us-west-2.amazonaws.com
SMTP_PORT=587
SMTP_USERNAME=AKIA...
SMTP_PASSWORD=...
GITBLIXT_FROM_EMAIL=noreply@yourdomain.com
Then add them to the gitblixt service's environment: section in your compose file, or restart with docker compose up -d.
Option 2: Admin UI
Go to Admin > Settings and fill in the SMTP section. All fields are stored in the database and override any environment variables.
Required Fields
| Field | Required | Notes |
|---|---|---|
| SMTP Host | Yes | Your SMTP provider's hostname |
| Port | Yes | Usually 587 (STARTTLS) or 465 (implicit TLS) |
| Username | Yes | SMTP auth username |
| Password | Yes | SMTP auth password |
| From Email | Yes | Must be a verified sender identity with your provider |
| TLS | No | if_available (default), always, or never |
The From Email is the address that appears in the "From" field of all outgoing emails. Your SMTP provider must allow sending from this address — for example, AWS SES requires the domain or email to be verified as a sending identity.
AWS SES
- Use the SES SMTP endpoint for your region (e.g.
email-smtp.us-west-2.amazonaws.com) - Create SMTP credentials in the SES console — these are separate from regular IAM access keys
- Verify your sending domain (or individual email) in the SES console
- Set the From Email to an address on your verified domain (e.g.
noreply@yourdomain.com) - If your SES account is in sandbox mode, you can only send to verified recipient addresses — request production access to send to anyone
Troubleshooting Email
- Use the Send Test button in Admin > Settings to verify your configuration
- Check
docker compose logs gitblixtfor delivery errors - retries_exceeded / TLS errors: Your SMTP provider requires TLS but the handshake is failing. Ensure the host and port are correct and try setting TLS to
always - No errors but email not received: Check that the From Email is set and is a verified sender identity. Without a From Email, emails silently fail
Development
Prerequisites
- Elixir 1.18+ / OTP 27+
- PostgreSQL 16+
- Node.js (for asset building)
- Git
Setup
git clone https://gitblixt.com/gitblixt/gitblixt.git
cd gitblixt
mix setup # Install deps, create DB, run migrations, build assets
mix phx.server # Start dev server at localhost:4000
Commands
| Command | Purpose |
|---|---|
mix setup |
Install deps, create DB, run migrations, build assets |
mix phx.server |
Start dev server (localhost:4000) |
iex -S mix phx.server |
Start dev server with interactive shell |
mix test |
Run all tests |
mix test path/to/test.exs:42 |
Run a specific test by line |
mix format |
Format all code |
mix precommit |
Run before committing (compile, format, test) |
Architecture
- Elixir/Phoenix 1.8 with Bandit HTTP server
- PostgreSQL 16 via Ecto (Docker Compose in production, local in dev)
- Docker Swarm for zero-downtime app deploys (start-first rolling updates)
- Phoenix LiveView for real-time UI
- Tailwind CSS 4 + daisyUI for styling
- Oban for background jobs (mirror sync, CI dispatch, webhook delivery, deployments, AI jobs, backups, imports)
- Git operations abstracted behind a behaviour (
Gitblixt.Git) with shell (Gitblixt.Git.Shell) and native Rust/gitoxide (Gitblixt.Git.Native) implementations - SSH transport via the Erlang
:sshapplication with database-backed key lookup
Building the Docker Image
docker build -t willc0de4food/gitblixt:latest .
Documentation
A complete, in-app knowledgebase ships with every instance at /docs — covering installation, configuration, and every feature (repositories, issues, merge requests, code review, CI/CD, the built-in PaaS, the AI assistant, and more).
GitBlixt also exposes a GitLab-compatible REST API at /api/v4, so existing GitLab tooling works against your instance unchanged. The endpoint reference lives at /docs/api.
Public repositories can be cloned by anyone over HTTPS — no account required:
git clone https://your-instance.example/namespace/repo.git
Pushing, and cloning private repositories, requires authentication: an SSH key or a personal access token (see /docs/access-tokens).
Contributing
Contributions are welcome — see CONTRIBUTING.md for the workflow and DCO sign-off requirement.
License
GitBlixt is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
If you run a modified version of GitBlixt as a network service, AGPL-3.0 requires that you make the corresponding source available to your users.
Copyright (c) 2026 GitBlixt contributors.
Disclaimer
GitBlixt is provided "as is", without warranty of any kind and you use it at your own risk. To the fullest extent permitted by law, the authors and contributors are not liable for any damage, data loss, downtime, security incident, cost, or other harm arising from the use, deployment, or operation of this software — including anything that happens to your server, infrastructure, or data. You are solely responsible for how you deploy and operate it. The full legal terms are in sections 15–17 of the LICENSE.