Bagisto 2.4.8 on AWS User Guide
Overview
This guide covers launching and using the Bagisto 2.4.8 on Ubuntu 24.04 AMI from cloudimg on Amazon EC2. It is one version of the cloudimg e-commerce platforms listing on AWS Marketplace; you pick it as the software version when you subscribe and launch.
Bagisto is an open source e-commerce platform built on Laravel. It gives you a customer storefront (catalogue, search, cart, checkout, customer accounts, reviews, compare and wishlist) and an admin panel for products, categories and attributes, inventory sources, orders, invoices, shipments and refunds, customers and groups, CMS pages, promotions and cart rules, themes, and multi channel, multi locale and multi currency selling.
What the cloudimg image adds:
- Ready to sign in. The database schema is migrated and seeded at build time (default channel, locale, currency, root category, CMS pages and theme), so the first pages you open are the storefront and the admin sign in, not the web installer.
- No default login. Upstream Bagisto seeds the well known
admin@example.com/admin123login. On this image that password is replaced before the application ever runs, the image ships with the admin account disabled, and first boot gives it an e-mail address and a password unique to your instance.admin@example.com/admin123is refused. - Secrets unique to your instance. The admin password, the MariaDB password Bagisto uses and the Laravel application key (
APP_KEY) are generated on first boot and written to/root/bagisto-credentials.txt(root only). The image ships with the database account locked and no password or key in the configuration, and nginx and PHP-FPM refuse to start until first boot has finished. - Web installer locked. The installer and its API answer 404, so nobody who reaches the instance first can claim the store.
- HTTPS only, from the first boot. nginx serves Bagisto on port 443 with a certificate generated on your instance; there is no plain HTTP listener, requests for a host name the instance does not serve are dropped, and the session cookie is
SecureandHttpOnly. - Host and client address from configuration. Bagisto is handed the configured host name and the real client address from the connection, never values a client sends: upstream Bagisto trusts
X-Forwarded-*headers from any address, and this image trusts them from the local machine only, so password reset links and redirects always name your store. - Only the application on the web. nginx serves the
public/directory only and runs exactly one PHP file, the Laravel front controller. Any other.phpfile, including anything uploaded, answers 404, and uploaded media is served as static files only. The code is owned by root and read only to PHP. - Hardened defaults. MariaDB listens on
127.0.0.1only, Laravel runs in production mode without debug output, and nginx, PHP-FPM, MariaDB and the first boot service are blocked from the instance metadata service. The AMI requires IMDSv2. - Separate data volumes. The MariaDB database (
/var/lib/mysql) and the application with its uploaded media (/var/www) each live on their own 10 GiB EBS volume that you can grow independently of the root volume. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on, and no build tools (Composer, compilers) left on the image.
What is on the image: Bagisto 2.4.8 (the upstream v2.4.8 release, checksum verified, with the PHP dependencies from its own composer.lock, Laravel 12.62), nginx 1.24, PHP 8.3 FPM with OPcache, MariaDB 10.11, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu · Architecture: x86_64 · Recommended instance type: m5.large
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH) from your admin network and TCP 443 (the storefront and admin panel) from your customers and staff. Never open 3306.
Step 1: Launch the instance
In the AWS Marketplace listing choose Continue to Subscribe, then Continue to Configuration, pick Bagisto 2.4.8 on Ubuntu 24.04 as the software version and your Region, then Launch through EC2. Choose m5.large, your key pair and a security group as above. The AMI brings three volumes: the 8 GiB root volume, a 10 GiB volume for the database and a 10 GiB volume for the application and its media; you can make any of them larger at launch.
With the AWS CLI (replace the values in angle brackets):
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=bagisto}]'
First boot takes well under a minute after the instance is running.
Step 2: Connect to your instance
| Version | SSH user |
|---|---|
| Bagisto 2.4.8 on Ubuntu 24.04 | ubuntu |
ssh -i <your-key.pem> ubuntu@<public-ip>
Step 3: Check the services
First boot sets the passwords, the application key and the certificate, then nginx and PHP-FPM start:
systemctl is-active nginx php8.3-fpm mariadb bagisto-firstboot
sudo test -f /var/lib/cloudimg/bagisto-firstboot.done && echo FIRSTBOOT_DONE
All four units are active and the first boot marker is present:
active
active
active
active
FIRSTBOOT_DONE
Only SSH and nginx listen on network ports, nginx on 443 only; MariaDB listens on the loopback address and PHP-FPM uses a local socket:
sudo ss -lntp | awk 'NR>1 {print $4, $6}' | grep -v '127.0.0.5' | sort
0.0.0.0:22 users:(("sshd",...))
0.0.0.0:443 users:(("nginx",...))
127.0.0.1:3306 users:(("mariadbd",...))
[::]:22 users:(("sshd",...))
[::]:443 users:(("nginx",...))
The database and the application each have their own volume:
findmnt -no TARGET,SOURCE,SIZE,FSTYPE /var/lib/mysql
findmnt -no TARGET,SOURCE,SIZE,FSTYPE /var/www
/var/lib/mysql /dev/nvme1n1 9.7G ext4
/var/www /dev/nvme2n1 9.7G ext4
Step 4: Get your URL and passwords
sudo cat /root/bagisto-credentials.txt
The file is readable by root only:
# Bagisto 2.4.8 - generated on first boot by bagisto-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret.
BAGISTO_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/
BAGISTO_ADMIN_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/admin/login
BAGISTO_ADMIN_EMAIL=admin@ec2-<public-ip-dashed>.compute-1.amazonaws.com
BAGISTO_ADMIN_PASSWORD=<BAGISTO_ADMIN_PASSWORD>
MARIADB_DATABASE=bagisto
MARIADB_USER=bagisto
MARIADB_PASSWORD=<MARIADB_PASSWORD>
# The Laravel application key (APP_KEY in /var/www/bagisto/.env); it signs and encrypts sessions and cookies.
BAGISTO_APP_KEY=<BAGISTO_APP_KEY>
# The certificate is self signed (minted on this instance). Bagisto is served on https (port 443) only.
# Change the name Bagisto is served as: sudo bagisto-set-hostname <your-dns-name>
# MariaDB listens on 127.0.0.1 only; on-box maintenance: sudo mariadb
# User guide: https://www.cloudimg.co.uk/guides/bagisto-2-4-8-on-ubuntu-24-04-aws/
The URL uses the instance's public DNS name from the EC2 instance metadata. The certificate also names the public and private addresses, so https://<public-ip>/ works too. If you stop and start the instance without an Elastic IP, the boot service picks up the new address, issues a new certificate for it and updates the store URL. To serve Bagisto under your own DNS name, see Step 8.
You only need the MariaDB password for your own tools; Bagisto already has it in /var/www/bagisto/.env. Keep the application key with your backups.
Step 5: Sign in
Open the BAGISTO_URL in your browser. The certificate is self signed, so your browser asks you to confirm it the first time (or install your own, Step 8). The storefront opens with the default theme:

Open the BAGISTO_ADMIN_URL and sign in with the BAGISTO_ADMIN_EMAIL and BAGISTO_ADMIN_PASSWORD from Step 4:

The dashboard shows sales, orders and customers for the selected dates:

You can also check the sign in from the instance. This script signs in through the real admin form over HTTPS with the instance's password and reaches the dashboard, then shows that admin@example.com / admin123, a blank password and common weak passwords are refused:
sudo bagisto-cred-roundtrip.sh
OK per-instance admin signs in over HTTPS and reaches the dashboard; admin@example.com/admin123, blank and weak passwords refused
The storefront and the admin sign in page answer over HTTPS:
H=$(sudo grep '^BAGISTO_URL=' /root/bagisto-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk -o /dev/null -w 'storefront %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/"
curl -sk -o /dev/null -w 'admin login page %{http_code}\n' --resolve "$H:443:127.0.0.1" "https://$H/admin/login"
storefront 200
admin login page 200
Step 6: Set up your store
The image ships Bagisto's own starting data: one channel (Default), the English locale, US dollars, the root category, the standard CMS pages and the default theme, and one admin user whose display name is Example. There are no products, customers or orders. Work through these first:
- Click the avatar at the top right, then My Account: set your own name and e-mail address and a new password.
- Settings, then Channels: edit the
Defaultchannel's name, description, logo, favicon, locales, currencies and SEO details. The Host Name is set to the instance's URL for you; Step 8 changes it with your own name.

- Settings: add the Locales, Currencies, Exchange Rates, Inventory Sources and Taxes you sell with, and Users and Roles for your staff.
- Catalog: create your Attributes, Attribute Families and Categories, then your Products (simple, configurable, virtual, grouped, downloadable, bundle and booking products). Settings, Data Transfer imports products from a spreadsheet.

- Configure: payment methods, shipping methods, e-mail settings, GDPR, sitemap, Magic AI and the storefront options.

Step 7: E-mail (optional)
Bagisto e-mails order confirmations, invoices, shipments and password resets. Set your SMTP relay under Configure, General, Emails (or in /var/www/bagisto/.env). Amazon SES works as the relay (port 587 with STARTTLS); allow outbound 587 in your security group or network ACLs if you restrict egress. Password reset links always use your store's configured host name.
Step 8: Your own DNS name and certificate
Point a DNS record at the instance (an Elastic IP keeps the address stable), then set the name Bagisto is served as. This mints a new self signed certificate for the name, updates nginx, APP_URL in /var/www/bagisto/.env, the default channel's host name and the URLs in /root/bagisto-credentials.txt, and keeps the name across reboots:
sudo bagisto-set-hostname <your-domain>
To use a certificate from a public or internal certificate authority instead (for example one issued by Let's Encrypt for <your-domain>), copy it over the generated pair and reload nginx (running bagisto-set-hostname again replaces it with a self signed one):
sudo install -m 0644 <your-domain>.crt /etc/ssl/bagisto/bagisto.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/bagisto/bagisto.key
sudo nginx -t && sudo systemctl reload nginx
Step 9: Security checks
nginx serves the application and its static files only. The web installer, the configuration file, the vendor code and any PHP file other than the front controller answer 404, there is no plain HTTP listener (curl reports 000), and a request for a host name the instance does not serve gets no answer:
H=$(sudo grep '^BAGISTO_URL=' /root/bagisto-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
for p in /install /index.php/install /.env /storage/test.php /vendor/autoload.php; do
curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p"
done
curl -s -o /dev/null -w 'http://127.0.0.1/ -> %{http_code}\n' -m 5 http://127.0.0.1/ || true
curl -sk -o /dev/null -w 'unknown host -> %{http_code}\n' --resolve "evil.example:443:127.0.0.1" https://evil.example/ || true
404 /install
404 /index.php/install
404 /.env
404 /storage/test.php
404 /vendor/autoload.php
http://127.0.0.1/ -> 000
unknown host -> 000
A forged X-Forwarded-Host header does not change where Bagisto sends you:
curl -sk -o /dev/null -w 'forged X-Forwarded-Host -> %{http_code} %{redirect_url}\n' -H 'X-Forwarded-Host: evil.example' https://127.0.0.1/admin/account
forged X-Forwarded-Host -> 302 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/admin/login
Bagisto reports version 2.4.8, trusts forwarded headers from the local machine only, and runs in production mode with secure cookies:
grep "const BAGISTO_VERSION" /var/www/bagisto/packages/Webkul/Core/src/Core.php
grep "trustProxies" /var/www/bagisto/bootstrap/app.php
sudo grep -E '^(APP_ENV|APP_DEBUG|APP_URL|SESSION_SECURE_COOKIE)=' /var/www/bagisto/.env
const BAGISTO_VERSION = '2.4.8';
$middleware->trustProxies(at: ['127.0.0.1', '::1']); // cloudimg: loopback only (upstream: '*')
APP_ENV=production
APP_DEBUG=false
APP_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com
SESSION_SECURE_COOKIE=true
The certificate was generated on this instance and names its own addresses:
H=$(sudo grep '^BAGISTO_URL=' /root/bagisto-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
subject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = cloudimg
X509v3 Subject Alternative Name:
DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, DNS:ip-<private-ip-dashed>.ec2.internal, IP Address:<private-ip>, IP Address:127.0.0.1, DNS:localhost
None of the services can reach the instance metadata service:
systemctl show nginx php8.3-fpm mariadb bagisto-firstboot -p Id -p IPAddressDeny
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=nginx.service
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=php8.3-fpm.service
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=mariadb.service
IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128
Id=bagisto-firstboot.service
nginx hands PHP the configured host name and the client address from the connection, never values a client sends:
grep -E 'fastcgi_param (HTTP_HOST|HTTPS|HTTP_X_FORWARDED_FOR|HTTP_X_FORWARDED_HOST|HTTP_X_REAL_IP) ' /etc/nginx/sites-available/cloudimg-bagisto
fastcgi_param HTTP_HOST $bagisto_host;
fastcgi_param HTTPS on;
fastcgi_param HTTP_X_FORWARDED_HOST "";
fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr;
fastcgi_param HTTP_X_REAL_IP $remote_addr;
Because the services cannot reach the metadata service, Bagisto cannot use the instance's IAM role. If you move media to Amazon S3 (FILESYSTEM_DISK=s3), give Bagisto an access key for a narrowly scoped IAM user in .env rather than relying on the instance role.
Step 10: Changing passwords
- Admin password: sign in, click the avatar, open My Account, enter the current password and a new one, and save. Then update or delete
BAGISTO_ADMIN_PASSWORDin/root/bagisto-credentials.txtso it does not hold an old password. - Give each member of staff their own admin user under Settings, Users, with a role that allows only what they need.
- MariaDB password: only change it together with
DB_PASSWORDin/var/www/bagisto/.env. - Application key: do not change
APP_KEYon a live store; every signed in customer and admin would be signed out and encrypted values could no longer be read.
Step 11: Backup and maintenance
The store database lives in MariaDB on its own volume (/var/lib/mysql); the application, its configuration (with the application key) and uploaded media live under /var/www/bagisto on the second volume. The simplest backup is an EBS snapshot of both data volumes. For a consistent file level copy while Bagisto is running:
sudo mariadb-dump --single-transaction --routines --triggers bagisto | gzip > <backup-dir>/bagisto-$(date +%F).sql.gz
sudo tar -czf <backup-dir>/bagisto-files-$(date +%F).tar.gz -C /var/www/bagisto .env storage/app
To grow a data volume, modify the EBS volume in the EC2 console, then extend the file system online (for example sudo resize2fs /dev/nvme2n1 for /var/www; check the device with findmnt).
Operating system security updates install automatically; run sudo apt-get update && sudo apt-get upgrade to apply everything else. nginx, PHP-FPM and MariaDB restart cleanly and Bagisto keeps all of its data.
| Component | Path |
|---|---|
| Bagisto | /var/www/bagisto (web root public/) |
| Configuration | /var/www/bagisto/.env (mode 0640) |
| Uploaded media | /var/www/bagisto/storage/app/public (served at /storage/) |
| Logs, sessions and cache | /var/www/bagisto/storage |
| Database | MariaDB database bagisto (/var/lib/mysql) |
| nginx site | /etc/nginx/sites-available/cloudimg-bagisto |
| Certificate and key | /etc/ssl/bagisto/ |
| Boot service | /usr/local/sbin/bagisto-firstboot.sh |
| Host name helper | /usr/local/sbin/bagisto-set-hostname |
| Credentials | /root/bagisto-credentials.txt (mode 0600) |
Step 12: Security recommendations
- Allow port 22 from your admin network only, and port 443 from your customers and staff. Never open 3306.
- Use your own DNS name and a certificate your browsers trust (Step 8).
- Change the admin e-mail and password to your own (Step 6), and give each person their own admin user.
- Keep the operating system patched, and snapshot the data volumes regularly.
- Bagisto publishes fixes in newer 2.4 releases; review the Bagisto release notes before you put the store into production.
Support and licensing
Bagisto is open source under the MIT licence (Copyright Webkul Software). There is no per store or per order licence fee. The AMI price covers cloudimg's hardening, first boot setup and support.
- Email: support@cloudimg.co.uk
- Website: https://www.cloudimg.co.uk
- Support: 24/7, with a 24 hour response SLA