Heptapod: GitLab with Mercurial support



Install and configure Heptapod: a fork of the GitLab software development platform that works with both Git and Mercurial.

Specify the replace_data_directory directory to store the
data in the preferred location.
Choose a container name replace_container, a hostname replace_hostname and volume names replace_volume.
Specify the network replace_network to serve behind a reverse proxy.

Create the directories and the volumes.



data_directory="replace_data_directory" # data_directory=/data/services

container=replace_container # container=gitlab
container_hostname=replace_hostname # container_hostname=gitlab
volume=replace_volume # volume=gitlab
volume_configuration=${volume}_configuration
volume_data=${volume}_data
volume_logs=${volume}_logs
network=replace_network # network=services

sudo mkdir --parents "$data_directory/gitlab"
sudo chmod --recursive a+rwX "$data_directory/gitlab/"

mkdir "$data_directory/gitlab/configuration"
mkdir "$data_directory/gitlab/data"
mkdir "$data_directory/gitlab/logs"

docker volume create \
--name $volume_configuration \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab/configuration/"
docker volume create \
--name $volume_data \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab/data/"
docker volume create \
--name $volume_logs \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab/logs/"



Edit and place the configuration file.
Set the web server hostname and form the Heptapod location replace_location that users will access.
Specify the internal network definition replace_network_addresses so that GitLab trusts the reverse proxy and correctly displays user addresses, not the reverse proxy address. The address and the mask of the network replace_network can be easily checked with the Docker command line interface or with Portainer.

It is worth tailoring one's own configuration from scratch. For that, export the template configuration file from the latest image and change the defaults, toggle features and specify integrations.



docker container create \
--name $container \
--hostname $container_hostname \
--mount type=tmpfs,destination=/etc/gitlab \
--mount type=tmpfs,destination=/var/opt/gitlab \
--mount type=tmpfs,destination=/var/log/gitlab \
octobus/heptapod
docker cp $container:/opt/gitlab/etc/gitlab.rb.template gitlab.rb
docker container rm $container

docker network inspect $network

# edit the template gitlab.rb or use the supplied one and diff with the latest

cp gitlab.rb "$data_directory/gitlab/configuration/"



Configure the reverse proxy. Put the configuration file to the web server directory. Set the Heptapod hostname replace_hostname in the configuration file to forward requests to the container. Apply the web server configuration.



container_caddy=replace_container_caddy # container_caddy=caddy

cp gitlab.caddy "$data_directory/caddy/configuration/"
docker container restart $container_caddy



Finally, start the container.



docker run --detach --restart unless-stopped \
--name $container \
--hostname $container_hostname \
--network $network \
--mount type=volume,source=$volume_configuration,destination=/etc/gitlab \
--mount type=volume,source=$volume_data,destination=/var/opt/gitlab \
--mount type=volume,source=$volume_logs,destination=/var/log/gitlab \
--shm-size 256m \
--mount type=bind,source=/etc/timezone,destination=/etc/timezone,readonly \
--mount type=bind,source=/etc/localtime,destination=/etc/localtime,readonly \
octobus/heptapod



Optionally, tweak the default password constraints.



docker container exec --interactive --tty $container /bin/bash
sed --regexp-extended --in-place \
's|'\
'^(  DEFAULT_MINIMUM_PASSWORD_LENGTH = 8)$|'\
'#\1\n  DEFAULT_MINIMUM_PASSWORD_LENGTH = 1|'\
'w /dev/stdout' \
/opt/gitlab/embedded/service/gitlab-rails/\
app/models/application_setting_implementation.rb
quit
docker container restart $container



Sign in to the site at the /gitlab path as root with the automatically generated password and perform configurations.



sudo cat "$data_directory/gitlab/configuration/initial_root_password"



General

Account and limit
Session duration (minutes)
User OAuth applications
Prompt users to upload SSH keys

Sign-up restrictions
Sign-up enabled
Minimum password length (number of characters)

Customer experience improvement and third-party offers
Do not display offers from third parties

Repository
Default branch

CI/CD

Continuous Integration and Deployment
Default to Auto DevOps pipeline for all projects

Metrics and profiling

Metrics - Prometheus
Self monitoring
Usage statistics
Enable version check
Enable Service Ping

Preferences

Email
Enable in-product marketing emails

What's new
Disable What's new

Localization
Default first day of the week

Overview
Users

Administrator
Edit
Password

New user
Edit
Password

Continuous Integration — Heptapod Runner



