Host several websites on one server with Apache

VPS & Servers

1 person found this article helpful

Give each website its own folder and its own Apache virtual host file, turn it on with a2ensite and reload Apache. Then add free SSL with Certbot.

Good to know: written for Ubuntu 24.04 (the same on 22.04 and 26.04) with Apache already installed: see Install the Apache web server on Ubuntu. Replace example.com and example.net with your own domains. Each domain needs an A record that points to your server's IP address.

1. Create a folder for each website

sudo mkdir -p /var/www/example.com/public_html
sudo mkdir -p /var/www/example.net/public_html

Give the folders to the user you upload files with, so you don't need sudo for every file. $USER is the user you're logged in as:

sudo chown -R $USER:$USER /var/www/example.com/public_html /var/www/example.net/public_html

Apache only needs to read the files. New folders get 755 and new files 644 by default, which is what it needs: no chmod required.

2. Add a test page

A small page per site shows you later which site answers:

echo '<h1>example.com works</h1>' > /var/www/example.com/public_html/index.html
echo '<h1>example.net works</h1>' > /var/www/example.net/public_html/index.html

3. Create a virtual host file for each website

Open a new file for the first site:

sudo nano /etc/apache2/sites-available/example.com.conf

Paste this, then save with Ctrl+O, Enter and close with Ctrl+X:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/example.com/public_html

    <Directory /var/www/example.com/public_html>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
  • ServerName and ServerAlias: the addresses this site answers to.
  • DocumentRoot: the folder with the site's files.
  • AllowOverride All: lets the site use .htaccess files, which WordPress and most PHP apps need.
  • ErrorLog and CustomLog: separate logs per site in /var/log/apache2/.

Create /etc/apache2/sites-available/example.net.conf the same way, with example.net in every line.

4. Turn the sites on

sudo a2ensite example.com.conf
sudo a2ensite example.net.conf
sudo a2enmod rewrite

a2ensite switches each site on. a2enmod rewrite turns on the module that .htaccess redirects and pretty links use. Optional: switch off Apache's default page so it doesn't answer for unknown names:

sudo a2dissite 000-default.conf

Check the settings and reload Apache:

sudo apache2ctl configtest
sudo systemctl reload apache2

configtest must end with Syntax OK. List the sites Apache now serves:

sudo apache2ctl -S

Each domain should appear with its own .conf file.

5. Test the sites

When the DNS of both domains points to the server, open http://example.com and http://example.net. Each shows its own test page.

To test before DNS is ready, ask the server directly with the domain name as the host:

curl -H "Host: example.com" http://203.0.113.10
curl -H "Host: example.net" http://203.0.113.10

Or point the domains to the server on your own computer only, by adding a line to your hosts file: C:\Windows\System32\drivers\etc\hosts on Windows (edit it as administrator), /etc/hosts on macOS and Linux:

203.0.113.10  example.com www.example.com example.net www.example.net

Remove the line again when you're done testing, or you won't see real DNS changes later.

6. Add free SSL with Let's Encrypt

Certbot gets free certificates from Let's Encrypt, adds the HTTPS settings to your virtual hosts and renews the certificates automatically. Port 443 must be open (sudo ufw allow 'Apache Full') and the domains must already point to the server.

sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com
sudo certbot --apache -d example.net -d www.example.net

Certbot asks for an email address and for you to accept the terms the first time. Then test the automatic renewal:

sudo certbot renew --dry-run

It should report that all simulated renewals succeeded. sudo certbot certificates lists your certificates and their expiry dates.

Add another website later

Repeat steps 1 to 6 for the new domain: folder, test page, .conf file, a2ensite, configtest, reload, Certbot.

Common problems

Every domain shows the same site

Apache uses the first site in the list when no ServerName or ServerAlias matches. Check the spelling in your .conf files, check with sudo apache2ctl -S that the site is on, and reload Apache.

"403 Forbidden"

Apache can't read the folder, or there's no index.html or index.php in it. Check the folder permissions (ls -ld /var/www/example.com/public_html) and the path in DocumentRoot.

.htaccess rules are ignored

The site's <Directory> block needs AllowOverride All, and the rewrite module must be on (sudo a2enmod rewrite, then reload).

Certbot fails with a connection or "unauthorized" error

Let's Encrypt couldn't reach your site over HTTP. Check that the domain's A record points to this server (dig +short example.com) and that port 80 is open. If you only just changed DNS, wait until the change has spread and try again.

Related articles

Still stuck? Open a support ticket and we'll help.


Was this answer helpful?

