# Add an offline page to display when Discourse is rebuilding or starting up

**URL:** https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238
**Category:** Sysadmins
**Tags:** configuring, how-to, advanced-setup
**Created:** [June 4, 2016, 8:41am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238 "2016-06-04T08:41:48Z")
**Posts on this page:** 20
**Page:** 7

<div class="post-metadata">

### Author: ![piffy](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/piffy/32/254198_2.png) [@piffy](https://meta.discourse.org/u/piffy)
#### Post date: [September 26, 2022, 5:58am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/141 "2022-09-26T05:58:23Z")

</div>

Is there an obvious reason why I can’t upload a .png \>500kb on my forum after following this guide?

I see some talk about this line ` client_max_body_size 0;` but that shouldn’t be the issue right?

**EDIT: I quickly figured it out after posting here. Needed to check ✅ `force https` in the settings. I will leave this post here in case future people have an issue**

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [September 29, 2022, 11:48am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/142 "2022-09-29T11:48:30Z")

</div>

I note that here:

> **[F5 NGINX: Built for cloud-native apps. Ready for AI traffic.](https://www.f5.com/products/nginx)**

nginx recommend disabling the `Connection: close` header as well as setting `proxy_http_version 1.1` — so something like this:

```plaintext
    proxy_http_version 1.1;
    # Disable default "Connection: close"
    proxy_set_header "Connection" "";

```

I can’t find any documentation on whether `Connection: close` has any impact on unix domain sockets, but since this documentation is also useful for running an external proxy on a separate system and I’d expect that removing the header won’t hurt, it might make sense to recommend removing it here?

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [September 30, 2022, 12:56pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/143 "2022-09-30T12:56:11Z")

</div>

If you have deployed this on a system with SELinux (enforcing), you can’t use the unix domain socket for the host to talk to the container, because even if you relabel the unix domain socket, it will be recreated without the label every time you restart the container. Instead, you’ll have to make two changes.

You will need to allow nginx to access the error pages, and switch from proxying over a unix domain socket to a port. That will cost a couple µs latency per request as the prices of running nginx with SELinux as one layer of security, but this won’t be perceptible to your users.

First, run these commands to allow nginx to make network connections and access error pages:

```plaintext
setsebool -P httpd_can_network_connect 1
semanage fcontext -a -t httpd_sys_content_t /var/www
restorecon -R -v /var/www

```

Then in your app.yaml, comment out or remove the `- "templates/web.socketed.template.yml"`, expose port 80 as a different port on the local machine and rebuild the container.

```plaintext
expose:
  - "8008:80" # http

```

Don’t use `https` here — you have terminated SSL in the external nginx, and the `X-Forwarded-Proto` header tells Discourse that the request came in via https. Make sure that port 8008 (or whatever other port you have chosen) is not exposed publicly by your firewall settings.

Then modify your external nginx configuration from proxying via `nginx.http.sock` to `http://127.0.0.1:8008` (or your chosen port) and clear the default `Connection: close` header, so that the external nginx doesn’t have to establish a new IP connection for every request.

```plaintext
...
  location / {
    proxy_pass http://127.0.0.1:8008;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    # Disable default "Connection: close"
    proxy_set_header "Connection" "";
...

```

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 7, 2022, 9:34pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/144 "2022-12-07T21:34:38Z")

</div>

