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