initial commit

This commit is contained in:
2026-03-16 02:43:58 +08:00
commit 515d11e663
8 changed files with 502 additions and 0 deletions

40
.env.sample Normal file
View File

@@ -0,0 +1,40 @@
# ==========================================
# GITLAB CORE CONFIGURATION
# ==========================================
GITLAB_EXTERNAL_URL=https://git.example.com # http://<SERVER_IP_OR_DOMAIN>
GITLAB_ROOT_PASSWORD=F3&o5@K0 # Initial root password (Min 8 chars)
GITLAB_ROOT_EMAIL=admin@example.com
GITLAB_HOME=./gitlab-data # Persisted data directory
LETSENCRYPT_ENABLE=false # Set to true if using https without a reverse proxy
# ==========================================
# PORTS
# ==========================================
HTTP_PORT=80
HTTPS_PORT=443
SSH_PORT=2224
# ==========================================
# SMTP / EMAIL SETTINGS (Required for production)
# ==========================================
SMTP_ADDRESS=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_DOMAIN=
SMTP_FROM=
# ==========================================
# MONITORING (Prometheus, Exporters)
# ==========================================
GITLAB_MONITORING_ENABLE=false # Set to 'false' to save ~1GB-1.5GB of RAM on smaller servers
# ==========================================
# HIGH PERFORMANCE TUNING
# NOTE: Run auto-tune.sh to optimize these for your hardware
# ==========================================
PUMA_WORKERS=2
PUMA_THREADS=4
SIDEKIQ_CONCURRENCY=10
POSTGRES_SHARED_BUFFERS=256
POSTGRES_WORKERS=2

30
.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# ==========================================
# GitLab Deployment .gitignore
# ==========================================
# Environment Variables
.env
# GitLab Application Data
# Contains the PostgreSQL database, repositories, logs, and registry data.
# This folder will grow very large and contains all your private code/data.
gitlab-data/
# GitLab Runner Configuration
# Ignore all files inside the runner configuration directory to prevent
# leaking the config.toml file and authentication tokens...
runner-config/*
# But force Git to track the empty directory itself using .gitkeep.
# This prevents the Docker "Root Owner" permission trap.
!runner-config/.gitkeep
# ==========================================
# Common OS & Editor Files (Recommended)
# ==========================================
.DS_Store
Thumbs.db
.vscode/
.idea/
*.swp
*.swo

90
README.md Normal file
View File

@@ -0,0 +1,90 @@
# Self-Hosted GitLab Docker Deployment
Welcome to the automated, self-hosted GitLab deployment project! This setup is designed to be as "one-click" as possible while remaining highly configurable. It automatically tunes itself to your server's hardware and simplifies the setup of CI/CD runners.
*Last Updated: 1404/12/24 (2026/03/15)*
## Architecture Overview
This project uses Docker Compose to spin up two main services:
1. **GitLab Server**: The main web application, database, and background workers.
2. **GitLab Runner**: A background service that runs your CI/CD pipeline jobs (like testing and deploying code).
**Directory Structure:**
- `run.sh`: The main launcher script. It checks your config and starts the server.
- `.env.sample`: A template for your configuration variables.
- `docker-compose.yml`: The blueprint that tells Docker how to build the services.
- `scripts/auto-tune.sh`: A smart script that calculates the perfect math variables (like $RAM \times 0.25$ for database buffers) to prevent your server from crashing.
- `scripts/setup-runner.sh`: Automates the tedious process of linking the GitLab Runner to your GitLab Server.
- `runner-config/`: An empty folder where Docker will safely store your runner's configuration.
---
## Prerequisites
- A server running Linux (Ubuntu/Debian recommended).
- **Docker** and **Docker Compose** installed.
- Minimum hardware: 4GB RAM and 2 CPU cores (8GB RAM + 4 Cores highly recommended).
---
## Step-by-Step Installation Guide
### Step 1: Prepare the Configuration
Before starting, GitLab needs to know your domain name, passwords, and email settings.
1. Make a copy of the sample environment file:
```bash
cp .env.sample .env
```
2. Open `.env` in your favorite text editor (e.g., `nano .env`).
3. **CRITICAL:** Change `GITLAB_EXTERNAL_URL` to your server's IP address (e.g., `http://192.168.1.50`) or domain name (e.g., `https://git.yourdomain.com`).
4. Update `GITLAB_ROOT_PASSWORD` (must be at least 8 characters).
### Step 2: Run the Orchestrator
We have provided a unified script to validate your configuration, optimize your server, and launch GitLab.
1. Make the script executable:
```bash
chmod +x run.sh
```
2. Execute the script:
```bash
./run.sh
```
3. **What happens next?**
- The script will verify that you filled out the `.env` file correctly.
- It will ask if you want to run the **Auto-Tuner**. Press `y`! The auto-tuner will detect your CPU and RAM and dynamically adjust GitLab's internal memory settings in your `.env` file so it doesn't consume all your server's resources.
- Finally, it triggers Docker to download and start GitLab.
### Step 3: Wait for GitLab to Boot
GitLab is an enterprise-grade application. Once the script finishes, **you must wait 3 to 5 minutes**.
If you navigate to your URL too early, you will see a **502 Bad Gateway** error. This simply means the internal web server is up, but the database and backend application are still loading. Grab a coffee and refresh the page in a few minutes.
### Step 4: Log In
Once the web interface loads:
- **Username:** `root`
- **Password:** The password you set in `GITLAB_ROOT_PASSWORD` inside your `.env` file.
### Step 5: Setup the CI/CD Runner
To run automated tasks (like building Docker images or running tests), you need to register your GitLab Runner.
1. Go to your GitLab Web UI.
2. Navigate to **Admin Area** -> **CI/CD** -> **Runners**.
3. Click **New instance runner** and copy the **Authentication Token**.
4. Go back to your server terminal and run:
```bash
bash ./scripts/setup-runner.sh
```
5. Follow the prompts! The script will ask for your GitLab URL and the token you just copied. It will automatically register the runner and configure it to match your server's CPU cores.
---
## Maintenance & Troubleshooting
- **How do I stop GitLab?**
Run `docker compose down` in this directory.
- **How do I view the logs?**
Run `docker compose logs -f gitlab` to see real-time background processes.
- **Permission Denied on Runner Setup?**
If the `setup-runner.sh` script throws a permission error, it means Docker created files as the `root` user. Simply run the script with sudo: `sudo bash ./scripts/setup-runner.sh`.

86
docker-compose.yml Normal file
View File

@@ -0,0 +1,86 @@
services:
gitlab:
image: 'gitlab/gitlab-ce:latest'
container_name: gitlab-server
restart: always
networks:
- gitlab_net
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url '${GITLAB_EXTERNAL_URL}'
gitlab_rails['initial_root_password'] = '${GITLAB_ROOT_PASSWORD}'
letsencrypt['enable'] = ${LETSENCRYPT_ENABLE}
letsencrypt['contact_emails'] = ['${GITLAB_ROOT_EMAIL}']
letsencrypt['auto_renew'] = true
letsencrypt['auto_renew_hour'] = 0
letsencrypt['auto_renew_minute'] = 30
letsencrypt['auto_renew_day_of_month'] = "*/7"
gitlab_rails['gitlab_shell_ssh_port'] = ${SSH_PORT}
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "${SMTP_ADDRESS}"
gitlab_rails['smtp_port'] = ${SMTP_PORT}
gitlab_rails['smtp_user_name'] = "${SMTP_USER}"
gitlab_rails['smtp_password'] = "${SMTP_PASSWORD}"
gitlab_rails['smtp_domain'] = "${SMTP_DOMAIN}"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
gitlab_rails['gitlab_email_from'] = '${SMTP_FROM}'
gitlab_rails['gitlab_email_reply_to'] = '${SMTP_FROM}'
# ==========================================
# MONITORING & METRICS
# ==========================================
prometheus['enable'] = ${GITLAB_MONITORING_ENABLE}
alertmanager['enable'] = ${GITLAB_MONITORING_ENABLE}
gitlab_exporter['enable'] = ${GITLAB_MONITORING_ENABLE}
node_exporter['enable'] = ${GITLAB_MONITORING_ENABLE}
redis_exporter['enable'] = ${GITLAB_MONITORING_ENABLE}
postgres_exporter['enable'] = ${GITLAB_MONITORING_ENABLE}
# ==========================================
# HIGH PERFORMANCE TUNING
# ==========================================
puma['worker_processes'] = ${PUMA_WORKERS}
puma['min_threads'] = ${PUMA_THREADS}
puma['max_threads'] = ${PUMA_THREADS}
sidekiq['max_concurrency'] = ${SIDEKIQ_CONCURRENCY}
postgresql['shared_buffers'] = "${POSTGRES_SHARED_BUFFERS}MB"
postgresql['max_worker_processes'] = ${POSTGRES_WORKERS}
ports:
- '${HTTP_PORT}:80'
- '${HTTPS_PORT}:443'
- '${SSH_PORT}:22'
volumes:
- '${GITLAB_HOME}/config:/etc/gitlab'
- '${GITLAB_HOME}/logs:/var/log/gitlab'
- '${GITLAB_HOME}/data:/var/opt/gitlab'
shm_size: '${POSTGRES_SHARED_BUFFERS}m'
gitlab-runner:
image: gitlab/gitlab-runner:latest
container_name: gitlab-runner
restart: always
networks:
- gitlab_net
depends_on:
- gitlab
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./runner-config:/etc/gitlab-runner
networks:
gitlab_net:
name: gitlab_net
driver: bridge

73
run.sh Normal file
View File

@@ -0,0 +1,73 @@
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
echo -e "${CYAN}==========================================${NC}"
echo -e "${CYAN} GitLab Deployment Bootstrapper ${NC}"
echo -e "${CYAN}==========================================${NC}\n"
if [ ! -f ".env" ]; then
echo -e "${YELLOW}[WARNING] No .env file found.${NC}"
echo -e "Creating one from .env.sample..."
cp .env.sample .env
echo -e "\n${RED}[ACTION REQUIRED] A new .env file has been created.${NC}"
echo -e "${RED}Please open the .env file, fill in your specific settings (especially GITLAB_EXTERNAL_URL), and run this script again.${NC}"
exit 1
fi
echo -e "${GREEN}[OK] .env file found. Validating configuration...${NC}"
EXTERNAL_URL=$(grep '^GITLAB_EXTERNAL_URL=' .env | cut -d '=' -f2-)
ROOT_PASSWORD=$(grep '^GITLAB_ROOT_PASSWORD=' .env | cut -d '=' -f2-)
if [[ -z "$EXTERNAL_URL" || "$EXTERNAL_URL" == *"<"* || "$EXTERNAL_URL" == *"example.com"* ]]; then
echo -e "\n${RED}[ERROR] GITLAB_EXTERNAL_URL is invalid or still using the default placeholder!${NC}"
echo -e "${YELLOW}Current value: $EXTERNAL_URL${NC}"
echo -e "${YELLOW}Please edit your .env file and set it to a valid URL (e.g., http://192.168.1.50 or https://gitlab.yourdomain.com).${NC}"
exit 1
fi
if [[ ! "$EXTERNAL_URL" =~ ^https?:// ]]; then
echo -e "\n${RED}[ERROR] GITLAB_EXTERNAL_URL must start with exactly 'http://' or 'https://'.${NC}"
exit 1
fi
if [ ${#ROOT_PASSWORD} -lt 8 ]; then
echo -e "\n${RED}[ERROR] GITLAB_ROOT_PASSWORD must be at least 8 characters long!${NC}"
echo -e "${YELLOW}GitLab enforces a strict 8-character minimum for all passwords.${NC}"
exit 1
fi
echo -e "${GREEN}[OK] Critical variables are valid.${NC}\n"
read -p "Do you want to run the auto-tune script to optimize GitLab for this server's RAM/CPU? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
if [ -f "./scripts/auto-tune.sh" ]; then
bash ./scripts/auto-tune.sh
else
echo -e "${YELLOW}[WARNING] ./scripts/auto-tune.sh not found. Skipping tuning.${NC}"
fi
fi
echo -e "\n${CYAN}Starting GitLab via Docker Compose...${NC}"
docker compose up -d
if [ $? -eq 0 ]; then
echo -e "\n${GREEN}==========================================${NC}"
echo -e "${GREEN} SUCCESS! GitLab is now booting up. ${NC}"
echo -e "${GREEN}==========================================${NC}"
echo -e "\n${YELLOW}================= READ THIS =================${NC}"
echo -e "1. GitLab Omnibus is huge. It takes roughly $3$ to $5$ minutes to fully start."
echo -e "2. If you visit $EXTERNAL_URL right now, you might see a '502 Bad Gateway' error. This is normal. Just wait."
echo -e "3. Once you can log in to the web interface, you can register your runner by executing:"
echo -e " ${CYAN}bash ./scripts/setup-runner.sh${NC}"
echo -e "${YELLOW}=============================================${NC}\n"
else
echo -e "\n${RED}[ERROR] Docker Compose failed to start the containers.${NC}"
exit 1
fi

0
runner-config/.gitkeep Normal file
View File

104
scripts/auto-tune.sh Normal file
View File

@@ -0,0 +1,104 @@
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
echo "=========================================="
echo " GitLab Dynamic Resource Auto-Tuner "
echo "=========================================="
CORES=$(nproc 2>/dev/null || echo 2)
RAM_MB=$(free -m | awk '/^Mem:/{print $2}')
RAM_GB=$(awk '/MemTotal/ {printf "%.0f", $2/1024/1024}' /proc/meminfo)
echo "Detected Hardware: $CORES CPU Cores, ${RAM_GB}GB RAM (${RAM_MB}MB)"
# PUMA WORKERS: 1 per CPU core (Minimum 2)
PUMA_WORKERS=$CORES
if [ "$PUMA_WORKERS" -lt 2 ]; then PUMA_WORKERS=2; fi
# PUMA THREADS: Usually optimal at 4
PUMA_THREADS=4
# SIDEKIQ CONCURRENCY: 5 background jobs per CPU core (Min 10)
SIDEKIQ_CONCURRENCY=$((CORES * 5))
if [ "$SIDEKIQ_CONCURRENCY" -lt 10 ]; then SIDEKIQ_CONCURRENCY=10; fi
# POSTGRES WORKERS: Match CPU cores
POSTGRES_WORKERS=$CORES
# POSTGRES SHARED BUFFERS: ~12.5% of total RAM in MB (Min 256MB)
POSTGRES_SHARED_BUFFERS=$((RAM_MB / 8))
if [ "$POSTGRES_SHARED_BUFFERS" -lt 256 ]; then POSTGRES_SHARED_BUFFERS=256; fi
update_env() {
local key=$1
local val=$2
local env_file=".env"
if [ ! -f "$env_file" ]; then
if ! touch "$env_file" 2>/dev/null; then
echo -e "\n${RED}[ERROR] Permission denied: Cannot create $env_file.${NC}"
echo -e "${RED}The script failed. Try running it with sudo.${NC}"
exit 1
fi
fi
if grep -q "^${key}=" "$env_file"; then
if ! sed -i "s/^${key}=.*/${key}=${val}/" "$env_file" 2>/dev/null; then
echo -e "\n${RED}[ERROR] Permission denied: sed cannot modify $env_file.${NC}"
echo -e "${RED}The script failed. This usually happens if .env is owned by root. Try running the script with sudo.${NC}"
exit 1
fi
else
if ! echo "${key}=${val}" >> "$env_file" 2>/dev/null; then
echo -e "\n${RED}[ERROR] Permission denied: Cannot append to $env_file.${NC}"
echo -e "${RED}The script failed. Try running it with sudo.${NC}"
exit 1
fi
fi
}
echo ""
echo "=========================================="
echo " Calculated Optimal Settings:"
echo "=========================================="
echo " PUMA_WORKERS=${PUMA_WORKERS}"
echo " PUMA_THREADS=${PUMA_THREADS}"
echo " SIDEKIQ_CONCURRENCY=${SIDEKIQ_CONCURRENCY}"
echo " POSTGRES_WORKERS=${POSTGRES_WORKERS}"
echo " POSTGRES_SHARED_BUFFERS=${POSTGRES_SHARED_BUFFERS}"
echo "=========================================="
echo ""
read -p "Do you want to apply these settings to your .env file? (y/n): " CONFIRM_ENV
if [[ "$CONFIRM_ENV" =~ ^[Yy]$ ]]; then
echo "Updating variables in .env file..."
update_env "PUMA_WORKERS" "$PUMA_WORKERS"
update_env "PUMA_THREADS" "$PUMA_THREADS"
update_env "SIDEKIQ_CONCURRENCY" "$SIDEKIQ_CONCURRENCY"
update_env "POSTGRES_WORKERS" "$POSTGRES_WORKERS"
update_env "POSTGRES_SHARED_BUFFERS" "$POSTGRES_SHARED_BUFFERS"
echo -e "${GREEN}-> Success: .env file updated successfully.${NC}"
else
echo "-> Skipped: No changes were made to the .env file."
fi
echo ""
read -p "Do you want to start/update the Docker containers now? (y/n): " CONFIRM_DOCKER
if [[ "$CONFIRM_DOCKER" =~ ^[Yy]$ ]]; then
echo "Starting containers with 'docker compose up -d'..."
docker compose up -d
echo ""
echo "=========================================="
echo " GitLab is now applying the configuration."
echo "=========================================="
else
echo "-> Skipped: Containers were not started/updated."
echo "-> Note: You can apply these changes later by running: docker compose up -d"
fi

79
scripts/setup-runner.sh Normal file
View File

@@ -0,0 +1,79 @@
#!/bin/bash
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "=========================================="
echo " GitLab Runner Automated Setup Script "
echo "=========================================="
echo ""
read -p "Enter your GitLab URL / SERVER IP (e.g., http://git.amiirkhl.ir): " GITLAB_URL
read -p "Enter your Runner Token (starts with glrt-): " RUNNER_TOKEN
echo ""
echo "Registering runner to $GITLAB_URL..."
docker exec gitlab-runner gitlab-runner register \
--non-interactive \
--url "$GITLAB_URL" \
--token "$RUNNER_TOKEN" \
--executor "docker" \
--docker-image "alpine:latest" \
--description "Auto-Registered Docker Runner" \
--docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
--docker-network-mode "gitlab_net"
if [ $? -eq 0 ]; then
echo -e "\n${GREEN}==========================================${NC}"
echo -e "${GREEN} SUCCESS! Runner registered successfully. ${NC}"
echo -e "${GREEN}==========================================${NC}"
echo ""
echo "--- Tuning Runner for Host Resources ---"
CORES=$(nproc 2>/dev/null || echo 1)
RAM_GB=$(awk '/MemTotal/ {printf "%.0f", $2/1024/1024}' /proc/meminfo 2>/dev/null || echo 2)
echo "Detected $CORES CPU Cores and ${RAM_GB}GB RAM."
CONCURRENT_JOBS=$CORES
if [ "$CONCURRENT_JOBS" -lt 1 ]; then
CONCURRENT_JOBS=1
fi
echo "Applying runner concurrency limit of $CONCURRENT_JOBS..."
CONFIG_FILE="./runner-config/config.toml"
if [ -f "$CONFIG_FILE" ]; then
if ! sed -i "s/^concurrent = .*/concurrent = $CONCURRENT_JOBS/" "$CONFIG_FILE" 2>/dev/null; then
echo -e "\n${RED}[ERROR] Permission denied: sed cannot modify $CONFIG_FILE.${NC}"
echo -e "${RED}The script failed. This usually happens if config.toml is owned by root (created by Docker).${NC}"
echo -e "${RED}Try running this script with sudo.${NC}"
exit 1
fi
if ! docker restart gitlab-runner >/dev/null 2>&1; then
echo -e "\n${RED}[ERROR] Permission denied: Cannot restart docker container.${NC}"
echo -e "${RED}Try running this script with sudo.${NC}"
exit 1
fi
echo -e "${GREEN}-> Runner restarted to apply new concurrency limit.${NC}"
else
echo -e "\n${YELLOW}[WARNING] config.toml not found at $CONFIG_FILE.${NC}"
echo -e "${YELLOW}-> Could not set concurrency automatically.${NC}"
fi
echo -e "\n${GREEN}==========================================${NC}"
echo -e "${GREEN} SETUP FULLY COMPLETE! ${NC}"
echo -e "${GREEN}==========================================${NC}\n"
else
echo -e "\n${RED}==========================================${NC}"
echo -e "${RED} ERROR! Failed to register the runner. ${NC}"
echo -e "${RED} Please check your URL and Token. ${NC}"
echo -e "${RED}==========================================${NC}\n"
exit 1
fi