<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[JinHyoung Kim]]></title><description><![CDATA[Coffee, Coding and Life..]]></description><link>https://www.jinhyoungkim.com/</link><image><url>https://www.jinhyoungkim.com/favicon.png</url><title>JinHyoung Kim</title><link>https://www.jinhyoungkim.com/</link></image><generator>Ghost 4.34</generator><lastBuildDate>Tue, 24 Mar 2026 13:55:40 GMT</lastBuildDate><atom:link href="https://www.jinhyoungkim.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend]]></title><description><![CDATA[With leveraging AWS API Gateway, lambda and entity detection feature in the Amazon Comprehend service, the fully functioning NER service endpoint can be easily created. ]]></description><link>https://www.jinhyoungkim.com/create-ner-endpoint/</link><guid isPermaLink="false">6225874023d2cd032a16104c</guid><category><![CDATA[Coding]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Lambda]]></category><category><![CDATA[Comprehend]]></category><category><![CDATA[API Gateway]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Mon, 18 Apr 2022 05:34:55 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/04/Method_Execution_Chart_2-2.png" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/04/Method_Execution_Chart_2-2.png" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend"><p></p><p>In this post, I will create a NER service endpoint by leveraging AWS API gateway, lambda and Amazon Comprehend. The post covers the followings:</p><ul><li>What is NER?</li><li>Amazon Comprehend</li><li>Create a Lambda function to handle a comprehend request and create a response with comprehend entities result</li><li>Create an API endpoint that leverage your lambda function</li><li>Almost done. Fix the possible permission issue!</li><li>Test your NER endpoint call vis postman</li></ul><blockquote>For your information, this post does NOT cover API documentation and any topic regarding authorizing an API service endpoint. </blockquote><hr><h2 id="what-is-ner">What is NER?</h2><p></p><p>NER stands for Named Entity Recognition. It is a Natural Language &#xA0;Processing (NLP) method to identify entities in a text. Entities can be varied such as person, organization, location, etc.</p><p>For example of the following text,</p><pre><code>Steve Jobs was born in San Francisco, California. He was the co-founder, chairman, and CEO of Apple. With Steve Wonzniak, he founded Apple Inc. in 1976. He was also the chairman of Pixar. </code></pre><p>With NER process, these entities below can be found.</p><p>Person: Steven Jobs, Steve Wonzniak</p><p>Organization: Apple Inc, Pixar</p><p>Location: San Francisco, California</p><hr><p></p><h2 id="amazon-comprehend">Amazon Comprehend</h2><p></p><p>Amazon Comprehend is a NLP service that leverages Machine Learning to process a text and extract valuable insights such as key phrases, entities, language detection, etc. Among these features, entity recognition provide us what we need to achieve from our NER service endpoint.</p><p>So the process of our NER service endpoint will follow the steps below.</p><ul><li>The end user makes our NER post call</li><li>API Gateway triggers Lamda function</li><li>Lambda function initiates the Amazon comprehend request and massage the response data from Amazon comprehend in the format of what we need (In this post, we will return the lists of Person, Location and Organization and each item in the list contains text and probability)</li><li>Response data is passed back to API Gateway</li><li>Return the response to the end user</li></ul><hr><h2 id="create-a-lambda-function-to-handle-a-comprehend-request-and-create-a-response-with-comprehend-entities-result">Create a Lambda function to handle a comprehend request and create a response with comprehend entities result</h2><p></p><p>To create a lambda function, first go to <code>AWS Lambda</code> dashboard by searching lambda in the AWS console. In the dashboard, click <code>Create Function</code> button on the right top corner of the screen.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Create_Lamda_Func.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="2000" height="525" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Create_Lamda_Func.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Create_Lamda_Func.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Create_Lamda_Func.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Create_Lamda_Func.png 2118w" sizes="(min-width: 720px) 720px"><figcaption>Basic Information of creating a lambda function</figcaption></figure><p>Provide a function name. In this post, I used <code>getNERFromContent</code> as a function name. Next, choose the Runtime as Python version 3.x. I chose the latest support version of Python at the time of writing this post which was 3.9. You can leave other options as they are. Click <code>Create Function</code> button again.</p><p>In the getNERFromContent detail page, the code source page will be automatically selected and the following source code should be there.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Lambda_Function_Code_Source.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1688" height="886" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Lambda_Function_Code_Source.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Lambda_Function_Code_Source.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Lambda_Function_Code_Source.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Lambda_Function_Code_Source.png 1688w" sizes="(min-width: 720px) 720px"><figcaption>Lambda Code Source</figcaption></figure><p>Remove the source code and paste the source code below.</p><blockquote>Be careful! Indentation is very important in Python. When you paste the code, indentation might be misplaced. Please double-check.</blockquote><pre><code class="language-Python">import json
import boto3

#NER TAG Class
class NerTag:
    def __init__(self, text, prob):
        self.text = text
        self.prob = prob

#NER Response Class
class NERResponse:
    
    def __init__(self, error, success):
        self.error = error
        self.success = success
        self.people = []
        self.organization =[]
        self.location = []
        
    def add_people(self, nerTag):
        self.people.append(nerTag)
        
    def add_organization(self, nerTag):
        self.organization.append(nerTag)
        
    def add_location(self, nerTag):
        self.location.append(nerTag)
    
    def toJSON(self):
        return json.dumps(self, default=lambda o: o.__dict__, 
            sort_keys=True, indent=4)


def lambda_handler(event, context):
    &apos;&apos;&apos;
    This handler will be triggered by API Gateway and create Amazon Comprehend request by
    using detect_entites function. The function will return a NERResponse that contains either lists of Person, Location and Organization NER tag
    or error message if there is an exception.
    &apos;&apos;&apos;
    try:
        #Get Content from Request body
        data = event[&quot;body&quot;]
        body = json.loads(data)
        content = body[&quot;content&quot;]
        #Get Language code that is passed as a path parameter
        params = event[&quot;pathParameters&quot;]
        lang = params[&quot;lang&quot;]
        
        #TODO:Language validation
        #Valid value should be en | es | fr | de | it | pt | ar | hi | ja | ko | zh | zh-TW
        
        #Get Comprehend client
        comprehend = boto3.client(&quot;comprehend&quot;)
        #Use detect entities function to get a list of entities
        entities = comprehend.detect_entities(Text = content, LanguageCode = lang)
        resp = NERResponse(&quot;&quot;, &quot;true&quot;)
        #Loop throuh entities and filter them by PERSON, ORGANIZATION and LOCATION type
        #Put them in their onw list respectively
        #Only Grab those entities whose score is greater than 9.0
        for entity in entities[&quot;Entities&quot;]:
            nt = NerTag(entity[&quot;Text&quot;], entity[&quot;Score&quot;])
            threshold = 0.9
            prob = float( entity[&quot;Score&quot;])
            if (entity[&quot;Type&quot;] == &apos;PERSON&apos; and prob &gt;= threshold):
                resp.add_people(nt)
            
            if (entity[&quot;Type&quot;] == &apos;ORGANIZATION&apos; and prob &gt;= threshold):
                resp.add_organization(nt)
            
            if (entity[&quot;Type&quot;] == &apos;LOCATION&apos; and prob &gt;= threshold):
                resp.add_location(nt)
        #Return the response. Make sure path statusCode and put the result in the body
        #Otherwise, it will throw 502 error when this api is being called.
        return {
            &quot;statusCode&quot;: &quot;200&quot;,
            &quot;body&quot;: resp.toJSON()
        }
    except Exception as e:
        print(e.__class__, &quot; occurred.&quot;)
        resp = NERResponse(str(e), &quot;false&quot;)
        return {
            &quot;statusCode&quot;: &quot;500&quot;,
            &quot;body&quot;: resp.toJSON()
        }

