# Soft Serve: a self-hosted Git server you reach over SSH

> Soft Serve is a single Go binary that serves Git over SSH, HTTP and the git protocol, with a terminal UI you connect to with ssh. It fits small teams who want Git hosting on their own box without a web application.

**charmbracelet/soft-serve** — The mighty, self-hostable Git server for the command line. You can also try some of the following commands: Or you can use Soft Serve to browse local repositories using soft browse [directory] or running soft within a Git repository.

- Repository: https://github.com/charmbracelet/soft-serve
- Stars: 7,231 · Forks: 242
- Language: Go
- License: MIT
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/charmbracelet-soft-serve

## The gap Soft Serve fills: Git hosting without a web app

Most self-hosted Git servers are web applications that happen to speak Git. Soft Serve inverts that. The README describes it as a self-hostable Git server for the command line, and the primary interface is an SSH connection that drops you into a terminal UI rather than a browser. The README points readers at a live example with ssh git.charm.sh, and the same connection handles browsing, file printing and repository administration.

The audience is narrow and specific. It is someone who already administers a Linux box, already has an SSH key, and wants a Git remote that is not GitHub or GitLab. The README lists the management surface: create repos on demand with SSH or git push, add collaborators with SSH public keys, mark repos public or private, and issue user access tokens. That is a hosting primitive, not a collaboration platform. If your team's workflow depends on reviewing a diff in a browser before merging, this is the wrong shape of tool and no amount of configuration changes that.

## How the pieces fit: one binary, three protocols, one data directory

The repository is a Go module, github.com/charmbracelet/soft-serve, built around a single command called soft. The cmd directory holds the entry point and pkg holds the rest. The dependency list shows what the server is assembled from: charm.land/wish/v2 for SSH, charm.land/bubbletea/v2 and charm.land/lipgloss/v2 for the terminal interface, go-git/go-git for repository access, and modernc.org/sqlite plus lib/pq for storage.

That last pair is the clearest architectural signal. Soft Serve supports both SQLite and Postgres for its database, so a single-file deployment and a shared database server are both on the table. The Dockerfile exposes four ports: 23231 for SSH, 23232 for HTTP, 23233 for stats, and 9418 for the git protocol. The default config.yaml sets the SSH listener to :23231 and the public clone URL to ssh://localhost:23231.

Configuration lives in config.yaml inside the data directory, and every setting has an environment variable counterpart prefixed with SOFT_SERVE_. The README names SOFT_SERVE_NAME, SOFT_SERVE_SSH_LISTEN_ADDR, SOFT_SERVE_SSH_KEY_PATH, SOFT_SERVE_HTTP_LISTEN_ADDR, SOFT_SERVE_HTTP_PUBLIC_URL, SOFT_SERVE_GIT_MAX_CONNECTIONS, SOFT_SERVE_ANON_ACCESS and SOFT_SERVE_ALLOW_KEYLESS. Environment variables override the file, which is what makes container deployment practical.

## Installing Soft Serve and creating the first admin

The README says Soft Serve is a single binary called soft and lists package managers for it. On macOS or Linux with Homebrew the command is brew install charmbracelet/tap/soft-serve. Windows users get winget install charmbracelet.soft-serve. Arch, Nix, Debian/Ubuntu and Fedora/RHEL are covered too, and the releases page carries binaries for Linux, macOS and Windows plus Alpine, Debian and RPM packages. Installing from source is also documented:

```bash
go install github.com/charmbracelet/soft-serve/cmd/soft@latest
```

That puts soft on your GOPATH bin path. Once it is there, the server setup is deliberately short. The README says to make sure git is installed, then run soft serve, and that this creates a data directory holding the repos, SSH keys and database. The one thing you should not skip on a first run is the admin key, because the README states that SOFT_SERVE_INITIAL_ADMIN_KEYS must be set to your SSH authorized key and that any key added to it is treated as admin with full privileges. A first boot that also creates a repository looks like this:

```bash
SOFT_SERVE_INITIAL_ADMIN_KEYS="$(cat ~/.ssh/id_ed25519.pub)" \
SOFT_SERVE_DEFAULT_REPO=gitops \
  soft serve
```

The README explains that SOFT_SERVE_DEFAULT_REPO creates the named repository on boot, empty and public, exactly as if a human had run repo create gitops with no flags. It is explicit that only the repository's existence is guaranteed on boot, not its reachability, which still follows the anon-access and allow-keyless settings. Booting again against the same data directory is a no-op if the repository already exists. That matters for GitOps tooling such as ArgoCD, which needs a git remote to point at during its own bootstrap. If you would rather not run the server on your workstation, the README points at the systemd page for running it as a service, and notes that the Apt and Yum packages ship with systemd units.

## Access control is SSH-first, and that is a real constraint

Soft Serve's authentication model is public keys. The README lists SSH authentication using public keys, the ability to allow or disallow anonymous access, adding collaborators by their SSH public keys, per-repo public or private visibility, and user access tokens. Two settings carry most of the weight: anon-access and allow-keyless, both overridable through SOFT_SERVE_ANON_ACCESS and SOFT_SERVE_ALLOW_KEYLESS.

The practical consequence is that onboarding a contributor means obtaining a key from them, not sending an email invite. That is fine for a small group that already trades keys, and awkward for anyone who expects a signup flow. The README does not describe a web-based account creation path, so treat key distribution as part of your process rather than something the server solves for you.

Anonymous access is a policy decision with a visible cost. With anonymous access allowed, the git protocol port and HTTP endpoints become an open read surface for whatever is public. The README does not document rate limiting on those endpoints. The only related knob it names is SOFT_SERVE_GIT_MAX_CONNECTIONS, described as the number of simultaneous connections to the git daemon, which bounds concurrency rather than request rate.

