Applications AWS

HortusFox Plant Management on AWS User Guide

| Product: HortusFox Plant Management on AWS

Overview

HortusFox is a free, open source self hosted collaborative plant and garden management system built on PHP and the Asatru framework. It organises plants by location and gives you a plant inventory, watering and care task scheduling, a photo gallery, a journal and history view, a calendar, inventory tracking and a collaborative group chat, all behind an admin dashboard and a REST API. The cloudimg AMI delivers HortusFox fully installed and configured on Ubuntu 24.04 LTS — a PHP 8.3 application served by nginx over HTTPS with php-fpm, backed by MariaDB 11.4 LTS bound to the loopback interface. The schema is migrated, default plant attributes and calendar classes are seeded, an initial workspace and admin account are created, and one starter location is added, so you land directly on a working sign-in with nothing to install. The database and the application tree each live on their own dedicated EBS volume. Backed by 24/7 cloudimg support.

What is included:

  • HortusFox 5.8 (MIT licensed), served from /var/www/hortusfox/public
  • nginx (TLS on :443, with :80 redirected to HTTPS) + PHP 8.3 (php8.3-fpm with OPcache) + MariaDB 11.4 LTS bound to 127.0.0.1
  • A per-instance self-signed TLS certificate generated on first boot, so the interface loads over a secure context
  • Per-instance administrator password, MariaDB password and cronjob token, all generated at first boot and written to a root-only file — no default or blank login ships in the image
  • A production-grade two-disk layout: the MariaDB database (/var/lib/mysql) and the HortusFox application tree (/var/www, including uploaded plant photos) each on their own independently resizable EBS volume
  • nginx.service, php8.3-fpm.service and mariadb.service as systemd units, enabled and active
  • 24/7 cloudimg support

HortusFox sign-in page

Prerequisites

An active AWS account, an EC2 key pair in the target region, and a VPC subnet with a security group. m5.large (2 vCPU / 8 GiB RAM) is a good starting point; scale up for larger collections or more collaborators. Security group inbound: allow 22/tcp from your management network and 443/tcp (HTTPS) plus 80/tcp (which redirects to HTTPS) from your users.

Connecting to your instance

Connect over SSH as the default login user for the AMI's operating system. The login user is per-OS:

OS variant SSH login user
Ubuntu 24.04 ubuntu

Step 1 — Launch from the AWS Marketplace

Sign in to the AWS Marketplace, search for HortusFox by cloudimg, choose Continue to Subscribe, accept the terms, then Continue to Configuration and Continue to Launch. Pick your region, the m5.large instance type, your VPC subnet, your EC2 key pair, and a security group that allows inbound 22 and 443 (and 80, which redirects to HTTPS). Then Launch.

Step 2 — Launch from the AWS CLI

aws ec2 run-instances \
  --image-id <hortusfox-ami-id> \
  --instance-type m5.large \
  --key-name <your-key-pair> \
  --subnet-id <your-subnet> \
  --security-group-ids <your-sg> \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=hortusfox}]'

Ensure the security group allows inbound 22/tcp (SSH) and 443/tcp (HTTPS) from the appropriate sources.

Step 3 — Connect to your instance

ssh ubuntu@<instance-public-ip>

Step 4 — Confirm the services are running

The services that back HortusFox should all report active, and the interface answers HTTP 200 over HTTPS (the plain HTTP port redirects to it). MariaDB listens only on the loopback interface (127.0.0.1:3306), never on the public network:

systemctl is-active nginx php8.3-fpm mariadb
curl -ks -o /dev/null -w 'app https    -> %{http_code}\n' https://127.0.0.1/auth
curl -s  -o /dev/null -w 'http redirect -> %{http_code}\n' http://127.0.0.1/
ss -tlnp | grep -E ':443 |:3306 ' | sed 's/  */ /g'

Expected: three lines of active, then app https -> 200 and http redirect -> 301, and MariaDB bound to 127.0.0.1:3306.

Service status and listening ports, with MariaDB bound to loopback only

Step 5 — Retrieve your administrator credentials

On the first boot of every instance, a one-shot service (hortusfox-firstboot.service) generates secrets that are unique to that instance: a fresh administrator password, a fresh MariaDB password and a fresh cronjob token. It also generates a per-instance self-signed TLS certificate. No shared or default credentials ship in the image.

sudo cat /root/hortusfox-credentials.txt

The file (mode 0600, root only) contains the administrator email (hortusfox.admin.user, the fixed value admin@hortusfox.local), the administrator password (hortusfox.admin.pass), the sign-in URL, and the database credentials. HortusFox signs in by email.

Per-instance credentials with the secrets masked

You can prove the login round-trip from the instance's own shell — this reads the per-instance credentials, posts a real admin sign-in (a signed-in session reaches the dashboard, which carries a Logout control), and confirms that a wrong password is rejected and redirected back to the sign-in page:

