> For the complete documentation index, see [llms.txt](https://docs.hivel.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hivel.ai/self-managed-hivel-deployment/virtual-private-cloud/azure/tl-dr-azure.md).

# TL;DR (Azure)

### Azure Quick Deployment Guide

Deploy Hivel on your own Azure account using a Virtual Machine for compute and Azure Database for PostgreSQL (Flexible Server) for the database. This condensed guide covers the same steps in the same order without omitting any part of the deployment process. Refer to the full [Azure Setup Guide](https://docs.hivel.ai/self-managed-hivel-deployment/virtual-private-cloud/azure) for additional context, detailed explanations, or troubleshooting guidance.

#### **Prerequisites**

> **Important:** Your VM and database run on Azure, but Hivel's Docker images and installer package are distributed via AWS (ECR and S3). You need both Azure CLI and AWS CLI, plus credentials for both platforms, to complete this guide.

{% hint style="warning" %}

Before you start, confirm you have:

* An Azure subscription with Contributor role (or equivalent permissions)
* Hivel-issued AWS Access Key ID and Secret Access Key, scoped to Hivel's ECR
* An S3 bucket path or pre-signed URL for the `hivel-onprem` installer package
* Hivel license files: `license_signed.json` and `hivel_onprem_public.pem`
  {% endhint %}

If you lack any of these, contact <support@hivel.ai> before starting. Deployment cannot complete without them.

#### Step 1: Provision an Azure Virtual Machine

**In Azure Portal:**

1. Create a new Virtual Machine with:
   * Image: Ubuntu Server 22.04 LTS
   * VM size: Standard\_D4s\_v5 (4 vCPU, 16GB RAM) or larger. For high integration or commit volume, consult Hivel before finalizing sizing
   * Storage: 50GB Premium SSD managed disk
   * Network Security Group: allow inbound on ports 22, 80, 443, 3000, 4317 (required only while integrating Claude Code), and 5432
2. Note the VM's public and private IP address

#### Step 2: Install Required Software

**On the VM, via SSH:**

```bash
# Update system
sudo apt update && sudo apt upgrade -y
sudo apt install -y postgresql postgresql-contrib
sudo apt install -y unzip

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Install Azure CLI (for managing your Azure resources and Key Vault, if used)
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Install AWS CLI (required, Hivel's container registry and installer package are hosted on AWS)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Verify installations
docker --version
docker-compose --version
az --version
aws --version
```

Required versions: Docker >= 26.0, Docker Compose >= 2.25.0, any current Azure CLI 2.x, any current AWS CLI v2.x. Log out and back in for the Docker group change to take effect.&#x20;

> If `docker ps` still asks for `sudo`, run `newgrp docker` or reboot the VM.

#### Step 3: Configure the AWS CLI

**On the VM:**

Hivel's Docker images and installer package are hosted on AWS even though your infrastructure runs on Azure.

```bash
aws configure
# AWS Access Key ID:     [Hivel-provided access key]
# AWS Secret Access Key: [Hivel-provided secret key]
# Default region name:   ap-south-1
# Default output format: json

# Verify
aws sts get-caller-identity
```

Expect a JSON object with Account, UserId, and Arn fields. If it fails with "Unable to locate credentials," re-run `aws configure` and check `cat ~/.aws/credentials`.

#### Step 4: Provision Azure Database for PostgreSQL

**In Azure Portal:**

1. Create Azure Database for PostgreSQL > Flexible Server with:
   * Version: PostgreSQL 12 or higher
   * Compute tier: General Purpose, Standard\_D2s\_v3 or larger
   * Storage: 20GB or more
   * Admin username: `postgres` (fixed, do not change)
   * Admin password: choose a strong password and save it
2. Configure server parameters: go to Server parameters, set `require_secure_transport` to `OFF` (this deployment uses network-level isolation as the security boundary), save. If marked "Static," restart the server
3. Note: server name/host (e.g., `myserver.postgres.database.azure.com`), port (usually 5432), admin username, admin password
4. Configure networking on the Networking page:
   * **Private access** (VNet Integration): recommended for production if the VM is in the same virtual network
   * **Public access:** with a firewall rule restricting access to the VM's public IP (rule name `allow-vm`, start/end IP = VM's public IP)

Expected: server shows Available status.

#### Step 5: Create the `insightly` Database

**On the VM (or Azure Portal):**

`insightly` is Hivel's fixed database name, not a placeholder to rename.

```bash
# Azure Flexible Server requires SSL by default
psql "host=<your-server>.postgres.database.azure.com port=5432 dbname=postgres user=<admin-username> password=<admin-password> sslmode=require"

CREATE DATABASE insightly;
\q
```

If you only have console access, use Azure Portal > your PostgreSQL server > Query editor (preview), connect with admin credentials, and run `CREATE DATABASE insightly;`.

If creation fails: a connection timeout means the firewall rule hasn't been added (recheck Step 4); an SSL-related error means `sslmode=require` was omitted.

#### Step 6: Download the Installer and License Files

**On the VM:**

```bash
cd /opt

# Download the package from S3
aws s3 cp s3://hivel-on-prem-logs/hivel-agent-onprem-deploy/hivel-onprem.zip ./

# Extract the package
unzip hivel-onprem.zip
cd hivel-onprem

# Make deploy script executable
chmod +x deploy.sh
```

Confirm with `ls` that `deploy.sh`, `config/`, `license/`, `services/`, and `scripts/` are present. Get your exact S3 bucket path or pre-signed URL from Hivel support. If download fails with "Access Denied," your AWS credentials lack S3 permission; confirm with Hivel which credentials to use or request a pre-signed URL.

> **Copy license files:**
>
> Locate your license files (they may not be in the `license/` directory initially), then copy them to `/opt/hivel-onprem/license/`:

```bash
# Copy license files to the license directory
cp license/license_signed.json license/
cp license/hivel_onprem_public.pem license/

# Verify
ls -l license/
```

#### Step 7: Test AWS ECR Access

**On the VM:**

Hivel's Docker images are stored in AWS ECR at `730335373269.dkr.ecr.ap-south-1.amazonaws.com`.

```bash
aws ecr get-login-password --region ap-south-1 | \
  docker login --username AWS --password-stdin \
  730335373269.dkr.ecr.ap-south-1.amazonaws.com
```

Expected: `Login Succeeded`. `deploy.sh` handles ECR authentication automatically from here on.

Using your own ECR instead is an advanced path: push Hivel's images to your own AWS repositories and update image URLs in `services/vm/docker-compose.yml` plus `ECR_REGISTRY`/`AWS_REGION` variables in `deploy.sh`. Only do this if your organization requires images in your own infrastructure.

#### Step 8: Configure the Environment File: Phase 1 (Migration Credentials)

**On the VM:**

```bash
cd /opt/hivel-onprem
cp config/.env.template config/.env
nano config/.env
```

Set the database variables to your PostgreSQL server's **admin** credentials:

```
# Your Azure PostgreSQL server host (from Azure Portal)
DB_HOST=your-server.postgres.database.azure.com

# Port (usually 5432)
DB_PORT=5432

# Database name (must be "insightly")
DB_NAME=insightly

# Server admin username (for migration only)
DB_USER=postgres

# Server admin password (for migration only)
DB_PASSWORD='your_admin_password'
```

If credentials are stored in Azure Key Vault:

```bash
az keyvault secret show --vault-name <your-vault-name> --name <secret-name> --query value -o tsv
```

###

> Passwords containing `()[]$&|;#<>*` or spaces must be wrapped in single quotes. A literal `$` must be written as `$$` even inside single quotes because Docker Compose interpolates `$VAR`. A literal single quote in the password is not allowed; choose a different password if needed.

#### Step 9: Verify Database Connectivity

**On the VM:**

```bash
# Install PostgreSQL client (if not already installed)
sudo apt update && sudo apt install -y postgresql-client

# Test connection (Azure requires SSL by default)
psql "host=$DB_HOST port=$DB_PORT dbname=$DB_NAME user=$DB_USER password=$DB_PASSWORD sslmode=require"

# Or using environment variables
export PGPASSWORD='your_password'
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -p $DB_PORT
```

Expected result: an `insightly=#` prompt with no errors. Do not continue until this works.

#### Step 10: Run the Database Migration

**On the VM:**

This runs once only, before any other services start. Verify `.env` currently holds Phase 1 (admin) credentials first; running migration with limited privileges will fail.

```bash
cd /opt/hivel-onprem

# Verify .env has admin credentials
cat config/.env | grep DB_USER
cat config/.env | grep DB_PASSWORD

# Run the one-time migration
./deploy.sh --service flyway-migration
```

Wait 1 to 2 minutes for completion, then verify:

```bash
# Check migration logs
docker logs flyway-migration

# Check exit code (0 = success)
docker inspect flyway-migration --format='{{.State.ExitCode}}'

# Check container status
docker ps -a | grep flyway-migration
```

Success: exit code `0`, logs containing "Successfully applied X migration(s)" and "user `<user>` created", container status "Exited (0)". Do not proceed if migration failed or rerun on an already-initialized database.

#### Step 11: Switch the Environment File to Application Credentials: Phase 2

**On the VM:**

```bash
nano config/.env
```

Update these values:

```
DB_USER=<user>
DB_PASSWORD='<password>'  # Default password (or your custom password)
```

The default application username and password are created by flyway-migration. If you customized the password before running migration, use that same password here. All services from this point on connect using this application user, not the server admin account.

#### Step 12: Deploy All Services

**On the VM:**

```bash
cd /opt/hivel-onprem

# Deploy all VM services
./deploy.sh --vm
```

Available `deploy.sh` commands:

```bash
./deploy.sh --all       # Deploy all services
./deploy.sh --vm        # Deploy VM services only
./deploy.sh --service <service-name>  # Deploy specific service
./deploy.sh --status    # Check service status
./deploy.sh --health    # Check service health
./deploy.sh --logs      # View logs
./deploy.sh --logs <service-name>     # View logs for one service
./deploy.sh --start     # Start services
./deploy.sh --stop      # Stop services
./deploy.sh --restart   # Restart services
./deploy.sh --update    # Update services (pull latest images)
./deploy.sh --list      # List all services
./deploy.sh --help      # Show help
```

> For specific service guidance, contact <support@hivel.ai>. Deploying with Docker Compose directly is available as an advanced alternative if you need custom orchestration.

#### Step 13: Set Up Log Rotation

**On the VM:**

```bash
cd /opt/hivel-onprem
sudo ./scripts/setup-log-rotation.sh

# Verify
sudo crontab -l
ls -la /var/log/hivel/

# Manually test rotation (optional)
sudo ./scripts/docker-log-rotate.sh
```

This creates `/var/log/hivel/`, adds a daily cron job at midnight, and configures rotation for all Docker containers with 7-day retention. Logs live at `/var/log/hivel/<service-name>/<service-name>-YYYY-MM-DD.log`.

#### Step 14: Verify the Deployment

**On the VM, then a browser:**

```bash
# Check all containers
docker ps
./deploy.sh --health

# Test service endpoints
curl http://localhost:80/health            # API Gateway
curl http://localhost:8095/health          # Auth Service
curl http://localhost:8082/hivelapi/health # Insightly Service
curl http://localhost:3000                 # UI
```

All containers should show `Up`/`healthy`, and each endpoint should return a healthy response.

Then access the app via one of these options:

* **Direct VM public IP** (testing/pilots only, no load balancing or HTTPS unless you also do Step 15): `http://<vm-public-ip>:3000`
* **Azure Load Balancer** (stable, no custom domain or HTTPS yet): create a Standard Load Balancer, configure a backend pool pointing to the VM on ports 80 and 3000, configure health probes and load balancing rules, access via the Load Balancer's public IP or DNS name
* **Azure DNS + Load Balancer** (recommended for production): create a Load Balancer or Application Gateway, create an Azure DNS zone for your domain, create an A record pointing to it, configure an SSL/TLS certificate (Application Gateway or Key Vault-managed). Access via `https://your-domain.com`. Alternatively, use Caddy (Step 15) for a lighter-weight HTTPS solution on smaller deployments

Deployment is complete when: all containers are healthy, every endpoint returns healthy, the app is reachable at your configured address, and at least one integration (Jira/GitHub/GitLab) is connected and shows data after Step 16.

#### Step 15 (Optional but Recommended): Enable HTTPS with Caddy

**In Azure Portal, then on the VM:**

Modern browsers restrict `crypto.randomUUID`, used on the sign-up page, to secure contexts (HTTPS or localhost). This is a lighter-weight alternative to standing up a full Load Balancer or Application Gateway, suitable for smaller deployments and pilots.

**In Azure Portal:** create an A record pointing your subdomain (e.g., `hivel.yourcompany.com`) at the VM's public IP. Use an Azure Static Public IP so the address doesn't change on restart.

```bash
# Verify DNS has propagated
dig +short hivel.yourcompany.com
```

**In the VM's Network Security Group:** add inbound rules for port 80 (source Any, required for Let's Encrypt's HTTP-01 validation) and port 443 (source Any, or your office/VPN CIDR).

**On the VM:**

```bash
mkdir -p ~/caddy && cd ~/caddy

cat > Caddyfile <<'EOF'
hivel.yourcompany.com {
  reverse_proxy localhost:3000
}
EOF

docker run -d --name caddy --restart unless-stopped --network host \
  -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile \
  -v caddy_data:/data \
  caddy:2

# Verify
docker logs -f caddy
```

Wait for a log line confirming the certificate was obtained, then open `https://hivel.yourcompany.com` in a browser. Expect a trusted certificate with no warnings.

> No domain yet? Use a temporary self-signed certificate for testing only; see the full DNS Setup guide's Option B, then upgrade once you have a domain.

#### Step 16: Sign Up and Connect Integrations

**In a browser, at the Hivel UI:**

1. Go to `http://<vm-public-ip>:3000/signup` (or your HTTPS domain), enter your email, create a password, and complete email verification
2. Log in. You'll be redirected to the Company Profile Creation page
3. Fill in your organization's details, select an approval method for new users, and continue to the Integration page
4. Connect the tools you need:
   * **GitLab:** your GitLab domain URL, the access-token user's name and email, your GitLab access token, API version `/api/v4`. Verify under Settings > Repository; you should see repositories being analyzed
   * **Jira:** your Jira URL (Cloud: `https://yourcompany.atlassian.net`), the access-token user's name and email, your Jira access token, API version `/rest/api/3/`
   * **SonarQube:** your SonarQube instance URL and access token

See [Integrations](https://docs.hivel.ai/integrations) for the full list of supported integrations.

{% content-ref url="/pages/0DjYyMycz6IX42k8sXub" %}
[Integrations](/integrations.md)
{% endcontent-ref %}

Initial data sync time depends on the volume of historical data. For issues during setup, see [Troubleshooting](https://docs.hivel.ai/self-managed-hivel-deployment/virtual-private-cloud/azure/hivel-on-premises-deployment-guide-azure/troubleshooting) or contact <support@hivel.ai>.

{% content-ref url="/pages/B5JSDAtfLEmLG3fCXLLu" %}
[Troubleshooting](/self-managed-hivel-deployment/virtual-private-cloud/azure/hivel-on-premises-deployment-guide-azure/troubleshooting.md)
{% endcontent-ref %}

***

Deployment complete. See the full [Azure Setup Guide](https://docs.hivel.ai/self-managed-hivel-deployment/virtual-private-cloud/azure) for detailed instructions.

{% columns %}
{% column width="33.33333333333333%" %} <a href="/self-managed-hivel-deployment/virtual-private-cloud/azure.md" class="button primary" data-icon="backward">Back to Azure</a>
{% endcolumn %}

{% column width="33.33333333333333%" %}

{% endcolumn %}

{% column %} <a href="/self-managed-hivel-deployment/virtual-private-cloud/azure/hivel-on-premises-deployment-guide-azure.md" class="button primary" data-icon="forward">Hivel On-Premises Deployment Guide (Azure)</a>
{% endcolumn %}
{% endcolumns %}
