Deploy and securely expose your App on a free Virtual Machine

Introduction

You’re looking for an easy way to deploy your application and expose it to the web?
Here is an step-by-step guide on how to create your own ‘always-free’ virtual machine and how to deploy a container and even expose it securely via https.
The technologies we’re about to use are:
  • Oracle Cloud with an Oracle Linux Arm VM
  • Docker for the container
  • Angular (you can use any static html files)
  • Caddy as web server

First step: Get your personal domain

To enable a secure connection you’ll have to get your own domain. This is the only part of this post, where you probably have to pay. But don’t worry, it’s only about 10$/year.
I used Google Domains, but feel free to use any other provider. The entry should be of Type A.

Create your own Oracle virtual machine

First you need to create an Account.
With the Oracle Cloud free tier, there are quite a few possibilities to use, from databases to load balancers and so on.We’ll only be using the VM instance.
 
After you signed in you’ll probably see the ‘Get Started’ page. Here you just click on ‘Create a VM Instance’
! Important !
Be careful that you leave everything on ‘Always Free-eligible’.
There will still be estimated costs for 2$ for some block storage.
This amount won’t be charged and seems to be some kind of bug. Hopefully they’ve fixed it by the time you’re reading this.
For the image I’m using the Oracle Linux 8 and as shape the VM.Standard.E2.1.Micro with the max resources you can get with the free tier.
In the Networking section you’ll have to create your own virtual cloud network (VCN) and subnet.
Assign a public IPv4 Adress. You’ll need it, when you want to expose your app. Everything else here is up to you. I’d recommend to create a SSH key on your computer with ssh-keygen -t rsa and upload the .pub file while creating the VM. In the boot volume and live migration sections I left everything to default.
Now click ‘create’.

Expose the VM

Depending on if you want to reach your VM via http, https or both you need to create Ingress Rules.
Therefore go to your virtual cloud network and then open the subnet you want to use.
Here you can add security lists. But there should already be a default security list. Open it and click ‘Add Ingress Rules’.

Add 0.0.0.0/0 as Source CIDR and for destination port choose 80 for http, 443 for https or both.

Connect to VM

Now it’s time to get to know the inside of the VM.
You can either use the Shell provided in Oracle Cloud or directly connect from your computer via SSH.
First change the rights of the SSH key you uploaded to the VM during creation.
				
					chmod 400 ~/.ssh/id_rsa
				
			
Then use it to connect from a terminal.
You’ll find the username (usually opc) and public IP adress, when you open your VM instance in Oracle Cloud.
				
					ssh -i ~/.ssh/id_rsa 'username'@'public-ip'
				
			

Welcome!

To change user rights to root permanently:

				
					sudo su
				
			

Install Docker on the VM

Oracle Linux is based on Fedora Linux. Therefore we’ll be using the DNF paket manager.
				
					dnf install -y dnf-utils zip unzip
    dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo

    dnf remove -y runc
    dnf install -y docker-ce --nobest
				
			

Finish Docker Setup

Enable and start the Docker service:
				
					systemctl enable docker.service
    systemctl start docker.service
				
			

Click here for more information on these commands.

Login to docker

				
					echo $PASSWORD | sudo docker login $DOCKER_DOMAIN -u $USERNAME --password-stdin
				
			

Creating your Container

For demonstration I’m using an Angular frontend and an NGINX container. But any Docker container will do for this use case.
 
Build your Angular project with:
				
					ng new oracle-cloud-frontend
				
			

Then add a ‘nginx.conf’ and ‘Dockerfile’:

				
					# nginx.conf

