# Nginx + Cgit +Dav

## erg_samowzbudnik

Hi.

I run cgit in a subdomain with Nginx. Pulling from repos works, what I can't get to work is pushing through https. 

I would like to enable pushing to repo only for some repositories, here for repository located in /subfolder

Nginx is compiled with dav and dav_ext modules.

Any pointers would be great.

```
git push

XML error: undefined entity

error: no DAV locking support on https://user:password@git.mydomain.com/subfolder

fatal: git-http-push failed

error: failed to push some refs to 'https://git.mydomain.com/subfolder'

```

nginx use flags:

```

Installed versions:  1.21.3(mainline)^t{tbz2}(20:21:34 26/10/21)(aio http http-cache http2 ipv6 pcre rtmp ssl threads vim-syntax -debug -libatomic -pcre-jit -selinux LUA_SINGLE_TARGET="luajit" NGINX_MODULES_HTTP="access addition auth_basic auth_request autoindex browser cache_purge charset dav dav_ext empty_gif fastcgi geo grpc gunzip gzip headers_more limit_conn limit_req map memc memcached mirror mp4 proxy push_stream referer rewrite scgi secure_link security slice slowfs_cache split_clients ssi upstream_check upstream_hash upstream_ip_hash upstream_keepalive upstream_least_conn upstream_zone userid uwsgi vhost_traffic_status xslt -auth_ldap -auth_pam -brotli -degradation -echo -fancyindex -flv -geoip -geoip2 -gzip_static -image_filter -javascript -lua -metrics -mogilefs -naxsi -perl -random_index -realip -spdy -sticky -stub_status -sub -upload_progress" NGINX_MODULES_MAIL="-imap -pop3 -smtp" NGINX_MODULES_STREAM="limit_conn upstream_hash upstream_least_conn upstream_zone -access -geo -geoip -geoip2 -javascript -map -realip -return -split_clients -ssl_preread" USERLAND="GNU")

```

nginx.conf:

```

user nginx nginx;

worker_processes 1;

error_log /var/log/nginx/error_log info;

events {

        worker_connections 1024;

        use epoll;

}

http {

    dav_ext_lock_zone zone=foo:10m;

    include /etc/nginx/mime.types;

    default_type application/octet-stream;

    log_format main

            '$remote_addr - $remote_user [$time_local] '

            '"$request" $status $bytes_sent '

            '"$http_referer" "$http_user_agent" '

            '"$gzip_ratio"';

    client_header_timeout 10m;

    client_body_timeout 10m;

     send_timeout 10m;

    client_max_body_size 5M;

    proxy_connect_timeout   10;

    proxy_send_timeout      15;

    proxy_read_timeout      20;

    connection_pool_size 256;

    client_header_buffer_size 1k;

    large_client_header_buffers 4 2k;

    request_pool_size 4k;

    ssl_prefer_server_ciphers on;

    ssl_protocols TLSv1.2 TLSv1.3;

    ssl_session_cache shared:SSL:50m;

    ssl_session_timeout 1d;

    ssl_session_tickets off;

    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    ssl_stapling on;

    ssl_stapling_verify on;

    ssl_trusted_certificate /etc/letsencrypt/live/my_domain/chain.pem;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    add_header X-Content-Type-Options nosniff;

    add_header X-Frame-Options "DENY";

    add_header X-XSS-Protection "1; mode=block";

    add_header X-Robots-Tag none;

    add_header X-Permitted-Cross-Domain-Policies none;

    add_header X-Download-Options noopen;

    gzip off;

    output_buffers 1 32k;

    postpone_output 1460;

    sendfile on;

    tcp_nopush on;

    tcp_nodelay on;

    keepalive_timeout 75 20;

    ignore_invalid_headers on;

    include /etc/nginx/conf.d/*.conf;

}

```

dav.conf:

```

server {

    listen 443 ssl http2;

    server_name my_domain.com'

    ssl_certificate /etc/letsencrypt/live/git.my_domain.com/fullchain.pem;

    my_domain.com

    ssl_certificate_key /etc/letsencrypt/live/git.-my_domain.com/privkey.pem

    ssl_protocols TLSv1.2 TLSv1.3;

    ssl_session_timeout 10m;

    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    ssl_stapling on;

    ssl_stapling_verify on;

    ssl_trusted_certificate /etc/letsencrypt/live/git./my_domain.comchain.pem;

    add_header X-Content-Type-Options nosniff;

    add_header X-Frame-Options "DENY";

    add_header X-XSS-Protection "1; mode=block";

    add_header X-Robots-Tag none;

    add_header X-Permitted-Cross-Domain-Policies none;

    add_header X-Download-Options noopen;

    access_log /var/log/nginx/git.access_log main;

    error_log /var/log/nginx/git.error_log info;

    location ~* ^.+(cgit.(css|png)|favicon.ico|robots.txt) {

        root /var/www/git.my_domain.com;

    }

    location / {

        alias /var/www/git.my_domain.com;

        try_files $uri @cgit;

        location /subfolder {

            sendfile on;

            autoindex on;

            auth_basic "Authenticated";

            auth_basic_user_file /etc/apache2/.httpasswd;

            proxy_pass_header Authorization;

            dav_methods PUT DELETE MKCOL COPY MOVE;

            dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;

            dav_ext_lock zone=foo;

            dav_access user:rw group:rw all:r;

            client_max_body_size 0;

            client_body_temp_path /var/cache/nginx/client_temp 1 2 3;

            create_full_put_path on;

            include fastcgi_params;

            fastcgi_param SCRIPT_FILENAME   /usr/libexec/git-core/git-http-backend;

            fastcgi_split_path_info ^(/*/?)(.+)$;

            fastcgi_param PATH_INFO $1;

            try_files $uri @cgit;

        }

    }

    location @cgit {

        include uwsgi_params;

        sendfile on;

        gzip on;

        uwsgi_modifier1 9;

        uwsgi_pass 127.0.0.1:1234;

    }

}

```

