> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo First Website with Nginx

> Guide to creating and serving a minimal Hello World website with NGINX, including configuration, document root, enabling site, testing with Host header, and troubleshooting.

This lesson walks through creating a minimal "Hello World" website served by NGINX on a single host. Follow these steps in order:

* Verify NGINX is running.
* Create a simple server block in `sites-available`.
* Create the document root and `index.html`.
* Enable the site and test it locally using the `Host` header.

## 1. Verify NGINX is running

Check the service status and start it if necessary:

```bash theme={null}
sudo systemctl status nginx
sudo systemctl start nginx
```

Confirm the default page is served:

```bash theme={null}
curl localhost
```

Example returned HTML (truncated):

```html theme={null}
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
</html>
```

This verifies that NGINX is installed and serving the default page.

## 2. Become root and inspect NGINX configuration directories

To avoid prefixing `sudo` for each command, switch to root for the remainder of the setup (optional but convenient):

```bash theme={null}
sudo su
cd /etc/nginx
ll
```

You should see `sites-available/` and `sites-enabled/` among the configuration files. Then change into `sites-available`:

```bash theme={null}
cd /etc/nginx/sites-available
ll
```

Typically you'll see a `default` file here.

## 3. Create a new site configuration

Copy the default site config to a new file named `helloworld`:

```bash theme={null}
cp default helloworld
```

Edit `helloworld` and simplify it to the essentials: `listen`, `root`, `index`, and `server_name`. Remove commented examples to keep the file focused.

Example minimal `helloworld` server block:

```nginx theme={null}
server {
    listen 80;

    root /var/www/helloworld;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    server_name helloworld.com;

    location / {
        # First attempt to serve request as file, then as directory,
        # then fall back to displaying a 404.
        try_files $uri $uri/ =404;
    }
}
```

Notes:

* Do not use `listen 80 default_server;` in more than one server block — this causes a duplicate default server error.
* Set `server_name` to the hostname you intend to serve (we'll test this with a Host header).

<Callout icon="lightbulb" color="#1CB2FE">
  Set `server_name` to the hostname you intend to serve (for example, `helloworld.com`). NGINX uses the `Host` header to select the matching server block; if no match is found, NGINX serves the first matching server block (often the default).
</Callout>

## 4. Create the document root and index page

Create the document root that matches the `root` directive and add a basic `index.html`:

```bash theme={null}
mkdir -p /var/www/helloworld
cd /var/www/helloworld
```

Create the index file:

```html theme={null}
<!-- /var/www/helloworld/index.html -->
<h1> Hello World! </h1>
```

Ensure the file is named `index.html` because the server block uses `index index.html` in its `index` list.

## 5. Enable the site (sites-available → sites-enabled)

Enable the site by creating a symbolic link from `sites-available` to `sites-enabled`:

```bash theme={null}
ln -s /etc/nginx/sites-available/helloworld /etc/nginx/sites-enabled/
```

Verify the symlink exists:

```bash theme={null}
ll /etc/nginx/sites-enabled/
# you should see something like:
# lrwxrwxrwx 1 root root 37 Feb  5 14:07 helloworld -> /etc/nginx/sites-available/helloworld
```

## 6. Test NGINX configuration and reload

Always test NGINX configuration syntax before reloading:

```bash theme={null}
nginx -t
```

Common error example:

```text theme={null}
nginx: [emerg] a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/helloworld:3
nginx: configuration file /etc/nginx/nginx.conf test failed
```

This indicates two server blocks are configured as the `default_server`. Fix the conflicting `listen` lines (remove `default_server` from one) or disable the default site, then re-run the test:

```bash theme={null}
nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Reload NGINX to apply the new configuration:

```bash theme={null}
nginx -s reload
```

(Alternatively: `systemctl reload nginx`.)

## 7. Test locally using the Host header

If you switched to root, return to your regular user for testing:

```bash theme={null}
exit
```

A plain `curl localhost` will still return the default "Welcome to nginx!" page because the request lacks a `Host` header matching `helloworld.com`:

```bash theme={null}
curl localhost
# returns the default "Welcome to nginx!" HTML
```

To test the `helloworld.com` site without DNS, send the `Host` header explicitly:

```bash theme={null}
curl --header "Host: helloworld.com" localhost
```

You should get the Hello World page:

```html theme={null}
<h1> Hello World! </h1>
```

If you pass a `Host` header that doesn't match any `server_name` in your enabled configs (for example `Host: someunknown`), NGINX will serve the first available server block (often the default). Proper `server_name` configuration and testing are important.

## Quick reference: useful paths and commands

| Item                  | Purpose                        | Example                                                                 |
| --------------------- | ------------------------------ | ----------------------------------------------------------------------- |
| NGINX config dir      | Main configuration files       | `/etc/nginx`                                                            |
| Available sites       | Site definitions (not enabled) | `/etc/nginx/sites-available/`                                           |
| Enabled sites         | Active site symlinks           | `/etc/nginx/sites-enabled/`                                             |
| Create site file      | Copy default stub              | `cp default helloworld`                                                 |
| Enable site           | Create symlink to enable       | `ln -s /etc/nginx/sites-available/helloworld /etc/nginx/sites-enabled/` |
| Test config           | Syntax check before reload     | `nginx -t`                                                              |
| Reload NGINX          | Apply configuration changes    | `nginx -s reload` or `systemctl reload nginx`                           |
| Test with Host header | Verify virtual host selection  | `curl --header "Host: helloworld.com" localhost`                        |

## Troubleshooting tips

* Duplicate default server error: remove `default_server` from one `listen` directive or disable the default site.
* 403 Forbidden: check filesystem permissions and ownership for `/var/www/helloworld` and the index file.
* Still seeing default page: ensure your `Host` header matches `server_name` or update `/etc/hosts`/DNS accordingly.

## 8. Next steps

* If you want this site reachable from other machines, open port 80 in your firewall. On Ubuntu, use `ufw`:

```bash theme={null}
sudo ufw allow http
```

* Use DNS or update `/etc/hosts` for a friendly hostname (e.g., `helloworld.com`) in your testing environment.
* For production, configure TLS (HTTPS) using a certificate from Let's Encrypt or another CA, and consider a reverse proxy or load balancer if needed.

Resources and further reading:

* NGINX official docs: [https://nginx.org/en/docs/](https://nginx.org/en/docs/)
* Ubuntu `ufw` guide: [https://help.ubuntu.com/community/UFW](https://help.ubuntu.com/community/UFW)
* curl manual: [https://curl.se/docs/manpage.html](https://curl.se/docs/manpage.html)

That’s it — you now have a minimal NGINX-hosted site and know how to test virtual hosts locally using the `Host` header.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/nginx-for-beginners/module/0de43784-b08d-4ce0-8470-a7541b78fe58/lesson/205db332-da0d-4f3d-8273-225f9566c386" />
</CardGroup>
