diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dace708 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.vagrant diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8aada5e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,41 @@ +FROM abevoelker/ruby +MAINTAINER Abe Voelker + +# Set up application user 'openproject' and check out source +RUN adduser openproject --home /home/openproject --shell /bin/bash --disabled-password --gecos "" &&\ + mkdir -p /var/www/openproject &&\ + git clone https://github.com/opf/openproject.git -b stable --single-branch /var/www/openproject &&\ + mkdir -p /var/www/openproject/docker/scripts + +COPY Gemfile.local /var/www/openproject/ + +RUN chown -R openproject:openproject /var/www/openproject + +USER openproject + +RUN cd /var/www/openproject &&\ + bundle install --without mysql mysql2 sqlite development test rmagick --path vendor/bundle + +USER root + +COPY database.yml /var/www/openproject/config/ +COPY configuration.yml /var/www/openproject/config/ +COPY scripts /var/www/openproject/docker/scripts + +RUN chown -R openproject:openproject /var/www/openproject &&\ + chmod u+x /var/www/openproject/docker/scripts/*.sh + +# Add nginx configuration +ADD nginx/nginx.conf /etc/nginx/ +ADD nginx/sites-available/openproject.conf /etc/nginx/sites-available/ +RUN chown -R openproject:openproject /etc/nginx/sites-available &&\ + chown -R openproject:openproject /etc/nginx/sites-enabled &&\ + cd /etc/nginx/sites-enabled &&\ + rm default &&\ + ln -s ../sites-available/openproject.conf + +# Add supervisord configs +ADD supervisord/rails.conf /etc/supervisor/conf.d/ +ADD supervisord/nginx.conf /etc/supervisor/conf.d/ + +CMD ["/var/www/openproject/docker/scripts/run_rails.sh"] diff --git a/Gemfile.local b/Gemfile.local new file mode 100644 index 0000000..f3a423b --- /dev/null +++ b/Gemfile.local @@ -0,0 +1,3 @@ +group :production do + gem 'puma' +end diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..0b8f3fb --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,52 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +ENV['VAGRANT_DEFAULT_PROVIDER'] ||= 'docker' + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + config.vm.define "postgres" do |postgres| + postgres.vm.provider 'docker' do |d| + d.image = 'paintedfox/postgresql' + d.name = 'openproject_postgres' + d.env = { + 'USER' => 'super', + 'PASS' => 'password' + } + end + end + + config.vm.define "memcached" do |memcached| + memcached.vm.provider 'docker' do |d| + d.image = 'tutum/memcached' + d.name = 'openproject_memcached' + d.env = { + 'MEMCACHED_PASS' => 'password' + } + end + end + + config.vm.define "openproject" do |openproject| + openproject.vm.provider 'docker' do |d| + d.image = 'abevoelker/openproject' + d.name = 'openproject' + d.cmd = ['/var/www/openproject/docker/scripts/run_rails.sh'] + + d.link('openproject_postgres:postgres') + d.link('openproject_memcached:memcached') + end + end + + config.vm.define "openproject_delayed_job" do |openproject| + openproject.vm.provider 'docker' do |d| + d.image = 'abevoelker/openproject' + d.name = 'openproject_delayed_job' + d.cmd = ['/var/www/openproject/docker/scripts/run_background_job.sh'] + + d.link('openproject_postgres:postgres') + d.link('openproject_memcached:memcached') + end + end +end diff --git a/configuration.yml b/configuration.yml new file mode 100644 index 0000000..61d58d2 --- /dev/null +++ b/configuration.yml @@ -0,0 +1,203 @@ +#-- copyright +# OpenProject is a project management system. +# Copyright (C) 2012-2014 the OpenProject Foundation (OPF) +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See doc/COPYRIGHT.rdoc for more details. +#++ + +# = OpenProject configuration file +# +# Each environment has it's own configuration options. If you are only +# running in production, only the production block needs to be configured. +# Environment specific configuration options override the default ones. +# +# Note that this file needs to be a valid YAML file. +# +# Instead of using a configuration.yml file, you can configure OpenProject via +# environment variables. See doc/CONFIGURATION.md for more information. +# +# +# == Outgoing email settings (email_delivery setting) +# +# === Common configurations +# +# ==== Sendmail command +# +# production: +# email_delivery_method: :sendmail +# +# ==== Simple SMTP server at localhost +# +# production: +# email_delivery_method: "smtp" +# smtp_address: "localhost" +# smtp_port: 25 +# +# ==== SMTP server at example.com using LOGIN authentication and checking HELO for foo.com +# +# production: +# email_delivery_method: "smtp" +# smtp_address: "example.com" +# smtp_port: 25 +# smtp_authentication: :login +# smtp_domain: 'foo.com' +# smtp_user_name: 'myaccount' +# smtp_password: 'password' +# +# ==== SMTP server at example.com using PLAIN authentication +# +# production: +# email_delivery_method: "smtp" +# smtp_address: "example.com" +# smtp_port: 25 +# smtp_authentication: :plain +# smtp_domain: 'example.com' +# smtp_user_name: 'myaccount' +# smtp_password: 'password' +# +# ==== SMTP server at using TLS (GMail) +# +# This requires some additional configuration. See the article at: +# http://redmineblog.com/articles/setup-redmine-to-send-email-using-gmail/ +# +# production: +# email_delivery_method: "smtp" +# smtp_enable_starttls_auto: true +# smtp_address: "smtp.gmail.com" +# smtp_port: 587 +# smtp_domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps +# smtp_authentication: :plain +# smtp_user_name: "your_email@gmail.com" +# smtp_password: "your_password" +# +# +# === More configuration options +# +# See following page: +# +# http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration + + +# default configuration options for all environments +default: + # Outgoing emails configuration (see examples above) + email_delivery_method: :smtp + smtp_address: smtp.example.net + smtp_port: 25 + smtp_domain: example.net + smtp_authentication: :login + smtp_user_name: "openproject@example.net" + smtp_password: "my_openproject_password" + + # Prefix to the url-path. This path is then prepended to all + # the routes and is used to correclty identify the path to the assets. + # Defaults to having no prefix. + # Examples: + # For OpenProject to be reachable as + # https://example.org/open_project + # the setting has o be: + # rails_relative_url_root: "/open_project" + # + # rails_relative_url_root: "" + + # Absolute path to the directory where attachments are stored. + # The default is the 'files' directory in your OpenProject instance. + # Your OpenProject instance needs to have write permission on this + # directory. + # Examples: + # attachments_storage_path: /var/openproject/files + # attachments_storage_path: + + # Configuration of the autologin cookie. + # autologin_cookie_name: the name of the cookie (default: autologin) + # autologin_cookie_path: the cookie path (default: /) + # autologin_cookie_secure: true sets the cookie secure flag (default: false) + # autologin_cookie_name: + # autologin_cookie_path: + # autologin_cookie_secure: + + # disable browser cache for security reasons + # see: https://websecuritytool.codeplex.com/wikipage?title=Checks#http-cache-control-header-no-store + # disable_browser_cache: true + + # use memcache for performance, memcached must be installed + #rails_cache_store: :memcache + + # defines where session data is stored + # possible values are :cookie_store, :cache_store, :active_record_store + session_store: :cache_store + + # Configuration of SCM executable command. + # Absolute path (e.g. /usr/local/bin/hg) or command name (e.g. hg.exe, bzr.exe) + # On Windows, *.cmd, *.bat (e.g. hg.cmd, bzr.bat) does not work. + # Examples: + # scm_subversion_command: svn # (default: svn) + # scm_git_command: /usr/local/bin/git # (default: git) + # scm_subversion_command: + # scm_git_command: + + # Key used to encrypt sensitive data in the database (SCM and LDAP passwords). + # If you don't want to enable data encryption, just leave it blank. + # WARNING: losing/changing this key will make encrypted data unreadable. + # + # If you want to encrypt existing passwords in your database: + # * set the cipher key here in your configuration file + # * encrypt data using 'rake db:encrypt RAILS_ENV=production' + # + # If you have encrypted data and want to change this key, you have to: + # * decrypt data using 'rake db:decrypt RAILS_ENV=production' first + # * change the cipher key here in your configuration file + # * encrypt data using 'rake db:encrypt RAILS_ENV=production' + # database_cipher_key: + # + # Omniauth direct login: + # + # Per default the user may choose the usual password login as well as several omniauth providers + # on the login page and in the login drop down menu. + # + # With his configuration option you can set a specific omniauth provider to be + # used for direct login. Meaning that the login provider selection is skipped and + # the configured provider is used directly instead. + # + # If this option is active /login will lead directly to the configured omniauth provider + # and so will a click on 'Sign in' (as opposed to opening the drop down menu). + # + # Note that this does not stop a user from manually navigating to any other + # omniauth provider if additional ones are configured. + # omniauth_direct_login_provider: developer + # + # disable_password_login: true + +# specific configuration options for production environment +# that overrides the default ones +# production: + +# specific configuration options for development environment +# that overrides the default ones +development: + email_delivery_method: :letter_opener + +# Configuration for the test environment +test: + email_delivery_method: :test diff --git a/database.yml b/database.yml new file mode 100644 index 0000000..8aba24e --- /dev/null +++ b/database.yml @@ -0,0 +1,7 @@ +production: + adapter: postgresql + database: openproject + host: <%= ENV['POSTGRES_PORT_5432_TCP_ADDR'] %> + username: openproject + password: <%= ENV['POSTGRES_ENV_PASS'] %> + encoding: utf8 diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..90b3457 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,96 @@ +user openproject; +worker_processes auto; +pid /run/nginx.pid; +daemon off; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + + ## + # Basic Settings + ## + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + # server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ## + # Logging Settings + ## + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + ## + # Gzip Settings + ## + + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; + + ## + # nginx-naxsi config + ## + # Uncomment it if you installed nginx-naxsi + ## + + #include /etc/nginx/naxsi_core.rules; + + ## + # nginx-passenger config + ## + # Uncomment it if you installed nginx-passenger + ## + + #passenger_root /usr; + #passenger_ruby /usr/bin/ruby; + + ## + # Virtual Host Configs + ## + + include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} + + +#mail { +# # See sample authentication script at: +# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript +# +# # auth_http localhost/auth.php; +# # pop3_capabilities "TOP" "USER"; +# # imap_capabilities "IMAP4rev1" "UIDPLUS"; +# +# server { +# listen localhost:110; +# protocol pop3; +# proxy on; +# } +# +# server { +# listen localhost:143; +# protocol imap; +# proxy on; +# } +#} diff --git a/nginx/sites-available/openproject.conf b/nginx/sites-available/openproject.conf new file mode 100644 index 0000000..174af86 --- /dev/null +++ b/nginx/sites-available/openproject.conf @@ -0,0 +1,50 @@ +upstream openproject { + server unix:/var/www/openproject/tmp/puma.sock fail_timeout=0; +} + +server { + listen 80 default_server; + + access_log /var/www/openproject/log/nginx_access.log; + error_log /var/www/openproject/log/nginx_error.log; + rewrite_log on; + + # path for static files + root /var/www/openproject/public; + + error_page 402 /402.html; + error_page 404 /404.html; + error_page 500 502 503 504 /50x.html; + + location / { + # an HTTP header important enough to have its own Wikipedia entry: + # http://en.wikipedia.org/wiki/X-Forwarded-For + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # enable this if and only if you use HTTPS, this helps Rack + # set the proper protocol for doing redirects: + # proxy_set_header X-Forwarded-Proto https; + + # pass the Host: header from the client right along so redirects + # can be set properly within the Rack application + proxy_set_header Host $http_host; + + # we don't want nginx trying to do something clever with + # redirects, we set the Host: header above already. + proxy_redirect off; + + # set "proxy_buffering off" *only* for Rainbows! when doing + # Comet/long-poll stuff. It's also safe to set if you're + # using only serving fast clients with Unicorn + nginx. + # Otherwise you _want_ nginx to buffer responses to slow + # clients, really. + # proxy_buffering off; + + # Try to serve static files from nginx, no point in making an + # *application* server like Unicorn/Rainbows! serve static files. + if (!-f $request_filename) { + proxy_pass http://openproject; + break; + } + } +} diff --git a/scripts/create_database.sql b/scripts/create_database.sql new file mode 100644 index 0000000..5177b00 --- /dev/null +++ b/scripts/create_database.sql @@ -0,0 +1,2 @@ +create role openproject login encrypted password 'password' noinherit valid until 'infinity'; +create database openproject with encoding='UTF8' owner=openproject; diff --git a/scripts/env.sh b/scripts/env.sh new file mode 100644 index 0000000..f9aba23 --- /dev/null +++ b/scripts/env.sh @@ -0,0 +1,7 @@ +#!/bin/bash +export RAILS_ENV="production" +source /etc/profile.d/ruby.sh + +# Execute the commands passed to this script +# e.g. "./env.sh bundle exec rake +exec "$@" diff --git a/scripts/run_background_job.sh b/scripts/run_background_job.sh new file mode 100644 index 0000000..2bf0530 --- /dev/null +++ b/scripts/run_background_job.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +cd /var/www/openproject &&\ + exec su openproject -c "/var/www/openproject/docker/scripts/env.sh bundle exec script/delayed_job run --exit-on-complete" diff --git a/scripts/run_rails.sh b/scripts/run_rails.sh new file mode 100644 index 0000000..e236eac --- /dev/null +++ b/scripts/run_rails.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +export RAILS_ENV=${RAILS_ENV:-production} + +if [ ! -f /var/www/openproject/.setup-complete ]; then + echo -e "\nSetup has not been completed. Running setup now..." + su -c "/var/www/openproject/docker/scripts/setup.sh" openproject + echo -e "\nSetup complete!\n" +fi + +echo -e "\nBooting Rails application..." +/usr/bin/supervisord -c /etc/supervisor/supervisord.conf -n diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100644 index 0000000..a6d5df9 --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +export RAILS_ENV=${RAILS_ENV:-production} +source /etc/profile.d/ruby.sh + +cd /var/www/openproject &&\ + echo -e "\nCreating database..." &&\ + PGPASSWORD=$POSTGRES_ENV_PASS psql -h $POSTGRES_PORT_5432_TCP_ADDR -d postgres -f /var/www/openproject/docker/scripts/create_database.sql -U $POSTGRES_ENV_USER &&\ + echo -e "\nGenerating secret token..." &&\ + bundle exec rake generate_secret_token &&\ + echo -e "\nRunning database migrations..." &&\ + bundle exec rake db:migrate &&\ + echo -e "\nSeeding database..." &&\ + bundle exec rake db:seed &&\ + echo -e "\nPrecompiling assets..." &&\ + bundle exec rake assets:precompile &&\ + touch /var/www/openproject/.setup-complete diff --git a/supervisord/nginx.conf b/supervisord/nginx.conf new file mode 100644 index 0000000..6bb50e9 --- /dev/null +++ b/supervisord/nginx.conf @@ -0,0 +1,5 @@ +[program:nginx] +# nginx switches user on its own +#user=www-data +command=/usr/sbin/nginx -c /etc/nginx/nginx.conf +autorestart=true diff --git a/supervisord/rails.conf b/supervisord/rails.conf new file mode 100644 index 0000000..20ebaae --- /dev/null +++ b/supervisord/rails.conf @@ -0,0 +1,6 @@ +[program:rails] +user=openproject +directory=/var/www/openproject +command=/var/www/openproject/docker/scripts/env.sh bundle exec puma -b unix:///var/www/openproject/tmp/puma.sock +redirect_stderr=true +autorestart=true