Summary Files Commits Branches @commit @diff @stats
diff options
context:
space:
mode:
Commitf522fb4f17114d48e2de5b60a9b34dea350e77cb (patch)
Author
 Syndamia <kamen@syndamia.com>
2026-10-31 11:01:59 +0200
Committer
 Syndamia <kamen@syndamia.com>
2026-10-31 11:10:51 +0200
Files949be2ee14d89675cd8723c6da3a91e30f32d9a9
cli-f522fb4f17114d48e2de5b60a9b34dea350e77cb.tar
cli-f522fb4f17114d48e2de5b60a9b34dea350e77cb.tar.gz
cli-f522fb4f17114d48e2de5b60a9b34dea350e77cb.zip
feat!: Initial setup
12 files changed, 289 insertions, 0 deletions
-rw-r--r--README.md45
-rw-r--r--bins.list12
-rw-r--r--devs.list5
-rw-r--r--libs.list9
-rwxr-xr-xscripts/checkout18
-rwxr-xr-xscripts/desc25
-rwxr-xr-xscripts/h20
-rwxr-xr-xscripts/homepage37
-rwxr-xr-xscripts/logo37
-rwxr-xr-xscripts/new20
-rwxr-xr-xscripts/private28
-rwxr-xr-xscripts/public33
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..53b62ea
--- /dev/null
+++ b/README.md
@@ -0,0 +1,45 @@
+# git.syndamia.com CLI
+
+Command-line utilities for managing my git repositories (creating a new repo, making it public/private, ...).
+
+## Usage
+
+The way I use them is by ssh-ing into my server in a chroot jail, which contains these, and only these, tools.
+
+I'll be the only one directly using <https://git.syndamia.com>, so I've opted to *not* use a software forge or any other fine-grained access control program (e.g. [gitolite](https://gitolite.com/gitolite/index.html)).
+As you'll see from the `new` script, repositories are stored as bare and [git over ssh](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols.html#_the_ssh_protocol) is used for push/pull operations (thank you [tsoding](https://www.youtube.com/watch?v=iuIdBfjL62s)).
+
+## Setup
+
+Do note, I've only done this once for my server, manually.
+If ever do it again, I'll setup scripts for an automated configuration.
+
+### chroot jail
+
+The best tutorial for a n00b like me was <https://www.tecmint.com/restrict-ssh-user-to-directory-using-chrooted-jail/>.
+[Appendix B.7](https://web.archive.org/web/20260424212124/https://www.debian.org/doc/manuals/securing-debian-manual/chroot-ssh-env.en.html) from the severely outdated Securing Debian Manual also helped.
+
+Some extra sshd configuration options which should always be added are:
+
+```
+PermitTunnel no
+AllowAgentForwarding no
+AllowTcpForwarding no
+X11Forwarding no
+```
+
+Documentation can be found on the [sshd_config man page](https://www.man7.org/linux/man-pages/man5/sshd_config.5.html).
+
+### External dependencies
+
+The primary utilities in this repository are simple shell scripts, however for them to work, a shell and some UNIX programs need to be available.
+Since I'm jailing the ssh-ed user, every program, alongside its dynamically-linked libraries, needs to be copied over.
+
+All `.list` files contain newline-separated names of **external** files and directories, relative to the root directory, which need to be **copied** into the jail root.
+
+- `libs.list` - all needed dynamically-allocated libraries
+- `bins.list` - all needed precompiled binaries.
+- `devs.list` - all needed devices (they are all pseudo-devices, not related to actual hardware)
+
+You also **must create `/tmp` directory**!
+Otherwise, git commands will not work properly.
diff --git a/bins.list b/bins.list
new file mode 100644
index 0000000..673b33d
--- /dev/null
+++ b/bins.list
@@ -0,0 +1,12 @@
+/bin/bash
+/bin/cat
+/bin/ed
+/bin/git
+/bin/git-receive-pack
+/bin/git-shell
+/bin/git-upload-archive
+/bin/git-upload-pack
+/bin/ln
+/bin/ls
+/bin/mkdir
+/bin/mv
diff --git a/devs.list b/devs.list
new file mode 100644
index 0000000..70abbaf
--- /dev/null
+++ b/devs.list
@@ -0,0 +1,5 @@
+/dev/null
+/dev/random
+/dev/tty
+/dev/urandom
+/dev/zero
diff --git a/libs.list b/libs.list
new file mode 100644
index 0000000..01d1a3b
--- /dev/null
+++ b/libs.list
@@ -0,0 +1,9 @@
+/lib64/ld-linux-x86-64.so.2
+/lib/x86_64-linux-gnu/libacl.so.1
+/lib/x86_64-linux-gnu/libattr.so.1
+/lib/x86_64-linux-gnu/libcap.so.2
+/lib/x86_64-linux-gnu/libc.so.6
+/lib/x86_64-linux-gnu/libpcre2-8.so.0
+/lib/x86_64-linux-gnu/libselinux.so.1
+/lib/x86_64-linux-gnu/libtinfo.so.6
+/lib/x86_64-linux-gnu/libz.so.1
diff --git a/scripts/checkout b/scripts/checkout
new file mode 100755
index 0000000..26a36b0
--- /dev/null
+++ b/scripts/checkout
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository: '
+ read
+ set "$REPLY"
+fi
+
+if [ -z "$2" ]
+then
+ printf 'Branch : '
+ read
+ set "$1" "$REPLY"
+fi
+
+cd "$1" && \
+git symbolic-ref HEAD refs/heads/"$2"
diff --git a/scripts/desc b/scripts/desc
new file mode 100755
index 0000000..ee7c13b
--- /dev/null
+++ b/scripts/desc
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository : '
+ read
+ set "$REPLY"
+fi
+
+if [ ! -f "$1/HEAD" ]
+then
+ echo 'Not a repository!'
+ exit 1
+fi
+
+if [ -z "$2" ]
+then
+ printf 'Description: '
+ read
+ set "$1" "$REPLY"
+fi
+
+# Beware of https://stackoverflow.com/questions/53465980/how-to-keep-parameter-with-spaces-when-running-remote-script-file-with-ssh
+cd "$1" && \
+git config set --file ./config gitweb.description "$2"
diff --git a/scripts/h b/scripts/h
new file mode 100755
index 0000000..5bdf467
--- /dev/null
+++ b/scripts/h
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+cat <<HELP
+h Print this message
+list Show all repositories (short format)
+list -l Show all repositories (long format)
+
+new <DIR/REPO> Create a repository
+public <DIR/REPO> Make repository publicly accessible
+private <DIR/REPO> Make repository publicly inaccessible
+
+checkout <DIR/REPO> <BRANCH> Set remote's active (default) branch
+desc <DIR/REPO> <DESCRIPTION> Set repository description
+logo <DIR/REPO> <URL> Set repository logo URL
+
+
+Standard tools: cat ed git ln ls mkdir mv new
+Delete : To remove a repository, move it to /trash
+Reorder : To change order of repositories, edit /public_repos
+HELP
diff --git a/scripts/homepage b/scripts/homepage
new file mode 100755
index 0000000..c72c91a
--- /dev/null
+++ b/scripts/homepage
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository : '
+ read
+ set "$REPLY"
+fi
+
+if [ ! -f "$1/HEAD" ]
+then
+ echo 'Not a repository!'
+ exit 1
+fi
+
+if [ ! -w "$1/HEAD" ]
+then
+ echo 'Read-only repository!'
+ exit 2
+fi
+
+if [ -z "$2" ]
+then
+ printf 'Homepage URL: '
+ read
+ set "$1" "$REPLY"
+fi
+
+if cd "$1"
+then
+ if [ "$2" = 'initial' ]
+ then
+ git config unset --file ./config gitweb.homepage
+ else
+ git config set --file ./config gitweb.homepage "$2"
+ fi
+fi
diff --git a/scripts/logo b/scripts/logo
new file mode 100755
index 0000000..d380e00
--- /dev/null
+++ b/scripts/logo
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository: '
+ read
+ set "$REPLY"
+fi
+
+if [ ! -f "$1/HEAD" ]
+then
+ echo 'Not a repository!'
+ exit 1
+fi
+
+if [ ! -w "$1/HEAD" ]
+then
+ echo 'Read-only repository!'
+ exit 2
+fi
+
+if [ -z "$2" ]
+then
+ printf 'Logo URL : '
+ read
+ set "$1" "$REPLY"
+fi
+
+if cd "$1"
+then
+ if [ "$2" = 'initial' ]
+ then
+ git config unset --file ./config cgit.logo
+ else
+ git config set --file ./config cgit.logo "$2"
+ fi
+fi
diff --git a/scripts/new b/scripts/new
new file mode 100755
index 0000000..65e677a
--- /dev/null
+++ b/scripts/new
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+while [ -z "$1" ]
+do
+ printf 'Repository: '
+ read
+ set "$REPLY"
+done
+
+set "${1##/}"
+
+root_dir="${1%%/*}"
+repo_dir="${1#*/}"
+
+cd "$root_dir"
+if git init --bare "$repo_dir"
+then
+ echo -e "\nClone repo with:\n\tgit clone git@syndamia.com:$1"
+ echo -e "\nUpload local repo with:\n\tgit push git@syndamia.com:$1 '*:*'"
+fi
diff --git a/scripts/private b/scripts/private
new file mode 100755
index 0000000..7035c19
--- /dev/null
+++ b/scripts/private
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository: '
+ read
+ set "$REPLY"
+fi
+
+if [ ! -f "$1/HEAD" ]
+then
+ echo 'Repository has been deleted or moved!'
+fi
+
+set "${1##/}"
+
+if echo -e "?^$1\$?" | ed -s /public_repos >/dev/null 2>&1
+then
+ echo -e "g|^$1$|d\nw" | ed -s /public_repos
+ echo "'$1' is now private!"
+elif [ -f "$1/HEAD" ]
+then
+ echo "Already private!"
+else
+ clue="$(echo -e "?$1?" | ed -s /public_repos 2>/dev/null)"
+ [ "$clue" != '?' ] && echo "Perhaps you wanted: $clue"
+ exit 1
+fi
diff --git a/scripts/public b/scripts/public
new file mode 100755
index 0000000..155a81e
--- /dev/null
+++ b/scripts/public
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+if [ -z "$1" ]
+then
+ printf 'Repository: '
+ read
+ set "$REPLY"
+fi
+
+if [ ! -f "$1/HEAD" ]
+then
+ echo 'Not a repository!'
+ exit 1
+fi
+
+set "${1##/}"
+
+# If repo is in file
+if echo -e "?^$1\$?" | ed -s /public_repos >/dev/null 2>&1
+then
+ echo "Already public!"
+# If repo root dir is in file
+elif echo -e "?^${1%%/*}?" | ed -s /public_repos >/dev/null 2>&1
+then
+ echo -e "?^${1%%/*}?a\n$1\n.\nw" | ed -s /public_repos
+ echo "'$1' is now public!"
+# Repo and repo root dir are not anywhere in file
+else
+ echo -e "\$a\n$1\n.\nw" | ed -s /public_repos
+ echo "'$1' is now public!"
+fi
+
+echo "https://git.syndamia.com/$1"