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