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.serviceandnginx.serviceas 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 StandardOpen 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 900Step 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/loginExpected 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.txtThe 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/mysqlExpected 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.txtExpected 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.comCertbot 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.gzKeep 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
Overview
Easy!Appointments is an open source, self-hosted web application that lets your customers book appointments online. Customers pick a service, a provider and an available time slot on a public booking page. You manage services, providers, secretaries, working plans and the appointment calendar from an admin backend.
This SecureAnyCloud image installs Easy!Appointments, a CodeIgniter 3 PHP application, under /var/www/easyappointments. nginx serves it and proxies dynamic requests to PHP 8.3 over php-fpm.
What you get:
- Application data in a MariaDB database whose data directory,
/var/lib/mysql, is a dedicated, independently resizable EBS data volume, which keeps the database off the operating system disk - An administrator account created on the first boot of every deployed instance, with a freshly generated password, so two instances launched from the same Amazon Machine Image never share a password
- Credentials written to
/root/easy-appointments-credentials.txtwith mode 0600, readable only by the root user
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and port 80 for the booking page and admin backend
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line
Launch the instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Easy!Appointments. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of t3.medium or larger. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet. Create or select a security group that opens port 22 from your management network and port 80 for the booking page and admin backend. Leave the root volume at the default size or larger.
Select Launch instance. First-boot initialization takes a few seconds after the instance state becomes Running and the status checks pass. During that time the database is created and the per-instance administrator is provisioned.
Launch the instance from the AWS CLI
Run the following command to launch an instance from the SecureAnyCloud Easy!Appointments Marketplace AMI into an existing subnet and security group.
Replace <ami-id> with the AMI ID shown on the Marketplace listing and <key-name> with your EC2 key pair name. Replace <subnet-id> with your subnet ID and <security-group-id> with a security group that opens ports 22 and 80 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type t3.medium \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=easyappointments}]'When the instance reaches the Running state and its status checks pass, note its public IP address or DNS name. You can find it in the EC2 console or with aws ec2 describe-instances.
Connect to your instance
Connect over SSH with your key pair and the login user for your operating system variant.
OS variant SSH login user
Ubuntu 24.04 ubuntu
ssh -i <key-name>.pem ubuntu@<public-ip>Retrieve the administrator password
The administrator password is unique to your instance and was generated on first boot. Read it as root:
sudo cat /root/easy-appointments-credentials.txtThe file lists the booking page URL, the admin backend login URL, the administrator login name and the generated password. Store this password somewhere safe.
Sign in to the admin backend
nginx serves the admin backend on port 80. In a browser, go to:
http://<instance-public-ip>/index.php/loginSign in with the login name administrator and the password from the credentials file.
After you sign in, you land on the appointment calendar. This is the central view where you manage bookings across your providers by day, week or month.
Confirm Easy!Appointments is running
Over SSH, confirm that the web server, the PHP processor and the database are active and that port 80 is listening:
sudo systemctl is-active nginx php8.3-fpm mariadb
sudo ss -tlnp | grep ':80 'All three services should report active, and nginx should listen on port 80. The MariaDB database listens on the loopback interface only and is never exposed directly.
Define your services
Open the Services menu in the backend. Each service is something a customer can book, with a duration, an optional price and a category. The image ships with one sample service, so the booking flow works immediately.
Select Add to create your own services. Set the Duration, Price and Availabilities Type, then save.
To present related services together on the booking page, group them with Categories from the same menu.
Add providers and their working plans
Open the Users menu and select Providers. A provider is a person customers book time with.
For each provider, set their name and contact details and tick the Services they offer. Then define their Working Plan: the weekly schedule of start and end times and breaks that determines which slots customers can book.
You can also add Secretaries, who manage appointments on behalf of one or more providers, and additional Admins.
Only the working hours you define are offered to customers, so set each provider's working plan before you share the booking page.
Share the public booking page
The public booking page is served at the root of the site and needs no login. Share this URL with your customers:
http://<instance-public-ip>/Customers choose a service and a provider, pick an available date and time, and enter their details to confirm the appointment. The slots offered reflect each provider's working plan and any existing bookings, blocked periods or working plan exceptions.
Confirmed appointments appear immediately on the admin calendar. Once you configure an SMTP server under Settings, the application can send confirmation and reminder emails.
Configure settings
Open the Settings menu, under the administrator account in the top right, to configure the application for your business:
- Business settings: your company name, email, working plan defaults, booking lead and cancellation times, and the time zone.
- General settings: the display name, the default language, the date and time format, and the appearance of the booking page.
- Localization: the language presented to customers on the booking page.
- Integrations: outbound email (SMTP) for confirmations and reminders, calendar synchronization, and webhooks.
The company name and details you set here are shown to customers on the booking page and in the emails they receive.
Check the data volume
The MariaDB database lives on a dedicated EBS volume mounted at /var/lib/mysql. This keeps the database off the operating system disk and lets you resize or snapshot it independently. Confirm the mount:
df -h /var/lib/mysqlTo grow the database store, expand the EBS volume in the AWS console. Then grow the filesystem on the instance with sudo resize2fs on the underlying device.
The application code under /var/www/easyappointments and any uploaded files in storage/uploads live on the root volume.
Enable HTTPS
nginx serves the booking page and admin backend over plain HTTP on port 80. For production use, place them behind TLS so that customer details and the administrator password are encrypted in transit.
Obtain a certificate for your domain. For example, use a managed certificate on an Application Load Balancer in front of the instance, or install Certbot on the instance. Then configure nginx to listen on 443 with your certificate and proxy to php-fpm exactly as the bundled site does for port 80.
After you point a domain name at the instance, set the application base URL to match so that links and redirects are correct. Edit the BASE_URL constant in /var/www/easyappointments/config.php and replace the value with your https:// site address. Then reload nginx:
sudo sed -i "s#const BASE_URL .*#const BASE_URL = 'https://your-domain.example';#" /var/www/easyappointments/config.php
sudo systemctl reload nginxRestrict the security group so that ports 80 and 443 are reachable only from the networks that need to book or administer appointments.
Back up and maintain the instance
Snapshot the /var/lib/mysql EBS volume to capture the entire database, and archive any uploaded files under /var/www/easyappointments/storage. You can also take a logical backup of the database over the loopback socket:
sudo mysqldump --protocol=socket easyappointments > easyappointments-backup.sqlApply operating system security updates with sudo apt-get update && sudo apt-get upgrade, and reboot when a new kernel is installed. nginx, php-fpm and MariaDB start automatically on boot.
Support
This image is published and supported by SecureAnyCloud. Support covers deployment, service and provider configuration, working plans, email and calendar integration, TLS, the database volume and backups. To reach SecureAnyCloud, use the support channel listed on the AWS Marketplace listing.
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 AWS
Launch Easy!Appointments on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com