# Nginx Proxy

Instead of using xpra's builtin proxy server, the apache http server can be configured as a single point of entry, on a single port.
Just like xpra's proxy, the apache proxy can provide multiple sessions, potentially on multiple remote backend servers.

This works well with both the html5 client and the regular xpra client with `ws://` and `wss://` URLs.

## SSL

In these examples, it may be useful to have SSL certificates ready to use.
Having mkcert installed can help to ensure that the certificates generated are trusted locally.
If your package manager did not create any certificates when you installed the xpra server, you can do so now:

    sudo /usr/bin/xpra setup-ssl

This command will not overwrite any existing certificates.

## Basic Configuration

show

### Create the config

    cat > /usr/share/nginx/xpra-basic.conf << EOF
    events {
    }

    http {

        map $http_upgrade $connection_upgrade {
            default upgrade;
            ''    close;
        }

        server {
            listen 443 ssl;
            listen 80;

            root /usr/share/xpra/www;

            ssl_certificate /etc/xpra/ssl/ssl-cert.pem;
            ssl_certificate_key /etc/xpra/ssl/key.pem;

            location / {
                proxy_pass http://127.0.0.1:10000;

                proxy_http_version 1.1;
                proxy_buffering off;
                proxy_cache_bypass $http_upgrade;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_set_header Host $host;
            }
        }
    }
    EOF

### Start nginx:

    sudo nginx -c xpra-basic.conf

### Xpra server

Start an xpra server on port 10000:

    xpra seamless --bind-tcp=0.0.0.0:10000 --start=xterm

(beware: authentication is turned off for simplicity)

Then you can simply open your browser to connect to the session via the nginx proxy:

    xdg-open http://localhost/

Or even via https if the certificates are configured correctly:

    xdg-open https://localhost/

## Multiple Servers

show

This example configuration maps different URLs to servers on different ports.

    http {

        map $http_upgrade $connection_upgrade {
            default upgrade;
            ''    close;
        }

        server {
            listen 443 ssl;
            listen 80;

            root /usr/share/xpra/www;

            ssl_certificate /etc/xpra/ssl/ssl-cert.pem;
            ssl_certificate_key /etc/xpra/ssl/key.pem;

            proxy_redirect off;
            proxy_http_version 1.1;
            proxy_buffering off;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            location /xpra1 {
                rewrite /xpra1/(.*) /$1 break;
                proxy_pass http://127.0.0.1:10000;
            }
            location /xpra2 {
                rewrite /xpra2/(.*) /$1 break;
                proxy_pass http://127.0.0.1:10001;
            }
        }
    }

## Advanced Options

show

Most of the options below can make the connection more robust and should be applied to the `location` matching the xpra server being proxied for.
However, increasing the timeouts should not be necessary as the xpra protocol already includes its own ping packets every few seconds, which should ensure that the connection is kept alive.

These options may even introduce new issues, by making it harder for nginx to detect broken connections.

| Option | Recommended value | Purpose | |--------------------------------------------------------------------------------------------------------------|----------------------------------------|-----------------------------------------------------------------------------------------------------------------------| | `proxy_connect_timeout` | unchanged | a lower value can be used to fail faster when xpra servers are already started and initial connections should be fast | | `proxy_read_timeout` | 10d | or more, increase this option to prevent unexpected disconnections | | `proxy_send_timeout` | 10d | same as `proxy_read_timeout` | | `limit_except` | `limit_except GET POST { deny all; }` | prevent unwanted http requests from reaching xpra's http server | | `proxy_socket_keepalive` | unchanged | should not be needed, can be enabled | | `tcp_nodelay` | on | keep the latency low, this should already be enabled automatically for WebSocket connections | | `tcp_nopush` | off | may introduce unwanted latency | | `proxy_no_cache` | `1` | prevent caching of the xpra-html5 client | | `proxy_cache_bypass` | `1` | prevent caching of the xpra-html5 client |

The following options should not need to be modified:

- `client_max_body_size` - does not affect WebSocket connections and all the xpra clients use chunked transfers anyway - as for the xpra-html5 client itself, it is orders of magnitude smaller than the default limit
- `proxy_intercept_errors` - once a WebSocket connection is established, http error codes are not used
- `keepalive_timeout` - see `proxy_socket_keepalive` above
- `send_timeout` - see `proxy_send_timeout` above
- `proxy_buffering` - should not affect WebSocket connections
- `proxy_buffering` `proxy_request_buffering` - let nginx handle http requests, this does not affect connections upgraded to WebSocket