Oracle Cloud Infrastructure Foundations 2021 Certified Associate

I studied for Oracle Cloud Infrastructure Foundation Certified Associate and took the exam today. I passed it!

This is a basic knowledge check for Oracle Cloud Infrastructure, so it wasn’t too hard. I did spend time to study for it though. There were some information I wish I had known a while ago… Oracle offers good study resources on their site.

Certification doesn’t determine your skill level but it’s good to go over it because there are pieces of information that you never come across through your daily work.

I will continue to go for a few more certifications as time allows.

How to Start a Local Git Repo and Upload it to GitHub

You start to write code locally in a directory and you want to keep track on file changes in a Git database and then upload (push) it to GitHub.

You have some files already in a directory and you start a Git repo locally by executing git init.

Now stage it and commit it.

git add .

git commit -m 'initial commit'

Once you create a repo on GitHub, you have a link to the GitHub repo in the page. Using that SSH repo link, you can push it to GitHub.

Now configure the remote repo in local Git database.

git remote add origin

And then, push it to the upstream repo.

git push --set-upstream origin master

You won’t need --setup-upstream origin master from the subsequent pushes.

AWS Workspaces Cost

I tried AWS Workspaces for a few days and the cost so far is the following.

$5.67 in just 3 days… The cost per month would be about $56.7. When I provisioned a Windows host, it said “Free Eligible”. I’m probably not understanding what’s costing me but that’s misleading to me.

So if that’s the cost I am going to have to bear, I am removing the workspace. Sorry Amazon, this is no go for me.

Amazon Workspaces

AWS has a feature called Workspaces. You can have Windows desktop on AWS cloud for relatively cheap price. I just provisioned one that says “Free Eligible” so I don’t know exactly how much it costs (AWS always has something to charge…) so I will see how it goes in the next few weeks and I’ll report the cost here.

It’s really nice to have a desktop on Cloud in a sense that I don’t have to manage hardware. That said, I am not sure if it can be used as my development machine because the free tier spec is quite weak.

Here is the spec of the virtual desktop.

  • 1 CPU (at 2.5 GHz)
  • Memory: 4GB
  • Diskspace: 80GB+40GB

How to Generate Free SSL by Let’s Encrypt

I attempted to use Certbot by Let’s Encrypt for free SSL certificate for my subdomain using a Docker container but it was never successful, so I left it alone for a while. The DNS service that I use provides SSL certs but it charges me extra for subdomain. There are other services such as SSL for Free but they either limit the number of certificates or they charge for subdomains or they want me to pay like $10 per month for wildcard certificate. That’s pretty steep considering the host is being used only privately. The alternative is to create your own private CA authority and issue SSL cert and have the root CA cert on the machines that you use the hosts.

But this morning, I figured out a way to generate the free SSL cert for my subdomain using Certbot. I will write about what worked for me.

I followed this instruction to install snapd on Ubuntu.

First, remove certbot if installed by apt.

sudo apt-get remove certbot

Install Certbot.

sudo snap install --classic certbot

Prepare the Certbot command.

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Now prepare your NGINX server to accept HTTP traffic for acme challenge.

