如何不购买域名在云服务器上搭建HTTPS服务
step 1: 事前准备
step 1.1: 云服务器
购买一台云服务器(带有弹性公网IP),阿里云,腾讯云,华为云什么的都可以。
选择ubuntu系统
开放安全组策略(把你需要的协议/端口暴露出来):
- TCP:22:ssh
- TCP:80:HTTP
- TCP:443:HTTPS
- ICMP:ping
这里我们强烈不推荐暴露所有的端口,根据权限最小化原则,仅应该暴露你需要的端口

step 1.2: Caddy
官方文档:https://caddy2.dengxiaolong.com/docs/install
仓库地址:https://github.com/caddyserver/caddy
Caddy是一个强大的反向代理工具,当然也可以被用作站点服务器。本文使用Caddy作为主要配置工具。
安装脚本:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
安装完成后,应当显示:
~# caddy --version
v2.9.1
step 1.3: Apifox
这里安利一波Apifox,可以非常方便的进行接口管理,构造自动化测试等工作,支持RESTful风格的API等。
界面简洁优雅,使用非常方便,并且对于个人开发者来说完全免费,符合我个人的审美观念。

step 2:获取证书
众所周知,HTTPS相比于HTTP,其最大的特性就是使用了SSL/TLS对数据进行加密。
我们依赖证书链使用TLS在客户端和服务器之间建立可信连接,具体原理比较复杂这里不多解释。
一般来说,证书是要由CA来进行签发,如果你购买了域名,自然会获取对应的证书。
但是,此处我们没有购买形似example.com的域名,而是类似149.33.138.14这样的裸露公网IP,这就需要我们提前获取对于裸IP的证书支持。
但遗憾的是,绝大部分针对裸IP的证书都需要收费。
毕竟,奇迹和魔法可不是免费的,https和域名当然也不是,大家都是穷人,尽量还是少花点钱。
step 2.1 获取免费证书
所幸,这里有一个方法,可以对裸IP获取90天的免费证书,到期相同方法续期即可
该服务由zeroSSL提供,我们使用的Caddy也是zeroSSL下的项目之一
这个教程写的还挺详细的,这里就不抄过来了:https://www.landiannews.com/archives/93605.html
但是,这里我们需要保证IP地址+文件夹+文件能够访问,这里我们需要使用Caddy先建立一个最简单的HTTP server,从服务器上获取静态文件
首先查看80端口(http),确保未被监听:
root@hcss-ecs-0ef3:~# sudo lsof -i :80
root@hcss-ecs-0ef3:~#
在当前路径下创建Caddyfile(可以理解为配置文件),需要设定为http,file_server支持静态文件访问,/var/www/html为server的根文件目录
http://149.33.138.14 {
root * /var/www/html
file_server
}
创建.well-known/pki-validation/路径并且将文件拷贝到路径下:
sudo mkdir -p /var/www/html/.well-known/pki-validation
sudo cp /path/to/{filename}.txt /var/www/html/.well-known/pki-validation/
caddy的管理端口默认为localhost:2019,如果发现端口被占用,可以通过sudo lsof -i :2019查看是谁占用了
有可能是自动启动的caddy systemd service和手动启动的caddy发生冲突了
这里我们选择手动启动,将service disable掉:
sudo systemctl status caddy
sudo systemctl stop caddy
sudo systemctl status caddy
此时应当观察到service状态为Active: inactive (dead),确定port 2019无人监听后可以重新手动启动caddy:
sudo caddy stop
caddy fmt --overwrite
sudo caddy start
如果想要更改默认2019端口,可以配置CADDY_ADMIN环境变量,此处不再赘述。
此时再次查看80端口(http),应当已经被监听:
root@hcss-ecs-0ef3:~# sudo lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
caddy 65370 root 9u IPv6 562057 0t0 TCP *:http (LISTEN)
此时可以开始验证http server是否能够被访问,查看是否有文件内容:
方法一:curl -X GET http://149.33.138.14/.well-known/pki-validation/{filename}.txt

方法二:使用Apifox,设置GET方法和request:

至此,HTTP server设置并验证完毕,返回zeroSSL,点击验证并签发证书,下载文件列表如下:
- certificate.crt:根节点证书
- ca_bundle.crt:中间节点证书
- private.key:密钥

