Your First Cumulus Virtual Personal Server

Your Cumulus server can serve content to the Internet when you set up web services, but server access requires VPN connection. **WARNING: This server must only be used for course activities. Unauthorized use for private projects will result in immediate loss of access and potential disciplinary action.**
The SSH key you have received should be considered a secret. Never share it with third parties or display it publicly.

What is Cumulus?

Cumulus is Linnaeus University's cloud computing platform that provides students with virtual personal servers (VPS) for course-related projects and exercises. Each student receives:

  • A personal Ubuntu Linux server running in the cloud
  • Root-level access to install software and configure services
  • Public internet connectivity with a unique DNS name (e.g., cuXXXX.camp.lnu.se)
  • SSH access through the university's VPN network

What you can do with your Cumulus server:

  • Deploy web applications and APIs
  • Learn Linux system administration
  • Practice server configuration and security
  • Host course projects accessible from anywhere on the internet
  • Experiment with different technologies without affecting your personal computer

Important limitations:

  • Access requires connection to the university VPN
  • The server is for course-related activities only - not personal projects
  • Your server and data may be reset between courses
  • Resource usage is monitored and limited

Think of Cumulus as your personal sandbox server where you can safely learn and experiment with real-world server technologies in a controlled environment.

Step 1: Verify SSH Availability

Before you can connect to your Cumulus server, make sure that the ssh command is available in your terminal.

Windows Instructions

If you're using Windows 10 or later, the built-in PowerShell or Command Prompt usually includes SSH, but we recommend using Git Bash as your terminal (this guide assumes you're using a Bash terminal).

Check if SSH is installed:

Open Git Bash (or your preferred terminal) and run:

If you see a version number (e.g., OpenSSH_9.9p1, OpenSSL 3.2.3 3 Sep 2024), you're good to go and can proceed to Step 2.

If SSH is not available, you have several options:

  • Install OpenSSH Client via Windows Features (Settings → Apps → Optional Features)
  • Use Windows Terminal with PowerShell or Command Prompt
  • Install Windows Subsystem for Linux (WSL) - provides a complete Linux environment with native SSH support
  • Alternatively, install PuTTY, though this guide assumes OpenSSH command-line tools
macOS Instructions

SSH is pre-installed on macOS. You can verify it's available by opening Terminal and running:

If you see a version number, you're ready to proceed to Step 2.

Linux Instructions

SSH is typically pre-installed on most Linux distributions. You can verify it's available by opening your terminal and running:

If you see a version number, you're ready to proceed to Step 2.

If SSH is not installed, you can install it using your distribution's package manager:

Ubuntu/Debian:

Fedora:

Arch Linux:

Step 2: Download Your Identity File from GitLab

To access your personal server in the Cumulus cloud via SSH, you need an identity file (private key). This file is provided through a GitLab project.

Locate and download the identity file:

  1. Go to the Secrets project in GitLab
  2. In this project, you will find:
    • Your private key file (named something like id_cumulus_xxx)
    • The IP address of your server
    • The DNS name assigned to your server
  3. Download the private key file (id_cumulus_xxx) to a known location on your computer

Keep this file safe - you'll need it in the next step.

Step 3: Create the .ssh Directory

The .ssh directory is a standard location for storing SSH keys and configuration files. If it doesn't already exist, you need to create it.

Windows (Git Bash) Instructions

Open Git Bash and run:

This creates the .ssh directory in your home folder if it doesn't already exist. The -p flag ensures no error occurs if the directory is already there.

macOS Instructions

Open Terminal and run:

This creates the .ssh directory in your home folder if it doesn't already exist. The -p flag ensures no error occurs if the directory is already there.

Linux Instructions

Open your terminal and run:

This creates the .ssh directory in your home folder if it doesn't already exist. The -p flag ensures no error occurs if the directory is already there.

Step 4: Move the Identity File to .ssh Directory

Now you need to move the downloaded identity file to the .ssh directory.

Windows (Git Bash) Instructions

In Git Bash, navigate to where you downloaded the file (e.g., Downloads folder) and move it to .ssh:

Replace id_cumulus_xxx with the actual filename of your private key.

If your file is in a different location, adjust the path accordingly:

macOS Instructions

In Terminal, move the file from your Downloads folder to .ssh:

