Task #244
openTask Group #243: [DevOps] DevOps related task management
[DevOps] Install the bitnami package for Redmine and configure Redmine to use as an external issue tracker for GitLab
90%
Description
Install the bitname package for Redmine and configure Redmine to use as an external issue tracker for GitLab
[GitLab] ──→ External Issue Tracker Setting ──→ [Bitnami Redmine:3000]
│
[MariaDB Container]
Redmine Installation & GitLab Integration Procedures¶
- Table of contents
- Redmine Installation & GitLab Integration Procedures
- 1. System Architecture Overview
- 2. Prerequisites
- 3. Directory Structure & File Configuration
- 4. Git Mirror Repository Setup
- 5. Build & Run Docker Containers
- 6. Redmine Initial Configuration (Web UI)
- 7. GitLab Webhook Configuration
- 8. GitLab Integrations Setup (Issue Tracker Linking)
- 9. Integration Testing Procedure
- 10. Troubleshooting
- 11. Maintenance
1. System Architecture Overview¶
┌─────────────────────────────────────────────────────────┐
│ GitLab │
│ │
│ Repository │ Issues │ Commit Messages │
└───────┬────────┴─────┬──────┴───────────┬───────────────┘
│ │ │
[1] Webhook │ │ [2] Integration │ [3] Commit message
push event triggered │ │ issue URL link │ XCP-#42 (refs #42)
│ │ │
v v │
┌───────────────────────────────┐ │
│ Redmine │ │
│ │ <───────┘
│ redmine_gitlab_hook plugin │ refs #42 → issue link
│ │ │
│ v │
│ git fetch --all -p │
│ (update mirror repository) │
│ │ │
│ v │
│ fetch_changesets │
│ (sync commits to DB) │
│ │
│ Issues │ Repository │ DB │
└───────────────────────────────┘
[1] Webhook : GitLab push → automatically syncs commits to Redmine repository
[2] Integration: GitLab Settings → Integrations → Redmine issue tracker URL linking
[3] Commit ref : "XCP-#42 (refs #42)" → creates issue links in both GitLab and Redmine
| Component | Version / Details |
|---|---|
| Redmine | 6.1 (redmine:6.1-trixie) |
| Database | MySQL 8.0 |
| Plugin | redmine_gitlab_hook v4.0.0 (phlegx/redmine_gitlab_hook) |
| Host IP | 192.168.1.102 |
| Redmine Port | 3000 |
| GitLab URL | http://git.xela.com:8888 |
2. Prerequisites¶
2-1. Verify Docker & Docker Compose Installation¶
docker --version
docker compose version
2-2. Create Required Directories¶
mkdir -p /home/xela/redmine/redmine_data
mkdir -p /home/xela/redmine/mysql_data
mkdir -p /home/xela/redmine/redmine_repos
mkdir -p /home/xela/redmine/plugins
2-3. Generate a GitLab Access Token¶
A token is required for authentication during git fetch operations.
- Go to GitLab → User Settings → Access Tokens (or project Settings → Repository → Deploy tokens)
- Select scope:
read_repository - Note down the generated username and token value
Deploy Token recommended: Grants read-only access scoped to a specific project, and is not affected by account password changes.
3. Directory Structure & File Configuration¶
/home/xela/redmine/ ├── docker-compose.yml # Container orchestration ├── Dockerfile # Custom image with plugins included ├── SETUP.md # Korean setup guide ├── SETUP_EN.md # Markdown version ├── SETUP_EN.textile # This document (Redmine wiki format) ├── plugins/ │ └── redmine_gitlab_hook/ # GitLab webhook integration plugin ├── redmine_data/ # Persistent Redmine data (file attachments, etc.) ├── redmine_repos/ # Git mirror repositories (host path) │ └── XCP.git/ # Example bare mirror repository └── mysql_data/ # Persistent MySQL data
Key docker-compose.yml Settings¶
services:
redmine_db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: <change this>
MYSQL_USER: redmine
MYSQL_PASSWORD: <change this>
MYSQL_DATABASE: redmine
volumes:
- /home/xela/redmine/mysql_data:/var/lib/mysql
redmine:
build: . # Custom build from Dockerfile
ports:
- "192.168.1.102:3000:3000" # Bind to specific IP only
volumes:
- /home/xela/redmine/redmine_data:/usr/src/redmine/files
- /home/xela/redmine/redmine_repos:/var/lib/redmine/repositories:rw
Volume mount note:
redmine_repos(host) →/var/lib/redmine/repositories(container).
Any changes to repository files on the host are immediately reflected inside the container.
Dockerfile Overview¶
FROM redmine:6.1-trixie
# Install build tools
RUN apt-get install -y build-essential gcc make git default-libmysqlclient-dev
# Copy plugins and set ownership
COPY ./plugins /usr/src/redmine/plugins
RUN chown -R redmine:redmine /usr/src/redmine/plugins
# Install plugin gem dependencies
USER redmine
RUN bundle install
When adding or updating plugins, the image must be rebuilt:
docker compose build --no-cache
4. Git Mirror Repository Setup¶
For each GitLab project to be integrated, create a local mirror repository on the Redmine server.
4-1. Create Mirror Clone¶
# Format: git clone --mirror http://USER:TOKEN@GITLAB_HOST/NAMESPACE/REPO.git DEST.git
git clone --mirror \
http://invokelshn:TOKEN@git.xela.com:8888/software/XCP.git \
/home/xela/redmine/redmine_repos/XCP.git
4-2. Verify Credentials Are Embedded in the Remote URL¶
cat /home/xela/redmine/redmine_repos/XCP.git/config
The url field under [remote "origin"] must include credentials in the format http://USER:TOKEN...:@
[remote "origin"]
url = http://USERNAME:TOKEN@git.xela.com:8888/software/XCP.git
fetch = +refs/*:refs/*
mirror = true
Important: The Redmine container runs git fetch in a non-interactive environment — there is no TTY available to prompt for username/password.
Credentials must be embedded in the URL or configured via a credential store.
If the repository was cloned without credentials, update the URL:
git --git-dir="/home/xela/redmine/redmine_repos/XCP.git" \
remote set-url origin \
"http://USERNAME:TOKEN@git.xela.com:8888/software/XCP.git"
4-3. Verify fetch Works (Test from Host)¶
git --git-dir="/home/xela/redmine/redmine_repos/XCP.git" fetch --all -p
Expected output:
From http://git.xela.com:8888/software/XCP 4acdd59..1caf25e main -> main
5. Build & Run Docker Containers¶
5-1. Build Image and Start Containers¶
cd /home/xela/redmine
docker compose build
docker compose up -d
5-2. Verify Container Status¶
docker compose ps
docker logs redmine --tail=30
When Puma starts successfully:
* Listening on http://0.0.0.0:3000
5-3. Rebuild After Plugin Changes¶
docker compose down
docker compose build --no-cache
docker compose up -d
6. Redmine Initial Configuration (Web UI)¶
Redmine Web UI: http://192.168.1.102:3000 (or http://redmine.xela.com:3000)
Default admin credentials: admin / admin — change immediately after first login
6-1. Retrieve API Key¶
The plugin uses this key to authenticate incoming webhook requests.
Administration → Settings → Repository tab → Check "Enable WS for repository management" → Copy the API key
6-2. Register a Git Repository for a Redmine Project¶
For each project to be integrated:
- Go to the project → Settings → Repositories → New repository
- Fill in the settings:
| Field | Value |
|---|---|
| SCM | Git |
| Identifier | xcp_mirror (must match the repository_name parameter in the webhook URL) |
| Path to repository | /var/lib/redmine/repositories/XCP.git (path inside the container) |
| Is default repository | Check |
3. Click Create and verify the repository is recognized correctly
6-3. Configure the redmine_gitlab_hook Plugin¶
Administration → Plugins → Redmine GitLab Hook plugin → Configure
| Setting | Value | Description |
|---|---|---|
| All Branches | Yes | Fetch all branches from all remotes |
| Prune | Yes | Remove stale remote-tracking references |
| Auto Create | Yes | Auto-create repository on first webhook (optional) |
| Fetch Updates | Yes | Run git fetch when webhook is received |
| Local Repositories Path | /var/lib/redmine/repositories |
Required when Auto Create is enabled |
7. GitLab Webhook Configuration¶
7-1. Webhook URL Format¶
http://redmine.xela.com:3000/gitlab_hook?project_id=REDMINE_PROJECT_ID&repository_name=REPO_IDENTIFIER&key=REDMINE_API_KEY
| Parameter | Description | Example |
|---|---|---|
project_id |
Redmine project identifier | fy26_xcp-project |
repository_name |
Redmine repository identifier | xcp_mirror |
key |
Redmine API key (from section 6-1) | u67PN12c2bDK5HyaTUdC |
Important: Use
repository_name, notrepository_id.
The plugin readsparams[:repository_name]— therepository_idparameter is ignored entirely.
7-2. Register the Webhook in GitLab¶
- GitLab project → Settings → Webhooks
- Configure:
| Field | Value |
|---|---|
| URL | The webhook URL from above |
| Trigger | Check Push events |
| SSL verification | Configure as needed |
3. Click Add webhook
7-3. Example Configuration (XCP Project)¶
http://redmine.xela.com:3000/gitlab_hook?project_id=fy26_xcp-project&repository_name=xcp_mirror&key=u67PN12c2bDK5HyaTUdC
8. GitLab Integrations Setup (Issue Tracker Linking)¶
The Settings → Integrations → Redmine feature in GitLab allows issue numbers referenced in commit messages or merge requests to become clickable links that navigate directly to Redmine issues.
Webhook vs Integrations
- Webhook (section 7): GitLab push event → automatically updates the Redmine repository mirror (commit sync)
- Integrations (this section): Links issue references in the GitLab UI to the Redmine issue tracker
8-1. Enable the Redmine Integration in GitLab¶
- GitLab project → Settings → Integrations → select Redmine
- Configure the following fields:
| Field | Value | Description |
|---|---|---|
| Active | Checked | Enable the integration |
| Project URL | http://redmine.xela.com:3000/projects/fy26_xcp-project |
URL of the Redmine project |
| Issues URL | http://redmine.xela.com:3000/issues/:id |
Issue URL pattern (keep :id as-is) |
| New issue URL | http://redmine.xela.com:3000/projects/fy26_xcp-project/issues/new |
URL to create a new issue |
3. Click Save changes
The project identifier in Project URL and New issue URL must match the Redmine project identifier exactly.
Example: if the Redmine project identifier isfy26_xcp-project, use the same value in the URLs.
8-2. Referencing Issues in Commit Messages¶
Once the integration is active, use the following format to create issue links in both GitLab and Redmine simultaneously:
# Format: "commit message GITLAB_PROJECT_ID-#issue_number (refs #issue_number)"
git commit -m "Fix sensor calibration logic XCP-#42 (refs #42)"
git push origin main
| Reference format | Recognized by | Description |
|---|---|---|
XCP-#42 |
GitLab | GitLab project ID (XCP) + issue number → links to GitLab issue |
refs #42 |
Redmine | Redmine issue number → links to Redmine issue |
GitLab Project ID: find it at GitLab project → Settings → General → Project ID
ReplaceXCPwith the actual project ID of your GitLab project.
In the GitLab commit detail page, refs #42 will appear as a clickable link that navigates to:
http://redmine.xela.com:3000/issues/42
8-3. Verify the Integration¶
- GitLab → project → Settings → Integrations → Redmine → click the Test button
- A successful connection shows a green checkmark with a success message
9. Integration Testing Procedure¶
Step 1: Test git fetch Directly¶
Verify that git fetch works from inside the container.
docker exec redmine git \
--git-dir="/var/lib/redmine/repositories/XCP.git" \
fetch --all -p
- Success: Branch update information is printed
- Failure: See Troubleshooting section below
Step 2: Manually Trigger Webhook from GitLab UI¶
- GitLab → project → Settings → Webhooks
- Click Test → Push events on the registered webhook
- Check the response:
HTTP 200: SuccessHTTP 406: git fetch failed (authentication or path issue)HTTP 500: Redmine internal error (project/repository configuration issue)
Step 3: Test Webhook via curl¶
curl -X POST \
"http://redmine.xela.com:3000/gitlab_hook?project_id=fy26_xcp-project&repository_name=xcp_mirror&key=u67PN12c2bDK5HyaTUdC" \
-H "Content-Type: application/json" \
-d '{"object_kind":"push","ref":"refs/heads/main"}'
Expected response: OK
Step 4: Monitor Logs in Real Time¶
# Terminal 1: watch logs
docker logs -f redmine
# Terminal 2: trigger webhook or push to GitLab
Expected log on successful processing:
Started POST "/gitlab_hook?..." for ... Processing by GitlabHookController#index Completed 200 OK
Step 5: Verify Commits Appear in Redmine UI¶
- Redmine → the project → Repository tab
- Confirm that commits pushed to GitLab are now visible
Step 6: End-to-End Test¶
# 1. Create a test commit (from a local development environment)
git commit --allow-empty -m "test: redmine webhook integration"
git push origin main
# 2. After a few seconds, check Redmine
# Project → Repository → verify the commit appears in the list
10. Troubleshooting¶
Error 1: HTTP 500 — "has no repository or repository not found"¶
TypeError: Project 'XXX' has no repository or repository not found with identifier 'yyy'Cause A: Webhook URL uses
repository_id instead of repository_name
- Fix: Replace
repository_id=...withrepository_name=...in the webhook URL
- Fix: Register a Git repository under project Settings → Repositories (see section 6-2)
repository_name parameter and the Redmine repository identifier
- Fix: Ensure the Redmine repository identifier exactly matches the
repository_namevalue in the webhook URL
Error 2: HTTP 406 — "Git command failed"¶
GitLabHook: Command 'git --git-dir="..." fetch --all -p' didn't exit properly. fatal: could not read Username for 'http://...': No such device or address
Cause: The mirror repository's remote URL does not contain credentials
Fix:
git --git-dir="/home/xela/redmine/redmine_repos/XCP.git" \
remote set-url origin \
"http://USERNAME:TOKEN@git.xela.com:8888/software/XCP.git"
Error 3: Cannot Reach GitLab Host from Inside the Container¶
fatal: unable to access 'http://git.xela.com:8888/...': Could not resolve host
Check:
docker exec redmine curl -I http://git.xela.com:8888
Fix: Add extra_hosts to docker-compose.yml or verify DNS configuration on the host.
How to Check Logs¶
# Container logs (last 100 lines)
docker logs --tail=100 redmine
# Follow logs in real time
docker logs -f redmine
# Redmine production.log (inside container)
docker exec redmine tail -100 /usr/src/redmine/log/production.log
11. Maintenance¶
Adding a New GitLab Project Integration¶
- Create a mirror repository (see section 4)
- Register the repository in the Redmine project (see section 6-2)
- Add a webhook in GitLab (see section 7)
- Run through the test procedure (see section 9)
Restart Containers¶
cd /home/xela/redmine
docker compose restart
Update the Plugin¶
cd /home/xela/redmine/plugins/redmine_gitlab_hook
git pull
cd /home/xela/redmine
docker compose down
docker compose build --no-cache
docker compose up -d
Backup¶
# MySQL database
docker exec redmine_db mysqldump -u redmine -pPASSWORD redmine > backup_$(date +%Y%m%d).sql
# Persistent Redmine data (file attachments, etc.)
tar -czf redmine_data_$(date +%Y%m%d).tar.gz /home/xela/redmine/redmine_data
# Git mirror repositories
tar -czf redmine_repos_$(date +%Y%m%d).tar.gz /home/xela/redmine/redmine_repos
Files