<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mayur Bhatti</title>
    <description>The latest articles on DEV Community by Mayur Bhatti (@mayurbhatti).</description>
    <link>https://dev.to/mayurbhatti</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2416220%2F3577222d-e352-4aa5-9b68-9d45c40c1065.png</url>
      <title>DEV Community: Mayur Bhatti</title>
      <link>https://dev.to/mayurbhatti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mayurbhatti"/>
    <language>en</language>
    <item>
      <title>Integrating Salesforce with AWS Using AWS IAM Roles Anywhere and Private CA</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Mon, 19 Jan 2026 20:07:29 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/integrating-salesforce-with-aws-using-aws-iam-roles-anywhere-and-private-ca-1chl</link>
      <guid>https://dev.to/mayurbhatti/integrating-salesforce-with-aws-using-aws-iam-roles-anywhere-and-private-ca-1chl</guid>
      <description>&lt;p&gt;Here we will setup a secure integration between Salesforce and AWS using AWS IAM Roles Anywhere with a Private Certificate Authority (CA). By utilizing certificate-based authentication instead of access keys, AWS IAM Roles Anywhere enables on-premises servers or services to assume an IAM Role permission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create a self-signed certificate in Salesforce:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In Salesforce, go to Setup and search for Certificate &amp;amp; Key Management. &lt;/li&gt;
&lt;li&gt;Choose Create Self-Signed Certificate. &lt;/li&gt;
&lt;li&gt;Enter a label and a unique name for the certificate, then click Save. &lt;/li&gt;
&lt;li&gt;Download the generated certificate as &lt;strong&gt;“cert.pem”&lt;/strong&gt; and store it securely. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Set up a Private CA in AWS Private Certificate Authority:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open the AWS Certificate Manager (ACM) Private CA console. &lt;/li&gt;
&lt;li&gt;Choose Create CA, then Set Mode to &lt;strong&gt;“General-Purpose”&lt;/strong&gt; &amp;amp; Choose CA Type as &lt;strong&gt;“Root”&lt;/strong&gt;.
 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fckqat02mjq1wzi6dge.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fckqat02mjq1wzi6dge.png" alt=" " width="744" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fill out all required details, then select RSA 2048 for the key algorithm. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8uxuhmgonkvt84c5937.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh8uxuhmgonkvt84c5937.png" alt=" " width="555" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uwm0oesizmbdkxuhqns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3uwm0oesizmbdkxuhqns.png" alt=" " width="550" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acknowledge the settings and click Create CA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4v8210w9xt8lh40n5d73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4v8210w9xt8lh40n5d73.png" alt=" " width="703" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once created, select &lt;strong&gt;“Install CA certificate”&lt;/strong&gt; under Actions to activate the CA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iwpldmkcz9z0k8cvnxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5iwpldmkcz9z0k8cvnxm.png" alt=" " width="800" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw92v6p43tdo1sf5u3qlj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw92v6p43tdo1sf5u3qlj.png" alt=" " width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify the CA status changes from &lt;strong&gt;“Pending Certificate”&lt;/strong&gt; to &lt;strong&gt;“Active”&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14kh7i4zk65pnjaydpqx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14kh7i4zk65pnjaydpqx.png" alt=" " width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Issue and Retrieve an ACM Certificate Using AWS CLI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open your terminal and ensure the AWS CLI is installed. &lt;/li&gt;
&lt;li&gt;Sign a certificate using your Private Root CA by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws acm-pca issue-certificate \ 
    --certificate-authority-arn "&amp;lt;PRIVATE_ROOT_CA_ARN&amp;gt;" \ 
    --csr fileb://crt.pem \ 
    --signing-algorithm "SHA256WITHRSA" \ 
    --validity Value=365,Type="DAYS" \ 
    --region "us-east-1" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Copy the &lt;strong&gt;“CertificateArn”&lt;/strong&gt; from the output, then retrieve the signed certificate:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws acm-pca get-certificate \ 
    --certificate-authority-arn "&amp;lt;PRIVATE_ROOT_CA_ARN&amp;gt;" \ 
    --certificate-arn "&amp;lt;CERTIFICATE_ARN&amp;gt;" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Save the certificate content in a .crt file, formatted with each line containing 64 characters. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Create a file on editor and copy the certificate between “BEGIN CERTIFICATE” and “END CERTIFICATE”. Include these lines in the certificate and extension of .crt for the file.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While saving the file, make sure you delete the “\n” and press enter for a new line. Each row of the certificate has to be 64 characters long for it to be recognised as a certificate. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Upload the Certificate to Salesforce
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In Salesforce, upload the .crt file created in Step 3 to activate the certificate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: Create a Trust Anchor in AWS IAM Roles Anywhere
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open the IAM Roles Anywhere in the AWS console and select Create Trust Anchor. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceupq9dxx5fzapj4o7hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fceupq9dxx5fzapj4o7hc.png" alt=" " width="759" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide a name, select the Private CA from Step 2, and click Create Trust Anchor. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmvtjti55faojku6qjqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzmvtjti55faojku6qjqw.png" alt=" " width="688" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Create an IAM Role for Salesforce Permissions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In AWS IAM, create a new role with the following trust policy: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trust Policy:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ 
    "Version": "2012-10-17", 
    "Statement": [ 
        { 
            "Effect": "Allow", 
            "Principal": {  
"Service": "rolesanywhere.amazonaws.com"  
 }, 
            "Action": [ 
                "sts:AssumeRole", 
                "sts:TagSession", 
                "sts:SetSourceIdentity" 
            ] 
        } 
    ] 
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ldqvay2nulllcjp92h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl4ldqvay2nulllcjp92h.png" alt=" " width="742" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach the AmazonConnect_FullAccess policy or another policy granting the necessary permissions.  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 7: Create a Roles Anywhere Profile in AWS IAM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In IAM Roles Anywhere, select Create Profile. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzuixk8ti16smjpw0uuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzuixk8ti16smjpw0uuk.png" alt=" " width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enter a profile name and attach the role created in Step 6 &amp;amp; Click Create Profile.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnupewa6zih7om9a4q0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnupewa6zih7om9a4q0a.png" alt=" " width="769" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Configure External Named Credentials in Salesforce
&lt;/h2&gt;

&lt;p&gt;In this step, configure a named credential in Salesforce to use the IAM role that you created in Step 6. &lt;/p&gt;

