React remains the most popular JavaScript framework for building modern web applications. But deploying to your own Ubuntu server gives you complete control, better performance, and significant cost savings. This comprehensive guide covers everything you need to know about React hosting on Ubuntu servers in 2025, from basic deployments to advanced optimization techniques.

Note: This guide focuses on deploying React on Ubuntu servers. CloudPloy currently supports Laravel applications, with React support coming soon. Stay tuned for updates!

Understanding React Hosting Requirements

React applications have unique hosting needs that differ from traditional server-side applications:

  • Static File Serving: Build outputs need efficient web server configuration
  • Client-Side Routing: Proper nginx configuration for SPA routing
  • API Integration: Backend proxy and CORS handling
  • SEO Optimization: Server-side rendering for better search visibility
  • Performance: Code splitting, compression, and caching
  • Security: XSS protection, Content Security Policies, and HTTPS

Ubuntu servers provide the perfect foundation for hosting React applications with complete control over your infrastructure.

Quick Start: Deploy React on Ubuntu Server

Step 1: Prepare Your Ubuntu Server

# Update system packages
sudo apt update && sudo apt upgrade -y

# Install Node.js (using NodeSource repository)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install nginx
sudo apt install nginx -y

# Install certbot for SSL certificates
sudo apt install certbot python3-certbot-nginx -y

Step 2: Prepare Your React Application

# Create a new React app (if needed)
npx create-react-app my-react-app
cd my-react-app

# Or use Vite for faster builds
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install

# Build for production
npm run build

Step 3: Deploy to Your Ubuntu Server

# Copy build files to server
scp -r build/ user@your-server:/var/www/my-react-app/

# Or use git deployment (recommended)
git clone https://github.com/yourusername/my-react-app.git /var/www/my-react-app
cd /var/www/my-react-app
npm ci --production
npm run build

Step 4: Configure Nginx

# Create nginx server block
sudo nano /etc/nginx/sites-available/my-react-app
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/my-react-app/build;
    index index.html;

    # Handle client-side routing
    location / {
        try_files $uri $uri/ /index.html;
    }

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

    # 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;
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/my-react-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 5: Set Up SSL Certificate

# Get SSL certificate with certbot
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# Verify auto-renewal
sudo certbot renew --dry-run

Your React app is now live with HTTPS, optimized caching, and production-ready configuration!

React Build Optimization for Production

1. Environment Configuration

Create a .env.production file for production settings:

REACT_APP_API_URL=https://api.yourdomain.com
REACT_APP_ENVIRONMENT=production
REACT_APP_VERSION=$npm_package_version

Load environment variables in your build process:

// src/config/api.js
const API_URL = process.env.REACT_APP_API_URL || 'http://localhost:3001';

export const fetchData = async (endpoint) => {
  const response = await fetch(`${API_URL}${endpoint}`);
  return response.json();
};

2. Build Optimization Techniques

Code Splitting with React.lazy()

// src/App.js
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

// Lazy load route components
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/profile" element={<Profile />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

Bundle Size Optimization

// webpack.config.js (for ejected apps)
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          priority: 10
        },
        common: {
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true
        }
      }
    }
  }
};

3. Advanced Nginx Configuration for React

Create an optimized nginx configuration for React applications:

server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;
    root /var/www/my-react-app/build;
    index index.html;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Handle client-side routing
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets aggressively
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # API proxy (if needed)
    location /api/ {
        proxy_pass http://localhost:3001/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

Advanced React Hosting Scenarios

Server-Side Rendering with Next.js

For SEO-critical React applications, deploy Next.js on Ubuntu:

# Create Next.js app
npx create-next-app@latest my-nextjs-app
cd my-nextjs-app

# Install PM2 for process management
sudo npm install -g pm2

# Create ecosystem file
echo 'module.exports = {
  apps: [{
    name: "nextjs-app",
    script: "npm",
    args: "start",
    cwd: "/var/www/my-nextjs-app",
    env: {
      NODE_ENV: "production",
      PORT: 3000
    }
  }]
}' > ecosystem.config.js

