Deployment guide

phpList

Overview

phpList is an open-source newsletter and email campaign manager. Charities, publishers, businesses and community groups use it to manage subscriber lists and send bulk email. One web console provides subscriber list management, subscribe, confirm and unsubscribe pages, an HTML and plain-text campaign editor, attribute-based segmentation, and open, click and bounce tracking.

The SecureAnyCloud image ships phpList 3 served by Apache and PHP 8.3 on a hardened Ubuntu 24.04 LTS base that is patched at build time. A bundled local MySQL server makes the appliance complete on its own. The database is already initialised and the administrator account is created, so no browser install wizard is ever exposed. The bundled MySQL listens only on the loopback interface (127.0.0.1:3306), and every VM generates a unique administrator password on first boot.

What you get:

  • phpList 3 served by Apache and PHP 8.3, managed by systemd
  • A bundled MySQL server that holds the phpList database, already installed and initialised
  • The database schema and admin account, created at build time so that no web install wizard is ever exposed
  • A per-VM administrator password, generated on first boot and recorded in a root-only file
  • No shipped default login: the administrator password ships rotated to a discarded random value, and the real per-VM password is set on first boot
  • MySQL bound to 127.0.0.1 only and never exposed to the network, with root authenticated by the local socket
  • The subscriber pages at /lists/ and the admin console at /lists/admin/
  • apache2.service and mysql.service as enabled systemd units
  • 24/7 SecureAnyCloud support

Prerequisites

You need the following:

  • An active Azure subscription
  • An SSH key pair
  • A virtual network and subnet in the target region
  • A VM size of Standard_B2s (2 vCPU / 4 GiB RAM) as a starting point. Choose a larger size for large lists or heavy send volumes.
  • Network security group inbound rules that allow 22/tcp from your management network, 80/tcp for the application, and 443/tcp if you terminate TLS on the VM

The bundled MySQL is never exposed. It listens on 127.0.0.1 only, so port 3306 stays off the network.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure portal, choose Create a resource, search the Marketplace for phpList by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22), HTTP (80) and HTTPS (443). Then choose Review + create and Create.

Step 2 - Deploy from the Azure CLI

Accept the Marketplace terms once per subscription, then create the VM:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:phplist-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name phplist \
  --image sac1647283583153:phplist-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open ports 80 and 443:

az vm open-port --resource-group <your-rg> --name phplist --port 80,443

Step 3 - Confirm the services are running

Connect over SSH as azureuser and confirm that Apache and MySQL are active. MySQL listens only on 127.0.0.1:3306, while Apache serves phpList on port 80.

systemctl is-active apache2 mysql
ss -tlnp | grep -E ':80 |:3306 ' | sed 's/ */ /g'

Step 4 - Retrieve the per-VM administrator password

Every VM generates its own phpList administrator password on first boot. It writes the password, the login user and the console URL to a root-only credentials file. Read the file with sudo:

sudo cat /root/phplist-credentials.txt

You sign in to the phpList admin console as the user admin, with the PHPLIST_ADMIN_PASSWORD value from this file. On the VM, you can also run sudo mysql to reach the database directly over the local socket without a password.

Step 5 - Sign in to the admin console

Browse to http://<vm-public-ip>/lists/admin/. The phpList sign-in page opens. Enter the username admin and the password from Step 4.

After you sign in, the phpList dashboard opens. The left navigation lists Subscribers, Campaigns, Statistics, System and Config. A Getting Started panel lets you import subscribers or start a campaign.

Step 6 - Manage subscriber lists

Open Subscribers, then Subscriber lists, to create and manage the lists that your subscribers belong to. Each list can be public (offered on the subscribe page) or private, and a subscriber can belong to several lists.

Choose Add a list to create a list. Choose Import subscribers to bring in existing contacts from a CSV file or a pasted list.

Step 7 - Compose and send a campaign

Open Campaigns, then Send a campaign. Compose the message, choose the lists to send it to, preview it, and then schedule or send it. phpList keeps draft campaigns, so you can work on a message over time before you send it.

Step 8 - Configure an SMTP relay to send mail

