Analytics cookies only (Google Analytics, PostHog). No ad networks, no cross-site tracking. See our privacy policy.
Self-host Bagisto
updated Oct 2026deployed by usprices checked · Jul 2026Install verified on Ubuntu 26.04 · Oct 2026 · how we test
We earn commissions when you shop through the links below. Full disclosure →
A Laravel e-commerce platform with a Vue storefront and admin panel: catalog, categories, customers, orders, multi-channel, multi-locale and multi-currency stores, marketing tools and a REST API. MIT-licensed PHP; the official production image runs as a single container that bundles Nginx, PHP-FPM and MySQL with the store already installed and seeded at build time.
Runs on a VPS from $6/mo (Kamatera 2GB, 2 GB RAM) · prices checked Sep 2026
Our recommendation
Pick Bagisto when you want a full storefront out of the box rather than a headless commerce API: catalog with configurable products, categories, customers, carts, orders and invoices, multi-channel, multi-locale and multi-currency stores, marketing and SEO tooling and an admin panel, all in one Laravel application with a Vue storefront. It is MIT-licensed PHP, and the official production image is unusual: a single container bundling Nginx, PHP-FPM and MySQL with the store already installed, migrated and seeded with sample products at build time, so first boot is seconds and there is no installer to click through. Our snippet is that image's README `docker run` turned into compose, pinned to a release tag, with the two volumes the README recommends and `APP_URL` set to the address people will use. Upstream's requirements page gives no RAM figure (only a `memory_limit = 512M` PHP starting point), so our 1 GB floor for the bundled MySQL plus PHP-FPM is an estimate. The catalog's Medusa and Saleor are headless engines you pair with your own front end; Bagisto is the one that comes with the shop.
What you need
Any VPS with at least 1024 MB of RAM
A domain you control — most self-hosted setups need HTTPS in front of them
Paid link — we earn a commission if you shop through it.
Install
Run these commands on your server:
# Bagisto — Laravel e-commerce storefront with admin panel — based on the production image README (docker/production in the Bagisto repo) and the Docker Hub page, pinned to 2.5.0cat > docker-compose.yml <<'EOF'services: bagisto: image: webkul/bagisto:2.5.0 restart: unless-stopped environment: APP_URL: http://SERVER_IP ports: - 80:80 volumes: - bagisto_mysql:/var/lib/mysql - bagisto_storage:/var/www/bagisto/storagevolumes: bagisto_mysql: bagisto_storage:EOFdocker compose up -dtimeout 180 bash -c 'until curl -fsS http://localhost/ >/dev/null; do sleep 5; done'# → http://SERVER_IP — admin at /admin/login as admin@example.com / admin123 (baked into the image: change it before anyone else can reach the store)
The production image's README (docker/production in the Bagisto repo) and the Docker Hub page flag these before you open the store:
non-negotiableThe admin account is baked into the image: admin@example.com / admin123 at /admin/login, and the README says to change it immediately after first login. There is no environment variable for it, so our snippet cannot generate it; change it before the store is reachable by anyone else. The bundled MySQL user is bagisto/bagisto on 127.0.0.1 and, per the README, is not reachable from outside the container. APP_ADMIN_URL moves the admin panel off /admin if you want it less guessable.
non-negotiableNo VOLUME is declared, so persistence is opt-in: without the two mounts in our compose, data survives docker stop/start but is lost on docker rm. We use the README's named volumes for /var/lib/mysql (the database) and /var/www/bagisto/storage (uploads, product images, logs, sessions, cached views). Use named volumes, not bind mounts: an empty host directory hides the database baked into the image and nothing initialises it, so the store will not start. Upgrading is a tag bump plus docker compose up -d, then Bagisto's own upgrade guide for migrations.
non-negotiableThe README and Docker Hub page run webkul/bagisto:latest; we pin a release tag. Tags encode two choices, web server (-nginx, -apache, -litespeed) and bundled database (-mysql, -mariadb, -postgres); the bare version tag resolves to nginx plus MySQL. The separate bagisto-docker repository is a development workspace whose interactive setup.sh clones and installs an older release inside the container; it is not the production path.
non-negotiableThe container serves plain HTTP on port 80, so put a TLS proxy in front and set APP_URL to the public URL: the entrypoint writes it into .env and re-runs Laravel's optimize on start, and image URLs and links are built from it. Our snippet uses the http://SERVER_IP placeholder you must replace. Point DB_HOST at anything other than 127.0.0.1/localhost and the bundled database is skipped entirely; then you create the database and user and run php artisan migrate --force yourself, per the README's external-database section.