Architecture & Azure deployment details
The project is configured to be developed using Codespaces. The initial script should be able to install all the dependencies, but the ElixirLS extension might require some time to fetch and build up all the dependencies.
It is possible to use NeoVim with a terminal connection. This script will have to be executed manually, then to access in SSH, follow these instructions in Codespaces.
In order to start developing the project, it's necessary to install Elixir.
After having installed Elixir and Erlang in the machine, install the Phoenix Framework by executing the following command in the terminal:
mix local.hex
mix archive.install hex phx_newNote: to run the project with a local database, for problems of trusting the emulator local certificate, it will be necessary to run the dotnet app described below.
To start the application, from the root folder, execute these commands
- Install the required dependencies:
mix deps.get && mix deps compile- Install Tailwind support
mix tailwind.install- Run the script to initialise the database with the required collections:
mix run apps/guilds/priv/seeds.exs- Start the local instance of the application:
mix phx.serverThis will start the application, that will listen to the port 4000.
To start development, run the database in a Docker container with this command:
docker run --name privee-database -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --restart=unless-stopped -p 5432:5432 -d postgresAlso, instead of relying on IDE tools, the PGAdmin tool can be started on Docker to explore the database:
docker run --name pgadmin -e "PGADMIN_DEFAULT_EMAIL=admin@admin.com" -e "PGADMIN_DEFAULT_PASSWORD=admin" --restart=unless-stopped -p 5050:80 -d dpage/pgadmin4
docker network create --driver bridge pgnetwork
docker network connect pgnetwork pgadmin
docker network connect pgnetwork privee-databaseFor those who prefer Podman over Docker, you can use these equivalent commands:
To start the PostgreSQL database with Podman:
podman run --name privee-database -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --restart=unless-stopped -p 5432:5432 -d postgresTo start PGAdmin with Podman:
podman run --name pgadmin -e "PGADMIN_DEFAULT_EMAIL=admin@admin.com" -e "PGADMIN_DEFAULT_PASSWORD=admin" --restart=unless-stopped -p 5050:80 -d dpage/pgadmin4
podman network create pgnetwork
podman network connect pgnetwork pgadmin
podman network connect pgnetwork privee-databaseThe most natural way of developing in Elixir is to use Visual Studio Code with Elixir-LS extension.
There are other extensions that helps with developing the application:
- Phoenix Framework
- Surface: A component based library for Phoenix
Normally, every Erlang instance should be connected to one another manually. The package libcluster anyway offers a way of doing it automatically inside a service pod.
For more information refer the package information and the guide to set it up.
There is also an interesting guide in parts on how to configure Elixir nodes on Kubernetes, always with libcluster.
To login to Azure, a User-defined Managed Identity has been created with a federated identity, and OpenID Connect authentication type has been selected; the reason Managed Identity has not been used as an authentication type is that it required a self-hosted environment, i.e. a VM on Azure.
For more information on how to setup the GitHub Action to work with Azure resources using User-defined Managed Identities,
please refer to the article of the azure/login GitHub Action.
The SECRET_KEY_BASE environment variable required by the Phoenix application is currently being stored as a Kubernetes secret, and inject as an environment variables directly in the Kubernetes deployment file. This is not optimal, but there is issue #109 addressing this.
This application supports deployment to both Fly.io and Azure AKS with automatic environment detection.
The application is pre-configured for Fly.io deployment. The rel/env.sh.eex file automatically detects Fly.io environment variables and configures clustering accordingly.
-
Deploy using Fly CLI:
fly deploy
Or use the deployment script:
./infra/deploy-fly.sh
For Azure Kubernetes Service deployment:
-
Build and push the Docker image:
# Build the image docker build -t privee.azurecr.io/privee:latest . # Push to Azure Container Registry docker push privee.azurecr.io/privee:latest
-
Create necessary Kubernetes secrets:
# Create database secret kubectl create secret generic postgres-secret \ --from-literal=POSTGRES_USER=your_user \ --from-literal=POSTGRES_PASSWORD=your_password \ --from-literal=POSTGRES_DB=your_database # Create application secret kubectl create secret generic privee-app-secret \ --from-literal=SECRET_KEY_BASE=$(mix phx.gen.secret)
-
Deploy to AKS:
kubectl apply -f k8s-deployment.yml
Or use the deployment script for a complete deployment:
./infra/deploy-aks.sh
-
Check deployment status:
kubectl get pods -l app=privee kubectl get services kubectl logs -l app=privee --tail=50
Or use the status check script:
./infra/check-aks.sh
The application automatically detects the deployment environment:
- Fly.io: Detected by
FLY_APP_NAMEenvironment variable - Azure AKS: Detected by
KUBERNETES_SERVICE_HOSTenvironment variable - Local/Default: Used when neither of the above are present
Each environment uses appropriate clustering and networking configurations:
- Fly.io: IPv6 support, DNS-based clustering via
${FLY_APP_NAME}.internal - Azure AKS: IPv4, Kubernetes DNS service discovery via headless service
- Local: Simple name-based distribution for development # Test ACR build improvements