ISPConfig Hosting Control Panel on Ubuntu 24.04 on Azure User Guide
Overview
This guide covers the deployment and configuration of ISPConfig 3.3 on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. ISPConfig is the open source hosting control panel that lets you run a web hosting server from a browser: it manages Apache web sites and their PHP settings, MariaDB databases, FTP accounts, clients and resellers from one interface.
The image installs ISPConfig with the official autoinstaller, focused on web, database and panel management: Apache 2.4, PHP, MariaDB and PureFTPd are wired together and the panel is served over HTTPS on port 8080. The mail (Postfix/Dovecot), DNS (BIND), firewall, Roundcube and phpMyAdmin modules are deliberately left out to keep the image lean and reduce attack surface; Step 10 shows how to add the mail and DNS modules if you want them.
Security by design, no baked login credential. Nothing usable ships in the image. On first boot ispconfig-firstboot.service generates a fresh MariaDB root password, a fresh panel database password, a fresh panel administrator password and a fresh remote API password, all unique to your VM, and writes them to /root/ispconfig-credentials.txt (mode 0600, root only). The build time secrets are locked and discarded, so no image and no person holds a working credential for your machine.
Security by design, the panel is held offline until the password is rotated. The panel is not served until first boot has generated your unique administrator password, so there is never a window in which a shipped default could be used, and the upstream admin / admin default is rejected outright.
Security by design, a per VM TLS certificate. A fresh self signed certificate for the panel is generated on first boot with your VM's address, so no two VMs share a key. Step 9 shows how to replace it with a trusted certificate.
What is included:
-
ISPConfig 3.3 hosting control panel, served over HTTPS on port 8080
-
Apache 2.4 + PHP 8.3 + MariaDB 10.11 + PureFTPd, configured and enabled
-
Per VM secret generation on first boot for the panel administrator, MariaDB root, panel database and remote API passwords
-
A per VM self signed panel TLS certificate, regenerated on first boot
-
The remote JSON-RPC API enabled for automated provisioning
-
Unattended security upgrades left enabled
Prerequisites
-
Active Azure subscription, SSH public key, VNet + subnet in the target region
-
Subscription to the ISPConfig listing on Azure Marketplace
-
Network Security Group rules allowing TCP 22 for administration and TCP 8080 for the control panel, both restricted to your own management network. Open TCP 80 and 443 as well once you start hosting web sites on the VM
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) to evaluate and run a small number of sites. Use Standard_B2ms or a Standard_D2s_v5 for a busier hosting server.
Step 1: Deploy from the Azure Portal
Search ISPConfig in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 22 and TCP 8080 from your management network only. Do not expose the panel to the whole internet until you have completed Step 9 and put a trusted certificate in front of it.
Step 2: Deploy from the Azure CLI
RG="ispconfig-prod"; LOCATION="eastus"; VM_NAME="ispconfig"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/ispconfig-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$GALLERY_IMAGE_ID" \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values "$SSH_KEY" \
--public-ip-sku Standard
Step 3: First boot
On the first boot the VM generates every secret it needs. ispconfig-firstboot.service runs once, before Apache starts serving the panel, and:
- rotates the MariaDB root password and the panel database password, rewriting ISPConfig's configuration files in lock step,
- rotates the panel administrator password and the remote API password,
- regenerates the self signed panel TLS certificate with the VM's address,
- writes everything to
/root/ispconfig-credentials.txtand drops a sentinel so it never runs again.
Give it about thirty seconds after the VM reports running, then connect over SSH and confirm the stack.
Step 4: Connect and confirm the stack is running
Connect over SSH:
ssh azureuser@<vm-ip>
Confirm the database and the panel are up:
systemctl is-active mariadb apache2
curl -ks -o /dev/null -w 'panel HTTP %{http_code}\n' https://127.0.0.1:8080/login/
MariaDB and Apache both report active, and the panel returns HTTP 200.

Confirm the component versions:
grep -oE "ISPC_APP_VERSION', *'[^']+'" /usr/local/ispconfig/interface/lib/config.inc.php
apache2 -v | head -1
php -v | head -1
mariadb --version

Confirm which ports are listening. Port 8080 is the control panel; ports 80 and 443 serve the web sites you host:
ss -tlnp | grep -E ':(8080|80|443) ' | awk '{print $1, $4}' | sort -u

Read your per VM credentials. This file is mode 0600 and readable only by root:
sudo cat /root/ispconfig-credentials.txt

The panel username is admin; the password is the ispconfig.admin.pass value in that file and is unique to your VM.
Step 5: First sign in to the control panel
Browse to https://<vm-ip>:8080/ and accept the self signed certificate warning (Step 9 replaces it with a trusted certificate). Sign in with the username admin and the ispconfig.admin.pass password from Step 4.

You land on the ISPConfig dashboard, with the Client, Sites, Monitor, Tools and System modules across the top and the available modules listed below.

The upstream default is rejected. ISPConfig normally ships with admin / admin; this image does not. You can confirm from the shell that the default no longer works and that your per VM password does, and that both the default and a blank password are refused:
sudo python3 /usr/local/sbin/ispconfig-panel-check.py && echo "per-VM password works; admin/admin and blank are rejected"
Step 6: Create your first client
Hosting in ISPConfig is organised around clients. Open the Client module and click Add new client to create a hosting customer, or drive it from the shell through the remote API in Step 8.