# Build and start
npm run build
pm2 start ecosystem.config.js
pm2 save
pm2 startup

Configure nginx as reverse proxy:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

React with Express Backend

Deploy full-stack React applications on Ubuntu:

// server.js
const express = require('express');
const path = require('path');
const app = express();

// API routes
app.use('/api', require('./routes/api'));

// Serve React build
app.use(express.static(path.join(__dirname, 'client/build')));

app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Create systemd service for your full-stack app:

# Create service file
sudo nano /etc/systemd/system/react-express-app.service
[Unit]
Description=React Express App
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/react-express-app
Environment=NODE_ENV=production
Environment=PORT=5000
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
# Enable and start service
sudo systemctl enable react-express-app
sudo systemctl start react-express-app
sudo systemctl status react-express-app

Micro-Frontend Architecture

Deploy multiple React apps as micro-frontends using nginx routing:

# Main nginx configuration for micro-frontends
server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    # Main app (shell)
    location / {
        root /var/www/main-app/build;
        try_files $uri $uri/ /index.html;
    }

    # Dashboard micro-frontend
    location /dashboard {
        alias /var/www/dashboard-app/build;
        try_files $uri $uri/ /dashboard/index.html;
    }

    # Settings micro-frontend  
    location /settings {
        alias /var/www/settings-app/build;
        try_files $uri $uri/ /settings/index.html;
    }

    # API gateway
    location /api/ {
        proxy_pass http://localhost:3001/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
// main-app/src/App.js
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'dashboard',
    entry: '/dashboard/',
    container: '#dashboard-container',
    activeRule: '/dashboard'
  },
  {
    name: 'settings',
    entry: '/settings/',
    container: '#settings-container',
    activeRule: '/settings'
  }
]);

start();

Performance Optimization for React on Ubuntu

1. Enable HTTP/2 and Compression

Optimize nginx for maximum performance:

# Update nginx.conf
sudo nano /etc/nginx/nginx.conf
http {
    # Enable HTTP/2
    listen 443 ssl http2;
    
    # Optimize gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;
        
    # Enable brotli compression (if installed)
    brotli on;
    brotli_comp_level 6;
    brotli_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml+rss
        application/atom+xml
        image/svg+xml;
        
    # Connection optimization
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
}

2. Implement Service Workers

// src/serviceWorker.js
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open('v1').then(cache => {
      return cache.addAll([
        '/',
        '/static/js/bundle.js',
        '/static/css/main.css'
      ]);
    })
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

3. Image Optimization with ImageMagick

Install and configure ImageMagick for automatic image optimization:

# Install ImageMagick
sudo apt install imagemagick -y

# Create image optimization script
sudo nano /usr/local/bin/optimize-images.sh
#!/bin/bash
# Image optimization script

WEBROOT="/var/www/my-react-app/build"

find "$WEBROOT" -name "*.jpg" -o -name "*.jpeg" | while read img; do
    convert "$img" -strip -interlace Plane -gaussian-blur 0.05 -quality 85% "$img"
done

find "$WEBROOT" -name "*.png" | while read img; do
    convert "$img" -strip "$img"
done

echo "Image optimization completed"
# Make script executable
sudo chmod +x /usr/local/bin/optimize-images.sh

# Run after each deployment
/usr/local/bin/optimize-images.sh
// src/components/OptimizedImage.js
import { useState, useEffect } from 'react';

const OptimizedImage = ({ src, alt, ...props }) => {
  const [loaded, setLoaded] = useState(false);

  return (
    <img 
      src={src} 
      alt={alt} 
      {...props}
      loading="lazy"
      onLoad={() => setLoaded(true)}
      style={{
        opacity: loaded ? 1 : 0,
        transition: 'opacity 0.3s',
        ...props.style
      }}
    />
  );
};

export default OptimizedImage;

Security Best Practices for React Hosting

1. Content Security Policy with Nginx

# Add to your nginx server block
server {
    # ... other configuration
    
    # Security headers
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https:; connect-src 'self' https:; media-src 'self'; object-src 'none'; child-src 'self';" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # Remove server tokens
    server_tokens off;
    
    # Limit request size
    client_max_body_size 10M;
    
    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
    limit_req zone=api burst=20 nodelay;
}