将以上证书文件上传到服务器中。
step 2.2 搭建https server
step 2.2.1 验证证书合法性
我们将证书存储在/etc/caddy/ssl路径下,统一管理:
sudo mkdir -p /etc/caddy/ssl
sudo cp certificate.crt /etc/caddy/ssl/
sudo cp ca_bundle.crt /etc/caddy/ssl/
sudo cp your_private.key /etc/caddy/ssl/
设置权限:
sudo chmod 600 /etc/caddy/ssl/*
sudo chown -R root:root /etc/caddy/ssl/
验证证书链是否完成,应当输出OK:
openssl verify -CAfile /etc/caddy/ssl/ca_bundle.crt /etc/caddy/ssl/certificate.crt
验证私钥和证书是否匹配,两者输出应当相同:
openssl x509 -noout -modulus -in /etc/caddy/ssl/certificate.crt | openssl md5
openssl rsa -noout -modulus -in /etc/caddy/ssl/private.key | openssl md5
出于使用简单的考虑,我们首先拼接证书链:
cat /etc/caddy/ssl/certificate.crt /etc/caddy/ssl/ca_bundle.crt > /etc/caddy/ssl/fullchain.crt
再次验证证书内容:
openssl x509 -in /etc/caddy/ssl/fullchain.crt -text -noout
openssl rsa -in /etc/caddy/ssl/private.key -check
step 2.2.2 搭建
首先查看443端口(https),确保未被监听:
root@hcss-ecs-0ef3:~# sudo lsof -i :443
root@hcss-ecs-0ef3:~#
修改Caddyfile,这是一个最简单的server配置:
{
default_sni 149.33.138.14
}
https://149.33.138.14 {
tls /etc/caddy/ssl/fullchain.crt /etc/caddy/ssl/private.key
respond "Hello, world!" 200
}
重新启动caddy服务:
sudo caddy stop
caddy fmt --overwrite
sudo caddy start
此时在另一台服务器上运行:
openssl s_client -connect 149.33.138.14:443 -servername 149.33.138.14
Verify return code应当返回:0 (ok)

在另一台服务器上执行curl -kv https://149.33.138.14/,可以查看到连接全过程:
xiao@DESKTOP-S896N2C:~$ curl -kv https://149.33.138.14/
* Trying 149.33.138.14:443...
* Connected to 149.33.138.14 (149.33.138.14) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=119.3.178.14
* start date: Mar 22 00:00:00 2025 GMT
* expire date: Jun 20 23:59:59 2025 GMT
* issuer: C=AT; O=ZeroSSL; CN=ZeroSSL RSA Domain Secure Site CA
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* Using Stream ID: 1 (easy handle 0x559918bdf9f0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: 149.33.138.14
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< alt-svc: h3=":443"; ma=2592000
< content-type: text/plain; charset=utf-8
< server: Caddy
< content-length: 13
< date: Sun, 23 Mar 2025 08:07:31 GMT
<
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection #0 to host 149.33.138.14 left intact
通过Apifox访问,能够正确响应输出: Hello, world!:

在浏览器中也能够正常访问,且没有任何安全问题:

至此,一个最简单的HTTPS server搭建完成。
过程中会踩的坑和可能遇到的问题
搭建http server时无法访问
表现:
2025/03/22 18:52:20.394 INFO http.auto_https server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS{"server_name": "srv0", "https_port": 443}
2025/03/22 18:52:20.394 INFO http.auto_https enabling automatic HTTP->HTTPS redirects {"server_name": "srv0"}
原因:http请求被重定向,可能是由于Caddyfile写成了这样:
119.3.178.14 {
root * /var/www/html
file_server
}
解决方案:单纯一个caddy已经可以作为http server了,但是会caddy自动重定向http到https,所以需要显式指定http
启动caddy失败
首先看日志,lsof监测对应端口是否被占用。
手动启动的和自动启动的systemd.service是有冲突的,只能启动一个,使用的Caddyfile也不同
https无法访问 Verify return code: 21 (unable to verify the first certificate)
openssl验证出现:Verify return code: 21 (unable to verify the first certificate)
https://github.com/caddyserver/caddy/issues/6344中提出了该问题,是由于client找不到裸ip server的server name(域名则无事)
所以在Caddyfile中一定需要:
{
default_sni 119.3.178.14
}
请求返回 405 The method is not allowed for the requested URL
这个问题大概率是由于混合使用了GET和POST方法,比如获取文件的方式是GET
curl -v 报错 TLSv1.3 (IN), TLS alert, internal error (592):
如果证书链分开,caddy似乎无法以这种方式建立TLS可信连接:
tls /etc/caddy/ssl/certificate.crt /etc/caddy/ssl/your_private.key {
ca_root /etc/caddy/ssl/ca_bundle.crt
}
如何不购买域名在云服务器上搭建HTTPS服务的更多相关文章
- 在centos 7云服务器上搭建Apache服务器并访问到你的网站
网站是指在互联网上根据一定的规则,用HTML等语言制作的网页的集合.网站的目的是用来展示一些信息,如果是个人网站则是为了展示自己的一些想被人知道的东西,例如自己的一些作品,又或者是通过网站来达到盈利的 ...
- 阿里云服务器上搭建seafile专业版
因为官方一键安装教程在阿里云服务器上无法安装,由于水平有限,无法解决,所以选择手动安装 参考资料: 1,.腾讯云搭建seafile服务器 2.How to Install Seafile with N ...
- 在云服务器上搭建个人版chatGPT及后端Spring Boot集成chat GPT
总结/朱季谦 本文分成两部分,包括[国内服务器上搭建chat GPT]和[后端Spring Boot集成chat GPT]. 无论是在[国内服务器上搭建chat GPT]和[后端Spring Boot ...
- 如何在阿里云服务器上搭建wordpress个人网站
1.购买云服务器.域名.域名解析.配置linux系统上的web环境.FTP等参照下面的链接. https://www.cnblogs.com/smyhvae/p/4965163.html?tdsour ...
- 在阿里云服务器上搭建xampp遇到的问题
参考文章:http://blog.csdn.net/hel12he/article/details/49781813 http://www.laozuo.org/8178.html http://bl ...
- 在centos7云服务器上搭建Apache服务器并访问到你的网站
使用X-shell ssh安全连接到云服务器 https://mail.qq.com/cgi-bin/mail_spam?action=check_link&url=https://www.n ...
- 云服务器上搭建cobalt strike遇到的一些小问题
一.前言: 当你兴高采烈的买了一台云服务器,迫不及待地想去搭建传说中的神器cobalt strike的时候,你可能会遇到以下的一些小问题,这里我会列出对应的解决方法. 二.遇到的一些小问题 1.上传文 ...
- 关于linux服务器上搭建ftp服务的流程
小龙最近折腾了一个阿里云的服务器,买完了就要开始做那么多那么多的功课,小龙对ssh也是一知半解的状态,做个小笔记,发布下整个ftp服务的搭建过程,大神勿喷:) 一.aliyun Linux(Redha ...
- 使用Samba在Linux服务器上搭建共享文件服务
最近我们的小团队需要在服务器上共分出一个共享文件夹用于大家存放公共的资源文档, 大家想啊,这肯定很简单呀,在Windows下面只要创建相关的windows account,共享某个文件夹,把读/写权限 ...
- 在阿里云服务器上搭建 Apache Tomat 应用
在阿里云上购买一台服务器,系统采用 window 2008 Server 企业版,64位 1.下载Java7 JRE,安装 http://www.java.com/zh_CN/download/man ...
随机推荐
- 大型IM工程重构实践:企业微信Android端的重构之路
本文由腾讯技术yeconglu分享,原题"企业微信大型Android系统重构之路",下文进行了排版和内容优化等. 1.引言 企业微信本地部署版(下文简称为本地版)是从2017年起, ...
- Solution Set -「OurOJ Contest #2587」浅写
\(\mathscr A\sim\)「OurOJ #47030」_ Link & Submission & Tags:「A.DP-计数 DP」「A.数学-Stirling 数/反演 ...
- 微服务实战系列(十)-网关高可用之中间件Keepalived-copy
1.场景描述 因为要做网关的高可用,用到了keepalived+nginx,来保证nginx的高可用,如下图: 安装了keepavlived,走了一些弯路,记录下吧,nginx的安装就不多说了,博客已 ...
- sax, dom, jdom技术对比
---- sax, dom, jdom技术的优缺点比较 SAX分析器在对XML文档进行分析时,触发一系列的事件,应用程序通过事件处理函数实现对XML文档的访问.由于事件触发本身是有时序性的,因此,SA ...
- nginx平台初探-4
模块开发高级篇(30%) 变量(80%) 综述 在Nginx中同一个请求需要在模块之间数据的传递或者说在配置文件里面使用模块动态的数据一般来说都是使用变量,比如在HTTP模块中导出了host/ ...
- Kotlin:【初始化】延时初始化、惰性初始化、初始化的三个陷阱
- Map 实现类之:TreeMap(SortedMap的实现类) 和 Properties(Hashtable的实现类)
TreeMap存储 Key-Value 对时,需要根据 key-value 对进行排序.TreeMap 可以保证所有的 Key-Value 对处于 有序状态.TreeSet底层使用 红黑树结构存储 ...
- 使用_begin{thebibliography}__bibitem 如何参考文献
本人是tex新手,如果各位大佬有更好的方法欢迎分享,不胜感激. 适用情况 本文适用于使用\begin{thebibliography}和\bibitem排序的情况,如果使用bibtex排序那么网上很多 ...
- uni-app封装网络请求promise
在项目的根目录下,创建http文件夹. 然后在创建request.js文件 文件代码如下 export function apiapi(myurl,myget,mydata,tou="Acc ...
- Flink同步kafka到iceberg数据延迟,两个checkpoint后才可查询
一.问题描述 用户配置了高级参数很多,观察kafka增量数据不多,flink负载不高情况下两个checkpoint后才可查询到数据. 排查时hdfs有数据文件产生,但是mainfast文件中最新快 ...