Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/build-and-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Build and Push Docker Image

on:
push:
tags:
- 'v*.*.*'

env:
IMAGE_NAME: xrubioj/qnap-git-server

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Extract version from tag
id: extract_version
run: |
echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_PAT }}

- name: Build and push multi-platform image
uses: docker/build-push-action@v5
with:
context: .
push: true
platforms: linux/amd64,linux/386,linux/arm/v7,linux/arm64
tags: |
${{ env.IMAGE_NAME }}:${{ steps.extract_version.outputs.TAG_NAME }}
${{ env.IMAGE_NAME }}:latest
23 changes: 9 additions & 14 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
FROM arm32v7/ubuntu:14.04
FROM alpine:3.21.3

RUN apt-get update \
&& apt-get install -y openssh-server bash git vim lighttpd libcgi-pm-perl busybox-syslogd \
&& rm -rf /var/lib/apt/lists/* \
&& rm /etc/update-motd.d/* \
&& addgroup --gid 1000 git \
&& adduser --home /home/git --shell /bin/bash --uid 1000 --gid 1000 --gecos "" --disabled-password git \
&& mkdir /var/run/sshd \
&& /usr/bin/ssh-keygen -A \
&& rm /etc/pam.d/sshd
RUN apk add --no-cache openssh-server git \
&& addgroup -g 1000 git \
&& adduser -h /home/git -s /bin/sh -u 1000 -G git -g "" -D git \
&& passwd -d git \
&& ln -s /home/git/pub /pub \
&& /usr/bin/ssh-keygen -A

ADD start.sh /start.sh
EXPOSE 22

EXPOSE 22 1234

CMD ["/start.sh"]
CMD ["/usr/sbin/sshd", "-D"]
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
MIT License

Copyright (c) 2018 Tomasz Prus
Copyright (c) 2025 Xavier Rubio Jansana

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
58 changes: 37 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@ Host your own Git repositories on QNAP server

## Introduction

QNAP is a linux-based Network Attached Storage. It has a lot of nice features but there is no option for hosting git repositories by default. Fortunately there is an application named _Container Station_ which allows you to run Docker or LXC images. So it’s pretty easy to extend functions and for example install _GitLab_ to host git repositories (it’s QNAP recommendation). _Gitlab_ is a quite big system and if you need a just simple git server you can use this [qnap-git-server](https://github.com/tomplus/qnap-git-server).
QNAP is a linux-based Network Attached Storage. It has a lot of nice features but there is no option for hosting git repositories by default. Fortunately there is an application named _Container Station_ which allows you to run Docker or LXC images. So it’s pretty easy to extend functions and for example install _GitLab_ to host git repositories (it’s QNAP recommendation). _Gitlab_ is a quite big system and if you need a just simple git server you can use this [xrubioj/qnap-git-server](https://github.com/xrubioj/qnap-git-server).

This project is based on [tomplus/qnap-git-server](https://github.com/tomplus/qnap-git-server), but it has been rewritten from the scratch to use a more lightweight alternative (Alpine Linux). Also, it builds images for Intel/AMD and ARM CPUs.

## Instalation

First, you have to prepare a directory which will be attached to Docker. This directory has to contain your ssh public key and it is also a place where your repositories will be stored.

You can use the following script:

```
$ ./init.sh <user>@<qnap-address> <ssh-public-key-path>
# e.g.
$ ./init.sh admin@my-qnap.local ~/.ssh/id_rsa.pub
```

Alternatively, you can run the steps manually by `ssh`ing to your QNAP box as `admin` and manually running the commands like so:

```
$ ssh admin@my-qnap.local
[~] cd /share
Expand All @@ -22,29 +34,46 @@ $ ssh admin@my-qnap.local
[/share] chmod 600 git/.ssh/authorized_keys
```

Now you can use _Container Station_ to start the image [tpimages/qnap-git-server](https://hub.docker.com/r/tpimages/qnap-git-server/). This image is prepared for arm32v7 only.
Now you can use _Container Station_ to start the image [xrubioj/qnap-git-server](https://hub.docker.com/r/xrubioj/qnap-git-server/). This image is prepared for linux/amd64, linux/386, linux/arm/v7 (32 bits) and linux/arm64.
You have to mount prepared directory as /home/git and expose port 22 as for example 2222 to connect it from your local network. You can also start it from command line:

```
[~] docker run -d -v /share/git:/home/git -p 2222:22 --rm tpimages/qnap-git-server:latest
```

## Accessing git repositories from your home directory

You can link your `pub` directory to be visible from your QNAP user's home directory. In my case:

```
$ ssh -p 2222 git@my-qnap.local

# Confirm where /share/homes point to
[~] ls -l /share/homes
lrwxrwxrwx 1 admin administrators 23 2024-08-16 09:25 /share/homes -> CE_CACHEDEV1_DATA/homes/

# Link /share/git to git directory in your user network share (based on the result of the previous ls command)
[~] ln -s /share/git/ /share/CE_CACHEDEV1_DATA/homes/my_user/git
```

## Creating your first repository

Now your server is up and running. You can connect to it via SSH to create a bare repository:

```
$ ssh -p 2222 git@my-qnap.local
$ mkdir pub/project.git
$ cd pub/project.git/
$ git init --bare
[~] mkdir pub/project.git
[~] cd pub/project.git/
[~] git init --bare
Initialized empty Git repository in /home/git/pub/project.git/
```

and then you can clone the repository
and then you can clone the repository:

```
$ git clone ssh://git@my-qnap.local:2222/pub/project.git
$ git clone ssh://git@my-qnap.local:2222/home/git/pub/project.git
```


## Building

If you want to build you own custom version of this image your can do it simple by docker build command:
Expand All @@ -53,23 +82,10 @@ If you want to build you own custom version of this image your can do it simple
docker build -t qnap-git-server:my-own-version .
```


## Troubleshooting

Structure of file `git/.ssh/authorized_keys` requires that each key is stored in separate lines.
If you store there only one key, ensure that there are not additional new lines `\n`.

To check logs from syslogd you can use command `docker exec` to run `syslogd`. It'll start the deamon
syslogd and all logs will be writting to /var/log/messages.

If you get errors like `exec user process caused "exec format error"` it means that your qnap
has different architecture (eg. amd64) than the prepared image (arm32v7). It this case try to replace
the base image in `Dockerfile` from
```
FROM arm32v7/ubuntu:14.04
```
to for example:
```
FROM amd64/ubuntu:14.04
```
and build your own image.
24 changes: 24 additions & 0 deletions init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

if [ "$#" -ne 2 ]; then
echo "Initializes the required environment in your QNAP NAS."
echo "Requires admin access."
echo
echo "Usage: $0 <user>@<qnap-address> <ssh-public-key-path>"
echo " e.g.: $0 admin@my-qnap.local ~/.ssh/id_rsa.pub"
exit 1
fi

public_key=$(cat "$2")

embedded_script="cd /share &&
mkdir -p git/.ssh &&
mkdir -p git/pub &&
echo \"$public_key\" > git/.ssh/authorized_keys &&
chown 1000:1000 -R git/ &&
chmod 700 git/ &&
chmod 700 git/.ssh/ &&
chmod 600 git/.ssh/authorized_keys"

output=$(ssh "$1" -v -t "/bin/sh" "-c" "'$embedded_script'" 2>&1)
echo $output
31 changes: 0 additions & 31 deletions start.sh

This file was deleted.