How to Deploy GitLab on AWS EC2 with Walrus
Tags: devops, beginners, gitlab, tutorial
Published: 2023-10-25 17:17:00

Walrus, the open-source application management platform, equips your team with templates designed to optimize best practices. In this blog, we'll walk you through the process of creating an AWS GitLab template and deploying a GitLab server on an AWS EC2 instance.

## Prerequisites

1. A GitHub or Gitlab Repository for storing the template.
2. [Walrus installed.](https://seal-io.github.io/docs/deploy/standalone)

## Create a repository on GitHub

1. Create a new repository on GitHub of your own. Here we use the repository [demo](https://gitlab.com/seal-eyod/gitlab-on-aws).
2. Clone the repository to your local machine.

```
git clone git@gitlab.com:seal-eyod/gitlab-on-aws.git
```

## Create Template Files

Go to the cloned repository directory.

```
cd gitlab-on-aws
```

Create files in the directory as follows:

```
  - gitlab-on-aws
    - main.tf
    - outputs.tf
    - variables.tf
    - README.md
```

The `main.tf` file defines the resources to be created. Here we define the resource for the template to create an AWS EC2 instance and run a Gitlab server on it.

```
  data "aws_ami" "ubuntu" {
    most_recent = true
  
    filter {
      name   = "name"
      values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
    }
  
    filter {
      name   = "virtualization-type"
      values = ["hvm"]
    }
  
    owners = ["099720109477"] # Canonical
  }
  
  
  data "aws_security_group" "selected" {
    name = var.security_group_name
  }
  
  data "aws_subnets" "selected" {
    filter {
      name   = "vpc-id"
      values = [data.aws_security_group.selected.vpc_id]
    }
  }
  
  resource "aws_instance" "gitlab" {
    ami           = data.aws_ami.ubuntu.id
    instance_type = var.instance_type
    subnet_id     = data.aws_subnets.selected.ids.0
    vpc_security_group_ids = [data.aws_security_group.selected.id]
    key_name      = var.key_name
    user_data     = <<-EOF
                    #!/bin/bash
                    set -ex;
                    public_ip=$(curl http://169.254.169.254/latest/meta-data/public-ipv4)
                    curl -fsSL https://get.docker.com | bash && sudo usermod -aG docker ubuntu
                    docker run -d --privileged --restart=always -p 80:80 -p 443:443 \
                    -e GITLAB_ROOT_PASSWORD="${var.gitlab_root_password}" \
                    "${var.gitlab_image}"
                    EOF
    tags = {
      "Name" = "${var.gitlab_metadata_application_instance_name}-gitlab"
    }
  
    root_block_device {
      volume_size = var.disk_size
    }
  }
  
  resource "null_resource" "gitlab_health_check" {
    depends_on = [
      aws_instance.gitlab,
    ]
  
    triggers = {
      always_run = timestamp()
    }
  
    provisioner "local-exec" {
      command     = "for i in `seq 1 100`; do curl -k -s $ENDPOINT >/dev/null && exit 0 || true; sleep 5; done; echo TIMEOUT && exit 1"
      interpreter = ["/bin/sh", "-c"]
      environment = {
        ENDPOINT = "http://${aws_instance.gitlab.public_ip}"
      }
    }
  }
```

The `variables.tf` file defines the variables used in the template. Walrus will use the variables to generate the form for users to fill in.

Walrus uses the `@label` and `@group` annotations to define the labels and groups of the variables. The optional `@options` annotation is used to define the dropdown options of the variable, if the `@options` annotation is not defined, the variable will be displayed as a text box in the form.Here are [more details about the annotations](https://seal-io.github.io/docs/operation/template#variable-style-extension).

In this example, we define two groups: `Basic` and `AWS`. It will be displayed as two tabs in the form when creating a service using this template.

```
  # @group "Basic"
variable "gitlab_image" {
  type        = string
  description = "gitlab image"
  default     = "gitlab/gitlab-ce"
}

# @group "Basic"
variable "gitlab_root_password" {
  type        = string
  description = "gitlab root password"
  default     = "seal123456"
  sensitive   = true
}

# @group "AWS"
# @options ["t3.medium", "c5.xlarge"]
variable "instance_type" {
  type        = string
  description = "Instance type"
  default     = "t3.medium"
}

# @group "AWS"
variable "disk_size" {
  type        = number
  description = "Root disk size in GiB"
  default     = 50
}

# @group "AWS"
variable "key_name" {
  type        = string
  description = "AWS key name"
  default     = "xueying"
}

# @group "AWS"
variable "security_group_name" {
  type        = string
  description = "Security group Name"
  default     = "all-open"
}

# @hidden
variable "gitlab_metadata_application_instance_name" {
  type        = string
  description = "gitlab metadata application instance name."
  default     = "bar"
}
```

The `outputs.tf` file defines the outputs of the template which will be displayed to the user after the service is created. The outputs of the template of a service could also be referenced by other services. In this example, we define an output `gitlab_url` which is the URL of the Gitlab instance.

```
  output "gitlab_url" {
    description = "The URL of the GitLab instance"
    value = "http://${aws_instance.gitlab.public_ip}"
  }
```

The `README.md` file is the description of the template. It will be displayed to the user when creating a service using this template.

Here we can use the tool [terraform-docs](https://github.com/terraform-docs/terraform-docs) to generate the description of the template. You need to follow the document of the project, install the tool on your laptop, and run the following command to generate a `README.md` file for the template.

```
  terraform-docs markdown . > README.md
```

The generated `README.md` file is as follows:

```
# Gitlab on AWS

This is a terraform module that will create a Gitlab instance on AWS.

## Providers

| Name | Version |
|------|---------|
| aws  | n/a     |

## Inputs

| Name                                      | Description                                |   Type   |       Default        | Required |
|-------------------------------------------|--------------------------------------------|:--------:|:--------------------:|:--------:|
| gitlab_image                              | Gitlab image                               | `string` | `"gitlab/gitlab-ce"` |    no    |
| gitlab_root_password                      | Gitlab root password                       | `string` |    `"seal123456"`    |    no    |
| instance\_type                            | Instance type                              | `string` |    `"t3.medium"`     |    no    |
| disk\_size                                | Root disk size in GiB                      | `number` |         `50`         |    no    |
| security\_group\_name                     | Security group Name                        | `string` |     `"all-open"`     |    no    |
| gitlab_metadata_application_instance_name | gitlab metadata application instance name. | `string` |       `"bar"`        |    no    |

## Outputs

| Name       | Description |
|------------|-------------|
| gitlab_url | Gitlab URL  |
```

## Commit and Tag Version

```
  git add .
  git commit -m "add template files"
  git push -u origin main
```

Create a tag for the template version.

```
  git tag v0.0.1
  git push --tags
```

## Create a Template on Walrus

1. Open Walrus in your browser and log in.

2. Navigate to the `Template` tab within the `Operations` Hub and craft a new template by selecting the one we've recently created.For reference, let's name this template `gitlab-on-aws`.


![new-template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3lvj222xqpom8yqcfohv.png)

After Walrus syncs the template, you can see the template in `Operations` Hub.


![operation-hub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k3boty0bpgz41uzaqmi9.png)

Once the import task is finished, you'll find the template proudly showcased in the list. Take note that the template boasts two versions: `v0.0.1` and `v0.0.2`.


![template-details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y1co4qeehxlpbkk3y1hd.png)

## Deploy Gitlab Server on AWS

Add AWS Cloud Provider in the `Connectors` tab within the `Operation` Hub.


![connector](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4y7p8jnogm4vcp4dht64.png)

Add Connector to the Environment.


![new-env](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0t3nkfgc6s4za591z4gb.png)

Generate a service utilizing the `gitlab-on-aws` template. The form groups and labels are dynamically generated based on the annotations specified in the template variables we've previously defined. Notably, there are two groups, and the input variables are outlined in the `variables.tf` file of the template.

To ensure network traffic management, an EC2 instance requires a security group. We can create a security group named `all-open` to permit all network traffic. For enhanced security, you can customize the group's rules as needed.


![security-groups](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvl76cukn89rrw401sjg.png)

After the security group is created in your AWS target region, you can save and apply the service.


![new-service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtdwj4qva96sgospjm9f.png)


![deployment-details](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujkwqw53kr0v79xkwgbr.png)

Once the deployment process is complete, the Gitlab instance is successfully provisioned on AWS.


![gitlab-on-AWS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hig14yniohhczm2uv0oo.png)

The GitLab URL will be shown in the outputs. Once you have the URL, you can access the GitLab server.


![gitlab-in-walrus](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ak6595w3ek97tdbpac0.png)


![gitlab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/isz4aw57rol24g6el73a.png)

## Conclusion

You've just witnessed the entire process of template creation in Walrus, a tool that significantly streamlines the deployment process. Furthermore, Walrus boasts compatibility with a plethora of mature templates from the Terraform community, allowing you to effortlessly adopt best practices with a single click.

We invite you to [give Walrus a try](https://github.com/seal-io/walrus) and encourage you to seek support on our [Discord](https://discord.gg/fXZUKK2baF). Your journey to smoother application management begins here!