</code></pre><p>In this source code example, I grab those entities whose score is greater than 0.9. You can change this by updating threshold variable. There are also <code>Date</code>, <code>Quantity</code> ,<code>Other</code> &#xA0;and more. You can check all list of types <a href="https://docs.aws.amazon.com/comprehend/latest/dg/how-entities.html">here</a>. You can save the source code by using the short key <code>command+s</code> or <code>control+s</code> depends on your OS or you can go to <code>File</code> and choose <code>Save</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Code_Source_File_Menu.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="516" height="624"><figcaption>Code Source File Menu</figcaption></figure><p></p><p>Once all source code looks ok, then click <code>Deploy</code> button.</p><hr><p></p><h2 id="create-an-api-endpoint-that-leverage-your-lambda-function">Create an API endpoint that leverage your lambda function</h2><p></p><p>Ok. It&apos;s time to set up an API endpoint. First, go to <code>API Gateway</code>. Again, you can type &quot;API Gateway&quot; in search bar and click the service.</p><p>In APIs page, click <code>Create API</code> button. There should be 4 options.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/API_Gateway_Restapi_Build.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1876" height="438" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/API_Gateway_Restapi_Build.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/API_Gateway_Restapi_Build.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/API_Gateway_Restapi_Build.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/API_Gateway_Restapi_Build.png 1876w" sizes="(min-width: 720px) 720px"><figcaption>Rest Api Build</figcaption></figure><p>Click <code>Build</code> button in the <code>REST API</code> (This is not private one). The initial setting like the below screenshot will be appeared.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Initial_Setting.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1156" height="930" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Initial_Setting.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Initial_Setting.png 1000w, https://www.jinhyoungkim.com/content/images/2022/04/Initial_Setting.png 1156w" sizes="(min-width: 720px) 720px"><figcaption>Initial Settings for Rest Api Build</figcaption></figure><p>Provide the input as follows:</p><ul><li>Choose the protocol: REST</li><li>Create new API: New API</li><li>API name: TestNER</li><li>Description: Test NER Service endpoint</li><li>Endpoint Type: Regional</li></ul><p>Click <code>Create API</code> button.</p><p>Once you can see the Resources page, there should be only one under Resources section which is <code>/</code>. In this post, I will construct the endpoint as follows.</p><pre><code>/ner/{lang}</code></pre><p>where lang should be one of <code>en | es | fr | de | it | pt | ar | hi | ja | ko | zh | zh-TW</code>.</p><p>Click <code>Actions</code> -&gt; <code>Create Resource</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Actions_Menu.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="734" height="674" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Actions_Menu.png 600w, https://www.jinhyoungkim.com/content/images/2022/04/Actions_Menu.png 734w" sizes="(min-width: 720px) 720px"><figcaption>Actions Menu</figcaption></figure><p>Type <code>ner</code> in the Resource Name. Resource Path will be automatically cloned. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Create_Resource-1.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1284" height="138" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Create_Resource-1.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Create_Resource-1.png 1000w, https://www.jinhyoungkim.com/content/images/2022/04/Create_Resource-1.png 1284w" sizes="(min-width: 720px) 720px"><figcaption>Resource Name</figcaption></figure><p>You can leave proxy resource and Enable API Gateway CORS as unchecked. Click <code>Create Resource</code> button. This will create <code>/ner</code> path under <code>/</code>. Select <code>/ner</code> and create resource one more time (Actions -&gt; Create Resource). &#xA0;However, in this time, enter <code>{lang}</code> first in the Resource Path and enter <code>lang param</code> as a resource name as shown below. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Create_Resource_lang_param-2.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1264" height="152" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Create_Resource_lang_param-2.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Create_Resource_lang_param-2.png 1000w, https://www.jinhyoungkim.com/content/images/2022/04/Create_Resource_lang_param-2.png 1264w" sizes="(min-width: 720px) 720px"><figcaption>Lang Parameter Resource Creation</figcaption></figure><p>Now you should be able to see <code>/{lang}</code> under <code>/ner</code>. Click <code>/{lang}</code> and create method (Action -&gt; Create Method). The dropdown will be appeared. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Create_Method_Post-1.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="454" height="604"><figcaption>Create Method</figcaption></figure><p>Select <code>POST</code> in the dropdown and click check icon. The page will be redirected to the new page where you can choose integration type.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Choose_Integration_Point_2-1.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="906" height="618" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Choose_Integration_Point_2-1.png 600w, https://www.jinhyoungkim.com/content/images/2022/04/Choose_Integration_Point_2-1.png 906w" sizes="(min-width: 720px) 720px"><figcaption>Choose Integration Type</figcaption></figure><p>Select <code>Lambda Function</code> as Integration Type and make sure to check <code>Use Lambda Proxy integration</code> so that Lambda function is able to receive path parameters such as <code>{lang}</code> in our case.</p><p>For Lambda Function text box, once you start typing the lambda function name that you used, the full name should be visible as an option underneath the dropdown. You can simply select it. Once click <code>Save</code> button, then there should be popup window to ask adding a permission to lambda function.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Add_Permission_To_Lambda.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1758" height="454" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Add_Permission_To_Lambda.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Add_Permission_To_Lambda.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Add_Permission_To_Lambda.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Add_Permission_To_Lambda.png 1758w" sizes="(min-width: 720px) 720px"><figcaption>Add Permission to Lambda Function</figcaption></figure><p>Click <code>OK</code> button. If there is no issue, then there should be a method execution diagram that is similar to the screenshot below.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Method_Execution_Chart_2-1.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="2000" height="883" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Method_Execution_Chart_2-1.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Method_Execution_Chart_2-1.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Method_Execution_Chart_2-1.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Method_Execution_Chart_2-1.png 2178w" sizes="(min-width: 720px) 720px"><figcaption>Method Execution Diagram</figcaption></figure><p>Great. We successfully create the endpoint with the lambda function. Let&apos;s deploy this API. From <code>Actions</code> button, choose <code>Deploy API</code>. In the modal, select <code>[New Stage]</code> as Deployment stage.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Deploy_API.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="1156" height="736" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Deploy_API.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Deploy_API.png 1000w, https://www.jinhyoungkim.com/content/images/2022/04/Deploy_API.png 1156w" sizes="(min-width: 720px) 720px"><figcaption>Deploy API</figcaption></figure><p>And provide Stage name, description and Deployment description. I used &quot;test&quot;, &quot;test ner endpoint&quot; and &quot;test deployment&quot; respectively. Click <code>Deploy</code> button.</p><p>That&apos;s it. Your API Url will be displayed in <code>Invoke URL</code>.</p><figure class="kg-card kg-image-card"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Invoke_Url.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="2000" height="151" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Invoke_Url.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Invoke_Url.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Invoke_Url.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Invoke_Url.png 2196w" sizes="(min-width: 720px) 720px"></figure><p>Ok. Your NER service endpoint is now set as</p><pre><code>https://YourInvokeURL.com/test/ner/{lang}
</code></pre><p>In my case, the NER endpoint should be</p><p><a href="https://e2zdt59opf.execute-api.us-east-1.amazonaws.com/test/ner/en"><code>https://e2zdt59opf.execute-api.us-east-1.amazonaws.com/test/ner/en</code></a></p><hr><p></p><h2 id="almost-done-fix-the-possible-permission-issue">Almost done. Fix the possible permission issue!</h2><p></p><p>Ok. We&apos;re almost done. However, if you test this endpoint via your postman, you should run into the permission issue. This is because the user role that is being used for executing lambda does not have the permission for using Amazon Comprehend yet. In order to fix this issue, go to <code>IAM</code> (search IAM) and select <code>Roles</code> under <code>Access management</code>. Search the role by using your lambda function name which is <code>getNERFromContent</code>. &#xA0;You can find the similar role below.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Lambda_Role.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="2000" height="84" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Lambda_Role.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Lambda_Role.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Lambda_Role.png 1600w, https://www.jinhyoungkim.com/content/images/2022/04/Lambda_Role.png 2194w" sizes="(min-width: 720px) 720px"><figcaption>Lambda Role</figcaption></figure><p>Click the link (getNERFromContent-role-xxxxxx) and click <code>Add permissions</code> -&gt; <code>Attach policies</code> menu in the detail page.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Iam_Attach_Policies.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="426" height="238"><figcaption>Attach Policies Option</figcaption></figure><p>In the new page, there should be a bunch of list of policies. To search comprehend related policies, let&apos;s type <code>comprehend</code> in the filter text field and hit enter key.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Comprehend_Full_Access-1.png" class="kg-image" alt="Create a NER endpoint  by using AWS API Gateway, Lambda and Comprehend" loading="lazy" width="2000" height="347" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Comprehend_Full_Access-1.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Comprehend_Full_Access-1.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/04/Comprehend_Full_Access-1.png 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/04/Comprehend_Full_Access-1.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Comprehend related policies</figcaption></figure><p>Select the checkbox for <code>ComprehendFullAccess</code> and click <code>Attach policies</code> button.</p><blockquote>I chose ComprehendFullRequest as an example. Depends on a situation, creating custom policy might be inevitable, or a different role might be used instead. Consider discussing with your IT/DevOp team if needed.</blockquote><p>Ok. All set. Let&apos;s test it.</p><hr><p></p><h2 id="test-your-ner-endpoint-call-vis-postman">Test your NER endpoint call vis postman</h2><p></p><p>In your postman, enter your NER service endpoint with adding the following content (in Json) in the body. </p><pre><code>{
    &quot;content&quot;: &quot;Steve Jobs was born in San Francisco, California. He was the co-founder, chairman, and CEO of Apple. With Steve Wonzniak, he founded Apple Inc. in 1976. He was also the chairman of Pixar.&quot;
}</code></pre><p>You should be able to see the result like below.</p><pre><code>{
    &quot;error&quot;: &quot;&quot;,
    &quot;location&quot;: [
        {
            &quot;prob&quot;: 0.9968991875648499,
            &quot;text&quot;: &quot;San Francisco, California&quot;
        }
    ],
    &quot;organization&quot;: [
        {
            &quot;prob&quot;: 0.9990672469139099,
            &quot;text&quot;: &quot;Apple&quot;
        },
        {
            &quot;prob&quot;: 0.9954066276550293,
            &quot;text&quot;: &quot;Apple Inc.&quot;
        },
        {
            &quot;prob&quot;: 0.9990543723106384,
            &quot;text&quot;: &quot;Pixar&quot;
        }
    ],
    &quot;people&quot;: [
        {
            &quot;prob&quot;: 0.9995225071907043,
            &quot;text&quot;: &quot;Steve Jobs&quot;
        },
        {
            &quot;prob&quot;: 0.9993040561676025,
            &quot;text&quot;: &quot;Steve Wonzniak&quot;
        }
    ],
    &quot;success&quot;: &quot;true&quot;
}</code></pre><p></p><p>If the endpoint does not work for some reason, check the indentation in the source code of the lambda function and double check the permission. You can also check the logs for lambda function from the <code>CloudWatch</code> as well. </p><blockquote>For your information, this test endpoint will not be available for the security reason. </blockquote><p>Hopefully this post will be helpful to you and thanks for your time to read this post. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[Trip to Mont Tremblant - Tips]]></title><description><![CDATA[In this post, I will share small tips that I learned from my first Mont Tremblant Trip regarding Lift Ticket, Trails, Ski Valet, etc. ]]></description><link>https://www.jinhyoungkim.com/trip-to-mont-tremblant-tips/</link><guid isPermaLink="false">624a4c7e2361f90301b8e722</guid><category><![CDATA[Life]]></category><category><![CDATA[Mont Trembalant Tips]]></category><category><![CDATA[Mont Tremblant]]></category><category><![CDATA[Trip]]></category><category><![CDATA[Ski]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Mon, 04 Apr 2022 04:07:10 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/04/ski-gadb22b163_1920-min.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/04/ski-gadb22b163_1920-min.jpg" alt="Trip to Mont Tremblant - Tips"><p></p><p>In this post, I would like to share small tips that I learned from my first Mont Tremblant trip. These tips are purely from my personal thoughts, so some people might think these are too obvious or disagree some of them. Please take them selectively if needed and hopefully you get some useful information in this post.</p><p>Ok. Enough intro. Let&apos;s get to the points. </p><h2 id="ski-lift-ticket">Ski Lift Ticket</h2><p></p><p>If you are like me who bought or plan to buy the tickets partially from the promotions (some afternoon tickets + full day promotion adult tickets + a regular child ticket), I would recommend not to use the ticket kiosk. Even though you scan the right QR code from your email for a given date into the ticket kiosk, you probably receive the promotion tickets instead of regular afternoon ticket for the given date you initially intend to use. This happened to both me and my friend&apos;s family. In order to solve this, you need to visit the ticket office.</p><figure class="kg-card kg-image-card"><img src="https://www.jinhyoungkim.com/content/images/2022/04/Lift_Ticket_Email.jpg" class="kg-image" alt="Trip to Mont Tremblant - Tips" loading="lazy" width="1414" height="916" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/04/Lift_Ticket_Email.jpg 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/04/Lift_Ticket_Email.jpg 1000w, https://www.jinhyoungkim.com/content/images/2022/04/Lift_Ticket_Email.jpg 1414w" sizes="(min-width: 720px) 720px"></figure><p>Therefore, instead of using ticket kiosk, go to the ticket office directly. All you need to provide is your order number (Like 60501553 from the above image) and they will print all your purchased tickets.</p><p>One benefit from getting all tickets for me was that you don&apos;t need to verify the proof of vaccination every day during your trip. They will punch a hole on your entire lift tickets as a proof that vaccination checking is completed. </p><blockquote>The proof of vaccination is no longer required now. Hopefully, we don&apos;t do this in the future.</blockquote><h2 id="trails">Trails</h2><p></p><p>If you are at beginner level and don&apos;t feel comfortable using blue trails, the following trails might be a good routine to start with. Obviously, if there is strong wind on south side, then try using trails on north side and vice versa.</p><p>For South Side</p><ul><li><code>2 LA CRETE</code> -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>6 NANSEN BAS</code> (Longest trails - 6 kim)</li><li><code>40 FRNC SUD</code>-&gt;<code>95 L&apos;ALGONQUIN</code> (Green) -&gt; Taking <code>LE SOLEIL</code> lift</li></ul><p>For North Side</p><ul><li><code>72 P&apos;TIT BONHEUR</code> -&gt; Taking <code>LOWELLTHOMAS</code> lift</li><li><code>72 P&apos;TIT BONHEUR</code> -&gt; <code>77 BEAUCHEMIN BAS</code> -&gt; Taking <code>DUNCAN EXPRESS</code> lift</li></ul><h2 id="lift-closing-time">Lift Closing Time</h2><p></p><p>If you have been skiing from various ski resorts such as Blue mountain, Moonstone, Horseshoe, Snow Valley, etc in Ontario, you might get used to doing a night ski. Unfortunately, &#xA0;there is no night ski at Mont Tremblant. When I visited, lifts stopped running at 4 pm. Lift closing time may varied during a season, so please check the closing time from this <a href="https://www.tremblant.ca/mountain-village/mountain-report?sc_lang=en#/lifts">page</a> ahead of time. </p><p>Moreover, if you&apos;re like me who wants to enjoy skiing even a few minutes more, then try the following trails before almost closing time.</p><ul><li><code>2 LA CRETE</code> -&gt; <code>7 ALPINE</code> -&gt; Taking <code>TGV</code> lift -&gt; <code>8 BEAUVALLON HAUT</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code></li></ul><p>This routine will lead you to the lift in the middle, take you to the top again and make you choose your true final trails for the day.</p><h2 id="ski-valet">Ski Valet</h2><p></p><p><strong>This is a must service you need. </strong>Before I visited Mont Tremblant, I was not aware of this ski valet service at all. Luckily, the hotel I stayed let me know and I truly felt grateful whenever I used the ski valet service on both a lunch break and the closing time. Bring you and your family&apos;s ski equipments back to your hotel wouldn&apos;t be easy since you probably feel exhausted already. Most importantly, this service is totally free.</p><p>So, before you book your hotel, <strong>make sure you ask whether your hotel provides ski valet service</strong>. &#xA0;Your life will be much easier during the trip.</p><h2 id="hot-tub-after-ski">Hot Tub After Ski</h2><p></p><p>Unless you hate using a hot tub, I strongly recommend using it after you enjoy your ski. Putting your tired body into the hot water for some time not only gets rid of fatigue but also make you feel refresh just as you get the massage from a famous massage therapist.</p><h2 id="on-a-way-back-home">On a Way Back Home</h2><p></p><p>One big mistake I made was driving home directly from Mont Tremblant. Especially, I also had afternoon ski and there was a snow storm on my last day. Luckily, I got home safely, but driving itself was not fun at all. If you require a long driving distance to get home and plan to do afternoon ski as well, I strongly recommend staying some place in the middle. In my case, Ottawa was the good place to stop by and take a rest. If I have a chance to do this Mont Tremblant trip again, I will definitely stay at Ottawa one night.</p><p></p><p>This is it. Hope you don&apos;t feel disappointed about these tips and again I am able to give you at least one or two useful information via this post. </p><p>Thanks for your time as always!</p>]]></content:encoded></item><item><title><![CDATA[Trip to Mont Tremblant - 3 days]]></title><description><![CDATA[In this post, I will share what happened during 3-days trip to Mont Tremblant in terms of hotel, ski valet and trails]]></description><link>https://www.jinhyoungkim.com/trip-to-mont-tremblant-overall/</link><guid isPermaLink="false">6237513c1e92430305dca7b8</guid><category><![CDATA[Life]]></category><category><![CDATA[Ski]]></category><category><![CDATA[Mont Tremblant]]></category><category><![CDATA[Trip]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Thu, 24 Mar 2022 04:10:15 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/03/MontTremblant-Lift.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/03/MontTremblant-Lift.jpeg" alt="Trip to Mont Tremblant - 3 days"><p></p><p>In this post, I will share what happened during 3-days trip to Mont Tremblant. For this trip, there were my two friends&apos; families joined the trip as well.</p><h2 id="d-1-day">D-1 day</h2><p>The day before I travelled, I called the hotel (<code>Ermitage Du Lac</code>) and asked if early check-in was available. I was told that the early check-in could not be confirmed over the phone call during this time and was able to check upon arrival. After that, I finished packing and put all luggages in the car trunk. Since I planned to leave home around 4 am, I needed to be ready by everything before I went to bed. </p><p>Why did I leave at 4 am? Well, there were several reasons. </p><p>First of all, I like driving in early morning because it is very quiet and there are no traffics on the road all the time. Plus, with a help of good weather, you can have a chance to check the beautiful sunrise while driving. &#xA0;</p><p>Secondly, and most importantly, I can drive as far as possible while my daughter is still sleeping in the car (Of course, &#xA0;there is 50% success rate). The kids usually do not like sitting in the car for long time. &#xA0;They can easily get bored and start complaining. That&apos;s when you need to stop every service station, take a rest and eventually cause the delay on your plan. </p><p>Thirdly, I purchased the afternoon lift tickets. I did not want to be late since we had only 4 hours (between 12 pm and 4 pm) to enjoy skiing.</p><p>To make my first day run smoothly, almost everything should be ready on the day before.</p><h2 id="1st-day">1st Day</h2><p>I woke up at 3:30 am with my alarm sound. I quickly brewed my coffee and took some frozen food from my freezer and put them in my small cool box along with water bottles and a couple of red bull drinks. </p><p>The next thing I did was to wake up my wife. Once we were ready to leave, &#xA0;we still had the most important and difficult task to proceed: Putting my daughter in the car without waking up. You can guess probably what happened. Thanks to my unstable movements during caring her to the car, my daughter woke up and she walked to the car by herself. &#xA0;This was obviously not a good start...</p><p>Despite my worry about my daughter not sleeping enough, she actually went back to sleep after I drove for a half hour . I guess her neck pillow, warm blanket and no too much noise on the road helped her back to sleep faster. &#xA0;She was able to sleep until we stopped by one of McDonald branches in Ottawa for the breakfast. </p><blockquote><strong>Note:</strong> I highly recommend brining cups of coffee and any type of sports drinks to prevent you from falling a sleep. However, whenever you feel sleepy, make sure you DO NOT DRIVE. Life is much more important than getting your destination on time. If your partner can drive, taking a turn would be very beneficial, especially for this early morning driving. &#xA0; &#xA0;</blockquote><p>Around 11:30 am, we arrived our hotel <code>Ermitage Du Lac</code>.</p><p>Once I got into the hotel, the woman asked me if I was the one who called for the early check-in and told me the room was ready. &#xA0;Thanks to early checkin, I did not need to spend time and money to find the parking spot and my family was able to have a lunch and prepare for ski in the hotel room comfortably.</p><ol><li><strong>Getting lift tickets</strong></li></ol><p>I purchased the following lift tickets.</p><ul><li>March 9 - Only Afternoon Ski</li><li>March 10 - Full Day</li><li>March 11 - Only Afternoon Ski</li></ul><p>When I went to the ticket office, I found two ticket kiosks right next to the ticket office. I used one of kiosks and put the QR code from one of emails, but I wasn&apos;t able to get all tickets. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Lift_Ticket_Email.jpg" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="1414" height="916" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Lift_Ticket_Email.jpg 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Lift_Ticket_Email.jpg 1000w, https://www.jinhyoungkim.com/content/images/2022/03/Lift_Ticket_Email.jpg 1414w" sizes="(min-width: 720px) 720px"><figcaption>Lift Ticket Email</figcaption></figure><p>I think it was because my full day tickets were purchased with promotion. I had to go to the ticket office and let them know. They printed all tickets again, but my daughter&apos;s last ticket did not print out. I checked again with the ticket office and finally got all tickets. &#xA0;To be honest, I did not like this whole ticket printing process, but people at the ticket office were super friendly and tried their best to fix the issue. I didn&apos;t have time for complains. My attention was all about trying skiing as quickly as possible. </p><p><strong>2. Checking the Proof of vaccination</strong></p><p>The next thing to do was to show my vaccine proof. There was a small section right next to the ticket kiosk. We showed our IDs (Driver license) and proof of vaccination. After that, they made a hole on your lift card as a poof.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Lift_Ticket-min.jpg" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="2000" height="1500" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Lift_Ticket-min.jpg 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Lift_Ticket-min.jpg 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/Lift_Ticket-min.jpg 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/03/Lift_Ticket-min.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Lift Ticket after checking the proof of vaccination</figcaption></figure><p>It was very quick and straight forward process. </p><p><strong>3. First Ski Experience</strong></p><p>My family have tried the following ski resorts before we hit Mont Tremblant.</p><ul><li>Uplands</li><li>Lakeridge</li><li>Dagmar</li><li>Horseshoe</li><li>Snow Valley</li><li>MSLM (Mout St. Louis Moonstone)</li></ul><p>Especially, we have purchased the silver pass on MSLM for 2 years and tried to maximize our ski experiences in there during winter time. I can not say our family are very good at skiing, but we feel comfortable by trying green &amp; blue trails and can manage black trails without having a big concern.</p><p>So, we took the express gondola and head to the top of mountain. It was not too cold and a perfect weather for skiing. &#xA0;Luckily, there were not many people too.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Family_On_Top_Of_Mountain.jpeg" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="960" height="1280" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Family_On_Top_Of_Mountain.jpeg 600w, https://www.jinhyoungkim.com/content/images/2022/03/Family_On_Top_Of_Mountain.jpeg 960w" sizes="(min-width: 720px) 720px"><figcaption>Family on the top of Mont Tremblant Mountain</figcaption></figure><p></p><p>For our first try, we decided to take the longest trail which was a combination of green trails. The following map was partially captured from the official website and the entire map of ski trails can be found <a href="https://vicomap-cdn.resorts-interactive.com/map/1711?menuWord=MENU">here</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Longest_Trails_In_Mont_Blant-min-1.png" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="1694" height="2296" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Longest_Trails_In_Mont_Blant-min-1.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Longest_Trails_In_Mont_Blant-min-1.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/Longest_Trails_In_Mont_Blant-min-1.png 1600w, https://www.jinhyoungkim.com/content/images/2022/03/Longest_Trails_In_Mont_Blant-min-1.png 1694w" sizes="(min-width: 720px) 720px"><figcaption>Longest trail in Mont Tremblant</figcaption></figure><p>We took <code>2 LA CRETE</code> -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>6 NANSEN BAS</code> which was around 6 km. It was the longest trail I have never tried before. &#xA0;It took us around 12 mins to get to the end of the trail where we took the gondola. Even after my first try, my legs seemed to be tired already. &#xA0;My first impression on the trail was that it was pretty dynamic in terms of &#xA0;a level of difficulty. Even though it was the green trail, any newbie might feel challenge because there were couple of areas to be considered as blue trail in my opinion. Similarly, some blue trails seemed to be a black trails in other ski resorts I have been tried. For our family, trying this longest trail made feel so happy. It was another level of our ski experience.</p><p>After that, we slightly changed our trails like the following:</p><ul><li><code>2 LA CRETE</code> -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>96 TAM-TAM</code> -&gt; <code>6 NANSEN BAS</code></li><li><code>2 LA CRETE</code> -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>96 TAM-TAM</code> -&gt; <code>38 PANACHE</code> -&gt; <code>6 NANSEN BAS</code> (Not recommended. <code>38 PANACHE</code> requires long walks)</li><li><code>2 LA CRETE</code> -&gt; <code>3 NANSEN</code> (Blue) -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>6 NANSEN BAS</code> </li><li><code>2 LA CRETE</code> -&gt; <code>3 NANSEN</code> (Blue) -&gt; <code>9 MI-CHEMIN</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code> (Not recommended. <code>9 MI-CHEMIN</code> was so long flat trail that requires long walks)</li></ul><p>We thought the gondola was running til 4:30 pm, but I was wrong. They stopped running at 4 pm. However, this was sufficient enough to know the taste of skiing in Mont Tremblant.</p><p><strong>4. &#xA0;Ski Valet Service</strong></p><p>I did not know there was such thing like <code>Ski Valet Service</code>, but the hotel receptionist let me know about this ski valet when I checked in. I am not sure who introduced the wonderful service at first time, but I want to give him or her the Nobel prize if I can. Using this service was apparently the best thing I had done in Mont Tremblant and I got lots of kudos from my family. </p><p>How can you use this? It is easy. &#xA0;There is a small cabin right next to the gondola express entrance. You just need to tell where you stay and give them your ski and poles. It&apos;s completely free.</p><p><strong>5. &#xA0; Rest of a day</strong></p><p>As soon as I came back to the hotel, my daughter and I wanted to use the hot tub really bad. There wasn&apos;t not many reservation, so we were able to the book quickly. Putting your body into the hot water after ski was the second best thing I had done. I felt so relaxed and all the body pains seemed to go away. </p><p>After using this fantastic hot tub experience, we had the dinner and walked around the villages where all stores, hotels and restaurants are gathered. &#xA0;Simply walking around the village was surprisingly fun. We also bought beavertails as a dessert.</p><p>I knew I was supposed to watch a movie with my daughter, but I only remembered the intro of Disney castle and my daughter yelling me &quot;Stop snoring. I can&apos;t sleep!&quot; a couple of times...</p><p>It was very tired day, but also perfect day.</p><h2 id="2nd-day">2nd Day</h2><p></p><p>I woke up at 8:30 am. I didn&apos;t know it was because of my snoring, my wife and daughter were still sleeping peacefully. Since the hotel provided the complimentary breakfast, I went to the dining place, ordered some breads, cereal, coffee and juice for my family and brought them back to my room. </p><p>Rest of schedules followed similar to the first day except for trying early ski.</p><p>We gained some confidence from the first day ski, we decided trying various blue trails. Here is the list of trails we tried. Especially, the first two trails were my favourite routines.</p><ul><li><code>2 LA CRETE</code> -&gt; <code>7 ALPINE</code> -&gt; <code>8 BEAUVALLON HAUT</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code></li><li><code>2 LA CRETE</code> -&gt; <code>8 BEAUVALLON HAUT</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code></li><li><code>40 FRNC SUD</code>-&gt;<code>95 L&apos;ALGONQUIN</code> (Green) -&gt; Taking <code>LE SOLEIL</code> lift (recommended for beginners) </li><li><code>40 FRNC SUD</code>-&gt; <code>41 TOBOGGAN</code> -&gt; <code>42 TAPECUL</code> -&gt; Taking <code>LE SOLEIL</code> lift</li><li>Taking <code>FLYING MILE</code> lift -&gt; <code>30 LIGNE DE PENTE</code> (Black) -&gt; <code>29 JOHANNSEN</code></li><li><code>2 LA CRETE</code> -&gt; <code>7 ALPINE</code> -&gt; Taking <code>TGV</code> lift -&gt; <code>8 BEAUVALLON HAUT</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code> (Before closing routine)</li></ul><p>I really liked the first two routines, so I had tried several times before I changed the trails on the other side.</p><p>After we finished skiing, my daughter and I headed to the hot tub (I felt like the first use of the hot tub addicted me to it). &#xA0;Once we had plenty of time to relax, we went to my friends&apos; accommodation for dinner and had delicious meals and drinks.</p><p>Another beautiful day was gone.</p><p></p><h2 id="3rd-day">3rd Day</h2><p></p><p>It was my last day already. Time flied, so we did not want to waste a minute.</p><p>In the morning, we had the breakfast and started packing. I moved all luggages to my car trunk and did checkout. My car still stayed safely in the parking lot in the hotel. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Hotel_Parking_Permit-min.jpg" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="2000" height="1500" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Hotel_Parking_Permit-min.jpg 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Hotel_Parking_Permit-min.jpg 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/Hotel_Parking_Permit-min.jpg 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/03/Hotel_Parking_Permit-min.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption>Hotel Parking Permit</figcaption></figure><p>Of course, we were all ready for enjoying our last day ski. </p><p>At this time, we decided to try some trails on north side (The first 2 days, we were on only south side).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/North_side_partial_map-min.png" class="kg-image" alt="Trip to Mont Tremblant - 3 days" loading="lazy" width="1162" height="2338" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/North_side_partial_map-min.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/North_side_partial_map-min.png 1000w, https://www.jinhyoungkim.com/content/images/2022/03/North_side_partial_map-min.png 1162w" sizes="(min-width: 720px) 720px"><figcaption>Partial Map on North Side</figcaption></figure><p> Here is the list of trails that we tried on north side.</p><ul><li><code>72 P&apos;TIT BONHEUR</code> -&gt; <code>77 BEAUCHEMIN BAS</code> -&gt; Taking <code>DUNCAN EXPRESS</code> lift (recommended for beginners) </li><li><code>72 P&apos;TIT BONHEUR</code> -&gt; <code>77 BEAUCHEMIN BAS</code> &#xA0;-&gt; Taking <code>EXPO EXPRESS</code> lift -&gt; <code>70 GAGNON</code> -&gt; Taking <code>LOWELLTHOMAS</code> lift</li><li><code>71 BEAUCHEMIN HAUT</code> -&gt; <code>77 BEAUCHEMIN BAS</code> &#xA0;-&gt; Taking <code>EXPO EXPRESS</code> lift -&gt; <code>70 GAGNON</code> -&gt; Taking <code>LOWELLTHOMAS</code> lift</li><li><code>67 LOWELL THOMAS</code> -&gt; Taking <code>LOWELLTHOMAS</code> lift</li></ul><p>We also tried some trails on south side too. </p><ul><li><code>18 MCCULLOCH</code> (Black) -&gt; Taking <code>TGV</code> lift</li><li><code>2 LA CRETE</code> -&gt; <code>7 ALPINE</code> -&gt; <code>8 BEAUVALLON HAUT</code> -&gt; <code>20 DESSERRES</code> -&gt; <code>29 JOHANNSEN</code></li><li><code>2 LA CRETE</code> -&gt; <code>4 NANSEN HAUT</code> -&gt; <code>6 NANSEN BAS</code> (The longest trail. recommended for beginners) </li><li>Taking <code>FLYING MILE</code> lift -&gt; <code>30 LIGNE DE PENTE</code> (Black) -&gt; <code>29 JOHANNSEN</code></li></ul><p>With Taking these last trails, <code>29 JOHANNSEN</code> -&gt; <code>37 VOYAGEUR</code>, we were able to come back to the hotel with short walks and head back to my home.</p><p>On a way back, we stopped by a take-out restaurant in Ottawa for our dinner. I also went to a beer brewery called <code>spark beer</code> and bought some beers too. &#xA0;Actually, my must go beer brewery in Ottawa was <code>Small Pony</code> brewery, but they closed early on that day. Well..at least I was able to find other good brewery. :)</p><p>From Ottawa to my home, the road condition was extremely bad because snow storm started hitting us. We were supposed to get home before 12 am, but we actually arrived at 2:30 am. </p><p>So this was it. It was very tight schedules, but we really enjoyed our trip to Mont Tremblant. I strongly recommend if you haven&apos;t been there yet.</p><p>I will create one more post regarding a few tips that I learned from the trip. </p><p>Thanks for your time to read this post!</p>]]></content:encoded></item><item><title><![CDATA[Trip to Mont Tremblant - Planning]]></title><description><![CDATA[Planning for a family trip always fun and exciting. A process of planning and researching about a trip brings me to the destination ahead of time]]></description><link>https://www.jinhyoungkim.com/trip-to-mont-tremblant-planning/</link><guid isPermaLink="false">623152b423d2cd032a16111b</guid><category><![CDATA[Life]]></category><category><![CDATA[Trip]]></category><category><![CDATA[Ski]]></category><category><![CDATA[Mont Tremblant]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Wed, 16 Mar 2022 05:29:28 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/03/rene-pierre-normandeau-sl87lljZVLg-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/03/rene-pierre-normandeau-sl87lljZVLg-unsplash.jpg" alt="Trip to Mont Tremblant - Planning"><p>Planning for a family trip always fun and exciting. A process of planning and researching about a trip brings me to the destination ahead of time in my imagination and show me how a trip would look like. Of course, sometimes, the reality of the actual trip betrays my &quot;supposed-to-be-well-plan&quot; and the entire trip goes to the totally different direction with various unexpected events. </p><p>But, I know all these will become eventually the part of our valuable memories...</p><h2 id="why-mont-tremblant">Why Mont Tremblant?</h2><p></p><p>With the invasion of Covid virus to our life, my family trip had become a series of staycations for almost 2 years. Staying home sounded easy at first time, but we realized it actually gave my family very hard times both mentally and physically. As my daughter&#x2019;s march break for 2022 was coming up, I wanted to do a family trip that can fulfill the followings:</p><ul><li>Outside activity that whole family can enjoy</li><li>Less safety concern</li><li>Somewhere that requires a bit of driving distance</li><li>Being beneficial for my daughter&#x2019;s education</li></ul><p>So...the only place I can think of is...Mont Tremblant!</p><p>Our whole family loves skiing, so it can definitely be the best option where my whole family can enjoy for sure. Moreover, we can still wear a mask while we enjoy skiing. Moreover, checking vaccine proof is mandatory for those who stay at a hotel or use a ski lift in Mont Tremblant. This activity would give us relatively less concern in terms of safety measure. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Distance_from_home_to_MontTremblant.png" class="kg-image" alt="Trip to Mont Tremblant - Planning" loading="lazy" width="2000" height="1178" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Distance_from_home_to_MontTremblant.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Distance_from_home_to_MontTremblant.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/Distance_from_home_to_MontTremblant.png 1600w, https://www.jinhyoungkim.com/content/images/2022/03/Distance_from_home_to_MontTremblant.png 2380w" sizes="(min-width: 720px) 720px"><figcaption>Google Map from my home to Mont Tremblant</figcaption></figure><p>Mon Tremblant is 6.5 hours driving distance from my home, so this wouldn&#x2019;t be bad to get some fresh airs outside of my current region. Lastly, Mon Tremblant is in Quebec, so this can be a perfect chance for my daughter to practice her french language.</p><p>So..Why not Mont Tremblant?</p><h2 id="planningdates">Planning - Dates</h2><p></p><p>My daughter&apos;s march break is from March 14 to March 18. However, I know during this time, the price usually goes up. So I decided to stay in Mont Tremblant a week before the march break which was from March 9, 10 and 11. </p><p>Actually, this was a good decision. The accommodation price was relatively cheaper, &#xA0;there were less people in ski hills and most importantly weather was also perfect (Except for the evening on the last day when snow storms hit me on my way back home).</p><h2 id="planningaccommodation">Planning - Accommodation</h2><p></p><p>Once the dates were set, I started looking for a place to stay. &#xA0;Even though, I picked the dates a week before the actual march break, the hotel prices in Mont Tremblant were still expensive. However, I had TD reward points that I collected during promotion last year and was able to redeem $590 by leveraging Expedia for TD. </p><p>With benefit of using the reward points, I would like to stay a hotel where the Express Gondola are easily accessible and also can cook inside the room. Of course, the price should not be too high. After spending quite some research time, I chose the hotel called <code>Ermitage Du Lac</code>. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Ermitage_Du_Lac_in_GoogleMap.png" class="kg-image" alt="Trip to Mont Tremblant - Planning" loading="lazy" width="1386" height="1378" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Ermitage_Du_Lac_in_GoogleMap.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Ermitage_Du_Lac_in_GoogleMap.png 1000w, https://www.jinhyoungkim.com/content/images/2022/03/Ermitage_Du_Lac_in_GoogleMap.png 1386w" sizes="(min-width: 720px) 720px"><figcaption>Ermitage Du Lac in Google Map</figcaption></figure><p>To be honest, this hotel is not directly closed to the Express gondola. However, it is closed enough to the lift located inside of the village, so accessing to the gondola wouldn&apos;t be an issue. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/ski-ga3a5c9705_1920.jpg" class="kg-image" alt="Trip to Mont Tremblant - Planning" loading="lazy" width="1920" height="1280" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/ski-ga3a5c9705_1920.jpg 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/ski-ga3a5c9705_1920.jpg 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/ski-ga3a5c9705_1920.jpg 1600w, https://www.jinhyoungkim.com/content/images/2022/03/ski-ga3a5c9705_1920.jpg 1920w" sizes="(min-width: 720px) 720px"><figcaption>Lift in the village (Image from <a href="https://pixabay.com/users/iulian_ursache-17029687/">iulian_ursache / 76 images</a> in pixabay)</figcaption></figure><p>So, our place to stay was finally set! </p><h2 id="planninglift-ticket">Planning - Lift Ticket</h2><p>I never thought the lift ticket can be the highest potion of the entire travel expense, but this was the actual case.</p><p>Here is the regular lift price that can be found from the <a href="https://www.tremblant.ca/plan/tickets-and-passes/winter-lift-tickets">official website</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Lift_Price_on_Tremblant_site.png" class="kg-image" alt="Trip to Mont Tremblant - Planning" loading="lazy" width="2000" height="652" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Lift_Price_on_Tremblant_site.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Lift_Price_on_Tremblant_site.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/03/Lift_Price_on_Tremblant_site.png 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/03/Lift_Price_on_Tremblant_site.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Lift Price on the official website</figcaption></figure><p>According to this chart, the lift price of full day regular for a family of 2 adults and 1 child per day is $306 (before tax). &#xA0;However, if you actually visit the <a href="https://reservations.tremblant.ca/ecomm/shop/calendar/2624850/en-US/?productcategoryid=117&amp;_gl=1*1ks7b9*_ga*MTczMzYzNjc2My4xNjQ1MTE0Njc4*_ga_B1YVPN56M6*MTY0NzQwNTYxNi4xMy4xLjE2NDc0MDYyNjIuMA..&amp;_ga=2.71039065.875909179.1647405617-1733636763.1645114678&amp;_gac=1.127243519.1646338135.Cj0KCQiA64GRBhCZARIsAHOLriIWXSaDWl_TAZ3skBAoxmexk2GKBzOEx1kVUsLOlF6XPYxV5CQCwnUaAqmGEALw_wcB">page</a> where you purchase the ticket, you can find that the price can be varied based on date.</p><p>For example of March 2022,</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/03/Lift_Price_in_March.png" class="kg-image" alt="Trip to Mont Tremblant - Planning" loading="lazy" width="1466" height="1082" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/03/Lift_Price_in_March.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/03/Lift_Price_in_March.png 1000w, https://www.jinhyoungkim.com/content/images/2022/03/Lift_Price_in_March.png 1466w" sizes="(min-width: 720px) 720px"><figcaption>Lift price in the purchase page</figcaption></figure><p>Moreover, there is lift ticket promotion in Mont Tremblant and check the official site frequently if you plan to purchase the ticket.</p><blockquote>For your information, Mont Tremblant does not have a night ski. All lifts stop working at 4 pm when I visited. Afternoon lift ticket is valid between 12 pm and 4 pm.</blockquote><p>In my case, &#xA0;I know I can&apos;t use three full day passes, so I planned to purchase the lift tickets as follows:</p><ul><li>March 9 - First day. Only Afternoon Ski</li><li>March 10 - Full Day </li><li>March 11 - Last day (Check out). Only Afternoon Ski</li></ul><p>Moreover, there was a promotion that I was able to purchase 1 day adult ticket for $95. I used the promotion to cover me and my wife on our second day. So the final price that I ended up paying was $838.46 (after tax).</p><p>After purchasing the lift ticket, only thing our family needed to do was to pack the luggages properly and enjoy the trip! </p><p>I&apos;ll continue posting about how my Mont Tremblant trip went and share some tips that I learned.</p><p>Thanks for reading this post!</p><p></p>]]></content:encoded></item><item><title><![CDATA[Teaching your kids to code]]></title><description><![CDATA[Teaching your kid to code might not be easy, but it definitely worth to try. In this post, I wrote about my personal story about how I started trying to teach my daughter how to code.]]></description><link>https://www.jinhyoungkim.com/m/</link><guid isPermaLink="false">62198d3a8dbcf40326d59f95</guid><category><![CDATA[Life]]></category><category><![CDATA[Teaching]]></category><category><![CDATA[Kids]]></category><category><![CDATA[Teaching kids to code]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Sun, 27 Feb 2022 05:27:56 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/girl-g5b8ae30cb_1920-min.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Before you read this post, this post is written for those who experienced the coding before. Of course, there is no such limitation of learning the coding. Any father or mother can start learning any programming language and teach their kids! Teaching is the best way to train and strengthen your knowledge.</blockquote><img src="https://www.jinhyoungkim.com/content/images/2022/02/girl-g5b8ae30cb_1920-min.jpg" alt="Teaching your kids to code"><p>&quot;Anyone can be my teacher if I can learn something from him or her&quot;</p><p>I am a huge believer of what is written above. When I was young, my dad always called my name and showed me how to fix stuffs such as broken appliances or house-related issues. When I was as tall as him , he started letting me to fix them on behalf of him and gave me advices if needed. &#xA0;</p><p>This was how I naturally learned several repair skills and am now able to fix most of (not-too-complicated) issues (Unfortunately, I couldn&apos;t be MacGyver and acknowledge when to call a professional)</p><p>The point is that my both parents have been great teachers in my life...</p><p> I have 8-years old daughter. I have been thinking what I can do for her since she was born. I have come up a couple of ideas and finally decided to teach her something. Something I am doing every day and something I have better knowledge with. Yes. teaching coding was my answer.</p><p>However, I have often heard the followings from other people:</p><ul><li>Teaching someone is hard.</li><li>Teaching kids is even harder.</li><li>Teaching your own kids is totally different level of challenge...</li></ul><p>And I agree. I finished a couple of coding classes with my daughter and I can not say that each class was a piece of cake. However, what I can tell for sure is that I enjoyed every single moment because... </p><ul><li>I got to know my daughter better in terms of finding her study habit, what makes her interested, etc.</li><li>I started looking at this coding lesson by a totally different perspective from simple knowledge transfer to something fun and enjoyable for both of us. </li><li>Finally, I am learning and reviewing my knowledge as well by preparing each class and thinking hard about how I can explain each lesson as easy as possible so that my daughter can understand. &#xA0;</li></ul><p>So, how can you start? &#xA0;The below steps are what I proceeded.</p><blockquote>Please keep in mind that this is just my personal opinions and what I tried. Every person has their own way of preparation and teaching styles, so there might be different effective approaches.</blockquote><ol><li>Choose a programming language</li></ol><p>I worked at the agency for very long time. One of advantages of working at the agency is that the programming language you need to use can be changed based on your project or client&apos;s needs. &#xA0;In other words, you have more chances to deal with different programming languages. In my case, I started with C#, but laster had chances to use other languages such as Java, Coldfusion, php and Python.</p><p>In my opinion, there is no right or wrong about picking a programming language. At the end, they all have similar concepts (variable, datatype, data structures, function, class, etc) and use different syntaxes and operators. Therefore, once you get familiar with one programming language, you should be able to learn your second or third languages without having any huge issue. &#xA0; </p><p>Therefore, I suggest two options:</p><ul><li>Choose the language that you are familiar most now</li><li>Choose the language that you want to learn. (I believe the best way to learn something new is to teach!)</li></ul><p>I chose <code>Python</code> for coding lesson because I would like to understand more deeply and also it helps my ML &amp; TensorFlow study that I started recently. Moreover, its syntax is not that complicated compared to the other language so it can be plus point for the lesson.</p><p>So, think about carefully and choose the language you like!</p><p>2.	Create Your Lesson plans</p><p>I am not a good speaker. That&apos;s why I make the note (usually use point form) even though it is short period of presentation or meeting. Similarly, this coding lesson might take up to 50 ~ 60 minutes. So I decided using one hour of my Saturday morning time for planning a lesson. I am using the <code>Notion</code> to store my lesson plans (Strongly recommend if you haven&apos;t used it!)</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Lesson_Plans.png" class="kg-image" alt="Teaching your kids to code" loading="lazy" width="2000" height="765" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Lesson_Plans.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Lesson_Plans.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Lesson_Plans.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/Lesson_Plans.png 2248w" sizes="(min-width: 720px) 720px"><figcaption>My Lesson Plan</figcaption></figure><p>When you plan your lesson, please make sure to keep your kids not to loose a focus on coding. Coding can be very difficult and boring for kids, so explain with examples your kids can be familiar with and also add some coding-related game playing times so that your kids can be entertained.</p><p>In my case, I found my daughter felt bored (she looked even sleepy) from the first lesson, so I implemented a simple number guessing game and hangman games in python and let her play those games with the reminder that she can make them eventually. I also created a simple quiz by using <code>Kahoot!</code> to review a previous lesson.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Lesson_plan_detail.png" class="kg-image" alt="Teaching your kids to code" loading="lazy" width="904" height="1026" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Lesson_plan_detail.png 600w, https://www.jinhyoungkim.com/content/images/2022/02/Lesson_plan_detail.png 904w" sizes="(min-width: 720px) 720px"><figcaption>Plan Example</figcaption></figure><p>Also, try to research any online learning site to see if there is a kids programming course and what agenda each course made. I am pretty sure it will give you the new insights in term of how your lesson might look like. I used <code>Udemy</code> as my research source.</p><p></p><p>3.	Do your first class with your kids</p><p>Like Nike&apos;s slogan, <code><strong>Just Do It</strong></code><strong> </strong></p><p>You don&apos;t need to be perfect for teaching your kids.</p><p>Make mistakes, fix them and explain to your kids how you fix. That&apos;s how I am doing it now and believe how my daughter learn naturally how to fix the mistakes as I learned how to fix the stuffs from my dad.</p><hr><p>I know this is very early stage to share what I learned and highly likely to change my proof of concept on teaching my kids constantly during the course of future lessons. But I strongly recommend trying a coding lesson with your kids. It will be definitely worth to trying and you may find yourself making great memory with your kids.</p><p></p><p>Cheers!</p>]]></content:encoded></item><item><title><![CDATA[Configure SMTP for your Ghost CMS with using Gmail]]></title><description><![CDATA[I found that email does not generate from Ghost CMS by using "forgot password" function and realized I haven't had a chance to set up any smtp configuration for the site. In this post, I'll use Gmail as an example.]]></description><link>https://www.jinhyoungkim.com/configure-smtp-for-your-ghost-cms/</link><guid isPermaLink="false">6213200938fe23581bbe5032</guid><category><![CDATA[Ghost CMS]]></category><category><![CDATA[SMTP]]></category><category><![CDATA[Gmail]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Mon, 21 Feb 2022 06:35:54 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/onlineprinters-oIpJ8koLx_s-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/onlineprinters-oIpJ8koLx_s-unsplash.jpg" alt="Configure SMTP for your Ghost CMS with using Gmail"><p>It&apos;s been almost 3 weeks since I launched this blog site. I have noticed a couple of missing pieces while I am using this AWS ec2-instance and blogging site.</p><p>Firstly, the public IP address of your ec2-instance will be changed when the instance stops or restarts. so I updated the <a href="https://www.jinhyoungkim.com/start-with-your-own-blogging-site-with-ghost-cms-aws-part-2/">post</a> so that your ec2-instance has a static public IP address by leveraging elastic IP to avoid this issue.</p><p>Secondly, I found that email does not generate from Ghost CMS by using &quot;forgot password&quot; function and realized I haven&apos;t had a chance to set up any smtp configuration for the site. That&apos;s why I make this post now. In this post, I&apos;ll use Gmail as an example.</p><ol><li>Generating App password</li></ol><p>First, go to your gmail and click your profile at top right corner. This should be either your image or initial first letter if you don&apos;t have image set up yet. You should be able to see the following button.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/gmail_account_button.png" class="kg-image" alt="Configure SMTP for your Ghost CMS with using Gmail" loading="lazy" width="550" height="116"><figcaption>Google Account button</figcaption></figure><p>Once you click this button, new tab will be appeared. Go to security.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/My-account-menu.png" class="kg-image" alt="Configure SMTP for your Ghost CMS with using Gmail" loading="lazy" width="564" height="538"><figcaption>Google Account Menu</figcaption></figure><p>Check &quot;Signing in to Google&quot; section and turn on <code>2-Step Verification</code> (This should involve checking code from your phone). Once you finish turning on 2-step verification, then click <code>App passwords</code></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Two_step_and_app_pass.png" class="kg-image" alt="Configure SMTP for your Ghost CMS with using Gmail" loading="lazy" width="1680" height="630" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Two_step_and_app_pass.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Two_step_and_app_pass.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Two_step_and_app_pass.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/Two_step_and_app_pass.png 1680w" sizes="(min-width: 720px) 720px"><figcaption>2-Step verification &amp; App passwords</figcaption></figure><p>You might need to enter the password again to proceed.</p><p>In your app passwords screen, you need to click the app dropdown list.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Select_app_and_device.png" class="kg-image" alt="Configure SMTP for your Ghost CMS with using Gmail" loading="lazy" width="990" height="162" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Select_app_and_device.png 600w, https://www.jinhyoungkim.com/content/images/2022/02/Select_app_and_device.png 990w" sizes="(min-width: 720px) 720px"><figcaption>App &amp; Device selection</figcaption></figure><p>Choose Other (custom name) option and enter your site name.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/App_name.png" class="kg-image" alt="Configure SMTP for your Ghost CMS with using Gmail" loading="lazy" width="1274" height="314" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/App_name.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/App_name.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/App_name.png 1274w" sizes="(min-width: 720px) 720px"><figcaption>Site Name</figcaption></figure><p>Click <code>Generate</code> button. You should be able to see the password in yellow box. </p><p>Don&apos;t forget to copy this password. This password is going to be your SMTP password. After you click <code>DONE</code> button, there is no way to check this password again. So, Don&apos;t lose it!</p><p>2. &#xA0;Configure SMTP for your site</p><p>Configuring SMTP in Ghost CMS is pretty straightforward.</p><ul><li>SSH into your ec2-instance that hosts your site</li><li>Go to the source directory of your site (In my case, the source directory is located at <code>/var/www/</code>)</li><li>Edit config.production.json file (Use your favourite editor such as nano, vi(m)) </li><li>Update mail configuration </li></ul><p>For Gmail,</p><pre><code>&quot;mail&quot;: {
    &quot;from&quot;: &quot;yourgmailaddress@gmail.com&quot;,
    &quot;transport&quot;: &quot;SMTP&quot;,
    &quot;options&quot;: {
      &quot;host&quot;: &quot;smtp.gmail.com&quot;,
      &quot;service&quot;: &quot;Gmail&quot;,
      &quot;port&quot;: &quot;465&quot;,
      &quot;secure&quot;: true,
      &quot;auth&quot;: {
        &quot;user&quot;: &quot;yourgmailaddress@gmail.com&quot;,
        &quot;pass&quot;: &quot;YOUR-APP-PASSWORD&quot;
      }
    }
  },</code></pre><ul><li>Restart your site</li></ul><pre><code>ghost restart</code></pre><p></p><p>Now your email in your Ghost CMS should be working fine (Test your <code>forgot password</code>!). For other email service alternatives such as Mailgun or Amazon SES, you should apply the similar approach which involves the followings:</p><ul><li>Getting SMTP endpoint</li><li>Authentication of SMTP (username &amp; password)</li><li>Update the <code>mail</code> section in <code>config.production.json</code></li><li>Restart your site</li></ul><p>Hope this post can be helpful. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[If there is a Java argument issue with Kubernetes deployment...]]></title><description><![CDATA[If YAML file is being used to create Kubernetes pods and for some reason, java arguments' values in deployment yaml file can not be retrieved from the application after deployment. This post might help you.]]></description><link>https://www.jinhyoungkim.com/java-argument-issue-in-deployment-yaml-in-kubernates/</link><guid isPermaLink="false">620efdedf780450476f7759f</guid><category><![CDATA[BugFix]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Java]]></category><category><![CDATA[Coding]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Fri, 18 Feb 2022 03:48:20 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/ihor-dvoretskyi-GCFuprAvC6A-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/ihor-dvoretskyi-GCFuprAvC6A-unsplash.jpg" alt="If there is a Java argument issue with Kubernetes deployment..."><p></p><p>Maybe this issue is &quot;NOT&quot; always happening to all Java spring boot application running on Kubernetes. </p><p>However, if YAML file is being used to create Kubernetes pods and for some reason, java arguments&apos; values in deployment yaml file can not be retrieved from the application during/after deployment. This post might help you.</p><p>Here is the example of deployment.yaml</p><pre><code>aviVersion: apps/v1
kind: Deployment
metadata:
...
...
template:
	spec:
    ...
    containers:
    - name: my-app
      image: docker.image.io/projects/my-app:12d4x3490df329dkkk5bb2v6e9e
      workingDir: /projects/my-app
      command:
      - java
      args:
      	- -jar
        - /projects/my-app/app.jar
        - -Dlogging.config=&quot;/projects/my-app/log4j2.xml&quot;
        - -DdbHost=&quot;$(DB_HOST)&quot;
        - -DdbUsername=&quot;$(DB_USERNAME)&quot;
        - -DdbPassword=&quot;$(DB_PASSWORD)&quot;
        ...
        ...</code></pre><p> </p><p>Let&apos;s assume the following arguments are originally retrieved from either application.properties or application.yaml file.</p><ul><li>dbHost</li><li>dbUsername</li><li>dbPassword</li></ul><p>From most of cases, these properties values will be different based on your environment such as Test, UAT or Prod. &#xA0;In your Kubernetes setup, they are highly likely to be encoded and placed in each env&apos;s secret file.</p><p>If you can see that</p><ul><li>property values are not getting picked up according to your value in the secret.</li><li>property values are identical through all environment (They are supposed to be different)</li></ul><p>, then check if your arguments&apos; names are matching with the corresponding the key name in its secrets files. In other words, make sure your corresponding key name in the secret.yaml file was being set correctly.</p><p>For example of these arguments, they can change as follows:</p><ul><li>dbHost -&gt; db.host since DB_USERNAME is the key name</li><li>dbUsername -&gt; db.username since DB_USERNAME is the key name</li><li>dbPassword -&gt; db.password since DB_PASSWORD is the key name</li></ul><p>Basically, &#xA0;when you create the corresponding key-value pair data in the secret files, do</p><ul><li>Change the value name to Upper Case (E.g., db.host -&gt; DB.HOST)</li><li>Replace &quot;.&quot; to &quot;_&quot; if needed (E.g. DB.HOST -&gt; DB_HOST)</li></ul><p>This should be able to resolve the issue.</p><p>Hope this is helpful. Happy Coding!</p><p> &#xA0;</p>]]></content:encoded></item><item><title><![CDATA[Useful and common git commands for newbie programmer (feat. ssh-agent)]]></title><description><![CDATA[In this post, I will cover how to start ssh-agent & add the key to get proper authentication from your Git hosting service and how to use common git commands.]]></description><link>https://www.jinhyoungkim.com/useful-commands-to-know-for-be/</link><guid isPermaLink="false">620b1a0410fadf2646c92d18</guid><category><![CDATA[Git]]></category><category><![CDATA[Coding]]></category><category><![CDATA[Github]]></category><category><![CDATA[Bitbucket]]></category><category><![CDATA[GitCommand]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Tue, 15 Feb 2022 05:21:34 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/roman-synkevych-wX2L8L-fGeA-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/roman-synkevych-wX2L8L-fGeA-unsplash.jpg" alt="Useful and common git commands for newbie programmer (feat. ssh-agent)"><p></p><p>In this post, I assume your ssh key was already registered in your git hosting service such as Github, bitbucket, etc. If you don&apos;t know how to generate a new ssh key, you can search from your favourite search engine by typing &#xA0;a search keyword like <code>github(or other alternative) generate ssh key</code></p><p>Just in case, I leave a page link for Github and Bitbucket in regards to this ssh key</p><ul><li><a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent">Github</a></li><li><a href="https://support.atlassian.com/bitbucket-cloud/docs/set-up-an-ssh-key/">BitBucket</a></li></ul><p>Ok. Let&apos;s start!</p><p>Here are some useful commands that I am personally using often on my day-to-day works. First, to avoid any authentication issue with your git hosting service, start with ssh agent.</p><ul><li>Start ssh agent </li></ul><pre><code>eval $(ssh-agent -s)</code></pre><ul><li> Add your private key</li></ul><p>Please make sure to use the private key (file <strong>without having file extension</strong> such as &quot;.pem&quot; or &quot;.ppk&quot;)</p><pre><code>ssh-add yourpathtoprivatekey</code></pre><p>For example, if your key is located under .ssh folder, then the command can be</p><pre><code>ssh-add ~/.ssh/iamprivatekey</code></pre><ul><li>Check list of keys</li></ul><pre><code>ssh-add -l</code></pre><p>If your key is successfully added, then you should not see the &quot;The agent has no identities.&quot; message</p><ul><li>Check your current branch</li></ul><pre><code>git branch</code></pre><p>This will show the list of branch you have checked out. The current working branch will have the asterisk(*) in front of a branch name (e.g. * develop)</p><ul><li>Create new branch</li></ul><p>If you need to make a code update on brand new branch, the use</p><pre><code>git checkout -b new-branch-name</code></pre><p>This will create the new branch and switch your current branch to the new branch.</p><ul><li>Switch your branch</li></ul><p>If you or your team member already create a new branch from your git hosting service and you need to switch your branch, then use this command.</p><pre><code>git fetch &amp;&amp; git checkout new-branch</code></pre><ul><li>Display the state of your working project directory</li></ul><pre><code>git status</code></pre><p>This command will show you the list of files that have been modified, but show them into three different groups: staged, non-staged, untracked. Staged files are one will be committed. &#xA0;Non-staged files are simply files that are not staged for commit yet. Untracked files are the one not being tracked by Git.</p><ul><li>Add a file for commit</li></ul><pre><code># Add your file to be staged
# Use git add yourfilepath
git add /src/main/java/com/test1/filetocommit.java

# If you want to add every file under test1 folder
git add /src/main/java/com/test1</code></pre><p>Git status command after this will allow you to see the list of staged files in green text.</p><ul><li>Unstage a file</li></ul><p>If you add a file by mistake and want to unstage, you can run</p><pre><code>git restore --staged woops-not-this-file.java</code></pre><ul><li>Discard your change of one file</li></ul><pre><code>git checkout yourfilepath/to/restore/back/to/original.java</code></pre><ul><li>Commit your changes</li></ul><p>Once you finish adding all files that you want to commit, run the following command.</p><pre><code>git commit -m &quot;Describe your changes in this double quotes, do not forget&quot;</code></pre><ul><li>Push your commit to your git repository</li></ul><pre><code>git push</code></pre><ul><li>Merge one branch to the other branch</li></ul><pre><code>#Assume your working branch is called &quot;feature-test&quot;
git merge branch-name-that-you-want-to-merge

#For example, you want to merge to develop branch
git merge develop</code></pre><p>However, merging branches wouldn&apos;t happen that often if you are working with other team members. In this case, a typical process would be as follows.</p><ol><li>Create a PR (Pull Request) from your Git hosting service</li><li>Add your team member as a reviewer</li><li>Team member review your PR and leave a feedback if needed</li><li>Team member approve your PR</li><li>Merge branch from your PR</li></ol><p></p><p>So, in this post, I covered</p><ul><li>how to start ssh-agent and add the key to get proper authentication from your Git hosting service.</li><li>how to use common git commands.</li></ul><p></p><p>Hope this can be useful for someone. Happy coding!</p>]]></content:encoded></item><item><title><![CDATA[If your Preview in Ghost admin does not work...]]></title><description><![CDATA[From your ghost admin pages, all preview page displays a blank page instead of an actual page. Try this solution.]]></description><link>https://www.jinhyoungkim.com/if-preview-from-ghost-admin-does-not-work/</link><guid isPermaLink="false">620481dc10fadf2646c92ca1</guid><category><![CDATA[BugFix]]></category><category><![CDATA[Ghost Issue]]></category><category><![CDATA[Ghost Preview]]></category><category><![CDATA[Ghost Preview Issue]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Thu, 10 Feb 2022 03:28:51 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/ghost_preview_sceeen-min.png" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/ghost_preview_sceeen-min.png" alt="If your Preview in Ghost admin does not work..."><p></p><p>Once I deployed this blog site, I realized that all Preview from Ghost page, post and design section displayed only blank page.</p><p>The reason was because my ghost config url was set to <code>https://jinhyoungkim.com</code>. However, my Nginx configuration has 301 redirect to <code>https://www.jinhyoungkim.com</code> on this url. Therefore, this redirection causes this preview issue.</p><ol><li>SSH into your host server</li><li>Go to your ghost blog source code directory</li><li>Run the following commands &#xA0; </li></ol><pre><code># Change your ghost config url to right one
ghost config url https://yourcorrectghostdomain.com