Edit nginx.conf to accept HTTP (port 80).

   server {
      location / {
          root   /var/www/html;
          index  index.html index.htm;
      listen       80 default_server;
      listen       [::]:80 default_server;
      server_name  _;

If you have the HTTP redirect to HTTPS, uncomment the line.

# return 301$request_uri;

Now back to Certbot, execute the following command to start to issue your ssl cert.

sudo certbot certonly -a manual --rsa-key-size 4096 --email -d

You will see an output like the following.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Create a file containing just this data:


And make it available on your web server at this URL:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Now you should create the file with the data specified in the output. Once you have that hit Enter to get the cert generated.

Lastly, when the cert generation is successful, you will see the output like the following.

Now switch to the root user by executing…

sudo -i

The cert files are at /etc/letsencrypt/archive/

Copy cert1.pem and privkey1.pem to the directory where you would like to store your SSL files. In my ssl.conf file, I have specified the cert files like the following.

server {
    listen 443 ssl;
    ssl_certificate /etc/nginx/conf.d/ssl/cert1.pem;
    ssl_certificate_key /etc/nginx/conf.d/ssl/privkey1.pem;
    client_max_body_size 3000m;

Now unc0mment the line in ssl.conf to redirect HTTP to HTTPS traffic. Once you restart your NGINX, NGINX starts to service the traffic in SSL.

I’m sure there are ways to automate this and I am thinking of exploring the way to do it but it works well for now.

Surface Pro 7 is Back

I had my Surface Pro 7 being repaired (replaced) and it had been away from me for about a month. It had come back to me in about 2 weeks when I first sent it back to Microsoft but the one that came back to me was a faulty one. I had to send it back to Microsoft again to get a replacement again. Not having my personal laptop made me feel somewhat crippled but it finally came back to me yesterday.

This time, things are working as expected. It will take some time for me to get back the software I usually use and set it up to the usable state.

Now that Windows 11 has been released officially, I have upgraded the OS to Windows 11.

How to Make Linux Jenkins Slave a Daemon

I wrote an article on creating a Jenkins slave on Linux. The method was to just create a bash script file that requires to be executed by hand. And it wouldn’t survive restarting the host, so what I need to do is to make the script a daemon (service).

Here is what I did before configuring the daemon.

  1. Provision a Ubuntu host on Azure (it doesn’t matter where you provision the host as long as your Jenkins master on the public Internet and secured).
  2. Update the system. (sudo apt update && sudo apt upgrade)
  3. Install OpenJDK. (sudo apt install openjdk-11-jre-headless)
  4. Open port 50000 (Inboud and Outbound) to the host. I am opening all protocols.

Creating a Daemon

We will create a script at home directory first. To contain everything for Jenkins slave, I am creating /home/azureuser/jenkins-slave directory. You can create jenkins-slave or whatever the directory name you would like anywhere.

Then create in /home/azureuser/jenkins-slave directory with the following content. Change the URL and the secret acccording to the Jenkins node you have created on Jenkins master. Make the script executable by executing chmod +x

java -jar agent.jar -jnlpUrl -secret 136fa14dcc4013727e24c9f1a9b84127d7c7ca0cfa15e22c1e1d4e0140122529 -workDir "./slave"
exit 0

Also make sure you download agent.jar from Jenkins master to /home/azureuser/jenkins-slave directory. Also user opessl and keytool to trust the SSL cert. You can refer to the previous blog article on how to use keytool.

Now create /etc/systemd/system/jenkins-slave.service file with the following content. sudo vim /etc/systemd/system/jenkins-slave.service


ExecStart=/bin/bash /home/azureuser/jenkins-slave/


Enable the daemon with the following command.

sudo systemctl enable jenkins-slave.service

Now start the daemon with the following command.

sudo systemctl start jenkins-slave.service

Check the status of it.

sudo systemctl status jenkins-slave.service


● jenkins-slave.service - JenkinsSlave
     Loaded: loaded (/etc/systemd/system/jenkins-slave.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2021-10-22 22:10:03 UTC; 8min ago
   Main PID: 14698 (bash)
      Tasks: 19 (limit: 486)
     Memory: 103.3M
     CGroup: /system.slice/jenkins-slave.service
             ├─14698 /bin/bash /home/azureuser/jenkins-slave/
             └─14699 java -jar agent.jar -jnlpUrl -secret 136fa14dcc40>

Oct 22 22:10:05 jenkins-slave bash[14699]: Oct 22, 2021 10:10:05 PM hudson.remoting.jnlp.Main$CuiListener status
Oct 22 22:10:05 jenkins-slave bash[14699]: INFO: Handshaking
Oct 22 22:10:05 jenkins-slave bash[14699]: Oct 22, 2021 10:10:05 PM hudson.remoting.jnlp.Main$CuiListener status
Oct 22 22:10:05 jenkins-slave bash[14699]: INFO: Connecting to
Oct 22 22:10:05 jenkins-slave bash[14699]: Oct 22, 2021 10:10:05 PM hudson.remoting.jnlp.Main$CuiListener status
Oct 22 22:10:05 jenkins-slave bash[14699]: INFO: Trying protocol: JNLP4-connect
Oct 22 22:10:06 jenkins-slave bash[14699]: Oct 22, 2021 10:10:06 PM hudson.remoting.jnlp.Main$CuiListener status
Oct 22 22:10:06 jenkins-slave bash[14699]: INFO: Remote identity confirmed: da:ca:7a:5a:1e:ac:df:56:81:96:8a:d7:71:d9:5e:4c
Oct 22 22:10:06 jenkins-slave bash[14699]: Oct 22, 2021 10:10:06 PM hudson.remoting.jnlp.Main$CuiListener status
Oct 22 22:10:06 jenkins-slave bash[14699]: INFO: Connected

When the connection is established to the Jenkins master, here is what it looks like.

With this method, it survives restarting the host.

If you try to list the services on the host with the following command, you will see the item in the list.

sudo systemctl list-units --type=service

How to Create Jenkins Slave on Linux

Most of the articles I find on creating a permanent Jenkins slave on Linux requires the slave node to be exposed to public Internet. I want the Linux slave to be pinging Jenkins master just like Windows service. Here is the way I came up with.

Install Prerequisites

  • Java (sudo dnf install java-11-openjdk.x86_64)
    • Check if the Java has been installed. (java -version)
openjdk version "11.0.12" 2021-07-20 LTS
OpenJDK Runtime Environment 18.9 (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.12+7-LTS, mixed mode, sharing)

Add a Permanent Node

Login to Jenkins master and click Manage Jenkins -> Manage Nodes and Clouds. Click New Node. And then give the node a name (like linux-node), select Permanent Agent and click OK.

And then, click Save button. If you navigate to the node that you just created, you should see something like…

We will take copy this line.

java -jar agent.jar -jnlpUrl -secret 136fa14dcc4013727e24c9f1a9b84127d7c7ca0cfa15e22c1e1d4e0140122529 -workDir ""

Now, we’ll have to download agent.jar from the Jenkins master and upload the file to the slave machine. Just click on the agent.jar link to download it.

I have the agent.jar file in Downloads directory, so here is the command to upload the agent.jar file to the slave machine.

scp ./Downloads/agent.jar hiriumi@

Now, ssh into the slave machine.

ssh hiriumi@

Trust SSL Certificate

If your Jenkins master has SSL implemented, it’s a good practice to trust the SSL certificate. Here is how you can download the certificate on your slave machine.

openssl s_client -showcerts -connect < /dev/null | openssl x509 -outform DER >

Now use keytool to trust it.

sudo keytool -trustcacerts \
-keystore "/etc/java/java-11-openjdk/java-11-openjdk-" \
-storepass changeit -alias jenkins -import -file \

Create a Script File and Execute

Paste the Java command you get from the node page in to

java -jar agent.jar \
-jnlpUrl \
-secret 136fa14dcc4013727e24c9f1a9b84127d7c7ca0cfa15e22c1e1d4e0140122529 -workDir "./slave"

Make sure is executable by adding execute flag on the file.

chmod +x

If you execute the file, it starts to communicate with the Jenkins master and starts to serve as one of the Jenkins slave.


Once the connection is successful, you will see something like the following.

Now, this method does not survive restarting the slave machine. Now that the communication is successful, I will look into making this script a daemon.

Where Cloud Makes Sense

There are some Cloud providers out there. AWS by Amazon being one of the most famous one. There is Azure by Microsoft and there is OCI (Oracle Cloud Infrastructure) by Oracle. Cloud is nothing but computers on the other side of the Internet is what I used to think, but it’s a lot more.

I mean imagine a situation where you want to run a high demanded service? You would have to hire bunch of experienced engineers, invest in infrastructure, compute resources and then you have to design networking, how applications can be deployed, and how they can be monitored… It is not hard to imagine the amount of money that you would have to spend up front is big.

And the service your company have may experience big spike by holiday season demand but other times, not so much. If you host your application on-premise, the money you need to invest is big throughout the year.

However, if you do it on Cloud, you spend pretty much nothing up front. You can scale up your infrastructure depending on the load but you can terminate the resources that you don’t use other times. I think Cloud can save you so much.

Plus, Cloud providers does hardware maintenance for you. If an SSD fails, they replace it for you at no cost. They are specialized in it. And they keep adding services so that you can use them.

When you think about the infrastructure that they have, it could cost you hundreds of millions of dollars if not a billion. I heard that the initial investment that Larry Ellison did for Oracle Cloud Infrastructure was around 2 billion dollars.

Imagine your company has to pay that much money up front to create your own Cloud? I mean, paying 2 billion dollars doesn’t mean you are gonna get good scalable Cloud. You have to have the right engineers at the right place.

The more I learn about Cloud, the more I believe in it and it amazes me how it can change the IT world.