stencil
+
svelte
+
npm
+
hapi
+
+
remix
+
+
koa
cosmos
|>
swc
linux
lit
phoenix
rollup
hack
+
+
[]
rubymine
+
+
+
echo
+
+
+
wsl
css
+
+
mxnet
perl
sklearn
+
+
rollup
+
+
+
tf
http
+
scipy
+=
supabase
+
+
svelte
+
lisp
+
esbuild
https
+
+
vault
+
tls
+
+
jwt
+
+
+
+
+
+
+
+
mocha
hugging
cypress
+
+
+
apex
zorin
vb
apex
zig
+
+
Back to Blog
Installing GitLab Server on Alpine Linux: Complete Setup Guide
alpine-linux gitlab git

Installing GitLab Server on Alpine Linux: Complete Setup Guide

Published Feb 14, 2025

Learn how to install and configure GitLab CE on Alpine Linux with PostgreSQL, Redis, SSL, and production-ready settings for team collaboration and CI/CD workflows.

18 min read
0 views
Table of Contents

Setting up your own GitLab server gives you complete control over your code repositories, CI/CD pipelines, and team collaboration workflows. I’ve deployed GitLab on Alpine Linux for multiple organizations, and it’s an excellent combination of lightweight infrastructure with powerful DevOps capabilities.

Alpine Linux’s minimal footprint makes it perfect for GitLab servers - you get enterprise-grade Git hosting without the resource overhead of heavier distributions. Plus, the security benefits of Alpine’s hardened design are crucial for protecting your source code.

Why GitLab on Alpine Linux

Running GitLab on Alpine brings several advantages:

  • Resource efficiency with Alpine’s minimal base system
  • Enhanced security through Alpine’s hardened kernel and packages
  • Fast deployment with quick boot times and efficient package management
  • Cost savings from reduced resource requirements
  • Better performance with optimized system stack

What You’ll Accomplish

  • Install GitLab Community Edition with all dependencies
  • Configure PostgreSQL and Redis for optimal performance
  • Set up SSL certificates for secure access
  • Configure GitLab CI/CD runners
  • Implement backup and monitoring solutions
  • Optimize GitLab for production workloads

Prerequisites

Before starting, ensure you have:

  • Alpine Linux 3.17 or newer with at least 4GB RAM
  • 20GB+ storage space for repositories and artifacts
  • Domain name pointing to your server (for SSL setup)
  • Root access or sudo privileges
  • Basic understanding of Git and DevOps concepts

Let’s start by updating the system:

apk update && apk upgrade

Installing Dependencies

System Dependencies

What we’re doing: Installing all required packages for GitLab and its components.

# Install essential packages
apk add curl wget git openssh openssl ca-certificates \
        postfix ruby ruby-bundler python3 py3-pip \
        nodejs npm yarn tzdata

# Install compilation tools
apk add build-base cmake libffi-dev openssl-dev \
        zlib-dev readline-dev yaml-dev sqlite-dev \
        postgresql-dev redis

# Install runtime libraries
apk add libxml2-dev libxslt-dev libgcrypt-dev \
        imagemagick-dev libre2-dev

PostgreSQL Installation and Setup

What we’re doing: Installing and configuring PostgreSQL as GitLab’s primary database.

# Install PostgreSQL
apk add postgresql postgresql-contrib postgresql-dev

# Initialize PostgreSQL database
rc-update add postgresql default
service postgresql setup
service postgresql start

# Configure PostgreSQL for GitLab
sudo -u postgres psql << 'EOF'
CREATE USER gitlab WITH PASSWORD 'secure_gitlab_password' CREATEDB;
CREATE DATABASE gitlabhq_production OWNER gitlab;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE EXTENSION IF NOT EXISTS btree_gist;
\q
EOF

# Configure PostgreSQL settings
cat >> /etc/postgresql/postgresql.conf << 'EOF'
# GitLab Optimizations
shared_buffers = 256MB
effective_cache_size = 1GB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200
work_mem = 4MB
min_wal_size = 1GB
max_wal_size = 4GB
max_worker_processes = 8
max_parallel_workers_per_gather = 4
max_parallel_workers = 8
max_parallel_maintenance_workers = 4
EOF

# Restart PostgreSQL to apply changes
service postgresql restart