server {
    listen 80;
    server_name _;

    root /usr/share/nginx/html;

    location / {
        try_files $uri $uri/ /index.html =404;
    }

    location /health {
        access_log off;
        return 200 'up';
    }

    location /nginx_status {
        stub_status;

        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

				
			
				
					# Dockerfile

FROM nginx:1.24

COPY /dist /usr/share/nginx/html
COPY /deployment/nginx.conf /etc/nginx/conf.d/default.conf

# Expose the default HTTP port
EXPOSE 80

# Start Nginx when the container launches
CMD ["nginx", "-g", "daemon off;"]

				
			

Now you should be able to build your project with Docker:

				
					docker build . -t $IMAGE_TAG
				
			

Run the Container

The easiest way to get the container onto your virtual machine is to upload it to a container registry like Docker Hub or Github Packages with ‘docker push’.

Then go to your VM and pull the image. Don’t forget that you have to be logged in.

				
					docker pull $IMAGE_TAG
				
			

Now start the container on the port you’d like to use. 

The NGINX frontend container we’re going to deploy is running on port 80, but for expandability reasons we want to publish on port 4200. Also if you want to startup your container in the background, use the -d flag.

				
					docker run -p 4200:80 -d $IMAGE_TAG

				
			

When typing ‘docker ps’ you should now see at least one running container with ports 0.0.0.0:4200->80/tcp’.

Congratulations!

You can now open your app via your browser. Just type in the IP with the port the app is running on.

E.g. ‘http://{your_public_ip}:4200’.

Make it secure with HTTPS

The next step will involve the domain, you got at the beginning of this post. Go to your providers DNS section and connect the domain to the public IP of your VM.

To test if you’ve done everything right, open ‘http://your_domain:4200’ in your browser. If you can see the same application that’s available on ‘http://your_public_ip:4200’ you succeeded.

But how can we easily enable a secure connection via https? The answer is Caddy.
On your machine you now want to install the caddy webserver. 

				
					dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
				
			

At ‘/etc/caddy’ you should now find a so called Caddyfile.
We want to use a reverse proxy to reach our frontend container on port 4200 through our domain.
Adjust your Caddyfile like so:

				
					# Caddyfile

your_domain.com {
	reverse_proxy localhost:4200
}
				
			

Caddy now automatically gets a certificate from let’s encrypt and redirects from ‘https://your_domain.com’ to ‘http://localhost:4200’ inside your VM. 

Configure the firewall

Additionally to exposing port 443 inside the Oracle Cloud UI you need to configure the firewall and restart it like so:

				
					firewall-cmd --zone=public --permanent --add-port=443/tcp
firewall-cmd --complete-reload
				
			

Last but not least

The last step is to go inside the caddy file ‘/etc/caddy’ again.
Now run:

				
					caddy run
				
			

Open ‘https://your_domain.com’ inside your browser. You should get to your secured frontend.

Einleitung

Du suchst nach einer einfachen Möglichkeit, deine Anwendung bereitzustellen und sie im Web zu präsentieren?
Hier findest du eine Schritt-für-Schritt-Anleitung, wie du deine eigene “always-free” virtuelle Maschine erstellen, einen Container bereitstellen und ihn sogar sicher über https zugänglich machen kannst.
Die Technologien, die wir verwenden werden, sind:

  • Oracle Cloud mit einer Oracle Linux Arm VM
  • Docker für den Container
  • Angular (Sie können beliebige statische HTML-Dateien verwenden)
  • Caddy als Webserver

Erster Schritt: Hole dir deine eigene persönliche Domain

Um eine sichere Verbindung zu ermöglichen, musst du dir eine eigene Domain zulegen. Dies ist der einzige Teil dieses Beitrags, bei dem du wahrscheinlich bezahlen musst. Aber keine Sorge, es sind nur etwa 7€/Jahr.
Ich habe Google Domains verwendet, aber du kannst auch jeden anderen Anbieter verwenden. Der Eintrag sollte vom Typ A sein.

Erstelle deine eigene virtuelle Maschine von Oracle

Als erstes musst du einen Account erstellen.
Mit dem Oracle Cloud free tier gibt es viele Möglichkeiten, kostenlose Datenbanken, Load Balancer, uvm. Wir werden nur die virtuelle Maschine nutzen.
 
Nachdem du dich eingeloggt hast, wirst du vermutlich die ‘Get Started’ Seite sehen. Klicke hier nun auf ‘Create a VM Instance’.
! Wichtig !
Stell sicher, dass du nur ‘Always Free-eligible’ Optionen nutzt.
Es werden dennoch Kosten von 2$ für einen ‘block storage’ angezeigt. Diese Summe wird dir aber nicht berechnet – es scheint sich um einen Bug von Oracle zu handeln. Hoffentlich wird dieser bereits gefixt sein, wenn du den Artikel liest.
 
Als Image nutze ich Oracle Linux 8 und als Shape den VM.Standard.E2.1.Micro mit den maximalen Ressourcen, welche du im free tier bekommen kannst.

Im Abschnitt Networking musst du nun dein eigenes virtuelles Cloud-Netzwerk (VCN) und Subnetz erstellen.
Weise eine öffentliche IPv4-Adresse zu. Diese wird benötigt, wenn du deine eigene Anwendung veröffentlichen willst.
Alles andere bleibt dir überlassen.
Ich würde empfehlen, einen SSH-Schlüssel auf deinem Computer mit ssh-keygen -t rsa zu erstellen und die .pub-Datei hochzuladen, während du die VM erstellst.
In den Abschnitten Boot-Volume und Live-Migration habe ich alles auf Standard gesetzt.
Klicke nun auf ‘Erstellen’.

Veröffentliche die virtuelle Maschine

Je nachdem, ob du deine virtuelle Maschine über http, https oder beides erreichen willst, müssen Ingress Rules erstellt werden.
Gehe dazu in dein virtuelles Cloud-Netzwerk und öffne das Subnetz, das verwendet werden soll.
Hier kannst du Security Lists hinzufügen. Es sollte jedoch bereits eine Standard Security List vorhanden sein. Öffne diese und klicke auf ‘Add Ingress Rules’.


Füge ‘0.0.0.0/0’ als Source-CIDR hinzu und wähle als Destination-Port 80 für http, 443 für https oder beides.

Verbinde dich mit der virtuellen Maschine

Jetzt ist es an der Zeit, das Innere der virtuellen Maschine kennenzulernen.
Du kannst entweder die in Oracle Cloud bereitgestellte Shell verwenden oder dich direkt von deinem Computer aus über SSH verbinden.
Ändere dafür zunächst die Rechte des SSH-Keys, den du bei der Erstellung in die VM hochgeladen hast.

				
					chmod 400 ~/.ssh/id_rsa
				
			
Verwende den ssh Key dann, um dich via Terminal mit der virtuellen Maschine zu verbinden.
Du findest den username (der Default ist opc) und die public IP Adresse, wenn du deine VM Instanz in Oracle Cloud öffnest.
				
					ssh -i ~/.ssh/id_rsa 'username'@'public-ip'
				
			

Willkommen!

Ändere deine Nutzerrechte permanent für eine Session:

				
					sudo su
				
			

Installiere Docker auf der virtuellen Maschine

Oracle Linux basiert auf Fedora Linux. Daher werden wir den DNF-Paketmanager verwenden.

				
					dnf install -y dnf-utils zip unzip
    dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo

    dnf remove -y runc
    dnf install -y docker-ce --nobest
				
			

Beende den Docker Setup

				
					systemctl enable docker.service
    systemctl start docker.service
				
			

Klicke hier für mehr Informationen über diese Befehle.

Logge dich bei Docker ein

				
					echo $PASSWORD | sudo docker login $DOCKER_DOMAIN -u $USERNAME --password-stdin
				
			

Erstelle deinen eigenen Container

Zur Demonstration verwende ich ein Angular-Frontend und einen NGINX-Container. Aber jeder Docker-Container ist für diesen Anwendungsfall geeignet.

Erstelle ein Angular-Projekt mit:

				
					ng new oracle-cloud-frontend
				
			

Dann füge eine ‘nginx.conf’ und ein ‘Dockerfile’ hinzu:

				
					# nginx.conf

server {
    listen 80;
    server_name _;

    root /usr/share/nginx/html;

    location / {
        try_files $uri $uri/ /index.html =404;
    }

    location /health {
        access_log off;
        return 200 'up';
    }

    location /nginx_status {
        stub_status;

        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

				
			
				
					# Dockerfile

FROM nginx:1.24

COPY /dist /usr/share/nginx/html
COPY /deployment/nginx.conf /etc/nginx/conf.d/default.conf

# Expose the default HTTP port
EXPOSE 80

# Start Nginx when the container launches
CMD ["nginx", "-g", "daemon off;"]

				
			

Jetzt solltest du dein Projekt mit Docker bauen können:

				
					docker build . -t $IMAGE_TAG
				
			

Starte den Container

Der einfachste Weg, den Container auf deine virtuelle Maschine zu bekommen, ist, ihn mit ‘docker push’ in eine Container-Registry wie Docker Hub oder Github Packages hochzuladen.

Gehe dann zu deiner VM und ziehe das Image. Vergiss nicht, dass du hierfür eingeloggt sein müsst.

				
					docker pull $IMAGE_TAG
				
			

Starte nun den Container an dem Port, den du verwenden möchtest.

Der NGINX-Frontend-Container, den wir einsetzen werden, läuft auf Port 80, aber aus Gründen der Erweiterbarkeit wollen wir auf Port 4200 veröffentlichen. Wenn der Container im Hintergrund gestartet werden soll, verwende die Option -d.

				
					docker run -p 4200:80 -d $IMAGE_TAG

				
			

Beim Ausführen von ‘docker ps’ solltest du nun mindestens einen Container sehen, welcher auf ports 0.0.0.0:4200->80/tcp’ läuft.

Glückwunsch!

Du kannst nun deine App im Browser öffnen. Gib hierfür die IP der virtuellen Maschine und dein Port des Containers ein.

z.B. ‘http://{your_public_ip}:4200’.

Sichere die Anwendung mit HTTPS

Der nächste Schritt betrifft die Domain, die du am Anfang dieses Beitrags erstellt hast. Gehe zum DNS-Bereich deines Providers und verbinde die Domain mit der öffentlichen IP deiner VM.

Um zu testen, ob alles richtig gemacht wurde, öffne ‘http://deine_domain:4200’ in deinem Browser. Wenn du die gleiche Anwendung siehst, die auch auf ‘http://deine_public_ip:4200’ verfügbar ist, hast du es geschafft.

Aber wie kann man auf einfache Weise eine sichere Verbindung über https herstellen? Die Antwort ist Caddy.
Installiere nun den Caddy-Webserver auf der virtuellen Maschine.

				
					dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
				
			

Unter ‘/etc/caddy’ solltest du nun ein sogenanntes Caddyfile finden.
Wir wollen einen Reverse Proxy verwenden, um unseren Frontend-Container auf Port 4200 über unsere Domain zu erreichen.
Passe dein Caddyfile wie folgt an:

				
					# Caddyfile

your_domain.com {
	reverse_proxy localhost:4200
}
				
			

Caddy holt sich nun automatisch ein Zertifikat von let’s encrypt und leitet von ‘https://deine_domain.com’ zu ‘http://localhost:4200’  in deiner virtuellen Maschine.

Konfiguriere die Firewall

Zusätzlich zum veröffentlichen des Ports 443 in der Oracle Cloud UI musst du deine Firewall konfigurieren und neu starten:

				
					firewall-cmd --zone=public --permanent --add-port=443/tcp
firewall-cmd --complete-reload
				
			

Und nicht zuletzt

Der letzte Schritt besteht darin, wieder in das Verzeichnis des Caddyfiles ‘/etc/caddy’ zu gehen.
Führe dort folgenden Befehl aus:

				
					caddy run
				
			

Öffne ‘https://your_domain.com’  in deinem Browser. Du solltest zu deinem sicheren Frontend kommen.