Step 7: Add a web site
Open the Sites module and click Add new website to provision an Apache virtual host, choose its PHP handler and version, and assign it to a client. ISPConfig writes the Apache configuration and the document root for you.

Step 8: Automate provisioning with the remote API
ISPConfig exposes a JSON-RPC remote API at /remote/json.php. The image ships a remote user (cloudimg_api) whose password is generated per VM and stored alongside the admin password in /root/ispconfig-credentials.txt. The following logs in, creates a client, reads it back and deletes it, proving the API end to end:
API_USER=$(sudo grep '^ispconfig.api.user=' /root/ispconfig-credentials.txt | cut -d= -f2)
API_PASS=$(sudo grep '^ispconfig.api.pass=' /root/ispconfig-credentials.txt | cut -d= -f2)
python3 - "$API_USER" "$API_PASS" <<'PY'
import sys, ssl, json, urllib.request, secrets
user, pw = sys.argv[1], sys.argv[2]
base = "https://127.0.0.1:8080"
ctx = ssl.create_default_context(); ctx.check_hostname = False; ctx.verify_mode = ssl.CERT_NONE
def call(fn, payload):
req = urllib.request.Request(base + "/remote/json.php?" + fn,
data=json.dumps(payload).encode(), headers={"Content-Type": "application/json"})
o = json.loads(urllib.request.urlopen(req, timeout=30, context=ctx).read().decode())
assert o.get("code") == "ok", "%s failed: %s" % (fn, o.get("message"))
return o.get("response")
sid = call("login", {"username": user, "password": pw})
name = "demo" + secrets.token_hex(3)
cid = int(call("client_add", {"session_id": sid, "reseller_id": 0, "params": {
"company_name": "Demo Hosting", "contact_name": "Demo", "username": name,
"password": secrets.token_hex(12), "email": name + "@example.com", "language": "en",
"usertheme": "default", "country": "US",
"web_php_options": "no,fast-cgi,php-fpm", "ssh_chroot": "no"}}))
got = call("client_get", {"session_id": sid, "client_id": cid})
print("created + read back client id", cid, "username", (got[0] if isinstance(got, list) else got)["username"])
call("client_delete", {"session_id": sid, "client_id": cid})
call("logout", {"session_id": sid})
print("API round-trip OK")
PY
Full remote API documentation is at docs.ispconfig.org.
Step 9: Put a trusted certificate on the panel
The panel ships with a per VM self signed certificate, so browsers warn on first use. Once you point a DNS name at the VM, obtain a Let's Encrypt certificate and place it where ISPConfig serves the panel:
sudo apt-get install -y certbot
sudo certbot certonly --standalone -d panel.your-domain.example
sudo cp /etc/letsencrypt/live/panel.your-domain.example/fullchain.pem /usr/local/ispconfig/interface/ssl/ispserver.crt
sudo cp /etc/letsencrypt/live/panel.your-domain.example/privkey.pem /usr/local/ispconfig/interface/ssl/ispserver.key
sudo cat /usr/local/ispconfig/interface/ssl/ispserver.key /usr/local/ispconfig/interface/ssl/ispserver.crt > /usr/local/ispconfig/interface/ssl/ispserver.pem
sudo systemctl restart apache2
Restrict the Network Security Group so port 8080 is reachable only from the networks that manage the server.
Step 10: Optionally enable the mail and DNS modules
This image is focused on web, database and panel management, so the mail and DNS server modules are not installed. To add them, re run the ISPConfig autoinstaller without the --no-mail or --no-dns switch, following the upstream documentation at docs.ispconfig.org, or install and configure Postfix, Dovecot and BIND and enable their ISPConfig server modules under System.
Step 11: Administration and upgrades
The panel lives under /usr/local/ispconfig, its interface configuration in /usr/local/ispconfig/interface/lib/config.inc.php, and hosted site data under /var/www. ISPConfig runs its periodic work from a cron entry that calls /usr/local/ispconfig/server/server.sh every minute; leave it in place.
Operating system and Apache, PHP and MariaDB packages continue to receive security updates through unattended upgrades. ISPConfig itself is pinned to the release this image shipped; follow the upstream release notes when you choose to move to a newer version.
Step 12: Security recommendations
-
Restrict the Network Security Group so TCP 22 and TCP 8080 are reachable only from your management networks, and put a trusted certificate in front of the panel before wider exposure (Step 9).
-
Treat
/root/ispconfig-credentials.txtas a one time handover: record the values in your password manager, then remove the file. -
Change the administrator password from the generated one after first sign in, under Tools -> Password and Language, and create named administrator accounts rather than sharing
admin. -
Keep MariaDB bound to the loopback interface. Nothing outside the VM needs to reach it directly.
-
Rotate the remote API user's password, or disable the remote user under System -> Remote Users, if you do not use the API.
Step 13: Support and Licensing
ISPConfig is free and open source software, published under the BSD 3-Clause License. Upstream project documentation is at docs.ispconfig.org.
This image is built and maintained by cloudimg. Support for the image, including deployment questions and security updates, is available 24/7 through the support channel listed on the Azure Marketplace offer page.