Redis Installation and Configuration

What we’re doing: Setting up Redis for GitLab’s caching and session storage.

# Install Redis
apk add redis

# Configure Redis for GitLab
cat > /etc/redis.conf << 'EOF'
# Basic Configuration
port 6379
bind 127.0.0.1
timeout 0
tcp-keepalive 300

# Memory Management
maxmemory 256mb
maxmemory-policy allkeys-lru

# Persistence
save 900 1
save 300 10
save 60 10000
rdbcompression yes
rdbchecksum yes
dbfilename gitlab-redis.rdb
dir /var/lib/redis/

# Security
requirepass gitlab_redis_password

# Logging
loglevel notice
logfile /var/log/redis/redis.log

# Performance
tcp-backlog 511
databases 16
EOF

# Start and enable Redis
rc-update add redis default
service redis start

# Test Redis connection
redis-cli -a gitlab_redis_password ping

Installing GitLab Community Edition

GitLab Installation

What we’re doing: Installing GitLab CE using the official installation method.

# Add GitLab repository
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.alpine.sh | bash

# Install GitLab CE
apk add gitlab-ce

# Alternative: Manual installation from source
# This gives more control but requires more configuration

# Create GitLab user
adduser -D -s /bin/bash git
adduser git git

# Download GitLab source
cd /home/git
sudo -u git git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b stable gitlab

# Install GitLab from source (if preferred)
cd /home/git/gitlab
sudo -u git cp config/gitlab.yml.example config/gitlab.yml
sudo -u git cp config/secrets.yml.example config/secrets.yml

GitLab Configuration

What we’re doing: Configuring GitLab with our PostgreSQL and Redis settings.

# Create GitLab configuration
cat > /etc/gitlab/gitlab.rb << 'EOF'
# Basic Configuration
external_url 'https://gitlab.yourdomain.com'
gitlab_rails['time_zone'] = 'UTC'

# Database Configuration
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'unicode'
gitlab_rails['db_database'] = 'gitlabhq_production'
gitlab_rails['db_username'] = 'gitlab'
gitlab_rails['db_password'] = 'secure_gitlab_password'
gitlab_rails['db_host'] = '127.0.0.1'
gitlab_rails['db_port'] = 5432

# Redis Configuration
gitlab_rails['redis_host'] = '127.0.0.1'
gitlab_rails['redis_port'] = 6379
gitlab_rails['redis_password'] = 'gitlab_redis_password'
gitlab_rails['redis_database'] = 0

# Email Configuration
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.yourdomain.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "[email protected]"
gitlab_rails['smtp_password'] = "email_password"
gitlab_rails['smtp_domain'] = "yourdomain.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false

# GitLab Settings
gitlab_rails['gitlab_email_from'] = '[email protected]'
gitlab_rails['gitlab_email_display_name'] = 'GitLab'
gitlab_rails['gitlab_email_reply_to'] = '[email protected]'

# Security Settings
gitlab_rails['webhook_timeout'] = 10
gitlab_rails['git_timeout'] = 800
gitlab_rails['gitlab_shell_ssh_port'] = 22
gitlab_rails['time_zone'] = 'UTC'