----------

## halcon

Hi erg_samowzbudnik,

AFAIK, cgit does not support git push:

Link to my GentooWiki page

----------

## erg_samowzbudnik

Thanks, I haven't realized.

Turns out I don't need DAV then. I am trying to arrange it differently now - pass all the traffic needed for git push to git-http-backend and the rest to cgit.

I realize it seems silly if one can just use ssh - but I found myself in a position where I need to set up one project/subfolder for a throw away joined project and it's just way more handy in this instance to pass login/password and use http.

I've tried to adapt apache example for my purposes but I'm still struggling. I.e git push doesn't work. I'm affraid I made a bit of a mess of those location directives. I'm not skilled in translating apache config to nginx neither, I'd be well gratefull for a constructive critique of my config.

```

server {

    listen 443 ssl http2;

    server_name git.mydomain;

    root /var/www/git.mydomain/;

    ssl_certificate /etc/letsencrypt/live/git.mydomain-0002/fullchain.pem; # managed by Certbot

    ssl_certificate_key /etc/letsencrypt/live/git.mydomain-0002/privkey.pem; # managed by Certbot

    ssl_protocols TLSv1.2 TLSv1.3;

    ssl_session_timeout 10m;

    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    # HSTS

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

    # OCSP stapling

    ssl_stapling on;

    ssl_stapling_verify on;

    # verify chain of trust of OCSP response using Root CA and Intermediate certs

    ssl_trusted_certificate /etc/letsencrypt/live/git.mydomain-0002/chain.pem;

    add_header X-Content-Type-Options nosniff;

    add_header X-Frame-Options "DENY";

    add_header X-XSS-Protection "1; mode=block";

    add_header X-Robots-Tag none;

    add_header X-Permitted-Cross-Domain-Policies none;

    add_header X-Download-Options noopen;

    access_log /var/log/nginx/git.access_log main;

    error_log /var/log/nginx/git.error_log info;

    location ~* ^.+(cgit.(css|png)|favicon.ico|robots.txt) {

        root /var/www/git.mydomain/htdocs/cgit;

    }

    location ~ /subfolder/\.git/objects/([0-9a-f]+.(pack|idx))$ {

        root /var/www/git.mydomain/git/subfolder;

        auth_basic "Login";

        auth_basic_user_file /etc/apache2/.httpasswd;

    }

location ~ /subfolder/\.git/(HEAD|info/refs|objects/info/.*|git-(upload|receive)-pack)$ {

        alias /var/www/git.mydomain/git/subfolder;

        auth_basic "Login";

        auth_basic_user_file /etc/apache2/.httpasswd;

        include /etc/nginx/uwsgi_params;

        client_max_body_size 0;

        fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;

        fastcgi_param GIT_HTTP_EXPORT_ALL "";

        fastcgi_param GIT_PROJECT_ROOT /var/www/git.mydomain/git/subfolder;

        fastcgi_param PATH_INFO $1;

        fastcgi_param REMOTE_USER $remote_user;

        fastcgi_pass unix:/var/run/fcgiwrap-unix.sock;

    }

    location ~ /subfolder {

        auth_basic "Login";

        auth_basic_user_file /etc/apache2/.httpasswd;

        try_files $uri @cgit;

    }

    location ~ / {

        try_files $uri @cgit;

    }

    location @cgit {

        include uwsgi_params;

        sendfile on;

        gzip on;

        uwsgi_modifier1 9;

        uwsgi_pass 127.0.0.1:1234;

    }

}

```

----------

## halcon

 *erg_samowzbudnik wrote:*   

> I realize it seems silly if one can just use ssh - but I found myself in a position where I need to set up one project/subfolder for a throw away joined project and it's just way more handy in this instance to pass login/password and use http.

 

No, I don't consider it silly.

First, ssh is not always convenient. Second, I've never been one for the easy way out in many things  :Smile: 

 *erg_samowzbudnik wrote:*   

> I've tried to adapt apache example for my purposes but I'm still struggling. I.e git push doesn't work. I'm affraid I made a bit of a mess of those location directives. I'm not skilled in translating apache config to nginx neither, I'd be well gratefull for a constructive critique of my config.

 

I am not skilled in such a translating either... 

Did you look at git-smart-http? I found a tutorial for git-smart-http + nginx (but didn't try it).

----------

## erg_samowzbudnik

I started with reading those pages you mentioned and went a bit further separating locations and stuff.

No luck. I'm stuck.

The only clue I can see but not interpret in any meaningful way is nginx error logs:

```

no user/password was provided for basic authentication (...) request: "GET /subfolder/info/refs?service=git-receive-pack HTTP/2.0"

```

and then

```

no user/password was provided for basic authentication request: "PROPFIND /subfolder/ HTTP/2.0"

```

While on the client side in the projects' .git/config I provide credentials with

```

[remote origin]

    url = https://login:password@host/subfolder

```

----------

## halcon

In this case, I would try to simplify the configuration to find "a minimal working configuration", which could help me isolate the issue... For example, does it work without subfolders? Without cgit?

----------