2. Firewall Configuration

# Configure UFW firewall
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Nginx Full'
sudo ufw status

2. Environment Variable Security

// Never expose sensitive data in React
// ❌ Wrong
const API_KEY = process.env.REACT_APP_SECRET_KEY;

// ✅ Correct - Use backend proxy
const fetchSecureData = async () => {
  const response = await fetch('/api/secure-endpoint');
  return response.json();
};

3. XSS Protection

// Always sanitize user input
import DOMPurify from 'dompurify';

const SafeHTML = ({ html }) => {
  const cleanHTML = DOMPurify.sanitize(html);
  return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;
};

Monitoring and Analytics

Server Monitoring with Netdata

# Install Netdata for real-time monitoring
bash <(curl -Ss https://my-netdata.io/kickstart.sh)

# Configure nginx monitoring
sudo nano /etc/netdata/python.d/nginx.conf
localhost:
  name: 'local'
  url: 'http://localhost/nginx_status'
# Add nginx status endpoint
sudo nano /etc/nginx/sites-available/default
# Add to server block
location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
}

Application Monitoring

// Error tracking and performance monitoring
window.addEventListener('error', (event) => {
  // Send error to your logging service
  fetch('/api/errors', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      message: event.error.message,
      stack: event.error.stack,
      url: window.location.href,
      timestamp: new Date().toISOString()
    })
  });
});

// Performance monitoring
if ('performance' in window) {
  window.addEventListener('load', () => {
    const perfData = performance.getEntriesByType('navigation')[0];
    const metrics = {
      loadTime: perfData.loadEventEnd - perfData.loadEventStart,
      domContentLoaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
      firstPaint: performance.getEntriesByType('paint')[0]?.startTime,
      url: window.location.href
    };
    
    fetch('/api/metrics', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(metrics)
    });
  });
}

Custom Analytics Integration

// src/analytics.js
export const trackEvent = (action, category, label, value) => {
  if (window.gtag) {
    window.gtag('event', action, {
      event_category: category,
      event_label: label,
      value: value
    });
  }
};

// Usage in components
import { trackEvent } from '../analytics';

const Button = ({ onClick, children }) => {
  const handleClick = (e) => {
    trackEvent('click', 'UI', children);
    onClick(e);
  };
  
  return <button onClick={handleClick}>{children}</button>;
};

CI/CD Pipeline for React Apps

GitHub Actions with Ubuntu Server Deployment

# .github/workflows/deploy.yml
name: Deploy React to Ubuntu Server

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Install dependencies
      run: npm ci
      
    - name: Run tests
      run: npm test -- --coverage --watchAll=false
      
    - name: Build production
      run: npm run build
      
    - name: Deploy to Ubuntu Server
      uses: appleboy/ssh-action@v0.1.7
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          cd /var/www/my-react-app
          git pull origin main
          npm ci --production
          npm run build
          sudo systemctl reload nginx
          
    - name: Health Check
      run: |
        sleep 30
        curl -f https://yourdomain.com || exit 1

Alternative: Deploy Script

#!/bin/bash
# deploy.sh - Simple deployment script

set -e

APP_DIR="/var/www/my-react-app"
BACKUP_DIR="/var/backups/my-react-app"

# Create backup
echo "Creating backup..."
sudo mkdir -p "$BACKUP_DIR"
sudo cp -r "$APP_DIR/build" "$BACKUP_DIR/build-$(date +%Y%m%d_%H%M%S)"

# Pull latest changes
echo "Pulling latest changes..."
cd "$APP_DIR"
git pull origin main

# Install dependencies and build
echo "Building application..."
npm ci --production
npm run build

# Test build
if [ ! -f "build/index.html" ]; then
    echo "Build failed - restoring backup"
    sudo rm -rf "$APP_DIR/build"
    sudo cp -r "$BACKUP_DIR/build-$(ls -t $BACKUP_DIR | head -1)" "$APP_DIR/build"
    exit 1
