How to Set Up and Configure an Application Server on Ubuntu 24.04

Installing and configuring an application server on Ubuntu 24.04 is an important step when preparing web applications for production use. Whether you plan to run Node.js applications, Python-based web services, or PHP websites, a correctly configured application server gives you a dependable, secure, and scalable base for deployment.

This guide explains how to prepare a production-ready application server on an Ubuntu 24.04 server. You will learn how to install and configure core components, use Nginx as a reverse proxy, protect the server with SSL certificates, and manage applications with systemd. The setup follows common production best practices so the server can handle real workloads reliably.

Key Takeaways

  • Set up a production-ready application server on Ubuntu 24.04 using a cloud-based or virtual server.
  • Configure Nginx as a reverse proxy to receive incoming requests and forward traffic to your applications.
  • Add SSL/TLS encryption with Let’s Encrypt to secure client connections.
  • Deploy and manage applications with systemd for stable process management.
  • Improve security with firewall rules, permissions, and hardening measures.
  • Support different application types, including Node.js, Python, and PHP applications.

Prerequisites

Before you begin, make sure you have the following:

  • An Ubuntu 24.04 server. The server should already have a non-root user with sudo privileges and a basic firewall configuration.
  • A domain name pointing to your server’s IP address.
  • Basic Linux command-line knowledge and SSH access to your server.

Step 1 — Updating System Packages

Begin by refreshing the package index and upgrading the installed packages. This ensures that your server uses current package information, security fixes, and software versions:

sudo apt update
sudo apt upgrade -y

This brings your Ubuntu 24.04 server up to date with the latest available security patches and package versions. Ubuntu 24.04 includes newer versions of important components compared with Ubuntu 22.04, including updated releases of systemd, Nginx, and other core system tools.

Step 2 — Installing Nginx as a Reverse Proxy

Nginx can act as a reverse proxy that accepts incoming HTTP and HTTPS requests and forwards them to your application server. This approach offers several advantages, including SSL termination, potential load balancing, and improved security because the application itself remains behind the proxy.

Install Nginx with apt:

After the installation finishes, start Nginx and enable it so it launches automatically when the server boots:

sudo systemctl start nginx
sudo systemctl enable nginx

Check whether Nginx is running:

sudo systemctl status nginx

The output should show that Nginx is active and running.

Output

● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-12-18 07:03:01 UTC; 32s ago
       Docs: man:nginx(8)
   Main PID: 46284 (nginx)
      Tasks: 3 (limit: 4656)
     Memory: 2.4M (peak: 5.3M)
        CPU: 46ms
     CGroup: /system.slice/nginx.service
             ├─46284 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
             ├─46286 "nginx: worker process"
             └─46287 "nginx: worker process"

Dec 18 07:03:01 Ubuntu-24 systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Dec 18 07:03:01 Ubuntu-24 systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.

Step 3 — Configuring the Firewall

Ubuntu 24.04 commonly uses UFW, the Uncomplicated Firewall, to manage firewall rules. Configure it to allow HTTP, HTTPS, and SSH traffic while blocking ports that are not required.

First, confirm that UFW is installed and review its current status:

If UFW is not active yet, allow the required services and enable the firewall:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Output

sudo ufw allow 'Nginx Full'
sudo ufw enable
Rules updated
Rules updated (v6)
Rules updated
Rules updated (v6)
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

The Nginx Full profile opens both HTTP on port 80 and HTTPS on port 443. Verify the active firewall rules:

You should see rules that allow OpenSSH and Nginx Full traffic.

Output

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp (OpenSSH)           ALLOW IN    Anywhere
80,443/tcp (Nginx Full)    ALLOW IN    Anywhere
22/tcp (OpenSSH (v6))      ALLOW IN    Anywhere (v6)
80,443/tcp (Nginx Full (v6)) ALLOW IN    Anywhere (v6)

Step 4 — Setting Up SSL with Let’s Encrypt

SSL/TLS encryption is essential for production application servers. Let’s Encrypt provides free certificates that can be renewed automatically.

Install Certbot together with the Nginx plugin:

sudo apt install certbot python3-certbot-nginx -y

Request an SSL certificate for your domain. Replace your_domain with your actual domain name:

