How to run PostGREST on DigitalOcean backed by Neon Postgres # Introduction Experience the power of Serverless Postgres, a fully managed solution with innovative architecture separating storage and computing, which provides unmatched autoscaling, branching, and extensive storage options. In this guide, we'll leverage the strengths of [Neon Serverless Postgres](https://neon.tech/) to establish a [PostGREST](https://postgrest.org/en/stable/) API on [DigitalOcean](https://www.digitalocean.com/). With PostGREST, a PostgreSQL database is turned into a RESTful API. As a practical illustration, we'll walk through creating a mini-project management application. This tangible example will demonstrate the seamless integration between Neon Serverless Postgres, PostGREST, and DigitalOcean. Upon completing this tutorial, we'll have a fully functional PostGREST API powered by Neon Serverless Postgres, seamlessly incorporated into our DigitalOcean environment. It stands ready to cater to our data management and API interaction needs, whether for a project management application or any other web or mobile app, we may develop. Project demo The project demo can be found [here](http://159.89.232.18//?utm_source=hackmamba&utm_medium=blog&utm_id=HMBcommunity). # Prerequisite To fully grasp the concepts presented in this tutorial, the following are required: * [A Neon account](https://console.neon.tech/) * [ A DigitalOcean account](https://cloud.digitalocean.com/registrations/new) * A basic understanding of PostgreSQL and REST APIs * Node.js installed on oour local machine # Create a Neon project To set up a Neon project, let's begin by [registering for an account](https://console.neon.tech/), assuming we don't have one already. Now, we'll create a new project by selecting a Project Name. We will use (Project Management), Database name (managementdata), and Postgres version. We'll opt for 16 as the Postgres version and choose the region closest to where we'd like to deploy our app. ![project creation](https://hackmd.io/_uploads/BJLFbz5Va.png) Upon successfully creating the project, we will get a connection string for connecting to our database. ![Connection string](https://hackmd.io/_uploads/r1leXzq4T.png) ## Loading Demo Data Into the Database To load the demo data into the database, we need to first connect to our database by running the connection string in our terminal: ``` psql 'postgresql://xxx:xxxx@ep-xxx-xxx-01196450.us-east-2.aws.neon.tech/xxx?sslmode=require' ``` The command connects to the database using the provided connection string. Now that we are connected to the database, let us upload our demo data by running the command below In the terminal: ``` psql 'postgresql://xxx:xxxx@ep-xxx-xxx-01196450.us-east-2.aws.neon.tech/xxx?sslmode=require < projects.sql ``` The demo data (projects.sql) can be downloaded [here](https://drive.google.com/file/d/1UkCJMlYsSv_cVkK25pRn-TpCw0BBCYr4/view?usp=sharing). > Note that the demo data must be in our project directory before running the command above. Upon successfully loading demo data into the database, we would see a response like the image below: ![Loading Data RESPONSE](https://hackmd.io/_uploads/ry8jnrcNa.png) The output `CREATE SEQUENCE`, `CREATE TABLE`, and `INSERT 0 5` Indicates that the sequence was created, the table was created, and 5 rows were inserted into the table, respectively. Next is to check if our demo data gets into the database by running: First, we connect to the database by using the connection string. ``` psql 'postgresql://xxx:xxxx@ep-xxx-xxx-01196450.us-east-2.aws.neon.tech/xxx?sslmode=require' ``` Then we run the command below in our terminal: ``` select * FROM projects LIMIT 1 ``` The SQL command `SELECT * FROM projects LIMIT 1` retrieves data from the "projects" table. We should get a response like in the image below. ![data response](https://hackmd.io/_uploads/S1O4gLqEp.png) As a result, our demo data has been successfully uploaded to our database. We will use the data in some sections below later. # PostgREST Setup Now that we have set up our database, the next step involves setting up PostgREST. First, we install PostgREST by following this installation [guide](https://postgrest.org/en/stable/explanations/install.html#install). After a successful installation, we can confirm everything works perfectly by typing `postgrest -e` in the terminal. We should see a response similar to the image below, indicating a successful operation. ![postgrest confirmation](https://hackmd.io/_uploads/rJgBuSoVT.png) ## Granting CRUD Access to Database User Now, we can connect to the database using the connection string above and then grant `SELECT`, `INSERT`, `UPDATE`, and `DELETE` (CRUD) operations on the `projects` table in the `public` schema to the user. In this case, the user is `femakin` in PostgrsSQL by running the command below: ``` GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE public.projects TO femakin ``` ## PostgREST Connection SetUp Next is to set up a PostgREST connection. First, we exit our database by typing `\q` and then typing: `vi projects.config` The command `vi projects.config` opens the `projects. config` file using the vi text editor. We then edit the `projects.config` file by pasting the command below. ``` db-uri = psql 'postgresql://xxx:xxxx@ep-xxx-xxx-01196450.us-east-2.aws.neon.tech/xxx?sslmode=require' db-schema = "public" db-anon-role = "femakin" ``` This configuration specifies a PostgreSQL database connection string URI with credentials and connection details. It also defines the default database schema as `public` and the anonymous role as `femakin` for authentication purposes. To ensure the proper setup of the PostgREST connection, we can run `postgrest projects.config` in the terminal. This command should yield a response similar to the image below. ![postgrest setup](https://hackmd.io/_uploads/SJwDuDi4T.png) ## Testing the API Routes Now, we can employ a tool such as Postman or a browser to conduct tests. In the browser, navigate to the URL `localhost:3000/projects`. The connection is working if we find something like this in the browser. ![Api response](https://hackmd.io/_uploads/r1ZFqPoNT.png) Otherwise, we must review all the steps and ensure everything is present. # Bootstrapping VueJS Application We need to Initiate the setup of our VueJS application by cloning the VueJS repository available here on [GitHub](https://github.com/femakin/Neo-Demo-PostgREST-DigitalOcean-App). Follow the instructions outlined in the README file to configure the necessary environment variables, execute `npm install` to install dependencies, and launch the application using `npm run dev`. Now we can start our application using `npm run dev` We should have a screen similar to the image below: ![Home screen](https://hackmd.io/_uploads/rJcMwnoNT.png) The code in the `src/App.vue` is a project management app using VueJS. It handles project data, loading status, and user interactions. It fetches project data and lets users view, add, update, and delete projects. The focus is on simplicity for managing projects in a web app. # Deploying to Digital Ocean We created our database, set up PostgREST, and got our mini-application running in VueJS. Now, we need to deploy everything to DigitalOcean. To do this, we log into the DigitalOcean dashboard and create a Droplet by following this [guide](https://docs.digitalocean.com/products/droplets/how-to/create/). DigitalOcean Droplets are Linux-based virtual machines (VMs) that operate on virtualized hardware. Now, we can log into our droplet by copying the `IP` address of the droplet we created and `SSH.` into the droplet. ![droplet ip](https://hackmd.io/_uploads/SJAqwt24a.png) Now, let's log into the droplet by using the copied IP and running the command below in the terminal: ``` ssh root@copied_IP ``` This will prompt us to enter a passphrase for the key. ![ssh connection](https://hackmd.io/_uploads/rkQCnYnVT.png) Next, we'll update the `apt cache` to get the latest packages by running: ``` sudo apt update ``` ![cache update](https://hackmd.io/_uploads/SJs-Pc3NT.png) We must install a runtime library, a crucial part of the PostgreSQL database system. This library is an interface to connect to and communicate with PostgreSQL database servers. Let us paste the command below in the terminal: ``` sudo apt install libpq5 ``` ![libpq5](https://hackmd.io/_uploads/BkAR592Na.png) Now, let's install PostgREST from the release page available [here](https://github.com/PostgREST/postgrest/releases/tag/v11.2.0). Choose a version that is compatible with our operating system; for example, we will install `postgrest-v11.2.0-linux-static-x64.tar.xz`. We can paste the command below in the terminal: ``` wget 'https://github.com/PostgREST/postgrest/releases/download/v11.2.0/postgrest-v11.2.0-linux-static-x64.tar.xz' ``` ![downloading PostgREST](https://hackmd.io/_uploads/HyIIYjnET.png) Next is to extract the compressed file to obtain the executable. run the command below in the terminal: ``` root@project-management:~# tar vxf postgrest-v11.2.1-linux-static-x64.tar.xz postgrest ``` To ensure everything works, let's run the following command: ``` ./postgrest -e ``` We should expect a response similar to the image below. ![starting postgrest](https://hackmd.io/_uploads/ryWAG62Np.png) Now, let us move PostgREST to `usr/bin` by executing the following command: sudo mv postgrest /usr/bin let us move PostgREST to usr/bin by executing the following command: sudo mv postgrest /usr/bin Then we navigate to `/usr/bin` using the command: cd /usr/bin Then, confirm that everything is in order by running: ./postgrest -e Now, we create a directory using the command: ``` mkdir projectsmanagement ``` let's return to our local machine within the project directory and copy the config file using: cat projects.config We previously created the config file in the section above. We will see a configuration similar to the one below: db-uri = 'postgresql://xxx:xxxx@ep-xxx-xxx-01196450.us-east-2.aws.neon.tech/xxx?sslmode=require' db-schema = "public" db-anon-role = "femakin" server-host = "localhost" Then, return to our droplet and create a new config using: ``` vi projects.config ``` Paste the copied `projects.config`, and save the file. ![projects.config](https://hackmd.io/_uploads/r1ReLC24T.png) Now, we can connect to our database using `postgrest postgrest.config` We will see a response stating that connection successful as shown in the image below ![connecting to database](https://hackmd.io/_uploads/HkliTCnN6.png) Now, we can test the API using the command `curl localhost:3000/projects`, and observe a response from our database, like the illustration below. ![response](https://hackmd.io/_uploads/HyqLk1aEp.png) ## Creating systemd Now, let's create a system service for a PostgREST. We need to go back to PostgREST documentation [here](https://postgrest.org/en/stable/integrations/systemd.html?highlight=daemonizing). ![systemd](https://hackmd.io/_uploads/SkToa1pVp.png) We can now go back to our droplet and create the system file using the command below: `vi /etc/systemd/system/postgrest.service` and paste the code below: ``` [Unit] Description=REST API for any PostgreSQL database After=postgresql.service [Service] ExecStart=/usr/bin/postgrest /usr/bin/postgrest.config ExecReload=/bin/kill -SIGUSR1 $MAINPID User=nobody Group=nogroup [Install] WantedBy=multi-user.target ``` Let us reload, start and check the status of the `systemd` Using the command below. ``` sudo systemctl daemon-reload sudo systemctl start postgrest sudo systemctl status postgrest ``` ![reload systemd](https://hackmd.io/_uploads/BkANQe64T.png) Testing the API using `curl localhost:3000/projects` gives us our expected response, as shown below: ![curl response](https://hackmd.io/_uploads/ByiZNgaET.png) ## Uploading the Vue App into Droplet It's time to upload our project management application into the droplet. We will return to our local machine to upload our application into the droplet and run `npm run build` inside the project directory. ![App build](https://hackmd.io/_uploads/Bk5SlM0Ea.png) Now that we have our production Vue App, we can copy it into the droplet using the command below: ``` scp -r dist root@copied_IP:/usr/bin/vueapp ``` ![copying App](https://hackmd.io/_uploads/HJ8p-fAV6.png) Next is to install a web server to serve the files. ``` sudo apt install nginx ``` ![installing a web server](https://hackmd.io/_uploads/ByGdOpAVp.png) Next is to create a virtual host using: ``` sudo vi /etc/nginx/sites-available/Copied_IP ``` Paste the code below and save. ![virtual host](https://hackmd.io/_uploads/BJw79pCNp.png) We can now create a link using. ``` sudo ln -s /etc/nginx/sites-available/Copied_IP /etc/nginx/sites-enabled/ ``` Then reload `nginx` using ``` sudo systemctl reload nginx ``` ## Testing Deployment We can now go to the browser and paste the copied URL. We should see our project management app on the page. ![Rendered App](https://hackmd.io/_uploads/rkoA36C46.png) But, if we look at the console, we will see an error. This error is there because we have not set up the API server. ![API Server Error](https://hackmd.io/_uploads/r1eAa6AVT.png) To take care of this, we must use `nginx` to proxy `/API` to the Postgrest instance running on our droplet, as described in this Postgrest documentation. We can now edit our `nginx` configuration using: ``` sudo vi /etc/nginx/sites-available/Copied_IP ``` Then, update the configuration with the command below. ``` location /api/ { default_type application/json; proxy_hide_header Content-Location; add_header Content-Location /api/$upstream_http_content_location; proxy_set_header Connection ""; proxy_http_version 1.1; proxy_pass http://localhost:3000/; } ``` ![update nginx configuration](https://hackmd.io/_uploads/r1idbRREa.png) Then reload `nginx` using ``` sudo systemctl reload nginx ``` We can now return to the browser and paste the copied IP Address. Now, we can see our application without any errors. ![Complete Page ](https://hackmd.io/_uploads/HknMQACEp.png) Now that we have been able to look at how to successfully run PostGREST on DigitalOcean backed by Neon Postgres. Here are a few recommendations to take it further. Including but not limited to; - To add a domain to the droplet - Configure HTTPS - Add more features to the applications. The possibilities are endless when it comes to Neon Serverless Postgres. # Conclusion In this article, we look at how to: - Leverage Neon Serverless Postgres to establish a PostGREST API on DigitalOcean. - Transform a PostgreSQL database into a RESTful API using PostGREST. - Create a mini-project management application as a practical illustration using VueJS. - Showcase seamless integration between Neon Serverless Postgres, PostGREST, and DigitalOcean. - Achieve a fully functional PostGREST API. # References [Neon Documentation](https://neon.tech/) [PostgREST Documentation](https://postgrest.org/en/stable/) [How to Create a Droplet](https://docs.digitalocean.com/products/droplets/how-to/create/) [Building a Contacts List with PostgREST and Vue.js](https://www.youtube.com/watch?v=iHtsALtD5-U)