Secure consul UI with nginx

Hello,

I would like to know if it is possible to secure consul UI with nginx like this:

location / {                                                                                  
        auth_basic off;                                                                             
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;          
        proxy_pass https://127.0.0.1:{{ consul_ports_https }};                                      
      }                                                                                             
                                                                                                    
      location /ui {                                                                              
        auth_basic "Consul UI access";                                                            
        auth_basic_user_file /etc/nginx/consul.htpasswd;                                          
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;        
        proxy_pass https://127.0.0.1:{{ consul_ports_https }};                                    
      }

The url /ui is only used for the web ui or in something else ?
Is-it better to secure / ? In this case, do I need to change the config of the consul agent ?

Thanks.

And I have this error message in the log which is due to the nginx config I think:

[ERROR] agent.http: Request error: method=GET url=/v1/agent/self from=127.0.0.1:3488
0 error="Permission denied"

Hi @smutel,

You can definitely use NGINX to secure access to Consul’s UI. In addition to proxying the /ui path, you’ll also need to proxy access to the HTTP API under the /v1 prefix.

You can do this by creating an additional location entry that explicitly forwards /v1 to the Consul server, or conditionally forwards based on the HTTP Referer header. For example:

location /ui {                                                                              
  auth_basic "Consul UI access";                                                            
  auth_basic_user_file /etc/nginx/consul.htpasswd;                                          
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;        
  proxy_pass https://127.0.0.1:{{ consul_ports_https }};                                    
}

location /v1 {
  if ($http_referer ~ (/ui)) {
    auth_basic "Consul UI access";                                                            
    auth_basic_user_file /etc/nginx/consul.htpasswd;                                          
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;    
    proxy_pass http://127.0.0.1:{{ consul_ports_https }};
  }
}

When clients attempt to connect to the Consul API through this proxy, they will need to set the CONSUL_HTTP_AUTH environment variable with their correct username and password so that the consul CLI is able to authenticate with the proxy using Basic Auth.

This seems a bit odd. Is the agent configured to communicate through the NGINX proxy to reach its own API?

Thank you for your answer.

I think I have something wrong in my consul config …

On the consul servers, I have:

    "addresses": {
        "dns": "127.0.0.1",
        "grpc": "127.0.0.1",
        "http": "127.0.0.1",
        "https": "127.0.0.1"
    },
    "ports": {
        "dns": 8600,
        "grpc": -1,
        "http": 8500,
        "https": 8501,
        "serf_lan": 8301,
        "serf_wan": 8302,
        "server": 8300
    },
    "retry_join": [
        "XX.XX.XX.10",
        "XX.XX.XX.11",
        "XX.XX.XX.13"
    ],

On the consul agents, I have:

    "addresses": {
        "dns": "127.0.0.1",
        "grpc": "127.0.0.1",
        "http": "127.0.0.1",
        "https": "127.0.0.1"
    },
    "ports": {
        "dns": 8600,
        "grpc": -1,
        "http": 8500,
        "https": -1,
        "serf_lan": 8301,
        "serf_wan": 8302,
        "server": 8300
    },
    "retry_join": [
        "XX.XX.XX.10",
        "XX.XX.XX.11",
        "XX.XX.XX.13"
    ],