Replace id_cumulus_xxx with the actual filename of your private key.

If your file is in a different location, adjust the path accordingly.

Linux Instructions

In your terminal, move the file from your Downloads folder to .ssh:

Replace id_cumulus_xxx with the actual filename of your private key.

If your file is in a different location, adjust the path accordingly.

Step 5: Set Correct Permissions on the Identity File

Setting the correct permissions ensures that your private key is only readable by you. SSH will refuse to use the key if it's accessible by others, as this would pose a security risk.

Windows (Git Bash) Instructions

In Git Bash, run:

Replace id_cumulus_xxx with the actual filename of your private key.

Note: When using Git Bash, chmod 600 works as expected and ensures your key is accepted by SSH, even though Windows handles file permissions differently under the hood.

macOS Instructions

In Terminal, run:

Replace id_cumulus_xxx with the actual filename of your private key.

This command sets the file permissions so that only you (the owner) can read and write the file, while removing all permissions for group and others.

Linux Instructions

In your terminal, run:

Replace id_cumulus_xxx with the actual filename of your private key.

This command sets the file permissions so that only you (the owner) can read and write the file, while removing all permissions for group and others.

## Step 3: Connect to Your Cumulus Server via SSH

Once your identity file is in place and has the correct permissions, you can connect to your virtual personal server in the Cumulus cloud using SSH.

  1. Use the DNS name (or IP address)

    In the GitLab Secrets project, you will find either:

    • The DNS name of your virtual personal server (recommended), e.g. cuXXXX.camp.lnu.se
    • Or the IP address, e.g. 172.27.XXX.XXX
  2. Connect using SSH

    Open your terminal (Git Bash on Windows) and run:

    Replace:

    • id_cumulus_xxx with the actual filename of your private key
    • cuXXXX.camp.lnu.se with your server’s DNS name (or IP address)

    📌 Example

    If this is your first time connecting, you may be asked to confirm the host's fingerprint. Type yes to continue.

    🔧 Troubleshooting: Remove a Previously Registered Key

    If you’ve connected to your server before and the host key has changed (for example, due to a reinstallation), SSH may refuse to connect and show a warning about a mismatched key.

    To fix this, remove the old key from your known hosts file:

    Replace cuXXXX.camp.lnu.se with your servers’s actual DNS name or IP address. This command deletes the outdated entry from ~/.ssh/known_hosts, allowing you to reconnect without errors.

  3. What Happens When You Successfully Connect

    If the SSH connection is successful, you’ll see a welcome message from the Ubuntu operating system, along with system information such as memory usage, IP address, and login history.

    You will land in your home directory, typically /home/ubuntu, and the prompt will look something like:

    From here, you can start working on your virtual personal server — installing packages, running applications, or setting up web services

Step 4: Update Package Lists

Before installing any software on your Cumulus virtual personal server, it's good practice to update the package lists. This ensures that you get the latest available versions of packages from the Ubuntu repositories.

You are logged in as a regular user (ubuntu), so administrative commands like apt update require sudo.

Run the following command:

This command fetches the most recent information about available packages and updates, which is necessary before installing tools like Node.js, npm, and nginx.

You only need to run this once before installing multiple packages. There's no need to repeat it before each installation unless a significant amount of time has passed or you've added new repositories.

Step 5: Install Node.js and npm

To run JavaScript applications on your Cumulus server, you need to install Node.js and its package manager npm.

  1. Add the NodeSource Repository

    Start by adding the official NodeSource repository for Node.js version 22:

    This command downloads and runs a setup script that configures your system to use the NodeSource repository.

  2. Install Node.js

    Once the repository is added, install Node.js and npm:

    The -y flag automatically confirms the installation.

  3. Verify the Installation

    After installation, check that both Node.js and npm are available:

    You should see version numbers printed in the terminal, confirming that the installation was successful.

Step 6: Install and Start nginx

To serve web content from your Cumulus server, you need to install a web server. We use nginx, a lightweight and high-performance HTTP server.

  1. Install nginx

    Run the following command to install nginx:

    This installs the nginx package and its dependencies.

  2. Start the nginx Service

    Once installed, start the nginx service:

    This launches the web server.

  3. Enable nginx to Start on Boot

    To make sure nginx starts automatically when the server boots:

  4. Check nginx Status

    You can verify that nginx is running with:

    You should see output indicating that the service is active (running).

