{"id":22289437,"url":"https://github.com/tf/paperclip-nginx-upload","last_synced_at":"2025-10-09T02:09:20.697Z","repository":{"id":13163977,"uuid":"15846899","full_name":"tf/paperclip-nginx-upload","owner":"tf","description":"Paperclip io adapter for integration with nginx upload module","archived":false,"fork":false,"pushed_at":"2022-06-28T07:00:29.000Z","size":33,"stargazers_count":15,"open_issues_count":0,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-04-07T00:10:01.696Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-12T17:27:35.000Z","updated_at":"2022-06-28T06:40:40.000Z","dependencies_parsed_at":"2022-08-21T00:20:47.815Z","dependency_job_id":null,"html_url":"https://github.com/tf/paperclip-nginx-upload","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf%2Fpaperclip-nginx-upload","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf%2Fpaperclip-nginx-upload/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf%2Fpaperclip-nginx-upload/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf%2Fpaperclip-nginx-upload/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tf","download_url":"https://codeload.github.com/tf/paperclip-nginx-upload/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227962302,"owners_count":17847912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-03T17:09:09.885Z","updated_at":"2025-10-09T02:09:15.651Z","avatar_url":"https://github.com/tf.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Paperclip Nginx Upload\n\n[![Gem Version](https://badge.fury.io/rb/paperclip-nginx-upload.png)](http://badge.fury.io/rb/paperclip-nginx-upload)\n[![Build Status](https://github.com/tf/paperclip-nginx-upload/actions/workflows/tests.yml/badge.svg)](https://github.com/tf/paperclip-nginx-upload/actions/workflows/tests.yml)\n\nA Paperclip IOAdapter to handle file upload requests which have been\nrewritten by the\n[nginx upload module](https://github.com/vkholodkov/nginx-upload-module).\n\nThe gem evolved out of the discussion in the following paperclip\nissue:\nhttps://github.com/thoughtbot/paperclip/issues/1396\n\n## Motivation\n\nNginx is much faster when it comes to parsing file uploads from the\nbody of HTTP requests.  We do not want to occupy our Rails processes\nwith this tasks.  Using the\n[nginx upload module](https://github.com/vkholodkov/nginx-upload-module),\nupload request can be rewritten to contain the path of a temp file\nparsed from the request body before they are passed to our Rails app.\n\n## Installation\n\nChoose one from two options and add line to your application's Gemfile:\n\n1.) with [paperclip](https://github.com/thoughtbot/paperclip) dependency, use:\n\n    gem 'paperclip-nginx-upload', '~\u003e 1.0'\n\n2.) with [kt-paperclip](https://github.com/kreeti/kt-paperclip) dependency, use:\n\n    gem 'paperclip-nginx-upload', '~\u003e 2.0'\n\n## Usage\n\nConfigure nginx to parse your upload requests. There is an example\nnginx configuration snippet in `examples/nginx.conf`.\n\nAdd an initializer to configure the gem:\n\n```ruby\n # config/intializers/paperclip_nginx_upload.rb\n require 'paperclip/nginx/upload'\n\n Paperclip::Nginx::Upload::IOAdapter.default_options.merge!(\n   # location where nginx places file uploads\n   tmp_path_whitelist: ['/tmp/nginx_uploads/**'],\n\n   # Change this option to true to move temp files created\n   # by nginx to the paperclip tmp file location. By default\n   # files are copied.\n   move_tempfile: false\n )\n```\n\nThe adapter is a drop in replacement. When using strong parameters,\nyou only have to make sure the param containing the upload can also be\na hash of values:\n\n```ruby\n class User\n   has_attached_file :avatar\n end\n\n class UsersController \u003c ApplicationController\n   def update\n     @user.update_attributes(user_params)\n   end\n\n   def user_params\n     params.require(:user)\n      # in production avatar will be a hash generated by nginx\n      .permit(avatar: [:tmp_path, :original_name, :content_type])\n\n      # in development we want to permit the uploaded file itself\n      .merge(params.require(:user).permit(:avatar))\n   end\n end\n```\n\n## Security Considerations\n\nAssume an upload request contains a form field named\n`user[avatar]`. Given the nginx configuration from\n`examples/nginx.conf`, the request is rewritten to contain the\nfollowing three form fields instead:\n\n* `user[avatar][original_name]`\n* `user[avatar][conten_type]`\n* `user[avatar][tmp_path]`\n\nBy using this gem, you basically tell your app to accept paths to\nlocal files in the `tmp_path` param and move them around the\nfile system. Nginx ensures that these parameters can not be passed in\nfrom the outside, preventing an attacker from passing `/etc/passwd` as\n`tmp_path` and having it delivered to him as his own upload\nlater on.\n\nStill, if you forget to configure the nginx-upload-module correctly\nfor one of your upload end points, this could become a threat. This is\nespecially dangerous when not using strong parameters. While, as seen\nabove, the nested hash has to be permitted explicitly, methods\nassigning attachments directly might be open to attacks:\n\n```ruby\n @user.avatar = params[:avatar]\n```\n\nTherefore the paperclip-nginx-upload adapter only accepts tmp files\nfrom locations matching an entry in the `tmp_path_whitelist`. That way\nan attacker will only be able to access running uploads of other\nvisitors of the site. He still would have to guess the random file\nnames chosen by nginx, which seems rather unfeasable.\n\n## Move vs Copy\n\nBy default, temp files created by ngninx are copied before passing\nthem to Paperclip. This ensures proper file ownership. When your nginx\nruns as the same user as your rails processes, it might be sufficient\nto simply move the file. Depending on your file system, this might be\na significant performance gain. In that case set `move_tempfile` to\n`true`.\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftf%2Fpaperclip-nginx-upload","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftf%2Fpaperclip-nginx-upload","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftf%2Fpaperclip-nginx-upload/lists"}