Installing OpenProject on FreeBSD
At work we want to run OpenProject. But since this a ruby-on-rails app and installation on Windows is not supported, I volunteered to set up a dedicated FreeBSD server for it.
Server
The server install was a basic FreeBSD 10 install done via the memory stick
image. On the harddisk I created a 50 GB root partition and 8 GB swap. The
rest of the disk was made into a data
partition.
Since you will generally log into a server via ssh, you can use long random passwords for the accounts on the server. I use a script to read data from the random device and convert it into something readable with base64. This will yield passwords like “yX5iD8FSpUdgy0Pu” or “4JYMnC4zxXsK_pZR”. Keep them in an encrypted file on your workstation so you can copy/paste them into ssh.
After the usual configuration, I installed an up to date ports tree using the built-in svnlite.
> su
# rm -rf /usr/ports/*
# svnlite checkout https://svn0.eu.FreeBSD.org/ports/head /usr/ports
After this initial checkout, keeping the ports tree up to date is simple;
# svnlite update /usr/ports
With the ports tree in place, the following programs have been installed;
- vim from
/usr/ports/editors/vim
- rsync from
/usr/ports/net/rsync
- git from
/usr/ports/devel/git
- nginx from
/usr/ports/www/nginx
- ruby 2.1 from
/usr/ports/lang/ruby21
- ruby-gems from
/usr/ports/devel/ruby-gems
- postgresql 9.3 server from
/usr/ports/databases/postgresql93-server
- gcc 4.7 from
/usr/ports/lang/gcc/
- sqlite 3.8 from
/usr/ports/databases/sqlite3
- npm 1.4 from
/usr/ports/www/npm
- ImageMagick 6.8 from
/usr/ports/graphics/ImageMagick-nox11
The installation of all ports goes much the same;
# cd /usr/ports/net/rsync
# make install clean
Before installing ruby-gems, the following needs to be set in
/etc/make.conf
;
DEFAULT_VERSIONS= ruby=2.1
Otherwise installing ruby-gems will start installing the default ruby 1.9.
After installing gcc 4.7, the g++47 and gcc executables are linked to g++ and gcc respectively.
When installing npm you should not choose node-devel (that gives v0.11, we need v0.10).
The ImageMagick port depends on ghostscript. In the ghostscript I disabled all the printer models and left in the different bitmap and vector formats.
Preparing OpenProject
The data and software for openproject will be installed on the /data
parition.
When postgresql was installed, a postgresql user named pgsql
was created
automatically. I set a long randomly generated password for this user. But you
can set *
as the password and use /usr/sbin/nologin
as the shell. This
prevents ordinary logins as this user. But root
can still use su -m
to
assume this identity.
We will now create the directories for the database and for openproject.
# mkdir /data/pgsql
# chown pgsql:pgsql /data/pgsql
# chmod 700 /data/pgsql
For openproject we will first create a user, and then create a directory owned by that user;
# pw useradd openproject -c "OpenProject user" -d /data/openproject -h 0
# mkdir /data/openproject
# chown openproject:openproject /data/openproject
# chmod 755 /data/openproject
The password for the openproject user is set to a long random one.
After ruby and ruby-gems were installed, I installed bundler
;
# gem install bundler --version '>=1.5.1'
Fetching: bundler-1.6.2.gem (100%)
Successfully installed bundler-1.6.2
1 gem installed
Installing ri documentation for bundler-1.6.2...
Installing RDoc documentation for bundler-1.6.2...
The following settings were added to /etc/rc.conf
to enable the postgresql server;
postgresql_enable="YES"
postgresql_data="/data/pgsql"
postgresql_flags="-w -s -m fast"
postgresql_initdb_flags="--encoding=utf-8 --lc-collate=C"
postgresql_class="default"
postgresql_profiles=""
Additionally, we need to initialze the database;
# service postgresql initdb
The files belonging to this database system will be owned by user "pgsql".
This user must also own the server process.
The database cluster will be initialized with locales
COLLATE: C
CTYPE: en_US.UTF-8
MESSAGES: en_US.UTF-8
MONETARY: en_US.UTF-8
NUMERIC: en_US.UTF-8
TIME: en_US.UTF-8
The default text search configuration will be set to "english".
Data page checksums are disabled.
fixing permissions on existing directory /data/pgsql ... ok
creating subdirectories ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
creating configuration files ... ok
creating template1 database in /data/pgsql/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects descriptions ... ok
creating collations ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
loading PL/pgSQL server-side language ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok
syncing data to disk ... ok
WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
Success. You can now start the database server using:
/usr/local/bin/postgres -D /data/pgsql
or
/usr/local/bin/pg_ctl -D /data/pgsql -l logfile start
After these changes the service was started using the new FreeBSD way;
# service postgresql start
According to the openproject installation instructions, I created the databases (the password used here is obviously not the real one);
# su - pgsql
$ createdb -O pgsql openproject
$ createdb -O pgsql openproject_test
$ createdb -O pgsql openproject_development
$ psql openproject
psql (9.3.4)
Type "help" for help.
openproject=# create role openproject login encrypted password 'W_PlqQbNHD28cm1c' noinherit valid until 'infinity';
CREATE ROLE
openproject-# \q
$ exit
Now it is time to install OpenProject itself. From here on, commands prefixed
with $
are carried out as the user openproject
.
# cd /data
# git clone https://github.com/opf/openproject.git
Cloning into '.'...
remote: Reusing existing pack: 139758, done.
remote: Counting objects: 36, done.
remote: Compressing objects: 100% (35/35), done.
remote: Total 139794 (delta 12), reused 0 (delta 0)
Receiving objects: 100% (139794/139794), 46.37 MiB | 1.25 MiB/s, done.
Resolving deltas: 100% (100180/100180), done.
Checking connectivity... done.
# chown -R openproject:openproject openproject/
Now we need to check out the latest release;
# su - openproject
$ git checkout stable
$ exit
Next is installing the necessary configuration files from the repository that
I created for it. The deploy
program checks if a file is out of date and
installs it when necessary.
# cd /home/rsmith/openproject-setup/
# ./deploy install
File 'op/Gemfile.plugins' was successfully installed as '/data/openproject/Gemfile.plugins'.
File 'op/configuration.yml' was successfully installed as '/data/openproject/config/configuration.yml'.
File 'op/database.yml' was successfully installed as '/data/openproject/config/database.yml'.
In the /data/openproject
directory we create a Gemfile.plugins
to
contain the plugins that we want to use;
# Required for each plug-in
gem "openproject-plugins", :git => "https://github.com/opf/openproject-plugins.git", :branch => "stable"
# Allow adding documents to projects
gem 'openproject-documents', :git => 'https://github.com/opf/openproject-documents.git', :branch => 'stable'
The openproject framework needs some javascript tools as well;
# npm -g install bower
# su - openproject
$ npm install
$ bower install
Next we need to install some gems;
# cd /data/openproject
# bundle install --without mysql --without mysql2
From the gems that are installed it seems that openproject is running the “thin” webserver.
Since we already created the databases earlier, we can now seed it, and create the secret token for the session store, and precompile the assets;
# su - openproject
$ env RAILS_ENV=production bundle exec rake db:create:all
$ env RAILS_ENV=production bundle exec rake generate_secret_token
$ env RAILS_ENV=production bundle exec rake db:migrate db:seed
$ env RAILS_ENV=production bundle exec rake assets:precompile
Now we should be able to run the rails server;
$ env RAILS_ENV=production bundle exec rails server
require 'rails/all'... 0.672s
Bundler.require... 2.000s
=> Booting Thin
=> Rails 3.2.18 application starting in production on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Application.initialize!... [deprecated] I18n.enforce_available_locales will default to true in the future. If you really want to skip validation of your locale you can set I18n.enforce_available_locales = false to avoid this message.
/usr/local/lib/ruby/gems/2.1/gems/svg-graph-1.0.5/lib/SVG/Graph/Graph.rb:3: warning: class variable access from toplevel
3.992s
>> Thin web server (v1.5.1 codename Straight Razor)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:3000, CTRL+C to stop
This will start the server listening on port 3000.
A production server only produces the dynamic content. The site also
requires static content like
/assets/favicon-ecd67ccc017223d35746687df7b5de89.ico
. This file is located
in
/data/openproject/public/assets/favicon-ecd67ccc017223d35746687df7b5de89.ico
.
So the root directory for the static content webserver is
/data/openproject/public
. We will be using the nginx web server.
Normally the server is run as the user www
. nginx requires a place to
store its log files. This is configured as the directory /var/log/nginx
;
# mkdir /var/log/nginx
# chown www:www /var/log/nginx
For testing purposes, the nginx server can now be started with;
# service nginx onestart
Performing sanity check on nginx configuration:
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
Starting nginx.
With this, the system seems to work. Yay!
To start OpenProject at boot, a FreeBSD rc script was written;
!/bin/sh
# vim:fileencoding=utf-8:ft=sh
# Restart commands for OpenProject
#
# Author: R.F. Smith <rsmith@xs4all.nl>
# Created: 2014-05-25 19:22:47 +0200
# $Date: 2014-05-25 22:22:27 +0200 $
# $Revision: bef6b1b $
# PROVIDE: openproject
# REQUIRE: postgresql nginx
# KEYWORD: shutdown
. /etc/rc.subr
name="openproject"
rcvar=openproject_enable
start_cmd="op_start"
stop_cmd="op_stop"
PID=/tmp/pids/server.pid
op_start()
{
CMD="cd /data/openproject; bundle exec rails server -d -e production -P $PID"
if [ ! -e $PID ]; then
su -m openproject -c "$CMD"
echo "Started OpenProject server."
else
echo "OpenProject already running."
fi
}
op_stop()
{
if [ -e $PID ]; then
kill `cat $PID`
else
echo "OpenProject not running."
fi
}
load_rc_config $name
run_rc_command "$1"
And the services that need starting are listed in rc.conf;
# file: rc.conf
# vim:fileencoding=utf-8
# Restart commands for openproject.vfi.local
#
# Author: R.F. Smith <rsmith@xs4all.nl>
# Created: 2014-05-10 22:20:05 +0200
# Modified: $Date: 2014-05-15 02:08:32 +0200 $
hostname="openproject.vfi.local"
ifconfig_em0="DHCP"
sshd_enable="YES"
powerd_enable="YES"
# Set dumpdev to "AUTO" to enable crash dumps, "NO" to disable
dumpdev="AUTO"
postgresql_enable="YES"
postgresql_data="/data/pgsql"
postgresql_flags="-w -s -m fast"
postgresql_initdb_flags="--encoding=utf-8 --lc-collate=C"
postgresql_class="default"
postgresql_profiles=""
powerd_enable="YES"
powerd_flags="-n hiadaptive -a hiadaptive"
sendmail_enable="NONE"
sysvipc_enable="YES"
nginx_enable="YES"
openproject_enable="YES"
Using the web interface I logged in as administrator, and created a new administrator ID for myself, and non-administrator user-IDs for the other users.
For comments, please send me an e-mail.
Related articles
- Writing speed on FreeBSD 13.1-p2 amd64 with ZFS
- FreeBSD 13.1 install on a Lenovo IdeaPad 5
- Gnumeric build fix for FreeBSD
- Writing speed on FreeBSD 12.1-STABLE amd64
- Cleaning up old port configurations