loic-sharma / BaGet

A lightweight NuGet and symbol server
https://loic-sharma.github.io/BaGet/
MIT License
2.62k stars 680 forks source link

private feeds via nginx reverse proxy (workaround) #515

Open jsiedentop opened 4 years ago

jsiedentop commented 4 years ago

Several people would like to run a private nuget feed. The depending pull request is open for 2 years now. It seems that this could take a while to be published. https://github.com/loic-sharma/BaGet/pull/69

I provide the baget service behind a nuget reverse proxy where nginx takes over the authentification part. In combination with docker compose this works quite well. I think this is a nice workaround as long the pull request is open.

The nginx site configuration:

server {
  listen 80;
  server_name packages.myawesomeproject.com;

  proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header   X-Forwarded-Proto $scheme;
  proxy_set_header   Host $host;

  location / {
    auth_basic "Resticted Content";
    auth_basic_user_file /etc/nginx/.htpasswd;
    proxy_pass http://baget:80;
  }

creating the htpasswd file:

sudo sh -c "echo -n '[username]:' >> /etc/nginx/.htpasswd"
sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"

As many people didn't know how nuget auth works exactly it would be nice to add this way to the documentation. An all in one docker-compose file with nginx and baget would be awesome.

pierrediancourt commented 4 years ago

You can also filter by IP as follow :

        location / {
        satisfy all;
                allow 127.0.0.1;
                allow xxx.xxx.xxx.xxx;
                deny all;

                proxy_max_temp_file_size 2048m;

                proxy_pass http://baget;
                proxy_set_header Host $http_host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                ... etc ...
        }

This is totally compatible with @jsiedentop's answer.

NB : I had to increase the "proxy_max_temp_file_size" value for my usage.

johanneswdm commented 4 years ago

But how is it possible to authenticate when using the included symbol-server? It seems like Visual Studio has no built-in option to use password-protected symbol servers and it returns me a 401: Unauthorized.

abakumov-v commented 4 years ago

Hello! @jsiedentop @pierrediancourt can you present full docker-compose.yml and nginx conf files? I'm trying set up nginx and baget but when I send request to "/" I'm getting 502 Bad Gateway error from nginx...

pierrediancourt commented 4 years ago

Hi @abakumov-v,
Here's something that works. It may not be the prettier or easier way as i didn't put a lot of time into it.
Just pop a thumb up on this message if that helps you ;)
Let's avoid flooding this topic !

version: '3'

services:
  baget:
    image: loicsharma/baget:latest
    restart: unless-stopped
    container_name: packagemanager_baget
    hostname: baget
    expose:
      - 80
    environment:
      - ASPNETCORE_ENVIRONMENT=Release
      - ApiKey=xxxxxxxxxxxxxxxxxx
      - PackageDeletionBehavior=Unlist
      - AllowPackageOverwrites=true
      - Storage__Type=FileSystem
      - Storage__Path=/var/baget/packages
      - Database__Type=PostgreSql
      - Database__ConnectionString=User ID=baget;Password=MySuperPassword;Host=postgres;Port=5432;Database=baget;
      - Search__Type=Database
      - Mirror__Enable=true
      - Mirror__PackageSource="https://api.nuget.org/v3/index.json"
    volumes:
      - baget_data:/var/baget

  postgres:
    image: postgres:12.3-alpine
    restart: unless-stopped
    container_name: packagemanager_postgres
    hostname: postgres
    expose:
      - 5432
    environment:
      - POSTGRES_USER=baget
      - POSTGRES_PASSWORD=MySuperPassword
      - POSTGRES_DB=baget
    volumes:
      # This needs explicit mapping due to https://github.com/docker-library/postgres/blob/4e48e3228a30763913ece952c611e5e9b95c8759/Dockerfile.template#L52
      - postgres_data:/var/lib/postgresql/data

volumes:
  baget_data:
  postgres_data:

nginx config :

upstream baget{
    server packagemanager_baget:80;
}