## Where Soft Serve stops: no web UI, no review workflow

The honest limitation is scope. There is no web interface in the README's feature list, and no mention of issues, pull requests, code review, CI or wikis. Browsing happens through the terminal: ssh git.charm.sh -t soft-serve jumps straight into a repo, ssh git.charm.sh repo tree soft-serve prints a directory tree, and ssh git.charm.sh repo blob soft-serve cmd/soft/main.go prints a file, with -c and -l adding syntax highlighting and line numbers. The README also notes you can browse local repositories with soft browse [directory] or by running soft inside a Git repository, which is a genuinely useful escape hatch for reading a repo you have already cloned.

The gap is not cosmetic. A team that reviews changes in a browser before merge is not served by a tree and blob printer, and no configuration option in the README produces a diff view with comments. The other limitation is operational: the README says the data directory stores the repos, SSH keys and database, and it does not document a built-in export, migration or rollback procedure. If you point Soft Serve at the default SQLite database, your backup story is a filesystem copy of that directory, and you should confirm that before you put anything you care about into it. The README is silent on rollback between releases, so pinning a version and reading the release notes before upgrading is the cautious path.

## Gitea and Forgejo take the opposite approach

The obvious alternative is a web-first forge such as Gitea or Forgejo. The difference is not a feature checklist, it is the primary interface. Gitea and Forgejo are web applications: you sign up in a browser, browse code there, open issues there, and review pull requests there. Git is served underneath, but the product is the web application.

Soft Serve is the inverse. The README's own framing is a server for the command line, and its distinguishing feature list is a TUI over SSH, cloning over SSH, HTTP or the git protocol, and Git LFS support with both HTTP and SSH backends. If you want issues and a review UI, choose a forge and accept the web stack, the database and the upgrade treadmill that come with it. If you want a Git remote with a terminal interface and you already live in SSH, Soft Serve removes a whole layer. The two are not substitutes for the same job, and picking the wrong one is usually a decision about whether your team reviews code in a browser.

One thing Soft Serve does that a heavier forge often makes awkward is Git LFS. The README lists LFS support with both HTTP and SSH backends, and the module requires github.com/charmbracelet/git-lfs-transfer, so LFS is a first-class path rather than an add-on you bolt on later.

## Licence, maintenance and the cost of staying current

Soft Serve is MIT licensed, which is permissive: you can run it commercially, modify it and redistribute it, provided the copyright notice and permission notice are preserved. This is not legal advice, and if you plan to redistribute a modified binary you should read the LICENSE file in the repository root yourself.

On maintenance, the repository is not archived, and the last push was on 2026-08-07. Releases v0.12.0, v0.12.1 and v0.12.2 all landed within the first week of August 2026, which suggests a project still cutting releases. The version numbers also tell you something about expectations: this is pre-1.0 software, so a minor bump can carry a breaking change and the README does not promise configuration stability across upgrades. The upgrade cost is therefore mostly your own diligence. Read the release notes for the version you are moving to, keep your config.yaml under version control, and remember that the data directory is the thing you cannot regenerate from a config file. The systemd unit shipped with the Apt and Yum packages is the simplest way to keep a server running across reboots without writing your own unit.

## Conclusion

Soft Serve suits a small team or a single admin who wants Git hosting on a machine they control and is comfortable giving out SSH keys. It is the wrong tool if you need an issue tracker, pull request review or a browser-based code view, because none of those exist here. Before adopting it, run soft serve once with SOFT_SERVE_INITIAL_ADMIN_KEYS set and read the generated config.yaml, then confirm your backup routine covers the data directory, which holds the repos, the SSH keys and the database.

## FAQ

### What does Soft Serve mean in this context?

It is the name of a self-hostable Git server for the command line, published by charmbracelet under the module github.com/charmbracelet/soft-serve. The README describes it as a tasty, self-hostable Git server for the command line, and the server binary itself is called soft.

### How is Soft Serve different from a web-based Git host?

Soft Serve's primary interface is an SSH-accessible terminal UI rather than a browser. The README lists a TUI over SSH, cloning over SSH, HTTP or the git protocol, repository management over SSH, and Git LFS support, and it does not list issues, pull requests or a web code browser.

### How to use Soft Serve to browse a repository?

The README gives ssh git.charm.sh repo tree soft-serve for a directory tree and ssh git.charm.sh repo blob soft-serve cmd/soft/main.go for a single file, with -c and -l adding syntax highlighting and line numbers. Locally you can run soft browse [directory] or run soft inside a Git repository.

### How do I set up a Soft Serve machine as an admin?

Make sure git is installed, then run soft serve. The README states that SOFT_SERVE_INITIAL_ADMIN_KEYS must be set to your SSH authorized key on the first run, and that any key added to it is treated as admin with full privileges, creating an admin user you can rename later.

### How to install Soft Serve?

The README lists brew install charmbracelet/tap/soft-serve for macOS or Linux, winget install charmbracelet.soft-serve on Windows, pacman -S soft-serve on Arch, nix-env -iA nixpkgs.soft-serve, and an Apt repository for Debian and Ubuntu. It also documents go install github.com/charmbracelet/soft-serve/cmd/soft@latest and binary downloads from the releases page.

## Sources

- [Official README](https://github.com/charmbracelet/soft-serve#readme)
- [Project repository](https://github.com/charmbracelet/soft-serve)
- [Release notes](https://github.com/charmbracelet/soft-serve/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/charmbracelet-soft-serve
