Deployment guide

Easy Appointments

Overview

Easy!Appointments is an open source, self-hosted online appointment scheduler. Customers pick a service, a provider and an available time slot on a public booking page, around the clock. You manage appointments, customers, services, providers and secretaries from the admin calendar, with working plans, blocked periods and exceptions.

It sends email and ICS notifications, syncs provider calendars with Google Calendar and CalDAV, and exposes a REST API. This SecureAnyCloud image delivers Easy!Appointments fully installed and configured on Ubuntu 24.04 as a LAMP application, so a complete scheduling system runs within minutes of launch and your booking data stays on your own server.

Easy!Appointments is licensed under the GNU General Public License v3.0 (GPL-3.0). All product and company names are trademarks or registered trademarks of their respective holders. This image repackages the upstream open source release with SecureAnyCloud's provisioning and support.

What you get:

  • Easy!Appointments 1.6.0 (GPL-3.0), served from /var/www/easyappointments
  • PHP 8.3 (php8.3-fpm), MariaDB and nginx, all from Ubuntu 24.04 main, with the public booking page and admin backend on port 80
  • The MariaDB database on a dedicated, independently resizable data disk mounted at /var/lib/mysql
  • A per-VM administrator password and MariaDB password, both generated on first boot and written to a root-only file, so no default or shared login ships in the image
  • mariadb.service, php8.3-fpm.service and nginx.service as enabled, active systemd units, with MariaDB bound to loopback only
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting size. Scale up for busier booking pages.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp (HTTP) from your users.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Easy!Appointments 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) and HTTP (80).

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

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

Open HTTP so you can reach the booking page and admin backend:

az vm open-port --resource-group <your-rg> --name easy-appointments --port 80 --priority 900

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

Check that the three services behind Easy!Appointments all report active. The public booking page (GET /) and the admin login page both answer HTTP 200 on port 80:

systemctl is-active mariadb php8.3-fpm nginx curl -s -o /dev/null -w 'GET / -> %{http_code}\n' http://127.0.0.1/ curl -s -o /dev/null -w 'GET /index.php/login -> %{http_code}\n' http://127.0.0.1/index.php/login

Expected output is three lines of active, then GET / -> 200 (the public booking page) and GET /index.php/login -> 200 (the admin sign-in page).

Only nginx on port 80 is exposed. php-fpm runs behind it, and MariaDB listens on loopback only.

Step 5 - Retrieve your administrator password

On the first boot of every VM, a one-shot service (easy-appointments-firstboot.service) generates credentials that are unique to that VM: a fresh MariaDB password and a fresh administrator password.

The service also installs the application schema, creates the administrator account and pins the application to your VM's own address. No shared or default credentials ship in the image. Read the credentials file as root:

sudo cat /root/easy-appointments-credentials.txt

The file (mode 0600, root only) contains the administrator login (ea.admin.login, which is administrator), the administrator password (ea.admin.pass), and the booking page and admin backend URLs.

You can verify the login round-trip from the VM's own shell. Easy!Appointments signs in through a JSON endpoint that carries a CSRF token. The command below reads the per-VM password, fetches the token and posts a real sign-in. A correct password answers "success":true. A wrong password is rejected with "success":false.

PASS=$(sudo grep '^ea.admin.pass=' /root/easy-appointments-credentials.txt | cut -d= -f2-)
J=$(mktemp)
T=$(curl -s -c "$J" -b "$J" http://127.0.0.1/index.php/login | grep -oE '"csrf_token":"[^"]+"' | head -1 | sed -E 's/.*"csrf_token":"([^"]+)".*/\1/')
echo -n 'good password -> '; curl -s -c "$J" -b "$J" -H 'X-Requested-With: XMLHttpRequest' \
  --data-urlencode "username=administrator" --data-urlencode "password=$PASS" --data-urlencode "csrf_token=$T" \
  http://127.0.0.1/index.php/login/validate;
echo rm -f "$J"

Expected output: good password -> {"success":true,...}. This confirms that the credentials in the file sign in.

Step 6 - Open the booking page and sign in to the backend

Browse to http://<vm-public-ip>/ for the public booking page. In a short wizard, customers pick a service, a provider and an available time slot, then confirm their appointment.

The admin backend is at http://<vm-public-ip>/index.php/login. Sign in with the login administrator and the password from the credentials file.

After you sign in, you land on the admin calendar. There you manage appointments across providers in day, week and month views.

Step 7 - Add your services and providers

In the backend navigation, open Services to define the services customers can book, with a name, duration, price and category. Then open Users to add providers and secretaries and set their working plans.

The public booking page updates automatically as you add services and providers.

Step 8 - Confirm the version and the data disk

grep -oE "\\\$config\['version'\] = '[^']+'" /var/www/easyappointments/application/config/app.php php -v | head -1 findmnt /var/lib/mysql

Expected output: $config['version'] = '1.6.0', PHP 8.3, and /var/lib/mysql mounted from the dedicated data disk (/dev/sdc).

The booking database lives on that disk, which is independently resizable and survives instance replacement. To add room, resize the disk from the Azure portal.

First-boot service and security model

A one-shot easy-appointments-firstboot.service runs after MariaDB and php-fpm are up. On first boot it does the following:

  • Generates a per-VM MariaDB password and a per-VM administrator password
  • Installs the schema with the Easy!Appointments console installer
  • Rotates the administrator password to the generated value, hard-gated so the stored hash always matches the credentials file
  • Pins the application URL to the VM's own address
  • Writes the credentials file at mode 0600 (root only)
  • Drops a sentinel so the service runs exactly once

Verify the service state and the credentials file permissions:

systemctl is-active easy-appointments-firstboot.service
sudo stat -c '%a %U:%G %n' /root/easy-appointments-credentials.txt

Expected output: active, then 600 root:root /root/easy-appointments-credentials.txt.

Enabling HTTPS with your own domain

The image serves the booking page over plain HTTP on port 80. For a browser-trusted certificate, point a DNS record at the VM and install a certificate from your CA, for example Let's Encrypt:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

Certbot updates the nginx site to serve your domain certificate. Then set the application base URL to your domain in /var/www/easyappointments/config.php (const BASE_URL), so generated links and the booking page use your domain.

Backup and maintenance

Easy!Appointments stores its data in the MariaDB easyappointments database on the dedicated data disk. Back up the database with mariadb-dump. For a full point-in-time copy, snapshot the data disk and OS disk from the Azure portal.

sudo mariadb-dump --single-transaction easyappointments | gzip > /var/backups/easyappointments-$(date +%F).sql.gz

Keep the OS current with sudo apt-get update && sudo apt-get upgrade. The image ships with unattended security updates enabled. Review the Easy!Appointments documentation before you move between major versions.

Support

This image is backed by 24/7 SecureAnyCloud support for deployment, services and providers setup, working plans and availability, email and calendar notifications, Google Calendar and CalDAV sync, the REST API, user management, database tuning, TLS and scaling.

Email sales@secureanycloud.com or use the live chat in the support portal. Critical issues receive a one-hour average response.

Deploy on Azure

Launch Easy!Appointments 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