
Redmine を Windows 上で運用していると、サーバー起動用のコマンドを毎回実行するのは面倒ですし、OS 再起動時に自動で立ち上がらないのも不便です。
本記事では、Puma + win32-service を利用して Redmine 6 を Windows サービスとして登録し、GUI や sc コマンドから開始・停止できるようにする手順をまとめます。
1. 参考 URL
以下ページを参考にしています。
https://www.redmine.org/projects/redmine/wiki/HowTo_run_Redmine_as_a_Windows_service_(win32-service_+_taskill_approach)
2. 前提環境
以下環境を前提としています。
| OS | Windows 11 (25H2) | |
|---|---|---|
| Redmine | 6.1.0 | |
| Redmine のインストール場所 | C:\redmine | |
| Ruby | RubyInstaller-DevKit 3.4.6-1 (x64) | |
| PostgreSQL | 18.0 | |
| Web サーバ | Puma |
■ 起動コマンド
PowerShell で以下コマンドでRedmine を起動している環境で確認しました。
$env:RAILS_RELATIVE_URL_ROOT="/redmine" bundle exec puma -C config/puma.rb
以下ページで構築している環境です。
・ Windows 11 (25H2) に Redmine 6.1.0 をインストール(Ruby 3.4 + PostgreSQL 18) - PokuG stdio.h
・ 【Redmine】Puma 設定で同時接続数を調整する(Windows 前提) - PokuG stdio.h
・ Apache で Redmine をサブURL /redmine に公開する方法 - PokuG stdio.h
3. サービス化に必要な gem のインストール
Railsをサービス化するために必要なツールをインストールします。
ツールのインストールには"お手軽パターン"と"行儀がよい?パターン"の 2 種類記載します。
どちらを選んでも問題ないと思います。
パターンの違いはサービス化に必要なツールをシステム全体の見える場所に置く(前者パターン)か。redmine単体の場所に置く(後者パターン)かの違いだと思います。
3.1 win32-service のインストール(お手軽パターン)
管理者権限で以下コマンドを実行します。
gem install win32-service

上記コマンドで以下3つのモジュールが入ります。
・ffi-1.17.0
・ffi-win32-extensions-1.1.0
・win32-service-2.3.2
■ モジュールが3つ入らなかった場合
なぜか「gem install win32-service」で「win32-service」の一つしかモジュールが入らなかった場合は、以下コマンドを実行したらうまく入りました。
gem install ffi -v 1.17.0 gem install ffi-win32-extensions gem install win32-service
3.1.1 service.rb の作成
C:\redmine 以下に service.rb を作成します。
参考にした URL サンプルを変更しています。
# C:\redmine\service.rb
REDMINE_DIR = 'C:\redmine'
LOG_FILE = "#{REDMINE_DIR}\\log\\service.log"
begin
require 'win32/daemon'
include Win32
class RedmineService < Daemon
def service_init
File.open(LOG_FILE, 'a'){ |f| f.puts "Initializing service #{Time.now}" }
# ==== ここで環境変数を固定 ====
ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine' # サブURL指定
# Puma 起動
@server_pid = Process.spawn(
'bundle', 'exec', 'puma', '-C', 'config/puma.rb',
chdir: REDMINE_DIR,
out: [LOG_FILE, 'a'],
err: [LOG_FILE, 'a']
)
end
def service_main
File.open(LOG_FILE, 'a'){ |f| f.puts "Service is running #{Time.now} pid=#{@server_pid}" }
while running?
sleep 10
end
end
def service_stop
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopping #{Time.now}" }
system "taskkill /PID #{@server_pid} /T /F"
Process.wait(@server_pid) rescue nil
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopped #{Time.now}" }
# exit! ←やめる
return
end
end
RedmineService.mainloop
rescue Exception => e
File.open(LOG_FILE,'a+'){ |f| f.puts "***Daemon failure #{Time.now} #{e.inspect}\n#{e.backtrace.join($/)}" }
raise
end変更点は以下です。
- ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine' を追加し redmine の URL をサブURLに変更しています
- Puma の起動に変更しています
- 停止時は exit! ではなく return にしています(GUIでサービスを止めるとメッセージ出るため)
3.2 win32-service のインストール(行儀がよい?パターン)
3.2.1 Gemfileの編集
Gemfile の ffi の行をコメントにします。

3.2.2 Gemfile.localの編集
Gemfile.local に以下3つの記述を記載します。
gem 'ffi', '1.17.0' gem 'ffi-win32-extensions', '1.1.0' gem 'win32-service', '2.3.2'

3.2.3 bundle install の実行
パワーシェルの管理者権限で「C:\redmine」へ移動し以下コマンドを実行します。
bundle install --without development test

3.2.4 service.rb の作成
C:\redmine 以下に service.rb を作成します。
# C:\redmine\service.rb
REDMINE_DIR = 'C:\redmine'
LOG_FILE = "#{REDMINE_DIR}\\log\\service.log"
begin
ENV['BUNDLE_GEMFILE'] ||= 'C:/redmine/Gemfile' # Gemfile位置を記載
require 'bundler/setup' # これで vendor/bundle が自動で読まれる
require 'win32/daemon'
include Win32
class RedmineService < Daemon
def service_init
File.open(LOG_FILE, 'a'){ |f| f.puts "Initializing service #{Time.now}" }
# ==== ここで環境変数を固定 ====
ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine' # サブURL指定
# Puma 起動
@server_pid = Process.spawn(
'bundle', 'exec', 'puma', '-C', 'config/puma.rb',
chdir: REDMINE_DIR,
out: [LOG_FILE, 'a'],
err: [LOG_FILE, 'a']
)
end
def service_main
File.open(LOG_FILE, 'a'){ |f| f.puts "Service is running #{Time.now} pid=#{@server_pid}" }
while running?
sleep 10
end
end
def service_stop
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopping #{Time.now}" }
system "taskkill /PID #{@server_pid} /T /F"
Process.wait(@server_pid) rescue nil
File.open(LOG_FILE, 'a'){ |f| f.puts "Stopped #{Time.now}" }
# exit! ←やめる
return
end
end
RedmineService.mainloop
rescue Exception => e
File.open(LOG_FILE,'a+'){ |f| f.puts "***Daemon failure #{Time.now} #{e.inspect}\n#{e.backtrace.join($/)}" }
raise
end変更点は以下です。
- ENV['RAILS_RELATIVE_URL_ROOT'] = '/redmine' を追加し redmine の URL をサブURLに変更しています
- Puma の起動に変更しています
- 停止時は exit! ではなく return にしています(GUIでサービスを止めるとメッセージ出るため)
- C:\redmine\vendor\bundle を見に行くように Gemfile の位置を環境変数を設定
4. サービスに登録
コマンドプロンプトを管理者権限で起動し、以下コマンドを実行します。
sc create "Redmine" binPath= "C:\Ruby34-x64\bin\rubyw -C C:\redmine\ service.rb"

ちなみに、サービスを削除したい時は以下コマンドになります。
sc delete "Redmine"
5. サービスの起動
以下コマンドを使用し確認します。
■ コマンドプロンプトの場合
sc start "Redmine" sc stop "Redmine"
■ PowerShell の場合
Start-Service -Name "Redmine" Stop-Service -Name "Redmine"
6. おわり
これで Redmine 6 を Windows サービスとして安定運用できるようになりました。
OS 再起動後も自動で立ち上がり、PowerShell から Start-Service / Stop-Service で簡単に制御できます。
同じように Windows 環境で Redmine を使っている方の参考になれば幸いです。