# Performance Settings
gitlab_rails['artifacts_enabled'] = true
gitlab_rails['artifacts_path'] = "/var/opt/gitlab/gitlab-rails/shared/artifacts"
gitlab_rails['lfs_enabled'] = true
gitlab_rails['lfs_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/lfs-objects"

# Backup Settings
gitlab_rails['manage_backup_path'] = true
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
gitlab_rails['backup_keep_time'] = 604800

# Disable components we don't need
postgresql['enable'] = false
redis['enable'] = false
prometheus['enable'] = false
grafana['enable'] = false
alertmanager['enable'] = false
EOF

# Reconfigure GitLab
gitlab-ctl reconfigure

# Start GitLab services
gitlab-ctl start

SSL Certificate Setup

SSL with Let’s Encrypt

What we’re doing: Setting up automatic SSL certificates with Let’s Encrypt for secure HTTPS access.

# Install Certbot
apk add certbot certbot-nginx

# Stop GitLab temporarily to obtain certificate
gitlab-ctl stop nginx

# Obtain SSL certificate
certbot certonly --standalone \
  --preferred-challenges http \
  --email [email protected] \
  --agree-tos \
  --no-eff-email \
  -d gitlab.yourdomain.com

# Configure GitLab to use SSL certificates
cat >> /etc/gitlab/gitlab.rb << 'EOF'

# SSL Configuration
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.yourdomain.com/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.yourdomain.com/privkey.pem"
nginx['ssl_protocols'] = "TLSv1.2 TLSv1.3"
nginx['ssl_ciphers'] = "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384"
nginx['ssl_prefer_server_ciphers'] = "on"
nginx['ssl_session_cache'] = "builtin:1000 shared:SSL:10m"
nginx['ssl_session_timeout'] = "5m"

# HSTS
nginx['hsts_max_age'] = 31536000
nginx['hsts_include_subdomains'] = true
EOF

# Reconfigure GitLab with SSL
gitlab-ctl reconfigure
gitlab-ctl restart

# Set up automatic certificate renewal
echo "0 2 * * * certbot renew --quiet && gitlab-ctl restart nginx" | crontab -

Manual SSL Configuration

What we’re doing: Alternative setup using custom SSL certificates.

# Create SSL directory
mkdir -p /etc/gitlab/ssl
chmod 700 /etc/gitlab/ssl

# Generate self-signed certificate for testing
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/gitlab/ssl/gitlab.yourdomain.com.key \
  -out /etc/gitlab/ssl/gitlab.yourdomain.com.crt \
  -subj "/C=US/ST=State/L=City/O=Organization/CN=gitlab.yourdomain.com"

# Set proper permissions
chmod 600 /etc/gitlab/ssl/gitlab.yourdomain.com.key
chmod 644 /etc/gitlab/ssl/gitlab.yourdomain.com.crt

# Update GitLab configuration for custom SSL
cat >> /etc/gitlab/gitlab.rb << 'EOF'

# Custom SSL Configuration
nginx['ssl_certificate'] = "/etc/gitlab/ssl/gitlab.yourdomain.com.crt"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/gitlab.yourdomain.com.key"
EOF

gitlab-ctl reconfigure

GitLab CI/CD Runner Setup

Installing GitLab Runner

What we’re doing: Setting up GitLab Runner for continuous integration and deployment.

# Install GitLab Runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.alpine.sh | bash
apk add gitlab-runner

# Create runner user
adduser -D -s /bin/bash gitlab-runner
adduser gitlab-runner docker

# Register GitLab Runner
gitlab-runner register \
  --url https://gitlab.yourdomain.com \
  --registration-token YOUR_REGISTRATION_TOKEN \
  --name "Alpine Runner" \
  --executor docker \
  --docker-image alpine:latest \
  --docker-privileged \
  --docker-volumes "/certs/client"

# Configure runner for better performance
cat > /etc/gitlab-runner/config.toml << 'EOF'
concurrent = 4
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "Alpine Docker Runner"
  url = "https://gitlab.yourdomain.com"
  token = "YOUR_RUNNER_TOKEN"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = true
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/certs/client", "/cache"]
    shm_size = 0
EOF

# Start GitLab Runner
rc-update add gitlab-runner default
service gitlab-runner start

Docker Integration

What we’re doing: Configuring Docker for GitLab CI/CD pipelines.

# Install Docker if not already installed
apk add docker

# Configure Docker for GitLab Runner
usermod -aG docker gitlab-runner

# Create Docker configuration for runners
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "insecure-registries": ["gitlab.yourdomain.com:5050"]
}
EOF

# Enable and start Docker
rc-update add docker default
service docker start

# Test Docker access for GitLab Runner
sudo -u gitlab-runner docker run hello-world

GitLab Configuration and Optimization

Performance Optimization

What we’re doing: Optimizing GitLab settings for better performance on Alpine Linux.

# Update GitLab configuration for performance
cat >> /etc/gitlab/gitlab.rb << 'EOF'

# Performance Optimization
puma['worker_processes'] = 2
puma['min_threads'] = 4
puma['max_threads'] = 4
puma['worker_timeout'] = 60
puma['worker_memory_limit_min'] = "400m"
puma['worker_memory_limit_max'] = "650m"