sudo certbot --nginx -d your_domain -d www.your_domain

Certbot asks for an email address and whether HTTP traffic should be redirected to HTTPS. Choose the redirect option to improve security. The certificate is then configured for automatic renewal before it expires.

Test the automatic renewal process:

sudo certbot renew --dry-run

If the command finishes without errors, automatic renewal is working correctly.

Step 5 — Configuring Nginx as a Reverse Proxy

Create an Nginx server block that forwards traffic to your application server. The following example uses a generic configuration that you can adapt to different application types.

Create a new configuration file for your domain:

sudo nano /etc/nginx/sites-available/your_domain

Add the following configuration. Replace your_domain with your actual domain and adjust the proxy_pass target so it matches the port used by your application:

server {
    listen 80;
    listen [::]:80;
    server_name your_domain www.your_domain;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name your_domain www.your_domain;

    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    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_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;
        proxy_cache_bypass $http_upgrade;
    }
}

This configuration:

  • Redirects HTTP requests to HTTPS.
  • Handles SSL termination at the Nginx layer.
  • Forwards requests to an application running on port 3000, which you can change as required.
  • Keeps client IP address and protocol information available to the application.

Enable the configuration by creating a symbolic link:

sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/

Check the Nginx configuration for syntax errors:

If the test is successful, reload Nginx to apply the new configuration:

sudo systemctl reload nginx

Step 6 — Installing Application Runtime Dependencies

The runtime packages you need depend on the type of application you want to run. This section covers Node.js, Python, and PHP application setups.

Installing Node.js

For Node.js applications, install Node.js from the NodeSource repository to use the current LTS version:

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

Verify the installation:

node --version
npm --version

Output

Installing Python and pip

Ubuntu 24.04 includes Python 3.12 by default. Install pip and the tools required for virtual environments:

sudo apt install python3-pip python3-venv -y

Confirm the installed versions:

python3 --version
pip3 --version

Output

pip3 --version
Python 3.12.3
pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)

Installing PHP and PHP-FPM

For PHP applications, install PHP together with PHP-FPM, the FastCGI Process Manager:

sudo apt install php-fpm php-mysql php-mbstring php-xml php-curl -y

Check whether PHP-FPM is running:

sudo systemctl status php8.3-fpm

