⚠ Port 443 of this computer does not appear to be accessible using hostname: metabolism.logophilia.eu ----

Hi, I get the error in the subject (see also below) after getting “ Ports 80 and 443 are free for use” during init. DNS is set up, SSl configured, website running from outside (test for yourself), curl output (truncated) added below, i.e. accessible from the box itself. I’m out of ideas what’s missing. Thanks for any insights.

PS. AlmaLinux 10.2 - 6.12.0-211.7.4.el10_2.x86_64

# ./discourse-setup  
→ Checking for setup wizard image updates... 
→ Starting Discourse Setup Wizard... 
 
 
 ___  _ 
|   \(_)___ __ ___ _  _ _ _ ___ ___ 
| |) | (_-</ _/ _ \ || | '_(_-</ -_) 
|___/|_/__/\__\___/\_,_|_| /__/\___| 
                       Setup Wizard 
 
 
→ This wizard will help you configure your Discourse installation. 
→ Press Ctrl+C at any time to cancel. 
 
── System Checks ── 
 
[1/5] Verifying system requirements 
✓ Running as root 
✓ Docker is available 
✓ Memory: 8GB, CPU: 4 cores 
 
── Configuration ── 
 
[2/5] Preparing configuration 
✓ Ports 80 and 443 are free for use 
→ Creating new configuration... 
→ Creating new configuration from template... 
 
── Site Settings ── 
 
[3/5] Enter your site details 
 
Email address for admin account(s)? 
eduard.pech@logophilia.eu▌ 
 
Do you have a domain name for your Discourse? 
▸ Yes      No 
 
Hostname for your Discourse? 
metabolism.logophilia.eu▌ 
 
Configure SMTP for sending emails? (Requires SMTP credentials) 
  Yes    ▸ No 
 
 
── Review Configuration ── 
 
 
╭────────────────────────────────────────────╮ 
│                                            │ 
│  Hostname       metabolism.logophilia.eu   │ 
│  Admin Email    eduard.pech@logophilia.eu  │ 
│  SMTP           (not configured)           │ 
│  Let's Encrypt  Enabled                    │ 
│                                            │ 
╰────────────────────────────────────────────╯ 
 
 
Does this look right? 
▸ Yes      No 
→ Found 8GB of memory and 4 CPU cores 
→ Setting db_shared_buffers = 2048MB 
→ Setting UNICORN_WORKERS = 8 
 
── Network Validation ── 
 
[4/5] Verifying domain configuration 
→ Checking your domain name... 
⚠ Port 443 of this computer does not appear to be accessible using hostname: metabolism.logophilia.eu 
⚠ Connection to http://metabolism.logophilia.eu (port 80) also fails. 
 
This suggests that metabolism.logophilia.eu resolves to some IP address that does not reach this 
machine where you are installing Discourse. 
 
The first thing to do is confirm that metabolism.logophilia.eu resolves to the IP address of this server. 
You usually do this at the same place you purchased the domain. 
 
If you are sure that the IP address resolves correctly, it could be a firewall issue. 
A web search for "open ports YOUR CLOUD SERVICE" might help. 
 
This tool is designed only for the most standard installations. If you cannot resolve 
the issue above, you will need to edit containers/app.yml yourself and then type: 
 
    ./launcher rebuild app 
 
 
✗ DNS verification failed for metabolism.logophilia.eu 
[root@logophilia discourse]# dig metabolism.logophilia.eu 
 
; <<>> DiG 9.18.33 <<>> metabolism.logophilia.eu 
;; global options: +cmd 
;; Got answer: 
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36726 
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 
 
;; OPT PSEUDOSECTION: 
; EDNS: version: 0, flags:; udp: 512 
;; QUESTION SECTION: 
;metabolism.logophilia.eu.      IN      A 
 
;; ANSWER SECTION: 
metabolism.logophilia.eu. 300   IN      A       75.119.134.68 
 
;; Query time: 8 msec 
;; SERVER: 213.136.95.10#53(213.136.95.10) (UDP) 
;; WHEN: Sat Jun 06 04:52:23 CEST 2026 
;; MSG SIZE  rcvd: 69 
 
[root@logophilia discourse]# curl -v https://metabolism.logophilia.eu 
* Host metabolism.logophilia.eu:443 was resolved. 
* IPv6: (none) 
* IPv4: 75.119.134.68 
*   Trying 75.119.134.68:443... 
* ALPN: curl offers h2,http/1.1 
* TLSv1.3 (OUT), TLS handshake, Client hello (1): 
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt 
*  CApath: none 
* TLSv1.3 (IN), TLS handshake, Server hello (2): 
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1): 
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): 
* TLSv1.3 (IN), TLS handshake, Certificate (11): 
* TLSv1.3 (IN), TLS handshake, CERT verify (15): 
* TLSv1.3 (IN), TLS handshake, Finished (20): 
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): 
* TLSv1.3 (OUT), TLS handshake, Finished (20): 
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS 
* ALPN: server accepted http/1.1 
* Server certificate: 
*  subject: CN=metabolism.logophilia.eu 
*  start date: Jun  6 00:26:43 2026 GMT 
*  expire date: Sep  4 00:26:42 2026 GMT 
*  subjectAltName: host "metabolism.logophilia.eu" matched cert's "metabolism.logophilia.eu" 
*  issuer: C=US; O=Let's Encrypt; CN=YR2 
*  SSL certificate verify ok. 
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption 
*   Certificate level 3: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption 
* Connected to metabolism.logophilia.eu (75.119.134.68) port 443 
* using HTTP/1.x 
> GET / HTTP/1.1 
> Host: metabolism.logophilia.eu 
> User-Agent: curl/8.12.1 
> Accept: */* 
>  
* Request completely sent off 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): 
< HTTP/1.1 200 OK 
< Date: Sat, 06 Jun 2026 02:52:36 GMT 
< Server: Apache 
< Last-Modified: Sat, 06 Jun 2026 01:25:19 GMT 
< ETag: "1325f-6538ba67ff892" 
< Accept-Ranges: bytes 
< Content-Length: 78431 
< Content-Type: text/html; charset=UTF-8 
<  
<!doctype html> 
<html lang="en" data-bs-theme="auto"> 
<head> 
  <title> 
    metabolism.logophilia.eu &mdash;  Domain welcome page for  </title> 
  <meta charset="utf-8">
……


Hi there,

I checked your website myself. It looks like your hosting provider is snagging port 443 to display this welcome page. You will need to find out how to entirely free port 443/80 so Discourse can control it.

I already did that, the VPS is managed with Virtualmin, and it’s just a checkmark. Unfortunately, when I uncheck “website enabled”, I cannot curl 443/80 from the host, and discourse setup still complains with the same error. So I thought I enable the website again, so that at least I can show that the SSL handshake works.
And as you can see in my original post, the discourse setup actually claims (initially) that 443 is available. It is my first install, and I would interpret that as: everything green. So why does the setup “change its mind”?
Then again, I don’t really need to understand every detail. Just saying: with Apache disabled on the subdomain the outcome of discourse setup is the same.

Thank you for taking the time, if there’s anything else I can provide for clarification, I’ll do (almost) anything.

I had the same problem here (on my own server at home):

I believe the fix is to just do this if you are 100% sure that the DNS is correct and your ports work correctly.

./install-discourse --skip-connection-test

Thank you, that seemed to have done it! :purple_heart:

The script is beyond 5/5 now, and uploading / installing a lot of additional things it seems. The SSL certificate is now wrong, I guess it’s waiting for either the TTL timeout or maybe it’l be ok once setup is finished.

While I have seriously no clue about Discours, or Docker, or even Ruby… the DNS side of things is never a problem :slight_smile: Thanks again!

I see it’s already marked as solution. But I have one more question, if I may.

I know Postgres is needed, but it is not mentioned at

https://github.com/discourse/discourse/blob/main/docs/INSTALL-cloud.md

So I thought the docker image comes with Postgres installed. Could you please clarify if I need to install Postgres on the VPS? Because the install instruction don’t mention that.

… or maybe the docker comes with Postgres, but the script failed somehow? Because it shuts down at the end:

........
I, [2026-06-06T04:23:49.114769 #1]  INFO -- : File > /etc/runit/1.d/install-ssl  chmod: +x  chown: 
I, [2026-06-06T04:23:49.114999 #1]  INFO -- : Replacing # after ssl with if [ -z "$DISABLE_LETSENCRYPT" ] || [ -n "$ENABLE_LETSENCRYPT" ]; then
  /usr/local/bin/configure-ssl
  exec /usr/local/bin/configure-letsencrypt
fi
# after ssl in /etc/runit/1.d/install-ssl
I, [2026-06-06T04:23:49.125964 #1]  INFO -- : File > /usr/local/bin/configure-ssl  chmod: +x  chown: 
I, [2026-06-06T04:23:49.127031 #1]  INFO -- : > curl https://raw.githubusercontent.com/acmesh-official/acme.sh/3.0.6/acme.sh > /opt/acme.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  215k  100  215k    0     0   635k      0 --:--:-- --:--:-- --:--:--  637k
I, [2026-06-06T04:23:49.514883 #1]  INFO -- : > chmod +x /opt/acme.sh
I, [2026-06-06T04:23:49.554670 #1]  INFO -- : File > /usr/local/bin/configure-letsencrypt  chmod: +x  chown: 
I, [2026-06-06T04:23:49.596808 #1]  INFO -- : File > /usr/local/bin/letsencrypt  chmod: +x  chown: 
I, [2026-06-06T04:23:49.598926 #1]  INFO -- : > echo "Beginning of custom commands"
Beginning of custom commands
I, [2026-06-06T04:23:49.605809 #1]  INFO -- : > echo "End of custom commands"
End of custom commands
I, [2026-06-06T04:23:49.608842 #1]  INFO -- : Terminating async processes
I, [2026-06-06T04:23:49.609015 #1]  INFO -- : Sending INT to HOME=/var/lib/postgresql USER=postgres exec chpst -u postgres:postgres:ssl-cert -U postgres:postgres:ssl-cert /usr/lib/postgresql/15/bin/postmaster -D /etc/postgresql/15/main pid: 44
I, [2026-06-06T04:23:49.609157 #1]  INFO -- : Sending TERM to exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf pid: 111
2026-06-06 04:23:49.609 UTC [44] LOG:  received fast shutdown request
111:signal-handler (1780719829) Received SIGTERM scheduling shutdown...
2026-06-06 04:23:49.612 UTC [44] LOG:  aborting any active transactions
2026-06-06 04:23:49.619 UTC [44] LOG:  background worker "logical replication launcher" (PID 58) exited with exit code 1
2026-06-06 04:23:49.623 UTC [53] LOG:  shutting down
2026-06-06 04:23:49.634 UTC [53] LOG:  checkpoint starting: shutdown immediate
111:M 06 Jun 2026 04:23:49.683 * User requested shutdown...
111:M 06 Jun 2026 04:23:49.683 * Saving the final RDB snapshot before exiting.
111:M 06 Jun 2026 04:23:49.698 * DB saved on disk
111:M 06 Jun 2026 04:23:49.700 # Redis is now ready to exit, bye bye...
2026-06-06 04:23:49.711 UTC [53] LOG:  checkpoint complete: wrote 87 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.041 s, sync=0.022 s, total=0.088 s; sync files=52, longest=0.008 s, average=0.001 s; distance=86 kB, estimate=86 kB
2026-06-06 04:23:49.735 UTC [44] LOG:  database system is shut down

Do not install postgres.

That is expected, because you haven’t installed Discourse to be the web server.

Then you (almost certainly) still have the issue that your VM does not have its ports exposed to the internet.

IT does not. It clearly states that Discourse does not have access to the port. The your curl command shows that something else has control of port 443

I think that the container built successfully but either it can’t start because something else has port 443, it’s not doing anything because port 443 is routed somewhere else.

You can try

docker ps

to see if any containers are running and

docker logs app

To see what discourse has logged via docker.

Thanks for the feedback, really appreciate the time. Not to be that smartass, but:

[2/5] Preparing configuration 
✓ Ports 80 and 443 are free for use 

It does initially say “free for use”. That said, I have my instance up and running now, with the help of Gemini (mostly about docker usage of all things lol). I would like to offer my “runbook” for any other Virtualmin users out there, because: “free the 443 port” is not the solution here. The rest of my post will be that, if I should rather post it somewhere else, like a new thread, please tell me where to go; I think I’m not the only one with this setup, and it might be useful for others. Thanks again!

So, after the setup has been completed with

cd /var/discourse
./discourse-setup --skip-connection-test

(c/o @darkpixlz :purple_heart:)

… you would do the following steps when on a VPS managed via Webmin and Virtualmin, and using a subdomain.

The Definitive Virtualmin + Discourse Runbook *

  • (1) Cleaning up remnants (If retrying, like I was):

    rm -rf /var/discourse/shared/standalone/ssl/*

    rm -rf /var/discourse/shared/standalone/letsencrypt

    rm -rf /var/discourse/shared/standalone/state

  • (2) Template Deletion:

    You must completely delete the templates/web.ssl.template.yml and templates/web.letsencrypt.ssl.template.yml lines from app.yml. The custom launcher parser will evaluate them even if prefixed with #.

  • (3) Email Setup & Variables:

    Change DISCOURSE_SKIP_EMAIL_SETUP from '1' to '0', because your Discourse won’t be able to connect and check DiscordID;

    Add DISCOURSE_FORCE_HTTPS: true so the backend generates secure URLs.

    Friendly reminder: Ensure your DISCOURSE_SMTP_USER_NAME is set to your raw mailbox account name (e.g., 'logophilia'), not the full email address (e.g., 'logophilia@logophilia.eu'), and wrap the credentials in single quotes (') to bypass potential YAML character parsing bugs.

  • (4) Expose Block Configuration:

    Ensure your expose: block in app.yml contains a HTTP mapping; mapping 443=>8443 is optional / redundant, since Virtualmin terminates the SSL logic before passing it along:

    expose:
      - 8080:80
    

    you can start rebuilding now:

    cd /var/discourse
    ./launcher rebuild app
    
  • (5) Subdomain and Proxy Path Setup:

    • Create your subdomain in Virtualmin as usual, and secure it with a Let’s Encrypt SSL certificate (done automatically, just saying: make sure it doesn’t error out for whatever unrelated reason).
    • Navigate to Proxy Paths (Virtualmin → your subdomain → Web Configuration → Proxy Paths), create a new mapping / to http://localhost:8080/, keep “serve locally” unchecked, but toggle Proxy WebSocket to Yes to allow real-time updates and notification streams.
  • (6) CSRF Header Directives:

    • In Webmin ➔ Servers ➔ Apache Webserver ➔ [find your subdomain config here and click on the config for 443] ➔ Edit Directives, place the following lines right above Virtualmin’s own proxy block for Let’s Encrypt (usually “ProxyPass /.well-known !”) to facilitate CSRF token forwarding:
    ProxyPreserveHost On
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-For %{REMOTE_ADDR}s
    

    ProxyPreserveHost On: Tells Discourse your actual domain name instead of “localhost”.
    RequestHeader set X-Forwarded-Proto "https": Explicitly tells Discourse the user is using a secure connection, matching up with your DISCOURSE_FORCE_HTTPS: true setting.
    RequestHeader set X-Forwarded-For: Passes the visitor’s real IP address to the container so security logs work.

  • (7) Clean Container Handshake:

    While the long (sorry … it’s true though;-) rebuild process finishes, ensure any potentially stuck container blueprint is wiped with docker rm -f app so that running ./launcher start app spins up a completely fresh instance bound to port 8080. Check that docker ps shows something under “ports” similar to:

    # docker ps
    CONTAINER ID   IMAGE                 COMMAND        CREATED          STATUS          PORTS                                                                                NAMES
    d21772a21e36   local_discourse/app   "/sbin/boot"   45 minutes ago   Up 45 minutes   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp, 0.0.0.0:8443->443/tcp, [::]:8443->443/tcp   app
    

    (As you can see, I left the 443=>8443 directive in my app.yml, works either way.)

  • (8) Monitoring & Launch:

    Tail the boot stream with docker logs -f app until the database migrations finish and the workers start processing requests. A bunch of “INFO” lines in quick succession, basically.

  • (9) Finalization:

    Load your subdomain in a browser, click Register, and let the system send a validation email to your mailbox.

*) until proven wrong :wink:

I needed to turn off my Nginx server prior to the installation. Good to see there is a flag to skip this test, though :slight_smile: