1Soft Serve
  2==========
  3
  4<p>
  5    <img style="width: 451px" src="https://stuff.charm.sh/soft-serve/soft-serve-header.png?0" alt="A nice rendering of some melting ice cream with the words āCharm Soft Serveā next to it"><br>
  6    <a href="https://github.com/charmbracelet/soft-serve/releases"><img src="https://img.shields.io/github/release/charmbracelet/soft-serve.svg" alt="Latest Release"></a>
  7    <a href="https://pkg.go.dev/github.com/charmbracelet/soft-serve?tab=doc"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a>
  8    <a href="https://github.com/charmbracelet/soft-serve/actions"><img src="https://github.com/charmbracelet/soft-serve/workflows/build/badge.svg" alt="Build Status"></a>
  9    <a href="https://nightly.link/charmbracelet/soft-serve/workflows/nightly/main"><img src="https://shields.io/badge/-Nightly%20Builds-orange?logo=hackthebox&logoColor=fff&style=appveyor"/></a>
 10</p>
 11
 12A tasty, self-hostable Git server for the command line. š¦
 13
 14<picture>
 15  <source media="(max-width: 750px)" srcset="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0">
 16  <source media="(min-width: 750px)" width="750" srcset="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0">
 17  <img src="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0" alt="Soft Serve screencast">
 18</picture>
 19
 20* Configure with `git`
 21* Create repos on demand with `git push`
 22* Browse repos, files and commits with an SSH-accessible TUI
 23* TUI mouse support
 24* Print files over SSH with or without syntax highlighting and line numbers
 25* Easy access control
 26  - Allow/disallow anonymous access
 27  - Add collaborators with SSH public keys
 28  - Repos can be public or private
 29
 30## Where can I see it?
 31
 32Just run `ssh git.charm.sh` for an example. You can also try some of the following commands:
 33
 34```bash
 35# Jump directly to a repo in the TUI
 36ssh git.charm.sh -t soft-serve
 37
 38# Print out a directory tree for a repo
 39ssh git.charm.sh ls soft-serve
 40
 41# Print a specific file
 42ssh git.charm.sh cat soft-serve/cmd/soft/root.go
 43
 44# Print a file with syntax highlighting and line numbers
 45ssh git.charm.sh cat soft-serve/cmd/soft/root.go -c -l
 46```
 47
 48## Installation
 49
 50Soft Serve is a single binary called `soft`. You can get it from a package
 51manager:
 52
 53```bash
 54# macOS or Linux
 55brew tap charmbracelet/tap && brew install charmbracelet/tap/soft-serve
 56
 57# Arch Linux
 58pacman -S soft-serve
 59
 60# Nix
 61nix-env -iA nixpkgs.soft-serve
 62
 63# Debian/Ubuntu
 64echo 'deb [trusted=yes] https://repo.charm.sh/apt/ /' | sudo tee /etc/apt/sources.list.d/charm.list
 65sudo apt update && sudo apt install soft-serve
 66
 67# Fedora
 68echo '[charm]
 69name=Charm
 70baseurl=https://repo.charm.sh/yum/
 71enabled=1
 72gpgcheck=0' | sudo tee /etc/yum.repos.d/charm.repo
 73sudo yum install soft-serve
 74```
 75
 76You can also download a binary from the [releases][releases] page. Packages are
 77available in Alpine, Debian, and RPM formats. Binaries are available for Linux,
 78macOS, and Windows.
 79
 80[releases]: https://github.com/charmbracelet/soft-serve/releases
 81
 82Or just install it with `go`:
 83
 84```bash
 85go install github.com/charmbracelet/soft-serve/cmd/soft@latest
 86```
 87
 88## Setting up a server
 89
 90Make sure `git` is installed, then run `soft`. Thatās it.
 91
 92A [Docker image][docker] is also available.
 93
 94[docker]: https://github.com/charmbracelet/soft-serve/blob/main/docker.md
 95
 96## Configuration
 97
 98The Soft Serve configuration is simple and straightforward:
 99
