README.md

  1# Soft Serve
  2
  3<p>
  4    <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>
  5    <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>
  6    <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>
  7    <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>
  8    <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>
  9</p>
 10
 11A tasty, self-hostable Git server for the command line. šŸ¦
 12
 13<picture>
 14  <source media="(max-width: 750px)" srcset="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0">
 15  <source media="(min-width: 750px)" width="750" srcset="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0">
 16  <img src="https://stuff.charm.sh/soft-serve/soft-serve-demo.gif?0" alt="Soft Serve screencast">
 17</picture>
 18
 19- Easy to navigate TUI available over SSH
 20- Clone repos over SSH, HTTP, or Git protocol
 21- Manage repos with SSH
 22- Create repos on demand with SSH or `git push`
 23- Browse repos, files and commits with SSH-accessible
 24- Print files over SSH with or without syntax highlighting and line numbers
 25- Easy access control with SSH
 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 repo tree soft-serve
 40
 41# Print a specific file
 42ssh git.charm.sh repo blob soft-serve cmd/soft/root.go
 43
 44# Print a file with syntax highlighting and line numbers
 45ssh git.charm.sh repo blob 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
 64sudo mkdir -p /etc/apt/keyrings
 65curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg
 66echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list
 67sudo apt update && sudo apt install soft-serve
 68
 69# Fedora/RHEL
 70echo '[charm]
 71name=Charm
 72baseurl=https://repo.charm.sh/yum/
 73enabled=1
 74gpgcheck=1
 75gpgkey=https://repo.charm.sh/yum/gpg.key' | sudo tee /etc/yum.repos.d/charm.repo
 76sudo yum install soft-serve
 77```
 78
 79You can also download a binary from the [releases][releases] page. Packages are
 80available in Alpine, Debian, and RPM formats. Binaries are available for Linux,
 81macOS, and Windows.
 82
 83[releases]: https://github.com/charmbracelet/soft-serve/releases
 84
 85Or just install it with `go`:
 86
 87```bash
 88go install github.com/charmbracelet/soft-serve/cmd/soft@latest
 89```
 90
 91## Setting up a server
 92
 93Make sure `git` is installed, then run `soft serve`. That’s it.
 94
 95This will create a `data` directory that will store all the repos, ssh keys,
 96and database.
 97
 98To change the default data path use `SOFT_SERVE_DATA_PATH` environment variable.
 99
100```sh
101SOFT_SERVE_DATA_PATH=/var/lib/soft-serve soft serve
102```
103
104When you run Soft Serve for the first time, make sure you have the
105`SOFT_SERVE_INITIAL_ADMIN_KEY` environment variable is set to your ssh
106authorized key. Any added key to this variable will be treated as admin with
107full privileges.
108
109Using this environment variable, Soft Serve will create a new `admin` user that
110has full privileges. You can rename and change the user settings later.
111
112### Server Settings
113
114Once you start the server for the first time, the settings will be in
115`config.yaml` under your data directory. The default `config.yaml` is
116self-explanatory and will look like this:
117
118```yaml
119# Soft Serve Server configurations
120
121# The name of the server.
122# This is the name that will be displayed in the UI.
123name: "Soft Serve"
124
125# The SSH server configuration.
126ssh:
127  # The address on which the SSH server will listen.
128  listen_addr: ":23231"
129
130  # The public URL of the SSH server.
131  # This is the address that will be used to clone repositories.
132  public_url: "ssh://localhost:23231"
133
134  # The path to the SSH server's private key.
135  key_path: "ssh/soft_serve_host"
136
137  # The path to the SSH server's client private key.
138  # This key will be used to authenticate the server to make git requests to
139  # ssh remotes.
140  client_key_path: "ssh/soft_serve_client"
141
142  # The path to the SSH server's internal api private key.
143  internal_key_path: "ssh/soft_serve_internal"
144
145  # The maximum number of seconds a connection can take.
146  # A value of 0 means no timeout.
147  max_timeout: 0
148
149  # The number of seconds a connection can be idle before it is closed.
150  idle_timeout: 120
151
152# The Git daemon configuration.
153git:
154  # The address on which the Git daemon will listen.
155  listen_addr: ":9418"
156
157  # The maximum number of seconds a connection can take.
158  # A value of 0 means no timeout.
159  max_timeout: 0
160
161  # The number of seconds a connection can be idle before it is closed.
162  idle_timeout: 3
163
164  # The maximum number of concurrent connections.
165  max_connections: 32
166
167# The HTTP server configuration.
168http:
169  # The address on which the HTTP server will listen.
170  listen_addr: ":8080"
171
172  # The path to the TLS private key.
173  tls_key_path: ""
174
175  # The path to the TLS certificate.
176  tls_cert_path: ""
177
178  # The public URL of the HTTP server.
179  # This is the address that will be used to clone repositories.
180  # Make sure to use https:// if you are using TLS.
181  public_url: "http://localhost:8080"
182
183# The stats server configuration.
184stats:
185  # The address on which the stats server will listen.
186  listen_addr: ":8081"
187```
188
189You can also use environment variables, to override these settings. All server
190settings environment variables start with `SOFT_SERVE_` followed by the setting
191name all in uppercase. Here are some examples:
192
193- `SOFT_SERVE_NAME`: The name of the server that will appear in the TUI
194- `SOFT_SERVE_SSH_LISTEN_ADDR`: SSH listen address
195- `SOFT_SERVE_SSH_KEY_PATH`: SSH host key-pair path
196- `SOFT_SERVE_HTTP_LISTEN_ADDR`: HTTP listen address
197- `SOFT_SERVE_HTTP_PUBLIC_URL`: HTTP public URL used for cloning
198- `SOFT_SERVE_GIT_MAX_CONNECTIONS`: The number of simultaneous connections to git daemon
199
200A [Docker image][docker] is also available.
201
202[docker]: https://github.com/charmbracelet/soft-serve/blob/main/docker.md
203
204## Configuration
205
206Configuring Soft Serve is simple and straightforward. Use the SSH command-line
207interface to manage access settings, users, and repos.
208
209For more info try `ssh localhost -i ~/.ssh/id_ed25519 -p 23231 help`. Make sure
210you use your key here.
211
212> **Note** The `-i` part will be omitted in the examples below for brevity. You
213> can add your server settings to your sshconfig for quicker access.
214
215### Access Levels
216
217Soft Serve offers a simple access control. There are four access levels,
218no-access, read-only, read-write, and admin-access.
219
220`admin-access` has full control of the server and can make changes to users and repos.
221
222`read-write` access gets full control of repos.
223
224`read-only` can read public repos.
225
226`no-access` denies access to all repos.
227
228### Authentication
229
230Everything that needs authentication is done using SSH.
231
232By default, Soft Serve gives ready-only permission to anonymous connections to
233any of the above protocols. This is controlled by two settings `anon-access`
234and `allow-keyless`.
235
236- `anon-access`: Defines the access level for anonymous users. Available
237  options are `no-access`, `read-only`, `read-write`, and `admin-access`.
238  Default is `read-only`.
239- `allow-keyless`: Whether to allow connections that doesn't use keys to pass.
240  Setting this to `false` would disable access to SSH keyboard-interactive,
241  HTTP, and Git protocol connections. Default is `true`.
242
243```sh
244$ ssh localhost settings
245Manage server settings
246
247Usage:
248  ssh -p 23231 localhost settings [command]
249
250Available Commands:
251  allow-keyless Set or get allow keyless access to repositories
252  anon-access   Set or get the default access level for anonymous users
253
254Flags:
255  -h, --help   help for settings
256
257Use "ssh -p 23231 localhost settings [command] --help" for more information about a command.
258```
259
260> **Note** These settings can only be changed by admins.
261
262When `allow-keyless` is disabled, connections that don't use SSH Public Key
263authentication will get denied. This means cloning repos over HTTP(s) or git://
264will get denied.
265
266Meanwhile, `anon-access` controls the access level granted to connections that
267use SSH Public Key authentication but are not registered users. The default
268setting for this is `read-only`. This will grant anonymous connections that use
269SSH Public Key authentication `read-only` access to public repos.
270
271## Authorization
272
273Admins can manage users and manage their keys. Once a user is created and has
274access to the server, they can manage their own keys and settings.
275
276To create a new user simply use `user create`:
277
278```sh
279# Create a new user
280ssh -p 23231 localhost user create beatrice
281
282# Add user keys
283ssh -p 23231 localhost user add-pubkey beatrice ssh-rsa AAAAB3Nz...
284ssh -p 23231 localhost user add-pubkey beatrice ssh-ed25519 AAAA...
285
286# Create another user with public key
287ssh -p 23231 localhost user create frankie '-k "ssh-ed25519 AAAATzN..."'
288
289# Need help?
290ssh -p 23231 localhost user help
291```
292
293Once a user has access, they get `read-only` access to public repositories.
294They can also create new repositories on the server.
295
296Non-admin users can manage their keys using the `pubkey` command:
297
298```sh
299# List user keys
300ssh -p 23231 localhost pubkey list
301
302# Add key
303ssh -p 23231 localhost pubkey add ssh-ed25519 AAAA...
304
305# Wanna change your username?
306ssh -p 23231 localhost set-username yolo
307
308# To display user info
309ssh -p 23231 localhost info
310```
311
312## Repositories
313
314You can manage repositories using the `repo` command.
315
316```sh
317# Run repo help
318$ ssh -p 23231 localhost repo help
319Manage repositories
320
321Usage:
322  ssh -p 23231 localhost repo [command]
323
324Aliases:
325  repo, repos, repository, repositories
326
327Available Commands:
328  blob         Print out the contents of file at path
329  branch       Manage repository branches
330  collab       Manage collaborators
331  create       Create a new repository
332  delete       Delete a repository
333  description  Set or get the description for a repository
334  hide         Hide or unhide a repository
335  import       Import a new repository from remote
336  info         Get information about a repository
337  is-mirror    Whether a repository is a mirror
338  list         List repositories
339  private      Set or get a repository private property
340  project-name Set or get the project name for a repository
341  rename       Rename an existing repository
342  tag          Manage repository tags
343  tree         Print repository tree at path
344
345Flags:
346  -h, --help   help for repo
347
348Use "ssh -p 23231 localhost repo [command] --help" for more information about a command.
349```
350
351### Creating Repositories
352
353To create a repository, first make sure you are an admin or a registered user.
354Use the `repo create <repo>` command to create a new repository:
355
356```sh
357# Create a new repository
358ssh -p 23231 localhost repo create icecream
359
360# Create a repo with description
361ssh -p 23231 localhost repo create icecream '-d "This is an Ice Cream description"'
362
363# ... and project name
364ssh -p 23231 localhost repo create icecream '-d "This is an Ice Cream description"' '-n "Ice Cream"'
365
366# I need my repository private!
367ssh -p 23231 localhost repo create icecream -p '-d "This is an Ice Cream description"' '-n "Ice Cream"'
368
369# Help?
370ssh -p 23231 localhost repo create -h
371```
372
373Or you can add your Soft Serve server as a remote to any existing repo, given
374you have write access, and push to remote:
375
376```
377git remote add origin ssh://localhost:23231/icecream
378```
379
380After you’ve added the remote just go ahead and push. If the repo doesn’t exist
381on the server it’ll be created.
382
383```
384git push origin main
385```
386
387Repositories can be nested too:
388
389```sh
390# Create a new nested repository
391ssh -p 23231 localhost repo create charmbracelet/icecream
392
393# Or ...
394git remote add charm ssh://localhost:23231/charmbracelet/icecream
395git push charm main
396```
397
398### Deleting Repositories
399
400You can delete repositories using the `repo delete <repo>` command.
401
402```sh
403ssh -p 23231 localhost repo delete icecream
404```
405
406### Renaming Repositories
407
408Use the `repo rename <old> <new>` command to rename existing repositories.
409
410```sh
411ssh -p 23231 localhost repo rename icecream vanilla
412```
413
414### Repository Collaborators
415
416Sometimes you want to restrict write access to certain repositories. This can
417be achieved by adding a collaborator to your repository.
418
419Use the `repo collab <command> <repo>` command to manage repo collaborators.
420
421```sh
422# Add collaborator to soft-serve
423ssh -p 23231 localhost repo collab add soft-serve frankie
424
425# Remove collaborator
426ssh -p 23231 localhost repo collab remove soft-serve beatrice
427
428# List collaborators
429ssh -p 23231 localhost repo collab list soft-serve
430```
431
432### Repository metadata
433
434You can also change the repo's description, project name, whether it's private,
435etc using the `repo <command>` command.
436
437```sh
438# Set description for repo
439ssh -p 23231 localhost repo description icecream "This is a new description"
440
441# Hide repo from listing
442ssh -p 23231 localhost repo hidden icecream true
443
444# List repository info (branches, tags, description, etc)
445ssh -p 23231 localhost repo icecream info
446```
447
448To make a repository private, use `repo private <repo> [true|false]`. Private
449repos can only be accessed by admins and collaborators.
450
451```sh
452ssh -p 23231 localhost repo icecream private true
453```
454
455### Repository Branches & Tags
456
457Use `repo branch` and `repo tag` to list, and delete branches or tags. You can
458also use `repo branch default` to set or get the repository default branch.
459
460### Repository Tree
461
462To print a file tree for the project, just use the `repo tree` command along with
463the repo name as the SSH command to your Soft Serve server:
464
465```sh
466ssh -p 23231 localhost repo tree soft-serve
467```
468
469You can also specify the sub-path and a specific reference or branch.
470
471```sh
472ssh -p 23231 localhost repo tree soft-serve server/config
473ssh -p 23231 localhost repo tree soft-serve main server/config
474```
475
476From there, you can print individual files using the `repo blob` command:
477
478```sh
479ssh -p 23231 localhost repo blob soft-serve cmd/soft/root.go
480```
481
482You can add the `-c` flag to enable syntax coloring and `-l` to print line
483numbers:
484
485```sh
486ssh -p 23231 localhost repo blob soft-serve cmd/soft/root.go -c -l
487
488```
489
490Use `--raw` to print raw file contents. This is useful for dumping binary data.
491
492## The Soft Serve TUI
493
494<img src="https://stuff.charm.sh/soft-serve/soft-serve-demo-commit.png" width="750" alt="TUI example showing a diff">
495
496Soft Serve serves a TUI over SSH for browsing repos, viewing files and commits,
497and grabbing clone commands:
498
499```sh
500ssh localhost -p 23231
501```
502
503It's also possible to ā€œlinkā€ to a specific repo:
504
505```sh
506ssh -p 23231 localhost -t soft-serve
507```
508
509You can copy text to your clipboard over SSH. For instance, you can press
510<kbd>c</kbd> on the highlighted repo in the menu to copy the clone command
511[^osc52].
512
513[^osc52]:
514    Copying over SSH depends on your terminal support of OSC52. Refer to
515    [go-osc52](https://github.com/aymanbagabas/go-osc52) for more information.
516
517## A note about RSA keys
518
519Unfortunately, due to a shortcoming in Go’s `x/crypto/ssh` package, Soft Serve
520does not currently support access via new SSH RSA keys: only the old SHA-1
521ones will work.
522
523Until we sort this out you’ll either need an SHA-1 RSA key or a key with
524another algorithm, e.g. Ed25519. Not sure what type of keys you have?
525You can check with the following:
526
527```sh
528$ find ~/.ssh/id_*.pub -exec ssh-keygen -l -f {} \;
529```
530
531If you’re curious about the inner workings of this problem have a look at:
532
533- https://github.com/golang/go/issues/37278
534- https://go-review.googlesource.com/c/crypto/+/220037
535- https://github.com/golang/crypto/pull/197
536
537## Feedback
538
539We’d love to hear your thoughts on this project. Feel free to drop us a note!
540
541- [Twitter](https://twitter.com/charmcli)
542- [The Fediverse](https://mastodon.social/@charmcli)
543- [Discord](https://charm.sh/chat)
544
545## License
546
547[MIT](https://github.com/charmbracelet/soft-serve/raw/main/LICENSE)
548
549---
550
551Part of [Charm](https://charm.sh).
552
553<a href="https://charm.sh/"><img alt="The Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
554
555Charmēƒ­ēˆ±å¼€ęŗ • Charm loves open source