Cloudflare + Nginx
This page helps you put Goiabada behind Cloudflare’s proxy on a server that already runs Nginx for other sites.
Cloudflare terminates the browser’s HTTPS and connects to Nginx over HTTPS again, with a certificate Nginx holds. Nginx forwards each request to the Docker Compose file the setup wizard writes, which publishes the two servers on 127.0.0.1 alone:
Browser ── HTTPS ──▶ Cloudflare ── HTTPS ──▶ Nginx on the host ── HTTP ──▶ 127.0.0.1:9090 and :9091You need a domain on Cloudflare, a server with Docker and Nginx, two hostnames under that domain, such as auth.example.com and admin.example.com, and the setup wizard. Both hostnames must share a registrable domain: see What every method needs.
Set it up
Section titled “Set it up”-
Point both hostnames at the server, through Cloudflare. In Cloudflare’s DNS, add an
Arecord for each, with the server’s IP address, and leave them DNS only (grey cloud) until you have the certificates:auth A <your-server-ip> DNS onlyadmin A <your-server-ip> DNS onlyIf the server has an IPv6 address too, add an
AAAArecord for each with it. -
Generate and start Goiabada. Run the setup wizard, choose Production with reverse proxy, enter
https://auth.example.comandhttps://admin.example.com, then start the files it wrote, as Docker Compose describes:Terminal window docker compose up -dcurl http://127.0.0.1:9090/health # healthy -
Get the certificates and configure Nginx, as steps 3 and 4 of Reverse proxy show. Let’s Encrypt reaches the server directly while the records are DNS only.
-
Turn Cloudflare’s proxy on. Switch both records to Proxied (orange cloud). Then, under SSL/TLS, set the encryption mode to Full (strict), so Cloudflare checks Nginx’s certificate, and turn on Always Use HTTPS.
-
Have Nginx resolve Cloudflare’s addresses, so Goiabada sees each client’s address rather than Cloudflare’s. Cloudflare + Nginx on Client IP and proxy trust has the file to write.
-
Open only 80 and 443, besides SSH. With ufw, allow your SSH port first, so turning the firewall on keeps your access.
Set
SSH_PORTto the port your SSH server listens on. In an SSH session, it’s the last field of$SSH_CONNECTION:Terminal window SSH_PORT="${SSH_CONNECTION##* }"; echo "SSH port: ${SSH_PORT:-unknown}"If that prints
unknown, or you’re in asudo -iorsushell, at a console, or in a tmux, screen or mosh session, which can keep an old value, look the port up and set it yourself, such asSSH_PORT=2222.sudo ss -tlnpshows SSH listening assshd, or assystemdon a host that starts it through socket activation, as recent Ubuntu releases do, wheresystemctl cat ssh.socketshows itsListenStream.Then add the rules. Nothing changes unless
SSH_PORTis a port from 1 to 65535 written without a leading zero, and each command runs only if the one before it succeeded. It runs the same in Bash and insh:Terminal window case "$SSH_PORT" in[1-9] | [1-9][0-9] | [1-9][0-9][0-9] | [1-9][0-9][0-9][0-9] | [1-9][0-9][0-9][0-9][0-9]) port_ok=yes ;;*) port_ok=no ;;esacif [ "$port_ok" = yes ] && [ "$SSH_PORT" -le 65535 ]; thensudo ufw allow "$SSH_PORT"/tcp && sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw enableelseecho "SSH_PORT isn't a port from 1 to 65535; nothing was changed."fiBefore you close this session, open a second SSH connection to check that you still get in. ufw comes with Ubuntu; on Debian,
sudo apt-get install ufwfirst, or open the same ports in the firewall you use.Never open 9090 or 9091.
-
Sign in at
https://admin.example.com, as First sign-in describes. Then read the auth server’s request log,docker compose logs goiabada-authserver: theipof your request should be your own address, not Cloudflare’s.
What this setup gives you
Section titled “What this setup gives you”- Two certificates protect each request: Cloudflare’s edge certificate on the browser’s side, and the Let’s Encrypt certificate Nginx serves to Cloudflare. Full (strict) makes Cloudflare refuse an Nginx certificate that isn’t valid for the hostname.
- Renewals work with the proxy on. The Nginx configuration answers Let’s Encrypt’s challenge on both 80 and 443, where Cloudflare’s redirect to HTTPS sends it.
sudo certbot renew --dry-runchecks it. - Each server sees the client’s address, once Nginx resolves Cloudflare’s: see Client IP and proxy trust.
- The admin console reaches the auth server inside the Compose network, not through Cloudflare: see The hop to the auth server.