Allow CORS for Virtualmin Remote API

I’m developing a frontend with Angular 7 and consumes Virtualmin Remote API but my GET requests are getting denied because of CORS policy.

With Postman or cURL the GET request works fine (also the OPTIONS request) but not with Angular HTTP, it’s possible to set CORS policy in the Virtualmin Remote API? How?


My headers are:

"Access-Control-Allow-Origin": "*",
"Content-Type": "application/json",
"cache-control": "no-cache",
Authorization: "Basic XXXXXXXXXXXXXXXXXXX"

I’m trying to get all the domains, https://example.com:10000/virtual-server/remote.cgi?json=1&program=list-domains

The issue you’re encountering with CORS (Cross-Origin Resource Sharing) is common when interacting with APIs via a browser-based frontend like Angular. While tools like Postman or curl bypass CORS restrictions, browsers enforce them for security reasons.

The Virtualmin Remote API does not natively include CORS support. However, you can address this issue by implementing a workaround. Here’s how you can enable CORS for the Virtualmin Remote API:

Option 1: Configure a Proxy Server

A common and straightforward solution is to set up a proxy server that sits between your Angular application and the Virtualmin Remote API. The proxy server can add the necessary CORS headers.

Steps:

  1. Install and Configure Nginx or Apache:
  • Install Nginx or Apache on the server where your Angular application is hosted or any intermediary server.
  • Configure it to proxy requests to the Virtualmin API.
  1. Nginx Configuration: Add the following to your Nginx configuration file:
server {
    listen 8080; # or any other available port
    server_name localhost;

    location /api/ {
        proxy_pass https://example.com:10000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # Add CORS headers
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization, Content-Type";
    }
}

Restart Nginx:

sudo systemctl restart nginx
  1. Update your Angular service to call the proxy server instead of the Virtualmin API directly:
this.http.get('http://localhost:8080/api/virtual-server/remote.cgi?json=1&program=list-domains')
    .subscribe(response => console.log(response));

Option 2: Add CORS Headers via Virtualmin’s Webmin Configuration

Virtualmin (Webmin) runs on its own web server, and you can configure it to send CORS headers by editing its settings.

Steps:

  1. SSH into the server running Virtualmin.
  2. Open the Webmin configuration file:
sudo nano /etc/webmin/miniserv.conf
  1. Add the following lines to enable CORS headers:
add_header=Access-Control-Allow-Origin: *
add_header=Access-Control-Allow-Methods: GET, POST, OPTIONS
add_header=Access-Control-Allow-Headers: Authorization, Content-Type
  1. Restart Webmin:
sudo systemctl restart webmin

This approach directly modifies the Virtualmin web server to support CORS.

Option 3: Use a Server-Side Middleware

If you have backend middleware (e.g., Node.js, Python, or PHP), you can create a server-side proxy to handle API requests and add CORS headers.

Example (Node.js with Express):

  1. Install Express:
npm install express cors
  1. Create a proxy script:
const express = require('express');
const cors = require('cors');
const axios = require('axios');

const app = express();
app.use(cors());
app.use(express.json());

app.get('/api/list-domains', async (req, res) => {
    try {
        const response = await axios.get('https://example.com:10000/virtual-server/remote.cgi?json=1&program=list-domains', {
            headers: {
                Authorization: 'Basic XXXXXXXXXXXXXXXXXXX',
                'Content-Type': 'application/json'
            }
        });
        res.json(response.data);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.listen(3000, () => console.log('Server running on port 3000'));
  1. Start the server and update Angular to call http://localhost:3000/api/list-domains.

Option 4: Modify Browser Behavior (Development Only)

During development, you can disable browser CORS enforcement by launching the browser with specific flags. This is not recommended for production.

Example (Google Chrome):

Launch Chrome with the following command:

google-chrome --disable-web-security --user-data-dir="/tmp/chrome_dev"

Conclusion

The most robust solutions are either Option 1 (Proxy Server) or Option 2 (Webmin Configuration), as they address the issue at the server level without compromising security. For development purposes, you can also use Option 4 temporarily to debug your Angular application.