Bagisto 2.4.13
Overview
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.
This SecureAnyCloud image runs Bagisto 2.4.13 on Ubuntu 24.04 on Amazon EC2. It is one version of the SecureAnyCloud e-commerce platforms listing on AWS Marketplace, and you pick it as the software version when you subscribe and launch.
What you get:
- Ready to sign in. The store (schema plus Bagisto's seed data: default channel, locale, currency, root category, CMS pages and theme) is prepared at build time and loaded into a database that first boot creates on your instance. 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 account ships disabled and with no password at all, 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, and no database password. The admin password and the Laravel application key (
APP_KEY) are generated on first boot and written to/root/bagisto-credentials.txt(root-only). Bagisto reaches MariaDB over the local socket as the system userwww-data, which MariaDB authenticates from the socket itself, so the database account has no password to steal, leak or rotate. The image ships no store database and no database account at all. First boot creates both, 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. - Current Bagisto and patched dependencies. Bagisto 2.4.13 is the newest 2.4 release, and its locked dependencies include the fixed Laravel, Dompdf, Guzzle and PhpSpreadsheet releases. Two upstream advisories that 2.4.13 still carries are closed on the image. SVG uploads with a DTD or a
<use>element are emptied before Bagisto's SVG sanitizer reads them, and every SVG is served sandboxed. nginx passes PHP only a plainCache-Controlheader. The admin sign-in is rate-limited to five failures a minute. - 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. Every PHP 8.3 package is at
8.3.6-0ubuntu0.24.04.13or later, the build that fixes CVE-2026-109618 and CVE-2026-109619 (PHP2Shell, USN-8948-1). - What is on the image: Bagisto 2.4.13 (the upstream
v2.4.13release, checksum verified, with the PHP dependencies from its owncomposer.lock, Laravel 12.69), nginx 1.24, PHP 8.3 FPM with OPcache (Ubuntu build 8.3.6-0ubuntu0.24.04.13, which fixes the PHP2Shell vulnerabilities CVE-2026-109618 and CVE-2026-109619, USN-8948-1), 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 port 3306.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick Bagisto 2.4.13 on Ubuntu 24.04 as the software version, select your Region, and choose Launch through EC2.
Choose m5.large, your key pair and the security group described 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.
To launch with the AWS CLI instead, 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. It creates the store database (about 5 seconds), then sets the admin login, the application key and the certificate.
Connect to your instance
Connect over SSH as the ubuntu user, the default user for Bagisto 2.4.13 on Ubuntu 24.04:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot creates the store database and sets the admin password, the application key and the certificate. Then nginx and PHP-FPM start. Check the units and the first-boot marker:
systemctl is-active nginx php8.3-fpm mariadb bagisto-firstboot
sudo test -f /var/lib/sac/data/bagisto-firstboot.done && echo FIRSTBOOT_DONEAll four units are active, and the first-boot marker is present:
active active active active FIRSTBOOT_DONEOnly SSH and nginx listen on network ports, and nginx listens 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' | sort0.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 ext4Get your URL and passwords
Read the credentials file. It is readable by root only:
sudo cat /root/bagisto-credentials.txtThe file looks like this:
# Bagisto 2.4.13 - 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>
# Bagisto reaches MariaDB over the local socket as the OS user www-data (MariaDB unix_socket authentication):
# the database account has NO password, so there is none to keep or rotate. On-box maintenance:
sudo mariadb MARIADB_DATABASE=bagisto MARIADB_USER=www-data
# 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. Run artisan as www-data:
sudo -u www-data php /var/www/bagisto/artisan <command>
# User guide: https://secureanycloud.com/stacks/bagisto-2-4-13/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.
Keep the application key with your backups. There is no database password. The store's MariaDB account is www-data, and MariaDB accepts it only from a process running as the system user www-data on this instance:
sudo mariadb -N -e "SELECT CONCAT(User,'@',Host,' ',JSON_VALUE(Priv,'$.plugin')) FROM mysql.global_priv WHERE User='www-data'"
sudo -u www-data mariadb -N -e 'SELECT CURRENT_USER()' bagistowww-data@localhost unix_socket www-data@localhostRun Bagisto's artisan commands as www-data too (sudo -u www-data php /var/www/bagisto/artisan <command>), so that they reach the database the same way. For your own tools on the instance, use sudo mariadb (root over the socket). MariaDB does not listen on the network.
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. You can install your own certificate instead, as described in 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. The following script signs in through the real admin form over HTTPS with the instance's password and reaches the dashboard. It then shows that admin@example.com / admin123, a blank password and common weak passwords are refused:
sudo bagisto-cred-roundtrip.shOK per-instance admin signs in over HTTPS and reaches the dashboard; admin@example.com/admin123, blank and weak passwords refusedConfirm that 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 200Set 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. It also includes one admin user whose display name is Example. There are no products, customers or orders.
Work through these tasks first:
- Click the avatar at the top right, then My Account. Set your own name, e-mail address and a new password.
- Open 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, and Step 8 changes it to your own name. - In Settings, add the Locales, Currencies, Exchange Rates, Inventory Sources and Taxes you sell with, and Users and Roles for your staff. Appearance holds the storefront themes and their sections, which you edit beside a live preview.
- In 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.
- In Configure, set payment methods, shipping methods, e-mail settings, GDPR, sitemap, Magic AI and the storefront options.
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). If you restrict egress, allow outbound 587 in your security group or network ACLs.
Password reset links always use your store's configured host name.
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:
sudo bagisto-set-hostname <your-domain>This command mints a new self-signed certificate for the name. It updates nginx, APP_URL in /var/www/bagisto/.env, the default channel's host name and the URLs in /root/bagisto-credentials.txt. It also keeps the name across reboots.
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 nginxSecurity 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/ || true404 /install 404 /index.php/install 404 /.env 404 /storage/test.php 404 /vendor/autoload.php http://127.0.0.1/ -> 000 unknown host -> 000A 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/accountforged X-Forwarded-Host -> 302 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/admin/loginBagisto reports version 2.4.13, trusts forwarded headers from the local machine only, and runs in production mode with secure cookies. Verify each setting:
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/.envconst BAGISTO_VERSION = '2.4.13'; $middleware->trustProxies(at: ['127.0.0.1', '::1']); // sac: loopback only (upstream: '*') APP_ENV=production APP_DEBUG=false APP_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com SESSION_SECURE_COOKIE=trueThe certificate was generated on this instance and names its own addresses. Inspect it:
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 subjectAltNamesubject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = sac 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:localhostNone of the services can reach the instance metadata service. Confirm the deny rules:
systemctl show nginx php8.3-fpm mariadb bagisto-firstboot -p Id -p IPAddressDenyIPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=nginx.service IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=php8.3-fpm.service IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=mariadb.service IPAddressDeny=169.254.169.254/32 fd00:ec2::254/128 168.63.129.16/32 Id=bagisto-firstboot.servicenginx 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/sac-bagistofastcgi_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;List the installed versions of the dependencies that carried advisories in earlier Bagisto releases:
php -r '$i=json_decode(file_get_contents("/var/www/bagisto/vendor/composer/installed.json"),true); foreach(($i["packages"]??$i) as $p) if (in_array($p["name"],["laravel/framework","dompdf/dompdf","guzzlehttp/guzzle","phpoffice/phpspreadsheet","symfony/http-foundation","enshrined/svg-sanitize","league/commonmark"])) echo $p["name"]," ",$p["version"],"\n";' | sortdompdf/dompdf v3.1.6 enshrined/svg-sanitize 0.22.0 guzzlehttp/guzzle 7.15.5 laravel/framework v12.69.2 league/commonmark 2.10.1 phpoffice/phpspreadsheet 1.30.6 symfony/http-foundation v7.4.18Two of these still have open upstream advisories, and the image closes both.
nginx passes PHP the Cache-Control request header only when it is plain, single-spaced tokens (symfony/http-foundation CVE-2026-108082). SVG files that carry a DTD or a <use> element are replaced with an empty SVG before the sanitizer reads them (enshrined/svg-sanitize CVE-2026-107379, CVE-2026-107380 and CVE-2026-107381). Every SVG response is sandboxed:
grep -E 'cache_control|svg_csp' /etc/nginx/sites-available/sac-bagisto | head -6
grep -c 'CVE-2026-1073' /var/www/bagisto/packages/Webkul/Core/src/Traits/Sanitizer.phpmap $http_cache_control $bagisto_cache_control { "~^[A-Za-z0-9=,._-]+( [A-Za-z0-9=,._-]+)*$" $http_cache_control; map $sent_http_content_type $bagisto_svg_csp { add_header Content-Security-Policy $bagisto_svg_csp always; fastcgi_param HTTP_CACHE_CONTROL $bagisto_cache_control; add_header Content-Security-Policy $bagisto_svg_csp always; 1Because 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), put an access key for a narrowly scoped IAM user in .env instead of relying on the instance role.
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 that it does not hold an old password. - Staff accounts: give each member of staff their own admin user under Settings, Users, with a role that allows only what they need.
- Database: there is no database password to change. Bagisto's account
www-data@localhostis authenticated by the local socket (DB_PASSWORDis empty in/var/www/bagisto/.envby design). If you ever move the database to another server, create an account with a password there and setDB_HOST,DB_USERNAMEandDB_PASSWORDin.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.
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, use:
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/appTo grow a data volume, modify the EBS volume in the EC2 console, then extend the file system online. For example, run sudo resize2fs /dev/nvme2n1 for /var/www, and 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.
Key locations on the instance:
- 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/sac-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)
Security recommendations
- Allow port 22 from your admin network only, and port 443 from your customers and staff. Never open port 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 open the store to customers.
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 SecureAnyCloud's hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24-hour response SLA
Deploy on AWS
Launch Bagisto 2.4.13 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com