#!/usr/bin/env fish # load environment source (status dirname)/env # # # function definitions # # function fail set_color red echo "$argv" set_color normal return 1 end function checkUser set -l user $argv[1] grep -q -E "^$user:" < /etc/passwd return $status end function setupUser set -l userConfig (string split ':' $argv[1]) set -l user $userConfig[1] set -l key $userConfig[2] set -l HOME "/home/$user" echo "Setting up user: $user" if [ "$user" = git ] echo "Error: User git is reserved" return 1 end # setup user exist if necessary if not checkUser "$user" # user is not restricted, this is done in ssh config with forceCommand # we need to be able to run a fish script to check for permissions adduser --home $HOME -D "$user"; or fail "Failed to create user $user" # add user to sudo group addgroup "$user" $_GIT_SUDO_GROUP; or fail "Failed to add user $user to group $_GIT_SUDO_GROUP" # unlock account to allow ssh logins passwd -u "$user" &>/dev/null; or fail "Failed to unlock account of $user" # create ssh folder mkdir "$HOME/.ssh" end # Copy/Overwrite ssh key echo "$key" > "$HOME/.ssh/authorized_keys" chown -R $user "$HOME" chmod -R 700 "$HOME" end function setupGitUser checkUser "git"; and return 0 echo "Setting up git user" # git user has read/write access to all repos, set git-shell # and no password login allowed -> no ssh login possible addgroup -g $GIT_GID git; or fail "Failed to create git user group" adduser git -u $GIT_UID -G git -D --shell "/usr/bin/git-shell"; or fail "Failed to setup git user" # group that is allowed to sudo addgroup $_GIT_SUDO_GROUP; or fail "Failed to setup git sudo group" end function setupRepo set -l repoConfig $argv[1] set -l parsedConfig (string split ';' -- $repoConfig) set -l repo $parsedConfig[1] # check repo name set -l matcher (string match -r -g "^$_REPO_VALIDATION_REGEX\$" -- $repo) if test -z $matcher[1] fail "Failed to setup repo, invalid config: $repoConfig" return 1 end # we assume all repos to be in /srv/repos set -l repoDir srv repos set repoDir /(string join -n '/' $repoDir (string split '/' $repo)) echo "Setting up repo: $repo" # write user as allowed into permission file for userConfig in $parsedConfig[2..] set -l parsedConfig (string split ':' -- $userConfig) set -l user $parsedConfig[1] set -l permission $parsedConfig[2] # check for valid permission if not contains $permission $_PERMISSIONS set permission "r" end echo "$repoDir:$user:$permission" >> $_REPO_PERMISSIONS_FILE end # setup repo dir if not test -d $repoDir mkdir -p $repoDir git init --bare $repoDir -b trunk end chown -R git:git "$repoDir" chmod -R 700 "$repoDir" end function setupSSH echo "Setting up server" # generate host keys in case mkdir -p /var/ssh/etc/ssh/ && ssh-keygen -A -f /var/ssh end # # # main # # argparse 'g/git-uid=?' 'u/user=+' 'r/repo=+' 'h/help' 'v/version' -- $argv or exit 1; if set -q _flag_h echo "Usage: $(status filename) [ OPTIONS ]..." echo -e "" echo -e "OPTIONS" echo -e "\t -h, --help \t\t Display this page" echo -e "\t -g, --git-uid \t\t UID of the git user that is used also as ownership for all repos" echo -e "\t -u, --user \t\t User setting in form of :" echo -e "\t -r, --repo \t\t Repo setting in form of ;:[;:;...]. You can add as many users as you want. If you do not specify a user for a repo, that user does not have access to it. If you specify a user without permission, the default fallback is read only." echo -e "\t -v, --version \t\t Version" echo -e "" return end if set -q _flag_v echo -e "$_VERSION" return end function showBanner echo echo $_BANNER echo echo Copyright Matthias Jaros 2025 echo This software is licensed under GPLv3. See /usr/share/doc/gitfish/LICENSE echo end showBanner # read variables set -l users $_flag_u for user in (set -n | string match -r "^USER_\S+") set users $users $$user end set -l repos $_flag_r for repo in (set -n | string match -r "^REPO_\S+") set repos $repos $$repo end if set -q $_flag_g set GIT_UID $_flag_g end # Setup git user setupGitUser; or return $status # Setup users for userConfig in $users setupUser "$userConfig" end # Setup repos echo > $_REPO_PERMISSIONS_FILE for repoConfig in $repos setupRepo "$repoConfig" end # create writable log file for run script touch $_LOG && chmod 777 $_LOG setupSSH; or return $status # run ssh daemon exec /usr/sbin/sshd -D -e