Setting Up Redmine on BESTNET-CLOUD

Setting Up Redmine on BESTNET-CLOUD

This article outlines the steps to build Redmine on an Ubuntu 24.04 LTS virtual machine provisioned on BESTNET-CLOUD,
through to the point where you can log in from a browser for the first time.

LDAP/LDAPS integration, external SMTP, and Zabbix integration will be covered in separate articles that follow.
This guide focuses on completing a stable Redmine server that can display the login screen reliably.

Goal for This Guide #

Endpoint #

Redmine login screen displays over HTTPS and you can log in as administrator for the first time.

Scope This Time #

OS initial setup, Redmine deployment, DB initialization, Apache + Passenger, and self-signed SSL.

Next Steps #

AD / LDAPS, external SMTP, Zabbix agent deployment, and monitoring integration will be handled separately.

Architecture Overview #

OS Ubuntu Server 24.04 LTS
Web/AP Apache + Passenger
DB PostgreSQL
Redmine 6.1.1
Ruby Ruby 3.2 series included with Ubuntu 24.04
Publication Method 80 → 443 redirect, 443 listens with self-signed certificate
Deployment Location /opt/redmine/releases/redmine-6.1.1
Note:
This article uses self-signed certificates for ease of verification.
For production environments, we recommend replacing with commercial or internal CA certificates.

Step 1. OS Update and Installation of Required Packages #

First, update the OS to the latest version and install packages needed for Redmine build and PostgreSQL connection together.
Be sure to include libyaml-dev.

sudo apt update
sudo apt full-upgrade -y

sudo apt install -y \
  build-essential \
  ruby-full ruby-dev bundler \
  zlib1g-dev libpq-dev libyaml-dev pkg-config \
  postgresql postgresql-contrib \
  apache2 apache2-dev \
  imagemagick ghostscript \
  curl ca-certificates gnupg dirmngr apt-transport-https \
  ldap-utils tar

Step 2. Passenger Installation #

Add the official Passenger repository and install it as an Apache module.

curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key-2025.txt \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null

echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger noble main" \
  | sudo tee /etc/apt/sources.list.d/passenger.list

sudo apt update
sudo apt install -y passenger libapache2-mod-passenger

sudo a2enmod passenger
sudo a2enconf servername
echo "ServerName rdm.bestnetllc.co.jp" | sudo tee /etc/apache2/conf-available/servername.conf

sudo apache2ctl configtest
sudo systemctl reload apache2

Verify operation with the following:

sudo /usr/bin/passenger-config validate-install
sudo /usr/sbin/passenger-memory-stats

Step 3. Preparation of Redmine User and Deployment Directory #

Deploy using the releases directory method to make upgrades easier.

sudo adduser --system --group --home /opt/redmine --shell /bin/bash redmine

sudo mkdir -p /opt/redmine/releases
sudo chown -R redmine:redmine /opt/redmine

Step 4. PostgreSQL Setup #

Create a dedicated role and database for Redmine.

sudo -u postgres psql
CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD '<DB_PASSWORD>' NOINHERIT VALID UNTIL 'infinity';
CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
\q

Step 5. Redmine Source Code Deployment #

This example uses version 6.1.1. Adjust as needed for maintenance releases.

cd /tmp
curl -L -o redmine-6.1.1.tar.gz https://www.redmine.org/releases/redmine-6.1.1.tar.gz

sudo -u redmine tar xzf redmine-6.1.1.tar.gz -C /opt/redmine/releases
sudo ln -sfn /opt/redmine/releases/redmine-6.1.1 /opt/redmine/current

Step 6. database.yml Configuration #

This is a common pitfall. Keep only the PostgreSQL definition and remove the MySQL sample.

cd /opt/redmine/releases/redmine-6.1.1

sudo tee config/database.yml > /dev/null <<'EOF'
production:
  adapter: postgresql
  database: redmine
  host: localhost
  username: redmine
  password: "<DB_PASSWORD>"
  encoding: utf8
  schema_search_path: public
EOF

Also prepare configuration.yml for encryption keys.

sudo -u redmine cp config/configuration.yml.example config/configuration.yml
default:
  database_cipher_key: "<LONG_RANDOM_STRING>"

production:

Step 7. bundle install and Database Initialization #

Execute gem installation, secret generation, database migration, and initial data loading.

sudo chown -R redmine:redmine /opt/redmine

sudo -u redmine -H bash -lc '
  cd /opt/redmine/releases/redmine-6.1.1
  rm -rf vendor/bundle
  bundle config set --local path vendor/bundle
  bundle config set --local without "development test"
  bundle install
  bundle exec rake generate_secret_token
  RAILS_ENV=production bundle exec rake db:migrate
  RAILS_ENV=production REDMINE_LANG=ja bundle exec rake redmine:load_default_data
'
Note:
If you see yaml.h not found, libyaml-dev is missing.
If mysql2 appears in the bundle targets, MySQL configuration
likely remains in config/database.yml.

Step 8. Self-Signed Certificate Creation #

This example creates a self-signed certificate with CA:FALSE and SAN.
This approach avoids excessive browser and Apache warnings compared to older methods.

sudo mkdir -p /etc/apache2/ssl