server {
    listen 80;
    server_name baget.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name baget.example.com;

     # managing the ssl/tls traffic decryption, dependant on your setup, this is just an example
     ssl_certificate /etc/letsencrypt/live/xxx/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/xxx/privkey.pem;
     ssl_protocols         TLSv1.2; # obsolete : SSLv3 TLSv1 TLSv1.1 
    ssl_ciphers           ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_session_cache     shared:SSL:20m;
    ssl_session_timeout   4h;

    # blocking the search engines
    location = /robots.txt {
        add_header Content-Type text/plain;
        return 200 "User-agent: *\nDisallow: /\n";
    }

    location / {
        # blacklisting every ip but these :
        satisfy all;
        allow 000.000.000.000; # my public ip accessing this service
        allow 000.000.000.001; # another ip allowed to access
        deny all;

        proxy_max_temp_file_size 2048m; # optional and depends on the size of the things that are uploaded/downloaded through nginx 

        proxy_pass http://baget;
        proxy_redirect off;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
aleks73337 commented 4 years ago

@pierrediancourt, It also works if your baget server in kubernetes. Without it, kubernetes resolves it's own virtual IP. But with your config, it works fine!

wojtek-viirtue commented 3 years ago

Posting the required K8s manifest here just in case anyone wants to run this in kubernetes.

Note: I SSL offload at a load balancer so the configuration is all over http, but it should simple enough to tweak for your own use case.

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: baget-nuget-server-pvc
spec:
  storageClassName: kadalu.replica3
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: baget-nuget-server
spec:
  selector:
    matchLabels:
      app: baget-nuget-server
  template:
    metadata:
      labels:
        app: baget-nuget-server
    spec:
      containers:
      - name: baget-nuget-server
        image: loicsharma/baget:latest
        env:
          - name: ASPNETCORE_ENVIRONMENT
            value: Releae

          - name: ApiKey
            value: XXXXXXXXXXXXXXX

          - name: Storage__Type
            value: FileSystem

          - name: Storage__Path
            value: /var/baget/packages

          - name: Database__Type
            value: Sqlite

          - name: Database__ConnectionString
            value: Data Source=/var/baget/baget.db

          - name: Search__Type
            value: Database

        resources:
          limits:
            memory: "512Mi"
            cpu: "500m"
        ports:
        - containerPort: 80

        volumeMounts:
          - mountPath: /var/baget/packages
            name: baget-packages

      volumes:
        - name: baget-packages
          persistentVolumeClaim:
            claimName: baget-nuget-server-pvc 
---
kind: Service
apiVersion: v1
metadata:
  name:  baget-nuget-server
spec:
  selector:
    app:  baget-nuget-server
  type:  ClusterIP
  ports:
  - name:  http
    port:  80
    targetPort:  80
---
apiVersion: v1
data:
  auth: XXXXXXXXXXXXXXX
kind: Secret
metadata:
  name: basic-auth
type: Opaque
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-baget
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Nuget Server'
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: nuget.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
            service:
              name: baget-nuget-server
              port: 
                number: 80
aleks73337 commented 3 years ago

Thank you!

On Wed, 20 Jan 2021 at 16:04, wojtek-viirtue notifications@github.com wrote:

Posting the required K8s manifest here just in case anyone wants to run this in kubernetes.

Note: I SSL offload at a load balancer so the configuration is all over http, but it should simple enough to tweak for your own use case.

kind: PersistentVolumeClaim apiVersion: v1 metadata: name: baget-nuget-server-pvc spec: storageClassName: kadalu.replica3 accessModes:

  • ReadWriteMany resources: requests: storage: 1Gi

    apiVersion: apps/v1 kind: Deployment metadata: name: baget-nuget-server spec: selector: matchLabels: app: baget-nuget-server template: metadata: labels: app: baget-nuget-server spec: containers:

    • name: baget-nuget-server image: loicsharma/baget:latest env:

      • name: ASPNETCORE_ENVIRONMENT value: Releae

      • name: ApiKey value: XXXXXXXXXXXXXXX

      • name: Storage__Type value: FileSystem

      • name: Storage__Path value: /var/baget/packages

      • name: Database__Type value: Sqlite

      • name: Database__ConnectionString value: Data Source=/var/baget/baget.db

      • name: Search__Type value: Database

      resources: limits: memory: "512Mi" cpu: "500m" ports:

      • containerPort: 80

      volumeMounts:

      • mountPath: /var/baget/packages name: baget-packages

      volumes:

      • name: baget-packages persistentVolumeClaim: claimName: baget-nuget-server-pvc

        kind: Service apiVersion: v1 metadata: name: baget-nuget-server spec: selector: app: baget-nuget-server type: ClusterIP ports:

      • name: http port: 80 targetPort: 80

        apiVersion: v1 data: auth: XXXXXXXXXXXXXXX kind: Secret metadata: name: basic-auth type: Opaque

        apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-baget annotations: nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Nuget Server' kubernetes.io/ingress.class: nginx spec: rules:

      • host: nuget.yourdomain.com http: paths:
    • path: / pathType: Prefix backend: service: name: baget-nuget-server port: number: 80

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/loic-sharma/BaGet/issues/515#issuecomment-763592536, or unsubscribe https://github.com/notifications/unsubscribe-auth/AH2SKKECUIBCEH2J5KSA3KDS23IFPANCNFSM4M4XHJHQ .