diff options
author | Stefan Tatschner | 2015-06-09 22:58:50 +0200 |
---|---|---|
committer | Stefan Tatschner | 2015-06-09 22:58:50 +0200 |
commit | 147947e25d90ec49368a7d12a1fdf2ffaac3fe0a (patch) | |
tree | 617cfeedee0fb4bdc3fdcf5c96777a164bc74d28 | |
download | aur-147947e25d90ec49368a7d12a1fdf2ffaac3fe0a.tar.gz |
Initial import
-rw-r--r-- | .SRCINFO | 70 | ||||
-rw-r--r-- | 0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch | 87 | ||||
-rw-r--r-- | PKGBUILD | 147 | ||||
-rw-r--r-- | apache-ssl.conf.example | 77 | ||||
-rw-r--r-- | apache.conf.example | 51 | ||||
-rw-r--r-- | discourse-kill.service | 6 | ||||
-rw-r--r-- | discourse-kill.timer | 9 | ||||
-rw-r--r-- | discourse-sidekiq.service | 26 | ||||
-rw-r--r-- | discourse-unicorn.service | 26 | ||||
-rw-r--r-- | discourse-update.service | 18 | ||||
-rw-r--r-- | discourse.install | 24 | ||||
-rw-r--r-- | discourse.logrotate | 8 | ||||
-rw-r--r-- | discourse.target | 6 | ||||
-rw-r--r-- | discourse.tmpfiles.d | 1 | ||||
-rw-r--r-- | nginx-ssl.conf.example | 142 | ||||
-rw-r--r-- | nginx.conf.example | 90 | ||||
-rw-r--r-- | unicorn.conf.rb | 114 |
17 files changed, 902 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..51f38c786c47 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,70 @@ +pkgbase = discourse + pkgdesc = A simple, flat forum, where replies flow down the page in a line + pkgver = 1.3.1 + pkgrel = 1 + url = http://www.discourse.org/ + install = discourse.install + arch = i686 + arch = x86_64 + license = GPL + makedepends = nodejs-uglify-js + depends = ruby>=2.0 + depends = ruby-bundler>=1.5.2 + depends = gmp + depends = libxml2 + depends = libxslt + depends = openssl + depends = krb5 + depends = libgcrypt + depends = libgpg-error + depends = postgresql-libs + depends = xz + depends = zlib + optdepends = apache: a webserver to deploy discourse + optdepends = nginx: another webserver to deploy discourse (example configs have to be fixed!) + optdepends = postgresql: database server + optdepends = postfix: mail server in order to receive mail notifications + optdepends = jpegoptim: needed to do optimizations on stored images + optdepends = pngcrush: needed to do optimizations on stored images + optdepends = pngout: needed to do optimizations on stored images + optdepends = advancecomp: needed to do optimizations on stored images + optdepends = gifsicle: needed to do optimizations on stored images + optdepends = jhead: needed to do optimizations on stored images + optdepends = nodejs-svgo: needed to do optimizations on stored images + optdepends = pngquant: needed to do optimizations on stored images + optdepends = optipng: needed to do optimizations on stored images + backup = etc/webapps/discourse/unicorn.conf.rb + backup = etc/webapps/discourse/discourse.conf + source = discourse::git+https://github.com/discourse/discourse.git#tag=v1.3.1 + source = discourse-sidekiq.service + source = discourse-unicorn.service + source = discourse-kill.service + source = discourse-kill.timer + source = discourse.target + source = discourse-update.service + source = discourse.tmpfiles.d + source = discourse.logrotate + source = unicorn.conf.rb + source = apache.conf.example + source = apache-ssl.conf.example + source = nginx.conf.example + source = nginx-ssl.conf.example + source = 0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch + sha256sums = SKIP + sha256sums = 51e2005fe002d42c8f5ffd3e9ccff54a739555c8e121584603c5d7daee255ca8 + sha256sums = ec711a14712cd7419378a92209b9db1af6a26f758f24aeddcf6e73efc763cd9b + sha256sums = 803c5b71fb350577a0e81c60ad5d511cba0d983046592a5dc8a2f9c726ec2143 + sha256sums = d8fab91c2b15e50db26caa00c034db4703b864e6434846b72225c871e4a3d508 + sha256sums = b512d219056537f7a7b749a10cfb90fb78116d7c6414e0a0bc72c08f1ced3f43 + sha256sums = 0b5110b99f3356d9931ce4991344b1149a2d3be04322043b555b91d8751c7a31 + sha256sums = 71fa450935dea04c30cc5a0eaaa16012ac765445644ca719b7a1d589aad1938f + sha256sums = 1c57caa7b2dad6b66db724a7db3ff8f156d0291e88cccdfb37d89e3557a7715d + sha256sums = c76423db80d2f4b39ea5fcd95fd66dfb38de9e9862e8370dfc3a45641e2204ca + sha256sums = b40c615d8da35fe5a02b914baf5920025ee7167b5d78b47d5905e633934ca11e + sha256sums = 8056354bac606f66a3667034ff93ffbfce3ec52664e7a809835d5cc45a121c30 + sha256sums = 7d00b5d99777b4843cdc2f8fb9c65beb94375dcaa6351d2c8f6d55161512b3c5 + sha256sums = cd8965f971047ce5cf5c32d4709fe231c392893702db181300b02de86e0f70fb + sha256sums = 77fc9f233a964fbb3a4952001e575b07772d1939bf2e0872f5161512ceffd62a + +pkgname = discourse + diff --git a/0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch b/0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch new file mode 100644 index 000000000000..edd60b1df934 --- /dev/null +++ b/0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch @@ -0,0 +1,87 @@ +From 964229bf6e14c4b4f16b05529b4e295d71e817ef Mon Sep 17 00:00:00 2001 +From: Stefan Tatschner <stefan@sevenbyte.org> +Date: Thu, 7 May 2015 18:06:42 +0200 +Subject: [PATCH] Revert "this quickstart file is confusing and not needed" + +This reverts commit 7bc220956a76463ee750d11e2c829498e83ce5eb. +--- + config/discourse_quickstart.conf | 67 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 67 insertions(+) + create mode 100644 config/discourse_quickstart.conf + +diff --git a/config/discourse_quickstart.conf b/config/discourse_quickstart.conf +new file mode 100644 +index 0000000..f60e823 +--- /dev/null ++++ b/config/discourse_quickstart.conf +@@ -0,0 +1,67 @@ ++# Discourse supports multiple mechanisms for production config, detailed in the _defaults file. ++# This file includes the most commonly changed enviroment variables, to allow users following the official install guide to quickly get started; if the option you're looking for is not here it may be defined in the _defaults file. ++ ++# Change the following! ++# All settings apply to production only ++ ++# database name running discourse, in INSTALL-ubuntu this is discourse_prod ++db_name = discourse_prod ++ ++# hostname running the forum; i.e the external address of your form. ++hostname = "discourse.example.com" ++ ++# address of smtp server used to send emails. If testing, this can be left empty; but e-mails are a very important part of discourse. ++smtp_address = ++ ++# port of smtp server used to send emails. This varies based on your e-mail host. ++smtp_port = 25 ++ ++# domain passed to smtp server ++smtp_domain = ++ ++# username for smtp server ++smtp_user_name = ++ ++# password for smtp server ++smtp_password = ++ ++# enable TLS encryption for smtp connections ++smtp_enable_start_tls = true ++ ++# enable MiniProfiler for developers, by default this is true. This shows response times in the top left for admin users only. Uncomment this line to turn this off. ++# load_mini_profiler = false ++ ++# recommended, cdn used to access assets. This can be left empty at first. ++cdn_url = ++ ++# comma delimited list of emails that have developer level access. ++developer_emails = ++ ++# More advanded settings. Unless you changed these in your enviroment, the defaults will work. ++ ++## Database ++ ++# host address for db server, uncomment if needed ++# db_host = localhost ++ ++# port running db server, uncomment if needed ++# db_port = 5432 ++ ++# username accessing database, if connecting remotely ++# db_username = discourse ++ ++# password used to access the db, if connecting remotely ++# db_password = ++ ++# Redis ++ ++# redis server address ++# redis_host = localhost ++ ++# redis server port ++# redis_port = 6379 ++ ++# redis password ++# redis_password = ++ ++ +-- +2.4.0 + diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..45e40dd28e56 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,147 @@ +# Maintainer: Stefan Tatschner <stefan@sevenbyte.org> +# Contributor: Tobias Hunger <tobias DOT hunger AT gmail DOT com> + +pkgname=discourse +pkgver=1.3.1 +pkgrel=1 +pkgdesc="A simple, flat forum, where replies flow down the page in a line" +arch=('i686' 'x86_64') +url="http://www.discourse.org/" +license=('GPL') +depends=('ruby>=2.0' 'ruby-bundler>=1.5.2' 'gmp' 'libxml2' 'libxslt' 'openssl' + 'krb5' 'libgcrypt' 'libgpg-error' 'postgresql-libs' 'xz' 'zlib') +makedepends=('nodejs-uglify-js') +optdepends=('apache: a webserver to deploy discourse' + 'nginx: another webserver to deploy discourse (example configs have to be fixed!)' + 'postgresql: database server' + 'postfix: mail server in order to receive mail notifications' + 'jpegoptim: needed to do optimizations on stored images' + 'pngcrush: needed to do optimizations on stored images' + 'pngout: needed to do optimizations on stored images' + 'advancecomp: needed to do optimizations on stored images' + 'gifsicle: needed to do optimizations on stored images' + 'jhead: needed to do optimizations on stored images' + 'nodejs-svgo: needed to do optimizations on stored images' + 'pngquant: needed to do optimizations on stored images' + 'optipng: needed to do optimizations on stored images') +backup=("etc/webapps/discourse/unicorn.conf.rb" + "etc/webapps/discourse/discourse.conf") +source=("${pkgname}::git+https://github.com/discourse/discourse.git#tag=v${pkgver}" + "discourse-sidekiq.service" + "discourse-unicorn.service" + "discourse-kill.service" + "discourse-kill.timer" + "discourse.target" + "discourse-update.service" + "discourse.tmpfiles.d" + "discourse.logrotate" + "unicorn.conf.rb" + "apache.conf.example" + "apache-ssl.conf.example" + "nginx.conf.example" + "nginx-ssl.conf.example" + "0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch") +install="${pkgname}.install" +sha256sums=('SKIP' + '51e2005fe002d42c8f5ffd3e9ccff54a739555c8e121584603c5d7daee255ca8' + 'ec711a14712cd7419378a92209b9db1af6a26f758f24aeddcf6e73efc763cd9b' + '803c5b71fb350577a0e81c60ad5d511cba0d983046592a5dc8a2f9c726ec2143' + 'd8fab91c2b15e50db26caa00c034db4703b864e6434846b72225c871e4a3d508' + 'b512d219056537f7a7b749a10cfb90fb78116d7c6414e0a0bc72c08f1ced3f43' + '0b5110b99f3356d9931ce4991344b1149a2d3be04322043b555b91d8751c7a31' + '71fa450935dea04c30cc5a0eaaa16012ac765445644ca719b7a1d589aad1938f' + '1c57caa7b2dad6b66db724a7db3ff8f156d0291e88cccdfb37d89e3557a7715d' + 'c76423db80d2f4b39ea5fcd95fd66dfb38de9e9862e8370dfc3a45641e2204ca' + 'b40c615d8da35fe5a02b914baf5920025ee7167b5d78b47d5905e633934ca11e' + '8056354bac606f66a3667034ff93ffbfce3ec52664e7a809835d5cc45a121c30' + '7d00b5d99777b4843cdc2f8fb9c65beb94375dcaa6351d2c8f6d55161512b3c5' + 'cd8965f971047ce5cf5c32d4709fe231c392893702db181300b02de86e0f70fb' + '77fc9f233a964fbb3a4952001e575b07772d1939bf2e0872f5161512ceffd62a') + +_homedir="/var/lib/${pkgname}" +_datadir="/usr/share/webapps/${pkgname}" +_logdir="/var/log/${pkgname}" +_etcdir="/etc/webapps/${pkgname}" +_systemddir="/usr/lib/systemd/system" + +prepare() { + cd "${srcdir}/${pkgname}" + + # Patch source files to include a static revision string and remove git repo. + # Including the git repository triples the package size. + _revision=$(git rev-parse HEAD) + _revision_describe=$(git describe --dirty) + if [ $_revision_describe = "latest-release" ]; then + _revision_describe=$pkgver + fi + msg2 "Patching internal revision numbers ${_revision} to a static string..." + sed -i "s|\`git rev-parse HEAD\`|'${_revision}'|g" "lib/discourse.rb" + # This one is used on the dashboard, see: + # https://github.com/discourse/discourse/commit/f1b606bf0890eb1f23cb9cbb9f35af86f4b94245 + sed -i "s|\`git describe --dirty\`|'${_revision_describe}'|g" "lib/discourse_updates.rb" + rm -rf .git + + # Bring back discourse_quickstart.conf; Sam broke it: + # https://github.com/discourse/discourse/commit/7bc220956a76463ee750d11e2c829498e83ce5eb + patch -p1 -i "${srcdir}/0001-Revert-this-quickstart-file-is-confusing-and-not-nee.patch" + + msg2 "Patching discourse_defaults.conf to serve assets..." + sed -i "s|serve_static_assets = false|serve_static_assets = true|g" "config/discourse_defaults.conf" +} + +build() { + cd "${srcdir}/${pkgname}" + + cpus=$(nproc) + msg2 "Starting bundler with ${cpus} jobs..." + msg2 "Gems will be installed into vendor/bundle." + bundle config build.nokogiri --use-system-libraries + bundle install --jobs ${cpus} --no-cache --no-prune --deployment --without development test +} + +package() { + cd "${srcdir}/${pkgname}" + + install -d "${pkgdir}/usr/share/webapps" + cp -r "${srcdir}/${pkgname}" "${pkgdir}${_datadir}" + + msg2 "Creating directories and symlinks..." + install -d \ + "${pkgdir}${_etcdir}" \ + "${pkgdir}/usr/share/doc/${pkgname}" \ + "${pkgdir}${_homedir}" \ + "${pkgdir}/usr/lib/systemd/system" + + mv "${pkgdir}${_datadir}/public" "${pkgdir}${_homedir}/public" && \ + ln -fs "${_homedir}/public" "${pkgdir}${_datadir}/public" + mv "${pkgdir}${_datadir}/plugins" "${pkgdir}${_homedir}/plugins" && \ + ln -fs "${_homedir}/plugins" "${pkgdir}${_datadir}/plugins" + # We are using PrivateTmp=true to start unicorn, so this is safe! + rm -rf "${pkgdir}${_datadir}/tmp" && ln -sf "/var/tmp" "${pkgdir}${_datadir}/tmp" + rm -rf "${pkgdir}${_datadir}/log" && ln -sf "${_logdir}" "${pkgdir}${_datadir}/log" + + msg2 "Install and symlink config files..." + install -Dm0644 "${srcdir}/unicorn.conf.rb" "${pkgdir}/${_etcdir}/unicorn.conf.rb" + cp "config/discourse_quickstart.conf" "config/discourse.conf" + for _file in "discourse.conf" "discourse_defaults.conf"; do + mv "config/${_file}" "${pkgdir}${_etcdir}" + ln -fs "${_etcdir}/${_file}" "${pkgdir}${_datadir}/config/" + done + + msg2 "Installing license, documentation and example files..." + mv "README.md" "CONTRIBUTING.md" "COPYRIGHT.txt" "${pkgdir}/usr/share/doc/${pkgname}" + cp ${srcdir}/*.conf.example "${pkgdir}/usr/share/doc/${pkgname}" + install -D "LICENSE.txt" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE.txt" + + msg2 "Installing systemd service files..." + install -Dm0644 "${srcdir}/discourse-unicorn.service" "${pkgdir}/${_systemddir}/discourse-unicorn.service" + install -Dm0644 "${srcdir}/discourse-sidekiq.service" "${pkgdir}/${_systemddir}/discourse-sidekiq.service" + install -Dm0644 "${srcdir}/discourse.target" "${pkgdir}/${_systemddir}/discourse.target" + install -Dm0644 "${srcdir}/discourse-update.service" "${pkgdir}/${_systemddir}/discourse-update.service" + + msg2 "Installing systemd tmpfiles.d..." + install -Dm0644 "${srcdir}/discourse.tmpfiles.d" "${pkgdir}/usr/lib/tmpfiles.d/discourse.conf" + + msg2 "Installing logrotate..." + install -Dm0644 "${srcdir}/discourse.logrotate" "${pkgdir}/etc/logrotate.d/discourse" +} diff --git a/apache-ssl.conf.example b/apache-ssl.conf.example new file mode 100644 index 000000000000..2e7bf2d3bc6e --- /dev/null +++ b/apache-ssl.conf.example @@ -0,0 +1,77 @@ +# Note this config assumes unicorn is listening on port 9737. +# Module dependencies +# mod_rewrite +# mod_ssl +# mod_proxy +# mod_proxy_http +# mod_headers + +# This section is only needed if you want to redirect http traffic to https. +# You can live without it but clients will have to type in https:// to reach discourse. +<VirtualHost *:80> + ServerName discourse.example.com + ServerSignature Off + + # Include the trailing slash! + Redirect permanent / https://discourse.example.com/ +</VirtualHost> + +<VirtualHost *:443> + SSLEngine on + # strong encryption ciphers only + # see ciphers(1) http://www.openssl.org/docs/apps/ciphers.html + SSLProtocol all -SSLv2 + SSLHonorCipherOrder on + SSLCipherSuite "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS" + Header add Strict-Transport-Security: "max-age=15768000;includeSubdomains" + SSLCompression Off + SSLCertificateFile /etc/httpd/ssl.crt/discourse.example.com.crt + SSLCertificateKeyFile /etc/httpd/ssl.key/discourse.example.com.key + SSLCACertificateFile /etc/httpd/ssl.crt/your-ca.crt + + ServerName discourse.example.com + ServerSignature Off + + ProxyPreserveHost On + + # Ensure that encoded slashes are not decoded but left in their encoded state. + # http://doc.discourse.com/ce/api/projects.html#get-single-project + AllowEncodedSlashes NoDecode + + <Location /> + # New authorization commands for apache 2.4 and up + # http://httpd.apache.org/docs/2.4/upgrading.html#access + Require all granted + + ProxyPassReverse http://127.0.0.1:9737 + ProxyPassReverse http://discourse.example.com/ + </Location> + + <LocationMatch "^/assets/.*$"> + # Set caching headers here, providing advice to downstream cache + Header set Cache-Control "public, max-age = 604800" + </LocationMatch> + + # apache equivalent of nginx try files + # http://serverfault.com/questions/290784/what-is-apaches-equivalent-of-nginxs-try-files + # http://stackoverflow.com/questions/10954516/apache2-proxypass-for-rails-app-gitlab + RewriteEngine on + RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f + RewriteRule .* http://127.0.0.1:9737%{REQUEST_URI} [P,QSA] + RequestHeader set X_FORWARDED_PROTO 'https' + + # needed for downloading attachments + DocumentRoot /usr/share/webapps/discourse/public + + # Set up apache error documents, if back end goes down an error page is thrown up. + ErrorDocument 403 /403.html + ErrorDocument 422 /422.html + ErrorDocument 500 /500.html + ErrorDocument 503 /503.html + + LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded + ErrorLog /var/log/httpd/logs/discourse.example.com_error.log + CustomLog /var/log/httpd/logs/discourse.example.com_forwarded.log common_forwarded + CustomLog /var/log/httpd/logs/discourse.example.com_access.log combined env=!dontlog + CustomLog /var/log/httpd/logs/discourse.example.com.log combined +</VirtualHost> diff --git a/apache.conf.example b/apache.conf.example new file mode 100644 index 000000000000..0b42de8da6bf --- /dev/null +++ b/apache.conf.example @@ -0,0 +1,51 @@ +# Note this config assumes unicorn is listening on default port 9737. +# Module dependencies +# mod_rewrite +# mod_proxy +# mod_proxy_http +<VirtualHost *:80> + ServerName discourse.example.com + ServerSignature Off + + ProxyPreserveHost On + + # Ensure that encoded slashes are not decoded but left in their encoded state. + # http://doc.gitlab.com/ce/api/projects.html#get-single-project + AllowEncodedSlashes NoDecode + + <Location /> + # New authorization commands for apache 2.4 and up + # http://httpd.apache.org/docs/2.4/upgrading.html#access + Require all granted + + ProxyPassReverse http://127.0.0.1:8080 + ProxyPassReverse http://discourse.example.com/ + </Location> + + <LocationMatch "^/assets/.*$"> + # Set caching headers here, providing advice to downstream cache + Header set Cache-Control "public, max-age = 604800" + </LocationMatch> + + # apache equivalent of nginx try files + # http://serverfault.com/questions/290784/what-is-apaches-equivalent-of-nginxs-try-files + # http://stackoverflow.com/questions/10954516/apache2-proxypass-for-rails-app-gitlab + RewriteEngine on + RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f + RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA] + + # needed for downloading attachments + DocumentRoot /usr/share/webapps/discourse/public + + # Set up apache error documents, if back end goes down an error page is thrown up. + ErrorDocument 403 /403.html + ErrorDocument 422 /422.html + ErrorDocument 500 /500.html + ErrorDocument 503 /503.html + + LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded + ErrorLog /var/log/httpd/logs/discourse.example.com_error.log + CustomLog /var/log/httpd/logs/discourse.example.com_forwarded.log common_forwarded + CustomLog /var/log/httpd/logs/discourse.example.com_access.log combined env=!dontlog + CustomLog /var/log/httpd/logs/discourse.example.com.log combined +</VirtualHost> diff --git a/discourse-kill.service b/discourse-kill.service new file mode 100644 index 000000000000..dae7e33b0cd0 --- /dev/null +++ b/discourse-kill.service @@ -0,0 +1,6 @@ +[Unit] +Description=Workaround for unicorn eating memory + +[Service] +Type=oneshot +ExecStart=/usr/bin/systemctl try-restart discourse-unicorn.service discourse-sidekiq.service diff --git a/discourse-kill.timer b/discourse-kill.timer new file mode 100644 index 000000000000..8f44fce51d2c --- /dev/null +++ b/discourse-kill.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Trigger for daily discourse RAM cleanup + +[Timer] +OnCalendar=daily +Persistent=true + +[Install] +WantedBy=timer.target diff --git a/discourse-sidekiq.service b/discourse-sidekiq.service new file mode 100644 index 000000000000..ab4618b31b06 --- /dev/null +++ b/discourse-sidekiq.service @@ -0,0 +1,26 @@ +[Unit] +Description=Discourse Sidekiq Worker +Requires=redis.service +After=redis.service network.target + +[Service] +User=discourse +Group=discourse +SyslogIdentifier=discourse-sidekiq +WorkingDirectory=/usr/share/webapps/discourse +Environment=RAILS_ENV=production RUBY_GC_MALLOC_LIMIT=90000000 + +CapabilityBoundingSet= +PrivateTmp=true +PrivateDevices=true +ProtectSystem=full +ProtectHome=true +# NoNewPrivileges breaks discourse's email delivery if you +# use postfix' sendmail wrapper. If you use an SMTP server +# instead you can safely enable this security feature. +# NoNewPrivileges=true + +ExecStart=/usr/bin/bundle exec "sidekiq -e production -L /var/log/discourse/sidekiq.log >> /var/log/discourse/sidekiq.log 2>&1" + +[Install] +WantedBy=multi-user.target diff --git a/discourse-unicorn.service b/discourse-unicorn.service new file mode 100644 index 000000000000..3c51a000cebb --- /dev/null +++ b/discourse-unicorn.service @@ -0,0 +1,26 @@ +[Unit] +Description=Discourse Unicorn Server +Requires=redis.service +After=redis.service network.target + +[Service] +User=discourse +Group=discourse +SyslogIdentifier=discourse-unicorn +WorkingDirectory=/usr/share/webapps/discourse +PIDFile=/run/discourse/unicorn.pid +Environment=RAILS_ENV=production RUBY_GC_MALLOC_LIMIT=90000000 +RuntimeDirectory=discourse +RuntimeDirectoryMode=775 + +CapabilityBoundingSet= +PrivateTmp=true +PrivateDevices=true +ProtectSystem=full +ProtectHome=true +NoNewPrivileges=true + +ExecStart=/usr/bin/bundle exec "unicorn_rails -c /etc/webapps/discourse/unicorn.conf.rb -E production" + +[Install] +WantedBy=multi-user.target diff --git a/discourse-update.service b/discourse-update.service new file mode 100644 index 000000000000..49f611487d37 --- /dev/null +++ b/discourse-update.service @@ -0,0 +1,18 @@ +[Unit] +Description=Discourse Update + +[Service] +Type=oneshot +User=discourse +Group=discourse +SyslogIdentifier=discourse-update +WorkingDirectory=/usr/share/webapps/discourse +Environment=RAILS_ENV=production + +CapabilityBoundingSet= +PrivateTmp=true +PrivateDevices=true +ProtectHome=true +NoNewPrivileges=true + +ExecStart=/usr/bin/bundle exec rake db:migrate assets:clean assets:precompile diff --git a/discourse.install b/discourse.install new file mode 100644 index 000000000000..db3e54d6e0c2 --- /dev/null +++ b/discourse.install @@ -0,0 +1,24 @@ +_homedir="/var/lib/discourse" +_datadir="/usr/share/webapps/discourse" + +fix_perms() { + chown -R discourse:discourse "${_homedir}" +} + +post_install() { + groupadd discourse &>/dev/null + useradd -d "${_homedir}" -g discourse -s /bin/bash discourse &>/dev/null + systemd-tmpfiles --create discourse.conf + fix_perms + echo "You have to configure few things." + echo "Configure the application in /etc/webapps/discourse/discourse.config and run:" + echo "sudo -u discourse -s /usr/bin/bash -c \"cd ${_datadir}; bundle exec rake discourse:setup RAILS_ENV=production\"" +} + +post_upgrade() { + systemd-tmpfiles --create discourse.conf + fix_perms + echo "The database may need to be migrated to reflect the latest changes in the application" + echo "Running 'systemctl start discourse-update.service'; it may take a few minutes." + systemctl start discourse-update.service +} diff --git a/discourse.logrotate b/discourse.logrotate new file mode 100644 index 000000000000..a3631d159e42 --- /dev/null +++ b/discourse.logrotate @@ -0,0 +1,8 @@ +/var/log/discourse/*.log { + daily + missingok + rotate 90 + compress + notifempty + copytruncate +} diff --git a/discourse.target b/discourse.target new file mode 100644 index 000000000000..92c5e59bf4bb --- /dev/null +++ b/discourse.target @@ -0,0 +1,6 @@ +[Unit] +Description=Discourse - A simple, flat forum +Wants=discourse-unicorn.service discourse-sidekiq.service + +[Install] +WantedBy=multi-user.target diff --git a/discourse.tmpfiles.d b/discourse.tmpfiles.d new file mode 100644 index 000000000000..81cd23c570a2 --- /dev/null +++ b/discourse.tmpfiles.d @@ -0,0 +1 @@ +d /var/log/discourse 0750 discourse discourse - diff --git a/nginx-ssl.conf.example b/nginx-ssl.conf.example new file mode 100644 index 000000000000..cbb198086b5b --- /dev/null +++ b/nginx-ssl.conf.example @@ -0,0 +1,142 @@ +## GitLab +## Contributors: randx, yin8086, sashkab, orkoden, axilleas +## +## Modified from nginx http version +## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/ +## Modified from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html +## +## Lines starting with two hashes (##) are comments with information. +## Lines starting with one hash (#) are configuration parameters that can be uncommented. +## +################################## +## CHUNKED TRANSFER ## +################################## +## +## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] +## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object +## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get +## around this by tweaking this configuration file and either: +## - installing an old version of Nginx with the chunkin module [2] compiled in, or +## - using a newer version of Nginx. +## +## At the time of writing we do not know if either of these theoretical solutions works. +## As a workaround users can use Git over SSH to push large files. +## +## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99 +## [1] https://github.com/agentzh/chunkin-nginx-module#status +## [2] https://github.com/agentzh/chunkin-nginx-module +## +## +################################### +## SSL configuration ## +################################### +## +## See installation.md#using-https for additional HTTPS configuration details. + +upstream gitlab { + server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; +} + +## Normal HTTP host +server { + listen *:80 default_server; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com + server_tokens off; ## Don't show the nginx version number, a security best practice + + ## Redirects all traffic to the HTTPS host + root /nowhere; ## root doesn't have to be a valid path since we are redirecting + rewrite ^ https://$server_name$request_uri? permanent; +} + +## HTTPS host +server { + listen 443 ssl; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com + server_tokens off; + root /home/git/gitlab/public; + + ## Increase this if you want to upload large attachments + ## Or if you want to accept large git objects over http + client_max_body_size 20m; + + ## Strong SSL Security + ## https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html & https://cipherli.st/ + ssl on; + ssl_certificate /etc/nginx/ssl/gitlab.crt; + ssl_certificate_key /etc/nginx/ssl/gitlab.key; + + # GitLab needs backwards compatible ciphers to retain compatibility with Java IDEs + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + + ## [WARNING] The following header states that the browser should only communicate + ## with your server over a secure connection for the next 24 months. + add_header Strict-Transport-Security max-age=63072000; + add_header X-Frame-Options SAMEORIGIN; + add_header X-Content-Type-Options nosniff; + + ## [Optional] If your certficate has OCSP, enable OCSP stapling to reduce the overhead and latency of running SSL. + ## Replace with your ssl_trusted_certificate. For more info see: + ## - https://medium.com/devops-programming/4445f4862461 + ## - https://www.ruby-forum.com/topic/4419319 + ## - https://www.digitalocean.com/community/tutorials/how-to-configure-ocsp-stapling-on-apache-and-nginx + # ssl_stapling on; + # ssl_stapling_verify on; + # ssl_trusted_certificate /etc/nginx/ssl/stapling.trusted.crt; + # resolver 208.67.222.222 208.67.222.220 valid=300s; # Can change to your DNS resolver if desired + # resolver_timeout 5s; + + ## [Optional] Generate a stronger DHE parameter: + ## sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096 + ## + # ssl_dhparam /etc/ssl/certs/dhparam.pem; + + ## Individual nginx logs for this GitLab vhost + access_log /var/log/nginx/gitlab_access.log; + error_log /var/log/nginx/gitlab_error.log; + + location / { + ## Serve static files from defined root folder. + ## @gitlab is a named location for the upstream fallback, see below. + try_files $uri $uri/index.html $uri.html @gitlab; + } + + ## If a file, which is not found in the root folder is requested, + ## then the proxy passes the request to the upsteam (gitlab unicorn). + location @gitlab { + ## If you use HTTPS make sure you disable gzip compression + ## to be safe against BREACH attack. + gzip off; + + ## https://github.com/gitlabhq/gitlabhq/issues/694 + ## Some requests take more than 30 seconds. + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_redirect off; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Ssl on; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + + proxy_pass http://gitlab; + } + + ## Enable gzip compression as per rails guide: + ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression + ## WARNING: If you are using relative urls remove the block below + ## See config/application.rb under "Relative url support" for the list of + ## other files that need to be changed for relative url support + location ~ ^/(assets)/ { + root /home/git/gitlab/public; + gzip_static on; # to serve pre-gzipped version + expires max; + add_header Cache-Control public; + } + + error_page 502 /502.html; +} diff --git a/nginx.conf.example b/nginx.conf.example new file mode 100644 index 000000000000..6357dc8fa468 --- /dev/null +++ b/nginx.conf.example @@ -0,0 +1,90 @@ +## GitLab +## Maintainer: @randx +## +## Lines starting with two hashes (##) are comments with information. +## Lines starting with one hash (#) are configuration parameters that can be uncommented. +## +################################## +## CHUNKED TRANSFER ## +################################## +## +## It is a known issue that Git-over-HTTP requires chunked transfer encoding [0] +## which is not supported by Nginx < 1.3.9 [1]. As a result, pushing a large object +## with Git (i.e. a single large file) can lead to a 411 error. In theory you can get +## around this by tweaking this configuration file and either: +## - installing an old version of Nginx with the chunkin module [2] compiled in, or +## - using a newer version of Nginx. +## +## At the time of writing we do not know if either of these theoretical solutions works. +## As a workaround users can use Git over SSH to push large files. +## +## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99 +## [1] https://github.com/agentzh/chunkin-nginx-module#status +## [2] https://github.com/agentzh/chunkin-nginx-module +## +################################### +## configuration ## +################################### +## + +upstream gitlab { + server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0; +} + +## Normal HTTP host +server { + listen *:80 default_server; + server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com + server_tokens off; ## Don't show the nginx version number, a security best practice + root /home/git/gitlab/public; + + ## Increase this if you want to upload large attachments + ## Or if you want to accept large git objects over http + client_max_body_size 20m; + + ## Individual nginx logs for this GitLab vhost + access_log /var/log/nginx/gitlab_access.log; + error_log /var/log/nginx/gitlab_error.log; + + location / { + ## Serve static files from defined root folder. + ## @gitlab is a named location for the upstream fallback, see below. + try_files $uri $uri/index.html $uri.html @gitlab; + } + + ## If a file, which is not found in the root folder is requested, + ## then the proxy passes the request to the upsteam (gitlab unicorn). + location @gitlab { + ## If you use HTTPS make sure you disable gzip compression + ## to be safe against BREACH attack. + # gzip off; + + ## https://github.com/gitlabhq/gitlabhq/issues/694 + ## Some requests take more than 30 seconds. + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_redirect off; + + 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; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Frame-Options SAMEORIGIN; + + proxy_pass http://gitlab; + } + + ## Enable gzip compression as per rails guide: + ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression + ## WARNING: If you are using relative urls remove the block below + ## See config/application.rb under "Relative url support" for the list of + ## other files that need to be changed for relative url support + location ~ ^/(assets)/ { + root /home/git/gitlab/public; + gzip_static on; # to serve pre-gzipped version + expires max; + add_header Cache-Control public; + } + + error_page 502 /502.html; +} diff --git a/unicorn.conf.rb b/unicorn.conf.rb new file mode 100644 index 000000000000..e3e605833f8e --- /dev/null +++ b/unicorn.conf.rb @@ -0,0 +1,114 @@ +# enable out of band gc out of the box, it is low risk and improves perf a lot +ENV['UNICORN_ENABLE_OOBGC'] ||= "1" + +# Use at least one worker per core if you're on a dedicated server, +# more will usually help for _short_ waits on databases/caches. +worker_processes 2 + +# Since Unicorn is never exposed to outside clients, it does not need to +# run on the standard HTTP port (80), there is no reason to start Unicorn +# as root unless it's from system init scripts. +# If running the master process as root and the workers as an unprivileged +# user, do this to switch euid/egid in the workers (also chowns logs): +# user "unprivileged_user", "unprivileged_group" + +# Help ensure your application will always spawn in the symlinked +# "current" directory that Capistrano sets up +working_directory '/usr/share/webapps/discourse' # available in 0.94.0+ + +# Listen on both a Unix domain socket and a TCP port. +# If you are load-balancing multiple Unicorn masters, lower the backlog +# setting to e.g. 64 for faster failover. +#listen "/var/run/discourse/discourse.socket", :backlog => 1024 +listen "127.0.0.1:9737", :tcp_nopush => true + +# nuke workers after 30 seconds instead of 60 seconds (the default) +timeout 30 + +# feel free to point this anywhere accessible on the filesystem +pid '/run/discourse/unicorn.pid' + +# By default, the Unicorn logger will write to stderr. +# Additionally, some applications/frameworks log to stderr or stdout, +# so prevent them from going to /dev/null when daemonized here: +stderr_path '/var/log/discourse/unicorn.stderr.log' +stdout_path '/var/log/discourse/unicorn.stdout.log' + +# combine Ruby 2.0.0dev or REE with "preload_app true" for memory savings +# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow +preload_app true + +# If 'UNICORN_ENABLE_OOBGC' is unset let's use GC.copy_on_write_friendly = true. +# http://unicorn.bogomips.org/Unicorn/Configurator.html +unless ENV['UNICORN_ENABLE_OOBGC'] + GC.respond_to?(:copy_on_write_friendly=) and + GC.copy_on_write_friendly = true +end + +# Enable this flag to have unicorn test client connections by writing the +# beginning of the HTTP headers before calling the application. This +# prevents calling the application for connections that have disconnected +# while queued. This is only guaranteed to detect clients on the same +# host unicorn runs on, and unlikely to detect disconnects even on a +# fast LAN. +check_client_connection false + +# local variable to guard against running a hook multiple times +run_once = true + +before_fork do |server, worker| + # Occasionally, it may be necessary to run non-idempotent code in the + # master before forking. Keep in mind the above disconnect! example + # is idempotent and does not need a guard. + if run_once + # load up the yaml for the localization bits, in master process + I18n.t(:posts) + + # load up all models and schema + (ActiveRecord::Base.connection.tables - %w[schema_migrations]).each do |table| + table.classify.constantize.first rescue nil + end + + # router warm up + Rails.application.routes.recognize_path('abc') rescue nil + + # get rid of rubbish so we don't share it + GC.start + + run_once = false # prevent from firing again + end + + # the following is highly recomended for Rails + "preload_app true" + # as there's no need for the master process to hold a connection + defined?(ActiveRecord::Base) and + ActiveRecord::Base.connection.disconnect! + $redis.client.disconnect + + # The following is only recommended for memory/DB-constrained + # installations. It is not needed if your system can house + # twice as many worker_processes as you have configured. + # + # This allows a new master process to incrementally + # phase out the old master process with SIGTTOU to avoid a + # thundering herd (especially in the "preload_app false" case) + # when doing a transparent upgrade. The last worker spawned + # will then kill off the old master process with a SIGQUIT. + old_pid = "#{server.config[:pid]}.oldbin" + if old_pid != server.pid + begin + sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU + Process.kill(sig, File.read(old_pid).to_i) + rescue Errno::ENOENT, Errno::ESRCH + end + end + + # Throttle the master from forking too quickly by sleeping. Due + # to the implementation of standard Unix signal handlers, this + # helps (but does not completely) prevent identical, repeated signals + # from being lost when the receiving process is busy. + sleep 1 +end + +after_fork do |server, worker| + Discourse.after_fork +end |