# Server WebSocket

**URL:** <https://community.letsencrypt.org/t/server-websocket/213884>\
**Category:** Help\
**Created:** [February 25, 2024, 3:54am UTC](https://community.letsencrypt.org/t/server-websocket/213884 "2024-02-25T03:54:04Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![andrys](https://avatars.discourse-cdn.com/v4/letter/a/c68b51/32.png) [@andrys](https://community.letsencrypt.org/u/andrys)\
**Post date:** [February 25, 2024, 3:54am UTC](https://community.letsencrypt.org/t/server-websocket/213884/1 "2024-02-25T03:54:04Z")

</div>

Hello.  
I have a WebSocket server running on a specific IP address that should operate over HTTPS (WSS).  
How can I obtain a certificate for this IP address? There is no website on this IP, it is not needed.

---

<div class="post-metadata">

**Author:** ![Bruce5051](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/bruce5051/32/76576_2.png) [@Bruce5051](https://community.letsencrypt.org/u/Bruce5051)\
**Post date:** [February 25, 2024, 3:59am UTC](https://community.letsencrypt.org/t/server-websocket/213884/2 "2024-02-25T03:59:29Z")

</div>

Hello @andrys, welcome to the Let's Encrypt community. 🙂

[Let’s Encrypt](https://letsencrypt.org/) offers [Domain Validation (DV) certificates](https://letsencrypt.org/docs/faq/#what-services-does-let-s-encrypt-offer); not IP Address Certificates.

Most of the ACME Clients have the ability to spin-up a temporary webserver for [HTTP-01 challenge](https://letsencrypt.org/docs/challenge-types/#http-01-challenge) of the [Challenge Types - Let's Encrypt](https://letsencrypt.org/docs/challenge-types/); however there is the [DNS-01 challenge](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge) which does not require a webserver for validation.

**Please fill out the fields below so we can help you better.** Note: you must provide your domain name to get help. Domain names for issued certificates are all made public in Certificate Transparency logs (e.g. [crt.sh | example.com](https://crt.sh/?q=example.com)), so withholding your domain name here does not increase secrecy, but only makes it harder for us to provide help.

My domain is:

I ran this command:

It produced this output:

My web server is (include version):

The operating system my web server runs on is (include version):

My hosting provider, if applicable, is:

I can login to a root shell on my machine (yes or no, or I don't know):

I'm using a control panel to manage my site (no, or provide the name and version of the control panel):

The version of my client is (e.g. output of `certbot --version` or `certbot-auto --version` if you're using Certbot):

Thank you for assisting us in helping **YOU**!

---

<div class="post-metadata">

**Author:** ![andrys](https://avatars.discourse-cdn.com/v4/letter/a/c68b51/32.png) [@andrys](https://community.letsencrypt.org/u/andrys)\
**Post date:** [February 25, 2024, 4:12am UTC](https://community.letsencrypt.org/t/server-websocket/213884/3 "2024-02-25T04:12:49Z")

</div>

I have Windows Server 2019 installed on a specific IP address. It only hosts a WSS server, so it doesn't require a domain name because connections are made via the IP address. Here's an example of a connection:

new WebSocket('wss://192.168.1.188:3300'); (using a local IP address for demonstration) Where 'WSS' indicates that the connection will occur over a secure protocol

---

<div class="post-metadata">

**Author:** ![Bruce5051](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/bruce5051/32/76576_2.png) [@Bruce5051](https://community.letsencrypt.org/u/Bruce5051)\
**Post date:** [February 25, 2024, 4:18am UTC](https://community.letsencrypt.org/t/server-websocket/213884/4 "2024-02-25T04:18:16Z")

</div>

> [@andrys](#):
>
> so it doesn't require a domain name because connections are made via the IP address

Then please see [https://letsencrypt.org/docs/certificates-for-localhost/](https://letsencrypt.org/docs/certificates-for-localhost/)

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 25, 2024, 4:40am UTC](https://community.letsencrypt.org/t/server-websocket/213884/5 "2024-02-25T04:40:24Z")

</div>

> [@andrys](#):
>
> it doesn't require a domain name

Are you planning on hosting this to the Internet?  
[if so, then you will require a domain name]

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [February 25, 2024, 7:37am UTC](https://community.letsencrypt.org/t/server-websocket/213884/6 "2024-02-25T07:37:56Z")

</div>

You can't get a certificate for an IP address through let's Encrypt. Just assign an actual subdomain on your real domain like [api.yourdomain.com](http://api.yourdomain.com) (or whatever you like) and get a real certificate, it's easier.

If you did it using [https://certifytheweb.com](https://certifytheweb.com) (for example, which I develop) you would open up port 80 so it can host the http challenge, then New Certificate \> add your domain(s), Request Certificate. Once you have a cert use a deployment task like _Deploy to Generic Server_ under Tasks, and export the fullchain pem file and the private key pem file somewhere your WSS server can see it, configure your WSS to use those files and hey presto!

You may need to restart your server periodically to make sure it picks up the latest cert, or build in a periodic certificate reload. I'm assuming with all this that your server is node or something similar and not just IIS.

---

<div class="post-metadata">

**Author:** ![andrys](https://avatars.discourse-cdn.com/v4/letter/a/c68b51/32.png) [@andrys](https://community.letsencrypt.org/u/andrys)\
**Post date:** [February 26, 2024, 5:07am UTC](https://community.letsencrypt.org/t/server-websocket/213884/7 "2024-02-26T05:07:31Z")

</div>

Yes, that's correct. I've linked the domain name [his-name.com](http://his-name.com) to my IP address and tried to obtain the certificate again. But again, I couldn't do it. It's just some kind of trouble.

(I've associated the IP with the domain name; there won't be an actual website)

ERROR:

Input the webroot for [his-name.com](http://his-name.com): (Enter 'c' to cancel): c:\certbot Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems: Domain: [his-name.com](http://his-name.com) Type: unauthorized Detail: 185.68.21.169: Invalid response from [http://his-name.com/.well-known/acme-challenge/\_f2so4QE2SkwTNk9wiZo\_Z7q7851kJfY1x1jdZ3\_bwg:](http://his-name.com/.well-known/acme-challenge/_f2so4QE2SkwTNk9wiZo_Z7q7851kJfY1x1jdZ3_bwg:) 404 Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet. Some challenges have failed. Ask for help or search for solutions at [https://community.letsencrypt.org](https://community.letsencrypt.org). See the logfile C:\Certbot\log\letsencrypt.log or re-run Certbot with -v for more details.

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 26, 2024, 9:44am UTC](https://community.letsencrypt.org/t/server-websocket/213884/8 "2024-02-26T09:44:22Z")

</div>

You may need to use _`standalone`_ instead of _`webroot`_.

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [February 26, 2024, 11:17am UTC](https://community.letsencrypt.org/t/server-websocket/213884/9 "2024-02-26T11:17:22Z")

</div>

As @rg305 says if you're using Certbot you'd probably need to use the _standalone_ mode (which runs a temporary port 80 web server for the http challenge response), webroot only works if you have a webserver process on port 80 and it will serve the files itself.

---

<div class="post-metadata">

**Author:** ![Osiris](https://avatars.discourse-cdn.com/v4/letter/o/839c29/32.png) [@Osiris](https://community.letsencrypt.org/u/Osiris)\
**Post date:** [February 26, 2024, 3:59pm UTC](https://community.letsencrypt.org/t/server-websocket/213884/10 "2024-02-26T15:59:19Z")

</div>

If there was a 404 file not found error returned, then _SOMETHING_ is answering on port 80... Thus `standalone` will probably not work either due to the fact it can't bind to port 80 _or_ the IP address or port mapping or something similar is incorrect.

Is `his-name.com` actually the literal hostname in question? Because there's an IIS webserver listening there.. Sooooooo... Either the hostname is incorrect, the IP address is incorrect or the "there is no website on this IP" was incorrect.

Also _insert Certbot for Windows is deprecated template here_

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 27, 2024, 1:19am UTC](https://community.letsencrypt.org/t/server-websocket/213884/11 "2024-02-27T01:19:49Z")

</div>

> [@Osiris](#):
>
> `standalone` will probably not work either due to the fact it can't bind to port 80

In the `Windows world`, port 80 can be shared.

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [February 27, 2024, 2:17am UTC](https://community.letsencrypt.org/t/server-websocket/213884/12 "2024-02-27T02:17:38Z")

</div>

@Osiris good point. Just clicked the link, it's IIS that's responding and therefore certbot standalone won't work because windows already has a port 80 binding.

@andrys see my instructions above on how to use Certify The Web - this will setup certificates for IIS and also gives you the option to export to other services (express js etc). Note that nodejs can use PEM components or the PFX/P12 archive format ([Install a certificate on Node.js](https://www.tbs-certificates.co.uk/FAQ/en/nodejs.html)). You could also use other clients like win-acme etc if you prefer.

The first step is to get your certificate, the second step is to automate your deployment.

[You can also optionally reverse proxy in IIS back to your node service, exposing just your IIS service to the internet, that way the https is handled by IIS/windows and you don't have to also configure your cert in node at all]

---

<div class="post-metadata">

**Author:** ![andrys](https://avatars.discourse-cdn.com/v4/letter/a/c68b51/32.png) [@andrys](https://community.letsencrypt.org/u/andrys)\
**Post date:** [February 27, 2024, 2:32am UTC](https://community.letsencrypt.org/t/server-websocket/213884/13 "2024-02-27T02:32:14Z")

</div>

Hello friends. Yes, I launched node.js, but I couldn't bind it to port 80, so I set it to 3300 for testing, it's visible over the network. Now the problem is to bind it to port 80. [http://his-name.com:3300/](http://his-name.com:3300/)

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 27, 2024, 3:03am UTC](https://community.letsencrypt.org/t/server-websocket/213884/14 "2024-02-27T03:03:50Z")

</div>

Can it be used behind a proxy?

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 27, 2024, 3:09am UTC](https://community.letsencrypt.org/t/server-websocket/213884/15 "2024-02-27T03:09:01Z")

</div>

> [@rg305](#):
>
> You may need to use _`standalone`_ instead of _`webroot`_.

> [@webprofusion](#):
>
> As @rg305 says if you're using Certbot you'd probably need to use the _standalone_ mode

I did not specify `certbot`.  
[quite the opposite]  
I was rather hoping they would use _`standalone`_ with a _real Windows client_.  
One that can share port 80; Like: [https://CertifyTheWeb.com/](https://CertifyTheWeb.com/)

---

<div class="post-metadata">

**Author:** ![Osiris](https://avatars.discourse-cdn.com/v4/letter/o/839c29/32.png) [@Osiris](https://community.letsencrypt.org/u/Osiris)\
**Post date:** [February 27, 2024, 6:25am UTC](https://community.letsencrypt.org/t/server-websocket/213884/16 "2024-02-27T06:25:52Z")

</div>

> [@rg305](#):
>
> In the `Windows world`, port 80 can be shared.

Also with Python (Certbot) or just IIS? 🤔 I'm not familiar with Windows, so I'm (slightly) curious to know 🙂

---

<div class="post-metadata">

**Author:** ![andrys](https://avatars.discourse-cdn.com/v4/letter/a/c68b51/32.png) [@andrys](https://community.letsencrypt.org/u/andrys)\
**Post date:** [February 27, 2024, 7:30am UTC](https://community.letsencrypt.org/t/server-websocket/213884/17 "2024-02-27T07:30:16Z")

</div>

Hello friends. I'm actually a programmer, not dealing much with servers, so this topic is new to me. I need to solve this task with as few problems as possible. I have Windows Server 2019, and I need to run node.js on it to work with WSS. There won't be anything else, but as I understand it, access to WSS will be through a domain name, so I had to set it up. Next. Now I need to get a real certificate to test the code. HTTP is running on port 3300, it needs to run on port 80 so that I can then get the certificate.

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [February 27, 2024, 7:35am UTC](https://community.letsencrypt.org/t/server-websocket/213884/18 "2024-02-27T07:35:35Z")

</div>

> [@Osiris](#):
>
> Also with Python (Certbot) or just IIS?

Not with python or at least not in the way the Certbot uses it. In Windows the http/https support is (optionally) handled by the kernel level http.sys and TLS is managed by the Schannel subsystems. IIS works on top of http.sys (and schannel) to provide a web application server (e.g. all the additional stuff you need like handlers for PHP or [asp.net](http://asp.net) etc), plus a management layer/api.

If an app directly binds to port 80 though, nothing else can. So Port 80 gets used up either as soon as you have any http enabled sites in IIS (or any other http.sys aware listener), or if you fire up Apache/nginx or a custom port 80 listener (python, node etc) and the two don't co-exist but technically they probably could if they wanted to.

---

<div class="post-metadata">

**Author:** ![webprofusion](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/webprofusion/32/85310_2.png) [@webprofusion](https://community.letsencrypt.org/u/webprofusion)\
**Post date:** [February 27, 2024, 8:02am UTC](https://community.letsencrypt.org/t/server-websocket/213884/19 "2024-02-27T08:02:35Z")

</div>

> [@andrys](#):
>
> HTTP is running on port 3300, it needs to run on port 80 so that I can then get the certificate.

You have installed IIS and you have a default website running on port 80, you just need to look at [http://his-name.com/](http://his-name.com/) to see that, HTTP is port 80 by default, that's why you don't need to specify the port in the URL.

To free up port 80 you can stop IIS or delete the default website. The _advantage_ of keeping it is that it could make it easier to validate your certificate domain. You could just point Certify The Web (or win-acme or Posh-ACME etc) at your IIS site and generate a certificate and it will take care of http validation.

To get a certificate using your _own_ service via HTTP validation you need to automatically prove to Let's Encrypt that you control the domain, that involves your server responding to `./well-known/acme-challenge/ requests`, so to do that with your node/express server you would configure your application to be able to server static files that are placed under the `/.well-known/acme-challenge` path (how you do that is specific to your choice of web server) and tell your ACME client to put the generate challenge response files there.

You can test this out by putting a test text file (with no .txt filename extension) under your application path so that [http://his-name.com/.well-known/acme-challenge/test](http://his-name.com/.well-known/acme-challenge/test) works

If you instead want to host the http challenge via your own node service, all ACME clients generally have an option for you to specify the root path of your website (in this case your express app), for example if you were using _Certify The Web_ to do this, you would set the Site Root Directory under the Authorization tab and the app would automatically generate the `./well-known/acme-challenge` path under that directory, and you can test it with the _Test_ option.

Keep in mind that you probably won't be using port 80 normally, so I don't see much of a problem just keeping IIS for the port 80 stuff (and helping get your certificate). WSS is Web Sockets over HTTPS so it defaults to port 443.

Here is an article discussing how you could just use IIS as the front end for your service but keep express running on a higher port behind the scenes. This simplifies your certificate renewals (you otherwise need to prepare your certificate files where express can see them, then restart express to pick them up).  
[IIS As Reverse Proxy To WebSocket Server | by Adrian Jenkins | Medium](https://adrianjnkns.medium.com/iis-as-reverse-proxy-to-websocket-server-c4fb5a7166f5)

If it feels like it getting complicated, it's because this is actually complicated. At the end of the day you are trying to achieve two things:

- getting a certificate (which involves proving you control the domain for it usually either via HTTP validation of DNS validation)
- applying a certificate to your service (preparing the files where your service can see them in the format it wants, then reloading the cert or restarting your service).

It's extra complicated because you are using two different web server stacks (IIS/http.sys and express/node), but there are advantages to that approach.

---

<div class="post-metadata">

**Author:** ![rg305](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/rg305/32/91314_2.png) [@rg305](https://community.letsencrypt.org/u/rg305)\
**Post date:** [February 27, 2024, 12:20pm UTC](https://community.letsencrypt.org/t/server-websocket/213884/20 "2024-02-27T12:20:55Z")

</div>

> [@andrys](#):
>
> I need to run node.js on it to work with WSS. There won't be anything else ...

When will there be nothing else?  
Right now: IIS is listening on port 80.  
Do you plan on removing IIS?

> [@andrys](#):
>
> HTTP is running on port 3300, it needs to run on port 80 so that I can then get the certificate.

Not exactly.  
It sounds like you are implying that whatever is on 3300 also needs to be on 80.  
It doesn't (have to be that same thing).  
Yes, something must be on 80 - but it doesn't have to be whatever is on 3300 now and it doesn't have to run all the time [only when needed].

That said, whatever is on 80 only really needs to be there to answer the challenge requests [then and only then]. Which means, it could be the ACME client itself that spins up a temporary web service to answer the HTTP request [_`standalone`_ mode].

That said, you already have IIS running [who know why] and it could facilitate the required HTTP response.

[Next page](https://community.letsencrypt.org/t/server-websocket/213884.md?page=2)
