Expose with HTTPS (Reverse Proxy)
By default ORDS uses plain HTTP on a high port, for example http://your-server:8181/ords/.
To reach your environment over a real domain with a valid TLS certificate, run nginx on the host. nginx works as a reverse proxy. It terminates TLS and sends the requests to the ORDS container. Let’s Encrypt gives you the certificates at no cost, and certbot renews them automatically.
What you install
Section titled “What you install”Browser ──HTTPS(443)──▶ nginx (host) ──HTTP(8181)──▶ ORDS container ──▶ APEX ◀─HTTP(80)──▶ redirect to HTTPS- nginx listens on port
80and port443on the host. - Port
80serves the ACME challenge for new and renewed certificates. It redirects all other requests to HTTPS. - Port
443terminates TLS and proxies/ords/and/i/to the ORDS HTTP connector on127.0.0.1:8181.
Prerequisites
Section titled “Prerequisites”-
A server that runs your
uc-local-apex-devstack. The ORDS HTTP port must be published on the host (8181by default). Show it withdocker psorpodman ps. -
root / sudo access on the host.
-
A domain name with a DNS
Arecord that points to the public IP address of the server. Add anAAAArecord for IPv6. Make sure that the name resolves before you start:Terminal window getent hosts your-domain.example.com -
Ports 80 and 443 open to the internet. If a firewall runs on the host, open the ports:
Terminal window # firewalld (RHEL/Rocky/Alma)firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reload# ufw (Debian/Ubuntu)ufw allow 80,443/tcp
-
Install nginx and certbot
Terminal window dnf install -y epel-releasednf install -y nginx certbot -
Create the ACME webroot and a bootstrap config
nginx must run, because certbot proves the ownership of the domain over port 80. Start with a small configuration that serves the challenge only:
Terminal window mkdir -p /var/www/certbotCreate
/etc/nginx/conf.d/apex.conf. Replaceyour-domain.example.comin every line:server {listen 80;listen [::]:80;server_name your-domain.example.com;location /.well-known/acme-challenge/ {root /var/www/certbot;}location / {return 404;}}Terminal window nginx -t && systemctl enable --now nginx -
Obtain the certificate
Terminal window certbot certonly --webroot -w /var/www/certbot \-d your-domain.example.com \--non-interactive --agree-tos \-m you@example.comAfter success the certificate is in
/etc/letsencrypt/live/your-domain.example.com/. -
Write the full reverse-proxy config
Replace the content of
/etc/nginx/conf.d/apex.confwith these two server blocks. Change the domain. If your ORDS HTTP port is not8181, also change theproxy_passport:# HTTP: ACME challenge + redirect everything else to HTTPSserver {listen 80;listen [::]:80;server_name your-domain.example.com;location /.well-known/acme-challenge/ {root /var/www/certbot;}location / {return 301 https://$host$request_uri;}}# HTTPS: TLS termination, reverse proxy to ORDSserver {listen 443 ssl;listen [::]:443 ssl;http2 on;server_name your-domain.example.com;client_max_body_size 50m;ssl_certificate /etc/letsencrypt/live/your-domain.example.com/fullchain.pem;ssl_certificate_key /etc/letsencrypt/live/your-domain.example.com/privkey.pem;# Modern TLS settingsssl_protocols TLSv1.2 TLSv1.3;ssl_prefer_server_ciphers off;ssl_session_timeout 1d;ssl_session_cache shared:SSL:10m;ssl_session_tickets off;access_log /var/log/nginx/apex_access.log;error_log /var/log/nginx/apex_error.log;# Send the bare domain to ORDSlocation = / {return 301 https://$host/ords/;}# ORDS / APEXlocation /ords/ {proxy_pass http://127.0.0.1:8181/ords/;proxy_http_version 1.1;proxy_set_header Connection "";proxy_set_header Origin "";# ORDS builds absolute redirect URLs from the Host header and keeps the# http:// scheme — rewrite them back to https so browsers don't bounce# through plain HTTP. See "Troubleshooting" below.proxy_redirect ~^http://[^/]+/(.*)$ https://your-domain.example.com/$1;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_connect_timeout 600;proxy_send_timeout 600;proxy_read_timeout 600;send_timeout 600;}# APEX static images (/i/)location /i/ {proxy_pass http://127.0.0.1:8181/i/;proxy_set_header X-Forwarded-Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}Terminal window nginx -t && systemctl reload nginx -
Make renewals reload nginx automatically
certbot renews the certificates on a schedule. nginx serves the old certificate until it reloads. Add a deploy hook, so nginx reloads after every renewal:
mkdir -p /etc/letsencrypt/renewal-hooks/deploycat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh <<'EOF'#!/bin/shsystemctl reload nginxEOFchmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh -
Enable and verify auto-renewal
The certbot package includes a systemd timer. Make sure that the timer is active. Then do a test renewal. The test uses the staging server and changes nothing:
Terminal window systemctl enable --now certbot-renew.timersystemctl list-timers certbot-renew.timer # shows the next runcertbot renew --dry-run # should report success
Verify
Section titled “Verify”# HTTP is redirected to HTTPScurl -sI http://your-domain.example.com/ords/ | grep -i location # -> https://.../ords/
# HTTPS reaches ORDS (302 to the landing/sign-in page)curl -sI https://your-domain.example.com/ords/
# Static APEX assets load over HTTPScurl -so /dev/null -w "%{http_code}\n" https://your-domain.example.com/i/apex_ui/css/Core.min.cssThen open https://your-domain.example.com/ords/ in a browser. The APEX sign-in page opens, and the browser shows a valid padlock.
Troubleshooting
Section titled “Troubleshooting”nginx -tfails onoptions-ssl-nginx.conf— this helper file exists only with the nginx installer plugin of certbot. This guide creates the certificates withcertonly, so the configuration above contains the TLS directives directly. Do notincludethat file.- certbot cannot reach the domain — make sure that DNS points to the server (
getent hosts your-domain.example.com). Make sure that ports 80 and 443 are open in the firewall of the operating system. Open them in the security group of your cloud provider too. - 502 Bad Gateway — nginx cannot reach ORDS at the
proxy_passtarget. Make sure that the container runs (docker psorpodman ps). Make sure that the port is correct (curl -sI http://127.0.0.1:8181/ords/on the host). - Redirect loop with
curl— APEX adds a?session=ID at the first request and expects a cookie in return. Use a cookie jar (curl -c cj.txt -b cj.txt -L ...). A browser does this automatically.