# Manual PrestaShop Classic Installation — Debian 13 This guide translates the uploaded **`prestashop-debian13-tui-v1.0.2(1).sh`** installer into manual commands. It uses the script's default configuration: PrestaShop Classic 9, Apache 2, PHP 8.4-FPM, a **local MariaDB** database, a French demo shop, and HTTP for a local/lab deployment. HTTPS and remote databases are covered at the end. **Important:** Run these steps on a **fresh Debian 13 (Trixie)** VM/container, not on a host with unrelated Apache sites or existing PrestaShop installations. These instructions do not use the interactive installation script. Replace the sample domain and administrator email before deploying. Commands are for **Bash running on the Debian server**. ## 1. Requirements - Root/sudo access on Debian 13, network access to Debian APT repositories and the official PrestaShop download sites. - At least **1 GiB available under `/var`** (the script's minimum); plan additional space for the shop, logs, backups, and upgrades. - Port **80/TCP** available. For Let's Encrypt, the domain must resolve publicly to the host and port 80 must be reachable from the Internet. - No active Nginx service or unrelated enabled Apache virtual hosts. Get a root shell and install the tools needed for the manual procedure: ```bash sudo -i umask 077 apt-get update apt-get install -y --no-install-recommends curl jq openssl unzip ca-certificates ``` ## 2. Set your configuration Paste this block into the same **root Bash session**. Edit the values first (especially `DOMAIN`, `ADMIN_EMAIL`, and shop identity). Keep the shell session open for the remaining steps. ```bash DOMAIN='shop.example.test' # Change to your domain or IP; no http:// or path SLUG='class-shop' # Lowercase identifier, used in paths and service names BASE_URI='/' # Or e.g. '/class/' SHOP_NAME='My Class Shop' LANGUAGE='fr' ALL_LANGUAGES=0 COUNTRY='fr' TIMEZONE='Europe/Paris' THEME='' # '' = release default; optional 'classic'/'hummingbird' FIXTURES=1 # 1 = install sample products; 0 = empty catalog MODULES='' # '' = bundled defaults; optional comma-separated names REWRITE=1 ADMIN_FIRST='Admin' ADMIN_LAST='Student' ADMIN_EMAIL='admin@example.test' # Replace with your actual administrator email ADMIN_PASS=$(openssl rand -hex 20) DB_MODE='local' DB_HOST='localhost' DB_NAME='prestashop_class' DB_USER='ps_class' DB_PASS=$(openssl rand -hex 24) DB_PREFIX='ps_' DB_ENGINE='InnoDB' PHP_MEMORY=512 PHP_UPLOAD=64 PHP_TIME=300 PHP_OPCACHE=1 PHP_WORKERS=4 PHP_INPUT_VARS=10000 SITE_ROOT="/var/www/prestashop-$SLUG/public" DEST="$SITE_ROOT${BASE_URI%/}" SOCKET="/run/php/php8.4-fpm-ps-$SLUG.sock" ``` The passwords are randomly generated, as in the original script. Keep them private: they remain in this shell's variables and are passed temporarily as command-line parameters to the official PrestaShop installer. Don't enable shell tracing (`set -x`). For a classroom-only hostname such as `shop.example.test`, add an entry mapping the name to the server IP in the **client computer's** hosts file, or set up internal DNS. This is not a public Let's Encrypt hostname. ## 3. Resolve the official PrestaShop Classic release The script uses the latest official **PrestaShopCorp/prestashop-classic** GitHub release and only accepts release tags belonging to the PrestaShop 9 series: ```bash RELEASE=$(curl -fsSL --retry 3 \ -H 'Accept: application/vnd.github+json' \ 'https://api.github.com/repos/PrestaShopCorp/prestashop-classic/releases/latest' \ | jq -er '.tag_name') [[ "$RELEASE" =~ ^9\.[0-9]+\.[0-9]+-[0-9]+\.[0-9]+$ ]] \ || { echo "Unsupported release tag: $RELEASE"; exit 1; } echo "Selected Classic release: $RELEASE" ``` Alternatively, manually set `RELEASE` to a **verified existing** tag with the same format, instead of querying `latest`. ## 4. Install Apache, PHP 8.4, and MariaDB ```bash apt-get update apt-get install -y --no-install-recommends \ apache2 \ php8.4-fpm php8.4-cli php8.4-common \ php8.4-mysql php8.4-curl php8.4-gd php8.4-intl \ php8.4-mbstring php8.4-xml php8.4-zip \ php8.4-bcmath php8.4-soap php8.4-opcache \ mariadb-server mariadb-client tzdata systemctl enable --now php8.4-fpm mariadb php8.4 -v php8.4 -m ``` The important PHP modules checked by the script are `curl`, `dom`, `fileinfo`, `gd`, `iconv`, `intl`, `mbstring`, `openssl`, `pdo_mysql`, `simplexml`, and `zip`. ## 5. Create the local database and SQL user The script intentionally refuses to reuse an existing database or SQL user. First confirm the names are unused: ```bash mariadb --protocol=socket -e \ "SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='$DB_NAME';" mariadb --protocol=socket -e \ "SELECT User,Host FROM mysql.user WHERE User='$DB_USER' AND Host='localhost';" ``` Both queries should return **no matching rows**. Then create the empty database and a restricted user: ```bash mariadb --protocol=socket < "/etc/php/8.4/fpm/pool.d/ps-$SLUG.conf" < "/etc/apache2/sites-available/ps-$SLUG.conf" < ServerName $DOMAIN DocumentRoot $SITE_ROOT DirectoryIndex index.php ErrorLog \${APACHE_LOG_DIR}/prestashop-$SLUG-error.log CustomLog \${APACHE_LOG_DIR}/prestashop-$SLUG-access.log combined Require all granted AllowOverride All Options FollowSymLinks SetHandler "proxy:unix:$SOCKET|fcgi://localhost/" $REDIRECT APACHE a2enmod rewrite proxy_fcgi setenvif headers a2dissite 000-default.conf a2ensite "ps-$SLUG.conf" apache2ctl configtest systemctl enable --now apache2 systemctl reload apache2 ``` Disabling `000-default.conf` matches the script's default. Do **not** blindly disable another website's virtual host; this procedure assumes a fresh dedicated server. ## 10. Optional: enable public HTTPS **before** installation Skip this for the default HTTP-only internal lab. For a public domain, make sure DNS points to the server, port 80 is publicly reachable, and the Apache site works. Then run: ```bash apt-get install -y --no-install-recommends certbot python3-certbot-apache certbot --apache --non-interactive --agree-tos --redirect \ --email "$ADMIN_EMAIL" -d "$DOMAIN" apache2ctl configtest systemctl reload apache2 ``` Use `SSL=1` for the CLI install below **only if certificate provisioning succeeded**. Otherwise use `SSL=0`. ```bash SSL=0 # Default local/lab installation. Change to 1 if step 10 succeeded. ``` ## 11. Run the official PrestaShop command-line installer This is the manual equivalent of the script's main installation operation. It runs as `www-data` (not as root), creates application tables in the already prepared database, and sets up the shop and administrator. ```bash INSTALLER="$DEST/install/index_cli.php" [[ -f "$INSTALLER" ]] || INSTALLER="$DEST/install-dev/index_cli.php" test -f "$INSTALLER" CLI_ARGS=( "--domain=$DOMAIN" "--base_uri=$BASE_URI" "--language=$LANGUAGE" "--all_languages=$ALL_LANGUAGES" "--timezone=$TIMEZONE" "--db_server=$DB_HOST" "--db_name=$DB_NAME" "--db_user=$DB_USER" "--db_password=$DB_PASS" '--db_clear=0' '--db_create=0' "--prefix=$DB_PREFIX" "--engine=$DB_ENGINE" "--name=$SHOP_NAME" "--country=$COUNTRY" "--firstname=$ADMIN_FIRST" "--lastname=$ADMIN_LAST" "--email=$ADMIN_EMAIL" "--password=$ADMIN_PASS" "--ssl=$SSL" "--rewrite=$REWRITE" "--fixtures=$FIXTURES" '--license=0' ) [[ -z "$THEME" ]] || CLI_ARGS+=("--theme=$THEME") [[ -z "$MODULES" ]] || CLI_ARGS+=("--modules=$MODULES") runuser -u www-data -- php8.4 \ -d "memory_limit=${PHP_MEMORY}M" \ -d "max_execution_time=$PHP_TIME" \ "$INSTALLER" "${CLI_ARGS[@]}" ``` **Security note:** The official CLI takes administrator and database passwords in its arguments; on a multi-user system they may be briefly visible in process listings. Avoid command tracing and shared servers during setup. ## 12. Remove installers and secure the admin directory Only do this **after confirming the CLI installation succeeded**. The original script checks for a generated PrestaShop configuration file: ```bash if [[ -s "$DEST/app/config/parameters.php" || -s "$DEST/config/settings.inc.php" ]]; then echo 'PrestaShop configuration detected.' else echo 'PrestaShop configuration missing — inspect installer output before cleanup.' fi ``` If configuration is present and installation completed: ```bash rm -rf -- "$DEST/install" "$DEST/install-dev" if [[ -d "$DEST/admin" ]]; then mv -- "$DEST/admin" "$DEST/admin$(openssl rand -hex 8)" fi ADMIN_DIR=$(find "$DEST" -maxdepth 1 -type d -name 'admin*' -printf '%f\n' | head -n 1) test -n "$ADMIN_DIR" chown -R www-data:www-data "$DEST" apache2ctl configtest systemctl reload apache2 ``` Don't run `rm -rf` against arbitrary paths: make sure `DEST` holds the correct shop directory first. ## 13. Verify your installation and save the credentials ```bash if [[ "$SSL" == 1 ]]; then SCHEME='https'; else SCHEME='http'; fi SHOP_URL="$SCHEME://$DOMAIN$BASE_URI" ADMIN_URL="${SHOP_URL}${ADMIN_DIR}/" systemctl status apache2 php8.4-fpm mariadb --no-pager curl -sS -L --connect-timeout 5 --max-time 20 \ --resolve "$DOMAIN:80:127.0.0.1" \ --resolve "$DOMAIN:443:127.0.0.1" \ -o /dev/null -w 'Storefront HTTP status: %{http_code}\n' \ "$SHOP_URL" printf 'SHOP: %s\nADMIN: %s\nADMIN LOGIN: %s\n' \ "$SHOP_URL" "$ADMIN_URL" "$ADMIN_EMAIL" printf 'ADMIN PASSWORD: %s\nDB NAME: %s\nDB USER: %s\nDB PASSWORD: %s\n' \ "$ADMIN_PASS" "$DB_NAME" "$DB_USER" "$DB_PASS" ``` An HTTP **200** is the script's successful storefront check. Store the credentials securely; revealing them on the terminal also exposes them to anyone viewing the session. Inspect `/var/log/apache2/prestashop-$SLUG-error.log`, `journalctl -u php8.4-fpm`, and PrestaShop's own logs if you see failures. Once everything works, remove the temporary download folder: ```bash rm -rf -- "$WORK" ``` ## Optional adjustments **Remote MySQL/MariaDB:** Set `DB_MODE=remote`, `DB_HOST='db.example.test:3306'`, and matching `DB_NAME`, `DB_USER`, `DB_PASS` in step 2. Install `mariadb-client` but omit `mariadb-server` and **skip step 5**. Have the remote administrator create an **empty database** and grant that user access before step 11. Test using the client with an explicit host/port. The CLI still receives `--db_create=0 --db_clear=0`. **Non-root URL path:** Set `BASE_URI='/class/'` in step 2. The site files go under `.../public/class`, Apache's `DocumentRoot` remains `.../public`, and the Apache redirect in step 9 sends `/` to `/class/`. **Theme selection:** Keep `THEME=''` to use the version default. Only use `classic` or `hummingbird` if that directory is actually contained in the downloaded package. **Bundled modules:** Keep `MODULES=''` for all bundled defaults. A comma-separated selection is supported by the script but may omit necessary features; verify module directories exist first. **Other defaults:** `FIXTURES=1` installs demo content; change to `0` for an empty shop. `ALL_LANGUAGES=0` installs only the selected primary language by default. `PHP_WORKERS=4` uses up to four PHP-FPM children, each subject to `PHP_MEMORY=512M`. **Scope of this guide:** Steps and settings follow the uploaded v1.0.2 script. They do not implement its interactive TUI, auto-saved root-only JSON configuration, install lock, automatic rollback, or rotating installer log. There is no automatic rollback; check each command's output before continuing.