2FA 301 redirect 3D Secure 404 page 500 error 550 error A record accept quote access log account credit account details account password Account Preferences account security add funds addon domain address importer affiliate program AI assistant AlmaLinux 9 Android email Apache Apache virtual host API token Apple Mail Ask AI auth code authenticator app auto-renew automatic payment automatic updates autoresponder AutoSSL bandwidth billing address billing contact billing section block editor block IP bounce bounce message BoxTrapper build a WordPress website bulk email accounts business email buy domain buy hosting buy SSL certificate CalDAV calendar sync callback can't log in cancel hosting cancellation card declined CardDAV catch-all Certbot change domain WordPress change email change nameserver change package change password change payment checklist checkout choose a plan client accounts client area clone WordPress cloud server coming soon page commission company name confirmation link contact contact form Contact Information contacts control panel cPanel cPanel API cPanel contact email cPanel DNS cPanel domains cPanel email cPanel install cPanel language cPanel layout cPanel login cPanel password cPanel SSL cPanel update cPanel users create cPanel account create mailbox credit card cron cron job CRT key CA bundle CSF firewall CSV import currency custom error page Custom Nameservers custom offer dashboard data center database password database privileges database user Database Wizard date.timezone DDNS deceptive site ahead default address delete database delete old emails deny access deploy deposit device email settings Directory Privacy disk space disk usage DKIM DMARC DNS cache DNS explained DNS Records DNS Zone Management document root domain alias domain grace period Domain Hosting Domain Management domain name domain renewal domain transfer downgrade download invoice due date dynamic DNS ElySpace email account email account exists email backup email client email delivery email disk usage email filters email forwarder email history email hosting email login email migration email password email ports email preferences email quota email routing email signature email test email verification EPP code error error log error pages EV SSL expired domain expiry expiry date export database export emails fake email faster support feedback File Manager file permissions firewall first website flush DNS folder force HTTPS forgot password form email not received forward email free migration free SSL FTP account's password FTP password Galaxy email setup getting started Git GitHub Gmail Gmail app GoDaddy good ticket Google malware warning Google sign-in Google Workspace GST number Gzip compression hacked website hacked WordPress hardening help help center home server hosting hosting addons hosting glossary hosting location hosting plan Hosting Service hosting terms hosting tools hosting types hostname hostname SSL hostnamectl hotlink protection HOW TO ADD NAME SERVERS TO MY DOMAIN NAME How to create additional FTP accounts in cPanel How to create FTP accounts in cPanel How to setup name-servers for a domain htaccess htaccess redirect HTTP to HTTPS image theft IMAP IMAP settings IMAP SMTP settings import emails import SQL Imunify360 index.php virus INR install plugin install SSL certificate install WordPress instant answers invite user invoice invoice details invoice emails invoice PDF invoices IP address IP Blocker iPad iPhone email knowledgebase language large database leech protection LEMP Let's Encrypt LFD linked accounts LiteSpeed Cache live chat locked out log out login login email login problem lost email Mac Mac email mail rules mailbox mailbox check mailbox full mailbox size mailing list Mailman maintenance maintenance mode malware removal malware scan manage services mass payment max_execution_time members area memory_limit menu migrate WordPress migration request migration ticket mobile webmail money-back guarantee move email move website move WordPress site MultiPHP INI Editor MultiPHP Manager multiple accounts multiple websites MX record MX records my domains MySQL MySQL database MySQL user mysqldump nameserver Nameservers network drive new account new order newsletter Nginx Node.js notifications npm nvm open ticket Optimize Website or delete order order email out of office outage Outlook Outlook app Outlook IMAP Outlook mobile Outlook password prompt OX App Suite OX webmail page speed password protect pay all pay invoice payment payment details payment failed payment method payment methods PayPal permalinks permissions phishing phone support PHP errors PHP timezone PHP version PHP-FPM php.ini PHPMailer phpMyAdmin plugin updates point domain print invoice printer SMTP product addons products professional email profile public_html publish a post quick start quota quote quotes rating Raw Access raw access logs reading settings redemption period redirect referral link refund register register domain remove user renew domain renewal repair database reseller hosting reset admin password reset password resource usage restore WordPress revoke access revoke privileges root login Roundcube Roundcube export Roundcube identities Roundcube signature rsync backup Samsung Email scam scan to email scheduled task search Search Console self-hosted WordPress send and receive send as server IP address server location server security server status service details services session setup setup domain i setup domain name shared passwords shared vs VPS sign up single sign-on site address Sitejet Builder SMTP SMTP settings spam spam filter SpamAssassin SPF SSH SSH hardening SSH key SSL certificate static front page strong password subaccount subdomain suggestions support ticket support ticket tips support tickets suspension switch account tar test site Thunderbird ticket reply ticket status track delivery transfer website troubleshooting two-factor authentication UAPI Ubuntu Ubuntu 24.04 UFW unpaid invoice unsubscribe unzip upcp upgrade hosting UPI upload files upload_max_filesize URL forwarding user management User Manager username vacation reply VAT ID verify email Web Disk web hosting web hosting basics web server WebDAV webmail webmail From address webmail on phone webmail password website builder website email website migration website not loading Website Performance website security welcome email WhatsApp WhatsApp support whitelist WHM wildcard SSL WordPress 404 WordPress backup WordPress caching WordPress critical error WordPress email WordPress errors WordPress homepage WordPress hosting WordPress login WordPress malware WordPress Management WordPress menu WordPress offline WordPress pages WordPress password WordPress plugins WordPress post WordPress security WordPress SMTP WordPress speed WordPress staging WordPress themes WordPress transfer WordPress update WordPress URL WordPress.org vs WordPress.com WP Mail SMTP wp-admin wp-admin login wp-cron zip Zone Editor zone templates