├── .dockerignore ├── .gitignore ├── .gitmodules ├── Dockerfile ├── LICENSE ├── README.md ├── build.sh ├── conf ├── nuget.conf └── supervisord.conf ├── exec-debug.sh ├── run-debug.sh └── scripts ├── patch-apikey.sh ├── patch-filesize.sh └── patch-routes.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .git* 3 | LICENSE 4 | VERSION 5 | README.md 6 | Changelog.md 7 | Makefile 8 | docker-compose.yml 9 | build.sh 10 | run.sh 11 | run-debug.sh 12 | exec-debug.sh 13 | server/.git -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | NuGetAPIKey 3 | *.bak 4 | run.sh 5 | nginx.conf.example 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "server"] 2 | path = server 3 | url = https://github.com/Daniel15/simple-nuget-server.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | MAINTAINER Markus Mayer 3 | 4 | ENV APP_BASE /var/www 5 | ENV APP_BRANCH master 6 | ENV DEBIAN_VERSION jessie 7 | ENV HHVM_VERSION 3.18.1~$DEBIAN_VERSION 8 | 9 | # Install HHVM, Supervisor and PHP DBO connectors 10 | RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449 && \ 11 | echo deb http://dl.hhvm.com/debian $DEBIAN_VERSION main | tee /etc/apt/sources.list.d/hhvm.list && \ 12 | apt-get update && \ 13 | apt-get install -y --no-install-recommends hhvm=$HHVM_VERSION \ 14 | php5-mysql php5-sqlite \ 15 | supervisor 16 | 17 | # Copy in the project 18 | RUN rm -rf $APP_BASE 19 | COPY server $APP_BASE 20 | RUN rm -rf $APP_BASE/.git && \ 21 | chown www-data:www-data $APP_BASE/db $APP_BASE/packagefiles && \ 22 | chown 0770 $APP_BASE/db $APP_BASE/packagefiles 23 | 24 | # Activate the nginx configuration 25 | RUN rm /etc/nginx/conf.d/default*.conf 26 | COPY conf/nuget.conf /etc/nginx/conf.d/ 27 | 28 | # Configure file sizes 29 | RUN echo "post_max_size = 20M" >> /etc/hhvm/php.ini && \ 30 | echo "upload_max_filesize = 20M" >> /etc/hhvm/php.ini && \ 31 | perl -pi -e 's/^(\s*)(root.+?;)/\1\2\n\1client_max_body_size 20M;/' /etc/nginx/conf.d/nuget.conf 32 | 33 | # Install the supervisor configuration 34 | COPY conf/supervisord.conf /etc/supervisor/conf.d/supervisord.conf 35 | COPY scripts/*.sh /tmp/ 36 | RUN chmod +x /tmp/*.sh 37 | 38 | # The base URL 39 | ENV BASE_URL / 40 | 41 | # Set randomly generated API key 42 | RUN echo $(date +%s | sha256sum | base64 | head -c 32; echo) > $APP_BASE/.api-key && \ 43 | echo "Auto-Generated NuGet API key: $(cat $APP_BASE/.api-key)" && \ 44 | sed -i $APP_BASE/inc/config.php -e "s/ChangeThisKey/$(cat $APP_BASE/.api-key)/" 45 | 46 | # Define the volumes 47 | VOLUME ["$APP_BASE/db", "$APP_BASE/packagefiles"] 48 | 49 | # Fire in the hole! 50 | CMD ["supervisord", "-n"] 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Markus Mayer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker NuGet Feed v0.5 2 | 3 | This project provides a NuGet feed based on the [simple-nuget-server](https://github.com/Daniel15/simple-nuget-server/) project. It runs on top of the official [nginx](https://github.com/docker-library/docs/tree/master/nginx) image and uses [HHVM](http://hhvm.com) for PHP execution. [Supervisor](http://supervisord.org) is used for tracking the processes. 4 | 5 | The corresponding docker image is `sunside/simple-nuget-server` and can be found [here](https://hub.docker.com/r/sunside/simple-nuget-server/). 6 | 7 | NuGet packages currently are allowed to have a maximum size of 20 MB on upload. 8 | 9 | ## Quickstart 10 | 11 | ```bash 12 | docker run --detach=true \ 13 | --publish 5000:80 \ 14 | --env NUGET_API_KEY= \ 15 | --volume /srv/docker/nuget/database:/var/www/db \ 16 | --volume /srv/docker/nuget/packages:/var/www/packagefiles \ 17 | --name nuget-server \ 18 | sunside/simple-nuget-server 19 | ``` 20 | 21 | ## Building the image 22 | 23 | To build the image named `simple-nuget-server`, execute the following command: 24 | 25 | ```bash 26 | docker build -t simple-nuget-server . 27 | ``` 28 | 29 | At build time, a random API key is generated and printed out to the console. Note that this implies that every new image has a different *default* API key. 30 | 31 | ## Running the image 32 | 33 | Make sure to have the submodule available by either cloning with `git clone --recursive` or executing 34 | 35 | ```bash 36 | git submodule init 37 | git submodule update 38 | ``` 39 | 40 | To run a container off the `simple-nuget-server` image, execute the following command: 41 | 42 | ```bash 43 | docker run -d --name nuget-server -p 80:80 \ 44 | -e NUGET_API_KEY= simple-nuget-server 45 | ``` 46 | 47 | Note that some NuGet clients might be picky about the port, so be sure to have your feed available on either port `80` or `443`, e.g. by having a reverse proxy in front on the container. 48 | 49 | ### Environment configuration 50 | 51 | * `NUGET_API_KEY` sets the NuGet feed's API key to your own private key 52 | * `BASE_URL` sets the base path of the feed, e.g. `/nuget` if it is available under `http://your.tld/nuget/` 53 | * `UPLOAD_MAX_FILESIZE` (optional) sets the maximum allowed filesize when uploading NuGet packages via API. Default is 20M. 54 | 55 | ### Exported volumes 56 | 57 | * `/var/www/db` contains the SQLite database 58 | * `/var/www/packagefiles` contains uploaded the NuGet packages 59 | * `/var/cache/nginx` nginx' cache files 60 | 61 | ## NuGet configuration 62 | 63 | In order to push a package to your new NuGet feed, use the following command: 64 | 65 | ```bash 66 | nuget push -Source http://url.to/your/feed/ -ApiKey path/to/package.nupkg 67 | ``` 68 | 69 | Deleting package version `` of package `` is done using 70 | 71 | ```bash 72 | nuget delete -Source http://url.to/your/feed/ -ApiKey 73 | ``` 74 | 75 | Listing packages including prereleases can be done using 76 | 77 | ```bash 78 | nuget list -Source http://url.to/your/feed/ -Prerelease 79 | ``` 80 | 81 | You can add your feed to a specific `NuGet.config` file using: 82 | 83 | ```bash 84 | nuget sources add -Name "Your Feed's Name" -Source http://url.to/your/feed/ -ConfigFile NuGet.config 85 | ``` 86 | 87 | In order to store the API key in a specifig `NuGet.config` file you can use: 88 | 89 | ```bash 90 | nuget setapikey -Source http://url.to/your/feed/ -ConfigFile NuGet.config 91 | ``` 92 | 93 | This will create or update the `apikeys` section of your configuration file. Make sure to not check anything sensitive into source control. 94 | 95 | In both cases, if you omit the `-ConfigFile ` option, your user configuration file will be used. 96 | 97 | ## Apache example configuration 98 | 99 | The following configuration sets up passwordless access from the local network `192.168.0.0/24` as well as the Docker network `172.17.42.0/24` and requires 100 | basic authentication from the outside world. 101 | 102 | ``` 103 | 104 | Require all denied 105 | Require local 106 | Require ip 192.168.0.0/24 107 | Require ip 172.17.42.0/24 108 | 109 | AuthType Basic 110 | AuthName "NuGet Feed" 111 | AuthBasicProvider file 112 | AuthUserFile "/srv/docker/nuget/auth-file" 113 | Require valid-user 114 | 115 | RequestHeader set X-Forwarded-Proto "https" 116 | ProxyPass http://127.0.0.1:16473/nuget/ 117 | ProxyPassReverse http://127.0.0.1:16473/nuget/ 118 | 119 | 120 | ``` 121 | 122 | ## License 123 | 124 | This project is licensed under the MIT license. See the `LICENSE` file for more information. 125 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker build -t simple-nuget-server . 4 | -------------------------------------------------------------------------------- /conf/nuget.conf: -------------------------------------------------------------------------------- 1 | # Example of an Nginx configuration for Simple NuGet Server 2 | 3 | server { 4 | server_name localhost; 5 | root /var/www/public/; 6 | 7 | rewrite ^/$ /index.php; 8 | rewrite ^/\$metadata$ /metadata.xml; 9 | rewrite ^/Search\(\)/\$count$ /count.php; 10 | rewrite ^/Search\(\)$ /search.php; 11 | rewrite ^/Packages\(\)$ /search.php; 12 | rewrite ^/Packages\(Id='([^']+)',Version='([^']+)'\)$ /findByID.php?id=$1&version=$2; 13 | rewrite ^/GetUpdates\(\)$ /updates.php; 14 | rewrite ^/FindPackagesById\(\)$ /findByID.php; 15 | # NuGet.exe sometimes uses two slashes (//download/blah) 16 | rewrite ^//?download/([^/]+)/([^/]+)$ /download.php?id=$1&version=$2; 17 | rewrite ^/([^/]+)/([^/]+)$ /delete.php?id=$1&version=$2; 18 | 19 | # NuGet.exe adds /api/v2/ to URL when the server is at the root 20 | rewrite ^/api/v2/package/$ /index.php; 21 | rewrite ^/api/v2/package/([^/]+)/([^/]+)$ /delete.php?id=$1&version=$2; 22 | 23 | location ~ \.php$ { 24 | fastcgi_keep_conn on; 25 | fastcgi_pass 127.0.0.1:9000; 26 | #fastcgi_index index.php; 27 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 28 | include fastcgi_params; 29 | } 30 | 31 | location = /index.php { 32 | dav_methods PUT DELETE; 33 | 34 | fastcgi_keep_conn on; 35 | fastcgi_pass 127.0.0.1:9000; 36 | fastcgi_index index.php; 37 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 38 | include fastcgi_params; 39 | 40 | # PHP doesn't parse request body for PUT requests, so fake a POST. 41 | fastcgi_param REQUEST_METHOD POST; 42 | fastcgi_param HTTP_X_METHOD_OVERRIDE $request_method; 43 | } 44 | 45 | include hhvm.conf; 46 | 47 | # Used with X-Accel-Redirect 48 | location /packagefiles { 49 | internal; 50 | root /var/www/; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /conf/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [program:patchapikey] 5 | command=/tmp/patch-apikey.sh 6 | priority=0 7 | autorestart=false 8 | autostart=true 9 | startretries=0 10 | startsecs=0 11 | redirect_stdout=true 12 | redirect_stderr=true 13 | stdout_logfile=/dev/stdout 14 | stdout_logfile_maxbytes=0 15 | stderr_logfile=/dev/stderr 16 | stderr_logfile_maxbytes=0 17 | 18 | [program:patchroutes] 19 | command=/tmp/patch-routes.sh 20 | priority=0 21 | autorestart=false 22 | startsecs=0 23 | redirect_stdout=true 24 | redirect_stderr=true 25 | stdout_logfile=/dev/stdout 26 | stderr_logfile=/dev/stderr 27 | stdout_logfile_maxbytes=0 28 | stderr_logfile_maxbytes=0 29 | 30 | [program:patchfilesize] 31 | command=/tmp/patch-filesize.sh 32 | priority=0 33 | autorestart=false 34 | startsecs=0 35 | redirect_stdout=true 36 | redirect_stderr=true 37 | stdout_logfile=/dev/stdout 38 | stderr_logfile=/dev/stderr 39 | stdout_logfile_maxbytes=0 40 | stdout_logfile_maxbytes=0 41 | 42 | [program:nginx] 43 | command=/usr/sbin/nginx -g "daemon off;" 44 | priority=200 45 | autorestart=unexpected 46 | startsecs=10 47 | startretries=0 48 | redirect_stdout=true 49 | redirect_stderr=true 50 | stdout_logfile=/dev/stdout 51 | stderr_logfile=/dev/stderr 52 | stdout_logfile_maxbytes=0 53 | stderr_logfile_maxbytes=0 54 | 55 | [program:hhvm] 56 | command=/usr/bin/hhvm -m server -c /etc/hhvm/server.ini 57 | priority=100 58 | directory=/var/www 59 | autorestart=unexpected 60 | startsecs=10 61 | startretries=3 62 | user=root 63 | -------------------------------------------------------------------------------- /exec-debug.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker exec -it nuget-server $@ 4 | -------------------------------------------------------------------------------- /run-debug.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker run --name nuget-server --rm -it -p 80:80 -e "NUGET_API_KEY=secret" simple-nuget-server $@ 4 | -------------------------------------------------------------------------------- /scripts/patch-apikey.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | GENERATED_API_KEY=$(cat $APP_BASE/.api-key) 4 | 5 | if [ -z ${NUGET_API_KEY+false} ] 6 | then 7 | echo "Using generated API key: $GENERATED_API_KEY" 8 | else 9 | echo "Using API key $NUGET_API_KEY" 10 | sed -i $APP_BASE/inc/config.php -e "s/$GENERATED_API_KEY/$NUGET_API_KEY/" 11 | fi 12 | -------------------------------------------------------------------------------- /scripts/patch-filesize.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DEFAULT_SIZE=20M 4 | 5 | if [ -z ${UPLOAD_MAX_FILESIZE+false} ] 6 | then 7 | echo "Using default max upload size: ${DEFAULT_SIZE}" 8 | else 9 | echo "Using max upload size: ${UPLOAD_MAX_FILESIZE}" 10 | 11 | # set size in nginx 12 | perl -pi -e "s/client_max_body_size(\s*)${DEFAULT_SIZE};/client_max_body_size\${1}${UPLOAD_MAX_FILESIZE};/" /etc/nginx/conf.d/nuget.conf 13 | 14 | # set size in php.ini 15 | perl -pi -e "s/upload_max_filesize = ${DEFAULT_SIZE}/upload_max_filesize = ${UPLOAD_MAX_FILESIZE}/" /etc/hhvm/php.ini 16 | perl -pi -e "s/post_max_size = ${DEFAULT_SIZE}/post_max_filesize = ${UPLOAD_MAX_FILESIZE}/" /etc/hhvm/php.ini 17 | fi 18 | -------------------------------------------------------------------------------- /scripts/patch-routes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -z ${BASE_URL+false} ] 4 | then 5 | echo "Using base URL: /" 6 | else 7 | CONFIGFILE=/etc/nginx/conf.d/nuget.conf 8 | echo "Using base URL: $BASE_URL" 9 | perl -pi -e "s#rewrite \^(?!$BASE_URL)/#rewrite ^$BASE_URL/#g" $CONFIGFILE 10 | # perl -pi -e "s#\\\$\\s+(?\$BASE_URL)/#\\\$ $BASE_URL/#g" $CONFIGFILE 11 | perl -pi -e "s#location = (?!$BASE_URL)/#location = $BASE_URL/#g" $CONFIGFILE 12 | fi 13 | --------------------------------------------------------------------------------