# Restart ghost
ghost restart</code></pre><p>In my case, &#xA0;I ran this command:</p><p> <code>ghost config url https://www.jinhyoungkim.com</code> </p><p>Hope this fix can be useful and resolve your issue! :) </p>]]></content:encoded></item><item><title><![CDATA[Start with your own blogging site with Ghost CMS & AWS - part 2]]></title><description><![CDATA[This post covers the way to ssh into ec2 instance, how to install ghost, domain setup and nginx 301 rediretion setup for your blog site.]]></description><link>https://www.jinhyoungkim.com/start-with-your-own-blogging-site-with-ghost-cms-aws-part-2/</link><guid isPermaLink="false">620336a93ba89502e2525337</guid><category><![CDATA[Ghost CMS]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Blog site launch]]></category><category><![CDATA[Ghost CMS on AWS]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Wed, 09 Feb 2022 08:03:47 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/Part2_MainImg.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/Part2_MainImg.jpg" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2"><p></p><p>Previously, I covered how you can create the new ec2-instance by leveraging AWS free-tier option. In this post, we will focus on the following steps.</p><ul><li>SSH into ec2-instance from your local</li><li>Install nginx, node and mysql</li><li>Install &amp; configure Ghost CMS</li><li>Set up the Domain for the site</li><li>Secure your site &amp; Update nginx configurations</li></ul><p></p><p>Before you ssh into our newly created instance, there should be a pem file in your Downloads folder that was downloaded before AWS launched the new instance.</p><p>Let&apos;s assume the key pair name was <code>test-key-pair-example</code> and open your terminal. (I&apos;m using iTerm)</p><pre><code># Go to Downloads folder
cd ~/Downloads