Output

 Loaded: loaded (/usr/lib/systemd/system/php8.3-fpm.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-12-18 08:02:36 UTC; 1min 56s ago
       Docs: man:php-fpm8.3(8)
    Process: 59077 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.3/fpm/pool.d/www.conf 83 (code=exited, >
   Main PID: 59074 (php-fpm8.3)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 4656)
     Memory: 9.5M (peak: 10.4M)
        CPU: 97ms
     CGroup: /system.slice/php8.3-fpm.service
             ├─59074 "php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)"
             ├─59075 "php-fpm: pool www"
             └─59076 "php-fpm: pool www"

Dec 18 08:02:36 Ubuntu-24 systemd[1]: Starting php8.3-fpm.service - The PHP 8.3 FastCGI Process Manager...

Note: Ubuntu 24.04 includes PHP 8.3. Adjust the version numbers if your system uses a different PHP version.

Step 7 — Creating a Systemd Service for Your Application

Systemd can run your application as a managed service. This makes it possible to start the application automatically on boot and restart it if it fails. The following example creates a systemd service for a Node.js application, but the same concept can be adapted to other application types.

Create a systemd service file:

sudo nano /etc/systemd/system/your-app.service

Add the following configuration and adjust paths, usernames, and environment variables to fit your application:

[Unit]
Description=Your Application Server
After=network.target

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

[Install]
WantedBy=multi-user.target

Important configuration points:

  • Type=simple: Use this for applications that stay in the foreground.
  • User=www-data: Runs the application as a non-root user for better security.
  • WorkingDirectory: Defines the directory from which the application runs.
  • Restart=on-failure: Restarts the application automatically if it crashes.
  • RestartSec=10: Waits 10 seconds before attempting a restart.

Reload systemd and start the service:

sudo systemctl daemon-reload
sudo systemctl start your-app
sudo systemctl enable your-app

Check the service status:

sudo systemctl status your-app

Output

● your-app.service
     Loaded: loaded (/etc/systemd/system/your-app.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-12-18 08:07:30 UTC; 4ms ago
   Main PID: 59408 ((node))
      Tasks: 1 (limit: 4656)
     Memory: 512.0K (peak: 512.0K)
        CPU: 936us
     CGroup: /system.slice/your-app.service
             └─59408 "(node)"

Dec 18 08:07:30 Ubuntu-24 systemd[1]: your-app.service: Scheduled restart job, restart counter is at 4.
Dec 18 08:07:30 Ubuntu-24 systemd[1]: Started your-app.service.

Python Application Example

For a Python application using Gunicorn, the systemd service could look like this:

[Unit]
Description=Your Python Application
After=network.target

[Service]
Type=notify
User=www-data
WorkingDirectory=/var/www/your-app
Environment="PATH=/var/www/your-app/venv/bin"
ExecStart=/var/www/your-app/venv/bin/gunicorn --bind 127.0.0.1:8000 app:app
Restart=on-failure

[Install]
WantedBy=multi-user.target

PHP Application Example

For PHP applications, PHP-FPM is usually used together with Nginx. Configure Nginx to forward PHP requests to PHP-FPM:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
}

Step 8 — Deploying Your Application

Create a directory for the application and apply suitable ownership:

sudo mkdir -p /var/www/your-app
sudo chown -R www-data:www-data /var/www/your-app

Copy or deploy your application files into this directory. You can use Git, SCP, or another deployment method:

cd /var/www/your-app
sudo -u www-data git clone https://github.com/your-username/your-repo.git .

Install dependencies and build the application as needed. For Node.js:

sudo -u www-data npm install --production

For Python:

sudo -u www-data python3 -m venv venv
sudo -u www-data ./venv/bin/pip install -r requirements.txt

After the deployment is complete, restart the application service:

sudo systemctl restart your-app

Step 9 — Production Hardening Best Practices

Apply the following security measures to make the application server more suitable for production use.

Disable Root Login via SSH

Edit the SSH configuration:

sudo nano /etc/ssh/sshd_config

Set the following values:

PermitRootLogin no
PasswordAuthentication no

Restart SSH:

sudo systemctl restart sshd

Configure Automatic Security Updates

Enable automatic security updates:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades

Set Up Log Rotation

Configure log rotation so log files do not consume excessive disk space. Edit the logrotate configuration:

sudo nano /etc/logrotate.d/your-app

Add the following configuration:

/var/www/your-app/logs/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data www-data
    sharedscripts
}

Monitor Disk Space

Set up monitoring so you can be alerted when disk space becomes low. Install and configure monitoring tools:

sudo apt install htop iotop -y

Step 10 — Troubleshooting Common Issues

This section covers frequent issues that can appear while setting up an application server.

Application Not Starting

Check the service status and logs:

sudo systemctl status your-app
sudo journalctl -u your-app -n 50 --no-pager

Common causes include:

  • Wrong file paths in the systemd service file.
  • Missing environment variables.
  • Permission problems, especially if the service user cannot access the application files.

Nginx 502 Bad Gateway Error

This error usually means Nginx cannot reach the application. Check the following:

Your application is running:

sudo systemctl status your-app

The application is listening on the expected port:

sudo netstat -tlnp | grep 3000

The proxy_pass URL in your Nginx configuration must match the port used by your application.

SSL Certificate Issues

If SSL certificates do not renew correctly, review the following points:

Check the Certbot logs:

sudo tail -f /var/log/letsencrypt/letsencrypt.log

Confirm that your domain’s DNS records point to your server:

Make sure ports 80 and 443 are open in the firewall.

High Memory Usage

Monitor memory usage:

If your application uses too much memory, consider:

  • Optimizing the application code.
  • Increasing the server’s available RAM.
  • Adding application-level caching.

Frequently Asked Questions

What is an application server in Ubuntu?

An application server is a server environment that runs and manages web applications. On Ubuntu 24.04, this usually means configuring a runtime environment such as Node.js, Python, or PHP, setting up a reverse proxy such as Nginx, and using systemd to manage application processes. The application server receives requests, runs the application code, and sends responses back to clients.

How do I configure systemd for my app?

To configure systemd for your application, create a service file. The following example shows the process step by step.