fi

# Reload nginx
echo "Reloading nginx..."
sudo nginx -t && sudo systemctl reload nginx

# Health check
echo "Performing health check..."
sleep 5
if curl -f https://yourdomain.com > /dev/null 2>&1; then
    echo "Deployment successful!"
else
    echo "Health check failed!"
    exit 1
fi

Cost Comparison: React Hosting Platforms

PlatformMonthly CostSetup TimeSSLCDNControl Level
Ubuntu Server$5-2030minFreeOptionalComplete
Vercel$20+2-3minFreeYesLimited
Netlify$19+2-4minFreeYesLimited
AWS Amplify$15+3-5minFreeYesModerate
DigitalOcean App$12+2-4minFreeYesLimited
Railway$20+3-5minFreeNoLimited

Ubuntu Server Advantages:

  • Complete Control: Full server access and customization
  • Cost Effective: $5-20/month for powerful VPS
  • No Vendor Lock-in: Switch providers anytime
  • Learning Experience: Understand deployment internals
  • Scalability: Easily upgrade resources
  • Multiple Apps: Host multiple projects on one server

Troubleshooting Common React Hosting Issues

Issue 1: Blank Page After Deployment

Solution: Configure proper routing for SPAs:

// cloudploy.json
{
  "routes": [
    { "src": "/(.*)", "dest": "/index.html" }
  ]
}

Issue 2: Environment Variables Not Working

Solution: Use REACT_APP_ prefix:

# .env.production
REACT_APP_API_URL=https://api.example.com

Issue 3: Large Bundle Size

Solution: Implement code splitting and tree shaking:

// Use dynamic imports
const HeavyComponent = lazy(() => 
  import(/* webpackChunkName: "heavy" */ './HeavyComponent')
);

Issue 4: CORS Errors

Solution: Configure nginx proxy:

