1. Connect to Your EC2 Server
Use SSH to connect to your EC2 instance:
ssh -i "yourfile.pem" ubuntu@ec2-XX-XXX-XX-XXX.us-west-2.compute.amazonaws.com
You should see a prompt like:
2. Generate SSL Key and CSR
Create the private key and certificate signing request (CSR):
sudo openssl req -new -newkey rsa:2048 -nodes \
-keyout linqra.key \
-out linqra.csr \
-subj "/C=US/ST=Texas/L=Houston/O=Linqra/OU=Production/CN=linqra.com"
Check the generated files:
ls -ltr
# Output example:
# -rw------- 1 root root 1704 Apr 8 17:02 linqra.key
3. Obtain SSL Certificates
- Go to your SSL provider (e.g., GoDaddy, Namecheap, or any hosting site that sells SSL certificates).
- Copy the contents of
linqra.csr
and paste it into the provider’s CSR box.
- Submit and wait for approval.
- Download the resulting ZIP file (Server type: Other), e.g.
linqra.com.zip
.
You will receive:
f8d48b14580110e.crt
f8d48b14580110e.pem
(identical to the .crt)
gd_bundle-g2.crt
4. Upload Certificates to the Server
Use FileZilla, IntelliJ, or another SFTP tool to upload the two .crt
files to /tmp/
on your EC2 server.
Then move them to the target directory:
sudo mv /tmp/*.crt /etc/pki/tls/certs/2025/
ls -ltr /etc/pki/tls/certs/2025/
Note: The .pem
and .crt
files from your provider are often identical.
5. Generate the Certificate Chain
Switch to root and concatenate the certificate and bundle to create the chained certificate:
sudo su
cat f8d48b14580110e.crt gd_bundle-g2.crt >> linqrachained2025.crt
exit
Check the resulting files:
ls -ltr
# -rw------- 1 root root 1704 Apr 8 17:03 linqra.key
# -rw-r--r-- 1 root root 1009 Apr 8 17:03 linqra.csr
# -rw-rw-r-- 1 ubuntu ubuntu 2329 Apr 8 17:21 f8d48b14580110e.crt
# -rw-rw-r-- 1 ubuntu ubuntu 3095 Apr 8 17:21 gd_bundle-g2.crt
# -rw-r--r-- 1 root root 5424 Apr 8 17:24 linqrachained2025.crt
You now have all the necessary SSL files (linqra.key
, linqrachained2025.crt
) to configure your web server for HTTPS on linqra.com.
6. Set Up AWS EC2 Folders and Prepare for Deployment
Create the necessary directories for your application and logs:
sudo mkdir -p /var/www/linqra
sudo mkdir -p /var/www/linqra/logs
7. Manage Nginx
You may need these commands to manage the Nginx service:
sudo systemctl status nginx
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
Edit the default Nginx site configuration:
sudo vi /etc/nginx/sites-available/default
Example configuration:
server {
server_name linqra.com www.linqra.com;
listen 80;
listen [::]:80;
return 301 https://linqra.com$request_uri;
}
server {
server_name www.linqra.com;
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/pki/tls/certs/2025/linqrachained2025.crt;
ssl_certificate_key /etc/pki/tls/certs/2025/linqra.key;
ssl_protocols TLSv1.2 TLSv1.1;
return 301 https://linqra.com$request_uri;
}
server {
listen 443 ssl;
ssl_certificate /etc/pki/tls/certs/2025/linqrachained2025.crt;
ssl_certificate_key /etc/pki/tls/certs/2025/linqra.key;
ssl_protocols TLSv1.2 TLSv1.1;
server_name linqra.com;
# Increase buffer sizes
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_max_temp_file_size 0;
proxy_http_version 1.1;
# Increase header buffer size
large_client_header_buffers 4 16k;
client_header_buffer_size 4k;
client_max_body_size 50M;
# Logs
access_log /var/www/linqra/logs/access.log;
error_log /var/www/linqra/logs/error.log;
location /keycloak/ {
proxy_pass http://localhost:8281;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# Add this rewrite rule to handle the redirect
proxy_redirect http://localhost:8281 https://linqra.com/keycloak;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect http:// https://;
}
# Handle realms paths
location /realms/ {
rewrite ^/realms/(.*) /keycloak/realms/$1 last;
}
# Handle resources paths
location /resources/ {
rewrite ^/resources/(.*) /keycloak/resources/$1 last;
}
# Handle admin paths
location /admin/ {
rewrite ^/admin/(.*) /keycloak/admin/$1 last;
}
location /eureka/ {
proxy_pass https://localhost:8761/eureka/;
proxy_ssl_verify off; # Only if using self-signed certs
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /api/auth/sso/callback {
proxy_pass https://localhost:7777/api/auth/sso/callback;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_ssl_verify off; # Since you're using self-signed certs
}
location /api/ {
proxy_pass https://localhost:7777/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /metrics/ {
proxy_pass https://localhost:7777/metrics/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /ws-linqra {
proxy_pass https://localhost:7777/ws-linqra;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_ssl_verify off; # Only if using self-signed certs
}
location /callback {
root /var/www/linqra/edge-service;
try_files $uri $uri/ /index.html;
# Add necessary headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
# Ensure proper proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /r/ {
proxy_pass https://localhost:7777/r/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_ssl_verify off; # Only if using self-signed certs
}
location /linq {
proxy_pass https://localhost:7777/linq;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Api-Key $http_x_api_key;
proxy_set_header X-Api-Key-Name $http_x_api_key_name;
proxy_ssl_verify off;
}
location / {
root /var/www/linqra/edge-service;
try_files $uri $uri/ /index.html;
# Basic security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
}
# Static assets
location /static/ {
root /var/www/html/linqra/edge-service;
expires 1y;
add_header Cache-Control "public, no-transform";
}
# Deny access to sensitive files
location ~ /\. {
deny all;
}
}
9. Enable the Nginx Site
Symlink the sites-available
file to the sites-enabled
folder:
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
10. Set Permissions for Deployment
Navigate to your deployment directory and set the correct permissions:
cd /var/www/html/linqra
sudo chown -R www-data:www-data edge-service
sudo find edge-service -type d -exec chmod 755 {} \;
sudo find edge-service -type f -exec chmod 644 {} \;
ls -la edge-service
Note:
- Always edit the
sites-available
file for Nginx configuration.
- Adjust the paths and domain names as needed for your environment.
To enable automated deployment and secure access, add the following secrets to your GitHub repository:
1. SSH Key for EC2
Generate or use your existing SSH private key.
Example (do not use this key, just for illustration):
-----BEGIN RSA PRIVATE KEY-----
AIIEogIBAAKCAQEAnIEpVE0yKTyvd63vXoFlICdqOlMNNIjCogHbE6Np/fgmDC8G
... (key content) ...
-----END RSA PRIVATE KEY-----
Add this as a new repository secret named:
2. EC2 Host and Deployment Info
Add the following repository secrets:
Secret Name | Example Value |
---|
HOST_DNS_PROD | ec2-XX-XXX-XX-XXX.us-west-2.compute.amazonaws.com |
USERNAME_PROD | ubuntu |
TARGET_DIR_PROD | /var/www/linqra |
3. AWS Credentials
Secret Name | Example Value |
---|
AWS_KEY | BKIA2YCP4BIK8KAWUILY |
AWS_SEC | 0UraNVReMtYbiqOB0ZGKiUTFzHFTFg9AZayniFda |
4. Web Application Secrets
Copy these from your web environment files and add as repository secrets:
Secret Name | Example Value |
---|
JWT_SECRET | 4a98d4c7b6e5f2a1d8c9b4a7e6f3d2c1b8a7e6f3d2c1b8a7e6f3d2c1b8a7e6f3d2c1b8a7e6f3d2c1b8a7e6f3d2c1b8a7e6f3d2c2 |
NODE_ENV | production |
VITE_WS_URL | wss://linqra.com/ws-linqra |
VITE_MONGODB_URI | mongodb://root:mongopw@localhost:27017 |
VITE_MONGODB_DB_NAME | Linqra |
VITE_API_GATEWAY_URL | https://linqra.com |
REACT_APP_KEYCLOAK_URL | https://linqra.com/keycloak |
REACT_APP_KEYCLOAK_REALM | Linqra |
REACT_APP_KEYCLOAK_CLIENT_ID | linqra-gateway-client |
VITE_API_KEY | lm_8e2093b6b9634dca9460f8d0cdfe38cb |
VITE_API_KEY_NAME | MyApiKey |
How to add a secret:
- Go to your GitHub repository.
- Click on Settings > Secrets and variables > Actions.
- Click New repository secret.
- Enter the name and value, then click Add secret.
Tip:
Never commit your private keys or secrets to the repository. Always use GitHub Actions secrets for sensitive data.
With the above GitHub secrets configured, your ci.yml
workflow will automatically deploy all necessary files to your EC2 server whenever new code is merged into the master
branch. This ensures a secure and automated deployment process.
We’ll cover the Dockerization steps for your application in the next section.
12. Final GitHub Actions CI/CD Pipeline (ci.yml
)
Below is the complete ci.yml
workflow file used for automated deployment.
Once code is merged into the master
branch, this pipeline will automatically build and deploy your application to the EC2 server—no additional manual steps are required.
name: Linqra CI
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
permissions:
contents: write
jobs:
java-app:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Upload API Gateway source files
- name: Upload API Gateway source
uses: actions/upload-artifact@v4
with:
name: api-gateway-source
path: |
api-gateway/**
!api-gateway/target/**
!api-gateway/target/
# Upload Discovery Server source files
- name: Upload Discovery Server source
uses: actions/upload-artifact@v4
with:
name: discovery-server-source
path: |
discovery-server/**
!discovery-server/target/**
!discovery-server/target/
# Upload docker-compose.yml
- name: Upload docker-compose file
uses: actions/upload-artifact@v4
with:
name: docker-compose
path: docker-compose-ec2.yml
# Upload root pom.xml
- name: Upload root pom file
uses: actions/upload-artifact@v4
with:
name: root-pom
path: pom.xml
# Debug and upload .kube directory with hidden files
- name: Debug .kube directory
run: |
echo "Checking .kube directory contents:"
ls -la .kube/
- name: Copy .kube to temporary directory
run: |
cp -r .kube kube-config
- name: Upload kube directory
uses: actions/upload-artifact@v4
with:
name: kube-config
path: kube-config/**
# Add this new step to upload keys directory
- name: Upload keys directory
uses: actions/upload-artifact@v4
with:
name: keys-config
path: keys/
if-no-files-found: error
# we build react here in the GitHub actions
react-build:
needs: java-app
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./edge-service
steps:
- uses: actions/checkout@v4
- name: Create .env file
run: |
cat <<EOF > .env
VITE_MONGODB_URI=${{ secrets.VITE_MONGODB_URI }}
VITE_MONGODB_DB_NAME=${{ secrets.VITE_MONGODB_DB_NAME }}
NODE_ENV=production
JWT_SECRET=${{ secrets.JWT_SECRET }}
VITE_WS_URL=${{ secrets.VITE_WS_URL }}
VITE_API_GATEWAY_URL=${{ secrets.VITE_API_GATEWAY_URL }}
REACT_APP_KEYCLOAK_URL=${{ secrets.REACT_APP_KEYCLOAK_URL }}
REACT_APP_KEYCLOAK_REALM=${{ secrets.REACT_APP_KEYCLOAK_REALM }}
REACT_APP_KEYCLOAK_CLIENT_ID=${{ secrets.REACT_APP_KEYCLOAK_CLIENT_ID }}
VITE_API_KEY=${{ secrets.VITE_API_KEY }}
VITE_API_KEY_NAME=${{ secrets.VITE_API_KEY_NAME }}
EOF
working-directory: ./edge-service
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '21.5.0'
cache: 'npm'
cache-dependency-path: './edge-service/package-lock.json'
- name: Upgrade npm
run: npm install -g npm@10.8.1
- name: Remove package-lock.json
run: rm -f package-lock.json
- name: Install dependencies
run: npm install --legacy-peer-deps
continue-on-error: true
- name: Build React app
run: npm run build
env:
CI: false
- name: Run tests
run: npm test
env:
CI: false
# Upload React build
- name: Upload React build
uses: actions/upload-artifact@v4
with:
name: react-build
path: edge-service/dist
deploy:
needs: [java-app, react-build]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Install SSH key
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.EC2_SSH_KEY_PROD }}
- name: Deploy to EC2
env:
EC2_HOST: ${{ secrets.HOST_DNS_PROD }}
EC2_USERNAME: ${{ secrets.USERNAME_PROD }}
TARGET_DIR: ${{ secrets.TARGET_DIR_PROD }}
run: |
# Disable strict host key checking
mkdir -p ~/.ssh
echo "StrictHostKeyChecking no" >> ~/.ssh/config
# Rsync main directories (only changed/new files, with sudo on remote)
rsync -avz --delete --rsync-path="sudo rsync" artifacts/api-gateway-source/ $EC2_USERNAME@$EC2_HOST:/var/www/linqra/api-gateway/
rsync -avz --delete --rsync-path="sudo rsync" artifacts/discovery-server-source/ $EC2_USERNAME@$EC2_HOST:/var/www/linqra/discovery-server/
rsync -avz --delete --rsync-path="sudo rsync" artifacts/react-build/ $EC2_USERNAME@$EC2_HOST:/var/www/linqra/edge-service/
# Use scp for sensitive or always-fresh files
scp -v artifacts/docker-compose/docker-compose-ec2.yml $EC2_USERNAME@$EC2_HOST:/var/www/linqra/docker-compose.yml
scp -v artifacts/root-pom/pom.xml $EC2_USERNAME@$EC2_HOST:/var/www/linqra/pom.xml
# .kube and keys (if needed, use scp or rsync as appropriate)
if [ -d "artifacts/kube-config" ]; then
rsync -avz --delete \
--exclude 'mongodb/data1/' \
--exclude 'mongodb/data2/' \
--exclude 'mongodb/data3/' \
--exclude 'postgres/data/' \
--exclude 'pgadmin/data/' \
--rsync-path="sudo rsync" artifacts/kube-config/ $EC2_USERNAME@$EC2_HOST:/var/www/linqra/.kube/
fi
if [ -d "artifacts/keys-config" ]; then
rsync -avz --delete --rsync-path="sudo rsync" artifacts/keys-config/ $EC2_USERNAME@$EC2_HOST:/var/www/linqra/keys/
fi
# Set correct permissions for pgadmin
if [ -d /var/www/linqra/.kube/pgadmin/data ]; then
sudo chown -R 5050:5050 /var/www/linqra/.kube/pgadmin/data
sudo chmod -R 755 /var/www/linqra/.kube/pgadmin/data
fi
# Set correct permissions for MongoDB
for d in data1 data2 data3; do
if [ -d /var/www/linqra/.kube/mongodb/$d ]; then
sudo chown -R 999:999 /var/www/linqra/.kube/mongodb/$d
fi
done
if [ -f /var/www/linqra/.kube/mongodb/mongo-keyfile ]; then
sudo chown 999:999 /var/www/linqra/.kube/mongodb/mongo-keyfile
sudo chmod 400 /var/www/linqra/.kube/mongodb/mongo-keyfile
fi
# Ensure the parent directory exists
sudo mkdir -p /var/www/linqra/.kube/pgadmin/data
# Now set permissions
sudo chown -R 5050:5050 /var/www/linqra/.kube/pgadmin
sudo chmod -R 755 /var/www/linqra/.kube/pgadmin
# Ensure the sessions directory exists and is owned by pgadmin
sudo mkdir -p /var/www/linqra/.kube/pgadmin/data/sessions
sudo chown 5050:5050 /var/www/linqra/.kube/pgadmin/data/sessions
sudo chmod 700 /var/www/linqra/.kube/pgadmin/data/sessions
# Check that HAProxy config and cert files exist on the EC2 host
ssh $EC2_USERNAME@$EC2_HOST "
ls -l /var/www/linqra/.kube/gateway/haproxy.cfg
ls -l /var/www/linqra/keys/haproxy/gateway-combined-container.pem
"
# Ensure HAProxy cert file is readable by HAProxy in the container
ssh $EC2_USERNAME@$EC2_HOST "
sudo chmod 644 /var/www/linqra/keys/haproxy/gateway-combined-container.pem
"
echo "About to run SSH block"
ssh $EC2_USERNAME@$EC2_HOST "
# Set permissions
sudo chown -R ubuntu:ubuntu /var/www/linqra
sudo chmod -R 600 /var/www/linqra/keys/* || echo 'No keys to set permissions for'
sudo find /var/www/linqra/keys -type d -exec chmod 755 {} \;
sudo find /var/www/linqra/keys -type f ! -name 'mongo-keyfile' -exec chmod 600 {} \;
# Set correct permissions for mongo-keyfile
if [ -f /var/www/linqra/.kube/mongodb/mongo-keyfile ]; then
sudo chown 999:999 /var/www/linqra/.kube/mongodb/mongo-keyfile
sudo chmod 400 /var/www/linqra/.kube/mongodb/mongo-keyfile
fi
# Ensure HAProxy cert file is readable
if [ -f /var/www/linqra/keys/haproxy/gateway-combined-container.pem ]; then
sudo chmod 644 /var/www/linqra/keys/haproxy/gateway-combined-container.pem
fi
# Move to the deployment directory
cd /var/www/linqra
# Stop running containers
echo 'Stopping running containers'
sudo docker compose stop
# Prune unused images/containers/volumes/networks
echo 'Pruning unused images/containers/volumes/networks'
sudo docker system prune -a -f
# Check disk usage
echo 'Checking disk usage'
df -hT
# Ensure the Docker network exists
echo 'Ensuring the Docker network exists'
sudo docker network create linqra-network || true
# Build and start containers
echo 'Building and starting containers'
sudo docker compose -f docker-compose.yml -p linqra up -d --build
# Check if containers are running
echo 'Checking if containers are running'
docker ps
"
dependency-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Dependency Review
uses: actions/dependency-review-action@v4
with:
fail-on-severity: high
## 13. Initial MongoDB Replica Set Setup (First Deployment Only)
On your very first deployment, you may encounter MongoDB issues because the replica set is not yet initialized.
**You only need to do this once.**
### 1. Connect to the Primary MongoDB Container
```bash
docker exec -it mongodb1 mongosh -u root -p mongopw --authenticationDatabase admin
You should see a prompt like:
2. Initialize the Replica Set
At the mongosh
prompt, run:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongodb1:27017" },
{ _id: 1, host: "mongodb2:27018" },
{ _id: 2, host: "mongodb3:27019" }
]
}, { force: true });
You should see output similar to:
3. Check Replica Set Status
You should see a status object with PRIMARY
and SECONDARY
members.
Note:
14. First Initial Data
After initializing the MongoDB replica set, you need to create the initial user and data for your application.
1. Exit the MongoDB Shell
If you are still inside the mongosh
shell, type:
2. Run the Initial Setup API Call
Use curl
to create the first user and initialize the database:
curl -k -X POST https://localhost:7777/api/setup/init \
-H "Content-Type: application/json" \
-d '{
"username": "linqrasa",
"email": "john@example.com",
"password": Something"
}'
3. Verify Data in MongoDB
Connect to MongoDB and list the databases to confirm the Linqra
database was created:
docker exec -it mongodb1 mongosh -u root -p mongopw --authenticationDatabase admin
show dbs
You should see output similar to:
Linqra 1016.00 KiB
admin 172.00 KiB
config 284.00 KiB
local 3.28 MiB
You should now see the Linqra
database listed.
15. Keycloak Configuration for EC2
Access Keycloak Admin Console
Access the Keycloak Admin Console at:
https://linqra.com/keycloak/admin/master/console/
1. Create New Realm
- Log in to the Keycloak Admin Console
- Click on the dropdown in the top-left corner (default shows “master”)
- Click “Create Realm”
- Configure the realm:
- Realm name:
Linqra
- Display name:
Linqra
- Frontend URL:
https://linqra.com/keycloak
- Ensure “Enabled” is switched ON
- Click “Create”
2. Create New Client
General Settings
- Navigate to “Clients” in the left sidebar
- Click “Create client”
- Configure the general settings:
- Client ID:
linqra-gateway-client
- Name:
Linqra Gateway Client
- Description:
Linqra Gateway Client
- Always display in UI:
ON
- Click “Next”
Access Settings
Configure the client’s access settings:
- Root URL:
https://linqra.com
- Home URL:
https://linqra.com
- Valid redirect URIs:
https://linqra.com/callback
- Valid post logout redirect URIs:
https://linqra.com
- Web origins:
https://linqra.com
- Admin URL:
https://linqra.com
Capability Config
Set up the authentication capabilities:
- Client authentication:
ON
- Authorization:
OFF
- Authentication flow:
- Standard flow:
Enabled
- Service accounts roles:
Enabled
- All other flows:
Disabled
3. Create Client Role
- Navigate to the “Roles” tab in your client settings
- Click “Create role”
- Configure the role:
- Role name:
gateway_admin
- Description:
Gateway admin role for the client id: linqra-gateway-client
- Click “Save”
4. Create Realm Role
- Navigate to “Realm roles” in the left sidebar
- Click “Create role”
- Configure the role:
- Role name:
gateway_admin_realm
- Description:
Role to identify the belongings of the Linqra realm
- Click “Save”
5. Assign Service Account Roles
- Navigate to your client’s “Service accounts roles” tab
- You’ll see the service account username:
service-account-linqra-gateway-client
- Assign both roles:
- Client role:
gateway_admin
- Realm role:
gateway_admin_realm
6. Create Client Scopes
a. Gateway Read Scope
- Navigate to “Client scopes” in the left sidebar
- Click “Create client scope”
- Configure the scope:
- Name:
gateway.read
- Description:
To read the gateway end points
- Type:
Default
- Display on consent screen:
ON
- Include in token scope:
ON
- Click “Save”
b. Team Scope
-
Create another client scope:
- Name:
team.scope
- Description:
Restricts access to specific teams
- Type:
Default
- Display on consent screen:
ON
- Include in token scope:
ON
-
Add a hardcoded claim mapper:
- Name:
teams
- Category:
Token mapper
- Mapper Type:
Hardcoded claim
- Claim name:
teams
- Claim value:
["67d0aeb17172416c411d419e"]
- Claim JSON type:
JSON
- Add to ID token:
ON
- Add to access token:
ON
- Add to userinfo:
ON
7. Assign Roles to Client Scope
- Navigate to the
gateway.read
client scope
- Go to the “Scope” tab
- Assign both roles:
- Client role:
gateway_admin
- Realm role:
gateway_admin_realm
8. Add Client Scopes to Client
- Navigate to the
linqra-gateway-client
settings
- Go to the “Client scopes” tab
- Add both scopes as “Default”:
The configuration above is specific to the EC2 deployment environment. Make sure all URLs are using https://linqra.com
instead of localhost URLs.
After configuring Keycloak, you may need to restart the Keycloak service to ensure all changes take effect:
sudo docker compose up -d --build keycloak-service
16. Useful Docker Commands and Maintenance
Check Running Containers
Example output:
76fb57dfd9a7 haproxy:2.8 "docker-entrypoint.s…" ... linqra-gateway-loadbalancer-1
6d35f7aee160 linqra-api-gateway-service "java -Djavax.net.de…" ... linqra-api-gateway-service-3
b926fdffecee linqra-api-gateway-service "java -Djavax.net.de…" ... linqra-api-gateway-service-2
40c635bed63d linqra-api-gateway-service "java -Djavax.net.de…" ... linqra-api-gateway-service-1
f39fd18fefe4 linqra-keycloak-service "/opt/keycloak/bin/k…" ... linqra-keycloak-service-1
a1294442aafa linqra-redis-service "redis-server /usr/l…" ... linqra-redis-service-1
0c4f29574158 linqra-mongodb2 "docker-entrypoint.s…" ... mongodb2
224725f44232 linqra-postgres-service "docker-entrypoint.s…" ... linqra-postgres-service-1
b2288bf0c2b6 linqra-mongodb3 "docker-entrypoint.s…" ... mongodb3
fed2910c43d5 linqra-discovery-service "java -Djavax.net.de…" ... linqra-discovery-service-1
2560a03d3bc1 linqra-mongodb1 "docker-entrypoint.s…" ... mongodb1
c83a6b2ec0cb linqra-pgadmin-service "/entrypoint.sh" ... linqra-pgadmin-service-1
Check Disk Usage
Stop All Containers and Remove Docker Images
cd /var/www/linqra/
docker-compose down
Check Docker storage usage:
sudo du -h --max-depth=1 /var/lib/docker
Remove all Docker data (network, volume, image):
docker system prune -a -f
Check disk usage again:
Check all containers (including stopped):
Restart or Build Specific Services
Restart only the Keycloak service:
sudo docker compose up -d --build keycloak-service
Restart only the Eureka server:
sudo docker compose up -d --build discovery-service
You should see: https://linqra.com/eureka/
Restart only the API Gateway service:
sudo docker compose up -d --build api-gateway-service
docker logs linqra-api-gateway-service-1
Build and start all services:
sudo docker compose up -d --build
Test and Debug
Refresh routes:
curl -k -H "Authorization: Bearer <ACCESS_TOKEN>" -X GET https://localhost:7777/api/routes/refresh/routes -v
Get OpenID certs from Keycloak (on EC2):
curl -v http://localhost:8281/keycloak/realms/Linqra/protocol/openid-connect/certs
Get OpenID certs from the gateway container:
docker exec -it linqra-api-gateway-service-1 curl -v http://keycloak-service:8080/keycloak/realms/Linqra/protocol/openid-connect/certs
Let me know if you want to add more commands or explanations!