Step 7: Verify nginx in Your Browser

Once nginx is installed and running, you can verify that it works by accessing your server in a web browser using HTTP.

  1. Use the DNS Name

    Open a browser and enter your server’s DNS name in the address bar, using http:

    Replace cuXXXX.camp.lnu.se with your actual DNS name.

  2. Expected Result

    You should see the default Welcome to nginx! page. This confirms that:

    • nginx is installed correctly
    • the service is running
    • your server is reachable over the network

    If you don’t see the page, double-check that:

    • VPN is connected
    • nginx is running (systemctl status nginx)
    • You used the correct DNS name
  3. What Happens If You Use HTTPS?

    At this stage, your nginx server is only configured to serve content over HTTP. If you try to access your server using HTTPS, like:

    …you will likely see a browser warning or error such as:

    • "Your connection is not private"
    • "This site can’t provide a secure connection"
    • "ERR_SSL_PROTOCOL_ERROR"

    This is expected, because no SSL/TLS certificate has been installed yet.

    You will configure HTTPS and install certificates in the next step.

Step 8: Request and Install a TLS Certificate from LNU FTK Campus CA

To enable HTTPS on your virtual server in the Cumulus network, you can request a certificate using Certbot and the LNU FTK Campus CA.

  1. Prerequisites

    • Your server has a floating IP address in the Cumulus campus network.
    • You have sudo privileges.
    • Nginx is installed and running.
  2. Install the LNU FTK Campus Root CA Certificate

    Download and install the root certificate so that Certbot can validate the CA:

    Verify that the certificate is installed:

    You should see that the system has created a hash-based symlink pointing to a .pem file, and another symlink named LNU_FTK_Campus_Root_CA_2025.pem pointing to the original .crt file. This confirms that the certificate has been added to the system trust store and is available for use by Certbot and other tools.

  3. Install Certbot

    Install Certbot using Snap and make it available via /usr/bin/certbot:

    This ensures that Certbot is available system-wide and can be used with plugins like Nginx.

  4. Request and Install the Certificate

    Use Certbot to request a certificate from the LNU FTK Campus CA using the Nginx plugin and the custom ACME endpoint. The command below automatically derives the correct FQDN from the server's floating IP:

    This command:

    • Uses the LNU FTK Campus ACME endpoint.
    • Automatically converts your floating IP to the correct FQDN.
    • Requests and installs the certificate via the Nginx plugin.
  5. Test and Restart nginx Configuration

    After Certbot has modified your nginx configuration, always test that the configuration is valid before proceeding:

    You should see:

    If the test is successful, restart nginx to apply the changes:

Step 9: Configuring Automatic Certificate Renewal

Certificates issued by the LNU FTK Campus Certificate Authority are short-lived (6–7 days). Therefore, automatic renewal is mandatory to avoid service interruptions.

When Certbot is installed via snap, automatic renewal is handled by a systemd timer. However, because an internal ACME CA is used, additional configuration is required.

How Automatic Renewal Works

  • Certbot is executed automatically by the systemd timer snap.certbot.renew.timer
  • The timer runs several times per day
  • Renewal occurs automatically when the certificate is close to expiration
  • No cron jobs or manual scripts are required

1. Configure Certbot for the Campus CA (One-time setup)

Certbot must be provided with:

  • the campus Root CA bundle
  • the internal ACME server URL

This is done using a systemd drop-in configuration.

1. Create a drop-in directory

2. Create the drop-in configuration file

Explanation:

  • REQUESTS_CA_BUNDLE Ensures Certbot trusts the LNU FTK Campus Root CA
  • CERTBOT_SERVER Points Certbot to the campus ACME endpoint instead of Let’s Encrypt

2. Reload systemd and test renewal

This runs the same renewal logic that the timer uses.

3. Verify automatic renewal is scheduled

Check that the systemd timer is active:

You should see output similar to:

This confirms that automatic renewal is enabled.

4. Verify renewal results

To check certificate status at any time:

To verify that a renewal actually occurred:

If the certificate is not close to expiration, Certbot will only perform a check. This is expected behavior.

Automatic renewal is now fully configured.

No further action is required. The certificate will be renewed automatically before it expires.

Step 10: Trust the CA in Your Browser

