{"id":1011,"date":"2026-11-05T13:00:00","date_gmt":"2026-11-05T13:00:00","guid":{"rendered":"https:\/\/vpslake.com\/blog\/?p=1011"},"modified":"2026-11-05T13:00:00","modified_gmt":"2026-11-05T13:00:00","slug":"install-php-composer-debian-13","status":"publish","type":"post","link":"https:\/\/vpslake.com\/blog\/2026\/11\/05\/install-php-composer-debian-13\/","title":{"rendered":"How to Install PHP Composer on Debian 13 (Step-by-Step)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Install PHP Composer on Debian 13 with a verified installer, then use it to add a PHP package and test the generated autoloader. A fresh VPS should be ready for a small project in about ten minutes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>A 64-bit Debian GNU\/Linux 13 (Trixie) VPS with the standard Debian repositories enabled.<\/li>\n\n\n<li>SSH access as <code>root<\/code>, or a normal account with <code>sudo<\/code> privileges and a writable home directory.<\/li>\n\n\n<li>At least 1 GB of RAM and 2 GB of free disk space for PHP, Composer&#8217;s cache, and the sample dependency.<\/li>\n\n\n<li>Outbound HTTPS access to <code>getcomposer.org<\/code> and Packagist. This guide does not need a domain or an inbound application port.<\/li>\n\n\n<li>A <a href=\"https:\/\/vpslake.com\/buy-vps\">VPSLake Linux VPS<\/a> if you need a Debian server with root access.<\/li>\n\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The commands use <code>sudo<\/code> for a normal SSH account. If you are already <code>root<\/code>, omit <code>sudo<\/code> where it appears and create the demo project as a non-root deployment user.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Confirm Debian 13 and install PHP prerequisites<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Confirm the release before installing packages so an old repository or a different PHP version does not get mixed into the setup. Debian 13 ships PHP 8.4, and <code>php-cli<\/code> supplies the interpreter Composer runs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>grep -E '^(PRETTY_NAME|VERSION_CODENAME)=' \/etc\/os-release\ndpkg --print-architecture\nsudo apt update\nsudo apt install -y ca-certificates curl php-cli php-curl php-mbstring php-zip unzip git\nphp --version<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The release check should identify Trixie, and the architecture should normally be <code>amd64<\/code> or <code>arm64<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>PRETTY_NAME=\"Debian GNU\/Linux 13 (trixie)\"\nVERSION_CODENAME=trixie\namd64\nPHP 8.4.x (cli) (built: ...)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>curl<\/code> and <code>ca-certificates<\/code> provide a trusted HTTPS download path. <code>php-curl<\/code>, <code>php-zip<\/code>, and <code>unzip<\/code> help Composer fetch and unpack packages; <code>php-mbstring<\/code> covers a common requirement for PHP applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Download and verify the Composer installer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check the installer\u2019s SHA-384 checksum before executing it. This catches an incomplete or altered download while the file is still only a PHP script in your home directory.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\ncurl -fsSLo composer-setup.php https:\/\/getcomposer.org\/installer\ncurl -fsSLo composer-setup.sig https:\/\/composer.github.io\/installer.sig\nEXPECTED_CHECKSUM=\"$(cat composer-setup.sig)\"\nACTUAL_CHECKSUM=\"$(php -r \"echo hash_file('sha384', 'composer-setup.php');\")\"\nif [ \"$EXPECTED_CHECKSUM\" != \"$ACTUAL_CHECKSUM\" ]; then echo 'ERROR: Invalid Composer installer checksum'; rm -f composer-setup.php composer-setup.sig; exit 1; fi\necho 'Installer checksum verified'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">A successful comparison prints:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Installer checksum verified<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The checksum changes when Composer publishes a new installer, so retrieve it alongside the installer every time. If the comparison fails, do not continue; remove the files and troubleshoot HTTPS or DNS first.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Install Composer globally<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Install the verified binary in <code>\/usr\/local\/bin<\/code>, which is on the normal system <code>PATH<\/code>, so every local user can run <code>composer<\/code> without maintaining a separate copy.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo php composer-setup.php --install-dir=\/usr\/local\/bin --filename=composer\nsudo chmod 0755 \/usr\/local\/bin\/composer\nrm -f composer-setup.php composer-setup.sig\ncomposer --version\ncomposer diagnose<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The installer reports the exact current release, so the version and date will change over time:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Composer (version 2.x.y) successfully installed to: \/usr\/local\/bin\/composer\nComposer version 2.x.y YYYY-MM-DD HH:MM:SS<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Composer&#8217;s <a href=\"https:\/\/getcomposer.org\/doc\/00-intro.md\" target=\"_blank\" rel=\"noopener\">official installation guide<\/a> explains the PHP requirements and local versus global placement. <code>composer diagnose<\/code> checks the PHP runtime, connectivity, and common configuration problems; review any warning before using the server for deployment.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Create a project as a non-root user<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Composer can run package scripts, so let the account that owns the application install dependencies instead of making the project tree root-owned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your SSH session is <code>root<\/code>, switch to an existing deployment account. Skip this command if you are already logged in as that account:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -iu YOUR_DEPLOY_USER<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace <code>YOUR_DEPLOY_USER<\/code> with the Linux username that should own the application. In that user\u2019s shell, create a clean project and require Monolog 3, a PHP logging library compatible with Debian 13\u2019s PHP 8.4:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mkdir -p ~\/composer-trixie-demo\ncd ~\/composer-trixie-demo\ncomposer require monolog\/monolog:^3.0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Composer writes the manifest, resolves compatible versions, records the result in <code>composer.lock<\/code>, and places package code below <code>vendor\/<\/code>. The final lines should mention autoload generation:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Writing .\/composer.json\nInstalling dependencies from lock file\nGenerating autoload files<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The <a href=\"https:\/\/getcomposer.org\/doc\/01-basic-usage.md\" target=\"_blank\" rel=\"noopener\">Composer basic usage guide<\/a> describes why the lock file belongs with an application and why <code>vendor\/<\/code> is normally rebuilt rather than committed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Test the generated autoloader<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Requiring <code>vendor\/autoload.php<\/code> lets PHP locate Monolog without hard-coded paths to individual package files. Create a small script in the demo project:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/composer-trixie-demo\ncat &gt; demo.php &lt;&lt;'PHP'\n&lt;?php\n\nrequire __DIR__ . '\/vendor\/autoload.php';\n\nuse Monolog\\Handler\\StreamHandler;\nuse Monolog\\Logger;\n\n$logger = new Logger('composer-demo');\n$logger-&gt;pushHandler(new StreamHandler('php:\/\/stdout', Logger::INFO));\n$logger-&gt;info('Composer autoloading works on Debian 13.');\nPHP\nphp demo.php<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The timestamp is expected to differ, but the message proves that PHP loaded both the Composer autoloader and the installed package:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[2026-10-08T12:00:00.000000+00:00] composer-demo.INFO: Composer autoloading works on Debian 13. [] []<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Verify Composer on Debian 13<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run the checks from the project directory. They validate the executable, the JSON manifest, the lock file, the PHP extensions required by the resolved packages, and the sample script.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cd ~\/composer-trixie-demo\ncommand -v composer\ncomposer --version\ncomposer validate --strict\ncomposer check-platform-reqs\nphp demo.php<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should see <code>\/usr\/local\/bin\/composer<\/code>, a Composer 2 version, a valid <code>composer.json<\/code>, successful platform requirements, and the Monolog message. Composer only needs outbound HTTPS for this example, so do not open an inbound web port or weaken the server firewall.<\/p>\n\n\n\n<aside class=\"vl-element vl-cta-banner\" aria-label=\"Build PHP projects on Debian\">\n\t<div class=\"vl-cta-banner__content\">\n\t\t<p class=\"vl-cta-banner__eyebrow\">Debian VPS<\/p>\n\t\t<h3 class=\"vl-cta-banner__title\">Build PHP projects on Debian<\/h3>\n\t\t<p class=\"vl-cta-banner__text\">Get a Debian VPS with root access for Composer projects and PHP deployments.<\/p>\n\t<\/div>\n\t<a class=\"vl-cta-banner__button\" href=\"\/buy-vps\" aria-label=\"View Linux VPS plans\">View Linux VPS plans<\/a>\n<\/aside>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><code>Invalid Composer installer checksum<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The two downloads do not belong to the same installer, or a proxy returned altered content. Delete both files, confirm that the VPS resolves the official HTTPS endpoints, and download them again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>rm -f ~\/composer-setup.php ~\/composer-setup.sig\ncurl -I https:\/\/getcomposer.org\/installer\ncurl -I https:\/\/composer.github.io\/installer.sig<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Do not execute an installer that fails the checksum comparison. If outbound requests are blocked, correct the network or proxy policy instead of bypassing TLS verification.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>curl: (60) SSL certificate problem<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The local CA bundle is missing or stale, so PHP and curl cannot validate the HTTPS certificate. Refresh Debian\u2019s package metadata and install the trust store:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt update\nsudo apt install -y ca-certificates\nsudo update-ca-certificates<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Avoid <code>curl -k<\/code> or other certificate-bypass flags; they remove the protection the installer check is meant to provide.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>Do not run Composer as root\/super user<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">This warning appears when dependency installation is launched by <code>root<\/code>, because package scripts would receive full system permissions. Switch to the application owner and run Composer there rather than setting <code>COMPOSER_ALLOW_SUPERUSER=1<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo -iu YOUR_DEPLOY_USER\ncd \/PATH\/TO\/YOUR_PROJECT\ncomposer install<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Replace the uppercase placeholders with an existing account and project path. <code>sudo<\/code> is appropriate for placing the global binary in <code>\/usr\/local\/bin<\/code>, not for routine project dependency commands.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><code>Your requirements could not be resolved<\/code> or <code>missing ext-*<\/code><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Composer is enforcing a package\u2019s PHP or extension requirement. See the exact requirement in the error, inspect the active runtime, and install the matching Debian extension instead of using <code>--ignore-platform-reqs<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>php --version\nphp -m | sort\nsudo apt install -y php-curl php-mbstring php-zip\ncomposer check-platform-reqs<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If a package requires a PHP release newer than 8.4, choose a compatible package constraint or a supported runtime plan; do not pretend the requirement is satisfied.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hardening<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n\n<li>Keep <code>composer.lock<\/code> in application version control and use <code>composer install<\/code> on deployments so every server receives the reviewed dependency versions.<\/li>\n\n\n<li>For a production build, use <code>composer install --no-dev --prefer-dist --optimize-autoloader<\/code> after reviewing the lock file.<\/li>\n\n\n<li>Run <code>composer audit<\/code> before releasing, and update dependencies deliberately with <code>composer update PACKAGE_NAME<\/code> rather than changing the whole dependency graph during a deployment.<\/li>\n\n\n<li>Keep Debian, PHP, and Composer updated through a maintenance process; do not expose Composer\u2019s project directory or <code>.env<\/code> files through a web server.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">FAQ<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Does Debian 13 include a PHP version that can run Composer?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Debian 13\u2019s standard PHP line is 8.4, which is above Composer\u2019s current minimum PHP requirement. A particular library can still require a different PHP version or extension, so Composer checks the project\u2019s platform requirements separately.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Should Composer be installed globally or inside each project?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The global <code>\/usr\/local\/bin\/composer<\/code> installation in this guide is convenient for a VPS administrator and makes the command available to multiple local users. A project-local PHAR can be preferable when a build must pin Composer itself to one exact version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the difference between <code>composer install<\/code> and <code>composer update<\/code>?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>composer install<\/code> uses the versions recorded in <code>composer.lock<\/code>, making it the normal choice for deployments and fresh checkouts. <code>composer update<\/code> resolves newer versions allowed by <code>composer.json<\/code> and rewrites the lock file, so use it intentionally during dependency maintenance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Do I need a domain or web server for Composer?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. Composer is a command-line dependency manager and only needs outbound HTTPS access to download packages. A domain, web server, and TLS certificate become relevant when the PHP application itself is ready to serve visitors.<\/p>\n\n\n\n<script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"Does Debian 13 include a PHP version that can run Composer?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes. Debian 13\u2019s standard PHP line is 8.4, which is above Composer\u2019s current minimum PHP requirement. A particular library can still require a different PHP version or extension, so Composer checks the project\u2019s platform requirements separately.\"}}, {\"@type\": \"Question\", \"name\": \"Should Composer be installed globally or inside each project?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"The global `\/usr\/local\/bin\/composer` installation in this guide is convenient for a VPS administrator and makes the command available to multiple local users. A project-local PHAR can be preferable when a build must pin Composer itself to one exact version.\"}}, {\"@type\": \"Question\", \"name\": \"What is the difference between `composer install` and `composer update`?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"`composer install` uses the versions recorded in `composer.lock`, making it the normal choice for deployments and fresh checkouts. `composer update` resolves newer versions allowed by `composer.json` and rewrites the lock file, so use it intentionally during dependency maintenance.\"}}, {\"@type\": \"Question\", \"name\": \"Do I need a domain or web server for Composer?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. Composer is a command-line dependency manager and only needs outbound HTTPS access to download packages. A domain, web server, and TLS certificate become relevant when the PHP application itself is ready to serve visitors.\"}}]}<\/script>\n\n","protected":false},"excerpt":{"rendered":"Install PHP Composer on Debian 13 with checksum verification, a non-root PHP project, autoload test, and fixes for common dependency errors.","protected":false},"author":1,"featured_media":1012,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_singular_sidebar":"","csco_page_header_type":"","csco_page_load_nextpost":"","footnotes":""},"categories":[5,9],"tags":[122,98,72,121],"class_list":["post-1011","post","type-post","status-publish","format-standard","has-post-thumbnail","category-guides","category-vps-hosting","tag-composer","tag-debian-13","tag-php","tag-php-composer","cs-entry"],"_links":{"self":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/comments?post=1011"}],"version-history":[{"count":1,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1011\/revisions"}],"predecessor-version":[{"id":3899,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/posts\/1011\/revisions\/3899"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media\/1012"}],"wp:attachment":[{"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/media?parent=1011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/categories?post=1011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vpslake.com\/blog\/wp-json\/wp\/v2\/tags?post=1011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}