Chapter 9: Domain Names, DNS and Subdomains
9.10 Subdomains
Subdomains are free and unlimited. Each one is just another DNS record plus (usually) another server block or virtual host.
example.com ─┐
www.example.com ─┼─► A 13.233.10.25 (web-1) ─► server_name decides the folder
blog.example.com ─┘ /var/www/example, /var/www/blog
api.example.com ───► A 13.234.55.60 (app server, Node on :3000 behind Nginx)
shop.example.com ───► CNAME my-alb-123.ap-south-1.elb.amazonaws.com
Step 1: DNS record (GoDaddy → DNS → Add New Record)
| Type | Name | Value | Use |
|---|---|---|---|
| A | blog |
13.233.10.25 |
Same server, different site |
| A | api |
13.234.55.60 |
Different EC2 instance (its own Elastic IP) |
| CNAME | shop |
my-alb-123.ap-south-1.elb.amazonaws.com |
AWS load balancer / other hostname |
| A | * |
13.233.10.25 |
Wildcard: any undefined subdomain |
In the Name field type only the subdomain part (blog), not blog.example.com. Otherwise you may create blog.example.com.example.com.
Step 2: a site for the subdomain on the server
sudo mkdir -p /var/www/blog
echo '<h1>Welcome to blog.example.com</h1>' | sudo tee /var/www/blog/index.html
# Nginx: blog.conf
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
index index.html;
}
# Apache: blog.conf
<VirtualHost *:80>
ServerName blog.example.com
DocumentRoot /var/www/blog
<Directory /var/www/blog>
Require all granted
</Directory>
</VirtualHost>
Test, reload, then verify with dig blog.example.com +short and curl http://blog.example.com.
Subdomain for a backend app (reverse proxy)
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000; # Express / Flask app (Chapter 10)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
(On CentOS remember sudo setsebool -P httpd_can_network_connect 1.)