# Move the pem file to .ssh folder
mv test-key-pair-example.pem ~/.ssh

# Change the permission of the pem file
chmod 400 ~/.ssh/test-key-pair-example.pem
</code></pre><p></p><ol><li>SSH into EC2-instance from your local</li></ol><p>Now, go to your AWS console -&gt; EC2 -&gt; Instances and select the ec2-instance you created. It will show the detail information of your instance. Copy the value under <code>Public IPv4 DNS</code> by clicking the icon in the red circle below.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Public_IPv4_DNS.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1652" height="342" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Public_IPv4_DNS.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Public_IPv4_DNS.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Public_IPv4_DNS.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/Public_IPv4_DNS.png 1652w" sizes="(min-width: 720px) 720px"><figcaption>Getting Public DNS</figcaption></figure><p>(You can also click &quot;Connect&quot; button and go to &quot;SSH client&quot; tab to get this public DNS information.)</p><p>Once you finish copying your public DNS value, go back to your terminal and run the following command.</p><pre><code># Let&apos;s ssh into the ec2-instance!
ssh -i ~/.ssh/test-key-pair-example.pem ubuntu@YourPublicDNS.com

#Example
ssh -i ~/.ssh/test-key-pair-example.pem ubuntu@ec2-22-11-43-31.compute-1.amazonaws.com</code></pre><p>If you see &quot;Are you sure you want to continue connecting (yes/no...)&quot; message, type &quot;yes&quot;. Now you should be able to ssh into the instance successfully.</p><p></p><p>2. Install NGINX, NODE and MYSQL</p><p>You can keep using <code>ubuntu</code> as a user, but don&apos;t forget to use <code>sudo</code> in front of following command.</p><p>Let&apos;s start with upgrading packages. Type &quot;y&quot; if &#xA0;system asks a permission to proceed after you execute each command.</p><pre><code># Update packages
sudo apt-get update

