{"id":17068621,"url":"https://github.com/defo89/hello-world-gitlab-ci","last_synced_at":"2026-03-01T11:03:44.011Z","repository":{"id":192762579,"uuid":"131111532","full_name":"defo89/hello-world-gitlab-ci","owner":"defo89","description":"Automated deployment to AWS using Gitlab CI, Terraform, Packer and Ansible ","archived":false,"fork":false,"pushed_at":"2018-06-18T09:15:00.000Z","size":1196,"stargazers_count":13,"open_issues_count":0,"forks_count":18,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-03T01:18:45.946Z","etag":null,"topics":["ansible","aws","ci-cd","gitlab-ci","gitlab-runner","infrastructure-as-code","packer","terraform"],"latest_commit_sha":null,"homepage":null,"language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/defo89.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-04-26T06:41:54.000Z","updated_at":"2024-08-22T19:47:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"a40f820e-2ec5-498c-9e69-29b0de82d590","html_url":"https://github.com/defo89/hello-world-gitlab-ci","commit_stats":null,"previous_names":["defo89/hello-world-gitlab-ci"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/defo89/hello-world-gitlab-ci","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defo89%2Fhello-world-gitlab-ci","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defo89%2Fhello-world-gitlab-ci/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defo89%2Fhello-world-gitlab-ci/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defo89%2Fhello-world-gitlab-ci/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/defo89","download_url":"https://codeload.github.com/defo89/hello-world-gitlab-ci/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/defo89%2Fhello-world-gitlab-ci/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29967932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T10:55:55.490Z","status":"ssl_error","status_checked_at":"2026-03-01T10:55:55.175Z","response_time":124,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","aws","ci-cd","gitlab-ci","gitlab-runner","infrastructure-as-code","packer","terraform"],"created_at":"2024-10-14T11:14:18.200Z","updated_at":"2026-03-01T11:03:43.981Z","avatar_url":"https://github.com/defo89.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Gitlab CI demo with Terraform and Packer\n\nThis project provisions an AWS Application Load Balancer including the required infrastructure.\nIt was created mainly for learning purposes and consists of the following building blocks:\n- EC2 instance AMI is pre-baked with [Packer](https://www.packer.io) using [Ansible](https://ansible.com) as a provisioner.\n- Infrastructure is provisioned using [Terraform](https://www.terraform.io) module.\n- Gitlab CI orchestrates actions with Packer and Terraform.\n\n**Note**\n- Public and private keys provided are just for demo purposes \n- You are encouraged to create your own ones and edit the *resource \"aws_key_pair\"* entry in the *aws-demo.tf* file\n\n![AWS infra](img/infra.png)\n\n## Terraform state\nTerraform state and plan files are stored on S3 bucket, so it needs to be created beforehand.\nNo public access is required.\n\n![S3 state](img/s3-state.png)\n\n```\n# state.tf\nterraform {\n  backend \"s3\" {\n    bucket = \"terraform-remote-state-defo\"\n    key    = \"terraform-state-packer-aws-with-gitlab.tfstate\"\n    region = \"eu-west-1\"\n  }\n}\n```\n\n# Manual way\n\n**Set desired AWS credentials**\n\nIn this example I am using [**aws-vault**](https://github.com/99designs/aws-vault) to work with desired profile.\n\n```\n❯ aws-vault add home\nEnter Access Key ID: your-aws-access-key-id\nEnter Secret Access Key: your-aws-access-key\nAdded credentials to profile \"home\" in vault\n\n# launches subshell with desired AWS environment variables\n❯ aws-vault exec -- home\n```\n\n**Requirements**\n- [Packer](https://www.packer.io)\n- [Terraform](https://www.terraform.io)\n- [aws-vault](https://github.com/99designs/aws-vault)\n\n\n```\n❯ git clone git@github.com:dmitrijsf/hello-world-gitlab-ci.git\n❯ cd hello-world-gitlab-ci\n```\n\n**Build AWS AMI using Packer**\n\nAnsible will apply 2 roles:\n- common: install common software and perform upgrade\n- web: install nginx and copy custom index.html\n\n```\n❯ cd packer \u0026\u0026 packer validate template_ami.json\nTemplate validated successfully.\n\n❯ packer build template_ami.json\namazon-ebs output will be in this color.\n\n==\u003e amazon-ebs: Prevalidating AMI Name: packer-ami 1529266559\n    amazon-ebs: Found Image ID: ami-ca0135b3\n==\u003e amazon-ebs: Creating temporary keypair: packer_5b26c17f-0903-cb8b-b765-0648cca27038\n==\u003e amazon-ebs: Creating temporary security group for this instance: packer_5b26c180-2856-7266-5c9f-2f9747183e4b\n==\u003e amazon-ebs: Authorizing access to port 22 from 0.0.0.0/0 in the temporary security group...\n==\u003e amazon-ebs: Launching a source AWS instance...\n==\u003e amazon-ebs: Adding tags to source instance\n    amazon-ebs: Adding tag: \"Name\": \"Packer Builder\"\n    amazon-ebs: Instance ID: i-0cd68683514e8c5d9\n==\u003e amazon-ebs: Waiting for instance (i-0cd68683514e8c5d9) to become ready...\n==\u003e amazon-ebs: Waiting for SSH to become available...\n==\u003e amazon-ebs: Connected to SSH!\n==\u003e amazon-ebs: Uploading scripts =\u003e /home/ec2-user/\n==\u003e amazon-ebs: Provisioning with shell script: scripts/prepare.sh\n-- snip --\n    amazon-ebs: Uploading Playbook directory to Ansible staging directory...\n    amazon-ebs: Creating directory: /tmp/packer-provisioner-ansible-local/5b26c17f-7a7a-ab3f-f096-0e3a47c4fe90\n    amazon-ebs: Uploading main Playbook file...\n    amazon-ebs: Uploading inventory file...\n    amazon-ebs: Executing Ansible: cd /tmp/packer-provisioner-ansible-local/5b26c17f-7a7a-ab3f-f096-0e3a47c4fe90 \u0026\u0026 ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 ansible-playbook /tmp/packer-provisioner-ansible-local/5b26c17f-7a7a-ab3f-f096-0e3a47c4fe90/provision_host.yml --extra-vars \"packer_build_name=amazon-ebs packer_builder_type=amazon-ebs packer_http_addr=\"  -c local -i /tmp/packer-provisioner-ansible-local/5b26c17f-7a7a-ab3f-f096-0e3a47c4fe90/packer-provisioner-ansible-local700540066\n    amazon-ebs:\n    amazon-ebs: PLAY [prepare host] ************************************************************\n    amazon-ebs:\n    amazon-ebs: TASK [common : install basic packages] *****************************************\n    amazon-ebs: changed: [127.0.0.1] =\u003e (item=[u'git', u'tree', u'vim', u'htop', u'mlocate'])\n    amazon-ebs:\n    amazon-ebs: TASK [common : upgrade all packages, including kernel] *************************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : install nginx] *****************************************************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : remove web root directory if exists] *******************************\n    amazon-ebs: ok: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : create web root directory] *****************************************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : generate and copy nginx configuration file to server] **************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : generate and copy index.html file to server] ***********************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: TASK [web : enable and start http] *********************************************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: RUNNING HANDLER [web : restart nginx] ******************************************\n    amazon-ebs: changed: [127.0.0.1]\n    amazon-ebs:\n    amazon-ebs: PLAY RECAP *********************************************************************\n    amazon-ebs: 127.0.0.1                  : ok=9    changed=8    unreachable=0    failed=0\n    amazon-ebs:\n==\u003e amazon-ebs: Provisioning with shell script: scripts/cleanup.sh\n    amazon-ebs: Uninstalling ansible-2.5.5:\n    amazon-ebs: You are using pip version 9.0.3, however version 10.0.1 is available.\n    amazon-ebs: You should consider upgrading via the 'pip install --upgrade pip' command.\n    amazon-ebs:   Successfully uninstalled ansible-2.5.5\n==\u003e amazon-ebs: Stopping the source instance...\n    amazon-ebs: Stopping instance, attempt 1\n==\u003e amazon-ebs: Waiting for the instance to stop...\n==\u003e amazon-ebs: Creating the AMI: packer-ami 1529266559\n    amazon-ebs: AMI: ami-47f0f3ad\n==\u003e amazon-ebs: Waiting for AMI to become ready...\n==\u003e amazon-ebs: Adding tags to AMI (ami-47f0f3ad)...\n==\u003e amazon-ebs: Tagging snapshot: snap-04af53cb030792e30\n==\u003e amazon-ebs: Creating AMI tags\n    amazon-ebs: Adding tag: \"Name\": \"webserver\"\n    amazon-ebs: Adding tag: \"Project\": \"testing\"\n==\u003e amazon-ebs: Creating snapshot tags\n==\u003e amazon-ebs: Terminating the source AWS instance...\n==\u003e amazon-ebs: Cleaning up any extra volumes...\n==\u003e amazon-ebs: No volumes to clean up, skipping\n==\u003e amazon-ebs: Deleting temporary security group...\n==\u003e amazon-ebs: Deleting temporary keypair...\nBuild 'amazon-ebs' finished.\n\n==\u003e Builds finished. The artifacts of successful builds are:\n--\u003e amazon-ebs: AMIs were created:\neu-west-1: ami-47f0f3ad\n```\n\n**Build AWS infrastructure using Terraform**\n\nTerraform will build the AWS infrastructure.\nPreviosly pre-baked AMI will be used in the Auto-Scaling Group.\n\n```\n# aws-demo.tfvars\nenvironment = \"dev\"\nvpc_cidr = \"10.172.0.0/16\"\npublic_subnet_cidrs = [\"10.172.1.0/24\", \"10.172.2.0/24\"]\nprivate_subnet_cidrs = [\"10.172.81.0/24\", \"10.172.82.0/24\"]\navailability_zones = [\"eu-west-1a\", \"eu-west-1b\"]\nmax_size = 4\nmin_size = 2\ninstance_type = \"t2.micro\"\n```\n\n```\n❯ cd ../terraform\n❯ terraform validate -var-file=aws-demo.tfvars\n❯ terraform apply -var-file=aws-demo.tfvars\n-- snip --\nApply complete! Resources: 32 added, 0 changed, 0 destroyed.\n\nOutputs:\n\nALB DNS Name = default-397873677.eu-west-1.elb.amazonaws.com\nBastion DNS Name = ec2-34-247-38-196.eu-west-1.compute.amazonaws.com\n```\n\n**Test web access**\n\n![Website](img/website.png)\n\n**Access the instances**\n\n```\n# ssh to bastion host\n❯ ssh -i aws_fake_key ubuntu@ec2-34-247-38-196.eu-west-1.compute.amazonaws.com\nAre you sure you want to continue connecting (yes/no)? yes\nubuntu@ip-10-172-1-73:~$\n\n# ssh to the instance through the bastion host\n❯ ssh-add -K aws_fake_key\n❯ ssh -A ubuntu@ec2-34-247-38-196.eu-west-1.compute.amazonaws.com\nubuntu@ip-10-172-1-73:~$ ssh ec2-user@10.172.82.192\nWarning: Permanently added '10.172.82.192' (ECDSA) to the list of known hosts.\n\n       __|  __|_  )\n       _|  (     /   Amazon Linux AMI\n      ___|\\___|___|\n\nhttps://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/\n[ec2-user@ip-10-172-82-192 ~]$ service nginx status\nnginx (pid 2625 2622) is running...\n[ec2-user@ip-10-172-82-192 ~]$\n```\n\n**Destroy the environment**\n\n```\n❯ terraform destroy -var-file=aws-demo.tfvars\n-- snip --\nDestroy complete! Resources: 32 destroyed.\n```\n\nDeregister the AMI created by Packer.\n\n![AMI deregister](img/ami-deregister.png)\n\nDelete the snaphot to avoid being charged for storing it.\n\n![Snapshot delete](img/snapshot-delete.png)\n\n\n# Using Gitlab CI\n\n## Configuration\n\n[Gitlab CI](https://about.gitlab.com/features/gitlab-ci-cd/) is used together with [GitLab Runner run in a container](https://docs.gitlab.com/runner/install/docker.html).\nGitLab Runner should already be [registered](https://docs.gitlab.com/runner/register/index.html#docker).\n\nYou need to pass your [AWS credentials](https://docs.gitlab.com/ee/ci/variables/#secret-variables) to the runner:\n- AWS_ACCESS_KEY_ID\n- AWS_SECRET_ACCESS_KEY\n\nAll CI actions are defined in the [.gitlab-ci.yml](.gitlab-ci.yml) file.\n\n**Docker container for CI**\n\nEach job will trigger the Gitlab runner to launch a [Docker container](https://hub.docker.com/r/dmitrijsf/ci-docker/) to execute commands as instructed in the **gitlab-ci.yml** file.\n\n```\nimage:\n  name: dmitrijsf/ci-docker:latest\n  entrypoint:\n    - '/usr/bin/env'\n    - 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'\n```\n\n**Operations workflow**\n\nGitlab CI Pipeline is triggered by committing to the repository.\nIf merged or commited to master, **terraform apply** and **packer build** options are available to run manually.\n\nEdit the variable for S3 bucket (S3_BUCKET) accordingly.\n\n```\nvariables:\n  PACKER_DIR: packer\n  TF_DIR: terraform\n  PLAN: plan.tfplan\n  S3_BUCKET: terraform-remote-state-defo\n```\n\n- before_script: verify Packer and Terraform versions and run **terraform init**\n\n- validate stage: run validation of Packer and Terraform configuration\n\n- build-ami stage: pre-bake AWS AMI with desired configuration using Ansible as provisioner\n\n- plan stage: run **terraform plan** and copy the plan file to an S3 bucket\n\n- deploy stage: copy the plan file back from an S3 bucket locally and run  **terraform apply**","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefo89%2Fhello-world-gitlab-ci","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdefo89%2Fhello-world-gitlab-ci","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdefo89%2Fhello-world-gitlab-ci/lists"}