# Polar **Lightweight self-hosted Git hosting in a single Go binary.** Polar is a small, fast alternative to heavyweight Git servers: push over HTTP, browse code, file issues, open pull requests, and publish releases — all served from one static binary with an embedded SQLite database and no external runtime dependencies. ## Highlights - **One binary, zero dependencies** — `CGO_ENABLED=0` build, pure-Go SQLite (`modernc.org/sqlite`) in WAL mode, bare repositories stored on disk. - **Git Smart HTTP** — anonymous read access for public repositories, token-authenticated push, per-user personal access tokens, and browser-assisted sign-in via the OAuth 2.0 Device Authorization Grant (RFC 8628). - **Code browsing** — file tree, blob viewer with server-side syntax highlighting (Chroma), commit history, diffs, branches, tags, and zip archives. The **New file**, **New folder** and **Upload files** actions let you create or upload content right in the browser — changes are committed straight to the selected branch, no local checkout required. - **Collaboration** — issues with comments and open/close state; pull requests with comments, approvals and change requests; forks with cross-fork pull requests; per-repository collaborators with read/write roles; and releases with changelogs. - **Polished UI** — `html/template` + htmx, no SPA build step; Markdown rendered with Goldmark and sanitized with bluemonday; Hugeicons outline sprite; self-hosted Inter and JetBrains Mono fonts (Cyrillic subsets included). - **Command palette** — press `Ctrl+K` / `Cmd+K` for quick navigation and actions. - **Three themes** — Light (`#fff` background, `#111` foreground), Dark (`#111` background, `#fff` foreground), and System (follows the OS `prefers-color-scheme`). The choice is persisted in a `polar_theme` cookie so the server renders the correct `data-theme` on first paint — no flash of the wrong theme. - **Bilingual interface** — Russian and English, with a configurable default language. - **Practical security** — Argon2id password hashing, CSRF protection, rate-limited login and registration, session cookies, and revocable access tokens. ## Quick Start ### Build from source Requirements: Go (version per `go.mod`) and `git` available on the host. ```bash CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o polar ./cmd/polar ./polar ``` Polar starts on `0.0.0.0:3000` and keeps its data in `./data`. Open http://localhost:3000 and register — **the first registered account becomes the administrator**. After that you can disable public registration or manage users from the admin panel. ### Docker ```bash docker compose up -d ``` Or without Compose: ```bash docker build -t polar . docker run -d --name polar -p 3000:3000 -v "$PWD/data:/app/data" polar ``` ### systemd ```ini # /etc/systemd/system/polar.service [Unit] Description=Polar Self-Hosted Git Server After=network.target [Service] Type=simple User=polar Group=polar WorkingDirectory=/var/lib/polar ExecStart=/usr/local/bin/polar -config /etc/polar/polar.toml Environment=POLAR_STORAGE_DATA_DIR=/var/lib/polar/data Restart=on-failure [Install] WantedBy=multi-user.target ``` ## Configuration Polar runs with sensible defaults and no config file. To customize, copy `polar.example.toml` to `polar.toml` (auto-detected in the working directory) or pass `-config /path/to/polar.toml`. Every setting can also be provided through environment variables, which take precedence over the file. ```toml [server] host = "0.0.0.0" port = 3000 base_url = "http://localhost:3000" [storage] data_dir = "./data" [auth] registration_enabled = true [landing] enabled = true default_lang = "en" # "en" or "ru" ``` | Environment variable | Description | Default | |---|---|---| | `POLAR_SERVER_HOST` | HTTP listen host | `0.0.0.0` | | `POLAR_SERVER_PORT` | HTTP listen port | `3000` | | `POLAR_SERVER_BASE_URL` | Public URL used for clone links | `http://localhost:3000` | | `POLAR_STORAGE_DATA_DIR` | Directory for the database and bare repositories | `./data` | | `POLAR_AUTH_REGISTRATION_ENABLED` | Allow public registration | `true` | | `POLAR_LANDING_ENABLED` | Serve the landing page at `/` | `true` | | `POLAR_LANDING_DEFAULT_LANG` | Default UI language (`ru` or `en`) | `ru` | | `POLAR_CONFIG` | Path to the configuration file | `polar.toml` if present | Short aliases are also accepted: `POLAR_HOST`, `POLAR_PORT`, `POLAR_BASE_URL`, `POLAR_DATA_DIR`. ## Git over HTTP Clone a public repository: ```bash git clone http://localhost:3000/rin/demo.git ``` Push using a personal access token (create one in **Settings → Access tokens**; it is shown once and looks like `polar_...`): ```bash git clone http://localhost:3000/rin/demo.git cd demo git remote set-url origin http://rin:polar_XXXXXXXXXX@localhost:3000/rin/demo.git git push ``` When git asks for credentials, use your username as the login and the token as the password. Tokens can be revoked at any time from the settings page. ### Browser-assisted sign-in (device flow) Instead of pasting a token, let the bundled credential helper obtain one through your browser. Polar implements the OAuth 2.0 Device Authorization Grant (RFC 8628): 1. `git push` asks for credentials; the helper requests a device code from `POST /api/v1/device/code`. 2. It opens `{base_url}/login/device?user_code=XXXX-XXXX` in your browser — sign in and approve (or deny) the request. 3. The helper polls `POST /api/v1/device/token`, receives a personal access token, and caches it in `~/.polar/credentials.json`. Register the helper once, pointing the path at your Polar checkout: ```bash # Linux / macOS git config --global credential.helper '!sh /path/to/polar/scripts/git-credential-polar.sh' # Windows (PowerShell) git config --global credential.helper "!powershell -NoProfile -ExecutionPolicy Bypass -File C:/path/to/polar/scripts/git-credential-polar.ps1" ``` Device codes expire after 15 minutes, are single-use, and the issued token can be revoked like any other. Set `POLAR_URL` to override the server address detected from the git remote. ## Forks, Collaborators and Reviews **Forks.** The **Fork** button on any repository page copies the project to your account. Forking a fork re-roots the copy to the upstream repository, and every fork records its origin — the repository page shows a `forked from` line linking back. If you already have a fork, the button takes you to it instead of creating a duplicate. **Cross-fork pull requests.** Open a pull request from any branch of your fork into the base repository. The PR page marks the head repository, and merging a cross-fork pull request first fetches the head commits into the base repository, so no commits are lost. **Collaborators.** Repository owners and instance administrators manage access in **Settings → Collaborators**: add any registered account with a `read` or `write` role, change roles, or remove access at any time. **Reviews.** On an open pull request, reviewers submit an **Approve** or **Request changes** verdict — reviewing your own pull request is not allowed. Each reviewer has one current verdict, and the review panel lists them all. ## Themes Polar ships exactly three themes, selectable from the theme switcher (or the command palette): | Theme | Background | Foreground | |---|---|---| | Light | `#fff` | `#111` | | Dark | `#111` | `#fff` | | System | follows the OS `prefers-color-scheme` | — | The active theme is saved to `localStorage` and a `polar_theme` cookie, so the server renders `` immediately and there is no flash of the wrong theme on load. ## Project Layout ``` polar/ ├── cmd/polar/main.go # Entry point, dependency wiring, graceful shutdown ├── internal/ │ ├── config/ # polar.toml + POLAR_* environment overrides │ ├── db/ # SQLite connection and migrations │ ├── auth/ # Sessions, CSRF, Argon2id, access tokens │ ├── user/ # User accounts and profiles │ ├── repo/ # Repositories, issues, pull requests, releases │ ├── git/ # Git plumbing (bare repos, commits, diffs) │ ├── i18n/ # Russian and English message catalogs │ └── web/ │ ├── handlers/ # HTTP and Git Smart HTTP handlers │ ├── middleware/ # Auth, CSRF, rate limiting, i18n │ ├── views/ # html/template views │ └── static/ # go:embed assets (CSS, JS, fonts, icons) ├── assets/input.css # Tailwind source for the generated stylesheet ├── scripts/ # git credential helpers (device-flow sign-in) ├── polar.example.toml ├── Makefile ├── Dockerfile └── docker-compose.yml ``` ## Development ```bash make dev # run locally make test # go test ./... make lint # go vet ./... make build # static binary with -trimpath -ldflags="-s -w" make build-all # cross-compile Linux/macOS/Windows binaries into dist/ make css # rebuild internal/web/static/css/app.css (requires the Tailwind CLI) ``` All runtime assets are embedded with `go:embed` — the binary needs no external CDN or asset directory. See `THIRD_PARTY.md` for licenses of bundled assets (Hugeicons icons, Inter and JetBrains Mono fonts, htmx) and Go dependencies. ## Data and Backups ``` data/ ├── polar.db # SQLite database (WAL mode) └── repos/ # Bare Git repositories, e.g. repos/rin/demo.git ``` Safe backup while Polar is running: ```bash sqlite3 data/polar.db "VACUUM INTO 'data/polar-backup.db';" tar -czf polar-backup-$(date +%F).tar.gz data/polar-backup.db data/repos/ rm data/polar-backup.db ``` To restore, stop Polar, replace `data/polar.db` and `data/repos/` with the backup contents, and start it again. ## Health Check `GET /healthz` returns JSON with the database status — handy for Docker health checks and load balancers.