先问一句:有没有人把 Redis 部署到公网或者测试机之后,被提醒“你的 Redis 被别人连上了”,然后你用redis-cli一敲发现里面真的多了不少奇奇怪怪的 key?我见过不止一次,起因基本都是同一件事——Redis 默认不设密码,只要端口暴露出去,谁都能直接执行FLUSHALL或者把你的数据当临时存储用。
所以今天的主题很简单:怎么给 Redis 设置密码。我按大家最常见的三种使用方式来拆解——第一是直接用redis.conf 配置文件做永久设置,第二是Docker 容器部署时的几种改密方式,第三是命令行下既改临时参数也做动态修改。这三条路覆盖了自建安装、容器化部署、临时调试三种真实工作场景,看完你应该能直接上手,顺带把几个常见的坑一起避开。
1. 先理解 Redis 的密码机制,再动手改
1.1 Redis 默认的安全状态
Redis 在默认配置下是不要求认证的,也就是说只要客户端能连上 6379 端口,发送PING、GET、SET、FLUSHALL这些命令都会被直接执行。本地开发环境这样用很顺手,因为你会下意识把它绑定在127.0.0.1上,外部网络根本连不进来。问题出在两类场景:一是你用0.0.0.0去监听所有网卡,二是你把它放进了 Docker 容器并映射了宿主机端口。这两种情况下,Redis 的服务端口就是暴露给整个网络的,等于你家大门敞开,门锁是不存在的。
Redis 官方其实提供了一个叫protected-mode的保护机制。默认情况下它确实是yes,但这个保护模式只有在“没有显式设置密码、没有绑定bind地址、没有配置 ACL 用户”时才生效。更麻烦的是它的保护逻辑是:如果 Redis 只监听在回环地址,外部请求会被拒绝;可一旦你手动设置了bind 0.0.0.0或者让容器端口映射到宿主机,protected-mode的判断就不那么靠谱了。所以指望默认配置是不现实的,最可靠的做法是设置一个强密码,并且让所有客户端统一走认证。
1.2 requirepass、AUTH、protected-mode 三者的关系
requirepass是 Redis 配置文件里最核心的认证参数,它设置“全局密码”。一旦设置,Redis 会要求所有连接在真正执行命令前先发送AUTH <password>。命令行参数--requirepass和运行时命令CONFIG SET requirepass最终改的也是同一个全局配置项。
protected-mode前面说了是“保险栓”。当密码没设置时,Redis 会拒绝来自非回环地址的连接。但只靠它会有误伤,也会带来“以为安全了,其实没安全”的错觉,所以应该把requirepass当成主要手段,protected-mode保持不变,作为第二道防线。
还有一个新东西叫ACL 用户体系,从 Redis 6 开始提供。ACL 可以给不同用户设置不同权限,requirepass本质上只是创建了一个默认用户的认证方式。对大多数中小项目来说,先用requirepass把门锁上,后续需要精细化权限再迁移到 AC L也不迟。
1.3 动手前先做三件准备工作
第一件:确定密码策略。不要用123456这种级别的密码,我建议至少 16 位,包含大小写字母、数字、特殊字符,而且不要和其他系统的口令重复。你想想 Redis 里可能缓存了什么,多半是 session、计数、热点数据,有些甚至是业务表的一级缓存,泄露出去不只是面子问题。
第二件:确认你手上有管理权限。如果是远程服务器上的 Redis,你需要能改配置文件并且能重启服务;如果是 Docker 容器,你需要能执行docker exec或者能重新docker run一个新的容器。否则你只能让运维协助操作。
第三件:备份。改配置文件之前先把redis.conf复制一份,例如cp redis.conf redis.conf.bak。如果你用的是云厂商的托管 Redis,那还要先搞清楚服务面板里有没有“重置密码”入口,有的话优先用客户端提供的安全能力,而不是直接改机器上的配置,因为托管实例很多配置是被云平台锁定的。
2. 场景一:配置文件方式设置 Redis 密码
2.1 找到 node_modules 都在哪个路径
不同安装方式的 Redis,配置文件位置差别很大。我列几个常见位置,帮你快速定位:
| 安装方式 | 常见路径 |
|---|---|
| Ubuntu / Debian apt 安装 | /etc/redis/redis.conf |
| CentOS / RHEL yum 安装 | /etc/redis.conf或/etc/redis/redis.conf |
| 源码编译安装 | 你执行./configure --prefix=xxx时指定的目录下,通常是源码目录里的redis.conf,安装后可能在/usr/local/redis/etc/redis.conf |
| Windows 安装包 | 安装目录下的redis.windows.conf |
| Mac 上用 Homebrew 安装 | /usr/local/etc/redis.conf或/opt/homebrew/etc/redis.conf |
如果实在找不到,可以用redis-server --version看版本信息,然后用ps -ef | grep redis查看启动命令,启动命令里往往带redis-server /path/to/redis.conf这类路径。再不行就find / -name "redis.conf" 2>/dev/null,虽然慢一点,但能找到。
2.2 修改 redis.conf 中的 requirepass
以最常见的/etc/redis/redis.conf为例。先用编辑器打开,比如vim /etc/redis/redis.conf,然后找到这一行:
# requirepass foobared注意#注释。默认配置里requirepass是被注释掉的,表示“不设密码”。你需要把注释去掉,改成自己的密码:
requirepass YourStrongPassw0rd!2024改完之后保存退出。这里有两个小细节要留意。
第一,requirepass后面是明文的,这意味着凡是能读到配置文件的人都会看到密码。所以在团队环境里,要注意这个文件本身的权限,比如chmod 640 /etc/redis/redis.conf。第二,配置文件里如果同时存在多个requirepass,Redis 只认最后一个,所以别指望用“多个密码并存”的方式来做轮换,旧版本那是行不通的,要做密码轮换就用 ACL 多用户。
2.3 重启 Redis 并验证密码是否生效
改完配置文件必须重启 Redis 才能生效,因为配置文件只在启动时加载。不同系统的重启命令不一样:
systemctl restart redis适用于大多数 Linux 发行版服务化安装。service redis-server restart适用于 SysV init 管理的老环境。- 如果你是直接前台起的,那就
Ctrl+C停掉,再用同样命令启动。
重启之后验证是非常关键的一步,不然你根本不知道密码是否真的生效。最简单的验证动作是执行:
redis-cli ping如果密码生效,你会看到:
(error) NOAUTH Authentication required.出现这个报错就说明密码已经挡在最前面了。紧接着用密码认证:
redis-cli -a 'YourStrongPassw0rd!2024' ping看到PONG就说明认证成功。这里有个提示:-a参数会把密码留在 shell 历史记录里,所以正式环境推荐用redis-cli进入交互模式后输入AUTH,或者临时设置REDISCLI_AUTH环境变量来完成验证。
2.4 配置文件方式的三个注意点
注意点一是不要把密码写在命令行参数里然后写进 systemd service 文件,因为 systemd 里用ExecStart启动 Redis 时,命令行参数会暴露给所有能执行ps的用户。正确的做法是让 systemd 通过-c /etc/redis/redis.conf指向配置文件,密码只存在于redis.conf中。
注意点二是改完配置后先做一次redis-cli -a 密码 config get requirepass验证,CONFIG GET返回的是一个数组,一般样子是:
1) "requirepass" 2) "YourStrongPassw0rd!2024"如果返回值是空,那就是你改错文件了,Redis 实际读取的是另一份配置。
注意点三是最容易被忽略的:配置文件方式适合永久生效,但不适合频繁换密码。你一改配置文件就要重启,而重启意味着短暂断连,缓存雪崩风险也会升高。所以线上环境如果突然需要紧急换密码,我一般先用后面要讲的命令行方式动态切换,等到业务低峰期再改配置文件做持久化。
3. 场景二:Docker 容器中设置 Redis 密码
3.1 Docker 环境下的三种改密思路
Docker 里跑 Redis 和本机跑 Redis 有个本质区别:容器的文件系统是临时层,你在容器里改的东西,容器一删就全没了。所以“在容器里用vim改 redis.conf” 这种操作虽然能生效,但是非常不可靠。靠谱的思路有三种:启动容器时直接通过命令行参数--requirepass设置;挂载一份自定义配置文件到容器内;或者在docker-compose.yml里编排好配置。下面逐个说。
3.2 方式 A:使用 docker run 启动参数直接指定密码
大多数官方 Redis 镜像默认会执行redis-server,所以你可以直接给它传参数。先看一条真实可用的启动命令:
docker run -d \ --name redis-pass \ -p 6379:6379 \ redis:7 \ redis-server --requirepass 'YourStrongPassw0rd!2024' --appendonly yes这条命令的意思是:用redis:7镜像,启动一个叫redis-pass的容器,把宿主机 6379 映射到容器 6379,然后在启动 Redis 服务时追加两个配置参数,一个是密码,一个是开启 AOF 持久化。
验证方式同样很简单:
docker exec -it redis-pass redis-cli -a 'YourStrongPassw0rd!2024' ping看到PONG就正常。如果你这时候进入容器内部用redis-cli ping,会得到NOAUTH报错,因为docker exec进去默认就在 Redis 容器里执行redis-cli,不会自动带密码。
这个方式的优点是干净、直接、不用准备配置文件。缺点是密码会出现在docker run的命令行里,如果你用 shell history 保存了这条命令,别人history一下就能看到。所以本地测试可以用,但正式环境建议用下面的挂载配置文件方式,或者把密码放到 Docker Secret 这种专门机制里。
3.3 方式 B:把自定义 redis.conf 挂载进容器
这是我自己在生成环境最常采用的方式,因为配置的可维护性更强。步骤分三步。
第一步,在宿主机上准备一份redis.conf。你可以从官方镜像里拷贝一份模板,也可以自己写一个最小配置。例如我在宿主机/opt/redis/config/redis.conf里写了:
bind 0.0.0.0 protected-mode yes port 6379 requirepass YourStrongPassw0rd!2024 appendonly yes appendfilename "appendonly.aof"第二步,用挂载参数启动容器:
docker run -d \ --name redis-pass-file \ -p 6379:6379 \ -v /opt/redis/config/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7 \ redis-server /usr/local/etc/redis/redis.conf这里的重点是把宿主机上的/opt/redis/config/redis.conf挂载到容器里的/usr/local/etc/redis/redis.conf,然后启动命令要显式指定让 Redis 使用这个配置文件。如果不指定,官方镜像默认启动时可能用的是源码编译目录里的默认配置,挂载进去也不会被读取。
第三步,验证:
docker exec redis-pass-file redis-cli -a 'YourStrongPassw0rd!2024' ping这个方式的好处非常明显:所有配置项都在宿主机的一个文件里,后续要调整maxmemory、持久化策略、密码等,只需要改宿主机的redis.conf再重启容器就行。而且这个配置文件还能直接用 Git 管理,整个 Redis 的运行时配置都有了版本记录。
3.4 方式 C:docker-compose 编排配置文件
如果你用 Docker Compose 来管理一堆服务,那 Redis 的密码配置应该写进docker-compose.yml里。我给出一个可以直接套用的示例:
services: redis: image: redis:7 container_name: redis-compose-pass restart: always ports: - "6379:6379" volumes: - /opt/redis/config/redis.conf:/usr/local/etc/redis/redis.conf - /opt/redis/data:/data command: ["redis-server", "/usr/local/etc/redis/redis.conf"]启动命令:
docker compose up -d然后验证:
docker compose exec redis redis-cli -a 'YourStrongPassw0rd!2024' pingCompose 方式最大优势是配置声明式、可复制,新环境只要把这份 YAML 和 redis.conf 拿过去,docker compose up -d就能得到一模一样的容器。
3.5 容器场景的避坑细节
这里我必须多说几句,都是踩过的坑。
第一个是挂载文件的权限问题。宿主机上挂载进容器的redis.conf文件如果权限设置成777,部分 Redis 镜像可能会拒绝执行。规范做法是chmod 644,保证 Redis 进程用户有读取权限,而不是直接给最高权限。
第二个是CONFIG REWRITE和容器配置文件的矛盾。假设你在容器里用redis-cli config set requirepass xxx改了密码,再执行config rewrite,这时 Redis 会尝试把当前配置写回它启动时读取的配置文件。如果这个文件是被挂载进容器的,重写会成功;但它如果属于容器内部文件系统,容器一删就全丢。更尴尬的是,如果挂载文件是只读的,config rewrite还会直接报错。所以容器场景下的正确姿势是:在宿主机上改redis.conf再重启容器。
第三个是日志排查技巧。如果容器启动异常,不要只盯着docker logs的简短输出,很多 Redis 配置错误会出现在最后几行。比如我遇到过容器直接退出,docker logs输出里明确写了:
# Warning: couldn't set memory limit # Can't open the log file: Permission denied这多半是挂载文件或数据目录的权限问题。调整目录归属chown -R redis:redis /opt/redis/data后就能解决。
第四个是关于端口冲突。如果宿主机 6379 已经被本机 Redis 占用了,Docker 启动时会报bind: address already in use。这种时候要么关掉本机 Redis,要么把宿主机端口改成16379再映射,比如-p 16379:6379。
4. 场景三:命令行方式设置 Redis 密码
4.1 启动时通过命令行参数指定密码
启动 Redis 时可以直接通过--requirepass传参,这个方式在临时测试和调试时最常用。看示例:
redis-server --port 6380 --requirepass 'TmpPassw0rd!888' --protected-mode yes这条命令会在 6380 端口启动一个 Redis 实例,并且设置密码为TmpPassw0rd!888。启动时加--protected-mode yes是为了避免“设置了密码但保护模式关闭”的不稳定状态。
验证这一步:
redis-cli -p 6380 -a 'TmpPassw0rd!888' ping这种方式适合本地多实例测试,比如你想在 6380、6381、6382 上分别起三个不同配置的 Redis,用命令行参数最省事,不用准备三份配置文件。但它也有致命缺陷:密码一旦以参数形式出现在进程启动信息里,你就能通过ps -ef看到明文,所以只适合临时调试,用来做生产环境是不可取的。
如果你用redis-server /usr/local/etc/redis/redis.conf --requirepass optimizePassword这种混合方式,要注意命令行参数的优先级高于配置文件。也就是说,如果配置文件和命令行参数都写了密码,以命令行参数为准。这个特性在临时覆盖配置时很有用,但也会迷惑人,我曾经遇到过有人改了配置文件却没生效,就是因为 service 启动脚本里残留了旧的命令参数。
4.2 运行中动态修改密码:CONFIG SET
这是不需要重启服务就能改密码的方法,也是线上应急改密的首选。先连接到 Redis:
redis-cli然后执行:
CONFIG SET requirepass "NewPassword-2024"执行成功后,Redis 会立刻启用新密码。这里有个非常关键的点:当你把requirepass设置为一个新密码时,当前连接不会断开,其他连接则会丢到认证区,需要重新AUTH。你自己这个连接是“以前密码连接进来的”,但它不会因为你改了密码就被踢掉,因为 Redis 只认证“连接建立后第一条命令”,而且CONFIG SET本身就是特殊命令,已验证过的连接保持可用。
如果你把密码设成空字符串:
CONFIG SET requirepass ""就相当于去掉密码,立刻恢复无认证状态。这个操作非常危险,但偶尔会用在调试和自动化环境里,生产环境千万别这么干。
4.3 持久化密码:CONFIG REWRITE 的作用
CONFIG SET只改内存中的配置,重启后就没了。要想把修改写入配置文件,必须执行:
CONFIG REWRITECONFIG REWRITE会把当前 Redis 配置和它启动时读取的配置文件进行合并,把内存中的变更写回文件。如果 Redis 启动时没有指定配置文件(也就是纯命令行参数的临时实例),执行CONFIG REWRITE会报错:
(error) ERR The server is running without a config file所以在生产环境我一般这么做:
- 先用
CONFIG SET requirepass临时降低风险,比如在漏报告警时快速加密码。 - 业务低峰期,执行
CONFIG REWRITE让配置持久化。 - 再准备一个快速重启窗口,确认配置文件里的
requirepass已经出现。
CFG REWRITE 还有一个坑:它不会完整保留配置文件里的所有注释和排版,因为它会按 Redis 自身的内存配置重新生成文件内容。所以一个写满精美中文注释的配置文件,执行一次 rewrite 之后,注释可能就少了一半。我的建议是:配置文件还是要通过 Git 管理,生成好的redis.conf是基础设施的一部分,不要依赖运行时 rewrite 来维护。
4.4 命令行验证密码的正确姿势
最后说说怎么用命令行验证密码。最常规的命令:
redis-cli -a 'YourPassword' ping输出为:
PONG第二招是进入交互模式后用AUTH:
redis-cli 127.0.0.1:6379> AUTH YourPassword OK 127.0.0.1:6379> PING PONG第三招是不用-a参数,用环境变量:
export REDISCLI_AUTH='YourPassword' redis-cli ping这样也能自动认证,并且密码不会出现在ps -ef的进程参数列表中。这个方法我在批量执行脚本时经常用。需要提醒的是,-a参数如果密码有特殊字符,比如!、$、&,shell 可能会做变量展开,建议用单引号把密码括住,或者用--raw再手动控制输出。
5. 三种方式对比与高频排障
5.1 三种设置方式对比
| 设置方式 | 生效方式 | 持久性 | 适合场景 | 风险点 |
|---|---|---|---|---|
| 配置文件修改 | 重启 Redis | 永久 | 生产环境正式部署 | 需要重启,有短暂中断 |
| Docker 挂载配置文件 | 重启容器 | 永久 | 容器化生产环境 | 挂载权限、路径易错 |
| docker run 带参 | 重启容器 | 容器生命周期内 | 临时测试、快速验证 | 密码会出现在命令行 |
| 命令行 CONFIG SET | 立即生效 | 不持久,需 REWRITE | 线上临时改密 | 忘写 rewrite 则重启失效 |
| redis-server 启动参数 | 启动时 | 进程运行期间 | 本地多实例调试 | 密码在进程参数中可见 |
我给你的实用建议是:开发环境用命令行参数,测试环境用 docker 挂载,生产环境要么用真机配置文件、要么用 Docker + 挂载配置文件。核心原则只有一个——不要让密码出现在能被人轻松看到的地方。
5.2 常见报错与排查手册
先列一个快速排查表:
| 报错 / 现象 | 可能原因 | 解决办法 |
|---|---|---|
(error) NOAUTH Authentication required. | 认证未通过或还没发 AUTH | 用redis-cli -a 密码或在连接后先执行 AUTH |
(error) ERR Client sent AUTH, but no password is set. | 正打算发 AUTH,但 Redis 没配置密码 | 检查CONFIG GET requirepass,为空说明没设密码 |
(error) WRONGPASS invalid username-password pair | 密码输错了 | 重新确认密码,注意特殊字符转义 |
docker: Error response from daemon: Conflict. | 容器名冲突 | 换个容器名或docker rm旧容器 |
Cannot connect to the Docker daemon | docker 服务未启动或无权限 | systemctl start docker,或检查用户组 |
| 容器启动后立即退出 | 配置文件路径错误或数据目录权限不对 | 看docker logs 容器名最后的错误信息 |
(error) ERR Unsupported CONFIG parameter: requirepass | 你连的可能不是 Redis,或者版本极老 | 确认端口和客户端类型 |
MISCONF Redis is configured to save RDB snapshots | CONFIG SET后持久化写入异常 | 检查磁盘权限和dir配置 |
这里重点说一下NOAUTH的排查思路。你看到NOAUTH不要立刻怀疑密码错了,先确认 Redis 是否真的设置了密码:
redis-cli -a 原密码 CONFIG GET requirepass或者当你知道密码但想试探时:
redis-cli CONFIG GET requirepass如果返回的是空数组,说明 Redis 当前是没有密码的;如果返回的是1) requirepass 2) 密码,那说明有密码,你需要在连接时带上。
排查容器端口的报错也要注意顺序。先用docker ps看容器状态是否Up,再用docker logs看启动日志,最后再决定是检查配置文件还是数据目录权限。顺序乱了容易白忙活。
5.3 设置密码后对主从复制、客户端和工具链的影响
设置密码这件事,最容易被忽视的是“连锁影响”。我举三个真实场景。
场景一:主从复制。如果你有一个 Redis 主实例和若干个从实例,给主实例设置密码后,从实例必须配置masterauth,否则从节点连不上主节点。从节点的配置里可以加:
masterauth "YourMasterPassword"masterauth要填写的是主实例的requirepass密码。如果你用的是 Redis 6+ 的 ACL,那么还需要对应主实例 master 用户权限。这个坑非常常见,我见过有人给主库加了强密码,结果从库同步中断了半天才发现。
场景二:客户端连接。你的业务代码里所有连接 Redis 的地方都要带上密码。以 Java 的 Lettuce 为例,需要在RedisClient配置里设置 password;以 Go 的 go-redis 为例,需要在Options里写Password字段。如果服务端已经设密码而客户端没跟上,你会看到大量ERR Client sent AUTH, but no password is set或者NOAUTH错误,业务日志瞬间被刷屏。
场景三:可视化工具。像 Redis Desktop Manager、Another Redis Desktop Manager、Redis Insight 这类 GUI 工具,连接时需要填写密码字段。更多人忽略的是连接地址里的认证方式,比如某些老版本工具默认是NoAuth,你填了密码也未必能在连接前认证,反而需要手动设置“使用密码认证”。
5.4 进阶:用 ACL 用户替代全局 requirepass
如果你只有一个密码控制全局读写,一旦密码泄露,攻击者能执行FLUSHALL把数据清空。Redis 6 之后的 ACL 可以把风险拆细。我简单举个例子。
在redis-cli里创建两个用户:
ACL SETUSER app_user on >'AppUserPassword!123' ~* +@all -@dangerous ACL SETUSER admin_user on >'AdminPassword!456' ~* +@all第一行创建了app_user,只能操作普通键空间,但禁止执行危险命令组,比如FLUSHALL、SHUTDOWN、KEYS等。第二行创建了admin_user,拥有全部权限。
实际使用时,业务连接用app_user,运维排查用admin_user,密码各自独立,即使业务侧密码泄露,也不能清空数据。ACL 的设置同样可以写进redis.conf:
user default on nopass ~* +@all user app_user on >'AppUserPassword!123' ~* +@all -@dangerous user admin_user on >'AdminPassword!456' ~* +@all从长期维护角度看,ACL 比单一requirepass更优雅,也更安全。但前提是你得规划好用户权限矩阵,否则前期迁移成本不小。对个人项目和小团队,先用好requirepass守住底线,等真有多个客户端、多角色需求时,再升级到 ACL。
6. 最后再聊几个我踩过的细节坑
给 Redis 设置密码这件事,说起来就是改一行配置的事,但真正放到生产上是有一堆细节的。最后分享几条能帮你少走弯路的心得。
第一,设置完密码一定要在第二台机器上测一下外网连接。我见过有人只在服务器本机用redis-cli验证通过,结果从办公网连过去还是报NOAUTH,原因是他本机 redis-cli 用了默认端口 6379,但服务器实际监听的是另一个端口。验证命令里一定要带上-h 服务器IP -p 端口。
第二,动态改密时优先改代码再改 Redis。线上环境如果必须换密码,不要先动 Redis 再改业务配置,那会造成一段时间内所有业务请求全部报错。正确顺序是:先把客户端连接信息改成新密码,然后灰度发布,最后再执行CONFIG SET requirepass切换服务端。如果客户端配置已经全部更新但 Redis 还没换,旧密码仍然有效,业务不会中断。
第三,不要把密码和 Redis 放在同一个配置文件里提交到公开仓库。即使你的redis.conf写得再规范,一旦推送到公开 GitHub,密码就已经泄露。现在很多项目会用到.gitignore过滤配置文件模板,或者用环境变量${REDIS_PASSWORD}占位,再由部署系统注入真实值,这才是更稳的做法。
第四,如果你用的是云厂商提供的 Redis 实例,千万不要尝试在控制台外去手动改配置文件。托管实例的配置入口通常在控制台的“参数组”或“安全设置”里。手动连接到服务器内部去改,大概率改变不了实际生效配置,还容易把实例搞到不可用。这个结论我反复验证过,云上资源就按云上的玩法来。
最后再补充一个小技巧:无论用了哪种方式设置密码,都应该在客户端的工具脚本里加一个快速自检。比如我习惯在部署脚本里加一行:
redis-cli -h $REDIS_HOST -p $REDIS_PORT -a "$REDIS_PASSWORD" ping >/dev/null 2>&1 && echo "Redis auth OK"别小看这一行,它能让你在代码上线前第一时间发现问题,而不是等业务跑起来之后被超时和报错淹没。毕竟 Redis 的密码设置不是“设完就结束”的事,后面跟着的是客户端、主从、监控、工具链的一整套联动。把每个环节都打通,这个密码才算真正设置成功了。