&lt;p&gt;The named credential is used for authenticating and managing API callouts to external services within Salesforce, to a specific endpoint URL. Initially, point it to AWS Security Token Service (AWS STS), a web service used to request temporary credentials. Then, you point it to the Amazon Connect service URL. Salesforce named credentials support two variants of the AWS Signature Version 4 authentication protocol: IAM User (identified by access key) and Roles Anywhere. &lt;/p&gt;

&lt;p&gt;For best practices, uses IAM Roles Anywhere role, but we must first configure an external credential to provide the required authentication configuration via IAM Roles Anywhere. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Salesforce, go to &lt;strong&gt;“Setup &amp;gt; Named Credentials &amp;gt; External Credentials”&lt;/strong&gt; and click New.&lt;/li&gt;
&lt;li&gt;Complete the following fields: 

&lt;ul&gt;
&lt;li&gt;Label: &lt;strong&gt;"AWS IAM Anywhere Credential"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Name: &lt;strong&gt;"AWS_IAM_Anywhere_Credential"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Authentication Protocol: &lt;strong&gt;"AWS Signature V4"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Service: Initially &lt;strong&gt;"sts"&lt;/strong&gt; (you'll change it to "connect" later). &lt;/li&gt;
&lt;li&gt;Region: &lt;strong&gt;"us-east-1"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;AWS Account ID: (Optional)
&lt;/li&gt;
&lt;li&gt;Obtain Temporary IAM Credentials via STS: Choose &lt;strong&gt;"Roles Anywhere"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Trust Anchor ARN and Profile ARN: Use the ARN values from earlier. &lt;/li&gt;
&lt;li&gt;Signing Certificate: A certificate from AWS (via a CA) that’s uploaded to Salesforce. &lt;/li&gt;
&lt;li&gt;STS Duration: &lt;strong&gt;3600&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Create a &lt;strong&gt;“New Principal”&lt;/strong&gt; for external credential: 

&lt;ul&gt;
&lt;li&gt;Name: e.g., &lt;strong&gt;"connect_principal"&lt;/strong&gt;. NOTE: Character requirements include [a-zA-Z0-9_+=,.@-]*. &lt;/li&gt;
&lt;li&gt;Enter the ARN of the IAM role created in Step 6 and save. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Create a &lt;strong&gt;“Named Credential”&lt;/strong&gt; in Salesforce with these details: 

&lt;ul&gt;
&lt;li&gt;Label: &lt;strong&gt;"Connect API Connection"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;Name: &lt;strong&gt;"Connect_API_Connection"&lt;/strong&gt;. &lt;/li&gt;
&lt;li&gt;URL: &lt;strong&gt;"&lt;a href="https://sts.us-east-1.amazonaws.com" rel="noopener noreferrer"&gt;https://sts.us-east-1.amazonaws.com&lt;/a&gt;"&lt;/strong&gt; (later changed to the Amazon Connect URL). &lt;/li&gt;
&lt;li&gt;Enable Generate Authorization Header.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 9: Validate the Integration with IAM Roles Anywhere
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In Salesforce, Create or edit a permission set for the principal to 

&lt;ul&gt;
&lt;li&gt;configure permission sets for access: &lt;/li&gt;
&lt;li&gt;Go to Permission Sets &amp;gt; New and provide a label. &lt;/li&gt;
&lt;li&gt;Select External Credential Principal Access and move the principal to the enabled field. &lt;/li&gt;
&lt;li&gt;Assign the permission set to the relevant Salesforce user. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Test the integration: 

&lt;ul&gt;
&lt;li&gt;In Developer Console, open Execute Anonymous Window and run:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HttpRequest req = new HttpRequest(); 
//APN_API_Connection is the name of the named credential 
req.setEndpoint('callout:Connect_API_Connection/?Action=GetCallerIdentity&amp;amp;Version=2011-06-15'); 
req.setMethod('GET'); 
Http http = new Http(); 
HTTPResponse res = http.send(req); 
System.debug(res.getBody()); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Open the log file to see the status. If successful, the log shows a 200 status code to indicate a successful Amazon STS API call from AWS. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Step 10: Update the Named Credential URL &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Named Credentials configuration, update: 

&lt;ul&gt;
&lt;li&gt;Service: Change "sts" to "connect". &lt;/li&gt;
&lt;li&gt;URL: Use &lt;a href="https://connect.us-east-1.amazonaws.com" rel="noopener noreferrer"&gt;https://connect.us-east-1.amazonaws.com&lt;/a&gt; instead of the sts URL. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Test the integration: 

&lt;ul&gt;
&lt;li&gt;In Developer Console, open Execute Anonymous Window and run:
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HttpRequest req = new HttpRequest(); 
//APN_API_Connection is the name of the named credential 
req.setEndpoint('callout:Connect_API_Connection/?Action=GetCallerIdentity&amp;amp;Version=2011-06-15'); 
req.setMethod('GET'); 
Http http = new Http(); 
HTTPResponse res = http.send(req); 
System.debug(res.getBody()); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the log file to see the status. If successful, the log shows a 200 status code along with attribute then it indicate a successful Amazon connect API call from AWS. &lt;/p&gt;

&lt;p&gt;Similar to Amazon Connect, you can configure it with any service.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understand AWS IAM Identifiers</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Thu, 15 Jan 2026 21:18:58 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/understand-aws-iam-identifiers-18ol</link>
      <guid>https://dev.to/mayurbhatti/understand-aws-iam-identifiers-18ol</guid>
      <description>&lt;p&gt;When working with AWS Security, one thing that often confuses beginners is IAM Identifiers.&lt;/p&gt;

&lt;p&gt;You may have seen terms like &lt;strong&gt;ARN&lt;/strong&gt;, &lt;strong&gt;UserID&lt;/strong&gt;, &lt;strong&gt;RoleID&lt;/strong&gt;, and &lt;strong&gt;FriendlyName&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Wonder why AWS need so many identifiers for the same thing?&lt;/p&gt;

&lt;p&gt;Here we will break it down clearly so you can understand what each identifier is, why it exists and when you will use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are AWS IAM Identifiers?
&lt;/h2&gt;

&lt;p&gt;In AWS Identity and Access Management (IAM), every identity and resource must be uniquely identifiable, so AWS achieves this using different types of identifiers, each designed for a specific purpose:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46zzqbz7zxzkgrnxohmt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46zzqbz7zxzkgrnxohmt.png" alt=" " width="752" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In simple terms, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Friendly Name = Display Name&lt;/li&gt;
&lt;li&gt;ARN = Full Address&lt;/li&gt;
&lt;li&gt;Unique ID = Government-issued ID number&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Let's break each in detail:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Friendly Name 
&lt;/h2&gt;

&lt;p&gt;Friendly names are the names that we assign to IAM resources, such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IAM User&lt;/li&gt;
&lt;li&gt;IAM Role&lt;/li&gt;
&lt;li&gt;IAM Group&lt;/li&gt;
&lt;li&gt;IAM Policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IAM user = “mayur”
IAM role = "ec2-s3-readonly-role”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Friendly name exists:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy for humans to read and remember&lt;/li&gt;
&lt;li&gt;Used in the AWS Console&lt;/li&gt;
&lt;li&gt;Used in CLI commands and scripts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important &lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be unique within the same account&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Friendly names are not globally unique, so two AWS accounts can have the same friendly name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. ARN
&lt;/h2&gt;

&lt;p&gt;An ARN is similar to a fully qualified domain name, a globally unique identifier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arn:aws:iam::123456789012:user/mayur
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ARN structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;arn:partition:service:region:account-id:resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt; &lt;br&gt;
&lt;strong&gt;Why ARNs matter:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used in IAM policies&lt;/li&gt;
&lt;li&gt;Used by AWS services internally&lt;/li&gt;
&lt;li&gt;Required for cross-account access&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;AWS trust ARNs, not the friendly names.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  3. Unique ID
&lt;/h2&gt;

&lt;p&gt;Every IAM resource also gets a unique ID assigned by AWS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AIDAJQABLZS4A3QDU576Q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why AWS uses this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Friendly names can change&lt;/li&gt;
&lt;li&gt;ARNs can change if the path changes&lt;/li&gt;
&lt;li&gt;Unique IDs ensure consistency &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You will not use these directly, but AWS relies on them internally, as they cannot be changed or reused even if resources are deleted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Paths
&lt;/h2&gt;

&lt;p&gt;Paths allow you to logically group IAM resources&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/dev/admins/dev-admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Paths:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;don’t affect permission&lt;/li&gt;
&lt;li&gt;Help with Organisation&lt;/li&gt;
&lt;li&gt;Are included in the ARN&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;When paths are useful:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large Enterprises&lt;/li&gt;
&lt;li&gt;Multiple teams&lt;/li&gt;
&lt;li&gt;Environment separation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How these Identifiers work together:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqf73reopx0nlhbg5sxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqf73reopx0nlhbg5sxv.png" alt=" " width="782" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each identifier serves a different audience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Humans —&amp;gt; Friendly Names&lt;/li&gt;
&lt;li&gt;Policies &amp;amp; Services —&amp;gt; ARNs&lt;/li&gt;
&lt;li&gt;AWS Internal systems —&amp;gt; Unique IDs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Mistakes to Avoid:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Assuming friendly names are globally unique&lt;/li&gt;
&lt;li&gt;Renaming IAM resources without checking the impact on other resources&lt;/li&gt;
&lt;li&gt;Confusing role ARN with Instance profile ARN&lt;/li&gt;
&lt;li&gt;Using wildcards carelessly in ARN policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Once you understand why each identifier exists, IAM becomes easier and safer to manage.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Importing a Custom EC2 Key Pair in AWS: A Step-by-Step Guide</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Thu, 15 Jan 2026 09:01:38 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/importing-a-custom-ec2-key-pair-in-aws-a-step-by-step-guide-5h3n</link>
      <guid>https://dev.to/mayurbhatti/importing-a-custom-ec2-key-pair-in-aws-a-step-by-step-guide-5h3n</guid>
      <description>&lt;p&gt;Managing secure access to your Amazon EC2 instances is critical, and one of the foundational steps is setting up an SSH key pair. AWS allows you to create and use your custom EC2 key pairs, providing flexibility for advanced security management. This guide outlines the steps to import a custom key pair into AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom SSH Key Pair: Generate an SSH key pair using your preferred method or tool, such as OpenSSL, ssh-keygen, or a third-party tool.

&lt;ul&gt;
&lt;li&gt;The private key will remain on your local machine for authentication.&lt;/li&gt;
&lt;li&gt;The public key will be imported into AWS.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;AWS CLI or AWS Management Console: This guide covers both methods for importing the key pair.&lt;/li&gt;

&lt;li&gt;IAM Permissions: Ensure your AWS user or role has the necessary permissions:

&lt;ul&gt;
&lt;li&gt;ec2:ImportKeyPair&lt;/li&gt;
&lt;li&gt;ec2:DescribeKeyPairs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: Generate a Custom Key Pair (if not already created)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Using ssh-keygen&lt;/strong&gt;&lt;br&gt;
On a Linux, macOS, or Windows machine (with WSL or Git Bash):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t rsa -b 2048 -m PEM -C "your-email@example.com" -f my-custom-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;-t rsa&lt;/strong&gt;: Specifies the RSA algorithm.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-b 2048&lt;/strong&gt;: Sets the key size to 2048 bits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-m PEM&lt;/strong&gt;: Specifies format of the key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-f my-custom-key&lt;/strong&gt;: Saves the key with the name my-custom-key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-C "&lt;a href="mailto:your-email@example.com"&gt;your-email@example.com&lt;/a&gt;"&lt;/strong&gt;: Adds a comment to identify the key.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This command generates two files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;my-custom-key:&lt;/strong&gt; The private key (keep it secure).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;my-custom-key.pub:&lt;/strong&gt; The public key for importing into AWS.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 2: Import the Key Pair in AWS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using AWS Management Console:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to AWS Management Console: Navigate to the &lt;strong&gt;&lt;em&gt;EC2 Dashboard&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Access Key Pairs:

&lt;ul&gt;
&lt;li&gt;On the left-hand menu, under Network &amp;amp; Security, click &lt;strong&gt;&lt;em&gt;Key Pairs&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Import Key Pair:

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;&lt;em&gt;Import key pair&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Provide a name for the key pair (e.g., my-custom-key).&lt;/li&gt;
&lt;li&gt;Copy the contents of the public key file (my-custom-key.pub) into the Public key contents field.&lt;/li&gt;
&lt;li&gt;Click Import key pair.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Using AWS CLI:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install and Configure AWS CLI: If not already installed, download and configure the AWS CLI following the installation guide.&lt;/li&gt;
&lt;li&gt;Run the Import Command: Use the following command to import your custom key pair:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 import-key-pair \
    --key-name "my-custom-key" \
    --public-key-material fileb://my-custom-key.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;--key-name: Specifies the name of the key pair in AWS.&lt;/li&gt;
&lt;li&gt;--public-key-material: Uploads the public key file.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Verify the Key Pair: To confirm the key pair was imported successfully:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 describe-key-pairs --key-name "my-custom-key"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your custom key pair is now available for use with EC2 instances.&lt;/p&gt;




&lt;h3&gt;
  
  
  Key Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep Private Keys Secure&lt;/strong&gt;: Store private keys in a secure location and never share them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Pair Limits&lt;/strong&gt;: AWS accounts have a soft limit on the number of key pairs per region (default: 5,000). Contact AWS Support if you need more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup&lt;/strong&gt;: Regularly back up private keys in a secure location to avoid losing access to your EC2 instances.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Importing a custom EC2 key pair into AWS provides flexibility and control over SSH access to your instances. By following the steps outlined in this guide, you can ensure secure, seamless access while maintaining compliance with your organization's security policies.&lt;/p&gt;

&lt;p&gt;For more details, refer to the official &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html" rel="noopener noreferrer"&gt;AWS Key Pair Documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Setting up a Self-Hosted Runner on GitHub Actions</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Mon, 18 Nov 2024 18:19:54 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/setting-up-a-self-hosted-runner-on-github-actions-5a7f</link>
      <guid>https://dev.to/mayurbhatti/setting-up-a-self-hosted-runner-on-github-actions-5a7f</guid>
      <description>&lt;p&gt;GitHub Actions is a powerful tool for automating workflows directly in GitHub. While GitHub-hosted runners are convenient, self-hosted runners offer much more flexibility by giving you full control over the hardware, operating system, and installed software. This guide will walk you through setting up a self-hosted runner on GitHub, giving you the ability to optimize your environment to meet specific project requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Companies are Switching to GitHub/GitLab for CI/CD Pipelines
&lt;/h2&gt;

&lt;p&gt;With the recent closure of AWS CodeCommit, many companies are transitioning to platforms like GitHub and GitLab for code storage and management. Solution architects are adapting CI/CD pipelines to align with this shift, leveraging GitHub and GitLab’s built-in CI/CD tools—GitHub Actions and GitLab CI/CD—rather than relying on standalone systems. This consolidation of code storage and CI/CD pipelines simplifies integration, enhances collaboration, and optimizes workflow visibility by keeping everything in one platform.&lt;/p&gt;

&lt;p&gt;GitHub Actions has become especially popular, providing companies with a robust CI/CD tool that automates code testing, deployment, and integration. However, GitHub Actions has limitations, particularly for companies with large-scale or complex workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming GitHub Actions Limitations with Self-Hosted Runners
&lt;/h2&gt;

&lt;p&gt;While GitHub Actions is powerful, it has certain restrictions, especially when relying solely on GitHub-hosted runners. These runners have runtime and billing limitations that could lead to higher costs or performance impacts if workflows exceed the provided limits. For example, GitHub Actions offers free tier limits (especially for public repositories) but imposes runtime limits, data transfer restrictions, and concurrency caps on GitHub-hosted runners. For extensive workflows, upgrading to a paid GitHub plan may be necessary.&lt;/p&gt;

&lt;p&gt;An alternative to relying solely on GitHub-hosted runners is self-hosted runners. Self-hosted runners provide several benefits, helping to overcome GitHub Actions’ limitations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Runtime Limits:&lt;/strong&gt; Self-hosted runners do not have a predefined runtime cap, which makes them ideal for handling longer or more complex jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Resource Control:&lt;/strong&gt; They allow you to choose hardware that meets the specific resource demands of your workflows, providing greater flexibility in CPU, memory, and storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost Efficiency:&lt;/strong&gt; Instead of upgrading to higher GitHub subscription tiers to increase runner usage, self-hosted runners can operate on existing infrastructure, reducing the overall costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility in Software:&lt;/strong&gt; With self-hosted runners, you can install and run custom software that may not be available in GitHub-hosted environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For companies looking to maximize GitHub Actions workflows without incurring high costs, self-hosted runners offer a flexible, efficient solution. You can read more about GitHub Actions’ billing limitations in the &lt;a href="https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions" rel="noopener noreferrer"&gt;GitHub Actions Billing Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2kqnym185smg9nomuf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm2kqnym185smg9nomuf3.png" alt="Difference" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Levels of Self-Hosted Runners:
&lt;/h3&gt;

&lt;p&gt;GitHub provides three levels of self-hosted runners for different scopes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Repository-Level:&lt;/strong&gt; Dedicated to a single repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization-Level:&lt;/strong&gt; Available to multiple repositories within an organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise-Level:&lt;/strong&gt; Can be assigned to repositories across various organizations within an enterprise.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide to Setting Up a Self-Hosted Runner
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create a New Self-Hosted Runner
&lt;/h3&gt;

&lt;p&gt;To begin, navigate to the appropriate settings page depending on the level at which you want to set up the runner:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository-Level:&lt;/strong&gt; Go to Repository Settings → Actions → Runners → New self-hosted runner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzobehm4j9o8ye1h6th8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzobehm4j9o8ye1h6th8l.png" alt="Repository level" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organization-Level:&lt;/strong&gt; Go to Organization Settings → Actions → Runners → New runner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5zhijuozbq50xzfpjai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs5zhijuozbq50xzfpjai.png" alt="Organization-Level" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub will display a setup page to guide you through creating a new self-hosted runner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Choose Your Machine and Download the Runner
&lt;/h3&gt;

&lt;p&gt;After Clicking on “New self-hosted runner”, This page will appear at both the Repository and Organization Level. On the setup page, select the machine type and architecture for your runner:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F156asbktt9fki4wfzwhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F156asbktt9fki4wfzwhi.png" alt="configuration" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Machine:&lt;/strong&gt; Choose from Linux, Windows, or macOS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architecture:&lt;/strong&gt; Select your desired architecture, such as x64 or ARM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After making your selections, GitHub provides a download script that you can use to install the runner application on your VM or server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; In ./Config there is one token generated which only works for a few minutes, if you have waited for a long time then need to again create a runner (STEP1).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Configure the Runner on Your Machine
&lt;/h3&gt;

&lt;p&gt;Once the runner is downloaded, follow these steps to configure it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the Configuration Script:&lt;/strong&gt; Execute &lt;strong&gt;&lt;em&gt;./config.sh&lt;/em&gt;&lt;/strong&gt; on your machine. During this step, you’ll generate a token from GitHub that’s required to authenticate the runner. Note that the token is only valid for a short period—if you wait too long, you’ll need to generate a new one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Runner Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runner Group:&lt;/strong&gt; Specify a group if needed (ensure the group exists before specifying it).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runner Name:&lt;/strong&gt; Provide a custom name for your runner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Labels:&lt;/strong&gt; Labels are used to identify the runner in your workflow YAML files. By default, labels include self-hosted, the OS type (e.g., Linux), and architecture (e.g., x64). You can add custom labels as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working Directory:&lt;/strong&gt; Specify the directory where the runner will download workflow files and operate.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ormcmcojk07of7qjom9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ormcmcojk07of7qjom9.png" alt="Runner Options" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Start the Runner
&lt;/h2&gt;

&lt;p&gt;To start the runner, use the following command: &lt;code&gt;./run.sh&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command starts the runner in interactive mode, allowing it to listen for and process incoming jobs. Make sure your workflow YAML files include labels that match the runner configuration so GitHub can correctly assign jobs to your self-hosted runner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hk3qjw7h93psitubtds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hk3qjw7h93psitubtds.png" alt="Run command" width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygdqaqhy1ddodptnb6t7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygdqaqhy1ddodptnb6t7.png" alt="Executions" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Set Up the Runner as a Service
&lt;/h2&gt;

&lt;p&gt;To set up the self-hosted runner as a service on Linux (using systemd), GitHub provides an svc.sh script, which makes it easy to install, start, check, stop, and uninstall the runner service.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install the Service:&lt;/strong&gt;
Stop the runner if it’s currently running, then install it as a service by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;To install it as a specific user, specify the username:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh install USERNAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start the Service:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check Service Status:&lt;/strong&gt; 
To check if the runner service is active and listening, run:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stop and Uninstall the Service:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If needed, stop the service with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To completely remove the service, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./svc.sh uninstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0loqg3l3tkz9cxgdgb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0loqg3l3tkz9cxgdgb8.png" alt="runner as service" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up the GitHub self-hosted runner as a service ensures it will automatically restart if the machine reboots, making it ideal for production environments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices for Managing Self-Hosted Runners
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Self-hosted runners have access to your local network and systems, so ensure they’re secured and access is limited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular Updates:&lt;/strong&gt; Keep your runner application updated to avoid compatibility issues and gain the latest features and security patches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring and Logging:&lt;/strong&gt; Use monitoring tools and GitHub’s built-in logs to track runner activity, resource usage, and any issues that arise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling:&lt;/strong&gt; For high-demand environments, consider adding multiple runners or using runners with autoscaling capabilities in cloud environments.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  References and Further Reading:
&lt;/h2&gt;

&lt;p&gt;For more detailed information, here are some helpful resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners" rel="noopener noreferrer"&gt;GitHub Documentation on Self-Hosted Runners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service" rel="noopener noreferrer"&gt;Configuring Self-Hosted Runners as a Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/managing-access-to-self-hosted-runners-using-groups" rel="noopener noreferrer"&gt;Managing Access with Runner Groups&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=SASoUr9X0QA" rel="noopener noreferrer"&gt;YouTube Guide to Self-Hosted Runners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=2lLsW9E3WcI" rel="noopener noreferrer"&gt;Advanced Configuration and Use Cases for GitHub Self-Hosted Runners&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>githubactions</category>
      <category>pipeline</category>
    </item>
    <item>
      <title>Setting up WireGuard VPN with WAG for Enhanced Security and MFA</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Sat, 16 Nov 2024 19:37:40 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/setting-up-wireguard-vpn-with-wag-for-enhanced-security-and-mfa-4f0j</link>
      <guid>https://dev.to/mayurbhatti/setting-up-wireguard-vpn-with-wag-for-enhanced-security-and-mfa-4f0j</guid>
      <description>&lt;p&gt;In today’s security-conscious environment, having a VPN setup that integrates multi-factor authentication (MFA) is essential. WAG, a tool that adds 2FA and device enrollment capabilities to WireGuard, enables secure VPN access with MFA for specific routes. This guide walks you through setting up a WireGuard VPN with WAG on an Ubuntu server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to WAG with WireGuard
&lt;/h2&gt;

&lt;p&gt;WAG enhances WireGuard by providing 2FA on selected routes while allowing other routes to remain accessible as long as the client has a valid public key. With WAG, you can ensure only authenticated users can access sensitive network resources, securing your VPN further.&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://github.com/NHAS/wag/" rel="noopener noreferrer"&gt;WAG GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;System Requirements: This guide assumes you are working on Ubuntu 20.04.&lt;/li&gt;
&lt;li&gt;Necessary Tools: Make sure iptables is installed and IP forwarding is enabled. Wag must be run as root, to manage iptables and the wireguard device.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sysctl -w net.ipv4.ip_forward=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Install WAG
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create Directory: Install WAG in the /opt directory.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir /opt/wag &amp;amp;&amp;amp; cd /opt/wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Download WAG:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -L $(curl -s https://api.github.com/repos/NHAS/wag/releases/latest | jq -M -r '.assets[0].browser_download_url') -o wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set Permissions:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod 700 wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Generate WAG Configurations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Generate the initial configuration file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./wag gen-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Rename the generated config file:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After providing valid information in the above command, it will generate one config file with the tag &lt;strong&gt;"config.json.*"&lt;/strong&gt;. Rename it to &lt;strong&gt;"config.json"&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mv config.json.* config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Modify WireGuard Port and Add ACLs in the Config File
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set Port and Add Private Key:
Configure WireGuard to listen on a chosen port (e.g., 51820).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Wireguard": {
    "DevName": "wg0",
    "ListenPort": 51820,
    "PrivateKey": "your_private_key_here",
    "Address": "10.1.2.1/24",
    "MTU": 1420,
    "PersistentKeepAlive": 25,
    "DNS": ["8.8.8.8"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Define ACLs:
Use ACL policies to enforce 2FA for specific networks while allowing general access to others.
Here, a username "mayur" is allowed only for network "0.0.0.0/0, ::/0" but it must enter MFA for network "172.69.0.0/16 and following", mfa defines the network which will be accessible only if it is authorized.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example ACL Configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Acls": {
    "Groups": {
        "group:admin": ["mayur"]
    },
    "Policies": {
        "group:admin": {
            "Mfa": [
               "172.69.0.0/16", "172.63.0.0/16"
            ],
            "Allow": [
               "0.0.0.0/0", "::/0"
            ]
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding this, the config will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Proxied": false,
  "ExposePorts": null,
  "HelpMail": "&amp;lt;email address&amp;gt;",
  "Lockout": 5,
  "ExternalAddress": "&amp;lt;public ip&amp;gt;",
  "MaxSessionLifetimeMinutes": 1440,
  "SessionInactivityTimeoutMinutes ": 60,
  "ManagementUI": {
    "ListenAddress": "",
    "Enabled": false
  },
  "Webserver": {
    "Public": {
      "ListenAddress": ":8080"
    },
    "Tunnel": {
      "Port": "80"
    }
  },
  "Authenticators": {
    "Issuer": "Wireguard",
    "Methods": ["totp"],
    "DomainURL": "",
    "OIDC": {
      "IssuerURL": "",
      "ClientSecret": "",
      "ClientID": ""
    }
  },
  "Wireguard": {
    "DevName": "wg0",
    "ListenPort": 51820,
    "PrivateKey": "&amp;lt;private key&amp;gt;",
    "Address": "10.1.2.1/24",
    "MTU": 1420,
    "PersistentKeepAlive": 25,
    "DNS": ["8.8.8.8"]
  },
  "DatabaseLocation": "devices.db",
  "Acls": {
    "Groups": {
      "group:admin": ["mayur"]
    },
    "Policies": {
      "group:admin": {
        "Mfa": ["172.69.0.0/16", "172.63.0.0/16"],
        "Allow": ["0.0.0.0/0", "::/0"]
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Start the WAG Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run WAG with the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./wag start -config config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;wag will create a database &lt;strong&gt;"devices.db"&lt;/strong&gt; where it will store all users and their respective keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Set Up WAG as a Service
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Create a wag.service file for managing WAG via systemd:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/systemd/system/wag.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add the following service configuration:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=WireguardManager

[Service]
User=root

WorkingDirectory=/opt/wag
ExecStart=/opt/wag/wag start

# If any of the ExecStarttasks fail, then ExecStopPostwill run
ExecStopPost=/opt/wag/wag cleanup

Restart=on-failure
RestartSec=10
RestartPreventExitStatus=3

KillSignal=SIGINT

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enable and start the service:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable wag
sudo systemctl start wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Register New Users with WAG
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Register a user:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./wag registration -add -username your_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7g1zkutf2cn9zovuj3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7g1zkutf2cn9zovuj3q.png" alt="token" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command generates a token for device enrollment. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restart the WAG service:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now copy the token that was generated from the adding username, Now restart the wag service&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Download User Configuration File
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Users can retrieve their VPN configuration file using their generated token:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://{public.server.address}:8080/register_device?key={token}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will download the config that will later need to be used in the WireGuard Client.&lt;/p&gt;




&lt;h3&gt;
  
  
  Additional Feature:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Registration - Deals with creating, deleting and listing the registration tokens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage of registration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"-add" : Create a new enrolment token &lt;/li&gt;
&lt;li&gt;"-del" : Delete existing enrolment token &lt;/li&gt;
&lt;li&gt;"-group value" : Manually set user group (can supply multiple -group, or use -groups for delimited group list, useful for OIDC) &lt;/li&gt;
&lt;li&gt;"-groups string" : Set user groups manually, ',' delimited list of groups, useful for OIDC &lt;/li&gt;
&lt;li&gt;"-list" : List tokens &lt;/li&gt;
&lt;li&gt;"-overwrite string" : Add registration token for an existing user device, will overwrite wireguard public key (but not 2FA)
&lt;/li&gt;
&lt;li&gt;"-socket string" : Wag socket to act on (default "/tmp/wag.sock") &lt;/li&gt;
&lt;li&gt;"-token string" : Manually set registration token (Optional) &lt;/li&gt;
&lt;li&gt;"-username string" : User to add device&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  (Optional) Configure WAG Management UI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To enable the WAG UI, make the following changes in config.json:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ManagementUI": {
    "ListenAddress": ":9000",
    "Enabled": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Restart WAG to apply changes:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart wag
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Set up an admin account for the web console:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ./wag webadmin -add -username admin -password admin_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now, Just use &lt;strong&gt;&lt;em&gt;http://{public_ip}:9000&lt;/em&gt;&lt;/strong&gt; and we will be able to access the WAG UI console where we will be able to manage the user and config.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgierh7fltjdnkbae1kf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgierh7fltjdnkbae1kf.png" alt="wag ui" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vpn</category>
      <category>wireguard</category>
      <category>security</category>
      <category>infrasecurity</category>
    </item>
    <item>
      <title>Getting started with AWS DeepRacer!!</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Wed, 13 Nov 2024 20:08:15 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/getting-started-with-aws-deepracer-3j94</link>
      <guid>https://dev.to/mayurbhatti/getting-started-with-aws-deepracer-3j94</guid>
      <description>&lt;p&gt;AWS DeepRacer is an integrated learning system for users of all levels to learn and explore reinforcement learning and to experiment and build autonomous driving applications. This blog will guide you to build your model on the new Deepracer Console. This can help you get ready for the Deepracer leagues at your nearest summits and also for Virtual circuits that take place throughout the year.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AWS DeepRacer?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxu0atx2w94q9b2pq74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5dxu0atx2w94q9b2pq74.png" alt="DeepRacer Logo" width="245" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS DeepRacer is a fully autonomous 1/18th scale race car driven by reinforcement learning. It lets you train your model on AWS DeepRacer Console. It also helps you to provide a Reward Function to your model that indicates to the agent (DeepRacer Car) whether the action performed resulted in a good, bad or neutral outcome.&lt;/p&gt;

&lt;p&gt;The AWS DeepRacer console is a graphical user interface to interact with the AWS DeepRacer service. You can use the console to train a reinforcement learning model and to evaluate the model performance in the AWS DeepRacer simulator built upon AWS RoboMaker. In the console, you can also download a trained model for deployment to your AWS DeepRacer vehicle for autonomous driving in a physical environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Types Of Race League:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw596gqv0bqucmuz8z0n8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw596gqv0bqucmuz8z0n8.png" alt="Type of League" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are three main racing formats in the AWS DeepRacer League:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Head-to-Head Racing:&lt;/strong&gt; In this mode, racers navigate the track while avoiding other AWS bot cars. The top racers qualify for a head-to-head elimination bracket at the end of each month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Object Avoidance:&lt;/strong&gt; In this format, participants must complete the track while dodging obstacles. The fastest time wins and advances toward the Championship Cup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time Trial:&lt;/strong&gt; Here, racers aim to complete the track within a set number of laps while staying on track. The fastest racer in this category advances to the Championship Cup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding Reinforcement Learning:
&lt;/h2&gt;

&lt;p&gt;In reinforcement learning (RL), an agent (in this case, the AWS DeepRacer car) interacts with an environment (the track) and learns by receiving rewards for taking certain actions that lead to desirable outcomes. The agent’s goal is to maximize these rewards by identifying the best actions over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Reinforcement Learning (RL) Terms:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz0gkx5dxj7rmxrly9kt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz0gkx5dxj7rmxrly9kt.png" alt="RL terms" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent&lt;/strong&gt; - The agent is represented by the AWS DeepRacer vehicle that needs to be trained. More specifically, it embodies the neural network that controls the vehicle, taking inputs, and deciding actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment&lt;/strong&gt; - The environment contains a track that defines where the vehicle can drives. The agent explores the environment to collect data to train the underlying neural network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State&lt;/strong&gt; - The state represents a snapshot of the environment where the agent is in at a point in time. The front-facing camera captures this state on the vehicle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action&lt;/strong&gt; - An action is a decision made by the agent in the current state. For AWS DeepRacer, an action corresponds to a vehicle move at a particular speed and steering angle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reward&lt;/strong&gt; - The reward is the score given as feedback to the agent when it takes action in a given state. In training the AWS DeepRacer model, the reward is returned by a reward function. In general, you define or supply a reward function to specify what is desirable or undesirable action for the agent to take in a given state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Episodes&lt;/strong&gt; - An episode is a set of processes until the agent terminated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Services Used &amp;amp; Architecture:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrx60etrzjoj0kqhugpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwrx60etrzjoj0kqhugpc.png" alt="architecture" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS DeepRacer leverages several AWS services:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS DeepRacer Console: Interface for training and evaluating models.&lt;/li&gt;
&lt;li&gt;Amazon SageMaker: Manages and trains the RL models.&lt;/li&gt;
&lt;li&gt;AWS RoboMaker: Simulates the virtual track environment.&lt;/li&gt;
&lt;li&gt;Amazon S3: Stores the model data.&lt;/li&gt;
&lt;li&gt;Amazon Kinesis: Streams data for live feedback.&lt;/li&gt;
&lt;li&gt;Amazon CloudWatch: Monitors and logs activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to Build Your AWS DeepRacer Model:
&lt;/h2&gt;

&lt;p&gt;Let’s train and evaluate our virtual model! Here are the steps (note that you can follow along &lt;a href="https://console.aws.amazon.com/deepracer/home?region=us-east-1#models" rel="noopener noreferrer"&gt;here&lt;/a&gt; by creating an AWS account):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a model in the AWS DeepRacer console.&lt;/li&gt;
&lt;li&gt;Set the name, description, and track.&lt;/li&gt;
&lt;li&gt;Set your action space (possible actions for the model to take).&lt;/li&gt;
&lt;li&gt;Create your reward functions.&lt;/li&gt;
&lt;li&gt;Set your hyperparameters.&lt;/li&gt;
&lt;li&gt;Start training!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Evaluating the Model:
&lt;/h2&gt;

&lt;p&gt;For an in-depth guide to model evaluation, &lt;a href="https://drive.google.com/file/d/1rjcLnKeleFOUss1UwFea0_w2BGbb3lHs/view?usp=sharing" rel="noopener noreferrer"&gt;Check this out&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building an Effective Reward Function:
&lt;/h2&gt;

&lt;p&gt;The AWS DeepRacer reward function takes a dictionary object as the input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def reward_function(params) :

    reward = ...

    return float(reward)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The params dictionary object contains the following key-value pairs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "all_wheels_on_track": Boolean,        # flag to indicate if the agent is on the track
    "x": float,                            # agent's x-coordinate in meters
    "y": float,                            # agent's y-coordinate in meters
    "closest_objects": [int, int],         # zero-based indices of the two closest objects to the agent's current position of (x, y).
    "closest_waypoints": [int, int],       # indices of the two nearest waypoints.
    "distance_from_center": float,         # distance in meters from the track center 
    "is_crashed": Boolean,                 # Boolean flag to indicate whether the agent has crashed.
    "is_left_of_center": Boolean,          # Flag to indicate if the agent is on the left side to the track center or not. 
    "is_offtrack": Boolean,                # Boolean flag to indicate whether the agent has gone off track.
    "is_reversed": Boolean,                # flag to indicate if the agent is driving clockwise (True) or counter clockwise (False).
    "heading": float,                      # agent's yaw in degrees
    "objects_distance": [float, ],         # list of the objects' distances in meters between 0 and track_length in relation to the starting line.
    "objects_heading": [float, ],          # list of the objects' headings in degrees between -180 and 180.
    "objects_left_of_center": [Boolean, ], # list of Boolean flags indicating whether elements' objects are left of the center (True) or not (False).
    "objects_location": [(float, float),], # list of object locations [(x,y), ...].
    "objects_speed": [float, ],            # list of the objects' speeds in meters per second.
    "progress": float,                     # percentage of track completed
    "speed": float,                        # agent's speed in meters per second (m/s)
    "steering_angle": float,               # agent's steering angle in degrees
    "steps": int,                          # number steps completed
    "track_length": float,                 # track length in meters.
    "track_width": float,                  # width of the track
    "waypoints": [(float, float), ]        # list of (x,y) as milestones along the track center
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reward function that worked for us is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import math
def reward_function(params):

    track_width = params['track_width']
    distance_from_center = params['distance_from_center']
    steering = abs(params['steering_angle'])
    direction_stearing=params['steering_angle']
    speed = params['speed']
    steps = params['steps']
    progress = params['progress']
    all_wheels_on_track = params['all_wheels_on_track']
    ABS_STEERING_THRESHOLD = 15
    SPEED_TRESHOLD = 5
    TOTAL_NUM_STEPS = 85

    # Read input variables
    waypoints = params['waypoints']
    closest_waypoints = params['closest_waypoints']
    heading = params['heading']

    reward = 1.0

    if progress == 100:
        reward += 100

    # Calculate the direction of the center line based on the closest waypoints
    next_point = waypoints[closest_waypoints[1]]
    prev_point = waypoints[closest_waypoints[0]]

    # Calculate the direction in radius, arctan2(dy, dx), the result is (-pi, pi) in radians
    track_direction = math.atan2(next_point[1] - prev_point[1], next_point[0] - prev_point[0]) 

    # Convert to degree
    track_direction = math.degrees(track_direction)

    # Calculate the difference between the track direction and the heading direction of the car
    direction_diff = abs(track_direction - heading)

    # Penalize the reward if the difference is too large
    DIRECTION_THRESHOLD = 10.0

    malus=1

    if direction_diff &amp;gt; DIRECTION_THRESHOLD:
        malus=1-(direction_diff/50)
        if malus&amp;lt;0 or malus&amp;gt;1:
            malus = 0
        reward *= malus

    return reward
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more examples of reward functions, you can visit this &lt;a href="https://docs.aws.amazon.com/deepracer/latest/developerguide/deepracer-reward-function-examples.html" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing:
&lt;/h2&gt;

&lt;p&gt;AWS DeepRacer provides a Free Tier, that covers the first 10 free hours to train or evaluate models and 5GB of free storage during your first month. After this, it cost around&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Training or evaluation : $3.50 per hour&lt;/li&gt;
&lt;li&gt;Model storage : $0.023 per GB-month&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Takeaways:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You should be careful while choosing the training time of your model. If you train it too much it will overfit the track and won’t be able to perform with slight changes in the environment, whereas on the other hand if your train it less, the model won’t be strong enough to make correct decisions.&lt;/li&gt;
&lt;li&gt;Your primary focus while building and training the model on the virtual environment should be on the accuracy and reliability of your model and not the speed or lap time of your DeepRacer. As in the Physical racing league, you will be able to accelerate your DeepRacer using their app on the phone.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>awsdeepracer</category>
      <category>reinforcementlearning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>WebLex - Using voice to control a website with Amazon Alexa</title>
      <dc:creator>Mayur Bhatti</dc:creator>
      <pubDate>Tue, 12 Nov 2024 10:01:15 +0000</pubDate>
      <link>https://dev.to/mayurbhatti/weblex-using-voice-to-control-a-website-with-amazon-alexa-1hg4</link>
      <guid>https://dev.to/mayurbhatti/weblex-using-voice-to-control-a-website-with-amazon-alexa-1hg4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction:
&lt;/h2&gt;

&lt;p&gt;With advances in Information Technology, modern communication tools, like voice bots, have become integral to user interactions. A prominent example is Amazon Alexa — a smart voice assistant developed by Amazon that can perform a wide array of tasks. Alexa enables users to set alarms, create reminders, play music, answer questions, browse the internet, and control smart home devices with just a voice command. Beyond personal use, Alexa’s functionality can even be embedded into websites. Here’s where WEBLEX comes in.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Objective&lt;/strong&gt;&lt;/em&gt; — WEBLEX aims to make website interactions more accessible and efficient by allowing users to control web content using Alexa voice commands. Users can seamlessly perform various tasks, such as navigating menus, displaying images, reading website content aloud, managing sign-in/sign-off, and scrolling—all with simple spoken prompts.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/em&gt; — Voice-controlled website navigation can be incredibly beneficial across various scenarios. Imagine having the ability to navigate a recipe website hands-free while cooking or a doctor reviewing a patient’s medical images and test results through voice commands. These use cases demonstrate the potential of voice navigation to enhance user experiences in unique, hands-free environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Now Let’s first see in short how Amazon Alexa works??
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mgvo2yk8yuox0g5o9tt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mgvo2yk8yuox0g5o9tt.png" alt="Alexa Working" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A user can access content in a skill by invoking it with Alexa. Alexa is always up for acquiring new skills. When a user speaks to any Alexa-enabled device and uses the wake word, “Alexa,” the device sends the speech to the Alexa service in the cloud. Alexa analyzes the user’s voice, determines what they want, and then makes a request to the skill that can assist them. Speech recognition and natural language processing are handled by the Alexa service. Your skill is deployed as a cloud service. Through an HTTPS enabled request-response mechanism, Alexa communicates with the skill. Alexa skill receives a post request with JSON body whenever they are requested by the user.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wake word:&lt;/strong&gt; Alexa starts listening to your commands once you say the wake word.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Launch word:&lt;/strong&gt; Invocation of the skill will likely follow a launch word, which triggers Alexa to initiate the skill invocation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invocation name:&lt;/strong&gt; A user invokes a skill’s invocation name in order to interact with it. For example, to use the Daily Horoscope skill, the user could say, “Alexa, open my daily horoscope.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Utterance:&lt;/strong&gt; Utterances are spoken requests made by users. Invocation of a skill, inputs for a skill, and confirmation of Alexa’s actions are all possible through spoken requests. Consider the many ways your users could form their requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompt:&lt;/strong&gt; When you talk to Alexa, you can send her a string of text that asks for information. Whenever you respond to a user, you include the prompt text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent:&lt;/strong&gt; A user’s spoken intent is fulfilled by an intent. Slots are optional arguments that can be attached to intents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slot Value:&lt;/strong&gt; Slots are input values entered by the user during their spoken request. By providing these values, Alexa can determine the speaker’s intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Working of WebLex:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9198dredtwkpyyb8h1cz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9198dredtwkpyyb8h1cz.png" alt="architecture" width="401" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The flow of WebLex involves several steps that enable Alexa to control website content effectively:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The user speaks the wake word, "Alexa."&lt;/li&gt;
&lt;li&gt;Alexa processes the wake word, listens to the user’s voice, and sends the command to the Alexa service.&lt;/li&gt;
&lt;li&gt;Alexa uses its interaction model to route the request appropriately.&lt;/li&gt;
&lt;li&gt;The backend, powered by an AWS Lambda function using Node.js, links the frontend with Alexa.&lt;/li&gt;
&lt;li&gt;Alexa sends a JSON-formatted request to the Lambda function, which stores relevant data in a database.&lt;/li&gt;
&lt;li&gt;The Lambda function evaluates the JSON request to determine a response, pulling data from the database as needed.&lt;/li&gt;
&lt;li&gt;An API then retrieves the Lambda function’s output, allowing the website to access this information and display it for the user.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Future Enhancement:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Website Integration&lt;/strong&gt;: Embedding WebLex functionality into a production-ready website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Deployment&lt;/strong&gt;: Hosting WebLex on a cloud platform for increased scalability and accessibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.amazon.com/en-US/docs/alexa/ask-overviews/what-is-the-alexa-skills-kit.html" rel="noopener noreferrer"&gt;Amazon Alexa Skills Kit Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/how-amazon-alexa-works-your-guide-to-natural-language-processing-ai-7506004709d3#:~:text=In%2Ddepth%20explanation" rel="noopener noreferrer"&gt;Understanding How Alexa Works&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>react</category>
      <category>alexa</category>
    </item>
  </channel>
</rss>
