Apollo Config on Ubuntu 24.04 on Azure User Guide
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
ApolloConfigDBandApolloPortalDBschemas created and seeded apollo-portal,apollo-configserviceandapollo-adminservicerunning as the dedicatedapollosystem user on Java 17apollo-config-firstboot.servicethat generates every credential per VM on first boot- Per VM credentials written to
/root/apollo-config-credentials.txt(mode0600, 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

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.

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"

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.

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.

Your project now appears on the portal home page.

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.

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

To let applications on other machines read configuration, expose the config service deliberately rather than by default:
- 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.
- Bind the config service to a routable address. Edit
/etc/systemd/system/apollo-configservice.serviceand change-Dserver.address=127.0.0.1to the VM's private address, then runsudo systemctl daemon-reload && sudo systemctl restart apollo-configservice. - 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.