sudo tee /tmp/rdm-openssl.cnf > /dev/null <<'EOF'
[req]
default_bits = 4096
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C  = JP
ST = Tokyo
L  = Tokyo
O  = BestNetLLC
OU = IT
CN = rdm.bestnetllc.co.jp

[v3_req]
basicConstraints = critical,CA:FALSE
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = rdm.bestnetllc.co.jp
EOF

sudo openssl req -x509 -nodes -newkey rsa:4096 -sha256 -days 3650 \
  -keyout /etc/apache2/ssl/rdm.bestnetllc.co.jp.key \
  -out /etc/apache2/ssl/rdm.bestnetllc.co.jp.crt \
  -config /tmp/rdm-openssl.cnf

sudo chmod 600 /etc/apache2/ssl/rdm.bestnetllc.co.jp.key
sudo chmod 644 /etc/apache2/ssl/rdm.bestnetllc.co.jp.crt

Step 9. Apache VirtualHost Configuration #

Port 80 redirects to 443, and port 443 sets Redmine’s public directory as DocumentRoot.
Using the actual path directly avoids symlink-induced 403 errors.

sudo a2enmod ssl rewrite headers

sudo tee /etc/apache2/sites-available/redmine.conf > /dev/null <<'EOF'
<VirtualHost *:80>
    ServerName rdm.bestnetllc.co.jp
    RewriteEngine On
    RewriteRule ^/(.*)$ https://rdm.bestnetllc.co.jp/$1 [R=301,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName rdm.bestnetllc.co.jp
    DocumentRoot /opt/redmine/releases/redmine-6.1.1/public

    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/rdm.bestnetllc.co.jp.crt
    SSLCertificateKeyFile /etc/apache2/ssl/rdm.bestnetllc.co.jp.key

    PassengerRuby /usr/bin/ruby
    PassengerAppEnv production

    <Directory /opt/redmine/releases/redmine-6.1.1/public>
        Options FollowSymLinks
        AllowOverride all
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/redmine_ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/redmine_ssl_access.log combined
</VirtualHost>
EOF

sudo a2ensite redmine
sudo a2dissite 000-default
sudo a2dissite default-ssl

sudo apache2ctl configtest
sudo systemctl reload apache2

Step 10. Permission Adjustment and Restart #

Grant execute permission on the parent directories as well, so that Apache can reach the Redmine directory tree.

sudo chmod 755 /opt
sudo chmod 755 /opt/redmine
sudo chmod 755 /opt/redmine/releases
sudo chmod 755 /opt/redmine/releases/redmine-6.1.1
sudo chmod 755 /opt/redmine/releases/redmine-6.1.1/public

sudo -u redmine mkdir -p /opt/redmine/releases/redmine-6.1.1/tmp/pdf
sudo -u redmine mkdir -p /opt/redmine/releases/redmine-6.1.1/public/assets

sudo touch /opt/redmine/releases/redmine-6.1.1/tmp/restart.txt
sudo systemctl restart apache2

Step 11. Initial Access Verification #

First, verify local connectivity.

curl -kI https://127.0.0.1/
openssl s_client -connect 127.0.0.1:443 -servername rdm.bestnetllc.co.jp </dev/null

In a browser, access https://rdm.bestnetllc.co.jp.
Because the certificate is self-signed, the browser will show a warning, but if the Redmine login screen is displayed, the setup was successful.

Initial Login:
Username admin / Password admin

After the first login, change the administrator password immediately,
and in Redmine’s “Administration → Settings → General”, update the host name and set the protocol to https accordingly.

Common Pitfalls During Setup #

1. GPG Error with the Passenger Repository #

Using an old key URL may result in a NO_PUBKEY error.
Standardizing on the new official key file usually resolves this.

2. Psych Build Fails with yaml.h not found #

In many cases, libyaml-dev is missing.
Add the OS package, then rerun bundle install.

3. mysql2 Appears in the Bundle Targets #

This tends to happen when the MySQL sample definition remains in config/database.yml.
Trimming it down to only the production definition for PostgreSQL resolves the issue.

4. ERR_SSL_PROTOCOL_ERROR Occurs #

In some cases, the VirtualHost for 443 is not enabled, or another site is still enabled.
Checking the enabled vhosts with apache2ctl -S makes it easier to isolate the cause.

5. 403 Forbidden Is Returned #

Access via the current symbolic link can run into permission issues.
Specifying the actual path directly as DocumentRoot and granting search permission from /opt downward usually improves the situation.

Summary #

With the steps above, you can build a Redmine server on BESTNET-CLOUD with an Ubuntu 24.04 / Apache + Passenger / PostgreSQL configuration
and reach the point where you can log in for the first time over HTTPS.

  • Deployment of Redmine itself is complete
  • Connection to PostgreSQL succeeds
  • The application starts on Apache + Passenger
  • Port 443 listens with the self-signed certificate
  • The login screen is displayed in the browser

In the next article, we will move on to AD / LDAPS authentication, external SMTP, and monitoring integration with Zabbix.

© BestNet Tech Blog

Updated on 2026/10/14

What are your feelings

  • Happy
  • Normal
  • Sad

©2020 BESTNET.LLC . All Rights Reserved.