|
1 | 1 | --- |
2 | | -title: Expose Omni with Nginx (HTTPS) |
3 | | -description: Configure Nginx as an HTTPS reverse proxy for Omni |
| 2 | +title: "Expose Omni with Nginx (HTTPS)" |
| 3 | +description: "Configure Nginx as an HTTPS reverse proxy for on-premises Omni deployments." |
4 | 4 | --- |
5 | 5 |
|
6 | | -### Omni deployment configuration |
| 6 | +This guide assumes Omni is deployed following the [Run Omni On-Prem](./run-omni-on-prem) guide. However, the flags used in the **Deploy Omni** section are modified as shown in **Step 1** so that Nginx handles all public traffic. |
| 7 | + |
| 8 | +In this setup, Nginx runs in front of Omni and routes traffic to three public endpoints: |
| 9 | + |
| 10 | +| Endpoint | Purpose | |
| 11 | +| --- | --- | |
| 12 | +| `https://$OMNI_DOMAIN_NAME` | Omni UI and main API | |
| 13 | +| `https://api.$OMNI_DOMAIN_NAME` | SideroLink machine API | |
| 14 | +| `https://kube.$OMNI_DOMAIN_NAME` | Kubernetes proxy | |
| 15 | + |
| 16 | +Omni itself listens only on localhost, while Nginx handles TLS termination and all external traffic. |
| 17 | + |
| 18 | +## Prerequisites |
| 19 | + |
| 20 | +Before proceeding, ensure the following: |
| 21 | + |
| 22 | +- Install Nginx on the machine serving public traffic |
| 23 | +- Open ports 80 and 443 on the Nginx machine |
| 24 | +- Create the following DNS A records and point them to the public IP address of the Nginx machine: |
| 25 | + - `<omni-domain-name>` |
| 26 | + - `api.<omni-domain-name>` |
| 27 | + - `kube.<omni-domain-name>` |
| 28 | + |
| 29 | +Replace `<omni-domain-name>` with your Omni domain name (for example, `omni.example.com`) in the DNS records above and throughout this guide. |
| 30 | + |
| 31 | +**If Nginx and Omni run on the same machine**, no additional network configuration is required. The `127.0.0.1` addresses in the Nginx configuration proxy traffic to Omni over localhost. |
| 32 | + |
| 33 | +**If Nginx and Omni run on separate machines:** |
| 34 | +- The Omni machine must be reachable from the Nginx machine over the internal network. |
| 35 | +- Open ports 8080, 8090, and 8100 on the Omni machine |
| 36 | +- Replace `127.0.0.1` in the Nginx configuration file with the internal IP address of the Omni machine |
| 37 | + |
| 38 | +## Step 1: Start Omni with the Nginx Flags |
| 39 | + |
| 40 | +Follow the [Run Omni On-Prem](./run-omni-on-prem) guide to deploy Omni on-prem. |
| 41 | +Before starting the Omni instance using either `docker run` or `docker compose`, complete the following steps. |
| 42 | + |
| 43 | +1. Verify that the required environment variables from the on-prem guide are set in your shell: |
| 44 | + |
| 45 | + ```bash |
| 46 | + echo $OMNI_DOMAIN_NAME |
| 47 | + echo $OMNI_ACCOUNT_UUID |
| 48 | + ``` |
| 49 | + |
| 50 | +2. If any are variables are missing, export them now: |
| 51 | + |
| 52 | + ```bash |
| 53 | + export OMNI_DOMAIN_NAME=<omni-domain> # e.g omni.example.com |
| 54 | + export OMNI_ACCOUNT_UUID=<account-id> # your Omni account ID |
| 55 | + ``` |
| 56 | + |
| 57 | +3. Start Omni using the following flags. Remember to include the authentication flags required by your authentication provider. For more details, see the [configure authentication guide](./run-omni-on-prem#configure-authentication): |
| 58 | + |
| 59 | + ```bash |
| 60 | + --name=$OMNI_NAME \ |
| 61 | + --private-key-source=file:///omni.asc \ |
| 62 | + --bind-addr=127.0.0.1:8080 \ |
| 63 | + --advertised-api-url=https://$OMNI_DOMAIN_NAME/ \ |
| 64 | + --siderolink-api-bind-addr=127.0.0.1:8090 \ |
| 65 | + --siderolink-api-advertised-url=https://api.$OMNI_DOMAIN_NAME:443 \ |
| 66 | + --k8s-proxy-bind-addr=127.0.0.1:8100 \ |
| 67 | + --advertised-kubernetes-proxy-url=https://kube.$OMNI_DOMAIN_NAME/ \ |
| 68 | + --account-id=$OMNI_ACCOUNT_UUID |
| 69 | + # Also add the authentication flags according to your setup |
| 70 | + ``` |
| 71 | + |
| 72 | + <Info>Authentication flags are not included here. Add the appropriate flags for your auth provider as described in the [authentication configuration guide](./run-omni-on-prem#configure-authentication). </Info> |
| 73 | + |
| 74 | + **Example:** Starting an Omni instance might look similar to the following: |
| 75 | + |
| 76 | + ```bash |
| 77 | + docker run \ |
| 78 | + --net=host \ |
| 79 | + --cap-add=NET_ADMIN \ |
| 80 | + --device /dev/net/tun \ |
| 81 | + -v $PWD/etcd:/_out/etcd \ |
| 82 | + -v $PWD/omni.asc:/omni.asc \ |
| 83 | + ghcr.io/siderolabs/omni:<tag> \ |
| 84 | + --name=$OMNI_NAME \ |
| 85 | + --private-key-source=file:///omni.asc \ |
| 86 | + --bind-addr=127.0.0.1:8080 \ |
| 87 | + --advertised-api-url=https://$OMNI_DOMAIN_NAME/ \ |
| 88 | + --siderolink-api-bind-addr=127.0.0.1:8090 \ |
| 89 | + --siderolink-api-advertised-url=https://api.$OMNI_DOMAIN_NAME:443 \ |
| 90 | + --k8s-proxy-bind-addr=127.0.0.1:8100 \ |
| 91 | + --advertised-kubernetes-proxy-url=https://kube.$OMNI_DOMAIN_NAME/ \ |
| 92 | + --account-id=$OMNI_ACCOUNT_UUID \ |
| 93 | + --auth-auth0-enabled=true \ |
| 94 | + --auth-auth0-domain=<Auth0 domain> \ |
| 95 | + --auth-auth0-client-id=<Auth0 client ID> \ |
| 96 | + --initial-users=<email address> |
| 97 | + ``` |
| 98 | +## Step 2: Provision TLS Certificates |
| 99 | + |
| 100 | +Use `acme` or `certbot` to generate TLS certificates for all three subdomains. **Step 3** expects the certificates at the following paths. If your certificates are stored elsewhere, update the paths in the Nginx config accordingly. |
| 101 | + |
| 102 | +| Subdomain | Certificate path | |
| 103 | +|---|---| |
| 104 | +| `$OMNI_DOMAIN_NAME` | `/var/lib/acme/omni/` | |
| 105 | +| `api.$OMNI_DOMAIN_NAME` | `/var/lib/acme/omni_api/` | |
| 106 | +| `kube.$OMNI_DOMAIN_NAME` | `/var/lib/acme/omni_kube/` | |
| 107 | + |
| 108 | +## Step 3: Apply the Nginx Configuration |
| 109 | + |
| 110 | +Run the following command to write the Nginx config: |
| 111 | + |
| 112 | +```sh |
| 113 | +cat <<EOF > /etc/nginx/nginx.conf |
| 114 | +http { |
| 115 | + proxy_redirect off; |
| 116 | + proxy_http_version 1.1; |
| 117 | + proxy_connect_timeout 60s; |
| 118 | + # Omni requires long timeouts for long-lived connections |
| 119 | + proxy_send_timeout 1h; |
| 120 | + proxy_read_timeout 1h; |
| 121 | +
|
| 122 | + # Used for WebSocket proxying |
| 123 | + map \$http_upgrade \$connection_upgrade { |
| 124 | + default upgrade; |
| 125 | + '' close; |
| 126 | + } |
| 127 | +
|
| 128 | + # Redirect HTTP to HTTPS |
| 129 | + server { |
| 130 | + listen 0.0.0.0:80; |
| 131 | + listen [::0]:80; |
| 132 | + server_name $OMNI_DOMAIN_NAME; |
| 133 | + location / { |
| 134 | + return 301 https://\$host\$request_uri; |
| 135 | + } |
| 136 | + } |
| 137 | +
|
| 138 | + map \$http_content_type \$is_grpc { |
| 139 | + default 0; |
| 140 | + "application/grpc" 1; |
| 141 | + } |
| 142 | +
|
| 143 | + # Main Omni API — routes gRPC and HTTP traffic |
| 144 | + server { |
| 145 | + listen 0.0.0.0:443 http2 ssl; |
| 146 | + listen [::0]:443 http2 ssl; |
| 147 | + server_name $OMNI_DOMAIN_NAME; |
| 148 | + ssl_certificate /var/lib/acme/omni/fullchain.pem; |
| 149 | + ssl_certificate_key /var/lib/acme/omni/key.pem; |
| 150 | + ssl_trusted_certificate /var/lib/acme/omni/chain.pem; |
| 151 | +
|
| 152 | + location / { |
| 153 | + error_page 418 = @grpc; |
| 154 | + error_page 419 = @http; |
| 155 | + if (\$is_grpc) { |
| 156 | + return 418; |
| 157 | + } |
| 158 | + return 419; |
| 159 | + } |
| 160 | +
|
| 161 | + location @grpc { |
| 162 | + # Long timeouts required for long-lived gRPC stream connections |
| 163 | + grpc_read_timeout 1h; |
| 164 | + grpc_send_timeout 1h; |
| 165 | + grpc_pass grpc://127.0.0.1:8080; |
| 166 | + } |
| 167 | +
|
| 168 | + location @http { |
| 169 | + proxy_pass http://127.0.0.1:8080; |
| 170 | + proxy_set_header Upgrade \$http_upgrade; |
| 171 | + proxy_set_header Connection \$connection_upgrade; |
| 172 | + } |
| 173 | + } |
| 174 | +
|
| 175 | + # SideroLink (Machine) API |
| 176 | + server { |
| 177 | + listen 0.0.0.0:443 http2 ssl; |
| 178 | + listen [::0]:443 http2 ssl; |
| 179 | + server_name api.$OMNI_DOMAIN_NAME; |
| 180 | + ssl_certificate /var/lib/acme/omni_api/fullchain.pem; |
| 181 | + ssl_certificate_key /var/lib/acme/omni_api/key.pem; |
| 182 | + ssl_trusted_certificate /var/lib/acme/omni_api/chain.pem; |
| 183 | +
|
| 184 | + location / { |
| 185 | + # Long timeouts required for long-lived gRPC stream connections |
| 186 | + grpc_read_timeout 1h; |
| 187 | + grpc_send_timeout 1h; |
| 188 | + grpc_pass grpc://127.0.0.1:8090; |
| 189 | + } |
| 190 | + } |
| 191 | +
|
| 192 | + # Kubernetes Proxy API |
| 193 | + server { |
| 194 | + listen 0.0.0.0:443 http2 ssl; |
| 195 | + listen [::0]:443 http2 ssl; |
| 196 | + server_name kube.$OMNI_DOMAIN_NAME; |
| 197 | + ssl_certificate /var/lib/acme/omni_kube/fullchain.pem; |
| 198 | + ssl_certificate_key /var/lib/acme/omni_kube/key.pem; |
| 199 | + ssl_trusted_certificate /var/lib/acme/omni_kube/chain.pem; |
| 200 | +
|
| 201 | + location / { |
| 202 | + proxy_pass http://127.0.0.1:8100; |
| 203 | + proxy_set_header Upgrade \$http_upgrade; |
| 204 | + proxy_set_header Connection \$connection_upgrade; |
| 205 | + } |
| 206 | + } |
| 207 | +} |
| 208 | +EOF |
| 209 | +``` |
7 | 210 |
|
8 | | -You need to deploy an omni instance the [how to deploy omni on prem guide](./run-omni-on-prem.mdx), with the following flags set: |
| 211 | +Then reload Nginx: |
9 | 212 |
|
10 | 213 | ```bash |
11 | | ---name=$OMNI_NAME |
12 | | ---private-key-source=file:///omni.asc |
13 | | ---bind-addr=127.0.0.1:8080 |
14 | | ---advertised-api-url=https://$OMNI_DOMAIN/ |
15 | | ---siderolink-api-bind-addr=127.0.0.1:8090 |
16 | | ---siderolink-api-advertised-url=https://api.$OMNI_DOMAIN:443 |
17 | | ---k8s-proxy-bind-addr=127.0.0.1:8100 |
18 | | ---advertised-kubernetes-proxy-url=https://kube.$OMNI_DOMAIN/ |
19 | | ---account-id=$OMNI_UUID |
20 | | -## Also add the authentication flags according to your setup |
| 214 | +nginx -t && systemctl reload nginx |
21 | 215 | ``` |
22 | 216 |
|
23 | | -### Certificates |
24 | | - |
25 | | -You can use acme or certbot to generate certificates for your domain. In the following nginx config, the are stored in `/var/lib/acme/omni/` and `/var/lib/acme/omni_api/` and `/var/lib/acme/omni_kube/`. Make sure to change the paths to your own or to output the certificates to those paths. |
26 | | - |
27 | | -### Nginx configuration |
28 | | - |
29 | | -Use the following configuration to expose omni with nginx. Make sure to change the domain name (`$OMNI_DOMAIN`) to your own domain and to update the certificate paths if applicable. |
30 | | - |
31 | | -```nginx |
32 | | -http { |
33 | | - proxy_redirect off; |
34 | | - proxy_http_version 1.1; |
35 | | -
|
36 | | - proxy_connect_timeout 60s; |
37 | | -
|
38 | | - # Omni needs long timeouts for the long-lived connections |
39 | | - proxy_send_timeout 1h; |
40 | | - proxy_read_timeout 1h; |
41 | | -
|
42 | | - # $connection_upgrade is used for websocket proxying |
43 | | - map $http_upgrade $connection_upgrade { |
44 | | - default upgrade; |
45 | | - '' close; |
46 | | - } |
47 | | -
|
48 | | - # Omni HTTPS redirection |
49 | | - server { |
50 | | - listen 0.0.0.0:80; |
51 | | - listen [::0]:80; |
52 | | - server_name $OMNI_DOMAIN; |
53 | | - location / { |
54 | | - return 301 https://$host$request_uri; |
55 | | - } |
56 | | - } |
57 | | -
|
58 | | - map $http_content_type $is_grpc { |
59 | | - default 0; |
60 | | - "application/grpc" 1; |
61 | | - } |
62 | | -
|
63 | | - # Omni main API |
64 | | - server { |
65 | | - listen 0.0.0.0:443 http2 ssl; |
66 | | - listen [::0]:443 http2 ssl; |
67 | | - server_name $OMNI_DOMAIN; |
68 | | - ssl_certificate /var/lib/acme/omni/fullchain.pem; |
69 | | - ssl_certificate_key /var/lib/acme/omni/key.pem; |
70 | | - ssl_trusted_certificate /var/lib/acme/omni/chain.pem; |
71 | | - location / { |
72 | | - error_page 418 = @grpc; |
73 | | - error_page 419 = @http; |
74 | | -
|
75 | | - if ($is_grpc) { |
76 | | - return 418; |
77 | | - } |
78 | | -
|
79 | | - return 419; |
80 | | - } |
81 | | -
|
82 | | - # Omni main GRPC API |
83 | | - location @grpc { |
84 | | - # Omni needs long timeouts for the long-lived GRPC stream connections |
85 | | - grpc_read_timeout 1h; |
86 | | - grpc_send_timeout 1h; |
87 | | - grpc_pass grpc://127.0.0.1:8080; |
88 | | - } |
89 | | -
|
90 | | - # Omni main HTTP API |
91 | | - location @http { |
92 | | - proxy_pass http://127.0.0.1:8080; |
93 | | - proxy_set_header Upgrade $http_upgrade; |
94 | | - proxy_set_header Connection $connection_upgrade; |
95 | | - } |
96 | | - } |
97 | | -
|
98 | | - # Omni SideroLink (a.k.a. Machine) API |
99 | | - server { |
100 | | - listen 0.0.0.0:443 http2 ssl; |
101 | | - listen [::0]:443 http2 ssl; |
102 | | - server_name api.$OMNI_DOMAIN; |
103 | | - ssl_certificate /var/lib/acme/omni_api/fullchain.pem; |
104 | | - ssl_certificate_key /var/lib/acme/omni_api/key.pem; |
105 | | - ssl_trusted_certificate /var/lib/acme/omni_api/chain.pem; |
106 | | - location / { |
107 | | - # Omni needs long timeouts for the long-lived GRPC stream connections |
108 | | - grpc_read_timeout 1h; |
109 | | - grpc_send_timeout 1h; |
110 | | - grpc_pass grpc://127.0.0.1:8090; |
111 | | - } |
112 | | - } |
113 | | -
|
114 | | - # Omni Kube API |
115 | | - server { |
116 | | - listen 0.0.0.0:443 http2 ssl; |
117 | | - listen [::0]:443 http2 ssl; |
118 | | - server_name kube.$OMNI_DOMAIN; |
119 | | - ssl_certificate /var/lib/acme/omni_kube/fullchain.pem; |
120 | | - ssl_certificate_key /var/lib/acme/omni_kube/key.pem; |
121 | | - ssl_trusted_certificate /var/lib/acme/omni_kube/chain.pem; |
122 | | - location / { |
123 | | - proxy_pass http://127.0.0.1:8100; |
124 | | - proxy_set_header Upgrade $http_upgrade; |
125 | | - proxy_set_header Connection $connection_upgrade; |
126 | | - } |
127 | | - } |
128 | | -} |
129 | | -``` |
| 217 | +## Endpoints |
130 | 218 |
|
131 | | -## How to use |
| 219 | +Once Nginx is running, your Omni instance is accessible at: |
132 | 220 |
|
133 | | -The omni instance will be available at `https://$OMNI_DOMAIN/`, the API at `https://api.$OMNI_DOMAIN/` and the kubernetes proxy at `https://kube.$OMNI_DOMAIN/`. |
| 221 | +| Service | URL | |
| 222 | +|---|---| |
| 223 | +| Omni UI & API | `https://$OMNI_DOMAIN_NAME/` | |
| 224 | +| SideroLink (Machine) API | `https://api.$OMNI_DOMAIN_NAME/` | |
| 225 | +| Kubernetes Proxy | `https://kube.$OMNI_DOMAIN_NAME/` | |
0 commit comments