[{"data":1,"prerenderedAt":165},["ShallowReactive",2],{"seo-verification":3,"blog-installer-gitlab-ce-vps-en":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"title":9,"excerpt":10,"readTime":11,"views":12,"isPinned":13,"publishedAt":14,"category":15,"categories":20,"featuredImage":22,"bgImage":23,"posterImage":24,"relatedSolution":22,"intro":25,"sections":26,"ctaTitle":124,"ctaBody":125,"ctaButton":126,"ctaUrl":127,"relatedPosts":128},235,"installer-gitlab-ce-vps","Install GitLab CE on a VPS: complete guide","Deploy GitLab CE on your VPS with Docker Compose: git forge, built-in CI\u002FCD, private Docker registry and project management — self-hosted.",8,0,false,"2026-08-07T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":18},3,"Deployment","deploiement","bg-success\u002F10 text-success",[21],{"id":16,"name":17,"slug":18,"color":19,"icon":18},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Finstaller-gitlab-ce-vps-poster.svg","GitHub and Bitbucket host your repositories, but they set the rules: metered CI minutes, uncertain code ownership, pricing that rises with team size. GitLab CE (Community Edition, MIT\u002FEE Core licence) brings together on a single server a complete git forge, a CI\u002FCD engine with no imposed minute quotas, a private Docker registry and wikis — all without a SaaS subscription. This guide shows you how to install it in under thirty minutes on a VPS with Docker Compose, configure SMTP, connect a runner and avoid the classic pitfalls: a misconfigured GITLAB_OMNIBUS_CONFIG, SSL that expires for lack of ACME, an unregistered runner.",[27,31,43,46,77,80,83,121],{"type":28,"title":29,"body":30},"h2","Why GitLab CE instead of GitHub or Bitbucket","GitHub and Bitbucket are managed services: convenient to start with, but their pricing evolves with team size, CI minutes are capped on free plans, and your code lives on third-party infrastructure. GitLab CE reverses this equation: you deploy the forge on your VPS, you retain full control of the code and data, and CI\u002FCD is included without minute quotas imposed by a third party — only your machine's capacity limits the number of parallel jobs. For an agency or a development team that bills clients or handles sensitive data, this control is often non-negotiable. GitLab CE is today one of the most widely deployed self-hosted git forges: its codebase is public, its core is free, and ten years of existence have earned it an active contributor community.",{"type":32,"title":33,"items":34},"ul","What GitLab CE includes out of the box",[35,36,37,38,39,40,41,42],"**Complete git forge**: private and public repositories, merge requests, code review, branch protection and CODEOWNERS.","**Integrated CI\u002FCD** with no imposed minute limit: YAML pipelines (`.gitlab-ci.yml`), environments, deploy tokens and artifacts.","**Private Docker registry** hosted on your domain: `docker pull git.yourdomain.com\u002Fgroup\u002Fimage:tag` without a Docker Hub account.","**Wikis and pages** per project and per group, with full Markdown rendering.","**Issue tracking and milestones**: kanban board, labels, iterations and burndown charts included.","**Parallel runners**: register as many runners as you want on your infrastructure or CI workers.","**Webhooks** to notify a third-party tool (Slack, PagerDuty, your deployment server) on every push or merge.","**Granular RBAC** with five access levels (Guest, Reporter, Developer, Maintainer, Owner) and optional LDAP\u002FSAML support.",{"type":28,"title":44,"body":45},"Prerequisites: what you need before you start","GitLab CE is memory-intensive — it is one of its most cited drawbacks compared to Forgejo or Gitea. Plan for **4 GB of RAM minimum** for light usage (fewer than ten active users); **8 GB are recommended** as soon as you add runners on the same machine or enable the Docker registry. Below 4 GB, Puma and Sidekiq compete for memory and GitLab responds with 502 under load. For storage, allow at least 20 GB for the installation and initial repositories — plan for 50 GB if you intend to store Docker images in the registry. You also need: a domain name pointing to the VPS IP (for example `git.yourdomain.com`) for Let's Encrypt to issue a TLS certificate; ports 80, 443 and 22 open in your firewall (port 22 is used by GitLab for SSH pushes — if your system SSH daemon also listens on 22, move it to another port); Docker Engine and the Compose v2 plugin installed (`docker compose version` should return `v2.x`).",{"type":47,"title":48,"steps":49},"steps","From installation to your first project",[50,53,56,59,62,65,68,71,74],{"title":51,"body":52},"Create the directory structure","Create a dedicated folder and the three persistent volumes GitLab uses: `mkdir -p \u002Fopt\u002Fgitlab\u002F{config,logs,data}`. These directories will be mounted into the container; without them, configuration and repositories vanish on every `docker compose down`.",{"title":54,"body":55},"Write the docker-compose.yml file","Create `\u002Fopt\u002Fgitlab\u002Fdocker-compose.yml`. The `GITLAB_OMNIBUS_CONFIG` key concentrates all instance-specific configuration — replace `git.yourdomain.com` with your actual domain. Define the gitlab service with image `gitlab\u002Fgitlab-ce:17.2.1-ce.0`, `restart: unless-stopped`, the hostname, environment variables (including `GITLAB_OMNIBUS_CONFIG` containing `external_url`, Let's Encrypt settings and SMTP parameters), ports 80, 443 and 22, volumes for `\u002Fetc\u002Fgitlab`, `\u002Fvar\u002Flog\u002Fgitlab` and `\u002Fvar\u002Fopt\u002Fgitlab`, `shm_size: 256m` and `env_file: .env`. **Important note**: the `external_url` value determines whether GitLab generates `http:\u002F\u002F` or `https:\u002F\u002F` URLs, and whether Let's Encrypt is attempted. It must exactly match a domain resolvable from the Internet — an incorrect value is the leading cause of access errors.",{"title":57,"body":58},"Set GITLAB_OMNIBUS_CONFIG","Inside `GITLAB_OMNIBUS_CONFIG`, define at minimum: `external_url 'https:\u002F\u002Fgit.yourdomain.com'`; `letsencrypt['enable'] = true` with `letsencrypt['contact_emails'] = ['admin@yourdomain.com']`; SMTP parameters — `gitlab_rails['smtp_enable'] = true`, address, port 587, user name, `gitlab_rails['smtp_password'] = ENV['GITLAB_SMTP_PASSWORD']`, authentication `login`, `smtp_enable_starttls_auto = true`, `gitlab_email_from`; and if you enable the registry: `registry_external_url 'https:\u002F\u002Fregistry.yourdomain.com'`. All these lines must be **inside** the `GITLAB_OMNIBUS_CONFIG` block, not as separate environment variables — a key outside the block is silently ignored.",{"title":60,"body":61},"Create the .env file for secrets","Create `\u002Fopt\u002Fgitlab\u002F.env` and restrict its permissions: `touch \u002Fopt\u002Fgitlab\u002F.env && chmod 600 \u002Fopt\u002Fgitlab\u002F.env`. Add your sensitive variables — at minimum `GITLAB_SMTP_PASSWORD=your_smtp_password`. Never put a password in plain text in the Compose file: it will end up versioned or shared. Add `.env` to your `.gitignore` if you version the configuration.",{"title":63,"body":64},"Start GitLab and wait for initialisation","Launch the stack: `docker compose -f \u002Fopt\u002Fgitlab\u002Fdocker-compose.yml up -d`. The first start takes time: GitLab initialises the database, compiles assets and configures Nginx and Puma. **Wait about 5 minutes** before accessing the web interface. Follow progress with `docker compose -f \u002Fopt\u002Fgitlab\u002Fdocker-compose.yml logs -f gitlab` and wait for the `gitlab Reconfigured!` message.",{"title":66,"body":67},"Retrieve the initial root password","On first initialisation, GitLab generates a temporary password for the `root` account. Retrieve it with: `docker exec -it gitlab-gitlab-1 grep 'Password:' \u002Fetc\u002Fgitlab\u002Finitial_root_password`. This file is **automatically deleted 24 hours** after the first start — note the password immediately.",{"title":69,"body":70},"Log in, change the password and disable open registration","Open `https:\u002F\u002Fgit.yourdomain.com` in your browser. Log in with `root` and the password retrieved above. Go to **User Settings → Password** and set a new strong password. Create your first non-root user: **Admin Area → Users → New User**. For internal use, disable public sign-up: **Admin Area → Settings → General → Sign-up restrictions → uncheck 'Sign-up enabled'**.",{"title":72,"body":73},"Register a GitLab Runner","CI\u002FCD pipelines require at least one runner. Install `gitlab-runner` on the VPS or a dedicated machine (download the binary from the official GitLab Runner page). Retrieve the registration token from **Admin Area → Runners** (shared) or from your project's **Settings → CI\u002FCD → Runners** (project runner). Register: `gitlab-runner register --url https:\u002F\u002Fgit.yourdomain.com --registration-token YOUR_TOKEN --executor docker --docker-image alpine:latest`. Once registered, the runner appears green in the interface and your `.gitlab-ci.yml` pipelines can execute.",{"title":75,"body":76},"Verify email delivery","Test SMTP from the GitLab Rails console: `docker exec -it gitlab-gitlab-1 gitlab-rails console` then type `Notify.test_email('your@email.com', 'Test GitLab', 'Hello').deliver_now`. If the email does not arrive, check that `smtp_*` keys are inside `GITLAB_OMNIBUS_CONFIG` and review the logs: `docker exec -it gitlab-gitlab-1 tail -f \u002Fvar\u002Flog\u002Fgitlab\u002Fgitlab-rails\u002Fproduction.log`.",{"type":78,"body":79},"tip","**Automatic backups.** GitLab ships a full backup command (repositories, database, uploads): `docker exec -t gitlab-gitlab-1 gitlab-backup create`. Schedule it in `crontab -e` with `0 3 * * * docker exec -t gitlab-gitlab-1 gitlab-backup create CRON=1`. Archives are created in `\u002Fvar\u002Fopt\u002Fgitlab\u002Fbackups` (mounted at `\u002Fopt\u002Fgitlab\u002Fdata\u002Fbackups` on the host) and timestamped. Sync this folder to external storage (S3, rclone) — a local backup is not a backup.",{"type":28,"title":81,"body":82},"Troubleshooting: the three most common failures","**502 Bad Gateway at startup.** GitLab takes about 5 minutes to become fully operational. If the 502 persists, check that Puma has started: `docker exec gitlab-gitlab-1 gitlab-ctl status puma`. Insufficient RAM is the most frequent cause — ensure you have at least 4 GB available. **SMTP not working.** Check first: is the `gitlab_rails['smtp_*']` block inside `GITLAB_OMNIBUS_CONFIG`, not defined as a separate environment variable? Incorrect indentation in the YAML or a key outside the omnibus block is silent — GitLab starts normally but ignores the SMTP configuration. Test from the Rails console (step 9). **Runner not connected.** If the runner shows grey or offline, check it can reach your instance: `gitlab-runner verify --url https:\u002F\u002Fgit.yourdomain.com`. A self-signed TLS certificate or a domain not resolvable from the runner machine are the usual causes. Also check that the token used at registration is for the correct level (instance, group or project).",{"type":84,"title":85,"headers":86,"rows":90},"comparison","GitLab CE, Forgejo or Gitea: how to choose",[87,88,89],"Criterion","GitLab CE","Forgejo \u002F Gitea",[91,95,99,103,107,109,113,117],[92,93,94],"Licence","MIT \u002F EE Core","MIT",[96,97,98],"Idle RAM","300–600 MB (Puma + Sidekiq)","30–50 MB",[100,101,102],"Native CI\u002FCD","Yes (`.gitlab-ci.yml`, runners)","Forgejo: yes via Woodpecker CI; Gitea: no native CI",[104,105,106],"Integrated Docker registry","Yes","Forgejo: yes; Gitea: not native",[108,105,105],"Per-project wikis",[110,111,112],"LDAP \u002F SAML","Yes (CE)","Forgejo: yes; Gitea: LDAP yes, SAML no",[114,115,116],"Learning curve","High (feature-rich interface)","Low to medium",[118,119,120],"Best for","Teams of 5+ needing CI, registry and RBAC","Lightweight teams, simple forge, low RAM footprint",{"type":28,"title":122,"body":123},"When to choose GitLab CE, when to choose Forgejo","GitLab CE is the right choice if your team needs robust CI\u002FCD directly integrated into the forge, a private Docker registry on your domain, deployment pipelines with environments and deploy tokens, or project management with issues, milestones and kanban without a third-party tool. Its memory footprint (4–8 GB) is the price of this functional richness. Forgejo or Gitea are the answer when RAM is the main constraint, when the forge is the only requirement (no integrated CI) and you run CI with an external tool (Woodpecker, Drone, GitHub Actions via a runner). On a 2 GB VPS, GitLab CE is not viable; Forgejo runs on 256 MB. On a VPS of 8 GB dedicated to a development team, GitLab CE provides a complete environment that GitHub puts on its SaaS platform — under your control and without a monthly per-user subscription.","A VPS ready for GitLab CE","GitLab CE needs a VPS with 4 to 8 GB of RAM, generous disk space and a dedicated IP. Our ServOrbit VPS are delivered with Debian 12 or Ubuntu 24.04 and immediate root access — enough to have your forge online in thirty minutes.","See ServOrbit VPS","\u002Fsolutions\u002Fdeveloppeurs",[129,144,155],{"id":130,"slug":131,"title":132,"excerpt":133,"readTime":134,"views":12,"isPinned":13,"publishedAt":135,"category":136,"categories":141,"featuredImage":22,"bgImage":23,"posterImage":143,"relatedSolution":22},212,"woodpecker-ci-pipeline-vps-forgejo","Woodpecker CI and Forgejo: CI\u002FCD pipeline on a VPS","Deploy Woodpecker CI with Forgejo on your VPS for a self-hosted, lightweight and sovereign open source CI\u002FCD pipeline. Step-by-step Docker guide.",4,"2026-08-02T00:00:00+00:00",{"id":137,"name":138,"slug":139,"color":140,"icon":139},2,"Automation","automatisation","bg-brand-action\u002F10 text-brand-action",[142],{"id":137,"name":138,"slug":139,"color":140,"icon":139},"\u002Fblog\u002Fcovers\u002Fwoodpecker-ci-pipeline-vps-forgejo-poster.svg",{"id":145,"slug":146,"title":147,"excerpt":148,"readTime":149,"views":12,"isPinned":13,"publishedAt":150,"category":151,"categories":152,"featuredImage":22,"bgImage":23,"posterImage":154,"relatedSolution":22},229,"docker-compose-production-checklist","Docker Compose in Production: 10-Point Checklist","10 Docker Compose settings to verify before any production deployment: restart, healthchecks, limits, secrets and logs.",11,"2026-08-06T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":18},[153],{"id":16,"name":17,"slug":18,"color":19,"icon":18},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":156,"slug":157,"title":158,"excerpt":159,"readTime":134,"views":12,"isPinned":13,"publishedAt":160,"category":161,"categories":162,"featuredImage":22,"bgImage":23,"posterImage":164,"relatedSolution":22},207,"k3s-kubernetes-leger-vps","K3s: lightweight Kubernetes on your VPS","Run a CNCF-certified Kubernetes cluster on a modest VPS with K3s, the Rancher\u002FSUSE distribution that fits in 60 MB.","2026-08-01T00:00:00+00:00",{"id":16,"name":17,"slug":18,"color":19,"icon":18},[163],{"id":16,"name":17,"slug":18,"color":19,"icon":18},"\u002Fblog\u002Fcovers\u002Fk3s-kubernetes-leger-vps-poster.svg",1786136484410]