> [@sam](#):
>
> Personally if I wanted the best experience
> 
> - I would add an haproxy in tcp mode container to farm reqs to either online/offline container
> - have the nginx offline container mount the same SSL volume so you don’t need to fuss with running lets encrypt in cron and simply have existing template run it
> - have a data container so I can bootstrap while online

Hey @sam (and maybe @falco). I’m tasked with cleaning up some of these #documentation:sysadmin docs. This one has very high reads and I think is one of the least helpfu.

Do you think it makes sense to write a replacement that spins up [haproxy - Official Image | Docker Hub](https://hub.docker.com/_/haproxy) and [nginx - Official Image | Docker Hub](https://hub.docker.com/_/nginx), perhaps with docker compose, making the nginx container mount the certs from the discourse container and have haproxy in tcp mode to do something like this (I’m sure this won’t work, but I presume I can figure out what will):

```plaintext
backend my_app_be
	balance roundrobin
	option httpchk HEAD /srv/status
        server discourse app:443 check
	server fallback nginx:80 check backup

```

I think that might be a workable solution that’s easier to follow than this topic. I’d then leave this one for historical purposes (and perhaps close it?) but link to the one described above.

---

<div class="post-metadata">

### Author: ![fefrei](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fefrei/32/119538_2.png) [@fefrei](https://meta.discourse.org/u/fefrei)
#### Post date: [December 7, 2022, 9:50pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/145 "2022-12-07T21:50:57Z")

</div>

Note that this topic has significant overlap with that one:

> [@Run other websites on the same machine as Discourse](https://meta.discourse.org/t/run-other-websites-on-the-same-machine-as-discourse/17247):
>
> @pfaffman edited this heavily 2022.02.24. Blame me if it’s broken. If you want to run other websites on the same machine as Discourse, you need to set up an extra NGINX or HAProxy proxy in front of the Docker container. NOTE: This is for advanced admins This guide assumes you already have Discourse working - if you don’t, it may be hard to tell whether or not the configuration is working. You cannot use ./discourse-setup to set up Discourse if another server is using port 80 or 443. You will…

That topic has received significant updating lately (that increased the overlap even more). Maybe it makes sense to merge the offline-page part from here to there as a note (since it’s easy to add if you already run a separate Nginx instance), then mark this one as deprecated (linking to the alternatives)?

Your suggested HAProxy topic would still make sense in addition, as the default way to go for people _not_ wanting to install a front Nginx for other reasons.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 7, 2022, 10:08pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/146 "2022-12-07T22:08:15Z")

</div>

> [@fefrei](#):
>
> That topic has received significant updating lately (that increased the overlap even more). Maybe it makes sense to merge the offline-page part from here to there as a note (since it’s easy to add if you already run a separate Nginx instance), then mark this one as deprecated (linking to the alternatives)?

How was I supposed to know?

> [@Run other websites on the same machine as Discourse](https://meta.discourse.org/t/run-other-websites-on-the-same-machine-as-discourse/17247/1):
>
> @pfaffman edited this heavily 2022.02.24. Blame me if it’s broken.

Oh.

But seriously, I like your solution better than mine!

And that topic says in big letters that it’s an advanced topic.

> [@fefrei](#):
>
> Your suggested HAProxy topic would still make sense in addition, as the default way to go for people _not_ wanting to install a front Nginx for other reasons.

But maybe isn’t that necessary either, as most people understand nginx better anyway. I’ve started thinking about it now, though, so the hard part will be to get me to stop. 🙂

---

<div class="post-metadata">

### Author: ![Jagster](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jagster/32/192154_2.png) [@Jagster](https://meta.discourse.org/u/Jagster)
#### Post date: [December 7, 2022, 10:58pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/147 "2022-12-07T22:58:48Z")

</div>

It is always good if out there is plenty of alternativies. But this one is one of the most easier ones (quite many ones…), and familiar for quite many.

So please, don’t touch this one.

And leaving this as it is has another point too: search results. Because of hight trafic (and very limited use of tags…) trying to find anything specific here is quite hard nowadays. But this is quite easy to find and has very targeted purpose. If this topic will move to another one finding it will be more harder.

There is a reson why this is so popular… not so many aren’t that inspired to use docker or haproxy.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 7, 2022, 11:08pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/148 "2022-12-07T23:08:42Z")

</div>

> [@Jagster](#):
>
> But this one is one of the most easier ones (quite many ones…), and familiar for quite many.

Sigh. Well, I guess that’s true too, but it’s at least 4 years out of date. I haven’t done it lately, but you don’t need to modify the files by hand anymore as `acme` (or something like it?) will do it for you.

What I really think is that it makes much more sense to use a two-container installation, which has little down time rather than to jump through these hoops to put a page up while you rebuild, but I can’t convince people of that either.

So maybe the thing to do is to rewrite this for how things work today.

---

<div class="post-metadata">

### Author: ![Jagster](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jagster/32/192154_2.png) [@Jagster](https://meta.discourse.org/u/Jagster)
#### Post date: [December 7, 2022, 11:30pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/149 "2022-12-07T23:30:32Z")

</div>

> [@pfaffman](#):
>
> What I really think is that it makes much more sense to use a two-container installation

Aaaand it is much more difficult. I reckon it is easier to fix instructions how to install and use certbot that start teaching how, when and where update sql-side etc. containers.

Plus there is another point against docker (even Discourse works that way…): we can find a lot totally basic level questions like how to use docker at the first place. Or how to avoid typos in yml-files 😉

> [@pfaffman](#):
>
> it’s at least 4 years out of date

And yet it works (except SSL-section is a bit confusing, but it was off even 4 years ago 😉 )

No. I’m not against another solutions. I’m very anti when old links and texts shall be moved to new locations without very solid reasons.

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [December 7, 2022, 11:39pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/150 "2022-12-07T23:39:52Z")

</div>

> [@Jagster](#):
>
> Aaaand it is much more difficult.

We’ll have to agree to disagree there. But I believe that there are likely lots of people who agree with you. (Maybe this solution is a “set it and forget it” solution, and the two-container solution does require paying attention to when there is a Postgres upgrade, which happens about every 2 years.)

> [@Jagster](#):
>
> (except SSL-section is a bit confusing, but it was off even 4 years ago

OK. That part we agree on! So I think the way forward is to see what I can do to clean up that bit, and put the haproxy solution on hold.

---

<div class="post-metadata">

### Author: ![JustinZ](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@JustinZ](https://meta.discourse.org/u/JustinZ)
#### Post date: [January 15, 2023, 11:55pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/151 "2023-01-15T23:55:52Z")

</div>

I’d love to see this done as part of Discourse but thank you @fefrei for this! Amazing work! I’ll be using Apache to do it but at least the base steps should be the same.

---

<div class="post-metadata">

### Author: ![JustinZ](https://avatars.discourse-cdn.com/v4/letter/j/e68b1a/32.png) [@JustinZ](https://meta.discourse.org/u/JustinZ)
#### Post date: [January 16, 2023, 2:11am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/152 "2023-01-16T02:11:27Z")

</div>

OK only took me 2 hours of fiddling to make it how I want!

# Discourse Maintenance Page with Apache2

As root

```plaintext
cd /var/discourse
nano containers/app.yml

```

Comment out these lines:

```plaintext
  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

expose:
  #- "80:80" # http
  #- "443:443" # https

```

Add at the _END_ of templates section add (must be last):

```plaintext
  - "templates/web.socketed.template.yml"

```

Note: This will make Discourse listen only on internal IP and apache2 will take over the 80/443 ports and SSL termination

Note: Discourse must be rebuilt for this to take effect:

```plaintext
cd /var/discourse
./launcher rebuild app

```

Install apache2 and certbot

```plaintext
apt install -y apache2 certbot python3-certbot-apache

```

Make a directory for the html page:

```plaintext
mkdir /var/www/discourse_maintenance

```

HTML page:  
/var/www/discourse\_maintenance/discourse\_maintenance.html

```plaintext
<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="refresh" content="5">
        <title>Discourse Maintenance</title>
        <style>
            .center {
                display: flex;
                justify-content: center;
            }
            .container {
                max-width: 500px;
                padding: 50px 50px 30px 50px;
            }
            .title {
                padding-top: 20px;
            }
            h1, p {
                font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
            }
        </style>
    </head>
    <body>
        <div class="center">
            <div class="container">
                <h1 class="title">Discourse Maintenance&hellip;</h1>
                <p>We are currently upgrading the site, or performing scheduled maintenance.</p>
                <p>You'll automatically be redirected to the site once it's available.</p>
            </div>
        </div>
    </body>
</html>

```

Enable Proxy Module:

```plaintext
a2enmod proxy
a2enmod proxy_http
a2enmod headers

```

Apache vhost file:

```plaintext
<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName your.discourse.domain
  ServerAdmin your@email.com
  DocumentRoot /var/www/discourse_maintenance

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  # Maintenance Mode
  RewriteEngine On
  RewriteCond /var/www/under_maintenance -f
  # safety check to prevent redirect loops 
  RewriteCond %{REQUEST_URI} !/discourse_maintenance.html$
  # redirect internally all requests to maintenance.html 
  RewriteRule ^.*$ /var/www/discourse_maintenance/discourse_maintenance.html

  ProxyPass / unix:///var/discourse/shared/standalone/nginx.http.sock|http://127.0.0.1/
  ProxyPassReverse / unix:///var/discourse/shared/standalone/nginx.http.sock|http://127.0.0.1/

  SSLCertificateFile /etc/letsencrypt/live/your.discourse.domain/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/your.discourse.domain/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

```

To enable maintenance run `touch /var/www/under_maintenance`

To disable maintenance run `touch /var/www/under_maintenance`

Credits: [Add an offline page to display when Discourse is rebuilding or starting up](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238) for the intial idea, html page (trimmed/edited to my liking) and nginx config from which I based the Apache config on.

Edit: Suggestions welcome to make it automatic when 502/503 is the response. I tried but couldn’t get it to work like I wanted so I went with a known method that I use on other webservers when the backend application is down for maintenance etc.

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [March 17, 2023, 12:54pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/153 "2023-03-17T12:54:41Z")

</div>

> [@pfaffman](#):
>
> Do you think it makes sense to write a replacement that spins up [haproxy in docker] and [nginx in docker], perhaps with docker compose, making the nginx container mount the certs from the discourse container and have haproxy in tcp mode to do something like this

On system reboot, this will delay the error/maintenance page until docker has spun up, which takes rather longer than booting the system. It also doesn’t give the option of system-provided SELinux protections for the system nginx. Using system nginx can, at least on a systemd-managed system with fast boot, get you the error page within a few seconds of boot. For me, this means that my systems answer with the maintenance page very quickly during system updates requiring reboot. (I’m running AlmaLinux 9 on the host, and it boots to nginx very fast.)

> [@pfaffman](#):
>
> I’d then leave this one for historical purposes (and perhaps close it?)

It might make sense to document an haproxy alternative and compare experiences, but haproxy-in-docker is not an apples-apples replacement for external nginx, and closing this topic would be a mistake.

It’s not just availability.

[Using docker for external traffic via IPv4 hides external IPv6 addresses from the internal nginx and Discourse.](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/122) You’ll have the same problem with haproxy. Look at your logs for 127.0.0.1 or 172.\* RFC1918 local-only IP space addresses. Not using an external proxy means that all IPv6 traffic shows up as the same IP, which breaks the internal nginx zone rate limiting, considering all IPv6 traffic to be a single zone.

IPv6 matters more and more.

---

<div class="post-metadata">

### Author: ![mcdanlj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcdanlj/32/131829_2.png) [@mcdanlj](https://meta.discourse.org/u/mcdanlj)
#### Post date: [March 17, 2023, 3:11pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/154 "2023-03-17T15:11:07Z")

</div>

> [@mcdanlj](#):
>
> Then in your app.yaml, comment out or remove the `- "templates/web.socketed.template.yml"`, expose port 80 as a different port on the local machine and rebuild the container.

I discovered by accident this morning that this step not only avoids applying unix socket, but **also** removes use of the real\_ip module, so that rate limiting is applied based on all connections together, rather than all connections per IP. I should probably contribute a new template with variables, but right now I’ve just added this to my app container YAML file:

```yaml
run:
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 80;/
     to: |
       listen unix:/shared/nginx.http.sock;
       set_real_ip_from 172.0.0.0/24;
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 443 ssl http2;/
     to: |
       listen unix:/shared/nginx.https.sock ssl http2;
       set_real_ip_from 172.0.0.0/24;

```

I don’t know whether it makes sense to have, say, a `templates/web.httpratelimit.yml` file with something like that with a variable for the address but not using unix domain sockets. Thoughts on that?

---

<div class="post-metadata">

### Author: ![syandriz](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/syandriz/32/274337_2.png) [@syandriz](https://meta.discourse.org/u/syandriz)
#### Post date: [April 23, 2023, 4:39pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/155 "2023-04-23T16:39:08Z")

</div>

```plaintext
server {
  listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2;
  server_name DOMAIN;
  ssl_certificate /etc/letsencrypt/live/DOMAIN/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/DOMAIN/privkey.pem;

ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
  ssl_protocols TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  add_header Strict-Transport-Security "max-age=63072000;";
  ssl_stapling on;
  ssl_stapling_verify on;

  client_max_body_size 0;

  location / {
    error_page 502 =502 /errorpages/offline.html;
    proxy_intercept_errors on;

    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }

  location /errorpages/ {
    alias /var/www/errorpages/;
  }
}

```

! # change your domain and path of error file

i got this script with ssl and work

---

<div class="post-metadata">

### Author: ![jericson](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jericson/32/116215_2.png) [@jericson](https://meta.discourse.org/u/jericson)
#### Post date: [January 5, 2024, 4:15pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/156 "2024-01-05T16:15:58Z")

</div>

> [@pfaffman](#):
>
> This one has very high reads and I think is one of the least helpfu.

I just tried using this guide and I couldn’t get it working.

I started with an Nginx proxy to [run two sites out of a single Discourse container](https://jlericson.com/2024/01/02/multisite_discourse.html). I just wanted to add in the error page bit, so I skipped the parts that seemed to overlap with [Run other websites on the same machine as Discourse](https://meta.discourse.org/t/run-other-websites-on-the-same-machine-as-discourse/17247). I must have missed a key step though. In the end I got what I needed from [this DigitalOcean tutorial](https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-to-use-custom-error-pages-on-ubuntu-22-04). It’s not _hard_ to manually set this up, but it does seem like there must be a better way.

> [@pfaffman](#):
>
> Do you think it makes sense to write a replacement that spins up [[HAProxy](https://hub.docker.com/_/haproxy) and [Nginx](https://hub.docker.com/_/nginx)], perhaps with docker compose, . . .

Given Docker as the standard way to run Discourse, this sounds better. I assume it would be the sort of thing where you’d set it up and forget about it.

---

<div class="post-metadata">

### Author: ![Sailor](https://avatars.discourse-cdn.com/v4/letter/s/a587f6/32.png) [@Sailor](https://meta.discourse.org/u/Sailor)
#### Post date: [March 5, 2025, 5:53pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/157 "2025-03-05T17:53:41Z")

</div>

The idea within this thread is also great for those of us running [caddy as a reverse proxy](https://meta.discourse.org/t/use-caddy-instead-of-ngnix-as-your-reverse-proxy/54716), be that in standalone application or using [Cloudflare Tunnels](https://meta.discourse.org/t/install-discourse-on-a-residential-internet-with-cloudflare-tunnel/211297).

```plaintext
discourse.example.org {
        reverse_proxy <host | ip>:port

        handle_errors 5xx {
                root * /path/to/error-pages
                rewrite * /error.html
                file_server {
                        status 404
                }
        }
}

```

The `status 404` section is important only if using Cloudflare Tunnels. If caddy returns 5xx to Cloudflare, Cloudflare Tunnel will display its own disconnect error. Changing the status indicates to Cloudflare there is a valid live connection that will serve an error page.

---

<div class="post-metadata">

### Author: ![tknospdr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tknospdr/32/529762_2.png) [@tknospdr](https://meta.discourse.org/u/tknospdr)
#### Post date: [May 26, 2025, 1:39am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/158 "2025-05-26T01:39:51Z")

</div>

> [@fefrei](#):
>
> I recommend that you include `<meta http-equiv="refresh" content="120">` in your page – this will refresh the page every 120 seconds, which means that Discourse will load automatically once it’s available again.

Maybe I’m misunderstanding how this works, but doesn’t a refresh just refresh the page you’re already on? How does that get you back to a different URL?

---

<div class="post-metadata">

### Author: ![fefrei](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fefrei/32/119538_2.png) [@fefrei](https://meta.discourse.org/u/fefrei)
#### Post date: [May 26, 2025, 9:02am UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/159 "2025-05-26T09:02:04Z")

</div>

There’s no need to go to a different URL – the trick is that the error page is served directly on the URL the user tried to access (e.g. `https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/158`), and that is the exact URL that will refresh, yielding either the same error again, or the page the user wanted 🙂

---

<div class="post-metadata">

### Author: ![tknospdr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tknospdr/32/529762_2.png) [@tknospdr](https://meta.discourse.org/u/tknospdr)
#### Post date: [May 26, 2025, 6:48pm UTC](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/160 "2025-05-26T18:48:15Z")

</div>

Oh, I see. I hadn’t read carefully through the entire setup as I’m using another server for the offline page, just in case my whole machine went down for some reason.  
Makes sense though. Now I’m just trying to get my js that’s supposed to be redirecting back to the original URL working…

[Previous page](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238.md?page=6)

[Next page](https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238.md?page=8)