# Sidekiq (background jobs)
sidekiq['max_concurrency'] = 10
sidekiq['min_concurrency'] = 5
sidekiq['queue_groups'] = [
  "urgent_queue",
  "high_queue", 
  "default_queue",
  "low_queue"
]

# Gitaly (Git operations)
gitaly['configuration'] = {
  'storage' => [
    {
      'name' => 'default',
      'path' => '/var/opt/gitlab/git-data/repositories'
    }
  ],
  'logging' => {
    'level' => 'warn'
  },
  'git' => {
    'catfile_cache_size' => 100
  }
}

# Prometheus monitoring
prometheus['enable'] = true
prometheus['scrape_interval'] = 15
prometheus['scrape_timeout'] = 15

# Node Exporter
node_exporter['enable'] = true
EOF

gitlab-ctl reconfigure

Storage Configuration

What we’re doing: Configuring GitLab storage for repositories, artifacts, and uploads.

# Create storage directories
mkdir -p /var/opt/gitlab/git-data/repositories
mkdir -p /var/opt/gitlab/gitlab-rails/shared/artifacts
mkdir -p /var/opt/gitlab/gitlab-rails/uploads
mkdir -p /var/opt/gitlab/backups

# Set proper ownership
chown -R git:git /var/opt/gitlab/git-data
chown -R git:git /var/opt/gitlab/gitlab-rails

# Configure storage paths in GitLab
cat >> /etc/gitlab/gitlab.rb << 'EOF'

# Storage Configuration
git_data_dirs({
  "default" => {
    "path" => "/var/opt/gitlab/git-data"
  }
})

gitlab_rails['artifacts_enabled'] = true
gitlab_rails['artifacts_path'] = "/var/opt/gitlab/gitlab-rails/shared/artifacts"
gitlab_rails['uploads_directory'] = "/var/opt/gitlab/gitlab-rails/uploads"
gitlab_rails['shared_path'] = "/var/opt/gitlab/gitlab-rails/shared"

# LFS Storage
gitlab_rails['lfs_enabled'] = true
gitlab_rails['lfs_storage_path'] = "/var/opt/gitlab/gitlab-rails/shared/lfs-objects"

# Container Registry (optional)
registry_external_url 'https://gitlab.yourdomain.com:5050'
gitlab_rails['registry_enabled'] = true
registry['enable'] = true
EOF

gitlab-ctl reconfigure

Backup and Monitoring

Automated Backup Setup

What we’re doing: Creating automated backup solutions for GitLab data and configuration.

# Create backup script
cat > /usr/local/bin/gitlab-backup.sh << 'EOF'
#!/bin/bash

# GitLab Backup Script
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/gitlab"
LOG_FILE="/var/log/gitlab-backup.log"

# Ensure backup directory exists
mkdir -p $BACKUP_DIR

echo "[$DATE] Starting GitLab backup" >> $LOG_FILE

# Create GitLab application backup
gitlab-backup create BACKUP=$DATE CRON=1

# Backup GitLab configuration
tar -czf $BACKUP_DIR/gitlab-config-$DATE.tar.gz \
  /etc/gitlab/gitlab.rb \
  /etc/gitlab/gitlab-secrets.json

# Backup SSL certificates
if [ -d "/etc/letsencrypt" ]; then
  tar -czf $BACKUP_DIR/ssl-certs-$DATE.tar.gz /etc/letsencrypt
fi

# Remove old backups (keep 7 days)
find /var/opt/gitlab/backups -name "*.tar" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

echo "[$DATE] GitLab backup completed" >> $LOG_FILE

# Optional: Upload to remote storage
# aws s3 sync $BACKUP_DIR s3://your-backup-bucket/gitlab/

echo "[$DATE] Backup process finished" >> $LOG_FILE
EOF

chmod +x /usr/local/bin/gitlab-backup.sh

# Schedule daily backups
echo "0 2 * * * /usr/local/bin/gitlab-backup.sh" | crontab -

# Test backup
/usr/local/bin/gitlab-backup.sh

Monitoring Setup

What we’re doing: Setting up comprehensive monitoring for GitLab health and performance.

# Create GitLab monitoring script
cat > /usr/local/bin/gitlab-monitor.sh << 'EOF'
#!/bin/bash

LOG_FILE="/var/log/gitlab-monitor.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