# Update installed packages
sudo apt-get upgrade</code></pre><p> It&apos;s time to install Nginx. Nginx is a server to serve your ghost CMS via port 80 (HTTP) and 442 (HTTPS).</p><pre><code># Install Nginx
sudo apt-get install nginx

# Make firewall allow HTTP and HTTPS connection
sudo ufw allow &apos;Nginx Full&apos;</code></pre><p>For node installation, ghost supports the following versions.</p><ul><li>12.x</li><li>14.x</li><li>16.x</li></ul><p>Since 14.x is the recommended version, we will use version 14 as our node version.</p><pre><code># Add NodeSource APT repository for Node 14
curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash

# Install Node
sudo apt-get install -y nodejs</code></pre><p>Ghost CMS needs the database to store the data. &#xA0;Let&apos;s install MySQL server.</p><pre><code># Install MySQL
sudo apt-get install mysql-server</code></pre><p>After installing MySQL server, you need to set a password of <code>root</code> db user.</p><pre><code># Access MySQL
sudo mysql

# Update the password of 
ALTER USER &apos;root&apos;@&apos;localhost&apos; IDENTIFIED WITH mysql_native_password BY &apos;yourpasswordhere&apos;;

# Exit MySQL
quit</code></pre><p>*Note: &#xA0;This root password will be used during ghost installation.</p><p>3. Install &amp; configure Ghost CMS</p><p>In order to create the new Ghost CMS, Ghost-CLI (commandline tool) is mandatory.</p><pre><code># Install Ghost-CLI
sudo npm install ghost-cli@latest -g