Before you can verify HTTPS access without security warnings, you need to install the Root CA certificate in your browser's trust store.

1. Download the Root CA

  1. Download LNU_FTK_Campus_Root_CA_2025.crt
  2. Remember the download location (e.g., Downloads folder)

2. Import the Certificate

Choose your operating system and browser:

💻 macOS

Google Chrome / Safari (uses macOS Keychain)

  1. Locate the downloaded LNU_FTK_Campus_Root_CA_2025.crt file
  2. Double-click it → opens in Keychain Access
  3. Select System keychain when prompted
  4. Find LNU FTK Campus Root CA 2025 in the list
  5. Double-click it → expand Trust section
  6. Set When using this certificateAlways Trust
  7. Close the window (enter admin password if prompted)

Note: Both Chrome and Safari now trust this CA.

Mozilla Firefox (separate certificate store)

  1. Open Firefox
  2. Go to Settings (⚙️)
  3. Navigate to Privacy & SecurityCertificatesView Certificates
  4. Select the Authorities tab
  5. Click Import
  6. Select the downloaded Root CA file
  7. Check "Trust this CA to identify websites"
  8. Click OK

Note: Firefox uses its own certificate store, independent of macOS Keychain.

💻 Windows

Google Chrome

  1. Open Chrome
  2. Navigate to: chrome://certificate-manager/localcerts/usercerts
  3. Select the Local certificates tab
  4. Under Installed by you, click Import (Trusted Certificates)
  5. Browse to the downloaded Root CA file
  6. Click Open → Confirm the import

Mozilla Firefox

  1. Open Firefox
  2. Go to SettingsPrivacy & SecurityView Certificates
  3. Select the Authorities tab
  4. Click Import
  5. Choose the downloaded Root CA file
  6. Check "Trust this CA to identify websites"
  7. Click OK
💻 Linux

Google Chrome

  1. Open Chrome
  2. Navigate to: chrome://certificate-manager/localcerts/usercerts
  3. Select the Local certificates tab
  4. Under Installed by you, click Import (Trusted Certificates)
  5. Browse to the downloaded Root CA file
  6. Click Open → Confirm the import

Mozilla Firefox

  1. Open Firefox
  2. Go to SettingsPrivacy & SecurityView Certificates
  3. Select the Authorities tab
  4. Click Import
  5. Choose the downloaded Root CA file
  6. Check "Trust this CA to identify websites"
  7. Click OK

3. Restart Your Browser

Important: Completely close and restart your browser for the changes to take effect.

Your browser now trusts the LNU FTK Campus CA and you're ready to verify HTTPS access without security warnings.

Step 11: Verify HTTPS in Your Browser

After installing the TLS certificate, you should verify that HTTPS is working correctly on your nginx server.

  1. Test HTTPS Access

    Open a browser and enter your server's DNS name using HTTPS:

    Replace cuXXXX.camp.lnu.se with your actual DNS name.

  2. Expected Result

    You should see:

    • The same Welcome to nginx! page as before
    • A secure connection indicator (lock icon) in your browser's address bar
    • No security warnings or certificate errors

    This confirms that:

    • The TLS certificate is installed correctly
    • HTTPS is properly configured
    • Your connection is encrypted and secure
  3. Troubleshooting HTTPS Issues

    If you encounter problems:

    • Certificate errors: Verify the certificate installation with:

    • Nginx configuration: Check that nginx is using the certificate:

    • Browser cache: Try a hard refresh (Ctrl+F5) or test in an incognito/private window

  4. HTTP vs HTTPS Behavior

    Now that HTTPS is configured:

    • HTTP requests http://cuXXXX.camp.lnu.se should automatically redirect to HTTPS
    • HTTPS requests https://cuXXXX.camp.lnu.se should work directly with a secure connection

    This automatic redirection is configured by Certbot when it updates your nginx configuration.

Step 12: Secure nginx Configuration

