Chapter 2 of 5

Install Composer on a Debian 13 server, signature checked

verified on 2 September 2026 · 3 min

Quick answer

Download the installer, compare its SHA-384 hash with the one published at composer.github.io/installer.sig, and run it only if the two match. Install it into /usr/local/bin/composer to make it available to every user. After that, never use sudo composer install: run Composer under the account that owns the project.

Composer installs Laravel and every one of its dependencies. On Debian the question is not simply how to install it, but how to do so without running an unchecked downloaded script: the official procedure verifies the hash of the installer before running it.

Steps run on Debian 13 “trixie” on 2 September 2026, with PHP 8.4.24. This chapter is part of installing Laravel on a Debian server, in the Web development path.

Prerequisites

Composer is a PHP program: you need PHP on the command line before it.

bash
php -v
sudo apt install -y php-cli unzip curl ca-certificates

unzip is not decorative: without it, Composer unpacks archives in PHP, which is much slower.

Installing Composer with signature verification

Four commands, in this order. The third is the one that matters: it compares the hash of the downloaded file with the one published by the project.

bash
# 1. the reference hash, published by the Composer project
EXPECTED="$(curl -sS https://composer.github.io/installer.sig)"

# 2. the installer itself
curl -sS https://getcomposer.org/installer -o composer-setup.php

# 3. the hash of the file received
ACTUAL="$(php -r 'echo hash_file("sha384", "composer-setup.php");')"

# 4. run nothing if the two differ
if [ "$EXPECTED" = "$ACTUAL" ]; then
    sudo php composer-setup.php --install-dir=/usr/local/bin --filename=composer
    rm composer-setup.php
else
    >&2 echo "Signature invalide : téléchargement corrompu ou altéré."
    rm composer-setup.php
    exit 1
fi

On the test install, the two hashes match:

code
attendue : c8b085408188070d5f52bcfe4ecfbee5f727afa458b2573b8eaaf77b3419b0bf2768dc67c86944da1544f06fa544fd47
obtenue  : c8b085408188070d5f52bcfe4ecfbee5f727afa458b2573b8eaaf77b3419b0bf2768dc67c86944da1544f06fa544fd47
→ signature valide
Why this step is not optional

Without it, you are running a PHP script downloaded off the network with sudo rights, and no guarantee whatsoever about its contents. That is why the official documentation publishes a reference hash. Tutorials that chain curl then php composer-setup.php with no comparison skip the only protection available.

Check the result:

bash
composer --version
code
Composer version 2.10.3 2026-08-27 13:34:23
PHP version 8.4.24 (/usr/bin/php8.4)

Placing it in /usr/local/bin under the name composer makes the command available to every user on the server, with no PATH tweaking.

What about the Debian package?

Debian ships a composer package. It works, but it follows the pace of the distribution: the repository version is almost always behind the current release. Since Composer updates itself with a single command, the manual install remains the better option on an application server.

bash
sudo composer self-update          # latest stable version
sudo composer self-update --rollback   # roll back to the previous one

Do not run Composer as root

Installing the binary with sudo is normal. Using it with sudo is not.

bash
# to avoid
sudo composer install

# correct: the user who owns the project
su - deploy
cd /var/www/mon-projet
composer install --no-dev --optimize-autoloader

On a macOS machine the problem takes a different shape, and usually surfaces as a laravel command not found.

Two reasons. The post-install scripts of your dependencies run with whatever rights you give them, which turns sudo composer install into third-party code executed as root. And the files created then belong to root, which causes write errors as soon as the web server tries to write into storage/.

Composer warns about this on its own, in fact, when it is started as root without COMPOSER_ALLOW_SUPERUSER.

Useful options in production

bash
composer install --no-dev --optimize-autoloader --no-interaction
Option Effect
--no-dev skips development dependencies (tests, debugging tools)
--optimize-autoloader generates a static class map, faster to load
--no-interaction asks no questions, essential in automated deployment

Always deploy the composer.lock file with the project, and run composer install rather than composer update: the first command installs exactly the versions in the lock file, the second recalculates them and can introduce untested changes in the middle of a release.

Common errors

Running the installer without checking the signature You are running a PHP script downloaded off the network with sudo, and no guarantee about its contents. Comparing the hash is the only protection available.
sudo composer install The post-install scripts of your dependencies run as root, and the files created belong to root, which then blocks writes by the web server.
composer update in production It recalculates versions and can introduce untested changes. In deployment it is composer install, from the composer.lock.
Forgetting unzip Composer then unpacks archives in PHP, which is noticeably slower.
Relying on the Debian package It works, but it stays behind the current release, whereas Composer updates itself with self-update.
Newsletter

New tests, tutorials and projects, by e-mail.

Reproducible tests, versioned code, dated results. Never any spam.