-
Notifications
You must be signed in to change notification settings - Fork 10
Apache Reverse Proxy Setup
Put Apache in front of a self-hosted LiveReview install, secure it with SSL via lrops.sh, and diagnose the issues most commonly hit along the way.
sudo apt update && sudo apt install -y apache2
sudo a2enmod proxy proxy_http headers deflate ssl
Each module's job:
| Module | Purpose |
|---|---|
proxy |
Core reverse-proxy support |
proxy_http |
Proxying to http:// backends |
headers |
Setting security headers and forwarded-request headers |
deflate |
Compressing API (JSON) responses |
ssl |
HTTPS support (needed once you set up SSL) |
lrops.sh already extracted a ready-made Apache config during install, at $LIVEREVIEW_INSTALL_DIR/config/apache.conf.example. It correctly splits traffic between the frontend and backend, sets security headers, upload limits, and long timeouts for reviews — use it instead of writing one by hand.
sudo cp ~/livereview/config/apache.conf.example /etc/apache2/sites-available/livereview.conf
sudo a2ensite livereview
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
sudo systemctl restart apache2
Don't skip
a2dissite 000-default.conf. Apache's default site otherwise wins overlivereview.conffor any request that doesn't match a specificServerName— including plain IP-address access. Skipping this step is why you'd see Ubuntu's "Apache2 Default Page" instead of LiveReview.
Substitute it into the copied vhost file:
sudo sed -i 's/your-domain.com/yourdomain.com/g' /etc/apache2/sites-available/livereview.conf
sudo systemctl reload apache2
If you're testing with a bare IP address (no domain), skip this step entirely — Apache only needs ServerName to choose between multiple vhosts sharing a port. With just one vhost active, it's used for every request regardless of what ServerName says.
This matters even for a working reverse proxy: in demo mode, LiveReview hardcodes its API URL to http://localhost:<port>, which only works when the browser and server are the same machine. Behind Apache, from any other machine, that breaks all API calls even though the page loads.
lrops.sh set-mode production
Apache being configured correctly doesn't help if the firewall blocks the ports it listens on. This is the single most common cause of "the site won't load."
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp # only needed once you set up SSL
sudo ufw status
If you're on a cloud provider (DigitalOcean, AWS, etc.), also check for a separate cloud firewall attached to the server — those exist independently of
ufwand block traffic before it even reaches the box.
lrops.sh automates certificate issuance and vhost reconfiguration end-to-end via setup-ssl.
Before running it:
- Your domain's DNS A record must already point at this server's IP — Let's Encrypt verifies ownership by reaching the server at that domain.
- Port
443must be open (see Firewall above).
Run it:
sudo lrops.sh setup-ssl yourdomain.com you@example.com
You'll be prompted to choose which reverse proxy is in use — select Apache. lrops.sh then:
- Obtains a certificate via
certbot certonly --standalone(briefly stopping Apache to bind port 80 for validation) - Sets up automatic renewal via cron
- Copies a fresh
apache.conf.exampleinto place, substitutes your domain, and uncomments the:443HTTPS block - Enables the needed modules and reloads Apache
- Verifies HTTPS actually answers, both locally and publicly
The email argument isn't optional in practice — without it,
certbotprompts interactively for one, and that prompt doesn't handle being skipped or cancelled cleanly. Always pass an email.
Once complete, https://yourdomain.com should be live.
Almost always a firewall issue, not an Apache configuration problem. Check, in order:
curl -I http://localhost/ # 1. Does Apache serve it locally?
sudo ss -tlnp | grep :80 # 2. Is Apache listening on 0.0.0.0, not just 127.0.0.1?
sudo ufw status # 3. Is port 80 actually allowed?
If step 1 and 2 look fine but the site is still unreachable from outside, it's the firewall (ufw, or a cloud provider's separate firewall) — see Firewall.
For a one-shot diagnostic covering all of this at once:
lrops.sh doctor
The default site is still enabled and winning over livereview.conf. Fix:
sudo a2dissite 000-default.conf
sudo systemctl reload apache2
Confirm only your site is active:
sudo apache2ctl -S
ls /etc/apache2/sites-enabled/
Two known traps in hand-edited or older Apache configs:
-
LimitRequestBody 104857600 # 100MB— Apache doesn't support a trailing# commenton a directive line; everything after the value is parsed as extra arguments. Put the comment on its own line above instead. -
ProxySetHeader ...— not a real Apache directive (it doesn't exist;mod_headers's actual directive isRequestHeader set). If you see "Invalid command 'ProxySetHeader'", that's the cause.
Both are already fixed in the current apache.conf.example template — re-copy it fresh if your install predates the fix:
sudo cp ~/livereview/config/apache.conf.example /etc/apache2/sites-available/livereview.conf
sudo apache2ctl configtest
You're likely still in demo mode. See Switch LiveReview to production mode — demo mode hardcodes the API URL to localhost, which breaks once the app is accessed through a reverse proxy from any other machine.
lrops.sh set-mode production
Hard-refresh the browser afterward (the old page may have cached the broken API URL in memory).
You ran it without the email argument, so certbot fell back to an interactive prompt that doesn't handle non-interactive input cleanly. Re-run with an email:
sudo lrops.sh setup-ssl yourdomain.com you@example.com
Almost always DNS or port 443, not Apache. Check:
dig yourdomain.com # does it resolve to this server's IP?
curl -s ifconfig.me # what IS this server's IP?
sudo ufw status # is 443 open?
All three must line up before certbot can succeed.