Virtual Hosts — Multiple Sites, One Apache
192.168.0.19/medtrack/. Give each project its own hostname — medtrack.local. Same server, multiple sites, pro vibe.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
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
- Right-click Notepad → Run as administrator (MANDATORY — the hosts file is protected)
- File → Open →
C:\Windows\System32\drivers\etc\hosts(set file filter to "All Files") - Add this line at the bottom:
192.168.0.19 medtrack.local - Save
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.
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.
- SSH in. Make a new folder:
mkdir -p /home/erictey/server/sandbox - Create an index file:
echo "<h1>Sandbox lives!</h1>" > /home/erictey/server/sandbox/index.html - Copy the medtrack vhost config:
sudo cp /etc/apache2/sites-available/medtrack.conf /etc/apache2/sites-available/sandbox.conf - Edit it:
sudo nano /etc/apache2/sites-available/sandbox.conf— change every "medtrack" to "sandbox" - Enable, validate, reload:
sudo a2ensite sandbox && sudo apache2ctl -t && sudo systemctl reload apache2 - Add
192.168.0.19 sandbox.localto your Windows hosts file - 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.
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.