Setup Postgres, and GraphQL API with Hasura on Azure

Prerequisites

Docker Compose Development Environment

services:
postgres:
image: postgres:12
restart: always
volumes:
- db_data:/Users/adron/Codez/databases
environment:
POSTGRES_PASSWORD: ${PPASSWORD}
ports:
- 5432:5432
volumes:
db_data:
  • HASURA_GRAPHQL_DATABASE_URL — this variable is the base postgres URL connection string.
  • HASURA_GRAPHQL_ENABLE_CONSOLE — this is the variable that will set the console user interface to initiate. We’ll definitely want to have this for the development environment. However in production I’d likely want this turned off.
graphql-engine:
image: hasura/graphql-engine:v1.1.0
ports:
- "8080:8080"
depends_on:
- "postgres"
restart: always
environment:
HASURA_GRAPHQL_DATABASE_URL: postgres://postgres:logistics@postgres:5432/postgres
HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
docker-compose up -d
docker-compose down

Terraform Production Environment

variable "database" {
type = string
}
variable "server" {
type = string
}
variable "username" {
type = string
}
variable "password" {
type = string
}
output "hasura_url" {
value = "postgres://${var.username}%40${azurerm_postgresql_server.logisticsserver.name}:${var.password}@${azurerm_postgresql_server.logisticsserver.fqdn}:5432/${var.database}"
}
provider "azurerm" {
version = "=2.20.0"
features {}
}
resource "azurerm_resource_group" "adronsrg" {
name = "adrons-rg"
location = "westus2"
}
resource "azurerm_postgresql_server" "logisticsserver" {
name = var.server
location = azurerm_resource_group.adronsrg.location
resource_group_name = azurerm_resource_group.adronsrg.name
sku_name = "B_Gen5_2"
storage_mb = 5120
backup_retention_days = 7
geo_redundant_backup_enabled = false
auto_grow_enabled = true
administrator_login = var.username
administrator_login_password = var.password
version = "9.5"
ssl_enforcement_enabled = true
}
resource "azurerm_postgresql_database" "logisticsdb" {
name = var.database
resource_group_name = azurerm_resource_group.adronsrg.name
server_name = azurerm_postgresql_server.logisticsserver.name
charset = "UTF8"
collation = "English_United States.1252"
}
resource "azurerm_postgresql_firewall_rule" "pgfirewallrule" {
name = "allow-azure-internal"
resource_group_name = azurerm_resource_group.adronsrg.name
server_name = azurerm_postgresql_server.logisticsserver.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
resource "azurerm_container_group" "adronshasure" {
name = "adrons-hasura-logistics-data-layer"
location = azurerm_resource_group.adronsrg.location
resource_group_name = azurerm_resource_group.adronsrg.name
ip_address_type = "public"
dns_name_label = "logisticsdatalayer"
os_type = "Linux"
container {
name = "hasura-data-layer"
image = "hasura/graphql-engine"
cpu = "0.5"
memory = "1.5"
ports {
port = 80
protocol = "TCP"
}
environment_variables = {
HASURA_GRAPHQL_SERVER_PORT = 80
HASURA_GRAPHQL_ENABLE_CONSOLE = true
}
secure_environment_variables = {
HASURA_GRAPHQL_DATABASE_URL = "postgres://${var.username}%40${azurerm_postgresql_server.logisticsserver.name}:${var.password}@${azurerm_postgresql_server.logisticsserver.fqdn}:5432/${var.database}"
}
}
tags = {
environment = "datalayer"
}
}
provider "azurerm" {
version = "=2.20.0"
features {}
}
resource "azurerm_resource_group" "adronsrg" {
name = "adrons-rg"
location = "westus2"
}
resource "azurerm_postgresql_server" "logisticsserver" {
name = var.server
location = azurerm_resource_group.adronsrg.location
resource_group_name = azurerm_resource_group.adronsrg.name
sku_name = "B_Gen5_2"
storage_mb = 5120
backup_retention_days = 7
geo_redundant_backup_enabled = false
auto_grow_enabled = true
administrator_login = var.username
administrator_login_password = var.password
version = "9.5"
ssl_enforcement_enabled = true
}
resource "azurerm_postgresql_database" "logisticsdb" {
name = var.database
resource_group_name = azurerm_resource_group.adronsrg.name
server_name = azurerm_postgresql_server.logisticsserver.name
charset = "UTF8"
collation = "English_United States.1252"
}
resource "azurerm_postgresql_firewall_rule" "pgfirewallrule" {
name = "allow-azure-internal"
resource_group_name = azurerm_resource_group.adronsrg.name
server_name = azurerm_postgresql_server.logisticsserver.name
start_ip_address = "0.0.0.0"
end_ip_address = "0.0.0.0"
}
resource "azurerm_container_group" "adronshasure" {
name = "adrons-hasura-logistics-data-layer"
location = azurerm_resource_group.adronsrg.location
resource_group_name = azurerm_resource_group.adronsrg.name
ip_address_type = "public"
dns_name_label = "logisticsdatalayer"
os_type = "Linux"
container {
name = "hasura-data-layer"
image = "hasura/graphql-engine"
cpu = "0.5"
memory = "1.5"
ports {
port = 80
protocol = "TCP"
}
environment_variables = {
HASURA_GRAPHQL_SERVER_PORT = 80
HASURA_GRAPHQL_ENABLE_CONSOLE = true
}
secure_environment_variables = {
HASURA_GRAPHQL_DATABASE_URL = "postgres://${var.username}%40${azurerm_postgresql_server.logisticsserver.name}:${var.password}@${azurerm_postgresql_server.logisticsserver.fqdn}:5432/${var.database}"
}
}
tags = {
environment = "datalayer"
}
}
variable "database" {
type = string
}
variable "server" {
type = string
}
variable "username" {
type = string
}
variable "password" {
type = string
}
output "hasura_url" {
value = "postgres://${var.username}%40${azurerm_postgresql_server.logisticsserver.name}:${var.password}@${azurerm_postgresql_server.logisticsserver.fqdn}:5432/${var.database}"
}
cd terraformterraform apply -auto-approve \
-var 'server=logisticscoresystemsdb' \
-var 'username='$PUSERNAME'' \
-var 'password='$PPASSWORD'' \
-var 'database=logistics'
./prod-start.sh 
azurerm_resource_group.adronsrg: Creating...
azurerm_resource_group.adronsrg: Creation complete after 1s [id=/subscriptions/77ad15ff-226a-4aa9-bef3-648597374f9c/resourceGroups/adrons-rg]
azurerm_postgresql_server.logisticsserver: Creating...
azurerm_postgresql_server.logisticsserver: Still creating... [10s elapsed]
azurerm_postgresql_server.logisticsserver: Still creating... [20s elapsed]
...and it continues.
... other output here ...
azurerm_container_group.adronshasure: Still creating... [40s elapsed]
azurerm_postgresql_database.logisticsdb: Still creating... [40s elapsed]
azurerm_postgresql_database.logisticsdb: Still creating... [50s elapsed]
azurerm_container_group.adronshasure: Still creating... [50s elapsed]
azurerm_postgresql_database.logisticsdb: Creation complete after 51s [id=/subscriptions/77ad15ff-226a-4aa9-bef3-648597374f9c/resourceGroups/adrons-rg/providers/Microsoft.DBforPostgreSQL/servers/logisticscoresystemsdb/databases/logistics]
azurerm_container_group.adronshasure: Still creating... [1m0s elapsed]
azurerm_container_group.adronshasure: Creation complete after 1m4s [id=/subscriptions/77ad15ff-226a-4aa9-bef3-648597374f9c/resourceGroups/adrons-rg/providers/Microsoft.ContainerInstance/containerGroups/adrons-hasura-logistics-data-layer]
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.Outputs:hasura_url = postgres://postgres%40logisticscoresystemsdb:theSecretPassword!@logisticscoresystemsdb.postgres.database.azure.com:5432/logistics

Next Steps

References

Sign Up for Thrashing Code

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store