Hummingbird in the cloud
Tags: oci, swift, api, hummingbird
Published: 2023-06-27 14:31:09

### Deploying your Server side Swift application using ARM-based server with Ubuntu in Oracle Cloud

The point, when you want to access your API server not only from localhost, comes very fast. When your application is in development phase, it is very difficult to commit yourself to any paid services, that's why I will show a way how to host your API server for free.

We will deploy our previously created [parkAPI](https://github.com/kicsipixel/parkAPI) on Oracle Cloud Infrastructure [(OCI)](https://www.oracle.com/cloud/free/). It offers you an "Always Free" Tier, you can find many tutorials on the web, how to register and start with it.

Although for the first sight it looks complicated, stay with me, you will see it is easy.

## Step 1 - Create an ARM-based virtual machine with Ubuntu

Before creating the VM we need to configure the network.

### Step 1.1 - Create a compartment
 To easily separate the different workloads and setup user access properly, it is recommended to create a separate [compartment](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingcompartments.htm).

 - Go to "Identity & Security", then from "Identity", choose "Compartments".

![image 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebwjn9alakglxrzkulz6.png)
 
 - "Create Compartment" and fill "Name" and "Description".

![image 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g9p7qcokvwbaqg40s16b.png)

### Step 1.2 - Create Virtual Cloud Network (VCN)
- Go to "Networking", then "Virtual cloud networks"

![image 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kvsv8kza0fdbwmm2u6y6.png)


- Set "Compartment" to "parkAPI"


![image 4](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/autcwzanwlqxvvqmvzbs.png)



- "Create VCN" and fill "Name" and "PIv4 CIDR Blocks"

![image 5](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8stn25kvvgdlsv4njww5.png)

### Step 1.3 - Create Subnets
- Choose "Subnets" then "Create Subnet"


![image 6](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88l8e7mvsb2n6ar8593c.png)


- Fill "Name", "Create in Compartment", "IPv4 CIDR Block", choose "Public Subnet"


![image 7](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eaexccuzon8zo9w53rjq.png)

- Add "Default Security List for VCN for parkAPI"

![image 8](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7iz46gzujdx6gb9dmeqn.png)

### Step 1.4 - Create Internet Gateway (IG)
- Choose "Internet Gateways", then "Create Internet Gateway"

![image 9](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2s695j7wnoiiv89vpcb1.png)


- Fill "Name" and "Create in Compartment"

![image 10](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sfxk70ctzjz1n5bqtkc1.png)


### Step 1.5 - Create Route rules
- Choose "Route Tables" and click on "Default Route Table for VCN for parkAPI"


![image 11](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/no6f9ad27jkf6p6ar9gw.png)


- Click "Add Route Rules"

![image 12](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8gknwlnh9rk25lg49xl.png)

- Set Internet Gateway

![image 13](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmu2hsh06q3lzg5403ej.png)

### Step 1.6 - Create VM server
- "Compute" and "Instances"

![image 14](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdhfxabc1l1723b2wx09.png)


-  Set "Compartment" to "parkAPI" then "Create Instance"

![image 15](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p4v67f8sabmvuj7yc9jm.png)


-  Fill "Name", change "Image" to "Canonical Ubuntu 22.04 Minimal aarch64" and the "Shape" will automatically change to Ampere.


![image 16](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x6w5v6iqrcljo7dour28.png)


-  Assign the newly created VCN at "Networking" section


![image 17](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtqs6y1w8hilwnmaongi.png)




-  At "Add SSH keys" you either "Generate a key pair for me" or "Paste public keys", but you must have to set SSH key for administration purposes.

![image 18](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3nl6nylopq6azdrg2bgd.png)


-  "Create"

### Step 1.7 - Test our newly created server
#### Step 1.7.1 - Enable `ping`
By default OCI doesn't allow ping traffic, you need to allow it.
- Go to "Security Lists" then click on "Default Security List for VCN for parkAPI"


![image 19](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tyxpixkifu2pmldilpcv.png)



- Click on "Add Ingress Rules" 
![image 20](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/to4iapkwolzsy3jc1izb.png)

- Fill "Source CIDR| "IP Protocol" and "Type"

![image 21](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ljr65a8llutkumc0ukew.png)



- Go to "Instances" and set "Compartment" to "parkAPI" and you will see your public IP


![image 22](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npie2wdibetrjcw3yw1j.png)



- Now you can try: 
```bash 
$ ping 144.24.166.181 -c 5
``` 

#### Step 1.7.2 - Use `ssh` to login
```bash
$ ssh -i oci ubuntu@144.24.166.181` 
```
where `oci` is your private SSH key.


## Step 2. - Install Swift
- Install developer tools
```bash
$ sudo apt install clang libpython2.7 libpython2.7-dev
```
- Download the Swift release for `aarch64` platform
```bash
$ wget https://download.swift.org/swift-5.8.1-release/ubuntu2204-aarch64/swift-5.8.1-RELEASE/swift-5.8.1-RELEASE-ubuntu22.04-aarch64.tar.gz
```
- Unpack it
```bash
$ tar xzf swift-5.8.1-RELEASE-ubuntu22.04-aarch64.tar.gz
```
- Move the unpacked Swift folder under `/usr`
```bash
$ sudo mv swift-5.8.1-RELEASE-ubuntu22.04-aarch64 /usr/share/swift
```
- Add it to your `PATH`
```bash
$ echo "export PATH=/usr/share/swift/usr/bin:$PATH" >> ~/.bashrc
```
- Reload your `SHELL` with the updated `PATH`
```bash
$ source ~/.bashrc
```

- Test your Swift version
```bash
$ swift -v
```

## Step 3 - Install `git`
```bash
$ sudo apt install git
```

## Step 4 - Install and configure NGINX
- Install NGINX server
```bash
$ sudo apt install nginx
```

- Start the service
```bash
$ sudo systemctl start nginx.service
```

- Add a rule at the top of the INPUT and OUTPUT chain to ACCEPT connexions to port 80. Try again after adding these rules:
```bash
$ sudo iptables -I INPUT -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

$ sudo iptables -I OUTPUT -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
```
- Before you can check your web server, you need to open the port: 80 on OCI side as well.

Under the `Networking / Virtual cloud networks / Virtual Cloud / Network Details / Security Lists` click on "Default Security List for VCN for parkAPI". 

![image 23](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3trp2m73lq721mtaxvno.png)

"Add Ingress Rules" and fill it.

![image 24](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6t756qi976yj88hqdg2i.png)

Now, you will see your web server running.

## Step 5 - Clone and run our API server
- Clone our Hummingbird app from Github:
```bash
$ git clone https://github.com/kicsipixel/parkAPI
```
- Run your app
```bash
$ swift run parkAPI
```

- To be able to reach your API server you need to configure NGINX to serve as reverse proxy and connect localhost:8080 to www: 80.

## Step 5 - NGINX as reverse proxy
- Remove the default NGINX config
```bash
$ sudo unlink /etc/nginx/sites-enabled/default
```

- Create your own `parkAPI.conf` file under `/etc/nginx/sites-available/`
```c
server {
    listen 80;
    listen [::]:80;    

    server_name 144.24.166.181 www.144.24.166.181;    

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
```

- Create a symlink to `sites-enabled`
```bash
$ sudo ln -s /etc/nginx/sites-available/parkAPI.conf /etc/nginx/sites-enabled/parkAPI.conf
```

- Restart the server
```bash
$ sudo systemctl reload nginx
```

- Test your server in the browser.

![image 25](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71fil3zbpcmujavg00lj.png)


Congratulations, your Hummingbird server is running in the cloud.