# Add to your nginx server block
location /api/ {
    # Remove trailing slash and proxy to backend
    proxy_pass http://localhost:3001/;
    
    # CORS headers
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
    
    # Handle preflight OPTIONS requests
    if ($request_method = 'OPTIONS') {
        add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization, Content-Type";
        add_header Access-Control-Max-Age 1728000;
        add_header Content-Type "text/plain; charset=utf-8";
        add_header Content-Length 0;
        return 204;
    }
    
    # Standard proxy headers
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

React Hosting Best Practices Checklist

✅ Pre-Deployment:

  • Optimize bundle size (< 200KB gzipped)
  • Implement code splitting
  • Configure environment variables
  • Add error boundaries
  • Test production build locally

✅ Deployment:

  • Use CI/CD pipeline
  • Enable CDN caching
  • Configure custom domain
  • Set up SSL certificate
  • Implement monitoring

✅ Post-Deployment:

  • Monitor Core Web Vitals
  • Set up error tracking
  • Configure analytics
  • Implement A/B testing
  • Regular performance audits

Migrating Existing React Apps to Ubuntu Server

From Shared Hosting

# Download your current files
wget -r --no-parent http://youroldsite.com/

# Upload to Ubuntu server
scp -r youroldsite.com/ user@your-server:/var/www/

# Set proper permissions
sudo chown -R www-data:www-data /var/www/youroldsite.com/
sudo chmod -R 755 /var/www/youroldsite.com/

From Vercel/Netlify

# Clone your repository
git clone https://github.com/yourusername/your-react-app.git /var/www/your-react-app
cd /var/www/your-react-app

# Install dependencies and build
npm ci --production
npm run build

# Configure nginx (use configuration from earlier sections)
sudo nano /etc/nginx/sites-available/your-react-app

From Heroku

# If using git deployment
heroku git:remote -a your-app-name
git remote add ubuntu user@your-server:/var/www/your-react-app.git

# Push to Ubuntu server
git push ubuntu main

# SSH into server and build
ssh user@your-server
cd /var/www/your-react-app
npm ci --production
npm run build

Advanced Features for React Developers

1. Staging Environment Setup

Create separate staging environment:

# Create staging directory
sudo mkdir -p /var/www/staging.yourdomain.com

# Configure staging nginx server block
sudo nano /etc/nginx/sites-available/staging.yourdomain.com
server {
    listen 80;
    server_name staging.yourdomain.com;
    root /var/www/staging.yourdomain.com/build;
    index index.html;
    
    # Basic auth for staging
    auth_basic "Staging Environment";
    auth_basic_user_file /etc/nginx/.htpasswd;
    
    location / {
        try_files $uri $uri/ /index.html;
    }
}
# Create basic auth file
sudo htpasswd -c /etc/nginx/.htpasswd staging_user

# Enable staging site
sudo ln -s /etc/nginx/sites-available/staging.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

2. Rollback System with Git

#!/bin/bash
# rollback.sh - Simple rollback script

APP_DIR="/var/www/my-react-app"
BACKUP_DIR="/var/backups/my-react-app"

if [ -z "$1" ]; then
    echo "Available backups:"
    ls -la "$BACKUP_DIR"
    echo "Usage: ./rollback.sh <backup-name>"
    exit 1
fi

BACKUP_NAME="$1"

if [ ! -d "$BACKUP_DIR/$BACKUP_NAME" ]; then
    echo "Backup $BACKUP_NAME not found!"
    exit 1
fi

# Stop application
echo "Rolling back to $BACKUP_NAME..."

# Backup current version
sudo cp -r "$APP_DIR/build" "$BACKUP_DIR/build-rollback-$(date +%Y%m%d_%H%M%S)"

# Restore backup
sudo rm -rf "$APP_DIR/build"
sudo cp -r "$BACKUP_DIR/$BACKUP_NAME" "$APP_DIR/build"

# Reload nginx
sudo systemctl reload nginx

echo "Rollback completed!"

3. A/B Testing with Nginx

# A/B testing with nginx split testing
server {
    listen 443 ssl http2;
    server_name yourdomain.com;
    
    # A/B testing logic
    set $variant "A";
    if ($cookie_ab_test = "B") {
        set $variant "B";
    }
    if ($cookie_ab_test = "") {
        set $variant $split_clients_$remote_addr;
    }
    
    # Split traffic 50/50
    split_clients $remote_addr $split_clients_$remote_addr {
        50% "A";
        50% "B";
    }
    
    # Serve different builds based on variant
    location / {
        if ($variant = "A") {
            root /var/www/my-react-app/build-a;
        }
        if ($variant = "B") {
            root /var/www/my-react-app/build-b;
        }
        
        add_header Set-Cookie "ab_test=$variant; Path=/; HttpOnly; Secure";
        try_files $uri $uri/ /index.html;
    }
}

Conclusion: Why Ubuntu Server for React Hosting?

Ubuntu servers offer the perfect combination of control, performance, and cost-effectiveness for React developers:

  • ⚡ Complete Control - Configure everything exactly as needed
  • 💰 Cost Effective - $5-20/month for powerful hosting
  • 🔒 Security First - Full control over security configuration
  • 📈 Scalable - Easy to upgrade resources as you grow
  • 🎓 Learning Experience - Understand deployment and DevOps
  • 🌐 No Vendor Lock-in - Switch providers anytime

Whether you’re building a simple portfolio or a complex enterprise application, Ubuntu servers provide the foundation you need to succeed while keeping costs low and maintaining complete control.

Get Started with Ubuntu Server React Hosting Today

Ready to take control of your React deployment?

  1. Get a VPS: DigitalOcean, Linode, or AWS EC2 ($5-20/month)
  2. Follow this guide: Complete setup in 30 minutes
  3. Deploy with confidence: Full control over your infrastructure

For managed deployment automation, consider using the Ploy CLI tool to streamline your Ubuntu server deployments while maintaining full control over your infrastructure.

Popular VPS Providers:

  • DigitalOcean - Developer-friendly, $6/month
  • Linode - High performance, $5/month
  • Vultr - Global locations, $6/month
  • AWS EC2 - Enterprise grade, varies

Last updated: September 2025. React is a trademark of Meta Platforms, Inc.