phpList composes and manages campaigns out of the box. To deliver email, you point it at your own SMTP relay, for example Azure Communication Services, SendGrid, Amazon SES, or your organisation's mail server. Open the configuration file:

sudo nano /var/www/html/phplist/public_html/lists/config/config.php

Set or add these lines with the details of your relay. Set TEST to 0 when you are ready to send real mail:

define('PHPMAILERHOST', 'smtp.your-provider.example'); $phpmailer_smtpuser = 'your-smtp-username'; $phpmailer_smtppassword = 'your-smtp-password'; define('PHPMAILER_SECURE', 'tls'); define('TEST', 0);

phpList sends queued campaigns when the message queue is processed. Process the queue with the bundled command-line tool:

sudo -u www-data /usr/local/bin/phplist -pprocessqueue

Once your relay is configured, add the command to a cron job, for example one that runs every five minutes.

Step 9 - No known or default credentials

The SecureAnyCloud image ships with the phpList administrator password rotated to a discarded random value. Every VM generates its real administrator password, a unique random secret, on first boot. No known or blank credential authenticates, and the admin account is the only phpList super user.

To confirm the admin account, list the super users:

sudo mysql -uroot -N -e "SELECT CONCAT(loginname,' (phpList super user)') FROM phplistdb.phplist_admin WHERE superuser=1"

Then run the built-in round-trip check. It confirms that the per-VM administrator signs in through the phpList login form, and that a blank password and common weak guesses are all rejected:

sudo bash /usr/local/sbin/phplist-cred-roundtrip.sh

Step 10 - Verify the stack and the endpoint

Confirm the installed phpList release, then confirm that the admin console answers on port 80:

sudo mysql -uroot -N -e "SELECT CONCAT('phpList ',value) FROM phplistdb.phplist_config WHERE item='version'"
curl -sI http://127.0.0.1/lists/admin/ | head -1

Adding your own domain and TLS

The appliance serves plain HTTP on port 80. To serve it over HTTPS, point a DNS record at your VM and obtain a certificate with Let's Encrypt:

sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d <your-domain>

phpList derives its page links from the request Host header. Once you reach the VM on your domain over HTTPS, the subscribe and admin links render correctly with no further change.

Backing up

Your data lives in the phpList database. Dump it with mysqldump over the local socket, then copy the archive off the VM:

sudo mysqldump --protocol=socket -uroot phplistdb > /tmp/phplist-backup.sql

To restore, load the SQL dump back into the phplistdb database. Uploaded campaign images live under the phpList tree at /var/www/html/phplist/public_html/lists/images. If you use uploaded images, archive that directory too.

Security notes

  • TLS. phpList serves plain HTTP on port 80 out of the box. For anything beyond a trusted network, add your own domain and TLS as described above, or front the VM with Azure Application Gateway.
  • MySQL. The bundled MySQL listens on 127.0.0.1 only and is never reachable from the network. root authenticates by the local socket, so administer MySQL on the VM with sudo mysql (no password required). Never expose port 3306.
  • Administrator password. The password is unique per VM, and no known or blank credential authenticates. Keep /root/phplist-credentials.txt protected. To rotate the web login password, sign in and change it under System, or set a new one directly from the VM:
sudo mysql phplistdb -e "UPDATE phplist_admin SET password=SHA2('<new-password>',256), passwordchanged=NOW() WHERE loginname='admin'"
  • Configuration. Apache denies access to the phpList configuration directory, so config.php is never reachable from the web.
  • Updates. Apply operating system updates regularly with sudo apt update && sudo apt upgrade. Unattended security updates are enabled by default.
  • Network access. Restrict inbound 80/tcp and 443/tcp in your network security group to the networks that need access.

Trademark

phpList is an open-source project distributed under the GNU Affero General Public License version 3. SecureAnyCloud independently packages this image from the open-source phpList software. The image is not affiliated with, sponsored by, or endorsed by phpList Ltd.

Support

SecureAnyCloud maintains this image and provides 24/7 support. If you need help deploying or operating phpList on Azure, contact us at secureanycloud.com.

Deploy on Azure

Launch phpList 3 Newsletter Manager 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

Deploy on Azure