title: Nginx HTTP authorization only for git push
body: <p>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.</p>
  
  <p>My Nginx configuration is as follows:</p>
  
  <pre><code>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;
  
    }
  </code></pre>
  
  <p>From my understanding, a <code>git push</code> request sends a <code>git-receive-pack</code> to my server. My simple solution was to capture this suffix with <code>$1</code> and use an if statement, but I found quickly that this is not the correct use for ifs (<a href="https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/" rel="noreferrer">ifisevil</a>).</p>
  
  <p>Is there a more appropriate solution to what I'm trying to accomplish?</p>