Files

158 lines
5.9 KiB
Bash
Raw Permalink Normal View History

2025-10-19 11:55:24 +03:00
#!/bin/sh
# GHMD is a shell script for setting up any of the following things:
# 1) a Git user on a remote instance (initial setup)
# 2) a private Git repo on the remote instance
# 3) a public Git repo using git:// protocol on the remote instance (if it uses systemd)
# 4) Git daemon (serving git:// protocol) on the remote instance
# 5) access via the Git daemon to individual repositories
# 6) repository description and clone URL for some services like stagit
# Usage: ghmd.sh [newsrv | newrepo | gitd-sd | gitd-publish | gitd-unpublish | set-repo-desc | set-repo-url | set-repo-owner] user@host [name] ("[desc|url]")
# regardless of the actions, the user must have root permissions
# prerequisite: git package must be already installed on the server
# Created by Luxferre in 2024, released into public domain
GITUSR="git"
PARAM="$1"
USERHOST="$2"
THOST="${USERHOST##*@}"
SSHCMD="ssh $USERHOST" # instance ssh cmd
help() {
cat <<EOF
GHMD: single shell script for self-hosted Git repository management
Initialize Git user on a new server (must have Git installed):
$0 newsrv root@hostname
Create a new Git repository (e.g. git@hostname:myrepo.git):
$0 newrepo root@hostname myrepo
Set up Git protocol daemon (if the host is running systemd):
$0 gitd-sd root@hostname
Publish an existing Git repository on the daemon (e.g. git://hostname/myrepo.git):
$0 gitd-publish root@hostname myrepo
Unpublish an existing Git repository on the daemon:
$0 gitd-unpublish root@hostname myrepo
Set the (displayed) description of an existing Git repository:
$0 set-repo-desc root@hostname myrepo "This is a cool repo"
Set the (displayed) clone URL of an existing Git repository:
$0 set-repo-url root@hostname myrepo git://hostname/myrepo.git
Set the (displayed) owner name of an existing Git repository:
$0 set-repo-owner root@hostname myrepo "Me, the Author"
Created by Luxferre in 2024, released into public domain
EOF
}
case "$PARAM" in
"help")
help
;;
"newsrv") # set up Git user on the server
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
$SSHCMD "useradd ${GITUSR}; passwd ${GITUSR}; mkdir -p /home/${GITUSR}/.ssh; echo 'no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty' > /home/${GITUSR}/.ssh/authorized_keys; chown -R ${GITUSR} /home/${GITUSR}/.ssh"
echo "Now, you'll need to enter the newly created ${GITUSR} user password:"
ssh-copy-id ${GITUSR}@${THOST}
$SSHCMD "chsh $GITUSR -s $(which git-shell)"
echo "Git user set up on ${THOST}. Now use $0 newrepo ${GITUSR}@${THOST} [name] to set up new Git repos"
;;
"newrepo") # set up a new Git repo
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
REPODIR="${REPONAME}.git"
FULLREPODIR="/home/${GITUSR}/$REPODIR"
$SSHCMD "mkdir -p $FULLREPODIR;cd $FULLREPODIR;git init --bare --shared;chown -R ${GITUSR}:${GITUSR} ."
echo "Empty repository created at ${USERHOST}:${REPODIR}"
;;
"set-repo-desc") # set the repo description for some services
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
VALUE="$4" # it may be empty
REPODIR="${REPONAME}.git"
FULLREPODIR="/home/${GITUSR}/$REPODIR"
$SSHCMD "cd $FULLREPODIR;echo \"$VALUE\" > description;chown -R ${GITUSR}:${GITUSR} description"
echo "Description set for ${REPODIR}"
;;
"set-repo-url") # set the repo clone URL for some services
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
VALUE="$4" # it may be empty
REPODIR="${REPONAME}.git"
FULLREPODIR="/home/${GITUSR}/$REPODIR"
$SSHCMD "cd $FULLREPODIR;echo \"$VALUE\" > url;chown -R ${GITUSR}:${GITUSR} url"
echo "Clone URL set for ${REPODIR}"
;;
"set-repo-owner") # set the repo owner name for some services
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
VALUE="$4" # it may be empty
REPODIR="${REPONAME}.git"
FULLREPODIR="/home/${GITUSR}/$REPODIR"
$SSHCMD "cd $FULLREPODIR;echo \"$VALUE\" > owner;chown -R ${GITUSR}:${GITUSR} owner"
echo "Owner name set for ${REPODIR}"
;;
"gitd-sd") # set up the Git daemon using a systemd unit
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
TMPUNIT="/tmp/git-daemon.service"
cat << EOF > $TMPUNIT
[Unit]
Description=Start Git Daemon
[Service]
ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/home/${GITUSR} /home/${GITUSR}
Restart=always
RestartSec=500ms
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=git-daemon
User=$GITUSR
Group=$GITUSR
[Install]
WantedBy=multi-user.target
EOF
scp $TMPUNIT ${USERHOST}:/etc/systemd/system/git-daemon.service
$SSHCMD "systemctl enable git-daemon; systemctl start git-daemon"
echo "Git daemon installed on ${THOST} via systemd"
rm -f $TMPUNIT
;;
"gitd-publish") # make a repository public via the Git daemon
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
REPODIR="${REPONAME}.git"
ACCFILE="/home/${GITUSR}/${REPODIR}/git-daemon-export-ok"
$SSHCMD "touch $ACCFILE; chown $GITUSR $ACCFILE"
echo "Repository git://${THOST}/$REPODIR made public"
;;
"gitd-unpublish") # revoke repository publishing via the Git daemon
[[ -z "$USERHOST" ]] && echo "Error: no user and hostname!" && exit 1
REPONAME="$3"
[[ -z "$REPONAME" ]] && echo "Error: no repository name!" && exit 1
REPODIR="${REPONAME}.git"
ACCFILE="/home/${GITUSR}/${REPODIR}/git-daemon-export-ok"
$SSHCMD "rm -f $ACCFILE"
echo "Repository git://${THOST}/$REPODIR made private"
;;
*)
help
esac