Skip to content

Commit db9b0c6

Browse files
committed
deployment guide updates
1 parent 45782be commit db9b0c6

File tree

1 file changed

+101
-59
lines changed
  • adminforth/documentation/blog/2025-02-19-compose-ec2-deployment-ci-registry

1 file changed

+101
-59
lines changed

adminforth/documentation/blog/2025-02-19-compose-ec2-deployment-ci-registry/index.md

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -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"
145145
mkdir .keys && ssh-keygen -f .keys/id_rsa -N ""
146146
```
147147

148148
Now 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

152164
Create `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

167201
First 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

491536
Open or create file `~/.aws/credentials` and add (if not already there):
492537

@@ -496,7 +541,7 @@ aws_access_key_id = <your_access_key>
496541
aws_secret_access_key = <your_secret_key>
497542
```
498543

499-
### Step 5.2 - Run deployment
544+
### Step 7.2 - Run deployment
500545

501546
To run the deployment first time, you need to run:
502547

@@ -510,7 +555,7 @@ Now run deployement:
510555
terraform apply -auto-approve
511556
```
512557

513-
## Step 6 - Migrate state to the cloud
558+
## Step 8 - Migrate state to the cloud
514559

515560
First 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
549594
Now 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

554599
Create 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 🚀
559604
on: [push]
560605
jobs:
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

643683
Go 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

651693
Now you can push your changes to GitHub and see how it will be deployed automatically.

0 commit comments

Comments
 (0)