THU.JUN.18
2026
23:38:54
← back to modules MODULE · 01 · PHP
0 / 10 chapters complete · 0%

Virtual Hosts — Multiple Sites, One Apache

Stop using ugly URLs like 192.168.0.19/medtrack/. Give each project its own hostname — medtrack.local. Same server, multiple sites, pro vibe.
Make a vhost config → enable it → tell each device on the LAN about the new hostname via hosts file → done.

How vhosts actually work

When you hit a URL, your browser doesn't just send "give me /page.html" — it also sends the hostname you typed. Apache reads that hostname and uses it to pick which "site" should answer. One Apache process, many sites, sorted by name like apartments in a building.

Step 1: Create the vhost config

SSH into Lubuntu. Run:
sudo nano /etc/apache2/sites-available/medtrack.conf
Paste:
<VirtualHost *:80>
    ServerName medtrack.local
    ServerAdmin admin@localhost
    DocumentRoot /home/erictey/server/medtrack

    <Directory /home/erictey/server/medtrack>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog \${APACHE_LOG_DIR}/medtrack-error.log
    CustomLog \${APACHE_LOG_DIR}/medtrack-access.log combined
</VirtualHost>
Save and exit.

Per-vhost log files = huge quality of life. When something breaks, tail just medtrack's log instead of swimming through a mixed firehose.

Step 2: Enable, validate, reload

sudo a2ensite medtrack
sudo apache2ctl -t
sudo systemctl reload apache2
The three-step ritual: enable → validate → reload. Burn this into muscle memory.

Step 3: Teach the server about the name

Apache will route requests for medtrack.local — but no device on your network actually knows what medtrack.local means. Each device needs a hosts file entry.

First, the server itself:

sudo nano /etc/hosts
Add at the bottom:
127.0.0.1   medtrack.local
Save. From the server itself, http://medtrack.local/ now works.

Step 4: Teach your Windows machine about it

On Windows:
  1. Right-click Notepad → Run as administrator (MANDATORY — the hosts file is protected)
  2. File → Open → C:\Windows\System32\drivers\etc\hosts (set file filter to "All Files")
  3. Add this line at the bottom:
    192.168.0.19   medtrack.local
  4. Save
From your Windows browser, hit http://medtrack.local/. Should serve MedTrack. No port, no IP, just a clean hostname. That's the magic.

Disable a site without deleting it

sudo a2dissite medtrack
sudo systemctl reload apache2

The config stays in sites-available/. Only the symlink in sites-enabled/ goes away. a2ensite medtrack brings it back. Right way to "pause" a site.

Clean URLs with .htaccess

The classic "send everything to index.php" router used by every PHP framework:

# /home/erictey/server/medtrack/.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

Plain English: "If the URL isn't a real file or folder, send it to index.php and let PHP figure it out." That's how URLs like medtrack.local/meds/12/edit work without a literal file at that path.

Enable mod_rewrite (if not already):
sudo a2enmod rewrite
sudo systemctl restart apache2

Build: Second Vhost

Goal: prove you can spin up a new vhost in under 2 minutes. The skill is repetition.

  1. SSH in. Make a new folder: mkdir -p /home/erictey/server/sandbox
  2. Create an index file: echo "<h1>Sandbox lives!</h1>" > /home/erictey/server/sandbox/index.html
  3. Copy the medtrack vhost config: sudo cp /etc/apache2/sites-available/medtrack.conf /etc/apache2/sites-available/sandbox.conf
  4. Edit it: sudo nano /etc/apache2/sites-available/sandbox.conf — change every "medtrack" to "sandbox"
  5. Enable, validate, reload: sudo a2ensite sandbox && sudo apache2ctl -t && sudo systemctl reload apache2
  6. Add 192.168.0.19 sandbox.local to your Windows hosts file
  7. Hit http://sandbox.local/ — should show "Sandbox lives!"

Now you can spin up a new site any time you want. Each project gets its own clean hostname. Genuinely the moment your home server starts feeling like a real hosting platform.

What if someone hits http://192.168.0.19/ (the IP, no hostname)? Apache picks the FIRST enabled vhost alphabetically. That's why the default is named 000-default.conf — leading zeros sort it first. Try renaming to test, or just leave it as is.