Skip to content

Instantly share code, notes, and snippets.

@Kirbo
Last active February 23, 2026 17:32
Show Gist options
  • Select an option

  • Save Kirbo/4a0f1dffcf9cb9d5991bc8793e768bd6 to your computer and use it in GitHub Desktop.

Select an option

Save Kirbo/4a0f1dffcf9cb9d5991bc8793e768bd6 to your computer and use it in GitHub Desktop.
UpCloud - GitLab Runner - Debian 13 - setup.sh
#!/usr/bin/env bash
# setup-runner.sh
# Purpose: Prepare a Debian 13 VM for GitLab Fleeting autoscale:
# - install locales, set safe locale (C.UTF-8)
# - install cloud-init
# - install Docker + buildx + docker compose plugin
# - install gitlab-runner package (but do NOT register)
# - create recommended /etc/docker/daemon.json
# - ensure SSH host keys exist (ssh-keygen -A)
# - enable services
#
# Run as root (sudo)
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
if [[ "$(id -u)" -ne 0 ]]; then
echo "This script must be run as root. Use sudo." >&2
exit 1
fi
echo "==> Update package lists"
apt update -y
echo "==> Ensure basic packages are installed"
apt install -y --no-install-recommends \
locales \
cloud-init \
ca-certificates \
curl \
gnupg \
lsb-release \
apt-transport-https \
software-properties-common
# Fix bad LC_CTYPE environment variable if present in /etc/environment
if grep -q '^LC_CTYPE' /etc/environment 2>/dev/null; then
echo "==> Removing invalid LC_CTYPE from /etc/environment"
sed -i '/^LC_CTYPE/d' /etc/environment
fi
# Set a minimal, robust locale suitable for CI images
echo "==> Setting system locale to C.UTF-8"
update-locale LANG=C.UTF-8 LC_ALL=C.UTF-8 || true
echo "==> Generating locales (safe)"
locale-gen C.UTF-8 || true
locale-gen en_US.UTF-8 || true
echo "==> Installing Docker (official repository)"
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
> /etc/apt/sources.list.d/docker.list
apt update -y
apt install -y --no-install-recommends \
docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
# Recommended Docker daemon options for CI
DOCKER_DAEMON_JSON='/etc/docker/daemon.json'
if [[ ! -f "${DOCKER_DAEMON_JSON}" ]]; then
echo "==> Writing recommended Docker daemon.json to ${DOCKER_DAEMON_JSON}"
cat > "${DOCKER_DAEMON_JSON}" <<'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"features": {
"buildkit": true
}
}
EOF
else
echo "==> ${DOCKER_DAEMON_JSON} exists, leaving it unchanged"
fi
echo "==> Enabling and starting Docker service"
systemctl enable --now docker
# Add the user who invoked sudo (if any) to docker group to allow non-root docker usage
if [[ -n "${SUDO_USER:-}" && "${SUDO_USER}" != "root" ]]; then
echo "==> Adding ${SUDO_USER} to docker group"
usermod -aG docker "${SUDO_USER}" || true
fi
# Install GitLab Runner package (do NOT register)
echo "==> Installing gitlab-runner package (no registration performed)"
curl -fsSL https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
apt update -y
apt install -y --no-install-recommends gitlab-runner
# Ensure gitlab-runner service is enabled (service will be idle until registration)
systemctl enable --now gitlab-runner || true
# Ensure SSH host keys exist (so we can SSH while configuring)
echo "==> Ensuring SSH host keys exist (ssh-keygen -A)"
ssh-keygen -A || true
# Ensure cloud-init is present and give status
echo "==> cloud-init status (should eventually be 'done')"
cloud-init status --long || true
# Ensure no pre-registered runner config in image
if [[ -f /etc/gitlab-runner/config.toml ]]; then
echo "==> Removing /etc/gitlab-runner/config.toml (avoid baking runner config)"
rm -f /etc/gitlab-runner/config.toml
fi
echo "==> Basic verification"
docker --version || true
docker buildx version || true
docker compose version || true
gitlab-runner --version || true
echo "==> setup-runner.sh finished. You can continue configuring the instance interactively."
echo "==> Remember: do NOT run 'gitlab-runner register' here; register via cloud-init on first boot for ephemeral runners."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment