How to Self-Host GitLab for Free on Windows Using WSL- (Localhost)

I tried creating my own AWS account to host GitLab, but it didn't work out 😅. The free tier VM, t2.micro, couldn't support the full GitLab 😕, and the VM kept crashing 💥, so I hosted my own GitLab instead 😊.
You can also host your own GitLab with a custom domain. Let's get started building it! 🚀💻✨
Setting Up GitLab CE in WSL with Docker (Localhost → gitlab.example.in)
Setting Up GitLab CE in WSL with Docker (Localhost → gitlab.example.in) 🎉🐳
The steps below will guide you through hosting GitLab Community Edition (CE) locally in WSL2 using Docker and accessing it via a custom domain gitlab.example.in mapped to localhost. We will skip HTTPS for simplicity and remove unnecessary services to keep it lightweight. 🚀🔧
1️⃣ Prerequisites 📋
WSL2/Ubuntu app installed on Windows 🖥️
Docker installed and configured for WSL2 backend or within Ubuntu 🐋
Basic familiarity with terminal commands 💻
Optional: A text editor like nano or Vim. ✏️
2️⃣ Map Custom Domain to Localhost 🌐
We want to use gitlab.example.in in our browser instead of localhost. 🌍
Open the Windows hosts file:
C:\Windows\System32\drivers\etc\hosts📂Add the following line: ✍️
127.0.0.1 gitlab.example.inSave the file.
✅ Now, http://gitlab.example.in will resolve to your local WSL instance.
3️⃣ Create a Minimal Docker Compose File
Create a directory for GitLab Docker setup:
mkdir ~/gitlab-docker
cd ~/gitlab-docker
Create a file docker-compose.yml:
version: '3.8'
services:
gitlab:
image: gitlab/gitlab-ce:latest
container_name: gitlab
restart: always
hostname: gitlab.example.in
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://gitlab.example.in' # Use HTTP only
nginx['redirect_http_to_https'] = false # Disable HTTPS redirect
prometheus['enable'] = false # Disable Prometheus
gitlab_kas['enable'] = false # Disable Kubernetes agent
letsencrypt['enable'] = false # Disable LetsEncrypt
registry_nginx['enable'] = false # Disable Docker registry
gitlab_rails['gitlab_shell_ssh_port'] = 22
ports:
- "80:80"
- "22:22"
#- "443:443" #Keeping it commented as we are not using HTTPS which requires Certificate and
#domain registered
volumes:
- ./gitlab/config:/etc/gitlab
- ./gitlab/logs:/var/log/gitlab
- ./gitlab/data:/var/opt/gitlab
✅ Explanation
external_url 🌐 → We use HTTP only (
http://gitlab.example.com) for local testing. 🧪Disabled services 🚫 → Prometheus, KAS, Let's Encrypt, and registry are disabled to reduce memory footprint. 🧠
Volumes 📦 → Persist configuration, logs, and repository data. 🗂️
Ports 🔌 → HTTP on 80, SSH on 22 for Git operations. 🛠️
4️⃣ Start GitLab
docker-compose up -d
This will pull the latest GitLab CE image and start the container.
The first start may take a few minutes to download images
Check container status:
docker ps
docker exec -it gitlab gitlab-ctl status
5️⃣ Access GitLab
Open your browser and navigate to:
http://gitlab.example.inThe first login will prompt you to enter the uname password.
In GitLab Omnibus Docker, the initial root password is automatically generated and stored in a file inside the container. You can retrieve it instead of setting it manually.
Access the GitLab container
docker exec -it gitlab /bin/bash cat /etc/gitlab/initial_root_passwordCopy the password and log in (default username = root)
The initial_root_password file is only generated once during the first startup.
If you forget it later, you can reset the root password via:
docker exec -it gitlab gitlab-rails console # then use: user = User.where(id: 1).first; user.password = 'newpassword'; user.save!
6️⃣ Push Your Local Repository
Step 6.1 — Create a project
In GitLab UI, click New Project → Create blank project
Name it e.g.,
first-repo
Step 6.2 — Initialize local repo
cd ~/first-repo
git init
git add .
git commit -m "Initial commit"
Step 6.3 — Add GitLab remote
git remote add origin http://gitlab.example.in/first-repo
Step 6.4—Authenticate using Personal Access Token (PAT)
Go to User Settings → Access Tokens
Create token with
write_repositoryscopeUse the token as a password when Git prompts during
git push.
Step 6.5 — Push to GitLab
If the remote is empty:
git push -u origin main
If the remote has a default README and you get conflicts:
git fetch origin
git rebase origin/main
# Resolve any conflicts
git push -u origin main
7️⃣ Optional: Using Nano ✏️
During conflict resolution, Git may open files in nano. 📝
Exit nano: 🚪
Ctrl + X→ exit ❌Y→ save changes 💾N→ discard changes 🚫
8️⃣ Summary 📋
GitLab CE now runs locally in Docker on WSL. 🐳
Access via
http://gitlab.example.in. 🌐Minimal setup: no HTTPS, no monitoring, only essential services. 🔧
Local projects can be pushed via HTTP using Personal Access Token. 🔑
Docker volumes ensure data persistence. 📦
9️⃣ Next Steps 🚀
Add more repositories for microservices. 📂
Experiment with GitLab CI/CD using
.gitlab-ci.yml. 🤖Optionally enable SSH push for convenience. 🔑
Once confident, move to production VM with HTTPS & monitoring enabled. 🌐🔍
This setup is perfect for learning DevOps, GitLab administration, and CI/CD pipelines without worrying about certificates or resource-heavy monitoring. 🎓💻