# Function to log messages
log_message() {
    echo "[$DATE] $1" >> $LOG_FILE
}

# Check GitLab services
SERVICES=("nginx" "postgresql" "redis" "gitlab-runsvdir")
for service in "${SERVICES[@]}"; do
    if ! pgrep $service > /dev/null; then
        log_message "ALERT: $service is not running"
        service $service start
        log_message "Attempted to restart $service"
    fi
done

# Check GitLab application health
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/-/health)
if [ "$HTTP_STATUS" != "200" ]; then
    log_message "ALERT: GitLab health check failed (HTTP $HTTP_STATUS)"
fi

# Check disk space
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
    log_message "WARNING: Disk usage is ${DISK_USAGE}%"
fi

# Check memory usage
MEMORY_USAGE=$(free | grep Mem | awk '{printf "%.0f", $3/$2 * 100.0}')
if [ $MEMORY_USAGE -gt 90 ]; then
    log_message "WARNING: Memory usage is ${MEMORY_USAGE}%"
fi

# Check GitLab background jobs
FAILED_JOBS=$(gitlab-rails runner "puts Sidekiq::RetrySet.new.size" 2>/dev/null || echo "0")
if [ $FAILED_JOBS -gt 10 ]; then
    log_message "WARNING: $FAILED_JOBS failed background jobs"
fi

log_message "Health check completed"
EOF

chmod +x /usr/local/bin/gitlab-monitor.sh

# Schedule monitoring every 5 minutes
echo "*/5 * * * * /usr/local/bin/gitlab-monitor.sh" | crontab -

# Install additional monitoring tools
apk add htop iotop nethogs

# Create system resource monitoring
cat > /usr/local/bin/system-stats.sh << 'EOF'
#!/bin/bash

STATS_FILE="/var/log/system-stats.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$DATE] System Statistics:" >> $STATS_FILE
echo "CPU Usage: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)" >> $STATS_FILE
echo "Memory Usage: $(free -h | grep Mem | awk '{print $3"/"$2}')" >> $STATS_FILE
echo "Disk Usage: $(df -h / | awk 'NR==2 {print $3"/"$2" ("$5")"}')" >> $STATS_FILE
echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')" >> $STATS_FILE
echo "Active Connections: $(netstat -an | grep ESTABLISHED | wc -l)" >> $STATS_FILE
echo "---" >> $STATS_FILE
EOF

chmod +x /usr/local/bin/system-stats.sh

# Schedule hourly system stats
echo "0 * * * * /usr/local/bin/system-stats.sh" | crontab -

Security Configuration

Enhanced Security Settings

What we’re doing: Implementing additional security measures for GitLab.

# Configure GitLab security settings
cat >> /etc/gitlab/gitlab.rb << 'EOF'

# Security Configuration
gitlab_rails['omniauth_enabled'] = false
gitlab_rails['omniauth_allow_single_sign_on'] = false
gitlab_rails['omniauth_block_auto_created_users'] = true

# Rate limiting
gitlab_rails['rack_attack_git_basic_auth'] = {
  'enabled' => true,
  'ip_whitelist' => ['127.0.0.1'],
  'maxretry' => 10,
  'findtime' => 60,
  'bantime' => 3600
}

# Session settings
gitlab_rails['session_expire_delay'] = 10080
gitlab_rails['session_store_key'] = '_gitlab_session'

# Security headers
nginx['proxy_set_headers'] = {
  'X-Forwarded-Proto' => 'https',
  'X-Forwarded-Ssl' => 'on',
  'Host' => '$http_host',
  'X-Real-IP' => '$remote_addr',
  'X-Forwarded-For' => '$proxy_add_x_forwarded_for',
  'X-Frame-Options' => 'SAMEORIGIN',
  'X-Content-Type-Options' => 'nosniff',
  'X-XSS-Protection' => '1; mode=block'
}

# Git security
gitlab_rails['webhook_timeout'] = 10
gitlab_rails['git_timeout'] = 800
EOF

# Configure firewall for GitLab
apk add iptables

# Create GitLab firewall rules
cat > /etc/iptables/gitlab-rules.sh << 'EOF'
#!/bin/sh

