GitLab CE AMI for AWS: self-hosted Git and CI/CD without the setup headache
A production-configured GitLab Community Edition deployment on Ubuntu 24.04 LTS, preinstalled and wired together so it's live and usable the same day, not a bare OS image with an install script bolted on.
Source control and CI/CD sit at the center of how a software team actually ships. When that infrastructure lives on a SaaS vendor's servers, every architectural decision, where build logs are stored, how long artifacts are retained, which IP ranges can reach the API, whether a compliance team can audit access logs directly, is made by someone else, on their schedule. Self-hosting GitLab Community Edition puts that infrastructure back inside the organization's own AWS account, but the operational cost of getting there has historically been real: provisioning a reverse proxy, hardening the firewall, wiring TLS, and validating that the whole stack survives a reboot under load is a multi-hour task even for an experienced DevOps engineer, and a multi-day one for anybody doing it for the first time.
This AMI removes that operational tax. It is a production-configured GitLab Community Edition deployment on Ubuntu 24.04 LTS, built to be launched and used the same day.
Quick facts
| Spec | Detail |
|---|---|
| Base OS | Ubuntu 24.04 LTS |
| Application | GitLab Community Edition (free, open source) |
| Pre-wired components | NGINX reverse proxy, OpenSSH, UFW firewall |
| Recommended instance | t3.large (8 GB RAM minimum) |
| Pricing | $0.10/hour AMI fee + standard AWS EC2 instance cost |
| Categories | Source Control · CI/CD · Software Development |
| Vendor | Techforce Services Inc |
Table 1. At-a-glance specification of the GitLab CE AMI.
Why self-host GitLab at all
Self-hosting isn't about rejecting GitLab's hosted offering on principle, it's about what an organization gets back in exchange for owning the infrastructure. Repositories, issue history, merge request discussions, and CI/CD logs stay inside the organization's own AWS account and VPC, which matters the moment data residency requirements, client contractual terms, or internal security policy enter the conversation. Pricing stops scaling with headcount: a 50-person engineering org pays for compute capacity, not 50 SaaS seats. And because the instance is fully under the organization's control, nothing about the CI/CD pipeline, webhook integrations, or custom Git hooks is bounded by what a SaaS platform happens to expose in its settings panel.
There is also a longevity argument that's easy to underweight at decision time. A SaaS vendor can change pricing tiers, storage limits, or feature gating on its own roadmap and timeline. A self-hosted instance only changes when the organization decides to change it, a meaningfully different risk profile for a team planning multi-year infrastructure around its source control and release pipeline.
Architecture: what's actually running under the hood
A production GitLab deployment is not a single process, it is a coordinated set of services, and understanding what each one does makes troubleshooting and capacity planning significantly easier down the line.
| Component | Role in the stack |
|---|---|
| GitLab Rails application | Core web application, API, and business logic |
| Gitaly | Git repository storage and RPC access layer |
| Sidekiq | Background job processing (emails, webhooks, CI triggers) |
| PostgreSQL | Primary relational datastore for projects, users, issues, MRs |
| Redis | Caching layer and job queue backing store |
| NGINX | Reverse proxy terminating HTTP(S) in front of the application |
| OpenSSH | Git-over-SSH access and operator shell access |
| UFW | Host-level firewall restricting inbound traffic to required ports |
Table 2. Core services bundled into a standard GitLab CE deployment, as shipped in this AMI.
Every one of these components is preinstalled, configured, and wired to the others correctly on first boot, precisely the part of a manual GitLab install that consumes the most engineering time and is the easiest to get subtly wrong (an unconfigured Gitaly socket path or a missing Sidekiq worker are both common sources of a GitLab instance that looks "up" but doesn't actually function).
Core features
| Feature | What it delivers |
|---|---|
| Git repository hosting | Unlimited private and public repositories inside your own infrastructure |
| Issue tracking | Boards, labels, milestones, and cross-project issue linking |
| Merge requests | Inline code review, approvals, and discussion threads |
| CI/CD pipelines | YAML-defined pipelines with built-in runners support |
| Container registry | Private Docker image hosting tied to each project |
| Web-based administration | User, group, and permission management via the admin UI |
Table 3. Core GitLab CE capabilities available immediately after launch.
Self-hosted GitLab vs. the alternatives
GitLab CE on this AMI isn't the only way to get Git hosting and CI/CD. The honest comparison is against GitLab's own hosted SaaS tier and against GitHub, the other dominant hosted option most engineering leaders will have evaluated.
| Factor | This AMI (self-hosted) | GitLab.com (SaaS) | GitHub (SaaS) |
|---|---|---|---|
| Pricing model | Flat compute cost ($0.10/hr + EC2) | Per-seat, tiered by feature set | Per-seat, tiered by feature set |
| Data location | Your own AWS account/VPC | GitLab's infrastructure | Microsoft/GitHub's infrastructure |
| CI/CD minutes | Unlimited, bound only by instance capacity | Capped per plan, overage billed | Capped per plan, overage billed |
| Customization | Full control of runners, hooks, configs | Limited to exposed settings | Limited to exposed settings |
| Advanced features (CE scope) | Core Git, CI/CD, issues, MRs | Adds EE features at higher tiers | Adds Advanced Security at higher tiers |
| Infrastructure ownership | You patch, back up, and maintain | Vendor-managed | Vendor-managed |
Table 4. How self-hosted GitLab CE compares against the two most common hosted alternatives.
Security hardening checklist
The AMI ships with sane defaults, UFW enabled, NGINX fronting the application, SSH configured, but "production-ready out of the box" and "fully hardened for your specific threat model" are not the same thing. Before putting real customer or proprietary code on the instance, work through the following.
| Area | Recommended action |
|---|---|
| TLS/SSL | Point a real domain at the instance and issue a certificate (e.g. via Let's Encrypt) instead of serving over plain HTTP |
| SSH access | Disable password authentication, restrict to key-based login, and limit source IPs via security group rules |
| Firewall / security groups | Only expose 80/443 (and 22 for admins) at the AWS security-group layer, on top of the host's UFW rules |
| Backups | Schedule automated EBS snapshots and GitLab's own backup rake task on a recurring cron job |
| Updates | Apply GitLab and OS security patches on a defined cadence rather than leaving the instance at its launch-time version |
| Two-factor authentication | Enforce 2FA for all GitLab user accounts, especially anyone with admin or Owner-level access |
| Audit logging | Review GitLab's audit events regularly, especially permission and admin-level changes |
Table 5. Baseline hardening steps to apply after first launch.
Backup, recovery, and scaling considerations
GitLab includes its own backup rake task (gitlab-backup create) that bundles the repository data, database, and uploads into a single archive, running this on a schedule and shipping the result to S3 is the standard pattern for disaster recovery on a self-hosted instance. Pairing that with periodic EBS snapshots of the root volume gives two independent recovery paths: a GitLab-native backup for application-level restores, and a volume-level snapshot for full instance recovery.
On scaling: a single EC2 instance handles the overwhelming majority of small-to-mid-size teams comfortably. Once CI/CD concurrency becomes the bottleneck rather than the application itself, the common next step is offloading GitLab Runners to separate instances (or autoscaling runner fleets) while keeping the GitLab application server itself on this AMI, decoupling where code review happens from where builds execute rather than forcing one box to do both indefinitely.
Step-by-step: from launch to first commit
- Launch the AMI from AWS Marketplace, selecting t3.large or larger based on expected team size.
- Attach a security group allowing inbound 80, 443, and 22 from appropriate source ranges.
- Once the instance reports healthy, retrieve the initial root password and log into the web UI over the instance's public IP or DNS.
- Point a real domain at the instance and configure TLS before onboarding real users.
- Create the first project, invite team members, and configure group-level permissions.
- Add a
.gitlab-ci.ymlto a repository to confirm CI/CD pipelines execute end-to-end before relying on them for production releases.
Common pitfalls to avoid
| Pitfall | Why it happens | How to avoid it |
|---|---|---|
| Undersized instance | t3.micro/small boots fine but chokes under real CI load | Start at t3.large minimum per the documented recommendation |
| No TLS in production | Skipping domain/certificate setup to save time | Configure DNS + certificate before onboarding real users |
| No backup schedule | Backups feel unnecessary until the first incident | Automate gitlab-backup + EBS snapshots from day one |
| Single point of failure for CI | Running heavy runners on the same box as the app | Move CI runners to separate/autoscaling instances as load grows |
Table 6. Mistakes most commonly made in the first weeks of a self-hosted GitLab deployment.
Who this is actually for
| Persona | Why this AMI fits |
|---|---|
| Startup engineering team | Owns Git history and CI pipeline from the first commit without per-seat SaaS cost |
| Platform/DevOps team | Standardizes self-hosted tooling on AWS-native infrastructure the team already manages |
| Regulated or compliance-driven org | Keeps source code and CI logs inside its own AWS account and audit boundary |
| Cost-conscious scaling team | Avoids per-seat pricing that compounds as headcount grows |
Table 7. Who gets the most value from this deployment model.
How billing works
Pricing is usage-based at $0.10 per hour on top of standard AWS EC2 infrastructure costs for whichever instance size is chosen. There's no separate GitLab license fee, no minimum commitment period, and the subscription can be canceled at any time, billing tracks compute time, not seat count.
We'll size, secure, and operate it for you.
What's the difference between this AMI and just installing GitLab manually on an EC2 instance?
A manual install means configuring the reverse proxy, firewall, SSH, Gitaly, Sidekiq, and service management yourself before GitLab is actually production-ready, typically a day or more of work. This AMI ships with all of that already wired together, so GitLab is live and usable as soon as the instance boots.
Which instance size should I actually use for GitLab CE?
t3.large with at least 8 GB RAM is the recommended minimum for real use. Smaller instances like t3.micro will launch the AMI but struggle once CI/CD jobs or multiple concurrent users are added.
How is billing structured for this AMI?
Billing is usage-based at $0.10 per hour, in addition to the normal AWS infrastructure costs for your chosen instance type. There's no minimum term, and you can cancel the subscription at any time.
Can I run CI/CD pipelines (GitLab Runners) on this same instance?
Yes, GitLab's built-in CI/CD is available out of the box. For heavier pipeline workloads, many teams eventually move runners to separate or autoscaling instances, but the initial AMI is fully capable of running CI/CD on its own for small-to-mid workloads.
Is my code and data kept inside my own AWS account?
Yes. Since this is a self-hosted deployment running on your own EC2 instance, all repositories, issues, and CI/CD data stay inside your AWS account and VPC rather than a third-party platform.
How do I back up this GitLab instance?
Use GitLab's built-in gitlab-backup rake task to generate application-level backups (repos, database, uploads) on a schedule, and pair it with periodic EBS snapshots for full-volume recovery.
What happens if my team outgrows a single instance?
The most common scaling path is offloading CI/CD runners to separate or autoscaling instances while keeping the GitLab application itself on this AMI, rather than resizing indefinitely or re-architecting from scratch.
Does this AMI include TLS/HTTPS out of the box?
NGINX is preconfigured as a reverse proxy, but TLS certificate issuance for a real domain is a setup step you complete after launch, it isn't something a generic AMI can pre-provision since it depends on your domain.