ADMIN_USER=$(sudo grep '^hortusfox.admin.user=' /root/hortusfox-credentials.txt | cut -d= -f2-)
ADMIN_PASS=$(sudo grep '^hortusfox.admin.pass=' /root/hortusfox-credentials.txt | cut -d= -f2-)
CJ=$(mktemp)
curl -ks -c "$CJ" https://127.0.0.1/auth >/dev/null
curl -ks -b "$CJ" -c "$CJ" -o /dev/null \
  --data-urlencode "email=$ADMIN_USER" --data-urlencode "password=$ADMIN_PASS" https://127.0.0.1/login
curl -ks -b "$CJ" -o /tmp/hf-check.html -w 'correct password -> HTTP %{http_code}\n' https://127.0.0.1/
grep -qi logout /tmp/hf-check.html && echo 'signed in (Logout present)' || echo 'not signed in'
rm -f "$CJ" /tmp/hf-check.html

Administrator account, credentials file permissions and the login round-trip proof

Step 6 — Sign in to HortusFox

Browse to https://<instance-public-ip>/auth and sign in with the administrator email and password from the credentials file. Because the image ships a per-instance self-signed certificate, your browser shows a one-time certificate warning on first visit — click through it, or install your own domain certificate into /etc/nginx/ssl/.

After signing in you land on the dashboard, which greets you and summarises your plants, locations, tasks and users at a glance.

HortusFox dashboard after signing in

Step 7 — Add locations and plants

HortusFox organises everything by location (a greenhouse, a room, a bed, a windowsill). The image ships with one starter location named Greenhouse so you can add plants immediately; create more from Admin → Locations. Choose Add Plant from the top bar to register a plant against a location, then attach photos, notes, custom attributes and a watering schedule. The Tasks view manages the recurring care work — watering, feeding, repotting — with To-Do and Done lists you can filter.

The plant care Tasks view

Step 8 — Plan care with the calendar

The Calendar view records important dates and reminders across a date range you choose, so seasonal care, fertilising windows and repotting dates are all in one place. Other built-in modules include an Inventory for pots, soil and supplies, a Search across your collection, a plant History timeline and a collaborative Chat for teams that share a workspace.

The HortusFox calendar view

Step 9 — Confirm the stack

php -v | head -1
mariadb --version
grep -E '^APP_DEBUG|^DB_HOST|^DB_DATABASE' /var/www/hortusfox/.env

Expected: PHP 8.3.x, MariaDB 11.4.x, and the application configured with APP_DEBUG=false (production posture) against the loopback database hortusfox.

PHP and MariaDB versions, endpoint health and the production configuration

First-boot service and security model

A one-shot hortusfox-firstboot.service runs After=mariadb.service and Before=nginx.service, so the per-instance secrets and TLS certificate are in place before the first page is ever served. It writes the credentials file at mode 0600 (root only) and drops a sentinel so it runs exactly once.

systemctl status hortusfox-firstboot.service --no-pager | head -6
sudo stat -c '%a %U:%G %n' /root/hortusfox-credentials.txt

Data volumes

This AMI uses a production-grade two-disk layout. The MariaDB datadir and the HortusFox application tree each live on their own dedicated EBS volume, so you can resize either tier independently:

lsblk -o NAME,SIZE,MOUNTPOINT | grep -E 'mysql|www'
df -h /var/lib/mysql /var/www

To grow a tier, expand the EBS volume in the EC2 console, then extend the filesystem on the instance (sudo growpart / sudo resize2fs). Uploaded plant photos live under /var/www/hortusfox/public/img on the application volume.

Administration

Day to day administration is done from the web Admin dashboard (the gear icon in the top bar): manage users, locations, workspace settings, themes, backups and the environment. HortusFox also ships a command line tool (php asatru <command>) intended for maintenance and deployment; it is only enabled when APP_DEBUG=true, which this image deliberately sets to false for a production posture, so use the Admin dashboard for routine tasks.

Users can be invited from Admin → Users; each can sign in by email, change their password from their profile, and reset a forgotten password by email once SMTP is configured under Admin → Settings.

Enabling HTTPS with your own domain

The image already serves HTTPS with a per-instance self-signed certificate. For production, point a real domain at the instance's public IP (an Elastic IP is recommended), open 443/tcp in the security group, then replace the self-signed certificate with a trusted one using Let's Encrypt (replace the domain):

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

HortusFox derives its links from the host you browse to, so once you reach the instance by your domain name over HTTPS the application uses it automatically — no configuration change is needed.

Backup and maintenance

The database and the application tree (including uploaded plant photos under /var/www/hortusfox/public/img) live on dedicated EBS volumes — snapshot the volumes in EC2 for a point-in-time backup, or dump the database with (the database password is in the credentials file):

sudo mariadb-dump hortusfox > hortusfox-backup.sql

Keep the OS patched with sudo apt update && sudo apt upgrade (unattended security upgrades are enabled by default). The stack restarts cleanly with sudo systemctl restart nginx php8.3-fpm mariadb.

Support

This image is backed by 24/7 cloudimg support. Contact us by email and chat for help with HortusFox deployment, upgrades, adding locations and plants, task and calendar configuration, SMTP and email reminders, the REST API, performance tuning and database administration.

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.