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.

·~3 min read·677 views·Updated: Oct 5, 2026

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-username

Set 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-server
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-server

With 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 -y
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner -y

Register 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_ed25519
sudo -u gitlab-runner ssh-keygen -t ed25519 -C "gitlab-runner@server" -N "" -f /home/gitlab-runner/.ssh/id_ed25519

Register 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/project
sudo -u gitlab-runner git config --global --add safe.directory /path/to/project

4. 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.target

5. .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-server
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-server

Results

When you push to the main branch,

  1. GitLab sends the job to the Runner.

  2. The Runner performs git pull on the server.

  3. Build executes (gradlew / go build).

  4. Service restarts with systemctl restart.

Now, code reflection is automated just by pushing to the main branch without manual deployment.

Share