Install concrete5 on Debian 11 by building an Apache, MariaDB, and PHP 7.4 stack, then open the browser installer to publish your first site. This guide uses Concrete CMS 8.5.21, the compatible 8.5 branch, and takes about 20 minutes once your domain points to the VPS.
Prerequisites
- A 64-bit Debian GNU/Linux 11 (Bullseye) VPS with at least 2 GB of RAM and 10 GB of free disk space.
- SSH access as
root, or a normal account with workingsudoprivileges. - A domain such as
YOUR_DOMAINwith an A record pointing to the VPS. You can test over the server IP first, but HTTPS requires a domain. - A strong site administrator password and a separate, long MariaDB password.
- Debian 11 is past its normal support window, so use this for an existing Bullseye server and plan an upgrade for a new public site. A VPSLake Linux VPS provides the root access needed for this setup.
Concrete CMS 8.5.21 is used because Debian 11 provides PHP 7.4. The Concrete CMS system requirements also list the PHP extensions, Apache support, and MariaDB compatibility used below.
The commands use sudo. If you are logged in as root, remove sudo from each command.
Step 1: Confirm Bullseye and install the LAMP packages
Checking the release first prevents you from installing packages meant for Debian 12 or 13.
grep -E '^(PRETTY_NAME|VERSION_CODENAME)=' /etc/os-release
dpkg --print-architecture
sudo apt update
sudo apt install -y apache2 mariadb-server php7.4 php7.4-cli libapache2-mod-php7.4 php7.4-mysql php7.4-gd php7.4-curl php7.4-xml php7.4-mbstring php7.4-zip php7.4-opcache unzip curl ca-certificates ufw certbot python3-certbot-apache
libapache2-mod-php7.4 lets Apache execute PHP, while the other PHP packages provide Concrete’s database, image, XML, archive, and multibyte features. The check should show Bullseye and a normal VPS architecture:
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
VERSION_CODENAME=bullseye
amd64
Set a reasonable PHP memory and upload limit before the installer runs:
sudo tee /etc/php/7.4/apache2/conf.d/99-concrete.ini >/dev/null <<'EOF'
memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
EOF
sudo a2enmod rewrite headers
sudo systemctl enable --now apache2 mariadb
sudo systemctl restart apache2
Step 2: Create the Concrete database
Concrete stores pages, users, configuration, and file metadata in MariaDB, so give it its own database and least-scope account.
Run the hardening wizard first and remove anonymous accounts, the test database, and remote root access when prompted:
sudo mariadb-secure-installation
Open MariaDB as the local administrative account:
sudo mariadb
Paste these statements at the MariaDB [(none)]> prompt, replacing YOUR_DB_PASSWORD with a unique password. Do not reuse the VPS or Concrete administrator password.
CREATE DATABASE concrete CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'concrete_user'@'localhost' IDENTIFIED BY 'YOUR_DB_PASSWORD';
GRANT ALL PRIVILEGES ON concrete.* TO 'concrete_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
The EXIT; line returns you to the shell. The database name, user, host, and password will be entered in the browser installer later.
Step 3: Download Concrete CMS 8.5.21
Using the official release archive avoids an unpinned Git checkout and keeps the PHP 7.4-compatible version explicit.
Download the release, extract it into the site directory, and remove the temporary archive:
sudo install -d -o www-data -g www-data /var/www/concrete
curl -fL https://www.concretecms.org/download_file/cdc12556-d0cc-4ca4-85cc-b1e76b6a4401/2718 -o /tmp/concretecms-8.5.21.zip
sudo unzip -q /tmp/concretecms-8.5.21.zip -d /var/www/concrete
rm -f /tmp/concretecms-8.5.21.zip
The archive should leave index.php, concrete/, application/, packages/, and updates/ directly under /var/www/concrete. Confirm the expected entry point exists:
test -f /var/www/concrete/index.php && echo "Concrete CMS files extracted"
Expected output:
Concrete CMS files extracted
The official Concrete CMS installation guide uses the same download, extraction, database, and web-installer flow.
Step 4: Configure Apache and file permissions
Apache needs a named virtual host and rewrite support so Concrete can turn friendly page URLs into application requests.
Create a virtual host, replacing every YOUR_DOMAIN occurrence before running the block:
sudo tee /etc/apache2/sites-available/YOUR_DOMAIN.conf >/dev/null <<'APACHE'
<VirtualHost *:80>
ServerName YOUR_DOMAIN
DocumentRoot /var/www/concrete
ErrorLog ${APACHE_LOG_DIR}/concrete_error.log
CustomLog ${APACHE_LOG_DIR}/concrete_access.log combined
<Directory /var/www/concrete>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
APACHE
sudo a2dissite 000-default.conf
sudo a2ensite YOUR_DOMAIN.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
Syntax OK confirms Apache accepted the configuration. Now make the web server the owner, keep ordinary files non-executable, and grant write access only to directories Concrete must update:
sudo chown -R www-data:www-data /var/www/concrete
sudo find /var/www/concrete -type d -exec chmod 0755 {} +
sudo find /var/www/concrete -type f -exec chmod 0644 {} +
sudo chmod 0775 /var/www/concrete/application/files /var/www/concrete/application/config /var/www/concrete/packages /var/www/concrete/updates
Step 5: Open the web ports and enable HTTPS
Allow SSH before enabling UFW so your current administration session is not cut off, then open only HTTP and HTTPS for the site.
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
sudo ufw status verbose
You should see 22/tcp, 80/tcp, and 443/tcp allowed. If SSH uses a custom port, allow that port instead of OpenSSH before enabling the firewall.
After the domain resolves to this server, request a certificate and let Certbot add the HTTPS virtual host and redirect:
sudo certbot --apache -d YOUR_DOMAIN --redirect --agree-tos --no-eff-email -m YOUR_EMAIL
Replace YOUR_EMAIL with an address that can receive certificate expiry notices. Certbot must be able to reach port 80 from the public internet; the command will fail if DNS or the firewall still points elsewhere.
Step 6: Finish the browser installation
The browser wizard writes the site configuration after it can reach both Apache and MariaDB.
Open this address:
https://YOUR_DOMAIN
On the requirements screen, continue only when the checks are green. For database settings, use:
- Database server:
localhost - Database name:
concrete - Database user:
concrete_user - Database password: the value used for
YOUR_DB_PASSWORD
Choose a site name, enter an administrator email, and create a unique administrator password. Complete the installation, then sign in to the dashboard and publish a small test page.
Verify the Concrete CMS installation
These checks confirm that the services are running, Apache loaded PHP, the required writable directories are usable, and the public site returns a response:
php --version
sudo systemctl is-active apache2 mariadb
apache2ctl -M | grep php
sudo -u www-data test -w /var/www/concrete/application/files && echo "files directory writable"
curl -fsSI https://YOUR_DOMAIN | sed -n '1,5p'
Expected output includes PHP 7.4, two active lines, a PHP module, the writable-directory message, and an HTTP success or redirect response:
PHP 7.4.x (cli) ...
active
active
php7_module (shared)
files directory writable
HTTP/2 200
Sign in to Concrete CMS, create a page, and open it in a private browser window. A page that loads over HTTPS proves the web server, PHP, database connection, rewrites, and certificate are working together.
Troubleshooting
apt update returns a 404 for bullseye-security
Debian 11 reached the end of its LTS period on August 31, 2026, so old images may still reference mirrors that no longer carry Bullseye security metadata. For a temporary legacy installation, point APT at the Debian archive, then schedule an OS upgrade instead of treating the archive as current security support.
sudo cp -a /etc/apt/sources.list /etc/apt/sources.list.before-bullseye-archive
sudo tee /etc/apt/sources.list >/dev/null <<'EOF'
deb http://archive.debian.org/debian bullseye main contrib non-free
deb http://archive.debian.org/debian bullseye-updates main contrib non-free
EOF
sudo find /etc/apt/sources.list.d -type f -name '*.list' -exec sed -i '/bullseye-security/d' {} +
sudo apt -o Acquire::Check-Valid-Until=false update
If this is a new deployment, rebuild it on a supported Debian release instead. Do not expose an unpatched Bullseye server as a permanent production host.
Apache shows 403 Forbidden or Concrete says folders are not writable
The web-server account cannot read the site or write one of Concrete’s application directories. Reapply the owner and the four narrowly scoped write permissions, then reload Apache:
sudo chown -R www-data:www-data /var/www/concrete
sudo chmod 0775 /var/www/concrete/application/files /var/www/concrete/application/config /var/www/concrete/packages /var/www/concrete/updates
sudo systemctl reload apache2
Avoid chmod 777; it gives every local account write access to the CMS.
SQLSTATE or “Unable to connect to the database”
The installer values do not match the MariaDB account, or the account was created for a different host. Check the account without printing its password, then test authentication:
sudo mariadb -e "SHOW DATABASES LIKE 'concrete'; SELECT User,Host FROM mysql.user WHERE User='concrete_user';"
mariadb -u concrete_user -p -h localhost concrete -e 'SELECT 1;'
Enter the same database name, user, password, and localhost host in the wizard. The second command should print 1.
The site loads the Apache default page or returns 404
The domain may not match the virtual host, or Apache may not have reloaded the file. Confirm the DNS target, site status, rewrite module, and configuration syntax:
sudo a2query -s YOUR_DOMAIN.conf
sudo a2query -m rewrite
sudo apache2ctl configtest
sudo systemctl reload apache2
Browse to https://YOUR_DOMAIN, not the raw IP, after DNS and the certificate are ready.
FAQ
Can I install the latest Concrete CMS 9 on Debian 11?
Not with Debian 11’s default PHP 7.4 as a general recommendation. This guide pins Concrete CMS 8.5.21 because it is the compatible 8.5 release; use a supported Debian release and a current PHP version for a new Concrete CMS 9 deployment.
Does Concrete CMS need Composer for this installation?
No. The official release archive contains the application and its dependencies, so the web installer can be used directly. Composer is useful for development workflows, but it adds no benefit to this pinned archive-based server install.
Can I use an IP address instead of a domain?
You can use the VPS IP for an initial HTTP check, but a normal trusted HTTPS certificate is issued for a domain name. Set the DNS A record first, then run Certbot with that domain.
Which directories must Concrete CMS write to?
The installer and later updates need application/files/, application/config/, packages/, and updates/. The guide makes only those directories group-writable and keeps regular files at mode 0644.