# Create a directory where the source code of Ghost CMS will be located at. I put &quot;ghostblog&quot; as my site name, but you can put any name instead of &quot;ghostblog&quot; here.

sudo mkdir -p /var/www/ghostblog

# Set ubuntu as user and group permission on this direcotry
sudo chown ubuntu:ubuntu /var/www/ghostblog

# Set correct directory permission 
sudo chmod 775 /var/www/ghostblog

# Go to the directory
cd /var/www/ghostblog</code></pre><p>Ok. &#xA0;Now it&apos;s finally time to install GhostCMS. &#xA0;Run the following command.</p><pre><code>ghost install</code></pre><p>This might take some time and start asking several questions. &#xA0;Before answering them, let&apos;s set up our domain.</p><p>4. &#xA0;Set up the Domain for the site</p><p>As I mentioned in part1, I&apos;ll use &quot;Godaddy&quot; &#xA0;as a domain service provider where I purchase a domain. However, you should be able to follow the similar steps described below to your domain service provider. &#xA0;</p><p>First, from your AWS console, search &quot;route 53&quot; &#xA0;and click the link from the search result.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Route53.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1240" height="420" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Route53.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Route53.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Route53.png 1240w" sizes="(min-width: 720px) 720px"><figcaption>Route 53 from search result</figcaption></figure><p>Go to &quot;Hosted zones&quot; from left menu and click &quot;Create hosted zone&quot; button.</p><p>Double check your domain name and enter the name in Domain name text field. You can leave the Type as &quot;Public hosted zone&quot;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/create_hosted_zone.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1558" height="1106" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/create_hosted_zone.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/create_hosted_zone.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/create_hosted_zone.png 1558w" sizes="(min-width: 720px) 720px"><figcaption>Hosted Zone Creation</figcaption></figure><p>Click &quot;Create hosted zone&quot; button. Once your domain hosted zone is created, you can see the NS record in the list.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/hosted_zone_ns_record.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1564" height="660" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/hosted_zone_ns_record.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/hosted_zone_ns_record.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/hosted_zone_ns_record.png 1564w" sizes="(min-width: 720px) 720px"><figcaption>NS Record</figcaption></figure><p>There should be 4 values for your NS record. We need to access the domain service provider and replace NS record values.</p><p>From Godaddy, follow the steps below.</p><ul><li>Log in</li><li>Click your user name on top right corner </li><li>Go to &quot;My Products&quot;</li><li>Find the domain name under &quot;All Product and Services&quot; section.</li><li>Click DNS button.</li><li>In Nameservers section, click &quot;Change&quot; button.</li><li>Select &quot;Enter my own nameservers (advanced)&quot; link.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/enter_my_own_nameserver_link.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="740" height="188" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/enter_my_own_nameserver_link.png 600w, https://www.jinhyoungkim.com/content/images/2022/02/enter_my_own_nameserver_link.png 740w" sizes="(min-width: 720px) 720px"><figcaption>Enter my own nameservers link</figcaption></figure><ul><li>Please make sure each NS record value does not end with a dot (When you copy the value, do not include the dot at the end)</li><li>Copy all 4 NS values in each name server from Route 53 to text fields in Godaddy&apos;s &quot;Edit Nameservers&quot; popup modal. (You might need to use &quot;Add Nameserver&quot; to have more text fields)</li><li>Click &quot;Save&quot; button.</li></ul><p>Ok. Now we need to create a couple of A records in the route 53. &#xA0;Before we go back to route 53, &#xA0;we need to grab a public IP address of the ec2-instance. </p><p>However, there is one additional step to do before we just copy the public IP address. Since we&apos;re using the free-tier instance, this public IP address will be changed every time this ec2-instance stops or restarts. To prevent this IP address from changing, you need to use the static IP address and associate to the ec2-instance. </p><p>In order to create this static IP address, go to EC2 -&gt; Elastic IPs under Network &amp; Security from left menu.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Elastic-IPs-menu.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="332" height="382"><figcaption>Elastic IPs Menu</figcaption></figure><p>In Elastic IPs page, click <code>Allocate Elastic IP address</code> button located at the top right corner of the screen.</p><p>Leave the default options and click <code>Allocate</code> button. There should be new IP record available on your Elastic IP address list. </p><p>Click the checkbox of the record -&gt; Actions -&gt; Associate Elastic IP address.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_menu.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="2000" height="331" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Associate_Elastic_IP_address_menu.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Associate_Elastic_IP_address_menu.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Associate_Elastic_IP_address_menu.png 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/02/Associate_Elastic_IP_address_menu.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>Associate Elastic IP address menu</figcaption></figure><p>In &quot;Associate Elastic IP address&quot; page, choose your ec2-instance in <code>instance</code> textbox. Once you choose it and click <code>Private IP address</code> textbox, then private IP address of the selected ec2-instance will be automatically shown up. Make sure you choose the IP address.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page-2.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1568" height="860" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Associate_Elastic_IP_address_page-2.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Associate_Elastic_IP_address_page-2.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page-2.png 1568w" sizes="(min-width: 720px) 720px"><figcaption>Associate Elastic IP address page</figcaption></figure><p>Tick the <code>Reassociation</code> checkbox if you want your Elastic IP address to be able to reassociated with other resource.</p><p>Click <code>Associate</code> button. </p><p>That&apos;s it. Now your ec2-instance has static public IP address!</p><p>Go to EC2 -&gt; Instances. You can notice your public IP address has been changed to the elastic IP address you had above. Copy Public IP address under &quot;Public IPv4 address&quot;</p><figure class="kg-card kg-image-card"><img src="https://www.jinhyoungkim.com/content/images/2022/02/public_ip.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1652" height="342" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/public_ip.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/public_ip.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/public_ip.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/public_ip.png 1652w" sizes="(min-width: 720px) 720px"></figure><p> Go back to Route 53 -&gt; hosted zones -&gt; Click your domain name. </p><p>Click &quot;Create Record&quot; button (Make sure you create two records) and following values.</p><p>For first record,</p><ul><li>Record name: leave as it is (empty)</li><li>Record type: A - Routes traffic...</li><li>Value: Public IP address you just copied from your ec2 instance detail page</li></ul><p>For second record,</p><ul><li>Record name: www</li><li>Record type: A - Routes traffic...</li><li>Value: Public IP address</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/a_record_creation.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="2000" height="529" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/a_record_creation.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/a_record_creation.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/a_record_creation.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/a_record_creation.png 2148w" sizes="(min-width: 720px) 720px"><figcaption>A Record Creation</figcaption></figure><p>Now your domain is all set for your ec2-instance.</p><p>5. Ghost Installation (Continue...)</p><p>Once you go back to your terminal where you executed <code>ghost install</code> command, the installation is on hold and asking the following questions. </p><ul><li>Enter your blog URL: http://yourghostdomain.com</li><li>Enter your MySQL hostname: localhost</li><li>Enter your MySQL username: root</li><li>Enter your MySQL password: Your root user password (Please refer to mysql server installation in Section 2)</li><li>Enter your Ghost database name: &#xA0;Any name should be fine. The default name is your site folder name + &quot;_prod&quot;. So in our case, &quot;ghostblog_prod&quot; is the default name.</li><li>Do you wish to set up &quot;ghost&quot; mysql user? : Y</li><li>Do you wish to set up Nginx?: Y</li><li>Do you wish to set up SSL? Y</li><li>Enter your email (For SSL Certificate): Your email address </li><li>Do you wish to set up Systemd?: Y</li><li>Do you want to start Ghost? Y</li></ul><p>Once you input all answers, the following message will be displayed. </p><pre><code>Ghost was installed successfully! To complete setup of your publication, visit:

http://yourghostdomain.com/ghost/</code></pre><p>Copy the url and paste it in your browser. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/welcome_to_ghost_page.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1036" height="1188" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/welcome_to_ghost_page.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/welcome_to_ghost_page.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/welcome_to_ghost_page.png 1036w" sizes="(min-width: 720px) 720px"><figcaption>Welcome Ghost Page</figcaption></figure><p>Click &quot;Create your account&quot; button. Enter the following information and click &quot;Last step: Invite staff users &gt;&quot; button.</p><ul><li>Site title</li><li>Full name</li><li>Email address</li><li>Password</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/create_your_account.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="898" height="1266" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/create_your_account.png 600w, https://www.jinhyoungkim.com/content/images/2022/02/create_your_account.png 898w" sizes="(min-width: 720px) 720px"><figcaption>Create Your Account Page</figcaption></figure><p>You can invite person who can help manage your site by providing an email address. Otherwise, click &quot;I&apos;ll do this later...&quot; link.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/invite_staff_users.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="868" height="580" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/invite_staff_users.png 600w, https://www.jinhyoungkim.com/content/images/2022/02/invite_staff_users.png 868w" sizes="(min-width: 720px) 720px"><figcaption>Invite staff users page</figcaption></figure><p>Well done. Your ghost site should be up and running properly. There is only one more step to go: Securing your website.</p><p>6. Secure your site &amp; Update nginx configurations</p><p>Go back to your terminal and make sure you&apos;re on the site root directory.</p><pre><code># Check your current path
pwd

