Apollo config
Overview
Apollo is an open source distributed configuration management center. Applications fetch typed, versioned configuration at runtime and pick up changes without a redeploy. 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 SecureAnyCloud image installs Apollo 2.5.2 from the official release distribution under /opt/apollo. It 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. Any caller that knows an application ID can read that application's configuration unless per-namespace access keys are enabled. 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 when 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.
An apollo-config-firstboot.service oneshot runs once before the Apollo services start. It generates a unique portal administrator password, a unique database password and a unique database root password for your VM, and writes them to a root-only file. No two instances share a credential.
What you get:
- 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.service, which 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.
Deploy from the Azure Portal
In the Azure Portal, choose Create a resource. Search for Apollo Config on Ubuntu 24.04 LTS from SecureAnyCloud, and select Create.
Choose your subscription, resource group and region. Set the VM size to Standard_B2ms or larger. 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. Select Review + create.
Deploy from the Azure CLI
Restrict both SSH and the portal to your own management network. Do not open them to the internet.
RG="apollo-config-prod"; LOCATION="eastus"; VM_NAME="apollo-config-01" IMAGE_URN="sac1647283583153:apollo-config-ubuntu-24-04:default:latest" 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
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:apollo-config-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--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 StandardDeployment takes two to three minutes. The first boot generates your credentials and starts the Apollo services.
Connect over SSH
ssh azureuser@<vm-ip>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-portalConfirm 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, so they 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. This is how a Java listener bound to 127.0.0.1 is reported.
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). Store it somewhere safe.
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 with 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"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. Enter 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. Use the Release History and Rollback controls to review and revert any change.
Connect your applications to the config service
Client applications read configuration from the config service on port 8080. This image binds it to the loopback interface, so 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; echoTo let applications on other machines read configuration, expose the config service deliberately:
- 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 only the portal on this VM calls it.
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 and before any Apollo service starts, apollo-config-firstboot.service generates a random portal password, hashes it and writes it into ApolloPortalDB. It also generates 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.
As a result, 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/sac/data/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"Enable HTTPS
The portal serves plain HTTP on 8070. For production, terminate TLS in front of it. Install a reverse proxy and point it at 127.0.0.1:8070. Obtain a certificate for your domain, 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-pagerTo restart the whole appliance in dependency order:
sudo systemctl restart apollo-configservice apollo-adminservice apollo-portalApplication logs are written under /var/log/apollo.
Support
This image is published and supported by SecureAnyCloud. For assistance, contact sales@secureanycloud.com. 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.
Deploy on Azure
Launch Apollo Config on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Apollo (apolloconfig/apollo) is an open source distributed configuration management center. Applications fetch typed, versioned configuration at runtime and receive updates in real time without a redeploy. Operators get per-environment and per-cluster namespaces, release and rollback history, grey-scale (canary) releases and a complete audit trail.
Instead of baking configuration into each application build, teams manage it centrally from one web console and push changes to running clients.
The SecureAnyCloud image delivers Apollo as a single-instance appliance. The config service, admin service and portal (three Java 17 Spring Boot services) run under systemd, backed by an on-box MySQL 8.0 database that holds the two Apollo schemas. Only the portal is reachable from the network, fronted by an nginx TLS reverse proxy. The config service, admin service and database are bound to localhost. The image is secure by default and installs nothing on first boot except your own credentials.
What you get:
- Apollo 2.5.2 (Apache-2.0), installed from the official GitHub release artifacts and SHA-verified at build time, with the LICENSE baked in at
/opt/apollo/LICENSE - The three Apollo services managed by systemd:
apollo-configservice(config service and embedded Eureka meta server,127.0.0.1:8080),apollo-adminservice(internal management API,127.0.0.1:8090) andapollo-portal(web console,127.0.0.1:8070) - MySQL 8.0 holding
ApolloConfigDBandApolloPortalDB, on a dedicated EBS data volume at/var/lib/mysql, listening on127.0.0.1:3306only - OpenJDK 17 from the Ubuntu repositories, so the Java runtime keeps receiving security updates
- An nginx TLS reverse proxy on port 443 in front of the portal, with a self-signed certificate regenerated per instance on first boot
- Per-instance portal administrator, application database, MySQL root and Debian maintenance passwords, all generated on first boot and written to a root-only file. The well-known upstream
apollo/adminportal login is destroyed in the image and is rejected on your instance - 24/7 SecureAnyCloud support
Connect to your instance
Connect over SSH on port 22, using the private key for the key pair you selected at launch. The login user depends on the operating system variant you launched:
OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i /path/to/your-key.pem ubuntu@<instance-public-ip>Prerequisites
You need an AWS account, an EC2 key pair and a VPC subnet. m5.large (2 vCPU, 8 GB RAM) is the recommended instance type and comfortably runs the three Apollo services plus MySQL. For large configuration estates or many client applications, move to an m5.xlarge or larger.
In the instance's security group, allow inbound TCP 443 from the addresses that should reach the portal, and TCP 22 for administration. Restricting 443 to your own office or VPN CIDR is strongly recommended. No other ports need to be open, because the config service, admin service and database are bound to localhost.
Step 1 - Launch from AWS Marketplace
In the AWS Marketplace console, find Apollo Config by SecureAnyCloud. Choose Continue to Subscribe, then Continue to Configuration and Continue to Launch.
Pick your Region, the m5.large instance type, your VPC subnet and your key pair. Choose a security group that allows inbound 22 and 443.
Step 2 - Launch from the AWS CLI
aws ec2 run-instances \
--image-id <ami-id-from-the-listing> \
--instance-type m5.large \
--key-name your-key \
--security-group-ids sg-xxxxxxxx \
--subnet-id subnet-xxxxxxxx \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=apollo-config}]'Step 3 - Confirm the services are running
All five services should report active. The only network-reachable ports are SSH (22) and the TLS portal (443). The config service, admin service and MySQL are bound to localhost:
for s in mysql nginx apollo-configservice apollo-adminservice apollo-portal; do echo "$s -> $(systemctl is-active "$s")" done echo "--- network-reachable TCP listeners (expect only :22 and :443) ---" ss -tlnH | awk '{print $4}' | grep -vE '127\.0\.0\.[0-9]+|\[::1\]' | sort -uThe portal answers over TLS on 443, and on its loopback port behind the proxy:
curl -sk -o /dev/null -w 'portal via nginx (https 443) -> HTTP %{http_code}\n' https://127.0.0.1/signin
curl -s -o /dev/null -w 'portal loopback (8070) -> HTTP %{http_code}\n' http://127.0.0.1:8070/signinStep 4 - Retrieve the portal password
Every instance generates its own portal administrator password on first boot. It writes the password, along with the database credentials, to a root-only file. Retrieve it over SSH:
sudo cat /root/apollo-config-credentials.txtThe file contains the portal URL, the portal user (apollo), the generated APOLLO_PORTAL_PASSWORD and the MySQL application and root passwords. The upstream default apollo / admin login does not work on your instance.
Step 5 - Sign in to the portal
Browse to https://<instance-public-ip>/. The image ships a self-signed certificate regenerated for your instance, so your browser warns on the first visit. Accept the warning, or install a trusted certificate (see the hardening section below).
Sign in as user apollo with the password from Step 4. After you sign in, you land on the project list, where every configured application appears with its owner and department.
Step 6 - Create your first application and configuration
Choose Create project. Enter an AppId (the identifier your client application uses to fetch configuration, for example order-service), a name and an owner, then create the project. Open the project and use Add Configuration to add typed key/value items to the application namespace.
Nothing is delivered to clients until you publish. Choose Release to publish the namespace. Each release is recorded with its author and comment. Open Release History to see every version, compare changes and roll back to a previous release with one click.
Step 7 - Consume configuration from a client application
Client applications fetch configuration from the config service. For security, the config service is bound to localhost by default, so a client running on the same instance reads it directly:
curl "http://127.0.0.1:8080/configs/order-service/default/application"The response is the released key/value set for that application, cluster and namespace. Apollo publishes official clients for Java and .NET, and any language can use the HTTP API above. Point the client at the config service address and set app.id to the AppId you created.
Step 8 - Expose the config service to your application subnet
When your client applications run on other hosts, expose the config service (port 8080) deliberately and safely. Do not open it to the world.
- In the Apollo portal, open Manage AccessKey for the application and enable an access key, so clients must authenticate to read configuration.
- Bind the config service to the instance's private address instead of loopback by editing its systemd unit override, or place it behind an internal load balancer. Open port 8080 only to your application subnet in the security group.
Leaving the config service on localhost with no access key, as shipped, is the safe default. Only workloads on the instance itself can read configuration until you choose to widen access.
Security and hardening
- Restrict the security group. Allow 443 only from trusted CIDRs and 22 only from your administration network.
- Install a trusted certificate. The image ships a self-signed certificate at
/etc/nginx/ssl/apollo.crt. For production, replace it with a certificate for your own domain. Alternatively, terminate TLS at an AWS load balancer with a certificate from AWS Certificate Manager, and put the portal behind it. - Enable EBS encryption for data at rest on the root and MySQL data volumes.
- Keep the database private. MySQL and the internal Apollo services listen only on localhost. Do not change this unless you have a specific need, and use access keys if you do.
- Migrate to Amazon RDS if you want managed backups and Multi-AZ failover for the configuration database.
Maintenance
Check the status and logs of any service with systemd and the journal:
systemctl status apollo-portal --no-pager | head -5Ubuntu's unattended-upgrades delivers operating system security updates, and the OpenJDK runtime is apt-managed so it keeps receiving updates. The Apollo services restart automatically on failure and on reboot.
Support
Every subscription includes 24/7 SecureAnyCloud technical support by email (sales@secureanycloud.com) and live chat. Support covers deployment, upgrades, performance tuning, database administration and integrating Apollo with your applications.
Deploy on AWS
Launch Apollo Config with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com