Set up continuous integration agents. Heptapod Runner is similar to Gitlab Runner.

Specify the data directory replace_data_directory.
Choose a container name replace_container, a hostname replace_hostname and volume names replace_volume.
Specify the network replace_network to interact with Heptapod.

Create the directories and the volumes.



data_directory="replace_data_directory" # data_directory=/data/services

container=replace_container # container=gitlab_ci
container_hostname=replace_hostname # container_hostname=gitlab-ci
volume=replace_volume # volume=gitlab_ci
volume_configuration=${volume}_configuration
volume_builds=${volume}_builds
volume_cache=${volume}_cache
network=replace_network # network=services

sudo mkdir --parents "$data_directory/gitlab_ci"
sudo chmod --recursive a+rwX "$data_directory/gitlab_ci/"

mkdir "$data_directory/gitlab_ci/configuration"
mkdir "$data_directory/gitlab_ci/builds"
mkdir "$data_directory/gitlab_ci/cache"

docker volume create \
--name $volume_configuration \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab_ci/configuration/"
docker volume create \
--name $volume_builds \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab_ci/builds/"
docker volume create \
--name $volume_cache \
--driver local-persist \
--opt mountpoint="$data_directory/gitlab_ci/cache/"



Place the configuration file, adapt as necessary.
Assign a description replace_container to the agent. It will be visible in the user interface. Set the Heptapod hostname replace_hostname_gitlab and the runner hostname replace_hostname so they can reach out to and interact with each other within the internal network.

Get an access token for the agent.
Navigate the settings and generate a registration token replace_token.

Overview
Runners
Register an instance runner

Execute the registration command. A configuration file will be created containing the access token. Save the token replace_token and paste it into the prepared file.
Be aware that the registration procedure is undergoing a redesign currently.



hostname_gitlab=replace_hostname_gitlab # hostname_gitlab=gitlab
token='replace_token' # token=********************

docker run --rm --interactive --tty \
--name $container \
--hostname $container_hostname \
--network $network \
--mount type=volume,source=$volume_configuration,destination=/etc/gitlab-runner \
octobus/heptapod-runner \
register --non-interactive \
--name $container \
--url "http://$hostname_gitlab/gitlab" \
--registration-token $token \
--executor docker --docker-image docker

sudo cat "$data_directory/gitlab_ci/configuration/config.toml"
sudo rm "$data_directory/gitlab_ci/configuration/config.toml"

# save the access token into the composed config.toml

cp config.toml "$data_directory/gitlab_ci/configuration/"



Now, if you are going to utilize Docker in Docker approach for builds, consider centralized volume management.
The --volumes-from parameter might come in handy for decoupling build steps from build environments. A running reference container is mandatory for other containers to be able to copy its volume configuration. Carefully define the volumes container name replace_container_volumes and the builds and cache volume names replace_volume.
The network replace_network also has to be repeated for pipeline connectivity.
Environment variables pass all possibly required options to pipelines. The container name replace_container and the hostname replace_hostname of the agent prepend the naming patterns for job containers. Overriding the location replace_hostname_gitlab on the runner level forces communication through the internal network.

There are sample scripts for pulling sources manually. They also demonstrate the use of the technique.



container_volumes=replace_container_volumes # container_volumes=gitlab_ci_volumes

docker run --detach --restart unless-stopped --interactive --tty --init \
--name $container_volumes \
--hostname $(echo $container_volumes | tr '_' '-') \
--network none \
--mount type=volume,source=$volume_builds,destination=/builds \
--mount type=volume,source=$volume_cache,destination=/cache \
--mount type=bind,source=/etc/timezone,destination=/etc/timezone,readonly \
--mount type=bind,source=/etc/localtime,destination=/etc/localtime,readonly \
alpine sleep infinity

# chmod +x here or in pipelines
cp --recursive scripts "$data_directory/gitlab_ci/builds/"



Start the container.
Check the logs and the user interface and verify that the agent works.



docker run --detach --restart unless-stopped \
--name $container \
--hostname $container_hostname \
--network $network \
--mount type=volume,source=$volume_configuration,destination=/etc/gitlab-runner \
--mount type=volume,source=$volume_cache,destination=/home/gitlab-runner \
--mount type=bind,source=/var/run/docker.sock,destination=/var/run/docker.sock \
--mount type=bind,source=/etc/timezone,destination=/etc/timezone,readonly \
--mount type=bind,source=/etc/localtime,destination=/etc/localtime,readonly \
octobus/heptapod-runner