The Perfect Server on Debian 13
Before you begin
This guide is for a new, empty Debian 13 VPS. It is not an in-place upgrade guide and must not be run on a server that already hosts sites, mail or a MariaDB installation.
server1.example.net, not a bare domain.Create A and, where applicable, AAAA records for the hostname. Set matching PTR/rDNS at the VPS provider before sending mail.
Do not use this procedure where Apache, a mail stack, MariaDB or another hosting panel has already been configured.
The command below uses the maintained ISPConfig auto-installer for Debian 13. It builds the Perfect Server service stack without copying an old Debian 12 package list.
Become root
Connect by SSH as root, or start a full root login shell:
su --loginConfirm the base OS before continuing:
cat /etc/os-release
uname -m
id -uVERSION_ID="13", an amd64 or arm64 architecture, and root user ID 0.Configure hostname and DNS
Replace the example FQDN once, then copy the whole block. It adds the local hostname mapping only if it is missing.
export FQDN="server1.example.net"
export SHORT_HOSTNAME="${FQDN%%.*}"
hostnamectl set-hostname "$FQDN"
grep -qF "$FQDN" /etc/hosts || printf '127.0.1.1\t%s %s\n' "$FQDN" "$SHORT_HOSTNAME" >> /etc/hosts
hostname
hostname -f
getent hosts "$FQDN"Update Debian and reboot
apt update
apt -y full-upgrade
apt -y install ca-certificates curl wget gnupg lsb-release
systemctl rebootReconnect after the reboot and run:
hostname -f
apt update
apt -y autoremove
timedatectl status
Install Apache, mail, DNS, FTP and ISPConfig
Run this on the freshly prepared host. Apache is the default web server; the selected passive FTP range is opened in the next step.
wget -O - https://get.ispconfig.org | sh -s -- --use-ftp-ports=40110-40210 --unattended-upgradesWhen asked for confirmation, type yes. The install sets up Apache, MariaDB, Postfix, Dovecot, Rspamd, BIND, Pure-FTPd, Jailkit, Roundcube, phpMyAdmin, ISPConfig and dependencies. At the end it prints the ISPConfig administrator and MariaDB root passwords.
printf 'ISPConfig URL: https://%s:8080\n' "$(hostname -f)"
systemctl --no-pager --full status apache2 mariadb postfix dovecot pure-ftpd
Set the firewall
Set it only after installation, so the initial SSH session remains available. These are ports for a complete single-server setup.
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 20,21/tcp
ufw allow 25,80,443,465,587,993,995,8080,8081/tcp
ufw allow 53/tcp
ufw allow 53/udp
ufw allow 40110:40210/tcp
ufw --force enable
ufw status numberedDo not expose MariaDB, Redis or Elasticsearch publicly. Keep them local-only unless a separately designed architecture requires access.
Verify the finished server
These commands are read-only checks:
systemctl is-active apache2 mariadb postfix dovecot pure-ftpd bind9
ss -lntup
apachectl configtest
mysqladmin ping
dig @127.0.0.1 localhost A
tail -n 50 /var/log/ispconfig/cron.logOpen https://server1.example.net:8080, sign in with the generated administrator credentials, and check the services under System → Server Services.
- Create a test client and website; check its HTTP and HTTPS response.
- Create a test database in ISPConfig and authenticate through phpMyAdmin.
- Create a temporary FTP account and check document-root restriction.
- Before real mail is sent, verify PTR/rDNS, SPF, DKIM and DMARC.
Add only what applications require
PHP 8.1, 8.4 and 8.5, PHP-FPM and ISPConfig registration.
A local-only compatibility database without weakening ISPConfig’s primary instance.
Install Redis and FFmpeg when applications need them; keep Redis local.
Install from Elastic’s current official repository; retain authentication/TLS and bind it to loopback.
Troubleshooting and safe recovery
Do not repeatedly rerun the installer over a partly configured server. First inspect the log; restore the pre-install snapshot if a clean retry is needed.
tail -n 200 /tmp/ispconfig-ai/var/log/ispconfig.log
systemctl --failed
journalctl -p err -b --no-pager
apachectl configtestFor diagnostics on a new server only, add --debug to the installer command. Its log is written to /tmp/ispconfig-ai/var/log/ispconfig.log.
Install the application runtimes and libraries
The ISPConfig base installer does not replace this application-specific layer. The following blocks install the required PHP versions and extensions for the current CMS estate, plus Redis, FFmpeg and Elasticsearch.
8.1 Add the PHP repository
install -d -m 0755 /usr/share/keyrings
wget -qO /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ trixie main" > /etc/apt/sources.list.d/sury-php.list
apt update
apt-cache policy php8.1 php8.4 php8.58.2 Install PHP 8.1, 8.4 and 8.5 with the CMS extension set
apt -y install \
php8.1-bcmath php8.1-bz2 php8.1-cli php8.1-common php8.1-curl php8.1-fpm php8.1-gd php8.1-igbinary php8.1-imagick php8.1-intl php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-redis php8.1-xml php8.1-zip \
php8.4-bcmath php8.4-bz2 php8.4-cli php8.4-common php8.4-curl php8.4-fpm php8.4-gd php8.4-igbinary php8.4-imagick php8.4-intl php8.4-mbstring php8.4-mysql php8.4-opcache php8.4-readline php8.4-redis php8.4-xml php8.4-zip \
php8.5-bcmath php8.5-bz2 php8.5-cli php8.5-common php8.5-curl php8.5-fpm php8.5-gd php8.5-igbinary php8.5-imagick php8.5-intl php8.5-mbstring php8.5-mysql php8.5-opcache php8.5-readline php8.5-redis php8.5-xml php8.5-zip
systemctl enable --now php8.1-fpm php8.4-fpm php8.5-fpm
# Verify BCMath for exact tax and money calculations.
php8.1 -r 'echo bcadd("1.20", "2.30", 2), PHP_EOL;'
php8.4 -r 'echo bcadd("1.20", "2.30", 2), PHP_EOL;'
php8.5 -m8.3 Register the versions in ISPConfig
In System → Additional PHP Versions, add the three FPM records. The paths are version-specific: FPM pool /etc/php/VERSION/fpm/pool.d, socket /run/php/phpVERSION-fpm.sock, ini /etc/php/VERSION/fpm/php.ini and CLI binary /usr/bin/phpVERSION. Use the full PHP article for the exact per-version fields, then select the runtime per site under Sites → Website → Options.
8.4 Install Redis and FFmpeg
apt -y install redis-server ffmpeg
systemctl enable --now redis-server
systemctl is-active redis-server
redis-cli ping
ffmpeg -version8.5 Install and contain Elasticsearch
Elasticsearch is intentionally installed from Elastic’s official APT repository. It is an application backend, not a public endpoint.
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/9.x/apt stable main" > /etc/apt/sources.list.d/elastic-9.x.list
apt update
apt -y install elasticsearch
printf '%s\n' '-Xms1g' '-Xmx1g' > /etc/elasticsearch/jvm.options.d/heap.options
printf '%s\n' 'http.host: ["127.0.0.1", "::1"]' 'transport.host: ["127.0.0.1", "::1"]' >> /etc/elasticsearch/elasticsearch.yml
systemctl daemon-reload
systemctl enable --now elasticsearch
systemctl --no-pager status elasticsearch
ss -lntp | grep -E ':(9200|9300)'Complete Perfect Server service coverage
The ISPConfig installer builds the base configuration. This chapter makes every component explicit, verifies it, and adds packages that are useful or required for the same functional coverage as a traditional manual Perfect Server installation.
9.1 SSH, editors and clock synchronization
apt -y install openssh-server nano vim-nox chrony rkhunter binutils
systemctl enable --now ssh chrony
systemctl is-active ssh chrony
chronyc tracking
rkhunter --versionKeep SSH on port 22 during initial deployment. Password authentication and root login can be hardened only after a named administrator account and tested SSH key access exist; otherwise remote access can be lost.
9.2 System mail, Postfix and Dovecot
Postfix accepts and submits mail, while Dovecot provides IMAP, POP3, LMTP and sieve. ISPConfig writes the virtual-domain and mailbox configuration; do not hand-edit its generated virtual user files.
systemctl enable --now postfix dovecot
systemctl is-active postfix dovecot
postconf -n
doveconf -n
ss -lntp | grep -E ':(25|465|587|110|143|993|995)'9.3 Rspamd and ClamAV
Rspamd provides modern spam filtering. ClamAV is installed for malware scanning when the server’s capacity and mail policy require it.
apt -y install rspamd clamav clamav-daemon
systemctl enable --now rspamd clamav-daemon
systemctl is-active rspamd clamav-daemon
rspamadm configtest
freshclam --versionUse the Rspamd web interface only from a trusted network. Do not publish it directly to the internet.
Apache, TLS, FTP and disk quotas
10.1 Apache and PHP-FPM
Apache vhosts and per-site PHP-FPM pools are generated by ISPConfig. Confirm the syntax and enabled modules before adding websites.
systemctl enable --now apache2
apachectl configtest
apachectl -M | grep -E 'rewrite|ssl|http2|proxy_fcgi'
systemctl is-active apache210.2 Let’s Encrypt
The ISPConfig installer uses acme.sh by default. Create the website in ISPConfig, enable Let’s Encrypt for that site, and ensure its public A/AAAA record already points at this server. Port 80 must be reachable for HTTP validation.
test -x /root/.acme.sh/acme.sh && /root/.acme.sh/acme.sh --version
systemctl list-timers --all | grep -Ei 'acme|cert'
curl -I http://server1.example.net/Use --use-certbot only when deliberately migrating an existing Certbot-based setup. Do not run both ACME clients for the same certificate.
10.3 Pure-FTPd and passive ports
systemctl enable --now pure-ftpd
systemctl is-active pure-ftpd
ss -lntp | grep -E ':(21|40110|40210)'
grep -R 40110 /etc/pure-ftpd /etc/default 2>/dev/null || trueCreate FTP users through ISPConfig. They are SQL-backed virtual users, not normal entries in /etc/passwd, and their files must be owned by the target site’s web user and client group.
10.4 Quotas
Traditional filesystem quotas require a quota-capable ext4/XFS mount and boot-time mount options. Do not force-enable them inside a ZFS-backed or restricted LXC VPS: use the provider’s storage quota instead. On a supported bare-metal or VM filesystem, install quota, configure the filesystem mount options, reboot, run quotacheck, then enable quotas before switching quota support on in ISPConfig.
BIND, web statistics and Jailkit
11.1 BIND DNS
BIND is installed for local resolution and optional ISPConfig-managed DNS zones. Installing BIND does not require changing your public nameservers. Keep the current DNS provider authoritative until a planned nameserver migration.
systemctl enable --now bind9
named-checkconf
dig @127.0.0.1 localhost A
dig @127.0.0.1 . NSCreate DNS zones in DNS → DNS Zone only when this server will be authoritative for them. Limit recursion to local/trusted clients; never run an unrestricted public recursive resolver.
11.2 Webalizer, AWStats and GoAccess
apt -y install webalizer awstats goaccess
webalizer --version
awstats.pl -version
goaccess --versionEnable a statistics application per website in ISPConfig. Log processing and report paths are generated by the panel; do not expose raw access logs through a document root.
11.3 Jailkit
apt -y install jailkit
command -v jk_init
jk_init --versionEnable jailed shell only for users that need it. Test each user’s deployment tools inside the jail before granting production access.
Fail2ban, phpMyAdmin and Roundcube
12.1 Fail2ban
apt -y install fail2ban
systemctl enable --now fail2ban
fail2ban-client status
fail2ban-client status sshdUse a local /etc/fail2ban/jail.d/*.local file for custom policy; never edit packaged jail.conf. Add a tested recovery IP only when you understand the security impact.
12.2 phpMyAdmin
test -f /usr/share/phpmyadmin/config.inc.php
apachectl -S | grep -i phpmyadmin || true
curl -kI https://127.0.0.1/phpmyadmin/Access phpMyAdmin at https://server1.example.net/phpmyadmin/ after its TLS certificate is ready. Restrict access with an ISPConfig-protected vhost, VPN, IP allow-list, or an additional HTTP authentication layer. Normal website databases are managed through ISPConfig; the separate legacy MariaDB is administered outside ISPConfig as described in the MariaDB article.
12.3 Roundcube
test -d /var/lib/roundcube -o -d /usr/share/roundcube
systemctl is-active postfix dovecot
curl -kI https://127.0.0.1/roundcube/Access webmail at https://server1.example.net/roundcube/. A successful Roundcube login requires an existing ISPConfig mailbox and working Dovecot authentication; it is not a replacement for DNS and mail-delivery validation.
Operations, backups and final acceptance
13.1 Updates and health checks
apt update
apt -y upgrade
systemctl --failed
df -h
free -h
journalctl -p err -b --no-pager
tail -n 100 /var/log/ispconfig/cron.logApply normal OS security updates regularly. Before major version upgrades, take a provider snapshot and verify ISPConfig’s documented upgrade procedure.
13.2 Backups are mandatory
ISPConfig can schedule per-client website and database backups, but a production server also needs an off-server backup target and tested restore process. Define retention, encryption, access control, monitoring and restoration ownership before onboarding production data.
- Restore one website and one database to a non-production location.
- Restore one mailbox and verify IMAP access.
- Confirm backups are stored outside the VPS and encrypted where appropriate.
- Alert when a scheduled backup or ISPConfig cron job fails.
13.3 Final service checklist
- Apache, MariaDB, Postfix, Dovecot, Pure-FTPd, BIND, Rspamd, Fail2ban and ISPConfig cron processing are active.
- UFW exposes only the intended web, mail, DNS, FTP and panel ports.
- All public website and mail hostnames resolve to the intended server and have valid certificates.
- PTR/rDNS, SPF, DKIM and DMARC are validated before mail is used in production.
- PHP 8.1/8.4/8.5, Redis, FFmpeg and Elasticsearch were tested by the applications that use them.
- Databases, virtual FTP accounts, web roots and mailboxes are created through their intended management path.
There's nothing here.
No comments have been posted here yet.