# Allow SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Allow HTTP and HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow GitLab SSH (if using custom port)
iptables -A INPUT -p tcp --dport 2222 -j ACCEPT

# Allow container registry (optional)
iptables -A INPUT -p tcp --dport 5050 -j ACCEPT

# Allow established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Allow loopback
iptables -A INPUT -i lo -j ACCEPT

# Drop everything else
iptables -A INPUT -j DROP
EOF

chmod +x /etc/iptables/gitlab-rules.sh
/etc/iptables/gitlab-rules.sh

gitlab-ctl reconfigure

Testing and Validation

GitLab Installation Test

What we’re doing: Creating comprehensive tests to verify GitLab installation and functionality.

cat > /usr/local/bin/test-gitlab.sh << 'EOF'
#!/bin/bash

echo "GitLab Installation Test Suite"
echo "============================="

# Test GitLab services
echo "Testing GitLab services..."
gitlab-ctl status

# Test web interface
echo "Testing web interface..."
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://gitlab.yourdomain.com)
if [ "$HTTP_STATUS" = "200" ]; then
    echo "✓ Web interface accessible"
else
    echo "✗ Web interface failed (HTTP $HTTP_STATUS)"
fi

# Test API
echo "Testing GitLab API..."
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://gitlab.yourdomain.com/api/v4/version)
if [ "$API_STATUS" = "200" ]; then
    echo "✓ GitLab API accessible"
else
    echo "✗ GitLab API failed (HTTP $API_STATUS)"
fi

# Test database connection
echo "Testing database connection..."
gitlab-rails runner "puts ActiveRecord::Base.connection.active?"

# Test Redis connection
echo "Testing Redis connection..."
gitlab-rails runner "puts Gitlab::Redis::Cache.with { |redis| redis.ping }"

# Test GitLab Runner
echo "Testing GitLab Runner..."
gitlab-runner verify

# Test backup functionality
echo "Testing backup functionality..."
gitlab-backup create BACKUP=test_backup

# Test repository creation
echo "Testing repository operations..."
gitlab-rails runner "
  user = User.new(
    name: 'Test User',
    username: 'testuser',
    email: '[email protected]',
    password: 'testpass123'
  )
  user.save!
  puts 'Test user created successfully'
"

echo ""
echo "GitLab test suite completed"
EOF

chmod +x /usr/local/bin/test-gitlab.sh

# Run tests
/usr/local/bin/test-gitlab.sh

Troubleshooting Common Issues

Common GitLab Problems

Service startup issues:

# Check GitLab logs
gitlab-ctl tail

# Check specific service logs
gitlab-ctl tail nginx
gitlab-ctl tail postgresql
gitlab-ctl tail redis

# Restart all services
gitlab-ctl restart

# Reconfigure GitLab
gitlab-ctl reconfigure

Database connection problems:

# Test PostgreSQL connection
sudo -u postgres psql -c "SELECT version();"

# Check PostgreSQL logs
tail -f /var/log/postgresql/postgresql.log

# Reset PostgreSQL password
sudo -u postgres psql -c "ALTER USER gitlab PASSWORD 'new_password';"

SSL certificate issues:

# Check certificate validity
openssl x509 -in /etc/letsencrypt/live/gitlab.yourdomain.com/cert.pem -text -noout

# Renew Let's Encrypt certificate
certbot renew --force-renewal

# Test SSL configuration
curl -vI https://gitlab.yourdomain.com

Performance issues:

# Check system resources
htop
iotop
df -h

# Analyze GitLab performance
gitlab-rails runner "puts Gitlab::Database.postgresql_minimum_supported_version?"

# Review GitLab configuration
gitlab-ctl show-config

Conclusion

You now have a fully functional GitLab server running on Alpine Linux with enterprise-grade features and security. This setup includes:

  • Complete GitLab CE installation with PostgreSQL and Redis backends
  • SSL/TLS encryption with automated certificate management
  • GitLab CI/CD runners for continuous integration and deployment
  • Automated backup solutions with retention policies
  • Comprehensive monitoring and health checking
  • Security hardening with firewall and access controls
  • Performance optimization for production workloads

Your GitLab server is ready for team collaboration, code repository management, and DevOps workflows. Remember to regularly update GitLab, monitor system resources, and maintain your backup procedures as your development team grows.