Assume your application is a Node.js app located at /home/ubuntu/my-app, and you want to run it with npm start using the ubuntu user.

Create the systemd service file:

sudo nano /etc/systemd/system/my-app.service

Add the following content to the file:

[Unit]
Description=My Node.js App
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/my-app
ExecStart=/usr/bin/npm start
Restart=on-failure
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

Reload systemd so it detects the new service:

sudo systemctl daemon-reload

Enable the service so it starts automatically on boot:

sudo systemctl enable my-app

Start the application:

sudo systemctl start my-app

Your application now runs in the background, restarts after failures, and starts automatically after a reboot. Check its status with:

sudo systemctl status my-app

This method works for most applications. Adjust ExecStart, User, and WorkingDirectory according to your application stack.

Should I use Nginx or Apache for my reverse proxy?

Both Nginx and Apache can be used effectively as reverse proxies. Nginx is often chosen for modern application servers because it usually has a lower memory footprint, performs well with many simultaneous connections, and has a straightforward configuration style for reverse proxy use cases.

Nginx is also strong at serving static files and forwarding traffic to application servers, which makes it well suited for production deployments. Apache remains a reliable option as well, especially if you need certain modules or are already familiar with its configuration syntax.

How do I secure my application server on Ubuntu 24.04?

You can secure your application server by enabling the UFW firewall and only allowing required ports, installing SSL certificates with Let’s Encrypt, running applications as non-root users, disabling root SSH login, enabling automatic security updates, keeping packages up to date, and using correct file permissions. In addition, use strong passwords or SSH keys, configure fail2ban to reduce brute-force attempts, and regularly review application and system logs for suspicious activity.

Can I host multiple apps on a single Ubuntu server?

Yes, multiple applications can run on a single Ubuntu 24.04 server. Create separate systemd services for each application and have each one listen on a different port, such as 3000, 3001, or 8000. Then configure separate Nginx server blocks, also known as virtual hosts, for each domain or subdomain. Each server block forwards requests to the matching application port. This allows you to use server resources efficiently while keeping applications separated from one another.

How do I check if my app is running correctly?

Check whether your application is running by reviewing the systemd service status with sudo systemctl status your-app. View the application logs with sudo journalctl -u your-app -f to monitor live log output. Test the application through its domain or IP address. Confirm that Nginx forwards requests correctly by checking the Nginx access and error logs at /var/log/nginx/access.log and /var/log/nginx/error.log. Monitor resources with htop or free -h to make sure the application is not using too much CPU or memory.

Conclusion

You have now set up and configured a production-ready application server on Ubuntu 24.04. The server uses Nginx as a reverse proxy, SSL/TLS encryption, systemd-based service management, and several security hardening measures. This setup can be used to deploy Node.js, Python, PHP, and other web applications in a secure and scalable environment.

The configuration follows production best practices, including automatic service restarts, SSL certificate renewal, firewall protection, and suitable user permissions. Your application server is now prepared for real-world workloads and can be expanded as your requirements grow.

Source: digitalocean.com

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in:

Moderne Hosting Services mit Cloud Server, Managed Server und skalierbarem Cloud Hosting für professionelle IT-Infrastrukturen

n8n Workflow Automation: Open-Source Guide

AI/ML, Tutorial
Vijona2 hours ago n8n Workflow Automation: Open-Source Automation for Apps, APIs, and Services Automation has become an essential part of modern software development and IT operations. Whether teams need to…
Moderne Hosting Services mit Cloud Server, Managed Server und skalierbarem Cloud Hosting für professionelle IT-Infrastrukturen

Web Grounding for LLMs with Python

AI/ML, Tutorial
Vijona3 hours ago How to Add Web Grounding to Large Language Model Responses with Python When you send questions about recent or upcoming events to a large language model, the…
Moderne Hosting Services mit Cloud Server, Managed Server und skalierbarem Cloud Hosting für professionelle IT-Infrastrukturen

QwenLong-L1.5: Long-Context AI Reasoning

AI/ML, Tutorial
Vijona3 hours ago QwenLong-L1.5: Long-Context Reasoning with Memory-Augmented AI Large Language Models (LLMs) are advancing quickly in reasoning capabilities, but long-context reasoning continues to be one of the most difficult…