Category: Cloud Education

  • How to Fix the “Safari Can’t Establish a Secure Connection to the Server” Error

    How to Fix the “Safari Can’t Establish a Secure Connection to the Server” Error

    Have you ever tried to open your bank, favorite store, or work portal – only to be stopped by this message?

    “Safari Can’t Establish a Secure Connection to the Server.”

    It’s frustrating, vague, and can block you completely – on a Mac, iPhone, or iPad.

    But what does this error mean?

    This guide explains what’s happening behind the scenes when Safari shows this message and gives you a step-by-step checklist to fix it. Whether the problem lies with your device or the website’s server, you’ll leave with a clear path to restore access.

    Let’s start by understanding why this error happens in the first place.

    What Causes the “Safari Can’t Establish a Secure Connection to the Server” Error?

    When you visit a website on your browser, your computer encrypts the data so no one else on your network can read it. This encryption is done using a TLS/SSL handshake. If any part of this process fails, Safari will terminate the connection and display this error to protect you from potentially insecure communication.

    The causes can range from a simple misconfiguration on your device to a serious problem with the website’s server.

    In this article, we will proceed with troubleshooting in a logical order, from the most common and simplest fixes to more advanced, system-level solutions.

    Let’s get started!

    Common Fixes to Solve the Secure Connection Error

    If you encounter the “Can’t Establish a Secure Connection to the Server” error, you should begin your troubleshooting process with these steps. The following solutions are entirely safe and non-destructive to your data and will successfully resolve the “secure connection” error in most situations.

    1. Verify the Website Address and Reload the Page

    The most straightforward fix is often to check the website’s domain name. Carefully check the URL in Safari’s address bar for any typos. A single misspelled character in a website’s domain name can direct your browser to an entirely different server or a server that does not possess a valid security certificate for the address you intended to visit, immediately triggering this security error.

    If the web address is correct, the next step is to perform a “force reload” of the page. You can accomplish this by pressing the Cmd + R key combination on your keyboard or by clicking the reload icon in the address bar. This action instructs Safari to discard any temporary data stored for the page and request a completely fresh copy from the server. This can resolve transient network hiccups or minor glitches that may have interrupted the initial connection.

    safari can't establish a secure connection

    2. Check and Correct Your System’s Date & Time

    An incorrect date or time setting on your computer or mobile device is the most frequent culprit behind this connection error. Secure browsing depends on accurate system time.

    Secure websites use SSL/TLS certificates that are only valid for a specific period, which includes a defined start date and an expiration date. If your device’s clock is set to a date and time outside this valid range, Safari will correctly determine that the website’s certificate is invalid. As a security precaution to protect your information, Safari will refuse to establish the connection.

    To resolve this, you should configure your device to automatically set its date and time using Apple’s reliable network time servers.

    How to Fix on macOS (Ventura & later):

    1. Navigate to the Apple menu in the top-left corner of your screen and select System Settings.
    1. Click General in the sidebar, then choose the Date & Time option on the right.
    1. Ensure the toggle switch next to “Set time and date automatically” is in the ‘on’ position.
    1. Make sure the server is set to time.apple.com or another reliable source.

    How to Fix on iOS / iPadOS:

    1. Open the Settings application from your Home Screen.
    2. Tap on General, and then select Date & Time.
    3. Verify that the toggle for “Set Automatically” is enabled, which allows your device to sync its time with the cellular or Wi-Fi network.

    3. Test the Issue Using a Private Window

    To determine whether the connection error is caused by your browser’s stored data or extensions, you should try opening the website in a private Window. A Private Window creates a temporary, isolated browsing session that acts as a “clean slate.” Safari doesn’t use your browsing history, cookies, or cached data in a Private Window.

    Additionally, it disables all third-party browser extensions you may have installed, such as ad blockers, security tools, or shopping assistants. Creating this clean environment allows you to test whether one of these components interferes with the secure connection process.

    To perform this test, follow these instructions:

    1. With Safari open, go to the File menu at the top of your screen and select New Private Window. Alternatively, you can use the keyboard shortcut Shift + Cmd + N.
    2. A new, dark-themed Safari window will appear, indicating you’re in Private Browsing mode.
    3. In the address bar of this new private window, type or paste the website URL that was previously failing and press Enter.

    Now, carefully observe the result, as it will tell you exactly where to look for the problem:

    • If the website loads successfully in the Private Window: This confirms the problem is within your Safari profile. It confirms that the issue lies within your regular Safari profile and is caused by corrupted website data (cache or cookies) or an interfering browser extension. You should now proceed directly to Step 4 to clean up this data.
    • If the error message appears again in the Private Window: This tells you that the problem is unrelated to your browser’s data or extensions. The cause is deeper, likely related to your device’s network settings, system-wide configurations, or an issue on the website’s server. In this case, you can skip the next step and move on to Network-Level Troubleshooting.

    4. Clear Corrupted Website Data (Cache & Cookies)

    If your test in Step 3 was successful, this step usually resolves it. Over time, the data that Safari stores to make websites load faster (the cache) and remember your login sessions (cookies) can become corrupted or “stale.” This outdated information can conflict with a website’s server when it tries to establish a new, secure connection.

    We will first try a targeted approach, which is highly recommended as it will not log you out of other websites.

    How to Clear Data for a Single Site (Recommended Method):

    This removes data just for the affected site, leaving your data for all other sites untouched.

    1. Open Safari and click on Safari in the menu bar at the top of the screen, then select Settings (or Preferences on older macOS versions).
    1. In the Settings window, navigate to the Privacy tab. This section controls how Safari handles website tracking and stored data.
    1. Click the button labeled Manage Website Data…. This will open a new window showing all the websites that have stored data on your computer.
    2. In the search bar in the corner of this window, type the name of the website causing the error (e.g., “example.com”).
    1. Select the website from the list and click the Remove button.
    2. Click Done. To ensure the changes take full effect, quit Safari (Cmd + Q) and reopen it. Now, try accessing the website again.

    How to Clear All Browser History and Data (Use if the Targeted Method Fails):

    If removing the data for the specific site did not work, you can take a more drastic step. This action will remove your browsing history and sign you out of all websites you are currently logged into.

    1. In the Safari menu bar, click History, then select Clear History… from the bottom.
    2. A small dialog box will appear. Click the dropdown menu next to “Clear” and select all history.
    1. Click the Clear History button to confirm. This action comprehensively removes all history, cookies, and cached data from Safari.
    2. After the process is complete, try visiting the website one more time.

    Network-Level Troubleshooting

    If the fixes mentioned above didn’t work, the problem may lie in your network configuration or filtering software. Follow these steps to continue the troubleshooting process

    5. Disable VPN, Antivirus, or Firewall Software

    If you are using any third-party security and network software that intercepts your network traffic to scan it. Then this “man-in-the-middle” position can sometimes interfere with the delicate TLS handshake.

    1. Temporarily disable active VPN clients, antivirus programs (like Norton, Avast, McAfee), or third-party firewalls.
    2. Quit and restart Safari completely.
    3. Try visiting the site again.

    These network security applications install their own “root certificates” to decrypt and inspect your traffic. If their software is outdated or misconfigured, it can break the connection to legitimate sites. If disabling one of them fixes the issue, you need to update that software or adjust its “SSL/TLS Inspection” settings.

    6. Change Your DNS Servers

    A Domain Name System (DNS) server is like the Internet’s phonebook. A slow, unreliable, or misconfigured DNS server can cause connection failures. These DNS issues can sometimes lead to routing problems or timeouts before the secure connection is established.

    Most ISPs use their own DNS server to analyze and predict network traffic patterns, but these servers are sometimes poorly maintained, making them unreliable. If you use a custom DNS server, consider switching to a public DNS server such as Google DNS, Cloudflare, or Quad9, which are fast, reliable, and highly secure.

    How to Change DNS on macOS:

    1. Go to Apple menu > System Settings > Wi-Fi.
    2. Click the Details… button next to your active network connection.
    3. Select the DNS tab from the sidebar.
    1. Click the + button and add the following servers:
      • 8.8.8.8 (Google)
      • 1.1.1.1 (Cloudflare)
      • 9.9.9.9 (Quad9)
    2. Click OK.

    How to Change DNS on iOS / iPadOS:

    1. Go to Settings > Wi-Fi.
    2. Tap the i (info) icon next to your network.
    1. Scroll down and tap Configure DNS.
    1. Select Manual, then Add Server to enter 8.8.8.8 and 1.1.1.1. Remove any old entries.
    2. Tap Save.

    Advanced System-Level Solutions

    Please proceed with the following steps, fully understanding that they involve changes to your core operating system.

    7. Update macOS and Safari to the Latest Version

    One of the most useful steps to resolve secure connection errors is to ensure your entire operating system is up-to-date. A modern, secure website server may refuse to communicate with a browser that uses older, deprecated security protocols (like early versions of TLS), because older protocols are now blocked for security reasons. Updating your OS is the only way to ensure Safari can “speak” this language’s latest and most secure version.

    Newer operating systems also include the latest version of the Apple Trust Store. It is a verified list of all the global organizations (Certificate Authorities) trusted to issue legitimate SSL/TLS security certificates. If a website is using a certificate from a newer authority that isn’t on your outdated list, Safari will be unable to verify its authenticity and will block the connection.

    Therefore, when you perform a software update, you not only get security patches and new features but also refresh Safari’s core components and directory of trusted entities.

    To check for and install updates on your Mac:

    1. Navigate to the Apple menu in the top-left corner of your screen and select System Settings.
    2. Click on General in the sidebar, and then choose Software Update.
    3. Your Mac will automatically check for available updates. If one is found, follow the on-screen prompts to download and install it.

    To update your iPhone or iPad:

    1. Open the Settings app, go to General, and tap on Software Update.
    2. Your device will check for and allow you to install any pending updates.

    8. Inspect Keychain Access for Problematic Certificates (For Advanced Users)

    Warning: This is a highly advanced troubleshooting step and should only be attempted if you are comfortable navigating core system utilities.

    Your Mac’s Keychain Access is a secure digital vault that stores all your passwords, private keys, and security certificates. Occasionally, a manually installed, expired, or corrupted certificate within this vault can create a conflict that blocks a secure connection to a specific website. This is particularly common if you have previously installed a “self-signed certificate” for a local development server or a corporate network, as these can sometimes interfere with public web traffic.

    Keychain Access is the heart of your Mac’s security. Deleting the wrong certificate (especially a “root” certificate) can cause widespread connection failures across multiple applications and websites. Therefore, you should only proceed if you strongly believe a specific certificate is the cause.

    To carefully inspect and remove a rogue certificate:

    1. Open Spotlight Search by pressing Cmd + Space, Keychain Access, and Enter.
    2. Once the application is open, focus on the “Keychains” panel at the top left. Select the System keychain, which contains certificates that affect all users on the Mac.
    3. In the bottom-left “Category” panel, click on Certificates to filter the main window’s view.
    4. You will now see a list of all system-level certificates. Carefully scan this list for any entries related to the website you are having trouble with. Pay close attention to any certificates marked with a red ‘X’ icon, as this is a clear visual sign that macOS considers them expired or untrusted.
    5. If, and only if, you locate a certificate that you are confident is the source of the problem (e.g., an expired certificate for that specific domain), you can attempt to remove it. Right-click on the certificate and select Delete.
    6. Enter your admin password to confirm the change. After deleting it, quit and restart Safari to see if the issue is resolved.

    Check A Different Website

    If you have tried everything above and the error persists on only one specific website, the problem is likely on the server’s end. This can be due to any of the following reasons:

    • Expired SSL Certificate: This is the most common server-side cause. The website owner forgot to renew their certificate.
    • Insecure Protocol Support: The server might be using an old, insecure version of TLS (like TLS 1.0 or 1.1), which Safari now blocks by default.
    • Certificate Name Mismatch: The certificate was issued for www.example.com, but the server is shop.example.com.
    • Incomplete Certificate Chain: The server isn’t providing the necessary intermediate certificates for Safari to establish trust.

    How to Verify a Server-Side Problem:

    You can use a third-party SSL checker tool to verify if the problem persists on the server itself. Go to a site like SSL Labs’ SSL Test or Security Headers and enter the hostname of the website you can’t access (e.g., www.example.com). The tool will run a deep analysis of the server’s configuration. It will give you a grade (A+ to F) and point out specific errors like expired certificates or weak protocol support.

    If the test reveals a problem, your only recourse is to contact the website’s administrator and inform them of the issue.

    Final Thoughts

    This guide covered the main causes behind the “Safari Can’t Establish a Secure Connection to the Server” error. By following the steps outlined above, you should be well-equipped to identify and resolve the issue from your end. For most users, these solutions will restore secure access to the websites you need.

    However, if you are a website owner or server administrator who has landed here while scratching your head over this error on your own domain, you know firsthand that hosting a secure server is no easy task. Even small mistakes can cause downtime and frustrate users, directly impacting your credibility and business. This is precisely why RunCloud has built solutions to eliminate these complexities.

    RunCloud provides a powerful server management panel that works with any cloud provider you choose, such as DigitalOcean, AWS, or Google Cloud. Its platform features a fully automatic SSL integration that deploys and renews Let’s Encrypt certificates without any manual intervention, ensuring you never have to worry about an expired certificate again.

    Additionally, its integrated DNS manager simplifies the once-complex task of pointing your domains correctly, preventing the configuration errors that often lead to secure connection failures.

    Prevent Errors Like This with RunCloud

    If you’re managing your own server or building websites for clients, errors like “Safari Can’t Establish a Secure Connection” are more than just frustrating – they’re a sign that something’s misconfigured. In many cases, these issues are caused by expired SSL certificates, DNS errors, or mismanaged server settings.

    RunCloud makes all of this easier.

    • Automatic SSL: RunCloud issues and renews Let’s Encrypt certificates automatically – no manual setup, no downtime, no security warnings.
    • Integrated DNS Manager: Configure domains properly with built-in tools that reduce errors and streamline deployment.
    • User-friendly interface: Manage everything through a clean, modern panel – no need to log in to the terminal just to tweak settings or fix issues.
    • Works with any cloud provider: Use RunCloud with DigitalOcean, AWS, Google Cloud, and more.

    If you’re tired of manually fixing preventable problems – or worried your users might be seeing connection errors without your knowledge – it’s time to take server management seriously.

    Get started with RunCloud – and keep your websites fast, secure, and always available.

  • How to Set Up an UpCloud Server with RunCloud

    UpCloud is a popular European cloud server provider that offers affordable cloud hosting services across the globe. What makes it especially striking is that UpCloud gives you a 100% Uptime SLA – which makes it one of the top choices for hosting your websites.

    UpCloud uses its own proprietary MaxIOPS storage technology to deliver industry-leading performance and reliability. It’s claimed to be faster than SSD – built on enterprise-grade SSDs, but up to 2x faster compared to industry-standard cloud servers.

    UpCloud offers a very simple pricing plan. The cheapest plan costs only €7/month, which includes 1GB Memory, 1 CPU Core, 25GB SSD, and 1 TB Transfer.

    UpCloud has 12 worldwide data centers, including digital hubs such as:

    1. Amsterdam
    2. Chicago
    3. Frankfurt
    4. Helsinki
    5. New York City
    6. London
    7. San Jose
    8. Singapore.

    This gives you the flexibility to deploy your applications close to your customers and reduce latency.

    In this post, we will show you how to set up an UpCloud server to host your websites with the help of RunCloud.

    Why Choose RunCloud to Setup Your UpCloud Server?

    RunCloud simplifies server management, allowing you to manage multiple servers and web applications with ease. You can easily change web application stacks and PHP versions, clone web applications, and secure them with SSL/TLS.

    RunCloud supports a range of web applications, including WordPress and Laravel, and offers features such as Git deployment and custom NGINX configuration. The Team feature is useful for agencies assigning different members to different servers with separate permissions. 

    Professional WordPress developers can use the one-click WordPress Staging feature to create a staging version of your website easily. If you don’t have a RunCloud account, you can sign up for a 5-day free trial, with no credit card required.

    Method 1 – UpCloud Server Provisioning (Recommended)

    With our server provisioning feature, you can set up a server in UpCloud directly from the RunCloud dashboard by connecting to UpCloud using their API in RunCloud.

    Video Tutorial: Setup UpCloud Server

    Create UpCloud API Key

    In UpCloud, your API key is in the form of the username and password of your UpCloud account. You only need to enable the “Allow API connection” option from your UpCloud account settings.

    It is NOT a good practice to use your main UpCloud username and password for the API key. We strongly recommend you create a dedicated subaccount that you can use for the API key.

    You can create a subaccount in UpCloud from the People tab within the account settings.

    creating API key

    For this subaccount permission, uncheck the “Access to control panel” option, and only enable the “Allow API connection” option. This subaccount will be dedicated to API connections only and can’t be used to access your UpCloud control panel.

    Upcloud API key

    Add UpCloud API Key to RunCloud

    After creating the key, you need to add it to RunCloud. You can either use the “Add a new key” shortcut when building a new server using RunCloud, or you can go to the “3rd Party API Key” menu by clicking your profile (top right), then clicking the Settings menu. There you will see the list of all server provider API keys that you have added to RunCloud.

    Upcloud Integration

    Click on UpCloud and add the login credentials of the new account that we just created. Once you have added your API key, you can start building the UpCloud server directly from the RunCloud dashboard.

    ADD upcloud integration

    Deploying Your UpCloud Server

    To get started, go to your RunCloud dashboard and click on the “Connect a Server” button to set up your first server.

    runcloud connect first server

    A screen will pop up showing you a list of available server providers – select UpCloud and click the “Deploy Server Automatically” option.

    Scroll down to the bottom of the page and give your server a suitable name, select the API key from the list, then click “Continue”.

    Upcloud create server

    On the next screen, you can pick your desired operating system, data center region and instance type according to your requirements. After this, you can deploy your server by clicking the “Add This Server” button – RunCloud will begin provisioning your server automatically.

    This step usually takes 5-10 minutes. Once the provision is complete, you will be returned to the RunCloud dashboard.

    Method 2 – Connect UpCloud With Direct Server Installation

    You can also use the direct server installation method to connect a server to RunCloud. To do this, go to your UpCloud dashboard and create a new server using either the Ubuntu 20, 22, or 24 LTS OS image in your desired datacenter.

    Upcloud dashboard create Server

    Next, configure any other settings that you want to change, such as adding SSH keys or updating your server’s name. The RunCloud agent requires TCP traffic on ports 80, 443, and 34210 to function properly, and we will explain how to do this later in the article.

    Upcloud SSH keys

    After creating your server, it should be visible in your UpCloud dashboard. Wait for the server to finish provisioning. Once it has, log into it using SSH.

    server summary upcloud

    After logging in to your server, go to the RunCloud dashboard and click on “Connect a Server”. In this method, instead of using “Direct installation” select “Connect via IP Address”.

    On the next screen, you will see a bash command. Copy this command and paste it in your SSH terminal. You’ll need to execute this command as the root user, so make sure you have the necessary permissions to do so.

    This will install all the necessary dependencies on your server that are required to run websites. After the installation is complete, you can close the terminal, and manage your server from the RunCloud dashboard.

    connect server manually RUnCloud

    Configuring the UpCloud Firewall for RunCloud

    After connecting your server to RunCloud, it is recommended that you configure a firewall. UpCloud provides a straightforward, network-level firewall that you can manage directly from your control panel. This section will guide you through setting up the necessary rules to ensure your server can communicate with RunCloud and serve web traffic securely while blocking all other unauthorized access.

    First, you need to access the firewall management interface for your server. To do this, log in to your UpCloud control panel and navigate to the details page of the server you intend to use with RunCloud. Once you are on the server’s overview screen, click on the Firewall tab to proceed.

    Next, you will add a series of rules to allow specific types of incoming traffic required for RunCloud and standard web hosting to function correctly. You will need to create a new rule for each of the following services:

    • Create a rule to allow standard HTTP traffic by permitting incoming connections on TCP port 80.
    • Add another rule for secure HTTPS traffic by allowing incoming connections on TCP port 443.
    • Optionally, to support the modern HTTP/3 protocol, you can add a rule that allows incoming traffic on UDP port 443.
    • Next, you must create a rule to allow the RunCloud agent to communicate with your server. Add a rule to permit incoming connections on TCP port 34210.
    • To allow yourself to connect to the server via SSH, create a rule for TCP port 22. For enhanced security, it is highly recommended that you disable or remove this rule if you don’t plan to connect to your server via SSH.

    Please note that when creating these firewall rules for incoming services, you must specify the port value at the target port on your server, not the source port. This is because you are defining which port on your server is “listening” for a connection. The source port of the connecting client is typically dynamic and unpredictable, so we leave its value to “All Ports” and create rules for the known service port (80, 443, 34210, etc.) on your end.

    After setting up the above rules, you must also allow traffic from UpCloud’s DNS servers. You need to add rules that permit incoming TCP and UDP traffic that originates from source port 53 from UpCloud’s specified DNS servers. You can simply create the necessary rules by clicking on the corresponding. checkbox.

    With all the necessary “allow” rules in place, you must now set the default policy for all other traffic. For a secure configuration, the default incoming traffic rule should be set to Drop. You can easily do this by selecting “drop” from the drop-down menu at the top. This ensures that any traffic not explicitly permitted by the rules you just created will be blocked, which will effectively secure your server from unsolicited connections.

    Finally, once you have added all the required rules and set the default policy to Drop, you can click on the “Save Changes” button on the top right. Next, you can flip the master switch to activate the firewall ruleset for your server and turn it on. Your server is now protected by the UpCloud firewall and correctly configured to communicate with the RunCloud platform.

    For a comprehensive guide and to learn more about advanced firewall features, please read the official UpCloud firewall documentation.

    After Action Report

    If you’re looking for a reliable and high-performing hosting option for your website, UpCloud is an excellent choice. Their enterprise-grade hardware and MaxIOPS storage technology provide consistent and fast performance, with an astonishing 100% Uptime SLA. Furthermore, their plans start as low as €7 per month, making it an affordable option for both businesses and individuals alike.

    To take your hosting experience to the next level, start using RunCloud alongside your UpCloud server. With RunCloud, you can easily manage your server and web applications from a single dashboard, even if you’re not an expert in Linux. Register for RunCloud and streamline your server management experience.

  • A Step-by-Step Guide to Connect a Microsoft Azure Server to RunCloud

    A Step-by-Step Guide to Connect a Microsoft Azure Server to RunCloud

    Managing servers through the command line can be tedious. Many cloud management platforms add to the friction by restricting functionality or locking you into their ecosystem.

    RunCloud was built to solve this exact problem.

    It is a flexible VPS management platform that works with any cloud platform, supports multiple server stacks, and supports both x86 and ARM CPU architectures.

    In this blog, we will show you how to combine the power and reliability of Microsoft’s Azure cloud with the simplicity and efficiency of the RunCloud server management panel.

    By the end of this guide, you’ll have a brand-new, optimized server ready to host your websites and applications.

    This guide is perfect for anyone, from hobbyists launching their first project to developers looking for a streamlined workflow.

    Important Note: RunCloud is designed to work on a fresh, clean server. This process will not work on an existing server with websites or other software (workloads) running on it. You must start with a brand-new server, which we’ll create together in the steps below.

    Let’s get started!

    Part 1: Creating Your Virtual Machine in Microsoft Azure

    First things first, we need a server. In Azure, a server is called a “Virtual Machine“ or VM.

    Step 1: Log in to Your Azure Portal and Create a VM

    1. Head over to the Microsoft Azure portal and log in.
    2. In the main dashboard, click on “Create a resource“.
    3. Search for “Virtual machine“ and select it, then click “Create“.
    Microsoft Azure dashboard

    Step 2: Configure the Basics

    Now you’ll see a screen with several options. Let’s fill them in.

    Project Details: Select your Azure Subscription and Resource Group. You can create a new resource group if you don’t have one. Think of it as a folder that holds all related resources for a specific project.

    Instance Details:

    • Virtual machine name: Give your server a memorable name, like runcloud-server.
    • Region: This is the physical location of your server. For the best performance, pick the region closest to most of your website visitors.
    • Availability options: You can leave this as the default for now.
    • Image: This is your server’s operating system. RunCloud works best with Ubuntu. Select the latest Ubuntu Server LTS version (e.g., Ubuntu Server 22.04 LTS).
    • VM architecture: RunCloud supports both x64 and Arm64. Unless you have a specific reason for using Arm64, x64 is the more widely compatible option.

    Step 3: Choose Your Server Size

    This setting determines how much power (CPU) and memory (RAM) your server has. We recommend starting small if you’re just starting out or hosting a small hobby project. Azure’s free plan often includes a B1s-size instance with one vCPU and 1 GB of memory. This is a great, cost-effective way to begin.

    You can always resize your server later if your website grows! However, when you resize your server, it will be rebooted, so you should be aware that your applications will be unavailable for a few moments.

    Step 4: Set Up Your Authentication Method

    This is how you (and RunCloud) will access the server for the initial setup. You have two choices:

    Option A: Password (The Simpler Route)

    This is the easiest option if you don’t plan on regularly logging in to your server’s command line.

    1. Select “Password“ as the authentication type.
    2. Choose a username. Azure sets the default username to azureuser, but you can choose any name you prefer.
    3. Create a strong password and confirm it.

    Security Note: While password authentication is generally less secure for long-term server access, it’s perfectly fine for our setup. Once RunCloud is connected, it manages your server, and you can disable direct SSH password login later if you don’t plan to use it.

    Option B: SSH Public Key (The More Secure Route)

    If you’re comfortable with the command line and want a more secure way to log in, choose this option.

    1. Select “SSH public key“.
    2. Azure can generate a new key pair for you. A key pair is made of two parts: a private key that you keep safe on your computer, and a public key that lives on the server.
    3. Select “Generate new key pair“ and give it a name.
    4. When you create the server, Azure will automatically download the private key (a .pem file) to your computer. Save this file in a secure location. Anyone with access to the private key can log in to your server.

    Step 5: Configure Inbound Ports and Firewall

    Under “Inbound port rules“, check the boxes to allow selected ports. From the dropdown, select:

    1. HTTP (80)
    2. HTTPS (443)
    3. SSH (22)

    These settings open 3 of the 4 required ports for RunCloud. We’ll manually add the final one (34210) in the next step.

    Step 6: Configure Disk Storage

    After configuring the above settings, you can move to the “Disks“ tab. Here, you can set the size of your VM’s disk.

    Step 7: Review and Deploy

    After this, you can click the “Review + Create“ button. Azure will validate your settings. If everything looks good, click “Create“.

    Your server will now be deployed, which usually takes a few minutes. If you chose the SSH key option, you will be prompted to download your private key file now.

    Part 2: Configuring Your Server’s Firewall

    Once your server is deployed, we need to configure one more networking setting. RunCloud uses a specific port to communicate securely with your server, and we need to open it.

    1. From your Azure dashboard, go to the resource page for your newly created virtual machine.
    2. On the left-hand menu, navigate to “Networking“ > “Network Settings“.
    3. Scroll down until you see a list of “Inbound port rules“. Click the “Create port rule“ button and create a new inbound port rule.
    1. A new panel will slide out. Fill in the following details:
      • Source: Any
      • Source port ranges: *
      • Destination: Any
      • Service: Custom
      • Destination port ranges: 34210
      • Protocol: TCP
      • Action: Allow
      • Priority: You can leave this as the default.
      • Name: Give it a clear name, like Allow_RunCloud_Agent.
    2. Click “Add“ to save this rule in your firewall. Once the rule is added to the firewall, it will be immediately enabled and applied to all the servers using this network security group.

    You might worry that opening a port to “Any“ IP address is risky. Don’t be! RunCloud has built-in security to protect this port. Our agent uses a double authentication mechanism. First, it verifies that the connection is coming from a legitimate RunCloud IP address. Second, it uses a unique server ID and key to validate every request. No one can access the agent without passing both of these checks.

    Your final firewall rules should look like this:

    • Port 22 (SSH): Allows you to connect via command line.
    • Port 80 (HTTP): Allows standard web traffic.
    • Port 443 (HTTPS): Allows secure web traffic (including UDP for HTTP/3).
    • Port 34210 (RunCloud Agent): Allows RunCloud to manage your server.

    Part 3: Connecting the Server to Your RunCloud Dashboard

    If you followed all the steps above, you can now connect this new server to your RunCloud account.

    1. Log in to your RunCloud Dashboard.
    2. Click “Connect a New Server“.
    3. Select “Microsoft Azure“ as your server provider, then choose the “Connect via IP Address“ method.
    1. After this, you will be required to configure the following details:
      • Server Stack: Choose your preferred stack. If you are unsure, you can leave these settings to their default value.
      • Server Name: Give your server a friendly name you’ll recognize in the dashboard.
      • IP Address: Copy the “Public IP address“ from your Azure VM’s overview page and paste it here.
    2. Click “Continue“.

    RunCloud will generate a custom installation script for your server. How you run it depends on the authentication method you chose in Azure.

    If you opted for Password Authentication:

    This is the easy part! RunCloud will simply ask for the server’s password. Enter this password into the RunCloud dashboard. The setup will continue automatically from there.

    Alternatively, you can also use the following command in your terminal to connect to the server manually via SSH. Before you execute the following command, make sure to replace the Azure user with the name of your user account and your_server_ip with the public IP address of your server:

    ssh azureuser@your_server_ip

    If you opted for SSH Key Authentication:

    You’ll need to log in to your server using a terminal and your downloaded .pem key file. We have already written an in-depth article that explains how to use SSH keys with PuTTY on RunCloud, but if you are in a hurry, then you can follow the steps below:

    1. Open a terminal (on Windows, you can use PowerShell or Command Prompt; on Mac/Linux, use the Terminal app). Use the following command format to connect to your server. Replace the file path and IP address with your own:
    ssh -i "C:\path\to\your\azure-key.pem" azureuser@your_server_ip

    Breakdown of the command:

    • "C:\path\to\your\azure-key.pem" is the path to your private key.
    • azureuser is your Azure username.
    • your_server_ip is your VM’s public IP.
    1. Once logged in, type sudo su to log in to the user account. RunCloud needs this user account to install the necessary software on your server. If you are unsure what user account you are using, you can run the whoami command to see your username.
    1. After logging in as the root user, copy the installation script from the RunCloud dashboard, paste it into your terminal, and press “Enter”.

    The installation will now begin; it typically takes 10-15 minutes for the script to install and optimize NGINX, PHP, MariaDB, Redis, and other essential tools for you.

    Once completed, you will see a success message on your screen with important information, such as your database root password and server details. We recommend saving this information in a secure password manager.

    Part 3: Experiencing the RunCloud Dashboard

    Once your server installation is finished, you can return to your RunCloud dashboard. Your new Azure server is listed, fully configured, and ready for action. You can now:

    Part 4: Disabling SSH Access

    Before you dive in, we suggest deploying a quick test web application to see RunCloud in action and confirm everything is running smoothly. Once you’re happy with the setup, we recommend taking one final step to enhance your server’s security.

    Since you’ll manage your server through the RunCloud dashboard, you can safely close the SSH port (22) we opened for the initial connection. Follow these steps below to disable SSH access to your server:

    1. Return to the “Network security group“ settings for your virtual machine in the Azure portal.
    2. Find the inbound rule for port 22 (SSH) in the list.
    3. On the far right of that rule, click the trash can icon.
    4. Confirm the deletion when prompted.

    Deleting this rule will block all SSH access to the server, preventing remote login attempts. You can now continue to use the RunCloud dashboard with the peace of mind that your server is safely managed.

    Final Thoughts

    This guide explains the process for connecting a new Microsoft Azure virtual machine to a RunCloud account. We covered the necessary steps, from creating the server and configuring its firewall rules in Azure to completing the connection through the RunCloud dashboard.

    Once setup is complete, you can manage your server entirely through the RunCloud dashboard. This allows for a more streamlined workflow for tasks such as deploying web applications, managing databases, and monitoring server health.

    While this guide covers the initial setup, RunCloud also offers a suite of tools for users with more advanced development workflows. Once you are comfortable with the basics, you may want to explore features such as:

    • One-Click Staging Environments: Create a safe copy of your live site to test updates, plugins, and code changes before pushing them to production.
    • WordPress Canvas: Define a master template with your preferred theme and plugins to deploy multiple, identical WordPress sites quickly and consistently.
    • Git & Atomic Deployments: Connect your repository from services like GitHub, Bitbucket, or GitLab for automated, seamless, and zero-downtime application deployments.

    These features help simplify and speed up both development and server management tasks.

    Sign up for RunCloud and join thousands of developers, agencies, and business owners who trust RunCloud to simplify their workflow and keep their websites running smoothly.

  • How to Set Up a Hetzner Server with RunCloud

    How to Set Up a Hetzner Server with RunCloud

    Setting up a cloud server to host your website can be a daunting task, especially if you are not experienced in server management. However, with the right cloud provider and management tools, the process can be made significantly easier.

    RunCloud supports many different cloud providers, including Hetzner, a well-known cloud provider that offers reliable, affordable, and flexible cloud solutions. In this article, we will guide you on how to set up your Hetzner cloud server to host your website with the help of RunCloud, a server management platform that simplifies server management experience.

    How To Deploy A Server Automatically

    Configuring The Settings

    Step 1: Start by opening your RunCloud dashboard and open the ‘Servers’ tab. Click on the “Connect a Server” button to deploy a new server.

    RunCloud Dashboard Connect Your First Server

    Step 2: From the list of cloud providers, select Hetzner Cloud. Next, select the “Deploy Server Automatically” to create a new server.

    Selecting Cloud Provider RunCloud

    Step 3: Select your preferred installation type, native or containerized.

    Next, you need to select whether you want to use NGINX or OpenLiteSpeed. If you are unsure, pick Native installation with OpenLiteSpeed stack. 

    Learn more about containerization on RunCloud, OpenLiteSpeed vs. NGINX.

    Selecting tech stack on RunCloud

    Integrating Hetzner Account With RunCloud Dashboard

    You only need to do this step once. If you have already added your Hetzner API key to your RunCloud dashboard then you can skip this step.

    Step 1: Open your Hetzner Cloud dashboard in a new browser tab and select the project that you want to use. Now navigate to the “Security” submenu and open the “API tokens” tab.

    Creating API token On Hetzner

    Step 2: Click on “Generate API token” to make a fresh key. Give it a suitable description for your reference.

    Make sure to select the “Read & Write” option while creating the key.

    Finally click on the “Generate API token” to create the key.

    Generating an API token on Hetzner

    Step 3: After the key is created, it will only be displayed once. Make sure to copy it and add it to RunCloud before closing the dialog box. If you have accidentally closed the box, then you’ll need to delete the existing key and create another one.

    For security reasons, it is NOT recommended to save the keys in a text file.

    Successful creation of API token on Hetzne

    Step 3: After copying the key, go back to the RunCloud dashboard and click on “Add API Key“.

    Adding an API key on RunCloud

    Step 4: Paste your API token and give it a descriptive label. Click on the “Test Integration” button to check your connection. If you did everything correctly then you should see a Success pop-up.

    Now you can click on “Add API Key” to complete the integration.

    Successful testing of API key on RunCloud

    Deploying The Server

    Step 1: Now you should be able to use the key that we just added to create a server automatically. If you can’t see the new key in the drop-down menu then try refreshing the page. Select the key and click “Next”.

    Selecting the API Key on RunCloud

    Step 2: Next you need to specify your Operating system, region, and instance type. RunCloud recommends using Ubuntu 22.04 LTS in the region closest to most of your customers.

    Now pick the instance type based on your needs. If this is your first time creating a website, we recommend using the cheapest option.

    Selecting Pricing plans on Hetzner

    Step 3: Now scroll down to the bottom and give a suitable name to this server. You also need to acknowledge that Hetzner will bill you directly for any resources that you use. After this you can click on the “Add Server” button to deploy your server.

    This step usually takes 5-10 minutes as RunCloud creates a new server, runs a preliminary inspection, and installs basic tools and dependencies on the server before it can be used to host a web application.

    Optionally, you can go back to your Hetzner dashboard to confirm that this created a new server with desired configuration in your account.

    Note: Hetzner charges extra for public IPv4 addresses, and you might be billed for an amount slightly higher than what is shown in RunCloud dashboard. The prices shown here should only be treated as an approximation, and you should refer to Hetzner Cloud pricing plans for updated information.

    Hetzner dashboard server overview

    After you have finished setting up your server, you can move on to Installing WordPress with RunCloud.

    You should note that RunCloud will not automatically manage the server’s firewall when deploying a server via the RunCloud API with the Docker stack. This means that you are responsible for securing your server’s network ports and configuring firewall rules. So, you will need to configure the firewall manually and make sure you configure the firewall rules as explained in the steps listed below to protect your server from unauthorized access.

    Deleting the Server

    If you no longer want to use the server, then you should delete it to avoid unnecessary charges. Scroll down to the bottom of the Server Settings page and click on the “Delete Server” button. Confirm that you want to delete the server by specifying its name and click “Proceed to Delete”.

    This will permanently delete the server along with any web applications that were deployed on it, and Hetzner will no longer bill you for this server.

    Deleting RunCloud Server via API

    How To Deploy A Server Manually

    Creating An SSH Key

    We need to add an SSH key to our Hetzner account to access the servers. If you have an existing key, you can use that, or you can create a new key-pair by running the following command in Windows PowerShell:

    ssh-keygen -t ed25519

    You will be asked to specify the location of the key, and enter a passphrase. Press ‘Enter‘ to select the default settings and store your key without any password.

    Creating SSH key in Powershell

    During the key creation process, two new files will be created – a public key and a private key. After you have created the key, you will get a message saying “Your public key has been saved in …” In the above example, our key was saved in “C:\Users\user/.ssh/id_ed25519.pub“.

    You can use your favorite text editor to view the public key; we used the cat command to view the contents of the key. We will use the private key to connect to the server via SSH. In the above example, our public ssh key is:

    ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAYZ+GefPeMeossXzW9Jr/K48s6kBBzdEiO2iWOGKwCa user@deck-stop

    Copy the public key and open the Hetzner dashboard. Open a project and head over to the Security sub-menu. Click on the “Add SSH key” button to add a new key.

    Adding SSH key on Hetzner

    Paste your key, give it a descriptive name, and set it as the default key. Finally, click on “Add SSH key” to save the changes.

    Creating A Firewall Rule

    We need to create a firewall rule that allows TCP traffic on ports 80, 443, and 34210 so that RunCloud can communicate with the server properly. Additionally, you can also allow incoming UDP traffic on port 443 to enable HTTP3 traffic.

    Head over to the Firewalls tab and click on “Create Firewall”.

    Creating a Firewall Rule on Hetzner

    Add new rules to allow incoming TCP connections on ports 80, 443, and 34210. We will be connecting to our server via SSH to set it up.

    Add another rule to allow TCP connections on port 22 – you can delete this rule later if you like.

    Adding new firewall rules for RunCloud

    Leave the Outbound rules unchanged to allow all outgoing traffic. In the “Apply to” section, create a new selector. We will use this selector to mark our servers so that this firewall rule is applied to them.

    Configuring firewall selector on RunCloud

    Give a suitable name to your firewall rule and click “Create Firewall“.

    successful creation of firewall rule on Hetzner

    Creating A New Hetzner Cloud Server

    Go to the Servers submenu and click on “Add Server” to create a new server.

    Adding a server on Hetzner Cloud

    Pick the location of your server and select the OS image that you want to use. RunCloud recommends using Ubuntu 22.04.

    Selecting Operating System on Hetzner Cloud

    Select the server size – more powerful servers cost more. We recommend starting with cheap servers to avoid unexpected costs.

    Selecting Machine size on Hetzner Cloud

    We plan to host a website on this server which will be accessible from the internet, and so we will need an IP address to do so. Our desired settings are already selected, so we left the network settings unchanged.

    We also note that the SSH key which we just created in the Creating A SSH Key step was selected by default.

    Configuring SSH key on Hetzner Cloud

    Next we will select the firewall rule that we created in the Creating A Firewall Rule step.

    Setting RunCloud Firewall Rule

    Give a suitable name to your machine, verify all the settings, and click “Create” to deploy the server. After the server is created, note down the Public IP address of the server.

    Successful Creation of new Server on Hetzner

    Connecting The Hetzner Cloud Server To RunCloud

    Go to your RunCloud dashboard and click “Connect a Server”. Pick Hetzner Cloud and select “Connect via IP Address” to add the server manually.

    Connecting a Server in RunCloud via IP address

    Select the installation type and pick the server stack that you want to use. Enter a suitable name for your server and provide its IP address. You can find this address in the Hetzner dashboard.

    Setting IP address of Hetzner Server

    Connecting To The Server via SSH

    Now we need to log into the server to install the RunCloud agent. We use the following SSH command in Windows PowerShell to log in:

    ssh root@<ip address> -i <identity file>

    In the above command, replace the <ip address> with the IP address of your server, and <identity file> with the path to your identity file.

    Connecting to server via SSH

    In the above example, our SSH command was:

    ssh root@95.217.159.81 -i C:\Users\user/.ssh/id_ed25519

    If you are connecting to the server for the first time, you will be prompted to verify the fingerprint of the address. Type ‘yes’ and press ‘Enter‘.

    Installing the RunCloud Agent

    After logging into the server, we can install the RunCloud agent. Go back to the RunCloud setup process and switch to the “Manual Installation” tab.

    Installing RunCloud Agent

    Copy the given command and paste it in your PowerShell window, then press ‘Enter‘ to run it on the Hetzner server. This step takes 10-15 minutes to complete.

    Executing installation script

    After the installation is complete, you can type ‘exit‘ in PowerShell to close the connection to the server. You can type ‘exit’ again to close the PowerShell window as well.

    Successful installation of RunCloud Agent

    Deleting Your Server

    If you have created a server manually, you will need to delete it manually, both from Hetzner and RunCloud.

    Go to the Hetzner Cloud dashboard, open the server that you want to delete, and go to the “Delete” tab. Click on the “Delete Server” button and confirm your action by entering the name of the server.

    After you have deleted the server, you will no longer be able to access its contents – be sure to make any backups beforehand.

    Deleting Hetzner Server

    After deleting the server from Hetzner, we need to delete it from the RunCloud as well. Go to the settings menu of the server and scroll down to the bottom. Click on “Delete Server”, confirm by entering the name of the server, and click “Proceed to Delete”.

    Deleting server manually on RunCloud

    Video Tutorial – Setup Hetzner Server With RunCloud

    Next Steps

    Using Hetzner and RunCloud as your cloud provider and server management platform respectively is a wise choice. After the initial setup, new servers can be launched with only a few clicks.

    If you are not already using RunCloud to manage your servers, you can start doing so today. Sign up for our free trial and see how it makes server management more effective and easy.

    After you have finished setting up our server, you should read about How To Install WordPress and How To Install Magento with RunCloud.

  • LiteSpeed Cache WordPress Plugin Configuration Tutorial

    LiteSpeed Cache WordPress Plugin Configuration Tutorial

    LiteSpeed Cache is a caching plugin for WordPress that helps improve the performance of a website by storing frequently accessed data in a cache. This allows the website to load faster for visitors by reducing the amount of time it takes for the server to process and retrieve the necessary data.

    LiteSpeed Cache is built for the LiteSpeed web server, which is known for its high performance and low resource usage.

    In this article, we will walk through the steps of installing the LiteSpeed plugin on your WordPress site and explain how to configure it correctly.

    Why Use LiteSpeed Cache Plugin On WordPress?

    One of the key benefits of using LiteSpeed Cache is that it can significantly improve website loading speed by caching website content and resources.

    Caching involves storing a copy of a webpage’s content and resources, such as images and CSS files, on the server. When a user requests the same page, the server can quickly serve the cached version, rather than having to generate the page from scratch each time. This can greatly reduce the amount of time it takes for a page to load.

    This can lead to a better user experience for visitors, which can help increase engagement and reduce bounce rates. Additionally, a faster website can also lead to improved search engine rankings, as search engines such as Google take page load speed into account when determining page rank.

    LiteSpeed Cache includes other features such as minification and concatenation of HTML, CSS, and JS files to reduce the size of resources. This also helps to decreases the website loading time.

    LiteSpeed Cache also supports CDN integration, which can further speed up page loading times by delivering content and resources to users from a server that is geographically closer to them.

    Suggested read: How To Configure LSCache for Laravel

    How to Install the LiteSpeed Cache Plugin on WordPress

    Installing the LiteSpeed Cache plugin on a WordPress website is a straightforward process. Here are the steps you can follow to install the plugin:

    • In the WordPress dashboard, navigate to the “Plugins” menu, and click on the “Add New” button.
    • In the “Add Plugins” page, type “LiteSpeed Cache” in the search bar, and click on the “Search Plugins” button.
    LiteSpeed Cache plugin homepage
    • From the search results, select the “LiteSpeed Cache” plugin by LiteSpeed Technologies, and click on the “Install Now” button.
    • Once the installation is complete, click on the “Activate” button to activate the plugin.
    • After the plugin is activated, you will see a new “LiteSpeed Cache” menu item in the WordPress dashboard (see below).
    LiteSpeed Cache menu in wordpress
    • Now navigate down to the “General” tab and click on “Request a Domain key” to start using the plugin.

    Configuring Redis ACL with LSCache on OpenLiteSpeed Servers

    On RunCloud, all new Redis instances are secured with Access Control Lists (ACL) by default. If you want to use Redis for object caching in WordPress using LSCache on your OpenLiteSpeed server, you’ll need to perform a few configuration steps.

    Before we go any further, ensure that Redis is installed, activated, and running correctly on your server.

    1. Define the Cache Prefix in wp-config.php

    You’ll need to define a specific cache prefix in your WordPress wp-config.php file. This is necessary for limiting the scope of keys when Redis ACLs are in use. To do this, open your wp-config.php file (found in the root directory of your WordPress installation) and add the following line:

    define('LSOC_PREFIX', 'application-name-rcredis:');

    You must replace application-name-rcredis: with your actual application-specific prefix. You can find the prefix value required for your application, along with the necessary Redis username and password, within your RunCloud dashboard under the “Settings” tab of your web application.

    After adding the correct prefix, save your wp-config.php file.

    1. Configure LSCache Object Cache Settings in WordPress

    Once the prefix is defined, navigate to your WordPress admin dashboard and go to LSCache > Cache, and then click on the “Object” tab. Here, you’ll configure LSCache to connect to your Redis instance using ACL credentials.

    On this screen, you will need to fill the following fields:

    • Object Cache: Set this toggle to ON. This enables LSCache’s external object cache functionality and allows it to use Redis (or Memcached) instead of relying solely on WordPress’s internal object caching.
    • Method: Select Redis from the dropdown menu.
    • Host: This is the IP address Redis listens on. If Redis is running on the same server as your OpenLiteSpeed web server (which is the default and most common setup), then you need to use the value 127.0.0.1.
    • Port: In this field, enter 6379, which is the default network port for Redis.
    • Username: Enter the Redis ACL username provided in your RunCloud dashboard.
    • Password: Enter the corresponding password for the Redis ACL username that you noted in the previous step.
    1. Save Changes and Verify Connection

    After filling in all the above fields using the details from your RunCloud dashboard, click the “Save Changes” button. After saving the changes, refresh the page, LSCache will then attempt to connect to your Redis server using the credentials you’ve provided. If the configuration is correct and Redis is accessible with the given ACL details, you should see a status update similar to this:

    LSCACHE with Redis in OLS
    • Redis Extension: Enabled confirms that your PHP environment has the necessary Redis extension loaded.
    • Connection Test: Passed confirms that the LSCache has successfully connected to your Redis server using the ACL username and password, and can communicate with it for object caching.

    Your WordPress site is now configured to use Redis with ACL for object caching via LSCache, which can significantly improve its performance and scalability.

    Step-By-Step Instructions On How To Configure The Plugin For Optimal Performance

    These are the steps we would advise you follow to configure the LiteSpeed Cache plugin for optimal performance on a RunCloud server:

    1. In the WordPress dashboard, navigate to the “LiteSpeed Cache” menu and click on the “Presets” tab. This tab contains some recommended presets, which are designed to work well for most websites. Pick the one closest to your requirements; we’ll fine tune the individual settings later. 
    2. Under the “Cache” tab:
      • Make sure that “Enable Cache” and “Cache Login Page” are both enabled.
      • Under “Cache TTL“, set the time for which a page will be cached before it needs to be rebuilt. If the content on your website is updated frequently, then you should consider a shorter time period like 5 minutes; if most of the content is static then you can pick longer timeframes such as 1 day, or even a week.
      • Under “Purge All on Upgrade“, select “Auto Purge” if you want the plugin to automatically purge the cache when you update WordPress or any plugins. This is useful because if you’ve recently updated your website’s content or design, you’ll want visitors to see those changes.
      • Under the “Excludes” section you can exclude certain pages or posts from being cached.
      • Enable “Browser Cache” and “Object Cache” to store static files locally in the user’s browser.
    LiteSpeed Cache settings
    1. In the “CDN” tab:
      • Turn on “QUIC.cloud CDN“ and enable “CDN Mapping”.
      • Configure the integration with Cloudflare or a content delivery network (CDN) by switching on the “Cloudflare API” option and entering the necessary information.
    2. Under the  “Image Optimization” tab:
      • Turn on “Auto Request Cron” to automatically optimize images on a schedule.
      • Make sure to turn on “Image WebP Replacement” to start using WebP versions of images. This significantly improves load times by replacing images with a newer image format.
    3. Under the “Page Optimization” tab:
      • Enable “CSS Minification“, “JS Minification“, and “HTML Minification” to minify the appropriate files.
      • Enable “DNS Prefetch Control“ to speed up the loading times of all URLs.
      • Enable “Lazy Load Images” and “Optimize Images on Upload” to optimize image loading and reduce page load times.
      • Turn on “Load JS Deferred” to defer JavaScript execution.
    LiteSpeed Cache js settings
    1. Once you have configured the plugin settings, click on the “Save Changes” button to save the settings.

    It’s important to note that the settings may vary depending on the website structure and the specific needs of the website. Therefore, it’s recommended to consult the plugin documentation for detailed information on configuration and optimization options.

    Testing Performance Improvements

    It’s always a good idea to test the website performance both with and without the plugin, and compare the results to see the actual impact of the plugin on your website’s performance.

    There are several tools available for testing website performance. Some popular options include:

    • Google PageSpeed Insights: This tool analyzes a webpage and provides a score, and suggestions for how to improve its performance.
    • GTmetrix: This tool analyzes a webpage and provides a score, along with detailed information about the page’s load time and resources.
    • Lighthouse: This is an open-source tool that can be run either as a browser extension, or in the command line. It analyzes web pages and provides performance metrics, and suggestions for improvements.

    Troubleshooting Tips For Common Issues

    There are several common issues that users may experience when using the LiteSpeed Cache plugin on a RunCloud server. Below are some troubleshooting tips that can help resolve these issues:

    • Cache not working: Make sure that the LiteSpeed web server and the LiteSpeed Cache plugin are both installed and configured correctly. Also, check the plugin settings to ensure that caching is enabled for the appropriate pages and posts.
    • Integration with Cloudflare or CDN not working: LiteSpeed Cache can integrate with Cloudflare or a content delivery network (CDN) to serve cached pages and resources to visitors. If the integration is not working, check the plugin settings to ensure that the appropriate integration is enabled and configured correctly.
    • Conflicts with other plugins or themes: Conflicts with other plugins or themes can cause issues with LiteSpeed Cache. In such cases, deactivate or remove any conflicting plugins or themes, and check if the issue is resolved.
    • Incorrect page cache: If LiteSpeed Cache is not caching pages correctly, make sure that the plugin settings are configured correctly for your website, and clear the cache.
    • Not seeing any improvements: In some cases, even after proper configuration, you may not see any improvements in website performance. One possible reason is that the website is already performing well, and LiteSpeed Cache is not able to make any significant improvements. In such cases, it’s always a good idea to monitor the website performance, and compare the results both with and without the plugin.

    After Action Report – Monitoring Site Performance

    LiteSpeed Cache is a highly effective caching plugin for WordPress that can significantly improve website performance.

    As your development projects become more complex and your team grows, it’s essential to have more control over your servers, and it’s always a good idea to test and measure the performance difference both with and without the plugin.

    RunCloud provides a comprehensive solution for managing your cloud servers, deploying websites and web applications, and monitoring server health – all through a secure and user-friendly management panel. Sign up for RunCloud today, and see the difference for yourself.

  • The Best Docker Alternatives for Containerization in 2025

    The Best Docker Alternatives for Containerization in 2025

    Docker has changed software development and application deployment through containerization. Its intuitive command-line interface, tools such as Docker Desktop, and the vast Docker Hub ecosystem have all made creating, sharing images, and running containerized applications incredibly accessible.

    But many people don’t realise that the Docker engine isn’t the only containerization technology available.

    This post will discuss some of the best alternatives to Docker and compare powerful options that adhere to the Open Container Initiative (OCI) standards.

    Whether you’re concerned about security, optimizing for Kubernetes clusters, managing container images across different container registries, or simply seeking improvements in your container management strategy, by the end of this article, you will be able to find the best containerization platform for your specific needs.

    Let’s get started!

    What is Containerization?

    Containerization is a new way to deploy applications on a remote server. Traditionally, we’ve been copying the application’s source code and executing it on the remote server.

    However, containerization technology allows us to bundle an application’s code and all its necessary dependencies, libraries, configuration files, and binaries, into a single, isolated unit called a container. This container image is a self-sufficient package that can run consistently across different computing environments, from a developer’s laptop to production servers in the cloud or on-premises data centers.

    In Linux, containerization uses operating system-level virtualization features, such as namespaces and control groups (cgroups). Unlike traditional virtual machines (VMs) that require a full guest operating system for each instance, containers share the host system’s OS kernel. This makes containers very lightweight, faster to start, and less resource-intensive than VMs. This allows developers to deploy multiple containers on a single VM for higher density and more efficient use of underlying hardware resources.

    📖 Suggested read: 20 Essential Docker Commands You Should Know

    Best Docker Alternatives for Containerization

    Docker is by far the most popular container runtime available. So much so that many people use the terms ‘Docker’ and ‘containers’ interchangeably – but it isn’t the only containerization technology.

    Let’s take a look at alternative container runtimes that you can use instead of Docker:

    S No.NameVisit Website
    1Podman https://podman.io/
    2Linux Containers https://linuxcontainers.org/
    3Red Hat OpenShift https://www.redhat.com/en/technologies/cloud-computing/openshift
    4Apptainer/Singularityhttps://apptainer.org/
    5Containerd https://containerd.io/
    6Cri-ohttps://cri-o.io/
    7Mirantis Container Runtime https://www.mirantis.com/software/mirantis-container-runtime/

    Podman

    Podman is a helpful tool for anyone working with software containers. It lets you easily find, download, run, build, and share containers using straightforward commands like search, pull, run, build, and push. One special thing about Podman is its ability to group related containers into ‘pods’, which makes it easier to manage applications where different parts need to work closely, similar to how bigger systems like Kubernetes operate.

    If you prefer using a visual interface instead of typing commands, you can use the Podman Desktop application on Windows, macOS, and Linux. This app gives you a single screen to manage your containers, even if they were created with other tools such as Docker.

    Podman Desktop makes building new container images simple, as well as getting images from online repositories, grouping containers into pods, and checking logs. It even helps you prepare and move your container applications to run on Kubernetes.

    📖 Suggested read: How to Create a Docker Image for Your Application

    Linux Containers

    Linux Containers, often abbreviated as LXC, are one of the longest-standing options built directly on the Linux kernel and include features such as namespaces and groups. LXC aims to create environments close to a standard Linux installation but without a separate kernel. This differs slightly from Docker, which typically focuses on packaging a single application and its dependencies.

    LXC is geared more towards running a ‘system container’ – a lightweight virtual machine that can run multiple services or a full init system inside. This ‘system container’ approach might not be a drop-in replacement for your Docker workflow and may require you to configure how you deploy applications.

    LXC uses powerful Linux features and offers management tools and libraries (like liblxc). It mimics a full OS environment, which might be more than most people need for simple application isolation. LXC could be great if you needed to replicate a traditional server setup within a container, but if you are just looking to run your apps, it might introduce unnecessary complexity.

    📖 Suggested read: Docker Security: Best Practices to Secure a Docker Container

    Red Hat OpenShift

    Red Hat OpenShift is much more than just a container runtime. It is a full-fledged application platform built on Kubernetes designed to handle the entire lifecycle of applications, from development and building to deployment and management at scale, even across different cloud environments or on your own servers.

    If you just want to build and run containers, this might not be the right tool for you. Red Hat OpenShift is designed to provide a consistent environment with integrated tools for building, automating deployments (like CI/CD pipelines), and managing applications, not just basic container orchestration.

    The platform offers different ways to use it, either as a managed service on clouds like AWS or Azure, where Red Hat handles the underlying infrastructure, or as a self-managed service for more control. It also has built-in security, developer tools, and the ability to manage virtual machines alongside containers.

    While Red Hat OpenShift is a powerful tool, especially for larger teams or complex applications that need this robust management and security, it is also more complex than just using Docker. Therefore, you must weigh whether the comprehensive features justify the potential learning curve and operational overhead for your needs.

    📖 Suggested read: How to Install WordPress on Docker in 2025 [Step-By-Step Guide]

    Apptainer

    Apptainer, which used to be called Singularity, is another tool for packaging and running software inside containers, similar to how Docker works. It’s open-source software, now part of the Linux Foundation, and designed to be straightforward, quick, and safe. Apptainer is particularly popular in environments where many people share the same computer systems, like university computing clusters or research labs, and for running software that needs a lot of computing power.

    It primarily focuses on performance-intensive applications commonly found in High-Performance Computing (HPC), scientific research, and AI/ML workloads. It is designed for environments where maximizing computational performance, managing complex software stacks, ensuring reproducibility, and handling specialized hardware like GPUs is very important.

    Apptainer is different in handling containers and interacting with the computer it’s running on. It packs everything into a single file, making the container easy to copy, move between computers, or share with others. Apptainer also lets the software inside the container easily use special hardware on the host machine, like powerful graphics cards (GPUs) or fast network connections, which is important for scientific computing.

    Its security approach is also quite simple: by default, you have the same permissions inside the container as you do outside, which helps prevent users from accidentally gaining extra privileges on the system.

    📖 Suggested read: What Are Docker Logs And How To Use Them

    Containerd

    Containerd is a core container runtime focused on managing the complete container lifecycle. This includes tasks like image transfer and storage, container execution and supervision, low-level storage, and network attachments.

    It might surprise you that Docker uses containerd under the hood (or components derived from it), meaning containerd isn’t necessarily a replacement for the entire Docker developer experience, but rather the engine component that does the heavy lifting.

    However, it is much lower-level than the Docker run command, as it exposes the distinct stages of container creation and execution. Rather than providing developers with a simple, all-in-one command-line interface, it’s designed more for integration into larger systems or for users who need fine-grained control.

    It has well-established documentation, API, and client libraries, particularly for the Go client for programmatic control. You can easily use this client to connect to the daemon, pull images, create OCI specs, manage snapshots (container filesystems), and much more.

    While containerd is a crucial piece of the container ecosystem and the standard runtime interface (CRI) implementation for Kubernetes, it doesn’t directly replace the user-facing Docker command-line tool and its associated build/compose functionalities out of the box. Instead, it replaces the runtime part that Docker traditionally managed.

    If you are looking for just the runtime component, containerd is the go-to option. However, replicating the full Docker developer workflow requires other tools (such as nerdctl for a Docker-compatible CLI or build tools like BuildKit).

    📖 Suggested read: Bringing Containerization to RunCloud’s Cloud Architecture

    Cri-o

    If you are working with Kubernetes, you might already be familiar with CRI-O. It is a lightweight Kubernetes Container Runtime Interface (CRI) implementation. This means its primary purpose isn’t to be a general-purpose container engine like Docker, but rather to provide exactly what Kubernetes needs to manage container lifecycles (pods) efficiently and reliably, using standard OCI-compliant runtimes like runc underneath.

    CRI-O acts as the bridge between the Kubernetes kubelet and the low-level container operations. It handles pulling images from any OCI-compliant registry, managing container storage, generating the OCI runtime spec, launching the actual runtime (like runc), setting up networking via CNI, and using conmon for monitoring. Concentrating only on these Kubernetes-essential tasks, it aims to be more stable and resource-efficient within a cluster than a more feature-rich daemon like Docker’s.

    If you are thinking of replacing Docker, you can use CRI-O to replace the runtime component on the Kubernetes nodes. However, you should note that it doesn’t offer a direct replacement for the Docker command-line interface or tools such as Docker Compose for local development workflows.

    Mirantis Container Runtime

    Mirantis Container Runtime (MCR) is similar to ‘Docker Engine – Enterprise’. It is designed to be compatible with the core Docker API and commands you might already know. The main goal of MCR is to provide this familiar Docker Engine functionality, but specifically tailored for enterprise needs, along with commercial support (like 24×7 options) and enhanced security features, which might be necessary if your organization has stricter requirements than those that standard open-source Docker offers.

    MCR heavily emphasizes security aspects often required by large organizations or regulated industries. For example, it uses FIPS 140-2 validated cryptography, has secure default configurations, and offers capabilities like enforcing the use of digitally signed images to secure the software supply chain.

    It has broad capability as it supports both Linux and Windows containers. It can run in standalone mode, as part of a Kubernetes deployment, or in Docker Swarm clusters. This means you can use it in various infrastructure setups without demanding a complete overhaul of orchestration strategies.

    Wrapping Up

    Choosing the right container runtime is a critical decision that depends heavily on your team’s needs, your infrastructure, and the type of applications you’re building. While Docker has been the default choice for years, it’s clear that the container landscape in 2025 offers powerful alternatives such as Podman, LXC, containerd, CRI-O, and OpenShift, each with unique strengths.

    If you manage large Kubernetes clusters, CRI-O or containerd might make sense. If you need a daemon-less solution with strong security principles, Podman is a compelling option. And if you operate in highly regulated enterprise environments, Mirantis Container Runtime brings Docker compatibility with hardened security features.

    However, while choosing the right containerization platform is critical, managing your servers and deployments effectively is equally important – and that’s where RunCloud comes in.

    RunCloud simplifies server management for developers and teams working with containerized or traditional PHP-based applications. Whether you’re using Docker, containerd, or another runtime under the hood, RunCloud helps you:

    • Deploy web applications faster
    • Set up automated backups
    • Manage server security with best practices baked in
    • Monitor performance from a unified dashboard
    • Scale projects effortlessly as your infrastructure grows

    Instead of worrying about the underlying complexities of servers and deployments, you can focus entirely on building and shipping better software.

    If you’re ready to streamline your application deployments and server management, no matter what container runtime you use, sign up for RunCloud today.

    Thousands of developers and businesses already trust RunCloud to manage their mission-critical projects. Discover a simpler, faster, more scalable way to run your applications.

    FAQs on Docker Alternatives for Containerization

    Is Podman better than Docker?

    Podman isn’t inherently ‘better’, but it offers advantages such as a daemonless architecture for enhanced security and rootless container execution. Docker has a more mature ecosystem and wider initial adoption, which makes it a strong choice for many workflows.

    Do I need Kubernetes if I use Docker?

    No, you don’t automatically need Kubernetes just for using Docker, as Docker excels at managing containers on a single host. Kubernetes becomes necessary to orchestrate, scale, and manage containerized applications across multiple hosts or clusters.

    Is LXC faster than Docker?

    LXC can exhibit slightly better performance in certain benchmarks due to operating at a lower level, closer to the kernel, often termed ‘system containers’. However, for typical application container workloads managed by Docker, the performance difference is usually negligible and less critical than Docker’s developer-focused tooling. The choice often depends on whether you must run full OS-like environments (LXC) or isolated applications (Docker).

    What is the best containerization platform?

    There is no single ‘best’ containerization platform; the ideal choice depends on your specific use case, team expertise, and requirements. Docker remains extremely popular for its ease of use and rich ecosystem, while Podman is favored for security-focused or daemonless environments.

    What is the difference between Docker and Kubernetes?

    Docker primarily focuses on building, shipping, and running individual containerized applications, often on a single machine. On the other hand, Kubernetes is a container orchestration platform designed to automate the deployment, scaling, and management of containerized applications across clusters of machines. Simply put, Docker creates the containers, and Kubernetes manages them at scale in production environments.

    Are Docker alternatives suitable for high-traffic applications?

    Docker alternatives like Podman, containerd, and CRI-O are suitable and commonly used for high-traffic, production-grade applications. The ability to handle high traffic effectively relies heavily on the orchestration layer (like Kubernetes) and the application architecture.

    What is the difference between containerization and virtualization?

    Virtualization creates virtual machines (VMs), each running a complete operating system instance with its own kernel on top of a hypervisor. Containerization packages an application and its dependencies, isolating them at the process level while sharing the host OS kernel. Therefore, containers are much lighter, faster to start, and consume fewer resources than VMs.

  • How to Identify and Kill Queries with MySQL Command-Line Tool

    How to Identify and Kill Queries with MySQL Command-Line Tool

    Is your application slow? Are users complaining about lag? This slowdown might be because your MySQL server is struggling under the weight of a long-running or problematic database query.

    When your WordPress site or web application relies heavily on its database (and most do!), a single poorly performing query can have a massive impact.

    Although many third-party tools are available to help with specific problems, in this article, we will use the built-in MySQL command-line tool, which offers a direct, powerful, and quick way to diagnose these issues.

    We’ll guide you through using the command line to:

    1. View currently running processes using SHOW PROCESSLIST.
    2. Identify the specific slow query or problematic process ID.
    3. Safely terminate (KILL) the query when required.

    Let’s get started!

    Prerequisites

    Before you can manage MySQL queries, you’ll need to ensure that you have the necessary access and permissions on your server. You’ll need the following:

    1. Shell access to your server
    2. MySQL user account with specific privileges. For administrative tasks like this, it is common to use the MySQL root user as it has all the necessary privileges.

    How to Kill MySQL Queries via Command Line

    Step 1: Connecting to Your MySQL Server via Command Line

    You can access the MySQL command-line interface via SSH once you’ve connected to your server. The most common way to connect locally is using the MySQL root user. Open your SSH terminal and execute the following command:

    mysql -u root -p   

    Let’s break this down:

    • mysql: Invokes the MySQL command-line client program.
    • -u root: Specifies that you want to log in as the MySQL user named root. Replace root if you are using a different administrative MySQL user.
    • -p: Tells the client to prompt you for the password. It’s more secure than typing the password directly in the command line.

    📖 Suggested read: How to Change/Reset MySQL Root Password on Ubuntu Linux?

    After running this command, you’ll be prompted to enter a password. Paste or type the MySQL root password you retrieved from your RunCloud dashboard. You’ll be greeted with the MySQL monitor prompt (mysql>) if the credentials are correct.

    Step 2: Viewing Running Processes in MySQL

    Now that you’re connected to your MySQL server via the command line, you can run the SHOW PROCESSLIST command to get a snapshot of all the active connections (threads) to your database server and what they are doing at that precise moment. Simply type the following at the mysql> prompt and press ‘Enter’:

    SHOW PROCESSLIST;

    While this command is useful, it truncates the actual SQL query being executed in the ‘Info’ column. For more effective troubleshooting, especially when dealing with complex or long queries, it’s highly recommended to use the extended version:

    SHOW FULL PROCESSLIST;

    The FULL keyword allows you to see the complete SQL statement, which is necessary for diagnosis.

    The output of either command presents a table with several columns, and understanding these columns is key to identifying problematic queries:

    • Id: This is the unique identifier for the connection thread. You will need this number later if you decide to terminate a query or connection using the KILL command.
    • User: Shows the MySQL username associated with the connection thread. This helps you trace the query back to a specific application user or system process.
    • Host: Displays the hostname or IP address (and port) from which the connection originates. This is useful for identifying queries coming from specific application servers, cron jobs, or even unexpected locations.
    • DB: This column indicates the thread’s current default database. If no database is selected, it will be NULL.
    • Command: Describes the type of command the thread is currently executing. For example, the query command means that the thread is actively executing an SQL statement.
    • Time: This is one of the most important columns for performance troubleshooting. It tells us the amount of time (in seconds) that the thread has spent in its current state. For ‘Query’ states, a high ‘Time’ value is a strong indicator of a long-running, potentially problematic query.
    • State: This column provides more granular details about what the thread is doing within its current command. Some states are benign (starting, checking permissions), but others often point towards bottlenecks or issues:
      • System lock: The query is waiting to acquire a lock on a table or row currently held by another thread. This is a common cause of application hangs.
      • Sending data: The thread is processing and sending results back to the client. If this state persists for a long time, it might indicate a query returning a huge result set or network latency.
      • Writing to net: Similar to sending data, indicates network transfer activity.
    • Info: This column displays the actual SQL statement being executed by the thread.

    📖 Suggested read: SQLite vs MySQL vs PostgreSQL (Detailed Comparison)

    If you are using RunCloud, you can use the Slow Script Monitoring functionality from your RunCloud dashboard to identify slow database operations over time. This method is ideal for less technical users as it doesn’t require connecting to your server via SSH or performing any other command-line operations.

    An alternative method offers more flexibility for users comfortable with SQL.

    MySQL provides the PROCESSLIST table within the information_schema database. You can query this table directly using standard SQL SELECT statements to create powerful filters.

    For instance, to find all actively running queries (Query command) that have been executing for more than 60 seconds, and order them by the longest running first, you could use:

    SELECT id, info FROM information_schema.PROCESSLIST
    WHERE COMMAND = 'Query' AND TIME > 60
    ORDER BY TIME DESC;

    This approach can be very helpful on busy servers where the output of SHOW PROCESSLIST is overwhelming. You can pinpoint the threads causing performance degradation or blocking by carefully examining the process list output. Similarly, you can filter visually by ‘User’ or ‘Host’ if you suspect a particular application or job is causing trouble.

    📖 Suggested read: How to Connect a MySQL Database to PHP (A Developer’s Guide)

    Step 3: Analyzing the Query (Optional but Recommended)

    Before killing a slow or seemingly stuck MySQL query, it’s important to investigate the underlying cause first to ensure it doesn’t happen again. You can begin by copying the complete query text from the ‘Info’ column associated with the problematic process.

    Once you have this query text, the next critical step is understanding its execution plan. In a separate MySQL session, execute EXPLAIN <query_text>; to get an overview of your SQL command. Replace the <query_text> with the SQL statement you retrieved.

    This EXPLAIN command provides insights into how MySQL intends to execute the query. This can reveal potential bottlenecks, such as full table scans, which would indicate potentially missing indexes on columns used in WHERE or JOIN clauses, inefficient join types, or an unexpectedly high number of rows being examined.

    Fixing the underlying issue leads to long-term performance gains. For example, let’s assume optimizing a frequent query saves just 20% of its CPU time. That could mean your current server can handle significantly more traffic, or you might even be able to downsize to a smaller, cheaper AWS instance, which would directly save money while providing a faster experience for your users.

    📖 Suggested read: MariaDB vs MySQL – A Detailed Comparison & How You Should Choose

    Step 4: Killing the Query or Connection (KILL)

    Once you’ve identified a suspicious query using the command described above, you can use the kill command to terminate the thread and manually restore server performance.

    ⚠️ Warning: Always double-check that you are using the correct process ID obtained from SHOW PROCESSLIST before executing any KILL command. Terminating the wrong process can lead to unexpected application errors or data inconsistencies.

    KILL QUERY <process_id>;

    This is generally the preferred first attempt. This command tries to terminate only the specific statement that the thread is currently executing, leaving the connection itself open. This is less disruptive to the connecting application.

    For example, if process ID 12345 is running a slow query, you would run:

    KILL QUERY 12345;

    Remember that KILL QUERY might not take effect instantly if the thread is performing an operation that cannot be safely interrupted (like writing to disk). In such cases, it will wait until the thread reaches a point where it can be safely terminated.

    KILL CONNECTION <process_id>;

    If the KILL QUERY command doesn’t work or if you need to terminate the entire connection associated with the thread, you can forcefully terminate the connection. This terminates the statement and drops the client connection.

    KILL CONNECTION 12345;

    In the following example, we can see that the database forcefully terminated the connection from the client. Therefore, you should always use this command with caution as it can lead to unexpected errors.

    Step 5: Verifying the Kill

    After issuing a KILL QUERY or KILL CONNECTION command, you must confirm that it worked.

    The most straightforward way to do this is to run SHOW PROCESSLIST; again immediately. If the kill was successful, the process ID you targeted should no longer be in the list.

    Occasionally, you might see the thread you attempted to kill still listed, but with ‘Killed’ appearing in the Command column. This usually means MySQL has registered the kill request but hasn’t terminated the thread yet. This can happen if the thread is engaged in an operation that cannot be interrupted instantly, such as waiting for disk I/O or performing cleanup tasks.

    The thread will disappear shortly after showing the ‘Killed’ state. However, if you used KILL QUERY and the thread persists, it might indicate the query itself is resistant to termination in its current state. In such scenarios, you can use the more forceful KILL CONNECTION command to terminate the connection and release its resources.

    Important Considerations and Best Practices for Killing MySQL Queries

    While the MySQL command-line tool provides a direct way to manage running queries, using the KILL command should always be done thoughtfully and with an understanding of the potential repercussions.

    • Kill with Caution: Terminating queries, especially KILL CONNECTION, isn’t always clean. Be aware of the potential consequences:
      • Transaction Rollbacks: If you kill a thread executing Data Manipulation Language (DML) statements like INSERT, UPDATE, or DELETE within a transaction (particularly with InnoDB), the entire transaction will typically be rolled back to ensure data consistency. This might be desirable, but it’s important to understand it will happen.
      • Application Errors: Applications are often not designed to handle unexpected database connection drops. Killing a connection might result in application-level errors, incomplete operations, or confusing states for end-users.
      • Resource Cleanup: While modern storage engines such as InnoDB are good at cleaning up, forcefully killing threads can sometimes, albeit rarely, leave behind temporary tables or orphaned locks that might require manual cleanup later.
    • Don’t Kill System Threads: Exercise extreme caution when viewing the process list. You might see threads run by internal system users (e.g., system user, event_scheduler) or replication users (often named repl or similar). Avoid killing these threads unless you have a deep understanding of MySQL internals and are sure it’s necessary and safe, as doing so can disrupt essential background processes, break replication, or even lead to server instability.
    • Focus on Root Cause Analysis: Killing a query is almost always a temporary band-aid, not a permanent solution. The most important step after resolving an immediate performance crisis is to investigate why the query was slow or problematic in the first place. Was it due to missing indexes? Poorly written SQL? Inefficient application logic? A bad schema design? It is always recommended that the application code be analyzed to identify and fix the underlying issue. Otherwise, the problem is likely to recur.
    • Proactive Prevention with max_execution_time: You can consider setting the max_execution_time system variable. This allows you to define a timeout (in milliseconds). The server will automatically abort queries exceeding this time limit, preventing runaway read queries from consuming excessive resources.

    Final Thoughts

    Identifying and killing problematic queries manually using MySQL’s command-line tool is an essential skill for any serious developer or server administrator. Knowing how to spot performance bottlenecks quickly can save your application from crashes, downtime, and user frustration.

    But even with the right techniques, managing servers directly through the terminal takes time, demands technical expertise, and leaves too much room for human error.

    That’s where RunCloud can transform your workflow.

    RunCloud provides a simple, powerful platform that handles the heavy lifting of server management for you. Instead of spending hours troubleshooting MySQL issues through command-line sessions, you can:

    • Monitor server performance and database health visually through an intuitive dashboard
    • Use built-in Slow Script Monitoring to proactively catch issues before they affect users
    • Automate backups, deployments, and SSH alerts – all without touching the command line
    • Easily manage MySQL databases, users, and permissions without memorizing commands

    Thousands of developers and businesses already trust RunCloud to manage their mission-critical servers – and for good reason. It saves time, reduces stress, and gives you peace of mind that your applications are running at their best.

    Ready to experience better server management? Sign up for RunCloud today.

    Stop putting out fires. Start focusing on building, growing, and delivering better results – with RunCloud by your side.

    Frequently Asked Questions About Managing MySQL Queries

    Managing a MySQL server often raises important questions, especially when diagnosing slow queries or optimizing database performance. Below, we answer the most common questions developers and administrators ask about viewing, analyzing, and safely killing MySQL queries.

    How can I list only queries that are running longer than a certain time in MySQL?

    You can filter the information_schema.PROCESSLIST table directly. For example: SELECT id, user, time, info FROM information_schema.PROCESSLIST
    WHERE command = 'Query' AND time > 60;
    This shows queries that have been active for more than 60 seconds, making it easier to detect slow or stuck queries.

    Is it better to kill a query manually or let MySQL’s timeout settings handle it?

    In emergencies, manually killing a slow query is faster. However, using server settings like max_execution_time provides automatic safeguards to prevent long-running queries from becoming a recurring problem without human intervention.

    How often should I monitor running MySQL queries?

    In production environments, continuous automated monitoring is ideal. RunCloud’s Slow Script Monitoring can alert you to persistent slow queries without constant manual checks. Manual investigation should be triggered whenever performance drops or after major deployment changes.

    Can killing queries help fix “Too many connections” MySQL errors?

    Yes, selectively killing idle or stuck queries can immediately free up connections. However, this is a temporary fix. For long-term stability, you should also optimize your database configuration and connection pooling.

    Will killing a query cause data loss or corruption?

    Killing a query mid-execution won’t typically cause corruption if you use transactional storage engines like InnoDB. However, it may cause the current transaction to roll back, potentially undoing changes made during that session. Always investigate and resolve the underlying issue afterward.

    What’s the safest way to kill a problematic query?

    Use KILL QUERY <process_id>; first, as it only attempts to stop the active SQL statement without closing the entire database connection. If that fails or the thread is unresponsive, escalate to KILL CONNECTION <process_id>; to terminate the session.

    How can I prevent long-running queries in the future?

    Analyze your slow queries using EXPLAIN plans and optimize indexing, query structure, or application code. Additionally, set reasonable limits like max_execution_time and actively monitor performance metrics using tools such as RunCloud’s dashboard.


    Ready to simplify server management and focus on what matters most? Sign up for RunCloud and see why thousands of developers and businesses trust it for fast, secure, and reliable server operations.

  • How to Build a CI/CD Pipeline with GitHub Actions and Docker

    How to Build a CI/CD Pipeline with GitHub Actions and Docker

    Are you tired of manually building, testing, and deploying your applications?

    Modern Continuous Integration (CI) and Continuous Deployment (CD) approaches can automatically trigger a deployment pipeline to build your Docker image, run tests, push it to a container registry like GHCR or Docker Hub, and deploy it to your server.

    The best part is that you can complete all of this in less than a minute after pushing code to your GitHub repository.

    By combining Docker with the automation capabilities of GitHub Actions, you can create a fast and effective DevOps pipeline. Docker ensures your application runs the same way everywhere by packaging it with its dependencies in a portable Docker container based on instructions in your Dockerfile. GitHub Actions then automates the build and push steps, securely manages secrets like access tokens, and handles the final deployment to your infrastructure.

    In this guide, we’ll walk you through configuring your GitHub Actions workflow step-by-step, from publishing a container to deploying it on your server without third-party tools or subscriptions.

    By the end of this tutorial, you will be able to configure a deployment pipeline that updates your live server in under a minute after you push changes to it.

    Let’s get started!

    What are GitHub Actions?

    GitHub Actions is a powerful automation tool built directly into the GitHub platform. It listens for specific events happening in your repository, like someone pushing new code, creating a pull request, or even on a set schedule, and then automatically performs tasks you’ve defined. These tasks form a workflow, which is essentially a sequence of steps designed to achieve a specific goal. You can use this functionality to create a Continuous Integration (CI) and Continuous Deployment (CD) pipeline.

    This means you can automate the entire process of building your software, running tests to ensure quality, and even deploying it to servers (perhaps managed through tools such as RunCloud) without manual intervention.

    Key Features of GitHub Actions

    GitHub Actions has several useful features that make it a compelling choice for automation. Firstly, its event-driven nature allows workflows to trigger automatically in response to a wide variety of GitHub events. Secondly, matrix builds let you efficiently test your code across different environments simultaneously; you can define combinations of operating systems (like Linux, macOS, and Windows), software versions (like different Node.js or Python versions), or other variables, and GitHub Actions will run a job for each combination.

    Furthermore, GitHub provides hosted runners, which are virtual machines managed by GitHub that can execute your workflow jobs without requiring you to manage any infrastructure. If you have very specific needs, then you can also consider using self-hosted runners on your own servers or cloud infrastructure.

    All the actions and workflows on GitHub can be reused. You can even configure pre-built steps created by the community (available in the GitHub Marketplace) and save significant development time. Lastly, GitHub Actions includes integrated secrets management for securely handling sensitive information like API keys and passwords. It provides live logs for monitoring workflow progress in real time and the ability to store artifacts like build outputs or test reports.

    📖 Suggested read: What is Docker And How Does it Work

    Steps to Deploy Docker Container with GitHub Actions for CI/CD

    Let’s walk through the steps to automate building your application’s Docker image, pushing it to a registry, and then deploying it to your server every time you push changes to your repository.

    Prerequisites:

    • GitHub Repository: You need a GitHub repository containing all your application code. Make sure you have committed and pushed your latest code changes to GitHub.
    • Dockerfile: You must have a Dockerfile in the root of your repository. This file contains the step-by-step instructions Docker uses to build an image of your application. The specific commands inside the Dockerfile depend heavily on your application’s language, framework, and dependencies (e.g., installing packages, copying code, setting entry points), so we assume you have already created a functional Dockerfile.

    Step 1: Connect to Linux Server via SSH

    First, ensure you can connect to the target Linux server where your Docker container will run. You’ll need SSH access for this.

    ssh your_server_user@your_server_ip

    In the above command, replace your_server_user with your username and your_server_ip with the server’s IP address. If you manage your server with RunCloud, you can use the simplified SSH key management to store SSH keys. We recommend reading the RunCloud documentation to learn how to easily create and manage SSH keys for secure server access.

    📖 Suggested read: What Are Docker Images And How To Use Them

    Step 2: Verify Docker Installation on the Server

    Once connected to your server via SSH, you need to confirm that Docker is installed and running correctly. The Docker Command Line Interface (CLI) is required to pull images and run containers. You can test this by running the standard Docker test image:

    docker run hello-world

    If Docker is installed and working, you will see a message starting with “Hello from Docker!”. This message indicates that your installation appears to be working correctly.

    If the command fails or Docker is not found, you must install Docker Engine on your Linux server before proceeding. Follow the official Docker installation documentation specific to your server’s Linux distribution (e.g., Ubuntu, RHEL).

    📖 Suggested read: How To Create a Docker Image For Your Application

    Step 3: Add GitHub Action Secrets for SSH Access

    To allow your GitHub Actions workflow to securely log in to your server and execute deployment commands, you must store your server’s connection details as encrypted secrets in your GitHub repository. You should never hardcode sensitive information directly into your workflow file – we recommend using GitHub’s built-in secret management system for this.

    Navigate to your GitHub repository > Settings > Secrets and variables > Actions. Click “New repository secret” for each of the following:

    1. SERVER_IP: The public IP address of your Linux server.
    2. SERVER_PORT: The SSH port for your server (usually 22, but might be different if customized).
    3. SERVER_USER: The username you use to log in to your server via SSH. We strongly recommend creating a new user account specifically for this deployment step and giving it appropriate permissions for better security.
    4. SERVER_PRIVATE_SSH_KEY: The entire content of the private SSH key file that corresponds to a public key authorized on your server. Your private SSH key should look something like this:
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
    ...
    UV7ErwUhELMZFrAAAAE3RhdHRpY29kZXJAc3Rhcmx1c3QBAgMEBQYH
    -----END OPENSSH PRIVATE KEY-----

    Using secrets prevents exposing your server credentials in your codebase. The workflow will reference these secrets securely during execution. We strongly recommend creating a dedicated SSH key pair specifically for automation.

    Again, consulting the RunCloud documentation can be very helpful in generating and managing SSH keys securely, especially regarding best practices for SSH security.

    📖 Suggested read: Understanding Docker Services | RunCloud Docs

    Step 4: Configure GitHub Actions Workflow

    Now, define the CI/CD pipeline using a GitHub Actions workflow file. This file tells GitHub what steps to perform when triggered (e.g., on a push to your main branch).

    Create a YAML file named docker-publish.yml inside your repository’s .github/workflows/ directory. You can create this directory and file directly via the GitHub web interface or in your local repository using a text editor, and then commit and push the changes.

    Storing secrets for GitHub Actions

    Paste the following code into .github/workflows/docker-publish.yml:

    name: Publish & Deploy Docker container
    
    # This workflow uses actions that are not certified by GitHub.
    # They are provided by a third-party and are governed by
    # separate terms of service, privacy policy, and support
    # documentation.
    
    
    on:
      push:
        # Adjust branch name if needed (e.g., master, production)
        branches: [ "main" ]
        # Publish semver tags as releases.
        tags: [ 'v*.*.*' ]
    env:
      # Use docker.io for Docker Hub if empty
      REGISTRY: ghcr.io
      # github.repository as <account>/<repo>
      IMAGE_NAME: ${{ github.repository }}
    jobs:
      build:
        runs-on: ubuntu-latest
        permissions:
          contents: read
          packages: write
          # This is used to complete the identity challenge
          # with sigstore/fulcio when running outside of PRs.
          id-token: write
    
    
        steps:
          - name: Checkout repository
            uses: actions/checkout@v4
    
    
          # Install the cosign tool except on PR
          # https://github.com/sigstore/cosign-installer
          - name: Install cosign
            if: github.event_name != 'pull_request'
            uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0
            with:
              cosign-release: 'v2.2.4'
    
    
          # Set up BuildKit Docker container builder to be able to build
          # multi-platform images and export cache
          # https://github.com/docker/setup-buildx-action
          - name: Set up Docker Buildx
            uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
    
    
          # Login against a Docker registry except on PR
          # https://github.com/docker/login-action
          - name: Log into registry ${{ env.REGISTRY }}
            if: github.event_name != 'pull_request'
            uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
            with:
              registry: ${{ env.REGISTRY }}
              username: ${{ github.actor }}
              password: ${{ secrets.GITHUB_TOKEN }}
    
    
          # Extract metadata (tags, labels) for Docker
          # https://github.com/docker/metadata-action
          - name: Extract Docker metadata
            id: meta
            uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
            with:
              images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
    
    
          # Build and push Docker image with Buildx (don't push on PR)
          # https://github.com/docker/build-push-action
          - name: Build and push Docker image
            id: build-and-push
            uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
            with:
              context: .
              push: ${{ github.event_name != 'pull_request' }}
              tags: ${{ steps.meta.outputs.tags }}
              labels: ${{ steps.meta.outputs.labels }}
              cache-from: type=gha
              cache-to: type=gha,mode=max
    
    
          # Sign the resulting Docker image digest except on PRs.
          # This will only write to the public Rekor transparency log when the Docker
          # repository is public to avoid leaking data.  If you would like to publish
          # transparency data even for private images, pass --force to cosign below.
          # https://github.com/sigstore/cosign
          - name: Sign the published Docker image
            if: ${{ github.event_name != 'pull_request' }}
            env:
              # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
              TAGS: ${{ steps.meta.outputs.tags }}
              DIGEST: ${{ steps.build-and-push.outputs.digest }}
            # This step uses the identity token to provision an ephemeral certificate
            # against the sigstore community Fulcio instance.
            run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
    
    
      deploy:
        needs: build
        runs-on: ubuntu-latest
        steps:
          - name: SSH and Deploy to Server
            uses: appleboy/ssh-action@v1
            with:
              host: ${{ secrets.SERVER_IP }}
              username: ${{ secrets.SERVER_USER }}
              key: ${{ secrets.SERVER_PRIVATE_SSH_KEY }}
              port: ${{ secrets.SERVER_PORT }}
              script: |
                echo ${{ secrets.GITHUB_TOKEN }} | docker login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin
                echo "--- Pulling latest Docker image ---"
                docker pull ghcr.io/tatticoder/terraform-get-time:main
                echo "--- Stopping existing container (if running) ---"
                docker stop my_container 
                echo "--- Removing existing container ---"
                docker rm my_container 
                echo "--- Starting new container ---"
               # Adjust ports (-p host:container) 
               # Add any necessary environment variables (-e)
                docker run -d --name my_container -p 3000:80 ghcr.io/tatticoder/terraform-get-time:main

    Let’s understand the important sections of the above code snippet:

    • name: Sets the display name for your workflow in the GitHub Actions tab.
    • on: push: branches: [ main ]: This triggers the workflow every time code is pushed to the main branch. You can change main to your default or production branch name (e.g., master).
    • Build Job: This section handles the process of creating and publishing the Docker container.
      • Checkout code: Uses the standard actions/checkout action to get your repository code onto the runner.
      • Log in to GHCR: Uses docker/login-action to authenticate with GitHub Container Registry using the automatically generated GITHUB_TOKEN.
      • Build and push: Uses docker/build-push-action.
    • Deploy via SSH Job: This job uses the popular SSH Remote Commands action to connect to your server using the secrets you configured and execute commands.
      • host, username, key, port: These fields use the secrets you created in Step 3.
      • script: This block contains the shell commands which will be executed on your target server.

        ❗Very Important – please read the following points very carefully:
        • The first command logs into GHCR on the server. Pulling public GHCR images might not require login. For private images, you can just use the provided command without any modifications.
        • The subsequent command pulls the latest tagged image from GHCR. Make sure to edit this command and replace ghcr.io/tatticoder/terraform-get-time:main with the name of your container image and its corresponding tag.
        • The subsequent command stops and removes any container with the name ‘my_container’ to avoid conflicts. Make sure to temporarily remove these commands to prevent the workflow from failing if the container doesn’t exist yet.
        • The final command runs a new container in detached mode (-d) using the pulled image. Make sure to replace the image’s name with the one you want to use and configure any additional parameters as per your requirements.

    ⚠️ Warning: The deployment script uses docker stop and docker rm before docker run. This means there will be a brief moment of downtime while the container is replaced. For zero-downtime deployments, more advanced strategies like blue-green deployments or using orchestration tools like Kubernetes are needed, which are beyond this basic setup.

    To minimize the impact of downtime, you can consider deploying once a day on weekdays outside of peak hours. This schedule can be configured easily using the GitHub action itself.

    📖 Suggested read: Docker Security: Best Practices to Secure a Docker Container

    Step 5: Commit Workflow and Trigger Deployment

    Finally, save the docker-publish.yml file. If you created it locally, commit it and push it to your GitHub repository using the following commands:

    git add .github/workflows/docker-publish.yml
    git commit -m "Add GitHub Actions workflow for Docker build and deploy"
    git push 
    Deploying and running a GitHub Actions for CI/CD

    Once you push this commit (or any future code changes) to the specified branch (main in this example), GitHub Actions will automatically detect the workflow file and start executing the defined steps.

    You can monitor the progress by going to the “Actions” tab in your GitHub repository. If all steps succeed, your code will be built into a Docker image, pushed to GHCR, and then pulled and run as a container on your designated Linux server.

    Once you have published your Dockerfile to GHCR, you will see a new tab in the bottom right of your GitHub dashboard. You can click on the name of your package to view your recently published packages.

    Step 6: Remove Unused Docker Resources (Optional)

    When you use a CI/CD pipeline, you will quickly end up with a large number of old obsolete containers on your server. These containers are often not needed and can slowly fill your disk space. If you are running low on disk space, then you can add an optional cleanup step to your deployment script to prevent your server’s disk space from filling up with old, unused Docker images, containers, and ‘build cache’.

    The following command will automatically remove any Docker resources (like stopped containers and images not associated with a running container) that haven’t been used in the last 24 hours without requiring confirmation. Running this periodically helps maintain server health and efficiently reclaim storage:

    docker system prune --filter "until=24h" --force

    If your deployment process takes a long time, consider optimizing the build stage of your container by using a caching layer within Docker to cache dependencies.

    Wrapping Up: Who Should Use Docker with GitHub Actions for CI/CD?

    Whether you’re a solo developer or part of a large team, automating builds and deployments saves invaluable time and reduces the potential for human error inherent in manual processes.

    While GitHub Actions handles the automation of building your Docker images and triggering deployment scripts, manually configuring, securing, monitoring, and updating servers can be complex and time-consuming.

    RunCloud provides a clean, efficient way to manage servers without the usual hassle. From provisioning and security hardening to database setup and app deployment, it streamlines the tasks that slow developers down. You stay in control of your infrastructure, but without getting buried in configuration files or command-line firefighting.

    That means more time building, testing, and shipping better software.

    Ready to take the work out of server management? Start with RunCloud today.

    FAQs on Docker with GitHub Actions for CI/CD

    What are the advantages of using Docker for CI/CD?

    Docker ensures consistent environments from development through production. It provides process isolation and ensures that builds and tests don’t interfere with each other or the host system dependencies. 

    How do I secure my Docker images in GitHub Actions?

    Start by scanning your images for vulnerabilities using container scanning tools directly within your GitHub Actions workflow. To reduce the attack surface, use minimal, trusted base images and avoid installing unnecessary packages. Always configure containers to run as non-root users and manage secrets securely using GitHub Secrets, never embedding them in the image layers.

    Can I use Docker Compose with GitHub Actions?

    Yes, Docker Compose can be effectively used within GitHub Actions workflows to manage multi-container setups. You simply need to ensure Docker Compose is installed on the runner, then use standard docker-compose commands to build images or spin up services like databases for integration testing.

    What is the best way to manage secrets in GitHub Actions?

    The most secure and recommended method is using GitHub Actions encrypted secrets, which are configured at the repository or organization level. These secrets can then be safely accessed within your workflow as environment variables or passed to specific actions needing credentials. Never hardcode sensitive information directly in your workflow files or application code checked into version control.

    Is Docker necessary for CI/CD?

    While not strictly mandatory, Docker offers substantial benefits that make it a highly popular choice for modern CI/CD pipelines. While alternative options are available, Docker provides reproducible and isolated build/test environments that are useful for reliable continuous integration and delivery.

    How does Docker improve CI/CD pipelines?

    Docker drastically improves CI/CD pipelines by guaranteeing environment consistency across all stages, from developer laptops to production servers. Its containerization isolates dependencies, preventing conflicts and simplifying the configuration of build agents. 

    Can I use self-hosted runners with Docker in GitHub Actions?

    You can absolutely use self-hosted runners with Docker in GitHub Actions. This approach gives you complete control over the build environment and resources.

    What is the difference between Docker and Kubernetes for CI/CD?

    Docker is primarily used within the CI/CD pipeline to build application images, run tests in isolated containerized environments, and consistently package dependencies. Kubernetes is a container orchestrator typically acting as the deployment target after the CI pipeline, responsible for managing the runtime, scaling, and health of containers in a cluster. Docker creates the portable application packages used in CI, while Kubernetes manages fleets of those packages in production or staging environments (CD).

  • The Ultimate Guide To Install NextCloud Using RunCloud

    The Ultimate Guide To Install NextCloud Using RunCloud

    NextCloud is a self-hosted productivity platform that offers industry-leading, on-premise content collaboration functionality.

    It’s an alternative to Dropbox or Google Drive, but with the advantage that it can be installed on your own server, ensuring that your data remains under your control.

    You can use NextCloud to share and collaborate on documents, send and receive emails, manage your calendar, and have video chats – all without any possibility of data leaks.

    In this post, we will show you exactly how to install NextCloud using RunCloud.

    Prerequisites

    You will need a server that meets NextCloud’s system requirements. When you connect your server to RunCloud, it automatically installs all necessary dependencies, and updates them. If you have an existing server connected to RunCloud, you can use that as well – as long as it has the necessary capacity to handle additional load.

    1. Create A PHP Web Application In RunCloud

    Go to your RunCloud dashboard and click “Deploy New Web App”. Next, switch to the “Empty Web App” tab and give your application a descriptive name.

    Deploy a web app

    For “Domain name“, you can either use your own domain name or use RunCloud’s test domain. If you are using RunCloud’s Cloudflare integration, RunCloud will automatically create the necessary DNS records for your domain.

    Set domain name on RUnCloud

    Next, select PHP version 8.1 and click “Deploy” to create the web application.

    set PHP RunCloud

    2. Prepare NextCloud Installer

    After deploying the application you will need to download the NextCloud installation file to your server. There are two ways to do this.

    2.1 Using SSH

    If you are comfortable with SSH then you can run the following commands to download the installation file to your website’s root directory. Don’t forget to update the path to your web application’s root directory (displayed in RunCloud dashboard).

    cd <path to root>
    wget https://download.nextcloud.com/server/installer/setup-nextcloud.php

    2.2 Using RunCloud File Manager

    The second method is to use RunCloud’s file manager. RunCloud has a graphical user interface for editing files on your server, and you can use this to add or remove files from your server. Click on the “File Manager” option to browse the files.

    RunCloud file manager

    Once you have opened the file manager, you should only see one file – index.html. Click on “New” and create a new file with the name setup-nextcloud.php.

    After the file has been created it will be displayed in the file manager. Click on it to edit the file – it will open a file editor in a new browser tab.

    create a file using runcloud file manager

    Download the installation file from https://download.nextcloud.com/server/installer/setup-nextcloud.php and open it in any text editor such as Notepad or VS Code. Press Ctrl + a to select all of the text, and Ctrl + c to copy it.Now go back to the RunCloud file editor and paste the text using Ctrl + v. Make sure to save the file afterwards.

    saving file in RunCloud

    3. Run NextCloud Installer

    After preparing your NextCloud installer, open the URL of your website in a web browser. By default you will see the “Welcome to RunCloud” message present in the index.html file. Go to the address bar of your browser and append /setup-nextcloud.php to the end of the URL.

    For example, if your website is located at www.example.com, you need to go to www.example.com/setup-nextcloud.php to start the installation.

    If you followed the steps correctly, you will be greeted with the following screen. Click on “Next” to move forward with the installation.

    Start Nextcloud installation

    On the next screen you will be asked to specify the installation directory of your web application. Enter a single full stop to install the setup in the current location – i.e., where we added the “setup-nextcloud.php” file.

    set installation directory Nextcloud

    After you have configured the directory, the installation will begin. It will take 5-10 minutes, depending on the speed of your internet connection. Once the installation is complete you will be greeted with a success message.

    nextcloud installation successful

    4. Configure NextCloud

    After installation you will need to set up the administrator account, storage path, and the database that will be used by NextCloud.

    First, go to the RunCloud dashboard and create a new database user. After you have done this, create a new database and grant its access to the user that you just created. Once you have created the database, it should look like this:

    nextcloud database create

    After creating the database, return to the NextCloud installation and enter the login credentials of your administrator account. If you don’t want to use the default path to store data then you can change that as well.

    Finally, make sure to switch to the MySQL/MariaDB tab and enter the details of the new database and user that you created in the last step. Update the database host to localhost:3306 and click “Install”. If you are using a containerised server, then you will need to enter host:3306 instead; refer to our docs on networking in containerised servers on RunCloud for more information.

    Create Nextcloud admin account

    After installation, you will be asked if you want to install the recommended apps. You can skip this step if you wish, and install any apps at a later time from the dashboard.

    5. Troubleshooting NextCloud

    After installation, you will need to tweak a few settings to properly secure your server. Click on the user icon in the top right corner of your screen, and navigate to “Administration Settings”.

    setup Nextcloud installation

    Ideally, you should see the green “All check passed” in the security and setup warning section. However, after installing NextCloud it is possible that you might see messages in any of three different colors:

    • red (error)
    • yellow (warning)
    • black (notice)

    Fortunately, RunCloud makes it very easy to remove these messages. Let’s start with red ones first.

    Warnings on Nextcloud dashboard

    5.1 Fixing “PHP Memory Limit Is Below The Recommended Value”

    This can be easily fixed in the RunCloud dashboard. Go to “Settings” and scroll down to the PHP settings section. You will see the option to modify the memory limit. Update the value, and save the changes.

    setting memory limit on RunCloud

    5.2 Warning – PHP Function is Not Available

    NextCloud requires a number of PHP functions to run properly. If there are any unavailable PHP functions, you will probably see this warning message.

    If you see the message that the PHP function set_time_limit is not available, this could result in scripts being halted mid-execution, breaking your installation. Therefore, enabling this function is strongly recommended.

    To fix this issue, go to the RunCloud dashboard panel, select your server, click the Web Application menu, select your web application, and then click the “Settings” menu of this web app. Scroll to find the disable_functions option and remove the following functions from the text:

    • set_time_limit
    • ignore_user_abort
    • posix_getuid
    • posix_getpwuid

    After removing the functions from the list, click the “Update Web Application Settings” button. Refresh the NextCloud page – the warning message should disappear.

    disable php functions on RunCloud

    5.3 Fixing “Strict-Transport-Security HTTP Header…”

    Enabling HTTP Strict Transport Security policy on your server will fix multiple error messages. Go to your dashboard and click on “Domain Name”. You will see all of the domains that are associated with your application. Configure the TLS settings to enable the HSTS policy.

    Configure HSTS header on RunCloud

    Once there, pick the third option to enable the policy, and click “Update” to save the changes.

    Enable HSTS header on RunCloud

    5.4 Configure Redis Memory Cache (with Enhanced Security)

    Memory caching can significantly improve your Nextcloud server performance, as frequently requested objects are stored for faster retrieval. While Nextcloud displays a warning if a local memcache isn’t configured, it’s not strictly required. However, using a memcache is highly recommended for optimal performance.

    With RunCloud, you can use either Redis or Memcached. Follow the steps below to configure the Redis cache for your Nextcloud installation:

    Step 1: Enable Redis Service (RunCloud)

    1. Log in to your RunCloud dashboard and select the server where your Nextcloud instance is running.
    2. Navigate to the Services section.
    3. Locate the Redis service. If it’s not already running, start it. RunCloud pre-installs Redis, so you generally only need to enable it.
    Enable Redis on RunCloud

    Step 2: Choose Your Redis Authentication Strategy

    RunCloud sets a default Redis password for the default user. You have two primary options:

    • Option A (Simpler): Use the RunCloud Default Redis User: This is the easiest approach but less granular. You’ll use the existing default user and its password.
    • Option B (More Secure): Create a Dedicated Nextcloud Redis User: This is the best security practice. You’ll create a new Redis user with specific permissions tailored only for Nextcloud, minimizing the risk of unauthorized access.

    Step 3: Using the RunCloud Default Redis User (Option A)Retrieve the Default Password: You’ll need the default Redis password set by RunCloud. Go to your Server, click Settings, scroll down to the Redis Password tab, and copy the password from the Current Password field.

    Step 4: Creating a Dedicated Nextcloud Redis User (Option B – Recommended only for Advanced Users)

    Before we proceed further, you should note that this step is optional. Once you have the master password for your Redis server (as explained in step 3), you can use it to connect your Nextcloud instance to Redis. However, advanced users should consider creating a separate user account for Nextcloud using the following steps:

    Connect to Redis via SSH: Connect to your server via SSH and use the following redis-cli to connect to your local Redis instance:

    ## Command to connect to Redis CLI
    redis-cli -h 127.0.0.1 -p 6379 -a "your_runcloud_redis_password"

    In the above command, you will need to replace your_runcloud_redis_password with the RunCloud Redis password that you noted in step 3.

    Create the User: After this, use the ACL SETUSER command provided below to create a new user with the correct permissions. Make sure to replace nextcloud_redis_user and your_secure_password with your desired username and a strong password.

    ## Create user in Redis without Dangerous permissions
    ACL SETUSER nextcloud_redis_user >your_secure_password on ~* +@all -@dangerous

    In the above ACL Rule:

    • +@all: Grants both read and write access to your database.
    • -@dangerous: Denies dangerous commands that could harm your Redis instance.

    You can configure these parameters to add or remove specific permissions by consulting the official Redis documentation.

    Step 5: Configure Nextcloud (config.php)

    1. Access Your Nextcloud Files: In the RunCloud dashboard, go to your server, select your Nextcloud web application, and then click File Manager.
    2. Edit config/config.php: Locate and edit the config/config.php file within your Nextcloud installation directory.

    Add the Redis Configuration: Add the following lines inside the main configuration array (not at the end of the file). Make sure the syntax is correct PHP. The location within the array doesn’t matter as long as it’s within the main $CONFIG = array ( ... ); block.

    If you chose Option A (Default User):

    'memcache.local' => '\OC\Memcache\Redis',
      'memcache.distributed' => '\OC\Memcache\Redis',
      'memcache.locking' => '\OC\Memcache\Redis',
        'redis' => [
        'host' => '127.0.0.1',
        'port' => 6379,
        'password' => 'your_runcloud_redis_password'
      ],

    If you chose Option B (Dedicated Nextcloud User):

    'memcache.local' => '\OC\Memcache\Redis',
      'memcache.distributed' => '\OC\Memcache\Redis',
      'memcache.locking' => '\OC\Memcache\Redis',
        'redis' => [
        'host' => '127.0.0.1',
        'port' => 6379,
        'user' => 'nextcloud_redis_user',
        'password' => 'your_secure_password'
      ],
    1. Save the config.php file.

    Step 6: Verify and Test

    Log in to your Nextcloud admin interface. Go to Administration settings -> Security & setup warnings. The warning about missing memcache should be gone.

    5.5. Enable Imagick (ImageMagick PHP Extension)

    NextCloud uses Imagick for the preview generation process. When Imagick is not available, you will see a warning message in NextCloud’s automated checks.

    Imagick is optional – it’s not required, and you may safely ignore the warning if only a few users are using your NextCloud server. If you want to enable it, read our quick guide on how to install Imagick (ImageMagick PHP Extension) in RunCloud.

    5.6. WebDAV Interface Seems to be Broken

    If you are getting the WebDAV interface seems to be broken error in your Nextcloud installation then you will need to tweak your server settings to fix this error. The exact steps vary for different tech stacks on RunCloud. You can find your application stack under the “Web Application Stack” section on the Settings page for your application.

    For NGINX Hybrid Stack on RunCloud

    If you are using the default hybrid stack on RunCloud, then you will need to create a custom NGINX configuration file for your Nextcloud application. When creating the config, make sure to select the type as location.main-before and give it a descriptive name. Next, paste the following code snippet in the provided text box as shown below:

    location ~ /.well-known {
        try_files $uri @proxy;
    }

    Once you save the configuration file, you can go back to your Nextcloud applications and refresh the page to check if the error still persists.

    For Native NGINX Stack on RunCloud

    If you are using the native NGINX stack, then you will need to create a custom NGINX configuration file for your Nextcloud application. When creating the config, make sure to select the type as location.main-before and give it a descriptive name. Next, paste the following code snippet in the provided text box as shown below:

    index index.php index.html /index.php$request_uri;
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }
    
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }
    
    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in `.htaccess` that concern `/.well-known`.
    
        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }
    
        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }
    
        # Let Nextcloud's API for `/.well-known` URIs handle all other
        # requests by passing them to the front-end controller.
        return 301 /index.php$request_uri;
    }
    
    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }
    
    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        # Required for legacy support
        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;
    
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;
    
        try_files $fastcgi_script_name =404;
    
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;
    
        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass unix:/var/run/<appname>.sock;
    
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    
        fastcgi_max_temp_file_size 0;
    }
    
    # Serve static files
    location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
        try_files $uri /index.php$request_uri;
        # HTTP response headers borrowed from Nextcloud `.htaccess`
        add_header Cache-Control                     "public, max-age=15778463,asset_immutable";
        add_header Referrer-Policy                   "no-referrer"       always;
        add_header X-Content-Type-Options            "nosniff"           always;
        add_header X-Frame-Options                   "SAMEORIGIN"        always;
        add_header X-Permitted-Cross-Domain-Policies "none"              always;
        add_header X-Robots-Tag                      "noindex, nofollow" always;
        add_header X-XSS-Protection                  "1; mode=block"     always;
        access_log off;     # Optional: Don't log access to assets
    }
    
    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }
    
    # Rule borrowed from `.htaccess`
    location /remote {
        return 301 /remote.php$request_uri;
    }
    
    # location / {
    #     try_files $uri $uri/ /index.php$request_uri;
    # }

    After adding the above snippet to your configuration file, you need to modify the line which contains fastcgi_pass unix:/var/run/<appname>.sock;. In this line, you need to replace the <appname> with the name of your application that you entered in the step 1. Once you have saved this config file, you will need to create another NGINX config file for this application, but this time at the root location. Paste the following text in the text box and hit save:

    try_files $uri $uri/ /index.php$request_uri;

    Once you save the second config file, you can go back to your Nextcloud installation and verify that the error is gone.

    For Containerised NGINX Stack on RunCloud

    If you are using containerised Docker servers on RunCloud to run your Nextcloud installation, then you will need to create custom NGINX config to redirect web requests. The steps for creating the custom configuration for this stack are similar to the native NGINX stack on RunCloud (as described above), but there is one key distinction.

    When editing the fastcgi_pass unix:/var/run/<appname>.sock; line in your configuration, you will need to replace it with fastcgi_pass unix:/var/run/php/<appname>.sock;. After replacing the line, you can modify it to update <appname> with the name of your application and continue with the rest of the process.

    Summary

    NextCloud is an open source file manager that provides many additional features such as calendar management and file sharing. If you want to run your own version of Dropbox or Google Drive on your server for your own team or business, NextCloud is a great solution, allowing you to share and collaborate on documents, and have video chats without potential data leaks.

    RunCloud is a server management platform that makes it easy to manage and optimize your servers with an easy to use graphical user interface. Sign up for RunCloud today and see how it can save you time and money.

  • Postfix vs Exim vs Sendmail Email MTA – Which One to Use in 2025?

    Postfix vs Exim vs Sendmail Email MTA – Which One to Use in 2025?

    If you send emails from your Linux server, you’ll need a Mail Transfer Agent (MTA) to process them, but choosing the right one can feel like navigating a complex technological labyrinth.

    There are a few popular MTAs available in the market: Postfix, Exim, and Sendmail. However, selecting the right one can be challenging, as each has its own set of pros and cons.

    Whether you’re a startup looking to establish your first email infrastructure or an enterprise seeking to optimize your existing systems, understanding the nuanced differences between these Mail Transfer Agents is necessary to build an effective infrastructure.

    In this comprehensive guide, we’ll dive deep into the functions and features of Mail Transfer Agents. We will share detailed comparisons of Postfix, Exim, and Sendmail, along with the pros and cons of each MTA.

    Let’s get started!

    What are Mail Transfer Agents?

    A Mail Transfer Agent (MTA) is like a digital postal service for email. It’s software in Linux systems that handles email message routing, delivery, and transmission across different computer networks. Think of an MTA as a specialized postal worker who knows how to pick up an email from one computer and deliver it to the correct destination, no matter how far away it might be.

    How Do Mail Transfer Agents Work?

    Mail Transfer Agents work through a series of systematic steps:

    1. Message Reception: When you send an email, the MTA first receives the message from your email client. It examines the recipient’s email address to determine where the message needs to go.
    2. Routing: The MTA then decides the best path to deliver the email. It uses Domain Name System (DNS) lookups to find the correct mail server for the recipient’s domain.
    3. Message Queuing: If the destination server is temporarily unavailable, the MTA doesn’t give up. It places the email in a queue and will attempt delivery multiple times over a set period.
    4. SMTP Protocol: Most MTAs use the Simple Mail Transfer Protocol (SMTP) to communicate between email servers. This is like a standardized language that ensures emails can be understood and transferred correctly.
    5. Delivery: Once the recipient’s mail server is reached, the MTA hands off the message to the Mail Delivery Agent (MDA), which places the email in the recipient’s mailbox.

    Suggested read: How to Send Email from PHP (With Guided Walkthrough)

    Why are Mail Transfer Agents Required in Linux?

    Mail Transfer Agents are essential in Linux systems for several reasons:

    1. Reliable Communication: MTAs ensure that emails are delivered reliably, even with network interruptions or temporary server issues. They can retry delivery and provide detailed error reporting.
    2. Security: Many MTAs include robust security features like spam filtering, virus scanning, and encryption support. Popular Linux MTAs like Postfix and Sendmail offer advanced security mechanisms.
    3. Flexibility: Linux MTAs can handle complex routing scenarios, support multiple domains, and integrate with various authentication methods.

    Suggested read: How To Resolve The “Email Address is Not Verified” Error With AWS SES

    Comparing Postfix vs. Exim vs. Sendmail Email MTA

    Let’s examine some of the most popular MTAs available and understand their pros and cons.

    What is Postfix?

    Postfix is a powerful, open-source Mail Transfer Agent (MTA) designed to efficiently route and deliver electronic mail across complex network environments. It was designed to provide robust email routing capabilities while maintaining exceptional security standards. It is popular for its modular architecture, which allows system administrators to configure and customize email transmission with granular control and enhanced protection against potential security vulnerabilities.

    Postfix supports multiple operating systems, including AIX, BSD, Linux, MacOS X, and Solaris, which makes it a highly adaptable solution for diverse computing environments. It also ensures seamless communication across different email systems and supports advanced features such as SMTP authentication, encryption, and internationalized email addressing.

    Suggested read: Using Mailgun To Send Transactional Email From WordPress

    Pros of Postfix

    Postfix offers an impressive array of advantages, making it a preferred choice for system administrators and organizations. Its modular design enables extensive customization through support for multiple databases, including LDAP, MySQL, PostgreSQL, and MongoDB. This allows seamless integration with existing authentication and directory services.

    It also provides robust security features, including advanced access controls, spam filtering capabilities, and support for encryption protocols like TLS, which help protect email communications from unauthorized access and potential threats.

    Cons of Postfix

    Despite its numerous strengths, Postfix presents certain challenges that organizations must carefully consider during implementation. The configuration complexity can be intimidating for less experienced system administrators as it requires deep technical knowledge to fully leverage its advanced features and customize its numerous parameters effectively.

    Some organizations might find the initial setup and fine-tuning process time-consuming, especially when integrating Postfix with existing email infrastructure or implementing complex routing and filtering rules.

    Additionally, it has a huge feature set, which can sometimes translate into increased resource consumption. This can potentially impact system performance on lower-powered hardware configurations.

    Suggested read: What are Linux Logs? What Are They & How To Use Them

    What is Exim?

    Exim is a mail transfer agent (MTA) used in Unix-like operating systems. The first version of EXIM was developed in 1995 for use in the University of Cambridge Computing Service’s e-mail systems. Exim is distributed under the GPL and is free to download, use, and modify.

    Exim follows the Sendmail design model, where a single main binary controls all the MTA facilities. This monolithic design is considered by some to be inherently less secure and slower, but despite this, Exim’s security record is much better than Sendmail and comparable with Qmail and Postfix, as is its speed. In advanced areas such as queue handling, address routing, and testing, it exhibits excellent performance.

    Suggested read: How To Flush DNS Cache — A Full Guide

    Pros of EXIM

    Exim is a highly versatile Mail Transfer Agent with robust message transport capabilities. It is an SMTP and LMTP email transport solution and provides comprehensive incoming and outgoing email handling mechanisms across multiple transport protocols. EXIM MTA supports RFC 2821 SMTP and RFC 2033 LMTP standards, enabling flexible message transmission through various methods, including TCP/IP, standard input/output, and daemon-based configurations.

    Additionally, its incoming server capabilities are particularly impressive, as it supports SMTP over multiple interfaces, including direct TCP/IP connections, inetd (internet service daemon) integration, and standard input processing. It also has advanced features such as encrypted and authenticated connections on specific ports like 587. EXIM also provides advanced routing controls that enable message redirection, quarantine, and delivery through multiple transport mechanisms.

    Suggested read: Uptime Monitoring Tools: Why You Need Them, and What to Look for

    Cons of Exim

    Exim isn’t a Mail Transport Agent, so there are some features that you won’t get. For example, it will not store emails and doesn’t support IMAP or POP protocols. However, it can deliver messages to mailstores that do, either using SMTP or LMTP message delivery or, in some cases, by saving messages directly into mailboxes.

    Exim doesn’t have a Graphical User Interface (GUI) to help you configure it, but some Linux distributions add one. Various tools are available to give you graphical views of Exim’s mail queues, traffic, and logs.

    What is Sendmail?

    Sendmail is an established Mail Transfer Agent that has been used for email communication in Unix and Unix-like operating systems for decades. It has become the de facto standard for routing and delivering email across complex network environments.

    Sendmail is critical in managing email transmission by interpreting email addresses, determining the most efficient routing path, and ensuring messages reach their intended destinations across different computer networks.

    Pros of Sendmail

    Sendmail offers numerous advantages that have established its reputation in the world of email infrastructure. Its extraordinary flexibility allows system administrators to create highly customized email routing configurations, making it adaptable to complex network environments. Sendmail supports extensive configuration options through its powerful configuration file, enabling precise control over email processing, routing, and security mechanisms.

    Being open-source, Sendmail benefits from continuous community improvements and has robust support for various authentication methods, encryption protocols, and integration with modern security technologies. Its long-standing presence in the market means it has weathered numerous technological shifts and continues to provide reliable email transmission services for organizations worldwide.

    Cons of Sendmail

    Despite its historical significance, Sendmail has several notable challenges that have prompted many organizations to explore alternative Mail Transfer Agents. The configuration process is notoriously complex, requiring deep technical expertise and extensive knowledge of its configuration syntax, which can be intimidating for less experienced system administrators.

    Its monolithic design has been criticized for potential security vulnerabilities, as a single binary controls multiple email processing functions. The default configuration can be less secure if not carefully managed, and the learning curve for proper implementation is steep. Performance can be slower than that of more modern MTAs, and the configuration complexity makes routine maintenance and troubleshooting time-consuming. These limitations have led many organizations to migrate to more contemporary and user-friendly email transfer agents such as Postfix and Exim.

    Postfix vs. Sendmail vs. Exim – Feature Comparison Table

    FeaturePostfixSendmailExim
    Open Source StatusFully open-source, actively maintainedOpen-source, less actively developedFully open-source, GPL licensed
    Configuration ComplexityModerate, more intuitiveHigh, complex configurationModerate to high, flexible but detailed
    Security ModelModular, security-focused designMonolithic, historically more vulnerableFlexible, strong security controls
    Performance ScalabilityHigh, efficient routingModerate, can be slowerGood, advanced queue handling
    Database IntegrationExtensive (LDAP, MySQL, PostgreSQL)Limited native supportModerate database connectivity

    Wrapping Up – Which Transfer Agent Should You Choose: Postfix, Exim, or Sendmail Mail?

    In this post, we have provided you with the pros and cons of some of the most popular MTAs; however, selecting the right MTA is critical and will depend on your specific organizational requirements, technical expertise, and infrastructure complexity.

    Postfix is the recommended solution for most scenarios as it offers an optimal balance between security, performance, and ease of configuration. However, if your organization works with legacy systems or complex email routing requirements, Sendmail remains a viable option, though it demands more advanced technical skills. Exim is also a good option for those seeking a highly customizable solution with robust routing capabilities.

    Implementing and managing Linux servers can be complex and time-consuming – that’s where RunCloud comes to the rescue.

    Our platform simplifies server management, offering one-click DNS configurations, automated security updates, and intuitive monitoring tools that take the complexity out of infrastructure management.

    Ready to simplify your server management? Sign Up for RunCloud Today.

    FAQs on Mail Transfer Agents

    Does Sendmail need an SMTP server?

    Sendmail is an SMTP server itself, functioning as both a Mail Transfer Agent (MTA) and an SMTP server simultaneously. It natively handles email routing, transmission, and delivery using the SMTP protocol without requiring a separate SMTP server.

    Does PHP use Sendmail?

    PHP can use Sendmail as a default method for sending emails on Unix and Linux systems by leveraging the built-in mail() function. The PHP configuration allows developers to specify the Sendmail path for email transmission, enabling seamless integration with the system’s mail transfer infrastructure.

    What is the main difference between postfix and prefix operators?

    This question seems unrelated to Mail Transfer Agents and more like a programming concept. In programming, prefix operators modify a variable before its value is used, while postfix operators modify a variable after its current value is used.

    What are the two roles of Simple Mail Transfer Protocol?

    Simple Mail Transfer Protocol (SMTP) primarily serves two critical roles: transferring email messages between email servers, and routing emails from a sender’s email client to the recipient’s mail server. SMTP ensures reliable, standardized communication for email transmission across different network infrastructures.

    What is the message transfer agent SMTP?

    SMTP is not a message transfer agent but a communication protocol MTAs use to send and receive email messages between servers. It defines the rules and procedures for transmitting emails, ensuring consistent and reliable communication across different email systems.

    What are the two types of user agents in email?

    The two primary types of user agents in email are the Mail User Agent (MUA), the email client interface users interact with (like Thunderbird or Outlook), and the Web-based Email User Agent, which allows users to access and manage emails through web browsers.

    What is the difference between MTA and MUA?

    A Mail Transfer Agent (MTA) is responsible for routing and delivering emails between servers using protocols such as SMTP, acting like a postal service for electronic messages. In contrast, a Mail User Agent (MUA) is the email client software that users directly interact with to compose, read, and manage their emails.