Now that HTTPS is working, it's time to enhance the security of your nginx server by modifying the configuration and removing unnecessary information disclosure.

  1. Edit the nginx Configuration

    Open the main nginx configuration file:

  2. Hide Server Version Information

    Find the http block in the configuration file. Look for the commented line:

    Uncomment this line by removing the # at the beginning:

    This prevents potential attackers from knowing which specific version of nginx you're running.

  3. Save and Exit

    In nano:

    • Press Ctrl + O to save
    • Press Enter to confirm
    • Press Ctrl + X to exit
  4. Test the Configuration

    Before restarting nginx, always test that your configuration is valid:

    You should see:

  5. Restart nginx

    Apply the changes by restarting the nginx service:

  6. Verify the Security Enhancement

    Test that the version information is now hidden by checking the HTTP headers:

    Replace cuXXXX.camp.lnu.se with your actual DNS name.

    Before the change, you would see:

    After the change, you should only see:

This simple security enhancement reduces information leakage that could be useful to potential attackers.

Step 13: Create Your Own Static Website

Instead of using the default nginx page, let's create your own custom website with a dedicated directory structure.

  1. Create a New Directory for Your Website

    Create a dedicated directory for your hello-world website:

  2. Set Proper Ownership

    Change ownership to the ubuntu user so you can edit files without sudo:

  3. Create Your Custom index.html

    Create your hello-world homepage:

    Add the following content:

  4. Create a New nginx Site Configuration

    Create a dedicated configuration file for your domain:

    Add the following configuration:

    Important: Replace cuXXXX.camp.lnu.se with your actual DNS name in both the server_name and SSL certificate paths.

    Configuration Breakdown:

    • First server block (HTTP): Redirects all HTTP traffic to HTTPS for security
    • Second server block (HTTPS): Handles encrypted connections on port 443
    • http2: Enables HTTP/2 protocol for faster page loading and better performance
    • SSL certificates: Points to the certificates installed by Certbot
    • root /var/www/hello-world: Sets the directory for static files
    • location /: Serves static files, returns 404 if not found
    • include locations/*.conf: Loads configurations for dynamic applications

    HTTP/2 Benefits:

    HTTP/2 is automatically enabled in your nginx configuration and provides:

    • Multiplexing - Multiple requests over a single connection
    • Header compression - Reduced overhead for HTTP headers
    • Server push - Proactive resource delivery (if configured)
    • Binary protocol - More efficient than HTTP/1.1 text-based protocol
  5. Create Directory for Application Configurations

    Create a dedicated directory structure for modular nginx configurations. This allows you to manage each application separately:

    This directory will store individual .conf files for each application you deploy, making it easy to add, remove, or modify applications without touching the main site configuration.

  6. Disable the Default Site and Enable Your Hello-World Site

    Remove the default nginx site and enable your custom hello-world site:

  7. Test and Restart nginx Configuration

    Always test the configuration before applying changes:

    If the test is successful, restart nginx:

  8. Visit Your Custom Hello-World Website

    Open your browser and navigate to:

    Replace cuXXXX.camp.lnu.se with your actual DNS name.

    You should now see your custom hello-world website instead of the default nginx page!

  9. Verify HTTP/2 is Working

    You can confirm that HTTP/2 is properly configured using either of these methods:

    • Browser Developer Tools: Open Developer Tools (F12) → Network tab → Refresh the page → Check the "Protocol" column (should show "h2")

    • Command line: Test with curl from your terminal:

      Note: Your curl must support HTTP/2. Check with:

      • Look for "Features: ... HTTP2 ..."
      • If --http2 is not recognized, you can try to update curl (Linux: apt install curl, Windows: winget install curl or download from https://curl.se/windows/.

      Look for HTTP/2 200 in the response headers.

Step 14: Create and Deploy an Express Application

Now let's create a dynamic web application using Node.js with Express and deploy it alongside your static website.

📁 What you'll build:

🌐 URL structure:

  • https://cuXXXX.camp.lnu.se/ → Static website
  • https://cuXXXX.camp.lnu.se/hello-world-express/ → Express application

Option A: Clone from GitLab (Recommended)

If you have access to the course GitLab repository with the Express Hello World project:

  1. Set Up GitLab SSH Access on Your Cumulus Server (First Time Only)

    To clone repositories from GitLab directly on your Cumulus server, you need to configure SSH access. This creates a separate key pair specifically for your Cumulus server to access GitLab repositories.

    ⚠️ Important: These commands are run on your Cumulus server (via SSH), not on your local computer.

    Generate a new SSH key pair for GitLab on your Cumulus server:

    When prompted:

    • Press Enter to save in the default location (/home/ubuntu/.ssh/id_gitlab)
    • Enter a passphrase (optional but recommended)

    Display the public key from your Cumulus server:

    Add the public key to your GitLab account:

    Copy the entire output from the command above and add it to your GitLab account:

    • Go to GitLab → User Settings → SSH Keys
    • Paste the public key content
    • Give it a descriptive title (e.g., "Cumulus Server cuXXXX")
    • Click "Add key"

    Configure SSH on your Cumulus server to use the GitLab key:

    Add the following configuration:

    Test the connection from your Cumulus server:

    You should see: "Welcome to GitLab, @yourusername!"

    What you've created:

    • A separate SSH key pair on your Cumulus server for GitLab access
    • SSH configuration that uses this key automatically for GitLab
    • Secure connection between your Cumulus server and GitLab repositories
  2. Navigate to your home directory

  3. Clone the Express Hello World Project

    You'll use a two-step process: clone in home directory, then move to the web directory:

    💡 Why you don't clone directly to /var/www/:

    • sudo git clone → SSH uses root's keys (which don't exist)
    • ❌ Direct clone to /var/www/ → Permission denied (directory owned by root)
    • ✅ Clone to home → move → fix ownership = Clean and simple solution
  4. Install Dependencies

  5. Test the Application

    You should see: 🚀 Server is running on http://localhost:3000

    Test locally: curl http://localhost:3000

    Stop the server with Ctrl + C before proceeding to nginx configuration.

Option B: Create from Scratch (Fallback)

If you don't have access to the GitLab repository, create the application manually:

  1. Create Project Directory

  2. Create package.json

    Add the following content:

  3. Create Source Directory and Server File

    Add the following Express application code:

  4. Install Dependencies

  5. Test the Application

Configure nginx as Reverse Proxy

Regardless of which option you used above, now configure nginx to serve your Express app using the modular configuration approach:

  1. Create Express App Location Configuration

    Instead of modifying the main nginx file, create a separate configuration for the Express app:

    Add the following configuration:

  2. Test and Restart nginx Configuration

    Test the configuration and restart nginx:

    No need to modify symlinks since we're using the include directive from Step 11.

  3. Start Your Express Application

  4. Test Your Setup

    Now you can access:

    • Static website: https://cuXXXX.camp.lnu.se/
    • Express app: https://cuXXXX.camp.lnu.se/hello-world-express/
    • Test error handling: https://cuXXXX.camp.lnu.se/hello-world-express/test/throw-error
    • Test crash (dangerous!): https://cuXXXX.camp.lnu.se/hello-world-express/test/crash

    Important: Replace cuXXXX.camp.lnu.se with your actual DNS name.

What You've Accomplished:

  • Deployed an Express application with ES6 modules
  • Configured nginx as a reverse proxy
  • Set up both static and dynamic content on the same domain
  • Added test routes with intentional errors and crashes

Critical Discovery:

Notice that when you close your terminal or visit /hello-world-express/test/crash, your Express application stops working completely! This demonstrates a fundamental problem with running Node.js applications directly - they don't survive crashes or disconnections.

This is why we need a process manager in the next step!

Step 15: Install and Configure PM2 Process Manager

As you discovered in the previous step, Node.js applications stop running when you close your terminal or when they crash. PM2 (Process Manager 2) solves this problem by keeping your applications running in the background, automatically restarting them on crashes, and providing process monitoring.

Instead of managing each application separately, we'll use a YAML configuration file to define all our applications in one place.

  1. Install PM2 using npm

    Install PM2 globally so it's available system-wide:

    This installs PM2 as a global package, making the pm2 command available from anywhere on your system.

  2. Create the Ecosystem Configuration File

    Navigate to your web directory and create a PM2 ecosystem file:

  3. Configure Your Applications

    Edit the ecosystem configuration file:

    Add the following YAML configuration:

    Configuration notes:

    • script: "src/server.js" - Direct path to the Node.js application file
    • cwd - Working directory for the application
    • exec_mode: "fork" - Runs a single Node.js process (vs "cluster" for multiple processes)
    • instances: 1 - Number of processes to run
    • env - Environment variables for production mode
  4. Start All Applications with PM2 Using the Ecosystem File

    Use PM2 to start all applications defined in your ecosystem file:

    PM2 will read the configuration and start your Express application.

  5. Verify Applications are Running

    Check the status of your PM2-managed applications:

    You should see output similar to:

  6. Test Your Express Application

    Visit your Express application in a browser:

    The application should be working normally.

  7. Test Crash Recovery

    Try the crash test route to see PM2's auto-restart feature:

    What happens:

    • The application crashes (as intended)
    • PM2 automatically detects the crash
    • PM2 immediately restarts the application
    • Your application is available again within seconds

    Check PM2 status after the crash:

    You should see the restart count has increased, showing that PM2 successfully restarted your application.

  8. Configure PM2 to Start on Server Boot

    ⚠️ Critical for Production: Without this configuration, your applications will NOT restart automatically when the server reboots, leading to downtime.

    For a production server, it's essential that your applications start automatically when the server reboots. PM2 provides a simple way to configure this.

    Generate the startup script:

    This command will analyze your system and output a custom command that you need to execute. The output will look similar to this:

    📋 Important Steps:

    1. Copy the command that PM2 outputs in YOUR terminal (not the example above)
    2. Paste and execute that specific command with sudo
    3. Each server generates a unique command - yours will be different from the example

    Example of what to do:

    ⚠️ Warning: The exact command will be different on your system. Always use the command that PM2 generates for YOUR specific server configuration.

    Save your current PM2 configuration:

    This saves the current list of running applications so they're restored on boot.

    Test the boot persistence:

    You can test this by rebooting your server:

    After the server comes back online, reconnect via SSH and check:

    Your applications should be running automatically without any manual intervention.

Monitor Your Applications

View real-time logs from all applications:

View logs for a specific application:

Monitor processes in real-time:

(Press q to exit the monitor)

✅ What You've Accomplished

  • Installed PM2 process manager
  • Created a YAML ecosystem configuration file for managing multiple applications
  • Configured centralized logging for your applications
  • Set up automatic crash recovery and restart functionality
  • Enabled applications to start automatically on server boot
  • Learned essential PM2 monitoring and management commands

🗝️ Key Benefits of Using PM2

  • Process persistence - Applications survive terminal disconnections
  • Automatic restart - Crashed applications are immediately restarted
  • Centralized logging - All application logs in one place
  • Easy scaling - Can run multiple instances of applications
  • Boot persistence - Applications start automatically when server boots
  • Process monitoring - Real-time monitoring of CPU, memory, and performance

Your Express application is now running as a production-ready service that can handle crashes, server reboots, and provides comprehensive monitoring capabilities!

What's Next?

Now that you have a fully functional web server with HTTPS, static content, dynamic Express applications, and process management, you can:

  • Deploy more applications - Add new location blocks for additional services
  • Learn database integration - Connect your Express apps to MongoDB or PostgreSQL
  • Implement monitoring - Set up log analysis and performance monitoring
  • Scale your applications - Use PM2's cluster mode for better performance
  • Add CI/CD - Automate deployments from your GitLab repositories

Your Cumulus virtual personal server is now a production-ready web server platform!

Summary: Your Server Stack

You've successfully built a complete web server stack:

Technologies mastered:

  • ✅ Linux system administration
  • ✅ SSH key management
  • ✅ nginx web server configuration
  • ✅ SSL/TLS certificate management
  • ✅ Node.js and Express development
  • ✅ Process management with PM2
  • ✅ Modular nginx configuration

Common Issues and Solutions

SSH Connection Problems

  • "Permission denied": Check key permissions with ls -l ~/.ssh/id_cumulus_*
  • "Host key verification failed": Run ssh-keygen -R cuXXXX.camp.lnu.se
  • "Connection refused": Verify VPN connection and DNS name

nginx Issues

  • 502 Bad Gateway: Check if your Node.js app is running with pm2 status
  • 403 Forbidden: Check file permissions in /var/www/
  • 404 Not Found: Verify file paths and nginx configuration syntax

PM2 Problems

  • App not starting: Check logs with pm2 logs
  • Port conflicts: Verify ports in ecosystem.config.yml
  • Apps not restarting after reboot: Run pm2 startup and pm2 save

SSL Certificate Issues

  • Certificate expired: Run sudo certbot renew
  • Certificate errors: Verify with sudo certbot certificates
  • Browser warnings: Clear cache or test in incognito mode