Developer Tools Azure

Apollo Config on Ubuntu 24.04 on Azure User Guide

| Product: Apollo Config on Ubuntu 24.04 LTS on Azure

Overview

Apollo is an open source distributed configuration management centre. Applications fetch typed, versioned configuration at runtime and pick up changes without a redeploy, while operators get per environment and per cluster namespaces, release and rollback history, grey scale (canary) releases and a complete audit trail of every change. A web portal manages all of it, so configuration stops living in scattered property files and becomes a governed, reviewable resource.

The cloudimg image installs Apollo 2.5.2 from the official release distribution under /opt/apollo and runs the full three service topology on a single VM, backed by an on box MySQL 8.0 with both Apollo schemas already created and seeded:

Component Port Bound to Role
apollo-portal 8070 all interfaces the web console you sign in to
apollo-configservice 8080 127.0.0.1 serves configuration to client apps, hosts the Eureka meta server
apollo-adminservice 8090 127.0.0.1 privileged management API used by the portal
mysqld 3306 127.0.0.1 ApolloConfigDB and ApolloPortalDB

Only the portal is reachable from the network. Apollo's config service is unauthenticated by default, meaning any caller that knows an application id can read that application's configuration unless per namespace access keys are enabled, and the admin service is a privileged API intended only for the portal. Shipping either one open to the network would be unsafe, so this image binds both to the loopback interface. Step 9 explains how to deliberately expose the config service to your own application subnet once you are ready to onboard client applications.

Secure by default: Apollo's published sample data seeds the portal user apollo with the well known password admin. This image ships neither that password nor any other usable login. Cleanup locks the account outright, and an apollo-config-firstboot.service oneshot runs once before the Apollo services start to generate a unique portal administrator password, a unique database password and a unique database root password for your VM, writing them to a root only file. No two instances share a credential.

What is included:

  • Apollo 2.5.2 (Apache-2.0) under /opt/apollo, installed from the official release zips with published checksums verified
  • MySQL 8.0 with the ApolloConfigDB and ApolloPortalDB schemas created and seeded
  • apollo-portal, apollo-configservice and apollo-adminservice running as the dedicated apollo system user on Java 17
  • apollo-config-firstboot.service that generates every credential per VM on first boot
  • Per VM credentials written to /root/apollo-config-credentials.txt (mode 0600, root only)
  • OpenJDK 17 runtime, apt managed for security updates

Prerequisites

  • An Azure subscription with permission to create virtual machines
  • An SSH key pair for administrative access
  • A VM size with at least 8 GiB of memory. Apollo runs three JVMs alongside MySQL, so Standard_B2ms (2 vCPU, 8 GiB) is the recommended minimum for real workloads.

Step 1: Deploy from the Azure Portal

In the Azure Portal choose Create a resource, search for Apollo Config on Ubuntu 24.04 LTS from cloudimg, and select Create. Choose your subscription, resource group and region, set the VM size to Standard_B2ms or larger, and select SSH public key as the authentication type with the username azureuser. Under Inbound port rules allow SSH (22), then add port 8070 for the Apollo portal. Review and create.

Step 2: Deploy from the Azure CLI

Restrict both SSH and the portal to your own management network rather than opening them to the internet.

RG="apollo-config-prod"; LOCATION="eastus"; VM_NAME="apollo-config-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/apollo-config-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name apollo-vnet --address-prefix 10.90.0.0/16 --subnet-name apollo-subnet --subnet-prefix 10.90.1.0/24
az network nsg create -g "$RG" --name apollo-nsg
az network nsg rule create -g "$RG" --nsg-name apollo-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name apollo-nsg --name allow-portal --priority 110 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 8070 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2ms --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name apollo-vnet --subnet apollo-subnet --nsg apollo-nsg --public-ip-sku Standard

Deployment takes two to three minutes. The first boot generates your credentials and starts the Apollo services.

Step 3: Connect via SSH

ssh azureuser@<vm-ip>

Step 4: Verify the services are running

Four units make up the appliance. All four should report active.

systemctl is-active mysql apollo-configservice apollo-adminservice apollo-portal

The four Apollo appliance services reporting active: MySQL, the config service, the admin service and the portal

Step 5: Confirm the listener posture

This is the security property worth checking on any configuration server. Only the portal on 8070 and SSH on 22 accept connections from the network. The config service, the admin service and MySQL are bound to the loopback interface and cannot be reached from off the VM.

ss -tlnp | grep -E ':8070|:8080|:8090|:3306|:22 ' | sed 's/  */ /g'

Addresses shown as [::ffff:127.0.0.1] are IPv4 mapped loopback, which is how a Java listener bound to 127.0.0.1 is reported.

The listener set showing the portal on 8070 and SSH on 22 reachable, with the config service, admin service and MySQL bound to loopback

Step 6: Retrieve your per VM credentials

There is no shared default login. On first boot the image generated a unique portal administrator password for this VM and stored it in a root only file.

sudo cat /root/apollo-config-credentials.txt 2>/dev/null || echo "credentials are generated on first boot"