# If you are not on the site root directory
cd /var/www/ghostblog

# add www domain with https
ghost config url https://www.yourghostdomain.com

# Create additional Nginx config files for www
ghost setup nginx ssl
</code></pre><p>After the last command is run, system will ask your email address again. Enter your email address and restart the ghost</p><pre><code># Restart Ghost CMS
ghost restart</code></pre><p>Next, we will update our nginx configuration files to make 301 redirection to cover the following cases:</p><ul><li>http://yourghostdomain.com -&gt; https://www.yourghostdomain.com</li><li>http://www.yourghostdomain.com -&gt; https://www.yourghostdomain.com</li><li>https://yourghostdomain.com -&gt; https://www.yourghostdomain.com</li></ul><pre><code># Go to Nginx conf folder
cd /etc/nginx/sites-enabled</code></pre><p>There should be 5 conf files.</p><ul><li>default</li><li>yourghostdomain.com.conf</li><li>yourghostdomain.com-ssl.conf</li><li>www.yourghostdomain.com.conf</li><li>www.yourghostdomain.com-ssl.conf</li></ul><p>However, we&apos;re going to add 301 redirection rule to the following conf files only:</p><pre><code># Copy this 301 redirection command

return 301 https://www.yourghostdomain.com$request_uri;</code></pre><ul><li>yourghostdomain.com.conf</li><li>yourghostdomain.com-ssl.conf</li><li>www.yourghostdomain.com.conf</li></ul><pre><code># Copy the following 
# Edit yourghostdomain.com.conf

sudo vi yourghostdomain.com.conf

# Move the cursor to right next &quot;proxy_pass&quot;
# type i &lt;- This will change vi editor to be insert mode
paste your 301 redirection rule here

# Hit ESC
:wq</code></pre><p>Repeat this process to yourghostdomain.com-ssl.conf and www.yourghostdomain.com.conf as well.</p><p>*Note: DO NOT ADD this to www.yourghostdomain.com-ssl.conf file.</p><p><br>For your information, &#xA0;the part of your nginx configuration looks similar to this.</p><pre><code>location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:2368;

        return 301 https://www.yourghostdomain.com$request_uri;
    }</code></pre><p>Last but not least restart the nginx!</p><pre><code>sudo systemctl nginx restart</code></pre><p></p><figure class="kg-card kg-image-card"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1568" height="860" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Associate_Elastic_IP_address_page.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Associate_Elastic_IP_address_page.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page.png 1568w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page-1.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 2" loading="lazy" width="1568" height="860" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Associate_Elastic_IP_address_page-1.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Associate_Elastic_IP_address_page-1.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Associate_Elastic_IP_address_page-1.png 1568w" sizes="(min-width: 720px) 720px"></figure><p>Well done! Your Ghost blogging site should be up and running with HTTPS. Happy Blogging!</p>]]></content:encoded></item><item><title><![CDATA[Start with your own blogging site with Ghost CMS & AWS - part 1]]></title><description><![CDATA[This post covers the steps to create an ec2-instance by leveraging AWS's free-tier option. Ghost CMS will eventually be hosted on this instance.   ]]></description><link>https://www.jinhyoungkim.com/start-with-your-own-blogging-site-with-ghost-cms-part-1/</link><guid isPermaLink="false">6201a6323ba89502e2525055</guid><category><![CDATA[Ghost CMS]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Ghost CMS on AWS]]></category><category><![CDATA[Blog site launch]]></category><dc:creator><![CDATA[JinHyoung Kim]]></dc:creator><pubDate>Tue, 08 Feb 2022 02:56:21 GMT</pubDate><media:content url="https://www.jinhyoungkim.com/content/images/2022/02/GhostCMS-Part1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://www.jinhyoungkim.com/content/images/2022/02/GhostCMS-Part1.jpg" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1"><p>This is a step-by-step guideline that I followed when I deployed my blogging site. For your information, I am using macOS. </p><p></p><p> There are many options where you can start your blogging site with Ghost CMS. Initially, I looked into the following options:</p><ul><li>Ghost Pro</li><li>Digital Ocean + Ghost CMS Installation</li><li>GCP (Google Cloud Platform) &#xA0;+ Ghost CMS Installation</li><li>AWS &#xA0;+ Ghost CMS Installation</li></ul><p>Obviously, starting with Ghost Pro is easiest and quickest way to launch your site. However, I decided going with AWS option. The main reason is simply because I am more familiar with AWS platform. Moreover, leveraging free-tier gives me flexibilities of experimenting this platform and a chance to save money initially. (Just FYI, GCP also provide $300 in free credit for new customer and free-tier as well).</p><p>Before you proceed, please make sure that</p><ul><li>Domain is purchased and ready to use (I will use Godaddy for this guildeline)</li><li><a href="https://aws.amazon.com/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc&amp;awsf.Free%20Tier%20Types=*all&amp;awsf.Free%20Tier%20Categories=*all">AWS account creation</a> is already completed</li></ul><hr><ol><li>Finding EC2 </li></ol><p>Once you log into AWS console successfully, type <code>ec2</code> in the search bar and click the &quot;EC2&quot; in the Services section of result panel.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Screen-Shot-2022-02-07-at-7.49.21-PM.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="2000" height="580" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Screen-Shot-2022-02-07-at-7.49.21-PM.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Screen-Shot-2022-02-07-at-7.49.21-PM.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Screen-Shot-2022-02-07-at-7.49.21-PM.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/Screen-Shot-2022-02-07-at-7.49.21-PM.png 2102w" sizes="(min-width: 720px) 720px"><figcaption>Searching EC2</figcaption></figure><p>In either Instances page or Dashboard page, find the orange button called &quot;Launch Instance&quot; and click it.</p><p>2. Choose an AMI (Amazon Machine Image)</p><p>Find Ubuntu Server 20.04 LTS (You can choose 18.04 LTS if you want) and click &quot;Select&quot; button. If you are having a trouble with finding it, you can click the checkbox &quot;Free tier only&quot; to filter the AMI list to show only eligible free tier.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Choose_AMI.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="2000" height="985" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Choose_AMI.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Choose_AMI.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Choose_AMI.png 1600w, https://www.jinhyoungkim.com/content/images/size/w2400/2022/02/Choose_AMI.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>AMI List</figcaption></figure><p>3. Choose an Instance Type</p><p><code>t2.micro</code> should already be pre-selected. Please make sure you can see &quot;Free tier eligible&quot; with green highlighted box. Click &quot;Next:Configure Instance Details&quot; button.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Choose_Instance_type.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="1526" height="644" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Choose_Instance_type.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Choose_Instance_type.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Choose_Instance_type.png 1526w" sizes="(min-width: 720px) 720px"><figcaption>EC2 Instance Type</figcaption></figure><p>4. Configure Instance Details.</p><p>Nothing needs to change in this page. Click &quot;Next: Add Storage&quot; button.</p><p>5. Add Storage</p><p>Free tier can cover up to 30 GB, so you can leave the size as default (8 GB) or upgrade the size up to 30. In my case, I didn&apos;t change the size. Click &quot;Next: Add Tags&quot; button.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Add_storage.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="1302" height="432" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Add_storage.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Add_storage.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/Add_storage.png 1302w" sizes="(min-width: 720px) 720px"><figcaption>EC2 Storage size</figcaption></figure><p>6. Add Tags</p><p>No need to add Tag. Click &quot;Next: Configure Security Group&quot;</p><p>7. Configure Security Group</p><p>SSH rule should exist in the list. Check &quot;Source&quot; column and change the dropdown list from &quot;Custom&quot; to &quot;My IP&quot;. AWS automatically detects your IP address and fills out the textbox with your IP. &#xA0;This basically whitelist your IP address so that you can ssh into this ec2-instance with your pem key file later.</p><p>Click &quot;Add Rule&quot; button to add <code>HTTP</code> and <code>HTTPS</code>.</p><p>For HTTP,</p><ul><li>Type: HTTP</li><li>Port: 80</li><li>Source: Anywhere</li></ul><p>For HTTPS,</p><ul><li>Type:HTTPS</li><li>Port: 443</li><li>Source: Anywhere</li></ul><p>This eventually makes HTTP and HTTPS publicly accessible.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/Configure_security_group.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="2000" height="292" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/Configure_security_group.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/Configure_security_group.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/Configure_security_group.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/Configure_security_group.png 2222w" sizes="(min-width: 720px) 720px"><figcaption>Configuring Security Group</figcaption></figure><p>Click &quot;Review and Launch&quot; button.</p><p>8. Review Instance Launch</p><p>Review the detail information of your instance once more time and click &quot;Launch&quot; button.</p><p><strong>Note:</strong> Under security group, there should be total 5 protocols which are 1 ssh, 2 HTTP and 2 HTTPS.</p><p>9. Key Pair setup</p><p>There are two options:</p><ul><li>Using an existing key pair: Choose this option if you already created the key pair before and want to use it to ssh into this newly created ec2-instance.</li><li>Creating a new key pair: Choose this option to create brand new key pair. Select &quot;RSA&quot; and provide key pair name and click download.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/key_pair_setup.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="1404" height="1128" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/key_pair_setup.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/key_pair_setup.png 1000w, https://www.jinhyoungkim.com/content/images/2022/02/key_pair_setup.png 1404w" sizes="(min-width: 720px) 720px"><figcaption>Key pair</figcaption></figure><p>Once you download the key, the &quot;Launch Instance&quot; button should be enabled. Click the button. &#xA0;Launch Status screen will be appeared. Click view instances button.</p><p>10. Verify and confirm the instance</p><p>The new instance should be on the instance list without having any name. You can add the name by moving your mouse over on the empty name column and click the edit icon. Provide the name and save it. </p><p>Next, check Instance state column and Status check column. They should have &quot;Running&quot; and &quot;2/2 checks passed&quot; values respectively.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://www.jinhyoungkim.com/content/images/2022/02/ec2-instance-list.png" class="kg-image" alt="Start with your own blogging site with Ghost CMS &amp; AWS - part 1" loading="lazy" width="2000" height="138" srcset="https://www.jinhyoungkim.com/content/images/size/w600/2022/02/ec2-instance-list.png 600w, https://www.jinhyoungkim.com/content/images/size/w1000/2022/02/ec2-instance-list.png 1000w, https://www.jinhyoungkim.com/content/images/size/w1600/2022/02/ec2-instance-list.png 1600w, https://www.jinhyoungkim.com/content/images/2022/02/ec2-instance-list.png 2230w" sizes="(min-width: 720px) 720px"><figcaption>EC2 instance list</figcaption></figure><p>Awesome! Now your ec2-instance is ready to install Ghost CMS. </p><p>In Part2, I will cover the following topics:</p><ul><li>SSH into ec2-instance from your local</li><li>Install nginx, node and mysql</li><li>Install &amp; configure Ghost CMS</li><li>Set up the Domain for the site</li><li>Update nginx configurations</li></ul><p>Thanks for reading this post!</p>]]></content:encoded></item></channel></rss>