Deploy Easy!Appointments | (Just Updated) Online Appointment Scheduling With REST API, Admin Password Generated

Easy!Appointments online appointment scheduling and booking, REST API

Deploy Easy!Appointments | (Just Updated) Online Appointment Scheduling With REST API, Admin Password Generated

Just deployed

/var/lib/mysql

Just deployed

/var/www/html/storage

Deploy and Host Easy!Appointments on Railway

Built for an LLM agent to deploy and use. The deploy form has no fields to fill: the administrator password is generated, the database is wired in, the Easy!Appointments installer runs by itself on first boot, and uploads, backups and the database sit on volumes. Easy!Appointments is an open-source, self-hosted appointment scheduler: a public booking page for customers, calendars for providers and secretaries, services, working plans, email notifications, Google Calendar sync and a REST API.

About Hosting Easy!Appointments

This template runs two services: easyappointments (the application on one public domain, with a volume at /var/www/html/storage holding uploads, backups, logs and sessions) and mariadb (MariaDB 11.8 with a volume at /var/lib/mysql). Appointments, customers, services and settings survive redeploys.

No wizard, no default login. Upstream expects someone to open a browser and fill in an installation form. This template runs the same installer at first boot with the administrator admin and the generated EA_ADMIN_PASSWORD (32 characters), so the instance is never reachable half-installed. The wrapper refuses to start with a password under 12 characters. The healthcheck is the front page /, which answers 307 and then 503 until the installer has finished, so Railway marks the deploy live only once the administrator exists.

What the wrapper fixes for Railway. Apache is moved onto Railway's injected PORT (upstream listens on 80). The base URL is derived from the public domain, so booking links and emails use https. Sessions are no longer bound to the client IP (sess_match_ip off), because Railway's edge address changes per request and would sign every user out on the next click. The storage directory is reseeded and handed to the web user on every start, because a volume arrives root-owned and hides the .htaccess files that keep uploads and backups private. A half-finished install is cleared before a new one starts. Upstream is Easy!Appointments 1.6.1, pinned by digest.

Using it. Sign in at https://YOUR_DOMAIN/index.php/login as admin with EA_ADMIN_PASSWORD (the username is fixed, it is not a template variable). Customers book at https://YOUR_DOMAIN/. To send email notifications set the SMTP variables on the easyappointments service (MAIL_PROTOCOL=smtp, MAIL_SMTP_HOST, MAIL_SMTP_PORT, MAIL_SMTP_USER, MAIL_SMTP_PASS, MAIL_SMTP_CRYPTO); the application works without them.

Agent contract

  • Public URL: https://RAILWAY_PUBLIC_DOMAIN (the generated domain of the easyappointments service; the REST API is under /index.php/api/v1)
  • Private URL: http://easyappointments.railway.internal:8080
  • Credentials: the variable EA_ADMIN_PASSWORD on the easyappointments service, for the fixed username admin (the username is not a template variable)
  • Auth: HTTP Basic on the REST API, Authorization: Basic base64(admin:EA_ADMIN_PASSWORD) (curl -u). A request with no credentials, or with a wrong password, answers 401, for reads and for writes alike.
  • Health: GET / returns 200 (it answers 307 and then 503 for the few seconds the installer runs on the first boot)
#!/bin/sh
# needs: RAILWAY_PUBLIC_DOMAIN, EA_ADMIN_PASSWORD (variables of the easyappointments service); also curl. Creates one throwaway customer.
R="https://$RAILWAY_PUBLIC_DOMAIN"; B="$R/index.php"
# first boot runs the installer (under a minute); wait for the front page
n=0; until [ "$(curl -s -o /dev/null -w '%{http_code}' "$R/")" = 200 ]; do n=$((n+1)); [ "$n" -le 60 ] || break; sleep 5; done
curl -s -o /dev/null -w "health: %{http_code}\n" "$R/"
curl -s -o /dev/null -w "read with key: %{http_code}\n" -u "admin:$EA_ADMIN_PASSWORD" "$B/api/v1/customers"
curl -s -o /dev/null -w "read without key: %{http_code}\n" "$B/api/v1/customers"
E="agent$(date +%s)@example.com"
D="{\"firstName\":\"Agent\",\"lastName\":\"Test\",\"email\":\"$E\",\"phone\":\"+10000000001\"}"
curl -s -o /dev/null -w "write with key: %{http_code}\n" -u "admin:$EA_ADMIN_PASSWORD" -X POST "$B/api/v1/customers" -H "Content-Type: application/json" -d "$D"
curl -s -u "admin:$EA_ADMIN_PASSWORD" "$B/api/v1/customers" | grep -c "$E" | sed 's/^/customer found after write: /'
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X POST "$B/api/v1/customers" -H "Content-Type: application/json" -d "$D"
curl -s -o /dev/null -w "write with wrong key: %{http_code}\n" -u "admin:${EA_ADMIN_PASSWORD}x" -X POST "$B/api/v1/customers" -H "Content-Type: application/json" -d "$D"

A fresh deploy prints health: 200, read with key: 200, read without key: 401, write with key: 201, customer found after write: 1, write without key: 401 and write with wrong key: 401.

Why Deploy Easy!Appointments on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Easy!Appointments on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

  • Agent-ready - no deployer fields, a contract block and one script that proves the installer finished, an authenticated read and write over the REST API, and the refusal of a write with no key or a wrong one.
  • No wizard and no default login - the administrator is created at first boot from a generated password.
  • Data survives redeploys - the database and the storage directory sit on volumes.
  • Pinned - the upstream image is pinned by digest and the wrapper by tag and digest.
  • Your bookings on your domain - customers, appointments and calendars stay on infrastructure you control.

Common Use Cases

  • Run a booking page for a small business - salons, clinics, tutors, consultants and repair shops let customers pick a service, a provider and a slot.
  • Replace a paid scheduling SaaS - keep customer data and calendars on your own domain without per-seat pricing.
  • Several providers and services - each provider has a working plan and breaks, each service has its own duration and price.
  • Agent-driven scheduling - give an agent the REST API to create customers, read availabilities and book or cancel appointments.

Dependencies for Easy!Appointments Hosting

  • The easyappointments service and the mariadb service with their volumes, created by the template. A custom domain and an SMTP account are optional.

Deployment Dependencies


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
51
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
52