The file lists the portal URL, your unique apollo password, the database password and the MySQL root password (mode 0600, owner root). Keep it safe.

Step 7: Confirm the stack is healthy end to end

The portal answers on 8070, and the loopback bound config service answers its meta server endpoint. The POST /signin endpoint establishes a session for your per VM administrator password.

curl -s -o /dev/null -w 'portal        -> HTTP %{http_code}\n' http://127.0.0.1:8070/
curl -s -o /dev/null -w 'config service -> HTTP %{http_code}\n' http://127.0.0.1:8080/services/config
PW=$(sudo sed -n 's/^APOLLO_PORTAL_PASSWORD=//p' /root/apollo-config-credentials.txt 2>/dev/null)
CJ=$(mktemp)
curl -s -o /dev/null -c "$CJ" -X POST http://127.0.0.1:8070/signin \
  -d username=apollo --data-urlencode "password=${PW:-<portal-password>}"
curl -s -b "$CJ" http://127.0.0.1:8070/user \
  | python3 -c 'import sys;d=sys.stdin.read();print("portal sign in OK" if "userId" in d else "sign in with the password from /root/apollo-config-credentials.txt")'
rm -f "$CJ"

Java, MySQL and Apollo versions alongside the two Apollo schemas present in MySQL

Step 8: Sign in to the portal and create your first project

Open http://<vm-ip>:8070/ in your browser and sign in with the username apollo and the password from /root/apollo-config-credentials.txt.

The Apollo portal sign in page served on port 8070

Choose Create project. Give the project a department, an App Id that your application will use to identify itself, an App Name and an owner, then submit.

The Apollo create project form showing the department, App Id, App Name and owner fields

Your project now appears on the portal home page.

The Apollo portal home page listing the newly created project with its App Id, name, department and owner

Open the project to reach its configuration view. Select the DEV environment, choose Add Configuration to add a key and value, then choose Release to publish it. Released items become visible to client applications immediately; the Release History and Rollback controls let you review and revert any change.

The Apollo configuration view showing a released configuration item in the DEV environment with the release, rollback and history controls

Step 9: Connect your applications to the config service

Client applications read configuration from the config service on port 8080, which this image binds to the loopback interface so that nothing unauthenticated is exposed by default. An application running on this same VM can use it immediately:

curl -s "http://127.0.0.1:8080/services/config" | head -c 300; echo

The config service meta server responding on loopback and a released configuration item read directly from ApolloConfigDB

To let applications on other machines read configuration, expose the config service deliberately rather than by default:

  1. Enable access keys first. In the portal open your project and choose Manage AccessKey, then create and enable a key. Client applications must then sign their requests, so knowing an App Id is no longer enough to read configuration.
  2. Bind the config service to a routable address. Edit /etc/systemd/system/apollo-configservice.service and change -Dserver.address=127.0.0.1 to the VM's private address, then run sudo systemctl daemon-reload && sudo systemctl restart apollo-configservice.
  3. Restrict the network path. Add an Azure network security group rule that allows 8080 only from your application subnet, never from the internet.

Leave the admin service on port 8090 bound to loopback. It is a privileged management API with no authentication of its own and is only ever called by the portal on this VM.

Step 10: How secure by default works

Apollo's published sample SQL seeds the portal user apollo with a BCrypt hash of the password admin, a value documented in Apollo's own quick start. An image that shipped that hash would give every customer the same publicly known administrator login.

This image removes it in two stages. During the build the account is locked: the seeded hash is replaced with a value that no password can match, so the captured image contains no usable portal login at all. Then on your VM's first boot, before any Apollo service starts, apollo-config-firstboot.service generates a random portal password, hashes it, and writes it into ApolloPortalDB, alongside fresh per VM passwords for the Apollo database user and MySQL root. The database credentials are written to a single systemd environment file with an atomic rename, so a partially written file can never leave the services in a broken state.

The result is that the documented apollo / admin login is rejected on every VM launched from this image, and each VM's credentials are unique to it.

The oneshot marks itself complete with a sentinel so it never re runs and never re rotates a credential you have started using:

ls -l /var/lib/cloudimg/apollo-config-firstboot.done 2>/dev/null || echo "first boot has not run yet"
sudo ls -l /root/apollo-config-credentials.txt 2>/dev/null || echo "written on first boot"

Step 11: Enable HTTPS

The portal serves plain HTTP on 8070. For production, terminate TLS in front of it. Install a reverse proxy, point it at 127.0.0.1:8070, obtain a certificate for your domain, and then restrict the network security group so that only the proxy port is reachable.

Managing the services

sudo systemctl status apollo-portal --no-pager
sudo systemctl restart apollo-portal
sudo journalctl -u apollo-portal -n 50 --no-pager

Restarting the whole appliance in dependency order:

sudo systemctl restart apollo-configservice apollo-adminservice apollo-portal

Application logs are written under /var/log/apollo.

Support

This image is published and supported by cloudimg. For assistance contact support@cloudimg.co.uk. Apollo is a trademark of its respective owners. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.