Soft Serve
A self-hosted Git server with SSH access, terminal browsing, repository permissions, and Git-based administration.
Why consider Soft Serve?
Soft Serve is a self-hostable, command-line-first Git server built by Charmbracelet. It ships as a single Go binary and exposes a beautiful SSH-accessible TUI for browsing repos, supports cloning over SSH/HTTP/Git protocol, Git LFS, public-key-based access control, and on-demand repo creation via `git push`. Configuration is handled via a plain YAML file and environment variables, with optional Docker or systemd deployment.
Learn Soft Serve by building
Practical setup notes, real use cases, and copy-ready examples in one focused guide.
In this guide8 sections
Soft Serve — Self-Hosted Git Server for the Command Line
Soft Serve is a tasty, self-hostable Git server for the command line. 🍦 Unlike heavyweight Git platforms, Soft Serve is built to live entirely in your terminal: its primary interface is an interactive TUI you reach over SSH, and it ships as a single, dependency-free Go binary.
Key Features
- SSH-first TUI — browse repos, files, and commits from any SSH client with no web browser needed.
- Multiple clone protocols — clone repos over SSH, HTTP, or the native Git protocol (port 9418).
- Git LFS — built-in Git Large File Storage support with both HTTP and SSH backends.
- On-demand repos — create a repository simply by pushing to it for the first time; no admin panel required.
- Public-key access control — granular permissions backed by SSH public keys; repos can be public or private.
- User access tokens — mint tokens for CI/CD pipelines without exposing raw SSH keys.
- Allow/disallow anonymous access — control whether unauthenticated users can clone public repos.
- Syntax-highlighted file printing — print any file over SSH with optional colour highlighting and line numbers.
Installation
Soft Serve is a single binary called soft. Install it from your package manager, download a release binary, or use go install:
# macOS or Linuxbrew install charmbracelet/tap/soft-serve# Windows (with Winget)winget install charmbracelet.soft-serve# Arch Linuxpacman -S soft-serve# Nixnix-env -iA nixpkgs.soft-serve# Debian/Ubuntusudo mkdir -p /etc/apt/keyringscurl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpgecho "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.listsudo apt update && sudo apt install soft-serve# Fedora/RHELecho '[charm]name=Charmbaseurl=https://repo.charm.sh/yum/enabled=1gpgcheck=1gpgkey=https://repo.charm.sh/yum/gpg.key' | sudo tee /etc/yum.repos.d/charm.reposudo yum install soft-serve# Gogo install github.com/charmbracelet/soft-serve/cmd/soft@latestBinaries are available for Linux, macOS, and Windows, as well as Alpine, Debian, and RPM packages, on the releases page.
Setting Up a Server
Make sure git is installed, then run soft serve. That's it.
This will create a data directory that will store all the repos, ssh keys, and database.
On first run, set SOFT_SERVE_INITIAL_ADMIN_KEYS to your SSH public key so you get admin access:
SOFT_SERVE_INITIAL_ADMIN_KEYS="$(cat ~/.ssh/id_ed25519.pub)" \SOFT_SERVE_DEFAULT_REPO=gitops \ soft serveAny key added to this variable is treated as admin with full privileges. Soft Serve will create a new admin user that you can rename later. The optional SOFT_SERVE_DEFAULT_REPO variable causes a named repository to be created empty and public on boot — useful for GitOps tools like ArgoCD.
To use a custom data path:
SOFT_SERVE_DATA_PATH=/var/lib/soft-serve soft serveRunning with Docker
The official Docker image is available at charmcli/soft-serve. Mount the /soft-serve volume to persist your repositories:
docker run \ --name=soft-serve \ --volume /path/to/data:/soft-serve \ --publish 23231:23231 \ --publish 23232:23232 \ --publish 23233:23233 \ --publish 9418:9418 \ -e SOFT_SERVE_INITIAL_ADMIN_KEYS="YOUR_ADMIN_KEY_HERE" \ --restart unless-stopped \ charmcli/soft-serve:latestPorts exposed: 23231 (SSH), 23232 (HTTP), 23233 (stats), 9418 (Git protocol).
Server Configuration
Once the server starts, a config.yaml is generated under the data directory. The default configuration covers SSH, HTTP, the Git daemon, database backend (SQLite or Postgres), Git LFS, cron mirror jobs, and a stats server:
# Soft Serve Server configurations# The name of the server.# This is the name that will be displayed in the UI.name: "Soft Serve"# Log format to use. Valid values are "json", "logfmt", and "text".log_format: "text"# The SSH server configuration.ssh: # The address on which the SSH server will listen. listen_addr: ":23231" # The public URL of the SSH server. # This is the address that will be used to clone repositories. public_url: "ssh://localhost:23231" # The path to the SSH server's private key. key_path: "ssh/soft_serve_host" # The path to the SSH server's client private key. client_key_path: "ssh/soft_serve_client" # The maximum number of seconds a connection can take. max_timeout: 0 # The number of seconds a connection can be idle before it is closed. idle_timeout: 120# The Git daemon configuration.git: listen_addr: ":9418" max_timeout: 0 idle_timeout: 3 max_connections: 32# The HTTP server configuration.http: listen_addr: ":23232" tls_key_path: "" tls_cert_path: "" public_url: "http://localhost:23232"# The database configuration.db: # Valid values are "sqlite" and "postgres". driver: "sqlite" data_source: "soft-serve.db?_pragma=busy_timeout(5000)&_pragma=foreign_keys(1)"# Git LFS configuration.lfs: enabled: true ssh_enabled: false# Cron job configurationjobs: mirror_pull: "@every 10m"# The stats server configuration.stats: listen_addr: ":23233"Every setting can also be overridden with an environment variable prefixed SOFT_SERVE_.
Browsing Repositories via SSH
With the server running you can connect to the live Charm demo to explore the TUI:
# Jump directly to a repo in the TUIssh git.charm.sh -t soft-serve# Print out a directory tree for a repossh git.charm.sh repo tree soft-serve# Print a specific filessh git.charm.sh repo blob soft-serve cmd/soft/main.go# Print a file with syntax highlighting and line numbersssh git.charm.sh repo blob soft-serve cmd/soft/main.go -c -lYou can also browse local repositories with soft browse [directory] or by running soft inside any Git repository.
Access Control
Soft Serve uses SSH public keys for authentication. Users are not tied to the underlying Linux system — all user and permission management is done through the server itself. Key capabilities:
- Allow or disallow anonymous access per-server.
- Mark individual repos public or private.
- Add collaborators by their SSH public key.
- Issue access tokens for scripted or CI use cases.
Summary
Soft Serve turns Git hosting into a pure terminal experience. A single soft serve command is all it takes to spin up a fully featured Git server with an SSH TUI, multi-protocol clone support, Git LFS, fine-grained access control, and optional Docker or systemd deployment — no Nginx, no databases to configure by hand, no web UI to maintain.
Related tools
More options with a similar category or technology profile.
diskus
Minimal, fast alternative to du -sh written in Rust using multi-threaded directory traversal.
peco
Simplistic interactive filtering tool for Unix pipelines, process lists, and file trees.
Dapr CLI
Command-line tool for managing Dapr distributed application runtime environments and sidecars.
Freeze
Generate beautiful image screenshots and SVGs of code snippets and terminal outputs.