Setting up GitLab On-Premises CI/CD Pipeline
Setting up an automatic deployment environment for a Spring Boot + Go project using GitLab Runner on Ubuntu 24.04.
While setting up the new server, I had to configure GitLab CI/CD from scratch, so I documented the process.
Architecture
┌──────────────┐ push to main ┌─────────────────────┐
│ Developer │ ───────────────────> │ GitLab (On-Premise)│
└──────────────┘ └──────────┬──────────┘
│ CI/CD Trigger
▼
┌─────────────────────┐
│ Deployment Server │
│ (GitLab Runner) │
│ │
│ git pull → build │
│ → systemctl restart │
└─────────────────────┘┌──────────────┐ push to main ┌─────────────────────┐
│ Developer │ ───────────────────> │ GitLab (On-Premise)│
└──────────────┘ └──────────┬──────────┘
│ CI/CD Trigger
▼
┌─────────────────────┐
│ Deployment Server │
│ (GitLab Runner) │
│ │
│ git pull → build │
│ → systemctl restart │
└─────────────────────┘The deployment targets are a Spring Boot (Gradle, Java 17) project and a Go project,
each operated in different repositories, and when there is a push or MR (Merge Request) to the main branch,
it is set up to automatically build and deploy through GitLab Runner.
1. Account Permission Separation
Create a Dedicated User for Deployment
I separated the user for running the service and the user for executing CI/CD.
# Create a user for running the service
sudo useradd -m -s /bin/bash service-username# Create a user for running the service
sudo useradd -m -s /bin/bash service-usernameSet Minimum Permissions in sudoers
I restricted the gitlab-runner to only be able to restart the service.
sudo visudo -f /etc/sudoers.d/gitlab-runner
gitlab-runner ALL=(ALL) NOPASSWD: /bin/systemctl restart springboot-server
gitlab-runner ALL=(ALL) NOPASSWD: /bin/systemctl restart go-serversudo visudo -f /etc/sudoers.d/gitlab-runner
gitlab-runner ALL=(ALL) NOPASSWD: /bin/systemctl restart springboot-server
gitlab-runner ALL=(ALL) NOPASSWD: /bin/systemctl restart go-serverWith this configuration, the gitlab-runner cannot execute other sudo commands and can only run the above commands.
2. Install GitLab Runner
Installation
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner -ycurl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner -yRegister the Runner
sudo gitlab-runner register \
--non-interactive \
--url "Your GitLab URL" \
--registration-token "Token" \
--description "deploy-server" \
--tag-list "deploy" \
--executor "shell"sudo gitlab-runner register \
--non-interactive \
--url "Your GitLab URL" \
--registration-token "Token" \
--description "deploy-server" \
--tag-list "deploy" \
--executor "shell"By setting the executor to shell, commands can be executed directly on the server.
Enter your GitLab URL in the url, and the token that can be found in the repository's CI/CD Runner settings in the registration-token.
3. SSH Key Configuration
You need to set up an SSH key so that the registered gitlab-runner user can pull code from GitLab.
sudo -u gitlab-runner ssh-keygen -t ed25519 -C "gitlab-runner@server" -N "" -f /home/gitlab-runner/.ssh/id_ed25519sudo -u gitlab-runner ssh-keygen -t ed25519 -C "gitlab-runner@server" -N "" -f /home/gitlab-runner/.ssh/id_ed25519Register the public key in the GitLab project's Settings -> Repository -> Deploy keys.
Git safe.directory Configuration
Set safe.directory as below to avoid ownership issues.
sudo -u gitlab-runner git config --global --add safe.directory /path/to/projectsudo -u gitlab-runner git config --global --add safe.directory /path/to/project4. Configure systemd Service
Configure systemd services for both the Spring Boot service and the Go service.
# /etc/systemd/system/springboot-server.service
[Unit]
Description=springboot-server
After=network.target mongod.service
Requires=mongod.service
[Service]
Type=simple
User=service-username
Group=service-username
WorkingDirectory=/path/to/project
ExecStart=/usr/bin/java -jar /path/to/project/build/libs/springboot-server-0.0.1-SNAPSHOT.jar
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target# /etc/systemd/system/springboot-server.service
[Unit]
Description=springboot-server
After=network.target mongod.service
Requires=mongod.service
[Service]
Type=simple
User=service-username
Group=service-username
WorkingDirectory=/path/to/project
ExecStart=/usr/bin/java -jar /path/to/project/build/libs/springboot-server-0.0.1-SNAPSHOT.jar
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target5. .gitlab-ci.yml Pipeline
Similarly, configure the gitlab-ci.yml settings for both the Spring Boot service and the Go repository.
stages:
- deploy
deploy:
stage: deploy
tags:
- console
only:
- main
script:
- cd /path/to/project
- git reset --hard HEAD
- git pull origin main
- ./gradlew build -x test
- sudo systemctl restart springboot-serverstages:
- deploy
deploy:
stage: deploy
tags:
- console
only:
- main
script:
- cd /path/to/project
- git reset --hard HEAD
- git pull origin main
- ./gradlew build -x test
- sudo systemctl restart springboot-serverResults
When you push to the main branch,
GitLab sends the job to the Runner.
The Runner performs git pull on the server.
Build executes (gradlew / go build).
Service restarts with systemctl restart.
Now, code reflection is automated just by pushing to the main branch without manual deployment.