100```yaml
101# The name of the server to show in the TUI.
102name: Soft Serve
103
104# The host and port to display in the TUI. You may want to change this if your
105# server is accessible from a different host and/or port that what it's
106# actually listening on (for example, if it's behind a reverse proxy).
107host: localhost
108port: 23231
109
110# Access level for anonymous users. Options are: admin-access, read-write,
111# read-only, and no-access.
112anon-access: read-write
113
114# You can grant read-only access to users without private keys.
115allow-keyless: false
116
117# Customize repos in the menu
118repos:
119  - name: Home
120    repo: config
121    private: true
122    note: "Configuration and content repo for this server"
123  - name: Example Public Repo
124    repo: my-public-repo
125    private: false
126    note: "A publicly-accessible repo"
127    readme: docs/README.md
128  - name: Example Private Repo
129    repo: my-private-repo
130    private: true
131    note: "A private repo"
132
133# Authorized users. Admins have full access to all repos. Regular users
134# can read all repos and push to their collab-repos.
135users:
136  - name: Beatrice
137    admin: true
138    public-keys:
139      - ssh-rsa AAAAB3Nz...   # redacted
140      - ssh-ed25519 AAAA...   # redacted
141  - name: Frankie
142    collab-repos:
143      - my-public-repo
144      - my-private-repo
145    public-keys:
146      - ssh-rsa AAAAB3Nz...   # redacted
147      - ssh-ed25519 AAAA...   # redacted
148```
149
150When `soft serve` is run for the first time, it creates a configuration repo
151containing the main README displayed in the TUI as well as a config file for
152user access control.
153
154```
155git clone ssh://localhost:23231/config
156```
157
158The `config` repo is publicly writable by default, so be sure to setup your
159access as desired. You can also set the `SOFT_SERVE_INITIAL_ADMIN_KEY`
160environment variable before first run and it will restrict access to that
161initial public key until you configure things otherwise.
162If you're having trouble, make sure you have generated keys with `ssh-keygen`
163as configuration is not supported for keyless users.
164
165### Server Settings
166
167In addition to the Git-based configuration above, there are a few
168environment-level settings:
169
170* `SOFT_SERVE_PORT`: SSH listen port (_default 23231_)
171* `SOFT_SERVE_HOST`: Address to use in public clone URLs
172* `SOFT_SERVE_BIND_ADDRESS`: Network interface to listen on (_default 0.0.0.0_)
173* `SOFT_SERVE_KEY_PATH`: SSH host key-pair path (_default .ssh/soft_serve_server_ed25519_)
174* `SOFT_SERVE_REPO_PATH`: Path where repos are stored (_default .repos_)
175* `SOFT_SERVE_INITIAL_ADMIN_KEY`: The public key that will initially have admin access to repos (_default ""_). This must be set before `soft` runs for the first time and creates the `config` repo. If set after the `config` repo has been created, this setting has no effect.
176
177## Pushing (and creating!) repos
178
179You can add your Soft Serve server as a remote to any existing repo:
180
181```
182git remote add soft ssh://localhost:23231/REPO
183```
184
185After youāve added the remote just go ahead and push. If the repo doesnāt exist
186on the server itāll be created.
187
188```
189git push soft main
190```
191
192## The Soft Serve TUI
193
194<img src="https://stuff.charm.sh/soft-serve/soft-serve-demo-commit.png" width="750" alt="TUI example showing a diff">
195
196Soft Serve serves a TUI over SSH for browsing repos, viewing files and commits,
197and grabbing clone commands:
198
199```
200ssh localhost -p 23231
201```
202
203It's also possible to ālinkā to a specific repo:
204
205```
206ssh localhost -t -p 23231 REPO
207```
208
209You can copy text to your clipboard over SSH. For instance, you can press <kbd>c</kbd> on the highlighted repo in the menu to copy the clone command [^osc52].
210
211[^osc52]: Copying over SSH depends on your terminal support of OSC52.
212
213## The Soft Serve SSH CLI
214
215```sh
216$ ssh -p 23231 localhost help
217Soft Serve is a self-hostable Git server for the command line.
218
219Usage:
220  ssh -p 23231 localhost [command]
221
222Available Commands:
223  cat         Outputs the contents of the file at path.
224  git         Perform Git operations on a repository.
225  help        Help about any command
226  ls          List file or directory at path.
227  reload      Reloads the configuration
228
229Flags:
230  -h, --help   help for ssh
231
232Use "ssh -p 23231 localhost [command] --help" for more information about a command.
233```
234
235Soft Serve SSH CLI has the ability to print files and list directories, perform
236`git` operations on remote repos, and reload the configuration when necessary.
237
238To print a file tree for the project, just use the `list` command along with the
239repo name as the SSH command to your Soft Serve server:
240
241```sh
242ssh -p 23231 localhost ls soft-serve
243```
244
245From there, you can print individual files using the `cat` command:
246
247```sh
248ssh -p 23231 localhost cat soft-serve/cmd/soft/root.go
249```
250
251You can add the `-c` flag to enable syntax coloring and `-l` to print line
252numbers:
253
254```sh
255ssh -p 23231 localhost cat soft-serve/cmd/soft/root.go -c -l
256```
257
258You can also use the `git` command to perform Git operations on a repo such as changing the default branch name for instance:
259
260```sh
261ssh -p 23231 localhost git soft-serve symbolic-ref HEAD refs/heads/taco
262```
263
264Both `git` and `reload` commands need admin access to the server to work. So
265make sure you have added your key as an admin user, or youāre using `anon-access:
266admin-access` in the configuration.
267
268## Managing Repos
269
270`.repos` and `.ssh` directories are created when you first run `soft` at the paths specified for the `SOFT_SERVE_KEY_PATH` and `SOFT_SERVE_REPO_PATH` environment variables. 
271It's recommended to have a dedicated directory for your soft-serve repos and config.
272
273### Deleting a Repo
274
275To delete a repo from your soft serve server, you'll have to remove the repo from the .repos directory.
276
277### Renaming a Repo
278
279To rename a repo's display name in the menu, change its name in the config.yaml file for your soft serve server.
280By default, the display name will be the repository name. 
281
282## A note about RSA keys
283
284Unfortunately, due to a shortcoming in Goās `x/crypto/ssh` package, Soft Serve
285does not currently support access via new SSH RSA keys: only the old SHA-1
286ones will work.
287
288Until we sort this out youāll either need an SHA-1 RSA key or a key with
289another algorithm, e.g. Ed25519. Not sure what type of keys you have?
290You can check with the following:
291
292```
293$ find ~/.ssh/id_*.pub -exec ssh-keygen -l -f {} \;
294```
295
296If youāre curious about the inner workings of this problem have a look at:
297
298- https://github.com/golang/go/issues/37278
299- https://go-review.googlesource.com/c/crypto/+/220037
300- https://github.com/golang/crypto/pull/197
301
302## Feedback
303
304Weād love to hear your thoughts on this project. Feel free to drop us a note!
305
306* [Twitter](https://twitter.com/charmcli)
307* [The Fediverse](https://mastodon.technology/@charm)
308* [Slack](https://charm.sh/slack)
309
310## License
311
312[MIT](https://github.com/charmbracelet/soft-serve/raw/main/LICENSE)
313
314***
315
316Part of [Charm](https://charm.sh).
317
318<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
319
320Charmēē±å¼ęŗ ⢠Charm loves open source