@@ -120,7 +120,7 @@ services:
120120 - " /var/run/docker.sock:/var/run/docker.sock:ro"
121121
122122 myadmin :
123- image : localhost:5000/comyadminre :latest
123+ image : localhost:5000/myadmin :latest
124124 pull_policy : always
125125 restart : always
126126 env_file :
@@ -139,15 +139,27 @@ volumes:
139139
140140## Step 3 - create a SSH keypair
141141
142- Make sure you are in ` deploy` folder, run next command here :
142+ Make sure you are still in ` deploy` folder, run next command:
143143
144144` ` ` bash title="deploy"
145145mkdir .keys && ssh-keygen -f .keys/id_rsa -N ""
146146` ` `
147147
148148Now it should create `deploy/.keys/id_rsa` and `deploy/.keys/id_rsa.pub` files with your SSH keypair. Terraform script will put the public key to the EC2 instance and will use private key to connect to the instance. Also you will be able to use it to connect to the instance manually.
149149
150- # # Step 4 - .gitignore file
150+ # # Step 4 - create TLS certificates to encrypt traffic between CI and registry
151+
152+ Make sure you are still in `deploy` folder, run next command :
153+
154+ Run next command to create TLS certificates :
155+
156+ ` ` ` bash
157+ openssl req -new -x509 -days 3650 -newkey rsa:4096 -nodes -keyout .keys/ca.key -subj "/CN=My Custom CA" -out .keys/ca.pem
158+ ` ` `
159+
160+ This will create `deploy/.keys/ca.key` and `deploy/.keys/ca.pem` files.
161+
162+ # # Step 5 - .gitignore file
151163
152164Create `deploy/.gitignore` file with next content :
153165
@@ -161,8 +173,30 @@ tfplan
161173.env.live
162174` ` `
163175
164- # # Step 5 - Main terraform file main.tf
176+ # # Step 6 - buildx bake file
177+
178+ Create file `deploy/docker-bake.hcl` :
179+
180+ ` ` ` hcl title="deploy/docker-bake.hcl"
181+ variable "REGISTRY_BASE" {
182+ default = "appserver.local:5000"
183+ }
184+
185+ group "default" {
186+ target = "myadmin"
187+ }
188+
189+ target "myadmin" {
190+ context = "../myadmin"
191+ tags = ["${REGISTRY_BASE}/myadmin:latest"]
192+ cache-from = ["type=registry,ref=${REGISTRY_BASE}/myadmin:cache"]
193+ cache-to = ["type=registry,ref=${REGISTRY_BASE}/myadmin:cache,mode=max,compression=zstd"]
194+ push = true
195+ }
196+ ` ` `
197+
165198
199+ # # Step 7 - main terraform file main.tf
166200
167201First of all install Terraform as described here [terraform installation](https://developer.hashicorp.com/terraform/install#linux).
168202
@@ -324,6 +358,13 @@ resource "null_resource" "setup_registry" {
324358 echo "Creating htpasswd file for local registry"
325359 docker run --rm --entrypoint htpasswd httpd:2 -Bbn ci-user $(cat ./.keys/registry.pure) > ./.keys/registry.htpasswd
326360
361+ echo "Generating server certificate for registry"
362+ openssl genrsa -out ./.keys/registry.key 4096
363+ echo "subjectAltName=DNS:appserver.local,DNS:localhost,IP:127.0.0.1" > san.ext
364+ openssl req -new -key ./.keys/registry.key -subj "/CN=appserver.local" -addext "$(cat san.ext)" -out ./.keys/registry.csr
365+
366+ openssl x509 -req -days 365 -CA ./.keys/ca.pem -CAkey ./.keys/ca.key -set_serial 01 -in ./.keys/registry.csr -extfile san.ext -out ./.keys/registry.crt
367+
327368 echo "Copying registry secret files to the instance"
328369 rsync -t -avz -e "ssh -i ./.keys/id_rsa -o StrictHostKeyChecking=no" \
329370 ./.keys/registry.* ubuntu@${aws_eip_association.eip_assoc.public_ip}:/home/ubuntu/registry-auth
@@ -338,7 +379,6 @@ resource "null_resource" "setup_registry" {
338379
339380 # remove old registry if exists
340381 docker rm -f registry
341-
342382 # run new registry
343383 docker run -d --network host \
344384 --name registry \
@@ -348,6 +388,8 @@ resource "null_resource" "setup_registry" {
348388 -e "REGISTRY_AUTH=htpasswd" \
349389 -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
350390 -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/registry.htpasswd" \
391+ -e "REGISTRY_HTTP_TLS_CERTIFICATE=/auth/registry.crt" \
392+ -e "REGISTRY_HTTP_TLS_KEY=/auth/registry.key" \
351393 registry:2
352394
353395 EOF
@@ -372,7 +414,7 @@ resource "null_resource" "sync_files_and_run" {
372414 provisioner "local-exec" {
373415 command = <<-EOF
374416
375- # map appserver.local to the instance (in GA we don't know the IP, so have to use DNS mapping)
417+ # map appserver.local to the instance (in GA we don't know the IP, so have to use this mapping)
376418 grep -q "appserver.local" /etc/hosts || echo "${aws_eip_association.eip_assoc.public_ip} appserver.local" | sudo tee -a /etc/hosts
377419
378420 # hosts modification may take some time to apply
@@ -382,7 +424,7 @@ resource "null_resource" "sync_files_and_run" {
382424 sha256sum ./.keys/id_rsa | cut -d ' ' -f1 | tr -d '\n ' > ./.keys/registry.pure
383425 echo '{"auths":{"appserver.local:5000":{"auth":"'$(echo -n "ci-user:$(cat ./.keys/registry.pure)" | base64 -w 0)'"}}}' > ~/.docker/config.json
384426
385- echo "Running build and push with buildx bake "
427+ echo "Running build"
386428 docker buildx bake --progress=plain --push --allow=fs.read=..
387429
388430 # compose temporarily it is not working https://github.com/docker/compose/issues/11072#issuecomment-1848974315
@@ -396,6 +438,7 @@ resource "null_resource" "sync_files_and_run" {
396438 --exclude '.keys' \
397439 --exclude 'tfplan' \
398440 . ubuntu@${aws_eip_association.eip_assoc.public_ip}:/home/ubuntu/app/deploy/
441+
399442 EOF
400443 }
401444
@@ -486,7 +529,9 @@ resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state"
486529
487530> 👆 Replace `<your_app_name>` with your app name (no spaces, only underscores or letters)
488531
489- # ## Step 5.1 - Configure AWS Profile
532+
533+
534+ # ## Step 7.1 - Configure AWS Profile
490535
491536Open or create file `~/.aws/credentials` and add (if not already there) :
492537
@@ -496,7 +541,7 @@ aws_access_key_id = <your_access_key>
496541aws_secret_access_key = <your_secret_key>
497542` ` `
498543
499- # ## Step 5 .2 - Run deployment
544+ # ## Step 7 .2 - Run deployment
500545
501546To run the deployment first time, you need to run :
502547
@@ -510,7 +555,7 @@ Now run deployement:
510555terraform apply -auto-approve
511556` ` `
512557
513- # # Step 6 - Migrate state to the cloud
558+ # # Step 8 - Migrate state to the cloud
514559
515560First deployment had to create S3 bucket for storing Terraform state. Now we need to migrate the state to the cloud.
516561
@@ -549,13 +594,13 @@ terraform apply -auto-approve
549594Now you can delete local `terraform.tfstate` file and `terraform.tfstate.backup` file as they are in the cloud now.
550595
551596
552- # # Step 7 - CI/CD - Github Actions
597+ # # Step 9 - CI/CD - Github Actions
553598
554599Create file `.github/workflows/deploy.yml` :
555600
556601` ` ` yml title=".github/workflows/deploy.yml"
557- name: Deploy upworker
558- run-name: ${{ github.actor }} builds upworker 🚀
602+ name: Deploy myadmin
603+ run-name: ${{ github.actor }} builds myadmin 🚀
559604on: [push]
560605jobs:
561606 Explore-GitHub-Actions:
@@ -571,81 +616,78 @@ jobs:
571616 - run: echo "🔎 The name of your branch is ${{ github.ref }}"
572617 - name: Check out repository code
573618 uses: actions/checkout@v4
619+
574620 - name: Set up Terraform
575621 uses: hashicorp/setup-terraform@v2
576622 with:
577623 terraform_version: 1.10.1
578624
625+ - name: Import Registry CA
626+ run: |
627+ mkdir -p deploy/.keys
628+ echo "$VAULT_REGISTRY_CA_PEM" > deploy/.keys/ca.pem
629+ echo "$VAULT_REGISTRY_CA_KEY" > deploy/.keys/ca.key
630+ env:
631+ VAULT_REGISTRY_CA_PEM: ${{ secrets.VAULT_REGISTRY_CA_PEM }}
632+ VAULT_REGISTRY_CA_KEY: ${{ secrets.VAULT_REGISTRY_CA_KEY }}
633+
579634
580635 - name: Set up Docker Buildx
581636 uses: docker/setup-buildx-action@v3
582637 with:
583- # use 127.0.0.1 for dns
584638 buildkitd-config-inline: |
585639 [registry."appserver.local:5000"]
586- http = true
640+ ca=["deploy/.keys/ca.pem"]
587641
588- # use host network
642+ # use host network for resolving appserver.local
589643 driver-opts: network=host
590644
591- - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
592- - name: Start building
645+ - name: Import registry SSH keys
646+ run: |
647+ mkdir -p deploy/.keys
648+ echo "$VAULT_SSH_PRIVATE_KEY" > deploy/.keys/id_rsa
649+ echo "$VAULT_SSH_PUBLIC_KEY" > deploy/.keys/id_rsa.pub
650+ chmod 600 deploy/.keys/id_rsa*
593651 env:
594- VAULT_AWS_ACCESS_KEY_ID: ${{ secrets.VAULT_AWS_ACCESS_KEY_ID }}
595- VAULT_AWS_SECRET_ACCESS_KEY: ${{ secrets.VAULT_AWS_SECRET_ACCESS_KEY }}
596652 VAULT_SSH_PRIVATE_KEY: ${{ secrets.VAULT_SSH_PRIVATE_KEY }}
597653 VAULT_SSH_PUBLIC_KEY: ${{ secrets.VAULT_SSH_PUBLIC_KEY }}
598654
655+ - name: Setup AWS credentials
599656 run: |
600- /bin/sh -x deploy/deploy.sh
657+ mkdir -p ~/.aws
658+ cat <<EOL > ~/.aws/credentials
659+ [myaws]
660+ aws_access_key_id=${VAULT_AWS_ACCESS_KEY_ID}
661+ aws_secret_access_key=${VAULT_AWS_SECRET_ACCESS_KEY}
662+ EOL
663+ env:
664+ VAULT_AWS_ACCESS_KEY_ID: ${{ secrets.VAULT_AWS_ACCESS_KEY_ID }}
665+ VAULT_AWS_SECRET_ACCESS_KEY: ${{ secrets.VAULT_AWS_SECRET_ACCESS_KEY }}
666+
667+ - name: Terraform build
668+ run: |
669+ cd deploy
670+ terraform init -reconfigure
671+ # example of unlocking tf state if needed
672+ # terraform force-unlock fb397548-8697-ea93-ab80-128a4f508fdf --force
673+ terraform plan -out=tfplan
674+ terraform apply tfplan
675+
601676
602677 - run: echo "🍏 This job's status is ${{ job.status }}."
603678` ` `
604679
605- # ## Step 7.1 - Create deploy script
606-
607- Now create file `deploy/deploy.sh` :
608-
609- ` ` ` bash title="deploy/deploy.sh"
610-
611- # cd to dir of script
612- cd "$(dirname "$0")"
613-
614- mkdir -p ~/.aws ./.keys
615-
616- cat <<EOF > ~/.aws/credentials
617- [myaws]
618- aws_access_key_id=$VAULT_AWS_ACCESS_KEY_ID
619- aws_secret_access_key=$VAULT_AWS_SECRET_ACCESS_KEY
620- EOF
621-
622- cat <<EOF > ./.keys/id_rsa
623- $VAULT_SSH_PRIVATE_KEY
624- EOF
625-
626- cat <<EOF > ./.keys/id_rsa.pub
627- $VAULT_SSH_PUBLIC_KEY
628- EOF
629-
630- chmod 600 ./.keys/id_rsa*
631-
632- # init .env.live
633- echo "" > .env.live
634-
635- # force Terraform to reinitialize the backend without migrating the state.
636- terraform init -reconfigure
637- terraform plan -out=tfplan
638- terraform apply tfplan
639- ` ` `
640680
641- # ## Step 7.2 - Add secrets to GitHub
681+ # ## Step 8.1 - Add secrets to GitHub
642682
643683Go to your GitHub repository, then `Settings` -> `Secrets` -> `New repository secret` and add :
644684
645685- ` VAULT_AWS_ACCESS_KEY_ID` - your AWS access key
646686- ` VAULT_AWS_SECRET_ACCESS_KEY` - your AWS secret key
647- - ` VAULT_SSH_PRIVATE_KEY` - make `cat ~/.ssh/id_rsa` and paste to GitHub secrets
648- - ` VAULT_SSH_PUBLIC_KEY` - make `cat ~/.ssh/id_rsa.pub` and paste to GitHub secrets
687+ - ` VAULT_SSH_PRIVATE_KEY` - execute `cat ~/.ssh/id_rsa` and paste to GitHub secrets
688+ - ` VAULT_SSH_PUBLIC_KEY` - execute `cat ~/.ssh/id_rsa.pub` and paste to GitHub secrets
689+ - ` VAULT_REGISTRY_CA_PEM` - execute `cat deploy/.keys/ca.pem` and paste to GitHub secrets
690+ - ` VAULT_REGISTRY_CA_KEY` - execute `cat deploy/.keys/ca.key` and paste to GitHub secrets
649691
650692
651693Now you can push your changes to GitHub and see how it will be deployed automatically.
0 commit comments