8

I host a private git server using Nginx. I'd like anyone to clone into my repos (without authorization) but require authorization if they try to push a commit.

My Nginx configuration is as follows:

server {
  listen 443 ssl;
  server_name git.example.com;
  ssl_certificate /fullchain.pem;
  ssl_certificate_key /privkey.pem;

  location ~ ^.*\.git/(HEAD|info/refs|objects/info/.*|git-(upload|recieve)-pack) {
    root /usr/share/nginx/git;

# --- incorrect solution ---

#    if ($1 = git-upload-pack) {
#        auth_basic "Restricted";
#        auth_basic_user_file /usr/share/nginx/htpasswd;
#    }
    client_max_body_size 0;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
    fastcgi_param GIT_HTTP_EXPORT_ALL "";
    fastcgi_param GIT_PROJECT_ROOT $realpath_root;
    fastcgi_param REMOTE_USER $remote_user;
    fastcgi_param PATH_INFO $uri;
    fastcgi_param unix:/var/fcgiwrap.socket;

  }

From my understanding, a git push request sends a git-receive-pack to my server. My simple solution was to capture this suffix with $1 and use an if statement, but I found quickly that this is not the correct use for ifs (ifisevil).

Is there a more appropriate solution to what I'm trying to accomplish?

2 Answers 2

5
+25

Try separating the locations:

server {
  listen 443 ssl;
  server_name git.example.com;
  ssl_certificate /fullchain.pem;
  ssl_certificate_key /privkey.pem;

  location ~ ^.*\.git/(HEAD|info/refs|objects/info/.*|git-recieve-pack) {
    # Do your stuff 

  location ~ ^.*\.git/git-upload-pack {
    auth_basic "Restricted";
    auth_basic_user_file /usr/share/nginx/htpasswd;
    # Do your stuff 
Sign up to request clarification or add additional context in comments.

7 Comments

Maybe I got the regex wrong. But this is the general idea. Feel free to fix it
I thought this would work, too, but, for some reason, it still asks me to type in username and password when I clone a remote repo. I am using jgit shell script instead of git, but this shouldn't change how I clone/push repos, right?
Look at the nginx access log, and look at the output for both git and jgit. There might be differences
Also, according to: git-scm.com/docs/git-http-backend It looks like it's the other way around and you should authenticate on ^.*\.git/git-recieve-pack
I think this is the desired behavior when using auth_basic without providing username and password. Maybe this is the way to provide them: stackoverflow.com/questions/6565357/… and maybe you just want application level authentication and authorization instead of auth_basic
|
3

You can auth/deny based on request_method.

        if ($request_method ~* "^(POST|PUT|DELETE)$" ) {
                # check if is there a cookie or something like that
                # and redirect to login if not
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.