Skip to content

A practical guide for deploying multiple web applications on a single RHEL 8 server using Nginx. instructions for migrating from PaaS solutions like Heroku to self-hosted infrastructure.

Notifications You must be signed in to change notification settings

afanto/nginx-deployment-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Web App Deployment Guide (RHEL 8 + Nginx)

RHEL: Red Hat Enterprise Linux - a commercial Linux distribution commonly used in enterprise environments
Nginx: A web server that can serve static files, reverse proxy to backend applications, load balance, etc.

This guide documents what I've learned so far about hosting multiple web apps on a single server. I moved away from Heroku to have more control and better understand how web deployment actually works. This is a reference for myself and others looking to do the same and get up and running quickly. While these examples show static file serving, Nginx can also reverse proxy to any backend application (Node.js, Python, Ruby, Java, etc.) running on different ports (e.g., proxy_pass http://localhost:3000).

Prerequisites

  • Port 80 must be open
  • Nginx installed and running
  • SSH access to server

Quick Deploy Steps

1. Transfer Files

With Internet Access:

cd ~
git clone https://github.com/username/myapp.git

Without Internet (VM/isolated server):

# On local machine
tar -czf myapp.tar.gz --exclude='.git*' *

# Transfer to server
scp myapp.tar.gz user@server:~/

# On server
mkdir ~/myapp
cd ~/myapp
tar -xzf ../myapp.tar.gz
rm ../myapp.tar.gz

2. Set Permissions

# Ensure directory is accessible
chmod 755 ~/myapp

3. Configure Nginx

# Edit nginx config
sudo nano /etc/nginx/nginx.conf

# Add location block inside server { } block (around line 40-60)
# See template below for exact placement

4. Reload Nginx

# Test configuration
sudo nginx -t

# Reload if test passes
sudo systemctl reload nginx

Nginx Configuration Template

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    include /etc/nginx/conf.d/*.conf;

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /var/www/html;

        include /etc/nginx/default.d/*.conf;

        # Security headers
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        add_header Referrer-Policy "strict-origin-when-cross-origin" always;

        # Homepage
        location = / {
            root $HOME;
            try_files /homepage.html =404;
        }

        # ========== ADD YOUR APPS HERE ==========

        location /myapp {
            alias $HOME/myapp;
            try_files $uri $uri/ /myapp/index.html;

            # Cache static assets
            location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
                expires 30d;
                add_header Cache-Control "public, immutable";
            }
        }

        # ========== END APP SECTION ==========

        # Health check
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;
        }
    }
}

Adding New Apps

  1. Upload app to ~/newapp/
  2. Run permissions:
    chmod 755 ~/newapp
  3. Add to nginx (inside server block):
    location /newapp {
        alias $HOME/newapp;
        try_files $uri $uri/ /newapp/index.html;
        
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
            expires 30d;
            add_header Cache-Control "public, immutable";
        }
    }
  4. Reload: sudo nginx -t && sudo systemctl reload nginx

Homepage (Optional)

The homepage at ~/homepage.html is a simple landing page to list all your apps. You can also access apps directly via their URLs (e.g., http://server/myapp).

<!DOCTYPE html>
<html>
<head>
    <title>Web Applications</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
        .app-list { list-style: none; padding: 0; }
        .app-list li { margin: 10px 0; }
        .app-list a { display: block; padding: 15px; background: #f5f5f5; text-decoration: none; color: #333; border-radius: 5px; }
        .app-list a:hover { background: #e0e0e0; }
    </style>
</head>
<body>
    <h1>Available Applications</h1>
    <ul class="app-list">
        <li><a href="/app1/">App 1 Description</a></li>
        <li><a href="/app2/">App 2 Description</a></li>
        <!-- Add more apps here -->
    </ul>
</body>
</html>

To use: Edit the list to include your apps, or skip the homepage entirely and access apps directly.

Troubleshooting

Problem Solution
403 Forbidden Run permission commands again, check ls -la ~/myapp/
404 Not Found Verify nginx path matches directory name
App won't load Check error log: sudo tail -f /var/log/nginx/error.log

About

A practical guide for deploying multiple web applications on a single RHEL 8 server using Nginx. instructions for migrating from PaaS solutions like Heroku to self-hosted infrastructure.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published