gitreef

A GIT over SSH server implemented using fish.
Log | Files | Refs | README | LICENSE

init (4716B)


      1 #!/usr/bin/env fish
      2 
      3 # load common environment
      4 source (status dirname)/env
      5 
      6 ###
      7 ###
      8 ### functions
      9 ###
     10 ###
     11 
     12 function fail
     13     set_color red
     14     echo "$argv"
     15     set_color normal
     16     return 1
     17 end
     18 
     19 function checkUser
     20 	set -l user $argv[1]
     21 	grep -q -E "^$user:" < /etc/passwd
     22 	return $status
     23 end
     24 
     25 function setupUser
     26 	set -l userConfig (string split ':' $argv[1])
     27 	set -l user $userConfig[1]
     28 	set -l key $userConfig[2]
     29 	set -l HOME "/home/$user"
     30 
     31 	echo "Setting up user: $user"
     32 	if [ "$user" = git ]
     33 		echo "Error: User git is reserved"
     34 		return 1
     35 	end
     36 	
     37 	# setup user exist if necessary
     38 	if not checkUser "$user"
     39 		# user is not restricted, this is done in ssh config with forceCommand
     40 		# we need to be able to run a fish script to check for permissions
     41 		adduser --home $HOME -D "$user"; or fail "Failed to create user $user"
     42 		# add user to sudo group
     43 		addgroup "$user" $_GIT_SUDO_GROUP; or fail "Failed to add user $user to group $_GIT_SUDO_GROUP"
     44 		# unlock account to allow ssh logins
     45 		passwd -u "$user" &>/dev/null; or fail "Failed to unlock account of $user"
     46 		# create ssh folder
     47 		mkdir "$HOME/.ssh"
     48 	end	
     49 
     50 	# Copy/Overwrite ssh key
     51 	echo "$key" > "$HOME/.ssh/authorized_keys"
     52 	chown -R $user "$HOME"
     53 	chmod -R 700 "$HOME"
     54 end
     55 
     56 function setupGitUser
     57 	checkUser "git"; and return 0
     58 	echo "Setting up git user"
     59 	# git user has read/write access to all repos, set git-shell
     60 	# and no password login allowed -> no ssh login possible
     61 	addgroup -g $GIT_GID git; or fail "Failed to create git user group"
     62 	adduser git -u $GIT_UID -G git -D --shell "/usr/bin/git-shell"; or fail "Failed to setup git user"
     63 	# group that is allowed to sudo
     64 	addgroup $_GIT_SUDO_GROUP; or fail "Failed to setup git sudo group"
     65 end
     66 
     67 function setupRepo
     68 	set -l repoConfig $argv[1]
     69 	set -l parsedConfig (string split ';' -- $repoConfig)
     70 	set -l repo $parsedConfig[1]
     71 
     72 	# check repo name
     73 	set -l matcher (string match -r -g "^$_REPO_VALIDATION_REGEX\$" -- $repo)
     74 	if test -z $matcher[1]
     75 		fail "Failed to setup repo, invalid config: $repoConfig"
     76 		return 1
     77 	end
     78 
     79 	# we assume all repos to be in /srv/repos
     80 	set -l repoDir srv repos
     81 	set repoDir /(string join -n '/' $repoDir (string split '/' $repo))
     82 	echo "Setting up repo: $repo"
     83 
     84 	# write user as allowed into permission file
     85 	for userConfig in $parsedConfig[2..]
     86 		set -l parsedConfig (string split ':' -- $userConfig)
     87 		set -l user $parsedConfig[1]
     88 		set -l permission $parsedConfig[2]
     89 		
     90 		# check for valid permission
     91 		if not contains $permission $_PERMISSIONS
     92 			set permission "r"
     93 		end
     94 		echo "$repoDir:$user:$permission" >> $_REPO_PERMISSIONS_FILE
     95 	end
     96 
     97 	# setup repo dir
     98 	if not test -d $repoDir
     99 		mkdir -p $repoDir
    100 		git init --bare $repoDir -b trunk
    101 	end
    102 	chown -R git:git "$repoDir"
    103 	chmod -R 700 "$repoDir"
    104 end
    105 
    106 function setupSSH
    107 	echo "Setting up server"
    108 	
    109 	# generate host keys in case
    110 	mkdir -p /var/ssh/etc/ssh/ && ssh-keygen -A -f /var/ssh
    111 end
    112 
    113 function setupRepoPermissionACL
    114 	echo -n > $_REPO_PERMISSIONS_FILE
    115 	chown root:$_GIT_SUDO_GROUP $_REPO_PERMISSIONS_FILE
    116 	chmod 740 $_REPO_PERMISSIONS_FILE
    117 end
    118 
    119 ###
    120 ###
    121 ### main
    122 ###
    123 ###
    124 
    125 argparse 'g/git-uid=?' 'u/user=+' 'r/repo=+' 'h/help' 'v/version' -- $argv
    126 or exit 1;
    127 
    128 if set -q _flag_h
    129 	echo "Usage: $(status filename) [ OPTIONS ]..."
    130 	echo -e ""
    131 	echo -e "OPTIONS"
    132 	echo -e "\t -h, --help \t\t Display this page"
    133 	echo -e "\t -g, --git-uid \t\t UID of the git user that is used also as ownership for all repos"
    134 	echo -e "\t -u, --user \t\t User setting in form of <user-name>:<public-key>"
    135 	echo -e "\t -r, --repo \t\t Repo setting in form of <repo-path>;<user>:<perm>[;<user2>:<perm>;...]. 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."
    136 	echo -e "\t -v, --version \t\t Version"
    137 	echo -e ""
    138 	return
    139 end
    140 
    141 if set -q _flag_v
    142 	echo -e "$_VERSION"
    143 	return
    144 end
    145 
    146 function showBanner
    147 	echo
    148 	echo $_BANNER
    149 	echo
    150 	echo Copyright Matthias Jaros 2026
    151 	echo This software is licensed under GPLv3. See /usr/share/doc/gitreef/LICENSE
    152 	echo
    153 end
    154 
    155 showBanner
    156 
    157 # read variables
    158 set -l users $_flag_u
    159 for user in (set -n | string match -r "^USER_\S+")
    160 	set users $users $$user
    161 end
    162 
    163 set -l repos $_flag_r
    164 for repo in (set -n | string match -r "^REPO_\S+")
    165 	set repos $repos $$repo
    166 end
    167 
    168 if set -q $_flag_g
    169 	set GIT_UID $_flag_g
    170 end
    171 
    172 # Setup git user
    173 setupGitUser; or return $status
    174 # Setup users
    175 for userConfig in $users
    176 	setupUser "$userConfig"
    177 end
    178 
    179 # Setup repos
    180 setupRepoPermissionACL
    181 for repoConfig in $repos
    182 	setupRepo "$repoConfig"
    183 end
    184 
    185 # create writable log file for run script
    186 touch $_LOG && chmod 777 $_LOG
    187 
    188 setupSSH; or return $status
    189 
    190 # run ssh daemon
    191 exec /usr/sbin/sshd -D -e