Gitlab blueprint (#2110)
* add gitlab blueprint * add TODO.md --------- Co-authored-by: Julio Castillo <jccb@google.com>
This commit is contained in:
parent
23c6723804
commit
a34d93fb43
|
@ -26,4 +26,10 @@ The blueprints in this folder show how to automate installation of specific thir
|
|||
|
||||
<a href="./f5-bigip/" title="F5 BigIP"><img src="./phpipam/diagram.png" align="left" width="320px"></a> <p style="margin-left: 340px">These examples show how to deploy F5 BigIP-VE load balancers in GCP.</p>
|
||||
|
||||
<br clear="left">
|
||||
|
||||
### Gitlab
|
||||
|
||||
<a href="./gitlab/" title="Gitlab"><img src="./gitlab/diagram.png" align="left" width="320px"></a> <p style="margin-left: 340px">This blueprint shows how to deploy a Gitlab instance in GCP. The architecture is based on the reference described in the [official documentation](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) with managed services such as Cloud SQL, Memorystore and Cloud Storage.</p>
|
||||
|
||||
<br clear="left">
|
|
@ -0,0 +1,389 @@
|
|||
# Gitlab Blueprint
|
||||
|
||||
This blueprint is responsible for provisioning a production ready Gitlab instance on the landing zone infrastructure. The [reference architecture](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html) of this deployment target 1K users, updates to the current code is required in of HA and/or higher capacity requirements.
|
||||
|
||||
The following diagram illustrates the high-level design of created resources, which can be adapted to specific requirements via variables:
|
||||
|
||||
<p align="center">
|
||||
<img src="diagram.png" alt="Gitlab">
|
||||
</p>
|
||||
|
||||
## Table of contents
|
||||
|
||||
<!-- TOC -->
|
||||
* [Gitlab Blueprint](#gitlab-blueprint)
|
||||
* [Table of contents](#table-of-contents)
|
||||
* [Managed Services for Seamless Operations](#managed-services-for-seamless-operations)
|
||||
* [Object Storage <-> Google Cloud Storage](#object-storage-----google-cloud-storage)
|
||||
* [Identity](#identity)
|
||||
* [SAML Integration](#saml-integration)
|
||||
* [Google Workspace Setup](#google-workspace-setup)
|
||||
* [Others Identity Integration](#others-identity-integration)
|
||||
* [Email](#email)
|
||||
* [Sendgrid integration](#sendgrid-integration)
|
||||
* [SSL Certificate Configuration](#ssl-certificate-configuration)
|
||||
* [Networking and scalability](#networking-and-scalability)
|
||||
* [HA](#ha)
|
||||
* [Deployment](#deployment)
|
||||
* [Step 0: Cloning the repository](#step-0--cloning-the-repository)
|
||||
* [Step 2: Prepare the variables](#step-2--prepare-the-variables)
|
||||
* [Step 3: Deploy resources](#step-3--deploy-resources)
|
||||
* [Step 4: Use the created resources](#step-4--use-the-created-resources)
|
||||
* [Reference and useful links](#reference-and-useful-links)
|
||||
* [Files](#files)
|
||||
* [Variables](#variables)
|
||||
* [Outputs](#outputs)
|
||||
<!-- TOC -->
|
||||
|
||||
## Managed Services for Seamless Operations
|
||||
|
||||
This Gitlab installation prioritizes the use of Google Cloud managed services to
|
||||
streamline infrastructure management and optimization. Here's a breakdown of the
|
||||
managed services incorporated:
|
||||
|
||||
1. [Google Cloud Storage](https://cloud.google.com/storage): is a highly
|
||||
scalable and secure object storage service for storing and accessing data in
|
||||
Google Cloud.<br/><br/>
|
||||
2. [Cloud SQL PostgreSQL](https://cloud.google.com/sql/docs/postgres): Cloud SQL
|
||||
for Postgres is a fully managed database service on Google Cloud Platform. It
|
||||
eliminates database administration tasks, allowing you to focus on your
|
||||
application, while offering high performance, automatic scaling, and secure
|
||||
management of your PostgreSQL databases.<br/><br/>
|
||||
3. [Memorystore](https://cloud.google.com/memorystore?hl=en): GCP Memorystore
|
||||
offers a fully managed Redis service for in-memory data caching and
|
||||
high-performance data access.
|
||||
|
||||
Benefits:
|
||||
|
||||
- Reduced Operational Overhead: Google handles infrastructure setup,
|
||||
maintenance, and updates, freeing up your time and resources.
|
||||
- Enhanced Security: Managed services often benefit from Google's comprehensive
|
||||
security measures and expertise.
|
||||
- Scalability: Easily adjust resource allocation to meet evolving demands.
|
||||
- Cost Optimization: Pay for the resources you use, benefiting from Google's
|
||||
infrastructure optimization.
|
||||
Integration: Managed services seamlessly integrate with other GCP services,
|
||||
promoting a cohesive cloud environment.
|
||||
This module embraces managed services to deliver a resilient, scalable, and
|
||||
cost-effective application architecture on Google Cloud.
|
||||
|
||||
### Object Storage <-> Google Cloud Storage
|
||||
|
||||
GitLab supports using an object storage service for holding numerous types of
|
||||
data. It’s recommended over NFS and in general it’s better in larger setups as
|
||||
object storage is typically much more performant, reliable, and scalable.
|
||||
|
||||
A single storage connection to Cloud Storage is configured for all object types,
|
||||
which leverages default Google Compute Engine credential (the so called "
|
||||
consolidated form"). A Cloud Storage bucket is bootstrapped for each object
|
||||
type, the table below summarized such a configuration:
|
||||
|
||||
| Object Type | Description | Cloud Storage Bucket |
|
||||
|------------------|----------------------------------------|-----------------------------------|
|
||||
| artifacts | CI artifacts | ${prefix}-gitlab-artifacts |
|
||||
| external_diffs | Merge request diffs | ${prefix}-mr-diffs |
|
||||
| uploads | User uploads | ${prefix}-gitlab-uploads |
|
||||
| lfs | Git Large File Storage objects | ${prefix}-gitlab-lfs |
|
||||
| packages | Project packages (e.g. PyPI, Maven ..) | ${prefix}-gitlab-packages |
|
||||
| dependency_proxy | Dependency Proxy | ${prefix}-gitlab-dependency-proxy |
|
||||
| terraform_state | Terraform state files | ${prefix}-gitlab-terraform-state |
|
||||
| pages | Pages | ${prefix}-gitlab-pages |
|
||||
|
||||
For more information on Gitlab object storage and Google Cloud Storage
|
||||
integration please refer to the official Gitlab documentation available at the
|
||||
following [link](https://docs.gitlab.com/ee/administration/object_storage.html).
|
||||
|
||||
- [PostgreSQL service](https://docs.gitlab.com/ee/administration/postgresql/external.html)
|
||||
|
||||
Updated postgres configuration to match documentation, created required database
|
||||
in postgres instance.
|
||||
|
||||
- [Redis](https://docs.gitlab.com/ee/administration/redis/replication_and_failover_external.html)
|
||||
|
||||
## Identity
|
||||
|
||||
GitLab integrates with a number of OmniAuth providers as well as external
|
||||
authentication and authorization providers such as Google Secure LDAP and many
|
||||
other providers.
|
||||
At this time this stage can deal with SAML integration for both user
|
||||
authentication and provisioning, in order to setup SAML integration please
|
||||
provide the saml block on gitlab_config variable.
|
||||
|
||||
### SAML Integration
|
||||
|
||||
This section details how configure GitLab to act as a SAML service provider (
|
||||
SP). This allows GitLab to consume assertions from a SAML identity provider (
|
||||
IdP), such as Cloud Identity, to authenticate users. Please find instructions
|
||||
below for integration with:
|
||||
|
||||
- [Google Workspace](#google-workspace-setup)
|
||||
|
||||
#### Google Workspace Setup
|
||||
|
||||
Setup of Google Workspace is documented in the official Gitlab documentation
|
||||
available at the
|
||||
following [link](https://docs.gitlab.com/ee/integration/saml.html#set-up-google-workspace)
|
||||
which are also reported below for simplicity.
|
||||
|
||||
Create a custom SAML webapp following instructions available at the
|
||||
following [link](https://support.google.com/a/answer/6087519), providing these
|
||||
information in the service provider configuration:
|
||||
|
||||
| Configuration | Typical Value | Cloud Storage Bucket |
|
||||
|-------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| Name of SAML App | Gitlab | Name of the app |
|
||||
| ACS URL | https://<GITLAB_DOMAIN>/users/auth/saml/callback | Assertion Consumer Service URL. |
|
||||
| GITLAB_DOMAIN | gitlab.example.com | Your GitLab instance domain. |
|
||||
| Entity ID | https://gitlab.example.com | A value unique to your SAML application. Set it to the issuer in your GitLab configuration. |
|
||||
| Name ID | EMAIL | Required value. Also known as name_identifier_format. |
|
||||
|
||||
Then setup the following SAML attribute mappings:
|
||||
|
||||
| Google Directory attributes | App attributes |
|
||||
|--------------------------------|----------------|
|
||||
| Basic information > Email | email |
|
||||
| Basic Information > First name | first_name |
|
||||
| Basic Information > Last name | last_name |
|
||||
|
||||
After configuring the Google Workspace SAML application, record the following
|
||||
information:
|
||||
|
||||
| Value | Description |
|
||||
|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| SSO URL | Setup in gitlab_config.saml.sso_target_url variable |
|
||||
| Certificate (download) | Setup in gitlab_config.saml.idp_cert_fingerprint (obtain value with the following command `openssl x509 -in <your_certificate.crt> -noout -fingerprint -sha1`) |
|
||||
|
||||
### Others Identity Integration
|
||||
|
||||
- [OpenID Connect OmniAuth](https://docs.gitlab.com/ee/administration/auth/oidc.html#configure-google)
|
||||
- [Google Secure LDAP](https://docs.gitlab.com/ee/administration/auth/ldap/google_secure_ldap.html)
|
||||
|
||||
## Email
|
||||
|
||||
### Gmail / Workspace
|
||||
|
||||
- [ ] [documentation](https://docs.gitlab.com/ee/administration/incoming_email.html#gmail)
|
||||
|
||||
### Sendgrid integration
|
||||
|
||||
Use
|
||||
the [Google Cloud Marketplace](https://console.cloud.google.com/marketplace/details/sendgrid-app/sendgrid-email)
|
||||
to sign up for the SendGrid email service. Make a note of your SendGrid SMTP
|
||||
account credentials, which include username, password, and hostname. Your SMTP
|
||||
username and password are the same as what you used to sign up for the service.
|
||||
The SendGrid hostname is smtp.sendgrid.net.
|
||||
Create an API key:
|
||||
Sign in to SendGrid and go to Settings > API Keys.
|
||||
|
||||
1. Create an API key.
|
||||
2. Select the permissions for the key. At a minimum, the key must have Mail send
|
||||
permissions to send email.
|
||||
3. Click Save to create the key.
|
||||
4. SendGrid generates a new key. This is the only copy of the key, so make sure
|
||||
that you copy the key and save it for later.
|
||||
|
||||
Configure the sendgrid API key in the gitlab_config variable, under mail,
|
||||
sendgrid arguments as per the following example:
|
||||
|
||||
```terraform
|
||||
gitlab_config = {
|
||||
hostname = "gitlab.example.com"
|
||||
mail = {
|
||||
sendgrid = {
|
||||
api_key = "test"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SSL Certificate Configuration
|
||||
|
||||
This module provides flexibility in configuring SSL certificates for the server.
|
||||
You have two options:
|
||||
|
||||
1. **Provide Your Own Certificates**: If you have existing SSL certificates, you
|
||||
can place them in the certs folder within the module's directory. The module
|
||||
will automatically detect and use them.
|
||||
File Names: Ensure the files are named ${gitlab_hostname}.crt (for the
|
||||
certificate) and
|
||||
gitlab_hostname.key (for the private key). Although it is not required in
|
||||
this stage it is mandatory to also place inside the certs folder the server
|
||||
CA certificate which is later use to secure HTTPS access from the Gitlab
|
||||
runner. Name of the CA certificate should be: ${gitlab_hostname}.ca.crt
|
||||
2. **Use Automatically Generated Self-Signed Certificates**: If you don't
|
||||
provide certificates, the module will generate a self-signed certificate for
|
||||
immediate use.
|
||||
Updating Later: You can replace the self-signed certificate with your own
|
||||
certificates at any time by placing them in the certs folder and re-running
|
||||
Terraform.
|
||||
|
||||
**Important Notes:**
|
||||
|
||||
Certificate Validation: Self-signed certificates are not validated by browsers
|
||||
and will trigger warnings. Use them only for development or testing
|
||||
environments.
|
||||
|
||||
For more information on how to configure HTTPS on Gitlab please refer to the
|
||||
original Gitlab documentation available at the
|
||||
following [link](https://docs.gitlab.com/omnibus/settings/ssl/#configure-https-manually).
|
||||
|
||||
## Networking and scalability
|
||||
|
||||
- [Load balancer](https://docs.gitlab.com/ee/administration/load_balancer.html)
|
||||
|
||||
## HA
|
||||
|
||||
- [High Availability](http://ubimol.it/12.0/ee/administration/high_availability/README.html)
|
||||
|
||||
### Deployment
|
||||
|
||||
#### Step 0: Cloning the repository
|
||||
|
||||
If you want to deploy from your Cloud Shell, click on the image below, sign in
|
||||
if required and when the prompt appears, click on “confirm”.
|
||||
|
||||
[![Open Cloudshell](../../../assets/images/cloud-shell-button.png)](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fcloud-foundation-fabric&cloudshell_workspace=blueprints%2Fthird-party-solutions%2Fwordpress%2Fcloudrun)
|
||||
|
||||
Otherwise, in your console of choice:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/GoogleCloudPlatform/cloud-foundation-fabric
|
||||
```
|
||||
|
||||
Before you deploy the architecture, you will need at least the following
|
||||
information (for more precise configuration see the Variables section):
|
||||
|
||||
* The project ID
|
||||
|
||||
The VPC host project, VPC and subnets should already exist and the following networking requirements are satisfied:
|
||||
- configured PSA for Cloud SQL on the VPC
|
||||
- subnets configured with PGA and Cloud NAT for internet access
|
||||
- Inbound firewall rule for IAP on port 22
|
||||
- Inbound firewall rule for TCP ports 80, 443, 2222 from proxy subnet CIDR (gitlab)
|
||||
|
||||
#### Step 2: Prepare the variables
|
||||
|
||||
Once you have the required information, head back to your cloned repository.
|
||||
Make sure you’re in the directory of this tutorial (where this README is in).
|
||||
|
||||
Configure the Terraform variables in your `terraform.tfvars` file.
|
||||
See [terraform.tfvars.sample](terraform.tfvars.sample) as starting point - just
|
||||
copy it to `terraform.tfvars` and edit the latter. See the variables
|
||||
documentation below.
|
||||
|
||||
#### Step 3: Deploy resources
|
||||
|
||||
Initialize your Terraform environment and deploy the resources:
|
||||
|
||||
```shell
|
||||
terraform init
|
||||
terraform apply
|
||||
```
|
||||
|
||||
#### Step 4: Use the created resources
|
||||
|
||||
Connect to squid-proxy for accessing gitlab instance using the gcloud command
|
||||
available in the `ssh_to_bastion` terraform output.
|
||||
|
||||
```bash
|
||||
terraform output ssh_to_bastion
|
||||
```
|
||||
|
||||
A gcloud command like the following should be available
|
||||
|
||||
```bash
|
||||
gcloud compute ssh squid-vm --project ${project} --zone europe-west8-b -- -L 3128:127.0.0.1:3128 -N -q -f
|
||||
```
|
||||
|
||||
Set as system proxy ip 127.0.0.1 and port 3128 and connect to Gitlab hostname https://gitlab.gcp.example.com.
|
||||
Use default admin password available in /run/gitlab/config/initial_root_password or reset admin password via the following command on the Docker container:
|
||||
|
||||
```bash
|
||||
gitlab-rake “gitlab:password:reset”
|
||||
```
|
||||
|
||||
## Reference and useful links
|
||||
|
||||
- [Reference architecture up to 1k users](https://docs.gitlab.com/ee/administration/reference_architectures/1k_users.html)
|
||||
- [`/etc/gitlab/gitlab.rb` template](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template)
|
||||
- [`/etc/gitlab/gitlab.rb` default options](https://docs.gitlab.com/ee/administration/package_information/defaults.html)
|
||||
|
||||
<!-- TFDOC OPTS files:1 show_extra:1 -->
|
||||
<!-- BEGIN TFDOC -->
|
||||
## Files
|
||||
|
||||
| name | description | modules | resources |
|
||||
|---|---|---|---|
|
||||
| [gitlab.tf](./gitlab.tf) | None | <code>compute-vm</code> · <code>iam-service-account</code> · <code>net-lb-int</code> | |
|
||||
| [main.tf](./main.tf) | Module-level locals and resources. | <code>project</code> | |
|
||||
| [outputs.tf](./outputs.tf) | Module outputs. | | |
|
||||
| [services.tf](./services.tf) | None | <code>cloudsql-instance</code> · <code>gcs</code> | <code>google_redis_instance</code> |
|
||||
| [ssl.tf](./ssl.tf) | None | | <code>tls_cert_request</code> · <code>tls_locally_signed_cert</code> · <code>tls_private_key</code> · <code>tls_self_signed_cert</code> |
|
||||
| [variables.tf](./variables.tf) | Module variables. | | |
|
||||
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default | producer |
|
||||
|---|---|:---:|:---:|:---:|:---:|
|
||||
| [gitlab_instance_config](variables.tf#L69) | Gitlab Compute Engine instance config. | <code title="object({ instance_type = optional(string, "n1-highcpu-8") name = optional(string, "gitlab-0") network_tags = optional(list(string), []) replica_zone = optional(string) zone = optional(string) boot_disk = optional(object({ size = optional(number, 20) type = optional(string, "pd-standard") }), {}) data_disk = optional(object({ size = optional(number, 100) type = optional(string, "pd-ssd") replica_zone = optional(string) }), {}) })">object({…})</code> | ✓ | | |
|
||||
| [network_config](variables.tf#L89) | Shared VPC network configurations to use for Gitlab Runner VM. | <code title="object({ host_project = optional(string) network_self_link = string subnet_self_link = string })">object({…})</code> | ✓ | | |
|
||||
| [prefix](variables.tf#L98) | Prefix used for resource names. | <code>string</code> | ✓ | | |
|
||||
| [project_id](variables.tf#L117) | Project id, references existing project if `project_create` is null. | <code>string</code> | ✓ | | |
|
||||
| [region](variables.tf#L136) | GCP Region. | <code>string</code> | ✓ | | |
|
||||
| [admin_principals](variables.tf#L17) | Users, groups and/or service accounts that are assigned roles, in IAM format (`group:foo@example.com`). | <code>list(string)</code> | | <code>[]</code> | |
|
||||
| [cloudsql_config](variables.tf#L23) | Cloud SQL Postgres config. | <code title="object({ name = optional(string, "gitlab-0") database_version = optional(string, "POSTGRES_13") tier = optional(string, "db-custom-2-8192") })">object({…})</code> | | <code>{}</code> | |
|
||||
| [gcs_config](variables.tf#L34) | GCS for Object Storage config. | <code title="object({ enable_versioning = optional(bool, false) location = optional(string, "EU") storage_class = optional(string, "STANDARD") })">object({…})</code> | | <code>{}</code> | |
|
||||
| [gitlab_config](variables.tf#L45) | Gitlab configuration. | <code title="object({ hostname = optional(string, "gitlab.gcp.example.com") mail = optional(object({ enabled = optional(bool, false) sendgrid = optional(object({ api_key = optional(string) email_from = optional(string, null) email_reply_to = optional(string, null) }), null) }), {}) saml = optional(object({ forced = optional(bool, false) idp_cert_fingerprint = string sso_target_url = string name_identifier_format = optional(string, "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress") }), null) ha_required = optional(bool, false) })">object({…})</code> | | <code>{}</code> | |
|
||||
| [project_create](variables.tf#L108) | Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | <code title="object({ billing_account_id = string parent = string })">object({…})</code> | | <code>null</code> | |
|
||||
| [redis_config](variables.tf#L122) | Redis Config. | <code title="object({ memory_size_gb = optional(number, 1) name = optional(string, "gitlab-0") persistence_mode = optional(string, "RDB") rdb_snapshot_period = optional(string, "TWELVE_HOURS") tier = optional(string, "BASIC") version = optional(string, "REDIS_6_X") })">object({…})</code> | | <code>{}</code> | |
|
||||
|
||||
## Outputs
|
||||
|
||||
| name | description | sensitive | consumers |
|
||||
|---|---|:---:|---|
|
||||
| [gitlab_ilb_ip](outputs.tf#L26) | Gitlab Internal Load Balancer IP Address. | | |
|
||||
| [instance](outputs.tf#L31) | Gitlab compute engine instance. | | |
|
||||
| [postgresql_users](outputs.tf#L36) | Gitlab postgres user password. | ✓ | |
|
||||
| [project](outputs.tf#L42) | GCP project. | | |
|
||||
| [ssh_to_gitlab](outputs.tf#L47) | gcloud command to ssh gitlab instance. | | |
|
||||
| [ssl_certs](outputs.tf#L52) | Gitlab SSL Certificates. | ✓ | |
|
||||
<!-- END TFDOC -->
|
||||
## Test
|
||||
|
||||
```hcl
|
||||
module "test" {
|
||||
source = "./fabric/blueprints/third-party-solutions/gitlab"
|
||||
gitlab_config = {
|
||||
hostname = "gitlab.gcp.example.com"
|
||||
mail = {
|
||||
sendgrid = {
|
||||
api_key = "sample_api_key"
|
||||
}
|
||||
}
|
||||
saml = {
|
||||
idp_cert_fingerprint = "67:90:96.....REPLACE_ME"
|
||||
sso_target_url = "https://accounts.google.com/o/saml2/idp?idpid=REPLACE_ME"
|
||||
}
|
||||
}
|
||||
gitlab_instance_config = {
|
||||
replica_zone = "europe-west8-c"
|
||||
zone = "europe-west8-b"
|
||||
data_disk = {
|
||||
replica_zone = "europe-west8-c"
|
||||
}
|
||||
}
|
||||
network_config = {
|
||||
host_project = "host-project"
|
||||
network_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/global/networks/prod-landing-0"
|
||||
subnet_self_link = "https://www.googleapis.com/compute/v1/projects/prod-net-landing-0/regions/europe-west1/subnetworks/landing-default-ew1"
|
||||
}
|
||||
prefix = "prefix"
|
||||
project_create = {
|
||||
billing_account_id = "1234-ABCD-1234"
|
||||
parent = "folders/1234563"
|
||||
}
|
||||
project_id = "my-project"
|
||||
region = "europe-west8"
|
||||
}
|
||||
# tftest modules=14 resources=50
|
||||
```
|
|
@ -0,0 +1,20 @@
|
|||
# Gitlab TODOs
|
||||
|
||||
- Integrations
|
||||
- [x] Identity
|
||||
- [x] SAML
|
||||
- [ ] Email:
|
||||
- [ ] Gmail / Workspace
|
||||
- [x] Sendgrid
|
||||
- [x] ILB
|
||||
- [ ] MIG
|
||||
- [ ] Gitaly
|
||||
- [x] HTTPS SSL
|
||||
- [x] Gitlab SSH on port 2222
|
||||
- [x] Check object store, use GCS wherever possible
|
||||
- [x] Cloud SQL HA
|
||||
- Memorystore
|
||||
- [ ] HA
|
||||
- [ ] PSC instead of PSA
|
||||
- [x] Integration with Cloud Logging for Gitlab running on Docker container
|
||||
- [ ] Integrate with Certificate Manager for SSH certificates
|
|
@ -0,0 +1,118 @@
|
|||
#cloud-config
|
||||
|
||||
# Copyright 2024 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# https://hub.docker.com/r/nginx/nginx/
|
||||
# https://nginx.io/manual/toc/#installation
|
||||
|
||||
write_files:
|
||||
- path: /var/lib/docker/daemon.json
|
||||
permissions: '0644'
|
||||
owner: root
|
||||
content: |
|
||||
{
|
||||
"live-restore": true,
|
||||
"storage-driver": "overlay2",
|
||||
"log-driver": "gcplogs",
|
||||
"log-opts": {
|
||||
"gcp-meta-name": "gitlab-0",
|
||||
"max-size": "1024m"
|
||||
}
|
||||
}
|
||||
- path: /tmp/gitlab/config/gitlab.rb
|
||||
permissions: '0600'
|
||||
owner: root
|
||||
content: |
|
||||
${gitlab_rb}
|
||||
- path: /tmp/gitlab/ssl/${gitlab_cert_name}.key
|
||||
permissions: '0600'
|
||||
owner: root
|
||||
content: |
|
||||
${gitlab_ssl_key}
|
||||
- path: /tmp/gitlab/ssl/${gitlab_cert_name}.crt
|
||||
permissions: '0600'
|
||||
owner: root
|
||||
content: |
|
||||
${gitlab_ssl_crt}
|
||||
- path: /tmp/gitlab/sshd_config
|
||||
permissions: '0644'
|
||||
owner: root
|
||||
content: |
|
||||
${gitlab_sshd_config}
|
||||
|
||||
- path: /etc/systemd/system/gitlab-data.service
|
||||
permissions: '0644'
|
||||
owner: root
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Gitlab data disk
|
||||
ConditionPathExists=/dev/disk/by-id/google-data
|
||||
Before=gitlab.service
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/mkdir -p /run/gitlab
|
||||
ExecStart=/bin/bash -c \
|
||||
"/bin/lsblk -fn -o FSTYPE \
|
||||
/dev/disk/by-id/google-data |grep ext4 \
|
||||
|| mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard \
|
||||
/dev/disk/by-id/google-data"
|
||||
ExecStart=/bin/bash -c \
|
||||
"mount |grep /run/gitlab \
|
||||
|| mount -t ext4 /dev/disk/by-id/google-data /run/gitlab"
|
||||
ExecStart=/sbin/resize2fs /dev/disk/by-id/google-data
|
||||
ExecStart=/bin/mkdir -p /run/gitlab/config
|
||||
ExecStart=/bin/mkdir -p /run/gitlab/ssl
|
||||
ExecStart=/bin/mv /tmp/gitlab/config/gitlab.rb /run/gitlab/config/gitlab.rb
|
||||
ExecStart=/bin/mv /tmp/gitlab/sshd_config /run/gitlab/sshd_config
|
||||
ExecStart=/bin/bash -c "base64 -d -i /tmp/gitlab/ssl/${gitlab_cert_name}.key > /run/gitlab/ssl/${gitlab_cert_name}.key"
|
||||
ExecStart=/bin/bash -c "base64 -d -i /tmp/gitlab/ssl/${gitlab_cert_name}.crt > /run/gitlab/ssl/${gitlab_cert_name}.crt"
|
||||
RemainAfterExit=true
|
||||
|
||||
# https://docs.gitlab.com/ee/install/docker.html#pre-configure-docker-container
|
||||
|
||||
- path: /etc/systemd/system/gitlab.service
|
||||
permissions: '0644'
|
||||
owner: root
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Start gitlab container
|
||||
After=gitlab-data.service gcr-online.target docker.socket
|
||||
Wants=gitlab-data.service gcr-online.target docker.socket docker-events-collector.service
|
||||
[Service]
|
||||
Environment="HOME=/home/gitlab"
|
||||
ExecStartPre=/usr/bin/docker-credential-gcr configure-docker
|
||||
ExecStartPre=mkdir -p /run/gitlab
|
||||
ExecStart=/usr/bin/docker run --rm --name=gitlab \
|
||||
--hostname ${gitlab_config.hostname} \
|
||||
--shm-size 256m \
|
||||
--env GITLAB_OMNIBUS_CONFIG="" \
|
||||
--publish 443:443 \
|
||||
--publish 80:80 \
|
||||
--publish 2222:2222 \
|
||||
-v /run/gitlab/config:/etc/gitlab \
|
||||
-v /run/gitlab/ssl:/etc/gitlab/ssl \
|
||||
-v /run/gitlab/logs:/var/log/gitlab \
|
||||
-v /run/gitlab/data:/var/opt/gitlab \
|
||||
-v /run/gitlab/sshd_config:/assets/sshd_config \
|
||||
gitlab/gitlab-ce
|
||||
ExecStop=/usr/bin/docker stop gitlab
|
||||
|
||||
runcmd:
|
||||
- systemctl start node-problem-detector
|
||||
- iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
- iptables -I INPUT 1 -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
- iptables -I INPUT 1 -p tcp -m tcp --dport 2222 -m state --state NEW,ESTABLISHED -j ACCEPT
|
||||
- systemctl daemon-reload
|
||||
- systemctl start gitlab
|
|
@ -0,0 +1,118 @@
|
|||
# Copyright 2024 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# /etc/gitlab/gitlab.rb
|
||||
|
||||
external_url "https://${hostname}"
|
||||
letsencrypt['enable'] = false
|
||||
nginx['redirect_http_to_https'] = true
|
||||
|
||||
# https://docs.gitlab.com/omnibus/settings/redis.html
|
||||
gitlab_rails['redis_enable_client'] = false
|
||||
gitlab_rails['redis_host'] = '${redis.host}'
|
||||
gitlab_rails['redis_port'] = ${redis.port}
|
||||
# TODO: use auth
|
||||
# gitlab_rails['redis_password'] = nil
|
||||
redis['enable'] = false
|
||||
|
||||
# https://docs.gitlab.com/omnibus/settings/database.html#using-a-non-packaged-postgresql-database-management-server
|
||||
postgresql['enable'] = false
|
||||
gitlab_rails['db_adapter'] = 'postgresql'
|
||||
gitlab_rails['db_encoding'] = 'utf8'
|
||||
gitlab_rails['db_host'] = '${cloudsql.host}'
|
||||
gitlab_rails['db_port'] = 5432
|
||||
gitlab_rails['db_password'] = '${cloudsql.password}'
|
||||
|
||||
# https://docs.gitlab.com/ee/administration/object_storage.html#google-cloud-storage-gcs
|
||||
# Consolidated object storage configuration
|
||||
gitlab_rails['object_store']['enabled'] = true
|
||||
gitlab_rails['object_store']['proxy_download'] = true
|
||||
gitlab_rails['object_store']['connection'] = {
|
||||
'provider' => 'Google',
|
||||
'google_project' => '${project_id}',
|
||||
'google_application_default' => true
|
||||
}
|
||||
# full example using the consolidated form
|
||||
# https://docs.gitlab.com/ee/administration/object_storage.html#full-example-using-the-consolidated-form-and-amazon-s3
|
||||
gitlab_rails['object_store']['objects']['artifacts']['bucket'] = '${prefix}-gitlab-artifacts'
|
||||
gitlab_rails['object_store']['objects']['external_diffs']['bucket'] = '${prefix}-gitlab-mr-diffs'
|
||||
gitlab_rails['object_store']['objects']['lfs']['bucket'] = '${prefix}-gitlab-lfs'
|
||||
gitlab_rails['object_store']['objects']['uploads']['bucket'] = '${prefix}-gitlab-uploads'
|
||||
gitlab_rails['object_store']['objects']['packages']['bucket'] = '${prefix}-gitlab-packages'
|
||||
gitlab_rails['object_store']['objects']['dependency_proxy']['bucket'] = '${prefix}-gitlab-dependency-proxy'
|
||||
gitlab_rails['object_store']['objects']['terraform_state']['bucket'] = '${prefix}-gitlab-terraform-state'
|
||||
gitlab_rails['object_store']['objects']['pages']['bucket'] = '${prefix}-gitlab-pages'
|
||||
|
||||
# SAML configuration
|
||||
# https://docs.gitlab.com/ee/integration/saml.html
|
||||
%{ if saml != null }
|
||||
gitlab_rails['omniauth_enabled'] = true
|
||||
gitlab_rails['omniauth_external_providers'] = ['saml']
|
||||
# create new user in case of sign in with SAML provider
|
||||
gitlab_rails['omniauth_allow_single_sign_on'] = ['saml']
|
||||
# do not force approval from admins for newly created users
|
||||
gitlab_rails['omniauth_block_auto_created_users'] = false
|
||||
# automatically link a first-time SAML sign-in with existing GitLab users if their email addresses match
|
||||
gitlab_rails['omniauth_auto_link_saml_user'] = true
|
||||
# Force user redirection to SAML
|
||||
# To bypass the auto sign-in setting, append ?auto_sign_in=false in the sign in URL, for example: https://gitlab.example.com/users/sign_in?auto_sign_in=false.
|
||||
%{ if saml.forced }
|
||||
gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'saml'
|
||||
%{ endif }
|
||||
# SHA1 Fingerprint
|
||||
gitlab_rails['omniauth_providers'] = [
|
||||
{
|
||||
name: "saml",
|
||||
label: "SAML",
|
||||
args: {
|
||||
assertion_consumer_service_url: "https://${hostname}/users/auth/saml/callback",
|
||||
idp_cert_fingerprint: '${saml.idp_cert_fingerprint}',
|
||||
idp_sso_target_url: '${saml.sso_target_url}',
|
||||
issuer: "https://${hostname}",
|
||||
name_identifier_format: "${saml.name_identifier_format}"
|
||||
}
|
||||
}
|
||||
]
|
||||
%{ endif }
|
||||
|
||||
|
||||
# mail configuration
|
||||
%{ if mail.sendgrid != null }
|
||||
gitlab_rails['smtp_enable'] = true
|
||||
gitlab_rails['smtp_address'] = "smtp.sendgrid.net"
|
||||
gitlab_rails['smtp_port'] = 587
|
||||
gitlab_rails['smtp_user_name'] = "apikey"
|
||||
gitlab_rails['smtp_password'] = "${mail.sendgrid.api_key}"
|
||||
gitlab_rails['smtp_domain'] = "smtp.sendgrid.net"
|
||||
gitlab_rails['smtp_authentication'] = "plain"
|
||||
gitlab_rails['smtp_enable_starttls_auto'] = true
|
||||
gitlab_rails['smtp_tls'] = false
|
||||
# If use Single Sender Verification You must configure from. If not fail
|
||||
# 550 The from address does not match a verified Sender Identity. Mail cannot be sent until this error is resolved.
|
||||
# Visit https://sendgrid.com/docs/for-developers/sending-email/sender-identity/ to see the Sender Identity requirements
|
||||
%{ if try(mail.sendgrid.email_from != null, false) }
|
||||
gitlab_rails['gitlab_email_from'] = '${mail.sendgrid.email_from}'
|
||||
%{ endif }
|
||||
%{ if try(mail.sendgrid.email_reply_to != null, false) }
|
||||
gitlab_rails['email_reply_to'] = '${mail.sendgrid.email_reply_to}'
|
||||
%{ endif }
|
||||
%{ endif }
|
||||
|
||||
|
||||
gitlab_rails['gitlab_shell_ssh_port'] = 2222
|
||||
# gitlab_sshd['enable'] = true
|
||||
# gitlab_sshd['listen_address'] = '[::]:2222'
|
||||
|
||||
# https://docs.gitlab.com/omnibus/installation/index.html#set-up-the-initial-password
|
||||
# gitlab_rails['initial_root_password'] = '<my_strong_password>'
|
|
@ -0,0 +1,27 @@
|
|||
Port 2222
|
||||
ChallengeResponseAuthentication no
|
||||
HostKey /etc/gitlab/ssh_host_rsa_key
|
||||
HostKey /etc/gitlab/ssh_host_ecdsa_key
|
||||
HostKey /etc/gitlab/ssh_host_ed25519_key
|
||||
Protocol 2
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication no
|
||||
MaxStartups 100:30:200
|
||||
AllowUsers git
|
||||
PrintMotd no
|
||||
PrintLastLog no
|
||||
PubkeyAuthentication yes
|
||||
AuthorizedKeysFile %h/.ssh/authorized_keys /gitlab-data/ssh/authorized_keys
|
||||
AuthorizedKeysCommand /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-authorized-keys-check git %u %k
|
||||
AuthorizedKeysCommandUser git
|
||||
|
||||
# With "UsePAM yes" the "!" is seen as a password disabled account and not fully locked so ssh public key login works
|
||||
# Please make sure that the account is created without passwordlogin ("*" in /etc/shadow) or configure pam.
|
||||
# Issue #5891 https://gitlab.com/gitlab-org/omnibus-gitlab
|
||||
UsePAM no
|
||||
|
||||
# Disabling use DNS in ssh since it tends to slow connecting
|
||||
UseDNS no
|
||||
|
||||
# Enable the use of Git protocol v2
|
||||
AcceptEnv GIT_PROTOCOL
|
Binary file not shown.
After Width: | Height: | Size: 81 KiB |
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
locals {
|
||||
gitlab_rb = templatefile("${path.module}/assets/config.rb.tpl", {
|
||||
project_id = module.project.project_id
|
||||
cloudsql = {
|
||||
host = module.db.instances.primary.private_ip_address
|
||||
password = module.db.user_passwords.gitlab
|
||||
}
|
||||
mail = var.gitlab_config.mail
|
||||
redis = {
|
||||
host = google_redis_instance.cache.host
|
||||
port = google_redis_instance.cache.port
|
||||
}
|
||||
prefix = var.prefix
|
||||
saml = var.gitlab_config.saml
|
||||
hostname = var.gitlab_config.hostname
|
||||
})
|
||||
gitlab_ssl_crt = local.self_signed_ssl_certs_required ? tls_locally_signed_cert.gitlab_server_singed_cert.0.cert_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.crt")
|
||||
gitlab_ssl_key = local.self_signed_ssl_certs_required ? tls_private_key.gitlab_server_key.0.private_key_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.key")
|
||||
gitlab_ssl_ca_crt = local.self_signed_ssl_certs_required ? tls_self_signed_cert.gitlab_ca_cert.0.cert_pem : file("${path.module}/certs/${var.gitlab_config.hostname}.ca.crt")
|
||||
gitlab_ssl_ca_key = local.self_signed_ssl_certs_required ? tls_private_key.gitlab_ca_private_key.0.private_key_pem : ""
|
||||
self_signed_ssl_certs_required = fileexists("${path.module}/certs/${var.gitlab_config.hostname}.crt") && fileexists("${path.module}/certs/${var.gitlab_config.hostname}.key") && fileexists("${path.module}/certs/${var.gitlab_config.hostname}.ca.crt") ? false : true
|
||||
gitlab_user_data = templatefile("${path.module}/assets/cloud-config.yaml", {
|
||||
gitlab_config = var.gitlab_config
|
||||
gitlab_rb = indent(6, local.gitlab_rb)
|
||||
gitlab_sshd_config = indent(6, file("${path.module}/assets/sshd_config"))
|
||||
gitlab_cert_name = var.gitlab_config.hostname
|
||||
gitlab_ssl_key = indent(6, base64encode(local.gitlab_ssl_key))
|
||||
gitlab_ssl_crt = indent(6, base64encode(local.gitlab_ssl_crt))
|
||||
})
|
||||
}
|
||||
|
||||
module "gitlab-sa" {
|
||||
source = "../../../modules/iam-service-account"
|
||||
project_id = module.project.project_id
|
||||
name = var.gitlab_instance_config.name
|
||||
display_name = "Gitlab instance service account"
|
||||
iam = {
|
||||
"roles/iam.serviceAccountTokenCreator" = [module.gitlab-sa.iam_email]
|
||||
}
|
||||
iam_project_roles = {
|
||||
(module.project.project_id) = [
|
||||
"roles/logging.logWriter",
|
||||
"roles/monitoring.metricWriter",
|
||||
"roles/storage.admin"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module "gitlab-instance" {
|
||||
source = "../../../modules/compute-vm"
|
||||
project_id = module.project.project_id
|
||||
zone = var.gitlab_instance_config.zone
|
||||
name = var.gitlab_instance_config.name
|
||||
instance_type = var.gitlab_instance_config.instance_type
|
||||
boot_disk = {
|
||||
initialize_params = {
|
||||
image = "projects/cos-cloud/global/images/family/cos-stable"
|
||||
size = var.gitlab_instance_config.boot_disk.size
|
||||
type = var.gitlab_instance_config.boot_disk.type
|
||||
}
|
||||
}
|
||||
attached_disks = [
|
||||
{
|
||||
name = "data"
|
||||
size = var.gitlab_instance_config.data_disk.size
|
||||
type = var.gitlab_instance_config.data_disk.type
|
||||
options = {
|
||||
replica_zone = var.gitlab_instance_config.replica_zone
|
||||
}
|
||||
}
|
||||
]
|
||||
network_interfaces = [
|
||||
{
|
||||
network = var.network_config.network_self_link
|
||||
subnetwork = var.network_config.subnet_self_link
|
||||
}
|
||||
]
|
||||
tags = var.gitlab_instance_config.network_tags
|
||||
metadata = {
|
||||
user-data = local.gitlab_user_data
|
||||
google-logging-enabled = "true"
|
||||
}
|
||||
service_account = {
|
||||
email = module.gitlab-sa.email
|
||||
}
|
||||
}
|
||||
|
||||
module "ilb" {
|
||||
source = "../../../modules/net-lb-int"
|
||||
project_id = module.project.project_id
|
||||
region = var.region
|
||||
name = "ilb"
|
||||
service_label = "ilb"
|
||||
vpc_config = {
|
||||
network = var.network_config.network_self_link
|
||||
subnetwork = var.network_config.subnet_self_link
|
||||
}
|
||||
group_configs = {
|
||||
gitlab = {
|
||||
zone = var.gitlab_instance_config.zone
|
||||
instances = [
|
||||
module.gitlab-instance.self_link
|
||||
]
|
||||
}
|
||||
}
|
||||
backends = [
|
||||
{ group = module.ilb.groups.gitlab.self_link }
|
||||
]
|
||||
health_check_config = {
|
||||
https = {
|
||||
port = 443
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
module "project" {
|
||||
source = "../../../modules/project"
|
||||
parent = try(var.project_create.parent, null)
|
||||
billing_account = try(var.project_create.billing_account_id, null)
|
||||
prefix = var.project_create == null ? null : var.prefix
|
||||
name = var.project_id
|
||||
project_create = var.project_create != null
|
||||
services = [
|
||||
"compute.googleapis.com",
|
||||
"memcache.googleapis.com",
|
||||
"redis.googleapis.com",
|
||||
"sqladmin.googleapis.com",
|
||||
"sql-component.googleapis.com",
|
||||
"stackdriver.googleapis.com",
|
||||
"dns.googleapis.com",
|
||||
"iam.googleapis.com",
|
||||
]
|
||||
shared_vpc_service_config = {
|
||||
attach = true
|
||||
host_project = var.network_config.host_project
|
||||
service_identity_iam = {
|
||||
"roles/compute.networkUser" = [
|
||||
"cloudservices", "compute"
|
||||
]
|
||||
}
|
||||
network_users = var.admin_principals
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
locals {
|
||||
ssl_certs = {
|
||||
"${var.gitlab_config.hostname}.crt" = local.gitlab_ssl_crt
|
||||
"${var.gitlab_config.hostname}.key" = local.gitlab_ssl_key,
|
||||
"${var.gitlab_config.hostname}.ca.crt" = local.gitlab_ssl_ca_crt,
|
||||
"${var.gitlab_config.hostname}.ca.key" = local.gitlab_ssl_ca_key
|
||||
}
|
||||
}
|
||||
|
||||
output "gitlab_ilb_ip" {
|
||||
description = "Gitlab Internal Load Balancer IP Address."
|
||||
value = module.ilb.forwarding_rule_addresses[""]
|
||||
}
|
||||
|
||||
output "instance" {
|
||||
description = "Gitlab compute engine instance."
|
||||
value = module.gitlab-instance.instance
|
||||
}
|
||||
|
||||
output "postgresql_users" {
|
||||
description = "Gitlab postgres user password."
|
||||
sensitive = true
|
||||
value = module.db.user_passwords
|
||||
}
|
||||
|
||||
output "project" {
|
||||
description = "GCP project."
|
||||
value = module.project
|
||||
}
|
||||
|
||||
output "ssh_to_gitlab" {
|
||||
description = "gcloud command to ssh gitlab instance."
|
||||
value = nonsensitive("gcloud compute ssh ${module.gitlab-instance.instance.name} --project ${module.project.project_id} --zone ${module.gitlab-instance.instance.zone} -- -L 8080:127.0.0.1:80 -L 2222:127.0.0.1:2222 -L 8443:127.0.0.1:443 -N -q -f")
|
||||
}
|
||||
|
||||
output "ssl_certs" {
|
||||
description = "Gitlab SSL Certificates."
|
||||
value = local.ssl_certs
|
||||
sensitive = true
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
locals {
|
||||
gitlab_buckets = [
|
||||
"gitlab-artifacts", "gitlab-mr-diffs", "gitlab-lfs", "gitlab-uploads",
|
||||
"gitlab-packages", "gitlab-dependency-proxy", "gitlab-terraform-state",
|
||||
"gitlab-pages"
|
||||
]
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# GITLAB MANAGED SERVICES #
|
||||
#######################################################################
|
||||
|
||||
# https://docs.gitlab.com/ee/install/requirements.html#database
|
||||
module "db" {
|
||||
source = "../../../modules/cloudsql-instance"
|
||||
project_id = module.project.project_id
|
||||
region = var.region
|
||||
name = var.cloudsql_config.name
|
||||
availability_type = var.gitlab_config.ha_required ? "REGIONAL" : "ZONAL"
|
||||
network_config = {
|
||||
authorized_networks = {}
|
||||
connectivity = {
|
||||
psa_config = {
|
||||
private_network = var.network_config.network_self_link
|
||||
}
|
||||
}
|
||||
}
|
||||
database_version = var.cloudsql_config.database_version
|
||||
databases = [
|
||||
"gitlabhq_production"
|
||||
]
|
||||
tier = var.cloudsql_config.tier
|
||||
users = {
|
||||
# generate password for user1
|
||||
gitlab = {
|
||||
password = null
|
||||
type = "BUILT_IN"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# https://docs.gitlab.com/ee/install/requirements.html#redis
|
||||
resource "google_redis_instance" "cache" {
|
||||
project = module.project.project_id
|
||||
region = var.region
|
||||
name = var.redis_config.name
|
||||
tier = var.redis_config.tier
|
||||
memory_size_gb = var.redis_config.memory_size_gb
|
||||
authorized_network = var.network_config.network_self_link
|
||||
connect_mode = "PRIVATE_SERVICE_ACCESS"
|
||||
|
||||
redis_version = var.redis_config.version
|
||||
display_name = "Gitlab Redis Instance"
|
||||
persistence_config {
|
||||
persistence_mode = var.redis_config.persistence_mode
|
||||
rdb_snapshot_period = var.redis_config.rdb_snapshot_period
|
||||
}
|
||||
}
|
||||
|
||||
# https://docs.gitlab.com/ee/administration/object_storage.html#google-cloud-storage-gcs
|
||||
module "gitlab_object_storage" {
|
||||
source = "../../../modules/gcs"
|
||||
for_each = toset(local.gitlab_buckets)
|
||||
project_id = module.project.project_id
|
||||
prefix = var.prefix
|
||||
name = each.key
|
||||
storage_class = var.gcs_config.storage_class
|
||||
location = var.gcs_config.location
|
||||
versioning = var.gcs_config.enable_versioning
|
||||
iam = {
|
||||
"roles/storage.objectUser" = [
|
||||
"serviceAccount:${module.gitlab-sa.email}",
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
locals {
|
||||
cert_subjects = [
|
||||
{
|
||||
country = "IT"
|
||||
province = "Lombardy"
|
||||
locality = "Milan"
|
||||
organization = "Example"
|
||||
organizational_unit = "Example"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# GITLAB CA PRIVATE KEY #
|
||||
#######################################################################
|
||||
|
||||
resource "tls_private_key" "gitlab_ca_private_key" {
|
||||
count = local.self_signed_ssl_certs_required ? 1 : 0
|
||||
algorithm = "RSA"
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# GITLAB CA CERT #
|
||||
#######################################################################
|
||||
|
||||
resource "tls_self_signed_cert" "gitlab_ca_cert" {
|
||||
count = local.self_signed_ssl_certs_required ? 1 : 0
|
||||
private_key_pem = tls_private_key.gitlab_ca_private_key.0.private_key_pem
|
||||
is_ca_certificate = true
|
||||
dynamic "subject" {
|
||||
for_each = toset(local.cert_subjects)
|
||||
content {
|
||||
country = subject.value.country
|
||||
province = subject.value.province
|
||||
locality = subject.value.locality
|
||||
common_name = "Gitlab CA"
|
||||
organization = subject.value.organization
|
||||
organizational_unit = subject.value.organizational_unit
|
||||
}
|
||||
}
|
||||
validity_period_hours = 43800 // 1825 days or 5 years
|
||||
allowed_uses = [
|
||||
"digital_signature",
|
||||
"cert_signing",
|
||||
"crl_signing",
|
||||
]
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# SERVER CERT SIGNED BY CA #
|
||||
#######################################################################
|
||||
|
||||
resource "tls_private_key" "gitlab_server_key" {
|
||||
count = local.self_signed_ssl_certs_required ? 1 : 0
|
||||
algorithm = "RSA"
|
||||
}
|
||||
|
||||
# Create CSR for Gitlab Server certificate
|
||||
resource "tls_cert_request" "gitlab_server_csr" {
|
||||
count = local.self_signed_ssl_certs_required ? 1 : 0
|
||||
private_key_pem = tls_private_key.gitlab_server_key.0.private_key_pem
|
||||
dns_names = [var.gitlab_config.hostname]
|
||||
|
||||
dynamic "subject" {
|
||||
for_each = toset(local.cert_subjects)
|
||||
content {
|
||||
country = subject.value.country
|
||||
province = subject.value.province
|
||||
locality = subject.value.locality
|
||||
common_name = "Gitlab"
|
||||
organization = subject.value.organization
|
||||
organizational_unit = subject.value.organizational_unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "tls_locally_signed_cert" "gitlab_server_singed_cert" {
|
||||
count = local.self_signed_ssl_certs_required ? 1 : 0
|
||||
cert_request_pem = tls_cert_request.gitlab_server_csr.0.cert_request_pem
|
||||
ca_private_key_pem = tls_private_key.gitlab_ca_private_key.0.private_key_pem
|
||||
ca_cert_pem = tls_self_signed_cert.gitlab_ca_cert.0.cert_pem
|
||||
|
||||
validity_period_hours = 43800
|
||||
|
||||
allowed_uses = [
|
||||
"digital_signature",
|
||||
"key_encipherment",
|
||||
"server_auth",
|
||||
"client_auth",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
gitlab_config = {
|
||||
hostname = "gitlab.gcp.example.com"
|
||||
mail = {
|
||||
sendgrid = {
|
||||
api_key = "sample_api_key"
|
||||
}
|
||||
}
|
||||
saml = {
|
||||
idp_cert_fingerprint = "67:90:96.....REPLACE_ME"
|
||||
sso_target_url = "https://accounts.google.com/o/saml2/idp?idpid=REPLACE_ME"
|
||||
}
|
||||
}
|
||||
network_config = {
|
||||
host_project = "host-project"
|
||||
network_self_link = "network_self_link"
|
||||
subnet_self_link = "subnetwork_self_link"
|
||||
}
|
||||
prefix = "prefix"
|
||||
project_id = "prod-gitlab-0"
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
variable "admin_principals" {
|
||||
description = "Users, groups and/or service accounts that are assigned roles, in IAM format (`group:foo@example.com`)."
|
||||
type = list(string)
|
||||
default = []
|
||||
}
|
||||
|
||||
variable "cloudsql_config" {
|
||||
description = "Cloud SQL Postgres config."
|
||||
type = object({
|
||||
name = optional(string, "gitlab-0")
|
||||
database_version = optional(string, "POSTGRES_13")
|
||||
tier = optional(string, "db-custom-2-8192")
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "gcs_config" {
|
||||
description = "GCS for Object Storage config."
|
||||
type = object({
|
||||
enable_versioning = optional(bool, false)
|
||||
location = optional(string, "EU")
|
||||
storage_class = optional(string, "STANDARD")
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "gitlab_config" {
|
||||
description = "Gitlab configuration."
|
||||
type = object({
|
||||
hostname = optional(string, "gitlab.gcp.example.com")
|
||||
mail = optional(object({
|
||||
enabled = optional(bool, false)
|
||||
sendgrid = optional(object({
|
||||
api_key = optional(string)
|
||||
email_from = optional(string, null)
|
||||
email_reply_to = optional(string, null)
|
||||
}), null)
|
||||
}), {})
|
||||
saml = optional(object({
|
||||
forced = optional(bool, false)
|
||||
idp_cert_fingerprint = string
|
||||
sso_target_url = string
|
||||
name_identifier_format = optional(string, "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress")
|
||||
}), null)
|
||||
ha_required = optional(bool, false)
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "gitlab_instance_config" {
|
||||
description = "Gitlab Compute Engine instance config."
|
||||
type = object({
|
||||
instance_type = optional(string, "n1-highcpu-8")
|
||||
name = optional(string, "gitlab-0")
|
||||
network_tags = optional(list(string), [])
|
||||
replica_zone = optional(string)
|
||||
zone = optional(string)
|
||||
boot_disk = optional(object({
|
||||
size = optional(number, 20)
|
||||
type = optional(string, "pd-standard")
|
||||
}), {})
|
||||
data_disk = optional(object({
|
||||
size = optional(number, 100)
|
||||
type = optional(string, "pd-ssd")
|
||||
replica_zone = optional(string)
|
||||
}), {})
|
||||
})
|
||||
}
|
||||
|
||||
variable "network_config" {
|
||||
description = "Shared VPC network configurations to use for Gitlab Runner VM."
|
||||
type = object({
|
||||
host_project = optional(string)
|
||||
network_self_link = string
|
||||
subnet_self_link = string
|
||||
})
|
||||
}
|
||||
|
||||
variable "prefix" {
|
||||
description = "Prefix used for resource names."
|
||||
type = string
|
||||
nullable = false
|
||||
validation {
|
||||
condition = var.prefix != ""
|
||||
error_message = "Prefix cannot be empty."
|
||||
}
|
||||
}
|
||||
|
||||
variable "project_create" {
|
||||
description = "Provide values if project creation is needed, uses existing project if null. Parent is in 'folders/nnn' or 'organizations/nnn' format."
|
||||
type = object({
|
||||
billing_account_id = string
|
||||
parent = string
|
||||
})
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "project_id" {
|
||||
description = "Project id, references existing project if `project_create` is null."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "redis_config" {
|
||||
description = "Redis Config."
|
||||
type = object({
|
||||
memory_size_gb = optional(number, 1)
|
||||
name = optional(string, "gitlab-0")
|
||||
persistence_mode = optional(string, "RDB")
|
||||
rdb_snapshot_period = optional(string, "TWELVE_HOURS")
|
||||
tier = optional(string, "BASIC")
|
||||
version = optional(string, "REDIS_6_X")
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "GCP Region."
|
||||
type = string
|
||||
}
|
Loading…
Reference in New Issue